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.

872 lines
21 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. #if !(_WIN32_WINNT >= 0x500)
  19. #if defined(_X86_)
  20. BOOL gbMMX = FALSE;
  21. /**************************************************************************\
  22. * bIsMMXProcessor
  23. *
  24. *
  25. * Arguments:
  26. *
  27. *
  28. *
  29. * Return Value:
  30. *
  31. *
  32. *
  33. * History:
  34. *
  35. * 4/10/1997 Mark Enstrom [marke]
  36. *
  37. \**************************************************************************/
  38. #define CPUID _asm _emit 0fh _asm _emit 0a2h
  39. BOOL
  40. bIsMMXProcessor(VOID)
  41. {
  42. BOOL retval = TRUE;
  43. DWORD RegEDX;
  44. //
  45. // Find out if procesor supports CPUID
  46. //
  47. __try
  48. {
  49. _asm
  50. {
  51. mov eax, 1
  52. // code bytes = 0fh, 0a2h
  53. CPUID
  54. mov RegEDX, edx
  55. }
  56. } __except(EXCEPTION_EXECUTE_HANDLER)
  57. {
  58. retval = FALSE;
  59. }
  60. if (retval == FALSE)
  61. {
  62. //
  63. // processor does not support CPUID
  64. //
  65. return FALSE;
  66. }
  67. //
  68. // bit 23 is set for MMX technology
  69. //
  70. if (RegEDX & 0x800000)
  71. {
  72. //
  73. // save and restore fp state around emms
  74. //
  75. __try
  76. {
  77. _asm emms
  78. }
  79. __except(EXCEPTION_EXECUTE_HANDLER)
  80. {
  81. retval = FALSE;
  82. }
  83. }
  84. else
  85. {
  86. //
  87. // processor supports CPUID but does not have MMX technology
  88. //
  89. return FALSE;
  90. }
  91. //
  92. // if retval == 0 here that means the processor has MMX technology but
  93. // the FP emulation is on so MMX technology is unavailable
  94. //
  95. return retval;
  96. }
  97. #endif
  98. /**************************************************************************\
  99. * bDetermineAlphaBlendFunction
  100. *
  101. *
  102. * Arguments:
  103. *
  104. *
  105. *
  106. * Return Value:
  107. *
  108. *
  109. *
  110. * History:
  111. *
  112. * 1/21/1997 Mark Enstrom [marke]
  113. *
  114. \**************************************************************************/
  115. BOOL
  116. bDetermineAlphaBlendFunction(
  117. CONST DIBINFO *pdibDst,
  118. CONST DIBINFO *pdibSrc,
  119. PALPHA_DISPATCH_FORMAT pAlphaDispatch
  120. )
  121. {
  122. PULONG pulSrcMask = (PULONG)&pdibSrc->pbmi->bmiColors[0];
  123. ULONG ulSrcFlRed;
  124. ULONG ulSrcFlGreen;
  125. ULONG ulSrcFlBlue;
  126. PULONG pulDstMask = (PULONG)&pdibDst->pbmi->bmiColors[0];
  127. ULONG ulDstFlRed;
  128. ULONG ulDstFlGreen;
  129. ULONG ulDstFlBlue;
  130. ULONG DstBitPerPixel = pdibDst->pbmi->bmiHeader.biBitCount;
  131. LONG DstWidth = pdibDst->pbmi->bmiHeader.biWidth;
  132. ULONG SrcBitPerPixel = pdibSrc->pbmi->bmiHeader.biBitCount;
  133. LONG SrcWidth = pdibSrc->pbmi->bmiHeader.biWidth;
  134. LONG cxDst = pdibDst->rclDIB.right - pdibDst->rclDIB.left;
  135. pAlphaDispatch->ulDstBitsPerPixel = DstBitPerPixel;
  136. pAlphaDispatch->ulSrcBitsPerPixel = SrcBitPerPixel;
  137. //
  138. // does src btimap have alpha
  139. //
  140. BOOL bSrcHasAlpha = FALSE;
  141. if (
  142. (pAlphaDispatch->BlendFunction.AlphaFormat & AC_SRC_ALPHA) &&
  143. (SrcBitPerPixel == 32) &&
  144. (
  145. (pdibSrc->pbmi->bmiHeader.biCompression == BI_RGB) ||
  146. (
  147. (pdibSrc->pbmi->bmiHeader.biCompression == BI_BITFIELDS) &&
  148. (
  149. (pulSrcMask[0] == 0xff0000) &&
  150. (pulSrcMask[1] == 0x00ff00) &&
  151. (pulSrcMask[2] == 0x0000ff)
  152. )
  153. )
  154. )
  155. )
  156. {
  157. bSrcHasAlpha = TRUE;
  158. }
  159. //
  160. // try to find special case
  161. //
  162. if (bSrcHasAlpha && (pAlphaDispatch->BlendFunction.SourceConstantAlpha == 255))
  163. {
  164. pAlphaDispatch->pfnGeneralBlend = vPixelOver;
  165. #if defined(_X86_)
  166. //
  167. // source and dest alignment must be 8 byte aligned to use mmx
  168. //
  169. if (gbMMX && (cxDst >= 8))
  170. {
  171. pAlphaDispatch->pfnGeneralBlend = mmxPixelOver;
  172. }
  173. #endif
  174. }
  175. else
  176. {
  177. //
  178. // if source format doesn't support alpha then use
  179. // constant src alpha routine
  180. //
  181. if (bSrcHasAlpha)
  182. {
  183. pAlphaDispatch->pfnGeneralBlend = vPixelBlendOrDissolveOver;
  184. #if defined(_X86_)
  185. //
  186. // source and dest alignment must be 8 byte aligned to use mmx
  187. //
  188. if (gbMMX && (cxDst >= 8))
  189. {
  190. pAlphaDispatch->pfnGeneralBlend = mmxPixelBlendOrDissolveOver;
  191. }
  192. #endif
  193. }
  194. else
  195. {
  196. pAlphaDispatch->pfnGeneralBlend = vPixelBlend;
  197. }
  198. }
  199. //
  200. // determine output conversion and storage routines
  201. //
  202. switch (DstBitPerPixel)
  203. {
  204. case 1:
  205. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvert1ToBGRA;
  206. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRAToDest;
  207. break;
  208. case 4:
  209. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvert4ToBGRA;
  210. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRAToDest;
  211. break;
  212. case 8:
  213. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvert8ToBGRA;
  214. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRAToDest;
  215. break;
  216. case 16:
  217. if (pdibDst->pbmi->bmiHeader.biCompression == BI_RGB)
  218. {
  219. ulDstFlRed = 0x7c00;
  220. ulDstFlGreen = 0x03e0;
  221. ulDstFlBlue = 0x001f;
  222. }
  223. else if (pdibDst->pbmi->bmiHeader.biCompression == BI_BITFIELDS)
  224. {
  225. ulDstFlRed = pulDstMask[0];
  226. ulDstFlGreen = pulDstMask[1];
  227. ulDstFlBlue = pulDstMask[2];
  228. }
  229. else
  230. {
  231. return(FALSE);
  232. }
  233. if (
  234. (ulDstFlRed == 0xf800) &&
  235. (ulDstFlGreen == 0x07e0) &&
  236. (ulDstFlBlue == 0x001f)
  237. )
  238. {
  239. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvertRGB16_565ToBGRA;
  240. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRAToRGB16_565;
  241. }
  242. else if (
  243. (ulDstFlRed == 0x7c00) &&
  244. (ulDstFlGreen == 0x03e0) &&
  245. (ulDstFlBlue == 0x001f)
  246. )
  247. {
  248. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvertRGB16_555ToBGRA;
  249. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRAToRGB16_555;
  250. }
  251. else
  252. {
  253. return(FALSE);
  254. }
  255. break;
  256. case 24:
  257. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvertRGB24ToBGRA;
  258. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRAToRGB24;
  259. break;
  260. case 32:
  261. if (pdibDst->pbmi->bmiHeader.biCompression == BI_RGB)
  262. {
  263. ulDstFlRed = 0xff0000;
  264. ulDstFlGreen = 0x00ff00;
  265. ulDstFlBlue = 0x0000ff;
  266. }
  267. else if (pdibDst->pbmi->bmiHeader.biCompression == BI_BITFIELDS)
  268. {
  269. ulDstFlRed = pulDstMask[0];
  270. ulDstFlGreen = pulDstMask[1];
  271. ulDstFlBlue = pulDstMask[2];
  272. }
  273. else
  274. {
  275. return(FALSE);
  276. }
  277. if (
  278. (ulDstFlRed == 0xff0000) &&
  279. (ulDstFlGreen == 0x00ff00) &&
  280. (ulDstFlBlue == 0x0000ff)
  281. )
  282. {
  283. //
  284. // assigned to null indicates no conversion needed
  285. //
  286. pAlphaDispatch->pfnLoadDstAndConvert = NULL;
  287. pAlphaDispatch->pfnConvertAndStore = NULL;
  288. }
  289. else if (
  290. (ulDstFlRed == 0x0000ff) &&
  291. (ulDstFlGreen == 0x00ff00) &&
  292. (ulDstFlBlue == 0xff0000)
  293. )
  294. {
  295. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvertRGB32ToBGRA;
  296. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRAToRGB32;
  297. }
  298. else
  299. {
  300. pAlphaDispatch->pfnLoadDstAndConvert = vLoadAndConvert32BitfieldsToBGRA;
  301. pAlphaDispatch->pfnConvertAndStore = vConvertAndSaveBGRAToDest;
  302. }
  303. break;
  304. }
  305. //
  306. // determine input load and conversion routine
  307. //
  308. switch (SrcBitPerPixel)
  309. {
  310. case 1:
  311. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvert1ToBGRA;
  312. break;
  313. case 4:
  314. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvert4ToBGRA;
  315. break;
  316. case 8:
  317. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvert8ToBGRA;
  318. break;
  319. case 16:
  320. if (pdibSrc->pbmi->bmiHeader.biCompression == BI_RGB)
  321. {
  322. ulSrcFlRed = 0x7c00;
  323. ulSrcFlGreen = 0x03e0;
  324. ulSrcFlBlue = 0x001f;
  325. }
  326. else if (pdibSrc->pbmi->bmiHeader.biCompression == BI_BITFIELDS)
  327. {
  328. ulSrcFlRed = pulSrcMask[0];
  329. ulSrcFlGreen = pulSrcMask[1];
  330. ulSrcFlBlue = pulSrcMask[2];
  331. }
  332. else
  333. {
  334. return(FALSE);
  335. }
  336. if (
  337. (ulSrcFlRed == 0xf800) &&
  338. (ulSrcFlGreen == 0x07e0) &&
  339. (ulSrcFlBlue == 0x001f)
  340. )
  341. {
  342. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvertRGB16_565ToBGRA;
  343. }
  344. else if (
  345. (ulSrcFlRed == 0x7c00) &&
  346. (ulSrcFlGreen == 0x03e0) &&
  347. (ulSrcFlBlue == 0x001f)
  348. )
  349. {
  350. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvertRGB16_555ToBGRA;
  351. }
  352. else
  353. {
  354. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvert16BitfieldsToBGRA;
  355. }
  356. break;
  357. case 24:
  358. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvertRGB24ToBGRA;
  359. break;
  360. case 32:
  361. if (pdibSrc->pbmi->bmiHeader.biCompression == BI_RGB)
  362. {
  363. ulSrcFlRed = 0xff0000;
  364. ulSrcFlGreen = 0x00ff00;
  365. ulSrcFlBlue = 0x0000ff;
  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 == 0xff0000) &&
  379. (ulSrcFlGreen == 0x00ff00) &&
  380. (ulSrcFlBlue == 0x0000ff)
  381. )
  382. {
  383. pAlphaDispatch->pfnLoadSrcAndConvert = NULL;
  384. }
  385. else if (
  386. (ulSrcFlRed == 0x0000ff) &&
  387. (ulSrcFlGreen == 0x00ff00) &&
  388. (ulSrcFlBlue == 0xff0000)
  389. )
  390. {
  391. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvertRGB32ToBGRA;
  392. }
  393. else
  394. {
  395. pAlphaDispatch->pfnLoadSrcAndConvert = vLoadAndConvert32BitfieldsToBGRA;
  396. }
  397. break;
  398. }
  399. //
  400. // special case 16 bpp vPixelBlend
  401. //
  402. if (pAlphaDispatch->pfnGeneralBlend == vPixelBlend)
  403. {
  404. if ((pAlphaDispatch->pfnLoadSrcAndConvert == vLoadAndConvertRGB24ToBGRA) &&
  405. (pAlphaDispatch->pfnLoadDstAndConvert == vLoadAndConvertRGB24ToBGRA))
  406. {
  407. //
  408. // use direct 16 bpp blend
  409. //
  410. pAlphaDispatch->pfnGeneralBlend = vPixelBlend24;
  411. #if defined(_X86_)
  412. //
  413. // source and dest alignment must be 8 byte aligned to use mmx
  414. //
  415. if (gbMMX && (cxDst >= 8))
  416. {
  417. pAlphaDispatch->pfnGeneralBlend = mmxPixelBlend24;
  418. }
  419. #endif
  420. pAlphaDispatch->pfnLoadSrcAndConvert = NULL;
  421. pAlphaDispatch->pfnLoadDstAndConvert = NULL;
  422. pAlphaDispatch->pfnConvertAndStore = NULL;
  423. }
  424. #if defined(_X86_)
  425. else if ((pAlphaDispatch->pfnLoadSrcAndConvert == vLoadAndConvertRGB16_555ToBGRA) &&
  426. (pAlphaDispatch->pfnLoadDstAndConvert == vLoadAndConvertRGB16_555ToBGRA))
  427. {
  428. //
  429. // use direct 16 bpp blend
  430. //
  431. pAlphaDispatch->pfnGeneralBlend = vPixelBlend16_555;
  432. //
  433. // source and dest alignment must be 8 byte aligned to use mmx
  434. //
  435. if (gbMMX && (cxDst >= 8))
  436. {
  437. pAlphaDispatch->pfnGeneralBlend = mmxPixelBlend16_555;
  438. }
  439. pAlphaDispatch->pfnLoadSrcAndConvert = NULL;
  440. pAlphaDispatch->pfnLoadDstAndConvert = NULL;
  441. pAlphaDispatch->pfnConvertAndStore = NULL;
  442. //
  443. // convert blend function from x/255 to y/31
  444. //
  445. int ia = pAlphaDispatch->BlendFunction.SourceConstantAlpha;
  446. ia = (ia * 31 + 128)/255;
  447. pAlphaDispatch->BlendFunction.SourceConstantAlpha = (BYTE)ia;
  448. }
  449. else if ((pAlphaDispatch->pfnLoadSrcAndConvert == vLoadAndConvertRGB16_565ToBGRA) &&
  450. (pAlphaDispatch->pfnLoadDstAndConvert == vLoadAndConvertRGB16_565ToBGRA))
  451. {
  452. //
  453. // use direct 16 bpp blend
  454. //
  455. pAlphaDispatch->pfnGeneralBlend = vPixelBlend16_565;
  456. //
  457. // source and dest alignment must be 8 byte aligned to use mmx
  458. //
  459. if (gbMMX && (cxDst >= 8))
  460. {
  461. pAlphaDispatch->pfnGeneralBlend = mmxPixelBlend16_565;
  462. }
  463. pAlphaDispatch->pfnLoadSrcAndConvert = NULL;
  464. pAlphaDispatch->pfnLoadDstAndConvert = NULL;
  465. pAlphaDispatch->pfnConvertAndStore = NULL;
  466. //
  467. // convert blend function from x/255 to y/31
  468. //
  469. int ia = pAlphaDispatch->BlendFunction.SourceConstantAlpha;
  470. ia = (ia * 31 + 128)/255;
  471. pAlphaDispatch->BlendFunction.SourceConstantAlpha = (BYTE)ia;
  472. }
  473. #endif
  474. }
  475. return(TRUE);
  476. }
  477. /******************************Public*Routine******************************\
  478. * WinAlphaBlend
  479. *
  480. *
  481. * Arguments:
  482. *
  483. *
  484. *
  485. * Return Value:
  486. *
  487. *
  488. *
  489. * History:
  490. *
  491. * 12/10/1996 Mark Enstrom [marke]
  492. *
  493. \**************************************************************************/
  494. BOOL
  495. WinAlphaBlend(
  496. HDC hdcDst,
  497. int DstX,
  498. int DstY,
  499. int DstCx,
  500. int DstCy,
  501. HDC hdcSrc,
  502. int SrcX,
  503. int SrcY,
  504. int SrcCx,
  505. int SrcCy,
  506. BLENDFUNCTION BlendFunction
  507. )
  508. {
  509. DIBINFO dibInfoDst;
  510. DIBINFO dibInfoSrc;
  511. ULONG ulStatus;
  512. BOOL bRet;
  513. BOOL bReadable;
  514. ALPHA_DISPATCH_FORMAT AlphaDispatch;
  515. INT OldSrcMapMode,OldDstMapMode;
  516. //
  517. // init source and dest surface info
  518. //
  519. bRet = bInitDIBINFO(hdcDst,DstX,DstY,DstCx,DstCy,&dibInfoDst);
  520. if (!bRet)
  521. {
  522. return(FALSE);
  523. }
  524. bRet = bInitDIBINFO(hdcSrc,SrcX,SrcY,SrcCx,SrcCy,&dibInfoSrc);
  525. if (!bRet)
  526. {
  527. goto AlphaBlendCleanup;
  528. }
  529. bSetupBitmapInfos(&dibInfoDst,&dibInfoSrc);
  530. //
  531. // get access to src surface or temp DIB
  532. //
  533. bRet = bGetSrcDIBits(&dibInfoDst,&dibInfoSrc,SOURCE_ALPHA, 0);
  534. if (!bRet)
  535. {
  536. goto AlphaBlendCleanup;
  537. }
  538. //
  539. // get access to Dst surface or temp DIB
  540. //
  541. // DST can be printer DC
  542. //
  543. if (dibInfoDst.flag & PRINTER_DC)
  544. {
  545. bReadable = FALSE;
  546. bRet = FALSE;
  547. }
  548. else
  549. {
  550. bRet = bGetDstDIBits(&dibInfoDst,&bReadable,SOURCE_ALPHA);
  551. }
  552. if ((!bRet) || (!bReadable) || (dibInfoDst.rclBounds.left == dibInfoDst.rclBounds.right))
  553. {
  554. goto AlphaBlendCleanup;
  555. }
  556. //
  557. // check blend
  558. //
  559. if (BlendFunction.BlendOp != AC_SRC_OVER)
  560. {
  561. WARNING("Illegal blend function\n");
  562. bRet = FALSE;
  563. }
  564. AlphaDispatch.BlendFunction = BlendFunction;
  565. //
  566. // determine alpha routine
  567. //
  568. bRet = bDetermineAlphaBlendFunction(&dibInfoDst,&dibInfoSrc,&AlphaDispatch);
  569. if (bRet)
  570. {
  571. //
  572. // call alpha blending routine
  573. //
  574. ulStatus = AlphaScanLineBlend(
  575. (PBYTE)dibInfoDst.pvBase,
  576. (PRECTL)&dibInfoDst.rclDIB,
  577. dibInfoDst.stride,
  578. (PBYTE)dibInfoSrc.pvBase,
  579. dibInfoSrc.stride,
  580. (PPOINTL)&dibInfoSrc.rclDIB,
  581. &AlphaDispatch,
  582. &dibInfoSrc,
  583. &dibInfoDst
  584. );
  585. //
  586. // ALPHA_COMPLETE: success, written to destination
  587. // ALPHA_SEND_TEMP: success, must write tmp bmp to dest
  588. // ALPHA_FAIL: error
  589. //
  590. if (ulStatus == ALPHA_SEND_TEMP)
  591. {
  592. bRet = bSendDIBINFO(hdcDst,&dibInfoDst);
  593. }
  594. else if (ulStatus == ALPHA_FAIL)
  595. {
  596. bRet = FALSE;
  597. }
  598. }
  599. //
  600. // release any temp storage
  601. //
  602. AlphaBlendCleanup:
  603. vCleanupDIBINFO(&dibInfoDst);
  604. vCleanupDIBINFO(&dibInfoSrc);
  605. return(bRet);
  606. }
  607. #endif
  608. /******************************Public*Routine******************************\
  609. * AlphaBlend
  610. *
  611. *
  612. * Arguments:
  613. *
  614. *
  615. *
  616. * Return Value:
  617. *
  618. *
  619. *
  620. * History:
  621. *
  622. * 12/3/1996 Mark Enstrom [marke]
  623. *
  624. \**************************************************************************/
  625. BOOL
  626. AlphaBlend(
  627. HDC hdcDest,
  628. int DstX,
  629. int DstY,
  630. int DstCx,
  631. int DstCy,
  632. HDC hSrc,
  633. int SrcX,
  634. int SrcY,
  635. int SrcCx,
  636. int SrcCy,
  637. BLENDFUNCTION BlendFunction
  638. )
  639. {
  640. BOOL bRet;
  641. //
  642. // check blend
  643. //
  644. if ((BlendFunction.BlendOp != AC_SRC_OVER) ||
  645. ((BlendFunction.AlphaFormat & (~ AC_SRC_ALPHA)) != 0))
  646. {
  647. SetLastError(ERROR_INVALID_PARAMETER);
  648. WARNING("AlphaBlend: Invalid Blend Function\n");
  649. return(FALSE);
  650. }
  651. //
  652. // flags used, must be zero or one of the valid ones.
  653. //
  654. if ((BlendFunction.BlendFlags & (~(AC_USE_HIGHQUALITYFILTER|AC_MIRRORBITMAP))) != 0)
  655. {
  656. SetLastError(ERROR_INVALID_PARAMETER);
  657. WARNING("AlphaBlend: Invalid Blend Function\n");
  658. return(FALSE);
  659. }
  660. //
  661. // If the caller claims that the source contains an Alpha channel, than the source
  662. // must be 32BPP.
  663. //
  664. if (BlendFunction.AlphaFormat & AC_SRC_ALPHA)
  665. {
  666. if (GetObjectType(hSrc) == OBJ_MEMDC)
  667. {
  668. HBITMAP hbitmap;
  669. BITMAP bitmap;
  670. if (hbitmap = (HBITMAP) GetCurrentObject(hSrc, OBJ_BITMAP))
  671. {
  672. if (!GetObject(hbitmap, sizeof(BITMAP), &bitmap))
  673. {
  674. WARNING("AlphaBlend: can't get bitmap information for source. Proeeding anyway");
  675. }
  676. else
  677. {
  678. if(bitmap.bmBitsPixel != 32)
  679. {
  680. WARNING("AlphaBlend: AlphaFormat claims that there is an alpha channel in a surface that's not 32BPP\n");
  681. SetLastError(ERROR_INVALID_PARAMETER);
  682. return FALSE;
  683. }
  684. }
  685. }
  686. else
  687. {
  688. WARNING("AlphaBlend: can't get bitmap information for source memory dc. Proceeding anyway");
  689. }
  690. }
  691. else
  692. {
  693. if (GetDeviceCaps(hSrc, BITSPIXEL) != 32)
  694. {
  695. WARNING("AlphaBlend: AlphaFormat claims that there is an alpha channel in a surface that's not 32BPP\n");
  696. SetLastError(ERROR_INVALID_PARAMETER);
  697. return FALSE;
  698. }
  699. }
  700. }
  701. //
  702. // no mirroring
  703. //
  704. if ((DstCx < 0) || (DstCy < 0) || (SrcCx < 0) || (SrcCy < 0))
  705. {
  706. SetLastError(ERROR_INVALID_PARAMETER);
  707. WARNING("AlphaBlend: Invalid parameter\n");
  708. return(FALSE);
  709. }
  710. //
  711. // dispatch call
  712. //
  713. bRet = gpfnAlphaBlend(hdcDest,DstX,DstY,DstCx,DstCy,hSrc,SrcX,SrcY,SrcCx,SrcCy,BlendFunction);
  714. return(bRet);
  715. }