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:
parent
714c4f5337
commit
3627af8d37
@ -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 {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ namespace Config
|
||||
public:
|
||||
static const UINT POINT = 0;
|
||||
static const UINT BILINEAR = 1;
|
||||
static const UINT LANCZOS = 2;
|
||||
|
||||
DisplayFilter();
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -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, ®isters[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{}
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -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>
|
50
DDrawCompat/Shaders/Convolution.hlsli
Normal file
50
DDrawCompat/Shaders/Convolution.hlsli
Normal 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;
|
||||
}
|
||||
}
|
10
DDrawCompat/Shaders/Lanczos.hlsl
Normal file
10
DDrawCompat/Shaders/Lanczos.hlsl
Normal 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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user