1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Handle resolution scaling in windowed mode

This commit is contained in:
narzoul 2022-06-05 15:08:53 +02:00
parent 96ad1d6ab6
commit fc16184256
7 changed files with 118 additions and 21 deletions

View File

@ -1038,19 +1038,22 @@ namespace D3dDdi
{ {
if (srcResource->m_lockResource) if (srcResource->m_lockResource)
{ {
if (srcResource->m_lockData[0].isSysMemUpToDate && if (srcResource->m_lockData[data.SrcSubResourceIndex].isSysMemUpToDate &&
!srcResource->m_fixedData.Flags.RenderTarget) !srcResource->m_fixedData.Flags.RenderTarget)
{ {
srcResource->m_lockData[0].isVidMemUpToDate = false; srcResource->m_lockData[data.SrcSubResourceIndex].isVidMemUpToDate = false;
} }
srcResource = &srcResource->prepareForGpuRead(0); srcResource = &srcResource->prepareForGpuRead(data.SrcSubResourceIndex);
} }
LONG srcWidth = srcResource->m_fixedData.pSurfList[0].Width; LONG srcWidth = srcResource->m_fixedData.pSurfList[data.SrcSubResourceIndex].Width;
LONG srcHeight = srcResource->m_fixedData.pSurfList[0].Height; LONG srcHeight = srcResource->m_fixedData.pSurfList[data.SrcSubResourceIndex].Height;
data.SrcRect = { 0, 0, srcWidth, srcHeight }; data.SrcRect = { 0, 0, srcWidth, srcHeight };
if (!IsRectEmpty(&g_presentationRect))
{
data.DstRect = g_presentationRect; data.DstRect = g_presentationRect;
}
auto& repo = SurfaceRepository::get(m_device.getAdapter()); auto& repo = SurfaceRepository::get(m_device.getAdapter());
const auto& rtSurface = repo.getTempRenderTarget(srcWidth, srcHeight); const auto& rtSurface = repo.getTempRenderTarget(srcWidth, srcHeight);
@ -1078,14 +1081,18 @@ namespace D3dDdi
pal[i].rgbGreen = entries[i].peGreen; pal[i].rgbGreen = entries[i].peGreen;
pal[i].rgbBlue = entries[i].peBlue; pal[i].rgbBlue = entries[i].peBlue;
} }
m_device.getShaderBlitter().palettizedBlt(*rt, rtIndex, rtRect, *srcResource, data.SrcRect, pal); m_device.getShaderBlitter().palettizedBlt(
*rt, rtIndex, rtRect, *srcResource, data.SrcSubResourceIndex, data.SrcRect, pal);
} }
else else
{ {
copySubResourceRegion(*rt, rtIndex, rtRect, *srcResource, 0, data.SrcRect); copySubResourceRegion(*rt, rtIndex, rtRect, *srcResource, data.SrcSubResourceIndex, data.SrcRect);
} }
if (!IsRectEmpty(&g_presentationRect))
{
presentLayeredWindows(*rt, rtIndex, rtRect); presentLayeredWindows(*rt, rtIndex, rtRect);
}
const auto cursorInfo = Gdi::Cursor::getEmulatedCursorInfo(); const auto cursorInfo = Gdi::Cursor::getEmulatedCursorInfo();
const bool isCursorEmulated = cursorInfo.flags == CURSOR_SHOWING && cursorInfo.hCursor; const bool isCursorEmulated = cursorInfo.flags == CURSOR_SHOWING && cursorInfo.hCursor;

View File

@ -45,6 +45,7 @@ namespace D3dDdi
void prepareForCpuWrite(UINT subResourceIndex); void prepareForCpuWrite(UINT subResourceIndex);
Resource& prepareForGpuRead(UINT subResourceIndex); Resource& prepareForGpuRead(UINT subResourceIndex);
void prepareForGpuWrite(UINT subResourceIndex); void prepareForGpuWrite(UINT subResourceIndex);
HRESULT presentationBlt(D3DDDIARG_BLT data, Resource* srcResource);
void scaleRect(RECT& rect); void scaleRect(RECT& rect);
void setAsGdiResource(bool isGdiResource); void setAsGdiResource(bool isGdiResource);
void setAsPrimary(); void setAsPrimary();
@ -106,7 +107,6 @@ namespace D3dDdi
void loadSysMemResource(UINT subResourceIndex); void loadSysMemResource(UINT subResourceIndex);
void loadVidMemResource(UINT subResourceIndex); void loadVidMemResource(UINT subResourceIndex);
void notifyLock(UINT subResourceIndex); void notifyLock(UINT subResourceIndex);
HRESULT presentationBlt(D3DDDIARG_BLT data, Resource* srcResource);
void presentLayeredWindows(Resource& dst, UINT dstSubResourceIndex, const RECT& dstRect); void presentLayeredWindows(Resource& dst, UINT dstSubResourceIndex, const RECT& dstRect);
HRESULT shaderBlt(D3DDDIARG_BLT& data, Resource& dstResource, Resource& srcResource); HRESULT shaderBlt(D3DDDIARG_BLT& data, Resource& dstResource, Resource& srcResource);

View File

@ -317,10 +317,11 @@ namespace D3dDdi
} }
void ShaderBlitter::palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect, void ShaderBlitter::palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, const RECT& srcRect, RGBQUAD palette[256]) const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, RGBQUAD palette[256])
{ {
LOG_FUNC("ShaderBlitter::palettizedBlt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect, LOG_FUNC("ShaderBlitter::palettizedBlt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
static_cast<HANDLE>(srcResource), srcRect, Compat::array(reinterpret_cast<void**>(palette), 256)); static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect,
Compat::array(reinterpret_cast<void**>(palette), 256));
auto paletteTexture(SurfaceRepository::get(m_device.getAdapter()).getPaletteTexture()); auto paletteTexture(SurfaceRepository::get(m_device.getAdapter()).getPaletteTexture());
if (!paletteTexture) if (!paletteTexture)
@ -344,7 +345,8 @@ namespace D3dDdi
m_device.getOrigVtable().pfnUnlock(m_device, &unlock); m_device.getOrigVtable().pfnUnlock(m_device, &unlock);
setTempTextureStage(1, *paletteTexture, srcRect, D3DTEXF_POINT); setTempTextureStage(1, *paletteTexture, srcRect, D3DTEXF_POINT);
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, 0, srcRect, m_psPaletteLookup.get(), D3DTEXF_POINT); blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
m_psPaletteLookup.get(), D3DTEXF_POINT);
} }
void ShaderBlitter::resetGammaRamp() void ShaderBlitter::resetGammaRamp()

View File

@ -34,7 +34,7 @@ namespace D3dDdi
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
const Resource& lockRefResource); const Resource& lockRefResource);
void palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect, void palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, const RECT& srcRect, RGBQUAD palette[256]); const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, RGBQUAD palette[256]);
void textureBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect, void textureBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
UINT filter, const UINT* srcColorKey = nullptr, const BYTE* alpha = nullptr, UINT filter, const UINT* srcColorKey = nullptr, const BYTE* alpha = nullptr,

View File

@ -9,12 +9,16 @@
#include <Config/Config.h> #include <Config/Config.h>
#include <D3dDdi/Device.h> #include <D3dDdi/Device.h>
#include <D3dDdi/KernelModeThunks.h> #include <D3dDdi/KernelModeThunks.h>
#include <D3dDdi/Resource.h>
#include <D3dDdi/ScopedCriticalSection.h>
#include <D3dDdi/SurfaceRepository.h>
#include <DDraw/DirectDraw.h> #include <DDraw/DirectDraw.h>
#include <DDraw/DirectDrawSurface.h> #include <DDraw/DirectDrawSurface.h>
#include <DDraw/IReleaseNotifier.h> #include <DDraw/IReleaseNotifier.h>
#include <DDraw/RealPrimarySurface.h> #include <DDraw/RealPrimarySurface.h>
#include <DDraw/ScopedThreadLock.h> #include <DDraw/ScopedThreadLock.h>
#include <DDraw/Surfaces/PrimarySurface.h> #include <DDraw/Surfaces/PrimarySurface.h>
#include <DDraw/Surfaces/TagSurface.h>
#include <DDraw/Types.h> #include <DDraw/Types.h>
#include <Gdi/Caret.h> #include <Gdi/Caret.h>
#include <Gdi/Cursor.h> #include <Gdi/Cursor.h>
@ -34,6 +38,7 @@ namespace
void onRelease(); void onRelease();
CompatWeakPtr<IDirectDrawSurface7> g_frontBuffer; CompatWeakPtr<IDirectDrawSurface7> g_frontBuffer;
CompatWeakPtr<IDirectDrawSurface7> g_windowedBackBuffer;
CompatWeakPtr<IDirectDrawClipper> g_clipper; CompatWeakPtr<IDirectDrawClipper> g_clipper;
RECT g_monitorRect = {}; RECT g_monitorRect = {};
DDSURFACEDESC2 g_surfaceDesc = {}; DDSURFACEDESC2 g_surfaceDesc = {};
@ -65,7 +70,24 @@ namespace
{ {
if (!g_isFullscreen) if (!g_isFullscreen)
{ {
Gdi::Window::present(*g_frontBuffer, src, *g_clipper); {
D3dDdi::ScopedCriticalSection lock;
auto srcResource = D3dDdi::Device::findResource(
DDraw::DirectDrawSurface::getDriverResourceHandle(src.get()));
auto bbResource = D3dDdi::Device::findResource(
DDraw::DirectDrawSurface::getDriverResourceHandle(*g_windowedBackBuffer));
D3DDDIARG_BLT blt = {};
blt.hSrcResource = *srcResource;
blt.SrcSubResourceIndex = DDraw::DirectDrawSurface::getSubResourceIndex(src.get());
blt.SrcRect = DDraw::PrimarySurface::getMonitorRect();
blt.hDstResource = *bbResource;
blt.DstSubResourceIndex = 0;
blt.DstRect = g_monitorRect;
bbResource->presentationBlt(blt, srcResource);
}
Gdi::Window::present(*g_frontBuffer, *g_windowedBackBuffer, *g_clipper);
return; return;
} }
@ -76,6 +98,48 @@ namespace
} }
} }
CompatPtr<IDirectDrawSurface7> createWindowedBackBuffer(DDRAWI_DIRECTDRAW_LCL* ddLcl, DWORD width, DWORD height)
{
if (!ddLcl)
{
LOG_INFO << "ERROR: createWindowedBackBuffer: ddLcl is null";
return nullptr;
}
auto tagSurface = DDraw::TagSurface::get(ddLcl);
if (!tagSurface)
{
LOG_INFO << "ERROR: createWindowedBackBuffer: TagSurface not found";
return nullptr;
}
auto resource = DDraw::DirectDrawSurface::getDriverResourceHandle(*tagSurface->getDDS());
if (!resource)
{
LOG_INFO << "ERROR: createWindowedBackBuffer: driver resource handle not found";
return nullptr;
}
auto device = D3dDdi::Device::findDeviceByResource(resource);
if (!device)
{
LOG_INFO << "ERROR: createWindowedBackBuffer: device not found";
return nullptr;
}
auto& repo = D3dDdi::SurfaceRepository::get(device->getAdapter());
D3dDdi::SurfaceRepository::Surface surface = {};
repo.getSurface(surface, width, height, DDraw::DirectDraw::getRgbPixelFormat(32),
DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY);
if (!surface.surface)
{
LOG_INFO << "ERROR: createWindowedBackBuffer: surface creation failed";
return nullptr;
}
return surface.surface;
}
CompatPtr<IDirectDrawSurface7> getBackBuffer() CompatPtr<IDirectDrawSurface7> getBackBuffer()
{ {
DDSCAPS2 caps = {}; DDSCAPS2 caps = {};
@ -133,6 +197,7 @@ namespace
g_frontBuffer = nullptr; g_frontBuffer = nullptr;
g_lastFlipSurface = nullptr; g_lastFlipSurface = nullptr;
g_windowedBackBuffer.release();
g_clipper.release(); g_clipper.release();
g_isFullscreen = false; g_isFullscreen = false;
g_surfaceDesc = {}; g_surfaceDesc = {};
@ -164,6 +229,11 @@ namespace
D3dDdi::KernelModeThunks::waitForVsyncCounter(D3dDdi::KernelModeThunks::getVsyncCounter() + 1); D3dDdi::KernelModeThunks::waitForVsyncCounter(D3dDdi::KernelModeThunks::getVsyncCounter() + 1);
} }
if (g_windowedBackBuffer)
{
g_windowedBackBuffer->Restore(g_windowedBackBuffer);
}
Compat::ScopedCriticalSection lock(g_presentCs); Compat::ScopedCriticalSection lock(g_presentCs);
g_isUpdatePending = false; g_isUpdatePending = false;
g_isUpdateReady = false; g_isUpdateReady = false;
@ -204,11 +274,7 @@ namespace
Gdi::Region excludeRegion(DDraw::PrimarySurface::getMonitorRect()); Gdi::Region excludeRegion(DDraw::PrimarySurface::getMonitorRect());
Gdi::Window::present(excludeRegion); Gdi::Window::present(excludeRegion);
auto palette(Gdi::Palette::getHardwarePalette());
D3dDdi::KernelModeThunks::setDcPaletteOverride(palette.data());
bltToPrimaryChain(*src); bltToPrimaryChain(*src);
D3dDdi::KernelModeThunks::setDcPaletteOverride(nullptr);
} }
void updateNow(CompatWeakPtr<IDirectDrawSurface7> src) void updateNow(CompatWeakPtr<IDirectDrawSurface7> src)
@ -282,6 +348,17 @@ namespace DDraw
return result; return result;
} }
if (0 == desc.dwBackBufferCount)
{
g_windowedBackBuffer = createWindowedBackBuffer(DDraw::DirectDraw::getInt(dd.get()).lpLcl,
g_monitorRect.right - g_monitorRect.left, g_monitorRect.bottom - g_monitorRect.top).detach();
if (!g_windowedBackBuffer)
{
g_monitorRect = {};
return DDERR_GENERIC;
}
}
g_frontBuffer = CompatPtr<IDirectDrawSurface7>::from(surface.get()).detach(); g_frontBuffer = CompatPtr<IDirectDrawSurface7>::from(surface.get()).detach();
g_frontBuffer->SetPrivateData(g_frontBuffer, IID_IReleaseNotifier, g_frontBuffer->SetPrivateData(g_frontBuffer, IID_IReleaseNotifier,
&g_releaseNotifier, sizeof(&g_releaseNotifier), DDSPD_IUNKNOWNPOINTER); &g_releaseNotifier, sizeof(&g_releaseNotifier), DDSPD_IUNKNOWNPOINTER);

View File

@ -67,14 +67,24 @@ namespace DDraw
} }
} }
TagSurface* TagSurface::get(CompatRef<IDirectDraw> dd) TagSurface* TagSurface::get(DDRAWI_DIRECTDRAW_LCL* ddLcl)
{ {
auto ddLcl = DDraw::DirectDraw::getInt(dd.get()).lpLcl;
auto it = g_ddObjects.find(ddLcl); auto it = g_ddObjects.find(ddLcl);
if (it != g_ddObjects.end()) if (it != g_ddObjects.end())
{ {
return it->second; return it->second;
} }
return nullptr;
}
TagSurface* TagSurface::get(CompatRef<IDirectDraw> dd)
{
auto ddLcl = DDraw::DirectDraw::getInt(dd.get()).lpLcl;
auto tagSurface = get(ddLcl);
if (tagSurface)
{
return tagSurface;
}
if (FAILED(create(dd))) if (FAILED(create(dd)))
{ {

View File

@ -15,6 +15,7 @@ namespace DDraw
TagSurface(DWORD origCaps, DDRAWI_DIRECTDRAW_LCL* ddLcl); TagSurface(DWORD origCaps, DDRAWI_DIRECTDRAW_LCL* ddLcl);
virtual ~TagSurface() override; virtual ~TagSurface() override;
static TagSurface* get(DDRAWI_DIRECTDRAW_LCL* ddLcl);
static TagSurface* get(CompatRef<IDirectDraw> dd); static TagSurface* get(CompatRef<IDirectDraw> dd);
static TagSurface* findFullscreenWindow(HWND hwnd); static TagSurface* findFullscreenWindow(HWND hwnd);