Source code of Windows XP (NT5)
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.

1062 lines
34 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) Microsoft Corporation, 2000.
  3. //
  4. // refdev.cpp
  5. //
  6. // Direct3D Reference Device - public interfaces
  7. //
  8. ///////////////////////////////////////////////////////////////////////////////
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. // This is a global static array of the block sizes in bytes for the
  12. // various DXTn compression formats
  13. int g_DXTBlkSize[NUM_DXT_FORMATS] =
  14. {
  15. sizeof(DXTBlockRGB),
  16. sizeof(DXTBlockAlpha4),
  17. sizeof(DXTBlockAlpha4),
  18. sizeof(DXTBlockAlpha3),
  19. sizeof(DXTBlockAlpha3),
  20. };
  21. //-----------------------------------------------------------------------------
  22. //
  23. // Memory management function installation
  24. //
  25. //-----------------------------------------------------------------------------
  26. // global pointers to memory allocation functions (used through MEM* macros)
  27. LPVOID (__cdecl *g_pfnMemAlloc)( size_t size ) = NULL;
  28. void (__cdecl *g_pfnMemFree)( LPVOID lptr ) = NULL;
  29. LPVOID (__cdecl *g_pfnMemReAlloc)( LPVOID ptr, size_t size ) = NULL;
  30. // install memory management functions - must be called before instancing
  31. // rasterizer object
  32. void RefRastSetMemif(
  33. LPVOID(__cdecl *pfnMemAlloc)(size_t),
  34. void(__cdecl *pfnMemFree)(LPVOID),
  35. LPVOID(__cdecl *pfnMemReAlloc)(LPVOID,size_t))
  36. {
  37. DPFRR(1, "RefRastSetMemif %08x %08x %08x\n",
  38. pfnMemAlloc,pfnMemFree,pfnMemReAlloc);
  39. g_pfnMemAlloc = pfnMemAlloc;
  40. g_pfnMemFree = pfnMemFree;
  41. g_pfnMemReAlloc = pfnMemReAlloc;
  42. }
  43. ///////////////////////////////////////////////////////////////////////////////
  44. // //
  45. // Public Interface Methods //
  46. // //
  47. ///////////////////////////////////////////////////////////////////////////////
  48. //-----------------------------------------------------------------------------
  49. //
  50. // SetRenderTarget -
  51. //
  52. //-----------------------------------------------------------------------------
  53. void
  54. RefDev::SetRenderTarget( RDRenderTarget* pRenderTarget )
  55. {
  56. m_pRenderTarget = pRenderTarget;
  57. // update the W scaling values for mapping interpolated W's into buffer range
  58. m_fWBufferNorm[0] = pRenderTarget->m_fWRange[0];
  59. FLOAT fWRange = pRenderTarget->m_fWRange[1] - pRenderTarget->m_fWRange[0];
  60. m_fWBufferNorm[1] = ( 0. != fWRange ) ? ( 1./fWRange ) : ( 1. );
  61. }
  62. //-----------------------------------------------------------------------------
  63. //
  64. // SetTextureStageState -
  65. //
  66. //-----------------------------------------------------------------------------
  67. // map DX6(&7) texture filtering enums to DX8 enums
  68. static DWORD
  69. MapDX6toDX8TexFilter( DWORD dwStageState, DWORD dwValue )
  70. {
  71. switch (dwStageState)
  72. {
  73. case D3DTSS_MAGFILTER:
  74. switch (dwValue)
  75. {
  76. case D3DTFG_POINT : return D3DTEXF_POINT;
  77. case D3DTFG_LINEAR : return D3DTEXF_LINEAR;
  78. case D3DTFG_FLATCUBIC : return D3DTEXF_FLATCUBIC;
  79. case D3DTFG_GAUSSIANCUBIC : return D3DTEXF_GAUSSIANCUBIC;
  80. case D3DTFG_ANISOTROPIC : return D3DTEXF_ANISOTROPIC;
  81. }
  82. break;
  83. case D3DTSS_MINFILTER:
  84. switch (dwValue)
  85. {
  86. case D3DTFN_POINT : return D3DTEXF_POINT;
  87. case D3DTFN_LINEAR : return D3DTEXF_LINEAR;
  88. case D3DTFN_ANISOTROPIC : return D3DTEXF_ANISOTROPIC;
  89. }
  90. break;
  91. case D3DTSS_MIPFILTER:
  92. switch (dwValue)
  93. {
  94. case D3DTFP_NONE : return D3DTEXF_NONE;
  95. case D3DTFP_POINT : return D3DTEXF_POINT;
  96. case D3DTFP_LINEAR : return D3DTEXF_LINEAR;
  97. }
  98. break;
  99. }
  100. return 0x0;
  101. }
  102. void
  103. RefDev::SetTextureStageState(
  104. DWORD dwStage, DWORD dwStageState, DWORD dwValue )
  105. {
  106. // check for range before continuing
  107. if ( dwStage >= D3DHAL_TSS_MAXSTAGES)
  108. {
  109. return;
  110. }
  111. if (dwStageState > D3DTSS_MAX)
  112. {
  113. return;
  114. }
  115. // set in internal per-stage state
  116. m_TextureStageState[dwStage].m_dwVal[dwStageState] = dwValue;
  117. if (m_pDbgMon) m_pDbgMon->StateChanged( D3DDM_SC_DEVICESTATE );
  118. m_dwRastFlags |= RDRF_TEXTURESTAGESTATE_CHANGED;
  119. switch ( dwStageState )
  120. {
  121. case D3DTSS_TEXTUREMAP:
  122. // bind texture indicated by handle to m_pTexture array
  123. if (IsDriverDX6AndBefore() || IsInterfaceDX6AndBefore())
  124. {
  125. // This is the legacy behavior (prev. to DX7)
  126. MapTextureHandleToDevice( dwStage );
  127. }
  128. else
  129. {
  130. // This is the new behavior (DX7 and beyond)
  131. SetTextureHandle( dwStage, dwValue );
  132. }
  133. m_dwRastFlags |= RDRF_LEGACYPIXELSHADER_CHANGED;
  134. if (m_pDbgMon) m_pDbgMon->StateChanged( D3DDM_SC_TEXTURE );
  135. break;
  136. case D3DTSS_COLOROP:
  137. m_dwRastFlags |= RDRF_LEGACYPIXELSHADER_CHANGED;
  138. break;
  139. // not including legacy headers, so don't have D3DTSS_ADDRESS
  140. // case D3DTSS_ADDRESS:
  141. // // map single set ADDRESS to U, V controls (pre-DX8 interfaces only)
  142. // m_TextureStageState[dwStage].m_dwVal[D3DTSS_ADDRESSU] = dwValue;
  143. // m_TextureStageState[dwStage].m_dwVal[D3DTSS_ADDRESSV] = dwValue;
  144. // break;
  145. case D3DTSS_MAGFILTER:
  146. case D3DTSS_MINFILTER:
  147. case D3DTSS_MIPFILTER:
  148. if ( IsDriverDX7AndBefore() )
  149. {
  150. m_TextureStageState[dwStage].m_dwVal[dwStageState]
  151. = MapDX6toDX8TexFilter( dwStageState, dwValue );
  152. }
  153. break;
  154. }
  155. }
  156. //-----------------------------------------------------------------------------
  157. //
  158. // TextureCreate - Instantiates new RDSurface2D object, computes texture handle
  159. // to associate with it, and returns both to caller. Note that texture handle
  160. // is a pointer and can be used to get at the corresponding texture object.
  161. //
  162. //-----------------------------------------------------------------------------
  163. BOOL
  164. RefDev::TextureCreate(
  165. LPD3DTEXTUREHANDLE phTex, RDSurface2D** ppTex )
  166. {
  167. // allocate internal texture structure
  168. *ppTex = new RDSurface2D();
  169. _ASSERTa( NULL != *ppTex, "new failure on texture create", return FALSE; );
  170. // use separately allocated pointer for handle
  171. RDSurface2D** ppTexForHandle = (RDSurface2D**)MEMALLOC( sizeof(RDSurface2D*) );
  172. _ASSERTa( NULL != ppTexForHandle, "malloc failure on texture create", return FALSE; );
  173. *ppTexForHandle = *ppTex;
  174. // return texture handle
  175. (*ppTex)->m_hTex = (ULONG_PTR)ppTexForHandle;
  176. *phTex = (*ppTex)->m_hTex;
  177. return TRUE;
  178. }
  179. //-----------------------------------------------------------------------------
  180. //
  181. // TextureDestroy -
  182. //
  183. //-----------------------------------------------------------------------------
  184. BOOL
  185. RefDev::TextureDestroy( D3DTEXTUREHANDLE hTex )
  186. {
  187. // first check if texture about to be destroyed is mapped - if so then
  188. // unmap it
  189. for ( int iStage=0; iStage<D3DHAL_TSS_MAXSTAGES; iStage++ )
  190. {
  191. if ( hTex == m_TextureStageState[iStage].m_dwVal[D3DTSS_TEXTUREMAP] )
  192. {
  193. SetTextureStageState( iStage, D3DTSS_TEXTUREMAP, 0x0 );
  194. }
  195. }
  196. // resolve handle to RDSurface2D pointer
  197. RDSurface2D* pTex = MapHandleToTexture( hTex );
  198. if ( NULL == pTex ) { return FALSE; }
  199. // free the handle pointer
  200. #ifdef _IA64_
  201. _ASSERTa(FALSE, "This will not work on IA64", return FALSE;);
  202. #endif
  203. RDSurface2D** ppTex = (RDSurface2D**)ULongToPtr(hTex);
  204. if ( NULL != ppTex) { MEMFREE( ppTex ); }
  205. // free the RDSurface2D
  206. delete pTex;
  207. return TRUE;
  208. }
  209. //-----------------------------------------------------------------------------
  210. //
  211. // TextureGetSurf -
  212. //
  213. //-----------------------------------------------------------------------------
  214. DWORD
  215. RefDev::TextureGetSurf( D3DTEXTUREHANDLE hTex )
  216. {
  217. RDSurface2D* pTex = MapHandleToTexture(hTex);
  218. if ( NULL == pTex ) { return 0x0; }
  219. return PtrToUlong( pTex->m_pDDSLcl[0] );
  220. }
  221. //-----------------------------------------------------------------------------
  222. //
  223. // GetCurrentTextureMaps - This function fills in a passed array texture handles
  224. // and pointers. The array should be sized by D3DHAL_TSS_MAXSTAGES.
  225. //
  226. // This is used to facilitate external locking/unlocking of surfaces used for
  227. // textures.
  228. //
  229. //-----------------------------------------------------------------------------
  230. int
  231. RefDev::GetCurrentTextureMaps(
  232. D3DTEXTUREHANDLE *phTex, RDSurface2D** pTex)
  233. {
  234. UpdateActiveTexStageCount();
  235. for ( int i=0; i<m_cActiveTextureStages; i++ )
  236. {
  237. if ( NULL == m_pTexture[i] )
  238. {
  239. phTex[i] = 0x0;
  240. pTex[i] = NULL;
  241. }
  242. else
  243. {
  244. phTex[i] = m_pTexture[i]->m_hTex;
  245. pTex[i] = m_pTexture[i];
  246. }
  247. }
  248. return m_cActiveTextureStages;
  249. }
  250. //-----------------------------------------------------------------------------
  251. //
  252. // SceneCapture - Used to trigger fragment buffer resolve.
  253. //
  254. //-----------------------------------------------------------------------------
  255. //#define DO_SCENE_RENDER_TIME
  256. #ifdef DO_SCENE_RENDER_TIME
  257. #include <mmsystem.h>
  258. #endif
  259. void
  260. RefDev::SceneCapture( DWORD dwFlags )
  261. {
  262. static INT32 iScene = 0;
  263. static INT32 iLastSceneEnd = 0;
  264. #ifdef DO_SCENE_RENDER_TIME
  265. static DWORD timeBS = 0;
  266. #endif
  267. switch (dwFlags)
  268. {
  269. case D3DHAL_SCENE_CAPTURE_START:
  270. iScene++;
  271. if (m_pDbgMon) m_pDbgMon->NextEvent(D3DDM_EVENT_BEGINSCENE);
  272. #ifdef DO_SCENE_RENDER_TIME
  273. timeBS = timeGetTime();
  274. #endif
  275. break;
  276. case D3DHAL_SCENE_CAPTURE_END:
  277. if (iScene == iLastSceneEnd) break; // getting multiple END per BEGIN
  278. iLastSceneEnd = iScene;
  279. #ifdef DO_SCENE_RENDER_TIME
  280. {
  281. DWORD timeES = timeGetTime();
  282. FLOAT dt = (FLOAT)(timeES - timeBS)/1000.f;
  283. timeBS = 0;
  284. RDDebugPrintf("SceneRenderTime: %f", dt );
  285. }
  286. #endif
  287. {
  288. if (m_pDbgMon) m_pDbgMon->NextEvent(D3DDM_EVENT_ENDSCENE);
  289. }
  290. break;
  291. }
  292. }
  293. //-----------------------------------------------------------------------------
  294. //
  295. // Query functions to get pointer to current render target and render state.
  296. //
  297. //-----------------------------------------------------------------------------
  298. RDRenderTarget*
  299. RefDev::GetRenderTarget(void)
  300. {
  301. return m_pRenderTarget;
  302. }
  303. //-----------------------------------------------------------------------------
  304. //
  305. //-----------------------------------------------------------------------------
  306. HRESULT
  307. RefDev::UpdateRastState( void )
  308. {
  309. // check 'dirty' flags
  310. if (m_dwRastFlags & RDRF_MULTISAMPLE_CHANGED)
  311. {
  312. // update multi-sample RS related state
  313. m_Rast.SetSampleMode(
  314. m_pRenderTarget->m_pColor->m_iSamples,
  315. m_dwRenderState[D3DRS_MULTISAMPLEANTIALIAS] );
  316. m_Rast.SetSampleMask(
  317. m_dwRenderState[D3DRS_MULTISAMPLEMASK] );
  318. m_dwRastFlags &= ~(RDRF_MULTISAMPLE_CHANGED);
  319. }
  320. if (m_dwRastFlags & RDRF_PIXELSHADER_CHANGED)
  321. {
  322. if (m_CurrentPShaderHandle)
  323. {
  324. m_Rast.m_pCurrentPixelShader =
  325. GetPShader(m_CurrentPShaderHandle);
  326. m_Rast.m_bLegacyPixelShade = FALSE;
  327. }
  328. else
  329. {
  330. // legacy pixel shader
  331. m_Rast.UpdateLegacyPixelShader();
  332. m_Rast.m_pCurrentPixelShader = m_Rast.m_pLegacyPixelShader;
  333. m_Rast.m_bLegacyPixelShade = TRUE;
  334. }
  335. UpdateActiveTexStageCount();
  336. m_dwRastFlags &= ~(RDRF_PIXELSHADER_CHANGED);
  337. }
  338. if (m_dwRastFlags & RDRF_LEGACYPIXELSHADER_CHANGED)
  339. {
  340. if (m_Rast.m_bLegacyPixelShade)
  341. {
  342. m_Rast.UpdateLegacyPixelShader();
  343. m_Rast.m_pCurrentPixelShader = m_Rast.m_pLegacyPixelShader;
  344. UpdateActiveTexStageCount();
  345. }
  346. m_dwRastFlags &= ~(RDRF_LEGACYPIXELSHADER_CHANGED);
  347. }
  348. if (m_dwRastFlags & RDRF_TEXTURESTAGESTATE_CHANGED)
  349. {
  350. m_Rast.UpdateTextureControls();
  351. m_dwRastFlags &= ~(RDRF_TEXTURESTAGESTATE_CHANGED);
  352. }
  353. return S_OK;
  354. }
  355. //-----------------------------------------------------------------------------
  356. //
  357. // Begin/End bracket functions - Called before/after a list of primitives are
  358. // rendered.
  359. //
  360. //-----------------------------------------------------------------------------
  361. HRESULT
  362. RefDev::BeginRendering( void )
  363. {
  364. // If already in Begin, do nothing
  365. if( m_bInBegin ) return S_OK;
  366. #ifdef _X86_
  367. // save floating point mode and set to extended precision mode
  368. {
  369. WORD wTemp, wSave;
  370. __asm
  371. {
  372. fstcw wSave
  373. mov ax, wSave
  374. or ax, 300h ;; extended precision mode
  375. // and ax, 00FFh ;; single precision mode + round nearest or even
  376. mov wTemp, ax
  377. fldcw wTemp
  378. }
  379. m_wSaveFP = wSave;
  380. }
  381. #endif
  382. m_bInBegin = TRUE;
  383. return S_OK;
  384. }
  385. //-----------------------------------------------------------------------------
  386. HRESULT
  387. RefDev::EndRendering( void )
  388. {
  389. if ( m_bInBegin )
  390. {
  391. #ifdef _X86_
  392. // restore floating point mode
  393. {
  394. WORD wSave = m_wSaveFP;
  395. __asm {fldcw wSave}
  396. }
  397. #endif
  398. m_bInBegin = FALSE;
  399. }
  400. return S_OK;
  401. }
  402. //-----------------------------------------------------------------------------
  403. //
  404. // Clear specified rectangles in the render target
  405. // Directly handles the command from the DP2 stream
  406. //
  407. //-----------------------------------------------------------------------------
  408. HRESULT RefDev::Clear(LPD3DHAL_DP2COMMAND pCmd)
  409. {
  410. D3DHAL_DP2CLEAR *pData = (D3DHAL_DP2CLEAR*)(pCmd + 1);
  411. WORD i;
  412. INT32 x,y;
  413. RDColor fillColor(pData->dwFillColor);
  414. RDDepth fillDepth;
  415. if (m_pRenderTarget->m_pDepth)
  416. {
  417. fillDepth.SetSType(m_pRenderTarget->m_pDepth->GetSurfaceFormat());
  418. }
  419. fillDepth = pData->dvFillDepth;
  420. struct
  421. {
  422. D3DHAL_DP2COMMAND cmd;
  423. D3DHAL_DP2CLEAR data;
  424. } WholeViewport;
  425. if (!(pData->dwFlags & D3DCLEAR_COMPUTERECTS))
  426. {
  427. // Do nothing for non-pure device
  428. }
  429. else
  430. if (pCmd->wStateCount == 0)
  431. {
  432. // When wStateCount is zero we need to clear whole viewport
  433. WholeViewport.cmd = *pCmd;
  434. WholeViewport.cmd.wStateCount = 1;
  435. WholeViewport.data.dwFlags = pData->dwFlags;
  436. WholeViewport.data.dwFillColor = pData->dwFillColor;
  437. WholeViewport.data.dvFillDepth = pData->dvFillDepth;
  438. WholeViewport.data.dwFillStencil = pData->dwFillStencil;
  439. WholeViewport.data.Rects[0].left = m_Clipper.m_Viewport.dwX;
  440. WholeViewport.data.Rects[0].top = m_Clipper.m_Viewport.dwY;
  441. WholeViewport.data.Rects[0].right = m_Clipper.m_Viewport.dwX +
  442. m_Clipper.m_Viewport.dwWidth;
  443. WholeViewport.data.Rects[0].bottom = m_Clipper.m_Viewport.dwY +
  444. m_Clipper.m_Viewport.dwHeight;
  445. // Replace pointers and continue as usual
  446. pCmd = (LPD3DHAL_DP2COMMAND)&WholeViewport;
  447. pData = &WholeViewport.data;
  448. }
  449. else
  450. {
  451. // We need to cull all rects against the current viewport
  452. UINT nRects = pCmd->wStateCount;
  453. // Compute how much memory we need to process rects
  454. UINT NeededSize = sizeof(D3DHAL_DP2COMMAND) +
  455. sizeof(D3DHAL_DP2CLEAR) +
  456. (nRects-1) * sizeof(RECT); // One rect is in DP2CLEAR
  457. HRESULT hr = S_OK;
  458. HR_RET(m_ClearRectBuffer.Grow(NeededSize));
  459. RECT vwport; // Viewport rectangle to cull against
  460. vwport.left = m_Clipper.m_Viewport.dwX;
  461. vwport.top = m_Clipper.m_Viewport.dwY;
  462. vwport.right = m_Clipper.m_Viewport.dwX + m_Clipper.m_Viewport.dwWidth;
  463. vwport.bottom = m_Clipper.m_Viewport.dwY + m_Clipper.m_Viewport.dwHeight;
  464. // Go through input rects and build output rect array
  465. LPRECT pInputRects = pData->Rects;
  466. LPRECT pOutputRects = (LPRECT)(&m_ClearRectBuffer[0] +
  467. sizeof(D3DHAL_DP2COMMAND) +
  468. sizeof(D3DHAL_DP2CLEAR) -
  469. sizeof(RECT));
  470. UINT nOutputRects = 0;
  471. for (UINT i = 0; i < nRects; i++)
  472. {
  473. if (IntersectRect(&pOutputRects[nOutputRects], &vwport,
  474. &pInputRects[i]))
  475. {
  476. nOutputRects++;
  477. }
  478. }
  479. if (nOutputRects == 0)
  480. return S_OK;
  481. // Now replace pCmd and pData pointers and continue as usual
  482. LPD3DHAL_DP2CLEAR pOldData = pData;
  483. LPD3DHAL_DP2COMMAND pOldCmd = pCmd;
  484. pCmd = (LPD3DHAL_DP2COMMAND)&m_ClearRectBuffer[0];
  485. pData = (D3DHAL_DP2CLEAR*)(pCmd + 1);
  486. *pCmd = *pOldCmd;
  487. pCmd->wStateCount = (WORD)nOutputRects;
  488. pData->dwFlags = pOldData->dwFlags;
  489. pData->dwFillColor = pOldData->dwFillColor;
  490. pData->dvFillDepth = pOldData->dvFillDepth;
  491. pData->dwFillStencil = pOldData->dwFillStencil;
  492. }
  493. #ifdef _X86_
  494. // Float to integer conversion routines for 24+ bit buffers work
  495. // only with extended FPU mode.
  496. //
  497. WORD wSaveFP;
  498. // save floating point mode and set to extended precision mode
  499. {
  500. WORD wTemp, wSave;
  501. __asm
  502. {
  503. fstcw wSaveFP
  504. mov ax, wSaveFP
  505. or ax, 300h ;; extended precision mode
  506. mov wTemp, ax
  507. fldcw wTemp
  508. }
  509. }
  510. #endif
  511. if(pData->dwFlags & D3DCLEAR_TARGET)
  512. {
  513. if (m_dwRenderState[D3DRENDERSTATE_DITHERENABLE] == FALSE)
  514. {
  515. m_pRenderTarget->Clear(fillColor, pCmd);
  516. }
  517. else
  518. {
  519. for (i = 0; i < pCmd->wStateCount; i++)
  520. {
  521. for (y = pData->Rects[i].top; y < pData->Rects[i].bottom; ++y)
  522. {
  523. for (x = pData->Rects[i].left; x < pData->Rects[i].right; ++x)
  524. {
  525. m_pRenderTarget->WritePixelColor(x, y, fillColor, TRUE);
  526. }
  527. }
  528. }
  529. }
  530. }
  531. switch (pData->dwFlags & (D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL))
  532. {
  533. case (D3DCLEAR_ZBUFFER):
  534. m_pRenderTarget->ClearDepth(fillDepth, pCmd);
  535. break;
  536. case (D3DCLEAR_STENCIL):
  537. m_pRenderTarget->ClearStencil(pData->dwFillStencil, pCmd);
  538. break;
  539. case (D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL):
  540. m_pRenderTarget->ClearDepthStencil(fillDepth, pData->dwFillStencil, pCmd);
  541. break;
  542. }
  543. #ifdef _X86_
  544. // restore floating point mode
  545. {
  546. __asm {fldcw wSaveFP}
  547. }
  548. #endif
  549. return D3D_OK;
  550. }
  551. //-----------------------------------------------------------------------------
  552. //
  553. // Clear specified rectangles in the render target
  554. // Directly handles the command from the DP2 stream
  555. //
  556. //-----------------------------------------------------------------------------
  557. void RDRenderTarget::Clear(RDColor fillColor, LPD3DHAL_DP2COMMAND pCmd)
  558. {
  559. LPD3DHAL_DP2CLEAR pData = (LPD3DHAL_DP2CLEAR)(pCmd + 1);
  560. UINT32 dwColor = 0;
  561. fillColor.ConvertTo( m_pColor->GetSurfaceFormat(), 0.5f, (char*)&dwColor);
  562. for (DWORD i = 0; i < pCmd->wStateCount; i++)
  563. {
  564. DWORD x0 = pData->Rects[i].left;
  565. DWORD y0 = pData->Rects[i].top;
  566. DWORD dwWidth = ( pData->Rects[i].right - x0 ) * m_pColor->GetSamples();
  567. DWORD dwHeight = pData->Rects[i].bottom - y0;
  568. char* pSurface = PixelAddress( x0, y0, 0, 0, m_pColor );
  569. switch ( m_pColor->GetSurfaceFormat() )
  570. {
  571. case RD_SF_B8G8R8A8:
  572. case RD_SF_B8G8R8X8:
  573. {
  574. for (DWORD y = dwHeight; y > 0; y--)
  575. {
  576. UINT32 *p = (UINT32*)pSurface;
  577. for (DWORD x = dwWidth; x > 0; x--)
  578. {
  579. *p++ = dwColor;
  580. }
  581. pSurface += m_pColor->GetPitch();
  582. }
  583. }
  584. break;
  585. case RD_SF_B8G8R8:
  586. {
  587. for (DWORD y = dwHeight; y > 0; y--)
  588. {
  589. UINT8 *p = (UINT8*)pSurface;
  590. for (DWORD x = dwWidth; x > 0; x--)
  591. {
  592. *p++ = ((UINT8*)&dwColor)[0];
  593. *p++ = ((UINT8*)&dwColor)[1];
  594. *p++ = ((UINT8*)&dwColor)[2];
  595. }
  596. pSurface += m_pColor->GetPitch();
  597. }
  598. }
  599. break;
  600. case RD_SF_B4G4R4A4:
  601. case RD_SF_B5G6R5:
  602. case RD_SF_B5G5R5A1:
  603. case RD_SF_B5G5R5X1:
  604. {
  605. for (DWORD y = dwHeight; y > 0; y--)
  606. {
  607. UINT16 *p = (UINT16*)pSurface;
  608. for (DWORD x = dwWidth; x > 0; x--)
  609. {
  610. *p++ = (UINT16)dwColor;
  611. }
  612. pSurface += m_pColor->GetPitch();
  613. }
  614. }
  615. break;
  616. case RD_SF_B2G3R3:
  617. {
  618. for (DWORD y = dwHeight; y > 0; y--)
  619. {
  620. UINT8 *p = (UINT8*)pSurface;
  621. for (DWORD x = dwWidth; x > 0; x--)
  622. {
  623. *p++ = (UINT8)dwColor;
  624. }
  625. pSurface += m_pColor->GetPitch();
  626. }
  627. }
  628. break;
  629. default:
  630. {
  631. for (int y = y0; y < pData->Rects[i].bottom; ++y)
  632. {
  633. for (int x = x0; x < pData->Rects[i].right; ++x)
  634. {
  635. this->WritePixelColor(x, y, fillColor, TRUE);
  636. }
  637. }
  638. }
  639. }
  640. }
  641. }
  642. //-----------------------------------------------------------------------------
  643. //
  644. // Clear specified rectangles in the depth buffer
  645. // Directly handles the command from the DP2 stream
  646. //
  647. //-----------------------------------------------------------------------------
  648. void RDRenderTarget::ClearDepth(RDDepth fillDepth, LPD3DHAL_DP2COMMAND pCmd)
  649. {
  650. LPD3DHAL_DP2CLEAR pData = (LPD3DHAL_DP2CLEAR)(pCmd + 1);
  651. if (!m_pDepth) return;
  652. for (DWORD i = 0; i < pCmd->wStateCount; i++)
  653. {
  654. DWORD x0 = pData->Rects[i].left;
  655. DWORD y0 = pData->Rects[i].top;
  656. DWORD dwWidth = ( pData->Rects[i].right - x0 ) * m_pDepth->GetSamples();
  657. DWORD dwHeight = pData->Rects[i].bottom - y0;
  658. char* pSurface = PixelAddress( x0, y0, 0, 0, m_pDepth );
  659. switch ( m_pDepth->GetSurfaceFormat() )
  660. {
  661. case RD_SF_Z16S0:
  662. {
  663. UINT16 Depth = UINT16(fillDepth);
  664. for (DWORD y = dwHeight; y > 0; y--)
  665. {
  666. UINT16 *p = (UINT16*)pSurface;
  667. for (DWORD x = dwWidth; x > 0; x--)
  668. {
  669. *p++ = Depth;
  670. }
  671. pSurface += m_pDepth->GetPitch();
  672. }
  673. }
  674. break;
  675. case RD_SF_Z24S8:
  676. case RD_SF_Z24X8:
  677. case RD_SF_Z24X4S4:
  678. {
  679. UINT32 Depth = UINT32(fillDepth) << 8;
  680. for (DWORD y = dwHeight; y > 0; y--)
  681. {
  682. UINT32 *p = (UINT32*)pSurface;
  683. for (DWORD x = dwWidth; x > 0; x--)
  684. {
  685. // need to do read-modify-write to not step on stencil
  686. *p++ = (*p & ~(0xffffff00)) | Depth;
  687. }
  688. pSurface += m_pDepth->GetPitch();
  689. }
  690. }
  691. break;
  692. case RD_SF_S8Z24:
  693. case RD_SF_X8Z24:
  694. case RD_SF_X4S4Z24:
  695. {
  696. UINT32 Depth = UINT32(fillDepth) & 0x00ffffff;
  697. for (DWORD y = dwHeight; y > 0; y--)
  698. {
  699. UINT32 *p = (UINT32*)pSurface;
  700. for (DWORD x = dwWidth; x > 0; x--)
  701. {
  702. // need to do read-modify-write to not step on stencil
  703. *p++ = (*p & ~(0x00ffffff)) | Depth;
  704. }
  705. pSurface += m_pDepth->GetPitch();
  706. }
  707. }
  708. break;
  709. case RD_SF_Z15S1:
  710. {
  711. UINT16 Depth = UINT16(fillDepth) << 1;
  712. for (DWORD y = dwHeight; y > 0; y--)
  713. {
  714. UINT16 *p = (UINT16*)pSurface;
  715. for (DWORD x = dwWidth; x > 0; x--)
  716. {
  717. // need to do read-modify-write to not step on stencil
  718. *p++ = (*p & ~(0xfffe)) | Depth;
  719. }
  720. pSurface += m_pDepth->GetPitch();
  721. }
  722. }
  723. break;
  724. case RD_SF_S1Z15:
  725. {
  726. UINT16 Depth = UINT16(fillDepth) & 0x7fff;
  727. for (DWORD y = dwHeight; y > 0; y--)
  728. {
  729. UINT16 *p = (UINT16*)pSurface;
  730. for (DWORD x = dwWidth; x > 0; x--)
  731. {
  732. // need to do read-modify-write to not step on stencil
  733. *p++ = (*p & ~(0x7fff)) | Depth;
  734. }
  735. pSurface += m_pDepth->GetPitch();
  736. }
  737. }
  738. break;
  739. case RD_SF_Z32S0:
  740. {
  741. UINT32 Depth = UINT32(fillDepth);
  742. for (DWORD y = dwHeight; y > 0; y--)
  743. {
  744. UINT32 *p = (UINT32*)pSurface;
  745. for (DWORD x = dwWidth; x > 0; x--)
  746. {
  747. *p++ = Depth;
  748. }
  749. pSurface += m_pDepth->GetPitch();
  750. }
  751. }
  752. break;
  753. default:
  754. {
  755. for (int y = y0; y < pData->Rects[i].bottom; ++y)
  756. {
  757. for (int x = x0; x < pData->Rects[i].right; ++x)
  758. {
  759. this->WritePixelDepth(x, y, fillDepth);
  760. }
  761. }
  762. }
  763. }
  764. }
  765. }
  766. //-----------------------------------------------------------------------------
  767. //
  768. // Clear specified rectangles in the stencil buffer
  769. // Directly handles the command from the DP2 stream
  770. //
  771. //-----------------------------------------------------------------------------
  772. void RDRenderTarget::ClearStencil(UINT8 uStencil, LPD3DHAL_DP2COMMAND pCmd)
  773. {
  774. LPD3DHAL_DP2CLEAR pData = (LPD3DHAL_DP2CLEAR)(pCmd + 1);
  775. for (DWORD i = 0; i < pCmd->wStateCount; i++)
  776. {
  777. DWORD x0 = pData->Rects[i].left;
  778. DWORD y0 = pData->Rects[i].top;
  779. DWORD dwWidth = (pData->Rects[i].right - x0 ) * m_pDepth->GetSamples();
  780. DWORD dwHeight = pData->Rects[i].bottom - y0;
  781. char* pSurface = PixelAddress( x0, y0, 0, 0, m_pDepth );
  782. switch ( m_pDepth->GetSurfaceFormat() )
  783. {
  784. case RD_SF_Z24S8:
  785. {
  786. for (DWORD y = dwHeight; y > 0; y--)
  787. {
  788. UINT8 *p = (UINT8*)pSurface;
  789. for (DWORD x = dwWidth; x > 0; x--)
  790. {
  791. *p = uStencil;
  792. p += 4;
  793. }
  794. pSurface += m_pDepth->GetPitch();
  795. }
  796. }
  797. break;
  798. case RD_SF_S8Z24:
  799. {
  800. for (DWORD y = dwHeight; y > 0; y--)
  801. {
  802. UINT8 *p = (UINT8*)&pSurface[3];
  803. for (DWORD x = dwWidth; x > 0; x--)
  804. {
  805. *p = uStencil;
  806. p += 4;
  807. }
  808. pSurface += m_pDepth->GetPitch();
  809. }
  810. }
  811. break;
  812. case RD_SF_Z24X4S4:
  813. {
  814. UINT32 stencil = uStencil & 0xf;
  815. for (DWORD y = dwHeight; y > 0; y--)
  816. {
  817. UINT32 *p = (UINT32*)pSurface;
  818. for (DWORD x = dwWidth; x > 0; x--)
  819. {
  820. // need to do read-modify-write to not step on depth
  821. *p++ = (*p & ~(0x000000ff)) | stencil;
  822. }
  823. pSurface += m_pDepth->GetPitch();
  824. }
  825. }
  826. break;
  827. case RD_SF_X4S4Z24:
  828. {
  829. UINT32 stencil = (uStencil & 0xf) << 24;
  830. for (DWORD y = dwHeight; y > 0; y--)
  831. {
  832. UINT32 *p = (UINT32*)pSurface;
  833. for (DWORD x = dwWidth; x > 0; x--)
  834. {
  835. // need to do read-modify-write to not step on depth
  836. *p++ = (*p & ~(0xff000000)) | stencil;
  837. }
  838. pSurface += m_pDepth->GetPitch();
  839. }
  840. }
  841. break;
  842. case RD_SF_Z15S1:
  843. {
  844. UINT16 stencil = uStencil & 0x1;
  845. for (DWORD y = dwHeight; y > 0; y--)
  846. {
  847. UINT16 *p = (UINT16*)pSurface;
  848. for (DWORD x = dwWidth; x > 0; x--)
  849. {
  850. // need to do read-modify-write to not step on depth
  851. *p++ = (*p & ~(0x0001)) | stencil;
  852. }
  853. pSurface += m_pDepth->GetPitch();
  854. }
  855. }
  856. break;
  857. case RD_SF_S1Z15:
  858. {
  859. UINT16 stencil = uStencil << 15;
  860. for (DWORD y = dwHeight; y > 0; y--)
  861. {
  862. UINT16 *p = (UINT16*)pSurface;
  863. for (DWORD x = dwWidth; x > 0; x--)
  864. {
  865. // need to do read-modify-write to not step on depth
  866. *p++ = (*p & ~(0x8000)) | stencil;
  867. }
  868. pSurface += m_pDepth->GetPitch();
  869. }
  870. }
  871. break;
  872. case RD_SF_Z16S0:
  873. case RD_SF_Z32S0:
  874. break;
  875. default:
  876. {
  877. for (int y = y0; y < pData->Rects[i].bottom; ++y)
  878. {
  879. for (int x = x0; x < pData->Rects[i].right; ++x)
  880. {
  881. this->WritePixelStencil(x, y, uStencil);
  882. }
  883. }
  884. }
  885. }
  886. }
  887. }
  888. //-----------------------------------------------------------------------------
  889. //
  890. // Clear specified rectangles in the depth and stencil buffers
  891. // Directly handles the command from the DP2 stream
  892. //
  893. //-----------------------------------------------------------------------------
  894. void RDRenderTarget::ClearDepthStencil(RDDepth fillDepth, UINT8 uStencil, LPD3DHAL_DP2COMMAND pCmd)
  895. {
  896. LPD3DHAL_DP2CLEAR pData = (LPD3DHAL_DP2CLEAR)(pCmd + 1);
  897. for (DWORD i = 0; i < pCmd->wStateCount; i++)
  898. {
  899. DWORD x0 = pData->Rects[i].left;
  900. DWORD y0 = pData->Rects[i].top;
  901. DWORD dwWidth = ( pData->Rects[i].right - x0 ) * m_pDepth->GetSamples();
  902. DWORD dwHeight = pData->Rects[i].bottom - y0;
  903. char* pSurface = PixelAddress( x0, y0, 0, 0, m_pDepth );
  904. switch (m_pDepth->GetSurfaceFormat())
  905. {
  906. case RD_SF_Z16S0:
  907. case RD_SF_Z32S0:
  908. break;
  909. case RD_SF_Z24S8:
  910. case RD_SF_Z24X8:
  911. case RD_SF_S8Z24:
  912. case RD_SF_X8Z24:
  913. case RD_SF_Z24X4S4:
  914. case RD_SF_X4S4Z24:
  915. {
  916. UINT32 v;
  917. switch (m_pDepth->GetSurfaceFormat())
  918. {
  919. case RD_SF_Z24S8: v = (UINT32(fillDepth) << 8) + uStencil; break;
  920. case RD_SF_Z24X8: v = (UINT32(fillDepth) << 8); break;
  921. case RD_SF_S8Z24: v = (UINT32(fillDepth) & 0x00ffffff) + (uStencil << 24); break;
  922. case RD_SF_X8Z24: v = (UINT32(fillDepth) & 0x00ffffff); break;
  923. case RD_SF_Z24X4S4: v = (UINT32(fillDepth) << 8) + (uStencil & 0xf); break;
  924. case RD_SF_X4S4Z24: v = (UINT32(fillDepth) & 0x00ffffff) + ((uStencil & 0xf) << 24); break;
  925. }
  926. for (DWORD y = dwHeight; y > 0; y--)
  927. {
  928. UINT32 *p = (UINT32*)pSurface;
  929. for (DWORD x = dwWidth; x > 0; x--)
  930. {
  931. *p++ = v;
  932. }
  933. pSurface += m_pDepth->GetPitch();
  934. }
  935. }
  936. break;
  937. case RD_SF_Z15S1:
  938. case RD_SF_S1Z15:
  939. {
  940. UINT16 v;
  941. switch (m_pDepth->GetSurfaceFormat())
  942. {
  943. case RD_SF_Z15S1: v = (UINT16(fillDepth) << 1) + (uStencil & 0x1); break;
  944. case RD_SF_S1Z15: v = (UINT16(fillDepth) & 0x7fff) + (uStencil << 15); break;
  945. }
  946. for (DWORD y = dwHeight; y > 0; y--)
  947. {
  948. UINT16 *p = (UINT16*)pSurface;
  949. for (DWORD x = dwWidth; x > 0; x--)
  950. {
  951. *p++ = v;
  952. }
  953. pSurface += m_pDepth->GetPitch();
  954. }
  955. }
  956. break;
  957. default:
  958. {
  959. for (int y = y0; y < pData->Rects[i].bottom; ++y)
  960. {
  961. for (int x = x0; x < pData->Rects[i].right; ++x)
  962. {
  963. this->WritePixelDepth(x, y, fillDepth);
  964. this->WritePixelStencil(x, y, uStencil);
  965. }
  966. }
  967. }
  968. }
  969. }
  970. }
  971. #ifndef __D3D_NULL_REF
  972. //-----------------------------------------------------------------------------
  973. //
  974. HRESULT WINAPI
  975. D3D8CreateDebugMonitor( ULONG_PTR dwContext, BOOL bDbgMonConnectionEnabled, D3DDebugMonitor** ppDbgMon )
  976. {
  977. RefDev* pRefDev = (RefDev*)dwContext;
  978. pRefDev->m_pDbgMon = new RDDebugMonitor(pRefDev, bDbgMonConnectionEnabled);
  979. if( pRefDev->m_pDbgMon == NULL )
  980. {
  981. return E_OUTOFMEMORY;
  982. }
  983. *ppDbgMon = (D3DDebugMonitor*)pRefDev->m_pDbgMon;
  984. pRefDev->m_pDbgMon->AttachToMonitor(1);
  985. return S_OK;
  986. }
  987. #endif //__D3D_NULL_REF
  988. ///////////////////////////////////////////////////////////////////////////////
  989. // end