mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Accumulate device state changes
This commit is contained in:
parent
664c573d91
commit
9fb450e233
57
DDrawCompat/Common/BitSet.h
Normal file
57
DDrawCompat/Common/BitSet.h
Normal file
@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <intrin.h>
|
||||
|
||||
template <int min, int max>
|
||||
class BitSet
|
||||
{
|
||||
public:
|
||||
BitSet() : m_bits{}
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Func>
|
||||
void forEach(Func func)
|
||||
{
|
||||
int value = min;
|
||||
unsigned long index = 0;
|
||||
for (unsigned bits : m_bits)
|
||||
{
|
||||
while (0 != bits)
|
||||
{
|
||||
_BitScanForward(&index, bits);
|
||||
func(value + index);
|
||||
bits &= ~(1 << index);
|
||||
}
|
||||
value += 32;
|
||||
}
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_bits.fill(0);
|
||||
}
|
||||
|
||||
void reset(int value)
|
||||
{
|
||||
const unsigned index = value - min;
|
||||
m_bits[index / 32] &= ~(1 << (index % 32));
|
||||
}
|
||||
|
||||
void set(int value)
|
||||
{
|
||||
const unsigned index = value - min;
|
||||
m_bits[index / 32] |= 1 << (index % 32);
|
||||
}
|
||||
|
||||
bool test(int value)
|
||||
{
|
||||
const unsigned index = value - min;
|
||||
return m_bits[index / 32] & (1 << (index % 32));
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<unsigned, (max - min + 32) / 32> m_bits;
|
||||
};
|
@ -159,6 +159,7 @@ namespace D3dDdi
|
||||
HRESULT Device::pfnClear(const D3DDDIARG_CLEAR* data, UINT numRect, const RECT* rect)
|
||||
{
|
||||
flushPrimitives();
|
||||
m_state.flush();
|
||||
if (data->Flags & D3DCLEAR_TARGET)
|
||||
{
|
||||
prepareForRendering();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,6 +7,8 @@
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <Common/BitSet.h>
|
||||
|
||||
const UINT D3DTEXF_NONE = 0;
|
||||
const UINT D3DTEXF_POINT = 1;
|
||||
const UINT D3DTEXF_LINEAR = 2;
|
||||
@ -19,9 +21,41 @@ namespace D3dDdi
|
||||
class DeviceState
|
||||
{
|
||||
public:
|
||||
typedef std::array<BOOL, 1> ShaderConstB;
|
||||
typedef std::array<FLOAT, 4> ShaderConstF;
|
||||
typedef std::array<INT, 4> ShaderConstI;
|
||||
|
||||
class TempPixelShaderConst
|
||||
{
|
||||
public:
|
||||
TempPixelShaderConst(DeviceState& state, const D3DDDIARG_SETPIXELSHADERCONST& data, const ShaderConstF* registers);
|
||||
~TempPixelShaderConst();
|
||||
|
||||
private:
|
||||
DeviceState& m_state;
|
||||
D3DDDIARG_SETPIXELSHADERCONST m_data;
|
||||
};
|
||||
|
||||
class TempStateLock
|
||||
{
|
||||
public:
|
||||
TempStateLock(DeviceState& state)
|
||||
: m_state(state)
|
||||
, m_prevChangedStates(state.m_changedStates)
|
||||
{
|
||||
state.m_changedStates = 0;
|
||||
}
|
||||
|
||||
~TempStateLock()
|
||||
{
|
||||
m_state.m_changedStates = m_prevChangedStates;
|
||||
}
|
||||
|
||||
private:
|
||||
DeviceState& m_state;
|
||||
UINT m_prevChangedStates;
|
||||
};
|
||||
|
||||
DeviceState(Device& device);
|
||||
|
||||
HRESULT pfnCreateVertexShaderDecl(D3DDDIARG_CREATEVERTEXSHADERDECL* data, const D3DDDIVERTEXELEMENT* vertexElements);
|
||||
@ -48,248 +82,106 @@ namespace D3dDdi
|
||||
HRESULT pfnSetZRange(const D3DDDIARG_ZRANGE* data);
|
||||
HRESULT pfnUpdateWInfo(const D3DDDIARG_WINFO* data);
|
||||
|
||||
void setTempDepthStencil(const D3DDDIARG_SETDEPTHSTENCIL& depthStencil);
|
||||
void setTempPixelShader(HANDLE shader);
|
||||
void setTempRenderState(const D3DDDIARG_RENDERSTATE& renderState);
|
||||
void setTempRenderTarget(const D3DDDIARG_SETRENDERTARGET& renderTarget);
|
||||
void setTempStreamSource(const D3DDDIARG_SETSTREAMSOURCE& streamSource);
|
||||
void setTempStreamSourceUm(const D3DDDIARG_SETSTREAMSOURCEUM& streamSourceUm, const void* umBuffer);
|
||||
void setTempTexture(UINT stage, HANDLE texture);
|
||||
void setTempTextureStageState(const D3DDDIARG_TEXTURESTAGESTATE& tss);
|
||||
void setTempVertexShaderDecl(HANDLE decl);
|
||||
void setTempViewport(const D3DDDIARG_VIEWPORTINFO& viewport);
|
||||
void setTempWInfo(const D3DDDIARG_WINFO& wInfo);
|
||||
void setTempZRange(const D3DDDIARG_ZRANGE& zRange);
|
||||
|
||||
void flush();
|
||||
void onDestroyResource(HANDLE resource);
|
||||
void updateConfig();
|
||||
|
||||
private:
|
||||
HRESULT deleteShader(HANDLE shader, HANDLE& currentShader,
|
||||
friend class ScopedDeviceState;
|
||||
|
||||
enum ChangedState
|
||||
{
|
||||
CS_MISC = 1 << 0,
|
||||
CS_RENDER_STATE = 1 << 1,
|
||||
CS_RENDER_TARGET = 1 << 2,
|
||||
CS_SHADER = 1 << 3,
|
||||
CS_STREAM_SOURCE = 1 << 4,
|
||||
CS_TEXTURE_STAGE = 1 << 5
|
||||
};
|
||||
|
||||
struct State
|
||||
{
|
||||
D3DDDIARG_SETDEPTHSTENCIL depthStencil;
|
||||
HANDLE pixelShader;
|
||||
std::array<UINT, D3DDDIRS_BLENDOPALPHA + 1> renderState;
|
||||
D3DDDIARG_SETRENDERTARGET renderTarget;
|
||||
D3DDDIARG_SETSTREAMSOURCE streamSource;
|
||||
D3DDDIARG_SETSTREAMSOURCEUM streamSourceUm;
|
||||
const void* streamSourceUmBuffer;
|
||||
std::array<HANDLE, 8> textures;
|
||||
std::array<std::array<UINT, D3DDDITSS_TEXTURECOLORKEYVAL + 1>, 8> textureStageState;
|
||||
HANDLE vertexShaderDecl;
|
||||
HANDLE vertexShaderFunc;
|
||||
D3DDDIARG_VIEWPORTINFO viewport;
|
||||
D3DDDIARG_WINFO wInfo;
|
||||
D3DDDIARG_ZRANGE zRange;
|
||||
};
|
||||
|
||||
HRESULT deleteShader(HANDLE shader, HANDLE State::* shaderMember,
|
||||
HRESULT(APIENTRY* origDeleteShaderFunc)(HANDLE, HANDLE));
|
||||
HRESULT setShader(HANDLE shader, HANDLE& currentShader,
|
||||
HRESULT(APIENTRY* origSetShaderFunc)(HANDLE, HANDLE));
|
||||
|
||||
template <typename SetShaderConstData, typename ShaderConst, typename Registers>
|
||||
HRESULT setShaderConst(const SetShaderConstData* data, const Registers* registers,
|
||||
std::vector<ShaderConst>& shaderConst,
|
||||
HRESULT(APIENTRY* origSetShaderConstFunc)(HANDLE, const SetShaderConstData*, const Registers*));
|
||||
template <typename Data>
|
||||
void removeResource(HANDLE resource, Data State::* data, HANDLE Data::* resourceMember,
|
||||
HRESULT(DeviceState::* pfnSetResourceFunc)(const Data*));
|
||||
|
||||
template <typename StateData>
|
||||
HRESULT setState(const StateData* data, StateData& currentState,
|
||||
HRESULT(APIENTRY* origSetState)(HANDLE, const StateData*));
|
||||
template <typename Data>
|
||||
bool setData(const Data& data, Data& currentData, HRESULT(APIENTRY* origSetData)(HANDLE, const Data*));
|
||||
|
||||
template <typename StateData, UINT size>
|
||||
HRESULT setStateArray(const StateData* data, std::array<UINT, size>& currentState,
|
||||
HRESULT(APIENTRY* origSetState)(HANDLE, const StateData*));
|
||||
bool setShader(HANDLE shader, HANDLE& currentShader, HRESULT(APIENTRY* origSetShaderFunc)(HANDLE, HANDLE));
|
||||
|
||||
void updateTextureStageState(UINT stage, D3DDDITEXTURESTAGESTATETYPE state);
|
||||
template <typename SetShaderConstData, typename ShaderConstArray, typename Register>
|
||||
HRESULT setShaderConst(const SetShaderConstData* data, const Register* registers,
|
||||
ShaderConstArray& shaderConstArray,
|
||||
HRESULT(APIENTRY* origSetShaderConstFunc)(HANDLE, const SetShaderConstData*, const Register*));
|
||||
|
||||
void setDepthStencil(const D3DDDIARG_SETDEPTHSTENCIL& depthStencil);
|
||||
void setPixelShader(HANDLE shader);
|
||||
void setRenderState(const D3DDDIARG_RENDERSTATE& renderState);
|
||||
void setRenderTarget(const D3DDDIARG_SETRENDERTARGET& renderTarget);
|
||||
void setStreamSource(const D3DDDIARG_SETSTREAMSOURCE& streamSource);
|
||||
void setStreamSourceUm(const D3DDDIARG_SETSTREAMSOURCEUM& streamSourceUm, const void* umBuffer);
|
||||
bool setTexture(UINT stage, HANDLE texture);
|
||||
void setTextureStageState(const D3DDDIARG_TEXTURESTAGESTATE& tss);
|
||||
void setVertexShaderDecl(HANDLE decl);
|
||||
void setVertexShaderFunc(HANDLE shader);
|
||||
void setViewport(const D3DDDIARG_VIEWPORTINFO& viewport);
|
||||
void setWInfo(const D3DDDIARG_WINFO& wInfo);
|
||||
void setZRange(const D3DDDIARG_ZRANGE& zRange);
|
||||
|
||||
void updateMisc();
|
||||
void updateRenderStates();
|
||||
void updateRenderTargets();
|
||||
void updateShaders();
|
||||
void updateStreamSource();
|
||||
void updateTextureColorKey(UINT stage);
|
||||
void updateTextureStages();
|
||||
|
||||
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;
|
||||
std::vector<BOOL> m_vertexShaderConstB;
|
||||
std::vector<ShaderConstI> m_vertexShaderConstI;
|
||||
State m_app;
|
||||
State m_current;
|
||||
std::array<ShaderConstF, 32> m_pixelShaderConst;
|
||||
std::array<ShaderConstB, 16> m_pixelShaderConstB;
|
||||
std::array<ShaderConstI, 16> m_pixelShaderConstI;
|
||||
std::array<ShaderConstF, 256> m_vertexShaderConst;
|
||||
std::array<ShaderConstB, 16> m_vertexShaderConstB;
|
||||
std::array<ShaderConstI, 16> m_vertexShaderConstI;
|
||||
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 ScopedPixelShaderConst
|
||||
{
|
||||
public:
|
||||
ScopedPixelShaderConst(
|
||||
DeviceState& deviceState, const D3DDDIARG_SETPIXELSHADERCONST& data, const ShaderConstF* registers)
|
||||
: m_deviceState(deviceState)
|
||||
, m_register(data.Register)
|
||||
{
|
||||
if (data.Register + data.Count > m_deviceState.m_pixelShaderConst.size())
|
||||
{
|
||||
m_deviceState.m_pixelShaderConst.resize(data.Register + data.Count);
|
||||
}
|
||||
|
||||
auto it = deviceState.m_pixelShaderConst.begin() + data.Register;
|
||||
m_prevRegisters.assign(it, it + data.Count);
|
||||
m_deviceState.pfnSetPixelShaderConst(&data, reinterpret_cast<const FLOAT*>(registers));
|
||||
}
|
||||
|
||||
~ScopedPixelShaderConst()
|
||||
{
|
||||
D3DDDIARG_SETPIXELSHADERCONST data = {};
|
||||
data.Register = m_register;
|
||||
data.Count = m_prevRegisters.size();
|
||||
m_deviceState.pfnSetPixelShaderConst(&data, reinterpret_cast<const FLOAT*>(m_prevRegisters.data()));
|
||||
}
|
||||
|
||||
private:
|
||||
DeviceState& m_deviceState;
|
||||
UINT m_register;
|
||||
std::vector<ShaderConstF> m_prevRegisters;
|
||||
};
|
||||
|
||||
class ScopedRenderState
|
||||
{
|
||||
public:
|
||||
ScopedRenderState(DeviceState& deviceState, const D3DDDIARG_RENDERSTATE& data);
|
||||
~ScopedRenderState();
|
||||
|
||||
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);
|
||||
~ScopedTextureStageState();
|
||||
|
||||
private:
|
||||
DeviceState& m_deviceState;
|
||||
D3DDDIARG_TEXTURESTAGESTATE m_prevData;
|
||||
};
|
||||
|
||||
class ScopedTexture
|
||||
{
|
||||
public:
|
||||
ScopedTexture(DeviceState& deviceState, UINT stage, HANDLE texture, UINT filter);
|
||||
~ScopedTexture();
|
||||
|
||||
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;
|
||||
ScopedTextureStageState m_scopedSrgbTexture;
|
||||
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;
|
||||
};
|
||||
UINT m_changedStates;
|
||||
UINT m_maxChangedTextureStage;
|
||||
BitSet<D3DDDIRS_ZENABLE, D3DDDIRS_BLENDOPALPHA> m_changedRenderStates;
|
||||
std::array<BitSet<D3DDDITSS_TEXTUREMAP, D3DDDITSS_TEXTURECOLORKEYVAL>, 8> m_changedTextureStageStates;
|
||||
};
|
||||
}
|
||||
|
@ -454,6 +454,8 @@ namespace D3dDdi
|
||||
|
||||
HRESULT DrawPrimitive::draw(D3DDDIARG_DRAWPRIMITIVE data, const UINT* flagBuffer)
|
||||
{
|
||||
m_device.getState().flush();
|
||||
|
||||
if (0 == m_batched.primitiveCount || flagBuffer ||
|
||||
!appendPrimitives(data.PrimitiveType, data.VStart, data.PrimitiveCount, nullptr, 0, 0))
|
||||
{
|
||||
@ -485,6 +487,8 @@ namespace D3dDdi
|
||||
HRESULT DrawPrimitive::drawIndexed(
|
||||
D3DDDIARG_DRAWINDEXEDPRIMITIVE2 data, const UINT16* indices, const UINT* flagBuffer)
|
||||
{
|
||||
m_device.getState().flush();
|
||||
|
||||
auto indexCount = getVertexCount(data.PrimitiveType, data.PrimitiveCount);
|
||||
auto [min, max] = std::minmax_element(indices, indices + indexCount);
|
||||
data.MinIndex = *min;
|
||||
|
@ -79,7 +79,7 @@ namespace D3dDdi
|
||||
|
||||
HRESULT setSysMemStreamSource(const BYTE* vertices, UINT stride);
|
||||
|
||||
HANDLE m_device;
|
||||
Device& m_device;
|
||||
const D3DDDI_DEVICEFUNCS& m_origVtable;
|
||||
DynamicVertexBuffer m_vertexBuffer;
|
||||
DynamicIndexBuffer m_indexBuffer;
|
||||
|
@ -105,7 +105,7 @@ namespace D3dDdi
|
||||
, m_origData(data)
|
||||
, m_fixedData(data)
|
||||
, m_lockBuffer(nullptr, &heapFree)
|
||||
, m_lockResource(nullptr, ResourceDeleter(device))
|
||||
, m_lockResource(nullptr, ResourceDeleter(device, device.getOrigVtable().pfnDestroyResource))
|
||||
, m_customSurface{}
|
||||
, m_multiSampleConfig{ D3DDDIMULTISAMPLE_NONE, 0 }
|
||||
, m_isSurfaceRepoResource(SurfaceRepository::inCreateSurface())
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <d3dumddi.h>
|
||||
|
||||
#include <D3dDdi/FormatInfo.h>
|
||||
#include <D3dDdi/ResourceDeleter.h>
|
||||
#include <D3dDdi/SurfaceRepository.h>
|
||||
|
||||
namespace D3dDdi
|
||||
@ -65,16 +66,6 @@ namespace D3dDdi
|
||||
bool isCustomUpToDate;
|
||||
};
|
||||
|
||||
class ResourceDeleter
|
||||
{
|
||||
public:
|
||||
ResourceDeleter(Device& device) : m_device(device) {}
|
||||
void operator()(HANDLE resource) { m_device.getOrigVtable().pfnDestroyResource(m_device, resource); }
|
||||
|
||||
private:
|
||||
Device& m_device;
|
||||
};
|
||||
|
||||
HRESULT bltLock(D3DDDIARG_LOCK& data);
|
||||
HRESULT bltUnlock(const D3DDDIARG_UNLOCK& data);
|
||||
void clipRect(UINT subResourceIndex, RECT& rect);
|
||||
|
27
DDrawCompat/D3dDdi/ResourceDeleter.h
Normal file
27
DDrawCompat/D3dDdi/ResourceDeleter.h
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
namespace D3dDdi
|
||||
{
|
||||
class ResourceDeleter
|
||||
{
|
||||
public:
|
||||
typedef HRESULT(APIENTRY* Deleter)(HANDLE, HANDLE);
|
||||
|
||||
ResourceDeleter(HANDLE device = nullptr, Deleter deleter = nullptr)
|
||||
: m_device(device)
|
||||
, m_deleter(deleter)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(HANDLE resource)
|
||||
{
|
||||
m_deleter(m_device, resource);
|
||||
}
|
||||
|
||||
private:
|
||||
HANDLE m_device;
|
||||
Deleter m_deleter;
|
||||
};
|
||||
}
|
@ -39,29 +39,32 @@ namespace D3dDdi
|
||||
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 });
|
||||
auto& state = m_device.getState();
|
||||
state.setTempRenderState({ D3DDDIRS_SCENECAPTURE, TRUE });
|
||||
state.setTempVertexShaderDecl(m_vertexShaderDecl.get());
|
||||
state.setTempPixelShader(pixelShader);
|
||||
state.setTempRenderTarget({ 0, dstResource, dstSubResourceIndex });
|
||||
state.setTempDepthStencil({ nullptr });
|
||||
state.setTempViewport({ 0, 0, dstSurface.Width, dstSurface.Height });
|
||||
state.setTempZRange({ 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(RenderState, { D3DDDIRS_SRGBWRITEENABLE, D3DTEXF_LINEAR == filter });
|
||||
state.setTempRenderState({ D3DDDIRS_ZENABLE, D3DZB_FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_FILLMODE, D3DFILL_SOLID });
|
||||
state.setTempRenderState({ D3DDDIRS_ZWRITEENABLE, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_ALPHATESTENABLE, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_CULLMODE, D3DCULL_NONE });
|
||||
state.setTempRenderState({ D3DDDIRS_DITHERENABLE, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_ALPHABLENDENABLE, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_FOGENABLE, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_COLORKEYENABLE, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_STENCILENABLE, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_CLIPPING, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_CLIPPLANEENABLE, 0 });
|
||||
state.setTempRenderState({ D3DDDIRS_MULTISAMPLEANTIALIAS, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_COLORWRITEENABLE, 0xF });
|
||||
state.setTempRenderState({ D3DDDIRS_SRGBWRITEENABLE, D3DTEXF_LINEAR == filter });
|
||||
|
||||
SCOPED_STATE(Texture, 0, srcResource, filter);
|
||||
setTempTextureStage(0, srcResource, filter);
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
@ -83,9 +86,9 @@ namespace D3dDdi
|
||||
{ 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);
|
||||
state.setTempStreamSourceUm({ 0, sizeof(Vertex) }, vertices);
|
||||
|
||||
DeviceState::TempStateLock lock(state);
|
||||
|
||||
D3DDDIARG_DRAWPRIMITIVE dp = {};
|
||||
dp.PrimitiveType = D3DPT_TRIANGLEFAN;
|
||||
@ -95,7 +98,7 @@ namespace D3dDdi
|
||||
m_device.flushPrimitives();
|
||||
}
|
||||
|
||||
HANDLE ShaderBlitter::createPixelShader(const BYTE* code, UINT size)
|
||||
std::unique_ptr<void, ResourceDeleter> ShaderBlitter::createPixelShader(const BYTE* code, UINT size)
|
||||
{
|
||||
D3DDDIARG_CREATEPIXELSHADER data = {};
|
||||
data.CodeSize = size;
|
||||
@ -103,10 +106,10 @@ namespace D3dDdi
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return data.ShaderHandle;
|
||||
return { data.ShaderHandle, ResourceDeleter(m_device, m_device.getOrigVtable().pfnDeletePixelShader) };
|
||||
}
|
||||
|
||||
HANDLE ShaderBlitter::createVertexShaderDecl()
|
||||
std::unique_ptr<void, ResourceDeleter> ShaderBlitter::createVertexShaderDecl()
|
||||
{
|
||||
const UINT D3DDECLTYPE_FLOAT2 = 1;
|
||||
const UINT D3DDECLTYPE_FLOAT4 = 3;
|
||||
@ -126,7 +129,7 @@ namespace D3dDdi
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return data.ShaderHandle;
|
||||
return { data.ShaderHandle, ResourceDeleter(m_device, m_device.getOrigVtable().pfnDeleteVertexShaderDecl) };
|
||||
}
|
||||
|
||||
void ShaderBlitter::cursorBlt(const Resource& dstResource, UINT dstSubResourceIndex, HCURSOR cursor, POINT pt)
|
||||
@ -163,10 +166,10 @@ namespace D3dDdi
|
||||
data.DstRect = clippedSrcRect;
|
||||
m_device.getOrigVtable().pfnBlt(m_device, &data);
|
||||
|
||||
SCOPED_STATE(Texture, 1, *cur.maskTexture, D3DTEXF_POINT);
|
||||
SCOPED_STATE(Texture, 2, *cur.colorTexture, D3DTEXF_POINT);
|
||||
SCOPED_STATE(Texture, 3, *xorTexture, D3DTEXF_POINT);
|
||||
blt(dstResource, dstSubResourceIndex, clippedDstRect, *cur.tempTexture, clippedSrcRect, m_psDrawCursor, D3DTEXF_POINT);
|
||||
setTempTextureStage(1, *cur.maskTexture, D3DTEXF_POINT);
|
||||
setTempTextureStage(2, *cur.colorTexture, D3DTEXF_POINT);
|
||||
setTempTextureStage(3, *xorTexture, D3DTEXF_POINT);
|
||||
blt(dstResource, dstSubResourceIndex, clippedDstRect, *cur.tempTexture, clippedSrcRect, m_psDrawCursor.get(), D3DTEXF_POINT);
|
||||
}
|
||||
|
||||
void ShaderBlitter::genBilinearBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||
@ -174,7 +177,7 @@ namespace D3dDdi
|
||||
{
|
||||
if (100 == blurPercent)
|
||||
{
|
||||
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcRect, m_psTextureSampler, D3DTEXF_LINEAR);
|
||||
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcRect, m_psTextureSampler.get(), D3DTEXF_LINEAR);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -186,14 +189,13 @@ namespace D3dDdi
|
||||
scaleX = 1 / ((1 - blur) / scaleX + blur);
|
||||
scaleY = 1 / ((1 - blur) / scaleY + blur);
|
||||
|
||||
const DeviceState::ShaderConstF registers[] = {
|
||||
const std::array<DeviceState::ShaderConstF, 2> registers{ {
|
||||
{ static_cast<float>(srcDesc.Width), static_cast<float>(srcDesc.Height), 0.0f, 0.0f },
|
||||
{ scaleX, scaleY, 0.0f, 0.0f }
|
||||
};
|
||||
} };
|
||||
|
||||
SCOPED_STATE(PixelShaderConst, { 0, sizeof(registers) / sizeof(registers[0]) }, registers);
|
||||
|
||||
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcRect, m_psGenBilinear, D3DTEXF_LINEAR);
|
||||
DeviceState::TempPixelShaderConst tempPsConst(m_device.getState(), { 0, registers.size() }, registers.data());
|
||||
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcRect, m_psGenBilinear.get(), D3DTEXF_LINEAR);
|
||||
}
|
||||
|
||||
void ShaderBlitter::palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex,
|
||||
@ -228,7 +230,20 @@ namespace D3dDdi
|
||||
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, *paletteTexture, D3DTEXF_POINT);
|
||||
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcRect, m_psPaletteLookup, D3DTEXF_POINT);
|
||||
setTempTextureStage(1, *paletteTexture, D3DTEXF_POINT);
|
||||
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcRect, m_psPaletteLookup.get(), D3DTEXF_POINT);
|
||||
}
|
||||
|
||||
void ShaderBlitter::setTempTextureStage(UINT stage, HANDLE texture, UINT filter)
|
||||
{
|
||||
auto& state = m_device.getState();
|
||||
state.setTempTexture(stage, texture);
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_ADDRESSU, D3DTADDRESS_CLAMP });
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_ADDRESSV, D3DTADDRESS_CLAMP });
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_MAGFILTER, filter });
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_MINFILTER, filter });
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_MIPFILTER, D3DTEXF_NONE });
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_SRGBTEXTURE, D3DTEXF_LINEAR == filter });
|
||||
state.setTempRenderState({ static_cast<D3DDDIRENDERSTATETYPE>(D3DDDIRS_WRAP0 + stage), 0 });
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include <D3dDdi/ResourceDeleter.h>
|
||||
|
||||
namespace D3dDdi
|
||||
{
|
||||
class Device;
|
||||
@ -27,19 +31,20 @@ namespace D3dDdi
|
||||
const Resource& srcResource, const RECT& srcRect, HANDLE pixelShader, UINT filter);
|
||||
|
||||
template <int N>
|
||||
HANDLE createPixelShader(const BYTE(&code)[N])
|
||||
std::unique_ptr<void, ResourceDeleter> createPixelShader(const BYTE(&code)[N])
|
||||
{
|
||||
return createPixelShader(code, N);
|
||||
}
|
||||
|
||||
HANDLE createPixelShader(const BYTE* code, UINT size);
|
||||
HANDLE createVertexShaderDecl();
|
||||
std::unique_ptr<void, ResourceDeleter> createPixelShader(const BYTE* code, UINT size);
|
||||
std::unique_ptr<void, ResourceDeleter> createVertexShaderDecl();
|
||||
void setTempTextureStage(UINT stage, HANDLE texture, UINT filter);
|
||||
|
||||
Device& m_device;
|
||||
HANDLE m_psDrawCursor;
|
||||
HANDLE m_psGenBilinear;
|
||||
HANDLE m_psPaletteLookup;
|
||||
HANDLE m_psTextureSampler;
|
||||
HANDLE m_vertexShaderDecl;
|
||||
std::unique_ptr<void, ResourceDeleter> m_psDrawCursor;
|
||||
std::unique_ptr<void, ResourceDeleter> m_psGenBilinear;
|
||||
std::unique_ptr<void, ResourceDeleter> m_psPaletteLookup;
|
||||
std::unique_ptr<void, ResourceDeleter> m_psTextureSampler;
|
||||
std::unique_ptr<void, ResourceDeleter> m_vertexShaderDecl;
|
||||
};
|
||||
}
|
||||
|
@ -191,6 +191,7 @@
|
||||
</FxCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Common\BitSet.h" />
|
||||
<ClInclude Include="Common\Comparison.h" />
|
||||
<ClInclude Include="Common\CompatPtr.h" />
|
||||
<ClInclude Include="Common\CompatQueryInterface.h" />
|
||||
@ -241,6 +242,7 @@
|
||||
<ClInclude Include="D3dDdi\Log\DeviceFuncsLog.h" />
|
||||
<ClInclude Include="D3dDdi\Log\KernelModeThunksLog.h" />
|
||||
<ClInclude Include="D3dDdi\Resource.h" />
|
||||
<ClInclude Include="D3dDdi\ResourceDeleter.h" />
|
||||
<ClInclude Include="D3dDdi\ScopedCriticalSection.h" />
|
||||
<ClInclude Include="D3dDdi\ShaderBlitter.h" />
|
||||
<ClInclude Include="D3dDdi\SurfaceRepository.h" />
|
||||
|
@ -495,6 +495,12 @@
|
||||
<ClInclude Include="D3dDdi\Log\AdapterCallbacksLog.h">
|
||||
<Filter>Header Files\D3dDdi\Log</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Common\BitSet.h">
|
||||
<Filter>Header Files\Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="D3dDdi\ResourceDeleter.h">
|
||||
<Filter>Header Files\D3dDdi</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Gdi\Gdi.cpp">
|
||||
|
Loading…
x
Reference in New Issue
Block a user