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.

1139 lines
27 KiB

  1. /*++
  2. Copyright (c) 1996-1999 Microsoft Corporation
  3. Module Name
  4. alpha.cxx
  5. Abstract:
  6. alpha blending functions
  7. Author:
  8. Mark Enstrom (marke) 23-Jun-1996
  9. Enviornment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include "precomp.hxx"
  14. #pragma hdrstop
  15. #if DBG
  16. ULONG DbgAlpha = 0;
  17. #endif
  18. extern PFNALPHABLEND gpfnAlphaBlend;
  19. extern PFNALPHADIB gpfnAlphaDIB;
  20. #if !(_WIN32_WINNT >= 0x500)
  21. #if defined(_X86_)
  22. ULONG gMMX = 0;
  23. /**************************************************************************\
  24. * IsMMXProcessor
  25. *
  26. *
  27. * Arguments:
  28. *
  29. *
  30. *
  31. * Return Value:
  32. *
  33. *
  34. *
  35. * History:
  36. *
  37. * 4/10/1997 Mark Enstrom [marke]
  38. *
  39. \**************************************************************************/
  40. #define CPUID _asm _emit 0fh _asm _emit 0a2h
  41. BOOL
  42. bIsMMXProcessor(VOID)
  43. {
  44. BOOL retval = TRUE;
  45. DWORD RegEDX;
  46. //
  47. // Find out if procesor supports CPUID
  48. //
  49. //
  50. //__try
  51. //{
  52. // _asm
  53. // {
  54. // mov eax, 1
  55. //
  56. // // code bytes = 0fh, 0a2h
  57. //
  58. // CPUID
  59. // mov RegEDX, edx
  60. // }
  61. //} __except(EXCEPTION_EXECUTE_HANDLER)
  62. //{
  63. // retval = FALSE;
  64. //}
  65. //
  66. //if (retval == FALSE)
  67. //{
  68. // //
  69. // // processor does not support CPUID
  70. // //
  71. //
  72. // return FALSE;
  73. //}
  74. //
  75. ////
  76. //// bit 23 is set for MMX technology
  77. ////
  78. //
  79. //if (RegEDX & 0x800000)
  80. //{
  81. //
  82. // save and restore fp state around emms!!!
  83. //
  84. __try
  85. {
  86. _asm emms
  87. }
  88. __except(EXCEPTION_EXECUTE_HANDLER)
  89. {
  90. retval = FALSE;
  91. }
  92. //}
  93. //else
  94. //{
  95. // //
  96. // // processor supports CPUID but does not have MMX technology
  97. // //
  98. //
  99. // return FALSE;
  100. //}
  101. //
  102. // if retval == 0 here that means the processor has MMX technology but
  103. // the FP emulation is on so MMX technology is unavailable
  104. //
  105. return retval;
  106. }
  107. #endif
  108. /**************************************************************************\
  109. * bDetermineAlphaBlendFunction
  110. *
  111. *
  112. * Arguments:
  113. *
  114. *
  115. *
  116. * Return Value:
  117. *
  118. *
  119. *
  120. * History:
  121. *
  122. * 1/21/1997 Mark Enstrom [marke]
  123. *
  124. \**************************************************************************/
  125. BOOL
  126. bDetermineAlphaBlendFunction(
  127. CONST DIBINFO *pdibDst,
  128. CONST DIBINFO *pdibSrc,
  129. PALPHA_DISPATCH_FORMAT pAlphaDispatch
  130. )
  131. {
  132. PULONG pulSrcMask = (PULONG)&pdibSrc->pbmi->bmiColors[0];
  133. ULONG ulSrcFlRed;
  134. ULONG ulSrcFlGreen;
  135. ULONG ulSrcFlBlue;
  136. PULONG pulDstMask = (PULONG)&pdibDst->pbmi->bmiColors[0];
  137. ULONG ulDstFlRed;
  138. ULONG ulDstFlGreen;
  139. ULONG ulDstFlBlue;
  140. pAlphaDispatch->pfnGeneralBlend = vPixelGeneralBlend;
  141. ULONG DstBitPerPixel = pdibDst->pbmi->bmiHeader.biBitCount;
  142. LONG DstWidth = pdibDst->pbmi->bmiHeader.biWidth;
  143. ULONG SrcBitPerPixel = pdibSrc->pbmi->bmiHeader.biBitCount;
  144. LONG SrcWidth = pdibSrc->pbmi->bmiHeader.biWidth;
  145. LONG cxDst = pdibDst->rclDIB.right - pdibDst->rclDIB.left;
  146. pAlphaDispatch->ulDstBitsPerPixel = DstBitPerPixel;
  147. pAlphaDispatch->ulSrcBitsPerPixel = SrcBitPerPixel;
  148. //
  149. // does src btimap have alpha
  150. //
  151. BOOL bSrcHasAlpha = FALSE;
  152. if (
  153. ((pAlphaDispatch->BlendFunction.AlphaFormat & AC_SRC_NO_ALPHA) == 0) &&
  154. (SrcBitPerPixel == 32) &&
  155. (
  156. (pdibSrc->pbmi->bmiHeader.biCompression == BI_RGB) ||
  157. (
  158. (pdibSrc->pbmi->bmiHeader.biCompression == BI_BITFIELDS) &&
  159. (
  160. (pulSrcMask[0] == 0xff0000) &&
  161. (pulSrcMask[1] == 0x00ff00) &&
  162. (pulSrcMask[2] == 0x0000ff)
  163. )
  164. )
  165. )
  166. )
  167. {
  168. bSrcHasAlpha = TRUE;
  169. }
  170. //
  171. // assume general blend, then try to find special case
  172. //
  173. pAlphaDispatch->pfnGeneralBlend = vPixelGeneralBlend;
  174. if (
  175. (
  176. (pAlphaDispatch->BlendFunction.SourceBlend == AC_SRC_OVER) &&
  177. (pAlphaDispatch->BlendFunction.DestinationBlend == AC_SRC_OVER)
  178. ) ||
  179. (
  180. (pAlphaDispatch->BlendFunction.SourceBlend == AC_SRC_UNDER) &&
  181. (pAlphaDispatch->BlendFunction.DestinationBlend == AC_SRC_UNDER)
  182. )
  183. )
  184. {
  185. //
  186. // use "over" optimized blend fucntion
  187. //
  188. if (bSrcHasAlpha && (pAlphaDispatch->BlendFunction.SourceConstantAlpha == 255))
  189. {
  190. pAlphaDispatch->pfnGeneralBlend = vPixelOver;
  191. #if defined(_X86_)
  192. //
  193. // source and dest alignment must be 8 byte aligned to use mmx
  194. //
  195. if (bIsMMXProcessor() && (cxDst >= 8))
  196. {
  197. if (
  198. ((DstWidth & 0x07) == 0) &&
  199. ((SrcWidth & 0x07) == 0)
  200. )
  201. {
  202. pAlphaDispatch->pfnGeneralBlend = mmxPixelOver;
  203. pAlphaDispatch->bUseMMX = TRUE;
  204. }
  205. }
  206. #endif
  207. }
  208. else
  209. {
  210. //
  211. // if source format doesn't support alpha then use
  212. // constant src alpha routine
  213. //
  214. if (bSrcHasAlpha)
  215. {
  216. pAlphaDispatch->pfnGeneralBlend = vPixelBlendOrDissolveOver;
  217. #if defined(_X86_)
  218. //
  219. // source and dest alignment must be 8 byte aligned to use mmx
  220. //
  221. if (bIsMMXProcessor() && (cxDst >= 8))
  222. {
  223. if (
  224. ((DstWidth & 0x07) == 0) &&
  225. ((SrcWidth & 0x07) == 0)
  226. )
  227. {
  228. pAlphaDispatch->pfnGeneralBlend = mmxPixelBlendOrDissolveOver;
  229. pAlphaDispatch->bUseMMX = TRUE;
  230. }
  231. }
  232. #endif
  233. }
  234. else
  235. {
  236. pAlphaDispatch->pfnGeneralBlend = vPixelBlend;
  237. }
  238. }
  239. }
  240. //
  241. // determine output conversion and storage routines
  242. //
  243. switch (DstBitPerPixel)
  244. {
  245. case 1:
  246. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvert1ToBGRA;
  247. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRATo1;
  248. break;
  249. case 4:
  250. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvert4ToBGRA;
  251. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRATo4;
  252. break;
  253. case 8:
  254. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvert8ToBGRA;
  255. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRATo8;
  256. break;
  257. case 16:
  258. if (pdibDst->pbmi->bmiHeader.biCompression == BI_RGB)
  259. {
  260. ulDstFlRed = 0x7c00;
  261. ulDstFlGreen = 0x03e0;
  262. ulDstFlBlue = 0x001f;
  263. }
  264. else if (pdibDst->pbmi->bmiHeader.biCompression == BI_BITFIELDS)
  265. {
  266. ulDstFlRed = pulDstMask[0];
  267. ulDstFlGreen = pulDstMask[1];
  268. ulDstFlBlue = pulDstMask[2];
  269. }
  270. else
  271. {
  272. return(FALSE);
  273. }
  274. if (
  275. (ulDstFlRed == 0xf800) &&
  276. (ulDstFlGreen == 0x07e0) &&
  277. (ulDstFlBlue == 0x001f)
  278. )
  279. {
  280. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvertRGB16_565ToBGRA;
  281. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRAToRGB16_565;
  282. }
  283. else if (
  284. (ulDstFlRed == 0x7c00) &&
  285. (ulDstFlGreen == 0x03e0) &&
  286. (ulDstFlBlue == 0x001f)
  287. )
  288. {
  289. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvertRGB16_555ToBGRA;
  290. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRAToRGB16_555;
  291. }
  292. else
  293. {
  294. return(FALSE);
  295. }
  296. break;
  297. case 24:
  298. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvertRGB24ToBGRA;
  299. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRAToRGB24;
  300. break;
  301. case 32:
  302. if (pdibDst->pbmi->bmiHeader.biCompression == BI_RGB)
  303. {
  304. ulDstFlRed = 0xff0000;
  305. ulDstFlGreen = 0x00ff00;
  306. ulDstFlBlue = 0x0000ff;
  307. }
  308. else if (pdibDst->pbmi->bmiHeader.biCompression == BI_BITFIELDS)
  309. {
  310. ulDstFlRed = pulDstMask[0];
  311. ulDstFlGreen = pulDstMask[1];
  312. ulDstFlBlue = pulDstMask[2];
  313. }
  314. else
  315. {
  316. return(FALSE);
  317. }
  318. if (
  319. (ulDstFlRed == 0xff0000) &&
  320. (ulDstFlGreen == 0x00ff00) &&
  321. (ulDstFlBlue == 0x0000ff)
  322. )
  323. {
  324. //
  325. // assigned to null indicates no conversion needed
  326. //
  327. pAlphaDispatch->pfnLoadDstAndConvert = NULL;
  328. pAlphaDispatch->pfnConvertAndStore = NULL;
  329. }
  330. else if (
  331. (ulDstFlRed == 0x0000ff) &&
  332. (ulDstFlGreen == 0x00ff00) &&
  333. (ulDstFlBlue == 0xff0000)
  334. )
  335. {
  336. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvertRGB32ToBGRA;
  337. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRAToRGB32;
  338. }
  339. else
  340. {
  341. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvert32BitfieldsToBGRA;
  342. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRATo32Bitfields;
  343. }
  344. break;
  345. }
  346. //
  347. // determine input load and conversion routine
  348. //
  349. switch (SrcBitPerPixel)
  350. {
  351. case 1:
  352. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvert1ToBGRA;
  353. break;
  354. case 4:
  355. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvert4ToBGRA;
  356. break;
  357. case 8:
  358. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvert8ToBGRA;
  359. break;
  360. case 16:
  361. if (pdibSrc->pbmi->bmiHeader.biCompression == BI_RGB)
  362. {
  363. ulSrcFlRed = 0x7c00;
  364. ulSrcFlGreen = 0x03e0;
  365. ulSrcFlBlue = 0x001f;
  366. }
  367. else if (pdibSrc->pbmi->bmiHeader.biCompression == BI_BITFIELDS)
  368. {
  369. ulSrcFlRed = pulSrcMask[0];
  370. ulSrcFlGreen = pulSrcMask[1];
  371. ulSrcFlBlue = pulSrcMask[2];
  372. }
  373. else
  374. {
  375. return(FALSE);
  376. }
  377. if (
  378. (ulSrcFlRed == 0xf800) &&
  379. (ulSrcFlGreen == 0x07e0) &&
  380. (ulSrcFlBlue == 0x001f)
  381. )
  382. {
  383. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvertRGB16_565ToBGRA;
  384. }
  385. else if (
  386. (ulSrcFlRed == 0x7c00) &&
  387. (ulSrcFlGreen == 0x03e0) &&
  388. (ulSrcFlBlue == 0x001f)
  389. )
  390. {
  391. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvertRGB16_555ToBGRA;
  392. }
  393. else
  394. {
  395. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvert16BitfieldsToBGRA;
  396. }
  397. break;
  398. case 24:
  399. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvertRGB24ToBGRA;
  400. break;
  401. case 32:
  402. if (pdibSrc->pbmi->bmiHeader.biCompression == BI_RGB)
  403. {
  404. ulSrcFlRed = 0xff0000;
  405. ulSrcFlGreen = 0x00ff00;
  406. ulSrcFlBlue = 0x0000ff;
  407. }
  408. else if (pdibSrc->pbmi->bmiHeader.biCompression == BI_BITFIELDS)
  409. {
  410. ulSrcFlRed = pulSrcMask[0];
  411. ulSrcFlGreen = pulSrcMask[1];
  412. ulSrcFlBlue = pulSrcMask[2];
  413. }
  414. else
  415. {
  416. return(FALSE);
  417. }
  418. if (
  419. (ulSrcFlRed == 0xff0000) &&
  420. (ulSrcFlGreen == 0x00ff00) &&
  421. (ulSrcFlBlue == 0x0000ff)
  422. )
  423. {
  424. pAlphaDispatch->pfnLoadSrcAndConvert = NULL;
  425. }
  426. else if (
  427. (ulSrcFlRed == 0x0000ff) &&
  428. (ulSrcFlGreen == 0x00ff00) &&
  429. (ulSrcFlBlue == 0xff0000)
  430. )
  431. {
  432. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvertRGB32ToBGRA;
  433. }
  434. else
  435. {
  436. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvert32BitfieldsToBGRA;
  437. }
  438. break;
  439. }
  440. //
  441. // special case 16 bpp vPixelBlend
  442. //
  443. if (pAlphaDispatch->pfnGeneralBlend == vPixelBlend)
  444. {
  445. if ((pAlphaDispatch->pfnLoadSrcAndConvert == vLoadAndConvertRGB16_555ToBGRA) &&
  446. (pAlphaDispatch->pfnLoadDstAndConvert == vLoadAndConvertRGB16_555ToBGRA))
  447. {
  448. //
  449. // use direct 16 bpp blend
  450. //
  451. pAlphaDispatch->pfnGeneralBlend = vPixelBlend16_555;
  452. pAlphaDispatch->pfnLoadSrcAndConvert = NULL;
  453. pAlphaDispatch->pfnLoadDstAndConvert = NULL;
  454. pAlphaDispatch->pfnConvertAndStore = NULL;
  455. //
  456. // convert blend function from x/255 to y/31
  457. //
  458. int ia = pAlphaDispatch->BlendFunction.SourceConstantAlpha;
  459. ia = (ia * 31 + 128)/255;
  460. pAlphaDispatch->BlendFunction.SourceConstantAlpha = (BYTE)ia;
  461. }
  462. else if ((pAlphaDispatch->pfnLoadSrcAndConvert == vLoadAndConvertRGB16_565ToBGRA) &&
  463. (pAlphaDispatch->pfnLoadDstAndConvert == vLoadAndConvertRGB16_565ToBGRA))
  464. {
  465. //
  466. // use direct 16 bpp blend
  467. //
  468. pAlphaDispatch->pfnGeneralBlend = vPixelBlend16_565;
  469. pAlphaDispatch->pfnLoadSrcAndConvert = NULL;
  470. pAlphaDispatch->pfnLoadDstAndConvert = NULL;
  471. pAlphaDispatch->pfnConvertAndStore = NULL;
  472. //
  473. // convert blend function from x/255 to y/31
  474. //
  475. int ia = pAlphaDispatch->BlendFunction.SourceConstantAlpha;
  476. ia = (ia * 31 + 128)/255;
  477. pAlphaDispatch->BlendFunction.SourceConstantAlpha = (BYTE)ia;
  478. }
  479. }
  480. return(TRUE);
  481. }
  482. /******************************Public*Routine******************************\
  483. * WinAlphaDIBBlend
  484. *
  485. *
  486. * Arguments:
  487. *
  488. *
  489. *
  490. * Return Value:
  491. *
  492. *
  493. *
  494. * History:
  495. *
  496. * 12/10/1996 Mark Enstrom [marke]
  497. *
  498. \**************************************************************************/
  499. BOOL
  500. WinAlphaDIBBlend(
  501. HDC hdcDst,
  502. int DstX,
  503. int DstY,
  504. int DstCx,
  505. int DstCy,
  506. CONST VOID *lpBits,
  507. CONST BITMAPINFO *lpBitsInfo,
  508. UINT iUsage,
  509. int SrcX,
  510. int SrcY,
  511. int SrcCx,
  512. int SrcCy,
  513. BLENDFUNCTION BlendFunction
  514. )
  515. {
  516. DIBINFO dibInfoDst;
  517. PALINFO palDst = {NULL,NULL,0};
  518. PALINFO palSrc = {NULL,NULL,0};
  519. DIBINFO dibInfoSrc;
  520. BOOL bRet;
  521. BOOL bReadable;
  522. ALPHA_DISPATCH_FORMAT AlphaDispatch;
  523. INT OldDstMapMode;
  524. //
  525. // init source and dest surface info
  526. //
  527. bRet = bInitDIBINFO(hdcDst,DstX,DstY,DstCx,DstCy,&dibInfoDst);
  528. if (!bRet)
  529. {
  530. return(FALSE);
  531. }
  532. bRet = bDIBInitDIBINFO((BITMAPINFO *)lpBitsInfo,lpBits,SrcX,SrcY,SrcCx,SrcCy,&dibInfoSrc);
  533. if (!bRet)
  534. {
  535. goto AlphaBlendCleanup;
  536. }
  537. //
  538. // work in MM_TEXT
  539. //
  540. OldDstMapMode = SetMapMode(hdcDst,MM_TEXT);
  541. //
  542. //
  543. //
  544. bSetupBitmapInfos (&dibInfoDst, &dibInfoSrc);
  545. dibInfoSrc.iUsage = iUsage;
  546. bRet = bDIBGetSrcDIBits(&dibInfoDst,&dibInfoSrc,SOURCE_ALPHA,0);
  547. if (!bRet)
  548. {
  549. goto AlphaBlendCleanup;
  550. }
  551. bRet = bGetDstDIBits(&dibInfoDst,&bReadable,SOURCE_ALPHA);
  552. if ((!bRet) || (!bReadable) || (dibInfoDst.rclClipDC.left == dibInfoDst.rclClipDC.right))
  553. {
  554. goto AlphaBlendCleanup;
  555. }
  556. //
  557. // determine alpha routine
  558. //
  559. AlphaDispatch.BlendFunction = BlendFunction;
  560. bRet = bDetermineAlphaBlendFunction(&dibInfoDst,&dibInfoSrc,&AlphaDispatch);
  561. if (bRet)
  562. {
  563. //
  564. // initialize palette translate objects
  565. //
  566. palSrc.pBitmapInfo = dibInfoSrc.pbmi;
  567. palDst.pBitmapInfo = dibInfoDst.pbmi;
  568. bRet = bInitializePALINFO(&palSrc);
  569. if (!bRet)
  570. {
  571. goto AlphaBlendCleanup;
  572. }
  573. bRet = bInitializePALINFO(&palDst);
  574. if (!bRet)
  575. {
  576. goto AlphaBlendCleanup;
  577. }
  578. //
  579. // call alpha blending routine
  580. //
  581. bRet = AlphaScanLineBlend( (PBYTE)dibInfoDst.pvBase,
  582. (PRECTL)&dibInfoDst.rclDIB,
  583. dibInfoDst.stride,
  584. (PBYTE)dibInfoSrc.pvBase,
  585. dibInfoSrc.stride,
  586. (PPOINTL)&dibInfoSrc.rclDIB,
  587. &palDst,
  588. &palSrc,
  589. &AlphaDispatch
  590. );
  591. bRet = bSendDIBINFO(hdcDst,&dibInfoDst);
  592. }
  593. //
  594. // release any temp storage
  595. //
  596. AlphaBlendCleanup:
  597. vCleanupDIBINFO(&dibInfoDst);
  598. vCleanupDIBINFO(&dibInfoSrc);
  599. vCleanupPALINFO(&palSrc);
  600. vCleanupPALINFO(&palDst);
  601. SetMapMode(hdcDst,OldDstMapMode);
  602. return(bRet);
  603. }
  604. /******************************Public*Routine******************************\
  605. * WinAlphaBlend
  606. *
  607. *
  608. * Arguments:
  609. *
  610. *
  611. *
  612. * Return Value:
  613. *
  614. *
  615. *
  616. * History:
  617. *
  618. * 12/10/1996 Mark Enstrom [marke]
  619. *
  620. \**************************************************************************/
  621. BOOL
  622. WinAlphaBlend(
  623. HDC hdcDst,
  624. int DstX,
  625. int DstY,
  626. int DstCx,
  627. int DstCy,
  628. HDC hdcSrc,
  629. int SrcX,
  630. int SrcY,
  631. int SrcCx,
  632. int SrcCy,
  633. BLENDFUNCTION BlendFunction
  634. )
  635. {
  636. DIBINFO dibInfoDst;
  637. PALINFO palDst = {NULL,NULL,0};
  638. PALINFO palSrc = {NULL,NULL,0};
  639. DIBINFO dibInfoSrc;
  640. BOOL bRet;
  641. BOOL bReadable;
  642. ALPHA_DISPATCH_FORMAT AlphaDispatch;
  643. INT OldSrcMapMode,OldDstMapMode;
  644. //
  645. // init source and dest surface info
  646. //
  647. bRet = bInitDIBINFO(hdcDst,DstX,DstY,DstCx,DstCy,&dibInfoDst);
  648. if (!bRet)
  649. {
  650. return(FALSE);
  651. }
  652. bRet = bInitDIBINFO(hdcSrc,SrcX,SrcY,SrcCx,SrcCy,&dibInfoSrc);
  653. if (!bRet)
  654. {
  655. goto AlphaBlendCleanup;
  656. }
  657. //
  658. // Now operate in MM_TEXT mode
  659. //
  660. OldSrcMapMode = SetMapMode(hdcSrc,MM_TEXT);
  661. if (hdcSrc != hdcDst)
  662. {
  663. OldDstMapMode = SetMapMode(hdcDst,MM_TEXT);
  664. }
  665. bSetupBitmapInfos(&dibInfoDst,&dibInfoSrc);
  666. //
  667. // get access to src surface or temp DIB
  668. //
  669. bRet = bGetSrcDIBits(&dibInfoDst,&dibInfoSrc,SOURCE_ALPHA, 0);
  670. if (!bRet)
  671. {
  672. goto AlphaBlendCleanup;
  673. }
  674. //
  675. // get access to Dst surface or temp DIB
  676. //
  677. bRet = bGetDstDIBits(&dibInfoDst,&bReadable,SOURCE_ALPHA);
  678. if ((!bRet) || (!bReadable) || (dibInfoDst.rclBounds.left == dibInfoDst.rclBounds.right))
  679. {
  680. goto AlphaBlendCleanup;
  681. }
  682. //
  683. // check and simplify blend
  684. //
  685. if (
  686. (BlendFunction.SourceBlend == AC_ONE) &&
  687. (BlendFunction.DestinationBlend == AC_ONE_MINUS_SRC_ALPHA)
  688. )
  689. {
  690. BlendFunction.SourceBlend = AC_SRC_OVER;
  691. BlendFunction.DestinationBlend = AC_SRC_OVER;
  692. BlendFunction.SourceConstantAlpha = (BYTE)255;
  693. }
  694. if (
  695. (BlendFunction.SourceBlend == AC_SRC_OVER) ||
  696. (BlendFunction.SourceBlend == AC_SRC_UNDER) ||
  697. (BlendFunction.DestinationBlend == AC_SRC_OVER) ||
  698. (BlendFunction.DestinationBlend == AC_SRC_UNDER)
  699. )
  700. {
  701. //
  702. // for over and under blend functions, blend functions
  703. // must be the same
  704. //
  705. if (BlendFunction.SourceBlend != BlendFunction.DestinationBlend)
  706. {
  707. WARNING("Illegal blend function\n");
  708. bRet = FALSE;
  709. }
  710. }
  711. AlphaDispatch.BlendFunction = BlendFunction;
  712. //
  713. // determine alpha routine
  714. //
  715. bRet = bDetermineAlphaBlendFunction(&dibInfoDst,&dibInfoSrc,&AlphaDispatch);
  716. if (!bRet)
  717. {
  718. goto AlphaBlendCleanup;
  719. }
  720. //
  721. // initialize palette translate objects
  722. //
  723. palSrc.pBitmapInfo = dibInfoSrc.pbmi;
  724. palDst.pBitmapInfo = dibInfoDst.pbmi;
  725. bRet = bInitializePALINFO(&palSrc);
  726. if (!bRet)
  727. {
  728. goto AlphaBlendCleanup;
  729. }
  730. bRet = bInitializePALINFO(&palDst);
  731. if (!bRet)
  732. {
  733. goto AlphaBlendCleanup;
  734. }
  735. //
  736. // call alpha blending routine
  737. //
  738. bRet = AlphaScanLineBlend( (PBYTE)dibInfoDst.pvBase,
  739. (PRECTL)&dibInfoDst.rclDIB,
  740. dibInfoDst.stride,
  741. (PBYTE)dibInfoSrc.pvBase,
  742. dibInfoSrc.stride,
  743. (PPOINTL)&dibInfoSrc.rclDIB,
  744. &palDst,
  745. &palSrc,
  746. &AlphaDispatch
  747. );
  748. //
  749. // write results to screen if needed
  750. //
  751. bRet = bSendDIBINFO(hdcDst,&dibInfoDst);
  752. //
  753. // release any temp storage
  754. //
  755. AlphaBlendCleanup:
  756. vCleanupPALINFO(&palDst);
  757. vCleanupPALINFO(&palSrc);
  758. vCleanupDIBINFO(&dibInfoDst);
  759. vCleanupDIBINFO(&dibInfoSrc);
  760. //
  761. // restore DC map modes
  762. //
  763. SetMapMode(hdcSrc,OldSrcMapMode);
  764. if (hdcSrc != hdcDst)
  765. {
  766. SetMapMode(hdcDst,OldDstMapMode);
  767. }
  768. return(bRet);
  769. }
  770. #endif
  771. /******************************Public*Routine******************************\
  772. * AlphaImage
  773. *
  774. *
  775. * Arguments:
  776. *
  777. *
  778. *
  779. * Return Value:
  780. *
  781. *
  782. *
  783. * History:
  784. *
  785. * 12/3/1996 Mark Enstrom [marke]
  786. *
  787. \**************************************************************************/
  788. BOOL
  789. AlphaBlend(
  790. HDC hdcDest,
  791. int DstX,
  792. int DstY,
  793. int DstCx,
  794. int DstCy,
  795. HDC hSrc,
  796. int SrcX,
  797. int SrcY,
  798. int SrcCx,
  799. int SrcCy,
  800. BLENDFUNCTION BlendFunction
  801. )
  802. {
  803. BOOL bRet;
  804. bRet = gpfnAlphaBlend(hdcDest,DstX,DstY,DstCx,DstCy,hSrc,SrcX,SrcY,SrcCx,SrcCy,BlendFunction);
  805. return(bRet);
  806. }
  807. /******************************Public*Routine******************************\
  808. * AlphaDIBImage
  809. *
  810. *
  811. * Arguments:
  812. *
  813. *
  814. *
  815. * Return Value:
  816. *
  817. *
  818. *
  819. * History:
  820. *
  821. * 12/3/1996 Mark Enstrom [marke]
  822. *
  823. \**************************************************************************/
  824. BOOL
  825. AlphaDIBBlend(
  826. HDC hdcDest,
  827. int DstX,
  828. int DstY,
  829. int DstCx,
  830. int DstCy,
  831. CONST VOID *lpBits,
  832. CONST BITMAPINFO *lpBitsInfo,
  833. UINT iUsage,
  834. int SrcX,
  835. int SrcY,
  836. int SrcCx,
  837. int SrcCy,
  838. BLENDFUNCTION BlendFunction
  839. )
  840. {
  841. BOOL bRet;
  842. BOOL bSrcHasAlpha = FALSE;
  843. //
  844. // simple validation
  845. //
  846. if ((lpBits == NULL) || (lpBitsInfo == NULL))
  847. {
  848. return(FALSE);
  849. }
  850. //
  851. // no COREHEADERs
  852. //
  853. if (lpBitsInfo->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
  854. {
  855. return(FALSE);
  856. }
  857. //
  858. // check and simplify blend, try to quick out to EngStretchBlt
  859. //
  860. if (
  861. (BlendFunction.SourceBlend == AC_ONE) &&
  862. (BlendFunction.DestinationBlend == AC_ONE_MINUS_SRC_ALPHA)
  863. )
  864. {
  865. BlendFunction.SourceBlend = AC_SRC_OVER;
  866. BlendFunction.DestinationBlend = AC_SRC_OVER;
  867. BlendFunction.SourceConstantAlpha = (BYTE)255;
  868. }
  869. //
  870. // check for quick out
  871. //
  872. if (
  873. (BlendFunction.SourceBlend == AC_SRC_OVER) ||
  874. (BlendFunction.DestinationBlend == AC_SRC_OVER)
  875. )
  876. {
  877. PULONG pulMask = (PULONG)((PBYTE)lpBitsInfo + sizeof(BITMAPINFOHEADER));
  878. //
  879. // for over and under blend functions, blend functions
  880. // must be the same
  881. //
  882. if (BlendFunction.SourceBlend != BlendFunction.DestinationBlend)
  883. {
  884. WARNING1("Illegal blend function\n");
  885. return(FALSE);
  886. }
  887. if (
  888. (lpBitsInfo->bmiHeader.biBitCount == 32) &&
  889. (
  890. (lpBitsInfo->bmiHeader.biCompression == BI_RGB) ||
  891. (
  892. (lpBitsInfo->bmiHeader.biCompression == BI_BITFIELDS) &&
  893. (
  894. (pulMask[0] == 0xff0000) &&
  895. (pulMask[1] == 0x00ff00) &&
  896. (pulMask[2] == 0x0000ff)
  897. )
  898. )
  899. )
  900. )
  901. {
  902. bSrcHasAlpha = TRUE;
  903. }
  904. //
  905. // check for quick out. !!! should add check for surface
  906. // format != 32bpp BGR
  907. //
  908. if (
  909. (BlendFunction.SourceConstantAlpha == 255) &&
  910. ( !bSrcHasAlpha ||
  911. (BlendFunction.AlphaFormat & AC_SRC_NO_ALPHA)
  912. )
  913. )
  914. {
  915. bRet = StretchDIBits(
  916. hdcDest,
  917. DstX,
  918. DstY,
  919. DstCx,
  920. DstCy,
  921. SrcX,
  922. SrcY,
  923. SrcCx,
  924. SrcCy,
  925. lpBits,
  926. lpBitsInfo,
  927. iUsage,
  928. SRCCOPY);
  929. return(bRet);
  930. }
  931. }
  932. bRet = gpfnAlphaDIB(
  933. hdcDest,
  934. DstX,
  935. DstY,
  936. DstCx,
  937. DstCy,
  938. lpBits,
  939. lpBitsInfo,
  940. iUsage,
  941. SrcX,
  942. SrcY,
  943. SrcCx,
  944. SrcCy,
  945. BlendFunction
  946. );
  947. return(bRet);
  948. }