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
|
||||
{
|
||||
class RenderColorDepth : public MappedSetting<unsigned>
|
||||
class RenderColorDepth : public MappedSetting<std::pair<unsigned, unsigned>>
|
||||
{
|
||||
public:
|
||||
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/DisplayAspectRatio.h>
|
||||
#include <Config/Settings/PalettizedTextures.h>
|
||||
#include <Config/Settings/RenderColorDepth.h>
|
||||
#include <Config/Settings/ResolutionScale.h>
|
||||
#include <Config/Settings/SupportedDepthFormats.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) };
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
const auto scaleFactor = getScaleFactor();
|
||||
@ -349,6 +385,14 @@ namespace D3dDdi
|
||||
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()
|
||||
{
|
||||
auto adapter = m_adapter;
|
||||
|
@ -41,6 +41,8 @@ namespace D3dDdi
|
||||
const auto& getMonitorInfo() const { return Win32::DisplayMode::getMonitorInfo(m_deviceName); }
|
||||
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> getMultisampleConfig(D3DDDIFORMAT format) const;
|
||||
const D3DDDI_ADAPTERFUNCS& getOrigVtable() const { return m_origVtable; }
|
||||
D3DDDIFORMAT getRenderColorDepthSrcFormat(D3DDDIFORMAT appFormat) const;
|
||||
D3DDDIFORMAT getRenderColorDepthDstFormat() const;
|
||||
CompatWeakPtr<IDirectDraw7> getRepository() const { return m_repository; }
|
||||
SIZE getScaledSize(Int2 size) const;
|
||||
bool isEmulatedRenderTargetFormat(D3DDDIFORMAT format) const;
|
||||
@ -66,6 +68,7 @@ namespace D3dDdi
|
||||
std::string getSupportedMsaaModes(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 isSupportedRttFormat(D3DDDIFORMAT format) const;
|
||||
|
||||
HANDLE m_adapter;
|
||||
D3DDDI_ADAPTERFUNCS m_origVtable;
|
||||
|
@ -48,6 +48,20 @@ namespace D3dDdi
|
||||
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& state, const D3DDDIARG_SETPIXELSHADERCONSTI& data, const ShaderConstI* registers)
|
||||
: m_state(state)
|
||||
|
@ -15,7 +15,9 @@ const UINT D3DTEXF_NONE = 0;
|
||||
const UINT D3DTEXF_POINT = 1;
|
||||
const UINT D3DTEXF_LINEAR = 2;
|
||||
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
|
||||
{
|
||||
@ -59,6 +61,17 @@ namespace D3dDdi
|
||||
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
|
||||
{
|
||||
public:
|
||||
|
@ -109,8 +109,10 @@ namespace
|
||||
{ D3DDDIFMT_A8R3G3B2, FormatInfoXARGB(0, 8, 3, 3, 2) },
|
||||
{ D3DDDIFMT_X4R4G4B4, FormatInfoXARGB(4, 0, 4, 4, 4) },
|
||||
|
||||
{ D3DDDIFMT_A8B8G8R8, FormatInfoXABGR(0, 8, 8, 8, 8) },
|
||||
{ D3DDDIFMT_X8B8G8R8, FormatInfoXABGR(8, 0, 8, 8, 8) },
|
||||
{ D3DDDIFMT_A2B10G10R10, FormatInfoXABGR(0, 2, 10, 10, 10) },
|
||||
{ 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_P8, FormatInfoAP(0, 8) },
|
||||
@ -141,6 +143,11 @@ namespace
|
||||
|
||||
DDPIXELFORMAT getPixelFormat(const D3dDdi::FormatInfo& info)
|
||||
{
|
||||
if (info.red.bitCount > 8)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
DDPIXELFORMAT pf = {};
|
||||
pf.dwSize = sizeof(pf);
|
||||
pf.dwFlags =
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include <Config/Settings/BltFilter.h>
|
||||
#include <Config/Settings/ColorKeyMethod.h>
|
||||
#include <Config/Settings/DepthFormat.h>
|
||||
#include <Config/Settings/RenderColorDepth.h>
|
||||
#include <Config/Settings/ResolutionScaleFilter.h>
|
||||
#include <D3dDdi/Adapter.h>
|
||||
#include <D3dDdi/Device.h>
|
||||
@ -529,6 +528,12 @@ namespace D3dDdi
|
||||
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,
|
||||
HANDLE src, UINT srcIndex, const RECT& srcRect)
|
||||
{
|
||||
@ -743,11 +748,7 @@ namespace D3dDdi
|
||||
|
||||
if (D3DDDIFMT_X8R8G8B8 == m_fixedData.Format || D3DDDIFMT_R5G6B5 == m_fixedData.Format)
|
||||
{
|
||||
switch (Config::renderColorDepth.get())
|
||||
{
|
||||
case 16: return D3DDDIFMT_R5G6B5;
|
||||
case 32: return D3DDDIFMT_X8R8G8B8;
|
||||
}
|
||||
return m_device.getAdapter().getRenderColorDepthSrcFormat(m_fixedData.Format);
|
||||
}
|
||||
else if (m_fixedData.Flags.ZBuffer && Config::Settings::DepthFormat::APP != Config::depthFormat.get() &&
|
||||
getFormatInfo(m_fixedData.Format).depth.bitCount != Config::depthFormat.get())
|
||||
@ -1212,7 +1213,7 @@ namespace D3dDdi
|
||||
}
|
||||
|
||||
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 rtIndex = rtSurface.resource ? 0 : data.DstSubResourceIndex;
|
||||
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);
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
presentLayeredWindows(*this, data.DstSubResourceIndex, getRect(data.DstSubResourceIndex),
|
||||
@ -1468,7 +1466,7 @@ namespace D3dDdi
|
||||
|
||||
if (!srcResource.m_fixedData.Flags.Texture ||
|
||||
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 height = data.SrcRect.bottom - data.SrcRect.top;
|
||||
@ -1498,11 +1496,11 @@ namespace D3dDdi
|
||||
}
|
||||
|
||||
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 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)
|
||||
{
|
||||
return LOG_RESULT(E_OUTOFMEMORY);
|
||||
|
@ -39,6 +39,8 @@ namespace D3dDdi
|
||||
|
||||
HRESULT blt(D3DDDIARG_BLT data);
|
||||
HRESULT colorFill(D3DDDIARG_COLORFILL data);
|
||||
HRESULT copySubResourceRegion(UINT dstIndex, const RECT& dstRect,
|
||||
HANDLE src, UINT srcIndex, const RECT& srcRect);
|
||||
void disableClamp();
|
||||
void* getLockPtr(UINT subResourceIndex);
|
||||
RECT getRect(UINT subResourceIndex) const;
|
||||
|
@ -15,11 +15,11 @@
|
||||
#include <Shaders/CubicConvolution4.h>
|
||||
#include <Shaders/DepthBlt.h>
|
||||
#include <Shaders/DrawCursor.h>
|
||||
#include <Shaders/Gamma.h>
|
||||
#include <Shaders/Lanczos.h>
|
||||
#include <Shaders/LockRef.h>
|
||||
#include <Shaders/PaletteLookup.h>
|
||||
#include <Shaders/Point.h>
|
||||
#include <Shaders/PointNoFilter.h>
|
||||
#include <Shaders/TextureSampler.h>
|
||||
|
||||
#define CONCAT_(a, b) a##b
|
||||
@ -28,6 +28,10 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
const UINT CF_HORIZONTAL = 1;
|
||||
const UINT CF_GAMMARAMP = 2;
|
||||
const UINT CF_DITHERING = 4;
|
||||
|
||||
D3DDDI_GAMMA_RAMP_RGB256x3x16 g_gammaRamp;
|
||||
bool g_isGammaRampDefault = true;
|
||||
bool g_isGammaRampInvalidated = false;
|
||||
@ -83,11 +87,11 @@ namespace D3dDdi
|
||||
}
|
||||
, m_psDepthBlt(createPixelShader(g_psDepthBlt))
|
||||
, m_psDrawCursor(createPixelShader(g_psDrawCursor))
|
||||
, m_psGamma(createPixelShader(g_psGamma))
|
||||
, m_psLanczos(createPixelShader(g_psLanczos))
|
||||
, m_psLockRef(createPixelShader(g_psLockRef))
|
||||
, m_psPaletteLookup(createPixelShader(g_psPaletteLookup))
|
||||
, m_psPoint(createPixelShader(g_psPoint))
|
||||
, m_psPointNoFilter(createPixelShader(g_psPointNoFilter))
|
||||
, m_psTextureSampler(createPixelShader(g_psTextureSampler))
|
||||
, m_vertexShaderDecl(createVertexShaderDecl())
|
||||
, m_convolutionParams{}
|
||||
@ -160,9 +164,13 @@ namespace D3dDdi
|
||||
const auto& srcSurface = srcResource.getFixedDesc().pSurfList[srcSubResourceIndex];
|
||||
const auto& dstSurface = dstResource.getFixedDesc().pSurfList[dstSubResourceIndex];
|
||||
|
||||
const bool srgb = (filter & D3DTEXF_SRGB) &&
|
||||
(srcResource.getFormatOp().Operations & FORMATOP_SRGBREAD) &&
|
||||
(dstResource.getFormatOp().Operations & FORMATOP_SRGBWRITE);
|
||||
bool srgbRead = (filter & D3DTEXF_SRGBREAD) && (srcResource.getFormatOp().Operations & FORMATOP_SRGBREAD);
|
||||
bool srgbWrite = (filter & D3DTEXF_SRGBWRITE) && (dstResource.getFormatOp().Operations & FORMATOP_SRGBWRITE);
|
||||
if (D3DTEXF_SRGB == HIWORD(filter) && (!srgbRead || !srgbWrite))
|
||||
{
|
||||
srgbRead = false;
|
||||
srgbWrite = false;
|
||||
}
|
||||
|
||||
auto& state = m_device.getState();
|
||||
state.setSpriteMode(false);
|
||||
@ -189,7 +197,7 @@ namespace D3dDdi
|
||||
state.setTempRenderState({ D3DDDIRS_MULTISAMPLEANTIALIAS, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_COLORWRITEENABLE, 0xF });
|
||||
state.setTempRenderState({ D3DDDIRS_SCISSORTESTENABLE, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_SRGBWRITEENABLE, srgb });
|
||||
state.setTempRenderState({ D3DDDIRS_SRGBWRITEENABLE, srgbWrite });
|
||||
|
||||
if (alpha)
|
||||
{
|
||||
@ -209,8 +217,7 @@ namespace D3dDdi
|
||||
state.setTempRenderState({ D3DDDIRS_DESTBLEND, D3DBLEND_INVSRCALPHA });
|
||||
}
|
||||
|
||||
setTempTextureStage(0, srcResource, srcRect, LOWORD(filter));
|
||||
state.setTempTextureStageState({ 0, D3DDDITSS_SRGBTEXTURE, srgb });
|
||||
setTempTextureStage(0, srcResource, srcRect, LOWORD(filter) | (srgbRead ? D3DTEXF_SRGBREAD : 0));
|
||||
|
||||
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,
|
||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
|
||||
bool isHorizontal, Float2 support, HANDLE pixelShader,
|
||||
const std::function<void(bool)> setExtraParams)
|
||||
Float2 support, HANDLE pixelShader, const std::function<void(bool)> setExtraParams, DWORD flags)
|
||||
{
|
||||
LOG_FUNC("ShaderBlitter::convolution", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
|
||||
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 Float2 dstSize(dstRect.right - dstRect.left, dstRect.bottom - dstRect.top);
|
||||
const Float2 srcSize(srcRect.right - srcRect.left, srcRect.bottom - srcRect.top);
|
||||
const Float2 scale = dstSize / srcSize;
|
||||
|
||||
const bool isHorizontal = flags & CF_HORIZONTAL;
|
||||
const bool isDual = srcSize.x != dstSize.x && srcSize.y != dstSize.y;
|
||||
const Float2 compMaskPri = isHorizontal ? Float2(1, 0) : Float2(0, 1);
|
||||
const Float2 compMaskSec = isHorizontal ? Float2(0, 1) : Float2(1, 0);
|
||||
@ -291,14 +298,43 @@ namespace D3dDdi
|
||||
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)) };
|
||||
DeviceState::TempPixelShaderConstI tempPsConstI(m_device.getState(), { 0, 1 }, ®);
|
||||
|
||||
DeviceState::TempPixelShaderConst tempPsConst(m_device.getState(),
|
||||
{ 0, sizeof(m_convolutionParams) / sizeof(DeviceState::ShaderConstF) },
|
||||
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,
|
||||
@ -315,15 +351,84 @@ namespace D3dDdi
|
||||
const Float2 kernelCoordStep = min(scale, 1.0f);
|
||||
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,
|
||||
true, support, pixelShader, setExtraParams);
|
||||
flags |= CF_GAMMARAMP;
|
||||
}
|
||||
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,
|
||||
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;
|
||||
@ -337,16 +442,17 @@ namespace D3dDdi
|
||||
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)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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,
|
||||
!isHorizontalFirst, support, pixelShader, setExtraParams);
|
||||
support, pixelShader, setExtraParams, flags | (isHorizontalFirst ? 0 : CF_HORIZONTAL));
|
||||
}
|
||||
|
||||
std::unique_ptr<void, ResourceDeleter> ShaderBlitter::createPixelShader(const BYTE* code, UINT size)
|
||||
@ -427,14 +533,7 @@ namespace D3dDdi
|
||||
|
||||
if (cur.maskTexture)
|
||||
{
|
||||
D3DDDIARG_BLT data = {};
|
||||
data.hSrcResource = dstResource;
|
||||
data.SrcSubResourceIndex = dstSubResourceIndex;
|
||||
data.SrcRect = clippedDstRect;
|
||||
data.hDstResource = *cur.tempTexture;
|
||||
data.DstRect = clippedSrcRect;
|
||||
m_device.getOrigVtable().pfnBlt(m_device, &data);
|
||||
|
||||
cur.tempTexture->copySubResourceRegion(0, clippedSrcRect, dstResource, dstSubResourceIndex, clippedDstRect);
|
||||
setTempTextureStage(1, *cur.maskTexture, clippedSrcRect, D3DTEXF_POINT);
|
||||
setTempTextureStage(2, *cur.colorTexture, clippedSrcRect, D3DTEXF_POINT);
|
||||
setTempTextureStage(3, *xorTexture, clippedSrcRect, D3DTEXF_POINT);
|
||||
@ -493,75 +592,42 @@ namespace D3dDdi
|
||||
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)
|
||||
{
|
||||
auto& repo = m_device.getRepo();
|
||||
const bool useGamma = !g_isGammaRampDefault && repo.getGammaRampTexture();
|
||||
|
||||
auto filter = Config::displayFilter.get();
|
||||
if (Rect::isEqualSize(dstRect, srcRect))
|
||||
{
|
||||
if (useGamma)
|
||||
{
|
||||
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;
|
||||
filter = Config::Settings::DisplayFilter::POINT;
|
||||
}
|
||||
|
||||
RECT r = { 0, 0, dstRect.right - dstRect.left, dstRect.bottom - dstRect.top };
|
||||
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())
|
||||
switch (filter)
|
||||
{
|
||||
case Config::Settings::DisplayFilter::POINT:
|
||||
m_device.getShaderBlitter().pointBlt(rt, rtIndex, rtRect,
|
||||
m_device.getShaderBlitter().pointBlt(dstResource, dstSubResourceIndex, dstRect,
|
||||
srcResource, srcSubResourceIndex, srcRect);
|
||||
break;
|
||||
|
||||
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());
|
||||
break;
|
||||
|
||||
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());
|
||||
break;
|
||||
|
||||
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());
|
||||
break;
|
||||
|
||||
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());
|
||||
break;
|
||||
}
|
||||
|
||||
if (rtGamma)
|
||||
{
|
||||
gammaBlt(dstResource, dstSubResourceIndex, dstRect, rt, rtIndex, rtRect);
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderBlitter::drawRect(const RECT& srcRect, const RectF& dstRect, UINT srcWidth, UINT srcHeight)
|
||||
@ -580,44 +646,6 @@ namespace D3dDdi
|
||||
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,
|
||||
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,
|
||||
static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect);
|
||||
|
||||
convolutionBlt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
|
||||
0.5f, m_psPoint.get());
|
||||
auto dstSize = Rect::getSize(dstRect);
|
||||
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()
|
||||
@ -701,16 +739,18 @@ namespace D3dDdi
|
||||
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();
|
||||
state.setTempTexture(stage, texture);
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_TEXCOORDINDEX, stage });
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_ADDRESSU, D3DTADDRESS_CLAMP });
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_ADDRESSV, D3DTADDRESS_CLAMP });
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_MAGFILTER, filter });
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_MINFILTER, filter });
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_ADDRESSU, textureAddress });
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_ADDRESSV, textureAddress });
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_MAGFILTER, LOWORD(filter) });
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_MINFILTER, LOWORD(filter) });
|
||||
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 });
|
||||
|
||||
auto& si = texture.getFixedDesc().pSurfList[0];
|
||||
|
@ -41,9 +41,7 @@ namespace D3dDdi
|
||||
HCURSOR cursor, POINT pt);
|
||||
void depthBlt(const Resource& dstResource, const RECT& dstRect,
|
||||
const Resource& srcResource, const RECT& srcRect, HANDLE nullResource);
|
||||
void displayBlt(const 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,
|
||||
void displayBlt(Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect);
|
||||
void lanczosBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, UINT lobes);
|
||||
@ -80,6 +78,11 @@ namespace D3dDdi
|
||||
Float2 kernelCoordStepPri;
|
||||
float support;
|
||||
float supportRcp;
|
||||
DeviceState::ShaderConstF maxRgb;
|
||||
DeviceState::ShaderConstF maxRgbRcp;
|
||||
float ditherScale;
|
||||
float ditherOffset;
|
||||
Float2 padding;
|
||||
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);
|
||||
void convolution(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
|
||||
bool isHorizontal, Float2 support, HANDLE pixelShader,
|
||||
const std::function<void(bool)> setExtraParams);
|
||||
Float2 support, HANDLE pixelShader, const std::function<void(bool)> setExtraParams, DWORD flags);
|
||||
void convolutionBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
|
||||
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> createVertexShaderDecl();
|
||||
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);
|
||||
|
||||
Device& m_device;
|
||||
@ -120,12 +123,13 @@ namespace D3dDdi
|
||||
std::unique_ptr<void, ResourceDeleter> m_psColorKeyBlend;
|
||||
std::unique_ptr<void, ResourceDeleter> m_psCubicConvolution[3];
|
||||
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_psGamma;
|
||||
std::unique_ptr<void, ResourceDeleter> m_psLanczos;
|
||||
std::unique_ptr<void, ResourceDeleter> m_psLockRef;
|
||||
std::unique_ptr<void, ResourceDeleter> m_psPaletteLookup;
|
||||
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_vertexShaderDecl;
|
||||
ConvolutionParams m_convolutionParams;
|
||||
|
@ -18,6 +18,27 @@ namespace
|
||||
{
|
||||
std::map<LUID, D3dDdi::SurfaceRepository> g_repositories;
|
||||
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
|
||||
@ -201,6 +222,14 @@ namespace D3dDdi
|
||||
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()
|
||||
{
|
||||
return getSurface(m_gammaRampTexture, 256, 3, D3DDDIFMT_L8, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY).resource;
|
||||
@ -245,19 +274,21 @@ namespace D3dDdi
|
||||
}
|
||||
|
||||
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;
|
||||
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)
|
||||
{
|
||||
break;
|
||||
}
|
||||
++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);
|
||||
}
|
||||
|
||||
|
@ -40,10 +40,11 @@ namespace D3dDdi
|
||||
SurfaceRepository();
|
||||
|
||||
Cursor getCursor(HCURSOR cursor);
|
||||
Resource* getDitherTexture(DWORD size);
|
||||
Resource* getLogicalXorTexture();
|
||||
Resource* getPaletteTexture();
|
||||
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);
|
||||
Surface& getSurface(Surface& surface, DWORD width, DWORD height,
|
||||
D3DDDIFORMAT format, DWORD caps, UINT surfaceCount = 1, DWORD caps2 = 0);
|
||||
@ -74,10 +75,12 @@ namespace D3dDdi
|
||||
Surface m_cursorMaskTexture;
|
||||
Surface m_cursorColorTexture;
|
||||
Surface m_cursorTempTexture;
|
||||
Surface m_ditherTexture;
|
||||
Surface m_gammaRampTexture;
|
||||
Surface m_logicalXorTexture;
|
||||
Surface m_paletteTexture;
|
||||
std::array<Surface, 3> m_renderTargets;
|
||||
std::array<Surface, 3> m_hqRenderTargets;
|
||||
std::map<D3DDDIFORMAT, Surface> m_textures;
|
||||
std::vector<Surface> m_releasedSurfaces;
|
||||
Surface m_sysMemSurface;
|
||||
|
@ -486,11 +486,11 @@
|
||||
<FxCompile Include="Shaders\CubicConvolution4.hlsl" />
|
||||
<FxCompile Include="Shaders\DepthBlt.hlsl" />
|
||||
<FxCompile Include="Shaders\DrawCursor.hlsl" />
|
||||
<FxCompile Include="Shaders\Gamma.hlsl" />
|
||||
<FxCompile Include="Shaders\Lanczos.hlsl" />
|
||||
<FxCompile Include="Shaders\LockRef.hlsl" />
|
||||
<FxCompile Include="Shaders\PaletteLookup.hlsl" />
|
||||
<FxCompile Include="Shaders\Point.hlsl" />
|
||||
<FxCompile Include="Shaders\PointNoFilter.hlsl" />
|
||||
<FxCompile Include="Shaders\TextureSampler.hlsl" />
|
||||
<FxCompile Include="Shaders\VertexFixup.hlsl">
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Vertex</ShaderType>
|
||||
|
@ -1136,9 +1136,6 @@
|
||||
<FxCompile Include="Shaders\VertexFixup.hlsl">
|
||||
<Filter>Shaders</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="Shaders\Gamma.hlsl">
|
||||
<Filter>Shaders</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="Shaders\LockRef.hlsl">
|
||||
<Filter>Shaders</Filter>
|
||||
</FxCompile>
|
||||
@ -1169,6 +1166,9 @@
|
||||
<FxCompile Include="Shaders\Point.hlsl">
|
||||
<Filter>Shaders</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="Shaders\PointNoFilter.hlsl">
|
||||
<Filter>Shaders</Filter>
|
||||
</FxCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="arrow.bmp">
|
||||
|
@ -1,8 +1,16 @@
|
||||
sampler2D s_texture : register(s0);
|
||||
sampler2D s_gammaRamp : register(s1);
|
||||
sampler2D s_dither : register(s2);
|
||||
int g_sampleCountHalfMinusOne : register(i0);
|
||||
|
||||
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_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 float g_support = c[5].z;
|
||||
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
|
||||
float4 kernel(float4 x);
|
||||
@ -22,14 +34,35 @@ float4 kernel(float4 x);
|
||||
float kernel(float x);
|
||||
#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
|
||||
const float weightSum = weights.x + weights.z;
|
||||
colorSum += weightSum * tex2Dlod(s_texture, lerp(textureCoord.xyxy, textureCoord.zwzw, weights.z / weightSum));
|
||||
#else
|
||||
colorSum += weights.x * tex2Dlod(s_texture, textureCoord.xyxy);
|
||||
colorSum += weights.z * tex2Dlod(s_texture, textureCoord.zwzw);
|
||||
[branch]
|
||||
if (g_useSrgbRead)
|
||||
{
|
||||
#endif
|
||||
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
|
||||
}
|
||||
|
||||
@ -42,8 +75,16 @@ float4 getWeights(float4 kernelCoord)
|
||||
#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 sampleCoordFrac = frac(sampleCoord);
|
||||
const float2 sampleCoordInt = sampleCoord - sampleCoordFrac;
|
||||
@ -55,21 +96,54 @@ float4 main(float2 texCoord : TEXCOORD0) : COLOR0
|
||||
const float4 weights = getWeights(kernelCoord);
|
||||
|
||||
#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;
|
||||
addSamples(colorSum, textureCoord, weights);
|
||||
float4 color = 0;
|
||||
addSamples(color, textureCoord, weights);
|
||||
|
||||
for (int i = 0; i < g_sampleCountHalfMinusOne; ++i)
|
||||
{
|
||||
textureCoord += g_textureCoordStepPri.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