From ccc23c75b9902fe0074a284d706923921162f39d Mon Sep 17 00:00:00 2001 From: narzoul Date: Tue, 15 Jun 2021 23:14:33 +0200 Subject: [PATCH] Emulate hardware cursor in scaled fullscreen mode --- DDrawCompat/Common/Comparison.h | 6 + DDrawCompat/D3dDdi/Device.cpp | 16 +- DDrawCompat/D3dDdi/Device.h | 4 +- DDrawCompat/D3dDdi/KernelModeThunks.cpp | 9 +- DDrawCompat/D3dDdi/KernelModeThunks.h | 2 +- DDrawCompat/D3dDdi/Resource.cpp | 79 ++++++-- DDrawCompat/D3dDdi/Resource.h | 13 +- DDrawCompat/D3dDdi/ShaderBlitter.cpp | 44 +++- DDrawCompat/D3dDdi/ShaderBlitter.h | 8 + DDrawCompat/D3dDdi/SurfaceRepository.cpp | 177 ++++++++++++++-- DDrawCompat/D3dDdi/SurfaceRepository.h | 33 ++- DDrawCompat/DDraw/RealPrimarySurface.cpp | 17 +- DDrawCompat/DDrawCompat.vcxproj | 3 + DDrawCompat/DDrawCompat.vcxproj.filters | 9 + DDrawCompat/Gdi/Cursor.cpp | 248 +++++++++++++++++++++++ DDrawCompat/Gdi/Cursor.h | 17 ++ DDrawCompat/Gdi/Gdi.cpp | 2 + DDrawCompat/Gdi/User32WndProcs.cpp | 53 +++++ DDrawCompat/Gdi/WinProc.cpp | 134 ++++++------ DDrawCompat/Shaders/DrawCursor.hlsl | 19 ++ DDrawCompat/Win32/DisplayMode.cpp | 47 ----- 21 files changed, 771 insertions(+), 169 deletions(-) create mode 100644 DDrawCompat/Gdi/Cursor.cpp create mode 100644 DDrawCompat/Gdi/Cursor.h create mode 100644 DDrawCompat/Shaders/DrawCursor.hlsl diff --git a/DDrawCompat/Common/Comparison.h b/DDrawCompat/Common/Comparison.h index e58b92c..b4c5768 100644 --- a/DDrawCompat/Common/Comparison.h +++ b/DDrawCompat/Common/Comparison.h @@ -11,6 +11,12 @@ std::enable_if_t && std::is_trivial_v, bool> operator==(co return toTuple(left) == toTuple(right); } +template +std::enable_if_t&& std::is_trivial_v, bool> operator!=(const T& left, const T& right) +{ + return toTuple(left) != toTuple(right); +} + template std::enable_if_t && std::is_trivial_v, bool> operator<(const T& left, const T& right) { diff --git a/DDrawCompat/D3dDdi/Device.cpp b/DDrawCompat/D3dDdi/Device.cpp index de2e8d2..5c5d295 100644 --- a/DDrawCompat/D3dDdi/Device.cpp +++ b/DDrawCompat/D3dDdi/Device.cpp @@ -82,7 +82,7 @@ namespace D3dDdi Resource* Device::getResource(HANDLE resource) { auto it = m_resources.find(resource); - return it != m_resources.end() ? &it->second : nullptr; + return it != m_resources.end() ? it->second.get() : nullptr; } void Device::prepareForRendering(HANDLE resource, UINT subResourceIndex, bool isReadOnly) @@ -90,7 +90,7 @@ namespace D3dDdi auto it = m_resources.find(resource); if (it != m_resources.end()) { - it->second.prepareForRendering(subResourceIndex, isReadOnly); + it->second->prepareForRendering(subResourceIndex, isReadOnly); } } @@ -140,7 +140,7 @@ namespace D3dDdi auto it = m_resources.find(data->hDstResource); if (it != m_resources.end()) { - return it->second.blt(*data); + return it->second->blt(*data); } prepareForRendering(data->hSrcResource, data->SrcSubResourceIndex, true); return m_origVtable.pfnBlt(m_device, data); @@ -162,7 +162,7 @@ namespace D3dDdi auto it = m_resources.find(data->hResource); if (it != m_resources.end()) { - return it->second.colorFill(*data); + return it->second->colorFill(*data); } return m_origVtable.pfnColorFill(m_device, data); } @@ -180,8 +180,8 @@ namespace D3dDdi { try { - Resource resource(*this, *data); - m_resources.emplace(resource, std::move(resource)); + auto resource(std::make_unique(*this, *data)); + m_resources.emplace(*resource, std::move(resource)); if (data->Flags.VertexBuffer && D3DDDIPOOL_SYSTEMMEM == data->Pool && data->pSurfList[0].pSysMem) @@ -283,7 +283,7 @@ namespace D3dDdi auto it = m_resources.find(data->hResource); if (it != m_resources.end()) { - return it->second.lock(*data); + return it->second->lock(*data); } return m_origVtable.pfnLock(m_device, data); } @@ -321,7 +321,7 @@ namespace D3dDdi auto it = m_resources.find(data->hResource); if (it != m_resources.end()) { - return it->second.unlock(*data); + return it->second->unlock(*data); } return m_origVtable.pfnUnlock(m_device, data); } diff --git a/DDrawCompat/D3dDdi/Device.h b/DDrawCompat/D3dDdi/Device.h index e3f2ac4..924b6c6 100644 --- a/DDrawCompat/D3dDdi/Device.h +++ b/DDrawCompat/D3dDdi/Device.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include @@ -71,7 +71,7 @@ namespace D3dDdi D3DDDI_DEVICEFUNCS m_origVtable; Adapter& m_adapter; HANDLE m_device; - std::unordered_map m_resources; + std::map> m_resources; Resource* m_renderTarget; UINT m_renderTargetSubResourceIndex; HANDLE m_sharedPrimary; diff --git a/DDrawCompat/D3dDdi/KernelModeThunks.cpp b/DDrawCompat/D3dDdi/KernelModeThunks.cpp index 4cf5190..2721442 100644 --- a/DDrawCompat/D3dDdi/KernelModeThunks.cpp +++ b/DDrawCompat/D3dDdi/KernelModeThunks.cpp @@ -19,7 +19,7 @@ namespace { D3DDDIFORMAT g_dcFormatOverride = D3DDDIFMT_UNKNOWN; - bool g_dcPaletteOverride = false; + PALETTEENTRY* g_dcPaletteOverride = nullptr; D3dDdi::KernelModeThunks::AdapterInfo g_gdiAdapterInfo = {}; D3dDdi::KernelModeThunks::AdapterInfo g_lastOpenAdapterInfo = {}; Compat::SrwLock g_lastOpenAdapterInfoSrwLock; @@ -59,8 +59,7 @@ namespace { if (g_dcPaletteOverride) { - palette = Gdi::Palette::getHardwarePalette(); - pData->pColorTable = palette.data(); + pData->pColorTable = g_dcPaletteOverride; } else { @@ -313,9 +312,9 @@ namespace D3dDdi g_dcFormatOverride = static_cast(format); } - void setDcPaletteOverride(bool enable) + void setDcPaletteOverride(PALETTEENTRY* palette) { - g_dcPaletteOverride = enable; + g_dcPaletteOverride = palette; } void waitForVsync() diff --git a/DDrawCompat/D3dDdi/KernelModeThunks.h b/DDrawCompat/D3dDdi/KernelModeThunks.h index 072d4f1..bb57b15 100644 --- a/DDrawCompat/D3dDdi/KernelModeThunks.h +++ b/DDrawCompat/D3dDdi/KernelModeThunks.h @@ -22,7 +22,7 @@ namespace D3dDdi UINT getVsyncCounter(); void installHooks(); void setDcFormatOverride(UINT format); - void setDcPaletteOverride(bool enable); + void setDcPaletteOverride(PALETTEENTRY* palette); void waitForVsync(); bool waitForVsyncCounter(UINT counter); } diff --git a/DDrawCompat/D3dDdi/Resource.cpp b/DDrawCompat/D3dDdi/Resource.cpp index 03765e4..738d9a5 100644 --- a/DDrawCompat/D3dDdi/Resource.cpp +++ b/DDrawCompat/D3dDdi/Resource.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -113,6 +114,14 @@ namespace D3dDdi if (m_origData.Flags.Primary) { g_presentationRect = calculatePresentationRect(); + auto& si = m_origData.pSurfList[0]; + RECT rect = { 0, 0, static_cast(si.Width), static_cast(si.Height) }; + + Gdi::Cursor::setMonitorClipRect(DDraw::PrimarySurface::getMonitorRect()); + if (!EqualRect(&g_presentationRect, &rect)) + { + Gdi::Cursor::setEmulated(true); + } } fixResourceData(); @@ -141,6 +150,15 @@ namespace D3dDdi data.hResource = m_fixedData.hResource; } + Resource::~Resource() + { + if (m_origData.Flags.Primary) + { + Gdi::Cursor::setEmulated(false); + Gdi::Cursor::setMonitorClipRect({}); + } + } + HRESULT Resource::blt(D3DDDIARG_BLT data) { if (!isValidRect(data.DstSubResourceIndex, data.DstRect)) @@ -177,7 +195,7 @@ namespace D3dDdi } else if (m_fixedData.Flags.Primary) { - return presentationBlt(data, *srcResource); + return presentationBlt(data, srcResource); } else { @@ -511,36 +529,59 @@ namespace D3dDdi } } - HRESULT Resource::presentationBlt(D3DDDIARG_BLT data, Resource& srcResource) + HRESULT Resource::presentationBlt(D3DDDIARG_BLT data, Resource* srcResource) { - if (srcResource.m_lockResource && - srcResource.m_lockData[0].isSysMemUpToDate) + if (srcResource->m_lockResource && + srcResource->m_lockData[0].isSysMemUpToDate) { - srcResource.copyToVidMem(0); + srcResource->copyToVidMem(0); } - if (D3DDDIFMT_P8 == srcResource.m_origData.Format) + 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 auto& si = srcResource.m_fixedData.pSurfList[0]; - auto palettizedBltRenderTarget(SurfaceRepository::get(m_device.getAdapter()).getPaletteBltRenderTarget( - si.Width, si.Height)); - if (!palettizedBltRenderTarget) + auto dst(SurfaceRepository::get(m_device.getAdapter()).getRenderTarget(si.Width, si.Height)); + if (!dst) { return E_OUTOFMEMORY; } - auto entries(Gdi::Palette::getHardwarePalette()); - RGBQUAD pal[256] = {}; - for (UINT i = 0; i < 256; ++i) + if (isPalettized) { - pal[i].rgbRed = entries[i].peRed; - pal[i].rgbGreen = entries[i].peGreen; - pal[i].rgbBlue = entries[i].peBlue; + auto entries(Gdi::Palette::getHardwarePalette()); + RGBQUAD pal[256] = {}; + for (UINT i = 0; i < 256; ++i) + { + pal[i].rgbRed = entries[i].peRed; + pal[i].rgbGreen = entries[i].peGreen; + pal[i].rgbBlue = entries[i].peBlue; + } + m_device.getShaderBlitter().palettizedBlt(*dst, 0, *srcResource, pal); + } + else + { + D3DDDIARG_BLT blt = {}; + blt.hSrcResource = data.hSrcResource; + blt.SrcRect = data.SrcRect; + blt.hDstResource = *dst; + blt.DstRect = data.SrcRect; + blt.Flags.Point = 1; + m_device.getOrigVtable().pfnBlt(m_device, &blt); } - m_device.getShaderBlitter().palettizedBlt(*palettizedBltRenderTarget, 0, srcResource, pal); - data.hSrcResource = *palettizedBltRenderTarget; - data.SrcSubResourceIndex = 0; + srcResource = dst; + data.hSrcResource = *dst; + } + + 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); } data.DstRect = g_presentationRect; diff --git a/DDrawCompat/D3dDdi/Resource.h b/DDrawCompat/D3dDdi/Resource.h index f05e483..cf72775 100644 --- a/DDrawCompat/D3dDdi/Resource.h +++ b/DDrawCompat/D3dDdi/Resource.h @@ -18,10 +18,10 @@ namespace D3dDdi Resource(Device& device, D3DDDIARG_CREATERESOURCE2& data); Resource(const Resource&) = delete; + Resource(Resource&&) = delete; Resource& operator=(const Resource&) = delete; - - Resource(Resource&&) = default; - Resource& operator=(Resource&&) = default; + Resource& operator=(Resource&&) = delete; + ~Resource(); operator HANDLE() const { return m_handle; } const D3DDDIARG_CREATERESOURCE2& getOrigDesc() const { return m_origData; } @@ -43,10 +43,9 @@ namespace D3dDdi Data(const D3DDDIARG_CREATERESOURCE2& data); Data(const Data&) = delete; + Data(Data&&) = delete; Data& operator=(const Data&) = delete; - - Data(Data&&) = default; - Data& operator=(Data&&) = default; + Data& operator=(Data&&) = delete; std::vector surfaceData; }; @@ -83,7 +82,7 @@ namespace D3dDdi void fixResourceData(); bool isOversized() const; bool isValidRect(UINT subResourceIndex, const RECT& rect); - HRESULT presentationBlt(D3DDDIARG_BLT data, Resource& srcResource); + HRESULT presentationBlt(D3DDDIARG_BLT data, Resource* srcResource); HRESULT splitBlt(D3DDDIARG_BLT& data, UINT& subResourceIndex, RECT& rect, RECT& otherRect); template diff --git a/DDrawCompat/D3dDdi/ShaderBlitter.cpp b/DDrawCompat/D3dDdi/ShaderBlitter.cpp index 5a25d06..3834244 100644 --- a/DDrawCompat/D3dDdi/ShaderBlitter.cpp +++ b/DDrawCompat/D3dDdi/ShaderBlitter.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #define CONCAT_(a, b) a##b @@ -14,7 +15,8 @@ namespace D3dDdi { ShaderBlitter::ShaderBlitter(Device& device) : m_device(device) - , m_psPaletteLookup(createPixelShader(g_psPaletteLookup, sizeof(g_psPaletteLookup))) + , m_psDrawCursor(createPixelShader(g_psDrawCursor)) + , m_psPaletteLookup(createPixelShader(g_psPaletteLookup)) , m_vertexShaderDecl(createVertexShaderDecl()) { } @@ -122,6 +124,46 @@ namespace D3dDdi return data.ShaderHandle; } + void ShaderBlitter::cursorBlt(const Resource& dstResource, UINT dstSubResourceIndex, HCURSOR cursor, POINT pt) + { + LOG_FUNC("ShaderBlitter::cursorBlt", static_cast(dstResource), dstSubResourceIndex, cursor, pt); + + auto& repo = SurfaceRepository::get(m_device.getAdapter()); + auto cur = repo.getCursor(cursor); + auto xorTexture = repo.getLogicalXorTexture(); + + pt.x -= cur.hotspot.x; + pt.y -= cur.hotspot.y; + RECT dstRect = { pt.x, pt.y, pt.x + cur.size.cx, pt.y + cur.size.cy }; + + auto& dstDesc = dstResource.getFixedDesc().pSurfList[dstSubResourceIndex]; + RECT clippedDstRect = {}; + clippedDstRect.right = dstDesc.Width; + clippedDstRect.bottom = dstDesc.Height; + IntersectRect(&clippedDstRect, &clippedDstRect, &dstRect); + + if (!cur.maskTexture || !cur.colorTexture || !cur.tempTexture || !xorTexture || IsRectEmpty(&clippedDstRect)) + { + return; + } + + RECT clippedSrcRect = clippedDstRect; + OffsetRect(&clippedSrcRect, -dstRect.left, -dstRect.top); + + D3DDDIARG_BLT data = {}; + data.hSrcResource = dstResource; + data.SrcSubResourceIndex = dstSubResourceIndex; + data.SrcRect = clippedDstRect; + data.hDstResource = *cur.tempTexture; + data.DstRect = clippedSrcRect; + m_device.getOrigVtable().pfnBlt(m_device, &data); + + SCOPED_STATE(Texture, 1, *cur.maskTexture, D3DTEXF_POINT); + SCOPED_STATE(Texture, 2, *cur.colorTexture, D3DTEXF_POINT); + SCOPED_STATE(Texture, 3, *xorTexture, D3DTEXF_POINT); + blt(dstResource, dstSubResourceIndex, clippedDstRect, *cur.tempTexture, clippedSrcRect, m_psDrawCursor, D3DTEXF_POINT); + } + void ShaderBlitter::palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex, const Resource& srcResource, RGBQUAD palette[256]) { diff --git a/DDrawCompat/D3dDdi/ShaderBlitter.h b/DDrawCompat/D3dDdi/ShaderBlitter.h index 45d998a..74fd8b1 100644 --- a/DDrawCompat/D3dDdi/ShaderBlitter.h +++ b/DDrawCompat/D3dDdi/ShaderBlitter.h @@ -16,6 +16,7 @@ namespace D3dDdi ShaderBlitter& operator=(const ShaderBlitter&) = delete; ShaderBlitter& operator=(ShaderBlitter&&) = delete; + void cursorBlt(const Resource& dstResource, UINT dstSubResourceIndex, HCURSOR cursor, POINT pt); void palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex, const Resource& srcResource, RGBQUAD palette[256]); @@ -23,10 +24,17 @@ namespace D3dDdi void blt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect, const Resource& srcResource, const RECT& srcRect, HANDLE pixelShader, UINT filter); + template + HANDLE createPixelShader(const BYTE(&code)[N]) + { + return createPixelShader(code, N); + } + HANDLE createPixelShader(const BYTE* code, UINT size); HANDLE createVertexShaderDecl(); Device& m_device; + HANDLE m_psDrawCursor; HANDLE m_psPaletteLookup; HANDLE m_vertexShaderDecl; }; diff --git a/DDrawCompat/D3dDdi/SurfaceRepository.cpp b/DDrawCompat/D3dDdi/SurfaceRepository.cpp index 9f4cdd2..0cd1abb 100644 --- a/DDrawCompat/D3dDdi/SurfaceRepository.cpp +++ b/DDrawCompat/D3dDdi/SurfaceRepository.cpp @@ -1,8 +1,15 @@ +#undef WIN32_LEAN_AND_MEAN + #include +#include +#include + #include #include #include +#include +#include #include #include @@ -15,6 +22,9 @@ namespace D3dDdi { SurfaceRepository::SurfaceRepository(const Adapter& adapter) : m_adapter(adapter) + , m_cursor(nullptr) + , m_cursorSize{} + , m_cursorHotspot{} { } @@ -57,10 +67,136 @@ namespace D3dDdi return g_repositories.emplace(adapter.getLuid(), SurfaceRepository(adapter)).first->second; } - Resource* SurfaceRepository::getPaletteBltRenderTarget(DWORD width, DWORD height) + Resource* SurfaceRepository::getBitmapResource( + Surface& surface, HBITMAP bitmap, const RECT& rect, const DDPIXELFORMAT& pf, DWORD caps) { - return getResource(m_paletteBltRenderTarget, width, height, DDraw::DirectDraw::getRgbPixelFormat(32), - DDSCAPS_3DDEVICE | DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY); + DWORD width = rect.right - rect.left; + DWORD height = rect.bottom - rect.top; + auto resource = getResource(surface, width, height, pf, caps); + if (!resource) + { + return nullptr; + } + + HDC srcDc = CreateCompatibleDC(nullptr); + HGDIOBJ prevBitmap = SelectObject(srcDc, bitmap); + HDC dstDc = nullptr; + PALETTEENTRY palette[256] = {}; + palette[255] = { 0xFF, 0xFF, 0xFF }; + KernelModeThunks::setDcPaletteOverride(palette); + surface.surface->GetDC(surface.surface, &dstDc); + KernelModeThunks::setDcPaletteOverride(nullptr); + + CALL_ORIG_FUNC(BitBlt)(dstDc, 0, 0, width, height, srcDc, rect.left, rect.top, SRCCOPY); + + surface.surface->ReleaseDC(surface.surface, dstDc); + SelectObject(srcDc, prevBitmap); + DeleteDC(srcDc); + return resource; + } + + SurfaceRepository::Cursor SurfaceRepository::getCursor(HCURSOR cursor) + { + if (isLost(m_cursorMaskTexture) || isLost(m_cursorColorTexture)) + { + m_cursor = nullptr; + release(m_cursorMaskTexture); + release(m_cursorColorTexture); + } + + if (cursor != m_cursor) + { + m_cursor = cursor; + ICONINFO iconInfo = {}; + if (!GetIconInfo(cursor, &iconInfo)) + { + return {}; + } + + BITMAP bm = {}; + GetObject(iconInfo.hbmMask, sizeof(bm), &bm); + + RECT rect = {}; + SetRect(&rect, 0, 0, bm.bmWidth, bm.bmHeight); + if (!iconInfo.hbmColor) + { + rect.bottom /= 2; + } + + getBitmapResource(m_cursorMaskTexture, iconInfo.hbmMask, rect, + DDraw::DirectDraw::getRgbPixelFormat(8), DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY); + + if (iconInfo.hbmColor) + { + getBitmapResource(m_cursorColorTexture, iconInfo.hbmColor, rect, + DDraw::DirectDraw::getRgbPixelFormat(32), DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY); + DeleteObject(iconInfo.hbmColor); + } + else + { + OffsetRect(&rect, 0, rect.bottom); + getBitmapResource(m_cursorColorTexture, iconInfo.hbmMask, rect, + DDraw::DirectDraw::getRgbPixelFormat(8), DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY); + } + DeleteObject(iconInfo.hbmMask); + + m_cursorMaskTexture.resource->prepareForRendering(0, true); + m_cursorColorTexture.resource->prepareForRendering(0, true); + + m_cursorSize.cx = rect.right - rect.left; + m_cursorSize.cy = rect.bottom - rect.top; + m_cursorHotspot.x = iconInfo.xHotspot; + m_cursorHotspot.y = iconInfo.yHotspot; + } + + Cursor result = {}; + result.cursor = m_cursor; + result.size = m_cursorSize; + result.hotspot = m_cursorHotspot; + result.maskTexture = m_cursorMaskTexture.resource; + result.colorTexture = m_cursorColorTexture.resource; + result.tempTexture = getResource(m_cursorTempTexture, m_cursorSize.cx, m_cursorSize.cy, + DDraw::DirectDraw::getRgbPixelFormat(32), DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY); + return result; + } + + Resource* SurfaceRepository::getLogicalXorTexture() + { + return getInitializedResource(m_logicalXorTexture, 256, 256, DDraw::DirectDraw::getRgbPixelFormat(8), + DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, + [](const DDSURFACEDESC2& desc) { + BYTE* p = static_cast(desc.lpSurface); + for (UINT y = 0; y < 256; ++y) + { + for (UINT x = 0; x < 256; ++x) + { + p[x] = static_cast(x ^ y); + } + p += desc.lPitch; + } + }); + } + + Resource* SurfaceRepository::getInitializedResource(Surface& surface, DWORD width, DWORD height, + const DDPIXELFORMAT& pf, DWORD caps, std::function initFunc) + { + if (!isLost(surface) || !getResource(surface, width, height, pf, caps)) + { + return surface.resource; + } + + DDSURFACEDESC2 desc = {}; + desc.dwSize = sizeof(desc); + surface.surface->Lock(surface.surface, nullptr, &desc, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, nullptr); + if (!desc.lpSurface) + { + return nullptr; + } + + initFunc(desc); + surface.surface->Unlock(surface.surface, nullptr); + surface.resource->prepareForRendering(0, true); + return surface.resource; } Resource* SurfaceRepository::getPaletteTexture() @@ -69,18 +205,18 @@ namespace D3dDdi DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY); } + Resource* SurfaceRepository::getRenderTarget(DWORD width, DWORD height) + { + return getResource(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) { - if (surface.surface) + if (surface.surface && (surface.width != width || surface.height != height || + 0 != memcmp(&surface.pixelFormat, &pf, sizeof(pf)) || isLost(surface))) { - DDSURFACEDESC2 desc = {}; - desc.dwSize = sizeof(desc); - surface.surface->GetSurfaceDesc(surface.surface, &desc); - if (desc.dwWidth != width || desc.dwHeight != height || FAILED(surface.surface->IsLost(surface.surface))) - { - surface.surface->Release(surface.surface); - surface = {}; - } + release(surface); } if (!surface.surface) @@ -90,9 +226,26 @@ namespace D3dDdi { surface.resource = D3dDdi::Device::findResource( DDraw::DirectDrawSurface::getDriverResourceHandle(*surface.surface)); + surface.width = width; + surface.height = height; + surface.pixelFormat = pf; } } return surface.resource; } + + bool SurfaceRepository::isLost(Surface& surface) + { + return !surface.surface || FAILED(surface.surface->IsLost(surface.surface)); + } + + void SurfaceRepository::release(Surface& surface) + { + if (surface.surface) + { + surface.surface->Release(surface.surface); + surface = {}; + } + } } diff --git a/DDrawCompat/D3dDdi/SurfaceRepository.h b/DDrawCompat/D3dDdi/SurfaceRepository.h index 6bc9cf5..1a390db 100644 --- a/DDrawCompat/D3dDdi/SurfaceRepository.h +++ b/DDrawCompat/D3dDdi/SurfaceRepository.h @@ -1,5 +1,7 @@ #pragma once +#include + #include #include @@ -12,8 +14,20 @@ namespace D3dDdi class SurfaceRepository { public: - Resource* getPaletteBltRenderTarget(DWORD width, DWORD height); + struct Cursor + { + HCURSOR cursor; + SIZE size; + POINT hotspot; + Resource* maskTexture; + Resource* colorTexture; + Resource* tempTexture; + }; + + Cursor getCursor(HCURSOR cursor); + Resource* getLogicalXorTexture(); Resource* getPaletteTexture(); + Resource* getRenderTarget(DWORD width, DWORD height); static SurfaceRepository& get(const Adapter& adapter); @@ -22,15 +36,30 @@ namespace D3dDdi { CompatWeakPtr surface; Resource* resource; + DWORD width; + DWORD height; + DDPIXELFORMAT pixelFormat; }; SurfaceRepository(const Adapter& adapter); CompatWeakPtr createSurface(DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps); + Resource* getBitmapResource(Surface& surface, HBITMAP bitmap, const RECT& rect, const DDPIXELFORMAT& pf, DWORD caps); + 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); + bool isLost(Surface& surface); + void release(Surface& surface); const Adapter& m_adapter; - Surface m_paletteBltRenderTarget; + HCURSOR m_cursor; + SIZE m_cursorSize; + POINT m_cursorHotspot; + Surface m_cursorMaskTexture; + Surface m_cursorColorTexture; + Surface m_cursorTempTexture; + Surface m_logicalXorTexture; Surface m_paletteTexture; + Surface m_renderTarget; }; } diff --git a/DDrawCompat/DDraw/RealPrimarySurface.cpp b/DDrawCompat/DDraw/RealPrimarySurface.cpp index 9ccbe9b..8e584fa 100644 --- a/DDrawCompat/DDraw/RealPrimarySurface.cpp +++ b/DDrawCompat/DDraw/RealPrimarySurface.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -16,7 +17,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -142,7 +145,7 @@ namespace g_surfaceDesc = desc; g_isFullScreen = isFlippable; - g_isUpdatePending = false; + g_isUpdatePending = true; g_qpcLastUpdate = Time::queryPerformanceCounter() - Time::msToQpc(Config::delayedFlipModeTimeout); if (isFlippable) @@ -169,9 +172,10 @@ namespace Gdi::Region excludeRegion(DDraw::PrimarySurface::getMonitorRect()); Gdi::Window::present(excludeRegion); - D3dDdi::KernelModeThunks::setDcPaletteOverride(true); + auto palette(Gdi::Palette::getHardwarePalette()); + D3dDdi::KernelModeThunks::setDcPaletteOverride(palette.data()); bltToPrimaryChain(*src); - D3dDdi::KernelModeThunks::setDcPaletteOverride(false); + D3dDdi::KernelModeThunks::setDcPaletteOverride(nullptr); if (g_isFullScreen && src == DDraw::PrimarySurface::getGdiSurface()) { @@ -222,10 +226,15 @@ namespace D3dDdi::KernelModeThunks::waitForVsync(); } skipWaitForVsync = false; - Gdi::Caret::blink(); Sleep(1); DDraw::ScopedThreadLock lock; + Gdi::Caret::blink(); + if (Gdi::Cursor::update()) + { + g_isUpdatePending = true; + } + if (g_isUpdatePending && !isPresentPending()) { auto qpcNow = Time::queryPerformanceCounter(); diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index a3f2e57..5a310ee 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -282,6 +282,7 @@ + @@ -366,6 +367,7 @@ + @@ -397,6 +399,7 @@ + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index 4661c43..80a9088 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -435,6 +435,9 @@ Header Files\D3dDdi + + Header Files\Gdi + @@ -683,6 +686,9 @@ Source Files\D3dDdi + + Source Files\Gdi + @@ -698,5 +704,8 @@ Shaders + + Shaders + \ No newline at end of file diff --git a/DDrawCompat/Gdi/Cursor.cpp b/DDrawCompat/Gdi/Cursor.cpp new file mode 100644 index 0000000..f914677 --- /dev/null +++ b/DDrawCompat/Gdi/Cursor.cpp @@ -0,0 +1,248 @@ +#include + +#include +#include +#include +#include +#include + +namespace +{ + RECT g_clipRect = {}; + HCURSOR g_cursor = nullptr; + bool g_isEmulated = false; + RECT g_monitorClipRect = {}; + HCURSOR g_nullCursor = nullptr; + CURSORINFO g_prevCursorInfo = {}; + Compat::CriticalSection g_cs; + + RECT intersectRect(RECT rect1, RECT rect2); + void normalizeRect(RECT& rect); + + BOOL WINAPI clipCursor(const RECT* lpRect) + { + LOG_FUNC("ClipCursor", lpRect); + Compat::ScopedCriticalSection lock(g_cs); + BOOL result = CALL_ORIG_FUNC(ClipCursor)(lpRect); + if (!result || IsRectEmpty(&g_monitorClipRect)) + { + return LOG_RESULT(result); + } + + CALL_ORIG_FUNC(GetClipCursor)(&g_clipRect); + RECT rect = intersectRect(g_clipRect, g_monitorClipRect); + CALL_ORIG_FUNC(ClipCursor)(&rect); + return LOG_RESULT(result); + } + + BOOL WINAPI getClipCursor(LPRECT lpRect) + { + LOG_FUNC("GetClipCursor", lpRect); + Compat::ScopedCriticalSection lock(g_cs); + BOOL result = CALL_ORIG_FUNC(GetClipCursor)(lpRect); + if (result && !IsRectEmpty(&g_monitorClipRect)) + { + *lpRect = g_clipRect; + } + return LOG_RESULT(result); + } + + HCURSOR WINAPI getCursor() + { + LOG_FUNC("GetCursor"); + Compat::ScopedCriticalSection lock(g_cs); + return LOG_RESULT(g_isEmulated ? g_cursor : CALL_ORIG_FUNC(GetCursor)()); + } + + BOOL WINAPI getCursorInfo(PCURSORINFO pci) + { + LOG_FUNC("GetCursorInfo", pci); + Compat::ScopedCriticalSection lock(g_cs); + BOOL result = CALL_ORIG_FUNC(GetCursorInfo)(pci); + if (result && pci->hCursor == g_nullCursor) + { + pci->hCursor = g_cursor; + } + return LOG_RESULT(result); + } + + RECT intersectRect(RECT rect1, RECT rect2) + { + normalizeRect(rect1); + normalizeRect(rect2); + IntersectRect(&rect1, &rect1, &rect2); + return rect1; + } + + void normalizeRect(RECT& rect) + { + if (rect.left == rect.right && rect.top == rect.bottom) + { + rect.right++; + rect.bottom++; + } + } + + HCURSOR WINAPI setCursor(HCURSOR hCursor) + { + LOG_FUNC("SetCursor", hCursor); + return LOG_RESULT(Gdi::Cursor::setCursor(hCursor)); + } + + void updateClipRect() + { + auto hwnd = GetForegroundWindow(); + if (!hwnd) + { + return; + } + + DWORD pid = 0; + GetWindowThreadProcessId(hwnd, &pid); + if (pid != GetCurrentProcessId()) + { + return; + } + + RECT realClipRect = {}; + CALL_ORIG_FUNC(GetClipCursor)(&realClipRect); + + RECT clipRect = intersectRect(g_clipRect, g_monitorClipRect); + if (!EqualRect(&clipRect, &realClipRect)) + { + CALL_ORIG_FUNC(ClipCursor)(&clipRect); + } + } +} + +namespace Gdi +{ + namespace Cursor + { + CURSORINFO getEmulatedCursorInfo() + { + CURSORINFO ci = {}; + ci.cbSize = sizeof(ci); + + Compat::ScopedCriticalSection lock(g_cs); + if (g_isEmulated) + { + CALL_ORIG_FUNC(GetCursorInfo)(&ci); + if (ci.hCursor == g_nullCursor) + { + ci.hCursor = g_cursor; + } + else + { + ci.hCursor = nullptr; + ci.flags = 0; + } + } + + return ci; + } + + void installHooks() + { + BYTE andPlane = 0xFF; + BYTE xorPlane = 0; + g_nullCursor = CreateCursor(nullptr, 0, 0, 1, 1, &andPlane, &xorPlane); + + HOOK_FUNCTION(user32, ClipCursor, clipCursor); + HOOK_FUNCTION(user32, GetCursor, getCursor); + HOOK_FUNCTION(user32, GetCursorInfo, getCursorInfo); + HOOK_FUNCTION(user32, GetClipCursor, getClipCursor); + HOOK_FUNCTION(user32, SetCursor, ::setCursor); + } + + bool isEmulated() + { + return g_isEmulated; + } + + HCURSOR setCursor(HCURSOR cursor) + { + Compat::ScopedCriticalSection lock(g_cs); + if (!g_isEmulated) + { + return CALL_ORIG_FUNC(SetCursor)(cursor); + } + + HCURSOR prevCursor = g_cursor; + if (cursor != g_nullCursor) + { + g_cursor = cursor; + CALL_ORIG_FUNC(SetCursor)(cursor ? g_nullCursor : nullptr); + } + return prevCursor; + } + + void setEmulated(bool isEmulated) + { + Compat::ScopedCriticalSection lock(g_cs); + if (isEmulated == g_isEmulated) + { + return; + } + + g_isEmulated = isEmulated; + g_prevCursorInfo = {}; + + if (isEmulated) + { + setCursor(CALL_ORIG_FUNC(GetCursor)()); + } + else + { + CALL_ORIG_FUNC(SetCursor)(g_cursor); + g_cursor = nullptr; + } + } + + void setMonitorClipRect(const RECT& rect) + { + Compat::ScopedCriticalSection lock(g_cs); + if (IsRectEmpty(&rect)) + { + if (!IsRectEmpty(&g_monitorClipRect)) + { + CALL_ORIG_FUNC(ClipCursor)(&g_clipRect); + g_clipRect = {}; + g_monitorClipRect = {}; + } + } + else + { + if (IsRectEmpty(&g_monitorClipRect)) + { + CALL_ORIG_FUNC(GetClipCursor)(&g_clipRect); + } + g_monitorClipRect = rect; + updateClipRect(); + } + } + + bool update() + { + Compat::ScopedCriticalSection lock(g_cs); + if (!IsRectEmpty(&g_monitorClipRect)) + { + updateClipRect(); + } + + if (g_isEmulated) + { + CURSORINFO cursorInfo = getEmulatedCursorInfo(); + if ((CURSOR_SHOWING == cursorInfo.flags) != (CURSOR_SHOWING == g_prevCursorInfo.flags) || + CURSOR_SHOWING == cursorInfo.flags && + (cursorInfo.hCursor != g_prevCursorInfo.hCursor || cursorInfo.ptScreenPos != g_prevCursorInfo.ptScreenPos)) + { + g_prevCursorInfo = cursorInfo; + return true; + } + } + + return false; + } + } +} diff --git a/DDrawCompat/Gdi/Cursor.h b/DDrawCompat/Gdi/Cursor.h new file mode 100644 index 0000000..d26987a --- /dev/null +++ b/DDrawCompat/Gdi/Cursor.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +namespace Gdi +{ + namespace Cursor + { + CURSORINFO getEmulatedCursorInfo(); + void installHooks(); + bool isEmulated(); + HCURSOR setCursor(HCURSOR cursor); + void setMonitorClipRect(const RECT& rect); + void setEmulated(bool isEmulated); + bool update(); + } +} diff --git a/DDrawCompat/Gdi/Gdi.cpp b/DDrawCompat/Gdi/Gdi.cpp index 1e9e9d7..0f5d8be 100644 --- a/DDrawCompat/Gdi/Gdi.cpp +++ b/DDrawCompat/Gdi/Gdi.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -46,6 +47,7 @@ namespace Gdi ScrollFunctions::installHooks(); User32WndProcs::installHooks(); Caret::installHooks(); + Cursor::installHooks(); Font::installHooks(); } diff --git a/DDrawCompat/Gdi/User32WndProcs.cpp b/DDrawCompat/Gdi/User32WndProcs.cpp index 236b897..38aae27 100644 --- a/DDrawCompat/Gdi/User32WndProcs.cpp +++ b/DDrawCompat/Gdi/User32WndProcs.cpp @@ -1,5 +1,7 @@ #include +#include #include +#include #include #include #include @@ -194,6 +196,57 @@ namespace } return origDefWindowProc(hwnd, msg, wParam, lParam); } + + case WM_SETCURSOR: + { + if (!Gdi::Cursor::isEmulated()) + { + return origDefWindowProc(hwnd, msg, wParam, lParam); + } + + switch (LOWORD(lParam)) + { + case HTLEFT: + case HTRIGHT: + Gdi::Cursor::setCursor(LoadCursor(nullptr, IDC_SIZEWE)); + return TRUE; + + case HTTOP: + case HTBOTTOM: + Gdi::Cursor::setCursor(LoadCursor(nullptr, IDC_SIZENS)); + return TRUE; + + case HTTOPLEFT: + case HTBOTTOMRIGHT: + Gdi::Cursor::setCursor(LoadCursor(nullptr, IDC_SIZENWSE)); + return TRUE; + + case HTBOTTOMLEFT: + case HTTOPRIGHT: + Gdi::Cursor::setCursor(LoadCursor(nullptr, IDC_SIZENESW)); + return TRUE; + } + + HWND parent = GetAncestor(hwnd, GA_PARENT); + if (parent && SendMessage(parent, msg, wParam, lParam)) + { + return TRUE; + } + + if (HTCLIENT == LOWORD(lParam)) + { + auto cursor = GetClassLong(hwnd, GCL_HCURSOR); + if (cursor) + { + Gdi::Cursor::setCursor(reinterpret_cast(cursor)); + } + } + else + { + Gdi::Cursor::setCursor(LoadCursor(nullptr, IDC_ARROW)); + } + return FALSE; + } } return defPaintProc(hwnd, msg, wParam, lParam, origDefWindowProc); diff --git a/DDrawCompat/Gdi/WinProc.cpp b/DDrawCompat/Gdi/WinProc.cpp index 87bdcd4..fce6123 100644 --- a/DDrawCompat/Gdi/WinProc.cpp +++ b/DDrawCompat/Gdi/WinProc.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -172,65 +173,6 @@ namespace IsWindowUnicode(hwnd) ? it->second.wndProcW : it->second.wndProcA); } - void CALLBACK objectCreateEvent( - HWINEVENTHOOK /*hWinEventHook*/, - DWORD /*event*/, - HWND hwnd, - LONG idObject, - LONG /*idChild*/, - DWORD /*dwEventThread*/, - DWORD /*dwmsEventTime*/) - { - if (OBJID_WINDOW == idObject && !Gdi::PresentationWindow::isPresentationWindow(hwnd)) - { - onCreateWindow(hwnd); - } - } - - void CALLBACK objectStateChangeEvent( - HWINEVENTHOOK /*hWinEventHook*/, - DWORD /*event*/, - HWND hwnd, - LONG idObject, - LONG /*idChild*/, - DWORD /*dwEventThread*/, - DWORD /*dwmsEventTime*/) - { - switch (idObject) - { - case OBJID_TITLEBAR: - { - HDC dc = GetWindowDC(hwnd); - Gdi::TitleBar(hwnd).drawButtons(dc); - ReleaseDC(hwnd, dc); - break; - } - - case OBJID_CLIENT: - if (!isUser32ScrollBar(hwnd)) - { - break; - } - case OBJID_HSCROLL: - case OBJID_VSCROLL: - { - HDC dc = GetWindowDC(hwnd); - if (OBJID_CLIENT == idObject) - { - SendMessage(GetParent(hwnd), WM_CTLCOLORSCROLLBAR, - reinterpret_cast(dc), reinterpret_cast(hwnd)); - } - else - { - DefWindowProc(hwnd, WM_CTLCOLORSCROLLBAR, - reinterpret_cast(dc), reinterpret_cast(hwnd)); - } - ReleaseDC(hwnd, dc); - break; - } - } - } - void onCreateWindow(HWND hwnd) { LOG_FUNC("onCreateWindow", hwnd); @@ -425,6 +367,72 @@ namespace } return LOG_RESULT(result); } + + void CALLBACK winEventProc( + HWINEVENTHOOK /*hWinEventHook*/, + DWORD event, + HWND hwnd, + LONG idObject, + LONG /*idChild*/, + DWORD /*dwEventThread*/, + DWORD /*dwmsEventTime*/) + { + LOG_FUNC("winEventProc", Compat::hex(event), hwnd, idObject); + + switch (event) + { + case EVENT_OBJECT_CREATE: + if (OBJID_WINDOW == idObject && !Gdi::PresentationWindow::isPresentationWindow(hwnd)) + { + onCreateWindow(hwnd); + } + break; + + case EVENT_OBJECT_NAMECHANGE: + case EVENT_OBJECT_SHOW: + case EVENT_OBJECT_HIDE: + if (OBJID_CURSOR == idObject && Gdi::Cursor::isEmulated()) + { + Gdi::Cursor::setCursor(GetCursor()); + } + break; + + case EVENT_OBJECT_STATECHANGE: + switch (idObject) + { + case OBJID_TITLEBAR: + { + HDC dc = GetWindowDC(hwnd); + Gdi::TitleBar(hwnd).drawButtons(dc); + ReleaseDC(hwnd, dc); + break; + } + + case OBJID_CLIENT: + if (!isUser32ScrollBar(hwnd)) + { + break; + } + case OBJID_HSCROLL: + case OBJID_VSCROLL: + { + HDC dc = GetWindowDC(hwnd); + if (OBJID_CLIENT == idObject) + { + SendMessage(GetParent(hwnd), WM_CTLCOLORSCROLLBAR, + reinterpret_cast(dc), reinterpret_cast(hwnd)); + } + else + { + DefWindowProc(hwnd, WM_CTLCOLORSCROLLBAR, + reinterpret_cast(dc), reinterpret_cast(hwnd)); + } + ReleaseDC(hwnd, dc); + break; + } + } + } + } } namespace Gdi @@ -461,9 +469,13 @@ namespace Gdi HOOK_FUNCTION(user32, UpdateLayeredWindowIndirect, updateLayeredWindowIndirect); SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, - Dll::g_currentModule, &objectCreateEvent, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT); + Dll::g_currentModule, &winEventProc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT); + SetWinEventHook(EVENT_OBJECT_NAMECHANGE, EVENT_OBJECT_NAMECHANGE, + Dll::g_currentModule, &winEventProc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT); + SetWinEventHook(EVENT_OBJECT_SHOW, EVENT_OBJECT_HIDE, + Dll::g_currentModule, &winEventProc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT); SetWinEventHook(EVENT_OBJECT_STATECHANGE, EVENT_OBJECT_STATECHANGE, - Dll::g_currentModule, &objectStateChangeEvent, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT); + Dll::g_currentModule, &winEventProc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT); } void onCreateWindow(HWND hwnd) diff --git a/DDrawCompat/Shaders/DrawCursor.hlsl b/DDrawCompat/Shaders/DrawCursor.hlsl new file mode 100644 index 0000000..fd90f33 --- /dev/null +++ b/DDrawCompat/Shaders/DrawCursor.hlsl @@ -0,0 +1,19 @@ +sampler2D s_dstTexture : register(s0); +sampler2D s_maskTexture : register(s1); +sampler2D s_colorTexture : register(s2); +sampler2D s_xorTexture : register(s3); + +float4 main(float2 texCoord : TEXCOORD0) : COLOR0 +{ + float4 dst = tex2D(s_dstTexture, texCoord); + float4 mask = tex2D(s_maskTexture, texCoord); + float4 color = tex2D(s_colorTexture, texCoord); + + float4 maskedDst = dst * mask; + + return float4( + tex2D(s_xorTexture, float2(maskedDst.r, color.r)).r, + tex2D(s_xorTexture, float2(maskedDst.g, color.g)).r, + tex2D(s_xorTexture, float2(maskedDst.b, color.b)).r, + 1); +} diff --git a/DDrawCompat/Win32/DisplayMode.cpp b/DDrawCompat/Win32/DisplayMode.cpp index 3a52792..b22f5ec 100644 --- a/DDrawCompat/Win32/DisplayMode.cpp +++ b/DDrawCompat/Win32/DisplayMode.cpp @@ -46,7 +46,6 @@ namespace }; DWORD g_desktopBpp = 0; - RECT g_cursorRect = {}; ULONG g_displaySettingsUniquenessBias = 0; EmulatedDisplayMode g_emulatedDisplayMode = {}; Compat::SrwLock g_srwLock; @@ -148,12 +147,9 @@ namespace return result; } - RECT clipRect = {}; - { Compat::ScopedSrwLockExclusive srwLock(g_srwLock); ++g_displaySettingsUniquenessBias; - clipRect = g_cursorRect; if (lpDevMode) { g_emulatedDisplayMode.width = lpDevMode->dmPelsWidth; @@ -167,8 +163,6 @@ namespace g_emulatedDisplayMode.rect.bottom = g_emulatedDisplayMode.rect.top + lpDevMode->dmPelsHeight; g_emulatedDisplayMode.diff.cx = lpDevMode->dmPelsWidth - currDevMode.dmPelsWidth; g_emulatedDisplayMode.diff.cy = lpDevMode->dmPelsHeight - currDevMode.dmPelsHeight; - - IntersectRect(&clipRect, &clipRect, &g_emulatedDisplayMode.rect); } else { @@ -177,8 +171,6 @@ namespace } } - CALL_ORIG_FUNC(ClipCursor)(&clipRect); - auto& dm = lpDevMode ? *lpDevMode : currDevMode; LPARAM resolution = (dm.dmPelsHeight << 16) | dm.dmPelsWidth; EnumWindows(sendDisplayChange, resolution); @@ -209,31 +201,6 @@ namespace lpszDeviceName, lpDevMode, hwnd, dwflags, lParam)); } - BOOL WINAPI clipCursor(const RECT* lpRect) - { - LOG_FUNC("ClipCursor", lpRect); - BOOL result = CALL_ORIG_FUNC(ClipCursor)(lpRect); - if (!result) - { - return result; - } - - RECT rect = {}; - CALL_ORIG_FUNC(GetClipCursor)(&rect); - - { - Compat::ScopedSrwLockExclusive srwLock(g_srwLock); - g_cursorRect = rect; - if (!g_emulatedDisplayMode.deviceName.empty()) - { - IntersectRect(&rect, &rect, &g_emulatedDisplayMode.rect); - CALL_ORIG_FUNC(ClipCursor)(&rect); - } - } - - return result; - } - void disableDwm8And16BitMitigation() { auto user32 = GetModuleHandle("user32"); @@ -342,17 +309,6 @@ namespace return CALL_ORIG_FUNC(GdiEntry13)() + g_displaySettingsUniquenessBias; } - BOOL WINAPI getClipCursor(LPRECT lpRect) - { - LOG_FUNC("GetClipCursor", lpRect); - BOOL result = CALL_ORIG_FUNC(GetClipCursor)(lpRect); - if (result) - { - *lpRect = g_cursorRect; - } - return LOG_RESULT(result); - } - template SIZE getConfiguredResolution(EnumDisplaySettingsExFunc origEnumDisplaySettingsEx, const Char* deviceName) { @@ -671,16 +627,13 @@ namespace Win32 g_desktopBpp = dm.dmBitsPerPel; g_emulatedDisplayMode.bpp = dm.dmBitsPerPel; - GetClipCursor(&g_cursorRect); EnumDisplayMonitors(nullptr, nullptr, &initMonitor, 0); HOOK_FUNCTION(user32, ChangeDisplaySettingsExA, changeDisplaySettingsExA); HOOK_FUNCTION(user32, ChangeDisplaySettingsExW, changeDisplaySettingsExW); - HOOK_FUNCTION(user32, ClipCursor, clipCursor); HOOK_FUNCTION(user32, EnumDisplaySettingsExA, enumDisplaySettingsExA); HOOK_FUNCTION(user32, EnumDisplaySettingsExW, enumDisplaySettingsExW); HOOK_FUNCTION(gdi32, GdiEntry13, gdiEntry13); - HOOK_FUNCTION(user32, GetClipCursor, getClipCursor); HOOK_FUNCTION(gdi32, GetDeviceCaps, getDeviceCaps); HOOK_FUNCTION(user32, GetMonitorInfoA, getMonitorInfoA); HOOK_FUNCTION(user32, GetMonitorInfoW, getMonitorInfoW);