Skip to content

Instantly share code, notes, and snippets.

@zeux
Created February 12, 2016 08:33
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save zeux/66e62f12fa4616711088 to your computer and use it in GitHub Desktop.
Save zeux/66e62f12fa4616711088 to your computer and use it in GitHub Desktop.
Implementing Direct3D for fun and profit
struct DeferredDirect3DDevice9: DummyDirect3DDevice9
{
private:
char* begin;
char* write;
char* read;
char* end;
enum command_t
{
DC_Unknown = 0,
DC_BeginScene,
DC_EndScene,
DC_SetRenderTarget,
DC_SetDepthStencilSurface,
DC_Clear,
DC_StretchRect,
DC_SetViewport,
DC_SetScissorRect,
DC_DrawPrimitive,
DC_DrawIndexedPrimitive,
DC_DrawPrimitiveUP,
DC_SetVertexDeclaration,
DC_SetStreamSource,
DC_SetStreamSourceFreq,
DC_SetIndices,
DC_SetVertexShader,
DC_SetPixelShader,
DC_SetVertexShaderConstantF,
DC_SetPixelShaderConstantF,
DC_SetTexture,
DC_SetSamplerState,
DC_SetRenderState
};
template <typename T> __forceinline void put(T value)
{
DL_ASSERT(write + sizeof(T) <= end);
*(T*)write = value;
write += sizeof(T);
}
__forceinline void put(const void* data, size_t size)
{
DL_ASSERT(write + size <= end);
memcpy(write, data, size);
write += size;
}
template <typename T> __forceinline T get()
{
DL_ASSERT(read + sizeof(T) <= write);
char* result = read;
read += sizeof(T);
return *(T*)result;
}
inline unsigned int get_vertex_count(D3DPRIMITIVETYPE type, unsigned int primitive_count)
{
switch (type)
{
case D3DPT_POINTLIST:
return primitive_count;
case D3DPT_LINELIST:
return primitive_count * 2;
case D3DPT_LINESTRIP:
return primitive_count + 1;
case D3DPT_TRIANGLELIST:
return primitive_count * 3;
case D3DPT_TRIANGLESTRIP:
return primitive_count + 2;
case D3DPT_TRIANGLEFAN:
return primitive_count + 2;
default:
DL_ASSERT(!"unknown primitive type");
return 0;
}
}
STDMETHOD(BeginScene)(THIS)
{
put(DC_BeginScene);
return S_OK;
}
STDMETHOD(EndScene)(THIS)
{
put(DC_EndScene);
return S_OK;
}
STDMETHOD(SetRenderTarget)(THIS_ DWORD RenderTargetIndex,IDirect3DSurface9* pRenderTarget)
{
put(DC_SetRenderTarget);
put(RenderTargetIndex);
put(pRenderTarget);
return S_OK;
}
STDMETHOD(SetDepthStencilSurface)(THIS_ IDirect3DSurface9* pNewZStencil)
{
put(DC_SetDepthStencilSurface);
put(pNewZStencil);
return S_OK;
}
STDMETHOD(Clear)(THIS_ DWORD Count,CONST D3DRECT* pRects,DWORD Flags,D3DCOLOR Color,float Z,DWORD Stencil)
{
DL_ASSERT(Count == 0 && pRects == 0);
put(DC_Clear);
put(Flags);
put(Color);
put(Z);
put(Stencil);
return S_OK;
}
STDMETHOD(StretchRect)(THIS_ IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect,IDirect3DSurface9* pDestSurface,CONST RECT* pDestRect,D3DTEXTUREFILTERTYPE Filter)
{
DL_ASSERT(pSourceRect == 0 && pDestRect == 0);
put(DC_StretchRect);
put(pSourceSurface);
put(pDestSurface);
put(Filter);
return S_OK;
}
STDMETHOD(SetViewport)(THIS_ CONST D3DVIEWPORT9* pViewport)
{
put(DC_SetViewport);
put(*pViewport);
return S_OK;
}
STDMETHOD(SetScissorRect)(THIS_ CONST RECT* pRect)
{
put(DC_SetScissorRect);
put(*pRect);
return S_OK;
}
STDMETHOD(DrawPrimitive)(THIS_ D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount)
{
put(DC_DrawPrimitive);
put(PrimitiveType);
put(StartVertex);
put(PrimitiveCount);
return S_OK;
}
STDMETHOD(DrawIndexedPrimitive)(THIS_ D3DPRIMITIVETYPE PrimitiveType,INT BaseVertexIndex,UINT MinVertexIndex,UINT NumVertices,UINT startIndex,UINT primCount)
{
put(DC_DrawIndexedPrimitive);
put(PrimitiveType);
put(BaseVertexIndex);
put(MinVertexIndex);
put(NumVertices);
put(startIndex);
put(primCount);
return S_OK;
}
STDMETHOD(DrawPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride)
{
put(DC_DrawPrimitiveUP);
put(PrimitiveType);
put(PrimitiveCount);
put(VertexStreamZeroStride);
unsigned int data_size = get_vertex_count(PrimitiveType, PrimitiveCount) * VertexStreamZeroStride;
put(pVertexStreamZeroData, data_size);
return S_OK;
}
STDMETHOD(SetVertexDeclaration)(THIS_ IDirect3DVertexDeclaration9* pDecl)
{
put(DC_SetVertexDeclaration);
put(pDecl);
return S_OK;
}
STDMETHOD(SetStreamSource)(THIS_ UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride)
{
put(DC_SetStreamSource);
put(StreamNumber);
put(pStreamData);
put(OffsetInBytes);
put(Stride);
return S_OK;
}
STDMETHOD(SetStreamSourceFreq)(THIS_ UINT StreamNumber,UINT Setting)
{
put(DC_SetStreamSourceFreq);
put(StreamNumber);
put(Setting);
return S_OK;
}
STDMETHOD(SetIndices)(THIS_ IDirect3DIndexBuffer9* pIndexData)
{
put(DC_SetIndices);
put(pIndexData);
return S_OK;
}
STDMETHOD(SetVertexShader)(THIS_ IDirect3DVertexShader9* pShader)
{
put(DC_SetVertexShader);
put(pShader);
return S_OK;
}
STDMETHOD(SetPixelShader)(THIS_ IDirect3DPixelShader9* pShader)
{
put(DC_SetPixelShader);
put(pShader);
return S_OK;
}
STDMETHOD(SetVertexShaderConstantF)(THIS_ UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount)
{
put(DC_SetVertexShaderConstantF);
put(StartRegister);
put(Vector4fCount);
put(pConstantData, Vector4fCount * 4 * sizeof(float));
return S_OK;
}
STDMETHOD(SetPixelShaderConstantF)(THIS_ UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount)
{
put(DC_SetPixelShaderConstantF);
put(StartRegister);
put(Vector4fCount);
put(pConstantData, Vector4fCount * 4 * sizeof(float));
return S_OK;
}
STDMETHOD(SetTexture)(THIS_ DWORD Stage,IDirect3DBaseTexture9* pTexture)
{
put(DC_SetTexture);
put(Stage);
put(pTexture);
return S_OK;
}
STDMETHOD(SetSamplerState)(THIS_ DWORD Sampler,D3DSAMPLERSTATETYPE Type,DWORD Value)
{
put(DC_SetSamplerState);
put(Sampler);
put(Type);
put(Value);
return S_OK;
}
STDMETHOD(SetRenderState)(THIS_ D3DRENDERSTATETYPE State,DWORD Value)
{
put(DC_SetRenderState);
put(State);
put(Value);
return S_OK;
}
public:
DeferredDirect3DDevice9(void* memory, size_t size)
{
begin = (char*)memory;
end = begin + size;
reset();
}
void reset()
{
read = write = begin;
}
void kick(IDirect3DDevice9* device)
{
#define GET(type, var) type var = get<type>()
#define CALL(expr) hr = device->expr; DL_ASSERT(SUCCEEDED(hr))
HRESULT hr;
read = begin;
while (read < write)
{
GET(enum command_t, command);
switch (command)
{
case DC_Unknown:
{
DL_ASSERT(!"unknown command");
} break;
case DC_BeginScene:
{
CALL(BeginScene());
} break;
case DC_EndScene:
{
CALL(EndScene());
} break;
case DC_SetRenderTarget:
{
GET(UINT, RenderTargetIndex);
GET(IDirect3DSurface9*, pRenderTarget);
CALL(SetRenderTarget(RenderTargetIndex, pRenderTarget));
} break;
case DC_SetDepthStencilSurface:
{
GET(IDirect3DSurface9*, pNewZStencil);
CALL(SetDepthStencilSurface(pNewZStencil));
} break;
case DC_Clear:
{
GET(DWORD, Flags);
GET(D3DCOLOR, Color);
GET(float, Z);
GET(DWORD, Stencil);
CALL(Clear(0, 0, Flags, Color, Z, Stencil));
} break;
case DC_StretchRect:
{
GET(IDirect3DSurface9*, pSourceSurface);
GET(IDirect3DSurface9*, pDestSurface);
GET(D3DTEXTUREFILTERTYPE, Filter);
CALL(StretchRect(pSourceSurface, 0, pDestSurface, 0, Filter));
} break;
case DC_SetViewport:
{
GET(D3DVIEWPORT9, Viewport);
CALL(SetViewport(&Viewport));
} break;
case DC_SetScissorRect:
{
GET(RECT, Rect);
CALL(SetScissorRect(&Rect));
} break;
case DC_DrawPrimitive:
{
GET(D3DPRIMITIVETYPE, PrimitiveType);
GET(UINT, StartVertex);
GET(UINT, PrimitiveCount);
CALL(DrawPrimitive(PrimitiveType, StartVertex, PrimitiveCount));
} break;
case DC_DrawIndexedPrimitive:
{
GET(D3DPRIMITIVETYPE, PrimitiveType);
GET(INT, BaseVertexIndex);
GET(UINT, MinVertexIndex);
GET(UINT, NumVertices);
GET(UINT, startIndex);
GET(UINT, primCount);
CALL(DrawIndexedPrimitive(PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount));
} break;
case DC_DrawPrimitiveUP:
{
GET(D3DPRIMITIVETYPE, PrimitiveType);
GET(UINT, PrimitiveCount);
GET(UINT, VertexStreamZeroStride);
unsigned int data_size = get_vertex_count(PrimitiveType, PrimitiveCount) * VertexStreamZeroStride;
DL_ASSERT(read + data_size <= write);
CALL(DrawPrimitiveUP(PrimitiveType, PrimitiveCount, read, VertexStreamZeroStride));
read += data_size;
} break;
case DC_SetVertexDeclaration:
{
GET(IDirect3DVertexDeclaration9*, pDecl);
CALL(SetVertexDeclaration(pDecl));
} break;
case DC_SetStreamSource:
{
GET(UINT, StreamNumber);
GET(IDirect3DVertexBuffer9*, pStreamData);
GET(UINT, OffsetInBytes);
GET(UINT, Stride);
CALL(SetStreamSource(StreamNumber, pStreamData, OffsetInBytes, Stride));
} break;
case DC_SetStreamSourceFreq:
{
GET(UINT, StreamNumber);
GET(UINT, Setting);
CALL(SetStreamSourceFreq(StreamNumber, Setting));
} break;
case DC_SetIndices:
{
GET(IDirect3DIndexBuffer9*, pIndexData);
CALL(SetIndices(pIndexData));
} break;
case DC_SetVertexShader:
{
GET(IDirect3DVertexShader9*, pShader);
CALL(SetVertexShader(pShader));
} break;
case DC_SetPixelShader:
{
GET(IDirect3DPixelShader9*, pShader);
CALL(SetPixelShader(pShader));
} break;
case DC_SetVertexShaderConstantF:
{
GET(UINT, StartRegister);
GET(UINT, Vector4fCount);
DL_ASSERT(read + Vector4fCount * 4 * sizeof(float) <= write);
CALL(SetVertexShaderConstantF(StartRegister, (const float*)read, Vector4fCount));
read += Vector4fCount * 4 * sizeof(float);
} break;
case DC_SetPixelShaderConstantF:
{
GET(UINT, StartRegister);
GET(UINT, Vector4fCount);
DL_ASSERT(read + Vector4fCount * 4 * sizeof(float) <= write);
CALL(SetPixelShaderConstantF(StartRegister, (const float*)read, Vector4fCount));
read += Vector4fCount * 4 * sizeof(float);
} break;
case DC_SetTexture:
{
GET(DWORD, Stage);
GET(IDirect3DBaseTexture9*, pTexture);
CALL(SetTexture(Stage, pTexture));
} break;
case DC_SetSamplerState:
{
GET(DWORD, Sampler);
GET(D3DSAMPLERSTATETYPE, Type);
GET(DWORD, Value);
CALL(SetSamplerState(Sampler, Type, Value));
} break;
case DC_SetRenderState:
{
GET(D3DRENDERSTATETYPE, State);
GET(DWORD, Value);
CALL(SetRenderState(State, Value));
} break;
default:
DL_ASSERT(!"unknown command");
}
}
DL_ASSERT(read == write);
#undef CALL
#undef GET
}
};
#pragma push_macro("PURE")
#undef PURE
#define PURE { DL_BREAK(); return 0; }
#define PUREVOID { DL_BREAK(); }
#pragma warning(push)
#pragma warning(disable: 4100) // unreferenced formal parameter
struct DummyDirect3DDevice9: IDirect3DDevice9
{
/*** IUnknown methods ***/
STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
/*** IDirect3DDevice9 methods ***/
STDMETHOD(TestCooperativeLevel)(THIS) PURE;
STDMETHOD_(UINT, GetAvailableTextureMem)(THIS) PURE;
STDMETHOD(EvictManagedResources)(THIS) PURE;
STDMETHOD(GetDirect3D)(THIS_ IDirect3D9** ppD3D9) PURE;
STDMETHOD(GetDeviceCaps)(THIS_ D3DCAPS9* pCaps) PURE;
STDMETHOD(GetDisplayMode)(THIS_ UINT iSwapChain,D3DDISPLAYMODE* pMode) PURE;
STDMETHOD(GetCreationParameters)(THIS_ D3DDEVICE_CREATION_PARAMETERS *pParameters) PURE;
STDMETHOD(SetCursorProperties)(THIS_ UINT XHotSpot,UINT YHotSpot,IDirect3DSurface9* pCursorBitmap) PURE;
STDMETHOD_(void, SetCursorPosition)(THIS_ int X,int Y,DWORD Flags) PUREVOID;
STDMETHOD_(BOOL, ShowCursor)(THIS_ BOOL bShow) PURE;
STDMETHOD(CreateAdditionalSwapChain)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DSwapChain9** pSwapChain) PURE;
STDMETHOD(GetSwapChain)(THIS_ UINT iSwapChain,IDirect3DSwapChain9** pSwapChain) PURE;
STDMETHOD_(UINT, GetNumberOfSwapChains)(THIS) PURE;
STDMETHOD(Reset)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters) PURE;
STDMETHOD(Present)(THIS_ CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) PURE;
STDMETHOD(GetBackBuffer)(THIS_ UINT iSwapChain,UINT iBackBuffer,D3DBACKBUFFER_TYPE Type,IDirect3DSurface9** ppBackBuffer) PURE;
STDMETHOD(GetRasterStatus)(THIS_ UINT iSwapChain,D3DRASTER_STATUS* pRasterStatus) PURE;
STDMETHOD(SetDialogBoxMode)(THIS_ BOOL bEnableDialogs) PURE;
STDMETHOD_(void, SetGammaRamp)(THIS_ UINT iSwapChain,DWORD Flags,CONST D3DGAMMARAMP* pRamp) PUREVOID;
STDMETHOD_(void, GetGammaRamp)(THIS_ UINT iSwapChain,D3DGAMMARAMP* pRamp) PUREVOID;
STDMETHOD(CreateTexture)(THIS_ UINT Width,UINT Height,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DTexture9** ppTexture,HANDLE* pSharedHandle) PURE;
STDMETHOD(CreateVolumeTexture)(THIS_ UINT Width,UINT Height,UINT Depth,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DVolumeTexture9** ppVolumeTexture,HANDLE* pSharedHandle) PURE;
STDMETHOD(CreateCubeTexture)(THIS_ UINT EdgeLength,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DCubeTexture9** ppCubeTexture,HANDLE* pSharedHandle) PURE;
STDMETHOD(CreateVertexBuffer)(THIS_ UINT Length,DWORD Usage,DWORD FVF,D3DPOOL Pool,IDirect3DVertexBuffer9** ppVertexBuffer,HANDLE* pSharedHandle) PURE;
STDMETHOD(CreateIndexBuffer)(THIS_ UINT Length,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DIndexBuffer9** ppIndexBuffer,HANDLE* pSharedHandle) PURE;
STDMETHOD(CreateRenderTarget)(THIS_ UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Lockable,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle) PURE;
STDMETHOD(CreateDepthStencilSurface)(THIS_ UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Discard,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle) PURE;
STDMETHOD(UpdateSurface)(THIS_ IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect,IDirect3DSurface9* pDestinationSurface,CONST POINT* pDestPoint) PURE;
STDMETHOD(UpdateTexture)(THIS_ IDirect3DBaseTexture9* pSourceTexture,IDirect3DBaseTexture9* pDestinationTexture) PURE;
STDMETHOD(GetRenderTargetData)(THIS_ IDirect3DSurface9* pRenderTarget,IDirect3DSurface9* pDestSurface) PURE;
STDMETHOD(GetFrontBufferData)(THIS_ UINT iSwapChain,IDirect3DSurface9* pDestSurface) PURE;
STDMETHOD(StretchRect)(THIS_ IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect,IDirect3DSurface9* pDestSurface,CONST RECT* pDestRect,D3DTEXTUREFILTERTYPE Filter) PURE;
STDMETHOD(ColorFill)(THIS_ IDirect3DSurface9* pSurface,CONST RECT* pRect,D3DCOLOR color) PURE;
STDMETHOD(CreateOffscreenPlainSurface)(THIS_ UINT Width,UINT Height,D3DFORMAT Format,D3DPOOL Pool,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle) PURE;
STDMETHOD(SetRenderTarget)(THIS_ DWORD RenderTargetIndex,IDirect3DSurface9* pRenderTarget) PURE;
STDMETHOD(GetRenderTarget)(THIS_ DWORD RenderTargetIndex,IDirect3DSurface9** ppRenderTarget) PURE;
STDMETHOD(SetDepthStencilSurface)(THIS_ IDirect3DSurface9* pNewZStencil) PURE;
STDMETHOD(GetDepthStencilSurface)(THIS_ IDirect3DSurface9** ppZStencilSurface) PURE;
STDMETHOD(BeginScene)(THIS) PURE;
STDMETHOD(EndScene)(THIS) PURE;
STDMETHOD(Clear)(THIS_ DWORD Count,CONST D3DRECT* pRects,DWORD Flags,D3DCOLOR Color,float Z,DWORD Stencil) PURE;
STDMETHOD(SetTransform)(THIS_ D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix) PURE;
STDMETHOD(GetTransform)(THIS_ D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) PURE;
STDMETHOD(MultiplyTransform)(THIS_ D3DTRANSFORMSTATETYPE,CONST D3DMATRIX*) PURE;
STDMETHOD(SetViewport)(THIS_ CONST D3DVIEWPORT9* pViewport) PURE;
STDMETHOD(GetViewport)(THIS_ D3DVIEWPORT9* pViewport) PURE;
STDMETHOD(SetMaterial)(THIS_ CONST D3DMATERIAL9* pMaterial) PURE;
STDMETHOD(GetMaterial)(THIS_ D3DMATERIAL9* pMaterial) PURE;
STDMETHOD(SetLight)(THIS_ DWORD Index,CONST D3DLIGHT9*) PURE;
STDMETHOD(GetLight)(THIS_ DWORD Index,D3DLIGHT9*) PURE;
STDMETHOD(LightEnable)(THIS_ DWORD Index,BOOL Enable) PURE;
STDMETHOD(GetLightEnable)(THIS_ DWORD Index,BOOL* pEnable) PURE;
STDMETHOD(SetClipPlane)(THIS_ DWORD Index,CONST float* pPlane) PURE;
STDMETHOD(GetClipPlane)(THIS_ DWORD Index,float* pPlane) PURE;
STDMETHOD(SetRenderState)(THIS_ D3DRENDERSTATETYPE State,DWORD Value) PURE;
STDMETHOD(GetRenderState)(THIS_ D3DRENDERSTATETYPE State,DWORD* pValue) PURE;
STDMETHOD(CreateStateBlock)(THIS_ D3DSTATEBLOCKTYPE Type,IDirect3DStateBlock9** ppSB) PURE;
STDMETHOD(BeginStateBlock)(THIS) PURE;
STDMETHOD(EndStateBlock)(THIS_ IDirect3DStateBlock9** ppSB) PURE;
STDMETHOD(SetClipStatus)(THIS_ CONST D3DCLIPSTATUS9* pClipStatus) PURE;
STDMETHOD(GetClipStatus)(THIS_ D3DCLIPSTATUS9* pClipStatus) PURE;
STDMETHOD(GetTexture)(THIS_ DWORD Stage,IDirect3DBaseTexture9** ppTexture) PURE;
STDMETHOD(SetTexture)(THIS_ DWORD Stage,IDirect3DBaseTexture9* pTexture) PURE;
STDMETHOD(GetTextureStageState)(THIS_ DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) PURE;
STDMETHOD(SetTextureStageState)(THIS_ DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD Value) PURE;
STDMETHOD(GetSamplerState)(THIS_ DWORD Sampler,D3DSAMPLERSTATETYPE Type,DWORD* pValue) PURE;
STDMETHOD(SetSamplerState)(THIS_ DWORD Sampler,D3DSAMPLERSTATETYPE Type,DWORD Value) PURE;
STDMETHOD(ValidateDevice)(THIS_ DWORD* pNumPasses) PURE;
STDMETHOD(SetPaletteEntries)(THIS_ UINT PaletteNumber,CONST PALETTEENTRY* pEntries) PURE;
STDMETHOD(GetPaletteEntries)(THIS_ UINT PaletteNumber,PALETTEENTRY* pEntries) PURE;
STDMETHOD(SetCurrentTexturePalette)(THIS_ UINT PaletteNumber) PURE;
STDMETHOD(GetCurrentTexturePalette)(THIS_ UINT *PaletteNumber) PURE;
STDMETHOD(SetScissorRect)(THIS_ CONST RECT* pRect) PURE;
STDMETHOD(GetScissorRect)(THIS_ RECT* pRect) PURE;
STDMETHOD(SetSoftwareVertexProcessing)(THIS_ BOOL bSoftware) PURE;
STDMETHOD_(BOOL, GetSoftwareVertexProcessing)(THIS) PURE;
STDMETHOD(SetNPatchMode)(THIS_ float nSegments) PURE;
STDMETHOD_(float, GetNPatchMode)(THIS) PURE;
STDMETHOD(DrawPrimitive)(THIS_ D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount) PURE;
STDMETHOD(DrawIndexedPrimitive)(THIS_ D3DPRIMITIVETYPE,INT BaseVertexIndex,UINT MinVertexIndex,UINT NumVertices,UINT startIndex,UINT primCount) PURE;
STDMETHOD(DrawPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) PURE;
STDMETHOD(DrawIndexedPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,UINT NumVertices,UINT PrimitiveCount,CONST void* pIndexData,D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) PURE;
STDMETHOD(ProcessVertices)(THIS_ UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer9* pDestBuffer,IDirect3DVertexDeclaration9* pVertexDecl,DWORD Flags) PURE;
STDMETHOD(CreateVertexDeclaration)(THIS_ CONST D3DVERTEXELEMENT9* pVertexElements,IDirect3DVertexDeclaration9** ppDecl) PURE;
STDMETHOD(SetVertexDeclaration)(THIS_ IDirect3DVertexDeclaration9* pDecl) PURE;
STDMETHOD(GetVertexDeclaration)(THIS_ IDirect3DVertexDeclaration9** ppDecl) PURE;
STDMETHOD(SetFVF)(THIS_ DWORD FVF) PURE;
STDMETHOD(GetFVF)(THIS_ DWORD* pFVF) PURE;
STDMETHOD(CreateVertexShader)(THIS_ CONST DWORD* pFunction,IDirect3DVertexShader9** ppShader) PURE;
STDMETHOD(SetVertexShader)(THIS_ IDirect3DVertexShader9* pShader) PURE;
STDMETHOD(GetVertexShader)(THIS_ IDirect3DVertexShader9** ppShader) PURE;
STDMETHOD(SetVertexShaderConstantF)(THIS_ UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount) PURE;
STDMETHOD(GetVertexShaderConstantF)(THIS_ UINT StartRegister,float* pConstantData,UINT Vector4fCount) PURE;
STDMETHOD(SetVertexShaderConstantI)(THIS_ UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount) PURE;
STDMETHOD(GetVertexShaderConstantI)(THIS_ UINT StartRegister,int* pConstantData,UINT Vector4iCount) PURE;
STDMETHOD(SetVertexShaderConstantB)(THIS_ UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount) PURE;
STDMETHOD(GetVertexShaderConstantB)(THIS_ UINT StartRegister,BOOL* pConstantData,UINT BoolCount) PURE;
STDMETHOD(SetStreamSource)(THIS_ UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride) PURE;
STDMETHOD(GetStreamSource)(THIS_ UINT StreamNumber,IDirect3DVertexBuffer9** ppStreamData,UINT* pOffsetInBytes,UINT* pStride) PURE;
STDMETHOD(SetStreamSourceFreq)(THIS_ UINT StreamNumber,UINT Setting) PURE;
STDMETHOD(GetStreamSourceFreq)(THIS_ UINT StreamNumber,UINT* pSetting) PURE;
STDMETHOD(SetIndices)(THIS_ IDirect3DIndexBuffer9* pIndexData) PURE;
STDMETHOD(GetIndices)(THIS_ IDirect3DIndexBuffer9** ppIndexData) PURE;
STDMETHOD(CreatePixelShader)(THIS_ CONST DWORD* pFunction,IDirect3DPixelShader9** ppShader) PURE;
STDMETHOD(SetPixelShader)(THIS_ IDirect3DPixelShader9* pShader) PURE;
STDMETHOD(GetPixelShader)(THIS_ IDirect3DPixelShader9** ppShader) PURE;
STDMETHOD(SetPixelShaderConstantF)(THIS_ UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount) PURE;
STDMETHOD(GetPixelShaderConstantF)(THIS_ UINT StartRegister,float* pConstantData,UINT Vector4fCount) PURE;
STDMETHOD(SetPixelShaderConstantI)(THIS_ UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount) PURE;
STDMETHOD(GetPixelShaderConstantI)(THIS_ UINT StartRegister,int* pConstantData,UINT Vector4iCount) PURE;
STDMETHOD(SetPixelShaderConstantB)(THIS_ UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount) PURE;
STDMETHOD(GetPixelShaderConstantB)(THIS_ UINT StartRegister,BOOL* pConstantData,UINT BoolCount) PURE;
STDMETHOD(DrawRectPatch)(THIS_ UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) PURE;
STDMETHOD(DrawTriPatch)(THIS_ UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) PURE;
STDMETHOD(DeletePatch)(THIS_ UINT Handle) PURE;
STDMETHOD(CreateQuery)(THIS_ D3DQUERYTYPE Type,IDirect3DQuery9** ppQuery) PURE;
};
#pragma warning(pop)
#undef PUREVOID
#pragma pop_macro("PURE")
inline UINT get_image_size(UINT Width, UINT Height, D3DFORMAT Format)
{
switch (Format)
{
case D3DFMT_A8R8G8B8:
case D3DFMT_A8B8G8R8:
return Width * Height * 4;
default:
DL_BREAK();
return 0;
}
}
#pragma push_macro("PURE")
#undef PURE
#define PURE { DL_BREAK(); return 0; }
#define PURE_(type) { DL_BREAK(); return (type)0; }
#pragma warning(push)
#pragma warning(disable: 4100) // unreferenced formal parameter
template <typename T>
struct SimpleUnknown: T
{
ULONG RefCount;
SimpleUnknown(): RefCount(1)
{
}
virtual ~SimpleUnknown()
{
assert(RefCount == 0);
}
STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE;
STDMETHOD_(ULONG,AddRef)(THIS)
{
return ++RefCount;
}
STDMETHOD_(ULONG,Release)(THIS)
{
assert(RefCount > 0);
ULONG result = --RefCount;
if (result == 0) delete this;
return result;
}
};
template <typename T>
struct SimpleDirect3DResource9: SimpleUnknown<T>
{
/*** IDirect3DResource9 methods ***/
STDMETHOD(GetDevice)(THIS_ IDirect3DDevice9** ppDevice) PURE;
STDMETHOD(SetPrivateData)(THIS_ REFGUID refguid,CONST void* pData,DWORD SizeOfData,DWORD Flags) PURE;
STDMETHOD(GetPrivateData)(THIS_ REFGUID refguid,void* pData,DWORD* pSizeOfData) PURE;
STDMETHOD(FreePrivateData)(THIS_ REFGUID refguid) PURE;
STDMETHOD_(DWORD, SetPriority)(THIS_ DWORD PriorityNew) PURE;
STDMETHOD_(DWORD, GetPriority)(THIS) PURE;
STDMETHOD_(void, PreLoad)(THIS) PURE_(void);
STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS) PURE_(D3DRESOURCETYPE);
};
struct SimpleDirect3DSurface9: SimpleDirect3DResource9<IDirect3DSurface9>
{
UINT Width;
UINT Height;
D3DFORMAT Format;
std::vector<char> Data;
SimpleDirect3DSurface9(UINT Width, UINT Height, D3DFORMAT Format): Width(Width), Height(Height), Format(Format)
{
Data.resize(Width * Height * 4);
}
STDMETHOD(GetDesc)(THIS_ D3DSURFACE_DESC *pDesc)
{
pDesc->Format = Format;
pDesc->Type = D3DRTYPE_SURFACE;
pDesc->Usage = 0;
pDesc->Pool = D3DPOOL_SCRATCH;
pDesc->MultiSampleType = D3DMULTISAMPLE_NONE;
pDesc->MultiSampleQuality = 0;
pDesc->Width = Width;
pDesc->Height = Height;
return S_OK;
}
STDMETHOD(LockRect)(THIS_ D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags)
{
// don't support partial locks
if (pRect) return D3DERR_INVALIDCALL;
pLockedRect->Pitch = get_image_size(Width, 1, Format);
pLockedRect->pBits = &Data[0];
return S_OK;
}
STDMETHOD(UnlockRect)(THIS)
{
return S_OK;
}
// IDirect3DSurface9 stubbed methods
STDMETHOD(GetContainer)(THIS_ REFIID riid,void** ppContainer) PURE;
STDMETHOD(GetDC)(THIS_ HDC *phdc) PURE;
STDMETHOD(ReleaseDC)(THIS_ HDC hdc) PURE;
};
struct SimpleDirect3DTexture9: SimpleDirect3DResource9<IDirect3DTexture9>
{
std::vector<IDirect3DSurface9*> surfaces;
SimpleDirect3DTexture9(UINT Width, UINT Height, UINT Levels, D3DFORMAT Format)
{
for (unsigned int i = 0; i < Levels; ++i)
{
surfaces.push_back(new SimpleDirect3DSurface9(Width, Height, Format));
Width >>= 1;
if (Width == 0) Width = 1;
Height >>= 1;
if (Height == 0) Height = 1;
}
}
~SimpleDirect3DTexture9()
{
for (size_t i = 0; i < surfaces.size(); ++i)
surfaces[i]->Release();
}
STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS)
{
return D3DRTYPE_TEXTURE;
}
STDMETHOD_(DWORD, GetLevelCount)(THIS)
{
return static_cast<DWORD>(surfaces.size());
}
STDMETHOD(GetLevelDesc)(THIS_ UINT Level,D3DSURFACE_DESC *pDesc)
{
return surfaces[Level]->GetDesc(pDesc);
}
STDMETHOD(GetSurfaceLevel)(THIS_ UINT Level,IDirect3DSurface9** ppSurfaceLevel)
{
IDirect3DSurface9* result = surfaces[Level];
result->AddRef();
*ppSurfaceLevel = result;
return S_OK;
}
STDMETHOD(LockRect)(THIS_ UINT Level,D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags)
{
return surfaces[Level]->LockRect(pLockedRect, pRect, Flags);
}
STDMETHOD(UnlockRect)(THIS_ UINT Level)
{
return surfaces[Level]->UnlockRect();
}
// IDirect3DTexture9 stubbed methods
STDMETHOD_(DWORD, SetLOD)(THIS_ DWORD LODNew) PURE;
STDMETHOD_(DWORD, GetLOD)(THIS) PURE;
STDMETHOD(SetAutoGenFilterType)(THIS_ D3DTEXTUREFILTERTYPE FilterType) PURE;
STDMETHOD_(D3DTEXTUREFILTERTYPE, GetAutoGenFilterType)(THIS) { DL_BREAK(); return D3DTEXF_NONE; }
STDMETHOD_(void, GenerateMipSubLevels)(THIS) PURE_(void);
STDMETHOD(AddDirtyRect)(THIS_ CONST RECT* pDirtyRect) PURE;
};
struct SimpleDirect3DCubeTexture9: SimpleDirect3DResource9<IDirect3DCubeTexture9>
{
IDirect3DTexture9* faces[6];
SimpleDirect3DCubeTexture9(UINT EdgeLength, UINT Levels, D3DFORMAT Format)
{
for (unsigned int i = 0; i < 6; ++i)
faces[i] = new SimpleDirect3DTexture9(EdgeLength, EdgeLength, Levels, Format);
}
~SimpleDirect3DCubeTexture9()
{
for (unsigned int i = 0; i < 6; ++i)
faces[i]->Release();
}
STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS)
{
return D3DRTYPE_CUBETEXTURE;
}
STDMETHOD_(DWORD, GetLevelCount)(THIS)
{
return faces[0]->GetLevelCount();
}
STDMETHOD(GetLevelDesc)(THIS_ UINT Level,D3DSURFACE_DESC *pDesc)
{
return faces[0]->GetLevelDesc(Level, pDesc);
}
STDMETHOD(GetCubeMapSurface)(THIS_ D3DCUBEMAP_FACES FaceType,UINT Level,IDirect3DSurface9** ppCubeMapSurface)
{
return faces[FaceType]->GetSurfaceLevel(Level, ppCubeMapSurface);
}
STDMETHOD(LockRect)(THIS_ D3DCUBEMAP_FACES FaceType,UINT Level,D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags)
{
return faces[FaceType]->LockRect(Level, pLockedRect, pRect, Flags);
}
STDMETHOD(UnlockRect)(THIS_ D3DCUBEMAP_FACES FaceType,UINT Level)
{
return faces[FaceType]->UnlockRect(Level);
}
// IDirect3DCubeTexture9 stubbed methods
STDMETHOD_(DWORD, SetLOD)(THIS_ DWORD LODNew) PURE;
STDMETHOD_(DWORD, GetLOD)(THIS) PURE;
STDMETHOD(SetAutoGenFilterType)(THIS_ D3DTEXTUREFILTERTYPE FilterType) PURE;
STDMETHOD_(D3DTEXTUREFILTERTYPE, GetAutoGenFilterType)(THIS) { DL_BREAK(); return D3DTEXF_NONE; }
STDMETHOD_(void, GenerateMipSubLevels)(THIS) PURE_(void);
STDMETHOD(AddDirtyRect)(THIS_ D3DCUBEMAP_FACES FaceType,CONST RECT* pDirtyRect) PURE;
};
struct SimpleDirect3DDevice9: SimpleUnknown<DummyDirect3DDevice9>
{
SimpleDirect3DDevice9()
{
}
STDMETHOD(CreateTexture)(THIS_ UINT Width,UINT Height,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DTexture9** ppTexture,HANDLE* pSharedHandle)
{
*ppTexture = new SimpleDirect3DTexture9(Width, Height, Levels, Format);
return S_OK;
}
STDMETHOD(CreateCubeTexture)(THIS_ UINT EdgeLength,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DCubeTexture9** ppTexture,HANDLE* pSharedHandle)
{
*ppTexture = new SimpleDirect3DCubeTexture9(EdgeLength, Levels, Format);
return S_OK;
}
};
#pragma warning(pop)
#pragma pop_macro("PURE")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment