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

Added ResolutionScale setting

This commit is contained in:
narzoul 2021-12-28 00:41:11 +01:00
parent 8b393ea498
commit c714383613
24 changed files with 405 additions and 157 deletions

View File

@ -9,6 +9,7 @@ namespace Config
Settings::DisplayFilter displayFilter;
Settings::DisplayResolution displayResolution;
Settings::RenderColorDepth renderColorDepth;
Settings::ResolutionScale resolutionScale;
Settings::SupportedResolutions supportedResolutions;
Settings::TextureFilter textureFilter;
Settings::ThreadPriorityBoost threadPriorityBoost;

View File

@ -7,6 +7,7 @@
#include <Config/Settings/DisplayFilter.h>
#include <Config/Settings/DisplayResolution.h>
#include <Config/Settings/RenderColorDepth.h>
#include <Config/Settings/ResolutionScale.h>
#include <Config/Settings/SupportedResolutions.h>
#include <Config/Settings/TextureFilter.h>
#include <Config/Settings/ThreadPriorityBoost.h>
@ -24,6 +25,7 @@ namespace Config
extern Settings::DisplayFilter displayFilter;
extern Settings::DisplayResolution displayResolution;
extern Settings::RenderColorDepth renderColorDepth;
extern Settings::ResolutionScale resolutionScale;
extern Settings::SupportedResolutions supportedResolutions;
extern Settings::TextureFilter textureFilter;
extern Settings::ThreadPriorityBoost threadPriorityBoost;

View File

@ -0,0 +1,44 @@
#include <Config/Settings/ResolutionScale.h>
namespace Config
{
namespace Settings
{
ResolutionScale::ResolutionScale()
: MappedSetting("ResolutionScale", "app", { {"app", APP}, {"display", DISPLAY} })
{
}
std::string ResolutionScale::getValueStr() const
{
try
{
return MappedSetting::getValueStr();
}
catch (const ParsingError&)
{
return std::to_string(m_value.cx) + 'x' + std::to_string(m_value.cy);
}
}
Setting::ParamInfo ResolutionScale::getParamInfo() const
{
return { "Multiplier", APP == m_value ? 1 : -16, 16, 1, m_param };
}
void ResolutionScale::setValue(const std::string& value)
{
try
{
MappedSetting::setValue(value);
}
catch (const ParsingError&)
{
m_value = Parser::parseResolution(value);
}
}
const SIZE ResolutionScale::APP = { 0, 0 };
const SIZE ResolutionScale::DISPLAY = { 1, 0 };
}
}

View File

@ -0,0 +1,27 @@
#pragma once
#include <Windows.h>
#include <Common/Comparison.h>
#include <Config/MappedSetting.h>
namespace Config
{
namespace Settings
{
class ResolutionScale : public MappedSetting<SIZE>
{
public:
static const SIZE APP;
static const SIZE DISPLAY;
ResolutionScale();
virtual ParamInfo getParamInfo() const override;
protected:
std::string getValueStr() const override;
void setValue(const std::string& value) override;
};
}
}

View File

@ -37,6 +37,7 @@ namespace D3dDdi
, m_runtimeVersion(data.Version)
, m_driverVersion(data.DriverVersion)
, m_luid(KernelModeThunks::getLastOpenAdapterInfo().luid)
, m_deviceName(KernelModeThunks::getLastOpenAdapterInfo().monitorInfo.szDevice)
, m_repository{}
{
}
@ -56,6 +57,11 @@ namespace D3dDdi
Compat::Log() << "Supported z-buffer bit depths: " << bitDepthsToString(info.supportedZBufferBitDepths);
Compat::Log() << "Supported MSAA modes: " << getSupportedMsaaModes(info.formatOps);
LOG_DEBUG << "Supported resource formats:";
for (const auto& formatOp : info.formatOps)
{
LOG_DEBUG << " " << formatOp.second;
}
return info;
}
@ -86,6 +92,14 @@ namespace D3dDdi
return result;
}
float Adapter::getMaxScaleFactor(SIZE size) const
{
const auto& caps = getInfo().d3dExtendedCaps;
const float scaleX = static_cast<float>(caps.dwMaxTextureWidth) / size.cx;
const float scaleY = static_cast<float>(caps.dwMaxTextureHeight) / size.cy;
return min(scaleX, scaleY);
}
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> Adapter::getMultisampleConfig(D3DDDIFORMAT format) const
{
UINT samples = Config::antialiasing.get();
@ -113,6 +127,53 @@ namespace D3dDdi
return { levels.MsType, min(static_cast<UINT>(Config::antialiasing.getParam()), levels.QualityLevels - 1) };
}
SIZE Adapter::getScaledSize(SIZE size) const
{
DEVMODEW dm = {};
dm.dmSize = sizeof(dm);
EnumDisplaySettingsExW(m_deviceName.c_str(), ENUM_CURRENT_SETTINGS, &dm, 0);
const SIZE emulatedDisplaySize = { static_cast<long>(dm.dmPelsHeight), static_cast<long>(dm.dmPelsHeight) };
const float displayMaxScaleFactor = getMaxScaleFactor(emulatedDisplaySize);
const float resourceMaxScaleFactor = getMaxScaleFactor(size);
float maxScaleFactor = min(displayMaxScaleFactor, resourceMaxScaleFactor);
if (Config::resolutionScale.getParam() > 0)
{
maxScaleFactor = floor(maxScaleFactor);
}
SIZE baseSize = Config::resolutionScale.get();
const int multiplier = Config::resolutionScale.getParam();
if (Config::Settings::ResolutionScale::APP == baseSize)
{
baseSize = emulatedDisplaySize;
}
else if (Config::Settings::ResolutionScale::DISPLAY == baseSize)
{
CALL_ORIG_FUNC(EnumDisplaySettingsExW)(m_deviceName.c_str(), ENUM_CURRENT_SETTINGS, &dm, 0);
baseSize = { static_cast<long>(dm.dmPelsHeight), static_cast<long>(dm.dmPelsHeight) };
}
float scaleX = static_cast<float>(baseSize.cx) / emulatedDisplaySize.cx;
float scaleY = static_cast<float>(baseSize.cy) / emulatedDisplaySize.cy;
float scale = min(scaleX, scaleY) * abs(multiplier);
if (multiplier > 0)
{
scale = ceil(scale);
}
scale = max(scale, 1.0f);
scale = min(scale, maxScaleFactor);
size.cx = static_cast<LONG>(size.cx * scale);
size.cy = static_cast<LONG>(size.cy * scale);
const auto& caps = getInfo().d3dExtendedCaps;
size.cx = min(size.cx, static_cast<LONG>(caps.dwMaxTextureWidth));
size.cy = min(size.cy, static_cast<LONG>(caps.dwMaxTextureHeight));
return size;
}
std::string Adapter::getSupportedMsaaModes(const std::map<D3DDDIFORMAT, FORMATOP>& formatOps) const
{
auto it = formatOps.find(D3DDDIFMT_X8R8G8B8);

View File

@ -35,6 +35,7 @@ namespace D3dDdi
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> getMultisampleConfig(D3DDDIFORMAT format) const;
const D3DDDI_ADAPTERFUNCS& getOrigVtable() const { return m_origVtable; }
CompatWeakPtr<IDirectDraw7> getRepository() const { return m_repository; }
SIZE getScaledSize(SIZE size) const;
HRESULT pfnCloseAdapter();
HRESULT pfnCreateDevice(D3DDDIARG_CREATEDEVICE* pCreateData);
@ -49,6 +50,7 @@ namespace D3dDdi
HRESULT getCaps(D3DDDICAPS_TYPE type, Data& data, UINT size = sizeof(Data)) const;
std::map<D3DDDIFORMAT, FORMATOP> getFormatOps() const;
float getMaxScaleFactor(SIZE size) const;
std::string getSupportedMsaaModes(const std::map<D3DDDIFORMAT, FORMATOP>& formatOps) const;
DWORD getSupportedZBufferBitDepths(const std::map<D3DDDIFORMAT, FORMATOP>& formatOps) const;
@ -57,6 +59,7 @@ namespace D3dDdi
UINT m_runtimeVersion;
UINT m_driverVersion;
LUID m_luid;
std::wstring m_deviceName;
CompatWeakPtr<IDirectDraw7> m_repository;
static std::map<HANDLE, Adapter> s_adapters;

View File

@ -18,6 +18,7 @@ namespace
{
HANDLE g_gdiResourceHandle = nullptr;
D3dDdi::Resource* g_gdiResource = nullptr;
bool g_isConfigUpdatePending = false;
}
namespace D3dDdi
@ -163,12 +164,22 @@ namespace D3dDdi
{
prepareForGpuWrite();
}
if (m_renderTarget && rect)
{
std::vector<RECT> scaledRect(rect, rect + numRect);
for (UINT i = 0; i < numRect; ++i)
{
m_renderTarget->scaleRect(scaledRect[i]);
}
return m_origVtable.pfnClear(m_device, data, numRect, scaledRect.data());
}
return m_origVtable.pfnClear(m_device, data, numRect, rect);
}
HRESULT Device::pfnColorFill(const D3DDDIARG_COLORFILL* data)
{
flushPrimitives();
auto it = m_resources.find(data->hResource);
if (it != m_resources.end())
{
@ -309,7 +320,10 @@ namespace D3dDdi
{
d.hSrcResource = resource->prepareForGpuRead(data->SrcSubResourceIndex);
}
return m_origVtable.pfnPresent(m_device, &d);
HRESULT result = m_origVtable.pfnPresent(m_device, &d);
updateAllConfigNow();
return result;
}
HRESULT Device::pfnPresent1(D3DDDIARG_PRESENT1* data)
@ -325,7 +339,10 @@ namespace D3dDdi
srcResources[i].hResource = resource->prepareForGpuRead(srcResources[i].SubResourceIndex);
}
}
return m_origVtable.pfnPresent1(m_device, data);
HRESULT result = m_origVtable.pfnPresent1(m_device, data);
updateAllConfigNow();
return result;
}
HRESULT Device::pfnUnlock(const D3DDDIARG_UNLOCK* data)
@ -341,11 +358,18 @@ namespace D3dDdi
void Device::updateAllConfig()
{
DDraw::ScopedThreadLock ddLock;
D3dDdi::ScopedCriticalSection lock;
for (auto& device : s_devices)
g_isConfigUpdatePending = true;
}
void Device::updateAllConfigNow()
{
if (g_isConfigUpdatePending)
{
device.second.updateConfig();
g_isConfigUpdatePending = false;
for (auto& device : s_devices)
{
device.second.updateConfig();
}
}
}

View File

@ -70,6 +70,8 @@ namespace D3dDdi
static void updateAllConfig();
private:
static void updateAllConfigNow();
D3DDDI_DEVICEFUNCS m_origVtable;
Adapter& m_adapter;
HANDLE m_device;

View File

@ -239,17 +239,13 @@ namespace D3dDdi
return;
}
if (m_changedStates & CS_MISC)
{
updateMisc();
}
if (m_changedStates & CS_RENDER_STATE)
{
updateRenderStates();
}
if (m_changedStates & CS_RENDER_TARGET)
{
updateRenderTargets();
updateRenderTarget();
}
if (m_changedStates & CS_SHADER)
{
@ -449,21 +445,21 @@ namespace D3dDdi
HRESULT DeviceState::pfnSetViewport(const D3DDDIARG_VIEWPORTINFO* data)
{
m_app.viewport = *data;
m_changedStates |= CS_MISC;
m_changedStates |= CS_RENDER_TARGET;
return S_OK;
}
HRESULT DeviceState::pfnSetZRange(const D3DDDIARG_ZRANGE* data)
{
m_app.zRange = *data;
m_changedStates |= CS_MISC;
m_changedStates |= CS_RENDER_TARGET;
return S_OK;
}
HRESULT DeviceState::pfnUpdateWInfo(const D3DDDIARG_WINFO* data)
{
m_app.wInfo = *data;
m_changedStates |= CS_MISC;
m_changedStates |= CS_RENDER_TARGET;
return S_OK;
}
@ -528,11 +524,10 @@ namespace D3dDdi
void DeviceState::setRenderTarget(const D3DDDIARG_SETRENDERTARGET& renderTarget)
{
if (setData(renderTarget, m_current.renderTarget, m_device.getOrigVtable().pfnSetRenderTarget))
{
m_device.setRenderTarget(m_app.renderTarget);
LOG_DS << renderTarget;
}
m_device.flushPrimitives();
m_device.getOrigVtable().pfnSetRenderTarget(m_device, &renderTarget);
m_current.renderTarget = renderTarget;
LOG_DS << renderTarget;
}
bool DeviceState::setShader(HANDLE shader, HANDLE& currentShader,
@ -600,6 +595,7 @@ namespace D3dDdi
void DeviceState::setTempRenderTarget(const D3DDDIARG_SETRENDERTARGET& renderTarget)
{
setRenderTarget(renderTarget);
m_device.setRenderTarget({});
m_changedStates |= CS_RENDER_TARGET;
}
@ -644,6 +640,7 @@ namespace D3dDdi
void DeviceState::setTempVertexShaderDecl(HANDLE decl)
{
m_current.vertexShaderDecl = DELETED_RESOURCE;
setVertexShaderDecl(decl);
m_changedStates |= CS_SHADER;
}
@ -651,19 +648,19 @@ namespace D3dDdi
void DeviceState::setTempViewport(const D3DDDIARG_VIEWPORTINFO& viewport)
{
setViewport(viewport);
m_changedStates |= CS_MISC;
m_changedStates |= CS_RENDER_TARGET;
}
void DeviceState::setTempWInfo(const D3DDDIARG_WINFO& wInfo)
{
setWInfo(wInfo);
m_changedStates |= CS_MISC;
m_changedStates |= CS_RENDER_TARGET;
}
void DeviceState::setTempZRange(const D3DDDIARG_ZRANGE& zRange)
{
setZRange(zRange);
m_changedStates |= CS_MISC;
m_changedStates |= CS_RENDER_TARGET;
}
bool DeviceState::setTexture(UINT stage, HANDLE texture)
@ -762,26 +759,6 @@ namespace D3dDdi
m_changedTextureStageStates[i].set(D3DDDITSS_MAXANISOTROPY);
}
m_maxChangedTextureStage = m_changedTextureStageStates.size() - 1;
updateVertexFixupConstants();
}
void DeviceState::updateMisc()
{
bool updateConstants = setViewport(m_app.viewport);
auto wInfo = m_app.wInfo;
if (1.0f == wInfo.WNear && 1.0f == wInfo.WFar)
{
wInfo.WNear = 0.0f;
}
setWInfo(wInfo);
updateConstants |= setZRange(m_app.zRange);
if (updateConstants)
{
updateVertexFixupConstants();
}
}
void DeviceState::updateRenderStates()
@ -794,23 +771,42 @@ namespace D3dDdi
m_changedRenderStates.reset();
}
void DeviceState::updateRenderTargets()
void DeviceState::updateRenderTarget()
{
auto vp = m_app.viewport;
auto renderTarget = m_app.renderTarget;
auto depthStencil = m_app.depthStencil;
Resource* resource = m_device.getResource(renderTarget.hRenderTarget);
if (resource && resource->getCustomResource())
{
resource->scaleRect(reinterpret_cast<RECT&>(vp));
renderTarget.hRenderTarget = *resource->getCustomResource();
resource = m_device.getResource(depthStencil.hZBuffer);
if (resource && resource->getCustomResource())
{
depthStencil.hZBuffer = *resource->getCustomResource();
}
}
setRenderTarget(renderTarget);
auto depthStencil = m_app.depthStencil;
resource = m_device.getResource(depthStencil.hZBuffer);
if (resource && resource->getCustomResource())
{
depthStencil.hZBuffer = *resource->getCustomResource();
}
setRenderTarget(renderTarget);
m_current.vertexShaderFunc = DELETED_RESOURCE;
m_changedStates |= CS_SHADER;
m_device.setRenderTarget(m_app.renderTarget);
setDepthStencil(depthStencil);
setViewport(vp);
auto wInfo = m_app.wInfo;
if (1.0f == wInfo.WNear && 1.0f == wInfo.WFar)
{
wInfo.WNear = 0.0f;
}
setWInfo(wInfo);
setZRange(m_app.zRange);
updateVertexFixupConstants();
}
void DeviceState::updateShaders()
@ -902,14 +898,19 @@ namespace D3dDdi
data.Count = 2;
const float apc = Config::alternatePixelCenter.get();
const auto& vp = m_current.viewport;
const auto& vp = m_app.viewport;
const auto& zr = m_current.zRange;
const float sx = static_cast<float>(m_current.viewport.Width) / m_app.viewport.Width;
const float sy = static_cast<float>(m_current.viewport.Height) / m_app.viewport.Height;
ShaderConstF registers[2] = {
{ apc - vp.X - vp.Width / 2, apc - vp.Y - vp.Height / 2, -zr.MinZ, 0.0f },
{ 0.5f + apc - 0.5f / sx - vp.X - vp.Width / 2, 0.5f + apc - 0.5f / sy - vp.Y - vp.Height / 2, -zr.MinZ, 0.0f },
{ 2.0f / vp.Width, -2.0f / vp.Height, 1.0f / (zr.MaxZ - zr.MinZ), 1.0f }
};
m_device.getOrigVtable().pfnSetVertexShaderConst(m_device, &data, registers);
if (0 != memcmp(registers, &m_vertexShaderConst[data.Register], sizeof(registers)))
{
pfnSetVertexShaderConst(&data, registers);
}
}
}

View File

@ -98,6 +98,7 @@ namespace D3dDdi
void setTempZRange(const D3DDDIARG_ZRANGE& zRange);
void flush();
HANDLE getVertexFixupDecl() const { return m_vsVertexFixup.get(); }
void onDestroyResource(HANDLE resource);
void updateConfig();
@ -106,12 +107,11 @@ namespace D3dDdi
enum ChangedState
{
CS_MISC = 1 << 0,
CS_RENDER_STATE = 1 << 1,
CS_RENDER_TARGET = 1 << 2,
CS_SHADER = 1 << 3,
CS_STREAM_SOURCE = 1 << 4,
CS_TEXTURE_STAGE = 1 << 5
CS_RENDER_STATE = 1 << 0,
CS_RENDER_TARGET = 1 << 1,
CS_SHADER = 1 << 2,
CS_STREAM_SOURCE = 1 << 3,
CS_TEXTURE_STAGE = 1 << 4
};
struct State
@ -170,9 +170,8 @@ namespace D3dDdi
void setWInfo(const D3DDDIARG_WINFO& wInfo);
bool setZRange(const D3DDDIARG_ZRANGE& zRange);
void updateMisc();
void updateRenderStates();
void updateRenderTargets();
void updateRenderTarget();
void updateShaders();
void updateStreamSource();
void updateTextureColorKey(UINT stage);

View File

@ -87,3 +87,13 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_GETCAPS& data)
<< data.pData
<< data.DataSize;
}
std::ostream& operator<<(std::ostream& os, const FORMATOP& data)
{
return Compat::LogStruct(os)
<< data.Format
<< Compat::hex(data.Operations)
<< Compat::hex(data.FlipMsTypes)
<< Compat::hex(data.BltMsTypes)
<< data.PrivateFormatBitCount;
}

View File

@ -10,3 +10,4 @@
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);
std::ostream& operator<<(std::ostream& os, const FORMATOP& data);

View File

@ -1,5 +1,6 @@
#include <type_traits>
#include <Common/Comparison.h>
#include <Common/HResultException.h>
#include <Common/Log.h>
#include <Common/Time.h>
@ -18,6 +19,7 @@
#include <Gdi/Palette.h>
#include <Gdi/VirtualScreen.h>
#include <Gdi/Window.h>
#include <Win32/DisplayMode.h>
namespace
{
@ -25,16 +27,12 @@ namespace
const UINT g_resourceTypeFlags = getResourceTypeFlags().Value;
RECT g_presentationRect = {};
RECT g_primaryRect = {};
D3DDDIFORMAT g_formatOverride = D3DDDIFMT_UNKNOWN;
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> g_msaaOverride = {};
RECT calculatePresentationRect()
RECT calculateScaledRect(const RECT& srcRect, const RECT& dstRect)
{
const RECT srcRect = DDraw::PrimarySurface::getMonitorRect();
const RECT dstRect = DDraw::RealPrimarySurface::getMonitorRect();
const int srcWidth = srcRect.right - srcRect.left;
const int srcHeight = srcRect.bottom - srcRect.top;
const int dstWidth = dstRect.right - dstRect.left;
@ -54,6 +52,11 @@ namespace
return rect;
}
RECT calculatePresentationRect()
{
return calculateScaledRect(DDraw::PrimarySurface::getMonitorRect(), DDraw::RealPrimarySurface::getMonitorRect());
}
LONG divCeil(LONG n, LONG d)
{
return (n + d - 1) / d;
@ -113,6 +116,7 @@ namespace D3dDdi
, m_msaaResolvedSurface{}
, m_formatConfig(D3DDDIFMT_UNKNOWN)
, m_multiSampleConfig{ D3DDDIMULTISAMPLE_NONE, 0 }
, m_scaledSize{}
, m_isSurfaceRepoResource(SurfaceRepository::inCreateSurface())
{
if (m_origData.Flags.VertexBuffer &&
@ -126,10 +130,10 @@ namespace D3dDdi
{
g_presentationRect = calculatePresentationRect();
auto& si = m_origData.pSurfList[0];
g_primaryRect = { 0, 0, static_cast<LONG>(si.Width), static_cast<LONG>(si.Height) };
RECT primaryRect = { 0, 0, static_cast<LONG>(si.Width), static_cast<LONG>(si.Height) };
Gdi::Cursor::setMonitorClipRect(DDraw::PrimarySurface::getMonitorRect());
if (!EqualRect(&g_presentationRect, &g_primaryRect))
if (!EqualRect(&g_presentationRect, &primaryRect))
{
Gdi::Cursor::setEmulated(true);
}
@ -139,6 +143,7 @@ namespace D3dDdi
fixResourceData();
m_formatInfo = getFormatInfo(m_fixedData.Format);
m_formatConfig = m_fixedData.Format;
m_scaledSize = { static_cast<LONG>(m_fixedData.pSurfList[0].Width), static_cast<LONG>(m_fixedData.pSurfList[0].Height) };
HRESULT result = m_device.createPrivateResource(m_fixedData);
if (FAILED(result))
@ -243,15 +248,17 @@ namespace D3dDdi
{
LOG_FUNC("Resource::bltLock", data);
loadSysMemResource(data.SubResourceIndex);
if (data.Flags.ReadOnly)
{
prepareForCpuRead(data.SubResourceIndex);
}
else
{
prepareForCpuWrite(data.SubResourceIndex);
}
auto& lockData = m_lockData[data.SubResourceIndex];
lockData.qpcLastForcedLock = Time::queryPerformanceCounter();
if (!data.Flags.ReadOnly)
{
clearUpToDateFlags(data.SubResourceIndex);
lockData.isSysMemUpToDate = true;
}
unsigned char* ptr = static_cast<unsigned char*>(lockData.data);
if (data.Flags.AreaValid)
@ -292,25 +299,7 @@ namespace D3dDdi
if (m_lockResource)
{
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 && !lockData.isVidMemUpToDate)
{
auto dstBuf = static_cast<BYTE*>(lockData.data) +
data.DstRect.top * lockData.pitch + data.DstRect.left * m_formatInfo.bytesPerPixel;
@ -318,21 +307,25 @@ namespace D3dDdi
DDraw::Blitter::colorFill(dstBuf, lockData.pitch,
data.DstRect.right - data.DstRect.left, data.DstRect.bottom - data.DstRect.top,
m_formatInfo.bytesPerPixel, colorConvert(m_formatInfo, data.Color));
}
return LOG_RESULT(S_OK);
return LOG_RESULT(S_OK);
}
}
prepareForBltDst(data.hResource, data.SubResourceIndex, data.DstRect);
return LOG_RESULT(m_device.getOrigVtable().pfnColorFill(m_device, &data));
}
HRESULT Resource::copySubResource(Resource& dstResource, Resource& srcResource, UINT subResourceIndex)
{
return copySubResourceRegion(dstResource, subResourceIndex, dstResource.getRect(subResourceIndex),
srcResource, subResourceIndex, srcResource.getRect(subResourceIndex));
}
HRESULT Resource::copySubResource(HANDLE dstResource, HANDLE srcResource, UINT subResourceIndex)
{
RECT rect = {};
rect.right = m_fixedData.pSurfList[subResourceIndex].Width;
rect.bottom = m_fixedData.pSurfList[subResourceIndex].Height;
return copySubResourceRegion(dstResource, subResourceIndex, rect, srcResource, subResourceIndex, rect);
return copySubResourceRegion(dstResource, subResourceIndex, getRect(subResourceIndex),
srcResource, subResourceIndex, getRect(subResourceIndex));
}
HRESULT Resource::copySubResourceRegion(HANDLE dst, UINT dstIndex, const RECT& dstRect,
@ -540,6 +533,24 @@ namespace D3dDdi
return { D3DDDIMULTISAMPLE_NONE, 0 };
}
RECT Resource::getRect(UINT subResourceIndex)
{
const auto& si = m_fixedData.pSurfList[subResourceIndex];
return { 0, 0, static_cast<LONG>(si.Width), static_cast<LONG>(si.Height) };
}
SIZE Resource::getScaledSize()
{
SIZE size = { static_cast<LONG>(m_fixedData.pSurfList[0].Width), static_cast<LONG>(m_fixedData.pSurfList[0].Height) };
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().getScaledSize(size);
}
return size;
}
bool Resource::isOversized() const
{
return m_fixedData.SurfCount != m_origData.SurfCount;
@ -564,7 +575,7 @@ namespace D3dDdi
else
{
loadVidMemResource(subResourceIndex);
copySubResource(*m_msaaSurface.resource, m_handle, subResourceIndex);
copySubResource(*m_msaaSurface.resource, *this, subResourceIndex);
}
m_lockData[subResourceIndex].isMsaaUpToDate = true;
}
@ -581,7 +592,7 @@ namespace D3dDdi
else
{
loadVidMemResource(subResourceIndex);
copySubResource(*m_msaaResolvedSurface.resource, m_handle, subResourceIndex);
copySubResource(*m_msaaResolvedSurface.resource, *this, subResourceIndex);
}
m_lockData[subResourceIndex].isMsaaResolvedUpToDate = true;
}
@ -592,7 +603,7 @@ namespace D3dDdi
if (!m_lockData[subResourceIndex].isSysMemUpToDate)
{
loadVidMemResource(subResourceIndex);
copySubResource(m_lockResource.get(), m_handle, subResourceIndex);
copySubResource(m_lockResource.get(), *this, subResourceIndex);
notifyLock(subResourceIndex);
m_lockData[subResourceIndex].isSysMemUpToDate = true;
}
@ -607,16 +618,16 @@ namespace D3dDdi
if (m_msaaResolvedSurface.resource)
{
loadMsaaResolvedResource(subResourceIndex);
copySubResource(m_handle, *m_msaaResolvedSurface.resource, subResourceIndex);
copySubResource(*this, *m_msaaResolvedSurface.resource, subResourceIndex);
}
else
{
copySubResource(m_handle, *m_msaaSurface.resource, subResourceIndex);
copySubResource(*this, *m_msaaSurface.resource, subResourceIndex);
}
}
else
{
copySubResource(m_handle, m_lockResource.get(), subResourceIndex);
copySubResource(*this, m_lockResource.get(), subResourceIndex);
notifyLock(subResourceIndex);
}
m_lockData[subResourceIndex].isVidMemUpToDate = true;
@ -686,28 +697,35 @@ namespace D3dDdi
}
Resource& Resource::prepareForBltDst(D3DDDIARG_BLT& data)
{
return prepareForBltDst(data.hDstResource, data.DstSubResourceIndex, data.DstRect);
}
Resource& Resource::prepareForBltDst(HANDLE& resource, UINT& subResourceIndex, RECT& rect)
{
if (m_lockResource)
{
if (m_lockData[data.DstSubResourceIndex].isMsaaUpToDate)
if (m_lockData[subResourceIndex].isMsaaUpToDate)
{
data.hDstResource = *m_msaaSurface.resource;
clearUpToDateFlags(data.DstSubResourceIndex);
m_lockData[data.DstSubResourceIndex].isMsaaUpToDate = true;
resource = *m_msaaSurface.resource;
clearUpToDateFlags(subResourceIndex);
m_lockData[subResourceIndex].isMsaaUpToDate = true;
scaleRect(rect);
return *m_msaaSurface.resource;
}
else if (m_lockData[data.DstSubResourceIndex].isMsaaResolvedUpToDate)
else if (m_lockData[subResourceIndex].isMsaaResolvedUpToDate)
{
data.hDstResource = *m_msaaResolvedSurface.resource;
clearUpToDateFlags(data.DstSubResourceIndex);
m_lockData[data.DstSubResourceIndex].isMsaaResolvedUpToDate = true;
resource = *m_msaaResolvedSurface.resource;
clearUpToDateFlags(subResourceIndex);
m_lockData[subResourceIndex].isMsaaResolvedUpToDate = true;
scaleRect(rect);
return *m_msaaResolvedSurface.resource;
}
else
{
loadVidMemResource(data.DstSubResourceIndex);
clearUpToDateFlags(data.DstSubResourceIndex);
m_lockData[data.DstSubResourceIndex].isVidMemUpToDate = true;
loadVidMemResource(subResourceIndex);
clearUpToDateFlags(subResourceIndex);
m_lockData[subResourceIndex].isVidMemUpToDate = true;
}
}
return *this;
@ -782,7 +800,9 @@ namespace D3dDdi
{
srcResource->m_lockData[0].isVidMemUpToDate = false;
}
data.hSrcResource = srcResource->prepareForGpuRead(0);
srcResource = &srcResource->prepareForGpuRead(0);
data.hSrcResource = *srcResource;
}
const bool isPalettized = D3DDDIFMT_P8 == srcResource->m_origData.Format;
@ -793,14 +813,18 @@ namespace D3dDdi
const RECT monitorRect = DDraw::PrimarySurface::getMonitorRect();
const bool isLayeredPresentNeeded = Gdi::Window::presentLayered(nullptr, monitorRect);
const LONG srcWidth = srcResource->m_fixedData.pSurfList[0].Width;
const LONG srcHeight = srcResource->m_fixedData.pSurfList[0].Height;
data.SrcRect = { 0, 0, srcWidth, srcHeight };
UINT presentationFilter = Config::displayFilter.get();
UINT presentationFilterParam = Config::displayFilter.getParam();
if (Config::Settings::DisplayFilter::BILINEAR == presentationFilter &&
(g_presentationRect.right - g_presentationRect.left == g_primaryRect.right &&
g_presentationRect.bottom - g_presentationRect.top == g_primaryRect.bottom) ||
(g_presentationRect.right - g_presentationRect.left == srcWidth &&
g_presentationRect.bottom - g_presentationRect.top == srcHeight) ||
(0 == presentationFilterParam &&
0 == (g_presentationRect.right - g_presentationRect.left) % g_primaryRect.right &&
0 == (g_presentationRect.bottom - g_presentationRect.top) % g_primaryRect.bottom))
0 == (g_presentationRect.right - g_presentationRect.left) % srcWidth &&
0 == (g_presentationRect.bottom - g_presentationRect.top) % srcHeight))
{
presentationFilter = Config::Settings::DisplayFilter::POINT;
}
@ -808,8 +832,7 @@ namespace D3dDdi
if (isPalettized || isCursorEmulated || isLayeredPresentNeeded ||
Config::Settings::DisplayFilter::POINT != presentationFilter)
{
const auto& si = srcResource->m_fixedData.pSurfList[0];
const auto& dst(SurfaceRepository::get(m_device.getAdapter()).getTempRenderTarget(si.Width, si.Height));
const auto& dst(SurfaceRepository::get(m_device.getAdapter()).getTempRenderTarget(srcWidth, srcHeight));
if (!dst.resource)
{
return E_OUTOFMEMORY;
@ -859,6 +882,17 @@ namespace D3dDdi
return m_device.getOrigVtable().pfnBlt(m_device, &data);
}
void Resource::scaleRect(RECT& rect)
{
const LONG origWidth = m_fixedData.pSurfList[0].Width;
const LONG origHeight = m_fixedData.pSurfList[0].Height;
rect.left = rect.left * m_scaledSize.cx / origWidth;
rect.top = rect.top * m_scaledSize.cy / origHeight;
rect.right = rect.right * m_scaledSize.cx / origWidth;
rect.bottom = rect.bottom * m_scaledSize.cy / origHeight;
}
void Resource::setAsGdiResource(bool isGdiResource)
{
m_lockResource.reset();
@ -1097,7 +1131,8 @@ namespace D3dDdi
}
}
if (m_fixedData.Flags.RenderTarget || data.Flags.SrcColorKey || data.Flags.MirrorLeftRight || data.Flags.MirrorUpDown)
if (D3DDDIPOOL_SYSTEMMEM != m_fixedData.Pool &&
(m_fixedData.Flags.RenderTarget || data.Flags.SrcColorKey || data.Flags.MirrorLeftRight || data.Flags.MirrorUpDown))
{
if (SUCCEEDED(shaderBlt(data, srcResource)))
{
@ -1163,12 +1198,14 @@ namespace D3dDdi
const auto msaa = getMultisampleConfig();
const auto formatConfig = getFormatConfig();
if (m_multiSampleConfig == msaa && m_formatConfig == formatConfig)
const auto scaledSize = getScaledSize();
if (m_multiSampleConfig == msaa && m_formatConfig == formatConfig && m_scaledSize == scaledSize)
{
return;
}
m_multiSampleConfig = msaa;
m_formatConfig = formatConfig;
m_scaledSize = scaledSize;
if (m_fixedData.Flags.RenderTarget &&
(m_msaaSurface.resource || m_msaaResolvedSurface.resource))
@ -1187,9 +1224,10 @@ namespace D3dDdi
m_msaaSurface = {};
m_msaaResolvedSurface = {};
if (D3DDDIMULTISAMPLE_NONE != msaa.first || m_fixedData.Format != formatConfig)
if (D3DDDIMULTISAMPLE_NONE != msaa.first || m_fixedData.Format != formatConfig ||
static_cast<LONG>(m_fixedData.pSurfList[0].Width) != m_scaledSize.cx ||
static_cast<LONG>(m_fixedData.pSurfList[0].Height) != m_scaledSize.cy)
{
g_formatOverride = formatConfig;
if (m_fixedData.Flags.ZBuffer)
{
DDPIXELFORMAT pf = {};
@ -1198,10 +1236,12 @@ namespace D3dDdi
pf.dwZBufferBitDepth = 16;
pf.dwZBitMask = 0xFFFF;
g_formatOverride = formatConfig;
g_msaaOverride = msaa;
SurfaceRepository::get(m_device.getAdapter()).getSurface(m_msaaSurface,
m_fixedData.surfaceData[0].Width, m_fixedData.surfaceData[0].Height, pf,
scaledSize.cx, scaledSize.cy, pf,
DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY, m_fixedData.SurfCount);
g_formatOverride = D3DDDIFMT_UNKNOWN;
g_msaaOverride = {};
}
else
@ -1210,18 +1250,15 @@ namespace D3dDdi
{
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);
scaledSize.cx, scaledSize.cy, getPixelFormat(formatConfig),
DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY, m_fixedData.SurfCount);
g_msaaOverride = {};
}
SurfaceRepository::get(m_device.getAdapter()).getSurface(m_msaaResolvedSurface,
m_fixedData.surfaceData[0].Width, m_fixedData.surfaceData[0].Height,
DDraw::DirectDraw::getRgbPixelFormat(32),
DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY);
scaledSize.cx, scaledSize.cy, getPixelFormat(formatConfig),
DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY, m_fixedData.SurfCount);
}
g_formatOverride = D3DDDIFMT_UNKNOWN;
}
}
}

View File

@ -37,10 +37,12 @@ namespace D3dDdi
void onDestroyResource(HANDLE resource);
Resource& prepareForBltSrc(const D3DDDIARG_BLT& data);
Resource& prepareForBltDst(D3DDDIARG_BLT& data);
Resource& prepareForBltDst(HANDLE& resource, UINT& subResourceIndex, RECT& rect);
void prepareForCpuRead(UINT subResourceIndex);
void prepareForCpuWrite(UINT subResourceIndex);
Resource& prepareForGpuRead(UINT subResourceIndex);
void prepareForGpuWrite(UINT subResourceIndex);
void scaleRect(RECT& rect);
void setAsGdiResource(bool isGdiResource);
HRESULT unlock(const D3DDDIARG_UNLOCK& data);
void updateConfig();
@ -74,6 +76,7 @@ namespace D3dDdi
HRESULT bltLock(D3DDDIARG_LOCK& data);
void clearUpToDateFlags(UINT subResourceIndex);
void clipRect(UINT subResourceIndex, RECT& rect);
HRESULT copySubResource(Resource& dstResource, Resource& srcResource, UINT subResourceIndex);
HRESULT copySubResource(HANDLE dstResource, HANDLE srcResource, UINT subResourceIndex);
HRESULT copySubResourceRegion(HANDLE dst, UINT dstIndex, const RECT& dstRect,
HANDLE src, UINT srcIndex, const RECT& srcRect);
@ -83,6 +86,8 @@ namespace D3dDdi
void fixResourceData();
D3DDDIFORMAT getFormatConfig();
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> getMultisampleConfig();
RECT getRect(UINT subResourceIndex);
SIZE getScaledSize();
bool isOversized() const;
bool isValidRect(UINT subResourceIndex, const RECT& rect);
void loadMsaaResource(UINT subResourceIndex);
@ -112,6 +117,7 @@ namespace D3dDdi
SurfaceRepository::Surface m_msaaResolvedSurface;
D3DDDIFORMAT m_formatConfig;
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> m_multiSampleConfig;
SIZE m_scaledSize;
bool m_isSurfaceRepoResource;
};
}

View File

@ -38,6 +38,7 @@ namespace D3dDdi
}
const auto& srcSurface = srcResource.getFixedDesc().pSurfList[srcSubResourceIndex];
const auto& dstSurface = dstResource.getFixedDesc().pSurfList[dstSubResourceIndex];
auto& state = m_device.getState();
state.setTempRenderState({ D3DDDIRS_SCENECAPTURE, TRUE });
@ -45,8 +46,7 @@ namespace D3dDdi
state.setTempPixelShader(pixelShader);
state.setTempRenderTarget({ 0, dstResource, dstSubResourceIndex });
state.setTempDepthStencil({ nullptr });
state.setTempViewport({ static_cast<DWORD>(dstRect.left), static_cast<DWORD>(dstRect.top),
static_cast<DWORD>(dstRect.right - dstRect.left), static_cast<DWORD>(dstRect.bottom - dstRect.top) });
state.setTempViewport({ 0, 0, dstSurface.Width, dstSurface.Height });
state.setTempZRange({ 0, 1 });
state.setTempRenderState({ D3DDDIRS_ZENABLE, D3DZB_FALSE });

View File

@ -241,7 +241,7 @@ namespace D3dDdi
const SurfaceRepository::Surface& SurfaceRepository::getTempRenderTarget(DWORD width, DWORD height)
{
return getTempSurface(m_renderTarget, width, height, DDraw::DirectDraw::getRgbPixelFormat(32),
return getTempSurface(m_renderTarget, width, height, getPixelFormat(D3DDDIFMT_A8R8G8B8),
DDSCAPS_3DDEVICE | DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY);
}

View File

@ -92,6 +92,7 @@ namespace DDraw
}
data->restore();
D3dDdi::Device::updateAllConfig();
return DD_OK;
}

View File

@ -221,6 +221,7 @@
<ClInclude Include="Config\Settings\DisplayFilter.h" />
<ClInclude Include="Config\Settings\DisplayResolution.h" />
<ClInclude Include="Config\Settings\RenderColorDepth.h" />
<ClInclude Include="Config\Settings\ResolutionScale.h" />
<ClInclude Include="Config\Settings\SupportedResolutions.h" />
<ClInclude Include="Config\Settings\TextureFilter.h" />
<ClInclude Include="Config\Settings\ThreadPriorityBoost.h" />
@ -340,6 +341,7 @@
<ClCompile Include="Config\Settings\CpuAffinity.cpp" />
<ClCompile Include="Config\Settings\DisplayFilter.cpp" />
<ClCompile Include="Config\Settings\DisplayResolution.cpp" />
<ClCompile Include="Config\Settings\ResolutionScale.cpp" />
<ClCompile Include="Config\Settings\SupportedResolutions.cpp" />
<ClCompile Include="Config\Settings\TextureFilter.cpp" />
<ClCompile Include="D3dDdi\Adapter.cpp" />

View File

@ -507,6 +507,9 @@
<ClInclude Include="DDraw\Comparison.h">
<Filter>Header Files\DDraw</Filter>
</ClInclude>
<ClInclude Include="Config\Settings\ResolutionScale.h">
<Filter>Header Files\Config\Settings</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Gdi\Gdi.cpp">
@ -797,6 +800,9 @@
<ClCompile Include="D3dDdi\Log\AdapterCallbacksLog.cpp">
<Filter>Source Files\D3dDdi\Log</Filter>
</ClCompile>
<ClCompile Include="Config\Settings\ResolutionScale.cpp">
<Filter>Source Files\Config\Settings</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="DDrawCompat.rc">

View File

@ -54,17 +54,6 @@ namespace
switch (uMsg)
{
case WM_ACTIVATEAPP:
if (!wParam)
{
auto configWindow = Gdi::PresentationWindow::getConfigWindow();
if (configWindow)
{
configWindow->setVisible(false);
}
}
break;
case WM_DISPLAYCHANGE:
{
if (0 != wParam)
@ -100,6 +89,18 @@ namespace
switch (uMsg)
{
case WM_ACTIVATEAPP:
if (!wParam)
{
auto configWindow = Gdi::PresentationWindow::getConfigWindow();
if (configWindow)
{
configWindow->setVisible(false);
}
CALL_ORIG_FUNC(ClipCursor)(nullptr);
}
break;
case WM_CTLCOLORSCROLLBAR:
if (reinterpret_cast<HWND>(lParam) != hwnd &&
isUser32ScrollBar(reinterpret_cast<HWND>(lParam)))

View File

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

View File

@ -6,6 +6,24 @@
#include <Overlay/ComboBoxControl.h>
#include <Overlay/SettingControl.h>
namespace
{
std::vector<std::string> getValueStrings(Config::Setting& setting)
{
auto values(setting.getDefaultValueStrings());
const auto currentValue = setting.getValueStr();
for (const auto& value : values)
{
if (Config::Parser::removeParam(value) == Config::Parser::removeParam(currentValue))
{
return values;
}
}
values.push_back(currentValue);
return values;
}
}
namespace Overlay
{
SettingControl::SettingControl(Control& parent, const RECT& rect, Config::Setting& setting)
@ -17,7 +35,7 @@ namespace Overlay
rect.left + SETTING_LABEL_WIDTH + SETTING_CONTROL_WIDTH, rect.bottom - BORDER / 2 };
m_valueControl.reset(new ComboBoxControl(*this, r));
getValueComboBox().setValue(setting.getValueStr());
getValueComboBox().setValues(setting.getDefaultValueStrings());
getValueComboBox().setValues(getValueStrings(setting));
onValueChanged();
updateValuesParam();
}
@ -40,6 +58,7 @@ namespace Overlay
if (&Config::antialiasing == &m_setting ||
&Config::renderColorDepth == &m_setting ||
&Config::resolutionScale == &m_setting ||
&Config::textureFilter == &m_setting)
{
D3dDdi::Device::updateAllConfig();

View File

@ -18,7 +18,7 @@ namespace Overlay
class SettingControl : public Control
{
public:
static const int PARAM_LABEL_WIDTH = 50;
static const int PARAM_LABEL_WIDTH = 70;
static const int PARAM_CONTROL_WIDTH = 151;
static const int SETTING_LABEL_WIDTH = 120;
static const int SETTING_CONTROL_WIDTH = 151;

View File

@ -205,10 +205,10 @@ namespace
g_emulatedDisplayMode.deviceName = getDeviceName(lpszDeviceName);
g_emulatedDisplayMode.rect = getMonitorInfo(g_emulatedDisplayMode.deviceName).rcMonitor;
g_emulatedDisplayMode.rect.right = g_emulatedDisplayMode.rect.left + lpDevMode->dmPelsWidth;
g_emulatedDisplayMode.rect.bottom = g_emulatedDisplayMode.rect.top + lpDevMode->dmPelsHeight;
g_emulatedDisplayMode.diff.cx = lpDevMode->dmPelsWidth - currDevMode.dmPelsWidth;
g_emulatedDisplayMode.diff.cy = lpDevMode->dmPelsHeight - currDevMode.dmPelsHeight;
g_emulatedDisplayMode.rect.right = g_emulatedDisplayMode.rect.left + emulatedResolution.cx;
g_emulatedDisplayMode.rect.bottom = g_emulatedDisplayMode.rect.top + emulatedResolution.cy;
g_emulatedDisplayMode.diff.cx = emulatedResolution.cx - currDevMode.dmPelsWidth;
g_emulatedDisplayMode.diff.cy = emulatedResolution.cy - currDevMode.dmPelsHeight;
}
else
{