diff --git a/DDrawCompat/D3dDdi/Resource.cpp b/DDrawCompat/D3dDdi/Resource.cpp index 738d9a5..aca08e8 100644 --- a/DDrawCompat/D3dDdi/Resource.cpp +++ b/DDrawCompat/D3dDdi/Resource.cpp @@ -16,6 +16,7 @@ #include #include #include +#include namespace { @@ -537,15 +538,19 @@ namespace D3dDdi srcResource->copyToVidMem(0); } - const auto& si = srcResource->m_fixedData.pSurfList[0]; const bool isPalettized = D3DDDIFMT_P8 == srcResource->m_origData.Format; + const auto cursorInfo = Gdi::Cursor::getEmulatedCursorInfo(); const bool isCursorEmulated = cursorInfo.flags == CURSOR_SHOWING && cursorInfo.hCursor; - if (isPalettized || isCursorEmulated) + const RECT monitorRect = DDraw::PrimarySurface::getMonitorRect(); + const bool isLayeredPresentNeeded = Gdi::Window::presentLayered(nullptr, monitorRect); + + if (isPalettized || isCursorEmulated || isLayeredPresentNeeded) { - auto dst(SurfaceRepository::get(m_device.getAdapter()).getRenderTarget(si.Width, si.Height)); - if (!dst) + const auto& si = srcResource->m_fixedData.pSurfList[0]; + const auto& dst(SurfaceRepository::get(m_device.getAdapter()).getRenderTarget(si.Width, si.Height)); + if (!dst.resource) { return E_OUTOFMEMORY; } @@ -560,28 +565,32 @@ namespace D3dDdi pal[i].rgbGreen = entries[i].peGreen; pal[i].rgbBlue = entries[i].peBlue; } - m_device.getShaderBlitter().palettizedBlt(*dst, 0, *srcResource, pal); + m_device.getShaderBlitter().palettizedBlt(*dst.resource, 0, *srcResource, pal); } else { D3DDDIARG_BLT blt = {}; blt.hSrcResource = data.hSrcResource; blt.SrcRect = data.SrcRect; - blt.hDstResource = *dst; + blt.hDstResource = *dst.resource; blt.DstRect = data.SrcRect; blt.Flags.Point = 1; m_device.getOrigVtable().pfnBlt(m_device, &blt); } - srcResource = dst; - data.hSrcResource = *dst; - } + srcResource = dst.resource; + data.hSrcResource = *dst.resource; - if (isCursorEmulated) - { - RECT monitorRect = DDraw::PrimarySurface::getMonitorRect(); - POINT pos = { cursorInfo.ptScreenPos.x - monitorRect.left, cursorInfo.ptScreenPos.y - monitorRect.top }; - m_device.getShaderBlitter().cursorBlt(*srcResource, 0, cursorInfo.hCursor, pos); + if (isLayeredPresentNeeded) + { + Gdi::Window::presentLayered(dst.surface, monitorRect); + } + + if (isCursorEmulated) + { + POINT pos = { cursorInfo.ptScreenPos.x - monitorRect.left, cursorInfo.ptScreenPos.y - monitorRect.top }; + m_device.getShaderBlitter().cursorBlt(*srcResource, 0, cursorInfo.hCursor, pos); + } } data.DstRect = g_presentationRect; diff --git a/DDrawCompat/D3dDdi/SurfaceRepository.cpp b/DDrawCompat/D3dDdi/SurfaceRepository.cpp index 0cd1abb..c16305b 100644 --- a/DDrawCompat/D3dDdi/SurfaceRepository.cpp +++ b/DDrawCompat/D3dDdi/SurfaceRepository.cpp @@ -205,13 +205,19 @@ namespace D3dDdi DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY); } - Resource* SurfaceRepository::getRenderTarget(DWORD width, DWORD height) + const SurfaceRepository::Surface& SurfaceRepository::getRenderTarget(DWORD width, DWORD height) { - return getResource(m_renderTarget, width, height, DDraw::DirectDraw::getRgbPixelFormat(32), + return getSurface(m_renderTarget, width, height, DDraw::DirectDraw::getRgbPixelFormat(32), DDSCAPS_3DDEVICE | DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY); } Resource* SurfaceRepository::getResource(Surface& surface, DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps) + { + return getSurface(surface, width, height, pf, caps).resource; + } + + SurfaceRepository::Surface& SurfaceRepository::getSurface(Surface& surface, DWORD width, DWORD height, + const DDPIXELFORMAT& pf, DWORD caps) { if (surface.surface && (surface.width != width || surface.height != height || 0 != memcmp(&surface.pixelFormat, &pf, sizeof(pf)) || isLost(surface))) @@ -232,7 +238,7 @@ namespace D3dDdi } } - return surface.resource; + return surface; } bool SurfaceRepository::isLost(Surface& surface) diff --git a/DDrawCompat/D3dDdi/SurfaceRepository.h b/DDrawCompat/D3dDdi/SurfaceRepository.h index 1a390db..e711164 100644 --- a/DDrawCompat/D3dDdi/SurfaceRepository.h +++ b/DDrawCompat/D3dDdi/SurfaceRepository.h @@ -24,14 +24,6 @@ namespace D3dDdi Resource* tempTexture; }; - Cursor getCursor(HCURSOR cursor); - Resource* getLogicalXorTexture(); - Resource* getPaletteTexture(); - Resource* getRenderTarget(DWORD width, DWORD height); - - static SurfaceRepository& get(const Adapter& adapter); - - private: struct Surface { CompatWeakPtr surface; @@ -41,6 +33,14 @@ namespace D3dDdi DDPIXELFORMAT pixelFormat; }; + Cursor getCursor(HCURSOR cursor); + Resource* getLogicalXorTexture(); + Resource* getPaletteTexture(); + const Surface& getRenderTarget(DWORD width, DWORD height); + + static SurfaceRepository& get(const Adapter& adapter); + + private: SurfaceRepository(const Adapter& adapter); CompatWeakPtr createSurface(DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps); @@ -48,6 +48,7 @@ namespace D3dDdi Resource* getInitializedResource(Surface& surface, DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps, std::function initFunc); Resource* getResource(Surface& surface, DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps); + Surface& getSurface(Surface& surface, DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps); bool isLost(Surface& surface); void release(Surface& surface); diff --git a/DDrawCompat/DDraw/RealPrimarySurface.cpp b/DDrawCompat/DDraw/RealPrimarySurface.cpp index 8e584fa..7f73420 100644 --- a/DDrawCompat/DDraw/RealPrimarySurface.cpp +++ b/DDrawCompat/DDraw/RealPrimarySurface.cpp @@ -176,16 +176,6 @@ namespace D3dDdi::KernelModeThunks::setDcPaletteOverride(palette.data()); bltToPrimaryChain(*src); D3dDdi::KernelModeThunks::setDcPaletteOverride(nullptr); - - if (g_isFullScreen && src == DDraw::PrimarySurface::getGdiSurface()) - { - auto backBuffer(getBackBuffer()); - if (backBuffer) - { - POINT offset = { -g_monitorRect.left, -g_monitorRect.top }; - Gdi::Window::presentLayered(*backBuffer, offset); - } - } } void updateNow(CompatWeakPtr src, UINT flipInterval) diff --git a/DDrawCompat/Gdi/WinProc.cpp b/DDrawCompat/Gdi/WinProc.cpp index fce6123..d961af5 100644 --- a/DDrawCompat/Gdi/WinProc.cpp +++ b/DDrawCompat/Gdi/WinProc.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -268,11 +269,9 @@ namespace { LOG_FUNC("SetLayeredWindowAttributes", hwnd, crKey, bAlpha, dwFlags); BOOL result = CALL_ORIG_FUNC(SetLayeredWindowAttributes)(hwnd, crKey, bAlpha, dwFlags); - if (result) + if (result && DDraw::RealPrimarySurface::isFullScreen()) { - Gdi::Window::updateLayeredWindowInfo(hwnd, - (dwFlags & LWA_COLORKEY) ? crKey : CLR_INVALID, - (dwFlags & LWA_ALPHA) ? bAlpha : 255); + DDraw::RealPrimarySurface::scheduleUpdate(); } return LOG_RESULT(result); } @@ -340,34 +339,6 @@ namespace } } - BOOL WINAPI updateLayeredWindow(HWND hWnd, HDC hdcDst, POINT* pptDst, SIZE* psize, - HDC hdcSrc, POINT* pptSrc, COLORREF crKey, BLENDFUNCTION* pblend, DWORD dwFlags) - { - LOG_FUNC("UpdateLayeredWindow", hWnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags); - BOOL result = CALL_ORIG_FUNC(UpdateLayeredWindow)( - hWnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags); - if (result && hdcSrc) - { - Gdi::Window::updateLayeredWindowInfo(hWnd, - (dwFlags & ULW_COLORKEY) ? crKey : CLR_INVALID, - ((dwFlags & LWA_ALPHA) && pblend) ? pblend->SourceConstantAlpha : 255); - } - return LOG_RESULT(result); - } - - BOOL WINAPI updateLayeredWindowIndirect(HWND hwnd, const UPDATELAYEREDWINDOWINFO* pULWInfo) - { - LOG_FUNC("UpdateLayeredWindowIndirect", hwnd, pULWInfo); - BOOL result = CALL_ORIG_FUNC(UpdateLayeredWindowIndirect)(hwnd, pULWInfo); - if (result && pULWInfo) - { - Gdi::Window::updateLayeredWindowInfo(hwnd, - (pULWInfo->dwFlags & ULW_COLORKEY) ? pULWInfo->crKey : CLR_INVALID, - ((pULWInfo->dwFlags & LWA_ALPHA) && pULWInfo->pblend) ? pULWInfo->pblend->SourceConstantAlpha : 255); - } - return LOG_RESULT(result); - } - void CALLBACK winEventProc( HWINEVENTHOOK /*hWinEventHook*/, DWORD event, @@ -393,7 +364,7 @@ namespace case EVENT_OBJECT_HIDE: if (OBJID_CURSOR == idObject && Gdi::Cursor::isEmulated()) { - Gdi::Cursor::setCursor(GetCursor()); + Gdi::Cursor::setCursor(CALL_ORIG_FUNC(GetCursor)()); } break; @@ -465,8 +436,6 @@ namespace Gdi HOOK_FUNCTION(user32, SetWindowLongA, setWindowLongA); HOOK_FUNCTION(user32, SetWindowLongW, setWindowLongW); HOOK_FUNCTION(user32, SetWindowPos, setWindowPos); - HOOK_FUNCTION(user32, UpdateLayeredWindow, updateLayeredWindow); - HOOK_FUNCTION(user32, UpdateLayeredWindowIndirect, updateLayeredWindowIndirect); SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, Dll::g_currentModule, &winEventProc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT); diff --git a/DDrawCompat/Gdi/Window.cpp b/DDrawCompat/Gdi/Window.cpp index bd1c184..0f36f93 100644 --- a/DDrawCompat/Gdi/Window.cpp +++ b/DDrawCompat/Gdi/Window.cpp @@ -31,8 +31,6 @@ namespace Gdi::Region windowRegion; Gdi::Region visibleRegion; Gdi::Region invalidatedRegion; - COLORREF colorKey; - BYTE alpha; bool isLayered; bool isVisibleRegionChanged; @@ -42,8 +40,6 @@ namespace , windowRect{} , clientRect{} , windowRegion(nullptr) - , colorKey(CLR_INVALID) - , alpha(255) , isLayered(true) , isVisibleRegionChanged(false) { @@ -447,56 +443,64 @@ namespace Gdi } } - void presentLayered(CompatRef dst, POINT offset) + bool presentLayered(CompatWeakPtr dst, const RECT& monitorRect) { - D3dDdi::ScopedCriticalSection lock; - HDC dstDc = nullptr; + bool result = false; for (auto it = g_windowZOrder.rbegin(); it != g_windowZOrder.rend(); ++it) { auto& window = **it; - if (!window.isLayered) + if (!window.isLayered || window.visibleRegion.isEmpty()) { continue; } + Gdi::Region rgn(window.visibleRegion); + rgn &= monitorRect; + if (rgn.isEmpty()) + { + continue; + } + + RECT wr = window.windowRect; + OffsetRect(&wr, -monitorRect.left, -monitorRect.top); + rgn.offset(-monitorRect.left, -monitorRect.top); + + if (!dst) + { + return true; + } + if (!dstDc) { - const UINT D3DDDIFMT_UNKNOWN = 0; - const UINT D3DDDIFMT_X8R8G8B8 = 22; - D3dDdi::KernelModeThunks::setDcFormatOverride(D3DDDIFMT_X8R8G8B8); - dst->GetDC(&dst, &dstDc); - D3dDdi::KernelModeThunks::setDcFormatOverride(D3DDDIFMT_UNKNOWN); + dst->GetDC(dst, &dstDc); if (!dstDc) { - return; + return false; } } + result = true; HDC windowDc = GetWindowDC(window.hwnd); - Gdi::Region rgn(window.visibleRegion); - RECT wr = window.windowRect; - - if (0 != offset.x || 0 != offset.y) - { - OffsetRect(&wr, offset.x, offset.y); - rgn.offset(offset.x, offset.y); - } - SelectClipRgn(dstDc, rgn); - auto colorKey = window.colorKey; - if (CLR_INVALID != colorKey) + COLORREF colorKey = 0; + BYTE alpha = 0; + DWORD flags = 0; + if (CALL_ORIG_FUNC(GetLayeredWindowAttributes)(window.hwnd, &colorKey, &alpha, &flags)) { - CALL_ORIG_FUNC(TransparentBlt)(dstDc, wr.left, wr.top, wr.right - wr.left, wr.bottom - wr.top, - windowDc, 0, 0, wr.right - wr.left, wr.bottom - wr.top, colorKey); - } - else - { - BLENDFUNCTION blend = {}; - blend.SourceConstantAlpha = window.alpha; - CALL_ORIG_FUNC(AlphaBlend)(dstDc, wr.left, wr.top, wr.right - wr.left, wr.bottom - wr.top, - windowDc, 0, 0, wr.right - wr.left, wr.bottom - wr.top, blend); + if (flags & LWA_COLORKEY) + { + CALL_ORIG_FUNC(TransparentBlt)(dstDc, wr.left, wr.top, wr.right - wr.left, wr.bottom - wr.top, + windowDc, 0, 0, wr.right - wr.left, wr.bottom - wr.top, colorKey); + } + else + { + BLENDFUNCTION blend = {}; + blend.SourceConstantAlpha = alpha; + CALL_ORIG_FUNC(AlphaBlend)(dstDc, wr.left, wr.top, wr.right - wr.left, wr.bottom - wr.top, + windowDc, 0, 0, wr.right - wr.left, wr.bottom - wr.top, blend); + } } CALL_ORIG_FUNC(ReleaseDC)(window.hwnd, windowDc); @@ -505,8 +509,9 @@ namespace Gdi if (dstDc) { SelectClipRgn(dstDc, nullptr); - dst->ReleaseDC(&dst, dstDc); + dst->ReleaseDC(dst, dstDc); } + return result; } void updateAll() @@ -558,20 +563,5 @@ namespace Gdi SendNotifyMessage(hwnd, WM_SYNCPAINT, 0, 0); } } - - void updateLayeredWindowInfo(HWND hwnd, COLORREF colorKey, BYTE alpha) - { - D3dDdi::ScopedCriticalSection lock; - auto it = g_windows.find(hwnd); - if (it != g_windows.end()) - { - it->second.colorKey = colorKey; - it->second.alpha = alpha; - if (!it->second.visibleRegion.isEmpty()) - { - DDraw::RealPrimarySurface::scheduleUpdate(); - } - } - } } } diff --git a/DDrawCompat/Gdi/Window.h b/DDrawCompat/Gdi/Window.h index 38bb546..2a4cfe2 100644 --- a/DDrawCompat/Gdi/Window.h +++ b/DDrawCompat/Gdi/Window.h @@ -2,6 +2,7 @@ #include +#include #include #include @@ -14,8 +15,7 @@ namespace Gdi void present(CompatRef dst, CompatRef src, CompatRef clipper); void present(Gdi::Region excludeRegion); - void presentLayered(CompatRef dst, POINT offset); + bool presentLayered(CompatWeakPtr dst, const RECT& monitorRect); void updateAll(); - void updateLayeredWindowInfo(HWND hwnd, COLORREF colorKey, BYTE alpha); } }