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.

778 lines
27 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * *******************
  4. * * GDI SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: download.c
  8. *
  9. * Contains the upload and 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 "gdi.h"
  16. //-----------------------------------------------------------------------------
  17. //
  18. // VOID vDownloadNative(GFNPB* ppb)
  19. //
  20. // Does a download of a native surface for a list of rectangles.
  21. // Note: this download takes the advantage of Permedia 2 packed data read.
  22. // Because of the permedia 2 hardware limitation, we can only use the
  23. // packedData download when the logic OP is SRC_COPY or the destination
  24. // is aligned to the packed data being downloaded. This will typically be
  25. // when the surface is 32 bpp. Otherwise, we just do the regular download
  26. //
  27. // Argumentes needed from function block (GFNPB)
  28. // ppdev-------PPDev
  29. // psurfSrc----Source surface
  30. // psurfDst----Destination surface
  31. // pRects------Pointer to a list of rectangles information which needed to be
  32. // filled
  33. // lNumRects---Number of rectangles to fill
  34. // prclDst-----Points to a RECTL structure that defines the rectangular area
  35. // to be modified
  36. // pptlSrc-----Original unclipped source point
  37. //
  38. //-----------------------------------------------------------------------------
  39. VOID
  40. vDownloadNative(GFNPB* ppb)
  41. {
  42. PDev* ppdev = ppb->ppdev;
  43. Surf* psurfDst = ppb->psurfDst;
  44. SURFOBJ* pSrcSurface = ppb->psoSrc;
  45. RECTL* pRects = ppb->pRects;
  46. RECTL* prclDst = ppb->prclDst;
  47. POINTL* pptlSrc = ppb->pptlSrc;
  48. BOOL bEnablePacked;
  49. DWORD dwRenderBits = __RENDER_TRAPEZOID_PRIMITIVE
  50. | __RENDER_SYNC_ON_HOST_DATA;
  51. LONG lNumRects = ppb->lNumRects;
  52. LONG lSrcStride;
  53. LONG lXOffset = pptlSrc->x - prclDst->left;
  54. LONG lYOffset = pptlSrc->y - prclDst->top;
  55. ULONG ulLogicOP = ulRop2ToLogicop(ppb->ulRop4 & 0xf);
  56. ULONG* pBuffer;
  57. //
  58. // Note: Due to the hardware limitation, we can take the advantage of
  59. // Permedia 2 PackedData copy only when the logic OP is SRC_COPY, or
  60. // the destination is aligned to the packed data being downloaded.
  61. // This will typically be when the surface is 32 bpp.
  62. //
  63. if ( (ulLogicOP == K_LOGICOP_COPY)
  64. ||(pSrcSurface->iBitmapFormat == BMF_32BPP) )
  65. {
  66. bEnablePacked = TRUE;
  67. }
  68. else
  69. {
  70. bEnablePacked = FALSE;
  71. }
  72. DBG_GDI((6, "vDownloadNative called, logicop=%d", ulLogicOP));
  73. DBG_GDI((6, "source SURFOBJ=0x%x", pSrcSurface));
  74. DBG_GDI((6, "pptlSrc(x, y)(%d, %d) logicop=%d",
  75. pptlSrc->x, pptlSrc->y, ulLogicOP));
  76. DBG_GDI((6, "prclDst(left, right, top, bottom)(%d, %d, %d, %d)",
  77. prclDst->left, prclDst->right, prclDst->top, prclDst->bottom));
  78. DBG_GDI((6, "lXOffset=%d, lYOffset=%d", lXOffset, lYOffset));
  79. vCheckGdiContext(ppdev);
  80. InputBufferReserve(ppdev, 10, &pBuffer);
  81. //
  82. // Setup loop invariant state
  83. //
  84. pBuffer[0] = __Permedia2TagLogicalOpMode;
  85. pBuffer[1] = P2_ENABLED_LOGICALOP(ulLogicOP);
  86. pBuffer[2] = __Permedia2TagFBWindowBase;
  87. pBuffer[3] = psurfDst->ulPixOffset;
  88. pBuffer[4] = __Permedia2TagFBPixelOffset;
  89. pBuffer[5] = 0;
  90. pBuffer[6] = __Permedia2TagFBReadPixel;
  91. pBuffer[7] = ppdev->cPelSize;
  92. pBuffer[8] = __Permedia2TagdY;
  93. pBuffer[9] = INTtoFIXED(1);
  94. pBuffer += 10;
  95. InputBufferCommit(ppdev, pBuffer);
  96. //
  97. // Loop all the rectangles to render
  98. //
  99. while( lNumRects-- )
  100. {
  101. ULONG ulMask = ppdev->dwBppMask;
  102. DWORD dwReadMode = PM_FBREADMODE_PARTIAL(psurfDst->ulPackedPP)
  103. | LogicopReadDest[ulLogicOP];
  104. ULONG ulStartXDom;
  105. ULONG ulStartXSub;
  106. LONG lSrcLeft = lXOffset + pRects->left;
  107. //
  108. // Calculate the 3 bit 2's compliment shift that is required to align
  109. // the source pixels with the destination. This relative offset can be
  110. // used to shift the downloaded data to the 32 bit destination alignment
  111. // that packing requires. This enables you to read DWORD aligned data
  112. // on the host despite the data not being aligned correctly for the
  113. // packing.
  114. //
  115. ULONG ulOffset = ( (pRects->left & ulMask)
  116. - (lSrcLeft & ulMask)) & 0x7;
  117. DBG_GDI((6, "ulOffset = 0x%x", ulOffset));
  118. DBG_GDI((6, "pRects(left, right, top, bottom)(%d, %d, %d, %d)",
  119. pRects->left, pRects->right, pRects->top, pRects->bottom));
  120. if ( (bEnablePacked == FALSE) && (ulOffset == 0) )
  121. {
  122. //
  123. // As long as the source and dest are aligned, then we can still use
  124. // the packed data copy, even with logic OPs
  125. //
  126. DBG_GDI((6, "Turn packed data on when src and dst are aligned"));
  127. bEnablePacked = TRUE;
  128. }
  129. ULONG ulWidth = pRects->right - pRects->left;
  130. ULONG ulHeight = pRects->bottom - pRects->top;
  131. ULONG ulDstLeft;
  132. ULONG ulDstRight;
  133. ULONG ulDstWidth;
  134. LONG lSrcRight;
  135. ULONG ulSrcWidth;
  136. ULONG ulExtra;
  137. if ( bEnablePacked == TRUE )
  138. {
  139. ULONG ulShift = ppdev->bBppShift;
  140. ulDstLeft = pRects->left >> ulShift;
  141. ulDstRight = (pRects->right + ulMask) >> ulShift;
  142. ulDstWidth = ulDstRight - ulDstLeft;
  143. lSrcRight = (lSrcLeft + ulWidth + ulMask) >> ulShift;
  144. lSrcLeft >>= ulShift;
  145. ulSrcWidth = (ULONG)(lSrcRight - lSrcLeft);
  146. //
  147. // We need to convert from pixel coordinates to ULONG coordinates.
  148. // Also, we need to set the destination width to the greater of the
  149. // source width or destination width. If destination width is
  150. // greater then the source width, we need to remember this so that
  151. // we can download an additional dummy value without reading past
  152. // the end of the source data (which could result in an access
  153. // fault).
  154. //
  155. if( ulDstWidth <= ulSrcWidth )
  156. {
  157. ulExtra = 0;
  158. ulWidth = ulSrcWidth;
  159. }
  160. else
  161. {
  162. ulWidth = ulDstWidth;
  163. ulExtra = 1;
  164. }
  165. dwReadMode |= (PM_FBREADMODE_RELATIVEOFFSET(ulOffset)
  166. | PM_FBREADMODE_READSOURCE(__PERMEDIA_DISABLE)
  167. | PM_FBREADMODE_PACKEDDATA(__PERMEDIA_ENABLE) );
  168. ulStartXDom = INTtoFIXED(ulDstLeft);
  169. ulStartXSub = INTtoFIXED(ulDstLeft + ulWidth);
  170. }
  171. else
  172. {
  173. dwReadMode |= PM_FBREADMODE_RELATIVEOFFSET(0);
  174. ulStartXDom = INTtoFIXED(pRects->left);
  175. ulStartXSub = INTtoFIXED(pRects->right);
  176. }
  177. InputBufferReserve(ppdev, 14, &pBuffer);
  178. pBuffer[0] = __Permedia2TagFBReadMode;
  179. pBuffer[1] = dwReadMode;
  180. pBuffer[2] = __Permedia2TagStartXDom;
  181. pBuffer[3] = ulStartXDom;
  182. pBuffer[4] = __Permedia2TagStartXSub;
  183. pBuffer[5] = ulStartXSub;
  184. //
  185. // Test result shows that it won't hurt if we are doing non-packed
  186. // download and setting this register. If we move this settings
  187. // inside the "bEnablePacked == TRUE" case, then we need the extra
  188. // InputBufferReserve/InputBufferCommit for packed data download
  189. // which will hurt performance
  190. //
  191. pBuffer[6] = __Permedia2TagPackedDataLimits;
  192. pBuffer[7] = PM_PACKEDDATALIMITS_OFFSET(ulOffset)
  193. |(INTtoFIXED(pRects->left)
  194. | pRects->right);
  195. pBuffer[8] = __Permedia2TagStartY;
  196. pBuffer[9] = INTtoFIXED(pRects->top);
  197. pBuffer[10] = __Permedia2TagCount;
  198. pBuffer[11] = ulHeight;
  199. pBuffer[12] = __Permedia2TagRender;
  200. pBuffer[13] = dwRenderBits;
  201. pBuffer += 14;
  202. InputBufferCommit(ppdev, pBuffer);
  203. if ( bEnablePacked == TRUE )
  204. {
  205. ULONG* pulSrcStart = (ULONG*)(pSrcSurface->pvScan0);
  206. lSrcStride = pSrcSurface->lDelta >> 2;
  207. ULONG* pulSrc = (ULONG*)(pulSrcStart
  208. + ((lYOffset + pRects->top) * lSrcStride)
  209. + lSrcLeft);
  210. ULONG* pulData = pulSrc;
  211. while ( ulHeight-- )
  212. {
  213. ULONG ulTemp = ulSrcWidth;
  214. ULONG* pulSrcTemp = pulData;
  215. InputBufferReserve(ppdev, ulWidth + 1, &pBuffer);
  216. pBuffer[0] = __Permedia2TagColor | ((ulWidth - 1) << 16);
  217. pBuffer +=1;
  218. while ( ulTemp-- )
  219. {
  220. *pBuffer++ = *pulSrcTemp++;
  221. }
  222. if ( ulExtra )
  223. {
  224. *pBuffer++ = 0;
  225. }
  226. InputBufferCommit(ppdev, pBuffer);
  227. pulData += lSrcStride;
  228. }// while ( ulHeight-- )
  229. }// PackedEnabled case
  230. else if ( pSrcSurface->iBitmapFormat == BMF_16BPP )
  231. {
  232. USHORT* psSrcStart = (USHORT*)(pSrcSurface->pvScan0);
  233. lSrcStride = pSrcSurface->lDelta >> 1;
  234. USHORT* psSrc = (USHORT*)(psSrcStart
  235. + ((lYOffset + pRects->top) * lSrcStride)
  236. + lSrcLeft);
  237. USHORT* psData = psSrc;
  238. while ( ulHeight-- )
  239. {
  240. ULONG ulTemp = ulWidth;
  241. USHORT* psSrcTemp = psData;
  242. InputBufferReserve(ppdev, ulWidth + 1, &pBuffer);
  243. pBuffer[0] = __Permedia2TagColor | ((ulWidth - 1) << 16);
  244. pBuffer +=1;
  245. while ( ulTemp-- )
  246. {
  247. *pBuffer++ = (ULONG)(*psSrcTemp++);
  248. }
  249. InputBufferCommit(ppdev, pBuffer);
  250. psData += lSrcStride;
  251. }// while ( ulHeight-- )
  252. }// 16 bpp non-packed case
  253. else if ( pSrcSurface->iBitmapFormat == BMF_8BPP )
  254. {
  255. BYTE* pcSrcStart = (BYTE*)(pSrcSurface->pvScan0);
  256. lSrcStride = pSrcSurface->lDelta;
  257. BYTE* pcSrc = (BYTE*)(pcSrcStart
  258. + ((lYOffset + pRects->top) * lSrcStride)
  259. + lSrcLeft);
  260. BYTE* pcData = pcSrc;
  261. while ( ulHeight-- )
  262. {
  263. ULONG ulTemp = ulWidth;
  264. BYTE* pcSrcTemp = pcData;
  265. InputBufferReserve(ppdev, ulWidth + 1, &pBuffer);
  266. pBuffer[0] = __Permedia2TagColor | ((ulWidth - 1) << 16);
  267. pBuffer +=1;
  268. while ( ulTemp-- )
  269. {
  270. *pBuffer++ = (ULONG)(*pcSrcTemp++);
  271. }
  272. InputBufferCommit(ppdev, pBuffer);
  273. pcData += lSrcStride;
  274. }// while ( ulHeight-- )
  275. }// 8 bpp non-packed case
  276. else
  277. {
  278. //
  279. // Since we have a check in DrvBitBlt
  280. // if(psoSrc->iBitmapFormat == pb.ppdev->iBitmapFormat) before we
  281. // allow it to call this function, so this ASSERT should never
  282. // be hit. It will if we implement 24 bpp download late.
  283. //
  284. ASSERTDD(0, "we don't handle it for now");
  285. }
  286. //
  287. // Next rectangle
  288. //
  289. pRects++;
  290. }// while( lNumRects-- )
  291. }// vDownloadNative()
  292. //-----------------------------------------------------------------------------
  293. //
  294. // VOID vDowload4Bpp(GFNPB* ppb)
  295. //
  296. // Does a download of a 4bpp surface for a list of rectangles.
  297. //
  298. // Argumentes needed from function block (GFNPB)
  299. // ppdev-------PPDev
  300. // psurfSrc----Source surface
  301. // psurfDst----Destination surface
  302. // pRects------Pointer to a list of rectangles information which needed to be
  303. // filled
  304. // lNumRects---Number of rectangles to fill
  305. // prclDst-----Points to a RECTL structure that defines the rectangular area
  306. // to be modified
  307. // pptlSrc-----Original unclipped source point
  308. //
  309. //-----------------------------------------------------------------------------
  310. ULONG gDownload4BppEnabled = 1;
  311. #if 0
  312. VOID
  313. vDownload4Bpp(GFNPB* ppb)
  314. {
  315. PDev* ppdev = ppb->ppdev;
  316. Surf* psurfDst = ppb->psurfDst;
  317. RECTL* prcl = ppb->pRects;
  318. LONG c = ppb->lNumRects;
  319. RECTL* prclDst = ppb->prclDst;
  320. POINTL* pptlSrc = ppb->pptlSrc;
  321. DWORD dwRenderBits = __RENDER_TRAPEZOID_PRIMITIVE | __RENDER_SYNC_ON_HOST_DATA;
  322. BYTE* pbSrcStart = (BYTE *) ppb->psoSrc->pvScan0;
  323. LONG lSrcStride = ppb->psoSrc->lDelta;
  324. ULONG ulOffset = ((pptlSrc->x & 1) -
  325. (prclDst->left & ppdev->dwBppMask)) & 0x7;
  326. if(!gDownload4BppEnabled) return;
  327. PERMEDIA_DECL_VARS;
  328. PERMEDIA_DECL_INIT;
  329. VALIDATE_GDI_CONTEXT;
  330. // P2_CHECK_STATE;
  331. P2_DEFAULT_FB_DEPTH;
  332. // setup loop invariant state
  333. WAIT_INPUT_FIFO(4);
  334. SEND_PERMEDIA_DATA(LogicalOpMode, __PERMEDIA_DISABLE);
  335. if(ppdev->cPelSize < 2)
  336. {
  337. SEND_PERMEDIA_DATA(FBReadMode, psurfDst->ulPackedPP |
  338. PM_FBREADMODE_PACKEDDATA(__PERMEDIA_ENABLE) |
  339. PM_FBREADMODE_RELATIVEOFFSET(ulOffset));
  340. }
  341. else
  342. {
  343. // Do we even need this at all???
  344. SEND_PERMEDIA_DATA(FBReadMode, psurfDst->ulPackedPP);
  345. }
  346. SEND_PERMEDIA_DATA(FBWindowBase, psurfDst->ulPixOffset);
  347. SEND_PERMEDIA_DATA(FBPixelOffset, 0);
  348. DEXE_INPUT_FIFO();
  349. while(c--) {
  350. LONG lSrcLeft = pptlSrc->x + (prcl->left - prclDst->left);
  351. LONG lSrcTop = pptlSrc->y + (prcl->top - prclDst->top);
  352. ASSERTDD(lSrcLeft >= 0, "ugh");
  353. ASSERTDD(lSrcTop >= 0, "ugh");
  354. // Render the rectangle
  355. ULONG left = prcl->left >> ppdev->bBppShift;
  356. ULONG right = (prcl->right + ppdev->dwBppMask) >> ppdev->bBppShift;
  357. ULONG width = right - left;
  358. ULONG count = prcl->bottom - prcl->top;
  359. WAIT_INPUT_FIFO((ppdev->cPelSize < 2 ? 6 : 5));
  360. SEND_PERMEDIA_DATA(StartXDom, left << 16);
  361. SEND_PERMEDIA_DATA(StartXSub, right << 16);
  362. if(ppdev->cPelSize < 2)
  363. {
  364. SEND_PERMEDIA_DATA(PackedDataLimits,
  365. PM_PACKEDDATALIMITS_OFFSET(ulOffset)
  366. | (prcl->left << 16) | prcl->right);
  367. }
  368. SEND_PERMEDIA_DATA(StartY, prcl->top << 16);
  369. SEND_PERMEDIA_DATA(Count, count);
  370. SEND_PERMEDIA_DATA(Render, dwRenderBits);
  371. DEXE_INPUT_FIFO();
  372. BYTE * srcScan = (BYTE *)(pbSrcStart + (lSrcTop * lSrcStride))
  373. + (lSrcLeft >> 1);
  374. ULONG* aulXlate = ppb->pxlo->pulXlate;
  375. while(count--)
  376. {
  377. LONG remaining = width;
  378. ULONG* lp = pPermedia->GetDMAPtr(width+1);
  379. BYTE* src = srcScan;
  380. *lp++ = __Permedia2TagColor | ((width-1) << 16);
  381. switch(ppdev->cPelSize)
  382. {
  383. case 0:
  384. while(remaining-- > 0)
  385. {
  386. *lp++ = aulXlate[src[0] & 0x0F] |
  387. (aulXlate[(src[0] & 0xF0) >> 4] << 8) |
  388. (aulXlate[src[1] & 0xf] << 16) |
  389. (aulXlate[(src[1] & 0xf0) >> 4] << 24);
  390. src += 2;
  391. }
  392. break;
  393. case 1:
  394. while(remaining >= 8)
  395. {
  396. remaining -= 8;
  397. lp[0] = aulXlate[src[0] & 0x0F] | (aulXlate[(src[0] & 0xF0) >> 4] << 16);
  398. lp[1] = aulXlate[src[1] & 0x0F] | (aulXlate[(src[1] & 0xF0) >> 4] << 16);
  399. lp[2] = aulXlate[src[2] & 0x0F] | (aulXlate[(src[2] & 0xF0) >> 4] << 16);
  400. lp[3] = aulXlate[src[3] & 0x0F] | (aulXlate[(src[3] & 0xF0) >> 4] << 16);
  401. lp[4] = aulXlate[src[4] & 0x0F] | (aulXlate[(src[4] & 0xF0) >> 4] << 16);
  402. lp[5] = aulXlate[src[5] & 0x0F] | (aulXlate[(src[5] & 0xF0) >> 4] << 16);
  403. lp[6] = aulXlate[src[6] & 0x0F] | (aulXlate[(src[6] & 0xF0) >> 4] << 16);
  404. lp[7] = aulXlate[src[7] & 0x0F] | (aulXlate[(src[7] & 0xF0) >> 4] << 16);
  405. lp+=8;
  406. src+=8;
  407. }
  408. while(remaining-- > 0)
  409. {
  410. *lp++ = aulXlate[src[0] & 0x0F] | (aulXlate[(src[0] & 0xF0) >> 4] << 16);
  411. src++;
  412. }
  413. break;
  414. case 2:
  415. if(lSrcLeft & 1)
  416. {
  417. *lp++ = aulXlate[(src[0] & 0xf0) >> 4];
  418. src++;
  419. remaining--;
  420. }
  421. while(remaining >= 8)
  422. {
  423. remaining -= 8;
  424. lp[0] = aulXlate[src[0] & 0x0F];
  425. lp[1] = aulXlate[(src[0] & 0xf0) >> 4];
  426. lp[2] = aulXlate[src[1] & 0x0F];
  427. lp[3] = aulXlate[(src[1] & 0xf0) >> 4];
  428. lp[4] = aulXlate[src[2] & 0x0F];
  429. lp[5] = aulXlate[(src[2] & 0xf0) >> 4];
  430. lp[6] = aulXlate[src[3] & 0x0F];
  431. lp[7] = aulXlate[(src[3] & 0xf0) >> 4];
  432. src+=4;
  433. lp += 8;
  434. }
  435. while(remaining > 1)
  436. {
  437. remaining -= 2;
  438. *lp++ = aulXlate[src[0] & 0x0F];
  439. *lp++ = aulXlate[(src[0] & 0xf0) >> 4];
  440. src++;
  441. }
  442. if(remaining)
  443. {
  444. *lp++ = aulXlate[src[0] & 0xf];
  445. }
  446. break;
  447. }
  448. srcScan += lSrcStride;
  449. pPermedia->DoneDMAPtr();
  450. }
  451. prcl++;
  452. }
  453. }// vDownload4Bpp()
  454. #endif
  455. //-----------------------------------------------------------------------------
  456. //
  457. // VOID vDowload4Bpp(GFNPB* ppb)
  458. //
  459. // Does a download of a 4bpp surface for a list of rectangles.
  460. //
  461. // Argumentes needed from function block (GFNPB)
  462. // ppdev-------PPDev
  463. // psurfSrc----Source surface
  464. // psurfDst----Destination surface
  465. // pRects------Pointer to a list of rectangles information which needed to be
  466. // filled
  467. // lNumRects---Number of rectangles to fill
  468. // prclDst-----Points to a RECTL structure that defines the rectangular area
  469. // to be modified
  470. // pptlSrc-----Original unclipped source point
  471. //
  472. //-----------------------------------------------------------------------------
  473. VOID
  474. vDownload24Bpp(GFNPB* ppb)
  475. {
  476. #if 0
  477. PDev* ppdev = ppb->ppdev;
  478. Surf* psurfDst = ppb->psurfDst;
  479. RECTL* prcl = ppb->pRects;
  480. LONG c = ppb->lNumRects;
  481. RECTL* prclDst = ppb->prclDst;
  482. POINTL* pptlSrc = ppb->pptlSrc;
  483. DWORD dwRenderBits = __RENDER_TRAPEZOID_PRIMITIVE
  484. | __RENDER_SYNC_ON_HOST_DATA;
  485. BYTE* pbSrcStart = (BYTE*)ppb->psoSrc->pvScan0;
  486. LONG lSrcStride = ppb->psoSrc->lDelta;
  487. ULONG ulOffset = ((pptlSrc->x & ppdev->dwBppMask)
  488. - (prclDst->left & ppdev->dwBppMask)) & 0x7;
  489. PERMEDIA_DECL_VARS;
  490. PERMEDIA_DECL_INIT;
  491. VALIDATE_GDI_CONTEXT;
  492. P2_CHECK_STATE;
  493. P2_DEFAULT_FB_DEPTH;
  494. // setup loop invariant state
  495. WAIT_INPUT_FIFO(4);
  496. SEND_PERMEDIA_DATA(LogicalOpMode, __PERMEDIA_DISABLE);
  497. SEND_PERMEDIA_DATA(FBReadMode, psurfDst->ulPackedPP |
  498. PM_FBREADMODE_PACKEDDATA(__PERMEDIA_ENABLE) |
  499. PM_FBREADMODE_RELATIVEOFFSET(ulOffset));
  500. SEND_PERMEDIA_DATA(FBWindowBase, psurfDst->ulPixOffset);
  501. SEND_PERMEDIA_DATA(FBPixelOffset, 0);
  502. DEXE_INPUT_FIFO();
  503. while(c--)
  504. {
  505. LONG lSrcLeft = pptlSrc->x + (prcl->left - prclDst->left);
  506. LONG lSrcTop = pptlSrc->y + (prcl->top - prclDst->top);
  507. ASSERTDD(lSrcLeft >= 0, "ugh");
  508. ASSERTDD(lSrcTop >= 0, "ugh");
  509. // Render the rectangle
  510. ULONG left = prcl->left >> ppdev->bBppShift;
  511. ULONG right = (prcl->right + ppdev->dwBppMask) >> ppdev->bBppShift;
  512. ULONG width = right - left;
  513. ULONG count = prcl->bottom - prcl->top;
  514. WAIT_INPUT_FIFO(6);
  515. SEND_PERMEDIA_DATA(StartXDom, left << 16);
  516. SEND_PERMEDIA_DATA(StartXSub, right << 16);
  517. SEND_PERMEDIA_DATA(PackedDataLimits,
  518. PM_PACKEDDATALIMITS_OFFSET(ulOffset)
  519. | (prcl->left << 16) | prcl->right);
  520. SEND_PERMEDIA_DATA(StartY, prcl->top << 16);
  521. SEND_PERMEDIA_DATA(Count, count);
  522. SEND_PERMEDIA_DATA(Render, dwRenderBits);
  523. DEXE_INPUT_FIFO();
  524. ULONG * src = (ULONG *) (pbSrcStart + (lSrcTop * lSrcStride)
  525. + ((lSrcLeft & ~(ppdev->dwBppMask)) << ppdev->cPelSize));
  526. #if 0
  527. BLKLD_INPUT_FIFO_LINES(__Permedia2TagColor, src, width, count, lSrcStride);
  528. #else
  529. while(count--)
  530. {
  531. ULONG i;
  532. for(i=0; i<width; i++)
  533. {
  534. WAIT_INPUT_FIFO(1);
  535. SEND_PERMEDIA_DATA(Color, 0);
  536. EXE_INPUT_FIFO();
  537. }
  538. }
  539. #endif
  540. prcl++;
  541. }
  542. #endif
  543. }// vDownload24Bpp()
  544. //-----------------------------------------------------------------------------
  545. //
  546. // VOID vUploadNative
  547. //
  548. // Does a VM-to-SM copy of a list of rectangles.
  549. //
  550. // Argumentes needed from function block (GFNPB)
  551. // ppdev-------PPDev
  552. // psurfSrc----Source surface
  553. // psurfDst----Destination surface
  554. // pRects------Pointer to a list of rectangles information which needed to be
  555. // filled
  556. // lNumRects---Number of rectangles to fill
  557. // prclDst-----Points to a RECTL structure that defines the rectangular area
  558. // to be modified
  559. // pptlSrc-----Original unclipped source point
  560. //
  561. //-----------------------------------------------------------------------------
  562. VOID
  563. vUploadNative(GFNPB* ppb)
  564. {
  565. PDev* ppdev = ppb->ppdev;
  566. POINTL* pptlSrc = ppb->pptlSrc;
  567. RECTL* prclDst = ppb->prclDst;
  568. RECTL* pRects = ppb->pRects;
  569. Surf* psurfSrc = ppb->psurfSrc;
  570. SURFOBJ* psoDst = ppb->psoDst;
  571. BYTE* pbDst;
  572. BYTE* pbDstStart = (BYTE*)psoDst->pvScan0;
  573. BYTE* pbSrc;
  574. BYTE* pbSrcStart = (BYTE*)ppdev->pjScreen + psurfSrc->ulByteOffset;
  575. LONG lDstStride = psoDst->lDelta;
  576. LONG lNumRects = ppb->lNumRects;
  577. LONG lSrcStride = psurfSrc->lDelta;
  578. InputBufferSync(ppdev);
  579. DBG_GDI((6, "vUploadNative called"));
  580. while( lNumRects-- )
  581. {
  582. LONG lWidthInBytes = (pRects->right - pRects->left)
  583. << ppdev->cPelSize;
  584. LONG lHeight = pRects->bottom - pRects->top;
  585. LONG lSrcX = pptlSrc->x + (pRects->left - prclDst->left);
  586. LONG lSrcY = pptlSrc->y + (pRects->top - prclDst->top);
  587. if( (lWidthInBytes != 0) && (lHeight != 0) )
  588. {
  589. pbSrc = pbSrcStart + (lSrcX << ppdev->cPelSize); // Offset in Bytes
  590. pbSrc += (lSrcY * lSrcStride); // Add vertical offset
  591. pbDst = pbDstStart + (pRects->left << ppdev->cPelSize);
  592. pbDst += (pRects->top * lDstStride);
  593. //
  594. // Up to this point, "pbSrc" points to the beginning of the bits
  595. // needs to be copied and "pbDst" points to the position for the
  596. // receiving bits
  597. //
  598. // Now copy it row by row, vertically
  599. //
  600. while( lHeight-- )
  601. {
  602. LONG lCount = lWidthInBytes;
  603. //
  604. // If the source address is not DWORD aligned,
  605. // (pbSrc & 0x3 != 0), then we copy these bytes first until
  606. // it reaches DWORD aligned condition
  607. //
  608. // The reason we are doing alignment is unaligned DWORD reads
  609. // are twice as expensive as aligned reads
  610. //
  611. while( (((ULONG_PTR)pbSrc & 0x3)) && (lCount > 0) )
  612. {
  613. *pbDst++ = *pbSrc++;
  614. lCount--;
  615. }
  616. //
  617. // Up to this point, the source should be DWORD aligned. So we
  618. // can start to do uploading at DWORD level till there are less
  619. // than bytes left
  620. //
  621. ULONG* pulSrc = (ULONG*)pbSrc;
  622. ULONG* pulDst = (ULONG*)pbDst;
  623. while( lCount >= 4 )
  624. {
  625. *(ULONG UNALIGNED*)pulDst++ = *pulSrc++;
  626. lCount -= 4;
  627. }
  628. //
  629. // Now copy the last several left over bytes
  630. //
  631. pbSrc = (BYTE*)pulSrc;
  632. pbDst = (BYTE*)pulDst;
  633. while( lCount > 0 )
  634. {
  635. *pbDst++ = *pbSrc++;
  636. lCount--;
  637. }
  638. //
  639. // Move onto next line
  640. //
  641. pbSrc += (lSrcStride - lWidthInBytes);
  642. pbDst += (lDstStride - lWidthInBytes);
  643. }// while( lHeight-- )
  644. }// if( (lWidthInBytes != 0) && (lHeight != 0) )
  645. pRects++;
  646. }// while( lNumRects-- )
  647. }// vUploadNative