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

Added RenderColorDepth setting

This commit is contained in:
narzoul 2021-12-14 13:15:19 +01:00
parent 9fb450e233
commit c1e654de7d
15 changed files with 350 additions and 181 deletions

View File

@ -8,6 +8,7 @@ namespace Config
Settings::DesktopColorDepth desktopColorDepth; Settings::DesktopColorDepth desktopColorDepth;
Settings::DisplayFilter displayFilter; Settings::DisplayFilter displayFilter;
Settings::DisplayResolution displayResolution; Settings::DisplayResolution displayResolution;
Settings::RenderColorDepth renderColorDepth;
Settings::SupportedResolutions supportedResolutions; Settings::SupportedResolutions supportedResolutions;
Settings::TextureFilter textureFilter; Settings::TextureFilter textureFilter;
Settings::ThreadPriorityBoost threadPriorityBoost; Settings::ThreadPriorityBoost threadPriorityBoost;

View File

@ -6,6 +6,7 @@
#include <Config/Settings/DesktopColorDepth.h> #include <Config/Settings/DesktopColorDepth.h>
#include <Config/Settings/DisplayFilter.h> #include <Config/Settings/DisplayFilter.h>
#include <Config/Settings/DisplayResolution.h> #include <Config/Settings/DisplayResolution.h>
#include <Config/Settings/RenderColorDepth.h>
#include <Config/Settings/SupportedResolutions.h> #include <Config/Settings/SupportedResolutions.h>
#include <Config/Settings/TextureFilter.h> #include <Config/Settings/TextureFilter.h>
#include <Config/Settings/ThreadPriorityBoost.h> #include <Config/Settings/ThreadPriorityBoost.h>
@ -22,6 +23,7 @@ namespace Config
extern Settings::DesktopColorDepth desktopColorDepth; extern Settings::DesktopColorDepth desktopColorDepth;
extern Settings::DisplayFilter displayFilter; extern Settings::DisplayFilter displayFilter;
extern Settings::DisplayResolution displayResolution; extern Settings::DisplayResolution displayResolution;
extern Settings::RenderColorDepth renderColorDepth;
extern Settings::SupportedResolutions supportedResolutions; extern Settings::SupportedResolutions supportedResolutions;
extern Settings::TextureFilter textureFilter; extern Settings::TextureFilter textureFilter;
extern Settings::ThreadPriorityBoost threadPriorityBoost; extern Settings::ThreadPriorityBoost threadPriorityBoost;

View File

@ -0,0 +1,18 @@
#pragma once
#include <Config/MappedSetting.h>
namespace Config
{
namespace Settings
{
class RenderColorDepth : public MappedSetting<unsigned>
{
public:
RenderColorDepth()
: MappedSetting("RenderColorDepth", "app", { {"app", 0}, {"16", 16}, {"32", 32} })
{
}
};
}
}

View File

@ -86,29 +86,11 @@ namespace D3dDdi
return it != m_resources.end() ? it->second.get() : nullptr; return it != m_resources.end() ? it->second.get() : nullptr;
} }
void Device::prepareForBlt(HANDLE resource, UINT subResourceIndex, bool isReadOnly) void Device::prepareForGpuWrite()
{
auto it = m_resources.find(resource);
if (it != m_resources.end())
{
it->second->prepareForBlt(subResourceIndex, isReadOnly);
}
}
void Device::prepareForRendering(HANDLE resource, UINT subResourceIndex)
{
auto it = m_resources.find(resource);
if (it != m_resources.end())
{
it->second->prepareForRendering(subResourceIndex);
}
}
void Device::prepareForRendering()
{ {
if (m_renderTarget) if (m_renderTarget)
{ {
m_renderTarget->prepareForRendering(m_renderTargetSubResourceIndex); m_renderTarget->prepareForGpuWrite(m_renderTargetSubResourceIndex);
} }
} }
@ -152,7 +134,12 @@ namespace D3dDdi
{ {
return it->second->blt(*data); return it->second->blt(*data);
} }
prepareForBlt(data->hSrcResource, data->SrcSubResourceIndex, true);
it = m_resources.find(data->hSrcResource);
if (it != m_resources.end())
{
it->second->prepareForBltSrc(*data);
}
return m_origVtable.pfnBlt(m_device, data); return m_origVtable.pfnBlt(m_device, data);
} }
@ -162,7 +149,7 @@ namespace D3dDdi
m_state.flush(); m_state.flush();
if (data->Flags & D3DCLEAR_TARGET) if (data->Flags & D3DCLEAR_TARGET)
{ {
prepareForRendering(); prepareForGpuWrite();
} }
return m_origVtable.pfnClear(m_device, data, numRect, rect); return m_origVtable.pfnClear(m_device, data, numRect, rect);
} }
@ -258,13 +245,11 @@ namespace D3dDdi
HRESULT Device::pfnDrawIndexedPrimitive2(const D3DDDIARG_DRAWINDEXEDPRIMITIVE2* data, HRESULT Device::pfnDrawIndexedPrimitive2(const D3DDDIARG_DRAWINDEXEDPRIMITIVE2* data,
UINT /*indicesSize*/, const void* indexBuffer, const UINT* flagBuffer) UINT /*indicesSize*/, const void* indexBuffer, const UINT* flagBuffer)
{ {
prepareForRendering();
return m_drawPrimitive.drawIndexed(*data, static_cast<const UINT16*>(indexBuffer), flagBuffer); return m_drawPrimitive.drawIndexed(*data, static_cast<const UINT16*>(indexBuffer), flagBuffer);
} }
HRESULT Device::pfnDrawPrimitive(const D3DDDIARG_DRAWPRIMITIVE* data, const UINT* flagBuffer) HRESULT Device::pfnDrawPrimitive(const D3DDDIARG_DRAWPRIMITIVE* data, const UINT* flagBuffer)
{ {
prepareForRendering();
return m_drawPrimitive.draw(*data, flagBuffer); return m_drawPrimitive.draw(*data, flagBuffer);
} }
@ -312,16 +297,27 @@ namespace D3dDdi
HRESULT Device::pfnPresent(const D3DDDIARG_PRESENT* data) HRESULT Device::pfnPresent(const D3DDDIARG_PRESENT* data)
{ {
flushPrimitives(); flushPrimitives();
prepareForBlt(data->hSrcResource, data->SrcSubResourceIndex, true); auto d = *data;
return m_origVtable.pfnPresent(m_device, data); auto resource = getResource(data->hSrcResource);
if (resource)
{
d.hSrcResource = resource->prepareForGpuRead(data->SrcSubResourceIndex);
}
return m_origVtable.pfnPresent(m_device, &d);
} }
HRESULT Device::pfnPresent1(D3DDDIARG_PRESENT1* data) HRESULT Device::pfnPresent1(D3DDDIARG_PRESENT1* data)
{ {
flushPrimitives(); flushPrimitives();
std::vector<D3DDDIARG_PRESENTSURFACE> srcResources(data->phSrcResources, data->phSrcResources + data->SrcResources);
data->phSrcResources = srcResources.data();
for (UINT i = 0; i < data->SrcResources; ++i) for (UINT i = 0; i < data->SrcResources; ++i)
{ {
prepareForBlt(data->phSrcResources[i].hResource, data->phSrcResources[i].SubResourceIndex, true); auto resource = getResource(srcResources[i].hResource);
if (resource)
{
srcResources[i].hResource = resource->prepareForGpuRead(srcResources[i].SubResourceIndex);
}
} }
return m_origVtable.pfnPresent1(m_device, data); return m_origVtable.pfnPresent1(m_device, data);
} }

View File

@ -55,9 +55,7 @@ namespace D3dDdi
HRESULT createPrivateResource(D3DDDIARG_CREATERESOURCE2& data); HRESULT createPrivateResource(D3DDDIARG_CREATERESOURCE2& data);
void flushPrimitives() { m_drawPrimitive.flushPrimitives(); } void flushPrimitives() { m_drawPrimitive.flushPrimitives(); }
void prepareForBlt(HANDLE resource, UINT subResourceIndex, bool isReadOnly); void prepareForGpuWrite();
void prepareForRendering(HANDLE resource, UINT subResourceIndex);
void prepareForRendering();
void setRenderTarget(const D3DDDIARG_SETRENDERTARGET& data); void setRenderTarget(const D3DDDIARG_SETRENDERTARGET& data);
void updateConfig(); void updateConfig();

View File

@ -354,7 +354,6 @@ namespace D3dDdi
{ {
m_app.renderTarget = *data; m_app.renderTarget = *data;
m_changedStates |= CS_RENDER_TARGET; m_changedStates |= CS_RENDER_TARGET;
m_device.setRenderTarget(*data);
return S_OK; return S_OK;
} }
@ -509,6 +508,7 @@ namespace D3dDdi
{ {
if (setData(renderTarget, m_current.renderTarget, m_device.getOrigVtable().pfnSetRenderTarget)) if (setData(renderTarget, m_current.renderTarget, m_device.getOrigVtable().pfnSetRenderTarget))
{ {
m_device.setRenderTarget(m_app.renderTarget);
LOG_DS << renderTarget; LOG_DS << renderTarget;
} }
} }

View File

@ -597,6 +597,7 @@ namespace D3dDdi
} }
LOG_DEBUG << "Flushing " << m_batched.primitiveCount << " primitives of type " << m_batched.primitiveType; LOG_DEBUG << "Flushing " << m_batched.primitiveCount << " primitives of type " << m_batched.primitiveType;
m_device.prepareForGpuWrite();
return m_batched.indices.empty() ? flush(flagBuffer) : flushIndexed(flagBuffer); return m_batched.indices.empty() ? flush(flagBuffer) : flushIndexed(flagBuffer);
} }

View File

@ -25,7 +25,9 @@ namespace
const UINT g_resourceTypeFlags = getResourceTypeFlags().Value; const UINT g_resourceTypeFlags = getResourceTypeFlags().Value;
RECT g_presentationRect = {}; RECT g_presentationRect = {};
RECT g_primaryRect = {}; RECT g_primaryRect = {};
D3DDDIFORMAT g_formatOverride = D3DDDIFMT_UNKNOWN; D3DDDIFORMAT g_formatOverride = D3DDDIFMT_UNKNOWN;
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> g_msaaOverride = {};
RECT calculatePresentationRect() RECT calculatePresentationRect()
{ {
@ -106,7 +108,9 @@ namespace D3dDdi
, m_fixedData(data) , m_fixedData(data)
, m_lockBuffer(nullptr, &heapFree) , m_lockBuffer(nullptr, &heapFree)
, m_lockResource(nullptr, ResourceDeleter(device, device.getOrigVtable().pfnDestroyResource)) , m_lockResource(nullptr, ResourceDeleter(device, device.getOrigVtable().pfnDestroyResource))
, m_customSurface{} , m_msaaSurface{}
, m_msaaResolvedSurface{}
, m_formatConfig(D3DDDIFMT_UNKNOWN)
, m_multiSampleConfig{ D3DDDIMULTISAMPLE_NONE, 0 } , m_multiSampleConfig{ D3DDDIMULTISAMPLE_NONE, 0 }
, m_isSurfaceRepoResource(SurfaceRepository::inCreateSurface()) , m_isSurfaceRepoResource(SurfaceRepository::inCreateSurface())
{ {
@ -133,6 +137,7 @@ namespace D3dDdi
fixResourceData(); fixResourceData();
m_formatInfo = getFormatInfo(m_fixedData.Format); m_formatInfo = getFormatInfo(m_fixedData.Format);
m_formatConfig = m_fixedData.Format;
HRESULT result = m_device.createPrivateResource(m_fixedData); HRESULT result = m_device.createPrivateResource(m_fixedData);
if (FAILED(result)) if (FAILED(result))
@ -195,31 +200,33 @@ namespace D3dDdi
{ {
if (srcResource) if (srcResource)
{ {
srcResource->prepareForBlt(data.SrcSubResourceIndex, true); srcResource->prepareForBltSrc(data);
} }
HRESULT result = splitBlt(data, data.DstSubResourceIndex, data.DstRect, data.SrcRect); return splitBlt(data, data.DstSubResourceIndex, data.DstRect, data.SrcRect);
notifyLock(data.DstSubResourceIndex);
return result;
} }
else if (srcResource)
if (srcResource)
{ {
if (srcResource->isOversized()) if (srcResource->isOversized())
{ {
prepareForBlt(data.DstSubResourceIndex, false); if (m_lockResource)
HRESULT result = srcResource->splitBlt(data, data.SrcSubResourceIndex, data.SrcRect, data.DstRect); {
srcResource->notifyLock(data.SrcSubResourceIndex); loadVidMemResource(data.DstSubResourceIndex);
return result; clearUpToDateFlags(data.DstSubResourceIndex);
m_lockData[data.DstSubResourceIndex].isVidMemUpToDate = true;
}
return srcResource->splitBlt(data, data.SrcSubResourceIndex, data.SrcRect, data.DstRect);
} }
else if (m_fixedData.Flags.Primary)
if (m_fixedData.Flags.Primary)
{ {
return presentationBlt(data, srcResource); return presentationBlt(data, srcResource);
} }
else
{ return sysMemPreferredBlt(data, *srcResource);
return sysMemPreferredBlt(data, *srcResource);
}
} }
prepareForBlt(data.DstSubResourceIndex, false);
prepareForBltDst(data);
return m_device.getOrigVtable().pfnBlt(m_device, &data); return m_device.getOrigVtable().pfnBlt(m_device, &data);
} }
@ -227,14 +234,15 @@ namespace D3dDdi
{ {
LOG_FUNC("Resource::bltLock", data); LOG_FUNC("Resource::bltLock", data);
loadSysMemResource(data.SubResourceIndex);
auto& lockData = m_lockData[data.SubResourceIndex]; auto& lockData = m_lockData[data.SubResourceIndex];
if (!lockData.isSysMemUpToDate)
{
copyToSysMem(data.SubResourceIndex);
}
lockData.isVidMemUpToDate &= data.Flags.ReadOnly;
lockData.isCustomUpToDate &= data.Flags.ReadOnly;
lockData.qpcLastForcedLock = Time::queryPerformanceCounter(); lockData.qpcLastForcedLock = Time::queryPerformanceCounter();
if (!data.Flags.ReadOnly)
{
clearUpToDateFlags(data.SubResourceIndex);
lockData.isSysMemUpToDate = true;
}
unsigned char* ptr = static_cast<unsigned char*>(lockData.data); unsigned char* ptr = static_cast<unsigned char*>(lockData.data);
if (data.Flags.AreaValid) if (data.Flags.AreaValid)
@ -244,18 +252,15 @@ namespace D3dDdi
data.pSurfData = ptr; data.pSurfData = ptr;
data.Pitch = lockData.pitch; data.Pitch = lockData.pitch;
++lockData.lockCount;
return LOG_RESULT(S_OK); return LOG_RESULT(S_OK);
} }
HRESULT Resource::bltUnlock(const D3DDDIARG_UNLOCK& data) void Resource::clearUpToDateFlags(UINT subResourceIndex)
{ {
LOG_FUNC("Resource::bltUnlock", data); m_lockData[subResourceIndex].isMsaaUpToDate = false;
if (0 != m_lockData[data.SubResourceIndex].lockCount) m_lockData[subResourceIndex].isMsaaResolvedUpToDate = false;
{ m_lockData[subResourceIndex].isVidMemUpToDate = false;
--m_lockData[data.SubResourceIndex].lockCount; m_lockData[subResourceIndex].isSysMemUpToDate = false;
}
return LOG_RESULT(S_OK);
} }
void Resource::clipRect(UINT subResourceIndex, RECT& rect) void Resource::clipRect(UINT subResourceIndex, RECT& rect)
@ -278,6 +283,24 @@ namespace D3dDdi
if (m_lockResource) if (m_lockResource)
{ {
auto& lockData = m_lockData[data.SubResourceIndex]; auto& lockData = m_lockData[data.SubResourceIndex];
if (lockData.isVidMemUpToDate)
{
m_device.getOrigVtable().pfnColorFill(m_device, &data);
}
if (lockData.isMsaaUpToDate)
{
data.hResource = *m_msaaSurface.resource;
m_device.getOrigVtable().pfnColorFill(m_device, &data);
}
if (lockData.isMsaaResolvedUpToDate)
{
data.hResource = *m_msaaResolvedSurface.resource;
m_device.getOrigVtable().pfnColorFill(m_device, &data);
}
if (lockData.isSysMemUpToDate) if (lockData.isSysMemUpToDate)
{ {
auto dstBuf = static_cast<BYTE*>(lockData.data) + auto dstBuf = static_cast<BYTE*>(lockData.data) +
@ -286,13 +309,11 @@ namespace D3dDdi
DDraw::Blitter::colorFill(dstBuf, lockData.pitch, DDraw::Blitter::colorFill(dstBuf, lockData.pitch,
data.DstRect.right - data.DstRect.left, data.DstRect.bottom - data.DstRect.top, data.DstRect.right - data.DstRect.left, data.DstRect.bottom - data.DstRect.top,
m_formatInfo.bytesPerPixel, colorConvert(m_formatInfo, data.Color)); m_formatInfo.bytesPerPixel, colorConvert(m_formatInfo, data.Color));
m_lockData[data.SubResourceIndex].isVidMemUpToDate = false;
m_lockData[data.SubResourceIndex].isCustomUpToDate = false;
return LOG_RESULT(S_OK);
} }
return LOG_RESULT(S_OK);
} }
prepareForBlt(data.SubResourceIndex, false);
return LOG_RESULT(m_device.getOrigVtable().pfnColorFill(m_device, &data)); return LOG_RESULT(m_device.getOrigVtable().pfnColorFill(m_device, &data));
} }
@ -319,32 +340,6 @@ namespace D3dDdi
return LOG_RESULT(result); return LOG_RESULT(result);
} }
void Resource::copyToSysMem(UINT subResourceIndex)
{
if (!m_lockData[subResourceIndex].isVidMemUpToDate)
{
copySubResource(m_handle, m_customSurface.resource->m_handle, subResourceIndex);
m_lockData[subResourceIndex].isVidMemUpToDate = true;
}
copySubResource(m_lockResource.get(), m_handle, subResourceIndex);
notifyLock(subResourceIndex);
m_lockData[subResourceIndex].isSysMemUpToDate = true;
}
void Resource::copyToVidMem(UINT subResourceIndex)
{
if (m_lockData[subResourceIndex].isCustomUpToDate)
{
copySubResource(m_handle, m_customSurface.resource->m_handle, subResourceIndex);
}
else
{
copySubResource(m_handle, m_lockResource.get(), subResourceIndex);
notifyLock(subResourceIndex);
}
m_lockData[subResourceIndex].isVidMemUpToDate = true;
}
void Resource::createGdiLockResource() void Resource::createGdiLockResource()
{ {
auto gdiSurfaceDesc(Gdi::VirtualScreen::getSurfaceDesc(DDraw::PrimarySurface::getMonitorRect())); auto gdiSurfaceDesc(Gdi::VirtualScreen::getSurfaceDesc(DDraw::PrimarySurface::getMonitorRect()));
@ -363,8 +358,8 @@ namespace D3dDdi
createSysMemResource({ surfaceInfo }); createSysMemResource({ surfaceInfo });
if (m_lockResource) if (m_lockResource)
{ {
m_lockData[0].isVidMemUpToDate = false; clearUpToDateFlags(0);
m_lockData[0].isCustomUpToDate = false; m_lockData[0].isSysMemUpToDate = true;
} }
else else
{ {
@ -444,7 +439,8 @@ namespace D3dDdi
m_lockData[i].qpcLastForcedLock = qpcLastForcedLock; m_lockData[i].qpcLastForcedLock = qpcLastForcedLock;
m_lockData[i].isSysMemUpToDate = true; m_lockData[i].isSysMemUpToDate = true;
m_lockData[i].isVidMemUpToDate = true; m_lockData[i].isVidMemUpToDate = true;
m_lockData[i].isCustomUpToDate = m_customSurface.resource; m_lockData[i].isMsaaUpToDate = m_msaaSurface.resource;
m_lockData[i].isMsaaResolvedUpToDate = m_msaaResolvedSurface.resource;
} }
} }
@ -472,9 +468,12 @@ namespace D3dDdi
if (D3DDDIFMT_UNKNOWN != g_formatOverride) if (D3DDDIFMT_UNKNOWN != g_formatOverride)
{ {
m_fixedData.Format = g_formatOverride; m_fixedData.Format = g_formatOverride;
auto msaa = getMultisampleConfig(); }
m_fixedData.MultisampleType = msaa.first;
m_fixedData.MultisampleQuality = msaa.second; if (D3DDDIMULTISAMPLE_NONE != g_msaaOverride.first)
{
m_fixedData.MultisampleType = g_msaaOverride.first;
m_fixedData.MultisampleQuality = g_msaaOverride.second;
} }
const bool isOffScreenPlain = 0 == (m_fixedData.Flags.Value & g_resourceTypeFlags); const bool isOffScreenPlain = 0 == (m_fixedData.Flags.Value & g_resourceTypeFlags);
@ -499,6 +498,20 @@ namespace D3dDdi
return m_lockData.empty() ? nullptr : m_lockData[subResourceIndex].data; return m_lockData.empty() ? nullptr : m_lockData[subResourceIndex].data;
} }
D3DDDIFORMAT Resource::getFormatConfig()
{
if (m_fixedData.Flags.RenderTarget && !m_fixedData.Flags.Primary && D3DDDIPOOL_SYSTEMMEM != m_fixedData.Pool &&
(D3DDDIFMT_X8R8G8B8 == m_fixedData.Format || D3DDDIFMT_R5G6B5 == m_fixedData.Format))
{
switch (Config::renderColorDepth.get())
{
case 16: return D3DDDIFMT_R5G6B5;
case 32: return D3DDDIFMT_X8R8G8B8;
}
}
return m_fixedData.Format;
}
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> Resource::getMultisampleConfig() std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> Resource::getMultisampleConfig()
{ {
if ((m_fixedData.Flags.RenderTarget && !m_fixedData.Flags.Texture && !m_fixedData.Flags.Primary || if ((m_fixedData.Flags.RenderTarget && !m_fixedData.Flags.Texture && !m_fixedData.Flags.Primary ||
@ -522,6 +535,77 @@ namespace D3dDdi
rect.bottom <= static_cast<LONG>(m_fixedData.pSurfList[subResourceIndex].Height); rect.bottom <= static_cast<LONG>(m_fixedData.pSurfList[subResourceIndex].Height);
} }
void Resource::loadMsaaResource(UINT subResourceIndex)
{
if (!m_lockData[subResourceIndex].isMsaaUpToDate)
{
if (m_msaaResolvedSurface.resource)
{
loadMsaaResolvedResource(subResourceIndex);
copySubResource(*m_msaaSurface.resource, *m_msaaResolvedSurface.resource, subResourceIndex);
}
else
{
loadVidMemResource(subResourceIndex);
copySubResource(*m_msaaSurface.resource, m_handle, subResourceIndex);
}
m_lockData[subResourceIndex].isMsaaUpToDate = true;
}
}
void Resource::loadMsaaResolvedResource(UINT subResourceIndex)
{
if (!m_lockData[subResourceIndex].isMsaaResolvedUpToDate)
{
if (m_lockData[subResourceIndex].isMsaaUpToDate)
{
copySubResource(*m_msaaResolvedSurface.resource, *m_msaaSurface.resource, subResourceIndex);
}
else
{
loadVidMemResource(subResourceIndex);
copySubResource(*m_msaaResolvedSurface.resource, m_handle, subResourceIndex);
}
m_lockData[subResourceIndex].isMsaaResolvedUpToDate = true;
}
}
void Resource::loadSysMemResource(UINT subResourceIndex)
{
if (!m_lockData[subResourceIndex].isSysMemUpToDate)
{
loadVidMemResource(subResourceIndex);
copySubResource(m_lockResource.get(), m_handle, subResourceIndex);
notifyLock(subResourceIndex);
m_lockData[subResourceIndex].isSysMemUpToDate = true;
}
}
void Resource::loadVidMemResource(UINT subResourceIndex)
{
if (!m_lockData[subResourceIndex].isVidMemUpToDate)
{
if (m_lockData[subResourceIndex].isMsaaUpToDate || m_lockData[subResourceIndex].isMsaaResolvedUpToDate)
{
if (m_msaaResolvedSurface.resource)
{
loadMsaaResolvedResource(subResourceIndex);
copySubResource(m_handle, *m_msaaResolvedSurface.resource, subResourceIndex);
}
else
{
copySubResource(m_handle, *m_msaaSurface.resource, subResourceIndex);
}
}
else
{
copySubResource(m_handle, m_lockResource.get(), subResourceIndex);
notifyLock(subResourceIndex);
}
m_lockData[subResourceIndex].isVidMemUpToDate = true;
}
}
HRESULT Resource::lock(D3DDDIARG_LOCK& data) HRESULT Resource::lock(D3DDDIARG_LOCK& data)
{ {
if (isOversized()) if (isOversized())
@ -558,69 +642,110 @@ namespace D3dDdi
m_device.getOrigVtable().pfnUnlock(m_device, &unlock); m_device.getOrigVtable().pfnUnlock(m_device, &unlock);
} }
void Resource::prepareForBlt(UINT subResourceIndex, bool isReadOnly) void Resource::prepareForBltSrc(const D3DDDIARG_BLT& data)
{ {
if (m_lockResource && 0 == m_lockData[subResourceIndex].lockCount) if (m_lockResource)
{ {
if (!m_lockData[subResourceIndex].isVidMemUpToDate) loadVidMemResource(data.SrcSubResourceIndex);
{
copyToVidMem(subResourceIndex);
}
m_lockData[subResourceIndex].isCustomUpToDate &= isReadOnly;
m_lockData[subResourceIndex].isSysMemUpToDate &= isReadOnly;
} }
} }
void Resource::prepareForGdiRendering(bool isReadOnly) void Resource::prepareForBltDst(D3DDDIARG_BLT& data)
{ {
if (!m_lockResource) if (m_lockResource)
{ {
return; if (m_lockData[data.DstSubResourceIndex].isMsaaUpToDate)
{
data.hDstResource = *m_msaaSurface.resource;
clearUpToDateFlags(data.DstSubResourceIndex);
m_lockData[data.DstSubResourceIndex].isMsaaUpToDate = true;
}
else if (m_lockData[data.DstSubResourceIndex].isMsaaResolvedUpToDate)
{
data.hDstResource = *m_msaaResolvedSurface.resource;
clearUpToDateFlags(data.DstSubResourceIndex);
m_lockData[data.DstSubResourceIndex].isMsaaResolvedUpToDate = true;
}
else
{
loadVidMemResource(data.DstSubResourceIndex);
clearUpToDateFlags(data.DstSubResourceIndex);
m_lockData[data.DstSubResourceIndex].isVidMemUpToDate = true;
}
} }
if (!m_lockData[0].isSysMemUpToDate)
{
copyToSysMem(0);
}
m_lockData[0].isVidMemUpToDate &= isReadOnly;
m_lockData[0].isCustomUpToDate &= isReadOnly;
m_lockData[0].qpcLastForcedLock = Time::queryPerformanceCounter();
} }
void Resource::prepareForRendering(UINT subResourceIndex) void Resource::prepareForCpuRead(UINT subResourceIndex)
{ {
if (m_lockResource && 0 == m_lockData[subResourceIndex].lockCount) if (m_lockResource)
{ {
if (m_customSurface.resource) loadSysMemResource(subResourceIndex);
}
}
void Resource::prepareForCpuWrite(UINT subResourceIndex)
{
if (m_lockResource)
{
loadSysMemResource(subResourceIndex);
clearUpToDateFlags(subResourceIndex);
m_lockData[subResourceIndex].isSysMemUpToDate = true;
}
}
Resource& Resource::prepareForGpuRead(UINT subResourceIndex)
{
if (m_lockResource)
{
if (m_msaaResolvedSurface.resource)
{ {
if (!m_lockData[subResourceIndex].isCustomUpToDate) loadMsaaResolvedResource(subResourceIndex);
{ return *m_msaaResolvedSurface.resource;
if (!m_lockData[subResourceIndex].isVidMemUpToDate)
{
copyToVidMem(subResourceIndex);
}
copySubResource(m_customSurface.resource->m_handle, m_handle, subResourceIndex);
m_lockData[subResourceIndex].isCustomUpToDate = true;
}
m_lockData[subResourceIndex].isVidMemUpToDate = false;
} }
else if (!m_lockData[subResourceIndex].isVidMemUpToDate) else
{ {
copyToVidMem(subResourceIndex); loadVidMemResource(subResourceIndex);
}
}
return *this;
}
void Resource::prepareForGpuWrite(UINT subResourceIndex)
{
if (m_lockResource)
{
if (m_msaaSurface.resource)
{
loadMsaaResource(subResourceIndex);
clearUpToDateFlags(subResourceIndex);
m_lockData[subResourceIndex].isMsaaUpToDate = true;
}
else if (m_msaaResolvedSurface.resource)
{
loadMsaaResolvedResource(subResourceIndex);
clearUpToDateFlags(subResourceIndex);
m_lockData[subResourceIndex].isMsaaResolvedUpToDate = true;
}
else
{
loadVidMemResource(subResourceIndex);
clearUpToDateFlags(subResourceIndex);
m_lockData[subResourceIndex].isVidMemUpToDate = true;
} }
m_lockData[subResourceIndex].isSysMemUpToDate = false;
} }
} }
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_fixedData.Flags.RenderTarget)
{ {
srcResource->m_lockData[0].isVidMemUpToDate = false; if (srcResource->m_lockData[0].isSysMemUpToDate &&
!srcResource->m_fixedData.Flags.RenderTarget)
{
srcResource->m_lockData[0].isVidMemUpToDate = false;
}
data.hSrcResource = srcResource->prepareForGpuRead(0);
} }
srcResource->prepareForBlt(0, true);
const bool isPalettized = D3DDDIFMT_P8 == srcResource->m_origData.Format; const bool isPalettized = D3DDDIFMT_P8 == srcResource->m_origData.Format;
@ -768,6 +893,7 @@ namespace D3dDdi
++tilePos.x; ++tilePos.x;
tileRect.left += caps.dwMaxTextureWidth; tileRect.left += caps.dwMaxTextureWidth;
tileRect.right += caps.dwMaxTextureWidth; tileRect.right += caps.dwMaxTextureWidth;
notifyLock(subResourceIndex);
} }
++tilePos.y; ++tilePos.y;
@ -803,7 +929,7 @@ namespace D3dDdi
m_fixedData.Flags.Texture = 0; m_fixedData.Flags.Texture = 0;
} }
HRESULT Resource::sysMemPreferredBlt(const D3DDDIARG_BLT& data, Resource& srcResource) HRESULT Resource::sysMemPreferredBlt(D3DDDIARG_BLT& data, Resource& srcResource)
{ {
if (m_fixedData.Format == srcResource.m_fixedData.Format && if (m_fixedData.Format == srcResource.m_fixedData.Format &&
!m_lockData.empty() && !m_lockData.empty() &&
@ -831,17 +957,8 @@ namespace D3dDdi
if (isSysMemBltPreferred) if (isSysMemBltPreferred)
{ {
if (!dstLockData.isSysMemUpToDate) prepareForCpuWrite(data.DstSubResourceIndex);
{ srcResource.prepareForCpuRead(data.SrcSubResourceIndex);
copyToSysMem(data.DstSubResourceIndex);
}
dstLockData.isVidMemUpToDate = false;
dstLockData.isCustomUpToDate = false;
if (!srcLockData.isSysMemUpToDate)
{
srcResource.copyToSysMem(data.SrcSubResourceIndex);
}
auto dstBuf = static_cast<BYTE*>(dstLockData.data) + auto dstBuf = static_cast<BYTE*>(dstLockData.data) +
data.DstRect.top * dstLockData.pitch + data.DstRect.left * m_formatInfo.bytesPerPixel; data.DstRect.top * dstLockData.pitch + data.DstRect.left * m_formatInfo.bytesPerPixel;
@ -866,8 +983,9 @@ namespace D3dDdi
} }
} }
prepareForBlt(data.DstSubResourceIndex, false); srcResource.prepareForBltSrc(data);
srcResource.prepareForBlt(data.SrcSubResourceIndex, true); prepareForBltDst(data);
HRESULT result = m_device.getOrigVtable().pfnBlt(m_device, &data); HRESULT result = m_device.getOrigVtable().pfnBlt(m_device, &data);
if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool) if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool)
{ {
@ -908,10 +1026,6 @@ namespace D3dDdi
} }
return splitLock(data, m_device.getOrigVtable().pfnUnlock); return splitLock(data, m_device.getOrigVtable().pfnUnlock);
} }
else if (m_lockResource)
{
return bltUnlock(data);
}
return m_device.getOrigVtable().pfnUnlock(m_device, &data); return m_device.getOrigVtable().pfnUnlock(m_device, &data);
} }
@ -924,30 +1038,35 @@ namespace D3dDdi
} }
const auto msaa = getMultisampleConfig(); const auto msaa = getMultisampleConfig();
if (m_multiSampleConfig == msaa) const auto formatConfig = getFormatConfig();
if (m_multiSampleConfig == msaa && m_formatConfig == formatConfig)
{ {
return; return;
} }
m_multiSampleConfig = msaa; m_multiSampleConfig = msaa;
m_formatConfig = formatConfig;
if (m_customSurface.resource && m_fixedData.Flags.RenderTarget) if (m_fixedData.Flags.RenderTarget &&
(m_msaaSurface.resource || m_msaaResolvedSurface.resource))
{ {
for (UINT i = 0; i < m_lockData.size(); ++i) for (UINT i = 0; i < m_lockData.size(); ++i)
{ {
if (m_lockData[i].isCustomUpToDate && !m_lockData[i].isVidMemUpToDate) if (m_lockData[i].isMsaaUpToDate || m_lockData[i].isMsaaResolvedUpToDate)
{ {
copyToVidMem(i); loadVidMemResource(i);
} }
m_lockData[i].isCustomUpToDate = false; m_lockData[i].isMsaaUpToDate = false;
m_lockData[i].isMsaaResolvedUpToDate = false;
} }
} }
auto& surfaceRepo(SurfaceRepository::get(m_device.getAdapter())); auto& surfaceRepo(SurfaceRepository::get(m_device.getAdapter()));
surfaceRepo.release(m_customSurface); surfaceRepo.release(m_msaaSurface);
surfaceRepo.release(m_msaaResolvedSurface);
if (D3DDDIMULTISAMPLE_NONE != msaa.first) if (D3DDDIMULTISAMPLE_NONE != msaa.first || m_fixedData.Format != formatConfig)
{ {
g_formatOverride = m_fixedData.Format; g_formatOverride = formatConfig;
if (m_fixedData.Flags.ZBuffer) if (m_fixedData.Flags.ZBuffer)
{ {
DDPIXELFORMAT pf = {}; DDPIXELFORMAT pf = {};
@ -956,13 +1075,25 @@ namespace D3dDdi
pf.dwZBufferBitDepth = 16; pf.dwZBufferBitDepth = 16;
pf.dwZBitMask = 0xFFFF; pf.dwZBitMask = 0xFFFF;
SurfaceRepository::get(m_device.getAdapter()).getSurface(m_customSurface, g_msaaOverride = msaa;
SurfaceRepository::get(m_device.getAdapter()).getSurface(m_msaaSurface,
m_fixedData.surfaceData[0].Width, m_fixedData.surfaceData[0].Height, pf, m_fixedData.surfaceData[0].Width, m_fixedData.surfaceData[0].Height, pf,
DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY, m_fixedData.SurfCount); DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY, m_fixedData.SurfCount);
g_msaaOverride = {};
} }
else else
{ {
SurfaceRepository::get(m_device.getAdapter()).getSurface(m_customSurface, if (D3DDDIMULTISAMPLE_NONE != msaa.first)
{
g_msaaOverride = msaa;
SurfaceRepository::get(m_device.getAdapter()).getSurface(m_msaaSurface,
m_fixedData.surfaceData[0].Width, m_fixedData.surfaceData[0].Height,
DDraw::DirectDraw::getRgbPixelFormat(32),
DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY);
g_msaaOverride = {};
}
SurfaceRepository::get(m_device.getAdapter()).getSurface(m_msaaResolvedSurface,
m_fixedData.surfaceData[0].Width, m_fixedData.surfaceData[0].Height, m_fixedData.surfaceData[0].Width, m_fixedData.surfaceData[0].Height,
DDraw::DirectDraw::getRgbPixelFormat(32), DDraw::DirectDraw::getRgbPixelFormat(32),
DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY); DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY);

View File

@ -26,7 +26,7 @@ namespace D3dDdi
~Resource(); ~Resource();
operator HANDLE() const { return m_handle; } operator HANDLE() const { return m_handle; }
const Resource* getCustomResource() { return m_customSurface.resource; } const Resource* getCustomResource() { return m_msaaSurface.resource ? m_msaaSurface.resource : m_msaaResolvedSurface.resource; }
const D3DDDIARG_CREATERESOURCE2& getFixedDesc() const { return m_fixedData; } const D3DDDIARG_CREATERESOURCE2& getFixedDesc() const { return m_fixedData; }
const D3DDDIARG_CREATERESOURCE2& getOrigDesc() const { return m_origData; } const D3DDDIARG_CREATERESOURCE2& getOrigDesc() const { return m_origData; }
@ -34,9 +34,12 @@ namespace D3dDdi
HRESULT colorFill(D3DDDIARG_COLORFILL data); HRESULT colorFill(D3DDDIARG_COLORFILL data);
void* getLockPtr(UINT subResourceIndex); void* getLockPtr(UINT subResourceIndex);
HRESULT lock(D3DDDIARG_LOCK& data); HRESULT lock(D3DDDIARG_LOCK& data);
void prepareForBlt(UINT subResourceIndex, bool isReadOnly); void prepareForBltSrc(const D3DDDIARG_BLT& data);
void prepareForGdiRendering(bool isReadOnly); void prepareForBltDst(D3DDDIARG_BLT& data);
void prepareForRendering(UINT subResourceIndex); void prepareForCpuRead(UINT subResourceIndex);
void prepareForCpuWrite(UINT subResourceIndex);
Resource& prepareForGpuRead(UINT subResourceIndex);
void prepareForGpuWrite(UINT subResourceIndex);
void setAsGdiResource(bool isGdiResource); void setAsGdiResource(bool isGdiResource);
HRESULT unlock(const D3DDDIARG_UNLOCK& data); HRESULT unlock(const D3DDDIARG_UNLOCK& data);
void updateConfig(); void updateConfig();
@ -63,22 +66,26 @@ namespace D3dDdi
long long qpcLastForcedLock; long long qpcLastForcedLock;
bool isSysMemUpToDate; bool isSysMemUpToDate;
bool isVidMemUpToDate; bool isVidMemUpToDate;
bool isCustomUpToDate; bool isMsaaUpToDate;
bool isMsaaResolvedUpToDate;
}; };
HRESULT bltLock(D3DDDIARG_LOCK& data); HRESULT bltLock(D3DDDIARG_LOCK& data);
HRESULT bltUnlock(const D3DDDIARG_UNLOCK& data); void clearUpToDateFlags(UINT subResourceIndex);
void clipRect(UINT subResourceIndex, RECT& rect); void clipRect(UINT subResourceIndex, RECT& rect);
HRESULT copySubResource(HANDLE dstResource, HANDLE srcResource, UINT subResourceIndex); HRESULT copySubResource(HANDLE dstResource, HANDLE srcResource, UINT subResourceIndex);
void copyToSysMem(UINT subResourceIndex);
void copyToVidMem(UINT subResourceIndex);
void createGdiLockResource(); void createGdiLockResource();
void createLockResource(); void createLockResource();
void createSysMemResource(const std::vector<D3DDDI_SURFACEINFO>& surfaceInfo); void createSysMemResource(const std::vector<D3DDDI_SURFACEINFO>& surfaceInfo);
void fixResourceData(); void fixResourceData();
D3DDDIFORMAT getFormatConfig();
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> getMultisampleConfig(); std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> getMultisampleConfig();
bool isOversized() const; bool isOversized() const;
bool isValidRect(UINT subResourceIndex, const RECT& rect); bool isValidRect(UINT subResourceIndex, const RECT& rect);
void loadMsaaResource(UINT subResourceIndex);
void loadMsaaResolvedResource(UINT subResourceIndex);
void loadSysMemResource(UINT subResourceIndex);
void loadVidMemResource(UINT subResourceIndex);
void notifyLock(UINT subResourceIndex); void notifyLock(UINT subResourceIndex);
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);
@ -87,7 +94,7 @@ namespace D3dDdi
HRESULT splitLock(Arg& data, HRESULT(APIENTRY *lockFunc)(HANDLE, Arg*)); HRESULT splitLock(Arg& data, HRESULT(APIENTRY *lockFunc)(HANDLE, Arg*));
void splitToTiles(UINT tileWidth, UINT tileHeight); void splitToTiles(UINT tileWidth, UINT tileHeight);
HRESULT sysMemPreferredBlt(const D3DDDIARG_BLT& data, Resource& srcResource); HRESULT sysMemPreferredBlt(D3DDDIARG_BLT& data, Resource& srcResource);
Device& m_device; Device& m_device;
HANDLE m_handle; HANDLE m_handle;
@ -97,7 +104,9 @@ namespace D3dDdi
std::unique_ptr<void, void(*)(void*)> m_lockBuffer; std::unique_ptr<void, void(*)(void*)> m_lockBuffer;
std::vector<LockData> m_lockData; std::vector<LockData> m_lockData;
std::unique_ptr<void, ResourceDeleter> m_lockResource; std::unique_ptr<void, ResourceDeleter> m_lockResource;
SurfaceRepository::Surface m_customSurface; SurfaceRepository::Surface m_msaaSurface;
SurfaceRepository::Surface m_msaaResolvedSurface;
D3DDDIFORMAT m_formatConfig;
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> m_multiSampleConfig; std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> m_multiSampleConfig;
bool m_isSurfaceRepoResource; bool m_isSurfaceRepoResource;
}; };

View File

@ -148,8 +148,8 @@ namespace D3dDdi
} }
DeleteObject(iconInfo.hbmMask); DeleteObject(iconInfo.hbmMask);
m_cursorMaskTexture.resource->prepareForBlt(0, true); m_cursorMaskTexture.resource->prepareForGpuRead(0);
m_cursorColorTexture.resource->prepareForBlt(0, true); m_cursorColorTexture.resource->prepareForGpuRead(0);
m_cursorSize.cx = rect.right - rect.left; m_cursorSize.cx = rect.right - rect.left;
m_cursorSize.cy = rect.bottom - rect.top; m_cursorSize.cy = rect.bottom - rect.top;
@ -203,7 +203,7 @@ namespace D3dDdi
initFunc(desc); initFunc(desc);
surface.surface->Unlock(surface.surface, nullptr); surface.surface->Unlock(surface.surface, nullptr);
surface.resource->prepareForBlt(0, true); surface.resource->prepareForGpuRead(0);
return surface.resource; return surface.resource;
} }

View File

@ -220,6 +220,7 @@
<ClInclude Include="Config\Settings\DesktopColorDepth.h" /> <ClInclude Include="Config\Settings\DesktopColorDepth.h" />
<ClInclude Include="Config\Settings\DisplayFilter.h" /> <ClInclude Include="Config\Settings\DisplayFilter.h" />
<ClInclude Include="Config\Settings\DisplayResolution.h" /> <ClInclude Include="Config\Settings\DisplayResolution.h" />
<ClInclude Include="Config\Settings\RenderColorDepth.h" />
<ClInclude Include="Config\Settings\SupportedResolutions.h" /> <ClInclude Include="Config\Settings\SupportedResolutions.h" />
<ClInclude Include="Config\Settings\TextureFilter.h" /> <ClInclude Include="Config\Settings\TextureFilter.h" />
<ClInclude Include="Config\Settings\ThreadPriorityBoost.h" /> <ClInclude Include="Config\Settings\ThreadPriorityBoost.h" />
@ -440,4 +441,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>
</Project> </Project>

View File

@ -501,6 +501,9 @@
<ClInclude Include="D3dDdi\ResourceDeleter.h"> <ClInclude Include="D3dDdi\ResourceDeleter.h">
<Filter>Header Files\D3dDdi</Filter> <Filter>Header Files\D3dDdi</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Config\Settings\RenderColorDepth.h">
<Filter>Header Files\Config\Settings</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Gdi\Gdi.cpp"> <ClCompile Include="Gdi\Gdi.cpp">

View File

@ -19,7 +19,14 @@ namespace Gdi
auto gdiResource = D3dDdi::Device::getGdiResource(); auto gdiResource = D3dDdi::Device::getGdiResource();
if (gdiResource) if (gdiResource)
{ {
gdiResource->prepareForGdiRendering(isReadOnly); if (isReadOnly)
{
gdiResource->prepareForCpuRead(0);
}
else
{
gdiResource->prepareForCpuWrite(0);
}
} }
} }
else else

View File

@ -11,6 +11,7 @@ namespace Overlay
addControl(Config::alternatePixelCenter); addControl(Config::alternatePixelCenter);
addControl(Config::antialiasing); addControl(Config::antialiasing);
addControl(Config::displayFilter); addControl(Config::displayFilter);
addControl(Config::renderColorDepth);
addControl(Config::textureFilter); addControl(Config::textureFilter);
} }

View File

@ -39,6 +39,7 @@ namespace Overlay
} }
if (&Config::antialiasing == &m_setting || if (&Config::antialiasing == &m_setting ||
&Config::renderColorDepth == &m_setting ||
&Config::textureFilter == &m_setting) &Config::textureFilter == &m_setting)
{ {
D3dDdi::Device::updateAllConfig(); D3dDdi::Device::updateAllConfig();