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.

2691 lines
102 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: alphablt.cxx
  3. *
  4. * Alpha Blending
  5. *
  6. * Created: 21-Jun-1996
  7. * Author: Mark Enstrom [marke]
  8. *
  9. * Copyright (c) 1996-1999 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.hxx"
  12. #include "stretch.hxx" // For mirroring code.
  13. /******************************Public*Routine******************************\
  14. * bIsSourceBGRA
  15. *
  16. * determine whether a surface is in BGR format
  17. *
  18. * Arguments:
  19. *
  20. * pSurf - pointer to the surface
  21. *
  22. * Return Value:
  23. *
  24. * TRUE if the surface is in BGR format, otherwise FALSE
  25. *
  26. * History:
  27. *
  28. * 12-Aug-1997 -by- Ori Gershony [orig]
  29. *
  30. \**************************************************************************/
  31. BOOL
  32. bIsSourceBGRA(
  33. PSURFACE pSurf
  34. )
  35. {
  36. XEPALOBJ pal(pSurf->ppal());
  37. //
  38. // A surface is in BGR format if it's a valid 32BPP surface that's either
  39. // PAL_BGR or PAL_BITFIELDS with the correct bitfields set.
  40. //
  41. return ((pSurf->iFormat() == BMF_32BPP) &&
  42. (pal.bValid()) &&
  43. ((pal.bIsBGR()) ||
  44. ((pal.bIsBitfields()) &&
  45. (pal.flRed() == 0xff0000) &&
  46. (pal.flGre() == 0xff00) &&
  47. (pal.flBlu() == 0xff))));
  48. }
  49. /******************************Public*Routine******************************\
  50. * psSetupTransparentSrcSurface
  51. *
  52. * make a temp copy of source surface if needed
  53. *
  54. * Arguments:
  55. *
  56. * pSurfSrc - original source surface
  57. * pSurfDst - original dset surfaca
  58. * prclDst - destination rect
  59. * pxloSrcTo32 - used only for alpha blend, tran src to 32 BGRA
  60. * prclSrc - source rect, change to temp src rect if allocated
  61. * &surfTmpSrc - use this surfmem to alloc
  62. * *bAllocSrcSurf - force temp allocation
  63. * ulSourceType - alpha or transparent surface
  64. * ulTranColor - transparent color
  65. *
  66. * Return Value:
  67. *
  68. * drawable surface or NULL
  69. *
  70. * History:
  71. *
  72. * 25-Jun-1996 -by- Mark Enstrom [marke]
  73. *
  74. \**************************************************************************/
  75. PSURFACE
  76. psSetupTransparentSrcSurface(
  77. PSURFACE pSurfSrc,
  78. PSURFACE pSurfDst,
  79. PRECTL prclDst,
  80. XLATEOBJ *pxloSrcTo32,
  81. PRECTL prclSrc,
  82. SURFMEM &surfTmpSrc,
  83. ULONG ulSourceType,
  84. ULONG ulTranColor
  85. )
  86. {
  87. BOOL bStatus;
  88. PSURFACE psurfRet = pSurfSrc;
  89. LONG DstCx = prclDst->right - prclDst->left;
  90. LONG DstCy = prclDst->bottom - prclDst->top;
  91. LONG SrcCx = prclSrc->right - prclSrc->left;
  92. LONG SrcCy = prclSrc->bottom - prclSrc->top;
  93. BOOL bStretch = ((DstCx != SrcCx) || (DstCy != SrcCy));
  94. BOOL bSourceIsBGRA = FALSE;
  95. BOOL bSrcRectExceedsBounds = FALSE;
  96. //
  97. // if the surface is a bitmap, identity translate and
  98. // no stretching, then a temp copy of the surface is not
  99. // needed.
  100. //
  101. if (bStretch)
  102. {
  103. DEVBITMAPINFO dbmi;
  104. PDEVOBJ pdoSrc( pSurfSrc->hdev());
  105. XEPALOBJ palSurf(pSurfSrc->ppal());
  106. //
  107. // calculate clipped extents of destinatoin rect
  108. //
  109. RECTL rclDstClip = {0,0,pSurfDst->sizl().cx,pSurfDst->sizl().cy};
  110. //
  111. // trimmed destination rect is trimmed surface boundary
  112. // Perf Note: clipping on destination is not taken into account,
  113. // this could reduce the size of the source copy surface at
  114. // times.
  115. //
  116. if (rclDstClip.left < prclDst->left)
  117. {
  118. rclDstClip.left = prclDst->left;
  119. }
  120. if (rclDstClip.top < prclDst->top)
  121. {
  122. rclDstClip.top = prclDst->top;
  123. }
  124. if (rclDstClip.right > prclDst->right)
  125. {
  126. rclDstClip.right = prclDst->right;
  127. }
  128. if (rclDstClip.bottom > prclDst->bottom)
  129. {
  130. rclDstClip.bottom = prclDst->bottom;
  131. }
  132. if ((rclDstClip.left < rclDstClip.right) &&
  133. (rclDstClip.top < rclDstClip.bottom))
  134. {
  135. //
  136. // does source rect exceed source bounds? (bad)
  137. //
  138. if ((prclSrc->left < 0) ||
  139. (prclSrc->right > pSurfSrc->sizl().cx) ||
  140. (prclSrc->top < 0) ||
  141. (prclSrc->bottom > pSurfSrc->sizl().cy)
  142. )
  143. {
  144. bSrcRectExceedsBounds = TRUE;
  145. }
  146. //
  147. // allocate surface as same size as dst
  148. //
  149. if (ulSourceType == SOURCE_ALPHA)
  150. {
  151. //
  152. // does original source contain alpha channel
  153. //
  154. bSourceIsBGRA = bIsSourceBGRA (pSurfSrc);
  155. //
  156. // allocate 32bpp BGRA surface for source, must be zero init
  157. //
  158. dbmi.cxBitmap = rclDstClip.right - rclDstClip.left;
  159. dbmi.cyBitmap = rclDstClip.bottom - rclDstClip.top;
  160. dbmi.iFormat = BMF_32BPP;
  161. dbmi.fl = pSurfSrc->bUMPD() ? UMPD_SURFACE : 0;
  162. XEPALOBJ palRGB(gppalRGB);
  163. dbmi.hpal = (HPALETTE)palRGB.hpal();
  164. bStatus = surfTmpSrc.bCreateDIB(&dbmi, (VOID *) NULL);
  165. //
  166. // since DIB is zero-init, no other initialization is needed to
  167. // make it transparent (so that portions of dst rect not covered
  168. // by source rect are not drawn)
  169. //
  170. // UNLESS source DIB does not have it's own alpha. In that case, if
  171. // the source extents do not completely cover dst extents, source
  172. // must be initialized to 0xffxxxxxx. StretchBlt will write 0x00xxxxxx.
  173. // After StretchBlt, must make all 0xffxxxxxx to 0x00xxxxxx and all
  174. // 0x00xxxxxx to 0xffxxxxxx
  175. //
  176. if (bStatus && bSrcRectExceedsBounds && !bSourceIsBGRA)
  177. {
  178. RtlFillMemoryUlong(surfTmpSrc.ps->pvBits(),surfTmpSrc.ps->cjBits(),0xFF000000);
  179. }
  180. }
  181. else
  182. {
  183. //
  184. // allocate compatible surface for TransparentBlt
  185. //
  186. dbmi.cxBitmap = DstCx;
  187. dbmi.cyBitmap = DstCy;
  188. dbmi.iFormat = pSurfSrc->iFormat();
  189. dbmi.fl = pSurfSrc->bUMPD() ? UMPD_SURFACE : 0;
  190. dbmi.hpal = (HPALETTE)NULL;
  191. if (palSurf.bValid())
  192. {
  193. dbmi.hpal = palSurf.hpal();
  194. }
  195. bStatus = surfTmpSrc.bCreateDIB(&dbmi, (VOID *) NULL);
  196. //
  197. // init DIB to transparent
  198. // (so that portions of dst rect not covered by source rect are not drawn)
  199. //
  200. if (bStatus && bSrcRectExceedsBounds)
  201. {
  202. ULONG i;
  203. ULONG cjBits = surfTmpSrc.ps->cjBits();
  204. ULONG ulColor4BPP;
  205. switch (pSurfSrc->iFormat())
  206. {
  207. case BMF_1BPP:
  208. if (ulTranColor)
  209. {
  210. memset(surfTmpSrc.ps->pvBits(),0xff,cjBits);
  211. }
  212. else
  213. {
  214. memset(surfTmpSrc.ps->pvBits(),0,cjBits);
  215. }
  216. break;
  217. case BMF_4BPP:
  218. ulColor4BPP = ulTranColor | (ulTranColor << 4);
  219. memset(surfTmpSrc.ps->pvBits(),ulColor4BPP,cjBits);
  220. break;
  221. case BMF_8BPP:
  222. memset(surfTmpSrc.ps->pvBits(),ulTranColor,cjBits);
  223. break;
  224. case BMF_16BPP:
  225. {
  226. PUSHORT pvBits = (PUSHORT) surfTmpSrc.ps->pvBits();
  227. for (i=0; i<(cjBits/sizeof(USHORT)); i++)
  228. {
  229. *pvBits++ = (USHORT) ulTranColor;
  230. }
  231. }
  232. break;
  233. case BMF_24BPP:
  234. {
  235. BYTE bC1 = ((PBYTE)&ulTranColor)[0];
  236. BYTE bC2 = ((PBYTE)&ulTranColor)[1];
  237. BYTE bC3 = ((PBYTE)&ulTranColor)[2];
  238. PULONG pulDstY = (PULONG)surfTmpSrc.ps->pvScan0();
  239. PULONG pulDstLastY = (PULONG)((PBYTE)pulDstY +
  240. (surfTmpSrc.ps->lDelta() * surfTmpSrc.ps->sizl().cy));
  241. while (pulDstY != pulDstLastY)
  242. {
  243. PBYTE pulDstX = (PBYTE) pulDstY;
  244. PBYTE pulDstLastX = pulDstX + 3 * surfTmpSrc.ps->sizl().cx;
  245. while (pulDstX < pulDstLastX-2)
  246. {
  247. *pulDstX++ = bC1;
  248. *pulDstX++ = bC2;
  249. *pulDstX++ = bC3;
  250. }
  251. pulDstY = (PULONG)((PBYTE)pulDstY + surfTmpSrc.ps->lDelta());
  252. }
  253. }
  254. break;
  255. case BMF_32BPP:
  256. {
  257. PULONG pvBits = (PULONG) surfTmpSrc.ps->pvBits();
  258. for (i=0; i<(cjBits/sizeof(ULONG)); i++)
  259. {
  260. *pvBits++ = ulTranColor;
  261. }
  262. }
  263. break;
  264. }
  265. }
  266. }
  267. if (bStatus)
  268. {
  269. //
  270. // zero DIB to make non-drawing areas transparent for alphablend
  271. //
  272. POINTL ptlBrushOrg = {0,0};
  273. RECTL rclDstCopy = *prclDst;
  274. ECLIPOBJ eco;
  275. ECLIPOBJ *pco = NULL;
  276. RGNMEMOBJTMP rmo((BOOL)FALSE);
  277. if (rmo.bValid())
  278. {
  279. //
  280. // offset dst rect
  281. //
  282. rclDstCopy.left -= rclDstClip.left;
  283. rclDstCopy.right -= rclDstClip.left;
  284. rclDstCopy.top -= rclDstClip.top;
  285. rclDstCopy.bottom -= rclDstClip.top;
  286. //
  287. // will need rect clipping if rclDstCopy exceeds tmp bitmap
  288. //
  289. if (
  290. (rclDstCopy.left < 0) ||
  291. (rclDstCopy.right > surfTmpSrc.ps->sizl().cx) ||
  292. (rclDstCopy.top < 0) ||
  293. (rclDstCopy.bottom > surfTmpSrc.ps->sizl().cy))
  294. {
  295. ERECTL rclSurface(0,0,surfTmpSrc.ps->sizl().cx,surfTmpSrc.ps->sizl().cy);
  296. rmo.vSet((RECTL *) &rclSurface);
  297. pco = (ECLIPOBJ *)&eco;
  298. ((XCLIPOBJ *)pco)->vSetup(rmo.prgnGet(),(ERECTL)rclDstCopy);
  299. }
  300. surfTmpSrc.ps->hdev(pSurfSrc->hdev());
  301. //
  302. // init with stretch
  303. //
  304. bStatus = EngStretchBlt (
  305. surfTmpSrc.ps->pSurfobj(),
  306. pSurfSrc->pSurfobj(),
  307. NULL,
  308. (CLIPOBJ *)pco,
  309. pxloSrcTo32,
  310. NULL,
  311. &ptlBrushOrg,
  312. &rclDstCopy,
  313. prclSrc,
  314. NULL,
  315. COLORONCOLOR
  316. );
  317. if (bStatus)
  318. {
  319. //
  320. // adjust prclSrc and prclDst to be non-stretch rects
  321. //
  322. prclSrc->left = 0;
  323. prclSrc->right = dbmi.cxBitmap;
  324. prclSrc->top = 0;
  325. prclSrc->bottom = dbmi.cyBitmap;
  326. *prclDst = rclDstClip;
  327. //
  328. // for alpha bitmaps that did not originally contain an alpha channel,
  329. // init alpha to ff.
  330. //
  331. // PERF: 2 other options to XOR whole bitmap are
  332. // 1: use compatible bitmap for source where rclSrc does not exceed src bounds
  333. // This saves memory maybee, saves xor, but require conversion of each scan to 32BRGA
  334. // 2: use flag to ignore alpha channel later where rclSrc does not exceed src bounds
  335. //
  336. if ((ulSourceType == SOURCE_ALPHA) && (!bSourceIsBGRA))
  337. {
  338. //
  339. // ULONGs that are 0xffxxxxxx must be made 0x00xxxxxx
  340. // ULONGs that are 0x00xxxxxx must be made 0xffxxxxxx
  341. // bitmaps that started out as 0x00BBGGRR (PAL_RGB) are still broken
  342. //
  343. PULONG pulDstY = (PULONG)surfTmpSrc.ps->pvScan0();
  344. PULONG pulDstLastY = (PULONG)((PBYTE)pulDstY + surfTmpSrc.ps->lDelta() * surfTmpSrc.ps->sizl().cy);
  345. while (pulDstY != pulDstLastY)
  346. {
  347. PULONG pulDstX = pulDstY;
  348. PULONG pulDstLastX = pulDstX + surfTmpSrc.ps->sizl().cx;
  349. while (pulDstX != pulDstLastX)
  350. {
  351. *pulDstX = *pulDstX ^ 0xff000000;
  352. pulDstX++;
  353. }
  354. pulDstY = (PULONG)((PBYTE)pulDstY + surfTmpSrc.ps->lDelta());
  355. }
  356. }
  357. //
  358. // mark surface to keep, set return status
  359. //
  360. psurfRet = surfTmpSrc.ps;
  361. }
  362. else
  363. {
  364. psurfRet = NULL;
  365. }
  366. }
  367. else
  368. {
  369. psurfRet = NULL;
  370. }
  371. }
  372. else
  373. {
  374. psurfRet = NULL;
  375. }
  376. }
  377. else
  378. {
  379. psurfRet = NULL;
  380. }
  381. }
  382. else
  383. {
  384. //
  385. // trim src rect to src surface bounds and reduce
  386. // dst rect accordingly
  387. //
  388. if (prclSrc->left < 0)
  389. {
  390. prclDst->left = prclDst->left - prclSrc->left;
  391. prclSrc->left = 0;
  392. }
  393. if (prclSrc->right > pSurfSrc->sizl().cx)
  394. {
  395. prclDst->right = prclDst->right - (prclSrc->right - pSurfSrc->sizl().cx);
  396. prclSrc->right = pSurfSrc->sizl().cx;
  397. }
  398. if (prclSrc->top < 0)
  399. {
  400. prclDst->top = prclDst->top - prclSrc->top;
  401. prclSrc->top = 0;
  402. }
  403. if (prclSrc->bottom > pSurfSrc->sizl().cy)
  404. {
  405. prclDst->bottom = prclDst->bottom - (prclSrc->bottom - pSurfSrc->sizl().cy);
  406. prclSrc->bottom = pSurfSrc->sizl().cy;
  407. }
  408. //
  409. // check dst rect exceeds dst surface, reduce src and rect accordingly
  410. // WINBUG #82938 2-8-2000 bhouse Fix assumption of surface position
  411. // Old Comment:
  412. // This code assumes that the surface starts at 0,0 and ends at sizl().cx, sizl().cy
  413. // which is not true for multimon code.
  414. // This is not a problem anymore. As this is called only from
  415. // EngAlphaBlend. According to Nagasae-San all Eng* Apis can assume
  416. // this surface start of 0,0 requirment.
  417. if (prclDst->left < 0)
  418. {
  419. prclSrc->left += (-prclDst->left);
  420. prclDst->left = 0;
  421. }
  422. if (prclDst->right > pSurfDst->sizl().cx)
  423. {
  424. prclSrc->right += (pSurfDst->sizl().cx - prclDst->right);
  425. prclDst->right = pSurfDst->sizl().cx;
  426. }
  427. if (prclDst->top < 0)
  428. {
  429. prclSrc->top += (-prclDst->top);
  430. prclDst->top = 0;
  431. }
  432. if (prclDst->bottom > pSurfDst->sizl().cy)
  433. {
  434. prclSrc->bottom += (pSurfDst->sizl().cy - prclDst->bottom);
  435. prclDst->bottom = pSurfDst->sizl().cy;
  436. }
  437. //
  438. // check for empty rect
  439. //
  440. if (
  441. (prclDst->left >= prclDst->right) ||
  442. (prclDst->top >= prclDst->bottom))
  443. {
  444. //
  445. // indicate empty rect
  446. //
  447. prclDst->left = prclDst->right;
  448. }
  449. else
  450. {
  451. if (pSurfSrc->iType() != STYPE_BITMAP)
  452. {
  453. DEVBITMAPINFO dbmi;
  454. PDEVOBJ pdoSrc( pSurfSrc->hdev());
  455. XEPALOBJ palSurf(pSurfSrc->ppal());
  456. LONG DstCx = prclDst->right - prclDst->left;
  457. LONG DstCy = prclDst->bottom - prclDst->top;
  458. //
  459. // allocate surface as same size as dst
  460. //
  461. dbmi.cxBitmap = DstCx;
  462. dbmi.cyBitmap = DstCy;
  463. dbmi.iFormat = pSurfSrc->iFormat();
  464. dbmi.fl = pSurfSrc->bUMPD() ? UMPD_SURFACE : 0;
  465. dbmi.hpal = (HPALETTE)NULL;
  466. if (palSurf.bValid())
  467. {
  468. dbmi.hpal = palSurf.hpal();
  469. }
  470. bStatus = surfTmpSrc.bCreateDIB(&dbmi, (VOID *) NULL);
  471. if (bStatus)
  472. {
  473. RECTL rclCopy;
  474. rclCopy.left = 0;
  475. rclCopy.right = DstCx;
  476. rclCopy.top = 0;
  477. rclCopy.bottom = DstCy;
  478. surfTmpSrc.ps->hdev(pSurfSrc->hdev());
  479. //
  480. // if src is same size as dest, init with CopyBits
  481. //
  482. POINTL ptlCopy;
  483. ptlCopy.x = prclSrc->left;
  484. ptlCopy.y = prclSrc->top;
  485. (*PPFNGET(pdoSrc,CopyBits,pSurfSrc->flags()))(
  486. surfTmpSrc.ps->pSurfobj(),
  487. pSurfSrc->pSurfobj(),
  488. (CLIPOBJ *) NULL,
  489. (XLATEOBJ *)NULL,
  490. &rclCopy,
  491. &ptlCopy);
  492. //
  493. // adjust prclSrc to be the new rect
  494. //
  495. *prclSrc = rclCopy;
  496. //
  497. // mark surface to keep, set return status
  498. //
  499. psurfRet = surfTmpSrc.ps;
  500. }
  501. else
  502. {
  503. psurfRet = NULL;
  504. }
  505. }
  506. }
  507. }
  508. return(psurfRet);
  509. }
  510. /******************************Public*Routine******************************\
  511. * psSetupDstSurface
  512. *
  513. * Create temporary destination surface for alpha and gradient fill,
  514. * if necessary, and optionally copy bits from the
  515. * actual destination surface.
  516. *
  517. * Arguments:
  518. *
  519. * pSurfDst - actual destination surface
  520. * prclDst - rectangle on dest surface
  521. * surfTmpDst - reference to surfmem
  522. * bForceDstAlloc - force allocation of temp dest
  523. * bCopyFromDst - copy bits from actual destination surface
  524. *
  525. * Return Value:
  526. *
  527. * surface to use, either original or new
  528. *
  529. * History:
  530. *
  531. * 25-Jun-1996 -by- Mark Enstrom [marke]
  532. *
  533. \**************************************************************************/
  534. PSURFACE
  535. psSetupDstSurface(
  536. PSURFACE pSurfDst,
  537. PRECTL prclDst,
  538. SURFMEM &surfTmpDst,
  539. BOOL bForceDstAlloc,
  540. BOOL bCopyFromDst
  541. )
  542. {
  543. PSURFACE psurfRet = pSurfDst;
  544. LONG DstCx = prclDst->right - prclDst->left;
  545. LONG DstCy = prclDst->bottom - prclDst->top;
  546. BOOL bStatus = FALSE;
  547. if (bForceDstAlloc || (pSurfDst->iType() != STYPE_BITMAP))
  548. {
  549. DEVBITMAPINFO dbmi;
  550. PDEVOBJ pdoDst( pSurfDst->hdev());
  551. XEPALOBJ palSurf(pSurfDst->ppal());
  552. //
  553. // allocate surface
  554. //
  555. dbmi.cxBitmap = DstCx;
  556. dbmi.cyBitmap = DstCy;
  557. dbmi.iFormat = pSurfDst->iFormat();
  558. dbmi.fl = pSurfDst->bUMPD() ? UMPD_SURFACE : 0;
  559. dbmi.hpal = (HPALETTE) 0;
  560. if (palSurf.bValid())
  561. {
  562. dbmi.hpal = palSurf.hpal();
  563. }
  564. bStatus = surfTmpDst.bCreateDIB(&dbmi, (VOID *) NULL);
  565. if (bStatus)
  566. {
  567. RECTL rclCopy;
  568. POINTL ptlCopy;
  569. surfTmpDst.ps->hdev(pSurfDst->hdev());
  570. rclCopy.left = 0;
  571. rclCopy.right = DstCx;
  572. rclCopy.top = 0;
  573. rclCopy.bottom = DstCy;
  574. if (bCopyFromDst)
  575. {
  576. ptlCopy.x = prclDst->left;
  577. ptlCopy.y = prclDst->top;
  578. bStatus = (*PPFNGET(pdoDst,CopyBits,pSurfDst->flags()))(
  579. surfTmpDst.pSurfobj(),
  580. pSurfDst->pSurfobj(),
  581. (CLIPOBJ *) NULL,
  582. &xloIdent,
  583. &rclCopy,
  584. &ptlCopy);
  585. }
  586. if (bStatus)
  587. {
  588. //
  589. // adjust dst rect
  590. //
  591. *prclDst = rclCopy;
  592. psurfRet = surfTmpDst.ps;
  593. }
  594. else
  595. {
  596. psurfRet = NULL;
  597. }
  598. }
  599. else
  600. {
  601. psurfRet = NULL;
  602. }
  603. }
  604. return(psurfRet);
  605. }
  606. #if defined(_X86_)
  607. /**************************************************************************\
  608. * IsMMXProcessor
  609. *
  610. * determine if the processor supports MMX
  611. *
  612. * Arguments:
  613. *
  614. * none
  615. *
  616. * Return Value:
  617. *
  618. * TRUE if MMX
  619. *
  620. * History:
  621. *
  622. * 4/10/1997 Mark Enstrom [marke]
  623. *
  624. \**************************************************************************/
  625. BOOL
  626. bIsMMXProcessor(VOID)
  627. {
  628. BOOL retval = FALSE;
  629. #if 0
  630. PVOID pFloatingPointState = (PVOID)PALLOCMEM(sizeof(KFLOATING_SAVE) + sizeof(BOOL),'pftG');
  631. if (pFloatingPointState != NULL)
  632. {
  633. BOOL bRet = EngSaveFloatingPointState(pFloatingPointState,sizeof(KFLOATING_SAVE) + sizeof(BOOL));
  634. if (bRet)
  635. {
  636. __try
  637. {
  638. _asm emms
  639. }
  640. __except(EXCEPTION_EXECUTE_HANDLER)
  641. {
  642. retval = FALSE;
  643. }
  644. EngRestoreFloatingPointState(pFloatingPointState);
  645. }
  646. else
  647. {
  648. WARNING1("bIsMMXProcessor: Failed to save fp state\n");
  649. retval = FALSE;
  650. }
  651. VFREEMEM(pFloatingPointState);
  652. }
  653. else
  654. {
  655. WARNING1("bIsMMXProcessor: Failed to allocate fpstate\n");
  656. retval = FALSE;
  657. }
  658. #else
  659. if (ExIsProcessorFeaturePresent(3)) // PF_MMX_INSTRUCTION_AVAILABLE
  660. {
  661. retval = TRUE;
  662. }
  663. #endif
  664. return retval;
  665. }
  666. #endif
  667. /**************************************************************************\
  668. * bDetermineAlphaBlendFunction
  669. *
  670. * determine alpha blending routine based on src and dst formats
  671. * and alpha BlendFunction
  672. *
  673. * Arguments:
  674. *
  675. * pSurfDst - dest surface
  676. * pSurfSrc - src surface
  677. * ppalDst - dest palette
  678. * ppalSrc - src palette
  679. * cxDst - width of alpha blt
  680. * pAlphaDispatch - blend function and routines
  681. *
  682. * Return Value:
  683. *
  684. * status
  685. *
  686. * History:
  687. *
  688. * 1/21/1997 Mark Enstrom [marke]
  689. *
  690. \**************************************************************************/
  691. BOOL
  692. bDetermineAlphaBlendFunction(
  693. PSURFACE pSurfDst,
  694. PSURFACE pSurfSrc,
  695. XEPALOBJ *ppalDst,
  696. XEPALOBJ *ppalSrc,
  697. XLATE *pxlateSrcTo32,
  698. LONG cxDst,
  699. PALPHA_DISPATCH_FORMAT pAlphaDispatch
  700. )
  701. {
  702. BOOL bRet = TRUE;
  703. BOOL bSrcHasAlpha = FALSE;
  704. pAlphaDispatch->bUseMMX = FALSE;
  705. //
  706. // does src bitmap have alpha
  707. //
  708. bSrcHasAlpha = (pAlphaDispatch->BlendFunction.AlphaFormat & AC_SRC_ALPHA);
  709. //
  710. // assume default blend, check for special cases
  711. //
  712. pAlphaDispatch->pfnGeneralBlend = vAlphaPerPixelOnly;
  713. //
  714. // use "over" optimized blend fucntion
  715. //
  716. if (bSrcHasAlpha && (pAlphaDispatch->BlendFunction.SourceConstantAlpha == 255))
  717. {
  718. pAlphaDispatch->pfnGeneralBlend = vAlphaPerPixelOnly;
  719. #if defined(_X86_)
  720. //
  721. // source and dest alignment must be 8 byte aligned to use mmx
  722. //
  723. if (gbMMXProcessor && (cxDst >= 8))
  724. {
  725. pAlphaDispatch->pfnGeneralBlend = mmxAlphaPerPixelOnly;
  726. pAlphaDispatch->bUseMMX = TRUE;
  727. }
  728. #endif
  729. }
  730. else
  731. {
  732. //
  733. // if source format doesn't support alpha then use
  734. // constant alpha routine
  735. //
  736. if (bSrcHasAlpha)
  737. {
  738. //
  739. // blend source and dest using SourceAlpha and
  740. // source bitmaps integral alpha
  741. //
  742. pAlphaDispatch->pfnGeneralBlend = vAlphaPerPixelAndConst;
  743. #if defined(_X86_)
  744. //
  745. // source and dest alignment must be 8 byte aligned to use mmx
  746. //
  747. if (gbMMXProcessor && (cxDst >= 8))
  748. {
  749. pAlphaDispatch->pfnGeneralBlend = mmxAlphaPerPixelAndConst;
  750. pAlphaDispatch->bUseMMX = TRUE;
  751. }
  752. #endif
  753. }
  754. else
  755. {
  756. //
  757. // blend src and dest using SourceConstantAlpha.
  758. //
  759. pAlphaDispatch->pfnGeneralBlend = vAlphaConstOnly;
  760. }
  761. }
  762. //
  763. // determine output conversion and storage routines
  764. //
  765. switch (pSurfDst->iFormat())
  766. {
  767. case BMF_1BPP:
  768. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvert1ToBGRA;
  769. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRATo1;
  770. pAlphaDispatch->ulDstBitsPerPixel = 1;
  771. break;
  772. case BMF_4BPP:
  773. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvert4ToBGRA;
  774. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRATo4;
  775. pAlphaDispatch->ulDstBitsPerPixel = 4;
  776. break;
  777. case BMF_8BPP:
  778. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvert8ToBGRA;
  779. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRATo8;
  780. pAlphaDispatch->ulDstBitsPerPixel = 8;
  781. break;
  782. case BMF_16BPP:
  783. ASSERTGDI((ppalDst->bIsBitfields()),"AlphaBlt: RGB16 palette must be bitfields");
  784. if (
  785. (ppalDst->flRed() == 0xf800) &&
  786. (ppalDst->flGre() == 0x07e0) &&
  787. (ppalDst->flBlu() == 0x001f)
  788. )
  789. {
  790. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvertRGB16_565ToBGRA;
  791. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRAToRGB16_565;
  792. }
  793. else if (
  794. (ppalDst->flRed() == 0x7c00) &&
  795. (ppalDst->flGre() == 0x03e0) &&
  796. (ppalDst->flBlu() == 0x001f)
  797. )
  798. {
  799. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvertRGB16_555ToBGRA;
  800. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRAToRGB16_555;
  801. }
  802. else
  803. {
  804. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvert16BitfieldsToBGRA;
  805. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRAToRGB16Bitfields;
  806. }
  807. pAlphaDispatch->ulDstBitsPerPixel = 16;
  808. break;
  809. case BMF_24BPP:
  810. // WINBUG #101656 bhouse 5-4-2000 AlphaBlend reversing R and B channels
  811. // when rendering to 24BPP
  812. if (
  813. (ppalDst->bIsBGR()) ||
  814. (
  815. (ppalDst->bIsBitfields()) &&
  816. (
  817. (
  818. (ppalDst->flRed() == 0xff0000) &&
  819. (ppalDst->flGre() == 0x00ff00) &&
  820. (ppalDst->flBlu() == 0x0000ff)
  821. ) ||
  822. (
  823. (ppalDst->flRed() == 0x000000) &&
  824. (ppalDst->flGre() == 0x000000) &&
  825. (ppalDst->flBlu() == 0x000000)
  826. )
  827. )
  828. )
  829. )
  830. {
  831. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvertBGR24ToBGRA;
  832. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRAToBGR24;
  833. pAlphaDispatch->ulDstBitsPerPixel = 24;
  834. }
  835. else
  836. {
  837. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvertRGB24ToBGRA;
  838. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRAToRGB24;
  839. pAlphaDispatch->ulDstBitsPerPixel = 24;
  840. }
  841. break;
  842. case BMF_32BPP:
  843. if (
  844. (ppalDst->bIsBGR()) ||
  845. (
  846. (ppalDst->bIsBitfields()) &&
  847. (
  848. (
  849. (ppalDst->flRed() == 0xff0000) &&
  850. (ppalDst->flGre() == 0x00ff00) &&
  851. (ppalDst->flBlu() == 0x0000ff)
  852. ) ||
  853. (
  854. (ppalDst->flRed() == 0x000000) &&
  855. (ppalDst->flGre() == 0x000000) &&
  856. (ppalDst->flBlu() == 0x000000)
  857. )
  858. )
  859. )
  860. )
  861. {
  862. //
  863. // assigned to null indicates no conversion needed
  864. //
  865. pAlphaDispatch->pfnLoadDstAndConvert = NULL;
  866. pAlphaDispatch->pfnConvertAndStore = NULL;
  867. }
  868. else if (ppalDst->flPal() & PAL_RGB)
  869. {
  870. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvertRGB32ToBGRA;
  871. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRAToRGB32;
  872. }
  873. else
  874. {
  875. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvert32BitfieldsToBGRA;
  876. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRATo32Bitfields;
  877. }
  878. pAlphaDispatch->ulDstBitsPerPixel = 32;
  879. break;
  880. default:
  881. WARNING("bDetermineAlphaBlendFunction: Illegal bitmap format\n");
  882. bRet = FALSE;
  883. }
  884. //
  885. // determine input load and conversion routine
  886. //
  887. switch (pSurfSrc->iFormat())
  888. {
  889. case BMF_1BPP:
  890. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvert1ToBGRA;
  891. pAlphaDispatch->ulSrcBitsPerPixel = 1;
  892. break;
  893. case BMF_4BPP:
  894. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvert4ToBGRA;
  895. pAlphaDispatch->ulSrcBitsPerPixel = 4;
  896. break;
  897. case BMF_8BPP:
  898. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvert8ToBGRA;
  899. pAlphaDispatch->ulSrcBitsPerPixel = 8;
  900. break;
  901. case BMF_16BPP:
  902. ASSERTGDI((ppalSrc->bIsBitfields()),"AlphaBlt: RGB16 palette must be bitfields");
  903. if ((ppalSrc->flRed() == 0xf800) &&
  904. (ppalSrc->flGre() == 0x07e0) &&
  905. (ppalSrc->flBlu() == 0x001f))
  906. {
  907. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvertRGB16_565ToBGRA;
  908. }
  909. else if ((ppalSrc->flRed() == 0x7c00) &&
  910. (ppalSrc->flGre() == 0x03e0) &&
  911. (ppalSrc->flBlu() == 0x001f))
  912. {
  913. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvertRGB16_555ToBGRA;
  914. }
  915. else
  916. {
  917. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvert16BitfieldsToBGRA;
  918. }
  919. pAlphaDispatch->ulSrcBitsPerPixel = 16;
  920. break;
  921. case BMF_24BPP:
  922. // WINBUG #101656 bhouse 5-4-2000 AlphaBlend reversing R and B channels
  923. // when rendering to 24BPP
  924. if ((ppalSrc->bIsBGR()) ||
  925. (
  926. (ppalSrc->bIsBitfields()) &&
  927. (
  928. (
  929. (ppalSrc->flRed() == 0xff0000) &&
  930. (ppalSrc->flGre() == 0x00ff00) &&
  931. (ppalSrc->flBlu() == 0x0000ff)
  932. ) ||
  933. (
  934. (ppalSrc->flRed() == 0x000000) &&
  935. (ppalSrc->flGre() == 0x000000) &&
  936. (ppalSrc->flBlu() == 0x000000)
  937. )
  938. )
  939. )
  940. )
  941. {
  942. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvertBGR24ToBGRA;
  943. }
  944. else
  945. {
  946. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvertRGB24ToBGRA;
  947. }
  948. pAlphaDispatch->ulSrcBitsPerPixel = 24;
  949. break;
  950. case BMF_32BPP:
  951. if (
  952. (pxlateSrcTo32 == NULL) ||
  953. (ppalSrc->bIsBGR()) ||
  954. (
  955. (ppalSrc->bIsBitfields()) &&
  956. (
  957. (
  958. (ppalSrc->flRed() == 0xff0000) &&
  959. (ppalSrc->flGre() == 0x00ff00) &&
  960. (ppalSrc->flBlu() == 0x0000ff)
  961. ) ||
  962. (
  963. (ppalSrc->flRed() == 0x000000) &&
  964. (ppalSrc->flGre() == 0x000000) &&
  965. (ppalSrc->flBlu() == 0x000000)
  966. )
  967. )
  968. )
  969. )
  970. {
  971. pAlphaDispatch->pfnLoadSrcAndConvert = NULL;
  972. }
  973. else if (ppalSrc->flPal() & PAL_RGB)
  974. {
  975. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvertRGB32ToBGRA;
  976. }
  977. else
  978. {
  979. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvert32BitfieldsToBGRA;
  980. }
  981. pAlphaDispatch->ulSrcBitsPerPixel = 32;
  982. break;
  983. default:
  984. WARNING("bDetermineAlphaBlendFunction: Illegal bitmap format\n");
  985. bRet = FALSE;
  986. }
  987. //
  988. // 16/24 bit per pixel blend optimization
  989. //
  990. if (pAlphaDispatch->pfnGeneralBlend == vAlphaConstOnly)
  991. {
  992. if ((pAlphaDispatch->pfnLoadSrcAndConvert == vLoadAndConvertRGB16_555ToBGRA) &&
  993. (pAlphaDispatch->pfnLoadDstAndConvert == vLoadAndConvertRGB16_555ToBGRA))
  994. {
  995. //
  996. // use direct 16 bpp blend
  997. //
  998. pAlphaDispatch->pfnGeneralBlend = vAlphaConstOnly16_555;
  999. #if defined(_X86_)
  1000. if (gbMMXProcessor && (cxDst >= 8))
  1001. {
  1002. pAlphaDispatch->pfnGeneralBlend = mmxAlphaConstOnly16_555;
  1003. pAlphaDispatch->bUseMMX = TRUE;
  1004. }
  1005. #endif
  1006. pAlphaDispatch->pfnLoadSrcAndConvert = NULL;
  1007. pAlphaDispatch->pfnLoadDstAndConvert = NULL;
  1008. pAlphaDispatch->pfnConvertAndStore = NULL;
  1009. //
  1010. // convert blend function from x/255 to y/31
  1011. //
  1012. int ia = pAlphaDispatch->BlendFunction.SourceConstantAlpha;
  1013. ia = (ia * 31 + 128)/255;
  1014. pAlphaDispatch->BlendFunction.SourceConstantAlpha = (BYTE)ia;
  1015. }
  1016. else if ((pAlphaDispatch->pfnLoadSrcAndConvert == vLoadAndConvertRGB16_565ToBGRA) &&
  1017. (pAlphaDispatch->pfnLoadDstAndConvert == vLoadAndConvertRGB16_565ToBGRA))
  1018. {
  1019. //
  1020. // use direct 16 bpp blend
  1021. //
  1022. pAlphaDispatch->pfnGeneralBlend = vAlphaConstOnly16_565;
  1023. #if defined(_X86_)
  1024. if (gbMMXProcessor && (cxDst >= 8))
  1025. {
  1026. pAlphaDispatch->pfnGeneralBlend = mmxAlphaConstOnly16_565;
  1027. pAlphaDispatch->bUseMMX = TRUE;
  1028. }
  1029. #endif
  1030. pAlphaDispatch->pfnLoadSrcAndConvert = NULL;
  1031. pAlphaDispatch->pfnLoadDstAndConvert = NULL;
  1032. pAlphaDispatch->pfnConvertAndStore = NULL;
  1033. //
  1034. // convert blend function from x/255 to y/31
  1035. //
  1036. int ia = pAlphaDispatch->BlendFunction.SourceConstantAlpha;
  1037. ia = (ia * 31 + 128)/255;
  1038. pAlphaDispatch->BlendFunction.SourceConstantAlpha = (BYTE)ia;
  1039. }
  1040. else if ((pAlphaDispatch->pfnLoadSrcAndConvert == vLoadAndConvertRGB24ToBGRA) &&
  1041. (pAlphaDispatch->pfnLoadDstAndConvert == vLoadAndConvertRGB24ToBGRA))
  1042. {
  1043. //
  1044. // use direct 24 bpp blend
  1045. //
  1046. pAlphaDispatch->pfnGeneralBlend = vAlphaConstOnly24;
  1047. #if defined(_X86_)
  1048. if (gbMMXProcessor && (cxDst >= 8))
  1049. {
  1050. pAlphaDispatch->pfnGeneralBlend = mmxAlphaConstOnly24;
  1051. pAlphaDispatch->bUseMMX = TRUE;
  1052. }
  1053. #endif
  1054. pAlphaDispatch->pfnLoadSrcAndConvert = NULL;
  1055. pAlphaDispatch->pfnLoadDstAndConvert = NULL;
  1056. pAlphaDispatch->pfnConvertAndStore = NULL;
  1057. }
  1058. }
  1059. return (bRet);
  1060. }
  1061. /******************************Public*Routine******************************\
  1062. * EngAlphaBlend
  1063. *
  1064. * Implement alpha blending
  1065. *
  1066. * Arguments:
  1067. *
  1068. * psoDst - destination surface
  1069. * psoSrc - source surface
  1070. * pco - clip object
  1071. * pxloSrcTo32 - translate src to 32 bgr
  1072. * pxloDstTo32 - translate dst to 32 bgr
  1073. * pxlo32ToDst - translate 32bgr to dst
  1074. * prclDst - dest rect
  1075. * prclSrc - src rect
  1076. * BlendFunction - blend function
  1077. *
  1078. * Return Value:
  1079. *
  1080. * status
  1081. *
  1082. * History:
  1083. *
  1084. * 21-Jun-1996 -by- Mark Enstrom [marke]
  1085. *
  1086. \**************************************************************************/
  1087. BOOL
  1088. EngAlphaBlend(
  1089. SURFOBJ *psoDst,
  1090. SURFOBJ *psoSrc,
  1091. CLIPOBJ *pco,
  1092. XLATEOBJ *pxlo,
  1093. RECTL *prclDst,
  1094. RECTL *prclSrc,
  1095. BLENDOBJ *pBlendObj
  1096. )
  1097. {
  1098. BOOL bRet = TRUE;
  1099. ASSERTGDI((prclSrc->left < prclSrc->right) &&
  1100. (prclSrc->top < prclSrc->bottom) &&
  1101. (prclDst->left < prclDst->right) &&
  1102. (prclDst->top < prclDst->bottom),
  1103. "Invalid rectangles");
  1104. EBLENDOBJ *peBlendObj = (EBLENDOBJ*)pBlendObj;
  1105. PSURFACE pSurfDst = SURFOBJ_TO_SURFACE(psoDst);
  1106. PSURFACE pSurfSrc = SURFOBJ_TO_SURFACE(psoSrc);
  1107. PSURFACE pSurfSrcTmp;
  1108. PSURFACE pSurfDstTmp;
  1109. BOOL bAllocDstSurf = FALSE;
  1110. XLATE *pxlateSrcTo32 = (XLATE *)peBlendObj->pxloSrcTo32;
  1111. XLATE *pxlateDstTo32 = (XLATE *)peBlendObj->pxloDstTo32;
  1112. XLATE *pxlate32ToDst = (XLATE *)peBlendObj->pxlo32ToDst;
  1113. RECTL rclDstWk = *prclDst;
  1114. RECTL rclSrcWk = *prclSrc;
  1115. POINTL ptlSrc;
  1116. CLIPOBJ *pcoDstWk = pco;
  1117. ALPHA_DISPATCH_FORMAT AlphaDispatch;
  1118. //
  1119. // check blend
  1120. //
  1121. AlphaDispatch.BlendFunction = peBlendObj->BlendFunction;
  1122. ASSERTGDI(peBlendObj->BlendFunction.BlendOp == AC_SRC_OVER,
  1123. "Invalid blend");
  1124. //
  1125. // must be alpha to pull palette information from xlates
  1126. //
  1127. SURFMEM surfTmpDst;
  1128. SURFMEM surfTmpSrc;
  1129. //
  1130. // For profiling purposes, set a flag in the PDEV to indicate that the
  1131. // driver punted this call.
  1132. //
  1133. {
  1134. PDEVOBJ po(pSurfDst->hdev());
  1135. if (po.bValid())
  1136. {
  1137. po.vDriverPuntedCall(TRUE);
  1138. }
  1139. }
  1140. if(peBlendObj->BlendFunction.BlendFlags & AC_USE_HIGHQUALITYFILTER)
  1141. {
  1142. BOOL bStretch = FALSE;
  1143. bStretch = ((rclDstWk.right - rclDstWk.left) != (rclSrcWk.right - rclSrcWk.left)) ||
  1144. ((rclDstWk.bottom - rclDstWk.top) != (rclSrcWk.bottom - rclSrcWk.top));
  1145. // Call EngHTBlt only when we have to stretch. When we dont have to
  1146. // stretch we fall through to the old 1:1 EngAlphaBlend code.
  1147. if(bStretch)
  1148. return EngHTBlt(psoDst,
  1149. psoSrc,
  1150. NULL,
  1151. pco,
  1152. pxlo,
  1153. NULL,
  1154. &gptlZero,
  1155. prclDst,
  1156. prclSrc,
  1157. NULL,
  1158. BBPF_DO_ALPHA_BLEND,
  1159. pBlendObj) == HTBLT_SUCCESS ? TRUE : FALSE ;
  1160. }
  1161. //
  1162. // Synchronize with the device driver before touching the device surface.
  1163. //
  1164. {
  1165. PDEVOBJ poDst(psoDst->hdev);
  1166. poDst.vSync(psoDst, NULL, 0);
  1167. PDEVOBJ poSrc(psoSrc->hdev);
  1168. poSrc.vSync(psoSrc, NULL, 0);
  1169. }
  1170. //
  1171. // Get a readable source surface that is stretched to the destination size.
  1172. //
  1173. pSurfSrcTmp = psSetupTransparentSrcSurface(
  1174. pSurfSrc,
  1175. pSurfDst,
  1176. &rclDstWk,
  1177. (XLATEOBJ *)pxlateSrcTo32,
  1178. &rclSrcWk,
  1179. surfTmpSrc,
  1180. SOURCE_ALPHA,
  1181. 0);
  1182. if ((pSurfSrcTmp != NULL) && (rclDstWk.left != rclDstWk.right))
  1183. {
  1184. //
  1185. // save final reduced dst rect. psSetupDstSurface may change rclDstWk to
  1186. // to a temp dib rect.
  1187. //
  1188. RECTL rclDstSurface = rclDstWk;
  1189. //
  1190. // temp surface rect is now same size as dst rect, just need point offset
  1191. //
  1192. ptlSrc.x = rclSrcWk.left;
  1193. ptlSrc.y = rclSrcWk.top;
  1194. //
  1195. // get a dst surface that can be written to, remember since it may have to
  1196. // be written back
  1197. //
  1198. pSurfDstTmp = psSetupDstSurface(
  1199. pSurfDst,
  1200. &rclDstWk,
  1201. surfTmpDst,
  1202. FALSE,
  1203. TRUE);
  1204. if (pSurfDstTmp)
  1205. {
  1206. if (pSurfDstTmp != pSurfDst)
  1207. {
  1208. bAllocDstSurf = TRUE;
  1209. }
  1210. XEPALOBJ palSrc(pSurfSrcTmp->ppal());
  1211. XEPALOBJ palDst(pSurfDstTmp->ppal());
  1212. //
  1213. // must have one valid surface palette. Must pass drawing routines
  1214. // two good palettes so duplicate good pointer
  1215. //
  1216. if (!palSrc.bValid())
  1217. {
  1218. //
  1219. // get source surface palette
  1220. //
  1221. // first try the palette translate, because the sprite code
  1222. // doesn't want to stick the palette in the surface
  1223. //
  1224. XLATE* pxlate = (XLATE*) pxlo;
  1225. if ((pxlate != NULL) && (pxlate->ppalSrc != NULL))
  1226. {
  1227. palSrc.ppalSet(pxlate->ppalSrc);
  1228. }
  1229. else
  1230. {
  1231. PDEVOBJ pdo(pSurfSrcTmp->hdev());
  1232. palSrc.ppalSet(pdo.ppalSurf());
  1233. }
  1234. ASSERTGDI(palSrc.bValid(),"EngAlphaBlend:can't get source palette");
  1235. }
  1236. if (!palDst.bValid())
  1237. {
  1238. //
  1239. // get destination surface palette
  1240. //
  1241. PDEVOBJ pdo(pSurfDstTmp->hdev());
  1242. ASSERTGDI(pdo.bValid(),"EngAlphaBlend:can't get destination palette");
  1243. palDst.ppalSet(pdo.ppalSurf());
  1244. }
  1245. //
  1246. // validate palettes
  1247. //
  1248. if (palSrc.bValid() && palDst.bValid())
  1249. {
  1250. LONG cxDst = rclDstWk.right - rclDstWk.left;
  1251. //
  1252. // if using a temp dst, no need to clip except to bounding rect
  1253. //
  1254. if (bAllocDstSurf)
  1255. {
  1256. pcoDstWk = NULL;
  1257. }
  1258. //
  1259. // determine blend function
  1260. //
  1261. bRet = bDetermineAlphaBlendFunction(pSurfDstTmp,
  1262. pSurfSrcTmp,
  1263. &palDst,
  1264. &palSrc,
  1265. pxlateSrcTo32,
  1266. cxDst,
  1267. &AlphaDispatch);
  1268. //
  1269. // NOTE:
  1270. // May be able to move setup of expensive EXLATE to and from 32 to
  1271. // here only for case where non-direct blending is needed
  1272. //
  1273. if (bRet)
  1274. {
  1275. KFLOATING_SAVE fsFpState;
  1276. //
  1277. // if alpha routines use MMX, must save and restore floating
  1278. // point state
  1279. //
  1280. if (bRet && AlphaDispatch.bUseMMX)
  1281. {
  1282. NTSTATUS status = KeSaveFloatingPointState(&fsFpState);
  1283. ASSERTGDI(NT_SUCCESS(status),
  1284. "Unexpected KeSaveFloatingPointState failure");
  1285. }
  1286. //
  1287. // Determine the clipping region complexity.
  1288. //
  1289. CLIPENUMRECT clenr;
  1290. BOOL bMore;
  1291. ULONG ircl;
  1292. //
  1293. // default (pcoDstWk = NULL) is use Dst rect as single clip rect,
  1294. // same as DC_TRIVIAL
  1295. //
  1296. bMore = FALSE;
  1297. clenr.c = 1;
  1298. clenr.arcl[0] = rclDstWk;
  1299. if (pcoDstWk != (CLIPOBJ *) NULL)
  1300. {
  1301. switch(pcoDstWk->iDComplexity)
  1302. {
  1303. case DC_TRIVIAL:
  1304. break;
  1305. case DC_RECT:
  1306. bMore = FALSE;
  1307. clenr.c = 1;
  1308. clenr.arcl[0] = pcoDstWk->rclBounds;
  1309. break;
  1310. case DC_COMPLEX:
  1311. bMore = TRUE;
  1312. ((ECLIPOBJ *) pcoDstWk)->cEnumStart(FALSE,
  1313. CT_RECTANGLES,
  1314. CD_LEFTDOWN,
  1315. CLIPOBJ_ENUM_LIMIT);
  1316. break;
  1317. default:
  1318. RIP("ERROR EngCopyBits bad clipping type");
  1319. }
  1320. }
  1321. //
  1322. // run through clipping enum
  1323. //
  1324. do
  1325. {
  1326. if (bMore)
  1327. {
  1328. bMore = ((ECLIPOBJ *) pcoDstWk)->bEnum(sizeof(clenr),
  1329. (PVOID) &clenr);
  1330. }
  1331. for (ircl = 0; ircl < clenr.c; ircl++)
  1332. {
  1333. PRECTL prcl = &clenr.arcl[ircl];
  1334. //
  1335. // Insersect the clip rectangle with the target rectangle to
  1336. // determine visible recangle
  1337. //
  1338. if (prcl->left < rclDstWk.left)
  1339. {
  1340. prcl->left = rclDstWk.left;
  1341. }
  1342. if (prcl->right > rclDstWk.right)
  1343. {
  1344. prcl->right = rclDstWk.right;
  1345. }
  1346. if (prcl->top < rclDstWk.top)
  1347. {
  1348. prcl->top = rclDstWk.top;
  1349. }
  1350. if (prcl->bottom > rclDstWk.bottom)
  1351. {
  1352. prcl->bottom = rclDstWk.bottom;
  1353. }
  1354. //
  1355. // Process the result if it's a valid rectangle.
  1356. //
  1357. if ((prcl->top < prcl->bottom) && (prcl->left < prcl->right))
  1358. {
  1359. POINTL pptlSrcOffset;
  1360. //
  1361. // Figure out the upper-left coordinates of rects to blt.
  1362. // NOTE: does not do right->left or bottom->top
  1363. //
  1364. pptlSrcOffset.x = ptlSrc.x + prcl->left - rclDstWk.left;
  1365. pptlSrcOffset.y = ptlSrc.y + prcl->top - rclDstWk.top;
  1366. bRet = AlphaScanLineBlend(
  1367. (PBYTE)pSurfDstTmp->pvScan0(),
  1368. prcl,
  1369. pSurfDstTmp->lDelta(),
  1370. (PBYTE)pSurfSrcTmp->pvScan0(),
  1371. pSurfSrcTmp->lDelta(),
  1372. &pptlSrcOffset,
  1373. pxlateSrcTo32,
  1374. pxlateDstTo32,
  1375. pxlate32ToDst,
  1376. palDst,
  1377. palSrc,
  1378. &AlphaDispatch
  1379. );
  1380. }
  1381. }
  1382. } while (bMore);
  1383. //
  1384. // if there is a dst temp surface, need to blt it to
  1385. // dst, then free
  1386. //
  1387. if (bAllocDstSurf)
  1388. {
  1389. PDEVOBJ pdoDst(pSurfDst->hdev());
  1390. POINTL ptlCopy = {0,0};
  1391. (*PPFNGET(pdoDst,CopyBits,pSurfDst->flags()))(
  1392. pSurfDst->pSurfobj(),
  1393. pSurfDstTmp->pSurfobj(),
  1394. pco,
  1395. &xloIdent,
  1396. &rclDstSurface,
  1397. &ptlCopy);
  1398. }
  1399. //
  1400. // restore fp state if MMX used
  1401. //
  1402. if (AlphaDispatch.bUseMMX)
  1403. {
  1404. KeRestoreFloatingPointState(&fsFpState);
  1405. }
  1406. }
  1407. }
  1408. else
  1409. {
  1410. bRet = FALSE;
  1411. }
  1412. }
  1413. else
  1414. {
  1415. WARNING1("EngAlphaBlend: failed to allocate and copy surface\n");
  1416. bRet = FALSE;
  1417. }
  1418. }
  1419. return (bRet);
  1420. }
  1421. /******************************Public*Routine******************************\
  1422. * NtGdiAlphaBlend
  1423. *
  1424. * Kernel stub for alpha blending
  1425. *
  1426. * Arguments:
  1427. *
  1428. * hdcDst - dst dc
  1429. * DstX - dst x origin
  1430. * DstY - dst y origin
  1431. * DstCx - dst width
  1432. * DstCy - dst height
  1433. * hdcSrc - src dc
  1434. * SrcX - src x origin
  1435. * SrcY - src y origin
  1436. * SrcCx - src width
  1437. * SrcCy - src height
  1438. * BlendFunction - blend function
  1439. *
  1440. * Return Value:
  1441. *
  1442. * status
  1443. *
  1444. * History:
  1445. *
  1446. * 27-Jun-1997 Added rotation support -by- Ori Gershony [orig]
  1447. *
  1448. * 21-Jun-1996 -by- Mark Enstrom [marke]
  1449. *
  1450. \**************************************************************************/
  1451. BOOL
  1452. NtGdiAlphaBlend(
  1453. HDC hdcDst,
  1454. LONG DstX,
  1455. LONG DstY,
  1456. LONG DstCx,
  1457. LONG DstCy,
  1458. HDC hdcSrc,
  1459. LONG SrcX,
  1460. LONG SrcY,
  1461. LONG SrcCx,
  1462. LONG SrcCy,
  1463. BLENDFUNCTION BlendFunction,
  1464. HANDLE hcmXform
  1465. )
  1466. {
  1467. BOOL bStatus = TRUE;
  1468. BOOL bQuickStretch = FALSE;
  1469. //
  1470. // check blend, only support AC_SRC_OVER now
  1471. //
  1472. if ((BlendFunction.BlendOp != AC_SRC_OVER) ||
  1473. ((BlendFunction.AlphaFormat & (~ AC_SRC_ALPHA)) != 0))
  1474. {
  1475. WARNING1("NtGdiAlphaBlend: invalid blend function\n");
  1476. EngSetLastError(ERROR_INVALID_PARAMETER);
  1477. return(FALSE);
  1478. }
  1479. if ((SrcCx == 0) || (SrcCy == 0))
  1480. {
  1481. //
  1482. // Src rectangle is empty--nothing to do.
  1483. //
  1484. return TRUE;
  1485. }
  1486. //
  1487. // no mirroring
  1488. //
  1489. if ((DstCx < 0) || (DstCy < 0) || (SrcCx < 0) || (SrcCy < 0))
  1490. {
  1491. WARNING1("NtGdiAlphaBlend: mirroring not allowed\n");
  1492. EngSetLastError(ERROR_INVALID_PARAMETER);
  1493. return(FALSE);
  1494. }
  1495. BOOL bMirrorBitmap = (BlendFunction.BlendFlags & AC_MIRRORBITMAP);
  1496. BlendFunction.BlendFlags &= ~AC_MIRRORBITMAP;
  1497. //
  1498. // validate dst DC
  1499. //
  1500. DCOBJ dcoDst(hdcDst);
  1501. if (!(dcoDst.bValid()) || dcoDst.bStockBitmap())
  1502. {
  1503. WARNING1("NtGdiAlphaBlend failed: invalid dst DC");
  1504. EngSetLastError(ERROR_INVALID_HANDLE);
  1505. return(FALSE);
  1506. }
  1507. DCOBJ dcoSrc(hdcSrc);
  1508. if (dcoSrc.bValid())
  1509. {
  1510. EXFORMOBJ xoDst(dcoDst, WORLD_TO_DEVICE);
  1511. EXFORMOBJ xoSrc(dcoSrc, WORLD_TO_DEVICE);
  1512. //
  1513. // no source rotation
  1514. //
  1515. if (!xoSrc.bRotationOrMirroring())
  1516. {
  1517. //
  1518. // Return null operations. Don't need to check source for
  1519. // empty because the xforms are the same except translation.
  1520. //
  1521. ERECTL erclSrc(SrcX,SrcY,SrcX+SrcCx,SrcY+SrcCy);
  1522. xoSrc.bXform(erclSrc);
  1523. erclSrc.vOrder();
  1524. //
  1525. // If destination has a rotation, compute a bounding box for the
  1526. // resulting parallelogram
  1527. //
  1528. POINTFIX pptfxDst[4];
  1529. ERECTL erclDst;
  1530. BOOL bRotationDst;
  1531. if ((bRotationDst = xoDst.bRotationOrMirroring()))
  1532. {
  1533. //
  1534. // Compute the resulting parallelogram. In order to make sure we don't lose
  1535. // precision in the rotation, we will store the output of the transformation
  1536. // in fixed point numbers (this is how PlgBlt does it and we want our output
  1537. // to match).
  1538. //
  1539. POINTL pptlDst[3];
  1540. pptlDst[0].x = DstX;
  1541. pptlDst[0].y = DstY;
  1542. pptlDst[1].x = DstX+DstCx;
  1543. pptlDst[1].y = DstY;
  1544. pptlDst[2].x = DstX;
  1545. pptlDst[2].y = DstY+DstCy;
  1546. xoDst.bXform(pptlDst, pptfxDst, 3);
  1547. if (!xoDst.bRotation())
  1548. {
  1549. //
  1550. // Mirroring transforms hack: back in windows 3.1, they used to shift
  1551. // by one for mirroring transforms. We need to support this here to
  1552. // be compatible with NT's BitBlt/StretchBlt that also use this hack, and
  1553. // also to be compatible with AlphaBlend that calls BitBlt/StretchBlt
  1554. // code when constant alpha=255 and there's no per-pixel alpha. Ick!
  1555. // See BLTRECORD::vOrderStupid for details. Also see bug 319917.
  1556. //
  1557. if (pptfxDst[0].x > pptfxDst[1].x)
  1558. {
  1559. //
  1560. // Mirroring in x
  1561. //
  1562. pptfxDst[0].x += LTOFX(1);
  1563. pptfxDst[1].x += LTOFX(1);
  1564. pptfxDst[2].x += LTOFX(1);
  1565. }
  1566. if (pptfxDst[0].y > pptfxDst[2].y)
  1567. {
  1568. //
  1569. // Mirroring in y
  1570. //
  1571. pptfxDst[0].y += LTOFX(1);
  1572. pptfxDst[1].y += LTOFX(1);
  1573. pptfxDst[2].y += LTOFX(1);
  1574. }
  1575. }
  1576. //
  1577. // Compute the fourth point using the first three points.
  1578. //
  1579. pptfxDst[3].x = pptfxDst[1].x + pptfxDst[2].x - pptfxDst[0].x;
  1580. pptfxDst[3].y = pptfxDst[1].y + pptfxDst[2].y - pptfxDst[0].y;
  1581. //
  1582. // Compute the bounding box. Algorithm borrowed from Donald Sidoroff's code
  1583. // in EngPlgBlt. Basically the first two statements decide whether the indices of
  1584. // the extremas are odd or even, and the last two statements determine exactly what
  1585. // they are.
  1586. //
  1587. int iLeft = (pptfxDst[1].x > pptfxDst[0].x) == (pptfxDst[1].x > pptfxDst[3].x);
  1588. int iTop = (pptfxDst[1].y > pptfxDst[0].y) == (pptfxDst[1].y > pptfxDst[3].y);
  1589. if (pptfxDst[iLeft].x > pptfxDst[iLeft ^ 3].x)
  1590. {
  1591. iLeft ^= 3;
  1592. }
  1593. if (pptfxDst[iTop].y > pptfxDst[iTop ^ 3].y)
  1594. {
  1595. iTop ^= 3;
  1596. }
  1597. erclDst = ERECTL(LONG_CEIL_OF_FIX(pptfxDst[iLeft ].x),
  1598. LONG_CEIL_OF_FIX(pptfxDst[iTop ].y),
  1599. LONG_CEIL_OF_FIX(pptfxDst[iLeft^3].x),
  1600. LONG_CEIL_OF_FIX(pptfxDst[iTop^3 ].y));
  1601. //
  1602. // The vertices should now be in vOrder, but it doesn't hurt to verify this...
  1603. //
  1604. ASSERTGDI((erclDst.right >= erclDst.left), "NtGdiAlphaBlend: erclDst not in vOrder");
  1605. ASSERTGDI((erclDst.bottom >= erclDst.top), "NtGdiAlphaBlend: erclDst not in vOrder");
  1606. }
  1607. else
  1608. {
  1609. //
  1610. // No rotation--just apply the transformation to the rectangle
  1611. //
  1612. erclDst = ERECTL(DstX,DstY,DstX+DstCx,DstY+DstCy);
  1613. xoDst.bXform(erclDst);
  1614. erclDst.vOrder();
  1615. }
  1616. if (!erclDst.bEmpty())
  1617. {
  1618. //
  1619. // Accumulate bounds. We can do this outside the DEVLOCK
  1620. //
  1621. if (dcoDst.fjAccum())
  1622. {
  1623. dcoDst.vAccumulate(erclDst);
  1624. }
  1625. //
  1626. // Lock the Rao region and the surface if we are drawing on a
  1627. // display surface. Bail out if we are in full screen mode.
  1628. //
  1629. DEVLOCKBLTOBJ dlo;
  1630. BOOL bLocked;
  1631. bLocked = dlo.bLock(dcoDst, dcoSrc);
  1632. if (bLocked)
  1633. {
  1634. //
  1635. // Check pSurfDst, this may be an info DC or a memory DC with default bitmap.
  1636. //
  1637. SURFACE *pSurfDst;
  1638. if ((pSurfDst = dcoDst.pSurface()) != NULL)
  1639. {
  1640. XEPALOBJ palDst(pSurfDst->ppal());
  1641. XEPALOBJ palDstDC(dcoDst.ppal());
  1642. SURFACE *pSurfSrc = dcoSrc.pSurface();
  1643. //
  1644. // Basically we check that pSurfSrc is not NULL which
  1645. // happens for memory bitmaps with the default bitmap
  1646. // and for info DC's. Otherwise we continue if
  1647. // the source is readable or if it isn't we continue
  1648. // if we are blting display to display or if User says
  1649. // we have ScreenAccess on this display DC. Note
  1650. // that if pSurfSrc is not readable the only way we
  1651. // can continue the blt is if the src is a display.
  1652. //
  1653. if (pSurfSrc != NULL)
  1654. {
  1655. if ((pSurfSrc->bReadable()) ||
  1656. ( (dcoSrc.bDisplay()) &&
  1657. ((dcoDst.bDisplay()) || UserScreenAccessCheck() )))
  1658. {
  1659. // Make sure that if the user claims that the source contains an
  1660. // Alpha channel, it's a 32BPP source. This is important, because
  1661. // the driver has no way of checking whether the source is 32BPP.
  1662. if ((BlendFunction.AlphaFormat & AC_SRC_ALPHA) &&
  1663. (!(bIsSourceBGRA(pSurfSrc))))
  1664. {
  1665. WARNING("NtGdiAlphaBlend: AlphaFormat claims that there is an Alpha channel in a surface that's not 32BPP");
  1666. EngSetLastError(ERROR_INVALID_PARAMETER);
  1667. return FALSE;
  1668. }
  1669. //
  1670. // With a fixed DC origin we can change the destination to SCREEN coordinates.
  1671. //
  1672. //
  1673. // This is useful later for rotations
  1674. //
  1675. ERECTL erclDstOrig = erclDst;
  1676. erclDst += dcoDst.eptlOrigin();
  1677. erclSrc += dcoSrc.eptlOrigin();
  1678. //
  1679. // Make sure the source rectangle lies completely within the source
  1680. // surface.
  1681. //
  1682. BOOL bBadRects;
  1683. // If the source is a Meta device, we must check bounds taking its
  1684. // origin into account.
  1685. PDEVOBJ pdoSrc( pSurfSrc->hdev() );
  1686. if( pSurfSrc->iType() == STYPE_DEVICE &&
  1687. pdoSrc.bValid() && pdoSrc.bMetaDriver())
  1688. {
  1689. bBadRects = ((erclSrc.left < pdoSrc.pptlOrigin()->x) ||
  1690. (erclSrc.top < pdoSrc.pptlOrigin()->y) ||
  1691. (erclSrc.right > pdoSrc.pptlOrigin()->x +
  1692. pSurfSrc->sizl().cx) ||
  1693. (erclSrc.bottom > pdoSrc.pptlOrigin()->y +
  1694. pSurfSrc->sizl().cy));
  1695. }
  1696. else
  1697. {
  1698. bBadRects = ((erclSrc.left < 0) ||
  1699. (erclSrc.top < 0) ||
  1700. (erclSrc.right > pSurfSrc->sizl().cx) ||
  1701. (erclSrc.bottom > pSurfSrc->sizl().cy));
  1702. }
  1703. if (bBadRects)
  1704. {
  1705. WARNING("NtGdiAlphaBlend -- source rectangle out of surface bounds");
  1706. }
  1707. //
  1708. // Make sure that source and destination rectangles don't overlap if the
  1709. // source surface is the same as the destination surface.
  1710. //
  1711. if (pSurfSrc == pSurfDst)
  1712. {
  1713. ERECTL erclIntersection = erclSrc;
  1714. erclIntersection *= erclDst;
  1715. if (!erclIntersection.bEmpty())
  1716. {
  1717. bBadRects = TRUE;
  1718. WARNING ("NtGdiAlphaBlend -- source and destination rectangles are on the same surface and overlap");
  1719. }
  1720. }
  1721. if (!bBadRects)
  1722. {
  1723. //
  1724. // check for quick out
  1725. //
  1726. if ((BlendFunction.SourceConstantAlpha == 255) &&
  1727. (!(BlendFunction.AlphaFormat & AC_SRC_ALPHA)) &&
  1728. (!(BlendFunction.BlendFlags & AC_USE_HIGHQUALITYFILTER)))
  1729. {
  1730. // BUGFIX #331222 2-2-2001
  1731. // Set stretch mode to COLORONCOLOR for duration of GreStretchBlt call
  1732. // AlphaBlend always point samples when stretching
  1733. BYTE jStretchBltMode = dcoDst.pdc->jStretchBltMode();
  1734. dcoDst.pdc->jStretchBltMode(COLORONCOLOR);
  1735. bStatus = GreStretchBlt(
  1736. hdcDst,
  1737. DstX,
  1738. DstY,
  1739. DstCx,
  1740. DstCy,
  1741. hdcSrc,
  1742. SrcX,
  1743. SrcY,
  1744. SrcCx,
  1745. SrcCy,
  1746. SRCCOPY,
  1747. 0xffffffff);
  1748. bQuickStretch = TRUE;
  1749. dcoDst.pdc->jStretchBltMode(jStretchBltMode);
  1750. }
  1751. //
  1752. // no quick out
  1753. //
  1754. if (bStatus & !bQuickStretch)
  1755. {
  1756. XEPALOBJ palSrc(pSurfSrc->ppal());
  1757. XEPALOBJ palSrcDC(dcoSrc.ppal());
  1758. EXLATEOBJ xlo,xlo1,xloSrcDCto32,xloDstDCto32,xlo32toDstDC;
  1759. XLATEOBJ *pxlo,*pxloSrcDCto32,*pxloDstDCto32,*pxlo32toDstDC;
  1760. XEPALOBJ palRGB(gppalRGB);
  1761. //
  1762. // Get a translate object from source dc to BGRA
  1763. //
  1764. COLORREF crBackColor = dcoSrc.pdc->ulBackClr();
  1765. //
  1766. // src to dst
  1767. //
  1768. bStatus = xlo.bInitXlateObj(
  1769. NULL,
  1770. DC_ICM_OFF,
  1771. palSrc,
  1772. palDst,
  1773. palSrcDC,
  1774. palDstDC,
  1775. dcoSrc.pdc->crTextClr(),
  1776. dcoSrc.pdc->crBackClr(),
  1777. crBackColor
  1778. );
  1779. pxlo = xlo.pxlo();
  1780. //
  1781. // src to 32
  1782. //
  1783. bStatus &= xloSrcDCto32.bInitXlateObj(
  1784. NULL,
  1785. DC_ICM_OFF,
  1786. palSrc,
  1787. palRGB,
  1788. palSrcDC,
  1789. palSrcDC,
  1790. dcoSrc.pdc->crTextClr(),
  1791. dcoSrc.pdc->crBackClr(),
  1792. crBackColor
  1793. );
  1794. pxloSrcDCto32 = xloSrcDCto32.pxlo();
  1795. //
  1796. // translate from dst dc to BGRA
  1797. //
  1798. bStatus &= xloDstDCto32.bInitXlateObj(
  1799. NULL,
  1800. DC_ICM_OFF,
  1801. palDst,
  1802. palRGB,
  1803. palDstDC,
  1804. palDstDC,
  1805. dcoSrc.pdc->crTextClr(),
  1806. dcoSrc.pdc->crBackClr(),
  1807. crBackColor
  1808. );
  1809. pxloDstDCto32 = xloDstDCto32.pxlo();
  1810. //
  1811. // create xlate from 32 to dst dc
  1812. //
  1813. bStatus &= xlo32toDstDC.bInitXlateObj(
  1814. NULL,
  1815. DC_ICM_OFF,
  1816. palRGB,
  1817. palDst,
  1818. palDstDC,
  1819. palDstDC,
  1820. dcoSrc.pdc->crTextClr(),
  1821. dcoSrc.pdc->crBackClr(),
  1822. crBackColor
  1823. );
  1824. pxlo32toDstDC = xlo32toDstDC.pxlo();
  1825. // Compute destination clipping
  1826. ECLIPOBJ eco(dcoDst.prgnEffRao(), erclDst);
  1827. // Check the destination which is reduced by clipping.
  1828. if (eco.erclExclude().bEmpty())
  1829. {
  1830. // NTBUG #456213 2-4-2000 bhouse Clean up use of multiple return
  1831. // perf and size: don't return here
  1832. return(TRUE);
  1833. }
  1834. // Compute the exclusion rectangle.
  1835. ERECTL erclExclude = eco.erclExclude();
  1836. // If we are going to the same source, prevent bad overlap situations
  1837. // Expand exclusion rectangle to cover source rectangle
  1838. if (dcoSrc.pSurface() == dcoDst.pSurface())
  1839. {
  1840. if (erclSrc.left < erclExclude.left)
  1841. erclExclude.left = erclSrc.left;
  1842. if (erclSrc.top < erclExclude.top)
  1843. erclExclude.top = erclSrc.top;
  1844. if (erclSrc.right > erclExclude.right)
  1845. erclExclude.right = erclSrc.right;
  1846. if (erclSrc.bottom > erclExclude.bottom)
  1847. erclExclude.bottom = erclSrc.bottom;
  1848. }
  1849. // We might have to exclude the source or the target, get ready to do either.
  1850. DEVEXCLUDEOBJ dxo;
  1851. // Lock the source and target LDEVs
  1852. PDEVOBJ pdoDst(pSurfDst->hdev());
  1853. // They can't both be display
  1854. if (dcoSrc.bDisplay())
  1855. {
  1856. ERECTL ercl(0,0,pSurfSrc->sizl().cx,pSurfSrc->sizl().cy);
  1857. if (dcoSrc.pSurface() == dcoDst.pSurface())
  1858. ercl *= erclExclude;
  1859. else
  1860. ercl *= erclSrc;
  1861. dxo.vExclude(dcoSrc.hdev(),&ercl,NULL);
  1862. }
  1863. else if (dcoDst.bDisplay())
  1864. {
  1865. dxo.vExclude(dcoDst.hdev(),&erclExclude,&eco);
  1866. }
  1867. //
  1868. // Note Win2k App compat: We do
  1869. // mirroring only when the caller has
  1870. // asked for it. This it to make sure
  1871. // apps that worked on win2k are not
  1872. // suddenly mirrored causing problems.
  1873. //
  1874. // If we need to do RTL layout then
  1875. // we create a temporary surface and
  1876. // mirror the source into it. Then
  1877. // we use it as the source surface.
  1878. //
  1879. SURFMEM surfMirrorSrc;
  1880. if (bMirrorBitmap &&
  1881. (MIRRORED_DC(dcoDst.pdc)) &&
  1882. (!MIRRORED_DC_NO_BITMAP_FLIP(dcoDst.pdc)))
  1883. {
  1884. // Create temporary surface
  1885. DEVBITMAPINFO dbmi;
  1886. dbmi.cxBitmap = pSurfSrc->sizl().cx;
  1887. dbmi.cyBitmap = pSurfSrc->sizl().cy;
  1888. dbmi.iFormat = pSurfSrc->iFormat();
  1889. dbmi.fl = 0;
  1890. XEPALOBJ palMirrorSrc(pSurfSrc->ppal());
  1891. dbmi.hpal = (HPALETTE)palMirrorSrc.hpal();
  1892. surfMirrorSrc.bCreateDIB(&dbmi,(VOID*)NULL);
  1893. if(!surfMirrorSrc.bValid())
  1894. {
  1895. WARNING("NtGdiAlphaBlend: Could not create surface to mirror the source");
  1896. return FALSE;
  1897. }
  1898. ERECTL erclMirrorSrc(0,0,pSurfSrc->sizl().cx,pSurfSrc->sizl().cy);
  1899. EPOINTL eptlMirrorSrcTopLeft(0,0);
  1900. // Copy source surface into the
  1901. // temporary
  1902. if(!(*PPFNGET(pdoSrc,CopyBits,pSurfSrc->flags()))(
  1903. surfMirrorSrc.ps->pSurfobj(),
  1904. pSurfSrc->pSurfobj(),
  1905. NULL,
  1906. NULL,
  1907. &erclMirrorSrc,
  1908. &eptlMirrorSrcTopLeft))
  1909. {
  1910. WARNING("NtGdiAlphaBlend: Could not mirror the source");
  1911. return FALSE;
  1912. }
  1913. // Mirror the temporary surface.
  1914. (*apfnMirror[surfMirrorSrc.ps->iFormat()])(surfMirrorSrc.ps);
  1915. // Use temporary surface as source.
  1916. pSurfSrc = surfMirrorSrc.ps;
  1917. }
  1918. //
  1919. // If the destination requires rotation, we allocate a surface and rotate the
  1920. // source surface into it.
  1921. //
  1922. SURFMEM surfMemTmpSrc;
  1923. //
  1924. // If the source is 32bits and has no per pixel Alpha, we need to first copy it
  1925. // and then add per pixel Alpha information (all this before the rotation).
  1926. //
  1927. SURFMEM surfMemTmpSrcPreRotate;
  1928. if (bRotationDst)
  1929. {
  1930. //
  1931. // allocate 32bpp BGRA surface for source, must be zero init
  1932. //
  1933. DEVBITMAPINFO dbmi;
  1934. dbmi.cxBitmap = erclDst.right - erclDst.left;
  1935. dbmi.cyBitmap = erclDst.bottom - erclDst.top;
  1936. dbmi.iFormat = BMF_32BPP;
  1937. dbmi.fl = 0;
  1938. XEPALOBJ palRGB(gppalRGB);
  1939. dbmi.hpal = (HPALETTE)palRGB.hpal();
  1940. bStatus &= surfMemTmpSrc.bCreateDIB(&dbmi, (VOID *) NULL);
  1941. //
  1942. // init DIB to transparent
  1943. // (so that portions of dst rect not covered by source rect are not drawn)
  1944. //
  1945. if (bStatus)
  1946. {
  1947. if (!(BlendFunction.AlphaFormat & AC_SRC_ALPHA))
  1948. {
  1949. //
  1950. // Source has no per pixel Alpha. Need to first
  1951. // copy source to a new bitmap, then set the per pixel Alpha,
  1952. // and only then rotate.
  1953. //
  1954. DEVBITMAPINFO dbmiPreRotate;
  1955. dbmiPreRotate.cxBitmap = erclSrc.right - erclSrc.left;
  1956. dbmiPreRotate.cyBitmap = erclSrc.bottom - erclSrc.top;
  1957. dbmiPreRotate.iFormat = BMF_32BPP;
  1958. dbmiPreRotate.fl = 0;
  1959. XEPALOBJ palRGB(gppalRGB);
  1960. dbmiPreRotate.hpal = (HPALETTE)palRGB.hpal();
  1961. bStatus = surfMemTmpSrcPreRotate.bCreateDIB(&dbmiPreRotate, (VOID *) NULL);
  1962. if (bStatus)
  1963. {
  1964. //
  1965. // Make sure the bitmap starts at (0,0), but remember the original
  1966. // starting point in eptlSrcTopLeft
  1967. //
  1968. EPOINTL eptlSrcTopLeft (erclSrc.left, erclSrc.top);
  1969. // Make sure the subtraction doesn't overflow
  1970. if (((erclSrc.left < 0) &&
  1971. (-erclSrc.left > MAXLONG/2) &&
  1972. (erclSrc.right > MAXLONG/2)) ||
  1973. ((erclSrc.top < 0) &&
  1974. (-erclSrc.top > MAXLONG/2) &&
  1975. (erclSrc.top > MAXLONG/2)))
  1976. {
  1977. //
  1978. // Fail the call
  1979. //
  1980. WARNING("NtGdiAlphaBlend: source rectangle too large\n");
  1981. EngSetLastError(ERROR_INVALID_PARAMETER);
  1982. return FALSE;
  1983. }
  1984. erclSrc -= eptlSrcTopLeft;
  1985. //
  1986. // Only call EngCopyBits for non-empty rectangles
  1987. //
  1988. if ((erclSrc.right > erclSrc.left) &&
  1989. (erclSrc.bottom > erclSrc.top) &&
  1990. (eptlSrcTopLeft.x <= pSurfSrc->sizl().cx) &&
  1991. (eptlSrcTopLeft.y <= pSurfSrc->sizl().cy))
  1992. {
  1993. EngCopyBits(
  1994. surfMemTmpSrcPreRotate.ps->pSurfobj(),
  1995. pSurfSrc->pSurfobj(),
  1996. NULL,
  1997. pxloSrcDCto32,
  1998. &erclSrc,
  1999. &eptlSrcTopLeft
  2000. );
  2001. }
  2002. //
  2003. // Now set the Alpha channel to 255 (opaque)
  2004. //
  2005. PULONG pulDstY = (PULONG)surfMemTmpSrcPreRotate.ps->pvScan0();
  2006. PULONG pulDstLastY = (PULONG)((PBYTE)pulDstY +
  2007. (surfMemTmpSrcPreRotate.ps->lDelta() *
  2008. surfMemTmpSrcPreRotate.ps->sizl().cy));
  2009. LONG DstYCount = 0;
  2010. while (pulDstY != pulDstLastY)
  2011. {
  2012. if ((DstYCount >= erclSrc.top) &&
  2013. (DstYCount < erclSrc.bottom))
  2014. {
  2015. PULONG pulDstX = pulDstY;
  2016. PULONG pulDstLastX = pulDstX + surfMemTmpSrcPreRotate.ps->sizl().cx;
  2017. LONG DstXCount = 0;
  2018. while (pulDstX != pulDstLastX)
  2019. {
  2020. if ((DstXCount >= erclSrc.left) &&
  2021. (DstXCount < erclSrc.right))
  2022. {
  2023. *pulDstX = *pulDstX | 0xff000000;
  2024. }
  2025. DstXCount++;
  2026. pulDstX++;
  2027. }
  2028. }
  2029. DstYCount++;
  2030. pulDstY = (PULONG)((PBYTE)pulDstY + surfMemTmpSrcPreRotate.ps->lDelta());
  2031. }
  2032. //
  2033. // Set source surface to pre rotated bitmap, and set color
  2034. // translation to trivial
  2035. //
  2036. pSurfSrc = surfMemTmpSrcPreRotate.ps;
  2037. pxloSrcDCto32 = &xloIdent;
  2038. //
  2039. // Now we have an Alpha channel
  2040. //
  2041. BlendFunction.AlphaFormat |= AC_SRC_ALPHA;
  2042. }
  2043. }
  2044. //
  2045. // Source is 32bit with per pixel Alpha. Make sure everything
  2046. // is transparent before the EngPlgBlt call.
  2047. //
  2048. RtlFillMemoryUlong(surfMemTmpSrc.ps->pvBits(),
  2049. surfMemTmpSrc.ps->cjBits(),
  2050. 0x00000000);
  2051. }
  2052. if (!bStatus)
  2053. {
  2054. //
  2055. // Fail the call
  2056. //
  2057. WARNING("NtGdiAlphaBlend: failed to create temporary DIB\n");
  2058. EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2059. return FALSE;
  2060. }
  2061. //
  2062. // Now define the parallelogram the source bitmap is mapped to in surfMemTmpSrc
  2063. //
  2064. EPOINTFIX eptlNewSrc[3];
  2065. eptlNewSrc[0] = EPOINTFIX(
  2066. pptfxDst[0].x - LTOFX(erclDstOrig.left),
  2067. pptfxDst[0].y - LTOFX(erclDstOrig.top)
  2068. );
  2069. eptlNewSrc[1] = EPOINTFIX(
  2070. pptfxDst[1].x - LTOFX(erclDstOrig.left),
  2071. pptfxDst[1].y - LTOFX(erclDstOrig.top)
  2072. );
  2073. eptlNewSrc[2] = EPOINTFIX(
  2074. pptfxDst[2].x - LTOFX(erclDstOrig.left),
  2075. pptfxDst[2].y - LTOFX(erclDstOrig.top)
  2076. );
  2077. EngPlgBlt(
  2078. surfMemTmpSrc.ps->pSurfobj(),
  2079. pSurfSrc->pSurfobj(),
  2080. NULL, // No mask
  2081. NULL, // No clipping object
  2082. pxloSrcDCto32,
  2083. NULL, // No color adjustment
  2084. NULL,
  2085. eptlNewSrc,
  2086. &erclSrc,
  2087. NULL,
  2088. COLORONCOLOR
  2089. );
  2090. //
  2091. // Now adjust the local variables. First fix color translation.
  2092. //
  2093. //
  2094. // src to dst
  2095. //
  2096. bStatus = xlo1.bInitXlateObj(
  2097. NULL,
  2098. DC_ICM_OFF,
  2099. palRGB,
  2100. palDst,
  2101. NULL,
  2102. palDstDC,
  2103. dcoSrc.pdc->crTextClr(),
  2104. dcoSrc.pdc->crBackClr(),
  2105. crBackColor
  2106. );
  2107. pxlo = xlo1.pxlo();
  2108. //
  2109. // src to 32
  2110. //
  2111. pxloSrcDCto32 = &xloIdent;
  2112. pSurfSrc = surfMemTmpSrc.ps;
  2113. erclSrc.left = 0;
  2114. erclSrc.top = 0;
  2115. erclSrc.right = erclDst.right - erclDst.left;
  2116. erclSrc.bottom = erclDst.bottom - erclDst.top;
  2117. }
  2118. if (bStatus)
  2119. {
  2120. //
  2121. // Inc the target surface uniqueness
  2122. //
  2123. INC_SURF_UNIQ(pSurfDst);
  2124. //
  2125. // Dispatch the call. Give it no mask.
  2126. //
  2127. //
  2128. // Check were on the same PDEV, we can't blt between
  2129. // different PDEV's. We could make blting between different
  2130. // PDEV's work easily. All we need to do force EngBitBlt to
  2131. // be called if the PDEV's aren't equal in the dispatch.
  2132. // EngBitBlt does the right thing.
  2133. //
  2134. if (dcoDst.hdev() == dcoSrc.hdev())
  2135. {
  2136. EBLENDOBJ eBlendObj;
  2137. eBlendObj.BlendFunction = BlendFunction;
  2138. eBlendObj.pxloSrcTo32 = pxloSrcDCto32;
  2139. eBlendObj.pxloDstTo32 = pxloDstDCto32;
  2140. eBlendObj.pxlo32ToDst = pxlo32toDstDC;
  2141. //
  2142. // dispatch to driver or engine
  2143. //
  2144. if ( (erclDst.right - erclDst.left) == (erclSrc.right - erclSrc.left) &&
  2145. (erclDst.bottom - erclDst.top) == (erclSrc.bottom - erclSrc.top) )
  2146. {
  2147. eBlendObj.BlendFunction.BlendFlags &= ~AC_USE_HIGHQUALITYFILTER;
  2148. }
  2149. bStatus = (*PPFNGET(pdoDst,AlphaBlend, pSurfDst->flags())) (
  2150. pSurfDst->pSurfobj(),
  2151. pSurfSrc->pSurfobj(),
  2152. &eco,
  2153. pxlo,
  2154. &erclDst,
  2155. &erclSrc,
  2156. (BLENDOBJ *)&eBlendObj
  2157. );
  2158. }
  2159. else
  2160. {
  2161. WARNING1("NtGdiAlphaBlend failed: source and destination surfaces not on same PDEV");
  2162. EngSetLastError(ERROR_INVALID_PARAMETER);
  2163. bStatus = FALSE;
  2164. }
  2165. }
  2166. else
  2167. {
  2168. WARNING1("bInitXlateObj failed in NtGdiAlphaBlend\n");
  2169. EngSetLastError(ERROR_INVALID_HANDLE);
  2170. bStatus = FALSE;
  2171. }
  2172. }
  2173. else
  2174. {
  2175. //
  2176. // Nothing to do--the call to GreStretchBlt succeeded.
  2177. //
  2178. NULL;
  2179. }
  2180. }
  2181. else
  2182. {
  2183. EngSetLastError(ERROR_INVALID_PARAMETER);
  2184. bStatus = FALSE;
  2185. }
  2186. }
  2187. else
  2188. {
  2189. WARNING1("NtGdiAlphaBlend failed - trying to read from unreadable surface\n");
  2190. EngSetLastError(ERROR_INVALID_HANDLE);
  2191. bStatus = FALSE;
  2192. }
  2193. }
  2194. else
  2195. {
  2196. bStatus = TRUE; // pSurfSrc is NULL
  2197. }
  2198. }
  2199. else
  2200. {
  2201. bStatus = TRUE; // pSurfDst is NULL
  2202. }
  2203. }
  2204. else
  2205. {
  2206. //
  2207. // Return True if we are in full screen mode.
  2208. //
  2209. bStatus = dcoDst.bFullScreen() | dcoSrc.bFullScreen();
  2210. }
  2211. }
  2212. else
  2213. {
  2214. bStatus = TRUE; // erclDst is empty
  2215. }
  2216. }
  2217. else
  2218. {
  2219. bStatus = FALSE;
  2220. EngSetLastError(ERROR_INVALID_PARAMETER);
  2221. WARNING1("Error in NtGdiAlphaBlend: source rotation is not allowed");
  2222. }
  2223. }
  2224. else
  2225. {
  2226. bStatus = FALSE;
  2227. EngSetLastError(ERROR_INVALID_PARAMETER);
  2228. WARNING1("NtGdiAlphaBlend failed: invalid src DC");
  2229. }
  2230. return(bStatus);
  2231. }