mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Added dithered RenderColorDepth values
This commit is contained in:
parent
7019ea18c9
commit
144dab2538
@ -6,11 +6,20 @@ namespace Config
|
|||||||
{
|
{
|
||||||
namespace Settings
|
namespace Settings
|
||||||
{
|
{
|
||||||
class RenderColorDepth : public MappedSetting<unsigned>
|
class RenderColorDepth : public MappedSetting<std::pair<unsigned, unsigned>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RenderColorDepth()
|
RenderColorDepth()
|
||||||
: MappedSetting("RenderColorDepth", "app", { {"app", 0}, {"16", 16}, {"32", 32} })
|
: MappedSetting("RenderColorDepth", "appd8", {
|
||||||
|
{ "app", { 0, 8 } },
|
||||||
|
{ "appd8", { 8, 0 } },
|
||||||
|
{ "appd10", { 10, 0 } },
|
||||||
|
{ "16", { 6, 8 } },
|
||||||
|
{ "16d8", { 8, 6 } },
|
||||||
|
{ "16d10", { 10, 6 } },
|
||||||
|
{ "32", { 8, 8 } },
|
||||||
|
{ "32d10", { 10, 8 } },
|
||||||
|
})
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <Config/Settings/Antialiasing.h>
|
#include <Config/Settings/Antialiasing.h>
|
||||||
#include <Config/Settings/DisplayAspectRatio.h>
|
#include <Config/Settings/DisplayAspectRatio.h>
|
||||||
#include <Config/Settings/PalettizedTextures.h>
|
#include <Config/Settings/PalettizedTextures.h>
|
||||||
|
#include <Config/Settings/RenderColorDepth.h>
|
||||||
#include <Config/Settings/ResolutionScale.h>
|
#include <Config/Settings/ResolutionScale.h>
|
||||||
#include <Config/Settings/SupportedDepthFormats.h>
|
#include <Config/Settings/SupportedDepthFormats.h>
|
||||||
#include <D3dDdi/Adapter.h>
|
#include <D3dDdi/Adapter.h>
|
||||||
@ -226,6 +227,41 @@ namespace D3dDdi
|
|||||||
return { levels.MsType, std::min(static_cast<UINT>(Config::antialiasing.getParam()), levels.QualityLevels - 1) };
|
return { levels.MsType, std::min(static_cast<UINT>(Config::antialiasing.getParam()), levels.QualityLevels - 1) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
D3DDDIFORMAT Adapter::getRenderColorDepthSrcFormat(D3DDDIFORMAT appFormat) const
|
||||||
|
{
|
||||||
|
switch (Config::renderColorDepth.get().first)
|
||||||
|
{
|
||||||
|
case 10:
|
||||||
|
if (isSupportedRttFormat(D3DDDIFMT_A2B10G10R10))
|
||||||
|
{
|
||||||
|
return D3DDDIFMT_A2B10G10R10;
|
||||||
|
}
|
||||||
|
if (isSupportedRttFormat(D3DDDIFMT_A2R10G10B10))
|
||||||
|
{
|
||||||
|
return D3DDDIFMT_A2R10G10B10;
|
||||||
|
}
|
||||||
|
[[fallthrough]];
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
return D3DDDIFMT_X8R8G8B8;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
return D3DDDIFMT_R5G6B5;
|
||||||
|
}
|
||||||
|
|
||||||
|
return appFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3DDDIFORMAT Adapter::getRenderColorDepthDstFormat() const
|
||||||
|
{
|
||||||
|
switch (Config::renderColorDepth.get().second)
|
||||||
|
{
|
||||||
|
case 6: return D3DDDIFMT_R5G6B5;
|
||||||
|
case 8: return D3DDDIFMT_X8R8G8B8;
|
||||||
|
}
|
||||||
|
return 16 == Win32::DisplayMode::getBpp() ? D3DDDIFMT_R5G6B5 : D3DDDIFMT_X8R8G8B8;
|
||||||
|
}
|
||||||
|
|
||||||
SIZE Adapter::getScaledSize(Int2 size) const
|
SIZE Adapter::getScaledSize(Int2 size) const
|
||||||
{
|
{
|
||||||
const auto scaleFactor = getScaleFactor();
|
const auto scaleFactor = getScaleFactor();
|
||||||
@ -349,6 +385,14 @@ namespace D3dDdi
|
|||||||
return it != formatOps.end() && (it->second.Operations & FORMATOP_OFFSCREEN_RENDERTARGET);
|
return it != formatOps.end() && (it->second.Operations & FORMATOP_OFFSCREEN_RENDERTARGET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Adapter::isSupportedRttFormat(D3DDDIFORMAT format) const
|
||||||
|
{
|
||||||
|
auto it = m_info.formatOps.find(format);
|
||||||
|
return it != m_info.formatOps.end() &&
|
||||||
|
(it->second.Format & FORMATOP_OFFSCREEN_RENDERTARGET) &&
|
||||||
|
(it->second.Format & FORMATOP_TEXTURE);
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT Adapter::pfnCloseAdapter()
|
HRESULT Adapter::pfnCloseAdapter()
|
||||||
{
|
{
|
||||||
auto adapter = m_adapter;
|
auto adapter = m_adapter;
|
||||||
|
@ -41,6 +41,8 @@ namespace D3dDdi
|
|||||||
const auto& getMonitorInfo() const { return Win32::DisplayMode::getMonitorInfo(m_deviceName); }
|
const auto& getMonitorInfo() const { return Win32::DisplayMode::getMonitorInfo(m_deviceName); }
|
||||||
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> getMultisampleConfig(D3DDDIFORMAT format) const;
|
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> getMultisampleConfig(D3DDDIFORMAT format) const;
|
||||||
const D3DDDI_ADAPTERFUNCS& getOrigVtable() const { return m_origVtable; }
|
const D3DDDI_ADAPTERFUNCS& getOrigVtable() const { return m_origVtable; }
|
||||||
|
D3DDDIFORMAT getRenderColorDepthSrcFormat(D3DDDIFORMAT appFormat) const;
|
||||||
|
D3DDDIFORMAT getRenderColorDepthDstFormat() const;
|
||||||
CompatWeakPtr<IDirectDraw7> getRepository() const { return m_repository; }
|
CompatWeakPtr<IDirectDraw7> getRepository() const { return m_repository; }
|
||||||
SIZE getScaledSize(Int2 size) const;
|
SIZE getScaledSize(Int2 size) const;
|
||||||
bool isEmulatedRenderTargetFormat(D3DDDIFORMAT format) const;
|
bool isEmulatedRenderTargetFormat(D3DDDIFORMAT format) const;
|
||||||
@ -66,6 +68,7 @@ namespace D3dDdi
|
|||||||
std::string getSupportedMsaaModes(const std::map<D3DDDIFORMAT, FORMATOP>& formatOps) const;
|
std::string getSupportedMsaaModes(const std::map<D3DDDIFORMAT, FORMATOP>& formatOps) const;
|
||||||
DWORD getSupportedZBufferBitDepths(const std::map<D3DDDIFORMAT, FORMATOP>& formatOps) const;
|
DWORD getSupportedZBufferBitDepths(const std::map<D3DDDIFORMAT, FORMATOP>& formatOps) const;
|
||||||
bool isEmulatedRenderTargetFormat(D3DDDIFORMAT format, const std::map<D3DDDIFORMAT, FORMATOP>& formatOps) const;
|
bool isEmulatedRenderTargetFormat(D3DDDIFORMAT format, const std::map<D3DDDIFORMAT, FORMATOP>& formatOps) const;
|
||||||
|
bool isSupportedRttFormat(D3DDDIFORMAT format) const;
|
||||||
|
|
||||||
HANDLE m_adapter;
|
HANDLE m_adapter;
|
||||||
D3DDDI_ADAPTERFUNCS m_origVtable;
|
D3DDDI_ADAPTERFUNCS m_origVtable;
|
||||||
|
@ -48,6 +48,20 @@ namespace D3dDdi
|
|||||||
m_state.m_device, &m_data, &m_state.m_pixelShaderConst[m_data.Register][0]);
|
m_state.m_device, &m_data, &m_state.m_pixelShaderConst[m_data.Register][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeviceState::TempPixelShaderConstB::TempPixelShaderConstB(
|
||||||
|
DeviceState& state, const D3DDDIARG_SETPIXELSHADERCONSTB& data, const BOOL* registers)
|
||||||
|
: m_state(state)
|
||||||
|
, m_data(data)
|
||||||
|
{
|
||||||
|
state.m_device.getOrigVtable().pfnSetPixelShaderConstB(state.m_device, &data, registers);
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceState::TempPixelShaderConstB::~TempPixelShaderConstB()
|
||||||
|
{
|
||||||
|
m_state.m_device.getOrigVtable().pfnSetPixelShaderConstB(
|
||||||
|
m_state.m_device, &m_data, &m_state.m_pixelShaderConstB[m_data.Register][0]);
|
||||||
|
}
|
||||||
|
|
||||||
DeviceState::TempPixelShaderConstI::TempPixelShaderConstI(
|
DeviceState::TempPixelShaderConstI::TempPixelShaderConstI(
|
||||||
DeviceState& state, const D3DDDIARG_SETPIXELSHADERCONSTI& data, const ShaderConstI* registers)
|
DeviceState& state, const D3DDDIARG_SETPIXELSHADERCONSTI& data, const ShaderConstI* registers)
|
||||||
: m_state(state)
|
: m_state(state)
|
||||||
|
@ -15,7 +15,9 @@ const UINT D3DTEXF_NONE = 0;
|
|||||||
const UINT D3DTEXF_POINT = 1;
|
const UINT D3DTEXF_POINT = 1;
|
||||||
const UINT D3DTEXF_LINEAR = 2;
|
const UINT D3DTEXF_LINEAR = 2;
|
||||||
const UINT D3DTEXF_ANISOTROPIC = 3;
|
const UINT D3DTEXF_ANISOTROPIC = 3;
|
||||||
const UINT D3DTEXF_SRGB = 0x10000;
|
const UINT D3DTEXF_SRGBREAD = 0x10000;
|
||||||
|
const UINT D3DTEXF_SRGBWRITE = 0x20000;
|
||||||
|
const UINT D3DTEXF_SRGB = D3DTEXF_SRGBREAD | D3DTEXF_SRGBWRITE;
|
||||||
|
|
||||||
namespace D3dDdi
|
namespace D3dDdi
|
||||||
{
|
{
|
||||||
@ -59,6 +61,17 @@ namespace D3dDdi
|
|||||||
D3DDDIARG_SETPIXELSHADERCONST m_data;
|
D3DDDIARG_SETPIXELSHADERCONST m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TempPixelShaderConstB
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TempPixelShaderConstB(DeviceState& state, const D3DDDIARG_SETPIXELSHADERCONSTB& data, const BOOL* registers);
|
||||||
|
~TempPixelShaderConstB();
|
||||||
|
|
||||||
|
private:
|
||||||
|
DeviceState& m_state;
|
||||||
|
D3DDDIARG_SETPIXELSHADERCONSTB m_data;
|
||||||
|
};
|
||||||
|
|
||||||
class TempPixelShaderConstI
|
class TempPixelShaderConstI
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -109,8 +109,10 @@ namespace
|
|||||||
{ D3DDDIFMT_A8R3G3B2, FormatInfoXARGB(0, 8, 3, 3, 2) },
|
{ D3DDDIFMT_A8R3G3B2, FormatInfoXARGB(0, 8, 3, 3, 2) },
|
||||||
{ D3DDDIFMT_X4R4G4B4, FormatInfoXARGB(4, 0, 4, 4, 4) },
|
{ D3DDDIFMT_X4R4G4B4, FormatInfoXARGB(4, 0, 4, 4, 4) },
|
||||||
|
|
||||||
{ D3DDDIFMT_A8B8G8R8, FormatInfoXABGR(0, 8, 8, 8, 8) },
|
{ D3DDDIFMT_A2B10G10R10, FormatInfoXABGR(0, 2, 10, 10, 10) },
|
||||||
{ D3DDDIFMT_X8B8G8R8, FormatInfoXABGR(8, 0, 8, 8, 8) },
|
{ D3DDDIFMT_A8B8G8R8, FormatInfoXABGR(0, 8, 8, 8, 8) },
|
||||||
|
{ D3DDDIFMT_X8B8G8R8, FormatInfoXABGR(8, 0, 8, 8, 8) },
|
||||||
|
{ D3DDDIFMT_A2R10G10B10, FormatInfoXARGB(0, 2, 10, 10, 10) },
|
||||||
|
|
||||||
{ D3DDDIFMT_A8P8, FormatInfoAP(8, 8) },
|
{ D3DDDIFMT_A8P8, FormatInfoAP(8, 8) },
|
||||||
{ D3DDDIFMT_P8, FormatInfoAP(0, 8) },
|
{ D3DDDIFMT_P8, FormatInfoAP(0, 8) },
|
||||||
@ -141,6 +143,11 @@ namespace
|
|||||||
|
|
||||||
DDPIXELFORMAT getPixelFormat(const D3dDdi::FormatInfo& info)
|
DDPIXELFORMAT getPixelFormat(const D3dDdi::FormatInfo& info)
|
||||||
{
|
{
|
||||||
|
if (info.red.bitCount > 8)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
DDPIXELFORMAT pf = {};
|
DDPIXELFORMAT pf = {};
|
||||||
pf.dwSize = sizeof(pf);
|
pf.dwSize = sizeof(pf);
|
||||||
pf.dwFlags =
|
pf.dwFlags =
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#include <Config/Settings/BltFilter.h>
|
#include <Config/Settings/BltFilter.h>
|
||||||
#include <Config/Settings/ColorKeyMethod.h>
|
#include <Config/Settings/ColorKeyMethod.h>
|
||||||
#include <Config/Settings/DepthFormat.h>
|
#include <Config/Settings/DepthFormat.h>
|
||||||
#include <Config/Settings/RenderColorDepth.h>
|
|
||||||
#include <Config/Settings/ResolutionScaleFilter.h>
|
#include <Config/Settings/ResolutionScaleFilter.h>
|
||||||
#include <D3dDdi/Adapter.h>
|
#include <D3dDdi/Adapter.h>
|
||||||
#include <D3dDdi/Device.h>
|
#include <D3dDdi/Device.h>
|
||||||
@ -529,6 +528,12 @@ namespace D3dDdi
|
|||||||
srcResource, subResourceIndex, getRect(subResourceIndex));
|
srcResource, subResourceIndex, getRect(subResourceIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT Resource::copySubResourceRegion(UINT dstIndex, const RECT& dstRect,
|
||||||
|
HANDLE src, UINT srcIndex, const RECT& srcRect)
|
||||||
|
{
|
||||||
|
return copySubResourceRegion(*this, dstIndex, dstRect, src, srcIndex, srcRect);
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT Resource::copySubResourceRegion(HANDLE dst, UINT dstIndex, const RECT& dstRect,
|
HRESULT Resource::copySubResourceRegion(HANDLE dst, UINT dstIndex, const RECT& dstRect,
|
||||||
HANDLE src, UINT srcIndex, const RECT& srcRect)
|
HANDLE src, UINT srcIndex, const RECT& srcRect)
|
||||||
{
|
{
|
||||||
@ -743,11 +748,7 @@ namespace D3dDdi
|
|||||||
|
|
||||||
if (D3DDDIFMT_X8R8G8B8 == m_fixedData.Format || D3DDDIFMT_R5G6B5 == m_fixedData.Format)
|
if (D3DDDIFMT_X8R8G8B8 == m_fixedData.Format || D3DDDIFMT_R5G6B5 == m_fixedData.Format)
|
||||||
{
|
{
|
||||||
switch (Config::renderColorDepth.get())
|
return m_device.getAdapter().getRenderColorDepthSrcFormat(m_fixedData.Format);
|
||||||
{
|
|
||||||
case 16: return D3DDDIFMT_R5G6B5;
|
|
||||||
case 32: return D3DDDIFMT_X8R8G8B8;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (m_fixedData.Flags.ZBuffer && Config::Settings::DepthFormat::APP != Config::depthFormat.get() &&
|
else if (m_fixedData.Flags.ZBuffer && Config::Settings::DepthFormat::APP != Config::depthFormat.get() &&
|
||||||
getFormatInfo(m_fixedData.Format).depth.bitCount != Config::depthFormat.get())
|
getFormatInfo(m_fixedData.Format).depth.bitCount != Config::depthFormat.get())
|
||||||
@ -1212,7 +1213,7 @@ namespace D3dDdi
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto& repo = m_device.getRepo();
|
auto& repo = m_device.getRepo();
|
||||||
const auto& rtSurface = repo.getNextRenderTarget(srcWidth, srcHeight);
|
const auto& rtSurface = repo.getNextRenderTarget(srcWidth, srcHeight, srcResource->m_fixedData.Format);
|
||||||
auto rt = rtSurface.resource ? rtSurface.resource : this;
|
auto rt = rtSurface.resource ? rtSurface.resource : this;
|
||||||
auto rtIndex = rtSurface.resource ? 0 : data.DstSubResourceIndex;
|
auto rtIndex = rtSurface.resource ? 0 : data.DstSubResourceIndex;
|
||||||
auto rtRect = rtSurface.resource ? data.SrcRect : data.DstRect;
|
auto rtRect = rtSurface.resource ? data.SrcRect : data.DstRect;
|
||||||
@ -1259,15 +1260,12 @@ namespace D3dDdi
|
|||||||
m_device.getShaderBlitter().cursorBlt(*rt, rtIndex, rtRect, cursorInfo.hCursor, cursorInfo.ptScreenPos);
|
m_device.getShaderBlitter().cursorBlt(*rt, rtIndex, rtRect, cursorInfo.hCursor, cursorInfo.ptScreenPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rtSurface.resource)
|
if (rtSurface.resource)
|
||||||
{
|
{
|
||||||
return LOG_RESULT(S_OK);
|
m_device.getShaderBlitter().displayBlt(*this, data.DstSubResourceIndex, data.DstRect, *rt, 0, data.SrcRect);
|
||||||
|
clearRectExterior(data.DstSubResourceIndex, data.DstRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_device.getShaderBlitter().displayBlt(*this, data.DstSubResourceIndex, data.DstRect, *rt, 0, data.SrcRect);
|
|
||||||
|
|
||||||
clearRectExterior(data.DstSubResourceIndex, data.DstRect);
|
|
||||||
|
|
||||||
if (!IsRectEmpty(&g_presentationRect))
|
if (!IsRectEmpty(&g_presentationRect))
|
||||||
{
|
{
|
||||||
presentLayeredWindows(*this, data.DstSubResourceIndex, getRect(data.DstSubResourceIndex),
|
presentLayeredWindows(*this, data.DstSubResourceIndex, getRect(data.DstSubResourceIndex),
|
||||||
@ -1468,7 +1466,7 @@ namespace D3dDdi
|
|||||||
|
|
||||||
if (!srcResource.m_fixedData.Flags.Texture ||
|
if (!srcResource.m_fixedData.Flags.Texture ||
|
||||||
D3DDDIPOOL_SYSTEMMEM == srcResource.m_fixedData.Pool ||
|
D3DDDIPOOL_SYSTEMMEM == srcResource.m_fixedData.Pool ||
|
||||||
(filter & D3DTEXF_SRGB) && !(srcResource.m_formatOp.Operations & FORMATOP_SRGBREAD))
|
(filter & D3DTEXF_SRGBREAD) && !(srcResource.m_formatOp.Operations & FORMATOP_SRGBREAD))
|
||||||
{
|
{
|
||||||
DWORD width = data.SrcRect.right - data.SrcRect.left;
|
DWORD width = data.SrcRect.right - data.SrcRect.left;
|
||||||
DWORD height = data.SrcRect.bottom - data.SrcRect.top;
|
DWORD height = data.SrcRect.bottom - data.SrcRect.top;
|
||||||
@ -1498,11 +1496,11 @@ namespace D3dDdi
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!dstResource.m_fixedData.Flags.RenderTarget && !dstResource.m_fixedData.Flags.ZBuffer ||
|
if (!dstResource.m_fixedData.Flags.RenderTarget && !dstResource.m_fixedData.Flags.ZBuffer ||
|
||||||
(filter & D3DTEXF_SRGB) && !(dstResource.m_formatOp.Operations & FORMATOP_SRGBWRITE))
|
(filter & D3DTEXF_SRGBWRITE) && !(dstResource.m_formatOp.Operations & FORMATOP_SRGBWRITE))
|
||||||
{
|
{
|
||||||
LONG width = data.DstRect.right - data.DstRect.left;
|
LONG width = data.DstRect.right - data.DstRect.left;
|
||||||
LONG height = data.DstRect.bottom - data.DstRect.top;
|
LONG height = data.DstRect.bottom - data.DstRect.top;
|
||||||
auto& rt = repo.getNextRenderTarget(width, height, srcRes);
|
auto& rt = repo.getNextRenderTarget(width, height, D3DDDIFMT_X8R8G8B8, srcRes);
|
||||||
if (!rt.resource)
|
if (!rt.resource)
|
||||||
{
|
{
|
||||||
return LOG_RESULT(E_OUTOFMEMORY);
|
return LOG_RESULT(E_OUTOFMEMORY);
|
||||||
|
@ -39,6 +39,8 @@ namespace D3dDdi
|
|||||||
|
|
||||||
HRESULT blt(D3DDDIARG_BLT data);
|
HRESULT blt(D3DDDIARG_BLT data);
|
||||||
HRESULT colorFill(D3DDDIARG_COLORFILL data);
|
HRESULT colorFill(D3DDDIARG_COLORFILL data);
|
||||||
|
HRESULT copySubResourceRegion(UINT dstIndex, const RECT& dstRect,
|
||||||
|
HANDLE src, UINT srcIndex, const RECT& srcRect);
|
||||||
void disableClamp();
|
void disableClamp();
|
||||||
void* getLockPtr(UINT subResourceIndex);
|
void* getLockPtr(UINT subResourceIndex);
|
||||||
RECT getRect(UINT subResourceIndex) const;
|
RECT getRect(UINT subResourceIndex) const;
|
||||||
|
@ -15,11 +15,11 @@
|
|||||||
#include <Shaders/CubicConvolution4.h>
|
#include <Shaders/CubicConvolution4.h>
|
||||||
#include <Shaders/DepthBlt.h>
|
#include <Shaders/DepthBlt.h>
|
||||||
#include <Shaders/DrawCursor.h>
|
#include <Shaders/DrawCursor.h>
|
||||||
#include <Shaders/Gamma.h>
|
|
||||||
#include <Shaders/Lanczos.h>
|
#include <Shaders/Lanczos.h>
|
||||||
#include <Shaders/LockRef.h>
|
#include <Shaders/LockRef.h>
|
||||||
#include <Shaders/PaletteLookup.h>
|
#include <Shaders/PaletteLookup.h>
|
||||||
#include <Shaders/Point.h>
|
#include <Shaders/Point.h>
|
||||||
|
#include <Shaders/PointNoFilter.h>
|
||||||
#include <Shaders/TextureSampler.h>
|
#include <Shaders/TextureSampler.h>
|
||||||
|
|
||||||
#define CONCAT_(a, b) a##b
|
#define CONCAT_(a, b) a##b
|
||||||
@ -28,6 +28,10 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
const UINT CF_HORIZONTAL = 1;
|
||||||
|
const UINT CF_GAMMARAMP = 2;
|
||||||
|
const UINT CF_DITHERING = 4;
|
||||||
|
|
||||||
D3DDDI_GAMMA_RAMP_RGB256x3x16 g_gammaRamp;
|
D3DDDI_GAMMA_RAMP_RGB256x3x16 g_gammaRamp;
|
||||||
bool g_isGammaRampDefault = true;
|
bool g_isGammaRampDefault = true;
|
||||||
bool g_isGammaRampInvalidated = false;
|
bool g_isGammaRampInvalidated = false;
|
||||||
@ -83,11 +87,11 @@ namespace D3dDdi
|
|||||||
}
|
}
|
||||||
, m_psDepthBlt(createPixelShader(g_psDepthBlt))
|
, m_psDepthBlt(createPixelShader(g_psDepthBlt))
|
||||||
, m_psDrawCursor(createPixelShader(g_psDrawCursor))
|
, m_psDrawCursor(createPixelShader(g_psDrawCursor))
|
||||||
, m_psGamma(createPixelShader(g_psGamma))
|
|
||||||
, m_psLanczos(createPixelShader(g_psLanczos))
|
, m_psLanczos(createPixelShader(g_psLanczos))
|
||||||
, m_psLockRef(createPixelShader(g_psLockRef))
|
, m_psLockRef(createPixelShader(g_psLockRef))
|
||||||
, m_psPaletteLookup(createPixelShader(g_psPaletteLookup))
|
, m_psPaletteLookup(createPixelShader(g_psPaletteLookup))
|
||||||
, m_psPoint(createPixelShader(g_psPoint))
|
, m_psPoint(createPixelShader(g_psPoint))
|
||||||
|
, m_psPointNoFilter(createPixelShader(g_psPointNoFilter))
|
||||||
, m_psTextureSampler(createPixelShader(g_psTextureSampler))
|
, m_psTextureSampler(createPixelShader(g_psTextureSampler))
|
||||||
, m_vertexShaderDecl(createVertexShaderDecl())
|
, m_vertexShaderDecl(createVertexShaderDecl())
|
||||||
, m_convolutionParams{}
|
, m_convolutionParams{}
|
||||||
@ -160,9 +164,13 @@ namespace D3dDdi
|
|||||||
const auto& srcSurface = srcResource.getFixedDesc().pSurfList[srcSubResourceIndex];
|
const auto& srcSurface = srcResource.getFixedDesc().pSurfList[srcSubResourceIndex];
|
||||||
const auto& dstSurface = dstResource.getFixedDesc().pSurfList[dstSubResourceIndex];
|
const auto& dstSurface = dstResource.getFixedDesc().pSurfList[dstSubResourceIndex];
|
||||||
|
|
||||||
const bool srgb = (filter & D3DTEXF_SRGB) &&
|
bool srgbRead = (filter & D3DTEXF_SRGBREAD) && (srcResource.getFormatOp().Operations & FORMATOP_SRGBREAD);
|
||||||
(srcResource.getFormatOp().Operations & FORMATOP_SRGBREAD) &&
|
bool srgbWrite = (filter & D3DTEXF_SRGBWRITE) && (dstResource.getFormatOp().Operations & FORMATOP_SRGBWRITE);
|
||||||
(dstResource.getFormatOp().Operations & FORMATOP_SRGBWRITE);
|
if (D3DTEXF_SRGB == HIWORD(filter) && (!srgbRead || !srgbWrite))
|
||||||
|
{
|
||||||
|
srgbRead = false;
|
||||||
|
srgbWrite = false;
|
||||||
|
}
|
||||||
|
|
||||||
auto& state = m_device.getState();
|
auto& state = m_device.getState();
|
||||||
state.setSpriteMode(false);
|
state.setSpriteMode(false);
|
||||||
@ -189,7 +197,7 @@ namespace D3dDdi
|
|||||||
state.setTempRenderState({ D3DDDIRS_MULTISAMPLEANTIALIAS, FALSE });
|
state.setTempRenderState({ D3DDDIRS_MULTISAMPLEANTIALIAS, FALSE });
|
||||||
state.setTempRenderState({ D3DDDIRS_COLORWRITEENABLE, 0xF });
|
state.setTempRenderState({ D3DDDIRS_COLORWRITEENABLE, 0xF });
|
||||||
state.setTempRenderState({ D3DDDIRS_SCISSORTESTENABLE, FALSE });
|
state.setTempRenderState({ D3DDDIRS_SCISSORTESTENABLE, FALSE });
|
||||||
state.setTempRenderState({ D3DDDIRS_SRGBWRITEENABLE, srgb });
|
state.setTempRenderState({ D3DDDIRS_SRGBWRITEENABLE, srgbWrite });
|
||||||
|
|
||||||
if (alpha)
|
if (alpha)
|
||||||
{
|
{
|
||||||
@ -209,8 +217,7 @@ namespace D3dDdi
|
|||||||
state.setTempRenderState({ D3DDDIRS_DESTBLEND, D3DBLEND_INVSRCALPHA });
|
state.setTempRenderState({ D3DDDIRS_DESTBLEND, D3DBLEND_INVSRCALPHA });
|
||||||
}
|
}
|
||||||
|
|
||||||
setTempTextureStage(0, srcResource, srcRect, LOWORD(filter));
|
setTempTextureStage(0, srcResource, srcRect, LOWORD(filter) | (srgbRead ? D3DTEXF_SRGBREAD : 0));
|
||||||
state.setTempTextureStageState({ 0, D3DDDITSS_SRGBTEXTURE, srgb });
|
|
||||||
|
|
||||||
state.setTempStreamSourceUm({ 0, sizeof(Vertex) }, m_vertices.data());
|
state.setTempStreamSourceUm({ 0, sizeof(Vertex) }, m_vertices.data());
|
||||||
|
|
||||||
@ -246,18 +253,18 @@ namespace D3dDdi
|
|||||||
|
|
||||||
void ShaderBlitter::convolution(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
void ShaderBlitter::convolution(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
|
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
|
||||||
bool isHorizontal, Float2 support, HANDLE pixelShader,
|
Float2 support, HANDLE pixelShader, const std::function<void(bool)> setExtraParams, DWORD flags)
|
||||||
const std::function<void(bool)> setExtraParams)
|
|
||||||
{
|
{
|
||||||
LOG_FUNC("ShaderBlitter::convolution", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
|
LOG_FUNC("ShaderBlitter::convolution", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
|
||||||
static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect,
|
static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect,
|
||||||
isHorizontal, support, pixelShader, static_cast<bool>(setExtraParams));
|
support, pixelShader, static_cast<bool>(setExtraParams), flags);
|
||||||
|
|
||||||
const auto& srcDesc = srcResource.getFixedDesc().pSurfList[0];
|
const auto& srcDesc = srcResource.getFixedDesc().pSurfList[0];
|
||||||
const Float2 dstSize(dstRect.right - dstRect.left, dstRect.bottom - dstRect.top);
|
const Float2 dstSize(dstRect.right - dstRect.left, dstRect.bottom - dstRect.top);
|
||||||
const Float2 srcSize(srcRect.right - srcRect.left, srcRect.bottom - srcRect.top);
|
const Float2 srcSize(srcRect.right - srcRect.left, srcRect.bottom - srcRect.top);
|
||||||
const Float2 scale = dstSize / srcSize;
|
const Float2 scale = dstSize / srcSize;
|
||||||
|
|
||||||
|
const bool isHorizontal = flags & CF_HORIZONTAL;
|
||||||
const bool isDual = srcSize.x != dstSize.x && srcSize.y != dstSize.y;
|
const bool isDual = srcSize.x != dstSize.x && srcSize.y != dstSize.y;
|
||||||
const Float2 compMaskPri = isHorizontal ? Float2(1, 0) : Float2(0, 1);
|
const Float2 compMaskPri = isHorizontal ? Float2(1, 0) : Float2(0, 1);
|
||||||
const Float2 compMaskSec = isHorizontal ? Float2(0, 1) : Float2(1, 0);
|
const Float2 compMaskSec = isHorizontal ? Float2(0, 1) : Float2(1, 0);
|
||||||
@ -291,14 +298,43 @@ namespace D3dDdi
|
|||||||
setExtraParams(isHorizontal);
|
setExtraParams(isHorizontal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct BoolParams
|
||||||
|
{
|
||||||
|
BOOL useSrgbRead;
|
||||||
|
BOOL useSrgbReadNeg;
|
||||||
|
BOOL useSrgbWrite;
|
||||||
|
BOOL useGammaRamp;
|
||||||
|
BOOL useDithering;
|
||||||
|
};
|
||||||
|
|
||||||
|
BoolParams boolParams = {};
|
||||||
|
boolParams.useSrgbRead = !(srcResource.getFormatOp().Operations & FORMATOP_SRGBREAD);
|
||||||
|
boolParams.useSrgbReadNeg = !boolParams.useSrgbRead;
|
||||||
|
boolParams.useSrgbWrite = (flags & (CF_GAMMARAMP | CF_DITHERING)) ||
|
||||||
|
!(dstResource.getFormatOp().Operations & FORMATOP_SRGBWRITE);
|
||||||
|
boolParams.useGammaRamp = flags & CF_GAMMARAMP;
|
||||||
|
boolParams.useDithering = flags & CF_DITHERING;
|
||||||
|
|
||||||
|
DeviceState::TempPixelShaderConstB tempPsConstB(m_device.getState(), { 0, 5 }, &boolParams.useSrgbRead);
|
||||||
|
|
||||||
const DeviceState::ShaderConstI reg = { dot(sampleCountHalf - 1, Int2(compMaskPri)) };
|
const DeviceState::ShaderConstI reg = { dot(sampleCountHalf - 1, Int2(compMaskPri)) };
|
||||||
DeviceState::TempPixelShaderConstI tempPsConstI(m_device.getState(), { 0, 1 }, ®);
|
DeviceState::TempPixelShaderConstI tempPsConstI(m_device.getState(), { 0, 1 }, ®);
|
||||||
|
|
||||||
DeviceState::TempPixelShaderConst tempPsConst(m_device.getState(),
|
DeviceState::TempPixelShaderConst tempPsConst(m_device.getState(),
|
||||||
{ 0, sizeof(m_convolutionParams) / sizeof(DeviceState::ShaderConstF) },
|
{ 0, sizeof(m_convolutionParams) / sizeof(DeviceState::ShaderConstF) },
|
||||||
reinterpret_cast<DeviceState::ShaderConstF*>(&m_convolutionParams));
|
reinterpret_cast<DeviceState::ShaderConstF*>(&m_convolutionParams));
|
||||||
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
|
|
||||||
pixelShader, (p.support <= 1 ? D3DTEXF_LINEAR : D3DTEXF_POINT) | D3DTEXF_SRGB);
|
UINT filter = (p.support <= 1 && !boolParams.useSrgbRead) ? D3DTEXF_LINEAR : D3DTEXF_POINT;
|
||||||
|
if (!boolParams.useSrgbRead && 0 != support.x)
|
||||||
|
{
|
||||||
|
filter |= D3DTEXF_SRGBREAD;
|
||||||
|
}
|
||||||
|
if (!boolParams.useSrgbWrite && 0 != support.x)
|
||||||
|
{
|
||||||
|
filter |= D3DTEXF_SRGBWRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect, pixelShader, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderBlitter::convolutionBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
void ShaderBlitter::convolutionBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||||
@ -315,15 +351,84 @@ namespace D3dDdi
|
|||||||
const Float2 kernelCoordStep = min(scale, 1.0f);
|
const Float2 kernelCoordStep = min(scale, 1.0f);
|
||||||
const Float2 sampleCountHalf = support / kernelCoordStep;
|
const Float2 sampleCountHalf = support / kernelCoordStep;
|
||||||
|
|
||||||
if (srcSize.y == dstSize.y || sampleCountHalf.y <= 1)
|
DWORD flags = 0;
|
||||||
|
Resource* gammaRampTexture = nullptr;
|
||||||
|
if (!g_isGammaRampDefault && nullptr != (gammaRampTexture = m_device.getRepo().getGammaRampTexture()))
|
||||||
{
|
{
|
||||||
return convolution(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
|
flags |= CF_GAMMARAMP;
|
||||||
true, support, pixelShader, setExtraParams);
|
|
||||||
}
|
}
|
||||||
else if (srcSize.x == dstSize.x || sampleCountHalf.x <= 1)
|
|
||||||
|
const auto& dstFi = getFormatInfo(m_device.getAdapter().getRenderColorDepthDstFormat());
|
||||||
|
const auto& srcFi = getFormatInfo(srcResource.getFixedDesc().Format);
|
||||||
|
BYTE maxBpcDiff = 0;
|
||||||
|
maxBpcDiff = std::max<BYTE>(maxBpcDiff, srcFi.red.bitCount - dstFi.red.bitCount);
|
||||||
|
maxBpcDiff = std::max<BYTE>(maxBpcDiff, srcFi.green.bitCount - dstFi.green.bitCount);
|
||||||
|
maxBpcDiff = std::max<BYTE>(maxBpcDiff, srcFi.blue.bitCount - dstFi.blue.bitCount);
|
||||||
|
|
||||||
|
Resource* ditherTexture = nullptr;
|
||||||
|
DWORD ditherSize = std::min(1 << maxBpcDiff, 16);
|
||||||
|
if (0 != maxBpcDiff && nullptr != (ditherTexture = m_device.getRepo().getDitherTexture(ditherSize)))
|
||||||
|
{
|
||||||
|
flags |= CF_DITHERING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & CF_GAMMARAMP) && g_isGammaRampInvalidated)
|
||||||
|
{
|
||||||
|
D3DDDIARG_LOCK lock = {};
|
||||||
|
lock.hResource = *gammaRampTexture;
|
||||||
|
lock.Flags.Discard = 1;
|
||||||
|
m_device.getOrigVtable().pfnLock(m_device, &lock);
|
||||||
|
if (lock.pSurfData)
|
||||||
|
{
|
||||||
|
auto ptr = static_cast<BYTE*>(lock.pSurfData);
|
||||||
|
setGammaValues(ptr, g_gammaRamp.Red);
|
||||||
|
setGammaValues(ptr + lock.Pitch, g_gammaRamp.Green);
|
||||||
|
setGammaValues(ptr + 2 * lock.Pitch, g_gammaRamp.Blue);
|
||||||
|
|
||||||
|
D3DDDIARG_UNLOCK unlock = {};
|
||||||
|
unlock.hResource = *gammaRampTexture;
|
||||||
|
m_device.getOrigVtable().pfnUnlock(m_device, &unlock);
|
||||||
|
g_isGammaRampInvalidated = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
flags &= ~CF_GAMMARAMP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & CF_GAMMARAMP)
|
||||||
|
{
|
||||||
|
setTempTextureStage(1, *gammaRampTexture, srcRect, D3DTEXF_LINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & CF_DITHERING)
|
||||||
|
{
|
||||||
|
setTempTextureStage(2, *ditherTexture, dstRect, D3DTEXF_POINT, D3DTADDRESS_WRAP);
|
||||||
|
m_convolutionParams.maxRgb[0] = static_cast<float>(1 << dstFi.red.bitCount) - 1;
|
||||||
|
m_convolutionParams.maxRgb[1] = static_cast<float>(1 << dstFi.green.bitCount) - 1;
|
||||||
|
m_convolutionParams.maxRgb[2] = static_cast<float>(1 << dstFi.blue.bitCount) - 1;
|
||||||
|
for (unsigned i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
m_convolutionParams.maxRgbRcp[i] = 1.0f / m_convolutionParams.maxRgb[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
const float d = static_cast<float>(ditherSize * ditherSize);
|
||||||
|
m_convolutionParams.ditherScale = (d - 1) / d;
|
||||||
|
m_convolutionParams.ditherOffset = 0.5f / d;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srcSize.y == dstSize.y ||
|
||||||
|
0 == support.y ||
|
||||||
|
sampleCountHalf.y <= 1 && (srcResource.getFormatOp().Operations & FORMATOP_SRGBREAD))
|
||||||
{
|
{
|
||||||
return convolution(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
|
return convolution(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
|
||||||
false, support, pixelShader, setExtraParams);
|
support, pixelShader, setExtraParams, flags | CF_HORIZONTAL);
|
||||||
|
}
|
||||||
|
if (srcSize.x == dstSize.x ||
|
||||||
|
sampleCountHalf.x <= 1 && (srcResource.getFormatOp().Operations & FORMATOP_SRGBREAD))
|
||||||
|
{
|
||||||
|
return convolution(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
|
||||||
|
support, pixelShader, setExtraParams, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool isHorizontalFirst = dstSize.x * srcSize.y <= srcSize.x * dstSize.y;
|
const bool isHorizontalFirst = dstSize.x * srcSize.y <= srcSize.x * dstSize.y;
|
||||||
@ -337,16 +442,17 @@ namespace D3dDdi
|
|||||||
rect.bottom = dstSize.y;
|
rect.bottom = dstSize.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto rt = m_device.getRepo().getNextRenderTarget(rect.right, rect.bottom, &srcResource, &dstResource).resource;
|
auto rt = m_device.getRepo().getNextRenderTarget(rect.right, rect.bottom,
|
||||||
|
srcResource.getFixedDesc().Format, &srcResource, &dstResource).resource;
|
||||||
if (!rt)
|
if (!rt)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
convolution(*rt, 0, rect, srcResource, srcSubResourceIndex, srcRect,
|
convolution(*rt, 0, rect, srcResource, srcSubResourceIndex, srcRect,
|
||||||
isHorizontalFirst, support, pixelShader, setExtraParams);
|
support, pixelShader, setExtraParams, isHorizontalFirst ? CF_HORIZONTAL : 0);
|
||||||
convolution(dstResource, dstSubResourceIndex, dstRect, *rt, 0, rect,
|
convolution(dstResource, dstSubResourceIndex, dstRect, *rt, 0, rect,
|
||||||
!isHorizontalFirst, support, pixelShader, setExtraParams);
|
support, pixelShader, setExtraParams, flags | (isHorizontalFirst ? 0 : CF_HORIZONTAL));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<void, ResourceDeleter> ShaderBlitter::createPixelShader(const BYTE* code, UINT size)
|
std::unique_ptr<void, ResourceDeleter> ShaderBlitter::createPixelShader(const BYTE* code, UINT size)
|
||||||
@ -427,14 +533,7 @@ namespace D3dDdi
|
|||||||
|
|
||||||
if (cur.maskTexture)
|
if (cur.maskTexture)
|
||||||
{
|
{
|
||||||
D3DDDIARG_BLT data = {};
|
cur.tempTexture->copySubResourceRegion(0, clippedSrcRect, dstResource, dstSubResourceIndex, clippedDstRect);
|
||||||
data.hSrcResource = dstResource;
|
|
||||||
data.SrcSubResourceIndex = dstSubResourceIndex;
|
|
||||||
data.SrcRect = clippedDstRect;
|
|
||||||
data.hDstResource = *cur.tempTexture;
|
|
||||||
data.DstRect = clippedSrcRect;
|
|
||||||
m_device.getOrigVtable().pfnBlt(m_device, &data);
|
|
||||||
|
|
||||||
setTempTextureStage(1, *cur.maskTexture, clippedSrcRect, D3DTEXF_POINT);
|
setTempTextureStage(1, *cur.maskTexture, clippedSrcRect, D3DTEXF_POINT);
|
||||||
setTempTextureStage(2, *cur.colorTexture, clippedSrcRect, D3DTEXF_POINT);
|
setTempTextureStage(2, *cur.colorTexture, clippedSrcRect, D3DTEXF_POINT);
|
||||||
setTempTextureStage(3, *xorTexture, clippedSrcRect, D3DTEXF_POINT);
|
setTempTextureStage(3, *xorTexture, clippedSrcRect, D3DTEXF_POINT);
|
||||||
@ -493,75 +592,42 @@ namespace D3dDdi
|
|||||||
m_device.flushPrimitives();
|
m_device.flushPrimitives();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderBlitter::displayBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
void ShaderBlitter::displayBlt(Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect)
|
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect)
|
||||||
{
|
{
|
||||||
auto& repo = m_device.getRepo();
|
auto filter = Config::displayFilter.get();
|
||||||
const bool useGamma = !g_isGammaRampDefault && repo.getGammaRampTexture();
|
|
||||||
|
|
||||||
if (Rect::isEqualSize(dstRect, srcRect))
|
if (Rect::isEqualSize(dstRect, srcRect))
|
||||||
{
|
{
|
||||||
if (useGamma)
|
filter = Config::Settings::DisplayFilter::POINT;
|
||||||
{
|
|
||||||
gammaBlt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
D3DDDIARG_BLT data = {};
|
|
||||||
data.hSrcResource = srcResource;
|
|
||||||
data.SrcSubResourceIndex = srcSubResourceIndex;
|
|
||||||
data.SrcRect = srcRect;
|
|
||||||
data.hDstResource = dstResource;
|
|
||||||
data.DstSubResourceIndex = dstSubResourceIndex;
|
|
||||||
data.DstRect = dstRect;
|
|
||||||
data.Flags.Point = 1;
|
|
||||||
m_device.getOrigVtable().pfnBlt(m_device, &data);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RECT r = { 0, 0, dstRect.right - dstRect.left, dstRect.bottom - dstRect.top };
|
switch (filter)
|
||||||
Resource* rtGamma = nullptr;
|
|
||||||
if (useGamma)
|
|
||||||
{
|
|
||||||
rtGamma = repo.getNextRenderTarget(r.right, r.bottom, &srcResource).resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& rt = rtGamma ? *rtGamma : dstResource;
|
|
||||||
const auto rtIndex = rtGamma ? 0 : dstSubResourceIndex;
|
|
||||||
const auto& rtRect = rtGamma ? r : dstRect;
|
|
||||||
|
|
||||||
switch (Config::displayFilter.get())
|
|
||||||
{
|
{
|
||||||
case Config::Settings::DisplayFilter::POINT:
|
case Config::Settings::DisplayFilter::POINT:
|
||||||
m_device.getShaderBlitter().pointBlt(rt, rtIndex, rtRect,
|
m_device.getShaderBlitter().pointBlt(dstResource, dstSubResourceIndex, dstRect,
|
||||||
srcResource, srcSubResourceIndex, srcRect);
|
srcResource, srcSubResourceIndex, srcRect);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Config::Settings::DisplayFilter::BILINEAR:
|
case Config::Settings::DisplayFilter::BILINEAR:
|
||||||
m_device.getShaderBlitter().bilinearBlt(rt, rtIndex, rtRect,
|
m_device.getShaderBlitter().bilinearBlt(dstResource, dstSubResourceIndex, dstRect,
|
||||||
srcResource, srcSubResourceIndex, srcRect, Config::displayFilter.getParam());
|
srcResource, srcSubResourceIndex, srcRect, Config::displayFilter.getParam());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Config::Settings::DisplayFilter::BICUBIC:
|
case Config::Settings::DisplayFilter::BICUBIC:
|
||||||
m_device.getShaderBlitter().bicubicBlt(rt, rtIndex, rtRect,
|
m_device.getShaderBlitter().bicubicBlt(dstResource, dstSubResourceIndex, dstRect,
|
||||||
srcResource, srcSubResourceIndex, srcRect, Config::displayFilter.getParam());
|
srcResource, srcSubResourceIndex, srcRect, Config::displayFilter.getParam());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Config::Settings::DisplayFilter::LANCZOS:
|
case Config::Settings::DisplayFilter::LANCZOS:
|
||||||
m_device.getShaderBlitter().lanczosBlt(rt, rtIndex, rtRect,
|
m_device.getShaderBlitter().lanczosBlt(dstResource, dstSubResourceIndex, dstRect,
|
||||||
srcResource, srcSubResourceIndex, srcRect, Config::displayFilter.getParam());
|
srcResource, srcSubResourceIndex, srcRect, Config::displayFilter.getParam());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Config::Settings::DisplayFilter::SPLINE:
|
case Config::Settings::DisplayFilter::SPLINE:
|
||||||
m_device.getShaderBlitter().splineBlt(rt, rtIndex, rtRect,
|
m_device.getShaderBlitter().splineBlt(dstResource, dstSubResourceIndex, dstRect,
|
||||||
srcResource, srcSubResourceIndex, srcRect, Config::displayFilter.getParam());
|
srcResource, srcSubResourceIndex, srcRect, Config::displayFilter.getParam());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rtGamma)
|
|
||||||
{
|
|
||||||
gammaBlt(dstResource, dstSubResourceIndex, dstRect, rt, rtIndex, rtRect);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderBlitter::drawRect(const RECT& srcRect, const RectF& dstRect, UINT srcWidth, UINT srcHeight)
|
void ShaderBlitter::drawRect(const RECT& srcRect, const RectF& dstRect, UINT srcWidth, UINT srcHeight)
|
||||||
@ -580,44 +646,6 @@ namespace D3dDdi
|
|||||||
m_device.pfnDrawPrimitive(&dp, nullptr);
|
m_device.pfnDrawPrimitive(&dp, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderBlitter::gammaBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
|
||||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect)
|
|
||||||
{
|
|
||||||
LOG_FUNC("ShaderBlitter::gammaBlt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
|
|
||||||
static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect);
|
|
||||||
|
|
||||||
auto gammaRampTexture(m_device.getRepo().getGammaRampTexture());
|
|
||||||
if (!gammaRampTexture)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_isGammaRampInvalidated)
|
|
||||||
{
|
|
||||||
D3DDDIARG_LOCK lock = {};
|
|
||||||
lock.hResource = *gammaRampTexture;
|
|
||||||
lock.Flags.Discard = 1;
|
|
||||||
m_device.getOrigVtable().pfnLock(m_device, &lock);
|
|
||||||
if (!lock.pSurfData)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ptr = static_cast<BYTE*>(lock.pSurfData);
|
|
||||||
setGammaValues(ptr, g_gammaRamp.Red);
|
|
||||||
setGammaValues(ptr + lock.Pitch, g_gammaRamp.Green);
|
|
||||||
setGammaValues(ptr + 2 * lock.Pitch, g_gammaRamp.Blue);
|
|
||||||
|
|
||||||
D3DDDIARG_UNLOCK unlock = {};
|
|
||||||
unlock.hResource = *gammaRampTexture;
|
|
||||||
m_device.getOrigVtable().pfnUnlock(m_device, &unlock);
|
|
||||||
g_isGammaRampInvalidated = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
setTempTextureStage(1, *gammaRampTexture, srcRect, D3DTEXF_POINT);
|
|
||||||
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, 0, srcRect, m_psGamma.get(), D3DTEXF_POINT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShaderBlitter::lanczosBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
void ShaderBlitter::lanczosBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, UINT lobes)
|
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, UINT lobes)
|
||||||
{
|
{
|
||||||
@ -680,8 +708,18 @@ namespace D3dDdi
|
|||||||
LOG_FUNC("ShaderBlitter::pointBlt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
|
LOG_FUNC("ShaderBlitter::pointBlt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
|
||||||
static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect);
|
static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect);
|
||||||
|
|
||||||
convolutionBlt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
|
auto dstSize = Rect::getSize(dstRect);
|
||||||
0.5f, m_psPoint.get());
|
auto srcSize = Rect::getSize(srcRect);
|
||||||
|
if (dstSize.cx >= srcSize.cx && dstSize.cy >= srcSize.cy)
|
||||||
|
{
|
||||||
|
convolutionBlt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
|
||||||
|
0.0f, m_psPointNoFilter.get());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
convolutionBlt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
|
||||||
|
0.5f, m_psPoint.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderBlitter::resetGammaRamp()
|
void ShaderBlitter::resetGammaRamp()
|
||||||
@ -701,16 +739,18 @@ namespace D3dDdi
|
|||||||
g_isGammaRampInvalidated = !g_isGammaRampDefault;
|
g_isGammaRampInvalidated = !g_isGammaRampDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderBlitter::setTempTextureStage(UINT stage, const Resource& texture, const RECT& rect, UINT filter)
|
void ShaderBlitter::setTempTextureStage(UINT stage, const Resource& texture, const RECT& rect, UINT filter,
|
||||||
|
UINT textureAddress)
|
||||||
{
|
{
|
||||||
auto& state = m_device.getState();
|
auto& state = m_device.getState();
|
||||||
state.setTempTexture(stage, texture);
|
state.setTempTexture(stage, texture);
|
||||||
state.setTempTextureStageState({ stage, D3DDDITSS_TEXCOORDINDEX, stage });
|
state.setTempTextureStageState({ stage, D3DDDITSS_TEXCOORDINDEX, stage });
|
||||||
state.setTempTextureStageState({ stage, D3DDDITSS_ADDRESSU, D3DTADDRESS_CLAMP });
|
state.setTempTextureStageState({ stage, D3DDDITSS_ADDRESSU, textureAddress });
|
||||||
state.setTempTextureStageState({ stage, D3DDDITSS_ADDRESSV, D3DTADDRESS_CLAMP });
|
state.setTempTextureStageState({ stage, D3DDDITSS_ADDRESSV, textureAddress });
|
||||||
state.setTempTextureStageState({ stage, D3DDDITSS_MAGFILTER, filter });
|
state.setTempTextureStageState({ stage, D3DDDITSS_MAGFILTER, LOWORD(filter) });
|
||||||
state.setTempTextureStageState({ stage, D3DDDITSS_MINFILTER, filter });
|
state.setTempTextureStageState({ stage, D3DDDITSS_MINFILTER, LOWORD(filter) });
|
||||||
state.setTempTextureStageState({ stage, D3DDDITSS_MIPFILTER, D3DTEXF_NONE });
|
state.setTempTextureStageState({ stage, D3DDDITSS_MIPFILTER, D3DTEXF_NONE });
|
||||||
|
state.setTempTextureStageState({ stage, D3DDDITSS_SRGBTEXTURE, 0 != (filter & D3DTEXF_SRGBREAD) });
|
||||||
state.setTempRenderState({ static_cast<D3DDDIRENDERSTATETYPE>(D3DDDIRS_WRAP0 + stage), 0 });
|
state.setTempRenderState({ static_cast<D3DDDIRENDERSTATETYPE>(D3DDDIRS_WRAP0 + stage), 0 });
|
||||||
|
|
||||||
auto& si = texture.getFixedDesc().pSurfList[0];
|
auto& si = texture.getFixedDesc().pSurfList[0];
|
||||||
|
@ -41,9 +41,7 @@ namespace D3dDdi
|
|||||||
HCURSOR cursor, POINT pt);
|
HCURSOR cursor, POINT pt);
|
||||||
void depthBlt(const Resource& dstResource, const RECT& dstRect,
|
void depthBlt(const Resource& dstResource, const RECT& dstRect,
|
||||||
const Resource& srcResource, const RECT& srcRect, HANDLE nullResource);
|
const Resource& srcResource, const RECT& srcRect, HANDLE nullResource);
|
||||||
void displayBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
void displayBlt(Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect);
|
|
||||||
void gammaBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
|
||||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect);
|
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect);
|
||||||
void lanczosBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
void lanczosBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, UINT lobes);
|
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, UINT lobes);
|
||||||
@ -80,6 +78,11 @@ namespace D3dDdi
|
|||||||
Float2 kernelCoordStepPri;
|
Float2 kernelCoordStepPri;
|
||||||
float support;
|
float support;
|
||||||
float supportRcp;
|
float supportRcp;
|
||||||
|
DeviceState::ShaderConstF maxRgb;
|
||||||
|
DeviceState::ShaderConstF maxRgbRcp;
|
||||||
|
float ditherScale;
|
||||||
|
float ditherOffset;
|
||||||
|
Float2 padding;
|
||||||
alignas(sizeof(DeviceState::ShaderConstF)) std::array<DeviceState::ShaderConstF, 4> extra;
|
alignas(sizeof(DeviceState::ShaderConstF)) std::array<DeviceState::ShaderConstF, 4> extra;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -96,8 +99,7 @@ namespace D3dDdi
|
|||||||
UINT filter, UINT flags = 0, const BYTE* alpha = nullptr, const Gdi::Region& srcRgn = nullptr);
|
UINT filter, UINT flags = 0, const BYTE* alpha = nullptr, const Gdi::Region& srcRgn = nullptr);
|
||||||
void convolution(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
void convolution(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
|
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
|
||||||
bool isHorizontal, Float2 support, HANDLE pixelShader,
|
Float2 support, HANDLE pixelShader, const std::function<void(bool)> setExtraParams, DWORD flags);
|
||||||
const std::function<void(bool)> setExtraParams);
|
|
||||||
void convolutionBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
void convolutionBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
|
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
|
||||||
Float2 support, HANDLE pixelShader, const std::function<void(bool)> setExtraParams = {});
|
Float2 support, HANDLE pixelShader, const std::function<void(bool)> setExtraParams = {});
|
||||||
@ -111,7 +113,8 @@ namespace D3dDdi
|
|||||||
std::unique_ptr<void, ResourceDeleter> createPixelShader(const BYTE* code, UINT size);
|
std::unique_ptr<void, ResourceDeleter> createPixelShader(const BYTE* code, UINT size);
|
||||||
std::unique_ptr<void, ResourceDeleter> createVertexShaderDecl();
|
std::unique_ptr<void, ResourceDeleter> createVertexShaderDecl();
|
||||||
void drawRect(const RECT& srcRect, const RectF& dstRect, UINT srcWidth, UINT srcHeight);
|
void drawRect(const RECT& srcRect, const RectF& dstRect, UINT srcWidth, UINT srcHeight);
|
||||||
void setTempTextureStage(UINT stage, const Resource& texture, const RECT& rect, UINT filter);
|
void setTempTextureStage(UINT stage, const Resource& texture, const RECT& rect, UINT filter,
|
||||||
|
UINT textureAddress = D3DTADDRESS_CLAMP);
|
||||||
void setTextureCoords(UINT stage, const RECT& rect, UINT width, UINT height);
|
void setTextureCoords(UINT stage, const RECT& rect, UINT width, UINT height);
|
||||||
|
|
||||||
Device& m_device;
|
Device& m_device;
|
||||||
@ -120,12 +123,13 @@ namespace D3dDdi
|
|||||||
std::unique_ptr<void, ResourceDeleter> m_psColorKeyBlend;
|
std::unique_ptr<void, ResourceDeleter> m_psColorKeyBlend;
|
||||||
std::unique_ptr<void, ResourceDeleter> m_psCubicConvolution[3];
|
std::unique_ptr<void, ResourceDeleter> m_psCubicConvolution[3];
|
||||||
std::unique_ptr<void, ResourceDeleter> m_psDepthBlt;
|
std::unique_ptr<void, ResourceDeleter> m_psDepthBlt;
|
||||||
|
std::unique_ptr<void, ResourceDeleter> m_psDitheredGammaControl;
|
||||||
std::unique_ptr<void, ResourceDeleter> m_psDrawCursor;
|
std::unique_ptr<void, ResourceDeleter> m_psDrawCursor;
|
||||||
std::unique_ptr<void, ResourceDeleter> m_psGamma;
|
|
||||||
std::unique_ptr<void, ResourceDeleter> m_psLanczos;
|
std::unique_ptr<void, ResourceDeleter> m_psLanczos;
|
||||||
std::unique_ptr<void, ResourceDeleter> m_psLockRef;
|
std::unique_ptr<void, ResourceDeleter> m_psLockRef;
|
||||||
std::unique_ptr<void, ResourceDeleter> m_psPaletteLookup;
|
std::unique_ptr<void, ResourceDeleter> m_psPaletteLookup;
|
||||||
std::unique_ptr<void, ResourceDeleter> m_psPoint;
|
std::unique_ptr<void, ResourceDeleter> m_psPoint;
|
||||||
|
std::unique_ptr<void, ResourceDeleter> m_psPointNoFilter;
|
||||||
std::unique_ptr<void, ResourceDeleter> m_psTextureSampler;
|
std::unique_ptr<void, ResourceDeleter> m_psTextureSampler;
|
||||||
std::unique_ptr<void, ResourceDeleter> m_vertexShaderDecl;
|
std::unique_ptr<void, ResourceDeleter> m_vertexShaderDecl;
|
||||||
ConvolutionParams m_convolutionParams;
|
ConvolutionParams m_convolutionParams;
|
||||||
|
@ -18,6 +18,27 @@ namespace
|
|||||||
{
|
{
|
||||||
std::map<LUID, D3dDdi::SurfaceRepository> g_repositories;
|
std::map<LUID, D3dDdi::SurfaceRepository> g_repositories;
|
||||||
bool g_enableSurfaceCheck = true;
|
bool g_enableSurfaceCheck = true;
|
||||||
|
|
||||||
|
void initDitherTexture(BYTE* tex, DWORD pitch, DWORD x, DWORD y, DWORD size, DWORD mul, DWORD value)
|
||||||
|
{
|
||||||
|
if (1 == size)
|
||||||
|
{
|
||||||
|
tex[y * pitch + x] = static_cast<BYTE>(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size /= 2;
|
||||||
|
initDitherTexture(tex, pitch, x, y, size, 4 * mul, value + 0 * mul);
|
||||||
|
initDitherTexture(tex, pitch, x + size, y, size, 4 * mul, value + 2 * mul);
|
||||||
|
initDitherTexture(tex, pitch, x, y + size, size, 4 * mul, value + 3 * mul);
|
||||||
|
initDitherTexture(tex, pitch, x + size, y + size, size, 4 * mul, value + 1 * mul);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void initDitherTexture(BYTE* tex, DWORD pitch, DWORD size)
|
||||||
|
{
|
||||||
|
initDitherTexture(tex, pitch, 0, 0, size, 1, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace D3dDdi
|
namespace D3dDdi
|
||||||
@ -201,6 +222,14 @@ namespace D3dDdi
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Resource* SurfaceRepository::getDitherTexture(DWORD size)
|
||||||
|
{
|
||||||
|
return getInitializedResource(m_ditherTexture, size, size, D3DDDIFMT_L8, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
|
||||||
|
[](const DDSURFACEDESC2& desc) {
|
||||||
|
initDitherTexture(static_cast<BYTE*>(desc.lpSurface), desc.lPitch, 16);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Resource* SurfaceRepository::getGammaRampTexture()
|
Resource* SurfaceRepository::getGammaRampTexture()
|
||||||
{
|
{
|
||||||
return getSurface(m_gammaRampTexture, 256, 3, D3DDDIFMT_L8, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY).resource;
|
return getSurface(m_gammaRampTexture, 256, 3, D3DDDIFMT_L8, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY).resource;
|
||||||
@ -245,19 +274,21 @@ namespace D3dDdi
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SurfaceRepository::Surface& SurfaceRepository::getNextRenderTarget(
|
const SurfaceRepository::Surface& SurfaceRepository::getNextRenderTarget(
|
||||||
DWORD width, DWORD height, const Resource* currentSrcRt, const Resource* currentDstRt)
|
DWORD width, DWORD height, D3DDDIFORMAT format, const Resource* currentSrcRt, const Resource* currentDstRt)
|
||||||
{
|
{
|
||||||
|
const bool hq = getFormatInfo(format).red.bitCount > 8;
|
||||||
|
auto& renderTargets = hq ? m_hqRenderTargets : m_renderTargets;
|
||||||
std::size_t index = 0;
|
std::size_t index = 0;
|
||||||
while (index < m_renderTargets.size())
|
while (index < renderTargets.size())
|
||||||
{
|
{
|
||||||
auto rt = m_renderTargets[index].resource;
|
auto rt = renderTargets[index].resource;
|
||||||
if (!rt || rt != currentSrcRt && rt != currentDstRt)
|
if (!rt || rt != currentSrcRt && rt != currentDstRt)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
return getTempSurface(m_renderTargets[index], width, height, D3DDDIFMT_X8R8G8B8,
|
return getTempSurface(renderTargets[index], width, height, hq ? format : D3DDDIFMT_X8R8G8B8,
|
||||||
DDSCAPS_3DDEVICE | DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY);
|
DDSCAPS_3DDEVICE | DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,10 +40,11 @@ namespace D3dDdi
|
|||||||
SurfaceRepository();
|
SurfaceRepository();
|
||||||
|
|
||||||
Cursor getCursor(HCURSOR cursor);
|
Cursor getCursor(HCURSOR cursor);
|
||||||
|
Resource* getDitherTexture(DWORD size);
|
||||||
Resource* getLogicalXorTexture();
|
Resource* getLogicalXorTexture();
|
||||||
Resource* getPaletteTexture();
|
Resource* getPaletteTexture();
|
||||||
Resource* getGammaRampTexture();
|
Resource* getGammaRampTexture();
|
||||||
const Surface& getNextRenderTarget(DWORD width, DWORD height,
|
const Surface& getNextRenderTarget(DWORD width, DWORD height, D3DDDIFORMAT format,
|
||||||
const Resource* currentSrcRt = nullptr, const Resource* currentDstRt = nullptr);
|
const Resource* currentSrcRt = nullptr, const Resource* currentDstRt = nullptr);
|
||||||
Surface& getSurface(Surface& surface, DWORD width, DWORD height,
|
Surface& getSurface(Surface& surface, DWORD width, DWORD height,
|
||||||
D3DDDIFORMAT format, DWORD caps, UINT surfaceCount = 1, DWORD caps2 = 0);
|
D3DDDIFORMAT format, DWORD caps, UINT surfaceCount = 1, DWORD caps2 = 0);
|
||||||
@ -74,10 +75,12 @@ namespace D3dDdi
|
|||||||
Surface m_cursorMaskTexture;
|
Surface m_cursorMaskTexture;
|
||||||
Surface m_cursorColorTexture;
|
Surface m_cursorColorTexture;
|
||||||
Surface m_cursorTempTexture;
|
Surface m_cursorTempTexture;
|
||||||
|
Surface m_ditherTexture;
|
||||||
Surface m_gammaRampTexture;
|
Surface m_gammaRampTexture;
|
||||||
Surface m_logicalXorTexture;
|
Surface m_logicalXorTexture;
|
||||||
Surface m_paletteTexture;
|
Surface m_paletteTexture;
|
||||||
std::array<Surface, 3> m_renderTargets;
|
std::array<Surface, 3> m_renderTargets;
|
||||||
|
std::array<Surface, 3> m_hqRenderTargets;
|
||||||
std::map<D3DDDIFORMAT, Surface> m_textures;
|
std::map<D3DDDIFORMAT, Surface> m_textures;
|
||||||
std::vector<Surface> m_releasedSurfaces;
|
std::vector<Surface> m_releasedSurfaces;
|
||||||
Surface m_sysMemSurface;
|
Surface m_sysMemSurface;
|
||||||
|
@ -486,11 +486,11 @@
|
|||||||
<FxCompile Include="Shaders\CubicConvolution4.hlsl" />
|
<FxCompile Include="Shaders\CubicConvolution4.hlsl" />
|
||||||
<FxCompile Include="Shaders\DepthBlt.hlsl" />
|
<FxCompile Include="Shaders\DepthBlt.hlsl" />
|
||||||
<FxCompile Include="Shaders\DrawCursor.hlsl" />
|
<FxCompile Include="Shaders\DrawCursor.hlsl" />
|
||||||
<FxCompile Include="Shaders\Gamma.hlsl" />
|
|
||||||
<FxCompile Include="Shaders\Lanczos.hlsl" />
|
<FxCompile Include="Shaders\Lanczos.hlsl" />
|
||||||
<FxCompile Include="Shaders\LockRef.hlsl" />
|
<FxCompile Include="Shaders\LockRef.hlsl" />
|
||||||
<FxCompile Include="Shaders\PaletteLookup.hlsl" />
|
<FxCompile Include="Shaders\PaletteLookup.hlsl" />
|
||||||
<FxCompile Include="Shaders\Point.hlsl" />
|
<FxCompile Include="Shaders\Point.hlsl" />
|
||||||
|
<FxCompile Include="Shaders\PointNoFilter.hlsl" />
|
||||||
<FxCompile Include="Shaders\TextureSampler.hlsl" />
|
<FxCompile Include="Shaders\TextureSampler.hlsl" />
|
||||||
<FxCompile Include="Shaders\VertexFixup.hlsl">
|
<FxCompile Include="Shaders\VertexFixup.hlsl">
|
||||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Vertex</ShaderType>
|
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Vertex</ShaderType>
|
||||||
|
@ -1136,9 +1136,6 @@
|
|||||||
<FxCompile Include="Shaders\VertexFixup.hlsl">
|
<FxCompile Include="Shaders\VertexFixup.hlsl">
|
||||||
<Filter>Shaders</Filter>
|
<Filter>Shaders</Filter>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
<FxCompile Include="Shaders\Gamma.hlsl">
|
|
||||||
<Filter>Shaders</Filter>
|
|
||||||
</FxCompile>
|
|
||||||
<FxCompile Include="Shaders\LockRef.hlsl">
|
<FxCompile Include="Shaders\LockRef.hlsl">
|
||||||
<Filter>Shaders</Filter>
|
<Filter>Shaders</Filter>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
@ -1169,6 +1166,9 @@
|
|||||||
<FxCompile Include="Shaders\Point.hlsl">
|
<FxCompile Include="Shaders\Point.hlsl">
|
||||||
<Filter>Shaders</Filter>
|
<Filter>Shaders</Filter>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
<FxCompile Include="Shaders\PointNoFilter.hlsl">
|
||||||
|
<Filter>Shaders</Filter>
|
||||||
|
</FxCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Image Include="arrow.bmp">
|
<Image Include="arrow.bmp">
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
sampler2D s_texture : register(s0);
|
sampler2D s_texture : register(s0);
|
||||||
|
sampler2D s_gammaRamp : register(s1);
|
||||||
|
sampler2D s_dither : register(s2);
|
||||||
int g_sampleCountHalfMinusOne : register(i0);
|
int g_sampleCountHalfMinusOne : register(i0);
|
||||||
|
|
||||||
float4 c[32] : register(c0);
|
float4 c[32] : register(c0);
|
||||||
float4 g_extraParams[4] : register(c6);
|
float4 g_extraParams[4] : register(c9);
|
||||||
|
|
||||||
|
bool g_useSrgbRead : register(b0);
|
||||||
|
bool g_useSrgbReadNeg : register(b1);
|
||||||
|
bool g_useSrgbWrite : register(b2);
|
||||||
|
bool g_useGammaRamp : register(b3);
|
||||||
|
bool g_useDithering : register(b4);
|
||||||
|
|
||||||
static const float2 g_textureSize = c[0].xy;
|
static const float2 g_textureSize = c[0].xy;
|
||||||
static const float2 g_sampleCoordOffset = c[0].zw;
|
static const float2 g_sampleCoordOffset = c[0].zw;
|
||||||
@ -15,6 +23,10 @@ static const float2 g_textureCoordStepSec = c[4].zw;
|
|||||||
static const float2 g_kernelCoordStepPri = c[5].xy;
|
static const float2 g_kernelCoordStepPri = c[5].xy;
|
||||||
static const float g_support = c[5].z;
|
static const float g_support = c[5].z;
|
||||||
static const float g_supportRcp = c[5].w;
|
static const float g_supportRcp = c[5].w;
|
||||||
|
static const float4 g_maxRgb = c[6];
|
||||||
|
static const float4 g_maxRgbRcp = c[7];
|
||||||
|
static const float g_ditherScale = c[8].x;
|
||||||
|
static const float g_ditherOffset = c[8].y;
|
||||||
|
|
||||||
#ifdef NONNEGATIVE
|
#ifdef NONNEGATIVE
|
||||||
float4 kernel(float4 x);
|
float4 kernel(float4 x);
|
||||||
@ -22,14 +34,35 @@ float4 kernel(float4 x);
|
|||||||
float kernel(float x);
|
float kernel(float x);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void addSamples(inout float4 colorSum, float4 textureCoord, float4 weights)
|
float4 srgb2lin(float4 color)
|
||||||
|
{
|
||||||
|
return float4(color.rgb < 0.04045f ? color.rgb / 12.92f : pow((abs(color.rgb) + 0.055f) / 1.055f, 2.4f), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addSamples(inout float4 color, float4 textureCoord, float4 weights)
|
||||||
{
|
{
|
||||||
#ifdef NONNEGATIVE
|
#ifdef NONNEGATIVE
|
||||||
const float weightSum = weights.x + weights.z;
|
[branch]
|
||||||
colorSum += weightSum * tex2Dlod(s_texture, lerp(textureCoord.xyxy, textureCoord.zwzw, weights.z / weightSum));
|
if (g_useSrgbRead)
|
||||||
#else
|
{
|
||||||
colorSum += weights.x * tex2Dlod(s_texture, textureCoord.xyxy);
|
#endif
|
||||||
colorSum += weights.z * tex2Dlod(s_texture, textureCoord.zwzw);
|
float4 color1 = tex2Dlod(s_texture, textureCoord.xyxy);
|
||||||
|
float4 color2 = tex2Dlod(s_texture, textureCoord.zwzw);
|
||||||
|
[branch]
|
||||||
|
if (g_useSrgbRead)
|
||||||
|
{
|
||||||
|
color1 = srgb2lin(color1);
|
||||||
|
color2 = srgb2lin(color2);
|
||||||
|
}
|
||||||
|
color += weights.x * color1;
|
||||||
|
color += weights.z * color2;
|
||||||
|
#ifdef NONNEGATIVE
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const float weightSum = weights.x + weights.z;
|
||||||
|
color += weightSum * tex2Dlod(s_texture, lerp(textureCoord.xyxy, textureCoord.zwzw, weights.z / weightSum));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,8 +75,16 @@ float4 getWeights(float4 kernelCoord)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
float4 main(float2 texCoord : TEXCOORD0) : COLOR0
|
float4 normalize(float4 color)
|
||||||
{
|
{
|
||||||
|
return color * 255.0f / 256.0f + 0.5f / 256.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 main(float2 texCoord : TEXCOORD0, float2 ditherCoord : TEXCOORD2) : COLOR0
|
||||||
|
{
|
||||||
|
#ifdef NOFILTER
|
||||||
|
float4 color = float4(tex2D(s_texture, texCoord).rgb, 1);
|
||||||
|
#else
|
||||||
const float2 sampleCoord = mad(texCoord, g_textureSize, g_sampleCoordOffset);
|
const float2 sampleCoord = mad(texCoord, g_textureSize, g_sampleCoordOffset);
|
||||||
const float2 sampleCoordFrac = frac(sampleCoord);
|
const float2 sampleCoordFrac = frac(sampleCoord);
|
||||||
const float2 sampleCoordInt = sampleCoord - sampleCoordFrac;
|
const float2 sampleCoordInt = sampleCoord - sampleCoordFrac;
|
||||||
@ -55,21 +96,54 @@ float4 main(float2 texCoord : TEXCOORD0) : COLOR0
|
|||||||
const float4 weights = getWeights(kernelCoord);
|
const float4 weights = getWeights(kernelCoord);
|
||||||
|
|
||||||
#ifdef NONNEGATIVE
|
#ifdef NONNEGATIVE
|
||||||
[branch] if (g_sampleCoordOffset.x == g_sampleCoordOffset.y)
|
[branch]
|
||||||
|
if (g_useSrgbReadNeg)
|
||||||
{
|
{
|
||||||
textureCoord = lerp(textureCoord, textureCoord + g_textureCoordStepSec.xyxy, weights.w / (weights.y + weights.w));
|
[branch]
|
||||||
|
if (g_sampleCoordOffset.x == g_sampleCoordOffset.y)
|
||||||
|
{
|
||||||
|
textureCoord = lerp(textureCoord, textureCoord + g_textureCoordStepSec.xyxy, weights.w / (weights.y + weights.w));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif // NONNEGATIVE
|
||||||
|
|
||||||
float4 colorSum = 0;
|
float4 color = 0;
|
||||||
addSamples(colorSum, textureCoord, weights);
|
addSamples(color, textureCoord, weights);
|
||||||
|
|
||||||
for (int i = 0; i < g_sampleCountHalfMinusOne; ++i)
|
for (int i = 0; i < g_sampleCountHalfMinusOne; ++i)
|
||||||
{
|
{
|
||||||
textureCoord += g_textureCoordStepPri.xyxy;
|
textureCoord += g_textureCoordStepPri.xyxy;
|
||||||
kernelCoord += g_kernelCoordStepPri.xyxy;
|
kernelCoord += g_kernelCoordStepPri.xyxy;
|
||||||
addSamples(colorSum, textureCoord, getWeights(kernelCoord));
|
addSamples(color, textureCoord, getWeights(kernelCoord));
|
||||||
}
|
}
|
||||||
|
|
||||||
return colorSum / colorSum.a;
|
color /= color.a;
|
||||||
|
|
||||||
|
[branch]
|
||||||
|
if (g_useSrgbWrite)
|
||||||
|
{
|
||||||
|
color = saturate(color);
|
||||||
|
color.rgb = color.rgb < 0.0031308f ? 12.92f * color.rgb : 1.055f * pow(color.rgb, 1.0f / 2.4f) - 0.055f;
|
||||||
|
#endif // NOFILTER
|
||||||
|
|
||||||
|
[branch]
|
||||||
|
if (g_useGammaRamp)
|
||||||
|
{
|
||||||
|
color = normalize(color);
|
||||||
|
color.r = tex2Dlod(s_gammaRamp, float4(color.r, 0.0f, 0, 0)).r;
|
||||||
|
color.g = tex2Dlod(s_gammaRamp, float4(color.g, 0.5f, 0, 0)).r;
|
||||||
|
color.b = tex2Dlod(s_gammaRamp, float4(color.b, 1.0f, 0, 0)).r;
|
||||||
|
}
|
||||||
|
|
||||||
|
[branch]
|
||||||
|
if (g_useDithering)
|
||||||
|
{
|
||||||
|
const float dither = tex2D(s_dither, ditherCoord).r * g_ditherScale + g_ditherOffset;
|
||||||
|
color = floor(color * g_maxRgb + dither) * g_maxRgbRcp;
|
||||||
|
}
|
||||||
|
#ifndef NOFILTER
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return color;
|
||||||
}
|
}
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
sampler2D s_texture : register(s0);
|
|
||||||
sampler2D s_gammaRamp : register(s1);
|
|
||||||
|
|
||||||
float4 main(float2 texCoord : TEXCOORD0) : COLOR0
|
|
||||||
{
|
|
||||||
const float4 color = tex2D(s_texture, texCoord);
|
|
||||||
return float4(
|
|
||||||
tex2D(s_gammaRamp, float2(color.r, 0.0f)).r,
|
|
||||||
tex2D(s_gammaRamp, float2(color.g, 0.5f)).r,
|
|
||||||
tex2D(s_gammaRamp, float2(color.b, 1.0f)).r,
|
|
||||||
0);
|
|
||||||
}
|
|
2
DDrawCompat/Shaders/PointNoFilter.hlsl
Normal file
2
DDrawCompat/Shaders/PointNoFilter.hlsl
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#define NOFILTER
|
||||||
|
#include "Convolution.hlsli"
|
Loading…
x
Reference in New Issue
Block a user