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.

627 lines
20 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * *********************
  4. * * DDraw SAMPLE CODE *
  5. * *********************
  6. *
  7. * Module Name: ddldblt.c
  8. *
  9. * Content: DirectDraw System to Videomemory download routines
  10. *
  11. * Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
  12. * Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
  13. \*****************************************************************************/
  14. #include "precomp.h"
  15. #include "directx.h"
  16. #include "dd.h"
  17. typedef struct tagSHORTDWORD
  18. {
  19. BYTE Red;
  20. BYTE Green;
  21. BYTE Blue;
  22. } SHORTDWORD, *LPSHORTDWORD;
  23. //-----------------------------------------------------------------------------
  24. //
  25. // PermediaPatchedTextureDownload
  26. //
  27. // Do a texture download to the linear region of memory. Access to textures
  28. // is faster if they are stored as "patched". This function downloads a texture
  29. // from system to videomemory and rearranges the data in the patched format.
  30. //
  31. // ppdev---------the PPDev
  32. // pPrivateDest--DDraw private surface data for the dest. surface
  33. // fpSrcVidMem---linear pointer to source systemmemory surface
  34. // lSrcPitch-----pitch of source surface
  35. // rSrc----------source rectangle
  36. // fpDstVidMem---offset in videomemory of dest surface
  37. // lDstPitch-----pitch of dest. surface
  38. // rDest---------destination rectangle
  39. //
  40. //-----------------------------------------------------------------------------
  41. VOID
  42. PermediaPatchedTextureDownload (PPDev ppdev,
  43. PermediaSurfaceData* pPrivateDest,
  44. FLATPTR fpSrcVidMem,
  45. LONG lSrcPitch,
  46. RECTL* rSrc,
  47. FLATPTR fpDstVidMem,
  48. LONG lDstPitch,
  49. RECTL* rDest)
  50. {
  51. PERMEDIA_DEFS(ppdev);
  52. ULONG ulTextureBase = (ULONG)(fpDstVidMem);
  53. LONG lWidth = rDest->right - rDest->left;
  54. LONG lLines = rDest->bottom - rDest->top;
  55. DBG_DD((5,"DDraw:PermediaPatchedTextureDownload:, PrivateDest: 0x%x",
  56. pPrivateDest));
  57. if (NULL == fpSrcVidMem)
  58. {
  59. DBG_DD(( 0, "DDraw:PermediaPatchedTextureDownload"
  60. " unexpected NULL = fpSrcVidMem"));
  61. return;
  62. }
  63. ASSERTDD(CHECK_P2_SURFACEDATA_VALIDITY(pPrivateDest),
  64. "Blt32: Destination Private Data not valid!");
  65. DBG_DD((6," Texture Base: 0x%x DstPitch=0x%x",
  66. ulTextureBase, lDstPitch));
  67. DBG_DD((6," Source Base: 0x%x SourcePitch: 0x%x",
  68. fpSrcVidMem,lSrcPitch));
  69. DBG_DD((6," rSource->left: 0x%x, rSource->right: 0x%x",
  70. rSrc->left,rSrc->right));
  71. DBG_DD((6," rSource->top: 0x%x, rSource->bottom: 0x%x\n",
  72. rSrc->top, rSrc->bottom));
  73. DBG_DD((6," rDest->left: 0x%x, rDest->right: 0x%x",
  74. rDest->left,rDest->right));
  75. DBG_DD((6," rDest->top: 0x%x, rDest->bottom: 0x%x\n",
  76. rDest->top, rDest->bottom));
  77. //
  78. // define some handy variables
  79. //
  80. LONG lPixelSize=pPrivateDest->SurfaceFormat.PixelSize;
  81. RESERVEDMAPTR(18);
  82. SEND_PERMEDIA_DATA( ColorDDAMode, __PERMEDIA_DISABLE);
  83. SEND_PERMEDIA_DATA( AlphaBlendMode, __PERMEDIA_DISABLE);
  84. SEND_PERMEDIA_DATA( Window, PM_WINDOW_DISABLELBUPDATE(__PERMEDIA_ENABLE));
  85. SEND_PERMEDIA_DATA( dXDom, 0x0);
  86. SEND_PERMEDIA_DATA( dXSub, 0x0);
  87. SEND_PERMEDIA_DATA( FBReadPixel, pPrivateDest->SurfaceFormat.FBReadPixel);
  88. switch (lPixelSize)
  89. {
  90. case __PERMEDIA_4BITPIXEL:
  91. // There are half as many 8-bit, 4-bit texels
  92. DBG_DD((6," Texture is 4-Bit indexed"));
  93. lWidth >>= 1;
  94. SEND_PERMEDIA_DATA(DitherMode, 0);
  95. break;
  96. case __PERMEDIA_8BITPIXEL:
  97. DBG_DD((6," Texture is 8-Bit indexed"));
  98. SEND_PERMEDIA_DATA(DitherMode, 0);
  99. break;
  100. default:
  101. if (lPixelSize != __PERMEDIA_24BITPIXEL) {
  102. DBG_DD((6," Texture is BGR"));
  103. ulTextureBase >>= lPixelSize;
  104. } else {
  105. DBG_DD((6," Texture is 24-Bit BGR"));
  106. ulTextureBase /= 3;
  107. }
  108. // Setup the Dither unit
  109. SEND_PERMEDIA_DATA(DitherMode,(
  110. (INV_COLOR_MODE << PM_DITHERMODE_COLORORDER)|
  111. (1 << PM_DITHERMODE_ENABLE) |
  112. (pPrivateDest->SurfaceFormat.Format <<
  113. PM_DITHERMODE_COLORFORMAT) |
  114. (pPrivateDest->SurfaceFormat.FormatExtension <<
  115. PM_DITHERMODE_COLORFORMATEXTENSION) ));
  116. break;
  117. }
  118. DBG_DD((6," Partial Products: 0x%x", pPrivateDest->ulPackedPP));
  119. DBG_DD((6," Texture Width: 0x%x, Downloaded as: 0x%x",
  120. (rDest->right - rDest->left),lWidth));
  121. DBG_DD((6," Texture Height: 0x%x", rDest->bottom - rDest->top));
  122. DBG_DD((6," PixelSize: 0x%x", pPrivateDest->SurfaceFormat.PixelSize));
  123. DBG_DD((6," Format: 0x%x", pPrivateDest->SurfaceFormat.Format));
  124. DBG_DD((6," Format Extension: 0x%x",
  125. pPrivateDest->SurfaceFormat.FormatExtension));
  126. // Downloading a texture, disable texture colour mode.
  127. SEND_PERMEDIA_DATA(TextureColorMode, (0 << PM_TEXCOLORMODE_ENABLE));
  128. SEND_PERMEDIA_DATA(LogicalOpMode, 0);
  129. //
  130. // all textures get by default marked as P2_CANPATCH,
  131. // except 4 bit paletted textures
  132. //
  133. if (pPrivateDest->dwFlags & P2_CANPATCH) {
  134. // Mark the texture as being patched.
  135. pPrivateDest->dwFlags |= P2_ISPATCHED;
  136. // set up partial product and patch
  137. SEND_PERMEDIA_DATA(FBReadMode,
  138. PM_FBREADMODE_PARTIAL(pPrivateDest->ulPackedPP) |
  139. PM_FBREADMODE_PATCHENABLE(__PERMEDIA_ENABLE) |
  140. PM_FBREADMODE_PATCHMODE(__PERMEDIA_SUBPATCH) );
  141. } else {
  142. // This texture isn't patched
  143. pPrivateDest->dwFlags &= ~P2_ISPATCHED;
  144. // Load up the partial products of the texture, don't use patching
  145. SEND_PERMEDIA_DATA(FBReadMode,
  146. PM_FBREADMODE_PARTIAL(pPrivateDest->ulPackedPP));
  147. }
  148. SEND_PERMEDIA_DATA(FBPixelOffset, 0);
  149. SEND_PERMEDIA_DATA(FBWindowBase, ulTextureBase);
  150. // Use left to right and top to bottom
  151. if (lWidth == 2048)
  152. {
  153. // special case for 2048-wide textures because of the precision
  154. // of the StartXSub register
  155. SEND_PERMEDIA_DATA(StartXDom, INTtoFIXED(-1));
  156. SEND_PERMEDIA_DATA(StartXSub, INTtoFIXED(lWidth-1));
  157. }
  158. else
  159. {
  160. SEND_PERMEDIA_DATA(StartXDom, INTtoFIXED(0));
  161. SEND_PERMEDIA_DATA(StartXSub, INTtoFIXED(lWidth));
  162. }
  163. SEND_PERMEDIA_DATA(StartY, INTtoFIXED(0));
  164. SEND_PERMEDIA_DATA(dY, INTtoFIXED(1));
  165. SEND_PERMEDIA_DATA(Count, (lLines));
  166. SEND_PERMEDIA_DATA(Render, __RENDER_TRAPEZOID_PRIMITIVE |
  167. __RENDER_SYNC_ON_HOST_DATA);
  168. COMMITDMAPTR();
  169. switch (lPixelSize) {
  170. case __PERMEDIA_4BITPIXEL:
  171. case __PERMEDIA_8BITPIXEL:
  172. {
  173. BYTE* pTextureData = (BYTE*)fpSrcVidMem;
  174. //
  175. // download texture data line by line
  176. //
  177. while(lLines-- > 0)
  178. {
  179. LONG lWords=lWidth;
  180. BYTE *pData=pTextureData;
  181. RESERVEDMAWORDS(lWords+1);
  182. LD_INPUT_FIFO_DATA( __Permedia2TagColor |
  183. ((lWords-1) << 16));
  184. while (lWords--)
  185. {
  186. LD_INPUT_FIFO_DATA(*pData++);
  187. }
  188. COMMITDMAPTR();
  189. //
  190. // force flush only every couple of lines
  191. //
  192. if ((lLines & 3)==0)
  193. {
  194. FLUSHDMA();
  195. }
  196. pTextureData += lSrcPitch;
  197. }
  198. }
  199. break;
  200. case __PERMEDIA_16BITPIXEL:
  201. {
  202. BYTE* pTextureData = (BYTE*)fpSrcVidMem;
  203. if (pPrivateDest->SurfaceFormat.RedMask == 0x7c00)
  204. {
  205. DBG_DD((6," Texture is BGR, 16 bit 5:5:5:1"));
  206. //
  207. // download texture data line by line
  208. //
  209. while(lLines-- > 0)
  210. {
  211. LONG lWords=lWidth;
  212. WORD *pData=(WORD*)pTextureData;
  213. RESERVEDMAWORDS(lWords+1);
  214. LD_INPUT_FIFO_DATA( __Permedia2TagColor |
  215. ((lWords-1) << 16));
  216. while (lWords--)
  217. {
  218. LD_INPUT_FIFO_DATA(FORMAT_5551_32BIT((DWORD)*pData));
  219. pData++;
  220. }
  221. COMMITDMAPTR();
  222. //
  223. // force flush only every couple of lines
  224. //
  225. if ((lLines & 3)==0)
  226. {
  227. FLUSHDMA();
  228. }
  229. pTextureData += lSrcPitch;
  230. }
  231. }
  232. else if(pPrivateDest->SurfaceFormat.RedMask == 0xF00)
  233. {
  234. DBG_DD((6," Texture is BGR, 16 bit 4:4:4:4"));
  235. //
  236. // download texture data line by line
  237. //
  238. while(lLines-- > 0)
  239. {
  240. LONG lWords=lWidth;
  241. WORD *pData=(WORD*)pTextureData;
  242. RESERVEDMAWORDS(lWords+1);
  243. LD_INPUT_FIFO_DATA( __Permedia2TagColor |
  244. ((lWords-1) << 16));
  245. while (lWords--)
  246. {
  247. LD_INPUT_FIFO_DATA(FORMAT_4444_32BIT((DWORD)*pData));
  248. pData++;
  249. }
  250. COMMITDMAPTR();
  251. //
  252. // force flush only every couple of lines
  253. //
  254. if ((lLines & 3)==0)
  255. {
  256. FLUSHDMA();
  257. }
  258. pTextureData += lSrcPitch;
  259. }
  260. }
  261. else
  262. {
  263. DBG_DD((6," Texture is BGR, 16 bit 5:6:5"));
  264. //
  265. // download texture data line by line
  266. //
  267. while(lLines-- > 0)
  268. {
  269. LONG lWords=lWidth;
  270. WORD *pData=(WORD*)pTextureData;
  271. RESERVEDMAWORDS(lWords+1);
  272. LD_INPUT_FIFO_DATA( __Permedia2TagColor |
  273. ((lWords-1) << 16));
  274. while (lWords--)
  275. {
  276. LD_INPUT_FIFO_DATA(FORMAT_565_32BIT((DWORD)*pData));
  277. pData++;
  278. }
  279. COMMITDMAPTR();
  280. //
  281. // force flush only every couple of lines
  282. //
  283. if ((lLines & 3)==0)
  284. {
  285. FLUSHDMA();
  286. }
  287. pTextureData += lSrcPitch;
  288. }
  289. }
  290. }
  291. break;
  292. case __PERMEDIA_24BITPIXEL:
  293. case __PERMEDIA_32BITPIXEL:
  294. {
  295. BYTE* pTextureData = (BYTE*)fpSrcVidMem;
  296. //
  297. // download texture data line by line
  298. //
  299. while(lLines-- > 0)
  300. {
  301. LONG lWords=lWidth;
  302. ULONG *pData=(ULONG*)pTextureData;
  303. RESERVEDMAWORDS(lWords+1);
  304. LD_INPUT_FIFO_DATA( __Permedia2TagColor |
  305. ((lWords-1) << 16));
  306. while (lWords--)
  307. {
  308. LD_INPUT_FIFO_DATA(*pData++);
  309. }
  310. COMMITDMAPTR();
  311. //
  312. // force flush only every couple of lines
  313. //
  314. if ((lLines & 3)==0)
  315. {
  316. FLUSHDMA();
  317. }
  318. pTextureData += lSrcPitch;
  319. }
  320. }
  321. break;
  322. }
  323. RESERVEDMAPTR(2);
  324. SEND_PERMEDIA_DATA(DitherMode, 0);
  325. SEND_PERMEDIA_DATA(WaitForCompletion, 0);
  326. COMMITDMAPTR();
  327. } // PermediaPatchedTextureDownload
  328. //-----------------------------------------------------------------------------
  329. //
  330. // PermediaPackedDownload
  331. //
  332. // Function to do a system to video memory blt.
  333. // Uses the packed bit on Permedia to do the packing for us. Needs
  334. // to setup the offset bit for alignment and doesn't need to adjust
  335. // the partial products. The calling function guarantees that the
  336. // source and destination rects have the same size.
  337. //
  338. //
  339. // ppdev----------the PPDev
  340. // pPrivateDst----Permedia Surface data for destination
  341. // lpSourceSurf---DDraw LCL for source surface
  342. // rSrc-----------source rect
  343. // lpDestSurf-----DDraw LCL for destination surface
  344. // rDest----------dest rect
  345. //
  346. //-----------------------------------------------------------------------------
  347. VOID
  348. PermediaPackedDownload(PPDev ppdev,
  349. PermediaSurfaceData* pPrivateDst,
  350. LPDDRAWI_DDRAWSURFACE_LCL lpSourceSurf,
  351. RECTL* rSrc,
  352. LPDDRAWI_DDRAWSURFACE_LCL lpDestSurf,
  353. RECTL* rDst)
  354. {
  355. PERMEDIA_DEFS(ppdev);
  356. LONG lDstOffset; // dest offset in packed coordinates
  357. LONG lSrcOffset; // source offset in buffer in bytes
  358. LONG lDstLeft, lDstRight; // left and right dst in packed coordiantes
  359. LONG lSrcLeft, lSrcRight; // left and right src in packed coordiantes
  360. LONG lPackedWidth; // packed width to download
  361. LONG lPixelMask; // mask for pixels per packed DWORD
  362. LONG lOffset; // relative offset between src and dest
  363. LONG lPixelShift; // handy helper var which contains pixel
  364. // shift from packed to surface format
  365. LONG lPixelSize; // just a helper
  366. LONG lExtraDword; // chip needs extra dummy
  367. // DWORD passed at end of line
  368. DBG_DD((5,"DDraw:PermediaPackedDownload, PrivateDst: 0x%x",
  369. pPrivateDst));
  370. ASSERTDD(CHECK_P2_SURFACEDATA_VALIDITY(pPrivateDst),
  371. "Blt: Destination Private Data not valid!");
  372. ASSERTDD((rSrc->right-rSrc->left)==(rDst->right-rDst->left),
  373. "PermediaPackedDownload: src and dest rect width not equal");
  374. ASSERTDD((rSrc->bottom-rSrc->top)==(rDst->bottom-rDst->top),
  375. "PermediaPackedDownload: src and dest rect height not equal");
  376. // get a handy variable for pixel shifts, masks and size
  377. lPixelSize=pPrivateDst->SurfaceFormat.PixelSize;
  378. lPixelMask=pPrivateDst->SurfaceFormat.PixelMask;
  379. lPixelShift=pPrivateDst->SurfaceFormat.PixelShift;
  380. // offset in dst buffer adjusted to packed format
  381. lDstOffset =(LONG)((UINT_PTR)(lpDestSurf->lpGbl->fpVidMem) >> lPixelShift);
  382. // calculate offset in source buffer adjusted to packed format
  383. lSrcOffset = ((rSrc->left & ~lPixelMask) << lPixelShift) +
  384. (rSrc->top * lpSourceSurf->lpGbl->lPitch);
  385. // Calculate the relative offset within the dword packed dimensions
  386. lOffset = ((rDst->left & lPixelMask) -
  387. (rSrc->left & lPixelMask)) & 0x7;
  388. // set up the left and right end of the unpacked source data
  389. lDstLeft = rDst->left;
  390. lDstRight = rDst->right;
  391. // precalc packed width for 32 bit case
  392. lPackedWidth = lDstRight-lDstLeft;
  393. lExtraDword=0;
  394. if (lPixelSize != __PERMEDIA_32BITPIXEL)
  395. {
  396. // we need to check both source and dest
  397. // if they have different alignments
  398. LONG lSrcLeft2 = rSrc->left;
  399. LONG lSrcRight2 = rSrc->right;
  400. // Set up the relative offset to allow us to download packed word
  401. // and byte aligned data.
  402. if (lPixelSize == __PERMEDIA_4BITPIXEL)
  403. {
  404. lDstLeft >>= 3;
  405. lSrcLeft2 >>= 3;
  406. lDstRight = (lDstRight + 7) >> 3;
  407. lSrcRight2 = (lSrcRight2 + 7) >> 3;
  408. }
  409. else
  410. if (lPixelSize == __PERMEDIA_8BITPIXEL)
  411. {
  412. lDstLeft >>= 2;
  413. lSrcLeft2 >>= 2;
  414. lDstRight = (lDstRight + 3) >> 2;
  415. lSrcRight2 = (lSrcRight2 + 3) >> 2;
  416. }
  417. else
  418. {
  419. lDstLeft >>= 1;
  420. lSrcLeft2 >>= 1;
  421. lDstRight = (lDstRight + 1) >> 1;
  422. lSrcRight2 = (lSrcRight2 + 1) >> 1;
  423. }
  424. if ((lSrcRight2-lSrcLeft2) < (lDstRight-lDstLeft))
  425. {
  426. lExtraDword=1;
  427. lPackedWidth = lDstRight-lDstLeft;
  428. } else
  429. {
  430. lPackedWidth = lSrcRight2-lSrcLeft2;
  431. }
  432. }
  433. RESERVEDMAPTR(12);
  434. SEND_PERMEDIA_DATA(FBReadPixel, pPrivateDst->SurfaceFormat.FBReadPixel);
  435. // No logical ops in SYS->VIDMEM Blits
  436. SEND_PERMEDIA_DATA(LogicalOpMode, 0);
  437. // Load up the partial products of image
  438. SEND_PERMEDIA_DATA(FBReadMode, (pPrivateDst->ulPackedPP) |
  439. PM_FBREADMODE_PACKEDDATA(__PERMEDIA_ENABLE)|
  440. PM_FBREADMODE_RELATIVEOFFSET(lOffset) );
  441. SEND_PERMEDIA_DATA(FBPixelOffset, 0);
  442. SEND_PERMEDIA_DATA(FBWindowBase, lDstOffset);
  443. // Use left to right and top to bottom
  444. SEND_PERMEDIA_DATA(StartXDom, INTtoFIXED(lDstLeft));
  445. SEND_PERMEDIA_DATA(StartXSub, INTtoFIXED(lDstLeft+lPackedWidth));
  446. SEND_PERMEDIA_DATA(PackedDataLimits,PM_PACKEDDATALIMITS_OFFSET(lOffset) |
  447. (rDst->left << 16) |
  448. rDst->right);
  449. SEND_PERMEDIA_DATA(StartY, INTtoFIXED(rDst->top));
  450. SEND_PERMEDIA_DATA(dY, INTtoFIXED(1));
  451. SEND_PERMEDIA_DATA(Count, (rDst->bottom - rDst->top));
  452. SEND_PERMEDIA_DATA(Render, __RENDER_TRAPEZOID_PRIMITIVE |
  453. __RENDER_SYNC_ON_HOST_DATA);
  454. COMMITDMAPTR();
  455. //
  456. // introduce some more handy pointers and LONGs
  457. //
  458. BYTE *pSurfaceData = (BYTE *)lpSourceSurf->lpGbl->fpVidMem + lSrcOffset;
  459. LONG lPitch =lpSourceSurf->lpGbl->lPitch;
  460. LONG lHeight=rDst->bottom - rDst->top;
  461. //
  462. // pump the whole thing in one huge block
  463. // if the pitch and linewidth are the same and no extra treatment
  464. // for the buffer end is necessary
  465. //
  466. if ((lExtraDword==0) &&
  467. (lPackedWidth*(LONG)sizeof(ULONG))==lPitch)
  468. {
  469. vBlockLoadInputFifo( pP2dma,
  470. __Permedia2TagColor,
  471. (ULONG*)pSurfaceData,
  472. lPackedWidth*lHeight);
  473. } else
  474. {
  475. //
  476. // lExtraDword is zero or 1, depends if we have to do a special
  477. // treatment after this while block
  478. //
  479. while (lHeight>lExtraDword)
  480. {
  481. LONG lWords=lPackedWidth;
  482. ULONG *pImage=(ULONG*)pSurfaceData;
  483. RESERVEDMAWORDS(lWords+1);
  484. LD_INPUT_FIFO_DATA( __Permedia2TagColor |
  485. ((lWords-1) << 16));
  486. while (lWords--)
  487. {
  488. LD_INPUT_FIFO_DATA(*pImage++);
  489. }
  490. COMMITDMAPTR();
  491. //
  492. // force flush only every couple of lines
  493. //
  494. if ((lHeight & 3)==0)
  495. {
  496. FLUSHDMA();
  497. }
  498. pSurfaceData += lPitch;
  499. lHeight--;
  500. }
  501. //
  502. // treat last line separately, because we could read over the
  503. // end of buffer here if the source and dest rects are aligned
  504. // differently. lHeight will only be one here if lExtraDword==1
  505. //
  506. if (lHeight==1)
  507. {
  508. LONG lWords=lPackedWidth-1;
  509. ULONG *pImage=(ULONG*)pSurfaceData;
  510. RESERVEDMAWORDS(lWords+1);
  511. LD_INPUT_FIFO_DATA( __Permedia2TagColor |
  512. ((lWords-1) << 16));
  513. while (lWords--)
  514. {
  515. LD_INPUT_FIFO_DATA(*pImage++);
  516. }
  517. COMMITDMAPTR();
  518. //
  519. // send extra dummy DWORD
  520. //
  521. RESERVEDMAPTR(1);
  522. SEND_PERMEDIA_DATA( Color, 0);
  523. COMMITDMAPTR();
  524. }
  525. FLUSHDMA();
  526. }
  527. } // PermediaPackedDownload