diff --git a/DDrawCompat/D3dDdi/Resource.cpp b/DDrawCompat/D3dDdi/Resource.cpp index 6075fb0..0a5584f 100644 --- a/DDrawCompat/D3dDdi/Resource.cpp +++ b/DDrawCompat/D3dDdi/Resource.cpp @@ -1038,19 +1038,22 @@ namespace D3dDdi { if (srcResource->m_lockResource) { - if (srcResource->m_lockData[0].isSysMemUpToDate && + if (srcResource->m_lockData[data.SrcSubResourceIndex].isSysMemUpToDate && !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 srcHeight = srcResource->m_fixedData.pSurfList[0].Height; + LONG srcWidth = srcResource->m_fixedData.pSurfList[data.SrcSubResourceIndex].Width; + LONG srcHeight = srcResource->m_fixedData.pSurfList[data.SrcSubResourceIndex].Height; data.SrcRect = { 0, 0, srcWidth, srcHeight }; - data.DstRect = g_presentationRect; + if (!IsRectEmpty(&g_presentationRect)) + { + data.DstRect = g_presentationRect; + } auto& repo = SurfaceRepository::get(m_device.getAdapter()); const auto& rtSurface = repo.getTempRenderTarget(srcWidth, srcHeight); @@ -1078,14 +1081,18 @@ namespace D3dDdi pal[i].rgbGreen = entries[i].peGreen; 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 { - copySubResourceRegion(*rt, rtIndex, rtRect, *srcResource, 0, data.SrcRect); + copySubResourceRegion(*rt, rtIndex, rtRect, *srcResource, data.SrcSubResourceIndex, data.SrcRect); } - presentLayeredWindows(*rt, rtIndex, rtRect); + if (!IsRectEmpty(&g_presentationRect)) + { + presentLayeredWindows(*rt, rtIndex, rtRect); + } const auto cursorInfo = Gdi::Cursor::getEmulatedCursorInfo(); const bool isCursorEmulated = cursorInfo.flags == CURSOR_SHOWING && cursorInfo.hCursor; diff --git a/DDrawCompat/D3dDdi/Resource.h b/DDrawCompat/D3dDdi/Resource.h index 56d0159..ee16abe 100644 --- a/DDrawCompat/D3dDdi/Resource.h +++ b/DDrawCompat/D3dDdi/Resource.h @@ -45,6 +45,7 @@ namespace D3dDdi void prepareForCpuWrite(UINT subResourceIndex); Resource& prepareForGpuRead(UINT subResourceIndex); void prepareForGpuWrite(UINT subResourceIndex); + HRESULT presentationBlt(D3DDDIARG_BLT data, Resource* srcResource); void scaleRect(RECT& rect); void setAsGdiResource(bool isGdiResource); void setAsPrimary(); @@ -106,7 +107,6 @@ namespace D3dDdi void loadSysMemResource(UINT subResourceIndex); void loadVidMemResource(UINT subResourceIndex); void notifyLock(UINT subResourceIndex); - HRESULT presentationBlt(D3DDDIARG_BLT data, Resource* srcResource); void presentLayeredWindows(Resource& dst, UINT dstSubResourceIndex, const RECT& dstRect); HRESULT shaderBlt(D3DDDIARG_BLT& data, Resource& dstResource, Resource& srcResource); diff --git a/DDrawCompat/D3dDdi/ShaderBlitter.cpp b/DDrawCompat/D3dDdi/ShaderBlitter.cpp index 169bbb3..4ad93e4 100644 --- a/DDrawCompat/D3dDdi/ShaderBlitter.cpp +++ b/DDrawCompat/D3dDdi/ShaderBlitter.cpp @@ -317,10 +317,11 @@ namespace D3dDdi } 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(dstResource), dstSubResourceIndex, dstRect, - static_cast(srcResource), srcRect, Compat::array(reinterpret_cast(palette), 256)); + static_cast(srcResource), srcSubResourceIndex, srcRect, + Compat::array(reinterpret_cast(palette), 256)); auto paletteTexture(SurfaceRepository::get(m_device.getAdapter()).getPaletteTexture()); if (!paletteTexture) @@ -344,7 +345,8 @@ namespace D3dDdi m_device.getOrigVtable().pfnUnlock(m_device, &unlock); 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() diff --git a/DDrawCompat/D3dDdi/ShaderBlitter.h b/DDrawCompat/D3dDdi/ShaderBlitter.h index b6e3799..e826f09 100644 --- a/DDrawCompat/D3dDdi/ShaderBlitter.h +++ b/DDrawCompat/D3dDdi/ShaderBlitter.h @@ -34,7 +34,7 @@ namespace D3dDdi const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, const Resource& lockRefResource); 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, const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, UINT filter, const UINT* srcColorKey = nullptr, const BYTE* alpha = nullptr, diff --git a/DDrawCompat/DDraw/RealPrimarySurface.cpp b/DDrawCompat/DDraw/RealPrimarySurface.cpp index 5786482..c5dde47 100644 --- a/DDrawCompat/DDraw/RealPrimarySurface.cpp +++ b/DDrawCompat/DDraw/RealPrimarySurface.cpp @@ -9,12 +9,16 @@ #include #include #include +#include +#include +#include #include #include #include #include #include #include +#include #include #include #include @@ -34,6 +38,7 @@ namespace void onRelease(); CompatWeakPtr g_frontBuffer; + CompatWeakPtr g_windowedBackBuffer; CompatWeakPtr g_clipper; RECT g_monitorRect = {}; DDSURFACEDESC2 g_surfaceDesc = {}; @@ -65,7 +70,24 @@ namespace { 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; } @@ -76,6 +98,48 @@ namespace } } + CompatPtr 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 getBackBuffer() { DDSCAPS2 caps = {}; @@ -133,6 +197,7 @@ namespace g_frontBuffer = nullptr; g_lastFlipSurface = nullptr; + g_windowedBackBuffer.release(); g_clipper.release(); g_isFullscreen = false; g_surfaceDesc = {}; @@ -164,6 +229,11 @@ namespace D3dDdi::KernelModeThunks::waitForVsyncCounter(D3dDdi::KernelModeThunks::getVsyncCounter() + 1); } + if (g_windowedBackBuffer) + { + g_windowedBackBuffer->Restore(g_windowedBackBuffer); + } + Compat::ScopedCriticalSection lock(g_presentCs); g_isUpdatePending = false; g_isUpdateReady = false; @@ -204,11 +274,7 @@ namespace Gdi::Region excludeRegion(DDraw::PrimarySurface::getMonitorRect()); Gdi::Window::present(excludeRegion); - - auto palette(Gdi::Palette::getHardwarePalette()); - D3dDdi::KernelModeThunks::setDcPaletteOverride(palette.data()); bltToPrimaryChain(*src); - D3dDdi::KernelModeThunks::setDcPaletteOverride(nullptr); } void updateNow(CompatWeakPtr src) @@ -282,6 +348,17 @@ namespace DDraw 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::from(surface.get()).detach(); g_frontBuffer->SetPrivateData(g_frontBuffer, IID_IReleaseNotifier, &g_releaseNotifier, sizeof(&g_releaseNotifier), DDSPD_IUNKNOWNPOINTER); diff --git a/DDrawCompat/DDraw/Surfaces/TagSurface.cpp b/DDrawCompat/DDraw/Surfaces/TagSurface.cpp index 74ea9db..41866d2 100644 --- a/DDrawCompat/DDraw/Surfaces/TagSurface.cpp +++ b/DDrawCompat/DDraw/Surfaces/TagSurface.cpp @@ -67,14 +67,24 @@ namespace DDraw } } - TagSurface* TagSurface::get(CompatRef dd) + TagSurface* TagSurface::get(DDRAWI_DIRECTDRAW_LCL* ddLcl) { - auto ddLcl = DDraw::DirectDraw::getInt(dd.get()).lpLcl; auto it = g_ddObjects.find(ddLcl); if (it != g_ddObjects.end()) { return it->second; } + return nullptr; + } + + TagSurface* TagSurface::get(CompatRef dd) + { + auto ddLcl = DDraw::DirectDraw::getInt(dd.get()).lpLcl; + auto tagSurface = get(ddLcl); + if (tagSurface) + { + return tagSurface; + } if (FAILED(create(dd))) { diff --git a/DDrawCompat/DDraw/Surfaces/TagSurface.h b/DDrawCompat/DDraw/Surfaces/TagSurface.h index d22e378..b8a4169 100644 --- a/DDrawCompat/DDraw/Surfaces/TagSurface.h +++ b/DDrawCompat/DDraw/Surfaces/TagSurface.h @@ -15,6 +15,7 @@ namespace DDraw TagSurface(DWORD origCaps, DDRAWI_DIRECTDRAW_LCL* ddLcl); virtual ~TagSurface() override; + static TagSurface* get(DDRAWI_DIRECTDRAW_LCL* ddLcl); static TagSurface* get(CompatRef dd); static TagSurface* findFullscreenWindow(HWND hwnd);