diff --git a/DDrawCompat/Config/Config.cpp b/DDrawCompat/Config/Config.cpp index 8385d8e..248f74d 100644 --- a/DDrawCompat/Config/Config.cpp +++ b/DDrawCompat/Config/Config.cpp @@ -3,6 +3,7 @@ namespace Config { Settings::AlternatePixelCenter alternatePixelCenter; + Settings::Antialiasing antialiasing; Settings::CpuAffinity cpuAffinity; Settings::DesktopColorDepth desktopColorDepth; Settings::DisplayFilter displayFilter; diff --git a/DDrawCompat/Config/Config.h b/DDrawCompat/Config/Config.h index 38b8cf9..41192ab 100644 --- a/DDrawCompat/Config/Config.h +++ b/DDrawCompat/Config/Config.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -16,6 +17,7 @@ namespace Config const unsigned maxPaletteUpdatesPerMs = 5; extern Settings::AlternatePixelCenter alternatePixelCenter; + extern Settings::Antialiasing antialiasing; extern Settings::CpuAffinity cpuAffinity; extern Settings::DesktopColorDepth desktopColorDepth; extern Settings::DisplayFilter displayFilter; diff --git a/DDrawCompat/Config/Settings/Antialiasing.cpp b/DDrawCompat/Config/Settings/Antialiasing.cpp new file mode 100644 index 0000000..3e7971b --- /dev/null +++ b/DDrawCompat/Config/Settings/Antialiasing.cpp @@ -0,0 +1,47 @@ +#include +#include + +#include + +namespace Config +{ + namespace Settings + { + Antialiasing::Antialiasing() + : MappedSetting("Antialiasing", "off", { + {"off", D3DDDIMULTISAMPLE_NONE}, + {"msaa", D3DDDIMULTISAMPLE_NONMASKABLE}, + {"msaa2x", D3DDDIMULTISAMPLE_2_SAMPLES}, + {"msaa4x", D3DDDIMULTISAMPLE_4_SAMPLES}, + {"msaa8x", D3DDDIMULTISAMPLE_8_SAMPLES} + }) + , m_param(0) + { + } + + std::string Antialiasing::getParamStr() const + { + return D3DDDIMULTISAMPLE_NONE != m_value ? std::to_string(m_param) : std::string(); + } + + void Antialiasing::setDefaultParam(const UINT& value) + { + m_param = D3DDDIMULTISAMPLE_NONE != value ? 7 : 0; + } + + void Antialiasing::setValue(const UINT& value, const std::string& param) + { + if (D3DDDIMULTISAMPLE_NONE != value) + { + const UINT p = Config::Parser::parseUnsigned(param); + if (p <= 7) + { + m_value = value; + m_param = p; + return; + } + } + throw ParsingError("invalid parameter: '" + param + "'"); + } + } +} diff --git a/DDrawCompat/Config/Settings/Antialiasing.h b/DDrawCompat/Config/Settings/Antialiasing.h new file mode 100644 index 0000000..cdbc760 --- /dev/null +++ b/DDrawCompat/Config/Settings/Antialiasing.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +namespace Config +{ + namespace Settings + { + class Antialiasing : public MappedSetting + { + public: + Antialiasing(); + + UINT getParam() const { return m_param; } + + protected: + virtual std::string getParamStr() const override; + virtual void setDefaultParam(const UINT& value) override; + virtual void setValue(const UINT& value, const std::string& param) override; + + UINT m_param; + }; + } +} diff --git a/DDrawCompat/D3dDdi/Adapter.cpp b/DDrawCompat/D3dDdi/Adapter.cpp index 53e04da..0f5c9c4 100644 --- a/DDrawCompat/D3dDdi/Adapter.cpp +++ b/DDrawCompat/D3dDdi/Adapter.cpp @@ -1,5 +1,9 @@ +#include +#include + #include #include +#include #include #include #include @@ -34,61 +38,124 @@ namespace D3dDdi , m_driverVersion(data.DriverVersion) , m_luid(KernelModeThunks::getLastOpenAdapterInfo().luid) , m_repository{} - , m_d3dExtendedCaps{} - , m_ddrawCaps{} { - if (m_adapter) - { - D3DDDIARG_GETCAPS getCaps = {}; - getCaps.Type = D3DDDICAPS_GETD3D7CAPS; - getCaps.pData = &m_d3dExtendedCaps; - getCaps.DataSize = sizeof(m_d3dExtendedCaps); - m_origVtable.pfnGetCaps(m_adapter, &getCaps); - - getCaps.Type = D3DDDICAPS_DDRAW; - getCaps.pData = &m_ddrawCaps; - getCaps.DataSize = sizeof(m_ddrawCaps); - m_origVtable.pfnGetCaps(m_adapter, &getCaps); - } } - DWORD Adapter::getSupportedZBufferBitDepths() + const Adapter::AdapterInfo& Adapter::getInfo() const { - UINT formatCount = 0; - D3DDDIARG_GETCAPS caps = {}; - caps.Type = D3DDDICAPS_GETFORMATCOUNT; - caps.pData = &formatCount; - caps.DataSize = sizeof(formatCount); - m_origVtable.pfnGetCaps(m_adapter, &caps); - - std::vector formatOp(formatCount); - caps.Type = D3DDDICAPS_GETFORMATDATA; - caps.pData = formatOp.data(); - caps.DataSize = formatCount * sizeof(FORMATOP); - m_origVtable.pfnGetCaps(m_adapter, &caps); - - DWORD supportedZBufferBitDepths = 0; - for (UINT i = 0; i < formatCount; ++i) + auto it = s_adapterInfos.find(m_luid); + if (it != s_adapterInfos.end()) { - if (formatOp[i].Operations & (FORMATOP_ZSTENCIL | FORMATOP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH)) - { - switch (formatOp[i].Format) - { - case D3DDDIFMT_D16: - supportedZBufferBitDepths |= DDBD_16; - break; - - case D3DDDIFMT_X8D24: - supportedZBufferBitDepths |= DDBD_24; - break; - - case D3DDDIFMT_D32: - supportedZBufferBitDepths |= DDBD_32; - break; - } - } + return it->second; } + AdapterInfo& info = s_adapterInfos.insert({ m_luid, {} }).first->second; + getCaps(D3DDDICAPS_GETD3D7CAPS, info.d3dExtendedCaps); + info.formatOps = getFormatOps(); + info.supportedZBufferBitDepths = getSupportedZBufferBitDepths(info.formatOps); + + Compat::Log() << "Supported z-buffer bit depths: " << bitDepthsToString(info.supportedZBufferBitDepths); + Compat::Log() << "Supported MSAA modes: " << getSupportedMsaaModes(info.formatOps); + + return info; + } + + template + HRESULT Adapter::getCaps(D3DDDICAPS_TYPE type, Data& data, UINT size) const + { + D3DDDIARG_GETCAPS caps = {}; + caps.Type = type; + caps.pData = &data; + caps.DataSize = size; + return m_origVtable.pfnGetCaps(m_adapter, &caps); + } + + std::map Adapter::getFormatOps() const + { + UINT formatCount = 0; + getCaps(D3DDDICAPS_GETFORMATCOUNT, formatCount); + + std::vector formatOps(formatCount); + getCaps(D3DDDICAPS_GETFORMATDATA, formatOps[0], formatCount * sizeof(FORMATOP)); + + std::map result; + for (UINT i = 0; i < formatCount; ++i) + { + result[formatOps[i].Format] = formatOps[i]; + } + return result; + } + + std::pair Adapter::getMultisampleConfig(D3DDDIFORMAT format) const + { + UINT samples = Config::antialiasing.get(); + if (D3DDDIMULTISAMPLE_NONE == samples) + { + return { D3DDDIMULTISAMPLE_NONE, 0 }; + } + + const auto& info(getInfo()); + auto it = info.formatOps.find(format); + if (it == info.formatOps.end() || 0 == it->second.BltMsTypes) + { + return { D3DDDIMULTISAMPLE_NONE, 0 }; + } + + while (samples > D3DDDIMULTISAMPLE_NONMASKABLE && !(it->second.BltMsTypes & (1 << (samples - 1)))) + { + --samples; + } + + DDIMULTISAMPLEQUALITYLEVELSDATA levels = {}; + levels.Format = D3DDDIFMT_X8R8G8B8; + levels.MsType = static_cast(samples); + getCaps(D3DDDICAPS_GETMULTISAMPLEQUALITYLEVELS, levels); + return { levels.MsType, min(Config::antialiasing.getParam(), levels.QualityLevels - 1) }; + } + + std::string Adapter::getSupportedMsaaModes(const std::map& formatOps) const + { + auto it = formatOps.find(D3DDDIFMT_X8R8G8B8); + if (it != formatOps.end() && 0 != it->second.BltMsTypes) + { + DDIMULTISAMPLEQUALITYLEVELSDATA levels = {}; + levels.Format = D3DDDIFMT_X8R8G8B8; + levels.MsType = D3DDDIMULTISAMPLE_NONMASKABLE; + getCaps(D3DDDICAPS_GETMULTISAMPLEQUALITYLEVELS, levels); + + std::ostringstream oss; + oss << "msaa(" << levels.QualityLevels - 1 << ')'; + + for (UINT i = D3DDDIMULTISAMPLE_2_SAMPLES; i <= D3DDDIMULTISAMPLE_16_SAMPLES; ++i) + { + if (it->second.BltMsTypes & (1 << (i - 1))) + { + levels.MsType = static_cast(i); + levels.QualityLevels = 0; + getCaps(D3DDDICAPS_GETMULTISAMPLEQUALITYLEVELS, levels); + oss << ", msaa" << i << "x(" << levels.QualityLevels - 1 << ')'; + } + } + return oss.str(); + } + return "none"; + } + + DWORD Adapter::getSupportedZBufferBitDepths(const std::map& formatOps) const + { + DWORD supportedZBufferBitDepths = 0; + if (formatOps.find(D3DDDIFMT_D16) != formatOps.end()) + { + supportedZBufferBitDepths |= DDBD_16; + } + if (formatOps.find(D3DDDIFMT_X8D24) != formatOps.end()) + { + supportedZBufferBitDepths |= DDBD_24; + } + if (formatOps.find(D3DDDIFMT_D32) != formatOps.end()) + { + supportedZBufferBitDepths |= DDBD_32; + } return supportedZBufferBitDepths; } @@ -132,14 +199,7 @@ namespace D3dDdi auto& caps = static_cast(pData->pData)->hwCaps; if (caps.dwFlags & D3DDD_DEVICEZBUFFERBITDEPTH) { - const DWORD supportedZBufferBitDepths = getSupportedZBufferBitDepths(); - if (supportedZBufferBitDepths != caps.dwDeviceZBufferBitDepth) - { - LOG_ONCE("Incorrect z-buffer bit depth capabilities detected; changed from " - << bitDepthsToString(caps.dwDeviceZBufferBitDepth) << " to " - << bitDepthsToString(supportedZBufferBitDepths)); - caps.dwDeviceZBufferBitDepth = supportedZBufferBitDepths; - } + caps.dwDeviceZBufferBitDepth = getInfo().supportedZBufferBitDepths; } break; } @@ -160,4 +220,5 @@ namespace D3dDdi } std::map Adapter::s_adapters; + std::map Adapter::s_adapterInfos; } diff --git a/DDrawCompat/D3dDdi/Adapter.h b/DDrawCompat/D3dDdi/Adapter.h index 98aa63b..7c722cc 100644 --- a/DDrawCompat/D3dDdi/Adapter.h +++ b/DDrawCompat/D3dDdi/Adapter.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -14,6 +15,13 @@ namespace D3dDdi class Adapter { public: + struct AdapterInfo + { + D3DNTHAL_D3DEXTENDEDCAPS d3dExtendedCaps; + std::map formatOps; + DWORD supportedZBufferBitDepths; + }; + Adapter(const D3DDDIARG_OPENADAPTER& data); Adapter(const Adapter&) = delete; Adapter(Adapter&&) = delete; @@ -22,9 +30,9 @@ namespace D3dDdi operator HANDLE() const { return m_adapter; } - const D3DNTHAL_D3DEXTENDEDCAPS& getD3dExtendedCaps() const { return m_d3dExtendedCaps; } - const DDRAW_CAPS& getDDrawCaps() const { return m_ddrawCaps; } + const AdapterInfo& getInfo() const; LUID getLuid() const { return m_luid; } + std::pair getMultisampleConfig(D3DDDIFORMAT format) const; const D3DDDI_ADAPTERFUNCS& getOrigVtable() const { return m_origVtable; } CompatWeakPtr getRepository() const { return m_repository.repo; } bool isSrcColorKeySupported() const { return m_repository.isSrcColorKeySupported; } @@ -38,7 +46,12 @@ namespace D3dDdi static void setRepository(LUID luid, const DDraw::DirectDraw::Repository& repository); private: - DWORD getSupportedZBufferBitDepths(); + template + HRESULT getCaps(D3DDDICAPS_TYPE type, Data& data, UINT size = sizeof(Data)) const; + + std::map getFormatOps() const; + std::string getSupportedMsaaModes(const std::map& formatOps) const; + DWORD getSupportedZBufferBitDepths(const std::map& formatOps) const; HANDLE m_adapter; D3DDDI_ADAPTERFUNCS m_origVtable; @@ -47,9 +60,7 @@ namespace D3dDdi LUID m_luid; DDraw::DirectDraw::Repository m_repository; - D3DNTHAL_D3DEXTENDEDCAPS m_d3dExtendedCaps; - DDRAW_CAPS m_ddrawCaps; - static std::map s_adapters; + static std::map s_adapterInfos; }; } diff --git a/DDrawCompat/D3dDdi/Device.cpp b/DDrawCompat/D3dDdi/Device.cpp index 5c5d295..40710af 100644 --- a/DDrawCompat/D3dDdi/Device.cpp +++ b/DDrawCompat/D3dDdi/Device.cpp @@ -85,12 +85,21 @@ namespace D3dDdi return it != m_resources.end() ? it->second.get() : nullptr; } - void Device::prepareForRendering(HANDLE resource, UINT subResourceIndex, bool isReadOnly) + void Device::prepareForBlt(HANDLE resource, UINT subResourceIndex, bool isReadOnly) { auto it = m_resources.find(resource); if (it != m_resources.end()) { - it->second->prepareForRendering(subResourceIndex, isReadOnly); + 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); } } @@ -98,7 +107,7 @@ namespace D3dDdi { if (m_renderTarget) { - m_renderTarget->prepareForRendering(m_renderTargetSubResourceIndex, false); + m_renderTarget->prepareForRendering(m_renderTargetSubResourceIndex); } } @@ -142,7 +151,7 @@ namespace D3dDdi { return it->second->blt(*data); } - prepareForRendering(data->hSrcResource, data->SrcSubResourceIndex, true); + prepareForBlt(data->hSrcResource, data->SrcSubResourceIndex, true); return m_origVtable.pfnBlt(m_device, data); } @@ -301,7 +310,7 @@ namespace D3dDdi HRESULT Device::pfnPresent(const D3DDDIARG_PRESENT* data) { flushPrimitives(); - prepareForRendering(data->hSrcResource, data->SrcSubResourceIndex, true); + prepareForBlt(data->hSrcResource, data->SrcSubResourceIndex, true); return m_origVtable.pfnPresent(m_device, data); } @@ -310,7 +319,7 @@ namespace D3dDdi flushPrimitives(); for (UINT i = 0; i < data->SrcResources; ++i) { - prepareForRendering(data->phSrcResources[i].hResource, data->phSrcResources[i].SubResourceIndex, true); + prepareForBlt(data->phSrcResources[i].hResource, data->phSrcResources[i].SubResourceIndex, true); } return m_origVtable.pfnPresent1(m_device, data); } diff --git a/DDrawCompat/D3dDdi/Device.h b/DDrawCompat/D3dDdi/Device.h index 924b6c6..7e2a3ba 100644 --- a/DDrawCompat/D3dDdi/Device.h +++ b/DDrawCompat/D3dDdi/Device.h @@ -55,7 +55,8 @@ namespace D3dDdi HRESULT createPrivateResource(D3DDDIARG_CREATERESOURCE2& data); void flushPrimitives() { m_drawPrimitive.flushPrimitives(); } - void prepareForRendering(HANDLE resource, UINT subResourceIndex, bool isReadOnly); + void prepareForBlt(HANDLE resource, UINT subResourceIndex, bool isReadOnly); + void prepareForRendering(HANDLE resource, UINT subResourceIndex); void prepareForRendering(); void setRenderTarget(const D3DDDIARG_SETRENDERTARGET& data); diff --git a/DDrawCompat/D3dDdi/DeviceState.cpp b/DDrawCompat/D3dDdi/DeviceState.cpp index 4c26775..576c9fc 100644 --- a/DDrawCompat/D3dDdi/DeviceState.cpp +++ b/DDrawCompat/D3dDdi/DeviceState.cpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace D3dDdi { @@ -191,7 +192,25 @@ namespace D3dDdi HRESULT DeviceState::pfnSetDepthStencil(const D3DDDIARG_SETDEPTHSTENCIL* data) { - return setState(data, m_depthStencil, m_device.getOrigVtable().pfnSetDepthStencil); + if (0 == memcmp(data, &m_depthStencil, sizeof(m_depthStencil))) + { + return S_OK; + } + + D3DDDIARG_SETDEPTHSTENCIL d = *data; + Resource* resource = m_device.getResource(d.hZBuffer); + if (resource && resource->getCustomResource()) + { + d.hZBuffer = *resource->getCustomResource(); + } + + m_device.flushPrimitives(); + HRESULT result = m_device.getOrigVtable().pfnSetDepthStencil(m_device, &d); + if (SUCCEEDED(result)) + { + m_depthStencil = *data; + } + return result; } HRESULT DeviceState::pfnSetPixelShader(HANDLE shader) @@ -216,6 +235,10 @@ namespace D3dDdi HRESULT DeviceState::pfnSetRenderState(const D3DDDIARG_RENDERSTATE* data) { + if (D3DDDIRS_MULTISAMPLEANTIALIAS == data->State) + { + return S_OK; + } if (data->State >= D3DDDIRS_WRAP0 && data->State <= D3DDDIRS_WRAP7) { auto d = *data; @@ -227,9 +250,23 @@ namespace D3dDdi HRESULT DeviceState::pfnSetRenderTarget(const D3DDDIARG_SETRENDERTARGET* data) { - HRESULT result = setState(data, m_renderTarget, m_device.getOrigVtable().pfnSetRenderTarget); + if (0 == memcmp(data, &m_renderTarget, sizeof(m_renderTarget))) + { + return S_OK; + } + + D3DDDIARG_SETRENDERTARGET d = *data; + Resource* resource = m_device.getResource(d.hRenderTarget); + if (resource && resource->getCustomResource()) + { + d.hRenderTarget = *resource->getCustomResource(); + } + + m_device.flushPrimitives(); + HRESULT result = m_device.getOrigVtable().pfnSetRenderTarget(m_device, &d); if (SUCCEEDED(result)) { + m_renderTarget = *data; m_device.setRenderTarget(*data); } return result; @@ -482,6 +519,18 @@ namespace D3dDdi return result; } + DeviceState::ScopedRenderState::ScopedRenderState(DeviceState& deviceState, const D3DDDIARG_RENDERSTATE& data) + : m_deviceState(deviceState) + , m_prevData{ data.State, deviceState.m_renderState[data.State] } + { + m_deviceState.m_device.getOrigVtable().pfnSetRenderState(m_deviceState.m_device, &data); + } + + DeviceState::ScopedRenderState::~ScopedRenderState() + { + m_deviceState.m_device.getOrigVtable().pfnSetRenderState(m_deviceState.m_device, &m_prevData); + } + DeviceState::ScopedTexture::ScopedTexture(DeviceState& deviceState, UINT stage, HANDLE texture, UINT filter) : m_deviceState(deviceState) , m_stage(stage) diff --git a/DDrawCompat/D3dDdi/DeviceState.h b/DDrawCompat/D3dDdi/DeviceState.h index a326c1d..842db0e 100644 --- a/DDrawCompat/D3dDdi/DeviceState.h +++ b/DDrawCompat/D3dDdi/DeviceState.h @@ -187,18 +187,9 @@ namespace D3dDdi class ScopedRenderState { public: - ScopedRenderState(DeviceState& deviceState, const D3DDDIARG_RENDERSTATE& data) - : m_deviceState(deviceState) - , m_prevData{ data.State, deviceState.m_renderState[data.State] } - { - m_deviceState.pfnSetRenderState(&data); - } - - ~ScopedRenderState() - { - m_deviceState.pfnSetRenderState(&m_prevData); - } - + ScopedRenderState(DeviceState& deviceState, const D3DDDIARG_RENDERSTATE& data); + ~ScopedRenderState(); + private: DeviceState& m_deviceState; D3DDDIARG_RENDERSTATE m_prevData; diff --git a/DDrawCompat/D3dDdi/Log/AdapterFuncsLog.cpp b/DDrawCompat/D3dDdi/Log/AdapterFuncsLog.cpp index 1229201..72071b1 100644 --- a/DDrawCompat/D3dDdi/Log/AdapterFuncsLog.cpp +++ b/DDrawCompat/D3dDdi/Log/AdapterFuncsLog.cpp @@ -36,3 +36,72 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_CREATEDEVICE& data) << Compat::hex(data.Flags.Value) << Compat::hex(data.CommandBuffer); } + +std::ostream& operator<<(std::ostream& os, D3DDDICAPS_TYPE data) +{ + switch (data) + { + LOG_CONST_CASE(D3DDDICAPS_DDRAW); + LOG_CONST_CASE(D3DDDICAPS_DDRAW_MODE_SPECIFIC); + LOG_CONST_CASE(D3DDDICAPS_GETFORMATCOUNT); + LOG_CONST_CASE(D3DDDICAPS_GETFORMATDATA); + LOG_CONST_CASE(D3DDDICAPS_GETMULTISAMPLEQUALITYLEVELS); + LOG_CONST_CASE(D3DDDICAPS_GETD3DQUERYCOUNT); + LOG_CONST_CASE(D3DDDICAPS_GETD3DQUERYDATA); + LOG_CONST_CASE(D3DDDICAPS_GETD3D3CAPS); + LOG_CONST_CASE(D3DDDICAPS_GETD3D5CAPS); + LOG_CONST_CASE(D3DDDICAPS_GETD3D6CAPS); + LOG_CONST_CASE(D3DDDICAPS_GETD3D7CAPS); + LOG_CONST_CASE(D3DDDICAPS_GETD3D8CAPS); + LOG_CONST_CASE(D3DDDICAPS_GETD3D9CAPS); + LOG_CONST_CASE(D3DDDICAPS_GETDECODEGUIDCOUNT); + LOG_CONST_CASE(D3DDDICAPS_GETDECODEGUIDS); + LOG_CONST_CASE(D3DDDICAPS_GETDECODERTFORMATCOUNT); + LOG_CONST_CASE(D3DDDICAPS_GETDECODERTFORMATS); + LOG_CONST_CASE(D3DDDICAPS_GETDECODECOMPRESSEDBUFFERINFOCOUNT); + LOG_CONST_CASE(D3DDDICAPS_GETDECODECOMPRESSEDBUFFERINFO); + LOG_CONST_CASE(D3DDDICAPS_GETDECODECONFIGURATIONCOUNT); + LOG_CONST_CASE(D3DDDICAPS_GETDECODECONFIGURATIONS); + LOG_CONST_CASE(D3DDDICAPS_GETVIDEOPROCESSORDEVICEGUIDCOUNT); + LOG_CONST_CASE(D3DDDICAPS_GETVIDEOPROCESSORDEVICEGUIDS); + LOG_CONST_CASE(D3DDDICAPS_GETVIDEOPROCESSORRTFORMATCOUNT); + LOG_CONST_CASE(D3DDDICAPS_GETVIDEOPROCESSORRTFORMATS); + LOG_CONST_CASE(D3DDDICAPS_GETVIDEOPROCESSORRTSUBSTREAMFORMATCOUNT); + LOG_CONST_CASE(D3DDDICAPS_GETVIDEOPROCESSORRTSUBSTREAMFORMATS); + LOG_CONST_CASE(D3DDDICAPS_GETVIDEOPROCESSORCAPS); + LOG_CONST_CASE(D3DDDICAPS_GETPROCAMPRANGE); + LOG_CONST_CASE(D3DDDICAPS_FILTERPROPERTYRANGE); + LOG_CONST_CASE(D3DDDICAPS_GETEXTENSIONGUIDCOUNT); + LOG_CONST_CASE(D3DDDICAPS_GETEXTENSIONGUIDS); + LOG_CONST_CASE(D3DDDICAPS_GETEXTENSIONCAPS); + LOG_CONST_CASE(D3DDDICAPS_GETGAMMARAMPCAPS); + LOG_CONST_CASE(D3DDDICAPS_CHECKOVERLAYSUPPORT); + LOG_CONST_CASE(D3DDDICAPS_DXVAHD_GETVPDEVCAPS); + LOG_CONST_CASE(D3DDDICAPS_DXVAHD_GETVPOUTPUTFORMATS); + LOG_CONST_CASE(D3DDDICAPS_DXVAHD_GETVPINPUTFORMATS); + LOG_CONST_CASE(D3DDDICAPS_DXVAHD_GETVPCAPS); + LOG_CONST_CASE(D3DDDICAPS_DXVAHD_GETVPCUSTOMRATES); + LOG_CONST_CASE(D3DDDICAPS_DXVAHD_GETVPFILTERRANGE); + LOG_CONST_CASE(D3DDDICAPS_GETCONTENTPROTECTIONCAPS); + LOG_CONST_CASE(D3DDDICAPS_GETCERTIFICATESIZE); + LOG_CONST_CASE(D3DDDICAPS_GETCERTIFICATE); + LOG_CONST_CASE(D3DDDICAPS_GET_ARCHITECTURE_INFO); + LOG_CONST_CASE(D3DDDICAPS_GET_SHADER_MIN_PRECISION_SUPPORT); + LOG_CONST_CASE(D3DDDICAPS_GET_MULTIPLANE_OVERLAY_CAPS); + LOG_CONST_CASE(D3DDDICAPS_GET_MULTIPLANE_OVERLAY_FILTER_RANGE); + LOG_CONST_CASE(D3DDDICAPS_GET_MULTIPLANE_OVERLAY_GROUP_CAPS); + LOG_CONST_CASE(D3DDDICAPS_GET_SIMPLE_INSTANCING_SUPPORT); + LOG_CONST_CASE(D3DDDICAPS_GET_MARKER_CAPS); + } + + return os << "D3DDDICAPS_" << static_cast(data); +} + +std::ostream& operator<<(std::ostream& os, const D3DDDIARG_GETCAPS& data) +{ + return Compat::LogStruct(os) + << data.Type + << data.pInfo + << data.pData + << data.DataSize; +} diff --git a/DDrawCompat/D3dDdi/Log/AdapterFuncsLog.h b/DDrawCompat/D3dDdi/Log/AdapterFuncsLog.h index 51bf5a2..c7893f3 100644 --- a/DDrawCompat/D3dDdi/Log/AdapterFuncsLog.h +++ b/DDrawCompat/D3dDdi/Log/AdapterFuncsLog.h @@ -10,3 +10,5 @@ std::ostream& operator<<(std::ostream& os, const D3DDDI_ALLOCATIONLIST& data); std::ostream& operator<<(std::ostream& os, const D3DDDI_PATCHLOCATIONLIST& data); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_CREATEDEVICE& data); +std::ostream& operator<<(std::ostream& os, const D3DDDIARG_GETCAPS& data); +std::ostream& operator<<(std::ostream& os, D3DDDICAPS_TYPE data); diff --git a/DDrawCompat/D3dDdi/Resource.cpp b/DDrawCompat/D3dDdi/Resource.cpp index a35c6be..5d7f07f 100644 --- a/DDrawCompat/D3dDdi/Resource.cpp +++ b/DDrawCompat/D3dDdi/Resource.cpp @@ -26,6 +26,7 @@ namespace RECT g_presentationRect = {}; UINT g_presentationFilter = Config::Settings::DisplayFilter::POINT; UINT g_presentationFilterParam = 0; + D3DDDIFORMAT g_formatOverride = D3DDDIFMT_UNKNOWN; RECT calculatePresentationRect() { @@ -106,6 +107,7 @@ namespace D3dDdi , m_fixedData(data) , m_lockBuffer(nullptr, &heapFree) , m_lockResource(nullptr, ResourceDeleter(device)) + , m_customSurface{} { if (m_origData.Flags.VertexBuffer && m_origData.Flags.MightDrawFromLocked && @@ -157,6 +159,35 @@ namespace D3dDdi } m_handle = m_fixedData.hResource; + if (!SurfaceRepository::inCreateSurface()) + { + const auto msaa = getMultisampleConfig(); + if (D3DDDIMULTISAMPLE_NONE != msaa.first) + { + g_formatOverride = m_fixedData.Format; + if (m_fixedData.Flags.ZBuffer) + { + DDPIXELFORMAT pf = {}; + pf.dwSize = sizeof(pf); + pf.dwFlags = DDPF_ZBUFFER; + pf.dwZBufferBitDepth = 16; + pf.dwZBitMask = 0xFFFF; + + SurfaceRepository::get(m_device.getAdapter()).getSurface(m_customSurface, + m_fixedData.surfaceData[0].Width, m_fixedData.surfaceData[0].Height, pf, + DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY, m_fixedData.SurfCount); + } + else + { + SurfaceRepository::get(m_device.getAdapter()).getSurface(m_customSurface, + m_fixedData.surfaceData[0].Width, m_fixedData.surfaceData[0].Height, + DDraw::DirectDraw::getRgbPixelFormat(32), + DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY); + } + g_formatOverride = D3DDDIFMT_UNKNOWN; + } + } + if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool && 0 != m_formatInfo.bytesPerPixel) { @@ -207,15 +238,22 @@ namespace D3dDdi if (isOversized()) { - m_device.prepareForRendering(data.hSrcResource, data.SrcSubResourceIndex, true); - return splitBlt(data, data.DstSubResourceIndex, data.DstRect, data.SrcRect); + if (srcResource) + { + srcResource->prepareForBlt(data.SrcSubResourceIndex, true); + } + HRESULT result = splitBlt(data, data.DstSubResourceIndex, data.DstRect, data.SrcRect); + notifyLock(data.DstSubResourceIndex); + return result; } else if (srcResource) { if (srcResource->isOversized()) { - prepareForRendering(data.DstSubResourceIndex, false); - return srcResource->splitBlt(data, data.SrcSubResourceIndex, data.SrcRect, data.DstRect); + prepareForBlt(data.DstSubResourceIndex, false); + HRESULT result = srcResource->splitBlt(data, data.SrcSubResourceIndex, data.SrcRect, data.DstRect); + srcResource->notifyLock(data.SrcSubResourceIndex); + return result; } else if (m_fixedData.Flags.Primary) { @@ -226,7 +264,7 @@ namespace D3dDdi return sysMemPreferredBlt(data, *srcResource); } } - prepareForRendering(data.DstSubResourceIndex, false); + prepareForBlt(data.DstSubResourceIndex, false); return m_device.getOrigVtable().pfnBlt(m_device, &data); } @@ -240,6 +278,7 @@ namespace D3dDdi copyToSysMem(data.SubResourceIndex); } lockData.isVidMemUpToDate &= data.Flags.ReadOnly; + lockData.isCustomUpToDate &= data.Flags.ReadOnly; lockData.qpcLastForcedLock = Time::queryPerformanceCounter(); unsigned char* ptr = static_cast(lockData.data); @@ -294,10 +333,11 @@ namespace D3dDdi 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); } } - prepareForRendering(data.SubResourceIndex, false); + prepareForBlt(data.SubResourceIndex, false); return LOG_RESULT(m_device.getOrigVtable().pfnColorFill(m_device, &data)); } @@ -321,31 +361,32 @@ namespace D3dDdi { LOG_ONCE("ERROR: Resource::copySubResource failed: " << Compat::hex(result)); } - - D3DDDIARG_LOCK lock = {}; - lock.hResource = m_lockResource.get(); - lock.SubResourceIndex = subResourceIndex; - lock.Flags.NotifyOnly = 1; - m_device.getOrigVtable().pfnLock(m_device, &lock); - - D3DDDIARG_UNLOCK unlock = {}; - unlock.hResource = m_lockResource.get(); - unlock.SubResourceIndex = subResourceIndex; - unlock.Flags.NotifyOnly = 1; - m_device.getOrigVtable().pfnUnlock(m_device, &unlock); - 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) { - copySubResource(m_handle, m_lockResource.get(), 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; } @@ -368,6 +409,7 @@ namespace D3dDdi if (m_lockResource) { m_lockData[0].isVidMemUpToDate = false; + m_lockData[0].isCustomUpToDate = false; } else { @@ -447,6 +489,7 @@ namespace D3dDdi m_lockData[i].qpcLastForcedLock = qpcLastForcedLock; m_lockData[i].isSysMemUpToDate = true; m_lockData[i].isVidMemUpToDate = true; + m_lockData[i].isCustomUpToDate = m_customSurface.resource; } } @@ -471,6 +514,14 @@ namespace D3dDdi m_fixedData.Format = D3DDDIFMT_X8R8G8B8; } + if (D3DDDIFMT_UNKNOWN != g_formatOverride) + { + m_fixedData.Format = g_formatOverride; + auto msaa = getMultisampleConfig(); + m_fixedData.MultisampleType = msaa.first; + m_fixedData.MultisampleQuality = msaa.second; + } + const bool isOffScreenPlain = 0 == (m_fixedData.Flags.Value & g_resourceTypeFlags); if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool && (isOffScreenPlain || m_fixedData.Flags.Texture) && @@ -478,7 +529,7 @@ namespace D3dDdi 0 == m_fixedData.pSurfList[0].Depth && 0 != D3dDdi::getFormatInfo(m_fixedData.Format).bytesPerPixel) { - const auto& caps = m_device.getAdapter().getD3dExtendedCaps(); + const auto& caps = m_device.getAdapter().getInfo().d3dExtendedCaps; const auto& surfaceInfo = m_fixedData.pSurfList[0]; if (0 != caps.dwMaxTextureWidth && surfaceInfo.Width > caps.dwMaxTextureWidth || 0 != caps.dwMaxTextureHeight && surfaceInfo.Height > caps.dwMaxTextureHeight) @@ -493,6 +544,17 @@ namespace D3dDdi return m_lockData.empty() ? nullptr : m_lockData[subResourceIndex].data; } + std::pair Resource::getMultisampleConfig() + { + if ((m_fixedData.Flags.RenderTarget && !m_fixedData.Flags.Texture && !m_fixedData.Flags.Primary || + m_fixedData.Flags.ZBuffer) && + D3DDDIPOOL_SYSTEMMEM != m_fixedData.Pool) + { + return m_device.getAdapter().getMultisampleConfig(m_fixedData.Format); + } + return { D3DDDIMULTISAMPLE_NONE, 0 }; + } + bool Resource::isOversized() const { return m_fixedData.SurfCount != m_origData.SurfCount; @@ -526,6 +588,34 @@ namespace D3dDdi return m_device.getOrigVtable().pfnLock(m_device, &data); } + void Resource::notifyLock(UINT subResourceIndex) + { + D3DDDIARG_LOCK lock = {}; + lock.hResource = D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool ? m_handle : m_lockResource.get(); + lock.SubResourceIndex = subResourceIndex; + lock.Flags.NotifyOnly = 1; + m_device.getOrigVtable().pfnLock(m_device, &lock); + + D3DDDIARG_UNLOCK unlock = {}; + unlock.hResource = lock.hResource; + unlock.SubResourceIndex = lock.SubResourceIndex; + unlock.Flags.NotifyOnly = 1; + m_device.getOrigVtable().pfnUnlock(m_device, &unlock); + } + + void Resource::prepareForBlt(UINT subResourceIndex, bool isReadOnly) + { + if (m_lockResource && 0 == m_lockData[subResourceIndex].lockCount) + { + if (!m_lockData[subResourceIndex].isVidMemUpToDate) + { + copyToVidMem(subResourceIndex); + } + m_lockData[subResourceIndex].isCustomUpToDate &= isReadOnly; + m_lockData[subResourceIndex].isSysMemUpToDate &= isReadOnly; + } + } + void Resource::prepareForGdiRendering(bool isReadOnly) { if (!m_lockResource) @@ -538,28 +628,44 @@ namespace D3dDdi copyToSysMem(0); } m_lockData[0].isVidMemUpToDate &= isReadOnly; + m_lockData[0].isCustomUpToDate &= isReadOnly; m_lockData[0].qpcLastForcedLock = Time::queryPerformanceCounter(); } - void Resource::prepareForRendering(UINT subResourceIndex, bool isReadOnly) + void Resource::prepareForRendering(UINT subResourceIndex) { if (m_lockResource && 0 == m_lockData[subResourceIndex].lockCount) { - if (!m_lockData[subResourceIndex].isVidMemUpToDate) + if (m_customSurface.resource) + { + if (!m_lockData[subResourceIndex].isCustomUpToDate) + { + 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) { copyToVidMem(subResourceIndex); } - m_lockData[subResourceIndex].isSysMemUpToDate &= isReadOnly; + m_lockData[subResourceIndex].isSysMemUpToDate = false; } } HRESULT Resource::presentationBlt(D3DDDIARG_BLT data, Resource* srcResource) { if (srcResource->m_lockResource && - srcResource->m_lockData[0].isSysMemUpToDate) + srcResource->m_lockData[0].isSysMemUpToDate && + !srcResource->m_fixedData.Flags.RenderTarget) { - srcResource->copyToVidMem(0); + srcResource->m_lockData[0].isVidMemUpToDate = false; } + srcResource->prepareForBlt(0, true); const bool isPalettized = D3DDDIFMT_P8 == srcResource->m_origData.Format; @@ -659,7 +765,7 @@ namespace D3dDdi return LOG_RESULT(m_device.getOrigVtable().pfnBlt(m_device, &data)); } - const auto& caps = m_device.getAdapter().getD3dExtendedCaps(); + const auto& caps = m_device.getAdapter().getInfo().d3dExtendedCaps; const auto tilesPerRow = divCeil(m_origData.pSurfList[0].Width, caps.dwMaxTextureWidth); const RECT origRect = rect; @@ -763,6 +869,7 @@ namespace D3dDdi copyToSysMem(data.DstSubResourceIndex); } dstLockData.isVidMemUpToDate = false; + dstLockData.isCustomUpToDate = false; if (!srcLockData.isSysMemUpToDate) { @@ -787,13 +894,23 @@ namespace D3dDdi data.Flags.DstColorKey ? reinterpret_cast(&data.ColorKey) : nullptr, data.Flags.SrcColorKey ? reinterpret_cast(&data.ColorKey) : nullptr); + notifyLock(data.DstSubResourceIndex); return S_OK; } } - prepareForRendering(data.DstSubResourceIndex, false); - srcResource.prepareForRendering(data.SrcSubResourceIndex, true); - return m_device.getOrigVtable().pfnBlt(m_device, &data); + prepareForBlt(data.DstSubResourceIndex, false); + srcResource.prepareForBlt(data.SrcSubResourceIndex, true); + HRESULT result = m_device.getOrigVtable().pfnBlt(m_device, &data); + if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool) + { + notifyLock(data.DstSubResourceIndex); + } + else if (D3DDDIPOOL_SYSTEMMEM == srcResource.m_fixedData.Pool) + { + srcResource.notifyLock(data.SrcSubResourceIndex); + } + return result; } template diff --git a/DDrawCompat/D3dDdi/Resource.h b/DDrawCompat/D3dDdi/Resource.h index cf72775..cf73a51 100644 --- a/DDrawCompat/D3dDdi/Resource.h +++ b/DDrawCompat/D3dDdi/Resource.h @@ -7,6 +7,7 @@ #include #include +#include namespace D3dDdi { @@ -24,15 +25,17 @@ namespace D3dDdi ~Resource(); operator HANDLE() const { return m_handle; } - const D3DDDIARG_CREATERESOURCE2& getOrigDesc() const { return m_origData; } + const Resource* getCustomResource() { return m_customSurface.resource; } const D3DDDIARG_CREATERESOURCE2& getFixedDesc() const { return m_fixedData; } + const D3DDDIARG_CREATERESOURCE2& getOrigDesc() const { return m_origData; } HRESULT blt(D3DDDIARG_BLT data); HRESULT colorFill(D3DDDIARG_COLORFILL data); void* getLockPtr(UINT subResourceIndex); HRESULT lock(D3DDDIARG_LOCK& data); + void prepareForBlt(UINT subResourceIndex, bool isReadOnly); void prepareForGdiRendering(bool isReadOnly); - void prepareForRendering(UINT subResourceIndex, bool isReadOnly); + void prepareForRendering(UINT subResourceIndex); void setAsGdiResource(bool isGdiResource); HRESULT unlock(const D3DDDIARG_UNLOCK& data); @@ -58,6 +61,7 @@ namespace D3dDdi long long qpcLastForcedLock; bool isSysMemUpToDate; bool isVidMemUpToDate; + bool isCustomUpToDate; }; class ResourceDeleter @@ -80,8 +84,10 @@ namespace D3dDdi void createLockResource(); void createSysMemResource(const std::vector& surfaceInfo); void fixResourceData(); + std::pair getMultisampleConfig(); bool isOversized() const; bool isValidRect(UINT subResourceIndex, const RECT& rect); + void notifyLock(UINT subResourceIndex); HRESULT presentationBlt(D3DDDIARG_BLT data, Resource* srcResource); HRESULT splitBlt(D3DDDIARG_BLT& data, UINT& subResourceIndex, RECT& rect, RECT& otherRect); @@ -99,5 +105,6 @@ namespace D3dDdi std::unique_ptr m_lockBuffer; std::vector m_lockData; std::unique_ptr m_lockResource; + SurfaceRepository::Surface m_customSurface; }; } diff --git a/DDrawCompat/D3dDdi/SurfaceRepository.cpp b/DDrawCompat/D3dDdi/SurfaceRepository.cpp index c16305b..04311c1 100644 --- a/DDrawCompat/D3dDdi/SurfaceRepository.cpp +++ b/DDrawCompat/D3dDdi/SurfaceRepository.cpp @@ -29,7 +29,7 @@ namespace D3dDdi } CompatWeakPtr SurfaceRepository::createSurface( - DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps) + DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps, UINT surfaceCount) { auto dd(m_adapter.getRepository()); if (!dd) @@ -47,8 +47,16 @@ namespace D3dDdi desc.dwHeight = height; desc.ddpfPixelFormat = pf; desc.ddsCaps.dwCaps = caps; + if (surfaceCount > 1) + { + desc.dwFlags |= DDSD_BACKBUFFERCOUNT; + desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX | DDSCAPS_FLIP; + desc.dwBackBufferCount = surfaceCount - 1; + } + s_inCreateSurface = true; HRESULT result = dd->CreateSurface(dd, &desc, &surface.getRef(), nullptr); + s_inCreateSurface = false; if (FAILED(result)) { LOG_ONCE("ERROR: Failed to create repository surface: " << Compat::hex(result) << " " << desc); @@ -72,7 +80,7 @@ namespace D3dDdi { DWORD width = rect.right - rect.left; DWORD height = rect.bottom - rect.top; - auto resource = getResource(surface, width, height, pf, caps); + auto resource = getSurface(surface, width, height, pf, caps).resource; if (!resource) { return nullptr; @@ -140,8 +148,8 @@ namespace D3dDdi } DeleteObject(iconInfo.hbmMask); - m_cursorMaskTexture.resource->prepareForRendering(0, true); - m_cursorColorTexture.resource->prepareForRendering(0, true); + m_cursorMaskTexture.resource->prepareForBlt(0, true); + m_cursorColorTexture.resource->prepareForBlt(0, true); m_cursorSize.cx = rect.right - rect.left; m_cursorSize.cy = rect.bottom - rect.top; @@ -155,8 +163,8 @@ namespace D3dDdi 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); + result.tempTexture = getSurface(m_cursorTempTexture, m_cursorSize.cx, m_cursorSize.cy, + DDraw::DirectDraw::getRgbPixelFormat(32), DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY).resource; return result; } @@ -180,7 +188,7 @@ namespace D3dDdi Resource* SurfaceRepository::getInitializedResource(Surface& surface, DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps, std::function initFunc) { - if (!isLost(surface) || !getResource(surface, width, height, pf, caps)) + if (!isLost(surface) || !getSurface(surface, width, height, pf, caps).resource) { return surface.resource; } @@ -195,14 +203,14 @@ namespace D3dDdi initFunc(desc); surface.surface->Unlock(surface.surface, nullptr); - surface.resource->prepareForRendering(0, true); + surface.resource->prepareForBlt(0, true); return surface.resource; } Resource* SurfaceRepository::getPaletteTexture() { - return getResource(m_paletteTexture, 256, 1, DDraw::DirectDraw::getRgbPixelFormat(32), - DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY); + return getSurface(m_paletteTexture, 256, 1, DDraw::DirectDraw::getRgbPixelFormat(32), + DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY).resource; } const SurfaceRepository::Surface& SurfaceRepository::getRenderTarget(DWORD width, DWORD height) @@ -211,13 +219,8 @@ namespace D3dDdi DDSCAPS_3DDEVICE | DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY); } - Resource* SurfaceRepository::getResource(Surface& surface, DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps) - { - return getSurface(surface, width, height, pf, caps).resource; - } - SurfaceRepository::Surface& SurfaceRepository::getSurface(Surface& surface, DWORD width, DWORD height, - const DDPIXELFORMAT& pf, DWORD caps) + const DDPIXELFORMAT& pf, DWORD caps, UINT surfaceCount) { if (surface.surface && (surface.width != width || surface.height != height || 0 != memcmp(&surface.pixelFormat, &pf, sizeof(pf)) || isLost(surface))) @@ -227,7 +230,7 @@ namespace D3dDdi if (!surface.surface) { - surface.surface = createSurface(width, height, pf, caps); + surface.surface = createSurface(width, height, pf, caps, surfaceCount); if (surface.surface) { surface.resource = D3dDdi::Device::findResource( @@ -254,4 +257,6 @@ namespace D3dDdi surface = {}; } } + + bool SurfaceRepository::s_inCreateSurface = false; } diff --git a/DDrawCompat/D3dDdi/SurfaceRepository.h b/DDrawCompat/D3dDdi/SurfaceRepository.h index e711164..221d536 100644 --- a/DDrawCompat/D3dDdi/SurfaceRepository.h +++ b/DDrawCompat/D3dDdi/SurfaceRepository.h @@ -37,18 +37,20 @@ namespace D3dDdi Resource* getLogicalXorTexture(); Resource* getPaletteTexture(); const Surface& getRenderTarget(DWORD width, DWORD height); + Surface& getSurface(Surface& surface, DWORD width, DWORD height, + const DDPIXELFORMAT& pf, DWORD caps, UINT surfaceCount = 1); static SurfaceRepository& get(const Adapter& adapter); + static bool inCreateSurface() { return s_inCreateSurface; } private: SurfaceRepository(const Adapter& adapter); - CompatWeakPtr createSurface(DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps); + CompatWeakPtr createSurface(DWORD width, DWORD height, + const DDPIXELFORMAT& pf, DWORD caps, UINT surfaceCount); Resource* getBitmapResource(Surface& surface, HBITMAP bitmap, const RECT& rect, const DDPIXELFORMAT& pf, DWORD caps); Resource* getInitializedResource(Surface& surface, DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps, std::function initFunc); - Resource* getResource(Surface& surface, DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps); - Surface& getSurface(Surface& surface, DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps); bool isLost(Surface& surface); void release(Surface& surface); @@ -62,5 +64,7 @@ namespace D3dDdi Surface m_logicalXorTexture; Surface m_paletteTexture; Surface m_renderTarget; + + static bool s_inCreateSurface; }; } diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index fac6c29..061c793 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -214,6 +214,7 @@ + @@ -322,6 +323,7 @@ + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index 071b84d..ff8101c 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -453,6 +453,9 @@ Header Files\Config\Settings + + Header Files\Config\Settings + @@ -713,6 +716,9 @@ Source Files\Config\Settings + + Source Files\Config\Settings + diff --git a/DDrawCompat/Direct3d/Hooks.cpp b/DDrawCompat/Direct3d/Hooks.cpp index a43380e..3ca8965 100644 --- a/DDrawCompat/Direct3d/Hooks.cpp +++ b/DDrawCompat/Direct3d/Hooks.cpp @@ -52,7 +52,7 @@ namespace desc.ddpfPixelFormat.dwRBitMask = 0x00FF0000; desc.ddpfPixelFormat.dwGBitMask = 0x0000FF00; desc.ddpfPixelFormat.dwBBitMask = 0x000000FF; - desc.ddsCaps.dwCaps = DDSCAPS_3DDEVICE; + desc.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; CompatPtr renderTarget; HRESULT result = dd->CreateSurface(&dd, &desc, &renderTarget.getRef(), nullptr);