Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

529 lines
17 KiB

//----------------------------------------------------------------------------
//
// 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)(((ULONG_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, 3);
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,
LPD3DDEVICEDESC pHwDesc,
LPD3DDEVICEDESC pHelDesc,
DWORD dwVersion)
{
return pCurHalProvider->GetCaps(pDdGbl, pHwDesc, pHelDesc, dwVersion);
}
//#endif //DEBUG_PIPELINE