|
|
//----------------------------------------------------------------------------
//
// testprov.cpp
//
// Test HAL provider class.
//
// Copyright (C) Microsoft Corporation, 1997.
//
//----------------------------------------------------------------------------
#include "pch.cpp"
#pragma hdrstop
//#ifdef DEBUG_PIPELINE
#include "testprov.h"
#include "testfile.h"
#include "stdio.h"
// Real rasterizer data
static D3DHALPROVIDER_INTERFACEDATA CurInterfaceData; static IHalProvider *pCurHalProvider; // Real HAL provider
// Test provider data
static CTestHalProvider g_TestHalProvider; static D3DHALPROVIDER_INTERFACEDATA TestInterfaceData; static D3DHAL_CALLBACKS TestCallbacks; static D3DHAL_CALLBACKS2 TestCallbacks2; static D3DHAL_CALLBACKS3 TestCallbacks3; static char szFileName[_MAX_PATH] = ""; // Output file name
static FILE *fout = NULL; // Output file
DWORD g_dwTestHalFlags = 0; // Could be set from debugger
// Bits for g_dwTestHalFlags
const DWORD __TESTHAL_OUTPUTFILE = 1; // If need output to test file
const DWORD __TESTHAL_NORENDER = 2; // If no rendering needed
//---------------------------------------------------------------------
// Provides access to DIRECTDRAWSURFACE memory;
// In the constructor the surface is locked.
// In the destructor it is unlocked.
// LPBYTE() or LPVOID() casts will get pointer to the surface bits.
//
class CLockedDDSurface { public: CLockedDDSurface(LPDIRECTDRAWSURFACE surface); ~CLockedDDSurface(); operator LPVOID() {return descr.lpSurface;} operator LPBYTE() {return (LPBYTE)descr.lpSurface;} protected: DDSURFACEDESC descr; LPDIRECTDRAWSURFACE pSurface; };
CLockedDDSurface::CLockedDDSurface(LPDIRECTDRAWSURFACE surface) { pSurface = surface; memset (&descr, 0, sizeof(descr)); descr.dwSize = sizeof(descr); surface->Lock(NULL, &descr, 0, NULL); }
CLockedDDSurface::~CLockedDDSurface() { if (descr.lpSurface) pSurface->Unlock(descr.lpSurface); } //---------------------------------------------------------------------
void PutHeader(DWORD id, DWORD size) { if (fout) { fwrite(&id, sizeof(DWORD), 1, fout); fwrite(&size, sizeof(DWORD), 1, fout); } } //---------------------------------------------------------------------
DWORD GetCurrentPosition() { if (fout) return ftell(fout); else return 0; } //---------------------------------------------------------------------
void SetCurrentPosition(DWORD offset) { if (fout) fseek(fout, offset, SEEK_SET); } //---------------------------------------------------------------------
void PutBuffer(LPVOID buffer, DWORD size) { if (fout) { fwrite(buffer, 1, size, fout); } } //---------------------------------------------------------------------
// Implementation of test callbacks
//
DWORD __stdcall TestDrawOnePrimitive(LPD3DHAL_DRAWONEPRIMITIVEDATA data) { if (g_dwTestHalFlags & __TESTHAL_OUTPUTFILE) { TFREC_DRAWONEPRIMITIVE rec; PutHeader(TFID_DRAWONEPRIMITIVE, sizeof(rec) + data->dwNumVertices*sizeof(D3DTLVERTEX)); rec.primitiveType = data->PrimitiveType; rec.vertexCount = data->dwNumVertices; rec.vertexType = data->VertexType; rec.dwFlags = data->dwFlags; PutBuffer(&rec, sizeof(rec)); PutBuffer(data->lpvVertices, sizeof(D3DTLVERTEX)*data->dwNumVertices); }
if (CurInterfaceData.pCallbacks2->DrawOnePrimitive && !(g_dwTestHalFlags & __TESTHAL_NORENDER)) return CurInterfaceData.pCallbacks2->DrawOnePrimitive(data); else return DDHAL_DRIVER_HANDLED; }
DWORD __stdcall TestDrawOneIndexedPrimitive(LPD3DHAL_DRAWONEINDEXEDPRIMITIVEDATA data) { if (g_dwTestHalFlags & __TESTHAL_OUTPUTFILE) { TFREC_DRAWONEINDEXEDPRIMITIVE rec; PutHeader(TFID_DRAWONEINDEXEDPRIMITIVE, sizeof(rec) + data->dwNumVertices*sizeof(D3DTLVERTEX) + data->dwNumIndices*sizeof(WORD)); rec.primitiveType = data->PrimitiveType; rec.vertexCount = data->dwNumVertices; rec.vertexType = data->VertexType; rec.dwFlags = data->dwFlags; rec.indexCount = data->dwNumIndices; PutBuffer(&rec, sizeof(rec)); PutBuffer(data->lpvVertices, sizeof(D3DTLVERTEX)*data->dwNumVertices); PutBuffer(data->lpwIndices, sizeof(WORD)*data->dwNumIndices); }
if (CurInterfaceData.pCallbacks2->DrawOneIndexedPrimitive && !(g_dwTestHalFlags & __TESTHAL_NORENDER)) return CurInterfaceData.pCallbacks2->DrawOneIndexedPrimitive(data); else return DDHAL_DRIVER_HANDLED; }
DWORD __stdcall TestDrawPrimitives(LPD3DHAL_DRAWPRIMITIVESDATA data) { if (g_dwTestHalFlags & __TESTHAL_OUTPUTFILE) { DWORD endPos = 0; LPVOID header = data->lpvData; PutHeader(0,0); // Dummy header. Will be filled later
DWORD startPos = GetCurrentPosition(); for (;;) { DWORD nStates = ((D3DHAL_DRAWPRIMCOUNTS*)header)->wNumStateChanges; DWORD nVertices = ((D3DHAL_DRAWPRIMCOUNTS*)header)->wNumVertices; DWORD size; // Primitive header
PutBuffer(header, sizeof(D3DHAL_DRAWPRIMCOUNTS)); header = (char*)header + sizeof(D3DHAL_DRAWPRIMCOUNTS); // States
size = nStates * sizeof(WORD); PutBuffer(header, size); header = (char*)header + size; header = (LPVOID)(((LONG_PTR)header + 31) & ~31); //32 bytes aligned
// Vertices
if (!nVertices) break; size = nVertices * sizeof(D3DTLVERTEX); PutBuffer(header, size);
} // Write record header
endPos = GetCurrentPosition(); SetCurrentPosition(startPos - sizeof(TF_HEADER)); PutHeader(TFID_DRAWPRIMITIVES, endPos - startPos); SetCurrentPosition(endPos); }
if (CurInterfaceData.pCallbacks2->DrawPrimitives && !(g_dwTestHalFlags & __TESTHAL_NORENDER)) return CurInterfaceData.pCallbacks2->DrawPrimitives(data); else return DDHAL_DRIVER_HANDLED; }
DWORD __stdcall TestDrawPrimitives2(LPD3DHAL_DRAWPRIMITIVES2DATA data) { if (g_dwTestHalFlags & __TESTHAL_OUTPUTFILE) { TFREC_DRAWPRIMITIVES2 rec; rec.dwFlags = 0; PutBuffer(&rec, sizeof(rec)); PutHeader(TFID_DRAWPRIMITIVES, sizeof(rec)); }
if (CurInterfaceData.pCallbacks3->DrawPrimitives2 && !(g_dwTestHalFlags & __TESTHAL_NORENDER)) return CurInterfaceData.pCallbacks3->DrawPrimitives2(data); else return DDHAL_DRIVER_HANDLED; }
DWORD __stdcall TestRenderState(LPD3DHAL_RENDERSTATEDATA data) { if (g_dwTestHalFlags & __TESTHAL_OUTPUTFILE) { // mem should be destroyed before calling to real driver to unlock
// the surface
CLockedDDSurface mem(data->lpExeBuf); LPD3DSTATE pState; pState = (LPD3DSTATE)(LPBYTE(mem) + data->dwOffset); PutHeader(TFID_RENDERSTATE, sizeof(DWORD) + data->dwCount*sizeof(D3DSTATE)); PutBuffer(&data->dwCount, sizeof(DWORD)); for (DWORD i = 0; i < data->dwCount; i++) { PutBuffer(&pState, sizeof(D3DSTATE)); pState++; } }
if (CurInterfaceData.pCallbacks->RenderState) return CurInterfaceData.pCallbacks->RenderState(data); else return DDHAL_DRIVER_HANDLED; }
DWORD __stdcall TestRenderPrimitive(LPD3DHAL_RENDERPRIMITIVEDATA data) { if (g_dwTestHalFlags & __TESTHAL_OUTPUTFILE) { // mem and tlmem should be destroyed before calling the real driver
// to unlock the surface
CLockedDDSurface mem(data->lpExeBuf); CLockedDDSurface tlmem(data->lpTLBuf); LPBYTE lpPrimData; LPD3DTLVERTEX lpTLData; DWORD i; DWORD primitiveDataSize; DWORD count = data->diInstruction.wCount; TFREC_RENDERPRIMITIVE rec;
// Find the pointer to the first primitive structure
lpPrimData = (LPBYTE)mem + data->dwOffset;
// Find the pointer to the vertex data
// Find the pointer to the first TL vertex
lpTLData = (LPD3DTLVERTEX)((LPBYTE)tlmem + data->dwTLOffset);
rec.status = data->dwStatus; rec.vertexType = D3DVT_TLVERTEX; // Find out number of vertices, primitive type and
// size of primitive data
switch (data->diInstruction.bOpcode) { case D3DOP_POINT: rec.primitiveType = D3DPT_POINTLIST; rec.vertexCount = count; primitiveDataSize = count*sizeof(D3DPOINT); break; case D3DOP_LINE: rec.primitiveType = D3DPT_LINELIST; rec.vertexCount = count*2; primitiveDataSize = count*sizeof(D3DLINE); break; case D3DOP_SPAN: rec.primitiveType = D3DPT_POINTLIST; rec.vertexCount = count; primitiveDataSize = count*sizeof(D3DSPAN); break; case D3DOP_TRIANGLE: rec.primitiveType = D3DPT_TRIANGLELIST; rec.vertexCount = count*3; primitiveDataSize = count*sizeof(D3DTRIANGLE); break; }
PutHeader(TFID_RENDERPRIMITIVE, sizeof(D3DINSTRUCTION) + sizeof(rec) + rec.vertexCount*sizeof(D3DTLVERTEX) + primitiveDataSize); PutBuffer(&rec, sizeof(rec)); PutBuffer(&data->diInstruction, sizeof(D3DINSTRUCTION));
// Parse the structures based on the instruction
switch (data->diInstruction.bOpcode) { case D3DOP_POINT: { LPD3DPOINT lpPoint = (LPD3DPOINT)lpPrimData; for (i = 0; i < count; i++) { PutBuffer(lpPoint, sizeof(D3DPOINT)); PutBuffer(&lpTLData[lpPoint->wFirst], lpPoint->wCount*sizeof(D3DTLVERTEX)); lpPoint++; } break; } case D3DOP_LINE: { LPD3DLINE lpLine = (LPD3DLINE)lpPrimData; for (i = 0; i < count; i++) { PutBuffer(lpLine, sizeof(D3DLINE)); PutBuffer(&lpTLData[lpLine->v1], sizeof(D3DTLVERTEX)); PutBuffer(&lpTLData[lpLine->v2], sizeof(D3DTLVERTEX)); lpLine++; } break; } case D3DOP_SPAN: { LPD3DSPAN lpSpan = (LPD3DSPAN)lpPrimData; for (i = 0; i < count; i++) { PutBuffer(lpSpan, sizeof(D3DSPAN)); PutBuffer(&lpTLData[lpSpan->wFirst], lpSpan->wCount*sizeof(D3DTLVERTEX)); lpSpan++; } break; } case D3DOP_TRIANGLE: { LPD3DTRIANGLE lpTri = (LPD3DTRIANGLE)lpPrimData; for (i = 0; i < count; i++) { PutBuffer(lpTri, sizeof(D3DTRIANGLE)); PutBuffer(&lpTLData[lpTri->v1], sizeof(D3DTLVERTEX)); PutBuffer(&lpTLData[lpTri->v2], sizeof(D3DTLVERTEX)); PutBuffer(&lpTLData[lpTri->v3], sizeof(D3DTLVERTEX)); lpTri++; } break; } } }
if (CurInterfaceData.pCallbacks->RenderPrimitive && !(g_dwTestHalFlags & __TESTHAL_NORENDER)) return CurInterfaceData.pCallbacks->RenderPrimitive(data); else return DDHAL_DRIVER_HANDLED; }
DWORD __stdcall TestSceneCapture(LPD3DHAL_SCENECAPTUREDATA pData) { if (g_dwTestHalFlags & __TESTHAL_OUTPUTFILE) { PutHeader(TFID_SCENECAPTURE, sizeof(DWORD)); PutBuffer(&pData->dwFlag, sizeof(DWORD)); fflush(fout); }
if (CurInterfaceData.pCallbacks->SceneCapture) return CurInterfaceData.pCallbacks->SceneCapture(pData); else return DDHAL_DRIVER_HANDLED; } //----------------------------------------------------------------------------
//
// TestHalProvider::QueryInterface
//
// Internal interface, no need to implement.
//
//----------------------------------------------------------------------------
STDMETHODIMP CTestHalProvider::QueryInterface(THIS_ REFIID riid, LPVOID* ppvObj) { *ppvObj = NULL; return E_NOINTERFACE; }
//----------------------------------------------------------------------------
//
// CTestHalProvider::AddRef
//
// Static implementation, no real refcount.
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CTestHalProvider::AddRef(THIS) { return 1; }
//----------------------------------------------------------------------------
//
// TestHalProvider::Release
//
// Static implementation, no real refcount.
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CTestHalProvider::Release(THIS) { if (fout) { fclose(fout); fout = NULL; } return pCurHalProvider->Release(); } //----------------------------------------------------------------------------
//
// GetTestProvider
//
// Input:
// riid and pCurrentHalProvider are equal to
// the currently selected provider.
// GlobalData - data provided by DDraw
// fileName - output file name
// dwFlagsInp - currently not used
//
// Returns:
// the test HAL provider in ppHalProvider.
//
// Notes:
// Only one instance of the test HAL is handled correctly.
//
//----------------------------------------------------------------------------
STDAPI GetTestHalProvider(REFIID riid, DDRAWI_DIRECTDRAW_GBL *GlobalData, IHalProvider **ppHalProvider, IHalProvider * pCurrentHalProvider, DWORD dwFlagsInp) { *ppHalProvider = &g_TestHalProvider; pCurHalProvider = pCurrentHalProvider;
g_dwTestHalFlags |= __TESTHAL_NORENDER; if (GetD3DRegValue(REG_SZ, "TestHalFile", &szFileName, _MAX_PATH) && szFileName[0] != 0) { g_dwTestHalFlags |= __TESTHAL_OUTPUTFILE; } DWORD dwValue; if (GetD3DRegValue(REG_DWORD, "TestHalDoRender", &dwValue, sizeof(DWORD)) && dwValue != 0) { g_dwTestHalFlags &= ~__TESTHAL_NORENDER; } // Get interface from the current hal provider to call to it
pCurrentHalProvider->GetInterface(GlobalData, &CurInterfaceData, 4);
TestInterfaceData = CurInterfaceData; TestInterfaceData.pCallbacks = &TestCallbacks; TestInterfaceData.pCallbacks2 = &TestCallbacks2; TestInterfaceData.pCallbacks3 = &TestCallbacks3;
// Initialize callbacks we do not care of
TestCallbacks = *CurInterfaceData.pCallbacks; TestCallbacks2 = *CurInterfaceData.pCallbacks2; TestCallbacks3 = *CurInterfaceData.pCallbacks3;
// Initialize callbacks that we want to intersept
TestCallbacks.RenderState = &TestRenderState; TestCallbacks.RenderPrimitive = &TestRenderPrimitive; TestCallbacks.SceneCapture = &TestSceneCapture;
TestCallbacks2.DrawOnePrimitive = &TestDrawOnePrimitive; TestCallbacks2.DrawOneIndexedPrimitive = &TestDrawOneIndexedPrimitive; TestCallbacks2.DrawPrimitives = &TestDrawPrimitives;
TestCallbacks3.DrawPrimitives2 = &TestDrawPrimitives2;
fout = NULL; if (g_dwTestHalFlags & __TESTHAL_OUTPUTFILE) { fout = fopen(szFileName, "wb"); if (!fout) return DDERR_GENERIC; }
return D3D_OK; }
//----------------------------------------------------------------------------
//
// CTestHalProvider::GetInterface
//
// Returns test provider interface and real rasterizer global data.
//
//----------------------------------------------------------------------------
STDMETHODIMP CTestHalProvider::GetInterface(THIS_ LPDDRAWI_DIRECTDRAW_GBL pDdGbl, LPD3DHALPROVIDER_INTERFACEDATA pInterfaceData, DWORD dwVersion) { *pInterfaceData = TestInterfaceData;
return D3D_OK; }
//----------------------------------------------------------------------------
//
// TestHalProvider::GetCaps
//
// Returns real rasterizer caps.
//
//----------------------------------------------------------------------------
STDMETHODIMP CTestHalProvider::GetCaps(THIS_ LPDDRAWI_DIRECTDRAW_GBL pDdGbl, LPD3DDEVICEDESC7 pHwDesc, LPD3DDEVICEDESC7 pHelDesc, DWORD dwVersion) { return pCurHalProvider->GetCaps(pDdGbl, pHwDesc, pHelDesc, dwVersion); }
//#endif //DEBUG_PIPELINE
|