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.

1381 lines
50 KiB

  1. /******************************Module*Header***********************************\
  2. *
  3. * *******************
  4. * * GDI SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: bitblt.c
  8. *
  9. * Contains the high-level DrvBitBlt and DrvCopyBits functions.
  10. *
  11. *
  12. * NOTE: Please see heap.c for a discussion of the types of bitmaps
  13. * our acceleration functions are likely to encounter and the
  14. * possible states of these bitmaps.
  15. *
  16. * Copyright (C) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
  17. * Copyright (C) 1995-1999 Microsoft Corporation. All rights reserved.
  18. ******************************************************************************/
  19. #include "precomp.h"
  20. #include "gdi.h"
  21. #include "clip.h"
  22. #include "heap.h"
  23. #include "log.h"
  24. //@@BEGIN_DDKSPLIT
  25. #if GDI_TEST
  26. ULONG
  27. vPuntBefore(SURFOBJ * psoSrc, SURFOBJ * psoDst)
  28. {
  29. ULONG flags = 0;
  30. if(MAKE_BITMAPS_OPAQUE)
  31. {
  32. if(psoSrc != NULL && psoSrc->iType == STYPE_DEVBITMAP)
  33. {
  34. Surf * psurfSrc = (Surf *) psoSrc->dhpdev;
  35. ASSERTDD(psurfSrc != NULL, "expected non-null psurf");
  36. psoSrc->iType = STYPE_BITMAP;
  37. flags |= 1;
  38. }
  39. if(psoDst != NULL && psoDst->iType == STYPE_DEVBITMAP)
  40. {
  41. Surf * psurfDst = (Surf *) psoDst->dhpdev;
  42. ASSERTDD(psurfDst != NULL, "expected non-null psurf");
  43. psoDst->iType = STYPE_BITMAP;
  44. flags |= 2;
  45. }
  46. }
  47. return flags;
  48. }
  49. void
  50. vPuntAfter(ULONG flags, SURFOBJ * psoSrc, SURFOBJ * psoDst)
  51. {
  52. if(MAKE_BITMAPS_OPAQUE)
  53. {
  54. if(psoSrc != NULL && (flags & 1))
  55. {
  56. Surf * psurfSrc = (Surf *) psoSrc->dhpdev;
  57. ASSERTDD(psurfSrc != NULL, "expected non-null psurf");
  58. ASSERTDD(psoSrc->iType == STYPE_BITMAP, "expected STYPE_BITMAP");
  59. psoSrc->iType = STYPE_DEVBITMAP;
  60. }
  61. ASSERTDD(psoDst != NULL, "expected non-null psoDst");
  62. if(flags & 2)
  63. {
  64. Surf * psurfDst = (Surf *) psoDst->dhpdev;
  65. ASSERTDD(psurfDst != NULL, "expected non-null psurf");
  66. ASSERTDD(psoDst->iType == STYPE_BITMAP, "expected STYPE_BITMAP");
  67. psoDst->iType = STYPE_DEVBITMAP;
  68. }
  69. }
  70. }
  71. #endif
  72. //@@END_DDKSPLIT
  73. //-----------------------------Public*Routine----------------------------------
  74. //
  75. // BOOL DrvBitBlt
  76. //
  77. // DrvBitBlt provides general bit-block transfer capabilities between
  78. // device-managed surfaces, between GDI-managed standard-format bitmaps, or
  79. // between a device-managed surface and a GDI-managed standard-format bitmap.
  80. //
  81. // Parameters:
  82. // psoDst---Points to the SURFOBJ structure that describes the surface on
  83. // which to draw
  84. // psoSrc---Points to a SURFOBJ structure that describes the source for
  85. // the bit-block transfer operation, if required by the rop4
  86. // parameter
  87. // psoMask--Points to a SURFOBJ structure that describes a surface to be
  88. // used as a mask for the rop4 parameter. The mask is a bitmap with
  89. // 1 bit per pixel. Typically, a mask is used to limit the area to
  90. // be modified in the destination surface. Masking is selected by
  91. // setting the rop4 parameter to the value 0xAACC. The destination
  92. // surface is unaffected if the mask is 0x0000.
  93. //
  94. // The mask will be large enough to cover the destination rectangle.
  95. //
  96. // If this parameter is null and a mask is required by the rop4
  97. // parameter, the implicit mask in the brush is used
  98. // pco------Points to a CLIPOBJ structure that limits the area to be modified
  99. // GDI services (CLIPOBJ_Xxx) that enumerate the clip region as a
  100. // set of rectangles are provided. Whenever possible, GDI simplifies
  101. // the clipping involved; for example, this function is never called
  102. // with a single clipping rectangle. GDI clips the destination
  103. // rectangle before calling this function, making additional
  104. // clipping unnecessary.
  105. // pxlo-----Points to a XLATEOBJ structure that specifies how color indices
  106. // should be translated between the source and destination surfaces.
  107. // If the source surface is palette-managed, its colors are
  108. // represented by indices into a lookup table of RGB values. The
  109. // XLATEOBJ structure can be queried for a translate vector that
  110. // will allow the device driver to translate any source index into
  111. // a color index for the destination.
  112. //
  113. // The situation is more complicated when, for example, the source
  114. // is RGB, but the destination is palette-managed. In this case,
  115. // the closest match to each source RGB value must be found in the
  116. // destination palette. The driver can call the XLATEOBJ_iXlate
  117. // service to perform this operation.
  118. //
  119. // Optionally, the device driver can match colors when the target
  120. // palette is the default device palette.
  121. // prclDst--Points to a RECTL structure that defines the area to be modified.
  122. // This structure uses the coordinate system of the destination
  123. // surface. The lower and right edges of this rectangle are not
  124. // part of the bit-block transfer, meaning the rectangle is lower
  125. // right exclusive.
  126. // DrvBitBlt is never called with an empty destination rectangle.
  127. // The two points that define the rectangle are always well-ordered.
  128. // pptlSrc--Points to a POINTL structure that defines the upper left corner
  129. // of the source rectangle, if a source exists. This parameter is
  130. // ignored if there is no source.
  131. // pptlMask-Points to a POINTL structure that defines which pixel in the mask
  132. // corresponds to the upper left corner of the source rectangle, if
  133. // a source exists. This parameter is ignored if the psoMask
  134. // parameter is null.
  135. // pbo------Points to the brush object that defines the pattern for the
  136. // bit-block transfer. GDI's BRUSHOBJ_pvGetRbrush service can be
  137. // used to retrieve the device's realization of the brush. This
  138. // parameter is ignored if the rop4 parameter does not require a
  139. // pattern.
  140. // pptlBrush-Points to a POINTL structure that defines the origin of the
  141. // brush in the destination surface. The upper left pixel of the
  142. // brush is aligned at this point, and the brush repeats according
  143. // to its dimensions. This parameter is ignored if the rop4
  144. // parameter does not require a pattern.
  145. // rop4-----Specifies a raster operation that defines how the mask, pattern,
  146. // source, and destination pixels are combined to write to the
  147. // destination surface.
  148. // This is a quaternary raster operation, which is an extension of
  149. // the ternary Rop3 operation. A Rop4 has 16 relevant bits, which
  150. // are similar to the 8 defining bits of a Rop3. The simplest way
  151. // to implement a Rop4 is to consider its 2 bytes separately: The
  152. // low byte specifies a Rop3 that should be calculated if the mask
  153. // is one; the high byte specifies a Rop3 that can be calculated and
  154. // applied if the mask is 0.
  155. //
  156. // Return Value
  157. // The return value is TRUE if the bit-block transfer operation is successful
  158. // Otherwise, it is FALSE, and an error code is logged.
  159. //
  160. //-----------------------------------------------------------------------------
  161. BOOL
  162. DrvBitBlt(SURFOBJ* psoDst,
  163. SURFOBJ* psoSrc,
  164. SURFOBJ* psoMsk,
  165. CLIPOBJ* pco,
  166. XLATEOBJ* pxlo,
  167. RECTL* prclDst,
  168. POINTL* pptlSrc,
  169. POINTL* pptlMsk,
  170. BRUSHOBJ* pbo,
  171. POINTL* pptlBrush,
  172. ROP4 rop4)
  173. {
  174. BOOL bResult;
  175. GFNPB pb;
  176. XLATEOBJ xloTmp;
  177. ULONG aulTmp[2];
  178. ASSERTDD(!(rop4 & 0xFFFF0000), "DrvBitBlt: unexpected rop4 code");
  179. pb.ulRop4 = (ULONG) rop4;
  180. pb.psurfDst = (Surf*)psoDst->dhsurf;
  181. pb.prclDst = prclDst;
  182. if ( psoSrc == NULL )
  183. {
  184. pb.psurfSrc = NULL;
  185. //
  186. // We will only be given fills to device managed surfaces
  187. //
  188. ASSERTDD(pb.psurfDst != NULL,
  189. "DrvBitBlt: unexpected gdi managed destination");
  190. if ( pb.psurfDst->flags & SF_SM )
  191. {
  192. goto puntIt;
  193. }
  194. //
  195. // We are filling surface in video memory
  196. //
  197. pb.ppdev = pb.psurfDst->ppdev;
  198. vSurfUsed(pb.ppdev, pb.psurfDst);
  199. //
  200. // If a mask is required punt it
  201. //
  202. if ( (rop4 & 0xFF) != (rop4 >> 8) )
  203. {
  204. goto puntIt;
  205. }
  206. //
  207. // Since 'psoSrc' is NULL, the rop3 had better not indicate
  208. // that we need a source.
  209. //
  210. ASSERTDD((((rop4 >> 2) ^ rop4) & 0x33) == 0,
  211. "Need source but GDI gave us a NULL 'psoSrc'");
  212. //
  213. // Default to solid fill
  214. //
  215. if ( (((rop4 >> 4) ^ rop4) & 0xf) != 0 )
  216. {
  217. //
  218. // The rop says that a pattern is truly required
  219. // (blackness, for instance, doesn't need one):
  220. //
  221. //
  222. // for pbo->iSolidColor, a value of 0xFFFFFFFF(-1) indicates that
  223. // a nonsolid brush must be realized
  224. //
  225. if ( pbo->iSolidColor == -1 )
  226. {
  227. //
  228. // Non-solid brush case. Try to realize the pattern brush; By
  229. // doing this call-back, GDI will eventually call us again
  230. // through DrvRealizeBrush
  231. //
  232. pb.prbrush = (RBrush*)pbo->pvRbrush;
  233. if ( pb.prbrush == NULL )
  234. {
  235. pb.prbrush = (RBrush*)BRUSHOBJ_pvGetRbrush(pbo);
  236. if ( pb.prbrush == NULL )
  237. {
  238. //
  239. // If we couldn't realize the brush, punt
  240. // the call (it may have been a non 8x8
  241. // brush or something, which we can't be
  242. // bothered to handle, so let GDI do the
  243. // drawing):
  244. //
  245. DBG_GDI((2, "DrvBitBlt: BRUSHOBJ_pvGetRbrush failed"));
  246. goto puntIt;
  247. }
  248. }
  249. pb.pptlBrush = pptlBrush;
  250. //
  251. // Check if brush pattern is 1 BPP or not
  252. // Note: This is set in DrvRealizeBrush
  253. //
  254. if ( pb.prbrush->fl & RBRUSH_2COLOR )
  255. {
  256. //
  257. // 1 BPP pattern. Do a Mono fill
  258. //
  259. pb.pgfn = vMonoPatFill;
  260. }
  261. else
  262. {
  263. pb.pgfn = vPatFill;
  264. }
  265. }
  266. else
  267. {
  268. ASSERTDD( (pb.ppdev->cBitsPerPel == 32)
  269. ||(pbo->iSolidColor&(0xFFFFFFFF<<pb.ppdev->cBitsPerPel))==0,
  270. "DrvBitBlt: unused solid color bits not zero");
  271. pb.solidColor = pbo->iSolidColor;
  272. if ( rop4 != ROP4_PATCOPY )
  273. {
  274. pb.pgfn = vSolidFillWithRop;
  275. }
  276. else
  277. {
  278. pb.pgfn = pb.ppdev->pgfnSolidFill;
  279. }
  280. }
  281. }// if ((((ucRop3 >> 4) ^ (ucRop3)) & 0xf) != 0)
  282. else
  283. {
  284. //
  285. // Turn some logicops into solid block fills. We get here
  286. // only for rops 00, 55, AA and FF.
  287. //
  288. if ( rop4 == ROP4_BLACKNESS )
  289. {
  290. pb.solidColor = 0;
  291. pb.ulRop4 = ROP4_PATCOPY;
  292. }
  293. else if( rop4 == ROP4_WHITENESS )
  294. {
  295. pb.solidColor = 0xffffff;
  296. pb.ulRop4 = ROP4_PATCOPY;
  297. }
  298. else if ( pb.ulRop4 == ROP4_NOP)
  299. {
  300. return TRUE;
  301. }
  302. else
  303. {
  304. pb.pgfn = vInvert;
  305. goto doIt;
  306. }
  307. pb.pgfn = pb.ppdev->pgfnSolidFill;
  308. }
  309. goto doIt;
  310. }// if ( psoSrc == NULL )
  311. //
  312. // We know we have a source
  313. //
  314. pb.psurfSrc = (Surf*)psoSrc->dhsurf;
  315. pb.pptlSrc = pptlSrc;
  316. if ( (pb.psurfDst == NULL) || (pb.psurfDst->flags & SF_SM) )
  317. {
  318. //
  319. // Destination is in system memory
  320. //
  321. if(pb.psurfSrc != NULL && pb.psurfSrc->flags & SF_VM)
  322. {
  323. pb.ppdev = pb.psurfSrc->ppdev;
  324. //
  325. // Source is in video memory
  326. //
  327. if(rop4 == ROP4_SRCCOPY)
  328. {
  329. if(pb.ppdev->iBitmapFormat != BMF_32BPP &&
  330. (pxlo == NULL || pxlo->flXlate == XO_TRIVIAL) )
  331. {
  332. pb.psoDst = psoDst;
  333. pb.pgfn = vUploadNative;
  334. goto doIt;
  335. }
  336. }
  337. }
  338. goto puntIt;
  339. }
  340. //
  341. // After this point we know that the destination is in video memory
  342. //
  343. pb.ppdev = pb.psurfDst->ppdev;
  344. if ( psoMsk != NULL )
  345. {
  346. goto puntIt;
  347. }
  348. //
  349. // After this point we know we do not have a mask
  350. //
  351. if( (rop4 == 0xb8b8 || rop4 == 0xe2e2)
  352. && (pbo->iSolidColor != (ULONG)-1)
  353. && (psoSrc->iBitmapFormat == BMF_1BPP)
  354. && (pxlo->pulXlate[0] == 0)
  355. && ((pxlo->pulXlate[1] & pb.ppdev->ulWhite) == pb.ppdev->ulWhite) )
  356. {
  357. //
  358. // When the background and foreground colors are black and
  359. // white, respectively, and the ROP is 0xb8 or 0xe2, and
  360. // the source bitmap is monochrome, the blt is simply a
  361. // color expanding monochrome blt.
  362. //
  363. //
  364. // Rather than add another parameter to 'pfnXfer', we simply
  365. // overload the 'pxlo' pointer. Note that we still have to
  366. // special-case 0xb8 and 0xe2 in our 'pfnXfer1bpp' routine
  367. // to handle this convention:
  368. //
  369. xloTmp = *pxlo;
  370. xloTmp.pulXlate = aulTmp;
  371. aulTmp[0] = pbo->iSolidColor;
  372. aulTmp[1] = pbo->iSolidColor;
  373. pb.pxlo = &xloTmp;
  374. DBG_GDI((6, "Rop is 0x%x", pb.ulRop4));
  375. pb.pgfn = vMonoDownload;
  376. pb.psoSrc = psoSrc;
  377. goto doIt;
  378. }
  379. if ( pbo != NULL )
  380. {
  381. goto puntIt;
  382. }
  383. //
  384. // After this point we know we do not have a brush
  385. //
  386. //
  387. // We have a source to dest rop2 operation
  388. //
  389. if ( pb.psurfSrc == NULL )
  390. {
  391. pb.psoSrc = psoSrc;
  392. if(psoSrc->iBitmapFormat == BMF_1BPP)
  393. {
  394. pb.pxlo = pxlo;
  395. pb.pgfn = vMonoDownload;
  396. goto doIt;
  397. }
  398. else if(psoSrc->iBitmapFormat == pb.ppdev->iBitmapFormat
  399. && (pxlo == NULL || pxlo->flXlate == XO_TRIVIAL) )
  400. {
  401. //@@BEGIN_DDKSPLIT
  402. // TODO: find out if we need to check for pxlo == NULL
  403. // TODO: Handle 24 bpp download since it get called many times
  404. // during WinBench 99 tests
  405. //@@END_DDKSPLIT
  406. pb.psoSrc = psoSrc;
  407. pb.pgfn = vDownloadNative;
  408. goto doIt;
  409. }
  410. else
  411. {
  412. goto puntIt;
  413. }
  414. }
  415. if ( pb.psurfSrc->flags & SF_SM )
  416. {
  417. //
  418. // Source is in system memory
  419. //
  420. goto puntIt;
  421. }
  422. //
  423. // We now have both a source and a destination in video memory
  424. //
  425. //@@BEGIN_DDKSPLIT
  426. // TODO: find if we will ever get a non-trivial translation when
  427. // both source and dest are device managed.
  428. //@@END_DDKSPLIT
  429. if( pxlo != NULL && !(pxlo->flXlate & XO_TRIVIAL))
  430. {
  431. goto puntIt;
  432. }
  433. if ( (rop4 == ROP4_SRCCOPY) || (psoSrc == psoDst) )
  434. {
  435. if ( pb.psurfSrc->ulPixDelta == pb.psurfDst->ulPixDelta )
  436. {
  437. pb.pgfn = vCopyBltNative;
  438. }
  439. else
  440. {
  441. pb.pgfn = vCopyBlt;
  442. }
  443. }
  444. else
  445. {
  446. pb.pgfn = vRop2Blt;
  447. }
  448. doIt:
  449. //@@BEGIN_DDKSPLIT
  450. #if MULTITHREADED
  451. if(pb.ppdev->ulLockCount)
  452. {
  453. DBG_GDI((MT_LOG_LEVEL, "DrvBitBlt: re-entered! %d", pb.ppdev->ulLockCount));
  454. }
  455. EngAcquireSemaphore(pb.ppdev->hsemLock);
  456. pb.ppdev->ulLockCount++;
  457. #endif
  458. //@@END_DDKSPLIT
  459. vCheckGdiContext(pb.ppdev);
  460. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  461. {
  462. pb.pRects = pb.prclDst;
  463. pb.lNumRects = 1;
  464. pb.pgfn(&pb);
  465. }
  466. else if (pco->iDComplexity == DC_RECT)
  467. {
  468. RECTL rcl;
  469. if (bIntersect(pb.prclDst, &pco->rclBounds, &rcl))
  470. {
  471. pb.pRects = &rcl;
  472. pb.lNumRects = 1;
  473. pb.pgfn(&pb);
  474. }
  475. }
  476. else
  477. {
  478. pb.pco = pco;
  479. vClipAndRender(&pb);
  480. }
  481. if( ((pb.pgfn == vCopyBlt) || (pb.pgfn == vCopyBltNative))
  482. &&(pb.ppdev->pdsurfScreen == pb.psurfSrc)
  483. &&(pb.psurfSrc == pb.psurfDst)
  484. &&(pb.ppdev->bNeedSync) )
  485. {
  486. pb.ppdev->bNeedSync = TRUE;
  487. InputBufferSwap(pb.ppdev);
  488. }
  489. else
  490. {
  491. InputBufferFlush(pb.ppdev);
  492. }
  493. //@@BEGIN_DDKSPLIT
  494. #if MULTITHREADED
  495. pb.ppdev->ulLockCount--;
  496. EngReleaseSemaphore(pb.ppdev->hsemLock);
  497. #endif
  498. //@@END_DDKSPLIT
  499. return TRUE;
  500. puntIt:
  501. //@@BEGIN_DDKSPLIT
  502. #if GDI_TEST
  503. ULONG flags = vPuntBefore(psoSrc, psoDst);
  504. #endif
  505. //@@END_DDKSPLIT
  506. bResult = EngBitBlt(psoDst, psoSrc, psoMsk, pco, pxlo, prclDst, pptlSrc,
  507. pptlMsk, pbo, pptlBrush, rop4);
  508. //@@BEGIN_DDKSPLIT
  509. #if GDI_TEST
  510. vPuntAfter(flags, psoSrc, psoDst);
  511. vLogPunt();
  512. #endif
  513. //@@END_DDKSPLIT
  514. return bResult;
  515. }// DrvBitBlt()
  516. //-----------------------------Public*Routine----------------------------------
  517. //
  518. // BOOL DrvCopyBits
  519. //
  520. // DrvCopyBits translates between device-managed raster surfaces and GDI
  521. // standard-format bitmaps.
  522. //
  523. // Parameters
  524. // psoDst------Points to the destination surface for the copy operation.
  525. // psoSrc------Points to the source surface for the copy operation.
  526. // pco---------Points to a CLIPOBJ structure that defines a clipping region on
  527. // the destination surface.
  528. // pxlo--------Points to a XLATEOBJ structure that defines the translation of
  529. // color indices between the source and target surfaces.
  530. // prclDst-----Points to a RECTL structure that defines the area to be
  531. // modified. This structure uses the coordinate system of the
  532. // destination surface. The lower and right edges of this
  533. // rectangle are not part of the bit-block transfer, meaning the
  534. // rectangle is lower right exclusive.
  535. // DrvCopyBits is never called with an empty destination rectangle
  536. // The two points that define the rectangle are always
  537. // well-ordered.
  538. //
  539. // pptlSrc-----Points to a POINTL structure that defines the upper-left corner
  540. // of the source rectangle.
  541. //
  542. // Return Value
  543. // The return value is TRUE if the source surface is successfully copied to
  544. // the destination surface.
  545. //
  546. // Comments
  547. // This function is required for a device driver that has device-managed
  548. // bitmaps or raster surfaces. The implementation in the driver must
  549. // translate driver surfaces to and from any standard-format bitmap.
  550. //
  551. // Standard-format bitmaps are single-plane, packed-pixel format. Each scan
  552. // line is aligned on a 4-byte boundary. These bitmaps have 1, 4, 8, 16, 24,
  553. // 32, or 64 bits per pixel.
  554. //
  555. // This function should ideally be able to deal with RLE and device-dependent
  556. // bitmaps (see the Platform SDK). The device-dependent format is optional;
  557. // only a few specialized drivers need to support it. These bitmaps can be
  558. // sent to this function as a result of the following Win32 GDI functions:
  559. // SetDIBits, SetDIBitsToDevice, GetDIBits, SetBitmapBits, and GetBitmapBits.
  560. //
  561. // Kernel-mode GDI calls this function from its simulations
  562. //
  563. //-----------------------------------------------------------------------------
  564. BOOL
  565. DrvCopyBits(SURFOBJ* psoDst,
  566. SURFOBJ* psoSrc,
  567. CLIPOBJ* pco,
  568. XLATEOBJ* pxlo,
  569. RECTL* prclDst,
  570. POINTL* pptlSrc)
  571. {
  572. return DrvBitBlt(psoDst, psoSrc, NULL, pco, pxlo, prclDst, pptlSrc,
  573. NULL, NULL, NULL, ROP4_SRCCOPY);
  574. }// DrvCopyBits()
  575. //-----------------------------Public*Routine----------------------------------
  576. //
  577. // BOOL DrvTransparentBlt
  578. //
  579. //DrvTransparentBlt provides bit-block transfer capabilities with transparency.
  580. //
  581. // Parameters
  582. // psoDst------Points to the SURFOBJ that identifies the target surface on
  583. // which to draw.
  584. // psoSrc------Points to the SURFOBJ that identifies the source surface of the
  585. // bit-block transfer.
  586. // pco---------Points to a CLIPOBJ structure. The CLIPOBJ_Xxx service routines
  587. // are provided to enumerate the clip region as a set of
  588. // rectangles. This enumeration limits the area of the destination
  589. // that is modified. Whenever possible, GDI simplifies the
  590. // clipping involved.
  591. // pxlo--------Points to a XLATEOBJ that tells how the source color indices
  592. // should be translated for writing to the target surface.
  593. // prclDst-----Points to a RECTL structure that defines the rectangular area
  594. // to be modified. This rectangle is specified in the coordinate
  595. // system of the destination surface and is defined by two points:
  596. // upper left and lower right. The rectangle is lower-right
  597. // exclusive; that is, its lower and right edges are not a part of
  598. // the bit-block transfer. The two points that define the
  599. // rectangle are always well ordered.
  600. // DrvTransparentBlt is never called with an empty destination
  601. // rectangle.
  602. // prclSrc-----Points to a RECTL structure that defines the rectangular area
  603. // to be copied. This rectangle is specified in the coordinate
  604. // system of the source surface and is defined by two points:
  605. // upper left and lower right. The two points that define the
  606. // rectangle are always well ordered.
  607. // The source rectangle will never exceed the bounds of the source
  608. // surface, and so will never overhang the source surface.
  609. //
  610. // This rectangle is mapped to the destination rectangle defined
  611. // by prclDst. DrvTransparentBlt is never called with an empty
  612. // source rectangle.
  613. // iTransColor-Specifies the transparent color in the source surface format.
  614. // It is a color index value that has been translated to the
  615. // source surface's palette.
  616. // ulReserved--Reserved; this parameter must be set to zero.
  617. //
  618. // Return Value
  619. // DrvTransparentBlt returns TRUE upon success. Otherwise, it returns FALSE.
  620. //
  621. // Comments
  622. // Bit-block transfer with transparency is supported between two
  623. // device-managed surfaces or between a device-managed surface and a
  624. // GDI-managed standard format bitmap. Driver writers are encouraged to
  625. // support the case of blting from off-screen device bitmaps in video memory
  626. // to other surfaces in video memory; all other cases can be punted to
  627. // EngTransparentBlt with little performance penalty.
  628. //
  629. // The pixels on the source surface that match the transparent color specified
  630. // by iTransColor are not copied.
  631. //
  632. // The driver will never be called with overlapping source and destination
  633. // rectangles on the same surface.
  634. //
  635. // The driver should ignore any unused bits in the color key comparison, such
  636. // as for the most significant bit when the bitmap format is a 5-5-5 16bpp.
  637. //
  638. // The driver hooks DrvTransparentBlt by setting the HOOK_TRANSPARENTBLT flag
  639. // when it calls EngAssociateSurface. If the driver has hooked
  640. // DrvTransparentBlt and is called to perform an operation that it does not
  641. // support, the driver should have GDI handle the operation by forwarding the
  642. // data in a call to EngTransparentBlt.
  643. //
  644. //-----------------------------------------------------------------------------
  645. BOOL
  646. DrvTransparentBlt(SURFOBJ* psoDst,
  647. SURFOBJ* psoSrc,
  648. CLIPOBJ* pco,
  649. XLATEOBJ* pxlo,
  650. RECTL* prclDst,
  651. RECTL* prclSrc,
  652. ULONG iTransColor,
  653. ULONG ulReserved)
  654. {
  655. GFNPB pb;
  656. BOOL bResult;
  657. ASSERTDD(psoDst != NULL, "DrvTransparentBlt: psoDst is NULL");
  658. ASSERTDD(psoSrc != NULL, "DrvTransparentBlt: psoSrc is NULL");
  659. pb.psurfDst = (Surf *) psoDst->dhsurf;
  660. pb.psurfSrc = (Surf *) psoSrc->dhsurf;
  661. ASSERTDD(pb.psurfDst != NULL || pb.psurfSrc != NULL,
  662. "DrvTransparentBlt: expected at least one device managed surface");
  663. // Only handle one-to-one blts
  664. if (prclDst->right - prclDst->left != prclSrc->right - prclSrc->left)
  665. goto puntIt;
  666. if (prclDst->bottom - prclDst->top != prclSrc->bottom - prclSrc->top)
  667. goto puntIt;
  668. // Only handle trivial color translation
  669. if ( pxlo != NULL && !(pxlo->flXlate & XO_TRIVIAL))
  670. goto puntIt;
  671. // for now, only handle video memory to video memory transparent blts
  672. if(pb.psurfDst == NULL || pb.psurfDst->flags & SF_SM)
  673. goto puntIt;
  674. if(pb.psurfSrc == NULL || pb.psurfSrc->flags & SF_SM)
  675. goto puntIt;
  676. pb.ppdev = (PPDev) psoDst->dhpdev;
  677. pb.prclDst = prclDst;
  678. pb.prclSrc = prclSrc;
  679. pb.pptlSrc = NULL;
  680. pb.colorKey = iTransColor;
  681. pb.pgfn = pb.ppdev->pgfnTransparentBlt;
  682. pb.pco = pco;
  683. //@@BEGIN_DDKSPLIT
  684. #if MULTITHREADED
  685. if(pb.ppdev->ulLockCount)
  686. {
  687. DBG_GDI((MT_LOG_LEVEL, "DrvTransparentBlt: re-entered! %d", pb.ppdev->ulLockCount));
  688. }
  689. EngAcquireSemaphore(pb.ppdev->hsemLock);
  690. pb.ppdev->ulLockCount++;
  691. #endif
  692. //@@END_DDKSPLIT
  693. vCheckGdiContext(pb.ppdev);
  694. vClipAndRender(&pb);
  695. InputBufferFlush(pb.ppdev);
  696. //@@BEGIN_DDKSPLIT
  697. #if MULTITHREADED
  698. pb.ppdev->ulLockCount--;
  699. EngReleaseSemaphore(pb.ppdev->hsemLock);
  700. #endif
  701. //@@END_DDKSPLIT
  702. return TRUE;
  703. puntIt:
  704. //@@BEGIN_DDKSPLIT
  705. #if GDI_TEST
  706. ULONG flags = vPuntBefore(psoSrc, psoDst);
  707. #endif
  708. //@@END_DDKSPLIT
  709. bResult = EngTransparentBlt(psoDst,
  710. psoSrc,
  711. pco,
  712. pxlo,
  713. prclDst,
  714. prclSrc,
  715. iTransColor,
  716. ulReserved);
  717. //@@BEGIN_DDKSPLIT
  718. #if GDI_TEST
  719. vPuntAfter(flags, psoSrc, psoDst);
  720. vLogPunt();
  721. #endif
  722. //@@END_DDKSPLIT
  723. return bResult;
  724. }// DrvTransparentBlt()
  725. //-----------------------------Public*Routine----------------------------------
  726. //
  727. // BOOL DrvAlphaBlend
  728. //
  729. // DrvAlphaBlend provides bit-block transfer capabilities with alpha blending.
  730. //
  731. // Parameters
  732. // psoDest-----Points to a SURFOBJ that identifies the surface on which to
  733. // draw.
  734. // psoSrc------Points to a SURFOBJ that identifies the source surface.
  735. // pco---------Points to a CLIPOBJ. The CLIPOBJ_Xxx service routines are
  736. // provided to enumerate the clip region as a set of rectangles.
  737. // This enumeration limits the area of the destination that is
  738. // modified. Whenever possible, GDI simplifies the clipping
  739. // involved. However, unlike DrvBitBlt, DrvAlphaBlend might be
  740. // called with a single rectangle in order to prevent round-off
  741. // errors in clipping the output.
  742. // pxlo--------Points to a XLATEOBJ that specifies how color indices should be
  743. // translated between the source and destination surfaces.
  744. // If the source surface is palette managed, its colors are
  745. // represented by indices into a lookup table of RGB color values.
  746. // In this case, the XLATEOBJ can be queried for a translate
  747. // vector that allows the device driver to quickly translate any
  748. // source index into a color index for the destination.
  749. //
  750. // The situation is more complicated when, for example, the source
  751. // is RGB but the destination is palette managed. In this case,
  752. // the closest match to each source RGB value must be found in the
  753. // destination palette. The driver can call the XLATEOBJ_iXlate
  754. // service routine to perform this matching operation.
  755. // prclDest----Points to a RECTL structure that defines the rectangular area
  756. // to be modified. This rectangle is specified in the coordinate
  757. // system of the destination surface and is defined by two points:
  758. // upper left and lower right. The two points that define the
  759. // rectangle are always well ordered. The rectangle is lower-right
  760. // exclusive; that is, its lower and right edges are not a part of
  761. // the blend.
  762. // The driver should be careful to do proper clipping when writing
  763. // the pixels because the specified rectangle might overhang the
  764. // destination surface.
  765. //
  766. // DrvAlphaBlend is never called with an empty destination
  767. // rectangle.
  768. // prclSrc-----Points to a RECTL structure that defines the area to be copied.
  769. // This rectangle is specified in the coordinate system of the
  770. // source surface, and is defined by two points: upper left and
  771. // lower right. The two points that define the rectangle are
  772. // always well ordered. The rectangle is lower-right exclusive;
  773. // that is, its lower and right edges are not a part of the blend.
  774. // The source rectangle will never exceed the bounds of the source
  775. // surface, and so will never overhang the source surface.
  776. //
  777. // DrvAlphaBlend is never called with an empty source rectangle.
  778. //
  779. // The mapping is defined by prclSrc and prclDest. The points
  780. // specified in prclDest and prclSrc lie on integer coordinates,
  781. // which correspond to pixel centers. A rectangle defined by two
  782. // such points is considered to be a geometric rectangle with two
  783. // vertices whose coordinates are the given points, but with 0.5
  784. // subtracted from each coordinate. (POINTL structures are
  785. // shorthand notation for specifying these fractional coordinate
  786. // vertices.)
  787. // pBlendObj---Points to a BLENDOBJ structure that describes the blending
  788. // operation to perform between the source and destination
  789. // surfaces. This structure is a wrapper for the BLENDFUNCTION
  790. // structure, which includes necessary source and destination
  791. // format information not available in the XLATEOBJ. BLENDFUNCTION
  792. // is declared in the Platform SDK. Its members are defined as
  793. // follows:
  794. // BlendOp defines the blend operation to be performed. Currently
  795. // this value must be AC_SRC_OVER, which means that the source
  796. // bitmap is placed over the destination bitmap based on the alpha
  797. // values of the source pixels. There are three possible cases
  798. // that this blend operation should handle. These are described in
  799. // the Comments section of this reference page.
  800. //
  801. // BlendFlags is reserved and is currently set to zero.
  802. //
  803. // SourceConstantAlpha defines the constant blend factor to apply
  804. // to the entire source surface. This value is in the range of
  805. // [0,255], where 0 is completely transparent and 255 is
  806. // completely opaque.
  807. //
  808. // AlphaFormat defines whether the surface is assumed to have an
  809. // alpha channel. This member can optionally be set to the
  810. // following value:
  811. //
  812. // AC_SRC_ALPHA
  813. // The source surface can be assumed to be in a pre-multiplied
  814. // alpha 32bpp "BGRA" format; that is, the surface type is
  815. // BMF_32BPP and the palette type is BI_RGB. The alpha
  816. // component is an integer in the range of [0,255], where 0 is
  817. // completely transparent and 255 is completely opaque.
  818. // Return Value
  819. // DrvAlphaBlend returns TRUE upon success. Otherwise, it reports an error and
  820. // returns FALSE.
  821. //
  822. // Comments
  823. // A bit-block transfer with alpha blending is supported between the following
  824. // surfaces:
  825. //
  826. // From one driver-managed surface to another driver-managed surface.
  827. // From one GDI-managed standard format bitmap to another GDI-managed standard
  828. // format bitmap.
  829. // From one device-managed surface to a GDI-managed surface, and vice versa.
  830. // The three possible cases for the AC_SRC_OVER blend function are:
  831. //
  832. // The source bitmap has no per pixel alpha (AC_SRC_ALPHA is not set), so the
  833. // blend is applied to the pixel's color channels based on the constant source
  834. // alpha value specified in SourceConstantAlpha as follows:
  835. //
  836. // Dst.Red = Round(((Src.Red * SourceConstantAlpha) +
  837. // ((255 ? SourceConstantAlpha) * Dst.Red)) / 255);
  838. // Dst.Green = Round(((Src.Green * SourceConstantAlpha) +
  839. // ((255 ? SourceConstantAlpha) * Dst.Green)) / 255);
  840. // Dst.Blue = Round(((Src.Blue * SourceConstantAlpha) +
  841. // ((255 ? SourceConstantAlpha) * Dst.Blue)) / 255);
  842. //
  843. // Do the next computation only if the destination bitmap has an alpha channel
  844. // Dst.Alpha = Round(((Src.Alpha * SourceConstantAlpha) +
  845. // ((255 ? SourceConstantAlpha) * Dst.Alpha)) / 255);
  846. //
  847. // The source bitmap has per pixel alpha values (AC_SRC_ALPHA is set), and
  848. // SourceConstantAlpha is not used (it is set to 255). The blend is computed
  849. // as follows:
  850. //
  851. // Temp.Red = Src.Red + Round(((255 ? Src.Alpha) * Dst.Red) / 255);
  852. // Temp.Green = Src.Green + Round(((255 ? Src.Alpha) * Dst.Green) / 255);
  853. // Temp.Blue = Src.Blue + Round(((255 ? Src.Alpha) * Dst.Blue) / 255);
  854. //
  855. // Do the next computation only if the destination bitmap has an alpha channel
  856. //
  857. // Temp.Alpha = Src.Alpha + Round(((255 ? Src.Alpha) * Dst.Alpha) / 255);
  858. //
  859. // The source bitmap has per pixel alpha values (AC_SRC_ALPHA is set), and
  860. // SourceConstantAlpha is used (it is not set to 255). The blend is computed
  861. // as follows:
  862. //
  863. // Temp.Red = Round((Src.Red * SourceConstantAlpha) / 255);
  864. // Temp.Green = Round((Src.Green * SourceConstantAlpha) / 255);
  865. // Temp.Blue = Round((Src.Blue * SourceConstantAlpha) / 255);
  866. //
  867. // The next computation must be done even if the destination bitmap does not
  868. // have an alpha channel
  869. //
  870. // Temp.Alpha = Round((Src.Alpha * SourceConstantAlpha) / 255);
  871. //
  872. // Note that the following equations use the just-computed Temp.Alpha value:
  873. //
  874. // Dst.Red = Temp.Red + Round(((255 ? Temp.Alpha) * Dst.Red) / 255);
  875. // Dst.Green = Temp.Green + Round(((255 ? Temp.Alpha) * Dst.Green) / 255);
  876. // Dst.Blue = Temp.Blue + Round(((255 ? Temp.Alpha) * Dst.Blue) / 255);
  877. //
  878. // Do the next computation only if the destination bitmap has an alpha channel
  879. //
  880. // Dst.Alpha = Temp.Alpha + Round(((255 ? Temp.Alpha) * Dst.Alpha) / 255);
  881. //
  882. // DrvAlphaBlend can be optionally implemented in graphics drivers. It can be
  883. // provided to handle some kinds of alpha blends, such as blends where the
  884. // source and destination surfaces are the same format and do not contain an
  885. // alpha channel.
  886. //
  887. // A hardware implementation can use floating point or fixed point in the
  888. // blend operation. Compatibility tests will account for a small epsilon in
  889. // the results. When using fixed point, an acceptable approximation to the
  890. // term x/255 is (x*257)/65536. Incorporating rounding, the term:
  891. //
  892. // (255 - Src.Alpha) * Dst.Red) / 255
  893. //
  894. // can then be approximated as:
  895. //
  896. // temp = (255 - Src.Alpha) * Dst.Red) + 128;
  897. // result = (temp + (temp >> 8)) >> 8;
  898. //
  899. // The Round(x) function rounds to the nearest integer, computed as:
  900. //
  901. // Trunc(x + 0.5);
  902. //
  903. // The driver hooks DrvAlphaBlend by setting the HOOK_ALPHABLEND flag when it
  904. // calls EngAssociateSurface. If the driver has hooked DrvAlphaBlend and is
  905. // called to perform an operation that it does not support, the driver should
  906. // have GDI handle the operation by forwarding the data in a call to
  907. // EngAlphaBlend.
  908. //
  909. //-----------------------------------------------------------------------------
  910. BOOL
  911. DrvAlphaBlend(SURFOBJ* psoDst,
  912. SURFOBJ* psoSrc,
  913. CLIPOBJ* pco,
  914. XLATEOBJ* pxlo,
  915. RECTL* prclDst,
  916. RECTL* prclSrc,
  917. BLENDOBJ* pBlendObj)
  918. {
  919. BOOL bSourceInSM;
  920. BOOL bResult;
  921. GFNPB pb;
  922. ASSERTDD(psoDst != NULL, "DrvAlphaBlend: psoDst is NULL");
  923. ASSERTDD(psoSrc != NULL, "DrvAlphaBlend: psoSrc is NULL");
  924. DBG_GDI((7,"DrvAlphaBlend"));
  925. pb.psurfDst = (Surf *) psoDst->dhsurf;
  926. pb.psurfSrc = (Surf *) psoSrc->dhsurf;
  927. // Only handle one-to-one alpha blts
  928. if (prclDst->right - prclDst->left != prclSrc->right - prclSrc->left)
  929. goto puntIt;
  930. if (prclDst->bottom - prclDst->top != prclSrc->bottom - prclSrc->top)
  931. goto puntIt;
  932. if(pb.psurfDst == NULL || pb.psurfDst->flags & SF_SM)
  933. goto puntIt;
  934. pb.ppdev = (PPDev) psoDst->dhpdev;
  935. // We can't handle blending in 8bpp
  936. //@@BEGIN_DDKSPLIT
  937. // TODO: Investigate doing blending in 8bpp
  938. //@@END_DDKSPLIT
  939. if (pb.ppdev->cPelSize == 0)
  940. goto puntIt;
  941. pb.ucAlpha = pBlendObj->BlendFunction.SourceConstantAlpha;
  942. if(pb.psurfSrc == NULL || pb.psurfSrc->flags & SF_SM)
  943. {
  944. pb.psoSrc = psoSrc;
  945. //@@BEGIN_DDKSPLIT
  946. // TODO: find out how we should verify that the XLATEOBJ is reasonable
  947. //@@END_DDKSPLIT
  948. if(pBlendObj->BlendFunction.AlphaFormat & AC_SRC_ALPHA)
  949. {
  950. ASSERTDD(psoSrc->iBitmapFormat == BMF_32BPP,
  951. "DrvAlphaBlend: source alpha specified with non 32bpp source");
  952. pb.pgfn = vAlphaBlendDownload;
  953. // This could be a cursor that is drawing... force a swap
  954. // buffer at the next synchronization event.
  955. pb.ppdev->bForceSwap = TRUE;
  956. //@@BEGIN_DDKSPLIT
  957. // TODO: improve our alpha blend download acceleration code
  958. // it's currently slower then punting
  959. //@@END_DDKSPLIT
  960. }
  961. else
  962. {
  963. goto puntIt;
  964. }
  965. }
  966. else
  967. {
  968. // Only handle trivial color translation
  969. if (pxlo != NULL && !(pxlo->flXlate & XO_TRIVIAL))
  970. goto puntIt;
  971. if(pBlendObj->BlendFunction.AlphaFormat & AC_SRC_ALPHA)
  972. {
  973. ASSERTDD(psoSrc->iBitmapFormat == BMF_32BPP,
  974. "DrvAlphaBlend: source alpha specified with non 32bpp source");
  975. pb.pgfn = vAlphaBlend;
  976. }
  977. else
  978. {
  979. pb.pgfn = vConstantAlphaBlend;
  980. }
  981. }
  982. pb.prclDst = prclDst;
  983. pb.prclSrc = prclSrc;
  984. pb.pptlSrc = NULL;
  985. pb.pco = pco;
  986. //@@BEGIN_DDKSPLIT
  987. #if MULTITHREADED
  988. if(pb.ppdev->ulLockCount)
  989. {
  990. DBG_GDI((MT_LOG_LEVEL, "DrvAlphaBlend: re-entered! %d", pb.ppdev->ulLockCount));
  991. }
  992. EngAcquireSemaphore(pb.ppdev->hsemLock);
  993. pb.ppdev->ulLockCount++;
  994. #endif
  995. //@@END_DDKSPLIT
  996. vCheckGdiContext(pb.ppdev);
  997. vClipAndRender(&pb);
  998. InputBufferFlush(pb.ppdev);
  999. //@@BEGIN_DDKSPLIT
  1000. #if MULTITHREADED
  1001. pb.ppdev->ulLockCount--;
  1002. EngReleaseSemaphore(pb.ppdev->hsemLock);
  1003. #endif
  1004. //@@END_DDKSPLIT
  1005. return TRUE;
  1006. puntIt:
  1007. //@@BEGIN_DDKSPLIT
  1008. #if GDI_TEST
  1009. ULONG flags = vPuntBefore(psoSrc, psoDst);
  1010. #endif
  1011. //@@END_DDKSPLIT
  1012. bResult = EngAlphaBlend(
  1013. psoDst, psoSrc, pco, pxlo, prclDst, prclSrc, pBlendObj);
  1014. //@@BEGIN_DDKSPLIT
  1015. #if GDI_TEST
  1016. vPuntAfter(flags, psoSrc, psoDst);
  1017. vLogPunt();
  1018. #endif
  1019. //@@END_DDKSPLIT
  1020. return bResult;
  1021. }// DrvAlphaBlend()
  1022. //-----------------------------Public*Routine----------------------------------
  1023. //
  1024. // BOOL DrvGradientFill
  1025. //
  1026. // DrvGradientFill shades the specified primitives.
  1027. //
  1028. // Parameters
  1029. // psoDest-----Points to the SURFOBJ that identifies the surface on which to
  1030. // draw.
  1031. // pco---------Points to a CLIPOBJ. The CLIPOBJ_Xxx service routines are
  1032. // provided to enumerate the clip region as a set of rectangles.
  1033. // This enumeration limits the area of the destination that is
  1034. // modified. Whenever possible, GDI simplifies the clipping
  1035. // involved.
  1036. // pxlo--------Should be ignored by the driver.
  1037. // pVertex-----Points to an array of TRIVERTEX structures, with each entry
  1038. // containing position and color information. TRIVERTEX is defined
  1039. // in the Platform SDK.
  1040. // nVertex-----Specifies the number of TRIVERTEX structures in the array to
  1041. // which pVertex points.
  1042. // pMesh-------Points to an array of structures that define the connectivity
  1043. // of the TRIVERTEX elements to which pVertex points.
  1044. // When rectangles are being drawn, pMesh points to an array of
  1045. // GRADIENT_RECT structures that specify the upper left and lower
  1046. // right TRIVERTEX elements that define a rectangle. Rectangle
  1047. // drawing is lower-right exclusive. GRADIENT_RECT is defined in
  1048. // the Platform SDK.
  1049. //
  1050. // When triangles are being drawn, pMesh points to an array of
  1051. // GRADIENT_TRIANGLE structures that specify the three TRIVERTEX
  1052. // elements that define a triangle. Triangle drawing is
  1053. // lower-right exclusive. GRADIENT_TRIANGLE is defined in the
  1054. // Platform SDK.
  1055. // nMesh-------Specifies the number of elements in the array to which pMesh
  1056. // points.
  1057. // prclExtents-Points to a RECTL structure that defines the area in which the
  1058. // gradient drawing is to occur. The points are specified in the
  1059. // coordinate system of the destination surface. This parameter is
  1060. // useful in estimating the size of the drawing operations.
  1061. // pptlDitherOrg-Points to a POINTL structure that defines the origin on the
  1062. // surface for dithering. The upper left pixel of the dither
  1063. // pattern is aligned with this point.
  1064. // ulMode------Specifies the current drawing mode and how to interpret the
  1065. // array to which pMesh points. This parameter can be one of the
  1066. // following values:
  1067. // Value Meaning
  1068. // GRADIENT_FILL_RECT_H pMesh points to an array of
  1069. // GRADIENT_RECT structures. Each
  1070. // rectangle is to be shaded from left to
  1071. // right. Specifically, the upper-left and
  1072. // lower-left pixels are the same color,
  1073. // as are the upper-right and lower-right
  1074. // pixels.
  1075. // GRADIENT_FILL_RECT_V pMesh points to an array of
  1076. // GRADIENT_RECT structures. Each
  1077. // rectangle is to be shaded from top to
  1078. // bottom. Specifically, the upper-left
  1079. // and upper-right pixels are the same
  1080. // color, as are the lower-left and
  1081. // lower-right pixels.
  1082. // GRADIENT_FILL_TRIANGLE pMesh points to an array of
  1083. // GRADIENT_TRIANGLE structures.
  1084. //
  1085. // The gradient fill calculations for each mode are documented in
  1086. // the Comments section.
  1087. //
  1088. // Return Value
  1089. // DrvGradientFill returns TRUE upon success. Otherwise, it returns FALSE. and
  1090. // reports an error by calling EngSetLastError.
  1091. //
  1092. // Comments
  1093. // DrvGradientFill can be optionally implemented in graphics drivers.
  1094. //
  1095. // The driver hooks DrvGradientFill by setting the HOOK_GRADIENTFILL flag when
  1096. // it calls EngAssociateSurface. If the driver has hooked DrvGradientFill and
  1097. // is called to perform an operation that it does not support, the driver
  1098. // should have GDI handle the operation by forwarding the data in a call to
  1099. // EngGradientFill.
  1100. //
  1101. // The formulas for computing the color value at each pixel of the primitive
  1102. // depend on ulMode as follows:
  1103. //
  1104. // GRADIENT_FILL_TRIANGLE
  1105. // The triangle's vertices are defined as V1, V2, and V3. Point P is
  1106. // inside the triangle. Draw lines from P to V1, V2, and V3 to form three
  1107. // sub-triangles. Let ai denote the area of the triangle opposite Vi for
  1108. // i=1,2,3. The color at point P is computed as:
  1109. //
  1110. // RedP = (RedV1 * a1 + RedV2 * a2 + RedV3 * a3) / (a1+a2+a3 ())
  1111. // GreenP = (GreenV1 * a1 + GreenV2 * a2 + GreenV3 * a3) / (a1+a2+a3 ())
  1112. // BlueP ( ) = (BlueV1 * a1 + BlueV2 * a2 + BlueV3 * a3) / (a1+a2+a3)
  1113. //
  1114. // GRADIENT_FILL_RECT_H
  1115. // The rectangle's top-left point is V1 and the bottom-right point is V2.
  1116. // Point P is inside the rectangle. The color at point P is given by:
  1117. //
  1118. // RedP = (RedV2 * (Px - V1x) + RedV1 * (V2x - Px)) / (V2x-V1x)
  1119. // GreenP = (GreenV2 * (Px - V1x) + GreenV1 * (V2x - Px)) / (V2x-V1x)
  1120. // BlueP = (BlueV2 * (Px - V1x) + BlueV1 * (V2x - Px)) / (V2x-V1x)
  1121. //
  1122. // GRADIENT_FILL_RECT_V
  1123. // The rectangle's top-left point is V1 and the bottom-right point is V2.
  1124. // Point P is inside the rectangle. The color at point P is given by:
  1125. //
  1126. // RedP = (RedV2 * (Py-V1y) + RedV1 * (V2y - Py)) / (V2y-V1y)
  1127. // GreenP = (GreenV2 * (Py-V1y) + GreenV1 * (V2y - Py)) / (V2y-V1y)
  1128. // BlueP = (BlueV2 * (Py-V1y) + BlueV1 * (V2y - Py)) / (V2y-V1y)
  1129. //
  1130. //-----------------------------------------------------------------------------
  1131. BOOL
  1132. DrvGradientFill(SURFOBJ* psoDst,
  1133. CLIPOBJ* pco,
  1134. XLATEOBJ* pxlo,
  1135. TRIVERTEX* pVertex,
  1136. ULONG nVertex,
  1137. PVOID pMesh,
  1138. ULONG nMesh,
  1139. RECTL* prclExtents,
  1140. POINTL* pptlDitherOrg,
  1141. ULONG ulMode)
  1142. {
  1143. GFNPB pb;
  1144. BOOL bResult;
  1145. ASSERTDD(psoDst != NULL, "DrvGradientFill: psoDst is NULL");
  1146. pb.psurfDst = (Surf *) psoDst->dhsurf;
  1147. pb.psurfSrc = NULL;
  1148. // for now, only handle video memory gradient fills
  1149. if(pb.psurfDst == NULL || pb.psurfDst->flags & SF_SM)
  1150. goto puntIt;
  1151. pb.ppdev = (PPDev) psoDst->dhpdev;
  1152. pb.ulMode = ulMode;
  1153. // setup default dest
  1154. if(pb.ulMode == GRADIENT_FILL_TRIANGLE)
  1155. {
  1156. //@@BEGIN_DDKSPLIT
  1157. // TODO: add support for triangle gradient fill ... our hardware
  1158. // can easily support this acceleration.
  1159. //@@END_DDKSPLIT
  1160. goto puntIt;
  1161. }
  1162. else
  1163. {
  1164. GRADIENT_RECT *pgr = (GRADIENT_RECT *) pMesh;
  1165. #ifdef DBG
  1166. for(ULONG i = 0; i < nMesh; i++)
  1167. {
  1168. ULONG ulLr = pgr[i].LowerRight;
  1169. ASSERTDD( ulLr < nVertex, "DrvGradientFill: bad vertex index");
  1170. }
  1171. #endif
  1172. pb.pgfn = pb.ppdev->pgfnGradientFillRect;
  1173. }
  1174. pb.pco = pco;
  1175. pb.ptvrt = pVertex;
  1176. pb.ulNumTvrt = nVertex;
  1177. pb.pvMesh = pMesh;
  1178. pb.ulNumMesh = nMesh;
  1179. pb.prclDst = prclExtents;
  1180. //@@BEGIN_DDKSPLIT
  1181. #if MULTITHREADED
  1182. if(pb.ppdev->ulLockCount)
  1183. {
  1184. DBG_GDI((MT_LOG_LEVEL, "DrvGradientFill: re-entered! %d", pb.ppdev->ulLockCount));
  1185. }
  1186. EngAcquireSemaphore(pb.ppdev->hsemLock);
  1187. pb.ppdev->ulLockCount++;
  1188. #endif
  1189. //@@END_DDKSPLIT
  1190. vCheckGdiContext(pb.ppdev);
  1191. vClipAndRender(&pb);
  1192. InputBufferFlush(pb.ppdev);
  1193. //@@BEGIN_DDKSPLIT
  1194. #if MULTITHREADED
  1195. pb.ppdev->ulLockCount--;
  1196. EngReleaseSemaphore(pb.ppdev->hsemLock);
  1197. #endif
  1198. //@@END_DDKSPLIT
  1199. return TRUE;
  1200. puntIt:
  1201. //@@BEGIN_DDKSPLIT
  1202. #if GDI_TEST
  1203. ULONG flags = vPuntBefore(NULL, psoDst);
  1204. #endif
  1205. //@@END_DDKSPLIT
  1206. bResult = EngGradientFill(
  1207. psoDst, pco, pxlo, pVertex, nVertex,
  1208. pMesh, nMesh, prclExtents, pptlDitherOrg, ulMode);
  1209. //@@BEGIN_DDKSPLIT
  1210. #if GDI_TEST
  1211. vPuntAfter(flags, NULL, psoDst);
  1212. vLogPunt();
  1213. #endif
  1214. //@@END_DDKSPLIT
  1215. return bResult;
  1216. }// DrvGradientFill()