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

  1. //----------------------------------------------------------------------------
  2. //
  3. // testprov.cpp
  4. //
  5. // Test HAL provider class.
  6. //
  7. // Copyright (C) Microsoft Corporation, 1997.
  8. //
  9. //----------------------------------------------------------------------------
  10. #include "pch.cpp"
  11. #pragma hdrstop
  12. //#ifdef DEBUG_PIPELINE
  13. #include "testprov.h"
  14. #include "testfile.h"
  15. #include "stdio.h"
  16. // Real rasterizer data
  17. static D3DHALPROVIDER_INTERFACEDATA CurInterfaceData;
  18. static IHalProvider *pCurHalProvider; // Real HAL provider
  19. // Test provider data
  20. static CTestHalProvider g_TestHalProvider;
  21. static D3DHALPROVIDER_INTERFACEDATA TestInterfaceData;
  22. static D3DHAL_CALLBACKS TestCallbacks;
  23. static D3DHAL_CALLBACKS2 TestCallbacks2;
  24. static D3DHAL_CALLBACKS3 TestCallbacks3;
  25. static char szFileName[_MAX_PATH] = ""; // Output file name
  26. static FILE *fout = NULL; // Output file
  27. DWORD g_dwTestHalFlags = 0; // Could be set from debugger
  28. // Bits for g_dwTestHalFlags
  29. const DWORD __TESTHAL_OUTPUTFILE = 1; // If need output to test file
  30. const DWORD __TESTHAL_NORENDER = 2; // If no rendering needed
  31. //---------------------------------------------------------------------
  32. // Provides access to DIRECTDRAWSURFACE memory;
  33. // In the constructor the surface is locked.
  34. // In the destructor it is unlocked.
  35. // LPBYTE() or LPVOID() casts will get pointer to the surface bits.
  36. //
  37. class CLockedDDSurface
  38. {
  39. public:
  40. CLockedDDSurface(LPDIRECTDRAWSURFACE surface);
  41. ~CLockedDDSurface();
  42. operator LPVOID() {return descr.lpSurface;}
  43. operator LPBYTE() {return (LPBYTE)descr.lpSurface;}
  44. protected:
  45. DDSURFACEDESC descr;
  46. LPDIRECTDRAWSURFACE pSurface;
  47. };
  48. CLockedDDSurface::CLockedDDSurface(LPDIRECTDRAWSURFACE surface)
  49. {
  50. pSurface = surface;
  51. memset (&descr, 0, sizeof(descr));
  52. descr.dwSize = sizeof(descr);
  53. surface->Lock(NULL, &descr, 0, NULL);
  54. }
  55. CLockedDDSurface::~CLockedDDSurface()
  56. {
  57. if (descr.lpSurface)
  58. pSurface->Unlock(descr.lpSurface);
  59. }
  60. //---------------------------------------------------------------------
  61. void PutHeader(DWORD id, DWORD size)
  62. {
  63. if (fout)
  64. {
  65. fwrite(&id, sizeof(DWORD), 1, fout);
  66. fwrite(&size, sizeof(DWORD), 1, fout);
  67. }
  68. }
  69. //---------------------------------------------------------------------
  70. DWORD GetCurrentPosition()
  71. {
  72. if (fout)
  73. return ftell(fout);
  74. else
  75. return 0;
  76. }
  77. //---------------------------------------------------------------------
  78. void SetCurrentPosition(DWORD offset)
  79. {
  80. if (fout)
  81. fseek(fout, offset, SEEK_SET);
  82. }
  83. //---------------------------------------------------------------------
  84. void PutBuffer(LPVOID buffer, DWORD size)
  85. {
  86. if (fout)
  87. {
  88. fwrite(buffer, 1, size, fout);
  89. }
  90. }
  91. //---------------------------------------------------------------------
  92. // Implementation of test callbacks
  93. //
  94. DWORD __stdcall
  95. TestDrawOnePrimitive(LPD3DHAL_DRAWONEPRIMITIVEDATA data)
  96. {
  97. if (g_dwTestHalFlags & __TESTHAL_OUTPUTFILE)
  98. {
  99. TFREC_DRAWONEPRIMITIVE rec;
  100. PutHeader(TFID_DRAWONEPRIMITIVE,
  101. sizeof(rec) + data->dwNumVertices*sizeof(D3DTLVERTEX));
  102. rec.primitiveType = data->PrimitiveType;
  103. rec.vertexCount = data->dwNumVertices;
  104. rec.vertexType = data->VertexType;
  105. rec.dwFlags = data->dwFlags;
  106. PutBuffer(&rec, sizeof(rec));
  107. PutBuffer(data->lpvVertices, sizeof(D3DTLVERTEX)*data->dwNumVertices);
  108. }
  109. if (CurInterfaceData.pCallbacks2->DrawOnePrimitive &&
  110. !(g_dwTestHalFlags & __TESTHAL_NORENDER))
  111. return CurInterfaceData.pCallbacks2->DrawOnePrimitive(data);
  112. else
  113. return DDHAL_DRIVER_HANDLED;
  114. }
  115. DWORD __stdcall
  116. TestDrawOneIndexedPrimitive(LPD3DHAL_DRAWONEINDEXEDPRIMITIVEDATA data)
  117. {
  118. if (g_dwTestHalFlags & __TESTHAL_OUTPUTFILE)
  119. {
  120. TFREC_DRAWONEINDEXEDPRIMITIVE rec;
  121. PutHeader(TFID_DRAWONEINDEXEDPRIMITIVE,
  122. sizeof(rec) +
  123. data->dwNumVertices*sizeof(D3DTLVERTEX) +
  124. data->dwNumIndices*sizeof(WORD));
  125. rec.primitiveType = data->PrimitiveType;
  126. rec.vertexCount = data->dwNumVertices;
  127. rec.vertexType = data->VertexType;
  128. rec.dwFlags = data->dwFlags;
  129. rec.indexCount = data->dwNumIndices;
  130. PutBuffer(&rec, sizeof(rec));
  131. PutBuffer(data->lpvVertices, sizeof(D3DTLVERTEX)*data->dwNumVertices);
  132. PutBuffer(data->lpwIndices, sizeof(WORD)*data->dwNumIndices);
  133. }
  134. if (CurInterfaceData.pCallbacks2->DrawOneIndexedPrimitive &&
  135. !(g_dwTestHalFlags & __TESTHAL_NORENDER))
  136. return CurInterfaceData.pCallbacks2->DrawOneIndexedPrimitive(data);
  137. else
  138. return DDHAL_DRIVER_HANDLED;
  139. }
  140. DWORD __stdcall
  141. TestDrawPrimitives(LPD3DHAL_DRAWPRIMITIVESDATA data)
  142. {
  143. if (g_dwTestHalFlags & __TESTHAL_OUTPUTFILE)
  144. {
  145. DWORD endPos = 0;
  146. LPVOID header = data->lpvData;
  147. PutHeader(0,0); // Dummy header. Will be filled later
  148. DWORD startPos = GetCurrentPosition();
  149. for (;;)
  150. {
  151. DWORD nStates = ((D3DHAL_DRAWPRIMCOUNTS*)header)->wNumStateChanges;
  152. DWORD nVertices = ((D3DHAL_DRAWPRIMCOUNTS*)header)->wNumVertices;
  153. DWORD size;
  154. // Primitive header
  155. PutBuffer(header, sizeof(D3DHAL_DRAWPRIMCOUNTS));
  156. header = (char*)header + sizeof(D3DHAL_DRAWPRIMCOUNTS);
  157. // States
  158. size = nStates * sizeof(WORD);
  159. PutBuffer(header, size);
  160. header = (char*)header + size;
  161. header = (LPVOID)(((ULONG_PTR)header + 31) & ~31); //32 bytes aligned
  162. // Vertices
  163. if (!nVertices)
  164. break;
  165. size = nVertices * sizeof(D3DTLVERTEX);
  166. PutBuffer(header, size);
  167. }
  168. // Write record header
  169. endPos = GetCurrentPosition();
  170. SetCurrentPosition(startPos - sizeof(TF_HEADER));
  171. PutHeader(TFID_DRAWPRIMITIVES, endPos - startPos);
  172. SetCurrentPosition(endPos);
  173. }
  174. if (CurInterfaceData.pCallbacks2->DrawPrimitives &&
  175. !(g_dwTestHalFlags & __TESTHAL_NORENDER))
  176. return CurInterfaceData.pCallbacks2->DrawPrimitives(data);
  177. else
  178. return DDHAL_DRIVER_HANDLED;
  179. }
  180. DWORD __stdcall
  181. TestDrawPrimitives2(LPD3DHAL_DRAWPRIMITIVES2DATA data)
  182. {
  183. if (g_dwTestHalFlags & __TESTHAL_OUTPUTFILE)
  184. {
  185. TFREC_DRAWPRIMITIVES2 rec;
  186. rec.dwFlags = 0;
  187. PutBuffer(&rec, sizeof(rec));
  188. PutHeader(TFID_DRAWPRIMITIVES, sizeof(rec));
  189. }
  190. if (CurInterfaceData.pCallbacks3->DrawPrimitives2 &&
  191. !(g_dwTestHalFlags & __TESTHAL_NORENDER))
  192. return CurInterfaceData.pCallbacks3->DrawPrimitives2(data);
  193. else
  194. return DDHAL_DRIVER_HANDLED;
  195. }
  196. DWORD __stdcall
  197. TestRenderState(LPD3DHAL_RENDERSTATEDATA data)
  198. {
  199. if (g_dwTestHalFlags & __TESTHAL_OUTPUTFILE)
  200. {
  201. // mem should be destroyed before calling to real driver to unlock
  202. // the surface
  203. CLockedDDSurface mem(data->lpExeBuf);
  204. LPD3DSTATE pState;
  205. pState = (LPD3DSTATE)(LPBYTE(mem) + data->dwOffset);
  206. PutHeader(TFID_RENDERSTATE, sizeof(DWORD) + data->dwCount*sizeof(D3DSTATE));
  207. PutBuffer(&data->dwCount, sizeof(DWORD));
  208. for (DWORD i = 0; i < data->dwCount; i++)
  209. {
  210. PutBuffer(&pState, sizeof(D3DSTATE));
  211. pState++;
  212. }
  213. }
  214. if (CurInterfaceData.pCallbacks->RenderState)
  215. return CurInterfaceData.pCallbacks->RenderState(data);
  216. else
  217. return DDHAL_DRIVER_HANDLED;
  218. }
  219. DWORD __stdcall
  220. TestRenderPrimitive(LPD3DHAL_RENDERPRIMITIVEDATA data)
  221. {
  222. if (g_dwTestHalFlags & __TESTHAL_OUTPUTFILE)
  223. {
  224. // mem and tlmem should be destroyed before calling the real driver
  225. // to unlock the surface
  226. CLockedDDSurface mem(data->lpExeBuf);
  227. CLockedDDSurface tlmem(data->lpTLBuf);
  228. LPBYTE lpPrimData;
  229. LPD3DTLVERTEX lpTLData;
  230. DWORD i;
  231. DWORD primitiveDataSize;
  232. DWORD count = data->diInstruction.wCount;
  233. TFREC_RENDERPRIMITIVE rec;
  234. // Find the pointer to the first primitive structure
  235. lpPrimData = (LPBYTE)mem + data->dwOffset;
  236. // Find the pointer to the vertex data
  237. // Find the pointer to the first TL vertex
  238. lpTLData = (LPD3DTLVERTEX)((LPBYTE)tlmem + data->dwTLOffset);
  239. rec.status = data->dwStatus;
  240. rec.vertexType = D3DVT_TLVERTEX;
  241. // Find out number of vertices, primitive type and
  242. // size of primitive data
  243. switch (data->diInstruction.bOpcode)
  244. {
  245. case D3DOP_POINT:
  246. rec.primitiveType = D3DPT_POINTLIST;
  247. rec.vertexCount = count;
  248. primitiveDataSize = count*sizeof(D3DPOINT);
  249. break;
  250. case D3DOP_LINE:
  251. rec.primitiveType = D3DPT_LINELIST;
  252. rec.vertexCount = count*2;
  253. primitiveDataSize = count*sizeof(D3DLINE);
  254. break;
  255. case D3DOP_SPAN:
  256. rec.primitiveType = D3DPT_POINTLIST;
  257. rec.vertexCount = count;
  258. primitiveDataSize = count*sizeof(D3DSPAN);
  259. break;
  260. case D3DOP_TRIANGLE:
  261. rec.primitiveType = D3DPT_TRIANGLELIST;
  262. rec.vertexCount = count*3;
  263. primitiveDataSize = count*sizeof(D3DTRIANGLE);
  264. break;
  265. }
  266. PutHeader(TFID_RENDERPRIMITIVE,
  267. sizeof(D3DINSTRUCTION) +
  268. sizeof(rec) + rec.vertexCount*sizeof(D3DTLVERTEX) +
  269. primitiveDataSize);
  270. PutBuffer(&rec, sizeof(rec));
  271. PutBuffer(&data->diInstruction, sizeof(D3DINSTRUCTION));
  272. // Parse the structures based on the instruction
  273. switch (data->diInstruction.bOpcode)
  274. {
  275. case D3DOP_POINT:
  276. {
  277. LPD3DPOINT lpPoint = (LPD3DPOINT)lpPrimData;
  278. for (i = 0; i < count; i++)
  279. {
  280. PutBuffer(lpPoint, sizeof(D3DPOINT));
  281. PutBuffer(&lpTLData[lpPoint->wFirst],
  282. lpPoint->wCount*sizeof(D3DTLVERTEX));
  283. lpPoint++;
  284. }
  285. break;
  286. }
  287. case D3DOP_LINE:
  288. {
  289. LPD3DLINE lpLine = (LPD3DLINE)lpPrimData;
  290. for (i = 0; i < count; i++)
  291. {
  292. PutBuffer(lpLine, sizeof(D3DLINE));
  293. PutBuffer(&lpTLData[lpLine->v1], sizeof(D3DTLVERTEX));
  294. PutBuffer(&lpTLData[lpLine->v2], sizeof(D3DTLVERTEX));
  295. lpLine++;
  296. }
  297. break;
  298. }
  299. case D3DOP_SPAN:
  300. {
  301. LPD3DSPAN lpSpan = (LPD3DSPAN)lpPrimData;
  302. for (i = 0; i < count; i++)
  303. {
  304. PutBuffer(lpSpan, sizeof(D3DSPAN));
  305. PutBuffer(&lpTLData[lpSpan->wFirst],
  306. lpSpan->wCount*sizeof(D3DTLVERTEX));
  307. lpSpan++;
  308. }
  309. break;
  310. }
  311. case D3DOP_TRIANGLE:
  312. {
  313. LPD3DTRIANGLE lpTri = (LPD3DTRIANGLE)lpPrimData;
  314. for (i = 0; i < count; i++)
  315. {
  316. PutBuffer(lpTri, sizeof(D3DTRIANGLE));
  317. PutBuffer(&lpTLData[lpTri->v1], sizeof(D3DTLVERTEX));
  318. PutBuffer(&lpTLData[lpTri->v2], sizeof(D3DTLVERTEX));
  319. PutBuffer(&lpTLData[lpTri->v3], sizeof(D3DTLVERTEX));
  320. lpTri++;
  321. }
  322. break;
  323. }
  324. }
  325. }
  326. if (CurInterfaceData.pCallbacks->RenderPrimitive &&
  327. !(g_dwTestHalFlags & __TESTHAL_NORENDER))
  328. return CurInterfaceData.pCallbacks->RenderPrimitive(data);
  329. else
  330. return DDHAL_DRIVER_HANDLED;
  331. }
  332. DWORD __stdcall
  333. TestSceneCapture(LPD3DHAL_SCENECAPTUREDATA pData)
  334. {
  335. if (g_dwTestHalFlags & __TESTHAL_OUTPUTFILE)
  336. {
  337. PutHeader(TFID_SCENECAPTURE, sizeof(DWORD));
  338. PutBuffer(&pData->dwFlag, sizeof(DWORD));
  339. fflush(fout);
  340. }
  341. if (CurInterfaceData.pCallbacks->SceneCapture)
  342. return CurInterfaceData.pCallbacks->SceneCapture(pData);
  343. else
  344. return DDHAL_DRIVER_HANDLED;
  345. }
  346. //----------------------------------------------------------------------------
  347. //
  348. // TestHalProvider::QueryInterface
  349. //
  350. // Internal interface, no need to implement.
  351. //
  352. //----------------------------------------------------------------------------
  353. STDMETHODIMP CTestHalProvider::QueryInterface(THIS_ REFIID riid, LPVOID* ppvObj)
  354. {
  355. *ppvObj = NULL;
  356. return E_NOINTERFACE;
  357. }
  358. //----------------------------------------------------------------------------
  359. //
  360. // CTestHalProvider::AddRef
  361. //
  362. // Static implementation, no real refcount.
  363. //
  364. //----------------------------------------------------------------------------
  365. STDMETHODIMP_(ULONG) CTestHalProvider::AddRef(THIS)
  366. {
  367. return 1;
  368. }
  369. //----------------------------------------------------------------------------
  370. //
  371. // TestHalProvider::Release
  372. //
  373. // Static implementation, no real refcount.
  374. //
  375. //----------------------------------------------------------------------------
  376. STDMETHODIMP_(ULONG) CTestHalProvider::Release(THIS)
  377. {
  378. if (fout)
  379. {
  380. fclose(fout);
  381. fout = NULL;
  382. }
  383. return pCurHalProvider->Release();
  384. }
  385. //----------------------------------------------------------------------------
  386. //
  387. // GetTestProvider
  388. //
  389. // Input:
  390. // riid and pCurrentHalProvider are equal to
  391. // the currently selected provider.
  392. // GlobalData - data provided by DDraw
  393. // fileName - output file name
  394. // dwFlagsInp - currently not used
  395. //
  396. // Returns:
  397. // the test HAL provider in ppHalProvider.
  398. //
  399. // Notes:
  400. // Only one instance of the test HAL is handled correctly.
  401. //
  402. //----------------------------------------------------------------------------
  403. STDAPI GetTestHalProvider(REFIID riid,
  404. DDRAWI_DIRECTDRAW_GBL *GlobalData,
  405. IHalProvider **ppHalProvider,
  406. IHalProvider * pCurrentHalProvider,
  407. DWORD dwFlagsInp)
  408. {
  409. *ppHalProvider = &g_TestHalProvider;
  410. pCurHalProvider = pCurrentHalProvider;
  411. g_dwTestHalFlags |= __TESTHAL_NORENDER;
  412. if (GetD3DRegValue(REG_SZ, "TestHalFile", &szFileName, _MAX_PATH) &&
  413. szFileName[0] != 0)
  414. {
  415. g_dwTestHalFlags |= __TESTHAL_OUTPUTFILE;
  416. }
  417. DWORD dwValue;
  418. if (GetD3DRegValue(REG_DWORD, "TestHalDoRender", &dwValue, sizeof(DWORD)) &&
  419. dwValue != 0)
  420. {
  421. g_dwTestHalFlags &= ~__TESTHAL_NORENDER;
  422. }
  423. // Get interface from the current hal provider to call to it
  424. pCurrentHalProvider->GetInterface(GlobalData, &CurInterfaceData, 3);
  425. TestInterfaceData = CurInterfaceData;
  426. TestInterfaceData.pCallbacks = &TestCallbacks;
  427. TestInterfaceData.pCallbacks2 = &TestCallbacks2;
  428. TestInterfaceData.pCallbacks3 = &TestCallbacks3;
  429. // Initialize callbacks we do not care of
  430. TestCallbacks = *CurInterfaceData.pCallbacks;
  431. TestCallbacks2 = *CurInterfaceData.pCallbacks2;
  432. TestCallbacks3 = *CurInterfaceData.pCallbacks3;
  433. // Initialize callbacks that we want to intersept
  434. TestCallbacks.RenderState = &TestRenderState;
  435. TestCallbacks.RenderPrimitive = &TestRenderPrimitive;
  436. TestCallbacks.SceneCapture = &TestSceneCapture;
  437. TestCallbacks2.DrawOnePrimitive = &TestDrawOnePrimitive;
  438. TestCallbacks2.DrawOneIndexedPrimitive = &TestDrawOneIndexedPrimitive;
  439. TestCallbacks2.DrawPrimitives = &TestDrawPrimitives;
  440. TestCallbacks3.DrawPrimitives2 = &TestDrawPrimitives2;
  441. fout = NULL;
  442. if (g_dwTestHalFlags & __TESTHAL_OUTPUTFILE)
  443. {
  444. fout = fopen(szFileName, "wb");
  445. if (!fout)
  446. return DDERR_GENERIC;
  447. }
  448. return D3D_OK;
  449. }
  450. //----------------------------------------------------------------------------
  451. //
  452. // CTestHalProvider::GetInterface
  453. //
  454. // Returns test provider interface and real rasterizer global data.
  455. //
  456. //----------------------------------------------------------------------------
  457. STDMETHODIMP
  458. CTestHalProvider::GetInterface(THIS_
  459. LPDDRAWI_DIRECTDRAW_GBL pDdGbl,
  460. LPD3DHALPROVIDER_INTERFACEDATA pInterfaceData,
  461. DWORD dwVersion)
  462. {
  463. *pInterfaceData = TestInterfaceData;
  464. return D3D_OK;
  465. }
  466. //----------------------------------------------------------------------------
  467. //
  468. // TestHalProvider::GetCaps
  469. //
  470. // Returns real rasterizer caps.
  471. //
  472. //----------------------------------------------------------------------------
  473. STDMETHODIMP
  474. CTestHalProvider::GetCaps(THIS_
  475. LPDDRAWI_DIRECTDRAW_GBL pDdGbl,
  476. LPD3DDEVICEDESC pHwDesc,
  477. LPD3DDEVICEDESC pHelDesc,
  478. DWORD dwVersion)
  479. {
  480. return pCurHalProvider->GetCaps(pDdGbl, pHwDesc, pHelDesc, dwVersion);
  481. }
  482. //#endif //DEBUG_PIPELINE