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

Perform P8 to R8G8B8 conversion in pixel shader

This commit is contained in:
narzoul 2021-06-02 00:34:50 +02:00
parent 74460b2d24
commit 51a451f424
15 changed files with 772 additions and 131 deletions

View File

@ -44,6 +44,7 @@ namespace D3dDdi
, m_sharedPrimary(nullptr)
, m_drawPrimitive(*this)
, m_state(*this)
, m_shaderBlitter(*this)
{
}
@ -51,6 +52,7 @@ namespace D3dDdi
{
s_devices.try_emplace(device, adapter, device);
}
bool Device::checkSrcColorKeySupport()
{
if (!(m_adapter.getDDrawCaps().CKeyCaps & DDRAW_CKEYCAPS_SRCBLT))
@ -211,6 +213,23 @@ namespace D3dDdi
return it != m_resources.end() ? &it->second : nullptr;
}
void Device::prepareForRendering(HANDLE resource, UINT subResourceIndex, bool isReadOnly)
{
auto it = m_resources.find(resource);
if (it != m_resources.end())
{
it->second.prepareForRendering(subResourceIndex, isReadOnly);
}
}
void Device::prepareForRendering()
{
if (m_renderTarget)
{
m_renderTarget->prepareForRendering(m_renderTargetSubResourceIndex, false);
}
}
void Device::setGdiResourceHandle(HANDLE resource)
{
ScopedCriticalSection lock;
@ -234,20 +253,12 @@ namespace D3dDdi
}
}
void Device::prepareForRendering(HANDLE resource, UINT subResourceIndex, bool isReadOnly)
void Device::setRenderTarget(const D3DDDIARG_SETRENDERTARGET& data)
{
auto it = m_resources.find(resource);
if (it != m_resources.end())
if (0 == data.RenderTargetIndex)
{
it->second.prepareForRendering(subResourceIndex, isReadOnly);
}
}
void Device::prepareForRendering()
{
if (m_renderTarget)
{
m_renderTarget->prepareForRendering(m_renderTargetSubResourceIndex, false);
m_renderTarget = getResource(data.hRenderTarget);
m_renderTargetSubResourceIndex = data.SubResourceIndex;
}
}
@ -335,7 +346,7 @@ namespace D3dDdi
g_gdiResource = nullptr;
}
m_drawPrimitive.removeSysMemVertexBuffer(resource);
m_state.removeTexture(resource);
m_state.onDestroyResource(resource);
}
return result;
@ -412,28 +423,6 @@ namespace D3dDdi
return m_origVtable.pfnPresent1(m_device, data);
}
HRESULT Device::pfnSetRenderTarget(const D3DDDIARG_SETRENDERTARGET* data)
{
flushPrimitives();
HRESULT result = m_origVtable.pfnSetRenderTarget(m_device, data);
if (SUCCEEDED(result) && 0 == data->RenderTargetIndex)
{
m_renderTarget = getResource(data->hRenderTarget);
m_renderTargetSubResourceIndex = data->SubResourceIndex;
}
return result;
}
HRESULT Device::pfnSetStreamSource(const D3DDDIARG_SETSTREAMSOURCE* data)
{
return m_drawPrimitive.setStreamSource(*data);
}
HRESULT Device::pfnSetStreamSourceUm(const D3DDDIARG_SETSTREAMSOURCEUM* data, const void* umBuffer)
{
return m_drawPrimitive.setStreamSourceUm(*data, umBuffer);
}
HRESULT Device::pfnUnlock(const D3DDDIARG_UNLOCK* data)
{
flushPrimitives();

View File

@ -9,6 +9,7 @@
#include <D3dDdi/DeviceState.h>
#include <D3dDdi/DrawPrimitive.h>
#include <D3dDdi/ShaderBlitter.h>
namespace D3dDdi
{
@ -43,9 +44,6 @@ namespace D3dDdi
HRESULT pfnOpenResource(D3DDDIARG_OPENRESOURCE* data);
HRESULT pfnPresent(const D3DDDIARG_PRESENT* data);
HRESULT pfnPresent1(D3DDDIARG_PRESENT1* data);
HRESULT pfnSetRenderTarget(const D3DDDIARG_SETRENDERTARGET* data);
HRESULT pfnSetStreamSource(const D3DDDIARG_SETSTREAMSOURCE* data);
HRESULT pfnSetStreamSourceUm(const D3DDDIARG_SETSTREAMSOURCEUM* data, const void* umBuffer);
HRESULT pfnUnlock(const D3DDDIARG_UNLOCK* data);
Adapter& getAdapter() const { return m_adapter; }
@ -53,11 +51,13 @@ namespace D3dDdi
const D3DDDI_DEVICEFUNCS& getOrigVtable() const { return m_origVtable; }
Resource* getResource(HANDLE resource);
DeviceState& getState() { return m_state; }
ShaderBlitter& getShaderBlitter() { return m_shaderBlitter; }
HRESULT createPrivateResource(D3DDDIARG_CREATERESOURCE2& data);
void flushPrimitives() { m_drawPrimitive.flushPrimitives(); }
void prepareForRendering(HANDLE resource, UINT subResourceIndex, bool isReadOnly);
void prepareForRendering();
void setRenderTarget(const D3DDDIARG_SETRENDERTARGET& data);
bool isSrcColorKeySupported() const { return m_isSrcColorKeySupported; }
@ -84,6 +84,7 @@ namespace D3dDdi
HANDLE m_sharedPrimary;
DrawPrimitive m_drawPrimitive;
DeviceState m_state;
ShaderBlitter m_shaderBlitter;
bool m_isSrcColorKeySupported;
static std::map<HANDLE, Device> s_devices;

View File

@ -64,20 +64,21 @@ namespace
SET_DEVICE_FUNC(pfnOpenResource);
SET_DEVICE_FUNC(pfnPresent);
SET_DEVICE_FUNC(pfnPresent1);
SET_DEVICE_FUNC(pfnSetRenderTarget);
SET_DEVICE_FUNC(pfnSetStreamSource);
SET_DEVICE_FUNC(pfnSetStreamSourceUm);
SET_DEVICE_FUNC(pfnUnlock);
SET_DEVICE_STATE_FUNC(pfnCreateVertexShaderDecl);
SET_DEVICE_STATE_FUNC(pfnDeletePixelShader);
SET_DEVICE_STATE_FUNC(pfnDeleteVertexShaderDecl);
SET_DEVICE_STATE_FUNC(pfnDeleteVertexShaderFunc);
SET_DEVICE_STATE_FUNC(pfnSetDepthStencil);
SET_DEVICE_STATE_FUNC(pfnSetPixelShader);
SET_DEVICE_STATE_FUNC(pfnSetPixelShaderConst);
SET_DEVICE_STATE_FUNC(pfnSetPixelShaderConstB);
SET_DEVICE_STATE_FUNC(pfnSetPixelShaderConstI);
SET_DEVICE_STATE_FUNC(pfnSetRenderState);
SET_DEVICE_STATE_FUNC(pfnSetRenderTarget);
SET_DEVICE_STATE_FUNC(pfnSetStreamSource);
SET_DEVICE_STATE_FUNC(pfnSetStreamSourceUm);
SET_DEVICE_STATE_FUNC(pfnSetTexture);
SET_DEVICE_STATE_FUNC(pfnSetTextureStageState);
SET_DEVICE_STATE_FUNC(pfnSetVertexShaderConst);
@ -85,6 +86,7 @@ namespace
SET_DEVICE_STATE_FUNC(pfnSetVertexShaderConstI);
SET_DEVICE_STATE_FUNC(pfnSetVertexShaderDecl);
SET_DEVICE_STATE_FUNC(pfnSetVertexShaderFunc);
SET_DEVICE_STATE_FUNC(pfnSetViewport);
SET_DEVICE_STATE_FUNC(pfnSetZRange);
SET_DEVICE_STATE_FUNC(pfnUpdateWInfo);
@ -94,10 +96,8 @@ namespace
SET_FLUSH_PRIMITIVES_FUNC(pfnDiscard);
SET_FLUSH_PRIMITIVES_FUNC(pfnGenerateMipSubLevels);
SET_FLUSH_PRIMITIVES_FUNC(pfnSetClipPlane);
SET_FLUSH_PRIMITIVES_FUNC(pfnSetDepthStencil);
SET_FLUSH_PRIMITIVES_FUNC(pfnSetPalette);
SET_FLUSH_PRIMITIVES_FUNC(pfnSetScissorRect);
SET_FLUSH_PRIMITIVES_FUNC(pfnSetViewport);
SET_FLUSH_PRIMITIVES_FUNC(pfnStateSet);
SET_FLUSH_PRIMITIVES_FUNC(pfnTexBlt);
SET_FLUSH_PRIMITIVES_FUNC(pfnTexBlt1);

View File

@ -4,37 +4,138 @@
#include <D3dDdi/DrawPrimitive.h>
#include <D3dDdi/Log/DeviceFuncsLog.h>
namespace
{
const UINT UNINITIALIZED_STATE = 0xBAADBAAD;
const HANDLE UNINITIALIZED_HANDLE = reinterpret_cast<HANDLE>(0xBAADBAAD);
bool operator==(const D3DDDIARG_ZRANGE& lhs, const D3DDDIARG_ZRANGE& rhs)
{
return lhs.MinZ == rhs.MinZ && lhs.MaxZ == rhs.MaxZ;
}
bool operator==(const D3DDDIARG_WINFO& lhs, const D3DDDIARG_WINFO& rhs)
{
return lhs.WNear == rhs.WNear && lhs.WFar == rhs.WFar;
}
}
namespace D3dDdi
{
DeviceState::DeviceState(Device& device)
: m_device(device)
, m_pixelShader(UNINITIALIZED_HANDLE)
, m_vertexShaderDecl(UNINITIALIZED_HANDLE)
, m_vertexShaderFunc(UNINITIALIZED_HANDLE)
, m_wInfo{ NAN, NAN }
, m_zRange{ NAN, NAN }
, m_depthStencil{}
, m_pixelShader(nullptr)
, m_renderTarget{}
, m_streamSource{}
, m_streamSourceUm{}
, m_streamSourceUmBuffer(nullptr)
, m_textures{}
, m_vertexShaderDecl(nullptr)
, m_vertexShaderFunc(nullptr)
, m_viewport{}
, m_wInfo{}
, m_zRange{}
{
const UINT D3DBLENDOP_ADD = 1;
const UINT UNINITIALIZED_STATE = 0xBAADBAAD;
m_device.getOrigVtable().pfnSetDepthStencil(m_device, &m_depthStencil);
m_device.getOrigVtable().pfnSetPixelShader(m_device, nullptr);
m_device.getOrigVtable().pfnSetRenderTarget(m_device, &m_renderTarget);
m_device.getOrigVtable().pfnSetVertexShaderDecl(m_device, nullptr);
m_device.getOrigVtable().pfnSetVertexShaderFunc(m_device, nullptr);
m_device.getOrigVtable().pfnSetViewport(m_device, &m_viewport);
m_device.getOrigVtable().pfnUpdateWInfo(m_device, &m_wInfo);
m_device.getOrigVtable().pfnSetZRange(m_device, &m_zRange);
m_renderState.fill(UNINITIALIZED_STATE);
m_textures.fill(UNINITIALIZED_HANDLE);
m_renderState[D3DDDIRS_ZENABLE] = D3DZB_TRUE;
m_renderState[D3DDDIRS_FILLMODE] = D3DFILL_SOLID;
m_renderState[D3DDDIRS_SHADEMODE] = D3DSHADE_GOURAUD;
m_renderState[D3DDDIRS_LINEPATTERN] = 0;
m_renderState[D3DDDIRS_ZWRITEENABLE] = TRUE;
m_renderState[D3DDDIRS_ALPHATESTENABLE] = FALSE;
m_renderState[D3DDDIRS_LASTPIXEL] = TRUE;
m_renderState[D3DDDIRS_SRCBLEND] = D3DBLEND_ONE;
m_renderState[D3DDDIRS_DESTBLEND] = D3DBLEND_ZERO;
m_renderState[D3DDDIRS_CULLMODE] = D3DCULL_CCW;
m_renderState[D3DDDIRS_ZFUNC] = D3DCMP_LESSEQUAL;
m_renderState[D3DDDIRS_ALPHAREF] = 0;
m_renderState[D3DDDIRS_ALPHAFUNC] = D3DCMP_ALWAYS;
m_renderState[D3DDDIRS_DITHERENABLE] = FALSE;
m_renderState[D3DDDIRS_ALPHABLENDENABLE] = FALSE;
m_renderState[D3DDDIRS_FOGENABLE] = FALSE;
m_renderState[D3DDDIRS_SPECULARENABLE] = FALSE;
m_renderState[D3DDDIRS_ZVISIBLE] = 0;
m_renderState[D3DDDIRS_FOGCOLOR] = 0;
m_renderState[D3DDDIRS_FOGTABLEMODE] = D3DFOG_NONE;
m_renderState[D3DDDIRS_FOGSTART] = 0;
m_renderState[D3DDDIRS_FOGEND] = 0x3F800000;
m_renderState[D3DDDIRS_FOGDENSITY] = 0x3F800000;
m_renderState[D3DDDIRS_COLORKEYENABLE] = FALSE;
m_renderState[D3DDDIRS_EDGEANTIALIAS] = 0;
m_renderState[D3DDDIRS_ZBIAS] = 0;
m_renderState[D3DDDIRS_RANGEFOGENABLE] = FALSE;
for (UINT i = D3DDDIRS_STIPPLEPATTERN00; i <= D3DDDIRS_STIPPLEPATTERN31; ++i)
{
m_renderState[i] = 0;
}
m_renderState[D3DDDIRS_STENCILENABLE] = FALSE;
m_renderState[D3DDDIRS_STENCILFAIL] = D3DSTENCILOP_KEEP;
m_renderState[D3DDDIRS_STENCILZFAIL] = D3DSTENCILOP_KEEP;
m_renderState[D3DDDIRS_STENCILPASS] = D3DSTENCILOP_KEEP;
m_renderState[D3DDDIRS_STENCILFUNC] = D3DCMP_ALWAYS;
m_renderState[D3DDDIRS_STENCILREF] = 0;
m_renderState[D3DDDIRS_STENCILMASK] = 0xFFFFFFFF;
m_renderState[D3DDDIRS_STENCILWRITEMASK] = 0xFFFFFFFF;
m_renderState[D3DDDIRS_TEXTUREFACTOR] = 0xFFFFFFFF;
for (UINT i = D3DDDIRS_WRAP0; i <= D3DDDIRS_WRAP7; ++i)
{
m_renderState[i] = 0;
}
m_renderState[D3DDDIRS_CLIPPING] = TRUE;
m_renderState[D3DDDIRS_CLIPPLANEENABLE] = 0;
m_renderState[D3DDDIRS_SOFTWAREVERTEXPROCESSING] = FALSE;
m_renderState[D3DDDIRS_POINTSIZE_MAX] = 0x3F800000;
m_renderState[D3DDDIRS_POINTSIZE] = 0x3F800000;
m_renderState[D3DDDIRS_POINTSIZE_MIN] = 0;
m_renderState[D3DDDIRS_POINTSPRITEENABLE] = 0;
m_renderState[D3DDDIRS_MULTISAMPLEMASK] = 0xFFFFFFFF;
m_renderState[D3DDDIRS_MULTISAMPLEANTIALIAS] = TRUE;
m_renderState[D3DDDIRS_PATCHEDGESTYLE] = FALSE;
m_renderState[D3DDDIRS_PATCHSEGMENTS] = 0x3F800000;
m_renderState[D3DDDIRS_COLORWRITEENABLE] = 0xF;
m_renderState[D3DDDIRS_BLENDOP] = D3DBLENDOP_ADD;
for (UINT i = 0; i < m_renderState.size(); i++)
{
if (UNINITIALIZED_STATE != m_renderState[i])
{
D3DDDIARG_RENDERSTATE data = {};
data.State = static_cast<D3DDDIRENDERSTATETYPE>(i);
data.Value = m_renderState[i];
m_device.getOrigVtable().pfnSetRenderState(m_device, &data);
}
}
for (UINT i = 0; i < m_textures.size(); ++i)
{
m_device.getOrigVtable().pfnSetTexture(m_device, i, nullptr);
}
for (UINT i = 0; i < m_textureStageState.size(); ++i)
{
m_textureStageState[i].fill(UNINITIALIZED_STATE);
m_textureStageState[i][D3DDDITSS_TEXCOORDINDEX] = i;
m_textureStageState[i][D3DDDITSS_ADDRESSU] = D3DTADDRESS_WRAP;
m_textureStageState[i][D3DDDITSS_ADDRESSV] = D3DTADDRESS_WRAP;
m_textureStageState[i][D3DDDITSS_BORDERCOLOR] = 0;
m_textureStageState[i][D3DDDITSS_MAGFILTER] = D3DTEXF_POINT;
m_textureStageState[i][D3DDDITSS_MINFILTER] = D3DTEXF_POINT;
m_textureStageState[i][D3DDDITSS_MIPFILTER] = D3DTEXF_NONE;
m_textureStageState[i][D3DDDITSS_MIPMAPLODBIAS] = 0;
m_textureStageState[i][D3DDDITSS_MAXMIPLEVEL] = 0;
m_textureStageState[i][D3DDDITSS_MAXANISOTROPY] = 1;
m_textureStageState[i][D3DDDITSS_TEXTURETRANSFORMFLAGS] = D3DTTFF_DISABLE;
m_textureStageState[i][D3DDDITSS_ADDRESSW] = D3DTADDRESS_WRAP;
m_textureStageState[i][D3DDDITSS_DISABLETEXTURECOLORKEY] = TRUE;
for (UINT j = 0; j < m_textureStageState[i].size(); ++j)
{
if (UNINITIALIZED_STATE != m_textureStageState[i][j])
{
D3DDDIARG_TEXTURESTAGESTATE data = {};
data.Stage = i;
data.State = static_cast<D3DDDITEXTURESTAGESTATETYPE>(j);
data.Value = m_textureStageState[i][j];
m_device.getOrigVtable().pfnSetTextureStageState(m_device, &data);
}
}
}
}
@ -76,6 +177,11 @@ namespace D3dDdi
return deleteShader(shader, m_vertexShaderFunc, m_device.getOrigVtable().pfnDeleteVertexShaderFunc);
}
HRESULT DeviceState::pfnSetDepthStencil(const D3DDDIARG_SETDEPTHSTENCIL* data)
{
return setState(data, m_depthStencil, m_device.getOrigVtable().pfnSetDepthStencil);
}
HRESULT DeviceState::pfnSetPixelShader(HANDLE shader)
{
return setShader(shader, m_pixelShader, m_device.getOrigVtable().pfnSetPixelShader);
@ -107,6 +213,40 @@ namespace D3dDdi
return setStateArray(data, m_renderState, m_device.getOrigVtable().pfnSetRenderState);
}
HRESULT DeviceState::pfnSetRenderTarget(const D3DDDIARG_SETRENDERTARGET* data)
{
HRESULT result = setState(data, m_renderTarget, m_device.getOrigVtable().pfnSetRenderTarget);
if (SUCCEEDED(result))
{
m_device.setRenderTarget(*data);
}
return result;
}
HRESULT DeviceState::pfnSetStreamSource(const D3DDDIARG_SETSTREAMSOURCE* data)
{
HRESULT result = m_device.getDrawPrimitive().setStreamSource(*data);
if (SUCCEEDED(result))
{
m_streamSource = *data;
m_streamSourceUm = {};
m_streamSourceUmBuffer = nullptr;
}
return result;
}
HRESULT DeviceState::pfnSetStreamSourceUm(const D3DDDIARG_SETSTREAMSOURCEUM* data, const void* umBuffer)
{
HRESULT result = m_device.getDrawPrimitive().setStreamSourceUm(*data, umBuffer);
if (SUCCEEDED(result))
{
m_streamSourceUm = *data;
m_streamSourceUmBuffer = umBuffer;
m_streamSource = {};
}
return result;
}
HRESULT DeviceState::pfnSetTexture(UINT stage, HANDLE texture)
{
if (stage >= m_textures.size())
@ -115,8 +255,7 @@ namespace D3dDdi
return m_device.getOrigVtable().pfnSetTexture(m_device, stage, texture);
}
if (texture == m_textures[stage] &&
texture != UNINITIALIZED_HANDLE)
if (texture == m_textures[stage])
{
return S_OK;
}
@ -126,23 +265,22 @@ namespace D3dDdi
if (SUCCEEDED(result))
{
m_textures[stage] = texture;
m_textureStageState[stage][D3DDDITSS_DISABLETEXTURECOLORKEY] = UNINITIALIZED_STATE;
m_textureStageState[stage][D3DDDITSS_TEXTURECOLORKEYVAL] = UNINITIALIZED_STATE;
m_textureStageState[stage][D3DDDITSS_DISABLETEXTURECOLORKEY] = TRUE;
D3DDDIARG_TEXTURESTAGESTATE data = {};
data.Stage = stage;
data.State = D3DDDITSS_DISABLETEXTURECOLORKEY;
data.Value = TRUE;
m_device.getOrigVtable().pfnSetTextureStageState(m_device, &data);
}
return result;
}
HRESULT DeviceState::pfnSetTextureStageState(const D3DDDIARG_TEXTURESTAGESTATE* data)
{
switch (data->State)
if (D3DDDITSS_TEXTURECOLORKEYVAL == data->State)
{
case D3DDDITSS_DISABLETEXTURECOLORKEY:
m_textureStageState[data->Stage][D3DDDITSS_TEXTURECOLORKEYVAL] = UNINITIALIZED_STATE;
break;
case D3DDDITSS_TEXTURECOLORKEYVAL:
m_textureStageState[data->Stage][D3DDDITSS_DISABLETEXTURECOLORKEY] = UNINITIALIZED_STATE;
break;
m_textureStageState[data->Stage][D3DDDITSS_DISABLETEXTURECOLORKEY] = FALSE;
}
return setStateArray(data, m_textureStageState[data->Stage], m_device.getOrigVtable().pfnSetTextureStageState);
}
@ -185,6 +323,11 @@ namespace D3dDdi
return setShader(shader, m_vertexShaderFunc, m_device.getOrigVtable().pfnSetVertexShaderFunc);
}
HRESULT DeviceState::pfnSetViewport(const D3DDDIARG_VIEWPORTINFO* data)
{
return setState(data, m_viewport, m_device.getOrigVtable().pfnSetViewport);
}
HRESULT DeviceState::pfnSetZRange(const D3DDDIARG_ZRANGE* data)
{
return setState(data, m_zRange, m_device.getOrigVtable().pfnSetZRange);
@ -211,27 +354,32 @@ namespace D3dDdi
HRESULT result = origDeleteShaderFunc(m_device, shader);
if (SUCCEEDED(result) && shader == currentShader)
{
currentShader = UNINITIALIZED_HANDLE;
currentShader = nullptr;
}
return result;
}
void DeviceState::removeTexture(HANDLE texture)
void DeviceState::onDestroyResource(HANDLE resource)
{
for (UINT i = 0; i < m_textures.size(); ++i)
{
if (m_textures[i] == texture)
if (m_textures[i] == resource)
{
m_textures[i] = UNINITIALIZED_HANDLE;
m_textures[i] = nullptr;
m_device.getOrigVtable().pfnSetTexture(m_device, i, nullptr);
}
}
if (m_renderTarget.hRenderTarget == resource)
{
m_renderTarget = {};
}
}
HRESULT DeviceState::setShader(HANDLE shader, HANDLE& currentShader,
HRESULT(APIENTRY* origSetShaderFunc)(HANDLE, HANDLE))
{
if (shader == currentShader &&
shader != UNINITIALIZED_HANDLE)
if (shader == currentShader)
{
return S_OK;
}
@ -273,7 +421,7 @@ namespace D3dDdi
HRESULT DeviceState::setState(const StateData* data, StateData& currentState,
HRESULT(APIENTRY* origSetState)(HANDLE, const StateData*))
{
if (*data == currentState)
if (0 == memcmp(data, &currentState, sizeof(currentState)))
{
return S_OK;
}
@ -297,8 +445,7 @@ namespace D3dDdi
return origSetState(m_device, data);
}
if (data->Value == currentState[data->State] &&
data->Value != UNINITIALIZED_STATE)
if (data->Value == currentState[data->State])
{
return S_OK;
}

View File

@ -4,6 +4,10 @@
#include <map>
#include <vector>
const UINT D3DTEXF_NONE = 0;
const UINT D3DTEXF_POINT = 1;
const UINT D3DTEXF_LINEAR = 2;
namespace D3dDdi
{
class Device;
@ -17,11 +21,15 @@ namespace D3dDdi
HRESULT pfnDeletePixelShader(HANDLE shader);
HRESULT pfnDeleteVertexShaderDecl(HANDLE shader);
HRESULT pfnDeleteVertexShaderFunc(HANDLE shader);
HRESULT pfnSetDepthStencil(const D3DDDIARG_SETDEPTHSTENCIL* data);
HRESULT pfnSetPixelShader(HANDLE shader);
HRESULT pfnSetPixelShaderConst(const D3DDDIARG_SETPIXELSHADERCONST* data, const FLOAT* registers);
HRESULT pfnSetPixelShaderConstB(const D3DDDIARG_SETPIXELSHADERCONSTB* data, const BOOL* registers);
HRESULT pfnSetPixelShaderConstI(const D3DDDIARG_SETPIXELSHADERCONSTI* data, const INT* registers);
HRESULT pfnSetRenderState(const D3DDDIARG_RENDERSTATE* data);
HRESULT pfnSetRenderTarget(const D3DDDIARG_SETRENDERTARGET* data);
HRESULT pfnSetStreamSource(const D3DDDIARG_SETSTREAMSOURCE* data);
HRESULT pfnSetStreamSourceUm(const D3DDDIARG_SETSTREAMSOURCEUM* data, const void* umBuffer);
HRESULT pfnSetTexture(UINT stage, HANDLE texture);
HRESULT pfnSetTextureStageState(const D3DDDIARG_TEXTURESTAGESTATE* data);
HRESULT pfnSetVertexShaderConst(const D3DDDIARG_SETVERTEXSHADERCONST* data, const void* registers);
@ -29,10 +37,11 @@ namespace D3dDdi
HRESULT pfnSetVertexShaderConstI(const D3DDDIARG_SETVERTEXSHADERCONSTI* data, const INT* registers);
HRESULT pfnSetVertexShaderDecl(HANDLE shader);
HRESULT pfnSetVertexShaderFunc(HANDLE shader);
HRESULT pfnSetViewport(const D3DDDIARG_VIEWPORTINFO* data);
HRESULT pfnSetZRange(const D3DDDIARG_ZRANGE* data);
HRESULT pfnUpdateWInfo(const D3DDDIARG_WINFO* data);
void removeTexture(HANDLE texture);
void onDestroyResource(HANDLE resource);
private:
typedef std::tuple<FLOAT, FLOAT, FLOAT, FLOAT> ShaderConstF;
@ -57,11 +66,16 @@ namespace D3dDdi
HRESULT(APIENTRY* origSetState)(HANDLE, const StateData*));
Device& m_device;
D3DDDIARG_SETDEPTHSTENCIL m_depthStencil;
HANDLE m_pixelShader;
std::vector<ShaderConstF> m_pixelShaderConst;
std::vector<BOOL> m_pixelShaderConstB;
std::vector<ShaderConstI> m_pixelShaderConstI;
std::array<UINT, D3DDDIRS_BLENDOPALPHA + 1> m_renderState;
D3DDDIARG_SETRENDERTARGET m_renderTarget;
D3DDDIARG_SETSTREAMSOURCE m_streamSource;
D3DDDIARG_SETSTREAMSOURCEUM m_streamSourceUm;
const void* m_streamSourceUmBuffer;
std::array<HANDLE, 8> m_textures;
std::array<std::array<UINT, D3DDDITSS_TEXTURECOLORKEYVAL + 1>, 8> m_textureStageState;
std::vector<ShaderConstF> m_vertexShaderConst;
@ -70,7 +84,228 @@ namespace D3dDdi
std::map<HANDLE, std::vector<D3DDDIVERTEXELEMENT>> m_vertexShaderDecls;
HANDLE m_vertexShaderDecl;
HANDLE m_vertexShaderFunc;
D3DDDIARG_VIEWPORTINFO m_viewport;
D3DDDIARG_WINFO m_wInfo;
D3DDDIARG_ZRANGE m_zRange;
public:
template <auto setterMethod, auto dataMemberPtr>
class ScopedData
{
public:
typedef std::remove_reference_t<decltype(std::declval<DeviceState>().*dataMemberPtr)> Data;
ScopedData(DeviceState& deviceState, const Data& data)
: m_deviceState(deviceState)
, m_prevData(deviceState.*dataMemberPtr)
{
(m_deviceState.*setterMethod)(&data);
}
~ScopedData()
{
(m_deviceState.*setterMethod)(&m_prevData);
}
protected:
DeviceState& m_deviceState;
Data m_prevData;
};
class ScopedDepthStencil : public ScopedData<&DeviceState::pfnSetDepthStencil, &DeviceState::m_depthStencil>
{
public:
using ScopedData::ScopedData;
};
template <HRESULT(DeviceState::* setHandle)(HANDLE), HANDLE DeviceState::* storedHandle>
class ScopedHandle
{
public:
ScopedHandle(DeviceState& deviceState, HANDLE handle)
: m_deviceState(deviceState)
, m_prevHandle(deviceState.*storedHandle)
{
(m_deviceState.*setHandle)(handle);
}
~ScopedHandle()
{
if (m_prevHandle)
{
(m_deviceState.*setHandle)(m_prevHandle);
}
}
private:
DeviceState& m_deviceState;
HANDLE m_prevHandle;
};
class ScopedPixelShader : public ScopedHandle<&DeviceState::pfnSetPixelShader, &DeviceState::m_pixelShader>
{
public:
using ScopedHandle::ScopedHandle;
};
class ScopedRenderState
{
public:
ScopedRenderState(DeviceState& deviceState, const D3DDDIARG_RENDERSTATE& data)
: m_deviceState(deviceState)
, m_prevData{ data.State, deviceState.m_renderState[data.State] }
{
m_deviceState.pfnSetRenderState(&data);
}
~ScopedRenderState()
{
m_deviceState.pfnSetRenderState(&m_prevData);
}
private:
DeviceState& m_deviceState;
D3DDDIARG_RENDERSTATE m_prevData;
};
class ScopedRenderTarget : public ScopedData<&DeviceState::pfnSetRenderTarget, &DeviceState::m_renderTarget>
{
public:
ScopedRenderTarget(DeviceState& deviceState, const D3DDDIARG_SETRENDERTARGET& data)
: ScopedData(deviceState, data)
{
if (!m_prevData.hRenderTarget)
{
m_prevData = data;
}
}
};
class ScopedStreamSourceUm
{
public:
ScopedStreamSourceUm(DeviceState& deviceState, const D3DDDIARG_SETSTREAMSOURCEUM& data, const void* umBuffer)
: m_deviceState(deviceState)
, m_prevStreamSource(deviceState.m_streamSource)
, m_prevStreamSourceUm(deviceState.m_streamSourceUm)
, m_prevStreamSourceUmBuffer(deviceState.m_streamSourceUmBuffer)
{
m_deviceState.pfnSetStreamSourceUm(&data, umBuffer);
}
~ScopedStreamSourceUm()
{
if (m_prevStreamSourceUmBuffer)
{
m_deviceState.pfnSetStreamSourceUm(&m_prevStreamSourceUm, m_prevStreamSourceUmBuffer);
}
else if (m_prevStreamSource.hVertexBuffer)
{
m_deviceState.pfnSetStreamSource(&m_prevStreamSource);
}
}
private:
DeviceState& m_deviceState;
D3DDDIARG_SETSTREAMSOURCE m_prevStreamSource;
D3DDDIARG_SETSTREAMSOURCEUM m_prevStreamSourceUm;
const void* m_prevStreamSourceUmBuffer;
};
class ScopedTextureStageState
{
public:
ScopedTextureStageState(DeviceState& deviceState, const D3DDDIARG_TEXTURESTAGESTATE& data)
: m_deviceState(deviceState)
, m_prevData{ data.Stage, data.State, deviceState.m_textureStageState[data.Stage][data.State] }
{
m_deviceState.pfnSetTextureStageState(&data);
}
~ScopedTextureStageState()
{
m_deviceState.pfnSetTextureStageState(&m_prevData);
}
private:
DeviceState& m_deviceState;
D3DDDIARG_TEXTURESTAGESTATE m_prevData;
};
class ScopedTexture
{
public:
ScopedTexture(DeviceState& deviceState, UINT stage, HANDLE texture, UINT filter)
: m_deviceState(deviceState)
, m_stage(stage)
, m_prevTexture(deviceState.m_textures[stage])
, m_scopedAddressU(deviceState, { stage, D3DDDITSS_ADDRESSU, D3DTADDRESS_CLAMP })
, m_scopedAddressV(deviceState, { stage, D3DDDITSS_ADDRESSV, D3DTADDRESS_CLAMP })
, m_scopedMagFilter(deviceState, { stage, D3DDDITSS_MAGFILTER, filter })
, m_scopedMinFilter(deviceState, { stage, D3DDDITSS_MINFILTER, filter })
, m_scopedMipFilter(deviceState, { stage, D3DDDITSS_MIPFILTER, D3DTEXF_NONE })
, m_scopedWrap(deviceState, { static_cast<D3DDDIRENDERSTATETYPE>(D3DDDIRS_WRAP0 + stage), 0 })
, m_prevTextureColorKeyVal(deviceState.m_textureStageState[stage][D3DDDITSS_TEXTURECOLORKEYVAL])
, m_prevDisableTextureColorKey(deviceState.m_textureStageState[stage][D3DDDITSS_DISABLETEXTURECOLORKEY])
{
m_deviceState.pfnSetTexture(stage, texture);
D3DDDIARG_TEXTURESTAGESTATE data = {};
data.Stage = stage;
data.State = D3DDDITSS_DISABLETEXTURECOLORKEY;
data.Value = TRUE;
m_deviceState.pfnSetTextureStageState(&data);
}
~ScopedTexture()
{
m_deviceState.pfnSetTexture(m_stage, m_prevTexture);
D3DDDIARG_TEXTURESTAGESTATE data = {};
data.Stage = m_stage;
if (m_prevDisableTextureColorKey)
{
data.State = D3DDDITSS_DISABLETEXTURECOLORKEY;
data.Value = TRUE;
}
else
{
data.State = D3DDDITSS_TEXTURECOLORKEYVAL;
data.Value = m_prevTextureColorKeyVal;
}
m_deviceState.pfnSetTextureStageState(&data);
}
private:
DeviceState& m_deviceState;
UINT m_stage;
HANDLE m_prevTexture;
ScopedTextureStageState m_scopedAddressU;
ScopedTextureStageState m_scopedAddressV;
ScopedTextureStageState m_scopedMagFilter;
ScopedTextureStageState m_scopedMinFilter;
ScopedTextureStageState m_scopedMipFilter;
ScopedRenderState m_scopedWrap;
UINT m_prevTextureColorKeyVal;
UINT m_prevDisableTextureColorKey;
};
class ScopedVertexShaderDecl : public ScopedHandle<&DeviceState::pfnSetVertexShaderDecl, &DeviceState::m_vertexShaderDecl>
{
public:
using ScopedHandle::ScopedHandle;
};
class ScopedViewport : public ScopedData<&DeviceState::pfnSetViewport, &DeviceState::m_viewport>
{
public:
using ScopedData::ScopedData;
};
class ScopedZRange : public ScopedData<&DeviceState::pfnSetZRange, &DeviceState::m_zRange>
{
public:
using ScopedData::ScopedData;
};
};
}

View File

@ -204,6 +204,12 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_RENDERSTATE& val)
<< val.Value;
}
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETDEPTHSTENCIL& val)
{
return Compat::LogStruct(os)
<< val.hZBuffer;
}
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETPIXELSHADERCONST& val)
{
return Compat::LogStruct(os)

View File

@ -25,6 +25,7 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_PRESENT& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_PRESENT1& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_PRESENTSURFACE& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_RENDERSTATE& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETDEPTHSTENCIL& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETPIXELSHADERCONST& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETRENDERTARGET& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETSTREAMSOURCE& val);

View File

@ -154,6 +154,13 @@ namespace D3dDdi
fixResourceData(device, reinterpret_cast<D3DDDIARG_CREATERESOURCE&>(m_fixedData));
m_formatInfo = getFormatInfo(m_fixedData.Format);
const bool isPalettized = D3DDDIFMT_P8 == m_fixedData.Format;
if (isPalettized)
{
m_fixedData.Format = D3DDDIFMT_L8;
m_fixedData.Flags.Texture = 1;
}
HRESULT result = createResourceFunc(device, reinterpret_cast<Arg*>(&m_fixedData));
if (FAILED(result))
{
@ -161,6 +168,12 @@ namespace D3dDdi
}
m_handle = m_fixedData.hResource;
if (isPalettized)
{
m_fixedData.Format = D3DDDIFMT_P8;
m_fixedData.Flags.Texture = 0;
}
if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool &&
0 != m_formatInfo.bytesPerPixel)
{
@ -432,7 +445,7 @@ namespace D3dDdi
{
LOG_FUNC("Resource::createSysMemResource", Compat::array(surfaceInfo.data(), surfaceInfo.size()));
D3DDDIARG_CREATERESOURCE2 data = {};
data.Format = m_fixedData.Format;
data.Format = (D3DDDIFMT_P8 == m_fixedData.Format) ? D3DDDIFMT_L8 : m_fixedData.Format;
data.Pool = D3DDDIPOOL_SYSTEMMEM;
data.pSurfList = surfaceInfo.data();
data.SurfCount = surfaceInfo.size();
@ -526,47 +539,27 @@ namespace D3dDdi
HRESULT Resource::presentationBlt(const D3DDDIARG_BLT& data, Resource& srcResource)
{
if (D3DDDIFMT_P8 == srcResource.m_origData.Format)
{
D3DDDIARG_LOCK lock = {};
lock.hResource = m_handle;
lock.SubResourceIndex = data.DstSubResourceIndex;
HRESULT result = m_device.getOrigVtable().pfnLock(m_device, &lock);
if (FAILED(result))
{
return result;
}
auto entries(Gdi::Palette::getHardwarePalette());
DWORD pal[256] = {};
for (UINT i = 0; i < 256; ++i)
{
pal[i] = (entries[i].peRed << 16) | (entries[i].peGreen << 8) | entries[i].peBlue;
}
auto& srcLockData = srcResource.m_lockData[data.SrcSubResourceIndex];
for (UINT y = 0; y < srcResource.m_fixedData.surfaceData[data.SrcSubResourceIndex].Height; ++y)
{
auto src = static_cast<const BYTE*>(srcLockData.data) + y * srcLockData.pitch;
auto dst = reinterpret_cast<DWORD*>(static_cast<BYTE*>(lock.pSurfData) + y * lock.Pitch);
for (UINT x = 0; x < srcResource.m_fixedData.surfaceData[data.SrcSubResourceIndex].Width; ++x)
{
dst[x] = pal[*src];
++src;
}
}
D3DDDIARG_UNLOCK unlock = {};
unlock.hResource = m_handle;
unlock.SubResourceIndex = data.DstSubResourceIndex;
return m_device.getOrigVtable().pfnUnlock(m_device, &unlock);
}
if (srcResource.m_lockResource &&
srcResource.m_lockData[data.SrcSubResourceIndex].isSysMemUpToDate)
{
srcResource.copyToVidMem(data.SrcSubResourceIndex);
}
if (D3DDDIFMT_P8 == srcResource.m_origData.Format)
{
auto entries(Gdi::Palette::getHardwarePalette());
RGBQUAD pal[256] = {};
for (UINT i = 0; i < 256; ++i)
{
pal[i].rgbRed = entries[i].peRed;
pal[i].rgbGreen = entries[i].peGreen;
pal[i].rgbBlue = entries[i].peBlue;
}
m_device.getShaderBlitter().palettizedBlt(*this, data.DstSubResourceIndex, srcResource, pal);
return S_OK;
}
return m_device.getOrigVtable().pfnBlt(m_device, &data);
}

View File

@ -25,6 +25,8 @@ namespace D3dDdi
Resource& operator=(Resource&&) = default;
operator HANDLE() const { return m_handle; }
const D3DDDIARG_CREATERESOURCE2& getOrigDesc() const { return m_origData; }
const D3DDDIARG_CREATERESOURCE2& getFixedDesc() const { return m_fixedData; }
HRESULT blt(D3DDDIARG_BLT data);
HRESULT colorFill(D3DDDIARG_COLORFILL data);

View File

@ -0,0 +1,177 @@
#include <Common/Log.h>
#include <D3dDdi/Device.h>
#include <D3dDdi/Resource.h>
#include <D3dDdi/ShaderBlitter.h>
#include <Shaders/PaletteLookup.h>
#define CONCAT_(a, b) a##b
#define CONCAT(a, b) CONCAT_(a, b)
#define SCOPED_STATE(state, ...) DeviceState::Scoped##state CONCAT(scopedState, __LINE__)(m_device.getState(), __VA_ARGS__)
namespace D3dDdi
{
ShaderBlitter::ShaderBlitter(Device& device)
: m_device(device)
, m_paletteTexture(nullptr)
, m_psPaletteLookup(createPixelShader(g_psPaletteLookup, sizeof(g_psPaletteLookup)))
, m_vertexShaderDecl(createVertexShaderDecl())
{
D3DDDI_SURFACEINFO si = {};
si.Width = 256;
si.Height = 1;
D3DDDIARG_CREATERESOURCE2 cr = {};
cr.Format = D3DDDIFMT_X8R8G8B8;
cr.Pool = D3DDDIPOOL_VIDEOMEMORY;
cr.pSurfList = &si;
cr.SurfCount = 1;
cr.Rotation = D3DDDI_ROTATION_IDENTITY;
cr.Flags.Texture = 1;
m_device.createPrivateResource(cr);
m_paletteTexture = cr.hResource;
}
ShaderBlitter::~ShaderBlitter()
{
if (m_paletteTexture)
{
m_device.getOrigVtable().pfnDestroyResource(m_device, m_paletteTexture);
m_paletteTexture = nullptr;
}
}
void ShaderBlitter::blt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, const RECT& srcRect, HANDLE pixelShader, UINT filter)
{
LOG_FUNC("ShaderBlitter::blt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
static_cast<HANDLE>(srcResource), srcRect, pixelShader, filter);
if (!m_vertexShaderDecl || !pixelShader)
{
return;
}
const auto& dstSurface = dstResource.getFixedDesc().pSurfList[dstSubResourceIndex];
const auto& srcSurface = srcResource.getFixedDesc().pSurfList[0];
SCOPED_STATE(RenderState, { D3DDDIRS_SCENECAPTURE, TRUE });
SCOPED_STATE(VertexShaderDecl, m_vertexShaderDecl);
SCOPED_STATE(PixelShader, pixelShader);
SCOPED_STATE(DepthStencil, { nullptr });
SCOPED_STATE(RenderTarget, { 0, dstResource, dstSubResourceIndex });
SCOPED_STATE(Viewport, { 0, 0, dstSurface.Width, dstSurface.Height });
SCOPED_STATE(ZRange, { 0, 1 });
SCOPED_STATE(RenderState, { D3DDDIRS_ZENABLE, D3DZB_FALSE });
SCOPED_STATE(RenderState, { D3DDDIRS_FILLMODE, D3DFILL_SOLID });
SCOPED_STATE(RenderState, { D3DDDIRS_ALPHATESTENABLE, FALSE });
SCOPED_STATE(RenderState, { D3DDDIRS_CULLMODE, D3DCULL_NONE });
SCOPED_STATE(RenderState, { D3DDDIRS_DITHERENABLE, FALSE });
SCOPED_STATE(RenderState, { D3DDDIRS_ALPHABLENDENABLE, FALSE });
SCOPED_STATE(RenderState, { D3DDDIRS_FOGENABLE, FALSE });
SCOPED_STATE(RenderState, { D3DDDIRS_STENCILENABLE, FALSE });
SCOPED_STATE(RenderState, { D3DDDIRS_CLIPPING, FALSE });
SCOPED_STATE(RenderState, { D3DDDIRS_CLIPPLANEENABLE, 0 });
SCOPED_STATE(RenderState, { D3DDDIRS_MULTISAMPLEANTIALIAS, FALSE });
SCOPED_STATE(RenderState, { D3DDDIRS_COLORWRITEENABLE, 0xF });
SCOPED_STATE(Texture, 0, srcResource, filter);
struct Vertex
{
float x;
float y;
float z;
float rhw;
float tu;
float tv;
};
const float srcWidth = static_cast<float>(srcSurface.Width);
const float srcHeight = static_cast<float>(srcSurface.Height);
Vertex vertices[4] = {
{ dstRect.left - 0.5f, dstRect.top - 0.5f, 0, 1, srcRect.left / srcWidth, srcRect.top / srcHeight },
{ dstRect.right - 0.5f, dstRect.top - 0.5f, 0, 1, srcRect.right / srcWidth, srcRect.top / srcHeight },
{ dstRect.right - 0.5f, dstRect.bottom - 0.5f, 0, 1, srcRect.right / srcWidth, srcRect.bottom / srcHeight },
{ dstRect.left - 0.5f, dstRect.bottom - 0.5f, 0, 1, srcRect.left / srcWidth, srcRect.bottom / srcHeight }
};
D3DDDIARG_SETSTREAMSOURCEUM um = {};
um.Stride = sizeof(Vertex);
SCOPED_STATE(StreamSourceUm, um, vertices);
D3DDDIARG_DRAWPRIMITIVE dp = {};
dp.PrimitiveType = D3DPT_TRIANGLEFAN;
dp.VStart = 0;
dp.PrimitiveCount = 2;
m_device.getDrawPrimitive().draw(dp, nullptr);
}
HANDLE ShaderBlitter::createPixelShader(const BYTE* code, UINT size)
{
D3DDDIARG_CREATEPIXELSHADER data = {};
data.CodeSize = size;
if (FAILED(m_device.getOrigVtable().pfnCreatePixelShader(m_device, &data, reinterpret_cast<const UINT*>(code))))
{
return nullptr;
}
return data.ShaderHandle;
}
HANDLE ShaderBlitter::createVertexShaderDecl()
{
const UINT D3DDECLTYPE_FLOAT2 = 1;
const UINT D3DDECLTYPE_FLOAT4 = 3;
const UINT D3DDECLMETHOD_DEFAULT = 0;
const UINT D3DDECLUSAGE_TEXCOORD = 5;
const UINT D3DDECLUSAGE_POSITIONT = 9;
const D3DDDIVERTEXELEMENT vertexElements[] = {
{ 0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT, 0 },
{ 0, 16, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }
};
D3DDDIARG_CREATEVERTEXSHADERDECL data = {};
data.NumVertexElements = sizeof(vertexElements) / sizeof(vertexElements[0]);
if (FAILED(m_device.getOrigVtable().pfnCreateVertexShaderDecl(m_device, &data, vertexElements)))
{
return nullptr;
}
return data.ShaderHandle;
}
void ShaderBlitter::palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex,
const Resource& srcResource, RGBQUAD palette[256])
{
if (!m_paletteTexture)
{
return;
}
D3DDDIARG_LOCK lock = {};
lock.hResource = m_paletteTexture;
lock.Flags.Discard = 1;
m_device.getOrigVtable().pfnLock(m_device, &lock);
if (!lock.pSurfData)
{
return;
}
memcpy(lock.pSurfData, palette, 256 * sizeof(RGBQUAD));
D3DDDIARG_UNLOCK unlock = {};
unlock.hResource = m_paletteTexture;
m_device.getOrigVtable().pfnUnlock(m_device, &unlock);
const auto& dstSurface = dstResource.getFixedDesc().pSurfList[dstSubResourceIndex];
const auto& srcSurface = srcResource.getFixedDesc().pSurfList[0];
const RECT dstRect = { 0, 0, static_cast<LONG>(dstSurface.Width), static_cast<LONG>(dstSurface.Height) };
const RECT srcRect = { 0, 0, static_cast<LONG>(srcSurface.Width), static_cast<LONG>(srcSurface.Height) };
SCOPED_STATE(Texture, 1, m_paletteTexture, D3DTEXF_POINT);
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcRect, m_psPaletteLookup, D3DTEXF_POINT);
}
}

View File

@ -0,0 +1,35 @@
#pragma once
#include <Windows.h>
namespace D3dDdi
{
class Device;
class Resource;
class ShaderBlitter
{
public:
ShaderBlitter(Device& device);
ShaderBlitter(const ShaderBlitter&) = delete;
ShaderBlitter(ShaderBlitter&&) = delete;
ShaderBlitter& operator=(const ShaderBlitter&) = delete;
ShaderBlitter& operator=(ShaderBlitter&&) = delete;
~ShaderBlitter();
void palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex,
const Resource& srcResource, RGBQUAD palette[256]);
private:
void blt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, const RECT& srcRect, HANDLE pixelShader, UINT filter);
HANDLE createPixelShader(const BYTE* code, UINT size);
HANDLE createVertexShaderDecl();
Device& m_device;
HANDLE m_paletteTexture;
HANDLE m_psPaletteLookup;
HANDLE m_vertexShaderDecl;
};
}

View File

@ -255,7 +255,7 @@ namespace DDraw
typename Types<DirectDraw>::TSurfaceDesc desc = {};
desc.dwSize = sizeof(desc);
desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
desc.dwBackBufferCount = 2;
CompatPtr<typename Types<DirectDraw>::TCreatedSurface> surface;

View File

@ -61,26 +61,23 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<TargetName>ddraw</TargetName>
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(ProjectDir);$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
<GenerateManifest>false</GenerateManifest>
<IntDir>$(SolutionDir)Build\$(Configuration)\</IntDir>
<MultiProcFXC>true</MultiProcFXC>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<TargetName>ddraw</TargetName>
<IncludePath>$(ProjectDir);$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>false</GenerateManifest>
<IntDir>$(SolutionDir)Build\$(Configuration)\</IntDir>
<MultiProcFXC>true</MultiProcFXC>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithDebugLogs|Win32'">
<TargetName>ddraw</TargetName>
<IncludePath>$(ProjectDir);$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>false</GenerateManifest>
<IntDir>$(SolutionDir)Build\$(Configuration)\</IntDir>
<MultiProcFXC>true</MultiProcFXC>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@ -94,6 +91,7 @@
<ObjectFileName>$(IntDir)%(RelativeDir)</ObjectFileName>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir);$(IntDir)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>dbgeng.lib;dxguid.lib;msimg32.lib;oleacc.lib;uxtheme.lib;dwmapi.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -109,6 +107,15 @@
<AdditionalIncludeDirectories>$(IntDir)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>SPECIALBUILD=\"$(Configuration)\"</PreprocessorDefinitions>
</ResourceCompile>
<FxCompile>
<VariableName>g_ps%(Filename)</VariableName>
</FxCompile>
<FxCompile>
<ObjectFileOutput />
<ShaderModel>2.0</ShaderModel>
<HeaderFileOutput>$(IntDir)%(RelativeDir)%(Filename).h</HeaderFileOutput>
<ShaderType>Pixel</ShaderType>
</FxCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@ -120,6 +127,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<ObjectFileName>$(IntDir)%(RelativeDir)</ObjectFileName>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir);$(IntDir)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>dbgeng.lib;dxguid.lib;msimg32.lib;oleacc.lib;uxtheme.lib;dwmapi.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -134,6 +142,17 @@
<ResourceCompile>
<AdditionalIncludeDirectories>$(IntDir)</AdditionalIncludeDirectories>
</ResourceCompile>
<FxCompile>
<VariableName>g_ps%(Filename)</VariableName>
</FxCompile>
<FxCompile>
<HeaderFileOutput>$(IntDir)%(RelativeDir)%(Filename).h</HeaderFileOutput>
</FxCompile>
<FxCompile>
<ObjectFileOutput />
<ShaderModel>2.0</ShaderModel>
<ShaderType>Pixel</ShaderType>
</FxCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithDebugLogs|Win32'">
<ClCompile>
@ -145,6 +164,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<ObjectFileName>$(IntDir)%(RelativeDir)</ObjectFileName>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir);$(IntDir)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>dbgeng.lib;dxguid.lib;msimg32.lib;oleacc.lib;uxtheme.lib;dwmapi.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -160,6 +180,15 @@
<AdditionalIncludeDirectories>$(IntDir)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>SPECIALBUILD=\"$(Configuration)\"</PreprocessorDefinitions>
</ResourceCompile>
<FxCompile>
<VariableName>g_ps%(Filename)</VariableName>
</FxCompile>
<FxCompile>
<ObjectFileOutput />
<ShaderModel>2.0</ShaderModel>
<HeaderFileOutput>$(IntDir)%(RelativeDir)%(Filename).h</HeaderFileOutput>
<ShaderType>Pixel</ShaderType>
</FxCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="Common\CompatPtr.h" />
@ -203,6 +232,7 @@
<ClInclude Include="D3dDdi\Log\KernelModeThunksLog.h" />
<ClInclude Include="D3dDdi\Resource.h" />
<ClInclude Include="D3dDdi\ScopedCriticalSection.h" />
<ClInclude Include="D3dDdi\ShaderBlitter.h" />
<ClInclude Include="D3dDdi\Visitors\AdapterCallbacksVisitor.h" />
<ClInclude Include="D3dDdi\Visitors\AdapterFuncsVisitor.h" />
<ClInclude Include="D3dDdi\Visitors\DeviceCallbacksVisitor.h" />
@ -302,6 +332,7 @@
<ClCompile Include="D3dDdi\Log\KernelModeThunksLog.cpp" />
<ClCompile Include="D3dDdi\Resource.cpp" />
<ClCompile Include="D3dDdi\ScopedCriticalSection.cpp" />
<ClCompile Include="D3dDdi\ShaderBlitter.cpp" />
<ClCompile Include="DDraw\Blitter.cpp" />
<ClCompile Include="DDraw\DirectDraw.cpp" />
<ClCompile Include="DDraw\DirectDrawClipper.cpp" />
@ -359,6 +390,9 @@
<ItemGroup>
<None Include="genversion.ps1" />
</ItemGroup>
<ItemGroup>
<FxCompile Include="Shaders\PaletteLookup.hlsl" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@ -88,6 +88,9 @@
<Filter Include="Source Files\Config\Settings">
<UniqueIdentifier>{0b4eec6c-ece5-4417-913c-8829b34ec08c}</UniqueIdentifier>
</Filter>
<Filter Include="Shaders">
<UniqueIdentifier>{00e06bd4-3f10-46dc-af0f-99834dfac835}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Gdi\Gdi.h">
@ -417,6 +420,9 @@
<ClInclude Include="Config\Settings\CpuAffinity.h">
<Filter>Header Files\Config\Settings</Filter>
</ClInclude>
<ClInclude Include="D3dDdi\ShaderBlitter.h">
<Filter>Header Files\D3dDdi</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Gdi\Gdi.cpp">
@ -656,6 +662,9 @@
<ClCompile Include="Config\Settings\CpuAffinity.cpp">
<Filter>Source Files\Config\Settings</Filter>
</ClCompile>
<ClCompile Include="D3dDdi\ShaderBlitter.cpp">
<Filter>Source Files\D3dDdi</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="DDrawCompat.rc">
@ -667,4 +676,9 @@
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
<ItemGroup>
<FxCompile Include="Shaders\PaletteLookup.hlsl">
<Filter>Shaders</Filter>
</FxCompile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,7 @@
sampler2D s_texture : register(s0);
sampler2D s_palette : register(s1);
float4 main(float2 texCoord : TEXCOORD0) : COLOR0
{
return tex2D(s_palette, float2(tex2D(s_texture, texCoord).r, 0));
}