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

Added Lanczos display filter

This commit is contained in:
narzoul 2023-03-12 14:55:16 +01:00
parent 714c4f5337
commit 3627af8d37
18 changed files with 356 additions and 106 deletions

View File

@ -5,17 +5,25 @@ namespace Config
namespace Settings
{
DisplayFilter::DisplayFilter()
: MappedSetting("DisplayFilter", "bilinear", { {"point", POINT}, {"bilinear", BILINEAR} })
: MappedSetting("DisplayFilter", "bilinear", {
{"point", POINT},
{"bilinear", BILINEAR},
{"lanczos", LANCZOS},
})
{
}
Setting::ParamInfo DisplayFilter::getParamInfo() const
{
if (BILINEAR == m_value)
switch (m_value)
{
case BILINEAR:
return { "Blur", 0, 100, 0, m_param };
case LANCZOS:
return { "Lobes", 2, 4, 2, m_param };
default:
return {};
}
return {};
}
}
}

View File

@ -11,6 +11,7 @@ namespace Config
public:
static const UINT POINT = 0;
static const UINT BILINEAR = 1;
static const UINT LANCZOS = 2;
DisplayFilter();

View File

@ -12,6 +12,7 @@
#include <D3dDdi/DeviceState.h>
#include <D3dDdi/DrawPrimitive.h>
#include <D3dDdi/ShaderBlitter.h>
#include <D3dDdi/SurfaceRepository.h>
namespace D3dDdi
{
@ -56,6 +57,7 @@ namespace D3dDdi
DrawPrimitive& getDrawPrimitive() { return m_drawPrimitive; }
const D3DDDI_DEVICEFUNCS& getOrigVtable() const { return m_origVtable; }
RGBQUAD* getPalette(UINT paletteHandle) { return m_palettes[paletteHandle].data(); }
SurfaceRepository& getRepo() const { return SurfaceRepository::get(m_adapter); }
Resource* getResource(HANDLE resource);
DeviceState& getState() { return m_state; }
ShaderBlitter& getShaderBlitter() { return m_shaderBlitter; }

View File

@ -48,6 +48,20 @@ namespace D3dDdi
m_state.m_device, &m_data, &m_state.m_pixelShaderConst[m_data.Register][0]);
}
DeviceState::TempPixelShaderConstI::TempPixelShaderConstI(
DeviceState& state, const D3DDDIARG_SETPIXELSHADERCONSTI& data, const ShaderConstI* registers)
: m_state(state)
, m_data(data)
{
state.m_device.getOrigVtable().pfnSetPixelShaderConstI(state.m_device, &data, &registers[0][0]);
}
DeviceState::TempPixelShaderConstI::~TempPixelShaderConstI()
{
m_state.m_device.getOrigVtable().pfnSetPixelShaderConstI(
m_state.m_device, &m_data, &m_state.m_pixelShaderConstI[m_data.Register][0]);
}
DeviceState::DeviceState(Device& device)
: m_device(device)
, m_app{}

View File

@ -59,6 +59,17 @@ namespace D3dDdi
D3DDDIARG_SETPIXELSHADERCONST m_data;
};
class TempPixelShaderConstI
{
public:
TempPixelShaderConstI(DeviceState& state, const D3DDDIARG_SETPIXELSHADERCONSTI& data, const ShaderConstI* registers);
~TempPixelShaderConstI();
private:
DeviceState& m_state;
D3DDDIARG_SETPIXELSHADERCONSTI m_data;
};
class TempStateLock
{
public:

View File

@ -8,7 +8,6 @@
#include <Config/Settings/BltFilter.h>
#include <Config/Settings/ColorKeyMethod.h>
#include <Config/Settings/DepthFormat.h>
#include <Config/Settings/DisplayFilter.h>
#include <Config/Settings/RenderColorDepth.h>
#include <Config/Settings/ResolutionScaleFilter.h>
#include <D3dDdi/Adapter.h>
@ -212,7 +211,7 @@ namespace D3dDdi
if (m_msaaSurface.surface || m_msaaResolvedSurface.surface || m_lockRefSurface.surface)
{
auto& repo = SurfaceRepository::get(m_device.getAdapter());
auto& repo = m_device.getRepo();
repo.release(m_msaaSurface);
repo.release(m_msaaResolvedSurface);
repo.release(m_lockRefSurface);
@ -669,11 +668,12 @@ namespace D3dDdi
void Resource::downscale(Resource*& rt, LONG& srcWidth, LONG& srcHeight, LONG dstWidth, LONG dstHeight)
{
auto& repo = m_device.getRepo();
while (srcWidth > 2 * dstWidth || srcHeight > 2 * dstHeight)
{
const LONG newSrcWidth = std::max(dstWidth, (srcWidth + 1) / 2);
const LONG newSrcHeight = std::max(dstHeight, (srcHeight + 1) / 2);
auto& nextRt = getNextRenderTarget(rt, newSrcWidth, newSrcHeight);
auto& nextRt = repo.getNextRenderTarget(newSrcWidth, newSrcHeight, rt);
if (!nextRt.resource)
{
return;
@ -808,17 +808,6 @@ namespace D3dDdi
return { D3DDDIMULTISAMPLE_NONE, 0 };
}
const SurfaceRepository::Surface& Resource::getNextRenderTarget(Resource* currentRt, DWORD width, DWORD height)
{
auto& repo = SurfaceRepository::get(m_device.getAdapter());
auto nextRt = &repo.getTempRenderTarget(width, height, 0);
if (nextRt->resource == currentRt)
{
nextRt = &repo.getTempRenderTarget(width, height, 1);
}
return *nextRt;
}
RECT Resource::getRect(UINT subResourceIndex) const
{
const auto& si = m_fixedData.pSurfList[subResourceIndex];
@ -855,8 +844,7 @@ namespace D3dDdi
const RECT srcRect = { 0, 0, static_cast<LONG>(si.Width), static_cast<LONG>(si.Height) };
if (!m_fixedData.Flags.Texture)
{
auto& repo = SurfaceRepository::get(m_device.getAdapter());
auto& texture = repo.getTempTexture(si.Width, si.Height, m_fixedData.Format);
auto& texture = m_device.getRepo().getTempTexture(si.Width, si.Height, m_fixedData.Format);
if (!texture.resource)
{
return;
@ -1193,8 +1181,8 @@ namespace D3dDdi
if (!m_colorKeyedSurface.surface)
{
auto& repo = SurfaceRepository::get(m_device.getAdapter());
repo.getSurface(m_colorKeyedSurface, m_fixedData.pSurfList[0].Width, m_fixedData.pSurfList[0].Height,
m_device.getRepo().getSurface(m_colorKeyedSurface,
m_fixedData.pSurfList[0].Width, m_fixedData.pSurfList[0].Height,
D3DDDIFMT_A8R8G8B8, DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY |
(m_fixedData.MipLevels > 1 ? DDSCAPS_MIPMAP : 0),
m_fixedData.SurfCount,
@ -1244,8 +1232,8 @@ namespace D3dDdi
data.DstRect = g_presentationRect;
}
auto& repo = SurfaceRepository::get(m_device.getAdapter());
const auto& rtSurface = repo.getTempRenderTarget(srcWidth, srcHeight);
auto& repo = m_device.getRepo();
const auto& rtSurface = repo.getNextRenderTarget(srcWidth, srcHeight);
auto rt = rtSurface.resource ? rtSurface.resource : this;
auto rtIndex = rtSurface.resource ? 0 : data.DstSubResourceIndex;
auto rtRect = rtSurface.resource ? data.SrcRect : data.DstRect;
@ -1300,39 +1288,7 @@ namespace D3dDdi
const LONG dstHeight = data.DstRect.bottom - data.DstRect.top;
downscale(rt, data.SrcRect.right, data.SrcRect.bottom, dstWidth, dstHeight);
const SurfaceRepository::Surface* rtGamma = nullptr;
if (!ShaderBlitter::isGammaRampDefault() &&
SurfaceRepository::get(m_device.getAdapter()).getGammaRampTexture())
{
rtGamma = &getNextRenderTarget(rt, dstWidth, dstHeight);
}
const bool useGamma = rtGamma && rtGamma->resource;
auto& rtNext = useGamma ? *rtGamma->resource : *this;
auto rtNextIndex = useGamma ? 0 : data.DstSubResourceIndex;
auto rtNextRect = useGamma ? RECT{ 0, 0, dstWidth, dstHeight } : data.DstRect;
if (Config::Settings::DisplayFilter::BILINEAR == Config::displayFilter.get())
{
m_device.getShaderBlitter().genBilinearBlt(rtNext, rtNextIndex, rtNextRect,
*rt, data.SrcRect, Config::displayFilter.getParam());
}
else
{
D3DDDIARG_BLT blt = {};
blt.hSrcResource = *rt;
blt.SrcSubResourceIndex = 0;
blt.SrcRect = data.SrcRect;
blt.hDstResource = rtNext;
blt.DstSubResourceIndex = rtNextIndex;
blt.DstRect = rtNextRect;
blt.Flags.Point = 1;
m_device.getOrigVtable().pfnBlt(m_device, &blt);
}
if (useGamma)
{
m_device.getShaderBlitter().gammaBlt(*this, data.DstSubResourceIndex, data.DstRect, rtNext, rtNextRect);
}
m_device.getShaderBlitter().displayBlt(*this, data.DstSubResourceIndex, data.DstRect, *rt, 0, data.SrcRect);
clearRectExterior(data.DstSubResourceIndex, data.DstRect);
@ -1351,7 +1307,7 @@ namespace D3dDdi
std::vector<Gdi::Window::LayeredWindow> layeredWindows, const RECT& monitorRect)
{
auto& blitter = m_device.getShaderBlitter();
auto& repo = SurfaceRepository::get(m_device.getAdapter());
auto& repo = m_device.getRepo();
for (auto& layeredWindow : layeredWindows)
{
@ -1513,7 +1469,7 @@ namespace D3dDdi
return LOG_RESULT(m_device.getOrigVtable().pfnBlt(m_device, &data));
}
auto& repo = SurfaceRepository::get(m_device.getAdapter());
auto& repo = m_device.getRepo();
Resource* srcRes = &srcResource;
UINT srcIndex = data.SrcSubResourceIndex;
@ -1574,7 +1530,7 @@ namespace D3dDdi
{
LONG width = data.DstRect.right - data.DstRect.left;
LONG height = data.DstRect.bottom - data.DstRect.top;
auto& rt = getNextRenderTarget(srcRes, width, height);
auto& rt = repo.getNextRenderTarget(width, height, srcRes);
if (!rt.resource)
{
return LOG_RESULT(E_OUTOFMEMORY);
@ -1716,39 +1672,36 @@ namespace D3dDdi
static_cast<LONG>(m_fixedData.pSurfList[0].Height) != m_scaledSize.cy;
if (D3DDDIMULTISAMPLE_NONE != msaa.first || m_fixedData.Format != formatConfig || isScaled)
{
auto& repo = m_device.getRepo();
const DWORD caps = (m_fixedData.Flags.ZBuffer ? DDSCAPS_ZBUFFER : DDSCAPS_3DDEVICE) | DDSCAPS_VIDEOMEMORY;
if (D3DDDIMULTISAMPLE_NONE != msaa.first)
{
g_msaaOverride = msaa;
SurfaceRepository::get(m_device.getAdapter()).getSurface(m_msaaSurface,
scaledSize.cx, scaledSize.cy, formatConfig, caps, m_fixedData.SurfCount);
repo.getSurface(m_msaaSurface, scaledSize.cx, scaledSize.cy, formatConfig, caps, m_fixedData.SurfCount);
g_msaaOverride = {};
}
if (m_fixedData.Flags.ZBuffer && m_msaaSurface.resource)
{
g_msaaOverride = msaa;
SurfaceRepository::get(m_device.getAdapter()).getSurface(m_nullSurface,
scaledSize.cx, scaledSize.cy, FOURCC_NULL,
repo.getSurface(m_nullSurface, scaledSize.cx, scaledSize.cy, FOURCC_NULL,
DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY, m_fixedData.SurfCount);
g_msaaOverride = {};
}
SurfaceRepository::get(m_device.getAdapter()).getSurface(m_msaaResolvedSurface,
scaledSize.cx, scaledSize.cy, m_nullSurface.resource ? FOURCC_INTZ : formatConfig,
caps, m_fixedData.SurfCount);
repo.getSurface(m_msaaResolvedSurface, scaledSize.cx, scaledSize.cy,
m_nullSurface.resource ? FOURCC_INTZ : formatConfig, caps, m_fixedData.SurfCount);
if (!m_msaaResolvedSurface.resource && m_msaaSurface.resource)
{
m_msaaSurface = {};
SurfaceRepository::get(m_device.getAdapter()).getSurface(m_msaaResolvedSurface,
scaledSize.cx, scaledSize.cy, formatConfig, caps, m_fixedData.SurfCount);
repo.getSurface(m_msaaResolvedSurface, scaledSize.cx, scaledSize.cy,
formatConfig, caps, m_fixedData.SurfCount);
}
if (!m_fixedData.Flags.ZBuffer && m_msaaResolvedSurface.resource)
{
SurfaceRepository::get(m_device.getAdapter()).getSurface(m_lockRefSurface,
m_fixedData.pSurfList[0].Width, m_fixedData.pSurfList[0].Height, m_fixedData.Format,
DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, m_fixedData.SurfCount);
repo.getSurface(m_lockRefSurface, m_fixedData.pSurfList[0].Width, m_fixedData.pSurfList[0].Height,
m_fixedData.Format, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, m_fixedData.SurfCount);
if (isScaled && m_device.getGdiResource() == this)
{

View File

@ -114,7 +114,6 @@ namespace D3dDdi
void fixResourceData();
D3DDDIFORMAT getFormatConfig();
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> getMultisampleConfig();
const SurfaceRepository::Surface& getNextRenderTarget(Resource* currentRt, DWORD width, DWORD height);
SIZE getScaledSize();
bool isValidRect(UINT subResourceIndex, const RECT& rect);
void loadFromLockRefResource(UINT subResourceIndex);

View File

@ -1,5 +1,6 @@
#include <Common/Log.h>
#include <Common/Rect.h>
#include <Config/Settings/DisplayFilter.h>
#include <D3dDdi/Adapter.h>
#include <D3dDdi/Device.h>
#include <D3dDdi/Resource.h>
@ -12,6 +13,7 @@
#include <Shaders/DrawCursor.h>
#include <Shaders/Gamma.h>
#include <Shaders/GenBilinear.h>
#include <Shaders/Lanczos.h>
#include <Shaders/LockRef.h>
#include <Shaders/PaletteLookup.h>
#include <Shaders/TextureSampler.h>
@ -61,6 +63,7 @@ namespace D3dDdi
, m_psDrawCursor(createPixelShader(g_psDrawCursor))
, m_psGamma(createPixelShader(g_psGamma))
, m_psGenBilinear(createPixelShader(g_psGenBilinear))
, m_psLanczos(createPixelShader(g_psLanczos))
, m_psLockRef(createPixelShader(g_psLockRef))
, m_psPaletteLookup(createPixelShader(g_psPaletteLookup))
, m_psTextureSampler(createPixelShader(g_psTextureSampler))
@ -172,6 +175,108 @@ namespace D3dDdi
m_psColorKeyBlend.get(), D3DTEXF_POINT);
}
void ShaderBlitter::convolution(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
bool isHorizontal, float kernelStep, int sampleCount, float support, HANDLE pixelShader)
{
LOG_FUNC("ShaderBlitter::convolution", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect,
isHorizontal, kernelStep, sampleCount, support, pixelShader);
const auto& srcDesc = srcResource.getFixedDesc().pSurfList[0];
const Float2 textureSize(srcDesc.Width, srcDesc.Height);
const Float2 textureSizeRcp = Float2(1) / textureSize;
const float textureStep = isHorizontal ? textureSizeRcp.x : textureSizeRcp.y;
const int firstSampleOffset = -sampleCount / 2 + 1;
const float firstKernelOffset = firstSampleOffset * kernelStep;
const float firstTextureOffset = firstSampleOffset * textureStep;
std::array<DeviceState::ShaderConstF, 5> reg = {};
reg[0] = { textureSize.x, textureSize.y, textureSizeRcp.x, textureSizeRcp.y };
if (isHorizontal)
{
reg[1] = { firstTextureOffset, 0, firstKernelOffset, 0 };
reg[2] = { textureStep, 0, kernelStep, 0 };
reg[3] = { -0.5f, 0, 0.5f * textureSizeRcp.x, 0.5f * textureSizeRcp.y };
}
else
{
reg[1] = { 0, firstTextureOffset, 0, firstKernelOffset };
reg[2] = { 0, textureStep, 0, kernelStep };
reg[3] = { 0, -0.5f, 0.5f * textureSizeRcp.x, 0.5f * textureSizeRcp.y };
}
reg[4] = { support, 1.0f / support, 0, 0 };
DeviceState::TempPixelShaderConst tempPsConst(m_device.getState(), { 0, reg.size() }, reg.data());
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
pixelShader, D3DTEXF_LINEAR | D3DTEXF_SRGB);
}
void ShaderBlitter::convolutionBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
Float2 support, HANDLE pixelShader)
{
LOG_FUNC("ShaderBlitter::convolutionBlt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect, support, pixelShader);
const Int2 dstSize(dstRect.right - dstRect.left, dstRect.bottom - dstRect.top);
const Int2 srcSize(srcRect.right - srcRect.left, srcRect.bottom - srcRect.top);
const Float2 scale = Float2(dstSize) / Float2(srcSize);
const Float2 kernelStep = min(scale, Float2(1));
const Int2 sampleCount = min(Float2(2) * ceil(support / kernelStep), Float2(255));
if (srcSize.y == dstSize.y)
{
return convolution(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
true, kernelStep.x, sampleCount.x, support.x, pixelShader);
}
else if (srcSize.x == dstSize.x)
{
return convolution(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
false, kernelStep.y, sampleCount.y, support.y, pixelShader);
}
const bool isHorizontalFirst = dstSize.x * srcSize.y <= srcSize.x * dstSize.y;
RECT rect = { 0, 0, srcSize.x, srcSize.y };
if (dstSize.x * srcSize.y <= srcSize.x * dstSize.y)
{
rect.right = dstSize.x;
}
else
{
rect.bottom = dstSize.y;
}
auto rt = m_device.getRepo().getNextRenderTarget(rect.right, rect.bottom, &srcResource, &dstResource).resource;
if (!rt)
{
return;
}
const std::array<DeviceState::ShaderConstI, 2> reg = { {
{ sampleCount.x },
{ sampleCount.y }
} };
DeviceState::TempPixelShaderConstI tempPsConstI(m_device.getState(), { 0, reg.size()}, reg.data());
if (isHorizontalFirst)
{
convolution(*rt, 0, rect, srcResource, srcSubResourceIndex, srcRect,
true, kernelStep.x, sampleCount.x, support.x, pixelShader);
convolution(dstResource, dstSubResourceIndex, dstRect, *rt, 0, rect,
false, kernelStep.y, sampleCount.y, support.y, pixelShader);
}
else
{
convolution(*rt, 0, rect, srcResource, srcSubResourceIndex, srcRect,
false, kernelStep.y, sampleCount.y, support.y, pixelShader);
convolution(dstResource, dstSubResourceIndex, dstRect, *rt, 0, rect,
true, kernelStep.x, sampleCount.x, support.x, pixelShader);
}
}
std::unique_ptr<void, ResourceDeleter> ShaderBlitter::createPixelShader(const BYTE* code, UINT size)
{
D3DDDIARG_CREATEPIXELSHADER data = {};
@ -214,7 +319,7 @@ namespace D3dDdi
{
LOG_FUNC("ShaderBlitter::cursorBlt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect, cursor, pt);
auto& repo = SurfaceRepository::get(m_device.getAdapter());
auto& repo = m_device.getRepo();
auto cur = repo.getCursor(cursor);
if (!cur.colorTexture)
{
@ -316,6 +421,67 @@ namespace D3dDdi
m_device.flushPrimitives();
}
void ShaderBlitter::displayBlt(const 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();
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;
}
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())
{
case Config::Settings::DisplayFilter::POINT:
m_device.getShaderBlitter().textureBlt(rt, rtIndex, rtRect,
srcResource, srcSubResourceIndex, srcRect, D3DTEXF_POINT);
break;
case Config::Settings::DisplayFilter::BILINEAR:
m_device.getShaderBlitter().genBilinearBlt(rt, rtIndex, rtRect,
srcResource, srcSubResourceIndex, srcRect, Config::displayFilter.getParam());
break;
case Config::Settings::DisplayFilter::LANCZOS:
m_device.getShaderBlitter().lanczosBlt(rt, rtIndex, rtRect,
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)
{
m_vertices[0].xy = { dstRect.left - 0.5f, dstRect.top - 0.5f };
@ -333,12 +499,12 @@ namespace D3dDdi
}
void ShaderBlitter::gammaBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, const RECT& srcRect)
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect)
{
LOG_FUNC("ShaderBlitter::gammaBlt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
static_cast<HANDLE>(srcResource), srcRect);
static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect);
auto gammaRampTexture(SurfaceRepository::get(m_device.getAdapter()).getGammaRampTexture());
auto gammaRampTexture(m_device.getRepo().getGammaRampTexture());
if (!gammaRampTexture)
{
return;
@ -371,13 +537,13 @@ namespace D3dDdi
}
void ShaderBlitter::genBilinearBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, const RECT& srcRect, UINT blurPercent)
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, UINT blurPercent)
{
LOG_FUNC("ShaderBlitter::genBilinearBlt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
static_cast<HANDLE>(srcResource), srcRect, blurPercent);
static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect, blurPercent);
if (100 == blurPercent)
{
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, 0, srcRect,
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
m_psTextureSampler.get(), D3DTEXF_LINEAR | D3DTEXF_SRGB);
return;
}
@ -396,13 +562,18 @@ namespace D3dDdi
} };
DeviceState::TempPixelShaderConst tempPsConst(m_device.getState(), { 0, registers.size() }, registers.data());
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, 0, srcRect, m_psGenBilinear.get(),
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect, m_psGenBilinear.get(),
D3DTEXF_LINEAR | D3DTEXF_SRGB);
}
bool ShaderBlitter::isGammaRampDefault()
void ShaderBlitter::lanczosBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, UINT lobes)
{
return g_isGammaRampDefault;
LOG_FUNC("ShaderBlitter::lanczosBlt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect, lobes);
convolutionBlt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
lobes, m_psLanczos.get());
}
void ShaderBlitter::lockRefBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
@ -425,7 +596,7 @@ namespace D3dDdi
static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect,
Compat::array(reinterpret_cast<void**>(palette), 256));
auto paletteTexture(SurfaceRepository::get(m_device.getAdapter()).getPaletteTexture());
auto paletteTexture(m_device.getRepo().getPaletteTexture());
if (!paletteTexture)
{
return;

View File

@ -5,6 +5,7 @@
#include <Windows.h>
#include <Common/Vector.h>
#include <D3dDdi/ResourceDeleter.h>
#include <Gdi/Region.h>
@ -30,10 +31,14 @@ 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,
const Resource& srcResource, const RECT& srcRect);
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect);
void genBilinearBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, const RECT& srcRect, UINT blurPercent);
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, UINT blurPercent);
void lanczosBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, UINT lobes);
void lockRefBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
const Resource& lockRefResource);
@ -44,7 +49,6 @@ namespace D3dDdi
UINT filter, const DeviceState::ShaderConstF* srcColorKey = nullptr, const BYTE* alpha = nullptr,
const Gdi::Region& srcRgn = nullptr);
static bool isGammaRampDefault();
static void resetGammaRamp();
static void setGammaRamp(const D3DDDI_GAMMA_RAMP_RGB256x3x16& ramp);
@ -62,6 +66,12 @@ namespace D3dDdi
void blt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, HANDLE pixelShader,
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, float kernelStep, int sampleCount, float support, HANDLE pixelShader);
void convolutionBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
Float2 support, HANDLE pixelShader);
template <int N>
std::unique_ptr<void, ResourceDeleter> createPixelShader(const BYTE(&code)[N])
@ -82,6 +92,7 @@ namespace D3dDdi
std::unique_ptr<void, ResourceDeleter> m_psDrawCursor;
std::unique_ptr<void, ResourceDeleter> m_psGamma;
std::unique_ptr<void, ResourceDeleter> m_psGenBilinear;
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_psTextureSampler;

View File

@ -229,6 +229,23 @@ namespace D3dDdi
return surface.resource;
}
const SurfaceRepository::Surface& SurfaceRepository::getNextRenderTarget(
DWORD width, DWORD height, const Resource* currentSrcRt, const Resource* currentDstRt)
{
std::size_t index = 0;
while (index < m_renderTargets.size())
{
auto rt = m_renderTargets[index].resource;
if (!rt || rt != currentSrcRt && rt != currentDstRt)
{
break;
}
++index;
}
return getTempSurface(m_renderTargets[index], width, height, D3DDDIFMT_A8R8G8B8,
DDSCAPS_3DDEVICE | DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY);
}
Resource* SurfaceRepository::getPaletteTexture()
{
return getSurface(m_paletteTexture, 256, 1, D3DDDIFMT_A8R8G8B8, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY).resource;
@ -263,16 +280,6 @@ namespace D3dDdi
return surface;
}
const SurfaceRepository::Surface& SurfaceRepository::getTempRenderTarget(DWORD width, DWORD height, UINT index)
{
if (index >= m_renderTargets.size())
{
m_renderTargets.resize(index + 1);
}
return getTempSurface(m_renderTargets[index], width, height, D3DDDIFMT_A8R8G8B8,
DDSCAPS_3DDEVICE | DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY);
}
SurfaceRepository::Surface& SurfaceRepository::getTempSurface(Surface& surface, DWORD width, DWORD height,
D3DDDIFORMAT format, DWORD caps, UINT surfaceCount)
{

View File

@ -1,7 +1,9 @@
#pragma once
#include <array>
#include <functional>
#include <map>
#include <vector>
#include <ddraw.h>
@ -41,9 +43,10 @@ namespace D3dDdi
Resource* getLogicalXorTexture();
Resource* getPaletteTexture();
Resource* getGammaRampTexture();
const Surface& getNextRenderTarget(DWORD width, DWORD height,
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);
const Surface& getTempRenderTarget(DWORD width, DWORD height, UINT index = 0);
Surface& getTempSysMemSurface(DWORD width, DWORD height);
Surface& getTempSurface(Surface& surface, DWORD width, DWORD height,
D3DDDIFORMAT format, DWORD caps, UINT surfaceCount = 1);
@ -74,7 +77,7 @@ namespace D3dDdi
Surface m_gammaRampTexture;
Surface m_logicalXorTexture;
Surface m_paletteTexture;
std::vector<Surface> m_renderTargets;
std::array<Surface, 3> m_renderTargets;
std::map<D3DDDIFORMAT, Surface> m_textures;
std::vector<Surface> m_releasedSurfaces;
Surface m_sysMemSurface;

View File

@ -194,7 +194,7 @@ namespace
return nullptr;
}
auto& repo = D3dDdi::SurfaceRepository::get(device->getAdapter());
auto& repo = device->getRepo();
D3dDdi::SurfaceRepository::Surface surface = {};
repo.getSurface(surface, width, height, D3DDDIFMT_X8R8G8B8,
DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY);

View File

@ -51,7 +51,7 @@ namespace
return LOG_RESULT(nullptr);
}
auto& repo = D3dDdi::SurfaceRepository::get(device->getAdapter());
auto& repo = device->getRepo();
D3dDdi::SurfaceRepository::Surface surface = {};
repo.getSurface(surface, 1, 1, D3DDDIFMT_X8R8G8B8, DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY);

View File

@ -80,7 +80,7 @@ namespace
return bltFunc(This, lpDDSrcSurface, lpSrcRect);
}
auto& repo = D3dDdi::SurfaceRepository::get(srcResource->getDevice().getAdapter());
auto& repo = srcResource->getDevice().getRepo();
RECT srcRect = getRect(lpSrcRect, srcDesc);
auto& tex = repo.getTempTexture(srcRect.right - srcRect.left, srcRect.bottom - srcRect.top,
srcResource->getOrigDesc().Format);

View File

@ -91,7 +91,7 @@
<FxCompile>
<HeaderFileOutput>$(IntDir)%(RelativeDir)%(Filename).h</HeaderFileOutput>
<ObjectFileOutput />
<ShaderModel>2.0</ShaderModel>
<ShaderModel>3.0</ShaderModel>
<ShaderType>Pixel</ShaderType>
<DisableOptimizations>false</DisableOptimizations>
</FxCompile>
@ -128,7 +128,7 @@
<FxCompile>
<HeaderFileOutput>$(IntDir)%(RelativeDir)%(Filename).h</HeaderFileOutput>
<ObjectFileOutput />
<ShaderModel>2.0</ShaderModel>
<ShaderModel>3.0</ShaderModel>
<ShaderType>Pixel</ShaderType>
</FxCompile>
</ItemDefinitionGroup>
@ -457,6 +457,7 @@
</ItemGroup>
<ItemGroup>
<None Include="genversion.ps1" />
<None Include="Shaders\Convolution.hlsli" />
</ItemGroup>
<ItemGroup>
<FxCompile Include="Shaders\ColorKey.hlsl" />
@ -465,6 +466,7 @@
<FxCompile Include="Shaders\DrawCursor.hlsl" />
<FxCompile Include="Shaders\Gamma.hlsl" />
<FxCompile Include="Shaders\GenBilinear.hlsl" />
<FxCompile Include="Shaders\Lanczos.hlsl" />
<FxCompile Include="Shaders\LockRef.hlsl" />
<FxCompile Include="Shaders\PaletteLookup.hlsl" />
<FxCompile Include="Shaders\TextureSampler.hlsl" />
@ -473,6 +475,8 @@
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Vertex</ShaderType>
<VariableName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">g_vs%(Filename)</VariableName>
<VariableName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">g_vs%(Filename)</VariableName>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">2.0</ShaderModel>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">2.0</ShaderModel>
</FxCompile>
</ItemGroup>
<ItemGroup>

View File

@ -665,7 +665,7 @@
</ClInclude>
<ClInclude Include="Config\Settings\ColorKeyMethod.h">
<Filter>Header Files\Config\Settings</Filter>
</ClInclude>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Gdi\Gdi.cpp">
@ -1055,7 +1055,7 @@
<ClCompile Include="Config\Settings\ColorKeyMethod.cpp">
<Filter>Source Files\Config\Settings</Filter>
</ClCompile>
</ItemGroup>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="DDrawCompat.rc">
<Filter>Resource Files</Filter>
@ -1065,6 +1065,9 @@
<None Include="genversion.ps1">
<Filter>Resource Files</Filter>
</None>
<None Include="Shaders\Convolution.hlsli">
<Filter>Shaders</Filter>
</None>
</ItemGroup>
<ItemGroup>
<FxCompile Include="Shaders\PaletteLookup.hlsl">
@ -1097,10 +1100,13 @@
<FxCompile Include="Shaders\ColorKeyBlend.hlsl">
<Filter>Shaders</Filter>
</FxCompile>
<FxCompile Include="Shaders\Lanczos.hlsl">
<Filter>Shaders</Filter>
</FxCompile>
</ItemGroup>
<ItemGroup>
<Image Include="arrow.bmp">
<Filter>Resource Files</Filter>
</Image>
</ItemGroup>
</Project>
</Project>

View File

@ -0,0 +1,50 @@
sampler2D s_texture : register(s0);
int g_sampleCountX : register(i0);
int g_sampleCountY : register(i1);
float4 c[32] : register(c0);
static const float2 g_textureSize = c[0].xy;
static const float2 g_textureSizeRcp = c[0].zw;
static const float4 g_firstCoordOffset = c[1];
static const float4 g_coordStep = c[2];
static const float2 g_sampleCoordOffset = c[3].xy;
static const float2 g_halfTexelOffset = c[3].zw;
static const float g_support = c[4].x;
static const float g_supportRcp = c[4].y;
float kernel(float x);
float4 main(float2 texCoord : TEXCOORD0) : COLOR0
{
const float2 sampleCoord = texCoord * g_textureSize + g_sampleCoordOffset;
const float2 sampleCoordFrac = frac(sampleCoord);
const float2 sampleCoordInt = sampleCoord - sampleCoordFrac;
const float2 centeredTexCoord = sampleCoordInt * g_textureSizeRcp + g_halfTexelOffset;
float4 coord = float4(centeredTexCoord, -sampleCoordFrac * g_coordStep.zw) + g_firstCoordOffset;
float4 coordStep = g_coordStep;
float4 colorSum = 0;
if (0 != coordStep.x)
{
for (int i = 0; i < g_sampleCountX; ++i)
{
coordStep.w = kernel(coord.z);
float4 color = tex2Dlod(s_texture, coord);
colorSum += coordStep.w * color;
coord += coordStep;
}
return colorSum / coord.w;
}
else
{
for (int i = 0; i < g_sampleCountY; ++i)
{
coordStep.z = kernel(coord.w);
float4 color = tex2Dlod(s_texture, coord);
colorSum += coordStep.z * color;
coord += coordStep;
}
return colorSum / coord.z;
}
}

View File

@ -0,0 +1,10 @@
#include "Convolution.hlsli"
float kernel(float x)
{
x = min(abs(x), g_support);
const float PI = radians(180);
const float pi_x = PI * x;
const float pi_x_2 = pi_x * pi_x;
return 0 == pi_x_2 ? 1 : (g_support * sin(pi_x) * sin(pi_x * g_supportRcp) / pi_x_2);
}