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.

604 lines
22 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * **************************
  4. * * DirectDraw SAMPLE CODE *
  5. * **************************
  6. *
  7. * Module Name: dddownld.c
  8. *
  9. * Content: DirectDraw Blt implementation for sysmem-vidmem blts and clears
  10. *
  11. * Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
  12. * Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved.
  13. \*****************************************************************************/
  14. #include "glint.h"
  15. #include "dma.h"
  16. #include "tag.h"
  17. #define UNROLL_COUNT 8 // Number of iterations of transfer in an unrolled loop
  18. #define P3_BLOCK_SIZE (UNROLL_COUNT * 8) // # of unrolled loops .
  19. #define GAMMA_BLOCK_SIZE (UNROLL_COUNT * 2) // # of unrolled loops .
  20. #define BLOCK_SIZE (DWORD)((TLCHIP_GAMMA)?GAMMA_BLOCK_SIZE:P3_BLOCK_SIZE)
  21. #define TAGGED_SIZE ((BLOCK_SIZE - 1) << 16)
  22. #define UNROLLED() \
  23. MEMORY_BARRIER(); \
  24. dmaPtr[0] = pCurrentLine[0]; \
  25. ulTotalImageDWORDs--; \
  26. MEMORY_BARRIER(); \
  27. dmaPtr[1] = pCurrentLine[1]; \
  28. ulTotalImageDWORDs--; \
  29. MEMORY_BARRIER(); \
  30. dmaPtr[2] = pCurrentLine[2]; \
  31. ulTotalImageDWORDs--; \
  32. MEMORY_BARRIER(); \
  33. dmaPtr[3] = pCurrentLine[3]; \
  34. ulTotalImageDWORDs--; \
  35. MEMORY_BARRIER(); \
  36. dmaPtr[4] = pCurrentLine[4]; \
  37. ulTotalImageDWORDs--; \
  38. MEMORY_BARRIER(); \
  39. dmaPtr[5] = pCurrentLine[5]; \
  40. ulTotalImageDWORDs--; \
  41. MEMORY_BARRIER(); \
  42. dmaPtr[6] = pCurrentLine[6]; \
  43. ulTotalImageDWORDs--; \
  44. MEMORY_BARRIER(); \
  45. dmaPtr[7] = pCurrentLine[7]; \
  46. ulTotalImageDWORDs--; \
  47. MEMORY_BARRIER(); \
  48. dmaPtr += UNROLL_COUNT; \
  49. CHECK_FIFO(UNROLL_COUNT); \
  50. pCurrentLine += UNROLL_COUNT;
  51. //-----------------------------------------------------------------------------
  52. //
  53. // _DD_P3Download
  54. //
  55. //
  56. // Function to do an image download to the rectangular region.
  57. // Uses the packed bit on Permedia to do the packing for us.
  58. //
  59. //-----------------------------------------------------------------------------
  60. void
  61. _DD_P3Download(
  62. P3_THUNKEDDATA* pThisDisplay,
  63. FLATPTR pSrcfpVidMem,
  64. FLATPTR pDestfpVidMem,
  65. DWORD dwSrcChipPatchMode,
  66. DWORD dwDestChipPatchMode,
  67. DWORD dwSrcPitch,
  68. DWORD dwDestPitch,
  69. DWORD dwDestPixelPitch,
  70. DWORD dwDestPixelSize,
  71. RECTL* rSrc,
  72. RECTL* rDest)
  73. {
  74. // Work out pixel offset into the framestore of the rendered surface
  75. ULONG ulSCRoundedUpDWords;
  76. ULONG ulSCWholeDWords, ulSCDWordsCnt, ulSCExtraBytes;
  77. ULONG ulTotalImageDWORDs;
  78. DWORD SrcOffset;
  79. DWORD DstOffset;
  80. ULONG ulImageLines;
  81. ULONG count;
  82. ULONG renderData;
  83. DWORD dwDownloadTag;
  84. int rDestleft, rDesttop, rSrcleft, rSrctop;
  85. RECTL rNewDest;
  86. P3_DMA_DEFS();
  87. // Because of a bug in RL we sometimes have to fiddle with these values
  88. rSrctop = rSrc->top;
  89. rSrcleft = rSrc->left;
  90. rDesttop = rDest->top;
  91. rDestleft = rDest->left;
  92. // Fix coords origin
  93. if(!_DD_BLT_FixRectlOrigin("_DD_P3Download", rSrc, rDest))
  94. {
  95. // Nothing to be blitted
  96. return;
  97. }
  98. SrcOffset = (DWORD)(rSrc->left << dwDestPixelSize) +
  99. (rSrc->top * dwSrcPitch);
  100. DstOffset = (DWORD)(rDest->left << dwDestPixelSize) +
  101. (rDest->top * dwDestPitch);
  102. ulSCRoundedUpDWords = rDest->right - rDest->left;
  103. ulImageLines = rDest->bottom - rDest->top;
  104. P3_DMA_GET_BUFFER();
  105. P3_ENSURE_DX_SPACE(16);
  106. WAIT_FIFO(16);
  107. SEND_P3_DATA(FBWriteBufferAddr0,
  108. (DWORD)(pDestfpVidMem -
  109. pThisDisplay->dwScreenFlatAddr) );
  110. SEND_P3_DATA(FBWriteBufferWidth0, dwDestPixelPitch);
  111. SEND_P3_DATA(FBWriteBufferOffset0,
  112. (rDest->top << 16) |
  113. (rDest->left & 0xFFFF));
  114. SEND_P3_DATA(LogicalOpMode, 7);
  115. SEND_P3_DATA(PixelSize, (2 - dwDestPixelSize));
  116. SEND_P3_DATA(FBWriteMode,
  117. P3RX_FBWRITEMODE_WRITEENABLE(__PERMEDIA_ENABLE) |
  118. P3RX_FBWRITEMODE_LAYOUT0(P3RX_LAYOUT_LINEAR));
  119. SEND_P3_DATA(FBDestReadMode,
  120. P3RX_FBDESTREAD_READENABLE(__PERMEDIA_DISABLE) |
  121. P3RX_FBDESTREAD_LAYOUT0(P3RX_LAYOUT_LINEAR));
  122. dwDownloadTag = Color_Tag;
  123. rNewDest = *rDest;
  124. DISPDBG((DBGLVL, "Image download %dx%d", ulSCRoundedUpDWords, ulImageLines));
  125. // ulSCWholeDWords is the number of whole DWORDs along each scanline
  126. // ulSCExtraBytes is the number of extra BYTEs at the end of each scanline
  127. // ulSCRoundedUpDWords is the size of each scanline rounded up to DWORDs
  128. if (dwDestPixelSize != __GLINT_32BITPIXEL)
  129. {
  130. if (dwDestPixelSize == __GLINT_8BITPIXEL)
  131. {
  132. ulSCExtraBytes = ulSCRoundedUpDWords & 3;
  133. ulSCWholeDWords = ulSCRoundedUpDWords >> 2;
  134. ulSCRoundedUpDWords = (ulSCRoundedUpDWords + 3) >> 2;
  135. if (dwDownloadTag != Color_Tag)
  136. {
  137. rNewDest.right = rNewDest.left + (ulSCRoundedUpDWords << 2);
  138. }
  139. }
  140. else
  141. {
  142. ulSCExtraBytes = (ulSCRoundedUpDWords & 1) << 1;
  143. ulSCWholeDWords = ulSCRoundedUpDWords >> 1;
  144. ulSCRoundedUpDWords = (ulSCRoundedUpDWords + 1) >> 1;
  145. if (dwDownloadTag != Color_Tag)
  146. {
  147. rNewDest.right = rNewDest.left + (ulSCRoundedUpDWords << 1);
  148. }
  149. }
  150. }
  151. else
  152. {
  153. ulSCExtraBytes = 0;
  154. ulSCWholeDWords = ulSCRoundedUpDWords;
  155. }
  156. // Calc the total number of image DWORDs to send to GPU
  157. ulTotalImageDWORDs = ulImageLines * ulSCWholeDWords;
  158. P3_ENSURE_DX_SPACE(20);
  159. WAIT_FIFO(20);
  160. SEND_P3_DATA(FBSourceReadMode,
  161. P3RX_FBSOURCEREAD_READENABLE(__PERMEDIA_DISABLE) |
  162. P3RX_FBSOURCEREAD_LAYOUT(dwSrcChipPatchMode));
  163. SEND_P3_DATA(RectanglePosition, 0);
  164. if (dwDownloadTag == Color_Tag)
  165. {
  166. renderData = P3RX_RENDER2D_WIDTH((rNewDest.right - rNewDest.left) & 0xfff )
  167. | P3RX_RENDER2D_HEIGHT((rNewDest.bottom - rNewDest.top ) & 0xfff )
  168. | P3RX_RENDER2D_OPERATION( P3RX_RENDER2D_OPERATION_SYNC_ON_HOST_DATA )
  169. | P3RX_RENDER2D_SPANOPERATION( P3RX_RENDER2D_SPAN_VARIABLE )
  170. | P3RX_RENDER2D_INCREASINGX( __PERMEDIA_ENABLE )
  171. | P3RX_RENDER2D_INCREASINGY( __PERMEDIA_ENABLE );
  172. SEND_P3_DATA(Render2D, renderData);
  173. }
  174. else
  175. {
  176. // Don't use spans for the unpacking scheme, but use the 2D Setup
  177. // unit to do the work of setting up the destination
  178. SEND_P3_DATA(ScissorMinXY, 0);
  179. SEND_P3_DATA(ScissorMaxXY, P3RX_SCISSOR_X_Y(rDest->right, rDest->bottom));
  180. SEND_P3_DATA(ScissorMode, P3RX_SCISSORMODE_USER(__PERMEDIA_ENABLE));
  181. renderData = P3RX_RENDER2D_WIDTH( (rNewDest.right - rNewDest.left) & 0xfff )
  182. | P3RX_RENDER2D_HEIGHT( 0 )
  183. | P3RX_RENDER2D_OPERATION( P3RX_RENDER2D_OPERATION_SYNC_ON_HOST_DATA )
  184. | P3RX_RENDER2D_INCREASINGX( __PERMEDIA_ENABLE )
  185. | P3RX_RENDER2D_INCREASINGY( __PERMEDIA_ENABLE );
  186. SEND_P3_DATA(Render2D, renderData);
  187. SEND_P3_DATA(Count, rDest->bottom - rDest->top );
  188. SEND_P3_DATA(Render, __RENDER_TRAPEZOID_PRIMITIVE | __RENDER_SYNC_ON_HOST_DATA);
  189. }
  190. P3_ENSURE_DX_SPACE(32);
  191. WAIT_FIFO(32);
  192. __try
  193. {
  194. BYTE *pSurfaceData = (BYTE *)pSrcfpVidMem + SrcOffset;
  195. UNALIGNED DWORD *pCurrentLine = (DWORD *)pSurfaceData;
  196. while (ulImageLines-- > 0)
  197. {
  198. DISPDBG((DBGLVL, "Image download lines %d", ulImageLines));
  199. // Initialize the number of DWORDs counter
  200. ulSCDWordsCnt = ulSCWholeDWords;
  201. // Send the texels in DWORDS
  202. while (ulSCDWordsCnt >= BLOCK_SIZE)
  203. {
  204. P3_ENSURE_DX_SPACE(BLOCK_SIZE + 1);
  205. WAIT_FIFO(BLOCK_SIZE + 1);
  206. ADD_FUNNY_DWORD(TAGGED_SIZE | dwDownloadTag);
  207. for (count = BLOCK_SIZE / UNROLL_COUNT; count; count--)
  208. {
  209. DISPDBG((DBGLVL, "Image download count %d", count));
  210. UNROLLED();
  211. }
  212. ulSCDWordsCnt -= BLOCK_SIZE;
  213. }
  214. // Finish off the rest of the whole DWORDs on the scanline
  215. if (ulSCDWordsCnt)
  216. {
  217. P3_ENSURE_DX_SPACE(ulSCDWordsCnt + 1);
  218. WAIT_FIFO(ulSCDWordsCnt + 1);
  219. ADD_FUNNY_DWORD(((ulSCDWordsCnt - 1) << 16) | dwDownloadTag);
  220. for (count = 0; count < ulSCDWordsCnt; count++, pCurrentLine++)
  221. {
  222. ADD_FUNNY_DWORD(*pCurrentLine);
  223. ulTotalImageDWORDs--;
  224. }
  225. }
  226. // Finish off the extra bytes at the end of the scanline
  227. if (ulSCExtraBytes)
  228. {
  229. DWORD dwTemp;
  230. P3_ENSURE_DX_SPACE(1 + 1); // 1 tag + 1 data DWORD
  231. WAIT_FIFO(1 + 1);
  232. ADD_FUNNY_DWORD(dwDownloadTag);
  233. memcpy(&dwTemp, pCurrentLine, ulSCExtraBytes);
  234. ADD_FUNNY_DWORD(dwTemp);
  235. ulTotalImageDWORDs--;
  236. }
  237. pSurfaceData += dwSrcPitch;
  238. pCurrentLine = (DWORD*)pSurfaceData;
  239. }
  240. }
  241. __except(EXCEPTION_EXECUTE_HANDLER)
  242. {
  243. DISPDBG((ERRLVL, "Perm3 caused exception at line %u of file %s",
  244. __LINE__,__FILE__));
  245. // Send enough DWORDs to the GPU to avoid deadlock
  246. for (count = 0; count < ulTotalImageDWORDs; count++)
  247. {
  248. ADD_FUNNY_DWORD(dwDownloadTag);
  249. ADD_FUNNY_DWORD(0); // Dummy pixel data
  250. }
  251. }
  252. P3_ENSURE_DX_SPACE(4);
  253. WAIT_FIFO(4);
  254. SEND_P3_DATA(WaitForCompletion, 0);
  255. SEND_P3_DATA(ScissorMode, __PERMEDIA_DISABLE);
  256. // Put back the values if we changed them.
  257. rSrc->top = rSrctop;
  258. rSrc->left = rSrcleft;
  259. rDest->top = rDesttop;
  260. rDest->left = rDestleft;
  261. P3_DMA_COMMIT_BUFFER();
  262. } // _DD_P3Download
  263. //-----------------------------------------------------------------------------
  264. //
  265. // _DD_P3DownloadDD
  266. //
  267. //
  268. // Function to do an image download to the rectangular region.
  269. // Uses the packed bit on Permedia to do the packing for us.
  270. //
  271. //-----------------------------------------------------------------------------
  272. void
  273. _DD_P3DownloadDD(
  274. P3_THUNKEDDATA* pThisDisplay,
  275. LPDDRAWI_DDRAWSURFACE_LCL pSource,
  276. LPDDRAWI_DDRAWSURFACE_LCL pDest,
  277. P3_SURF_FORMAT* pFormatSource,
  278. P3_SURF_FORMAT* pFormatDest,
  279. RECTL* rSrc,
  280. RECTL* rDest)
  281. {
  282. _DD_P3Download(pThisDisplay,
  283. pSource->lpGbl->fpVidMem,
  284. pDest->lpGbl->fpVidMem,
  285. P3RX_LAYOUT_LINEAR, // src
  286. P3RX_LAYOUT_LINEAR, // dst,
  287. pSource->lpGbl->lPitch,
  288. pDest->lpGbl->lPitch,
  289. DDSurf_GetPixelPitch(pDest),
  290. DDSurf_GetChipPixelSize(pDest),
  291. rSrc,
  292. rDest);
  293. } // _DD_P3DownloadDD
  294. //-----------------------------------------------------------------------------
  295. //
  296. // _DD_P3DownloadDstCh
  297. //
  298. // Function to do an image download to the rectangular region.
  299. // Uses the packed bit on Permedia to do the packing for us.
  300. //
  301. //-----------------------------------------------------------------------------
  302. void
  303. _DD_P3DownloadDstCh(
  304. P3_THUNKEDDATA* pThisDisplay,
  305. LPDDRAWI_DDRAWSURFACE_LCL pSource,
  306. LPDDRAWI_DDRAWSURFACE_LCL pDest,
  307. P3_SURF_FORMAT* pFormatSource,
  308. P3_SURF_FORMAT* pFormatDest,
  309. LPDDHAL_BLTDATA lpBlt,
  310. RECTL* rSrc,
  311. RECTL* rDest)
  312. {
  313. // Work out pixel offset into the framestore of the rendered surface
  314. ULONG ulSCRoundedUpDWords;
  315. ULONG ulSCWholeDWords, ulSCDWordsCnt, ulSCExtraBytes;
  316. ULONG ulTotalImageDWORDs;
  317. DWORD SrcOffset;
  318. ULONG ulImageLines;
  319. ULONG count;
  320. ULONG renderData;
  321. DWORD dwDownloadTag;
  322. int rDestleft, rDesttop, rSrcleft, rSrctop;
  323. RECTL rNewDest;
  324. BOOL bDstKey = FALSE;
  325. P3_DMA_DEFS();
  326. // Because of a bug in RL we sometimes have to fiddle with these values
  327. rSrctop = rSrc->top;
  328. rSrcleft = rSrc->left;
  329. rDesttop = rDest->top;
  330. rDestleft = rDest->left;
  331. // Fix coords origin
  332. if(!_DD_BLT_FixRectlOrigin("_DD_P3DownloadDstCh", rSrc, rDest))
  333. {
  334. // Nothing to be blitted
  335. return;
  336. }
  337. SrcOffset = (DWORD)(rSrc->left << DDSurf_GetChipPixelSize(pDest)) + (rSrc->top * pSource->lpGbl->lPitch);
  338. ulSCRoundedUpDWords = rDest->right - rDest->left;
  339. ulImageLines = rDest->bottom - rDest->top;
  340. P3_DMA_GET_BUFFER();
  341. P3_ENSURE_DX_SPACE(32);
  342. WAIT_FIFO(32);
  343. SEND_P3_DATA(FBWriteBufferAddr0, DDSurf_SurfaceOffsetFromMemoryBase(pThisDisplay, pDest));
  344. SEND_P3_DATA(FBWriteBufferWidth0, DDSurf_GetPixelPitch(pDest));
  345. SEND_P3_DATA(FBWriteBufferOffset0, (rDest->top << 16) | (rDest->left & 0xFFFF));
  346. SEND_P3_DATA(LogicalOpMode, 7);
  347. SEND_P3_DATA(PixelSize, (2 - DDSurf_GetChipPixelSize(pDest)));
  348. if (lpBlt->dwFlags & DDBLT_KEYDESTOVERRIDE)
  349. {
  350. bDstKey = TRUE;
  351. // Dest keying.
  352. // The conventional chroma test is set up to key off the dest - the framebuffer.
  353. SEND_P3_DATA(ChromaTestMode, P3RX_CHROMATESTMODE_ENABLE(__PERMEDIA_ENABLE) |
  354. P3RX_CHROMATESTMODE_SOURCE(P3RX_CHROMATESTMODE_SOURCE_FBDATA) |
  355. P3RX_CHROMATESTMODE_PASSACTION(P3RX_CHROMATESTMODE_ACTION_PASS) |
  356. P3RX_CHROMATESTMODE_FAILACTION(P3RX_CHROMATESTMODE_ACTION_REJECT)
  357. );
  358. SEND_P3_DATA(ChromaLower, lpBlt->bltFX.ddckDestColorkey.dwColorSpaceLowValue);
  359. SEND_P3_DATA(ChromaUpper, lpBlt->bltFX.ddckDestColorkey.dwColorSpaceHighValue);
  360. // The source buffer is the source for the destination color key
  361. SEND_P3_DATA(FBSourceReadBufferAddr, DDSurf_SurfaceOffsetFromMemoryBase(pThisDisplay, pDest));
  362. SEND_P3_DATA(FBSourceReadBufferWidth, DDSurf_GetPixelPitch(pDest));
  363. SEND_P3_DATA(FBSourceReadBufferOffset, (rDest->top << 16) | (rDest->left & 0xFFFF));
  364. // Enable source reads to get the colorkey color
  365. SEND_P3_DATA(FBSourceReadMode, P3RX_FBSOURCEREAD_READENABLE(__PERMEDIA_ENABLE) |
  366. P3RX_FBSOURCEREAD_LAYOUT(P3RX_LAYOUT_LINEAR));
  367. }
  368. else
  369. {
  370. SEND_P3_DATA(FBSourceReadMode, P3RX_FBSOURCEREAD_READENABLE(__PERMEDIA_DISABLE));
  371. }
  372. SEND_P3_DATA(FBWriteMode, P3RX_FBWRITEMODE_WRITEENABLE(__PERMEDIA_ENABLE) |
  373. P3RX_FBWRITEMODE_LAYOUT0(P3RX_LAYOUT_LINEAR));
  374. SEND_P3_DATA(FBDestReadMode, P3RX_FBDESTREAD_READENABLE(__PERMEDIA_DISABLE) |
  375. P3RX_FBDESTREAD_LAYOUT0(P3RX_LAYOUT_LINEAR));
  376. // This dest-colorkey download always needs to send unpacked color data
  377. // because it can't use spans.
  378. SEND_P3_DATA(DownloadTarget, Color_Tag);
  379. switch (DDSurf_GetChipPixelSize(pDest))
  380. {
  381. case __GLINT_8BITPIXEL:
  382. dwDownloadTag = Packed8Pixels_Tag;
  383. break;
  384. case __GLINT_16BITPIXEL:
  385. dwDownloadTag = Packed16Pixels_Tag;
  386. break;
  387. default:
  388. dwDownloadTag = Color_Tag;
  389. break;
  390. }
  391. rNewDest = *rDest;
  392. DISPDBG((DBGLVL, "Image download %dx%d", ulSCRoundedUpDWords, ulImageLines));
  393. if (DDSurf_GetChipPixelSize(pDest) != __GLINT_32BITPIXEL)
  394. {
  395. if (DDSurf_GetChipPixelSize(pDest) == __GLINT_8BITPIXEL)
  396. {
  397. ulSCExtraBytes = ulSCRoundedUpDWords & 3;
  398. ulSCWholeDWords = ulSCRoundedUpDWords >> 2;
  399. ulSCRoundedUpDWords = (ulSCRoundedUpDWords + 3) >> 2;
  400. if (dwDownloadTag != Color_Tag)
  401. {
  402. rNewDest.right = rNewDest.left + (ulSCRoundedUpDWords << 2);
  403. }
  404. }
  405. else
  406. {
  407. ulSCExtraBytes = (ulSCRoundedUpDWords & 1) << 1;
  408. ulSCWholeDWords = ulSCRoundedUpDWords >> 1;
  409. ulSCRoundedUpDWords = (ulSCRoundedUpDWords + 1) >> 1;
  410. if (dwDownloadTag != Color_Tag)
  411. {
  412. rNewDest.right = rNewDest.left + (ulSCRoundedUpDWords << 1);
  413. }
  414. }
  415. }
  416. // Calc the total number of image DWORDs to send to GPU
  417. ulTotalImageDWORDs = ulImageLines * ulSCWholeDWords;
  418. P3_ENSURE_DX_SPACE(32);
  419. WAIT_FIFO(32);
  420. SEND_P3_DATA(RectanglePosition, 0);
  421. // Don't use spans for the unpacking scheme, but use the 2D Setup
  422. // unit to do the work of setting up the destination
  423. SEND_P3_DATA(ScissorMinXY, 0 )
  424. SEND_P3_DATA(ScissorMaxXY,P3RX_SCISSOR_X_Y(rDest->right - rDest->left ,
  425. rDest->bottom - rDest->top ));
  426. SEND_P3_DATA(ScissorMode, P3RX_SCISSORMODE_USER(__PERMEDIA_ENABLE));
  427. renderData = P3RX_RENDER2D_WIDTH( (rNewDest.right - rNewDest.left) & 0xfff )
  428. | P3RX_RENDER2D_HEIGHT( 0 )
  429. | P3RX_RENDER2D_OPERATION( P3RX_RENDER2D_OPERATION_SYNC_ON_HOST_DATA )
  430. | P3RX_RENDER2D_INCREASINGX( __PERMEDIA_ENABLE )
  431. | P3RX_RENDER2D_INCREASINGY( __PERMEDIA_ENABLE )
  432. | P3RX_RENDER2D_FBREADSOURCEENABLE((bDstKey ? __PERMEDIA_ENABLE : __PERMEDIA_DISABLE));
  433. SEND_P3_DATA(Render2D, renderData);
  434. SEND_P3_DATA(Count, rNewDest.bottom - rNewDest.top );
  435. SEND_P3_DATA(Render, P3RX_RENDER_PRIMITIVETYPE(P3RX_RENDER_PRIMITIVETYPE_TRAPEZOID) |
  436. P3RX_RENDER_SYNCONHOSTDATA(__PERMEDIA_ENABLE) |
  437. P3RX_RENDER_FBSOURCEREADENABLE((bDstKey ? __PERMEDIA_ENABLE : __PERMEDIA_DISABLE)));
  438. _try
  439. {
  440. BYTE *pSurfaceData = (BYTE *)pSource->lpGbl->fpVidMem + SrcOffset;
  441. DWORD *pCurrentLine = (DWORD *)pSurfaceData;
  442. while (ulImageLines-- > 0)
  443. {
  444. DISPDBG((DBGLVL, "Image download lines %d", ulImageLines));
  445. // Initialize the number of DWORDs counter
  446. ulSCDWordsCnt = ulSCWholeDWords;
  447. // Send the texels in DWORDS
  448. while (ulSCDWordsCnt >= BLOCK_SIZE)
  449. {
  450. P3_ENSURE_DX_SPACE(BLOCK_SIZE + 1);
  451. WAIT_FIFO(BLOCK_SIZE + 1);
  452. ADD_FUNNY_DWORD(TAGGED_SIZE | dwDownloadTag);
  453. for (count = BLOCK_SIZE / UNROLL_COUNT; count; count--)
  454. {
  455. DISPDBG((DBGLVL, "Image download count %d", count));
  456. UNROLLED();
  457. }
  458. ulSCDWordsCnt -= BLOCK_SIZE;
  459. }
  460. // Finish off the rest of the whole DWORDs on the scanline
  461. if (ulSCDWordsCnt)
  462. {
  463. P3_ENSURE_DX_SPACE(ulSCDWordsCnt + 1);
  464. WAIT_FIFO(ulSCDWordsCnt + 1);
  465. ADD_FUNNY_DWORD(((ulSCDWordsCnt - 1) << 16) | dwDownloadTag);
  466. for (count = 0; count < ulSCDWordsCnt; count++, pCurrentLine++)
  467. {
  468. ADD_FUNNY_DWORD(*pCurrentLine);
  469. ulTotalImageDWORDs--;
  470. }
  471. }
  472. // Finish off the extra bytes at the end of the scanline
  473. if (ulSCExtraBytes)
  474. {
  475. DWORD dwTemp;
  476. P3_ENSURE_DX_SPACE(1 + 1); // 1 tag + 1 data DWORD
  477. WAIT_FIFO(1 + 1);
  478. ADD_FUNNY_DWORD(dwDownloadTag);
  479. memcpy(&dwTemp, pCurrentLine, ulSCExtraBytes);
  480. ADD_FUNNY_DWORD(dwTemp);
  481. ulTotalImageDWORDs--;
  482. }
  483. pSurfaceData += pSource->lpGbl->lPitch;
  484. pCurrentLine = (DWORD*)pSurfaceData;
  485. }
  486. }
  487. __except(EXCEPTION_EXECUTE_HANDLER)
  488. {
  489. DISPDBG((ERRLVL, "Perm3 caused exception at line %u of file %s",
  490. __LINE__,__FILE__));
  491. // Send enough DWORDs to the GPU to avoid deadlock
  492. for (count = 0; count < ulTotalImageDWORDs; count++)
  493. {
  494. ADD_FUNNY_DWORD(dwDownloadTag);
  495. ADD_FUNNY_DWORD(0); // Dummy pixel data
  496. }
  497. }
  498. P3_ENSURE_DX_SPACE(6);
  499. WAIT_FIFO(6);
  500. SEND_P3_DATA(WaitForCompletion, 0);
  501. SEND_P3_DATA(ScissorMode, __PERMEDIA_DISABLE);
  502. SEND_P3_DATA(FBSourceReadMode, __PERMEDIA_DISABLE);
  503. // Put back the values if we changed them.
  504. rSrc->top = rSrctop;
  505. rSrc->left = rSrcleft;
  506. rDest->top = rDesttop;
  507. rDest->left = rDestleft;
  508. P3_DMA_COMMIT_BUFFER();
  509. } //_DD_P3DownloadDstCh