mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Emulate hardware cursor in scaled fullscreen mode
This commit is contained in:
parent
647a4bfcff
commit
ccc23c75b9
@ -11,6 +11,12 @@ std::enable_if_t<std::is_class_v<T> && std::is_trivial_v<T>, bool> operator==(co
|
|||||||
return toTuple(left) == toTuple(right);
|
return toTuple(left) == toTuple(right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::enable_if_t<std::is_class_v<T>&& std::is_trivial_v<T>, bool> operator!=(const T& left, const T& right)
|
||||||
|
{
|
||||||
|
return toTuple(left) != toTuple(right);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::enable_if_t<std::is_class_v<T> && std::is_trivial_v<T>, bool> operator<(const T& left, const T& right)
|
std::enable_if_t<std::is_class_v<T> && std::is_trivial_v<T>, bool> operator<(const T& left, const T& right)
|
||||||
{
|
{
|
||||||
|
@ -82,7 +82,7 @@ namespace D3dDdi
|
|||||||
Resource* Device::getResource(HANDLE resource)
|
Resource* Device::getResource(HANDLE resource)
|
||||||
{
|
{
|
||||||
auto it = m_resources.find(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)
|
void Device::prepareForRendering(HANDLE resource, UINT subResourceIndex, bool isReadOnly)
|
||||||
@ -90,7 +90,7 @@ namespace D3dDdi
|
|||||||
auto it = m_resources.find(resource);
|
auto it = m_resources.find(resource);
|
||||||
if (it != m_resources.end())
|
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);
|
auto it = m_resources.find(data->hDstResource);
|
||||||
if (it != m_resources.end())
|
if (it != m_resources.end())
|
||||||
{
|
{
|
||||||
return it->second.blt(*data);
|
return it->second->blt(*data);
|
||||||
}
|
}
|
||||||
prepareForRendering(data->hSrcResource, data->SrcSubResourceIndex, true);
|
prepareForRendering(data->hSrcResource, data->SrcSubResourceIndex, true);
|
||||||
return m_origVtable.pfnBlt(m_device, data);
|
return m_origVtable.pfnBlt(m_device, data);
|
||||||
@ -162,7 +162,7 @@ namespace D3dDdi
|
|||||||
auto it = m_resources.find(data->hResource);
|
auto it = m_resources.find(data->hResource);
|
||||||
if (it != m_resources.end())
|
if (it != m_resources.end())
|
||||||
{
|
{
|
||||||
return it->second.colorFill(*data);
|
return it->second->colorFill(*data);
|
||||||
}
|
}
|
||||||
return m_origVtable.pfnColorFill(m_device, data);
|
return m_origVtable.pfnColorFill(m_device, data);
|
||||||
}
|
}
|
||||||
@ -180,8 +180,8 @@ namespace D3dDdi
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Resource resource(*this, *data);
|
auto resource(std::make_unique<Resource>(*this, *data));
|
||||||
m_resources.emplace(resource, std::move(resource));
|
m_resources.emplace(*resource, std::move(resource));
|
||||||
if (data->Flags.VertexBuffer &&
|
if (data->Flags.VertexBuffer &&
|
||||||
D3DDDIPOOL_SYSTEMMEM == data->Pool &&
|
D3DDDIPOOL_SYSTEMMEM == data->Pool &&
|
||||||
data->pSurfList[0].pSysMem)
|
data->pSurfList[0].pSysMem)
|
||||||
@ -283,7 +283,7 @@ namespace D3dDdi
|
|||||||
auto it = m_resources.find(data->hResource);
|
auto it = m_resources.find(data->hResource);
|
||||||
if (it != m_resources.end())
|
if (it != m_resources.end())
|
||||||
{
|
{
|
||||||
return it->second.lock(*data);
|
return it->second->lock(*data);
|
||||||
}
|
}
|
||||||
return m_origVtable.pfnLock(m_device, data);
|
return m_origVtable.pfnLock(m_device, data);
|
||||||
}
|
}
|
||||||
@ -321,7 +321,7 @@ namespace D3dDdi
|
|||||||
auto it = m_resources.find(data->hResource);
|
auto it = m_resources.find(data->hResource);
|
||||||
if (it != m_resources.end())
|
if (it != m_resources.end())
|
||||||
{
|
{
|
||||||
return it->second.unlock(*data);
|
return it->second->unlock(*data);
|
||||||
}
|
}
|
||||||
return m_origVtable.pfnUnlock(m_device, data);
|
return m_origVtable.pfnUnlock(m_device, data);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
#include <memory>
|
||||||
|
|
||||||
#include <d3d.h>
|
#include <d3d.h>
|
||||||
#include <d3dnthal.h>
|
#include <d3dnthal.h>
|
||||||
@ -71,7 +71,7 @@ namespace D3dDdi
|
|||||||
D3DDDI_DEVICEFUNCS m_origVtable;
|
D3DDDI_DEVICEFUNCS m_origVtable;
|
||||||
Adapter& m_adapter;
|
Adapter& m_adapter;
|
||||||
HANDLE m_device;
|
HANDLE m_device;
|
||||||
std::unordered_map<HANDLE, Resource> m_resources;
|
std::map<HANDLE, std::unique_ptr<Resource>> m_resources;
|
||||||
Resource* m_renderTarget;
|
Resource* m_renderTarget;
|
||||||
UINT m_renderTargetSubResourceIndex;
|
UINT m_renderTargetSubResourceIndex;
|
||||||
HANDLE m_sharedPrimary;
|
HANDLE m_sharedPrimary;
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
D3DDDIFORMAT g_dcFormatOverride = D3DDDIFMT_UNKNOWN;
|
D3DDDIFORMAT g_dcFormatOverride = D3DDDIFMT_UNKNOWN;
|
||||||
bool g_dcPaletteOverride = false;
|
PALETTEENTRY* g_dcPaletteOverride = nullptr;
|
||||||
D3dDdi::KernelModeThunks::AdapterInfo g_gdiAdapterInfo = {};
|
D3dDdi::KernelModeThunks::AdapterInfo g_gdiAdapterInfo = {};
|
||||||
D3dDdi::KernelModeThunks::AdapterInfo g_lastOpenAdapterInfo = {};
|
D3dDdi::KernelModeThunks::AdapterInfo g_lastOpenAdapterInfo = {};
|
||||||
Compat::SrwLock g_lastOpenAdapterInfoSrwLock;
|
Compat::SrwLock g_lastOpenAdapterInfoSrwLock;
|
||||||
@ -59,8 +59,7 @@ namespace
|
|||||||
{
|
{
|
||||||
if (g_dcPaletteOverride)
|
if (g_dcPaletteOverride)
|
||||||
{
|
{
|
||||||
palette = Gdi::Palette::getHardwarePalette();
|
pData->pColorTable = g_dcPaletteOverride;
|
||||||
pData->pColorTable = palette.data();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -313,9 +312,9 @@ namespace D3dDdi
|
|||||||
g_dcFormatOverride = static_cast<D3DDDIFORMAT>(format);
|
g_dcFormatOverride = static_cast<D3DDDIFORMAT>(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setDcPaletteOverride(bool enable)
|
void setDcPaletteOverride(PALETTEENTRY* palette)
|
||||||
{
|
{
|
||||||
g_dcPaletteOverride = enable;
|
g_dcPaletteOverride = palette;
|
||||||
}
|
}
|
||||||
|
|
||||||
void waitForVsync()
|
void waitForVsync()
|
||||||
|
@ -22,7 +22,7 @@ namespace D3dDdi
|
|||||||
UINT getVsyncCounter();
|
UINT getVsyncCounter();
|
||||||
void installHooks();
|
void installHooks();
|
||||||
void setDcFormatOverride(UINT format);
|
void setDcFormatOverride(UINT format);
|
||||||
void setDcPaletteOverride(bool enable);
|
void setDcPaletteOverride(PALETTEENTRY* palette);
|
||||||
void waitForVsync();
|
void waitForVsync();
|
||||||
bool waitForVsyncCounter(UINT counter);
|
bool waitForVsyncCounter(UINT counter);
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <DDraw/Blitter.h>
|
#include <DDraw/Blitter.h>
|
||||||
#include <DDraw/RealPrimarySurface.h>
|
#include <DDraw/RealPrimarySurface.h>
|
||||||
#include <DDraw/Surfaces/PrimarySurface.h>
|
#include <DDraw/Surfaces/PrimarySurface.h>
|
||||||
|
#include <Gdi/Cursor.h>
|
||||||
#include <Gdi/Palette.h>
|
#include <Gdi/Palette.h>
|
||||||
#include <Gdi/VirtualScreen.h>
|
#include <Gdi/VirtualScreen.h>
|
||||||
|
|
||||||
@ -113,6 +114,14 @@ namespace D3dDdi
|
|||||||
if (m_origData.Flags.Primary)
|
if (m_origData.Flags.Primary)
|
||||||
{
|
{
|
||||||
g_presentationRect = calculatePresentationRect();
|
g_presentationRect = calculatePresentationRect();
|
||||||
|
auto& si = m_origData.pSurfList[0];
|
||||||
|
RECT rect = { 0, 0, static_cast<LONG>(si.Width), static_cast<LONG>(si.Height) };
|
||||||
|
|
||||||
|
Gdi::Cursor::setMonitorClipRect(DDraw::PrimarySurface::getMonitorRect());
|
||||||
|
if (!EqualRect(&g_presentationRect, &rect))
|
||||||
|
{
|
||||||
|
Gdi::Cursor::setEmulated(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fixResourceData();
|
fixResourceData();
|
||||||
@ -141,6 +150,15 @@ namespace D3dDdi
|
|||||||
data.hResource = m_fixedData.hResource;
|
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)
|
HRESULT Resource::blt(D3DDDIARG_BLT data)
|
||||||
{
|
{
|
||||||
if (!isValidRect(data.DstSubResourceIndex, data.DstRect))
|
if (!isValidRect(data.DstSubResourceIndex, data.DstRect))
|
||||||
@ -177,7 +195,7 @@ namespace D3dDdi
|
|||||||
}
|
}
|
||||||
else if (m_fixedData.Flags.Primary)
|
else if (m_fixedData.Flags.Primary)
|
||||||
{
|
{
|
||||||
return presentationBlt(data, *srcResource);
|
return presentationBlt(data, srcResource);
|
||||||
}
|
}
|
||||||
else
|
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 &&
|
if (srcResource->m_lockResource &&
|
||||||
srcResource.m_lockData[0].isSysMemUpToDate)
|
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 dst(SurfaceRepository::get(m_device.getAdapter()).getRenderTarget(si.Width, si.Height));
|
||||||
auto palettizedBltRenderTarget(SurfaceRepository::get(m_device.getAdapter()).getPaletteBltRenderTarget(
|
if (!dst)
|
||||||
si.Width, si.Height));
|
|
||||||
if (!palettizedBltRenderTarget)
|
|
||||||
{
|
{
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto entries(Gdi::Palette::getHardwarePalette());
|
if (isPalettized)
|
||||||
RGBQUAD pal[256] = {};
|
|
||||||
for (UINT i = 0; i < 256; ++i)
|
|
||||||
{
|
{
|
||||||
pal[i].rgbRed = entries[i].peRed;
|
auto entries(Gdi::Palette::getHardwarePalette());
|
||||||
pal[i].rgbGreen = entries[i].peGreen;
|
RGBQUAD pal[256] = {};
|
||||||
pal[i].rgbBlue = entries[i].peBlue;
|
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);
|
srcResource = dst;
|
||||||
data.hSrcResource = *palettizedBltRenderTarget;
|
data.hSrcResource = *dst;
|
||||||
data.SrcSubResourceIndex = 0;
|
}
|
||||||
|
|
||||||
|
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;
|
data.DstRect = g_presentationRect;
|
||||||
|
@ -18,10 +18,10 @@ namespace D3dDdi
|
|||||||
Resource(Device& device, D3DDDIARG_CREATERESOURCE2& data);
|
Resource(Device& device, D3DDDIARG_CREATERESOURCE2& data);
|
||||||
|
|
||||||
Resource(const Resource&) = delete;
|
Resource(const Resource&) = delete;
|
||||||
|
Resource(Resource&&) = delete;
|
||||||
Resource& operator=(const Resource&) = delete;
|
Resource& operator=(const Resource&) = delete;
|
||||||
|
Resource& operator=(Resource&&) = delete;
|
||||||
Resource(Resource&&) = default;
|
~Resource();
|
||||||
Resource& operator=(Resource&&) = default;
|
|
||||||
|
|
||||||
operator HANDLE() const { return m_handle; }
|
operator HANDLE() const { return m_handle; }
|
||||||
const D3DDDIARG_CREATERESOURCE2& getOrigDesc() const { return m_origData; }
|
const D3DDDIARG_CREATERESOURCE2& getOrigDesc() const { return m_origData; }
|
||||||
@ -43,10 +43,9 @@ namespace D3dDdi
|
|||||||
Data(const D3DDDIARG_CREATERESOURCE2& data);
|
Data(const D3DDDIARG_CREATERESOURCE2& data);
|
||||||
|
|
||||||
Data(const Data&) = delete;
|
Data(const Data&) = delete;
|
||||||
|
Data(Data&&) = delete;
|
||||||
Data& operator=(const Data&) = delete;
|
Data& operator=(const Data&) = delete;
|
||||||
|
Data& operator=(Data&&) = delete;
|
||||||
Data(Data&&) = default;
|
|
||||||
Data& operator=(Data&&) = default;
|
|
||||||
|
|
||||||
std::vector<D3DDDI_SURFACEINFO> surfaceData;
|
std::vector<D3DDDI_SURFACEINFO> surfaceData;
|
||||||
};
|
};
|
||||||
@ -83,7 +82,7 @@ namespace D3dDdi
|
|||||||
void fixResourceData();
|
void fixResourceData();
|
||||||
bool isOversized() const;
|
bool isOversized() const;
|
||||||
bool isValidRect(UINT subResourceIndex, const RECT& rect);
|
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);
|
HRESULT splitBlt(D3DDDIARG_BLT& data, UINT& subResourceIndex, RECT& rect, RECT& otherRect);
|
||||||
|
|
||||||
template <typename Arg>
|
template <typename Arg>
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <D3dDdi/Resource.h>
|
#include <D3dDdi/Resource.h>
|
||||||
#include <D3dDdi/ShaderBlitter.h>
|
#include <D3dDdi/ShaderBlitter.h>
|
||||||
#include <D3dDdi/SurfaceRepository.h>
|
#include <D3dDdi/SurfaceRepository.h>
|
||||||
|
#include <Shaders/DrawCursor.h>
|
||||||
#include <Shaders/PaletteLookup.h>
|
#include <Shaders/PaletteLookup.h>
|
||||||
|
|
||||||
#define CONCAT_(a, b) a##b
|
#define CONCAT_(a, b) a##b
|
||||||
@ -14,7 +15,8 @@ namespace D3dDdi
|
|||||||
{
|
{
|
||||||
ShaderBlitter::ShaderBlitter(Device& device)
|
ShaderBlitter::ShaderBlitter(Device& device)
|
||||||
: m_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())
|
, m_vertexShaderDecl(createVertexShaderDecl())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -122,6 +124,46 @@ namespace D3dDdi
|
|||||||
return data.ShaderHandle;
|
return data.ShaderHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShaderBlitter::cursorBlt(const Resource& dstResource, UINT dstSubResourceIndex, HCURSOR cursor, POINT pt)
|
||||||
|
{
|
||||||
|
LOG_FUNC("ShaderBlitter::cursorBlt", static_cast<HANDLE>(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,
|
void ShaderBlitter::palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex,
|
||||||
const Resource& srcResource, RGBQUAD palette[256])
|
const Resource& srcResource, RGBQUAD palette[256])
|
||||||
{
|
{
|
||||||
|
@ -16,6 +16,7 @@ namespace D3dDdi
|
|||||||
ShaderBlitter& operator=(const ShaderBlitter&) = delete;
|
ShaderBlitter& operator=(const ShaderBlitter&) = delete;
|
||||||
ShaderBlitter& operator=(ShaderBlitter&&) = delete;
|
ShaderBlitter& operator=(ShaderBlitter&&) = delete;
|
||||||
|
|
||||||
|
void cursorBlt(const Resource& dstResource, UINT dstSubResourceIndex, HCURSOR cursor, POINT pt);
|
||||||
void palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex,
|
void palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex,
|
||||||
const Resource& srcResource, RGBQUAD palette[256]);
|
const Resource& srcResource, RGBQUAD palette[256]);
|
||||||
|
|
||||||
@ -23,10 +24,17 @@ namespace D3dDdi
|
|||||||
void blt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
void blt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||||
const Resource& srcResource, const RECT& srcRect, HANDLE pixelShader, UINT filter);
|
const Resource& srcResource, const RECT& srcRect, HANDLE pixelShader, UINT filter);
|
||||||
|
|
||||||
|
template <int N>
|
||||||
|
HANDLE createPixelShader(const BYTE(&code)[N])
|
||||||
|
{
|
||||||
|
return createPixelShader(code, N);
|
||||||
|
}
|
||||||
|
|
||||||
HANDLE createPixelShader(const BYTE* code, UINT size);
|
HANDLE createPixelShader(const BYTE* code, UINT size);
|
||||||
HANDLE createVertexShaderDecl();
|
HANDLE createVertexShaderDecl();
|
||||||
|
|
||||||
Device& m_device;
|
Device& m_device;
|
||||||
|
HANDLE m_psDrawCursor;
|
||||||
HANDLE m_psPaletteLookup;
|
HANDLE m_psPaletteLookup;
|
||||||
HANDLE m_vertexShaderDecl;
|
HANDLE m_vertexShaderDecl;
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
|
#undef WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <d3dkmthk.h>
|
||||||
|
|
||||||
#include <Common/Comparison.h>
|
#include <Common/Comparison.h>
|
||||||
#include <D3dDdi/Adapter.h>
|
#include <D3dDdi/Adapter.h>
|
||||||
#include <D3dDdi/Device.h>
|
#include <D3dDdi/Device.h>
|
||||||
|
#include <D3dDdi/KernelModeThunks.h>
|
||||||
|
#include <D3dDdi/Resource.h>
|
||||||
#include <D3dDdi/SurfaceRepository.h>
|
#include <D3dDdi/SurfaceRepository.h>
|
||||||
#include <DDraw/DirectDrawSurface.h>
|
#include <DDraw/DirectDrawSurface.h>
|
||||||
|
|
||||||
@ -15,6 +22,9 @@ namespace D3dDdi
|
|||||||
{
|
{
|
||||||
SurfaceRepository::SurfaceRepository(const Adapter& adapter)
|
SurfaceRepository::SurfaceRepository(const Adapter& adapter)
|
||||||
: m_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;
|
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),
|
DWORD width = rect.right - rect.left;
|
||||||
DDSCAPS_3DDEVICE | DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY);
|
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<BYTE*>(desc.lpSurface);
|
||||||
|
for (UINT y = 0; y < 256; ++y)
|
||||||
|
{
|
||||||
|
for (UINT x = 0; x < 256; ++x)
|
||||||
|
{
|
||||||
|
p[x] = static_cast<BYTE>(x ^ y);
|
||||||
|
}
|
||||||
|
p += desc.lPitch;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource* SurfaceRepository::getInitializedResource(Surface& surface, DWORD width, DWORD height,
|
||||||
|
const DDPIXELFORMAT& pf, DWORD caps, std::function<void(const DDSURFACEDESC2&)> 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()
|
Resource* SurfaceRepository::getPaletteTexture()
|
||||||
@ -69,18 +205,18 @@ namespace D3dDdi
|
|||||||
DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY);
|
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)
|
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 = {};
|
release(surface);
|
||||||
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 = {};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!surface.surface)
|
if (!surface.surface)
|
||||||
@ -90,9 +226,26 @@ namespace D3dDdi
|
|||||||
{
|
{
|
||||||
surface.resource = D3dDdi::Device::findResource(
|
surface.resource = D3dDdi::Device::findResource(
|
||||||
DDraw::DirectDrawSurface::getDriverResourceHandle(*surface.surface));
|
DDraw::DirectDrawSurface::getDriverResourceHandle(*surface.surface));
|
||||||
|
surface.width = width;
|
||||||
|
surface.height = height;
|
||||||
|
surface.pixelFormat = pf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return surface.resource;
|
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 = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#include <ddraw.h>
|
#include <ddraw.h>
|
||||||
|
|
||||||
#include <Common/CompatWeakPtr.h>
|
#include <Common/CompatWeakPtr.h>
|
||||||
@ -12,8 +14,20 @@ namespace D3dDdi
|
|||||||
class SurfaceRepository
|
class SurfaceRepository
|
||||||
{
|
{
|
||||||
public:
|
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* getPaletteTexture();
|
||||||
|
Resource* getRenderTarget(DWORD width, DWORD height);
|
||||||
|
|
||||||
static SurfaceRepository& get(const Adapter& adapter);
|
static SurfaceRepository& get(const Adapter& adapter);
|
||||||
|
|
||||||
@ -22,15 +36,30 @@ namespace D3dDdi
|
|||||||
{
|
{
|
||||||
CompatWeakPtr<IDirectDrawSurface7> surface;
|
CompatWeakPtr<IDirectDrawSurface7> surface;
|
||||||
Resource* resource;
|
Resource* resource;
|
||||||
|
DWORD width;
|
||||||
|
DWORD height;
|
||||||
|
DDPIXELFORMAT pixelFormat;
|
||||||
};
|
};
|
||||||
|
|
||||||
SurfaceRepository(const Adapter& adapter);
|
SurfaceRepository(const Adapter& adapter);
|
||||||
|
|
||||||
CompatWeakPtr<IDirectDrawSurface7> createSurface(DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps);
|
CompatWeakPtr<IDirectDrawSurface7> 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<void(const DDSURFACEDESC2&)> initFunc);
|
||||||
Resource* getResource(Surface& surface, DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps);
|
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;
|
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_paletteTexture;
|
||||||
|
Surface m_renderTarget;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <Common/Comparison.h>
|
||||||
#include <Common/CompatPtr.h>
|
#include <Common/CompatPtr.h>
|
||||||
#include <Common/Hook.h>
|
#include <Common/Hook.h>
|
||||||
#include <Common/Time.h>
|
#include <Common/Time.h>
|
||||||
@ -16,7 +17,9 @@
|
|||||||
#include <DDraw/Surfaces/PrimarySurface.h>
|
#include <DDraw/Surfaces/PrimarySurface.h>
|
||||||
#include <DDraw/Types.h>
|
#include <DDraw/Types.h>
|
||||||
#include <Gdi/Caret.h>
|
#include <Gdi/Caret.h>
|
||||||
|
#include <Gdi/Cursor.h>
|
||||||
#include <Gdi/Gdi.h>
|
#include <Gdi/Gdi.h>
|
||||||
|
#include <Gdi/Palette.h>
|
||||||
#include <Gdi/VirtualScreen.h>
|
#include <Gdi/VirtualScreen.h>
|
||||||
#include <Gdi/Window.h>
|
#include <Gdi/Window.h>
|
||||||
#include <Win32/DisplayMode.h>
|
#include <Win32/DisplayMode.h>
|
||||||
@ -142,7 +145,7 @@ namespace
|
|||||||
|
|
||||||
g_surfaceDesc = desc;
|
g_surfaceDesc = desc;
|
||||||
g_isFullScreen = isFlippable;
|
g_isFullScreen = isFlippable;
|
||||||
g_isUpdatePending = false;
|
g_isUpdatePending = true;
|
||||||
g_qpcLastUpdate = Time::queryPerformanceCounter() - Time::msToQpc(Config::delayedFlipModeTimeout);
|
g_qpcLastUpdate = Time::queryPerformanceCounter() - Time::msToQpc(Config::delayedFlipModeTimeout);
|
||||||
|
|
||||||
if (isFlippable)
|
if (isFlippable)
|
||||||
@ -169,9 +172,10 @@ namespace
|
|||||||
Gdi::Region excludeRegion(DDraw::PrimarySurface::getMonitorRect());
|
Gdi::Region excludeRegion(DDraw::PrimarySurface::getMonitorRect());
|
||||||
Gdi::Window::present(excludeRegion);
|
Gdi::Window::present(excludeRegion);
|
||||||
|
|
||||||
D3dDdi::KernelModeThunks::setDcPaletteOverride(true);
|
auto palette(Gdi::Palette::getHardwarePalette());
|
||||||
|
D3dDdi::KernelModeThunks::setDcPaletteOverride(palette.data());
|
||||||
bltToPrimaryChain(*src);
|
bltToPrimaryChain(*src);
|
||||||
D3dDdi::KernelModeThunks::setDcPaletteOverride(false);
|
D3dDdi::KernelModeThunks::setDcPaletteOverride(nullptr);
|
||||||
|
|
||||||
if (g_isFullScreen && src == DDraw::PrimarySurface::getGdiSurface())
|
if (g_isFullScreen && src == DDraw::PrimarySurface::getGdiSurface())
|
||||||
{
|
{
|
||||||
@ -222,10 +226,15 @@ namespace
|
|||||||
D3dDdi::KernelModeThunks::waitForVsync();
|
D3dDdi::KernelModeThunks::waitForVsync();
|
||||||
}
|
}
|
||||||
skipWaitForVsync = false;
|
skipWaitForVsync = false;
|
||||||
Gdi::Caret::blink();
|
|
||||||
Sleep(1);
|
Sleep(1);
|
||||||
|
|
||||||
DDraw::ScopedThreadLock lock;
|
DDraw::ScopedThreadLock lock;
|
||||||
|
Gdi::Caret::blink();
|
||||||
|
if (Gdi::Cursor::update())
|
||||||
|
{
|
||||||
|
g_isUpdatePending = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (g_isUpdatePending && !isPresentPending())
|
if (g_isUpdatePending && !isPresentPending())
|
||||||
{
|
{
|
||||||
auto qpcNow = Time::queryPerformanceCounter();
|
auto qpcNow = Time::queryPerformanceCounter();
|
||||||
|
@ -282,6 +282,7 @@
|
|||||||
<ClInclude Include="Direct3d\Visitors\Direct3dVtblVisitor.h" />
|
<ClInclude Include="Direct3d\Visitors\Direct3dVtblVisitor.h" />
|
||||||
<ClInclude Include="Dll\Dll.h" />
|
<ClInclude Include="Dll\Dll.h" />
|
||||||
<ClInclude Include="Gdi\CompatDc.h" />
|
<ClInclude Include="Gdi\CompatDc.h" />
|
||||||
|
<ClInclude Include="Gdi\Cursor.h" />
|
||||||
<ClInclude Include="Gdi\Font.h" />
|
<ClInclude Include="Gdi\Font.h" />
|
||||||
<ClInclude Include="Gdi\Gdi.h" />
|
<ClInclude Include="Gdi\Gdi.h" />
|
||||||
<ClInclude Include="Gdi\Caret.h" />
|
<ClInclude Include="Gdi\Caret.h" />
|
||||||
@ -366,6 +367,7 @@
|
|||||||
<ClCompile Include="Dll\DllMain.cpp" />
|
<ClCompile Include="Dll\DllMain.cpp" />
|
||||||
<ClCompile Include="Dll\Dll.cpp" />
|
<ClCompile Include="Dll\Dll.cpp" />
|
||||||
<ClCompile Include="Gdi\CompatDc.cpp" />
|
<ClCompile Include="Gdi\CompatDc.cpp" />
|
||||||
|
<ClCompile Include="Gdi\Cursor.cpp" />
|
||||||
<ClCompile Include="Gdi\Font.cpp" />
|
<ClCompile Include="Gdi\Font.cpp" />
|
||||||
<ClCompile Include="Gdi\Gdi.cpp" />
|
<ClCompile Include="Gdi\Gdi.cpp" />
|
||||||
<ClCompile Include="Gdi\Caret.cpp" />
|
<ClCompile Include="Gdi\Caret.cpp" />
|
||||||
@ -397,6 +399,7 @@
|
|||||||
<None Include="genversion.ps1" />
|
<None Include="genversion.ps1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<FxCompile Include="Shaders\DrawCursor.hlsl" />
|
||||||
<FxCompile Include="Shaders\PaletteLookup.hlsl" />
|
<FxCompile Include="Shaders\PaletteLookup.hlsl" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
@ -435,6 +435,9 @@
|
|||||||
<ClInclude Include="D3dDdi\SurfaceRepository.h">
|
<ClInclude Include="D3dDdi\SurfaceRepository.h">
|
||||||
<Filter>Header Files\D3dDdi</Filter>
|
<Filter>Header Files\D3dDdi</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Gdi\Cursor.h">
|
||||||
|
<Filter>Header Files\Gdi</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="Gdi\Gdi.cpp">
|
<ClCompile Include="Gdi\Gdi.cpp">
|
||||||
@ -683,6 +686,9 @@
|
|||||||
<ClCompile Include="D3dDdi\SurfaceRepository.cpp">
|
<ClCompile Include="D3dDdi\SurfaceRepository.cpp">
|
||||||
<Filter>Source Files\D3dDdi</Filter>
|
<Filter>Source Files\D3dDdi</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Gdi\Cursor.cpp">
|
||||||
|
<Filter>Source Files\Gdi</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="DDrawCompat.rc">
|
<ResourceCompile Include="DDrawCompat.rc">
|
||||||
@ -698,5 +704,8 @@
|
|||||||
<FxCompile Include="Shaders\PaletteLookup.hlsl">
|
<FxCompile Include="Shaders\PaletteLookup.hlsl">
|
||||||
<Filter>Shaders</Filter>
|
<Filter>Shaders</Filter>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
<FxCompile Include="Shaders\DrawCursor.hlsl">
|
||||||
|
<Filter>Shaders</Filter>
|
||||||
|
</FxCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
248
DDrawCompat/Gdi/Cursor.cpp
Normal file
248
DDrawCompat/Gdi/Cursor.cpp
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
#include <Common/ScopedCriticalSection.h>
|
||||||
|
|
||||||
|
#include <Common/Hook.h>
|
||||||
|
#include <Common/Log.h>
|
||||||
|
#include <DDraw/Surfaces/PrimarySurface.h>
|
||||||
|
#include <Gdi/Cursor.h>
|
||||||
|
#include <Win32/DisplayMode.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
DDrawCompat/Gdi/Cursor.h
Normal file
17
DDrawCompat/Gdi/Cursor.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
#include <DDraw/Surfaces/PrimarySurface.h>
|
#include <DDraw/Surfaces/PrimarySurface.h>
|
||||||
#include <Gdi/Caret.h>
|
#include <Gdi/Caret.h>
|
||||||
|
#include <Gdi/Cursor.h>
|
||||||
#include <Gdi/Dc.h>
|
#include <Gdi/Dc.h>
|
||||||
#include <Gdi/DcFunctions.h>
|
#include <Gdi/DcFunctions.h>
|
||||||
#include <Gdi/Font.h>
|
#include <Gdi/Font.h>
|
||||||
@ -46,6 +47,7 @@ namespace Gdi
|
|||||||
ScrollFunctions::installHooks();
|
ScrollFunctions::installHooks();
|
||||||
User32WndProcs::installHooks();
|
User32WndProcs::installHooks();
|
||||||
Caret::installHooks();
|
Caret::installHooks();
|
||||||
|
Cursor::installHooks();
|
||||||
Font::installHooks();
|
Font::installHooks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include <D3dDdi/ScopedCriticalSection.h>
|
#include <D3dDdi/ScopedCriticalSection.h>
|
||||||
|
#include <DDraw/RealPrimarySurface.h>
|
||||||
#include <Gdi/CompatDc.h>
|
#include <Gdi/CompatDc.h>
|
||||||
|
#include <Gdi/Cursor.h>
|
||||||
#include <Gdi/ScrollBar.h>
|
#include <Gdi/ScrollBar.h>
|
||||||
#include <Gdi/ScrollFunctions.h>
|
#include <Gdi/ScrollFunctions.h>
|
||||||
#include <Gdi/TitleBar.h>
|
#include <Gdi/TitleBar.h>
|
||||||
@ -194,6 +196,57 @@ namespace
|
|||||||
}
|
}
|
||||||
return origDefWindowProc(hwnd, msg, wParam, lParam);
|
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<HCURSOR>(cursor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Gdi::Cursor::setCursor(LoadCursor(nullptr, IDC_ARROW));
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return defPaintProc(hwnd, msg, wParam, lParam, origDefWindowProc);
|
return defPaintProc(hwnd, msg, wParam, lParam, origDefWindowProc);
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <Common/ScopedSrwLock.h>
|
#include <Common/ScopedSrwLock.h>
|
||||||
#include <Dll/Dll.h>
|
#include <Dll/Dll.h>
|
||||||
#include <Gdi/CompatDc.h>
|
#include <Gdi/CompatDc.h>
|
||||||
|
#include <Gdi/Cursor.h>
|
||||||
#include <Gdi/Dc.h>
|
#include <Gdi/Dc.h>
|
||||||
#include <Gdi/PresentationWindow.h>
|
#include <Gdi/PresentationWindow.h>
|
||||||
#include <Gdi/ScrollBar.h>
|
#include <Gdi/ScrollBar.h>
|
||||||
@ -172,65 +173,6 @@ namespace
|
|||||||
IsWindowUnicode(hwnd) ? it->second.wndProcW : it->second.wndProcA);
|
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<WPARAM>(dc), reinterpret_cast<LPARAM>(hwnd));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DefWindowProc(hwnd, WM_CTLCOLORSCROLLBAR,
|
|
||||||
reinterpret_cast<WPARAM>(dc), reinterpret_cast<LPARAM>(hwnd));
|
|
||||||
}
|
|
||||||
ReleaseDC(hwnd, dc);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void onCreateWindow(HWND hwnd)
|
void onCreateWindow(HWND hwnd)
|
||||||
{
|
{
|
||||||
LOG_FUNC("onCreateWindow", hwnd);
|
LOG_FUNC("onCreateWindow", hwnd);
|
||||||
@ -425,6 +367,72 @@ namespace
|
|||||||
}
|
}
|
||||||
return LOG_RESULT(result);
|
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<WPARAM>(dc), reinterpret_cast<LPARAM>(hwnd));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DefWindowProc(hwnd, WM_CTLCOLORSCROLLBAR,
|
||||||
|
reinterpret_cast<WPARAM>(dc), reinterpret_cast<LPARAM>(hwnd));
|
||||||
|
}
|
||||||
|
ReleaseDC(hwnd, dc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Gdi
|
namespace Gdi
|
||||||
@ -461,9 +469,13 @@ namespace Gdi
|
|||||||
HOOK_FUNCTION(user32, UpdateLayeredWindowIndirect, updateLayeredWindowIndirect);
|
HOOK_FUNCTION(user32, UpdateLayeredWindowIndirect, updateLayeredWindowIndirect);
|
||||||
|
|
||||||
SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE,
|
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,
|
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)
|
void onCreateWindow(HWND hwnd)
|
||||||
|
19
DDrawCompat/Shaders/DrawCursor.hlsl
Normal file
19
DDrawCompat/Shaders/DrawCursor.hlsl
Normal file
@ -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);
|
||||||
|
}
|
@ -46,7 +46,6 @@ namespace
|
|||||||
};
|
};
|
||||||
|
|
||||||
DWORD g_desktopBpp = 0;
|
DWORD g_desktopBpp = 0;
|
||||||
RECT g_cursorRect = {};
|
|
||||||
ULONG g_displaySettingsUniquenessBias = 0;
|
ULONG g_displaySettingsUniquenessBias = 0;
|
||||||
EmulatedDisplayMode g_emulatedDisplayMode = {};
|
EmulatedDisplayMode g_emulatedDisplayMode = {};
|
||||||
Compat::SrwLock g_srwLock;
|
Compat::SrwLock g_srwLock;
|
||||||
@ -148,12 +147,9 @@ namespace
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RECT clipRect = {};
|
|
||||||
|
|
||||||
{
|
{
|
||||||
Compat::ScopedSrwLockExclusive srwLock(g_srwLock);
|
Compat::ScopedSrwLockExclusive srwLock(g_srwLock);
|
||||||
++g_displaySettingsUniquenessBias;
|
++g_displaySettingsUniquenessBias;
|
||||||
clipRect = g_cursorRect;
|
|
||||||
if (lpDevMode)
|
if (lpDevMode)
|
||||||
{
|
{
|
||||||
g_emulatedDisplayMode.width = lpDevMode->dmPelsWidth;
|
g_emulatedDisplayMode.width = lpDevMode->dmPelsWidth;
|
||||||
@ -167,8 +163,6 @@ namespace
|
|||||||
g_emulatedDisplayMode.rect.bottom = g_emulatedDisplayMode.rect.top + lpDevMode->dmPelsHeight;
|
g_emulatedDisplayMode.rect.bottom = g_emulatedDisplayMode.rect.top + lpDevMode->dmPelsHeight;
|
||||||
g_emulatedDisplayMode.diff.cx = lpDevMode->dmPelsWidth - currDevMode.dmPelsWidth;
|
g_emulatedDisplayMode.diff.cx = lpDevMode->dmPelsWidth - currDevMode.dmPelsWidth;
|
||||||
g_emulatedDisplayMode.diff.cy = lpDevMode->dmPelsHeight - currDevMode.dmPelsHeight;
|
g_emulatedDisplayMode.diff.cy = lpDevMode->dmPelsHeight - currDevMode.dmPelsHeight;
|
||||||
|
|
||||||
IntersectRect(&clipRect, &clipRect, &g_emulatedDisplayMode.rect);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -177,8 +171,6 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CALL_ORIG_FUNC(ClipCursor)(&clipRect);
|
|
||||||
|
|
||||||
auto& dm = lpDevMode ? *lpDevMode : currDevMode;
|
auto& dm = lpDevMode ? *lpDevMode : currDevMode;
|
||||||
LPARAM resolution = (dm.dmPelsHeight << 16) | dm.dmPelsWidth;
|
LPARAM resolution = (dm.dmPelsHeight << 16) | dm.dmPelsWidth;
|
||||||
EnumWindows(sendDisplayChange, resolution);
|
EnumWindows(sendDisplayChange, resolution);
|
||||||
@ -209,31 +201,6 @@ namespace
|
|||||||
lpszDeviceName, lpDevMode, hwnd, dwflags, lParam));
|
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()
|
void disableDwm8And16BitMitigation()
|
||||||
{
|
{
|
||||||
auto user32 = GetModuleHandle("user32");
|
auto user32 = GetModuleHandle("user32");
|
||||||
@ -342,17 +309,6 @@ namespace
|
|||||||
return CALL_ORIG_FUNC(GdiEntry13)() + g_displaySettingsUniquenessBias;
|
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 <typename DevMode, typename EnumDisplaySettingsExFunc, typename Char>
|
template <typename DevMode, typename EnumDisplaySettingsExFunc, typename Char>
|
||||||
SIZE getConfiguredResolution(EnumDisplaySettingsExFunc origEnumDisplaySettingsEx, const Char* deviceName)
|
SIZE getConfiguredResolution(EnumDisplaySettingsExFunc origEnumDisplaySettingsEx, const Char* deviceName)
|
||||||
{
|
{
|
||||||
@ -671,16 +627,13 @@ namespace Win32
|
|||||||
g_desktopBpp = dm.dmBitsPerPel;
|
g_desktopBpp = dm.dmBitsPerPel;
|
||||||
g_emulatedDisplayMode.bpp = dm.dmBitsPerPel;
|
g_emulatedDisplayMode.bpp = dm.dmBitsPerPel;
|
||||||
|
|
||||||
GetClipCursor(&g_cursorRect);
|
|
||||||
EnumDisplayMonitors(nullptr, nullptr, &initMonitor, 0);
|
EnumDisplayMonitors(nullptr, nullptr, &initMonitor, 0);
|
||||||
|
|
||||||
HOOK_FUNCTION(user32, ChangeDisplaySettingsExA, changeDisplaySettingsExA);
|
HOOK_FUNCTION(user32, ChangeDisplaySettingsExA, changeDisplaySettingsExA);
|
||||||
HOOK_FUNCTION(user32, ChangeDisplaySettingsExW, changeDisplaySettingsExW);
|
HOOK_FUNCTION(user32, ChangeDisplaySettingsExW, changeDisplaySettingsExW);
|
||||||
HOOK_FUNCTION(user32, ClipCursor, clipCursor);
|
|
||||||
HOOK_FUNCTION(user32, EnumDisplaySettingsExA, enumDisplaySettingsExA);
|
HOOK_FUNCTION(user32, EnumDisplaySettingsExA, enumDisplaySettingsExA);
|
||||||
HOOK_FUNCTION(user32, EnumDisplaySettingsExW, enumDisplaySettingsExW);
|
HOOK_FUNCTION(user32, EnumDisplaySettingsExW, enumDisplaySettingsExW);
|
||||||
HOOK_FUNCTION(gdi32, GdiEntry13, gdiEntry13);
|
HOOK_FUNCTION(gdi32, GdiEntry13, gdiEntry13);
|
||||||
HOOK_FUNCTION(user32, GetClipCursor, getClipCursor);
|
|
||||||
HOOK_FUNCTION(gdi32, GetDeviceCaps, getDeviceCaps);
|
HOOK_FUNCTION(gdi32, GetDeviceCaps, getDeviceCaps);
|
||||||
HOOK_FUNCTION(user32, GetMonitorInfoA, getMonitorInfoA);
|
HOOK_FUNCTION(user32, GetMonitorInfoA, getMonitorInfoA);
|
||||||
HOOK_FUNCTION(user32, GetMonitorInfoW, getMonitorInfoW);
|
HOOK_FUNCTION(user32, GetMonitorInfoW, getMonitorInfoW);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user