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.

1452 lines
46 KiB

  1. /******************************Module*Header***********************************\
  2. *
  3. * *******************
  4. * * GDI SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: solidfil.c
  8. *
  9. * Contains grab bag collection of hardware acceleration entry points.
  10. *
  11. * Note, we will be moving several of the routines in this file to there
  12. * modle leaving only the solid fill related entry points.
  13. *
  14. * Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
  15. * Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
  16. \******************************************************************************/
  17. #include "precomp.h"
  18. #include "gdi.h"
  19. #include "directx.h"
  20. // The shift equations are a nuisance. We want x<<32 to be
  21. // zero but some processors only use the bottom 5 bits
  22. // of the shift value. So if we want to shift by n bits
  23. // where we know that (32 >= n > 0), we do it in two parts.
  24. // In some places the algorithm guarantees n < 32 so we can
  25. // use a single shift.
  26. #define SHIFT_LEFT(src, n) (((src) << ((n)-1)) << 1)
  27. VOID
  28. vMonoBitsDownload(PPDev ppdev,
  29. BYTE* pSrcBase, // ptr to word containing first bit we want to download
  30. LONG lSrcDelta, // offset in bytes from one scanline to the next
  31. LONG xOffset, // offset of first bit to download in pSrcBase
  32. LONG widthInBits, // number of bits to download on each scanline
  33. LONG nScanLines) // number of scanlines to download
  34. {
  35. ULONG bitWord;
  36. ULONG bitMask;
  37. ULONG bits;
  38. LONG unused;
  39. LONG nStart;
  40. LONG nRemainder;
  41. LONG nBits;
  42. ULONG *pSrc;
  43. ULONG* pBuffer;
  44. ULONG* pReservationEnd;
  45. ULONG* pBufferEnd;
  46. InputBufferStart(ppdev, MAX_INPUT_BUFFER_RESERVATION,
  47. &pBuffer, &pBufferEnd, &pReservationEnd);
  48. DBG_GDI((6, "vDoMonoBitsDownload called"));
  49. ASSERTDD(((INT_PTR)pSrcBase & 3) == 0,
  50. "vDoMonoBitsDownload: non-dword aligned source");
  51. //
  52. // Special case where the source width is a multiple of 32 bits.
  53. // This is true for many small resources such as icons.
  54. //
  55. if ( (xOffset | (widthInBits & 31)) == 0 )
  56. {
  57. //
  58. // Simplest case: one 32 bit word per scanline
  59. //
  60. if ( widthInBits == 32 )
  61. {
  62. *pBuffer++ = ((nScanLines - 1) << 16)
  63. | __Permedia2TagBitMaskPattern;
  64. do
  65. {
  66. LSWAP_BYTES(bits, pSrcBase);
  67. *pBuffer++ = bits;
  68. if(pBuffer == pReservationEnd)
  69. {
  70. InputBufferContinue(ppdev, MAX_INPUT_BUFFER_RESERVATION,
  71. &pBuffer, &pBufferEnd, &pReservationEnd);
  72. }
  73. pSrcBase += lSrcDelta;
  74. } while ( --nScanLines > 0 );
  75. InputBufferCommit(ppdev, pBuffer);
  76. return;
  77. }
  78. //
  79. // Multiple 32 bit words per scanline. convert the delta to the
  80. // delta as we need it at the end of each line by subtracting the
  81. // width in bytes of the data we're downloading. Note, pSrcBase
  82. // is always 1 LONG short of the end of the line because we break
  83. // before adding on the last ULONG. Thus, we subtract sizeof(ULONG)
  84. // from the original adjustment.
  85. //
  86. LONG widthInLongs = widthInBits >> 5;
  87. do {
  88. LONG lLongs = widthInLongs;
  89. ULONG* src = (ULONG *) pSrcBase;
  90. *pBuffer++ = ((lLongs - 1) << 16)
  91. | __Permedia2TagBitMaskPattern;
  92. if(pBuffer == pReservationEnd)
  93. {
  94. InputBufferContinue(ppdev, MAX_INPUT_BUFFER_RESERVATION,
  95. &pBuffer, &pBufferEnd, &pReservationEnd);
  96. }
  97. do
  98. {
  99. LSWAP_BYTES(bits, src);
  100. *pBuffer++ = bits;
  101. if(pBuffer == pReservationEnd)
  102. {
  103. InputBufferContinue(ppdev, MAX_INPUT_BUFFER_RESERVATION,
  104. &pBuffer, &pBufferEnd, &pReservationEnd);
  105. }
  106. src++;
  107. } while( --lLongs > 0);
  108. pSrcBase += lSrcDelta;
  109. } while(--nScanLines > 0);
  110. InputBufferCommit(ppdev, pBuffer);
  111. return;
  112. }
  113. //
  114. // Some common values at the start of each scanline:
  115. // bitWord: collect bits in this ulong and write out when full
  116. // unused: number of bits left to fill in bitWord
  117. // nStart = number of valid bits in the first longword
  118. // nRemainder = number of bits on scanline minus nStart
  119. //
  120. bitWord = 0;
  121. unused = 32;
  122. nStart = 32 - xOffset;
  123. nRemainder = widthInBits - nStart;
  124. //
  125. // We special case where the complete set of bits on a scanline
  126. // is contained in the first ulong.
  127. //
  128. //@@BEGIN_DDKSPLIT
  129. //TODO: We should be able to clean this up a little. It would be
  130. // nice to be able to calculate the number of bit masks we
  131. // will be sending enabling us to use the dma hold method
  132. // for all cases.
  133. //@@END_DDKSPLIT
  134. if ( nRemainder <= 0 )
  135. {
  136. nBits = -nRemainder; // number of invalid bits on right
  137. bitMask = (1 << widthInBits) - 1; // widthInBits == 32 is handled above
  138. pSrc = (ULONG *)pSrcBase;
  139. while ( TRUE )
  140. {
  141. LSWAP_BYTES(bits, pSrc);
  142. bits = (bits >> nBits) & bitMask;
  143. unused -= widthInBits;
  144. if ( unused > 0 )
  145. {
  146. bitWord |= bits << unused;
  147. }
  148. else
  149. {
  150. bitWord |= bits >> -unused;
  151. InputBufferContinue(ppdev, 2, &pBuffer, &pBufferEnd, &pReservationEnd);
  152. pBuffer[0] = __Permedia2TagBitMaskPattern;
  153. pBuffer[1] = bitWord;
  154. pBuffer += 2;
  155. unused += 32;
  156. bitWord = SHIFT_LEFT(bits, unused);
  157. }
  158. //
  159. // Break will generate an extra jump
  160. //
  161. if ( --nScanLines == 0 )
  162. {
  163. goto completeDownload;
  164. }
  165. pSrc = (ULONG *) (((UCHAR *)pSrc) + lSrcDelta);
  166. }
  167. }// if ( nRemainder <= 0 )
  168. else
  169. {
  170. //
  171. // Use bitMask to zero left edge bits in first long
  172. //
  173. bitMask = SHIFT_LEFT(1, nStart) - 1;
  174. while ( TRUE )
  175. {
  176. //
  177. // Read the first word from this scanline of the bitmap
  178. // and mask out the lefthand offset bits if any.
  179. //
  180. nBits = nRemainder;
  181. pSrc = (ULONG *)pSrcBase;
  182. LSWAP_BYTES(bits, pSrc);
  183. bits &= bitMask;
  184. //
  185. // Handle the left hand edge
  186. //
  187. unused -= nStart;
  188. if ( unused > 0 )
  189. {
  190. bitWord |= bits << unused;
  191. }
  192. else
  193. {
  194. bitWord |= bits >> -unused;
  195. InputBufferContinue(ppdev, 2, &pBuffer, &pBufferEnd, &pReservationEnd);
  196. pBuffer[0] = __Permedia2TagBitMaskPattern;
  197. pBuffer[1] = bitWord;
  198. pBuffer += 2;
  199. unused += 32;
  200. bitWord = SHIFT_LEFT(bits, unused);
  201. }
  202. //
  203. // Handle all the full longs in the middle, if any
  204. //
  205. while ( nBits >= 32 )
  206. {
  207. ++pSrc;
  208. LSWAP_BYTES(bits, pSrc);
  209. bitWord |= bits >> (32 - unused);
  210. InputBufferContinue(ppdev, 2, &pBuffer, &pBufferEnd, &pReservationEnd);
  211. pBuffer[0] = __Permedia2TagBitMaskPattern;
  212. pBuffer[1] = bitWord;
  213. pBuffer += 2;
  214. bitWord = SHIFT_LEFT(bits, unused);
  215. nBits -= 32;
  216. }
  217. //
  218. // Handle the right hand edge, if any
  219. //
  220. if ( nBits > 0 )
  221. {
  222. ++pSrc;
  223. LSWAP_BYTES(bits, pSrc);
  224. bits >>= (32 - nBits);
  225. unused -= nBits;
  226. if ( unused > 0 )
  227. {
  228. bitWord |= bits << unused;
  229. }
  230. else
  231. {
  232. bitWord |= bits >> -unused;
  233. InputBufferContinue(ppdev, 2, &pBuffer, &pBufferEnd, &pReservationEnd);
  234. pBuffer[0] = __Permedia2TagBitMaskPattern;
  235. pBuffer[1] = bitWord;
  236. pBuffer += 2;
  237. unused += 32;
  238. bitWord = SHIFT_LEFT(bits, unused);
  239. }
  240. }
  241. if ( --nScanLines == 0 )
  242. {
  243. goto completeDownload;
  244. }
  245. //
  246. // go onto next scanline
  247. //
  248. pSrcBase += lSrcDelta;
  249. }
  250. }
  251. completeDownload:
  252. //
  253. // Write out final, partial bitWord if any
  254. //
  255. if ( unused < 32 )
  256. {
  257. InputBufferContinue(ppdev, 2, &pBuffer, &pBufferEnd, &pReservationEnd);
  258. pBuffer[0] = __Permedia2TagBitMaskPattern;
  259. pBuffer[1] = bitWord;
  260. pBuffer += 2;
  261. }
  262. InputBufferCommit(ppdev, pBuffer);
  263. }// vDoMonoBitsDownload()
  264. //-----------------------------------------------------------------------------
  265. //
  266. // void vMonoDownload(GFNPB * ppb)
  267. //
  268. // Dowload the monochrome source from system memory to video memory using
  269. // provided source to destination rop2.
  270. //
  271. // Argumentes needed from function block (GFNPB)
  272. //
  273. // ppdev-------PPDev
  274. // psoSrc------Source SURFOBJ
  275. // psurfDst----Destination Surf
  276. // lNumRects---Number of rectangles to fill
  277. // pptlSrc-----Source point
  278. // prclDst-----Points to a RECTL structure that defines the rectangular area
  279. // to be modified
  280. // pRects------Pointer to a list of rectangles information which needed to be
  281. // filled
  282. // pxlo--------XLATEOBJ
  283. // usRop4------Rop to be performed
  284. //
  285. //-----------------------------------------------------------------------------
  286. VOID
  287. vMonoDownload(GFNPB * ppb)
  288. {
  289. PDev* ppdev = ppb->ppdev;
  290. RECTL* prcl = ppb->pRects;
  291. LONG count = ppb->lNumRects;
  292. SURFOBJ* psoSrc = ppb->psoSrc;
  293. POINTL* pptlSrc = ppb->pptlSrc;
  294. RECTL* prclDst = ppb->prclDst;
  295. XLATEOBJ * pxlo = ppb->pxlo;
  296. ULONG logicop = ulRop2ToLogicop((unsigned char)(ppb->ulRop4 & 0xf));
  297. DWORD dwBitMask;
  298. PERMEDIA_DECL_VARS;
  299. PERMEDIA_DECL_INIT;
  300. ASSERTDD(count > 0, "Can't handle zero rectangles");
  301. if ( ppb->ulRop4 == 0xB8B8 )
  302. {
  303. dwBitMask = permediaInfo->RasterizerMode
  304. | INVERT_BITMASK_BITS;
  305. logicop = K_LOGICOP_COPY;
  306. }
  307. else if ( ppb->ulRop4 == 0xE2E2 )
  308. {
  309. dwBitMask = permediaInfo->RasterizerMode;
  310. logicop = K_LOGICOP_COPY;
  311. }
  312. else
  313. {
  314. dwBitMask = permediaInfo->RasterizerMode | FORCE_BACKGROUND_COLOR;
  315. }
  316. ULONG* pBuffer;
  317. InputBufferReserve(ppdev, 14, &pBuffer);
  318. pBuffer[0] = __Permedia2TagFBReadMode;
  319. pBuffer[1] = PM_FBREADMODE_PARTIAL(ppb->psurfDst->ulPackedPP)
  320. | LogicopReadDest[logicop];
  321. pBuffer[2] = __Permedia2TagLogicalOpMode;
  322. pBuffer[3] = P2_ENABLED_LOGICALOP(logicop);
  323. pBuffer[4] = __Permedia2TagColorDDAMode;
  324. pBuffer[5] = __COLOR_DDA_FLAT_SHADE;
  325. pBuffer[6] = __Permedia2TagConstantColor;
  326. pBuffer[7] = pxlo->pulXlate[1];
  327. pBuffer[8] = __Permedia2TagTexel0;
  328. pBuffer[9] = pxlo->pulXlate[0];
  329. pBuffer[10] = __Permedia2TagFBWindowBase;
  330. pBuffer[11] = ppb->psurfDst->ulPixOffset;
  331. pBuffer[12] = __Permedia2TagRasterizerMode;
  332. pBuffer[13] = dwBitMask;
  333. pBuffer += 14;
  334. InputBufferCommit(ppdev, pBuffer);
  335. while (count--) {
  336. LONG xOffset;
  337. BYTE* pjSrc;
  338. // calc x pixel offset from origin
  339. xOffset = pptlSrc->x + (prcl->left - prclDst->left);
  340. // pjSrc is first dword containing a bit to download
  341. pjSrc = (BYTE*)((INT_PTR)((PUCHAR) psoSrc->pvScan0
  342. + ((pptlSrc->y + (prcl->top - prclDst->top)) * psoSrc->lDelta)
  343. + ((xOffset >> 3) & ~3)));
  344. // pjSrc gets us to the first DWORD. Convert xOffset to be the offset
  345. // to the first pixel in the first DWORD
  346. xOffset &= 0x1f;
  347. InputBufferReserve(ppdev, 10, &pBuffer);
  348. // set up the destination rectangle
  349. pBuffer[0] = __Permedia2TagStartXDom;
  350. pBuffer[1] = INTtoFIXED(prcl->left);
  351. pBuffer[2] = __Permedia2TagStartXSub;
  352. pBuffer[3] = INTtoFIXED(prcl->right);
  353. pBuffer[4] = __Permedia2TagStartY;
  354. pBuffer[5] = INTtoFIXED(prcl->top);
  355. pBuffer[6] = __Permedia2TagCount;
  356. pBuffer[7] = prcl->bottom - prcl->top;
  357. pBuffer[8] = __Permedia2TagRender;
  358. pBuffer[9] = __RENDER_TRAPEZOID_PRIMITIVE
  359. | __RENDER_SYNC_ON_BIT_MASK;
  360. pBuffer += 10;
  361. InputBufferCommit(ppdev, pBuffer);
  362. vMonoBitsDownload(
  363. ppdev, pjSrc, psoSrc->lDelta, xOffset,
  364. prcl->right - prcl->left, prcl->bottom - prcl->top);
  365. prcl++;
  366. }
  367. InputBufferReserve(ppdev, 4, &pBuffer);
  368. pBuffer[0] = __Permedia2TagColorDDAMode;
  369. pBuffer[1] = __PERMEDIA_DISABLE;
  370. pBuffer[2] = __Permedia2TagRasterizerMode;
  371. pBuffer[3] = permediaInfo->RasterizerMode;
  372. pBuffer += 4;
  373. InputBufferCommit(ppdev, pBuffer);
  374. }
  375. //-----------------------------------------------------------------------------
  376. //
  377. // void vGradientFillRect(GFNPB * ppb)
  378. //
  379. // Shades the specified primitives.
  380. //
  381. // Argumentes needed from function block (GFNPB)
  382. //
  383. // ppdev-------PPDev
  384. // psurfDst----Destination surface
  385. // lNumRects---Number of rectangles to fill
  386. // pRects------Pointer to a list of rectangles information which needed to be
  387. // filled
  388. // ulMode------Specifies the current drawing mode and how to interpret the
  389. // array to which pMesh points
  390. // ptvrt-------Points to an array of TRIVERTEX structures, with each entry
  391. // containing position and color information.
  392. // ulNumTvrt---Specifies the number of TRIVERTEX structures in the array to
  393. // which pVertex points
  394. // pvMesh------Points to an array of structures that define the connectivity
  395. // of the TRIVERTEX elements to which ptvrt points
  396. // ulNumMesh---Specifies the number of elements in the array to which pvMesh
  397. // points
  398. //
  399. //-----------------------------------------------------------------------------
  400. VOID
  401. vGradientFillRect(GFNPB * ppb)
  402. {
  403. Surf * psurfDst = ppb->psurfDst;
  404. RECTL* prcl = ppb->pRects;
  405. LONG c = ppb->lNumRects;
  406. PPDev ppdev = psurfDst->ppdev;
  407. DWORD windowBase = psurfDst->ulPixOffset;
  408. TRIVERTEX *ptvrt = ppb->ptvrt;
  409. GRADIENT_RECT *pgr;
  410. GRADIENT_RECT *pgrSentinel = ((GRADIENT_RECT *) ppb->pvMesh)
  411. + ppb->ulNumMesh;
  412. LONG xShift;
  413. LONG yShift;
  414. ULONG* pBuffer;
  415. DBG_GDI((10, "vGradientFillRect"));
  416. // setup loop invariant state
  417. InputBufferReserve(ppdev, 14, &pBuffer);
  418. pBuffer[0] = __Permedia2TagLogicalOpMode;
  419. pBuffer[1] = __PERMEDIA_DISABLE;
  420. pBuffer[2] = __Permedia2TagDitherMode;
  421. pBuffer[3] = (COLOR_MODE << PM_DITHERMODE_COLORORDER) |
  422. (ppdev->ulPermFormat << PM_DITHERMODE_COLORFORMAT) |
  423. (ppdev->ulPermFormatEx << PM_DITHERMODE_COLORFORMATEXTENSION) |
  424. (1 << PM_DITHERMODE_ENABLE) |
  425. (1 << PM_DITHERMODE_DITHERENABLE);
  426. pBuffer[4] = __Permedia2TagFBReadMode;
  427. pBuffer[5] = PM_FBREADMODE_PARTIAL(ppb->psurfDst->ulPackedPP) |
  428. PM_FBREADMODE_PACKEDDATA(__PERMEDIA_DISABLE);
  429. pBuffer[6] = __Permedia2TagFBWindowBase;
  430. pBuffer[7] = windowBase;
  431. pBuffer[8] = __Permedia2TagLogicalOpMode;
  432. pBuffer[9] = __PERMEDIA_DISABLE;
  433. pBuffer[10] = __Permedia2TagColorDDAMode;
  434. pBuffer[11] = 3;
  435. pBuffer[12] = __Permedia2TagdY;
  436. pBuffer[13] = 1 << 16;
  437. pBuffer += 14;
  438. //@@BEGIN_DDKSPLIT
  439. // TODO: This code can be cleaned up a little
  440. // 1. the delta values should not change with each rectangle
  441. // 2. we can use the render rectangle primitive
  442. //@@END_DDKSPLIT
  443. InputBufferCommit(ppdev, pBuffer);
  444. while(c--)
  445. {
  446. pgr = (GRADIENT_RECT *) ppb->pvMesh;
  447. while(pgr < pgrSentinel)
  448. {
  449. TRIVERTEX *ptrvtLr = ptvrt + pgr->LowerRight;
  450. TRIVERTEX *ptrvtUl = ptvrt + pgr->UpperLeft;
  451. LONG rd;
  452. LONG gd;
  453. LONG bd;
  454. LONG dx;
  455. LONG dy;
  456. RECTL rect;
  457. LONG rdx;
  458. LONG rdy;
  459. LONG gdx;
  460. LONG gdy;
  461. LONG bdx;
  462. LONG bdy;
  463. LONG rs;
  464. LONG gs;
  465. LONG bs;
  466. LONG lTemp;
  467. BOOL bReverseH = FALSE;
  468. BOOL bReverseV = FALSE;
  469. rect.left = ptrvtUl->x;
  470. rect.right = ptrvtLr->x;
  471. rect.top = ptrvtUl->y;
  472. rect.bottom = ptrvtLr->y;
  473. if ( rect.left > rect.right )
  474. {
  475. //
  476. // The fill is from right to left. So we need to swap
  477. // the rectangle coordinates
  478. //
  479. lTemp = rect.left;
  480. rect.left = rect.right;
  481. rect.right = lTemp;
  482. bReverseH = TRUE;
  483. }
  484. if ( rect.top > rect.bottom )
  485. {
  486. //
  487. // The coordinate is from bottom to top. So we need to swap
  488. // the rectangle coordinates
  489. //
  490. lTemp = rect.top;
  491. rect.top = rect.bottom;
  492. rect.bottom = lTemp;
  493. bReverseV = TRUE;
  494. }
  495. //
  496. // We need to set start color and color delta according to the
  497. // rectangle drawing direction
  498. //
  499. if( (ppb->ulMode == GRADIENT_FILL_RECT_H) && (bReverseH == TRUE)
  500. ||(ppb->ulMode == GRADIENT_FILL_RECT_V) && (bReverseV == TRUE) )
  501. {
  502. rd = (ptrvtUl->Red - ptrvtLr->Red) << 7;
  503. gd = (ptrvtUl->Green - ptrvtLr->Green) << 7;
  504. bd = (ptrvtUl->Blue - ptrvtLr->Blue) << 7;
  505. rs = ptrvtLr->Red << 7;
  506. gs = ptrvtLr->Green << 7;
  507. bs = ptrvtLr->Blue << 7;
  508. }
  509. else
  510. {
  511. rd = (ptrvtLr->Red - ptrvtUl->Red) << 7;
  512. gd = (ptrvtLr->Green - ptrvtUl->Green) << 7;
  513. bd = (ptrvtLr->Blue - ptrvtUl->Blue) << 7;
  514. rs = ptrvtUl->Red << 7;
  515. gs = ptrvtUl->Green << 7;
  516. bs = ptrvtUl->Blue << 7;
  517. }
  518. // quick clipping reject
  519. if(prcl->left >= rect.right ||
  520. prcl->right <= rect.left ||
  521. prcl->top >= rect.bottom ||
  522. prcl->bottom <= rect.top)
  523. goto nextPgr;
  524. dx = rect.right - rect.left;
  525. dy = rect.bottom - rect.top;
  526. if(ppb->ulMode == GRADIENT_FILL_RECT_H)
  527. {
  528. rdx = rd / dx;
  529. gdx = gd / dx;
  530. bdx = bd / dx;
  531. rdy = 0;
  532. gdy = 0;
  533. bdy = 0;
  534. }
  535. else
  536. {
  537. rdy = rd / dy;
  538. gdy = gd / dy;
  539. bdy = bd / dy;
  540. rdx = 0;
  541. gdx = 0;
  542. bdx = 0;
  543. }
  544. //
  545. // Convert from 9.15 to 9.11 format. The Permedia2
  546. // dRdx, dGdx etc. registers using 9.11 fixed format. The bottom 4
  547. // bits are not used.
  548. //
  549. rdx &= ~0xf;
  550. gdx &= ~0xf;
  551. bdx &= ~0xf;
  552. rdy &= ~0xf;
  553. gdy &= ~0xf;
  554. bdy &= ~0xf;
  555. // now perform some clipping adjusting start values as necessary
  556. xShift = prcl->left - rect.left;
  557. if(xShift > 0)
  558. {
  559. rs = rs + (rdx * xShift);
  560. gs = gs + (gdx * xShift);
  561. bs = bs + (bdx * xShift);
  562. rect.left = prcl->left;
  563. }
  564. yShift = prcl->top - rect.top;
  565. if(yShift > 0)
  566. {
  567. rs = rs + (rdy * yShift);
  568. gs = gs + (gdy * yShift);
  569. bs = bs + (bdy * yShift);
  570. rect.top = prcl->top;
  571. }
  572. // just move up the bottom right as necessary
  573. if(prcl->right < rect.right)
  574. rect.right = prcl->right;
  575. if(prcl->bottom < rect.bottom)
  576. rect.bottom = prcl->bottom;
  577. InputBufferReserve(ppdev, 28, &pBuffer);
  578. pBuffer[0] = __Permedia2TagRStart;
  579. pBuffer[1] = rs;
  580. pBuffer[2] = __Permedia2TagGStart;
  581. pBuffer[3] = gs;
  582. pBuffer[4] = __Permedia2TagBStart;
  583. pBuffer[5] = bs;
  584. pBuffer[6] = __Permedia2TagdRdx;
  585. pBuffer[7] = rdx;
  586. pBuffer[8] = __Permedia2TagdRdyDom;
  587. pBuffer[9] = rdy;
  588. pBuffer[10] = __Permedia2TagdGdx;
  589. pBuffer[11] = gdx;
  590. pBuffer[12] = __Permedia2TagdGdyDom;
  591. pBuffer[13] = gdy;
  592. pBuffer[14] = __Permedia2TagdBdx;
  593. pBuffer[15] = bdx;
  594. pBuffer[16] = __Permedia2TagdBdyDom;
  595. pBuffer[17] = bdy;
  596. // NOTE: alpha is always constant
  597. // Render the rectangle
  598. pBuffer[18] = __Permedia2TagStartXDom;
  599. pBuffer[19] = rect.left << 16;
  600. pBuffer[20] = __Permedia2TagStartXSub;
  601. pBuffer[21] = rect.right << 16;
  602. pBuffer[22] = __Permedia2TagStartY;
  603. pBuffer[23] = rect.top << 16;
  604. pBuffer[24] = __Permedia2TagCount;
  605. pBuffer[25] = rect.bottom - rect.top;
  606. pBuffer[26] = __Permedia2TagRender;
  607. pBuffer[27] = __RENDER_TRAPEZOID_PRIMITIVE;
  608. pBuffer += 28;
  609. InputBufferCommit(ppdev, pBuffer);
  610. nextPgr:
  611. pgr++;
  612. }
  613. prcl++;
  614. }
  615. InputBufferReserve(ppdev, 6, &pBuffer);
  616. pBuffer[0] = __Permedia2TagdY;
  617. pBuffer[1] = INTtoFIXED(1);
  618. pBuffer[2] = __Permedia2TagDitherMode;
  619. pBuffer[3] = 0;
  620. pBuffer[4] = __Permedia2TagColorDDAMode;
  621. pBuffer[5] = 0;
  622. pBuffer += 6;
  623. InputBufferCommit(ppdev, pBuffer);
  624. }// vGradientFillRect()
  625. //-----------------------------------------------------------------------------
  626. //
  627. // void vTransparentBlt(GFNPB * ppb)
  628. //
  629. // Provides bit-block transfer capabilities with transparency.
  630. //
  631. // Argumentes needed from function block (GFNPB)
  632. //
  633. // ppdev-------PPDev
  634. // psurfSrc----Source surface
  635. // psurfDst----Destination surface
  636. // lNumRects---Number of rectangles to fill
  637. // prclSrc-----Points to a RECTL structure that defines the rectangular area
  638. // to be copied
  639. // prclDst-----Points to a RECTL structure that defines the rectangular area
  640. // to be modified
  641. // colorKey----Specifies the transparent color in the source surface format.
  642. // It is a color index value that has been translated to the
  643. // source surface's palette.
  644. // pRects------Pointer to a list of rectangles information which needed to be
  645. // filled
  646. //
  647. //-----------------------------------------------------------------------------
  648. VOID
  649. vTransparentBlt(GFNPB * ppb)
  650. {
  651. Surf * psurfDst = ppb->psurfDst;
  652. Surf * psurfSrc = ppb->psurfSrc;
  653. RECTL* prcl = ppb->pRects;
  654. LONG c = ppb->lNumRects;
  655. RECTL* prclSrc = ppb->prclSrc;
  656. RECTL* prclDst = ppb->prclDst;
  657. DWORD colorKey = ppb->colorKey;
  658. PPDev ppdev = psurfDst->ppdev;
  659. DWORD windowBase = psurfDst->ulPixOffset;
  660. LONG sourceOffset = psurfSrc->ulPixOffset;
  661. DWORD dwRenderDirection;
  662. DWORD format = ppdev->ulPermFormat;
  663. DWORD extension = ppdev->ulPermFormatEx;
  664. DWORD dwLowerBound;
  665. DWORD dwUpperBound;
  666. ULONG* pBuffer;
  667. DBG_GDI((6, "vTransparentBlt"));
  668. ASSERTDD(prclSrc->right - prclSrc->left == (prclDst->right - prclDst->left),
  669. "vTransparentBlt: expect one-to-one blts only");
  670. ASSERTDD(prclSrc->bottom - prclSrc->top == (prclDst->bottom - prclDst->top),
  671. "vTransparentBlt: expect one-to-one blts only");
  672. //@@BEGIN_DDKSPLIT
  673. // TODO: should call utility function to format color key
  674. //@@END_DDKSPLIT
  675. if (format == PERMEDIA_8BIT_PALETTEINDEX)
  676. {
  677. colorKey = FORMAT_PALETTE_32BIT(colorKey);
  678. dwLowerBound = CHROMA_LOWER_ALPHA(colorKey);
  679. dwUpperBound = CHROMA_UPPER_ALPHA(colorKey);
  680. }
  681. else if(ppdev->ulPermFormat == PERMEDIA_565_RGB)
  682. {
  683. colorKey = FORMAT_565_32BIT_BGR(colorKey);
  684. dwLowerBound = CHROMA_LOWER_ALPHA(colorKey);
  685. dwUpperBound = CHROMA_UPPER_ALPHA(colorKey);
  686. dwLowerBound = dwLowerBound & 0xF8F8FCF8;
  687. dwUpperBound = dwUpperBound | 0x07070307;
  688. }
  689. else
  690. {
  691. colorKey = FORMAT_8888_32BIT_BGR(colorKey);
  692. dwLowerBound = CHROMA_LOWER_ALPHA(colorKey);
  693. dwUpperBound = CHROMA_UPPER_ALPHA(colorKey);
  694. }
  695. // setup loop invariant state
  696. InputBufferReserve(ppdev, 24, &pBuffer);
  697. // Reject range
  698. pBuffer[0] = __Permedia2TagYUVMode;
  699. pBuffer[1] = 0x2 << 1;
  700. pBuffer[2] = __Permedia2TagFBWindowBase;
  701. pBuffer[3] = windowBase;
  702. // set no read of source.
  703. // add read src/dest enable
  704. pBuffer[4] = __Permedia2TagFBReadMode;
  705. pBuffer[5] = psurfDst->ulPackedPP;
  706. pBuffer[6] = __Permedia2TagLogicalOpMode;
  707. pBuffer[7] = __PERMEDIA_DISABLE;
  708. // set base of source
  709. pBuffer[8] = __Permedia2TagTextureBaseAddress;
  710. pBuffer[9] = sourceOffset;
  711. pBuffer[10] = __Permedia2TagTextureAddressMode;
  712. pBuffer[11] = 1 << PM_TEXADDRESSMODE_ENABLE;
  713. //
  714. // modulate & ramp??
  715. pBuffer[12] = __Permedia2TagTextureColorMode;
  716. pBuffer[13] = (1 << PM_TEXCOLORMODE_ENABLE) |
  717. (_P2_TEXTURE_COPY << PM_TEXCOLORMODE_APPLICATION);
  718. pBuffer[14] = __Permedia2TagTextureReadMode;
  719. pBuffer[15] = PM_TEXREADMODE_ENABLE(__PERMEDIA_ENABLE) |
  720. PM_TEXREADMODE_FILTER(__PERMEDIA_DISABLE) |
  721. PM_TEXREADMODE_WIDTH(11) |
  722. PM_TEXREADMODE_HEIGHT(11);
  723. pBuffer[16] = __Permedia2TagTextureDataFormat;
  724. pBuffer[17] = (format << PM_TEXDATAFORMAT_FORMAT) |
  725. (extension << PM_TEXDATAFORMAT_FORMATEXTENSION) |
  726. (COLOR_MODE << PM_TEXDATAFORMAT_COLORORDER);
  727. pBuffer[18] = __Permedia2TagTextureMapFormat;
  728. pBuffer[19] = (psurfSrc->ulPackedPP) |
  729. (ppdev->cPelSize << PM_TEXMAPFORMAT_TEXELSIZE);
  730. pBuffer[20] = __Permedia2TagChromaLowerBound;
  731. pBuffer[21] = dwLowerBound;
  732. pBuffer[22] = __Permedia2TagChromaUpperBound;
  733. pBuffer[23] = dwUpperBound;
  734. pBuffer += 24;
  735. InputBufferCommit(ppdev, pBuffer);
  736. if (format != PERMEDIA_8BIT_PALETTEINDEX)
  737. {
  738. InputBufferReserve(ppdev, 2, &pBuffer);
  739. // Reject range
  740. pBuffer[0] = __Permedia2TagDitherMode;
  741. pBuffer[1] = (COLOR_MODE << PM_DITHERMODE_COLORORDER) |
  742. (format << PM_DITHERMODE_COLORFORMAT) |
  743. (extension << PM_DITHERMODE_COLORFORMATEXTENSION) |
  744. (1 << PM_DITHERMODE_ENABLE);
  745. pBuffer += 2;
  746. InputBufferCommit(ppdev, pBuffer);
  747. }
  748. while(c--) {
  749. RECTL rDest;
  750. RECTL rSrc;
  751. rDest = *prcl;
  752. rSrc.left = prclSrc->left + (rDest.left - prclDst->left);
  753. rSrc.top = prclSrc->top + (rDest.top - prclDst->top);
  754. rSrc.right = rSrc.left + (rDest.right - rDest.left);
  755. rSrc.bottom = rSrc.top + (rDest.bottom - rDest.top);
  756. if (rSrc.top < 0) {
  757. rDest.top -= rSrc.top;
  758. rSrc.top = 0;
  759. }
  760. if (rSrc.left < 0) {
  761. rDest.left -= rSrc.left;
  762. rSrc.left = 0;
  763. }
  764. if ((psurfSrc->ulPixOffset) != (psurfDst->ulPixOffset))
  765. {
  766. dwRenderDirection = 1;
  767. }
  768. else
  769. {
  770. if(rSrc.top < rDest.top)
  771. {
  772. dwRenderDirection = 0;
  773. }
  774. else if(rSrc.top > rDest.top)
  775. {
  776. dwRenderDirection = 1;
  777. }
  778. else if(rSrc.left < rDest.left)
  779. {
  780. dwRenderDirection = 0;
  781. }
  782. else dwRenderDirection = 1;
  783. }
  784. InputBufferReserve(ppdev, 24, &pBuffer);
  785. // Left -> right, top->bottom
  786. if (dwRenderDirection)
  787. {
  788. // set offset of source
  789. pBuffer[0] = __Permedia2TagSStart;
  790. pBuffer[1] = rSrc.left << 20;
  791. pBuffer[2] = __Permedia2TagTStart;
  792. pBuffer[3] = rSrc.top << 20;
  793. pBuffer[4] = __Permedia2TagdSdx;
  794. pBuffer[5] = 1 << 20;
  795. pBuffer[6] = __Permedia2TagdSdyDom;
  796. pBuffer[7] = 0;
  797. pBuffer[8] = __Permedia2TagdTdx;
  798. pBuffer[9] = 0;
  799. pBuffer[10] = __Permedia2TagdTdyDom;
  800. pBuffer[11] = 1 << 20;
  801. pBuffer[12] = __Permedia2TagStartXDom;
  802. pBuffer[13] = rDest.left << 16;
  803. pBuffer[14] = __Permedia2TagStartXSub;
  804. pBuffer[15] = rDest.right << 16;
  805. pBuffer[16] = __Permedia2TagStartY;
  806. pBuffer[17] = rDest.top << 16;
  807. pBuffer[18] = __Permedia2TagdY;
  808. pBuffer[19] = 1 << 16;
  809. pBuffer[20] = __Permedia2TagCount;
  810. pBuffer[21] = rDest.bottom - rDest.top;
  811. pBuffer[22] = __Permedia2TagRender;
  812. pBuffer[23] = __RENDER_TRAPEZOID_PRIMITIVE |
  813. __RENDER_TEXTURED_PRIMITIVE;
  814. }
  815. else
  816. // right->left, bottom->top
  817. {
  818. // set offset of source
  819. pBuffer[0] = __Permedia2TagSStart;
  820. pBuffer[1] = rSrc.right << 20;
  821. pBuffer[2] = __Permedia2TagTStart;
  822. pBuffer[3] = (rSrc.bottom - 1) << 20;
  823. pBuffer[4] = __Permedia2TagdSdx;
  824. pBuffer[5] = (DWORD) (-1 << 20);
  825. pBuffer[6] = __Permedia2TagdSdyDom;
  826. pBuffer[7] = 0;
  827. pBuffer[8] = __Permedia2TagdTdx;
  828. pBuffer[9] = 0;
  829. pBuffer[10] = __Permedia2TagdTdyDom;
  830. pBuffer[11] = (DWORD)(-1 << 20);
  831. // Render right to left, bottom to top
  832. pBuffer[12] = __Permedia2TagStartXDom;
  833. pBuffer[13] = rDest.right << 16;
  834. pBuffer[14] = __Permedia2TagStartXSub;
  835. pBuffer[15] = rDest.left << 16;
  836. pBuffer[16] = __Permedia2TagStartY;
  837. pBuffer[17] = (rDest.bottom - 1) << 16;
  838. pBuffer[18] = __Permedia2TagdY;
  839. pBuffer[19] = (DWORD)(-1 << 16);
  840. pBuffer[20] = __Permedia2TagCount;
  841. pBuffer[21] = rDest.bottom - rDest.top;
  842. pBuffer[22] = __Permedia2TagRender;
  843. pBuffer[23] = __RENDER_TRAPEZOID_PRIMITIVE |
  844. __RENDER_TEXTURED_PRIMITIVE;
  845. }
  846. pBuffer += 24;
  847. InputBufferCommit(ppdev, pBuffer);
  848. prcl++;
  849. }
  850. // restore default state
  851. InputBufferReserve(ppdev, 12, &pBuffer);
  852. pBuffer[0] = __Permedia2TagdY;
  853. pBuffer[1] = INTtoFIXED(1);
  854. pBuffer[2] = __Permedia2TagDitherMode;
  855. pBuffer[3] = 0;
  856. pBuffer[4] = __Permedia2TagYUVMode;
  857. pBuffer[5] = 0x0;
  858. pBuffer[6] = __Permedia2TagTextureAddressMode;
  859. pBuffer[7] = __PERMEDIA_DISABLE;
  860. pBuffer[8] = __Permedia2TagTextureColorMode;
  861. pBuffer[9] = __PERMEDIA_DISABLE;
  862. pBuffer[10] = __Permedia2TagTextureReadMode;
  863. pBuffer[11] = __PERMEDIA_DISABLE;
  864. pBuffer += 12;
  865. InputBufferCommit(ppdev,pBuffer);
  866. }// vTransparentBlt()
  867. //-----------------------------------------------------------------------------
  868. //
  869. // void vSolidFill(GFNPB* ppb)
  870. //
  871. // Fill a set of rectangles with a solid color
  872. //
  873. // Argumentes needed from function block (GFNPB)
  874. //
  875. // ppdev-------PPDev
  876. // psurfDst----Destination surface
  877. // lNumRects---Number of rectangles to fill
  878. // pRects------Pointer to a list of rectangles information which needed to be
  879. // filled
  880. // solidColor--Fill color
  881. //
  882. //-----------------------------------------------------------------------------
  883. VOID
  884. vSolidFill(GFNPB * ppb)
  885. {
  886. PPDev ppdev = ppb->ppdev;
  887. ULONG color = ppb->solidColor;
  888. RECTL * pRect = ppb->pRects;
  889. LONG count = ppb->lNumRects;
  890. Surf* psurf = ppb->psurfDst;
  891. //@@BEGIN_DDKSPLIT
  892. // TODO should call utility function to setup fill color
  893. //@@END_DDKSPLIT
  894. //
  895. // Note: GDI guarantees that the unused bits are set to zero. We have
  896. // an assert in DrvBitBlt to check the color value for unused high bits
  897. // to make it sure that they are zero.
  898. //
  899. if (ppdev->cPelSize == 1)
  900. {
  901. color |= (color << 16);
  902. }
  903. else if (ppdev->cPelSize == 0)
  904. {
  905. color |= color << 8;
  906. color |= color << 16;
  907. }
  908. //
  909. // setup loop invariant state
  910. //
  911. ULONG* pBuffer;
  912. ULONG* pReservationEnd;
  913. ULONG* pBufferEnd;
  914. InputBufferStart(ppdev, 8, &pBuffer, &pBufferEnd, &pReservationEnd);
  915. pBuffer[0] = __Permedia2TagFBBlockColor;
  916. pBuffer[1] = color;
  917. pBuffer[2] = __Permedia2TagFBReadMode;
  918. pBuffer[3] = PM_FBREADMODE_PARTIAL(psurf->ulPackedPP) |
  919. PM_FBREADMODE_PACKEDDATA(__PERMEDIA_DISABLE);
  920. pBuffer[4] = __Permedia2TagLogicalOpMode;
  921. pBuffer[5] = __PERMEDIA_CONSTANT_FB_WRITE;
  922. pBuffer[6] = __Permedia2TagFBWindowBase;
  923. pBuffer[7] = psurf->ulPixOffset;
  924. while(count--)
  925. {
  926. // Render the rectangle
  927. pBuffer = pReservationEnd;
  928. InputBufferContinue(ppdev, 6, &pBuffer, &pBufferEnd, &pReservationEnd);
  929. pBuffer[0] = __Permedia2TagRectangleOrigin;
  930. pBuffer[1] = pRect->top << 16 | pRect->left;
  931. pBuffer[2] = __Permedia2TagRectangleSize;
  932. pBuffer[3] = ((pRect->bottom - pRect->top) << 16) |
  933. (pRect->right - pRect->left);
  934. pBuffer[4] = __Permedia2TagRender;
  935. pBuffer[5] = __RENDER_FAST_FILL_ENABLE | __RENDER_RECTANGLE_PRIMITIVE |
  936. __RENDER_INCREASE_X | __RENDER_INCREASE_Y;
  937. pRect++;
  938. }
  939. pBuffer = pReservationEnd;
  940. InputBufferCommit(ppdev, pBuffer);
  941. }// vSolidFill()
  942. //-----------------------------------------------------------------------------
  943. //
  944. // VOID vInvert
  945. //
  946. // Fill a set of rectangles with a solid color
  947. //
  948. // Argumentes needed from function block (GFNPB)
  949. //
  950. // ppdev-------PPDev
  951. // psurfDst----Pointer to device surface
  952. // lNumRects---Number of clipping rectangles
  953. // pRect-------Array of clipping rectangles
  954. //
  955. //-----------------------------------------------------------------------------
  956. VOID
  957. vInvert(GFNPB * ppb)
  958. {
  959. PPDev ppdev = ppb->ppdev;
  960. RECTL * pRect = ppb->pRects;
  961. LONG count = ppb->lNumRects;
  962. Surf* psurf = ppb->psurfDst;
  963. ULONG* pBuffer;
  964. // setup loop invariant state
  965. InputBufferReserve(ppdev, 6, &pBuffer);
  966. pBuffer[0] = __Permedia2TagFBWindowBase;
  967. pBuffer[1] = psurf->ulPixOffset;
  968. pBuffer[2] = __Permedia2TagFBReadMode;
  969. pBuffer[3] = PM_FBREADMODE_PARTIAL(psurf->ulPackedPP) |
  970. PM_FBREADMODE_READDEST(__PERMEDIA_ENABLE);
  971. pBuffer[4] = __Permedia2TagLogicalOpMode;
  972. pBuffer[5] = P2_ENABLED_LOGICALOP(K_LOGICOP_INVERT);
  973. pBuffer += 6;
  974. InputBufferCommit(ppdev, pBuffer);
  975. while(count--)
  976. {
  977. // Render the rectangle
  978. InputBufferReserve(ppdev, 6, &pBuffer);
  979. pBuffer[0] = __Permedia2TagRectangleOrigin;
  980. pBuffer[1] = (pRect->top << 16) | pRect->left;
  981. pBuffer[2] = __Permedia2TagRectangleSize;
  982. pBuffer[3] = ((pRect->bottom - pRect->top) << 16)
  983. | (pRect->right - pRect->left);
  984. pBuffer[4] = __Permedia2TagRender;
  985. pBuffer[5] = __RENDER_RECTANGLE_PRIMITIVE
  986. | __RENDER_INCREASE_X
  987. | __RENDER_INCREASE_Y;
  988. pBuffer += 6;
  989. InputBufferCommit(ppdev, pBuffer);
  990. pRect++;
  991. }
  992. }// vInvert()
  993. //-----------------------------------------------------------------------------
  994. //
  995. // void vSolidFillWithRop(GFNPB* ppb)
  996. //
  997. // Fill a set of rectangles with a solid color based on the given lLogicOP.
  998. //
  999. // Argumentes needed from function block (GFNPB)
  1000. //
  1001. // ppdev-------PPDev
  1002. // psurfDst----Destination surface
  1003. // lNumRects---Number of rectangles to fill
  1004. // pRects------Pointer to a list of rectangles information which needed to be
  1005. // filled
  1006. // solidColor--Fill color
  1007. // ulRop4------Logic OP for the fill
  1008. //
  1009. //-----------------------------------------------------------------------------
  1010. //@@BEGIN_DDKSPLIT
  1011. // TODO: Some clean up: Why are we calculating lLeft andn lRight
  1012. // but use pRcl->left and pRcl->right below.
  1013. //@@END_DDKSPLIT
  1014. VOID
  1015. vSolidFillWithRop(GFNPB* ppb)
  1016. {
  1017. PPDev ppdev = ppb->ppdev;
  1018. Surf* psurfDst = ppb->psurfDst;
  1019. DWORD dwExtra = 0;
  1020. DWORD dwRenderBits;
  1021. DWORD dwShift = 0;
  1022. DWORD dwWindowBase = psurfDst->ulPixOffset;
  1023. LONG lLeft;
  1024. LONG lNumOfRects = ppb->lNumRects; // Number of rectangles
  1025. LONG lRight;
  1026. RECTL* pRcl = ppb->pRects;
  1027. ULONG ulColor = ppb->solidColor; // Brush solid fill color
  1028. ULONG ulLogicOP = ulRop3ToLogicop(ppb->ulRop4 & 0xFF);
  1029. // Hardware mix mode
  1030. // (foreground mix mode if
  1031. // the brush has a mask)
  1032. ULONG* pBuffer;
  1033. DBG_GDI((6,"vSolidFillWithRop: numRects = %ld Rop4 = 0x%x",
  1034. lNumOfRects, ppb->ulRop4));
  1035. //
  1036. // Setup logic OP invariant state
  1037. //
  1038. InputBufferReserve(ppdev, 2, &pBuffer);
  1039. pBuffer[0] = __Permedia2TagFBWindowBase;
  1040. pBuffer[1] = dwWindowBase;
  1041. pBuffer += 2;
  1042. InputBufferCommit(ppdev, pBuffer);
  1043. switch ( ulLogicOP )
  1044. {
  1045. case K_LOGICOP_COPY:
  1046. DBG_GDI((6,"vSolidFillWithRop: COPY"));
  1047. //
  1048. // For SRC_COPY, we can use fastfill
  1049. //
  1050. dwRenderBits = __RENDER_FAST_FILL_ENABLE
  1051. | __RENDER_TRAPEZOID_PRIMITIVE
  1052. | __RENDER_INCREASE_Y
  1053. | __RENDER_INCREASE_X;
  1054. //
  1055. // Setup color data based on current color mode we are in
  1056. //
  1057. if ( ppdev->cPelSize == 1 )
  1058. {
  1059. //
  1060. // We are in 16 bit packed mode. So the color data must be
  1061. // repeated in both halves of the FBBlockColor register
  1062. //
  1063. ASSERTDD((ulColor & 0xFFFF0000) == 0,
  1064. "vSolidFillWithRop: upper bits not zero");
  1065. ulColor |= (ulColor << 16);
  1066. }
  1067. else if ( ppdev->cPelSize == 0 )
  1068. {
  1069. //
  1070. // We are in 8 bit packed mode. So the color data must be
  1071. // repeated in all 4 bytes of the FBBlockColor register
  1072. //
  1073. ASSERTDD((ulColor & 0xFFFFFF00) == 0,
  1074. "vSolidFillWithRop: upper bits not zero");
  1075. ulColor |= ulColor << 8;
  1076. ulColor |= ulColor << 16;
  1077. }
  1078. //
  1079. // Setup some loop invariant states
  1080. //
  1081. InputBufferReserve(ppdev, 6, &pBuffer);
  1082. pBuffer[0] = __Permedia2TagLogicalOpMode;
  1083. pBuffer[1] = __PERMEDIA_CONSTANT_FB_WRITE;
  1084. pBuffer[2] = __Permedia2TagFBReadMode;
  1085. pBuffer[3] = PM_FBREADMODE_PARTIAL(psurfDst->ulPackedPP)
  1086. | PM_FBREADMODE_PACKEDDATA(__PERMEDIA_DISABLE);
  1087. pBuffer[4] = __Permedia2TagFBBlockColor;
  1088. pBuffer[5] = ulColor;
  1089. pBuffer += 6;
  1090. InputBufferCommit(ppdev, pBuffer);
  1091. break;
  1092. case K_LOGICOP_INVERT:
  1093. DBG_GDI((6,"vSolidFillWithRop: INVERT"));
  1094. dwRenderBits = __RENDER_TRAPEZOID_PRIMITIVE
  1095. | __RENDER_INCREASE_Y
  1096. | __RENDER_INCREASE_X;
  1097. //
  1098. // When using packed operations we have to convert the left and
  1099. // right X coordinates into 32-bit-based quantities, we do this by
  1100. // shifting. We also have to round up the right X co-ord if the
  1101. // pixels don't fill a DWORD. Not a problem for 32BPP.
  1102. //
  1103. dwShift = 2 - (ppdev->cPelSize);
  1104. if ( dwShift )
  1105. {
  1106. dwExtra = (dwShift << 1) - 1;
  1107. }
  1108. else
  1109. {
  1110. dwExtra = 0;
  1111. }
  1112. //
  1113. // setup some loop invariant states
  1114. //
  1115. InputBufferReserve(ppdev, 6, &pBuffer);
  1116. pBuffer[0] = __Permedia2TagLogicalOpMode;
  1117. pBuffer[1] = __PERMEDIA_DISABLE;
  1118. pBuffer[2] = __Permedia2TagFBReadMode;
  1119. pBuffer[3] = PM_FBREADMODE_PARTIAL(psurfDst->ulPackedPP)
  1120. | PM_FBREADMODE_PACKEDDATA(__PERMEDIA_DISABLE);
  1121. pBuffer[4] = __Permedia2TagConfig;
  1122. pBuffer[5] = __PERMEDIA_CONFIG_LOGICOP(ulLogicOP)
  1123. | __PERMEDIA_CONFIG_FBWRITE
  1124. | __PERMEDIA_CONFIG_PACKED_DATA
  1125. | ConfigReadDest[ulLogicOP];
  1126. pBuffer += 6;
  1127. InputBufferCommit(ppdev, pBuffer);
  1128. break;
  1129. default:
  1130. DBG_GDI((6,"vSolidFillWithRop: numRects %ld, Rop4=0x%x color=0x%lx",
  1131. lNumOfRects, ppb->ulRop4, ulColor));
  1132. dwRenderBits = __RENDER_TRAPEZOID_PRIMITIVE
  1133. | __RENDER_INCREASE_Y
  1134. | __RENDER_INCREASE_X;
  1135. InputBufferReserve(ppdev, 8, &pBuffer);
  1136. pBuffer[0] = __Permedia2TagLogicalOpMode;
  1137. pBuffer[1] = __PERMEDIA_DISABLE;
  1138. pBuffer[2] = __Permedia2TagFBReadMode;
  1139. pBuffer[3] = PM_FBREADMODE_PARTIAL(psurfDst->ulPackedPP);
  1140. pBuffer[4] = __Permedia2TagConstantColor;
  1141. pBuffer[5] = ulColor;
  1142. pBuffer[6] = __Permedia2TagConfig;
  1143. pBuffer[7] = __PERMEDIA_CONFIG_LOGICOP(ulLogicOP)
  1144. | __PERMEDIA_CONFIG_FBWRITE
  1145. | __PERMEDIA_CONFIG_COLOR_DDA
  1146. | ConfigReadDest[ulLogicOP];
  1147. pBuffer += 8;
  1148. InputBufferCommit(ppdev, pBuffer);
  1149. break;
  1150. }// switch( ulLogicOP )
  1151. //
  1152. // Loop through all the rectangles and fill them
  1153. //
  1154. for(;;)
  1155. {
  1156. //
  1157. // Calculate the left and right pixels from the rectangle.
  1158. //
  1159. lLeft = pRcl->left;
  1160. lRight = pRcl->right;
  1161. InputBufferReserve(ppdev, 12, &pBuffer);
  1162. //
  1163. // If we need to set up the packed data limits then do it, also convert
  1164. // the left and right X coordinates to DWORD-based numbers, with a bit
  1165. // of rounding
  1166. //
  1167. if ( ulLogicOP == K_LOGICOP_INVERT )
  1168. {
  1169. pBuffer[0] = __Permedia2TagPackedDataLimits;
  1170. pBuffer[1] = (lLeft << 16) | lRight;
  1171. pBuffer += 2;
  1172. lLeft >>= dwShift;
  1173. lRight = (lRight + dwExtra) >> dwShift;
  1174. }
  1175. pBuffer[0] = __Permedia2TagStartXDom;
  1176. pBuffer[1] = pRcl->left << 16;
  1177. pBuffer[2] = __Permedia2TagStartXSub;
  1178. pBuffer[3] = pRcl->right << 16;
  1179. pBuffer[4] = __Permedia2TagStartY;
  1180. pBuffer[5] = pRcl->top << 16;
  1181. pBuffer[6] = __Permedia2TagCount;
  1182. pBuffer[7] = pRcl->bottom - pRcl->top;
  1183. pBuffer[8] = __Permedia2TagRender;
  1184. pBuffer[9] = dwRenderBits;
  1185. pBuffer += 10;
  1186. InputBufferCommit(ppdev, pBuffer);
  1187. if ( --lNumOfRects == 0 )
  1188. {
  1189. break;
  1190. }
  1191. //
  1192. // Move onto the next rectangle
  1193. //
  1194. ++pRcl;
  1195. } // for()
  1196. //
  1197. // Restore the DDA mode
  1198. //
  1199. InputBufferReserve(ppdev, 2, &pBuffer);
  1200. pBuffer[0] = __Permedia2TagColorDDAMode;
  1201. pBuffer[1] = __PERMEDIA_DISABLE;
  1202. pBuffer += 2;
  1203. InputBufferCommit(ppdev, pBuffer);
  1204. }// vSolidFillWithRop()