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.

856 lines
28 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * *******************
  4. * * GDI SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: patnfill.c
  8. *
  9. * Contains all the pattern fill 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. #include "directx.h"
  17. //-----------------------------Note--------------------------------------------
  18. //
  19. // A Note on brushes
  20. //
  21. // Out cached brushes are 64x64. Here is the reason. The minimum brush
  22. // size that we can use as a pattern is 32.
  23. //
  24. // Now, we need to be able to offset the pattern when rendering in x and y
  25. // by as much as 7 pixels in either direction. The P2
  26. // hardware does not have a simple x/Y pattern offset mechanism. Instead
  27. // we are forced to offset the origin by offsetting the base address of the
  28. // pattern. This requires that we store in memory a pattern that is
  29. // 39 pixels wide. However, the stride still needs to be acceptable to the
  30. // texture address generation hardware. The next valid stride is 64.
  31. //
  32. // That's why we have 64x64 pattern brushes in our cache.
  33. //
  34. // Note also that we over do it when caching duplicating the brush to fill
  35. // up the entire 64x64 even though we only use 39x39. We might change
  36. // this in the near future.
  37. //
  38. //-----------------------------------------------------------------------------
  39. //-----------------------------------------------------------------------------
  40. //
  41. // VOID vMonoOffset(GFNPB* ppb)
  42. //
  43. // Update the offset to be used in the area stipple unit. We do this for a
  44. // mono brush which is realized in the hardware but whose alignment has simply
  45. // changed. This avoids a full scale realization.
  46. //
  47. // Argumentes needed from function block (GFNPB)
  48. //
  49. // ppdev-------PPDev
  50. // prbrush-----Pointer to the RBrush structure
  51. // pptlBrush---Pointer to pointer brush structure
  52. //
  53. //-----------------------------------------------------------------------------
  54. VOID
  55. vMonoOffset(GFNPB* ppb)
  56. {
  57. PPDev ppdev = ppb->ppdev;
  58. DWORD dwMode;
  59. POINTL* pptlBrush = ppb->pptlBrush;
  60. RBrush* prb = ppb->prbrush;
  61. PERMEDIA_DECL;
  62. DBG_GDI((6, "vMonoOffset started"));
  63. //
  64. // Construct the AreaStippleMode value. It contains the pattern size,
  65. // the offset for the brush origin and the enable bit. Remember the
  66. // offset so we can later check if it changes and update the hardware.
  67. // Remember the mode so we can do a mirrored stipple easily.
  68. //
  69. prb->ptlBrushOrg.x = pptlBrush->x;
  70. prb->ptlBrushOrg.y = pptlBrush->y;
  71. dwMode = __PERMEDIA_ENABLE
  72. | AREA_STIPPLE_XSEL(__PERMEDIA_AREA_STIPPLE_32_PIXEL_PATTERN)
  73. | AREA_STIPPLE_YSEL(__PERMEDIA_AREA_STIPPLE_8_PIXEL_PATTERN)
  74. | AREA_STIPPLE_MIRROR_X
  75. | AREA_STIPPLE_XOFF(8 - (prb->ptlBrushOrg.x & 7))
  76. | AREA_STIPPLE_YOFF(8 - (prb->ptlBrushOrg.y & 7));
  77. prb->areaStippleMode = dwMode;
  78. DBG_GDI((7, "setting new area stipple offset to %d, %d",
  79. 8 - (prb->ptlBrushOrg.x & 7), 8 - (prb->ptlBrushOrg.y & 7)));
  80. ULONG* pBuffer;
  81. InputBufferReserve(ppdev, 2, &pBuffer);
  82. pBuffer[0] = __Permedia2TagAreaStippleMode;
  83. pBuffer[1] = dwMode;
  84. pBuffer += 2;
  85. InputBufferCommit(ppdev, pBuffer);
  86. }// vMonoOffset()
  87. //-----------------------------------------------------------------------------
  88. //
  89. // VOID vPatRealize(GFNPB* ppb)
  90. //
  91. // This routine transfers an 8x8 pattern to off-screen display memory, and
  92. // duplicates it to make a 32x32 cached realization which is then used by
  93. // vPatFill.
  94. //
  95. // Argumentes needed from function block (GFNPB)
  96. //
  97. // ppdev-------PPDev
  98. // prbrush-----Pointer to the RBrush structure
  99. //
  100. //-----------------------------------------------------------------------------
  101. VOID
  102. vPatRealize(GFNPB* ppb)
  103. {
  104. PDev* ppdev = ppb->ppdev;
  105. RBrush* prb = ppb->prbrush; // Points to brush realization structure
  106. BrushEntry* pbe = prb->pbe;
  107. BYTE* pcSrc;
  108. LONG lNextCachedBrush;
  109. LONG lTemp;
  110. LONG lPelSize;
  111. ULONG* pBuffer;
  112. PERMEDIA_DECL;
  113. // VALIDATE_GDI_CONTEXT;
  114. DBG_GDI((6, "vPatRealize started"));
  115. if ( (pbe == NULL) || (pbe->prbVerify != prb) )
  116. {
  117. //
  118. // Mono brushes are realized into the area stipple unit. For this we
  119. // have a set of special BRUSHENTRYs, one for each board.
  120. //
  121. if ( prb->fl & RBRUSH_2COLOR )
  122. {
  123. //
  124. // 1 BPP patten
  125. //
  126. DBG_GDI((7, "loading mono brush into cache"));
  127. pbe = &ppdev->abeMono;
  128. pbe->prbVerify = prb;
  129. prb->pbe = pbe;
  130. }
  131. else
  132. {
  133. //
  134. // We have to allocate a new off-screen cache brush entry for
  135. // the brush
  136. //
  137. lNextCachedBrush = ppdev->lNextCachedBrush; // Get the next index
  138. pbe = &ppdev->abe[lNextCachedBrush]; // Get the brush entry
  139. //
  140. // Check if this index is out of the total brush stamps cached
  141. // If yes, rotate to the 1st one
  142. //
  143. lNextCachedBrush++;
  144. if ( lNextCachedBrush >= ppdev->cBrushCache )
  145. {
  146. lNextCachedBrush = 0;
  147. }
  148. //
  149. // Reset the next brush to be allocated
  150. //
  151. ppdev->lNextCachedBrush = lNextCachedBrush;
  152. //
  153. // Update our links:
  154. //
  155. pbe->prbVerify = prb;
  156. prb->pbe = pbe;
  157. DBG_GDI((7, "new cache entry allocated for color brush"));
  158. }// Get cached brush entry depends on its color depth
  159. }// If the brush is not cached
  160. //
  161. // We're going to load mono patterns into the area stipple and set the
  162. // start offset to the brush origin. WARNING: we assume that we are
  163. // running little endian. I believe this is always true for NT.
  164. //
  165. if ( prb->fl & RBRUSH_2COLOR )
  166. {
  167. //
  168. // 1 BPP patten
  169. //
  170. DWORD* pdwSrc = &prb->aulPattern[0];
  171. //
  172. // This function loads the stipple offset into the hardware. We also
  173. // call this function on its own if the brush is realized but its
  174. // offset changes. In that case we don't have to go through a complete
  175. // realize again.
  176. //
  177. ppb->prbrush = prb;
  178. (*ppdev->pgfnMonoOffset)(ppb);
  179. DBG_GDI((7, "area stipple pattern:"));
  180. InputBufferReserve(ppdev, 16, &pBuffer);
  181. for ( lTemp = 0; lTemp < 8; ++lTemp, ++pdwSrc )
  182. {
  183. pBuffer[0] = __Permedia2TagAreaStipplePattern0 + lTemp;
  184. pBuffer[1] = *pdwSrc;
  185. pBuffer += 2;
  186. }
  187. InputBufferCommit(ppdev, pBuffer);
  188. DBG_GDI((7, "area stipple downloaded. vPatRealize done"));
  189. return;
  190. }// 1 BPP case
  191. lPelSize = ppdev->cPelSize;
  192. pcSrc = (BYTE*)&prb->aulPattern[0]; // Copy from brush buffer
  193. InputBufferReserve(ppdev, 12 + 65, &pBuffer);
  194. pBuffer[0] = __Permedia2TagFBWindowBase;
  195. pBuffer[1] = pbe->ulPixelOffset;
  196. pBuffer[2] = __Permedia2TagFBReadMode;
  197. pBuffer[3] = PM_FBREADMODE_PARTIAL(ppdev->ulBrushPackedPP);
  198. pBuffer[4] = __Permedia2TagLogicalOpMode;
  199. pBuffer[5] = __PERMEDIA_DISABLE;
  200. pBuffer[6] = __Permedia2TagRectangleOrigin;
  201. pBuffer[7] = 0;
  202. pBuffer[8] = __Permedia2TagRectangleSize;
  203. pBuffer[9] = (8 << 16) | 8;
  204. pBuffer[10] = __Permedia2TagRender;
  205. pBuffer[11] = __RENDER_RECTANGLE_PRIMITIVE
  206. | __RENDER_SYNC_ON_HOST_DATA
  207. | __RENDER_INCREASE_Y
  208. | __RENDER_INCREASE_X;
  209. pBuffer += 12;
  210. *pBuffer++ = (63 << 16) | __Permedia2TagColor;
  211. switch( lPelSize )
  212. {
  213. case 0:
  214. for ( lTemp = 0; lTemp < 64; ++lTemp )
  215. {
  216. *pBuffer++ = pcSrc[lTemp];
  217. }
  218. break;
  219. case 1:
  220. for ( lTemp = 0; lTemp < 64; ++lTemp )
  221. {
  222. *pBuffer++ = ((USHORT *) pcSrc)[lTemp];
  223. }
  224. break;
  225. case 2:
  226. for ( lTemp = 0; lTemp < 64; ++lTemp )
  227. {
  228. *pBuffer++ = ((ULONG *) pcSrc)[lTemp];
  229. }
  230. break;
  231. }
  232. InputBufferCommit(ppdev, pBuffer);
  233. // ���������
  234. // �0�1�2 � We now have an 8x8 colour-expanded copy of
  235. // ��������� the pattern sitting in off-screen memory,
  236. // �5 � represented here by square '0'.
  237. // � �
  238. // � � We're now going to expand the pattern to
  239. // � � 64x64 by repeatedly copying larger rectangles
  240. // � � in the indicated order, and doing a 'rolling'
  241. // � � blt to copy vertically.
  242. // � �
  243. // ���������
  244. InputBufferReserve(ppdev, 36, &pBuffer);
  245. pBuffer[0] = __Permedia2TagFBReadMode;
  246. pBuffer[1] = PM_FBREADMODE_PARTIAL(ppdev->ulBrushPackedPP)
  247. | __FB_READ_SOURCE;
  248. pBuffer[2] = __Permedia2TagStartXDom;
  249. pBuffer[3] = INTtoFIXED(8);
  250. pBuffer[4] = __Permedia2TagStartXSub;
  251. pBuffer[5] = INTtoFIXED(16);
  252. pBuffer[6] = __Permedia2TagFBSourceOffset;
  253. pBuffer[7] = -8;
  254. pBuffer[8] = __Permedia2TagRender;
  255. pBuffer[9] = __RENDER_TRAPEZOID_PRIMITIVE;
  256. pBuffer[10] = __Permedia2TagStartXDom;
  257. pBuffer[11] = INTtoFIXED(16);
  258. pBuffer[12] = __Permedia2TagStartXSub;
  259. pBuffer[13] = INTtoFIXED(32);
  260. pBuffer[14] = __Permedia2TagFBSourceOffset;
  261. pBuffer[15] = -16;
  262. pBuffer[16] = __Permedia2TagRender;
  263. pBuffer[17] = __RENDER_TRAPEZOID_PRIMITIVE;
  264. pBuffer[18] = __Permedia2TagStartXDom;
  265. pBuffer[19] = INTtoFIXED(32);
  266. pBuffer[20] = __Permedia2TagStartXSub;
  267. pBuffer[21] = INTtoFIXED(64);
  268. pBuffer[22] = __Permedia2TagFBSourceOffset;
  269. pBuffer[23] = -32;
  270. pBuffer[24] = __Permedia2TagRender;
  271. pBuffer[25] = __RENDER_TRAPEZOID_PRIMITIVE;
  272. //
  273. // Now rolling copy downward.
  274. //
  275. pBuffer[26] = __Permedia2TagStartXDom;
  276. pBuffer[27] = INTtoFIXED(0);
  277. pBuffer[28] = __Permedia2TagStartY;
  278. pBuffer[29] = INTtoFIXED(8);
  279. pBuffer[30] = __Permedia2TagFBSourceOffset;
  280. pBuffer[31] = -(CACHED_BRUSH_WIDTH << 3);
  281. pBuffer[32] = __Permedia2TagCount;
  282. pBuffer[33] = CACHED_BRUSH_HEIGHT - 8;
  283. pBuffer[34] = __Permedia2TagRender;
  284. pBuffer[35] = __RENDER_TRAPEZOID_PRIMITIVE;
  285. pBuffer += 36;
  286. InputBufferCommit(ppdev, pBuffer);
  287. }// vPatRealize()
  288. //-----------------------------------------------------------------------------
  289. //
  290. // VOID vMonoPatFill(GFNPB* ppb)
  291. //
  292. // Fill a series of rectangles with a monochrome pattern previously loaded
  293. // into the area stipple unit. If bTransparent is false we must do each
  294. // rectangle twice, inverting the stipple pattern in the second go.
  295. //
  296. // Argumentes needed from function block (GFNPB)
  297. //
  298. // ppdev-------PPDev
  299. // psurfDst----Destination surface
  300. // lNumRects---Number of rectangles to fill
  301. // pRects------Pointer to a list of rectangles information which needed to be
  302. // filled
  303. // ucFgRop3----Foreground Logic OP for the fill
  304. // ucBgRop3----Background Logic OP for the fill
  305. // prbrush-----Pointer to the RBrush structure
  306. // pptlBrush---Structure for brush origin
  307. //
  308. //-----------------------------------------------------------------------------
  309. VOID
  310. vMonoPatFill(GFNPB* ppb)
  311. {
  312. PPDev ppdev = ppb->ppdev;
  313. Surf* psurf = ppb->psurfDst;
  314. RBrush* prb = ppb->prbrush;
  315. POINTL* pptlBrush = ppb->pptlBrush;
  316. BrushEntry* pbe = prb->pbe; // Brush entry
  317. RECTL* pRect = ppb->pRects; // List of rectangles to be
  318. // filled in relative
  319. // coordinates
  320. ULONG* pBuffer;
  321. DWORD dwColorMode;
  322. DWORD dwColorReg;
  323. DWORD dwLogicMode;
  324. DWORD dwReadMode;
  325. LONG lNumPass;
  326. LONG lNumRects; // Can't be zero
  327. // ULONG ulBgLogicOp = ulRop3ToLogicop(ppb->ucBgRop3);
  328. ULONG ulBgLogicOp = ulRop3ToLogicop(ppb->ulRop4 >> 8);
  329. // Not used (unless the brush
  330. // has a mask, in which case it
  331. // is the background mix mode)
  332. // ULONG ulFgLogicOp = ulRop3ToLogicop(ppb->ucFgRop3);
  333. ULONG ulFgLogicOp = ulRop3ToLogicop(ppb->ulRop4 & 0xFF);
  334. // Hardware mix mode
  335. // (foreground mix mode if
  336. // the brush has a mask)
  337. ULONG ulBgColor = prb->ulBackColor;
  338. ULONG ulFgColor = prb->ulForeColor;
  339. ULONG ulCurrentFillColor;
  340. ULONG ulCurrentLogicOp;
  341. PERMEDIA_DECL;
  342. DBG_GDI((6, "vMonoPatFill called: %d rects. ulRop4 = %x",
  343. ppb->lNumRects, ppb->ulRop4));
  344. // DBG_GDI((6, "ulFgLogicOp = 0x%x, ulBgLogicOp = 0x%x",
  345. // ulFgLogicOp, ulBgLogicOp));
  346. DBG_GDI((6, "ulFgColor 0x%x, ulBgColor 0x%x", ulFgColor, ulBgColor));
  347. //
  348. // If anything has changed with the brush we must re-realize it. If the
  349. // brush has been kicked out of the area stipple unit we must fully realize
  350. // it. If only the alignment has changed we can simply update the alignment
  351. // for the stipple.
  352. //
  353. if ( (pbe == NULL) || (pbe->prbVerify != prb) )
  354. {
  355. DBG_GDI((7, "full brush realize"));
  356. (*ppdev->pgfnPatRealize)(ppb);
  357. }
  358. else if ( (prb->ptlBrushOrg.x != pptlBrush->x)
  359. ||(prb->ptlBrushOrg.y != pptlBrush->y) )
  360. {
  361. DBG_GDI((7, "changing brush offset"));
  362. (*ppdev->pgfnMonoOffset)(ppb);
  363. }
  364. //
  365. // We get some common operations which are really noops. we can save
  366. // lots of time by cutting these out. As this happens a lot for masking
  367. // operations it's worth doing.
  368. //
  369. if ( ((ulFgLogicOp == K_LOGICOP_AND) && (ulFgColor == ppdev->ulWhite))
  370. ||((ulFgLogicOp == K_LOGICOP_XOR) && (ulFgColor == 0)) )
  371. {
  372. DBG_GDI((7, "Set FgLogicOp to NOOP"));
  373. ulFgLogicOp = K_LOGICOP_NOOP;
  374. }
  375. //
  376. // Same for background
  377. //
  378. if ( ((ulBgLogicOp == K_LOGICOP_AND) && (ulBgColor == ppdev->ulWhite))
  379. ||((ulBgLogicOp == K_LOGICOP_XOR) && (ulBgColor == 0)) )
  380. {
  381. DBG_GDI((7, "Set BgLogicOp to NOOP"));
  382. ulBgLogicOp = K_LOGICOP_NOOP;
  383. }
  384. //
  385. // Try to do the background as a solid fill. lNumPass starts at 1 rather
  386. // than 2 because we want to do all comparisons with zero. This is faster.
  387. // We also do a trick with its value to avoid an extra WAIT_FIFO on the
  388. // first pass.
  389. //
  390. if ( (ulBgLogicOp == K_LOGICOP_COPY)
  391. &&(ulFgLogicOp == K_LOGICOP_COPY) )
  392. {
  393. DBG_GDI((7, "FgLogicOp and BgLogicOp are COPY"));
  394. //
  395. // For PatCopy case, we can use solid fill to fill the background first
  396. // Note: we do not need to set FBWindowBase, it will be set by
  397. // the solid fill
  398. //
  399. ppb->solidColor = ulBgColor;
  400. (*ppdev->pgfnSolidFill)(ppb);
  401. //
  402. // We've done the background so we only want to go round the stipple
  403. // loop once. So set the lNumPass counter up for only one loop and set
  404. // the ulCurrentLogicOp and color to the foreground values.
  405. //
  406. lNumPass = 0;
  407. ulCurrentFillColor = ulFgColor;
  408. ulCurrentLogicOp = ulFgLogicOp;
  409. //
  410. // Do this here in case the solid fill changed the packing.
  411. //
  412. // brh not needed
  413. // P2_DEFAULT_FB_DEPTH;
  414. }
  415. else
  416. {
  417. //
  418. // For non-PATCOPY cases, we have to do 2 passes. Fill the background
  419. // first and then fill the foreground
  420. //
  421. lNumPass = 1;
  422. ulCurrentFillColor = ulBgColor;
  423. ulCurrentLogicOp = ulBgLogicOp;
  424. //
  425. // Note: In this case, dxDom, dXSub and dY are initialised to 0, 0,
  426. // and 1, so we don't need to re-load them here. But we need to set
  427. // WindowBase here
  428. //
  429. InputBufferReserve(ppdev, 2, &pBuffer);
  430. pBuffer[0] = __Permedia2TagFBWindowBase;
  431. pBuffer[1] = psurf->ulPixOffset;
  432. pBuffer += 2;
  433. InputBufferCommit(ppdev, pBuffer);
  434. }// if-else for LOGICOP_COPY case
  435. //
  436. // Do 2 passes loop or single loop depends on "lNumPass"
  437. //
  438. while ( TRUE )
  439. {
  440. if ( ulCurrentLogicOp != K_LOGICOP_NOOP )
  441. {
  442. dwReadMode = psurf->ulPackedPP;
  443. if ( ulCurrentLogicOp == K_LOGICOP_COPY )
  444. {
  445. DBG_GDI((7, "Current logicOP is COPY"));
  446. dwColorReg = __Permedia2TagFBWriteData;
  447. dwColorMode = __PERMEDIA_DISABLE;
  448. dwLogicMode = __PERMEDIA_CONSTANT_FB_WRITE;
  449. }
  450. else
  451. {
  452. DBG_GDI((7, "Current logicOP is NOT-COPY"));
  453. dwColorReg = __Permedia2TagConstantColor;
  454. dwColorMode = __COLOR_DDA_FLAT_SHADE;
  455. dwLogicMode = P2_ENABLED_LOGICALOP(ulCurrentLogicOp);
  456. dwReadMode |= LogicopReadDest[ulCurrentLogicOp];
  457. }
  458. //
  459. // On the bg fill pass, we have to invert the sense of the
  460. // download bits. On the first pass, lNumPass == 1; on the second
  461. // pass, lNumPass == 0, so we get our WAIT_FIFO sums correct!!
  462. //
  463. InputBufferReserve(ppdev, 10, &pBuffer);
  464. if ( lNumPass > 0 )
  465. {
  466. pBuffer[0] = __Permedia2TagAreaStippleMode;
  467. pBuffer[1] = (prb->areaStippleMode
  468. | AREA_STIPPLE_INVERT_PAT);
  469. pBuffer += 2;
  470. }
  471. pBuffer[0] = __Permedia2TagColorDDAMode;
  472. pBuffer[1] = dwColorMode;
  473. pBuffer[2] = __Permedia2TagFBReadMode;
  474. pBuffer[3] = dwReadMode;
  475. pBuffer[4] = __Permedia2TagLogicalOpMode;
  476. pBuffer[5] = dwLogicMode;
  477. pBuffer[6] = dwColorReg,
  478. pBuffer[7] = ulCurrentFillColor;
  479. pBuffer += 8;
  480. InputBufferCommit(ppdev, pBuffer);
  481. //
  482. // Fill rects one by one
  483. //
  484. lNumRects = ppb->lNumRects;
  485. while ( TRUE )
  486. {
  487. DBG_GDI((7, "mono pattern fill to rect (%d,%d) to (%d,%d)",
  488. pRect->left,
  489. pRect->top,
  490. pRect->right,
  491. pRect->bottom));
  492. InputBufferReserve(ppdev, 12, &pBuffer);
  493. //
  494. // Render the rectangle
  495. //
  496. pBuffer[0] = __Permedia2TagStartXDom;
  497. pBuffer[1] = pRect->left << 16;
  498. pBuffer[2] = __Permedia2TagStartXSub;
  499. pBuffer[3] = pRect->right << 16;
  500. pBuffer[4] = __Permedia2TagStartY;
  501. pBuffer[5] = pRect->top << 16;
  502. pBuffer[6] = __Permedia2TagdY;
  503. pBuffer[7] = 1 << 16;
  504. pBuffer[8] = __Permedia2TagCount;
  505. pBuffer[9] = pRect->bottom - pRect->top;
  506. pBuffer[10] = __Permedia2TagRender;
  507. pBuffer[11] = __RENDER_TRAPEZOID_PRIMITIVE
  508. |__RENDER_AREA_STIPPLE_ENABLE;
  509. pBuffer += 12;
  510. InputBufferCommit(ppdev, pBuffer);
  511. if ( --lNumRects == 0 )
  512. {
  513. break;
  514. }
  515. pRect++;
  516. }// loop through all the rectangles
  517. //
  518. // Reset our pixel values.
  519. //
  520. InputBufferReserve(ppdev, 2, &pBuffer);
  521. pBuffer[0] = __Permedia2TagLogicalOpMode;
  522. pBuffer[1] = __PERMEDIA_DISABLE;
  523. pBuffer += 2;
  524. InputBufferCommit(ppdev, pBuffer);
  525. //
  526. // We must reset the area stipple mode for the foreground pass. if
  527. // there's no foreground pass we must reset it anyway.
  528. //
  529. if ( lNumPass > 0 )
  530. {
  531. InputBufferReserve(ppdev, 2, &pBuffer);
  532. pBuffer[0] = __Permedia2TagAreaStippleMode;
  533. pBuffer[1] = prb->areaStippleMode;
  534. pBuffer += 2;
  535. InputBufferCommit(ppdev, pBuffer);
  536. }
  537. }// if ( ulCurrentLogicOp != K_LOGICOP_NOOP )
  538. if ( --lNumPass < 0 )
  539. {
  540. break;
  541. }
  542. //
  543. // We need to the 2nd pass. So reset the rectangle info, color mode
  544. // and logicop status
  545. //
  546. pRect = ppb->pRects;
  547. ulCurrentFillColor = ulFgColor;
  548. ulCurrentLogicOp = ulFgLogicOp;
  549. }// Loop through all the passes
  550. if ( dwColorMode != __PERMEDIA_DISABLE )
  551. {
  552. InputBufferReserve(ppdev, 2, &pBuffer);
  553. //
  554. // Restore ColorDDAMode
  555. //
  556. pBuffer[0] = __Permedia2TagColorDDAMode;
  557. pBuffer[1] = __PERMEDIA_DISABLE;
  558. pBuffer += 2;
  559. InputBufferCommit(ppdev, pBuffer);
  560. }
  561. DBG_GDI((6, "vMonoPatFill returning"));
  562. }// vMonoPatFill()
  563. //-----------------------------------------------------------------------------
  564. //
  565. // VOID vPatFill(GFNPB* ppb)
  566. //
  567. // Function to fill a set of rectangles with a given pattern. Colored patterns
  568. // only. Monochrome patterns are handled in a different routine. This routine
  569. // only handles patterns which were not rotated in memory and which have been
  570. // replicated in X to cope with different alignments.
  571. //
  572. // Parameter block arguments
  573. //
  574. // ppdev-------Valid
  575. // lNumRects---Number of rects pointed to by pRects
  576. // pRects------Of destination rectangles to be filled
  577. // ucFgRop3----Valid Pattern fill rop3 code (source invariant)
  578. // pptlBrush---Origin of brush
  579. // pdsurfDst---Destination surface
  580. // prbrush-----ponter to RBRUSH
  581. //
  582. //-----------------------------------------------------------------------------
  583. VOID
  584. vPatFill(GFNPB* ppb)
  585. {
  586. PPDev ppdev = ppb->ppdev;
  587. LONG lNumRects = ppb->lNumRects;
  588. RECTL* prcl = ppb->pRects;
  589. POINTL* pptlBrush = ppb->pptlBrush;
  590. Surf* psurf = ppb->psurfDst;
  591. RBrush* prbrush = ppb->prbrush;
  592. BrushEntry* pbe = prbrush->pbe;
  593. DWORD dwRenderBits;
  594. ULONG ulBrushX;
  595. ULONG ulBrushY;
  596. ULONG ulBrushOffset;
  597. // ULONG ulLogicOP = ulRop3ToLogicop(ppb->ucFgRop3);
  598. ULONG ulLogicOP = ulRop3ToLogicop(ppb->ulRop4 & 0xFF);
  599. ULONG* pBuffer;
  600. PERMEDIA_DECL;
  601. ASSERTDD(lNumRects > 0, "vPatFill: unexpected rectangle lNumRects <= 0");
  602. if ( (pbe == NULL) || (pbe->prbVerify != ppb->prbrush) )
  603. {
  604. vPatRealize(ppb);
  605. pbe = prbrush->pbe;
  606. ASSERTDD(pbe != NULL, "vPatFill: unexpected null pattern brush entry");
  607. }
  608. dwRenderBits = __RENDER_TRAPEZOID_PRIMITIVE
  609. | __RENDER_TEXTURED_PRIMITIVE;
  610. InputBufferReserve(ppdev, 34, &pBuffer);
  611. pBuffer[0] = __Permedia2TagFBWindowBase;
  612. pBuffer[1] = psurf->ulPixOffset;
  613. pBuffer[2] = __Permedia2TagLogicalOpMode;
  614. pBuffer[3] = P2_ENABLED_LOGICALOP(ulLogicOP);
  615. pBuffer[4] = __Permedia2TagFBReadMode;
  616. pBuffer[5] = PM_FBREADMODE_PARTIAL(psurf->ulPackedPP)
  617. | LogicopReadDest[ulLogicOP];
  618. pBuffer[6] = __Permedia2TagFBWriteConfig;
  619. pBuffer[7] = PM_FBREADMODE_PARTIAL(psurf->ulPackedPP)
  620. | LogicopReadDest[ulLogicOP];
  621. pBuffer[8] = __Permedia2TagFBSourceOffset;
  622. pBuffer[9] = 0;
  623. //
  624. // Setup the texture unit with the pattern
  625. //
  626. pBuffer[10] = __Permedia2TagDitherMode;
  627. pBuffer[11] = (COLOR_MODE << PM_DITHERMODE_COLORORDER)
  628. | (ppdev->ulPermFormat << PM_DITHERMODE_COLORFORMAT)
  629. | (ppdev->ulPermFormatEx << PM_DITHERMODE_COLORFORMATEXTENSION)
  630. | (1 << PM_DITHERMODE_ENABLE);
  631. pBuffer[12] = __Permedia2TagTextureAddressMode;
  632. pBuffer[13] = (1 << PM_TEXADDRESSMODE_ENABLE);
  633. pBuffer[14] = __Permedia2TagTextureColorMode;
  634. pBuffer[15] = (1 << PM_TEXCOLORMODE_ENABLE)
  635. | (0 << 4) // RGB
  636. | (3 << 1); // Copy
  637. pBuffer[16] = __Permedia2TagTextureReadMode;
  638. pBuffer[17] = PM_TEXREADMODE_ENABLE(__PERMEDIA_ENABLE)
  639. | PM_TEXREADMODE_WIDTH(CACHED_BRUSH_WIDTH_LOG2 - 1)
  640. | PM_TEXREADMODE_HEIGHT(CACHED_BRUSH_HEIGHT_LOG2 - 1)
  641. | (1 << 1) // repeat S
  642. | (1 << 3); // repeat T
  643. pBuffer[18] = __Permedia2TagTextureDataFormat;
  644. pBuffer[19] = (ppdev->ulPermFormat << PM_TEXDATAFORMAT_FORMAT)
  645. | (ppdev->ulPermFormatEx << PM_TEXDATAFORMAT_FORMATEXTENSION)
  646. | (COLOR_MODE << PM_TEXDATAFORMAT_COLORORDER);
  647. pBuffer[20] = __Permedia2TagTextureMapFormat;
  648. pBuffer[21] = (ppdev->ulBrushPackedPP)
  649. | (ppdev->cPelSize << PM_TEXMAPFORMAT_TEXELSIZE);
  650. //@@BEGIN_DDKSPLIT
  651. // TODO: use SStart and TStart to avoid having to offset the pattern using
  652. // ulBrushOffset. This will also allow us to save some space in the
  653. // pattern cache (we have to make it 7 pixels wider and taller due to
  654. // our need to set different origins).
  655. //@@END_DDKSPLIT
  656. pBuffer[22] = __Permedia2TagSStart;
  657. pBuffer[23] = 0;
  658. pBuffer[24] = __Permedia2TagTStart;
  659. pBuffer[25] = 0;
  660. pBuffer[26] = __Permedia2TagdSdx;
  661. pBuffer[27] = 1 << 20;
  662. pBuffer[28] = __Permedia2TagdSdyDom;
  663. pBuffer[29] = 0;
  664. pBuffer[30] = __Permedia2TagdTdx;
  665. pBuffer[31] = 0;
  666. pBuffer[32] = __Permedia2TagdTdyDom;
  667. pBuffer[33] = 1 << 20;
  668. pBuffer += 34;
  669. InputBufferCommit(ppdev, pBuffer);
  670. //
  671. // Render rectangles
  672. //
  673. do
  674. {
  675. //
  676. // Caclulate brush offset taking into account the brush origin
  677. // NOTE: that the texture unit places the origin of the texture
  678. // at the upper left of the destination rectangle
  679. //
  680. ulBrushX = (prcl->left - ppb->pptlBrush->x) & 7;
  681. ulBrushY = (prcl->top - ppb->pptlBrush->y) & 7;
  682. ulBrushOffset = pbe->ulPixelOffset
  683. + ulBrushX
  684. + (ulBrushY * CACHED_BRUSH_WIDTH);
  685. InputBufferReserve(ppdev, 12, &pBuffer);
  686. pBuffer[0] = __Permedia2TagTextureBaseAddress;
  687. pBuffer[1] = ulBrushOffset;
  688. pBuffer[2] = __Permedia2TagStartXDom;
  689. pBuffer[3] = INTtoFIXED(prcl->left);
  690. pBuffer[4] = __Permedia2TagStartXSub;
  691. pBuffer[5] = INTtoFIXED(prcl->right);
  692. pBuffer[6] = __Permedia2TagStartY;
  693. pBuffer[7] = INTtoFIXED(prcl->top);
  694. pBuffer[8] = __Permedia2TagCount;
  695. pBuffer[9] = (prcl->bottom - prcl->top);
  696. pBuffer[10] = __Permedia2TagRender;
  697. pBuffer[11] = dwRenderBits;
  698. pBuffer += 12;
  699. InputBufferCommit(ppdev, pBuffer);
  700. prcl++;
  701. } while (--lNumRects != 0);
  702. //
  703. // Restore defaults
  704. //
  705. InputBufferReserve(ppdev, 8, &pBuffer);
  706. pBuffer[0] = __Permedia2TagTextureAddressMode;
  707. pBuffer[1] = (0 << PM_TEXADDRESSMODE_ENABLE);
  708. pBuffer[2] = __Permedia2TagTextureColorMode;
  709. pBuffer[3] = (0 << PM_TEXCOLORMODE_ENABLE);
  710. pBuffer[4] = __Permedia2TagDitherMode;
  711. pBuffer[5] = (0 << PM_DITHERMODE_ENABLE);
  712. pBuffer[6] = __Permedia2TagTextureReadMode;
  713. pBuffer[7] = __PERMEDIA_DISABLE;
  714. pBuffer += 8;
  715. InputBufferCommit(ppdev, pBuffer);
  716. DBG_GDI((6, "vPatternFillRects done"));
  717. }// vPatFill