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

Moved palettized presentation handling to driver level

This commit is contained in:
narzoul 2021-01-16 12:42:56 +01:00
parent affc5ab17e
commit 0e7f397863
4 changed files with 58 additions and 84 deletions

View File

@ -15,7 +15,6 @@ namespace
{
HANDLE g_gdiResourceHandle = nullptr;
D3dDdi::Resource* g_gdiResource = nullptr;
bool g_isReadOnlyGdiLockEnabled = false;
void logSrcColorKeySupportFailure(const char* reason, UINT32 resultCode)
{
@ -453,11 +452,6 @@ namespace D3dDdi
}
}
void Device::setReadOnlyGdiLock(bool enable)
{
g_isReadOnlyGdiLockEnabled = enable;
}
std::map<HANDLE, Device> Device::s_devices;
bool Device::s_isFlushEnabled = true;
}

View File

@ -68,7 +68,6 @@ namespace D3dDdi
static Resource* findResource(HANDLE resource);
static Resource* getGdiResource();
static void setGdiResourceHandle(HANDLE resource);
static void setReadOnlyGdiLock(bool enable);
private:
bool checkSrcColorKeySupport();

View File

@ -10,6 +10,7 @@
#include <D3dDdi/Log/DeviceFuncsLog.h>
#include <D3dDdi/Resource.h>
#include <DDraw/Blitter.h>
#include <Gdi/Palette.h>
#include <Gdi/VirtualScreen.h>
namespace
@ -530,6 +531,43 @@ namespace D3dDdi
HRESULT Resource::presentationBlt(const D3DDDIARG_BLT& data, Resource& srcResource)
{
if (D3DDDIFMT_P8 == srcResource.m_origData.Format)
{
D3DDDIARG_LOCK lock = {};
lock.hResource = m_handle;
lock.SubResourceIndex = data.DstSubResourceIndex;
lock.Flags.Discard = 1;
HRESULT result = m_device.getOrigVtable().pfnLock(m_device, &lock);
if (FAILED(result))
{
return result;
}
auto entries(Gdi::Palette::getHardwarePalette());
DWORD pal[256] = {};
for (UINT i = 0; i < 256; ++i)
{
pal[i] = (entries[i].peRed << 16) | (entries[i].peGreen << 8) | entries[i].peBlue;
}
auto& srcLockData = srcResource.m_lockData[data.SrcSubResourceIndex];
for (UINT y = 0; y < srcResource.m_fixedData.surfaceData[data.SrcSubResourceIndex].Height; ++y)
{
auto src = static_cast<const BYTE*>(srcLockData.data) + y * srcLockData.pitch;
auto dst = reinterpret_cast<DWORD*>(static_cast<BYTE*>(lock.pSurfData) + y * lock.Pitch);
for (UINT x = 0; x < srcResource.m_fixedData.surfaceData[data.SrcSubResourceIndex].Width; ++x)
{
dst[x] = pal[*src];
++src;
}
}
D3DDDIARG_UNLOCK unlock = {};
unlock.hResource = m_handle;
unlock.SubResourceIndex = data.DstSubResourceIndex;
return m_device.getOrigVtable().pfnUnlock(m_device, &unlock);
}
if (srcResource.m_lockResource &&
srcResource.m_lockData[data.SrcSubResourceIndex].isSysMemUpToDate)
{
@ -547,6 +585,10 @@ namespace D3dDdi
{
createGdiLockResource();
}
else
{
createLockResource();
}
}
HRESULT Resource::splitBlt(D3DDDIARG_BLT& data, UINT& subResourceIndex, RECT& rect, RECT& otherRect)
@ -621,16 +663,19 @@ namespace D3dDdi
bool isSysMemBltPreferred = true;
auto now = Time::queryPerformanceCounter();
if (data.Flags.MirrorLeftRight || data.Flags.MirrorUpDown ||
(data.Flags.SrcColorKey && !m_device.isSrcColorKeySupported()))
if (D3DDDIFMT_P8 != m_fixedData.Format)
{
dstLockData.qpcLastForcedLock = now;
srcLockData.qpcLastForcedLock = now;
}
else
{
isSysMemBltPreferred = dstLockData.isSysMemUpToDate &&
Time::qpcToMs(now - dstLockData.qpcLastForcedLock) <= Config::evictionTimeout;
if (data.Flags.MirrorLeftRight || data.Flags.MirrorUpDown ||
(data.Flags.SrcColorKey && !m_device.isSrcColorKeySupported()))
{
dstLockData.qpcLastForcedLock = now;
srcLockData.qpcLastForcedLock = now;
}
else
{
isSysMemBltPreferred = dstLockData.isSysMemUpToDate &&
Time::qpcToMs(now - dstLockData.qpcLastForcedLock) <= Config::evictionTimeout;
}
}
if (isSysMemBltPreferred)

View File

@ -27,7 +27,6 @@ namespace
void onRelease();
CompatWeakPtr<IDirectDrawSurface7> g_frontBuffer;
CompatWeakPtr<IDirectDrawSurface7> g_paletteConverter;
CompatWeakPtr<IDirectDrawClipper> g_clipper;
DDSURFACEDESC2 g_surfaceDesc = {};
DDraw::IReleaseNotifier g_releaseNotifier(onRelease);
@ -62,38 +61,6 @@ namespace
}
}
template <typename TDirectDraw>
HRESULT createPaletteConverter(CompatRef<TDirectDraw> dd)
{
auto dm = DDraw::getDisplayMode(*CompatPtr<IDirectDraw7>::from(&dd));
if (dm.ddpfPixelFormat.dwRGBBitCount > 8)
{
return DD_OK;
}
typename DDraw::Types<TDirectDraw>::TSurfaceDesc desc = {};
desc.dwSize = sizeof(desc);
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
desc.dwWidth = dm.dwWidth;
desc.dwHeight = dm.dwHeight;
desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
desc.ddpfPixelFormat.dwRGBBitCount = 32;
desc.ddpfPixelFormat.dwRBitMask = 0x00FF0000;
desc.ddpfPixelFormat.dwGBitMask = 0x0000FF00;
desc.ddpfPixelFormat.dwBBitMask = 0x000000FF;
desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
CompatPtr<DDraw::Types<TDirectDraw>::TCreatedSurface> paletteConverter;
HRESULT result = dd->CreateSurface(&dd, &desc, &paletteConverter.getRef(), nullptr);
if (SUCCEEDED(result))
{
g_paletteConverter = Compat::queryInterface<IDirectDrawSurface7>(paletteConverter.get());
}
return result;
}
CompatPtr<IDirectDrawSurface7> getBackBuffer()
{
DDSCAPS2 caps = {};
@ -157,7 +124,6 @@ namespace
g_clipper.release();
g_isFullScreen = false;
g_waitingForPrimaryUnlock = false;
g_paletteConverter.release();
g_surfaceDesc = {};
}
@ -206,32 +172,9 @@ namespace
Gdi::Region excludeRegion(monitorRect);
Gdi::Window::present(excludeRegion);
if (Win32::DisplayMode::getBpp() <= 8)
{
HDC paletteConverterDc = nullptr;
g_paletteConverter->GetDC(g_paletteConverter, &paletteConverterDc);
HDC srcDc = nullptr;
D3dDdi::Device::setReadOnlyGdiLock(true);
D3dDdi::KernelModeThunks::setDcPaletteOverride(true);
src->GetDC(src, &srcDc);
D3dDdi::KernelModeThunks::setDcPaletteOverride(false);
D3dDdi::Device::setReadOnlyGdiLock(false);
if (paletteConverterDc && srcDc)
{
CALL_ORIG_FUNC(BitBlt)(paletteConverterDc,
0, 0, g_surfaceDesc.dwWidth, g_surfaceDesc.dwHeight, srcDc, 0, 0, SRCCOPY);
}
src->ReleaseDC(src, srcDc);
g_paletteConverter->ReleaseDC(g_paletteConverter, paletteConverterDc);
bltToPrimaryChain(*g_paletteConverter);
}
else
{
bltToPrimaryChain(*src);
}
D3dDdi::KernelModeThunks::setDcPaletteOverride(true);
bltToPrimaryChain(*src);
D3dDdi::KernelModeThunks::setDcPaletteOverride(false);
if (g_isFullScreen && src == DDraw::PrimarySurface::getGdiSurface())
{
@ -309,12 +252,6 @@ namespace DDraw
HRESULT RealPrimarySurface::create(CompatRef<DirectDraw> dd)
{
DDraw::ScopedThreadLock lock;
HRESULT result = createPaletteConverter(dd);
if (FAILED(result))
{
Compat::Log() << "ERROR: Failed to create the palette converter surface: " << Compat::hex(result);
return result;
}
typename Types<DirectDraw>::TSurfaceDesc desc = {};
desc.dwSize = sizeof(desc);
@ -323,7 +260,7 @@ namespace DDraw
desc.dwBackBufferCount = 2;
CompatPtr<typename Types<DirectDraw>::TCreatedSurface> surface;
result = dd->CreateSurface(&dd, &desc, &surface.getRef(), nullptr);
HRESULT result = dd->CreateSurface(&dd, &desc, &surface.getRef(), nullptr);
if (DDERR_NOEXCLUSIVEMODE == result)
{
@ -336,7 +273,6 @@ namespace DDraw
if (FAILED(result))
{
Compat::Log() << "ERROR: Failed to create the real primary surface: " << Compat::hex(result);
g_paletteConverter.release();
return result;
}