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.

2763 lines
78 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: alphablt.c
  6. * Content: DirectDraw Surface support for alpha-blended blt
  7. * History:
  8. * Date By Reason
  9. * ==== == ======
  10. * 30-sep-97 jvanaken Original version adapted from ddsblt.c
  11. *
  12. ***************************************************************************/
  13. #include "ddrawpr.h"
  14. // function from ddraw module ddclip.c
  15. extern HRESULT InternalGetClipList(LPDIRECTDRAWCLIPPER,
  16. LPRECT,
  17. LPRGNDATA,
  18. LPDWORD,
  19. LPDDRAWI_DIRECTDRAW_GBL);
  20. #ifndef WINNT
  21. #define DONE_BUSY() \
  22. (*pdflags) &= ~BUSY;
  23. #define LEAVE_BOTH_NOBUSY() \
  24. { if(pdflags) \
  25. (*pdflags) &= ~BUSY; \
  26. } \
  27. LEAVE_BOTH();
  28. #else
  29. #define DONE_BUSY()
  30. #define LEAVE_BOTH_NOBUSY() \
  31. LEAVE_BOTH();
  32. #endif
  33. #define DONE_LOCKS() \
  34. if (dest_lock_taken) \
  35. { \
  36. InternalUnlock(surf_dest_lcl,NULL,NULL,0); \
  37. dest_lock_taken = FALSE; \
  38. } \
  39. if (src_lock_taken && surf_src_lcl) \
  40. { \
  41. InternalUnlock(surf_src_lcl,NULL,NULL,0); \
  42. src_lock_taken = FALSE; \
  43. }
  44. #if defined(WIN95)
  45. #define DONE_EXCLUDE() \
  46. if (surf_dest_lcl->lpDDClipper != NULL) \
  47. { \
  48. if ((pdrv->dwFlags & DDRAWI_DISPLAYDRV) && pdrv->dwPDevice && \
  49. !(*pdrv->lpwPDeviceFlags & HARDWARECURSOR)) \
  50. { \
  51. DD16_Unexclude(pdrv->dwPDevice); \
  52. } \
  53. }
  54. #elif defined(WINNT)
  55. #define DONE_EXCLUDE() ;
  56. #endif
  57. /*
  58. * Stretch-blit info
  59. */
  60. typedef struct
  61. {
  62. DWORD src_height;
  63. DWORD src_width;
  64. DWORD dest_height;
  65. DWORD dest_width;
  66. BOOL halonly; // HEL can't do this alpha-blit
  67. BOOL helonly; // hardware driver can't do this alpha-blit
  68. } STRETCH_BLT_INFO, FAR *LPSTRETCH_BLT_INFO;
  69. /*
  70. * Alpha-blitting capability bits
  71. */
  72. typedef struct
  73. {
  74. // caps for hardware driver
  75. DWORD dwCaps;
  76. DWORD dwCKeyCaps;
  77. DWORD dwFXCaps;
  78. DWORD dwAlphaCaps;
  79. DWORD dwFilterCaps;
  80. // caps for HEL
  81. DWORD dwHELCaps;
  82. DWORD dwHELCKeyCaps;
  83. DWORD dwHELFXCaps;
  84. DWORD dwHELAlphaCaps;
  85. DWORD dwHELFilterCaps;
  86. // caps common to hardware driver and HEL
  87. DWORD dwBothCaps;
  88. DWORD dwBothCKeyCaps;
  89. DWORD dwBothFXCaps;
  90. DWORD dwBothAlphaCaps;
  91. DWORD dwBothFilterCaps;
  92. BOOL bHALSeesSysmem;
  93. } ALPHA_BLT_CAPS, *LPALPHA_BLT_CAPS;
  94. /*
  95. * Return a pointer to the DDPIXELFORMAT structure that
  96. * describes the specified surface's pixel format.
  97. */
  98. static LPDDPIXELFORMAT getPixelFormatPtr(LPDDRAWI_DDRAWSURFACE_LCL surf_lcl)
  99. {
  100. LPDDPIXELFORMAT pDDPF;
  101. if (surf_lcl == NULL)
  102. {
  103. return NULL;
  104. }
  105. if (surf_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT)
  106. {
  107. // surface contains explicitly defined pixel format
  108. pDDPF = &surf_lcl->lpGbl->ddpfSurface;
  109. }
  110. else
  111. {
  112. // surface's pixel format is implicit -- same as primary's
  113. pDDPF = &surf_lcl->lpSurfMore->lpDD_lcl->lpGbl->vmiData.ddpfDisplay;
  114. }
  115. return pDDPF;
  116. } /* getPixelFormatPtr */
  117. /*
  118. * Initialize ALPHA_BLT_CAPS structure according to whether source and
  119. * dest surfaces are in system or video (local or nonlocal) memory.
  120. */
  121. static void initAlphaBltCaps(DWORD dwDstCaps,
  122. DWORD dwSrcCaps,
  123. LPDDRAWI_DIRECTDRAW_GBL pdrv,
  124. LPALPHA_BLT_CAPS pcaps,
  125. LPBOOL helonly)
  126. {
  127. DDASSERT(pcaps != NULL);
  128. memset(pcaps, 0, sizeof(ALPHA_BLT_CAPS));
  129. if ((dwSrcCaps | dwDstCaps) & DDSCAPS_NONLOCALVIDMEM &&
  130. pdrv->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEMCAPS)
  131. {
  132. /*
  133. * At least one of the surfaces is nonlocal video memory. The device
  134. * exports different capabilities for local and nonlocal video memory.
  135. * If this is a nonlocal-to-local transfer then check the appropriate
  136. * caps. Otherwise, force software emulation of the blit.
  137. */
  138. if (dwSrcCaps & DDSCAPS_NONLOCALVIDMEM && dwDstCaps & DDSCAPS_LOCALVIDMEM)
  139. {
  140. /*
  141. * Non-local to local video memory transfer.
  142. */
  143. DDASSERT(NULL != pdrv->lpddNLVCaps);
  144. DDASSERT(NULL != pdrv->lpddNLVHELCaps);
  145. DDASSERT(NULL != pdrv->lpddNLVBothCaps);
  146. /*
  147. * We have specific caps for nonlocal video memory. Use them.
  148. */
  149. pcaps->dwCaps = pdrv->lpddNLVCaps->dwNLVBCaps;
  150. pcaps->dwCKeyCaps = pdrv->lpddNLVCaps->dwNLVBCKeyCaps;
  151. pcaps->dwFXCaps = pdrv->lpddNLVCaps->dwNLVBFXCaps;
  152. if (pdrv->lpddMoreCaps)
  153. {
  154. if (pcaps->dwFXCaps & DDFXCAPS_BLTALPHA)
  155. {
  156. pcaps->dwAlphaCaps = pdrv->lpddMoreCaps->dwAlphaCaps;
  157. }
  158. if (pcaps->dwFXCaps & DDFXCAPS_BLTFILTER)
  159. {
  160. pcaps->dwFilterCaps = pdrv->lpddMoreCaps->dwFilterCaps;
  161. }
  162. }
  163. pcaps->dwHELCaps = pdrv->lpddNLVHELCaps->dwNLVBCaps;
  164. pcaps->dwHELCKeyCaps = pdrv->lpddNLVHELCaps->dwNLVBCKeyCaps;
  165. pcaps->dwHELFXCaps = pdrv->lpddNLVHELCaps->dwNLVBFXCaps;
  166. if (pdrv->lpddHELMoreCaps)
  167. {
  168. if (pcaps->dwHELFXCaps & DDFXCAPS_BLTALPHA)
  169. {
  170. pcaps->dwHELAlphaCaps = pdrv->lpddHELMoreCaps->dwAlphaCaps;
  171. }
  172. if (pcaps->dwHELFXCaps & DDFXCAPS_BLTFILTER)
  173. {
  174. pcaps->dwHELFilterCaps = pdrv->lpddHELMoreCaps->dwFilterCaps;
  175. }
  176. }
  177. pcaps->dwBothCaps = pdrv->lpddNLVBothCaps->dwNLVBCaps;
  178. pcaps->dwBothCKeyCaps = pdrv->lpddNLVBothCaps->dwNLVBCKeyCaps;
  179. pcaps->dwBothFXCaps = pdrv->lpddNLVBothCaps->dwNLVBFXCaps;
  180. if (pdrv->lpddBothMoreCaps)
  181. {
  182. if (pcaps->dwBothFXCaps & DDFXCAPS_BLTALPHA)
  183. {
  184. pcaps->dwBothAlphaCaps = pdrv->lpddBothMoreCaps->dwAlphaCaps;
  185. }
  186. if (pcaps->dwBothFXCaps & DDFXCAPS_BLTFILTER)
  187. {
  188. pcaps->dwBothFilterCaps = pdrv->lpddBothMoreCaps->dwFilterCaps;
  189. }
  190. }
  191. /*
  192. * A driver that cannot filter is trivially capable of disabling filtering.
  193. * By similar logic, a driver than cannot filter does not fail to respect
  194. * the DDABLT_FILTERTRANSPBORDER flag unless filtering is explicitly enabled.
  195. */
  196. if (!(pcaps->dwFXCaps & DDFXCAPS_BLTFILTER))
  197. {
  198. pcaps->dwFilterCaps = DDFILTCAPS_BLTCANDISABLEFILTER | DDFILTCAPS_BLTTRANSPBORDER;
  199. pcaps->dwFXCaps |= DDFXCAPS_BLTFILTER;
  200. }
  201. if (!(pcaps->dwHELFXCaps & DDFXCAPS_BLTFILTER))
  202. {
  203. pcaps->dwHELFilterCaps = DDFILTCAPS_BLTCANDISABLEFILTER | DDFILTCAPS_BLTTRANSPBORDER;
  204. pcaps->dwHELFXCaps |= DDFXCAPS_BLTFILTER;
  205. }
  206. if (!(pcaps->dwBothFXCaps & DDFXCAPS_BLTFILTER))
  207. {
  208. pcaps->dwBothFilterCaps = DDFILTCAPS_BLTCANDISABLEFILTER | DDFILTCAPS_BLTTRANSPBORDER;
  209. pcaps->dwBothFXCaps |= DDFXCAPS_BLTFILTER;
  210. }
  211. pcaps->bHALSeesSysmem = FALSE;
  212. return;
  213. }
  214. /*
  215. * Nonlocal-to-nonlocal or local-to-nonlocal transfer. Force emulation.
  216. */
  217. *helonly = TRUE;
  218. }
  219. if (!(pdrv->ddCaps.dwCaps & DDCAPS_CANBLTSYSMEM))
  220. {
  221. if ((dwSrcCaps | dwDstCaps) & DDSCAPS_SYSTEMMEMORY)
  222. {
  223. *helonly = TRUE;
  224. }
  225. }
  226. if (dwSrcCaps & dwDstCaps & DDSCAPS_VIDEOMEMORY)
  227. {
  228. pcaps->dwCaps = pdrv->ddCaps.dwCaps;
  229. pcaps->dwCKeyCaps = pdrv->ddCaps.dwCKeyCaps;
  230. pcaps->dwFXCaps = pdrv->ddCaps.dwFXCaps;
  231. if (pdrv->lpddMoreCaps)
  232. {
  233. if (pcaps->dwFXCaps & DDFXCAPS_BLTALPHA)
  234. {
  235. pcaps->dwAlphaCaps = pdrv->lpddMoreCaps->dwAlphaCaps;
  236. }
  237. if (pcaps->dwFXCaps & DDFXCAPS_BLTFILTER)
  238. {
  239. pcaps->dwFilterCaps = pdrv->lpddMoreCaps->dwFilterCaps;
  240. }
  241. }
  242. pcaps->dwHELCaps = pdrv->ddHELCaps.dwCaps;
  243. pcaps->dwHELCKeyCaps = pdrv->ddHELCaps.dwCKeyCaps;
  244. pcaps->dwHELFXCaps = pdrv->ddHELCaps.dwFXCaps;
  245. if (pdrv->lpddHELMoreCaps)
  246. {
  247. if (pcaps->dwHELFXCaps & DDFXCAPS_BLTALPHA)
  248. {
  249. pcaps->dwHELAlphaCaps = pdrv->lpddHELMoreCaps->dwAlphaCaps;
  250. }
  251. if (pcaps->dwHELFXCaps & DDFXCAPS_BLTFILTER)
  252. {
  253. pcaps->dwHELFilterCaps = pdrv->lpddHELMoreCaps->dwFilterCaps;
  254. }
  255. }
  256. pcaps->dwBothCaps = pdrv->ddBothCaps.dwCaps;
  257. pcaps->dwBothCKeyCaps = pdrv->ddBothCaps.dwCKeyCaps;
  258. pcaps->dwBothFXCaps = pdrv->ddBothCaps.dwFXCaps;
  259. if (pdrv->lpddBothMoreCaps)
  260. {
  261. if (pcaps->dwBothFXCaps & DDFXCAPS_BLTALPHA)
  262. {
  263. pcaps->dwBothAlphaCaps = pdrv->lpddBothMoreCaps->dwAlphaCaps;
  264. }
  265. if (pcaps->dwBothFXCaps & DDFXCAPS_BLTFILTER)
  266. {
  267. pcaps->dwBothFilterCaps = pdrv->lpddBothMoreCaps->dwFilterCaps;
  268. }
  269. }
  270. pcaps->bHALSeesSysmem = FALSE;
  271. }
  272. else if ((dwSrcCaps & DDSCAPS_SYSTEMMEMORY) && (dwDstCaps & DDSCAPS_VIDEOMEMORY))
  273. {
  274. pcaps->dwCaps = pdrv->ddCaps.dwSVBCaps;
  275. pcaps->dwCKeyCaps = pdrv->ddCaps.dwSVBCKeyCaps;
  276. pcaps->dwFXCaps = pdrv->ddCaps.dwSVBFXCaps;
  277. if (pdrv->lpddMoreCaps)
  278. {
  279. if (pcaps->dwFXCaps & DDFXCAPS_BLTALPHA)
  280. {
  281. pcaps->dwAlphaCaps = pdrv->lpddMoreCaps->dwSVBAlphaCaps;
  282. }
  283. if (pcaps->dwFXCaps & DDFXCAPS_BLTFILTER)
  284. {
  285. pcaps->dwFilterCaps = pdrv->lpddMoreCaps->dwSVBFilterCaps;
  286. }
  287. }
  288. pcaps->dwHELCaps = pdrv->ddHELCaps.dwSVBCaps;
  289. pcaps->dwHELCKeyCaps = pdrv->ddHELCaps.dwSVBCKeyCaps;
  290. pcaps->dwHELFXCaps = pdrv->ddHELCaps.dwSVBFXCaps;
  291. if (pdrv->lpddHELMoreCaps)
  292. {
  293. if (pcaps->dwHELFXCaps & DDFXCAPS_BLTALPHA)
  294. {
  295. pcaps->dwHELAlphaCaps = pdrv->lpddHELMoreCaps->dwSVBAlphaCaps;
  296. }
  297. if (pcaps->dwHELFXCaps & DDFXCAPS_BLTFILTER)
  298. {
  299. pcaps->dwHELFilterCaps = pdrv->lpddHELMoreCaps->dwSVBFilterCaps;
  300. }
  301. }
  302. pcaps->dwBothCaps = pdrv->ddBothCaps.dwSVBCaps;
  303. pcaps->dwBothCKeyCaps = pdrv->ddBothCaps.dwSVBCKeyCaps;
  304. pcaps->dwBothFXCaps = pdrv->ddBothCaps.dwSVBFXCaps;
  305. if (pdrv->lpddBothMoreCaps)
  306. {
  307. if (pcaps->dwBothFXCaps & DDFXCAPS_BLTALPHA)
  308. {
  309. pcaps->dwBothAlphaCaps = pdrv->lpddBothMoreCaps->dwSVBAlphaCaps;
  310. }
  311. if (pcaps->dwBothFXCaps & DDFXCAPS_BLTFILTER)
  312. {
  313. pcaps->dwBothFilterCaps = pdrv->lpddBothMoreCaps->dwSVBFilterCaps;
  314. }
  315. }
  316. pcaps->bHALSeesSysmem = TRUE;
  317. }
  318. else if ((dwSrcCaps & DDSCAPS_VIDEOMEMORY) && (dwDstCaps & DDSCAPS_SYSTEMMEMORY))
  319. {
  320. pcaps->dwCaps = pdrv->ddCaps.dwVSBCaps;
  321. pcaps->dwCKeyCaps = pdrv->ddCaps.dwVSBCKeyCaps;
  322. pcaps->dwFXCaps = pdrv->ddCaps.dwVSBFXCaps;
  323. if (pdrv->lpddMoreCaps)
  324. {
  325. if (pcaps->dwFXCaps & DDFXCAPS_BLTALPHA)
  326. {
  327. pcaps->dwAlphaCaps = pdrv->lpddMoreCaps->dwVSBAlphaCaps;
  328. }
  329. if (pcaps->dwFXCaps & DDFXCAPS_BLTFILTER)
  330. {
  331. pcaps->dwFilterCaps = pdrv->lpddMoreCaps->dwVSBFilterCaps;
  332. }
  333. }
  334. pcaps->dwHELCaps = pdrv->ddHELCaps.dwVSBCaps;
  335. pcaps->dwHELCKeyCaps = pdrv->ddHELCaps.dwVSBCKeyCaps;
  336. pcaps->dwHELFXCaps = pdrv->ddHELCaps.dwVSBFXCaps;
  337. if (pdrv->lpddHELMoreCaps)
  338. {
  339. if (pcaps->dwHELFXCaps & DDFXCAPS_BLTALPHA)
  340. {
  341. pcaps->dwHELAlphaCaps = pdrv->lpddHELMoreCaps->dwVSBAlphaCaps;
  342. }
  343. if (pcaps->dwHELFXCaps & DDFXCAPS_BLTFILTER)
  344. {
  345. pcaps->dwHELFilterCaps = pdrv->lpddHELMoreCaps->dwVSBFilterCaps;
  346. }
  347. }
  348. pcaps->dwBothCaps = pdrv->ddBothCaps.dwVSBCaps;
  349. pcaps->dwBothCKeyCaps = pdrv->ddBothCaps.dwVSBCKeyCaps;
  350. pcaps->dwBothFXCaps = pdrv->ddBothCaps.dwVSBFXCaps;
  351. if (pdrv->lpddBothMoreCaps)
  352. {
  353. if (pcaps->dwBothFXCaps & DDFXCAPS_BLTALPHA)
  354. {
  355. pcaps->dwBothAlphaCaps = pdrv->lpddBothMoreCaps->dwVSBAlphaCaps;
  356. }
  357. if (pcaps->dwBothFXCaps & DDFXCAPS_BLTFILTER)
  358. {
  359. pcaps->dwBothFilterCaps = pdrv->lpddBothMoreCaps->dwVSBFilterCaps;
  360. }
  361. }
  362. pcaps->bHALSeesSysmem = TRUE;
  363. }
  364. else if (dwSrcCaps & dwDstCaps & DDSCAPS_SYSTEMMEMORY)
  365. {
  366. pcaps->dwCaps = pdrv->ddCaps.dwSSBCaps;
  367. pcaps->dwCKeyCaps = pdrv->ddCaps.dwSSBCKeyCaps;
  368. pcaps->dwFXCaps = pdrv->ddCaps.dwSSBFXCaps;
  369. if (pdrv->lpddMoreCaps)
  370. {
  371. if (pcaps->dwFXCaps & DDFXCAPS_BLTALPHA)
  372. {
  373. pcaps->dwAlphaCaps = pdrv->lpddMoreCaps->dwSSBAlphaCaps;
  374. }
  375. if (pcaps->dwFXCaps & DDFXCAPS_BLTFILTER)
  376. {
  377. pcaps->dwFilterCaps = pdrv->lpddMoreCaps->dwSSBFilterCaps;
  378. }
  379. }
  380. pcaps->dwHELCaps = pdrv->ddHELCaps.dwSSBCaps;
  381. pcaps->dwHELCKeyCaps = pdrv->ddHELCaps.dwSSBCKeyCaps;
  382. pcaps->dwHELFXCaps = pdrv->ddHELCaps.dwSSBFXCaps;
  383. if (pdrv->lpddHELMoreCaps)
  384. {
  385. if (pcaps->dwHELFXCaps & DDFXCAPS_BLTALPHA)
  386. {
  387. pcaps->dwHELAlphaCaps = pdrv->lpddHELMoreCaps->dwSSBAlphaCaps;
  388. }
  389. if (pcaps->dwHELFXCaps & DDFXCAPS_BLTFILTER)
  390. {
  391. pcaps->dwHELFilterCaps = pdrv->lpddHELMoreCaps->dwSSBFilterCaps;
  392. }
  393. }
  394. pcaps->dwBothCaps = pdrv->ddBothCaps.dwSSBCaps;
  395. pcaps->dwBothCKeyCaps = pdrv->ddBothCaps.dwSSBCKeyCaps;
  396. pcaps->dwBothFXCaps = pdrv->ddBothCaps.dwSSBFXCaps;
  397. if (pdrv->lpddBothMoreCaps)
  398. {
  399. if (pcaps->dwBothFXCaps & DDFXCAPS_BLTALPHA)
  400. {
  401. pcaps->dwBothAlphaCaps = pdrv->lpddBothMoreCaps->dwSSBAlphaCaps;
  402. }
  403. if (pcaps->dwBothFXCaps & DDFXCAPS_BLTFILTER)
  404. {
  405. pcaps->dwBothFilterCaps = pdrv->lpddBothMoreCaps->dwSSBFilterCaps;
  406. }
  407. }
  408. pcaps->bHALSeesSysmem = TRUE;
  409. }
  410. /*
  411. * A driver that cannot filter is trivially capable of disabling filtering.
  412. * By similar logic, a driver than cannot filter does not fail to respect
  413. * the DDABLT_FILTERTRANSPBORDER flag unless filtering is explicitly enabled.
  414. */
  415. if (!(pcaps->dwFXCaps & DDFXCAPS_BLTFILTER))
  416. {
  417. pcaps->dwFilterCaps = DDFILTCAPS_BLTCANDISABLEFILTER | DDFILTCAPS_BLTTRANSPBORDER;
  418. pcaps->dwFXCaps |= DDFXCAPS_BLTFILTER;
  419. }
  420. if (!(pcaps->dwHELFXCaps & DDFXCAPS_BLTFILTER))
  421. {
  422. pcaps->dwHELFilterCaps = DDFILTCAPS_BLTCANDISABLEFILTER | DDFILTCAPS_BLTTRANSPBORDER;
  423. pcaps->dwHELFXCaps |= DDFXCAPS_BLTFILTER;
  424. }
  425. if (!(pcaps->dwBothFXCaps & DDFXCAPS_BLTFILTER))
  426. {
  427. pcaps->dwBothFilterCaps = DDFILTCAPS_BLTCANDISABLEFILTER | DDFILTCAPS_BLTTRANSPBORDER;
  428. pcaps->dwBothFXCaps |= DDFXCAPS_BLTFILTER;
  429. }
  430. } /* initAlphaBltCaps */
  431. /*
  432. * Verify that driver can perform requested stretching for blit.
  433. */
  434. static HRESULT validateStretching(LPALPHA_BLT_CAPS pcaps,
  435. LPSTRETCH_BLT_INFO psbi)
  436. {
  437. DWORD caps;
  438. BOOL fail = FALSE;
  439. /*
  440. * Can we even stretch at all?
  441. */
  442. if (!(pcaps->dwBothCaps & DDCAPS_BLTSTRETCH))
  443. {
  444. GETFAILCODEBLT(pcaps->dwCaps,
  445. pcaps->dwHELCaps,
  446. psbi->halonly,
  447. psbi->helonly,
  448. DDCAPS_BLTSTRETCH);
  449. if (fail)
  450. {
  451. return DDERR_NOSTRETCHHW;
  452. }
  453. }
  454. if (psbi->helonly)
  455. caps = pcaps->dwHELFXCaps;
  456. else
  457. caps = pcaps->dwFXCaps;
  458. /*
  459. * verify height
  460. */
  461. if (psbi->src_height != psbi->dest_height)
  462. {
  463. if (psbi->src_height > psbi->dest_height)
  464. {
  465. /*
  466. * can we shrink Y arbitrarily?
  467. */
  468. if (!(caps & (DDFXCAPS_BLTSHRINKY)))
  469. {
  470. /*
  471. * see if this is a non-integer shrink
  472. */
  473. if ((psbi->src_height % psbi->dest_height) != 0)
  474. {
  475. GETFAILCODEBLT(pcaps->dwFXCaps,
  476. pcaps->dwHELFXCaps,
  477. psbi->halonly,
  478. psbi->helonly,
  479. DDFXCAPS_BLTSHRINKY);
  480. if (fail)
  481. {
  482. return DDERR_NOSTRETCHHW;
  483. }
  484. /*
  485. * see if we can integer shrink
  486. */
  487. }
  488. else if (!(caps & DDFXCAPS_BLTSHRINKYN))
  489. {
  490. GETFAILCODEBLT(pcaps->dwFXCaps,
  491. pcaps->dwHELFXCaps,
  492. psbi->halonly,
  493. psbi->helonly,
  494. DDFXCAPS_BLTSHRINKYN);
  495. if (fail)
  496. {
  497. return DDERR_NOSTRETCHHW;
  498. }
  499. }
  500. }
  501. }
  502. else
  503. {
  504. if (!(caps & DDFXCAPS_BLTSTRETCHY))
  505. {
  506. /*
  507. * see if this is a non-integer stretch
  508. */
  509. if ((psbi->dest_height % psbi->src_height) != 0)
  510. {
  511. GETFAILCODEBLT(pcaps->dwFXCaps,
  512. pcaps->dwHELFXCaps,
  513. psbi->halonly,
  514. psbi->helonly,
  515. DDFXCAPS_BLTSTRETCHY);
  516. if (fail)
  517. {
  518. return DDERR_NOSTRETCHHW;
  519. }
  520. /*
  521. * see if we can integer stretch
  522. */
  523. }
  524. else if (!(caps & DDFXCAPS_BLTSTRETCHYN))
  525. {
  526. GETFAILCODEBLT(pcaps->dwFXCaps,
  527. pcaps->dwHELFXCaps,
  528. psbi->halonly,
  529. psbi->helonly,
  530. DDFXCAPS_BLTSTRETCHYN);
  531. if (fail)
  532. {
  533. return DDERR_NOSTRETCHHW;
  534. }
  535. }
  536. }
  537. }
  538. }
  539. /*
  540. * verify width
  541. */
  542. if (psbi->src_width != psbi->dest_width)
  543. {
  544. if (psbi->src_width > psbi->dest_width)
  545. {
  546. if (!(caps & DDFXCAPS_BLTSHRINKX))
  547. {
  548. /*
  549. * Are we stretching by a non-integer factor?
  550. */
  551. if ((psbi->src_width % psbi->dest_width) != 0)
  552. {
  553. GETFAILCODEBLT(pcaps->dwFXCaps,
  554. pcaps->dwHELFXCaps,
  555. psbi->halonly,
  556. psbi->helonly,
  557. DDFXCAPS_BLTSHRINKX);
  558. if (fail)
  559. {
  560. return DDERR_NOSTRETCHHW;
  561. }
  562. /*
  563. * see if we can integer shrink
  564. */
  565. }
  566. else if (!(caps & DDFXCAPS_BLTSHRINKXN))
  567. {
  568. GETFAILCODEBLT(pcaps->dwFXCaps,
  569. pcaps->dwHELFXCaps,
  570. psbi->halonly,
  571. psbi->helonly,
  572. DDFXCAPS_BLTSHRINKXN);
  573. if (fail)
  574. {
  575. return DDERR_NOSTRETCHHW;
  576. }
  577. }
  578. }
  579. }
  580. else
  581. {
  582. if (!(caps & DDFXCAPS_BLTSTRETCHX))
  583. {
  584. /*
  585. * Are we stretching by a non-integer factor?
  586. */
  587. if ((psbi->dest_width % psbi->src_width) != 0)
  588. {
  589. GETFAILCODEBLT(pcaps->dwFXCaps,
  590. pcaps->dwHELFXCaps,
  591. psbi->halonly,
  592. psbi->helonly,
  593. DDFXCAPS_BLTSTRETCHX);
  594. if (fail)
  595. {
  596. return DDERR_NOSTRETCHHW;
  597. }
  598. }
  599. if (!(caps & DDFXCAPS_BLTSTRETCHXN))
  600. {
  601. GETFAILCODEBLT(pcaps->dwFXCaps,
  602. pcaps->dwHELFXCaps,
  603. psbi->halonly,
  604. psbi->helonly,
  605. DDFXCAPS_BLTSTRETCHXN);
  606. if (fail)
  607. {
  608. return DDERR_NOSTRETCHHW;
  609. }
  610. }
  611. }
  612. }
  613. }
  614. return DD_OK;
  615. } /* validateStretching */
  616. #undef DPF_MODNAME
  617. #define DPF_MODNAME "AlphaBlt"
  618. /*
  619. * Wait for pending hardware operation on specified surface to finish.
  620. *
  621. * This function waits for the hardware driver to report that it has finished
  622. * operating on the given surface. We should only call this function if the
  623. * surface was a system memory surface involved in a DMA/busmastering transfer.
  624. * Note this function clears the DDRAWISURFGBL_HARDWAREOPSTARTED flag.
  625. */
  626. static void WaitForHardwareOp(LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl,
  627. LPDDRAWI_DDRAWSURFACE_LCL surf_lcl)
  628. {
  629. HRESULT hr;
  630. #ifdef DEBUG
  631. BOOL bSentMessage = FALSE;
  632. DWORD dwStart = GetTickCount();
  633. #endif
  634. DDASSERT(surf_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY);
  635. DPF(5, B, "Waiting for driver to finish with %08x", surf_lcl->lpGbl);
  636. do
  637. {
  638. hr = InternalGetBltStatus(pdrv_lcl, surf_lcl, DDGBS_ISBLTDONE);
  639. #ifdef DEBUG
  640. if (GetTickCount() - dwStart >= 10000 && !bSentMessage)
  641. {
  642. bSentMessage = TRUE;
  643. DPF_ERR("Driver error: Hardware op still pending on surface after 5 sec!");
  644. }
  645. #endif
  646. } while (hr == DDERR_WASSTILLDRAWING);
  647. DDASSERT(hr == DD_OK);
  648. DPF(5, B, "Driver finished with that surface");
  649. surf_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_HARDWAREOPSTARTED;
  650. } /* WaitForHardwareOp */
  651. /*
  652. * DD_Surface_AlphaBlt
  653. *
  654. * BitBLT from one surface to another with alpha blending.
  655. */
  656. HRESULT DDAPI DD_Surface_AlphaBlt(
  657. LPDIRECTDRAWSURFACE lpDDDestSurface,
  658. LPRECT lpDestRect,
  659. LPDIRECTDRAWSURFACE lpDDSrcSurface,
  660. LPRECT lpSrcRect,
  661. DWORD dwFlags,
  662. LPDDALPHABLTFX lpDDAlphaBltFX)
  663. {
  664. struct
  665. {
  666. RGNDATAHEADER rdh;
  667. RECT clipRect[8];
  668. } myRgnBuffer;
  669. DWORD rc;
  670. LPDDRAWI_DDRAWSURFACE_INT surf_src_int;
  671. LPDDRAWI_DDRAWSURFACE_LCL surf_src_lcl;
  672. LPDDRAWI_DDRAWSURFACE_GBL surf_src;
  673. LPDDRAWI_DDRAWSURFACE_INT surf_dest_int;
  674. LPDDRAWI_DDRAWSURFACE_LCL surf_dest_lcl;
  675. LPDDRAWI_DDRAWSURFACE_GBL surf_dest;
  676. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  677. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  678. LPDDHAL_ALPHABLT bltfn;
  679. DDHAL_BLTDATA bd;
  680. STRETCH_BLT_INFO sbi;
  681. BOOL fail;
  682. BOOL dest_lock_taken=FALSE;
  683. BOOL src_lock_taken=FALSE;
  684. LPVOID dest_bits;
  685. LPVOID src_bits;
  686. HRESULT ddrval;
  687. RECT rect;
  688. ALPHA_BLT_CAPS caps;
  689. LPWORD pdflags=0;
  690. LPRGNDATA pRgn;
  691. DDARGB ddargbScaleFactors;
  692. DWORD dwFillValue;
  693. DWORD dwDDPFDestFlags;
  694. DWORD dwDDPFSrcFlags;
  695. DDASSERT(sizeof(DDARGB)==sizeof(DWORD)); // we rely on this
  696. ENTER_BOTH();
  697. DPF(2,A,"ENTERAPI: DD_Surface_AlphaBlt");
  698. TRY
  699. {
  700. ZeroMemory(&bd, sizeof(bd)); // initialize to zero
  701. /*
  702. * Validate surface pointers.
  703. */
  704. surf_dest_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDDestSurface;
  705. surf_src_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSrcSurface;
  706. if (!VALID_DIRECTDRAWSURFACE_PTR(surf_dest_int))
  707. {
  708. DPF_ERR("Invalid dest surface") ;
  709. LEAVE_BOTH();
  710. return DDERR_INVALIDOBJECT;
  711. }
  712. surf_dest_lcl = surf_dest_int->lpLcl;
  713. surf_dest = surf_dest_lcl->lpGbl;
  714. if (SURFACE_LOST(surf_dest_lcl))
  715. {
  716. DPF_ERR("Dest surface lost") ;
  717. LEAVE_BOTH();
  718. return DDERR_SURFACELOST;
  719. }
  720. if (surf_src_int != NULL)
  721. {
  722. if (!VALID_DIRECTDRAWSURFACE_PTR(surf_src_int))
  723. {
  724. DPF_ERR("Invalid source surface");
  725. LEAVE_BOTH();
  726. return DDERR_INVALIDOBJECT;
  727. }
  728. surf_src_lcl = surf_src_int->lpLcl;
  729. surf_src = surf_src_lcl->lpGbl;
  730. if (SURFACE_LOST(surf_src_lcl))
  731. {
  732. DPF_ERR("Src surface lost") ;
  733. LEAVE_BOTH();
  734. return DDERR_SURFACELOST;
  735. }
  736. }
  737. else
  738. {
  739. surf_src_lcl = NULL;
  740. surf_src = NULL;
  741. }
  742. if (dwFlags & ~DDABLT_VALID)
  743. {
  744. DPF_ERR("Invalid flags") ;
  745. LEAVE_BOTH();
  746. return DDERR_INVALIDPARAMS;
  747. }
  748. // Is the DONOTWAIT flag set?
  749. if (dwFlags & DDABLT_DONOTWAIT)
  750. {
  751. if (dwFlags & DDABLT_WAIT)
  752. {
  753. DPF_ERR("WAIT and DONOTWAIT flags are mutually exclusive");
  754. LEAVE_BOTH_NOBUSY();
  755. return DDERR_INVALIDPARAMS;
  756. }
  757. }
  758. else
  759. {
  760. // Unless the DONOTWAIT flag is explicitly set, use the default (WAIT).
  761. dwFlags |= DDABLT_WAIT;
  762. }
  763. /*
  764. * Set ARGB scaling factors and fill value to their default values.
  765. * Note that setting ddargbScaleFactors to all ones effectively
  766. * disables ARGB scaling, and a fill value of zero represents black.
  767. */
  768. *(LPDWORD)&ddargbScaleFactors = ~0UL;
  769. dwFillValue = 0;
  770. /*
  771. * Read parameters pointed to by lpDDAlphaBltFX argument.
  772. */
  773. if (lpDDAlphaBltFX != 0)
  774. {
  775. if (IsBadWritePtr((LPVOID)lpDDAlphaBltFX, sizeof(DDALPHABLTFX)))
  776. {
  777. DPF_ERR("Argument lpDDAlphaBltFX is a bad pointer") ;
  778. LEAVE_BOTH();
  779. return DDERR_INVALIDPARAMS;
  780. }
  781. if (dwFlags & DDABLT_USEFILLVALUE)
  782. {
  783. dwFillValue = lpDDAlphaBltFX->dwFillValue;
  784. }
  785. else
  786. {
  787. ddargbScaleFactors = lpDDAlphaBltFX->ddargbScaleFactors;
  788. }
  789. }
  790. // Is this a color-fill operation that uses dwFillValue?
  791. if (dwFlags & DDABLT_USEFILLVALUE && surf_src_lcl == NULL)
  792. {
  793. // Could this possibly be an alpha-blended fill?
  794. if (!(dwFlags & DDABLT_NOBLEND))
  795. {
  796. HRESULT hres;
  797. // If the fill value is less than 100% opaque, we need to
  798. // do an alpha fill rather than just a simple color fill.
  799. // Convert physcolor to DDARGB value and test its opacity.
  800. hres = ConvertFromPhysColor(
  801. surf_dest_lcl,
  802. &dwFillValue,
  803. &ddargbScaleFactors);
  804. if ((hres == DD_OK) && (ddargbScaleFactors.alpha != 255))
  805. {
  806. // The fill value is not 100% opaque, so do an alpha fill.
  807. dwFlags &= ~DDABLT_USEFILLVALUE;
  808. }
  809. }
  810. // Make sure DEGRADEARGBSCALING flag is not set.
  811. if (dwFlags & DDABLT_DEGRADEARGBSCALING)
  812. {
  813. DPF_ERR("DEGRADEARGBSCALING and USEFILLVALUE flags are incompatible");
  814. LEAVE_BOTH();
  815. return DDERR_INVALIDPARAMS;
  816. }
  817. }
  818. /*
  819. * We do not allow blitting to or from an optimized surface.
  820. */
  821. if (surf_dest_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED ||
  822. surf_src && surf_src_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  823. {
  824. DPF_ERR("Can't blt optimized surfaces") ;
  825. LEAVE_BOTH();
  826. return DDERR_INVALIDPARAMS;
  827. }
  828. pdrv = surf_dest->lpDD;
  829. pdrv_lcl = surf_dest_lcl->lpSurfMore->lpDD_lcl;
  830. #ifdef WINNT
  831. // Update DDraw handle in driver GBL object.
  832. pdrv->hDD = pdrv_lcl->hDD;
  833. #endif
  834. /*
  835. * Default behavior is to automatically fail-over to software
  836. * emulation if hardware driver cannot handle the specified
  837. * blit. The DDABLT_HARDWAREONLY flag overrides this default.
  838. */
  839. sbi.halonly = dwFlags & DDABLT_HARDWAREONLY;
  840. sbi.helonly = dwFlags & DDABLT_SOFTWAREONLY;
  841. /*
  842. * Only the HEL can blit between two surfaces created by two
  843. * different drivers.
  844. */
  845. if (surf_src && surf_src->lpDD != pdrv &&
  846. surf_src->lpDD->dwFlags & DDRAWI_DISPLAYDRV &&
  847. pdrv->dwFlags & DDRAWI_DISPLAYDRV)
  848. {
  849. sbi.helonly = TRUE;
  850. }
  851. }
  852. EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  853. {
  854. DPF_ERR("Exception encountered validating parameters");
  855. LEAVE_BOTH();
  856. return DDERR_INVALIDPARAMS;
  857. }
  858. #ifdef USE_ALIAS
  859. if ((pdrv_lcl->lpDDCB->HALDDMiscellaneous2.AlphaBlt == NULL) &&
  860. (pdrv->dwBusyDueToAliasedLock > 0))
  861. {
  862. /*
  863. * Aliased locks (the ones that don't take the Win16 lock) don't
  864. * set the busy bit either (it can't or USER gets very confused).
  865. * However, we must prevent blits happening via DirectDraw as
  866. * otherwise we get into the old host talking to VRAM while
  867. * blitter does at the same time. Bad. So fail if there is an
  868. * outstanding aliased lock just as if the BUSY bit had been set.
  869. */
  870. DPF_ERR("Graphics adapter is busy (due to a DirectDraw lock)");
  871. LEAVE_BOTH();
  872. return DDERR_SURFACEBUSY;
  873. }
  874. #endif /* USE_ALIAS */
  875. if(surf_src_lcl)
  876. FlushD3DStates(surf_src_lcl); // Need to flush src because it could be a rendertarget
  877. FlushD3DStates(surf_dest_lcl);
  878. /*
  879. * Test and set the busy bit. If it was already set, bail.
  880. */
  881. #ifdef WIN95
  882. {
  883. BOOL isbusy = 0;
  884. pdflags = pdrv->lpwPDeviceFlags;
  885. _asm
  886. {
  887. mov eax, pdflags
  888. bts word ptr [eax], BUSY_BIT
  889. adc byte ptr isbusy,0
  890. }
  891. if (isbusy)
  892. {
  893. DPF(3, "BUSY - AlphaBlt");
  894. LEAVE_BOTH();
  895. return DDERR_SURFACEBUSY;
  896. }
  897. }
  898. #endif
  899. /*
  900. * The following code was added to keep all of the HALs from
  901. * changing their Blt() code when they add video port support.
  902. * If the video port was using this surface but was recently
  903. * flipped, we will make sure that the flip actually occurred
  904. * before allowing access. This allows double buffered capture
  905. * w/o tearing.
  906. */
  907. if ((surf_src_lcl != NULL) &&
  908. (surf_src_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOPORT))
  909. {
  910. LPDDRAWI_DDVIDEOPORT_INT lpVideoPort;
  911. LPDDRAWI_DDVIDEOPORT_LCL lpVideoPort_lcl;
  912. // Look at all video ports to see if any of them recently
  913. // flipped from this surface.
  914. lpVideoPort = pdrv->dvpList;
  915. while(NULL != lpVideoPort)
  916. {
  917. lpVideoPort_lcl = lpVideoPort->lpLcl;
  918. if (lpVideoPort_lcl->fpLastFlip == surf_src->fpVidMem)
  919. {
  920. // This can potentially tear - check the flip status
  921. LPDDHALVPORTCB_GETFLIPSTATUS pfn;
  922. DDHAL_GETVPORTFLIPSTATUSDATA GetFlipData;
  923. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  924. pdrv_lcl = surf_src_lcl->lpSurfMore->lpDD_lcl;
  925. pfn = pdrv_lcl->lpDDCB->HALDDVideoPort.GetVideoPortFlipStatus;
  926. if (pfn != NULL) // Will simply tear if function not supported
  927. {
  928. GetFlipData.lpDD = pdrv_lcl;
  929. GetFlipData.fpSurface = surf_src->fpVidMem;
  930. KeepTrying:
  931. rc = DDHAL_DRIVER_NOTHANDLED;
  932. DOHALCALL(GetVideoPortFlipStatus, pfn, GetFlipData, rc, 0);
  933. if ((DDHAL_DRIVER_HANDLED == rc) &&
  934. (DDERR_WASSTILLDRAWING == GetFlipData.ddRVal))
  935. {
  936. if (dwFlags & DDABLT_WAIT)
  937. {
  938. goto KeepTrying;
  939. }
  940. LEAVE_BOTH_NOBUSY();
  941. return DDERR_WASSTILLDRAWING;
  942. }
  943. }
  944. }
  945. lpVideoPort = lpVideoPort->lpLink;
  946. }
  947. }
  948. TRY
  949. {
  950. /*
  951. * Remove any cached run-length-encoded data for the source surface.
  952. */
  953. if (surf_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  954. {
  955. extern void FreeRleData(LPDDRAWI_DDRAWSURFACE_LCL); //in fasthel.c
  956. FreeRleData(surf_dest_lcl);
  957. }
  958. /*
  959. * Is either surface locked?
  960. */
  961. if (surf_dest->dwUsageCount > 0 ||
  962. surf_src != NULL && surf_src->dwUsageCount > 0)
  963. {
  964. DPF_ERR("Surface is locked");
  965. LEAVE_BOTH_NOBUSY();
  966. return DDERR_SURFACEBUSY;
  967. }
  968. BUMP_SURFACE_STAMP(surf_dest);
  969. /*
  970. * It is possible this function could be called in the middle
  971. * of a mode change, in which case we could trash the frame buffer.
  972. * To avoid regression, we will simply succeed the call without
  973. * actually doing anything.
  974. */
  975. if (pdrv->dwFlags & DDRAWI_CHANGINGMODE &&
  976. !(surf_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY))
  977. {
  978. LEAVE_BOTH_NOBUSY()
  979. return DD_OK;
  980. }
  981. /*
  982. * Some parameters are valid only if a source surface is specified.
  983. */
  984. if (surf_src == NULL)
  985. {
  986. /*
  987. * No source surface is specified, so this must be a fill operation.
  988. */
  989. if (dwFlags & (DDABLT_MIRRORLEFTRIGHT | DDABLT_MIRRORUPDOWN |
  990. DDABLT_FILTERENABLE | DDABLT_FILTERDISABLE |
  991. DDABLT_FILTERTRANSPBORDER | DDABLT_KEYSRC))
  992. {
  993. DPF_ERR("Specified flag requires source surface");
  994. LEAVE_BOTH_NOBUSY();
  995. return DDERR_INVALIDPARAMS;
  996. }
  997. if (lpSrcRect != NULL)
  998. {
  999. DPF_ERR("Source rectangle specified without source surface");
  1000. LEAVE_BOTH_NOBUSY();
  1001. return DDERR_INVALIDPARAMS;
  1002. }
  1003. }
  1004. else
  1005. {
  1006. /*
  1007. * A source surface is specified, so this must be a two-operand blit.
  1008. */
  1009. if (dwFlags & DDABLT_USEFILLVALUE)
  1010. {
  1011. DPF_ERR("USEFILLVALUE flag incompatible with use of source surface");
  1012. LEAVE_BOTH_NOBUSY();
  1013. return DDERR_INVALIDPARAMS;
  1014. }
  1015. }
  1016. /*
  1017. * Get capability bits for source/dest memory combination.
  1018. */
  1019. if (surf_src != NULL)
  1020. {
  1021. // initialize the blit caps according to the surface types
  1022. initAlphaBltCaps(surf_dest_lcl->ddsCaps.dwCaps,
  1023. surf_src_lcl->ddsCaps.dwCaps,
  1024. pdrv,
  1025. &caps,
  1026. &sbi.helonly);
  1027. }
  1028. else
  1029. {
  1030. /*
  1031. * No source surface. Use caps for vram-to-vram blits and choose
  1032. * hal or hel based on whether dest surface is in system memory.
  1033. * If the dest surface is in nonlocal video memory, we also force
  1034. * emulation as we don't currently support accelerated operation
  1035. * with nonlocal video memory as a target.
  1036. */
  1037. initAlphaBltCaps(DDSCAPS_VIDEOMEMORY,
  1038. DDSCAPS_VIDEOMEMORY,
  1039. pdrv,
  1040. &caps,
  1041. &sbi.helonly);
  1042. if (surf_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ||
  1043. surf_dest_lcl->ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM)
  1044. {
  1045. caps.bHALSeesSysmem = FALSE;
  1046. sbi.helonly = TRUE;
  1047. }
  1048. }
  1049. /*
  1050. * Can we really blit? -- Test DDCAPS_BLTCOLORFILL if src surf is null?
  1051. */
  1052. if (!(caps.dwBothCaps & DDCAPS_BLT))
  1053. {
  1054. /*
  1055. * Unable to blit with both HEL and hardware driver.
  1056. * Can either of them do the blit?
  1057. */
  1058. if (caps.dwCaps & DDCAPS_BLT)
  1059. {
  1060. sbi.halonly = TRUE; // hardware driver only
  1061. }
  1062. else if (caps.dwHELCaps & DDCAPS_BLT)
  1063. {
  1064. caps.bHALSeesSysmem = FALSE;
  1065. sbi.helonly = TRUE; // HEL only
  1066. }
  1067. else
  1068. {
  1069. DPF_ERR("Driver does not support blitting");
  1070. LEAVE_BOTH_NOBUSY();
  1071. return DDERR_NOBLTHW;
  1072. }
  1073. }
  1074. /*
  1075. * Validate height and width of destination rectangle.
  1076. */
  1077. if (lpDestRect != NULL)
  1078. {
  1079. if (!VALID_RECT_PTR(lpDestRect))
  1080. {
  1081. DPF_ERR("Invalid dest rect specified");
  1082. LEAVE_BOTH_NOBUSY();
  1083. return DDERR_INVALIDRECT;
  1084. }
  1085. bd.rDest = *(LPRECTL)lpDestRect;
  1086. }
  1087. else
  1088. {
  1089. MAKE_SURF_RECT(surf_dest, surf_dest_lcl, bd.rDest);
  1090. }
  1091. sbi.dest_height = bd.rDest.bottom - bd.rDest.top;
  1092. sbi.dest_width = bd.rDest.right - bd.rDest.left;
  1093. if (((int)sbi.dest_height <= 0) || ((int)sbi.dest_width <= 0))
  1094. {
  1095. DPF_ERR("Bad dest width or height -- must be positive and nonzero");
  1096. LEAVE_BOTH_NOBUSY();
  1097. return DDERR_INVALIDRECT;
  1098. }
  1099. /*
  1100. * Validate height and width of source rectangle.
  1101. */
  1102. if (surf_src != NULL)
  1103. {
  1104. /*
  1105. * Get source rectangle.
  1106. */
  1107. if (lpSrcRect != NULL)
  1108. {
  1109. if (!VALID_RECT_PTR(lpSrcRect))
  1110. {
  1111. DPF_ERR("Invalid src rect specified");
  1112. LEAVE_BOTH_NOBUSY();
  1113. return DDERR_INVALIDRECT;
  1114. }
  1115. bd.rSrc = *(LPRECTL)lpSrcRect;
  1116. }
  1117. else
  1118. {
  1119. MAKE_SURF_RECT(surf_src, surf_src_lcl, bd.rSrc);
  1120. }
  1121. sbi.src_height = bd.rSrc.bottom - bd.rSrc.top;
  1122. sbi.src_width = bd.rSrc.right - bd.rSrc.left;
  1123. if (((int)sbi.src_height <= 0) || ((int)sbi.src_width <= 0))
  1124. {
  1125. DPF_ERR("Bad source width or height -- must be positive and nonzero");
  1126. LEAVE_BOTH_NOBUSY();
  1127. return DDERR_INVALIDRECT;
  1128. }
  1129. /*
  1130. * Multi-mon: Is this the primary for the desktop? This is the
  1131. * only case where the upper-left coord of the surface is not (0,0).
  1132. */
  1133. if ((surf_src->lpDD->dwFlags & DDRAWI_VIRTUALDESKTOP) &&
  1134. (surf_src_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
  1135. {
  1136. if ((bd.rSrc.left < surf_src->lpDD->rectDevice.left) ||
  1137. (bd.rSrc.top < surf_src->lpDD->rectDevice.top) ||
  1138. (bd.rSrc.right > surf_src->lpDD->rectDevice.right)||
  1139. (bd.rSrc.bottom > surf_src->lpDD->rectDevice.bottom))
  1140. {
  1141. DPF_ERR("Source rect doesn't fit on Desktop");
  1142. LEAVE_BOTH_NOBUSY();
  1143. return DDERR_INVALIDRECT;
  1144. }
  1145. }
  1146. else
  1147. {
  1148. if ((int)bd.rSrc.left < 0 ||
  1149. (int)bd.rSrc.top < 0 ||
  1150. (DWORD)bd.rSrc.bottom > (DWORD)surf_src->wHeight ||
  1151. (DWORD)bd.rSrc.right > (DWORD)surf_src->wWidth)
  1152. {
  1153. DPF_ERR("Invalid source rect specified");
  1154. LEAVE_BOTH_NOBUSY();
  1155. return DDERR_INVALIDRECT;
  1156. }
  1157. }
  1158. /*
  1159. * Verify stretching...
  1160. */
  1161. if (sbi.src_height != sbi.dest_height || sbi.src_width != sbi.dest_width)
  1162. {
  1163. HRESULT ddrval = validateStretching(&caps, &sbi);
  1164. if (ddrval != DD_OK)
  1165. {
  1166. DPF_ERR("Can't perform specified stretching");
  1167. LEAVE_BOTH_NOBUSY();
  1168. return ddrval;
  1169. }
  1170. /*
  1171. * Do source and dest rectangles lie on the same surface and overlap?
  1172. */
  1173. if (surf_src_lcl == surf_dest_lcl &&
  1174. IntersectRect(&rect, (LPRECT)&bd.rSrc, (LPRECT)&bd.rDest))
  1175. {
  1176. DPF_ERR("Can't stretch if source/dest rectangles overlap");
  1177. LEAVE_BOTH_NOBUSY();
  1178. return DDERR_OVERLAPPINGRECTS;
  1179. }
  1180. }
  1181. }
  1182. /*
  1183. * Get pixel-format flags for source and destination surfaces.
  1184. */
  1185. dwDDPFDestFlags = getPixelFormatPtr(surf_dest_lcl)->dwFlags;
  1186. if (surf_src_lcl != NULL)
  1187. {
  1188. dwDDPFSrcFlags = getPixelFormatPtr(surf_src_lcl)->dwFlags;
  1189. }
  1190. else
  1191. {
  1192. dwDDPFSrcFlags = 0;
  1193. }
  1194. /*
  1195. * Special Restrictions on Pixel Formats:
  1196. * -- If the surfaces have pixel formats that either are FOURCCs
  1197. * or are understood by the AlphaBlt HEL, no restrictions are
  1198. * imposed on the range of AlphaBlt features available for
  1199. * blit and fill operations. All formats that are understood
  1200. * by the HEL are listed in the PFTable array in ablthel.c.
  1201. * -- If either surface has a non-FOURCC pixel format that is not
  1202. * understood by AlphaBlt HEL, only a copy blit is permitted.
  1203. * For a copy blit, the source and dest formats are identical,
  1204. * and features such as stretching, mirroring, filtering, color
  1205. * keying, alpha blending, and ARGB scaling are not used.
  1206. */
  1207. if ((!(dwDDPFDestFlags & DDPF_FOURCC) &&
  1208. (GetSurfPFIndex(surf_dest_lcl) == PFINDEX_UNSUPPORTED)) ||
  1209. ((surf_src_lcl != NULL) && !(dwDDPFDestFlags & DDPF_FOURCC) &&
  1210. (GetSurfPFIndex(surf_src_lcl) == PFINDEX_UNSUPPORTED)))
  1211. {
  1212. LPDDPIXELFORMAT pDDPFDest = getPixelFormatPtr(surf_dest_lcl);
  1213. LPDDPIXELFORMAT pDDPFSrc = getPixelFormatPtr(surf_src_lcl);
  1214. /*
  1215. * This blit involves a non-FOURCC format that is unknown to the
  1216. * AlphaBlt HEL. In this case, we accept the blit operation only
  1217. * if it is a simple copy blit. It's okay if the rects overlap.
  1218. */
  1219. if ((surf_src_lcl == NULL) || !doPixelFormatsMatch(pDDPFDest, pDDPFSrc))
  1220. {
  1221. DPF_ERR("Only copy blits are available with specified pixel format");
  1222. LEAVE_BOTH_NOBUSY();
  1223. return DDERR_INVALIDPARAMS;
  1224. }
  1225. // Is the DDABLT_NOBLEND flag specified?
  1226. if (!(dwFlags & DDABLT_NOBLEND))
  1227. {
  1228. DPF_ERR("NOBLEND flag is required to blit with specified pixel format");
  1229. LEAVE_BOTH_NOBUSY();
  1230. return DDERR_INVALIDPARAMS;
  1231. }
  1232. // Are any inappropriate DDABLT flags set?
  1233. if (dwFlags & (DDABLT_MIRRORUPDOWN | DDABLT_MIRRORLEFTRIGHT |
  1234. DDABLT_KEYSRC | DDABLT_DEGRADEARGBSCALING |
  1235. DDABLT_FILTERENABLE | DDABLT_FILTERTRANSPBORDER))
  1236. {
  1237. DPF_ERR("Specified DDABLT flag is incompatible with pixel format");
  1238. LEAVE_BOTH_NOBUSY();
  1239. return DDERR_INVALIDPARAMS;
  1240. }
  1241. // Is stretching required for this blit?
  1242. if (sbi.src_height != sbi.dest_height || sbi.src_width != sbi.dest_width)
  1243. {
  1244. DPF_ERR("Stretching is not permitted with specified pixel format");
  1245. LEAVE_BOTH_NOBUSY();
  1246. return DDERR_INVALIDPARAMS;
  1247. }
  1248. // Are the ARGB-scaling factors disabled (i.e., set to all ones)?
  1249. if (*(LPDWORD)&ddargbScaleFactors != ~0UL)
  1250. {
  1251. DPF_ERR("ARGB scaling must be disabled with specified pixel format");
  1252. LEAVE_BOTH_NOBUSY();
  1253. return DDERR_INVALIDPARAMS;
  1254. }
  1255. }
  1256. /*
  1257. * Do source and dest rectangles lie on the same surface and overlap?
  1258. */
  1259. if (surf_src_lcl == surf_dest_lcl &&
  1260. IntersectRect(&rect, (LPRECT)&bd.rSrc, (LPRECT)&bd.rDest))
  1261. {
  1262. /*
  1263. * Yes, enforce restrictions on blits with overlapping rectangles.
  1264. */
  1265. if (!(dwFlags & DDABLT_NOBLEND))
  1266. {
  1267. DPF_ERR("Can't blit between overlapping rects unless NOBLEND flag is set");
  1268. LEAVE_BOTH_NOBUSY();
  1269. return DDERR_OVERLAPPINGRECTS;
  1270. }
  1271. if (dwFlags & (DDABLT_MIRRORUPDOWN | DDABLT_MIRRORLEFTRIGHT |
  1272. DDABLT_KEYSRC | DDABLT_DEGRADEARGBSCALING |
  1273. DDABLT_FILTERENABLE | DDABLT_FILTERTRANSPBORDER))
  1274. {
  1275. DPF_ERR("Specified flag is illegal if source/dest rectangles overlap");
  1276. LEAVE_BOTH_NOBUSY();
  1277. return DDERR_OVERLAPPINGRECTS;
  1278. }
  1279. if (dwDDPFDestFlags & DDPF_FOURCC)
  1280. {
  1281. DPF_ERR("Overlapping source/dest rectangles illegal with FOURCC surface");
  1282. LEAVE_BOTH_NOBUSY();
  1283. return DDERR_OVERLAPPINGRECTS;
  1284. }
  1285. }
  1286. /*
  1287. * Does the destination surface have a FOURCC pixel format?
  1288. */
  1289. if (dwDDPFDestFlags & DDPF_FOURCC)
  1290. {
  1291. // The DDABLT_USEFILLVALUE flag is illegal with a FOURCC dest surface.
  1292. if (dwFlags & DDABLT_USEFILLVALUE)
  1293. {
  1294. DPF_ERR("Can't use USEFILLVALUE flag with FOURCC dest surface");
  1295. LEAVE_BOTH_NOBUSY();
  1296. return DDERR_INVALIDPARAMS;
  1297. }
  1298. }
  1299. fail = FALSE; // initialize before using GETFAILCODEBLT macro
  1300. /*
  1301. * Validate source color key.
  1302. */
  1303. if (dwFlags & DDABLT_KEYSRC)
  1304. {
  1305. DDASSERT(surf_src != NULL);
  1306. // make sure we can do this
  1307. if (!(caps.dwBothCKeyCaps & DDCKEYCAPS_SRCBLT))
  1308. {
  1309. GETFAILCODEBLT(caps.dwCKeyCaps,
  1310. caps.dwHELCKeyCaps,
  1311. sbi.halonly,
  1312. sbi.helonly,
  1313. DDCKEYCAPS_SRCBLT);
  1314. if (fail)
  1315. {
  1316. DPF_ERR("KEYSRC specified, not supported");
  1317. LEAVE_BOTH_NOBUSY();
  1318. return DDERR_NOCOLORKEYHW;
  1319. }
  1320. }
  1321. if (!(surf_src_lcl->dwFlags & DDRAWISURF_HASCKEYSRCBLT) ||
  1322. (dwDDPFSrcFlags & (DDPF_FOURCC | DDPF_ALPHAPIXELS)))
  1323. {
  1324. /*
  1325. * If the src color-key flag is set but the source surface has
  1326. * no associated src color key, just clear the flag instead of
  1327. * treating this as an error.
  1328. */
  1329. dwFlags &= ~DDABLT_KEYSRC;
  1330. }
  1331. }
  1332. /*
  1333. * Validate up/down mirroring
  1334. */
  1335. if (dwFlags & DDABLT_MIRRORUPDOWN)
  1336. {
  1337. DDASSERT(surf_src != NULL);
  1338. if (!(caps.dwBothFXCaps & DDFXCAPS_BLTMIRRORUPDOWN))
  1339. {
  1340. GETFAILCODEBLT(caps.dwFXCaps,
  1341. caps.dwHELFXCaps,
  1342. sbi.halonly,
  1343. sbi.helonly,
  1344. DDFXCAPS_BLTMIRRORUPDOWN);
  1345. if (fail)
  1346. {
  1347. DPF_ERR("Mirror up/down specified, not supported");
  1348. LEAVE_BOTH_NOBUSY();
  1349. return DDERR_NOMIRRORHW;
  1350. }
  1351. }
  1352. }
  1353. /*
  1354. * Validate left/right mirroring
  1355. */
  1356. if (dwFlags & DDABLT_MIRRORLEFTRIGHT)
  1357. {
  1358. DDASSERT(surf_src != NULL);
  1359. if (!(caps.dwBothFXCaps & DDFXCAPS_BLTMIRRORLEFTRIGHT))
  1360. {
  1361. GETFAILCODEBLT(caps.dwFXCaps,
  1362. caps.dwHELFXCaps,
  1363. sbi.halonly,
  1364. sbi.helonly,
  1365. DDFXCAPS_BLTMIRRORLEFTRIGHT);
  1366. if (fail)
  1367. {
  1368. DPF_ERR("Mirror left/right specified, not supported");
  1369. LEAVE_BOTH_NOBUSY();
  1370. return DDERR_NOMIRRORHW;
  1371. }
  1372. }
  1373. }
  1374. /*
  1375. * Does destination surface have a palette-indexed pixel format?
  1376. */
  1377. if (dwDDPFDestFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
  1378. DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8))
  1379. {
  1380. /*
  1381. * Is this a blit or a color-fill operation?
  1382. */
  1383. if (surf_src_lcl == NULL)
  1384. {
  1385. /*
  1386. * Color-Fill: Palette-indexed dest is illegal without USEFILLVALUE flag.
  1387. */
  1388. if (!(dwFlags & DDABLT_USEFILLVALUE))
  1389. {
  1390. DPF_ERR("USEFILLVALUE flag required to fill palette-indexed dest surface");
  1391. LEAVE_BOTH_NOBUSY();
  1392. return DDERR_INVALIDPARAMS;
  1393. }
  1394. }
  1395. else
  1396. {
  1397. /*
  1398. * Blit: Destination surface is palette-indexed, so we require source
  1399. * surface to have same pixel format as destination. (Note that this
  1400. * also makes color fills illegal to palette-indexed dest surfaces.)
  1401. */
  1402. if (dwDDPFSrcFlags != dwDDPFDestFlags)
  1403. {
  1404. DPF_ERR("If dest is palette-indexed, source must have same pixel format");
  1405. LEAVE_BOTH_NOBUSY();
  1406. return DDERR_INVALIDPARAMS;
  1407. }
  1408. if (dwFlags & (DDABLT_FILTERENABLE | DDABLT_FILTERTRANSPBORDER))
  1409. {
  1410. DPF_ERR("Illegal to specify filtering with palette-indexed destination");
  1411. LEAVE_BOTH_NOBUSY();
  1412. return DDERR_INVALIDPARAMS;
  1413. }
  1414. if (*(LPDWORD)&ddargbScaleFactors != ~0UL)
  1415. {
  1416. DPF_ERR("Illegal to enable ARGB scaling with palette-indexed destination");
  1417. LEAVE_BOTH_NOBUSY();
  1418. return DDERR_INVALIDPARAMS;
  1419. }
  1420. /*
  1421. * If source and dest surfaces both have attached palettes, we require that
  1422. * they reference the same palette object. In a later release, we may relax
  1423. * this requirement in order to support color-table conversion or dithering.
  1424. */
  1425. if ((surf_src_lcl->lpDDPalette != NULL) &&
  1426. (surf_dest_lcl->lpDDPalette != NULL) &&
  1427. (surf_src_lcl->lpDDPalette->lpLcl->lpGbl->lpColorTable !=
  1428. surf_dest_lcl->lpDDPalette->lpLcl->lpGbl->lpColorTable))
  1429. {
  1430. DPF_ERR("If source and dest surfaces both have palettes, must be same palette");
  1431. LEAVE_BOTH_NOBUSY();
  1432. return DDERR_INVALIDPARAMS;
  1433. }
  1434. }
  1435. }
  1436. else if (dwDDPFSrcFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
  1437. DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8) &&
  1438. (surf_src_lcl->lpDDPalette == NULL ||
  1439. surf_src_lcl->lpDDPalette->lpLcl->lpGbl->lpColorTable == NULL))
  1440. {
  1441. /*
  1442. * Conversion of source pixels to destination pixel format is
  1443. * impossible because source surface has no attached palette.
  1444. */
  1445. DPF_ERR( "No palette associated with palette-indexed source surface" );
  1446. LEAVE_BOTH_NOBUSY();
  1447. return DDERR_NOPALETTEATTACHED;
  1448. }
  1449. /*
  1450. * We do no ARGB scaling if NOBLEND flag is set.
  1451. */
  1452. if (dwFlags & DDABLT_NOBLEND)
  1453. {
  1454. if (dwFlags & DDABLT_DEGRADEARGBSCALING)
  1455. {
  1456. DPF_ERR("NOBLEND and DEGRADEARGBSCALING flags are incompatible");
  1457. LEAVE_BOTH();
  1458. return DDERR_INVALIDPARAMS;
  1459. }
  1460. if (surf_src != NULL && *(LPDWORD)&ddargbScaleFactors != ~0UL)
  1461. {
  1462. DPF_ERR("ARGB scaling of source surface illegal if NOBLEND flag is set");
  1463. LEAVE_BOTH_NOBUSY();
  1464. return DDERR_INVALIDPARAMS;
  1465. }
  1466. }
  1467. else if ((dwDDPFSrcFlags | dwDDPFDestFlags) & DDPF_ALPHAPIXELS)
  1468. {
  1469. /*
  1470. * We've been asked to perform a blit or fill that requires blending
  1471. * with the alpha-channel information in the pixel formats for one
  1472. * or both surfaces. Verify that the driver supports this.
  1473. */
  1474. if (!(caps.dwBothFXCaps & DDFXCAPS_BLTALPHA))
  1475. {
  1476. GETFAILCODEBLT(caps.dwFXCaps,
  1477. caps.dwHELFXCaps,
  1478. sbi.halonly,
  1479. sbi.helonly,
  1480. DDFXCAPS_BLTALPHA);
  1481. if (fail)
  1482. {
  1483. DPF_ERR("Alpha-blended blit requested, but not supported");
  1484. LEAVE_BOTH_NOBUSY();
  1485. return DDERR_NOALPHAHW;
  1486. }
  1487. }
  1488. /*
  1489. * Verify that the driver supports surfaces whose pixel
  1490. * formats contain an alpha-channel component.
  1491. */
  1492. if (!(caps.dwBothAlphaCaps & DDALPHACAPS_BLTALPHAPIXELS))
  1493. {
  1494. GETFAILCODEBLT(caps.dwAlphaCaps,
  1495. caps.dwHELAlphaCaps,
  1496. sbi.halonly,
  1497. sbi.helonly,
  1498. DDALPHACAPS_BLTALPHAPIXELS);
  1499. if (fail)
  1500. {
  1501. DPF_ERR("Alpha pixel format specified, but not supported");
  1502. LEAVE_BOTH_NOBUSY();
  1503. return DDERR_NOALPHAHW;
  1504. }
  1505. }
  1506. /*
  1507. * Does dest surface have alpha channel?
  1508. */
  1509. if (dwDDPFDestFlags & DDPF_ALPHAPIXELS)
  1510. {
  1511. /*
  1512. * Verify that destination surface has a premultiplied-
  1513. * alpha pixel format. Non-premultiplied alpha won't do.
  1514. */
  1515. if (!(dwDDPFDestFlags & DDPF_ALPHAPREMULT))
  1516. {
  1517. DPF_ERR("Illegal to blend with non-premultiplied alpha in dest surface");
  1518. LEAVE_BOTH_NOBUSY();
  1519. return DDERR_INVALIDPARAMS;
  1520. }
  1521. /*
  1522. * Verify that driver can handle premultiplied-alpha pixel format.
  1523. * (Dest surface is not allowed to be non-premultiplied alpha.)
  1524. */
  1525. if (!(caps.dwBothAlphaCaps & DDALPHACAPS_BLTPREMULT))
  1526. {
  1527. GETFAILCODEBLT(caps.dwAlphaCaps,
  1528. caps.dwHELAlphaCaps,
  1529. sbi.halonly,
  1530. sbi.helonly,
  1531. DDALPHACAPS_BLTPREMULT);
  1532. if (fail)
  1533. {
  1534. DPF_ERR("No driver support for premultiplied alpha");
  1535. LEAVE_BOTH_NOBUSY();
  1536. return DDERR_NOALPHAHW;
  1537. }
  1538. }
  1539. }
  1540. /*
  1541. * Does source surface have alpha channel?
  1542. */
  1543. if (dwDDPFSrcFlags & DDPF_ALPHAPIXELS)
  1544. {
  1545. /*
  1546. * Are we asking the driver to handle both ARGB scaling and a
  1547. * source alpha channel when it can't do both at the same time?
  1548. */
  1549. if (*(LPDWORD)&ddargbScaleFactors != ~0 &&
  1550. !(caps.dwBothAlphaCaps & DDALPHACAPS_BLTALPHAANDARGBSCALING) &&
  1551. !(dwFlags & DDABLT_DEGRADEARGBSCALING))
  1552. {
  1553. if (!(caps.dwBothAlphaCaps & DDALPHACAPS_BLTALPHAANDARGBSCALING))
  1554. {
  1555. GETFAILCODEBLT(caps.dwAlphaCaps,
  1556. caps.dwHELAlphaCaps,
  1557. sbi.halonly,
  1558. sbi.helonly,
  1559. DDALPHACAPS_BLTALPHAANDARGBSCALING);
  1560. if (fail)
  1561. {
  1562. DPF_ERR("No driver support for alpha channel and ARGB scaling in same blit");
  1563. LEAVE_BOTH_NOBUSY();
  1564. return DDERR_NOALPHAHW;
  1565. }
  1566. }
  1567. }
  1568. /*
  1569. * Are color components in pixel format premultiplied by the
  1570. * alpha component or not? In either case, verify that the
  1571. * driver supports the specified alpha format.
  1572. */
  1573. if (dwDDPFSrcFlags & DDPF_ALPHAPREMULT)
  1574. {
  1575. if (!(caps.dwBothAlphaCaps & DDALPHACAPS_BLTPREMULT))
  1576. {
  1577. GETFAILCODEBLT(caps.dwAlphaCaps,
  1578. caps.dwHELAlphaCaps,
  1579. sbi.halonly,
  1580. sbi.helonly,
  1581. DDALPHACAPS_BLTPREMULT);
  1582. if (fail)
  1583. {
  1584. DPF_ERR("No driver support for premultiplied alpha");
  1585. LEAVE_BOTH_NOBUSY();
  1586. return DDERR_NOALPHAHW;
  1587. }
  1588. }
  1589. }
  1590. else
  1591. {
  1592. DWORD val = 0x01010101UL*ddargbScaleFactors.alpha;
  1593. if (!(caps.dwBothAlphaCaps & DDALPHACAPS_BLTNONPREMULT))
  1594. {
  1595. GETFAILCODEBLT(caps.dwAlphaCaps,
  1596. caps.dwHELAlphaCaps,
  1597. sbi.halonly,
  1598. sbi.helonly,
  1599. DDALPHACAPS_BLTNONPREMULT);
  1600. if (fail)
  1601. {
  1602. DPF_ERR("No driver support for non-premultiplied alpha");
  1603. LEAVE_BOTH_NOBUSY();
  1604. return DDERR_NOALPHAHW;
  1605. }
  1606. }
  1607. /*
  1608. * We allow only one-factor ARGB scaling with a source
  1609. * surface that has a non-premultiplied alpha pixel format.
  1610. * The following code enforces this rule.
  1611. */
  1612. if (*(LPDWORD)&ddargbScaleFactors != val)
  1613. {
  1614. if (dwFlags & DDABLT_DEGRADEARGBSCALING)
  1615. {
  1616. *(LPDWORD)&ddargbScaleFactors = val;
  1617. }
  1618. else
  1619. {
  1620. DPF_ERR("Can't do 2 or 4-mult ARGB scaling with non-premultiplied alpha surface");
  1621. LEAVE_BOTH_NOBUSY();
  1622. return DDERR_INVALIDPARAMS;
  1623. }
  1624. }
  1625. }
  1626. }
  1627. }
  1628. /*
  1629. * If filtering is to be explicitly enabled or disabled, verify that
  1630. * the hardware driver is capable of performing the blit as requested.
  1631. */
  1632. if (dwFlags & (DDABLT_FILTERENABLE | DDABLT_FILTERDISABLE | DDABLT_FILTERTRANSPBORDER))
  1633. {
  1634. /*
  1635. * Is driver capable of doing any kind of filtering at all?
  1636. */
  1637. if (!(caps.dwBothFXCaps & DDFXCAPS_BLTFILTER))
  1638. {
  1639. GETFAILCODEBLT(caps.dwFXCaps,
  1640. caps.dwHELFXCaps,
  1641. sbi.halonly,
  1642. sbi.helonly,
  1643. DDFXCAPS_BLTFILTER);
  1644. if (fail)
  1645. {
  1646. DPF_ERR("No driver support for filtered blit");
  1647. LEAVE_BOTH_NOBUSY();
  1648. return DDERR_NOALPHAHW;
  1649. }
  1650. }
  1651. if (!(~dwFlags & (DDABLT_FILTERENABLE | DDABLT_FILTERDISABLE)))
  1652. {
  1653. DPF_ERR("Illegal to both enable and disable filtering");
  1654. LEAVE_BOTH_NOBUSY();
  1655. return DDERR_INVALIDPARAMS;
  1656. }
  1657. if (!(~dwFlags & (DDABLT_FILTERTRANSPBORDER | DDABLT_FILTERDISABLE)))
  1658. {
  1659. DPF_ERR("Illegal to set FILTERTRANSPBORDER if filtering is explicitly disabled");
  1660. LEAVE_BOTH_NOBUSY();
  1661. return DDERR_INVALIDPARAMS;
  1662. }
  1663. if ((dwFlags & DDABLT_FILTERENABLE) &&
  1664. !(caps.dwBothFilterCaps & DDFILTCAPS_BLTQUALITYFILTER))
  1665. {
  1666. GETFAILCODEBLT(caps.dwFilterCaps,
  1667. caps.dwHELFilterCaps,
  1668. sbi.halonly,
  1669. sbi.helonly,
  1670. DDFILTCAPS_BLTQUALITYFILTER);
  1671. if (fail)
  1672. {
  1673. DPF_ERR("No driver support for filtered blit");
  1674. LEAVE_BOTH_NOBUSY();
  1675. return DDERR_NOALPHAHW;
  1676. }
  1677. }
  1678. if ((dwFlags & DDABLT_FILTERDISABLE) &&
  1679. !(caps.dwBothFilterCaps & DDFILTCAPS_BLTCANDISABLEFILTER))
  1680. {
  1681. GETFAILCODEBLT(caps.dwFilterCaps,
  1682. caps.dwHELFilterCaps,
  1683. sbi.halonly,
  1684. sbi.helonly,
  1685. DDFILTCAPS_BLTCANDISABLEFILTER);
  1686. if (fail)
  1687. {
  1688. DPF_ERR("Driver cannot disable filtering for blits");
  1689. LEAVE_BOTH_NOBUSY();
  1690. return DDERR_NOALPHAHW;
  1691. }
  1692. }
  1693. if ((dwFlags & DDABLT_FILTERTRANSPBORDER) &&
  1694. !(caps.dwBothFilterCaps & DDFILTCAPS_BLTTRANSPBORDER))
  1695. {
  1696. GETFAILCODEBLT(caps.dwFilterCaps,
  1697. caps.dwHELFilterCaps,
  1698. sbi.halonly,
  1699. sbi.helonly,
  1700. DDFILTCAPS_BLTTRANSPBORDER);
  1701. if (fail)
  1702. {
  1703. DPF_ERR("Driver cannot filter with transparent border");
  1704. LEAVE_BOTH_NOBUSY();
  1705. return DDERR_NOALPHAHW;
  1706. }
  1707. }
  1708. }
  1709. /*
  1710. * Validate ARGB scaling factors.
  1711. */
  1712. if (!(dwFlags & DDABLT_DEGRADEARGBSCALING) &&
  1713. *(LPDWORD)&ddargbScaleFactors != ~0UL &&
  1714. !(surf_src_lcl == NULL && ddargbScaleFactors.alpha == 255))
  1715. {
  1716. /*
  1717. * Some kind of ARGB scaling is specified. Can the driver
  1718. * do any kind of alpha blending at all?
  1719. */
  1720. if (!(caps.dwBothFXCaps & DDFXCAPS_BLTALPHA))
  1721. {
  1722. GETFAILCODEBLT(caps.dwFXCaps,
  1723. caps.dwHELFXCaps,
  1724. sbi.halonly,
  1725. sbi.helonly,
  1726. DDFXCAPS_BLTALPHA);
  1727. if (fail)
  1728. {
  1729. DPF_ERR("ARGB scaling requested for blit, but not supported");
  1730. LEAVE_BOTH_NOBUSY();
  1731. return DDERR_NOALPHAHW;
  1732. }
  1733. }
  1734. /*
  1735. * We permit a color factor to be bigger than the alpha
  1736. * factor only if the hardware uses saturated arithmetic
  1737. * to prevent the calculated color value from overflowing.
  1738. */
  1739. if (!(dwFlags & DDABLT_NOBLEND) &&
  1740. (ddargbScaleFactors.red > ddargbScaleFactors.alpha ||
  1741. ddargbScaleFactors.green > ddargbScaleFactors.alpha ||
  1742. ddargbScaleFactors.blue > ddargbScaleFactors.alpha))
  1743. {
  1744. /*
  1745. * Driver must be capable of doing saturated arithmetic.
  1746. */
  1747. if (!(caps.dwBothAlphaCaps & DDALPHACAPS_BLTSATURATE))
  1748. {
  1749. GETFAILCODEBLT(caps.dwAlphaCaps,
  1750. caps.dwHELAlphaCaps,
  1751. sbi.halonly,
  1752. sbi.helonly,
  1753. DDALPHACAPS_BLTSATURATE);
  1754. if (fail)
  1755. {
  1756. // Neither the H/W driver nor HEL can handle it, so fail.
  1757. DPF_ERR("Driver can't do saturated arithmetic during alpha blending");
  1758. LEAVE_BOTH_NOBUSY();
  1759. return DDERR_NOALPHAHW;
  1760. }
  1761. }
  1762. }
  1763. /*
  1764. * Is this an alpha-blit or an alpha-fill operation?
  1765. */
  1766. if (surf_src_lcl == NULL)
  1767. {
  1768. /*
  1769. * This is an alpha fill. Can the driver handle it?
  1770. */
  1771. if (!(caps.dwBothAlphaCaps & DDALPHACAPS_BLTALPHAFILL))
  1772. {
  1773. GETFAILCODEBLT(caps.dwAlphaCaps,
  1774. caps.dwHELAlphaCaps,
  1775. sbi.halonly,
  1776. sbi.helonly,
  1777. DDALPHACAPS_BLTALPHAFILL);
  1778. if (fail)
  1779. {
  1780. // Neither the H/W driver nor HEL can handle it, so fail.
  1781. DPF_ERR("Driver can't do alpha-blended color-fill operation");
  1782. LEAVE_BOTH_NOBUSY();
  1783. return DDERR_NOALPHAHW;
  1784. }
  1785. }
  1786. }
  1787. else
  1788. {
  1789. /*
  1790. * Alpha blit. Can the driver handle any ARGB scaling at all?
  1791. */
  1792. #define ARGBSCALINGBITS \
  1793. (DDALPHACAPS_BLTARGBSCALE1F | DDALPHACAPS_BLTARGBSCALE2F | DDALPHACAPS_BLTARGBSCALE4F)
  1794. if (!(caps.dwBothAlphaCaps & ARGBSCALINGBITS))
  1795. {
  1796. GETFAILCODEBLT(caps.dwAlphaCaps,
  1797. caps.dwHELAlphaCaps,
  1798. sbi.halonly,
  1799. sbi.helonly,
  1800. ARGBSCALINGBITS);
  1801. if (fail)
  1802. {
  1803. // Neither the H/W driver nor HEL can handle it, so fail.
  1804. DPF_ERR("Driver can't handle any ARGB scaling at all");
  1805. LEAVE_BOTH_NOBUSY();
  1806. return DDERR_NOALPHAHW;
  1807. }
  1808. }
  1809. #undef ARGBSCALINGBITS
  1810. if (ddargbScaleFactors.red != ddargbScaleFactors.green ||
  1811. ddargbScaleFactors.red != ddargbScaleFactors.blue)
  1812. {
  1813. /*
  1814. * Driver must be capable of doing 4-factor ARGB scaling.
  1815. */
  1816. if (!(caps.dwBothAlphaCaps & DDALPHACAPS_BLTARGBSCALE4F))
  1817. {
  1818. GETFAILCODEBLT(caps.dwAlphaCaps,
  1819. caps.dwHELAlphaCaps,
  1820. sbi.halonly,
  1821. sbi.helonly,
  1822. DDALPHACAPS_BLTARGBSCALE4F);
  1823. if (fail)
  1824. {
  1825. // Neither the H/W driver nor HEL can handle it, so fail.
  1826. DPF_ERR("Driver can't handle 4-factor ARGB scaling");
  1827. LEAVE_BOTH_NOBUSY();
  1828. return DDERR_NOALPHAHW;
  1829. }
  1830. }
  1831. }
  1832. else if (ddargbScaleFactors.red != ddargbScaleFactors.alpha)
  1833. {
  1834. /*
  1835. * Driver must be capable of doing 2-factor ARGB scaling.
  1836. */
  1837. if (!(caps.dwBothAlphaCaps & (DDALPHACAPS_BLTARGBSCALE2F |
  1838. DDALPHACAPS_BLTARGBSCALE4F)))
  1839. {
  1840. GETFAILCODEBLT(caps.dwAlphaCaps,
  1841. caps.dwHELAlphaCaps,
  1842. sbi.halonly,
  1843. sbi.helonly,
  1844. DDALPHACAPS_BLTARGBSCALE2F |
  1845. DDALPHACAPS_BLTARGBSCALE4F);
  1846. if (fail)
  1847. {
  1848. // Neither the H/W driver nor HEL can handle it, so fail.
  1849. DPF_ERR("Driver can't handle 2-factor ARGB scaling");
  1850. LEAVE_BOTH_NOBUSY();
  1851. return DDERR_NOALPHAHW;
  1852. }
  1853. }
  1854. }
  1855. }
  1856. }
  1857. }
  1858. EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  1859. {
  1860. DPF_ERR("Exception encountered validating parameters");
  1861. LEAVE_BOTH_NOBUSY();
  1862. return DDERR_INVALIDPARAMS;
  1863. }
  1864. DDASSERT(!(sbi.halonly && sbi.helonly));
  1865. /*
  1866. * Are we permitted to degrade the specified ARGB-scaling operation
  1867. * to one the driver can handle?
  1868. */
  1869. if (dwFlags & DDABLT_DEGRADEARGBSCALING)
  1870. {
  1871. DWORD dwFXCaps, dwAlphaCaps;
  1872. // Get the caps for the selected driver.
  1873. dwFXCaps = (sbi.helonly) ? caps.dwHELFXCaps : caps.dwFXCaps;
  1874. dwAlphaCaps = (sbi.helonly) ? caps.dwHELAlphaCaps : caps.dwAlphaCaps;
  1875. if (!(dwFXCaps & DDFXCAPS_BLTALPHA))
  1876. {
  1877. /*
  1878. * The driver should have done this anyway, but just in case...
  1879. */
  1880. dwAlphaCaps = 0;
  1881. }
  1882. /*
  1883. * Is this a blit or a fill operation?
  1884. */
  1885. if (surf_src_lcl == NULL)
  1886. {
  1887. /*
  1888. * This is a fill -- and possibly an alpha fill.
  1889. */
  1890. if (!(dwAlphaCaps & DDALPHACAPS_BLTALPHAFILL))
  1891. {
  1892. /*
  1893. * The driver can't do an alpha fill, so we'll ask
  1894. * it to do just a simple color fill instead.
  1895. */
  1896. ddargbScaleFactors.alpha = 255;
  1897. }
  1898. }
  1899. else
  1900. {
  1901. /*
  1902. * This is a blit. What are the driver's ARGB-scaling capabilities?
  1903. */
  1904. if (!(dwAlphaCaps & (DDALPHACAPS_BLTARGBSCALE1F |
  1905. DDALPHACAPS_BLTARGBSCALE2F |
  1906. DDALPHACAPS_BLTARGBSCALE4F)))
  1907. {
  1908. /*
  1909. * Driver can't do any kind of ARGB scaling at all, so just
  1910. * disable ARGB scaling by setting all four factors to 255.
  1911. */
  1912. *(LPDWORD)&ddargbScaleFactors = ~0UL;
  1913. }
  1914. else if (!(dwAlphaCaps & (DDALPHACAPS_BLTARGBSCALE2F |
  1915. DDALPHACAPS_BLTARGBSCALE4F)))
  1916. {
  1917. /*
  1918. * The driver can do only 1-factor ARGB scaling, so set the
  1919. * three color factors to the same value as the alpha factor.
  1920. */
  1921. *(LPDWORD)&ddargbScaleFactors = 0x01010101UL*ddargbScaleFactors.alpha;
  1922. }
  1923. else if (!(dwAlphaCaps & DDALPHACAPS_BLTARGBSCALE4F))
  1924. {
  1925. /*
  1926. * Driver can do only 2-factor ARGB scaling, so make sure
  1927. * all three color factors are set to the same value.
  1928. */
  1929. if (ddargbScaleFactors.red != ddargbScaleFactors.green ||
  1930. ddargbScaleFactors.red != ddargbScaleFactors.blue)
  1931. {
  1932. /*
  1933. * Set all three color factors to value F, which is the
  1934. * weighted average of their specified values (Fr,Fg,Fb):
  1935. * F = .299*Fr + .587*Fg + .114*Fb
  1936. */
  1937. DWORD F = 19595UL*ddargbScaleFactors.red +
  1938. 38470UL*ddargbScaleFactors.green +
  1939. 7471UL*ddargbScaleFactors.blue;
  1940. ddargbScaleFactors.red =
  1941. ddargbScaleFactors.green =
  1942. ddargbScaleFactors.blue = (BYTE)(F >> 16);
  1943. }
  1944. }
  1945. if (!(dwAlphaCaps & DDALPHACAPS_BLTALPHAANDARGBSCALING))
  1946. {
  1947. /*
  1948. * Driver can't handle both a source alpha channel and ARGB scaling
  1949. * factors in the same blit operation, so just turn off ARGB scaling.
  1950. */
  1951. *(LPDWORD)&ddargbScaleFactors = ~0UL;
  1952. }
  1953. }
  1954. /*
  1955. * Can driver do saturated arithmetic for alpha blit or alpha fill?
  1956. */
  1957. if (!(dwAlphaCaps & DDALPHACAPS_BLTSATURATE))
  1958. {
  1959. /*
  1960. * Driver can't do saturated arithmetic, so make sure no
  1961. * no color factors exceed the value of the alpha factor.
  1962. */
  1963. if (ddargbScaleFactors.red > ddargbScaleFactors.alpha)
  1964. {
  1965. ddargbScaleFactors.red = ddargbScaleFactors.alpha;
  1966. }
  1967. if (ddargbScaleFactors.green > ddargbScaleFactors.alpha)
  1968. {
  1969. ddargbScaleFactors.green = ddargbScaleFactors.alpha;
  1970. }
  1971. if (ddargbScaleFactors.blue > ddargbScaleFactors.alpha)
  1972. {
  1973. ddargbScaleFactors.blue = ddargbScaleFactors.alpha;
  1974. }
  1975. }
  1976. }
  1977. /*
  1978. * Tell the driver to do the blit.
  1979. */
  1980. TRY
  1981. {
  1982. /*
  1983. * Finish loading blit data for HAL callback.
  1984. */
  1985. bd.lpDD = pdrv;
  1986. bd.lpDDDestSurface = surf_dest_lcl;
  1987. bd.lpDDSrcSurface = surf_src_lcl;
  1988. bd.ddargbScaleFactors = ddargbScaleFactors;
  1989. bd.bltFX.dwSize = sizeof( DDBLTFX );
  1990. /*
  1991. * For the AlphaBlt callback, the rOrigDest and rOrigSrc members
  1992. * ALWAYS contain the original dest and source rects.
  1993. */
  1994. bd.rOrigDest = bd.rDest;
  1995. bd.rOrigSrc = bd.rSrc;
  1996. /*
  1997. * The only AlphaBlt API flags that are propagated to the
  1998. * driver are those that have no Blt API equivalents.
  1999. */
  2000. bd.dwAFlags = dwFlags & (DDABLT_FILTERENABLE | DDABLT_FILTERDISABLE |
  2001. DDABLT_FILTERTRANSPBORDER | DDABLT_NOBLEND);
  2002. /*
  2003. * This flag tells the driver that it's a source-over-dest operation.
  2004. * This flag is never passed by the Blt API, so drivers which have a
  2005. * unified DDI can distinguish who called them
  2006. */
  2007. bd.dwAFlags |= DDABLT_SRCOVERDEST;
  2008. if (dwFlags & DDABLT_KEYSRC) // source color key?
  2009. {
  2010. bd.dwFlags |= DDBLT_KEYSRCOVERRIDE;
  2011. bd.bltFX.ddckSrcColorkey = surf_src_lcl->ddckCKSrcBlt;
  2012. }
  2013. if (dwFlags & (DDABLT_MIRRORLEFTRIGHT | DDABLT_MIRRORUPDOWN))
  2014. {
  2015. bd.dwFlags |= DDBLT_DDFX;
  2016. if (dwFlags & DDABLT_MIRRORLEFTRIGHT) //left-right mirroring?
  2017. {
  2018. bd.bltFX.dwDDFX |= DDBLTFX_MIRRORLEFTRIGHT;
  2019. }
  2020. if (dwFlags & DDABLT_MIRRORUPDOWN) // up-down mirroring?
  2021. {
  2022. bd.bltFX.dwDDFX |= DDBLTFX_MIRRORUPDOWN;
  2023. }
  2024. }
  2025. /*
  2026. * If the specified blit operation can be handled by the Blt HAL
  2027. * callback instead of by the AlphaBlt HAL callback, should it
  2028. * treat the blit as a color-fill or a source-copy operation?
  2029. */
  2030. if (surf_src_lcl != NULL)
  2031. {
  2032. //it's a srccopy. Set flags appropriately
  2033. bd.dwFlags |= DDBLT_ROP;
  2034. bd.bltFX.dwROP = SRCCOPY;
  2035. bd.dwROPFlags = ROP_HAS_SOURCE; // 0x00000001
  2036. }
  2037. else
  2038. {
  2039. // This is a fill operation of some kind.
  2040. if (dwFlags & DDABLT_USEFILLVALUE)
  2041. {
  2042. HRESULT hres;
  2043. // The client specified a fill value in the dest pixel format.
  2044. bd.bltFX.dwFillColor = dwFillValue;
  2045. bd.dwFlags |= DDBLT_COLORFILL;
  2046. }
  2047. else if ((bd.ddargbScaleFactors.alpha == 255) || (dwFlags & DDABLT_NOBLEND))
  2048. {
  2049. // The client specified an alpha fill, but no alpha blending is
  2050. // required, so we can replace it with a simple color fill.
  2051. // convert the ARGB value to a physcolor:
  2052. HRESULT hres = ConvertToPhysColor(
  2053. surf_dest_lcl,
  2054. &bd.ddargbScaleFactors,
  2055. &bd.bltFX.dwFillColor);
  2056. // Make sure this is not a FOURCC or some other funny pixel format.
  2057. if (hres == DD_OK)
  2058. {
  2059. bd.dwFlags |= DDBLT_COLORFILL;
  2060. }
  2061. }
  2062. }
  2063. #ifdef WINNT
  2064. // Did the mode change since ENTER_DDRAW?
  2065. if (DdQueryDisplaySettingsUniqueness() != uDisplaySettingsUnique)
  2066. {
  2067. // mode changed, don't do the blt
  2068. DPF_ERR("Mode changed between ENTER_DDRAW and HAL call");
  2069. LEAVE_BOTH_NOBUSY()
  2070. return DDERR_SURFACELOST;
  2071. }
  2072. #endif
  2073. #if defined(WIN95)
  2074. /*
  2075. * Some drivers (like S3) do stuff in their BeginAccess call
  2076. * that screws up stuff that they did in their DDHAL Lock Call.
  2077. *
  2078. * Exclusion needs to happen BEFORE the lock call to prevent this.
  2079. *
  2080. */
  2081. if (surf_dest_lcl->lpDDClipper != NULL)
  2082. {
  2083. /*
  2084. * exclude the mouse cursor.
  2085. *
  2086. * we only need to do this for the windows display driver
  2087. *
  2088. * we only need to do this if we are blitting to or from the
  2089. * primary surface.
  2090. *
  2091. * we only do this in the clipping case, we figure if the
  2092. * app cares enough to not scribble all over other windows
  2093. * he also cares enough to not to wipe out the cursor.
  2094. *
  2095. * we only need to do this if the driver is using a
  2096. * software cursor.
  2097. *
  2098. * NOTE
  2099. * we should check and only do this on the primary?
  2100. * we should make sure the clipper is window based?
  2101. * we should check for the source being the primary?
  2102. *
  2103. */
  2104. if ((pdrv->dwFlags & DDRAWI_DISPLAYDRV) && pdrv->dwPDevice &&
  2105. !(*pdrv->lpwPDeviceFlags & HARDWARECURSOR) &&
  2106. (surf_dest->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE) )
  2107. {
  2108. if (lpDDDestSurface == lpDDSrcSurface)
  2109. {
  2110. RECTL rcl;
  2111. UnionRect((RECT*)&rcl, (RECT*)&bd.rDest, (RECT*)&bd.rSrc);
  2112. DD16_Exclude(pdrv->dwPDevice, &rcl);
  2113. }
  2114. else
  2115. {
  2116. DD16_Exclude(pdrv->dwPDevice, &bd.rDest);
  2117. }
  2118. }
  2119. }
  2120. #endif
  2121. #ifdef WINNT
  2122. get_clipping_info:
  2123. #endif
  2124. /*
  2125. * Determine clipping region for destination surface.
  2126. */
  2127. {
  2128. LPDIRECTDRAWCLIPPER pClipper;
  2129. RECT rcDestSurf;
  2130. pRgn = (LPRGNDATA)&myRgnBuffer; // this buffer's probably big enough
  2131. pClipper = (LPDIRECTDRAWCLIPPER)surf_dest_lcl->lpSurfMore->lpDDIClipper;
  2132. SetRect(&rcDestSurf, 0, 0, surf_dest->wWidth, surf_dest->wHeight);
  2133. if (pClipper == NULL)
  2134. {
  2135. /*
  2136. * The destination surface has no attached clipper.
  2137. * Set the clip region to a single rectangle the
  2138. * width and height of the primary surface.
  2139. */
  2140. pRgn->rdh.nCount = 1; // default = a single clip rect
  2141. memcpy((LPRECT)&pRgn->Buffer, &rcDestSurf, sizeof(RECT));
  2142. /*
  2143. * Add a rect to the region list if this is a managed surface
  2144. */
  2145. if(IsD3DManaged(surf_dest_lcl))
  2146. {
  2147. LPREGIONLIST lpRegionList = surf_dest_lcl->lpSurfMore->lpRegionList;
  2148. if(lpDestRect)
  2149. {
  2150. if(lpRegionList->rdh.nCount != NUM_RECTS_IN_REGIONLIST)
  2151. {
  2152. lpRegionList->rect[(lpRegionList->rdh.nCount)++] = bd.rDest;
  2153. lpRegionList->rdh.nRgnSize += sizeof(RECT);
  2154. if(bd.rDest.left < lpRegionList->rdh.rcBound.left)
  2155. lpRegionList->rdh.rcBound.left = bd.rDest.left;
  2156. if(bd.rDest.right > lpRegionList->rdh.rcBound.right)
  2157. lpRegionList->rdh.rcBound.right = bd.rDest.right;
  2158. if(bd.rDest.top < lpRegionList->rdh.rcBound.top)
  2159. lpRegionList->rdh.rcBound.top = bd.rDest.top;
  2160. if(bd.rDest.bottom > lpRegionList->rdh.rcBound.bottom)
  2161. lpRegionList->rdh.rcBound.bottom = bd.rDest.bottom;
  2162. }
  2163. }
  2164. else
  2165. {
  2166. /* Mark everything dirty */
  2167. lpRegionList->rdh.nCount = NUM_RECTS_IN_REGIONLIST;
  2168. }
  2169. }
  2170. }
  2171. else
  2172. {
  2173. DWORD rgnSize = 0;
  2174. LPDDRAWI_DIRECTDRAW_GBL pdrv = surf_dest_lcl->lpGbl->lpDD;
  2175. /*
  2176. * This surface has an attached clipper. Get the clip list.
  2177. */
  2178. ddrval = InternalGetClipList(pClipper,
  2179. &rcDestSurf,
  2180. NULL, // we just want rgnSize
  2181. &rgnSize,
  2182. pdrv);
  2183. if (ddrval != DD_OK)
  2184. {
  2185. DPF_ERR("Couldn't get size of clip region");
  2186. LEAVE_BOTH_NOBUSY();
  2187. return DDERR_GENERIC;
  2188. }
  2189. if (rgnSize > sizeof(myRgnBuffer))
  2190. {
  2191. /*
  2192. * Statically allocated region buffer isn't big enough.
  2193. * Need to dynamically allocate a bigger buffer.
  2194. */
  2195. pRgn = (LPRGNDATA)MemAlloc(rgnSize);
  2196. if (!pRgn)
  2197. {
  2198. // couldn't allocate memory for clip region
  2199. DPF_ERR("Can't allocate memory to buffer clip region");
  2200. LEAVE_BOTH_NOBUSY();
  2201. return DDERR_OUTOFMEMORY;
  2202. }
  2203. }
  2204. ddrval = InternalGetClipList(pClipper,
  2205. &rcDestSurf,
  2206. pRgn,
  2207. &rgnSize,
  2208. pdrv);
  2209. if (ddrval != DD_OK)
  2210. {
  2211. // can't get clip region
  2212. if (pRgn != (LPRGNDATA)&myRgnBuffer)
  2213. {
  2214. MemFree(pRgn);
  2215. }
  2216. DPF_ERR("Can't get dest clip region");
  2217. LEAVE_BOTH_NOBUSY();
  2218. return DDERR_GENERIC;
  2219. }
  2220. if(IsD3DManaged(surf_dest_lcl))
  2221. {
  2222. /* We don't want to deal with this mess, so mark everything dirty */
  2223. surf_dest_lcl->lpSurfMore->lpRegionList->rdh.nCount = NUM_RECTS_IN_REGIONLIST;
  2224. }
  2225. }
  2226. /*
  2227. * Load clipping info into data struct for HAL callback.
  2228. */
  2229. bd.dwRectCnt = pRgn->rdh.nCount;
  2230. bd.prDestRects = (LPRECT)&pRgn->Buffer;
  2231. }
  2232. /*
  2233. * Does the driver have to do any clipping?
  2234. */
  2235. if (bd.dwRectCnt > 1)
  2236. {
  2237. // Yes, clipping is (probably) required.
  2238. bd.IsClipped = TRUE;
  2239. }
  2240. else if (bd.dwRectCnt == 0)
  2241. {
  2242. // Window is completely obscured, so don't draw anything.
  2243. LEAVE_BOTH_NOBUSY();
  2244. return DD_OK;
  2245. }
  2246. else
  2247. {
  2248. /*
  2249. * The visibility region consists of a single clip rect.
  2250. * Is any portion of the destination rectangle visible?
  2251. */
  2252. if (!IntersectRect((LPRECT)&bd.rDest, (LPRECT)&bd.rOrigDest,
  2253. &bd.prDestRects[0]))
  2254. {
  2255. // No portion of the destination rectangle is visible.
  2256. LEAVE_BOTH_NOBUSY();
  2257. return DD_OK;
  2258. }
  2259. /*
  2260. * Will the source rectangle have to be adjusted to
  2261. * compensate for the clipping of the dest rect?
  2262. */
  2263. if (surf_src_lcl != NULL &&
  2264. !EqualRect((LPRECT)&bd.rDest, (LPRECT)&bd.rOrigDest))
  2265. {
  2266. // Yes, the source rect must be adjusted.
  2267. if (sbi.dest_width != sbi.src_width ||
  2268. sbi.dest_height != sbi.src_height)
  2269. {
  2270. /*
  2271. * The driver must do the clipping for a stretched blit
  2272. * because bd.rSrc permits us to express the adjusted
  2273. * source rect only to the nearest integer coordinates.
  2274. */
  2275. bd.IsClipped = TRUE;
  2276. }
  2277. else
  2278. {
  2279. // We can do the clipping here for a nonstretched blit.
  2280. POINT p;
  2281. p.x = bd.rOrigSrc.left - bd.rOrigDest.left;
  2282. p.y = bd.rOrigSrc.top - bd.rOrigDest.top;
  2283. CopyRect((LPRECT)&bd.rSrc, (LPRECT)&bd.rDest);
  2284. OffsetRect((LPRECT)&bd.rSrc, p.x, p.y);
  2285. }
  2286. }
  2287. }
  2288. /*
  2289. * Older drivers may support the Blt callback, but not the AlphaBlt
  2290. * callback. One of these drivers may be able to perform the specified
  2291. * blit operation as long as it doesn't use any AlphaBlt-specific
  2292. * features such as alpha blending, ARGB scaling, or filtering.
  2293. * In this case, we can use the Blt callback to perform the blit.
  2294. * Decide which DDI to call. Start off assuming Alpha DDI
  2295. */
  2296. bltfn = pdrv_lcl->lpDDCB->HALDDMiscellaneous2.AlphaBlt;
  2297. bd.dwFlags |= DDBLT_AFLAGS; // assume we'll use AlphaBlt callback
  2298. /*
  2299. * Check to see if we can pass this call to old blt DDI
  2300. */
  2301. if ( !((dwDDPFDestFlags | dwDDPFSrcFlags) & DDPF_ALPHAPIXELS) &&
  2302. !(dwFlags & DDABLT_FILTERENABLE) )
  2303. {
  2304. // There are no alpha pixels involved. Maybe we can use the Blt DDI
  2305. if ( (bd.ddargbScaleFactors.alpha == 255) && (!sbi.helonly) )
  2306. {
  2307. LPDDPIXELFORMAT pDDPFDest = getPixelFormatPtr(surf_dest_lcl);
  2308. LPDDPIXELFORMAT pDDPFSrc = getPixelFormatPtr(surf_src_lcl);
  2309. // If this is a blit (and not a color fill), the source and dest pixel
  2310. // formats must be identical and the scaling factors must all be 1.0.
  2311. if ( (surf_src_lcl == NULL) ||
  2312. (!memcmp(pDDPFDest, pDDPFSrc, sizeof(DDPIXELFORMAT)) &&
  2313. (~0UL == *((LPDWORD)(&bd.ddargbScaleFactors)))) )
  2314. {
  2315. // Make sure the driver doesn't have to do any clipping. Also ensure
  2316. // that the driver does not require DDraw to pagelock sysmem surfaces.
  2317. if (!bd.IsClipped &&
  2318. (!caps.bHALSeesSysmem ||
  2319. pdrv->ddCaps.dwCaps2 & DDCAPS2_NOPAGELOCKREQUIRED))
  2320. {
  2321. // Verify that the driver supports the Blt HAL callback.
  2322. bltfn = (LPDDHAL_ALPHABLT) pdrv_lcl->lpDDCB->HALDDSurface.Blt;
  2323. if (bltfn)
  2324. {
  2325. bd.dwFlags &= ~DDBLT_AFLAGS; // we'll use Blt callback
  2326. if (surf_src_lcl == NULL)
  2327. {
  2328. DPF(4,"Calling Blt DDI for AlphaBlt color fill");
  2329. }
  2330. else
  2331. {
  2332. DPF(4,"Calling Blt DDI for AlphaBlt copy");
  2333. }
  2334. /*
  2335. * The following thunk address is used by the Blt callback,
  2336. * but is ignored by the AlphaBlt callback.
  2337. */
  2338. bd.Blt = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.Blt;
  2339. }
  2340. }
  2341. }
  2342. }
  2343. }
  2344. /*
  2345. * Set up for a HAL or a HEL call?
  2346. */
  2347. if (bltfn == NULL)
  2348. {
  2349. /*
  2350. * Neither the alphablt nor blt ddi calls apply or aren't implemented
  2351. */
  2352. sbi.helonly = TRUE;
  2353. }
  2354. if (sbi.helonly && sbi.halonly)
  2355. {
  2356. DPF_ERR("AlphaBlt not supported in software or hardware");
  2357. if (pRgn != (LPRGNDATA)&myRgnBuffer)
  2358. {
  2359. MemFree(pRgn); // this clip region was malloc'd
  2360. }
  2361. LEAVE_BOTH_NOBUSY();
  2362. return DDERR_NOBLTHW;
  2363. }
  2364. /*
  2365. * Can the hardware driver perform the blit?
  2366. */
  2367. if (!sbi.helonly)
  2368. {
  2369. /*
  2370. * Yes, we're going to do a hardware-accelerated blit.
  2371. */
  2372. DPF(4, "Hardware AlphaBlt");
  2373. /*
  2374. * The DDI was selected above
  2375. */
  2376. //bd.AlphaBlt = NULL; // 32-bit call, no thunk
  2377. /*
  2378. * Tell the hardware driver to perform the blit. We may have to wait
  2379. * if the driver is still busy with a previous drawing operation.
  2380. */
  2381. do
  2382. {
  2383. DOHALCALL_NOWIN16(AlphaBlt, bltfn, bd, rc, sbi.helonly);
  2384. if (rc != DDHAL_DRIVER_HANDLED || bd.ddRVal != DDERR_WASSTILLDRAWING)
  2385. {
  2386. break; // driver's finished for better or worse...
  2387. }
  2388. DPF(4, "Waiting...");
  2389. } while (dwFlags & DDABLT_WAIT);
  2390. /*
  2391. * Was the hardware driver able to handle the blit?
  2392. */
  2393. if (rc == DDHAL_DRIVER_HANDLED)
  2394. {
  2395. #ifdef WINNT
  2396. if (bd.ddRVal == DDERR_VISRGNCHANGED)
  2397. {
  2398. if (pRgn != (LPRGNDATA)&myRgnBuffer)
  2399. {
  2400. MemFree(pRgn);
  2401. }
  2402. DPF(5,"Resetting VisRgn for surface %x", surf_dest_lcl);
  2403. DdResetVisrgn(surf_dest_lcl, (HWND)0);
  2404. goto get_clipping_info;
  2405. }
  2406. #endif
  2407. if (bd.ddRVal != DDERR_WASSTILLDRAWING)
  2408. {
  2409. /*
  2410. * Yes, the blit was handled by the hardware driver.
  2411. * If source or dest surface is in system memory, tag it so
  2412. * we know it's involved in an ongoing hardware operation.
  2413. */
  2414. if (bd.ddRVal == DD_OK && caps.bHALSeesSysmem)
  2415. {
  2416. DPF(5,B,"Tagging surface %08x", surf_dest);
  2417. if (surf_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  2418. surf_dest->dwGlobalFlags |= DDRAWISURFGBL_HARDWAREOPDEST;
  2419. if (surf_src)
  2420. {
  2421. DPF(5,B,"Tagging surface %08x", surf_src);
  2422. if (surf_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  2423. surf_src->dwGlobalFlags |= DDRAWISURFGBL_HARDWAREOPSOURCE;
  2424. }
  2425. }
  2426. }
  2427. }
  2428. else
  2429. {
  2430. DDASSERT(rc == DDHAL_DRIVER_NOTHANDLED);
  2431. /*
  2432. * No, the hardware driver says it could not handle the blit.
  2433. * If sbi.halonly = FALSE, we'll let the HEL do the blit.
  2434. */
  2435. sbi.helonly = TRUE; // force fail-over to HEL
  2436. }
  2437. }
  2438. /*
  2439. * Do we need to ask the HEL to perform the blit?
  2440. */
  2441. if (sbi.helonly && !sbi.halonly)
  2442. {
  2443. /*
  2444. * Yes, we'll ask the HEL to do a software-emulated blit.
  2445. */
  2446. bltfn = pdrv_lcl->lpDDCB->HELDDMiscellaneous2.AlphaBlt;
  2447. /*
  2448. * Is dest surface in system memory or video memory?
  2449. */
  2450. if (surf_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  2451. {
  2452. /*
  2453. * Destination surface is in system memory.
  2454. * If this surface was involved in a hardware op, we need to
  2455. * probe the driver to see if it's done. NOTE: This assumes
  2456. * that only one driver can be responsible for a system-memory
  2457. * operation. See comment with WaitForHardwareOp.
  2458. */
  2459. if (surf_dest->dwGlobalFlags & DDRAWISURFGBL_HARDWAREOPSTARTED)
  2460. {
  2461. WaitForHardwareOp(pdrv_lcl, surf_dest_lcl);
  2462. }
  2463. dest_lock_taken = FALSE;
  2464. }
  2465. else
  2466. {
  2467. /*
  2468. * Wait loop: Take write lock on dest surface in video memory.
  2469. */
  2470. while(1)
  2471. {
  2472. ddrval = InternalLock(surf_dest_lcl, &dest_bits, NULL, 0);
  2473. if (ddrval == DD_OK)
  2474. {
  2475. GET_LPDDRAWSURFACE_GBL_MORE(surf_dest)->fpNTAlias = (FLATPTR)dest_bits;
  2476. break; // successfully locked dest surface
  2477. }
  2478. if (ddrval != DDERR_WASSTILLDRAWING)
  2479. {
  2480. /*
  2481. * Can't lock dest surface. Fail the call.
  2482. */
  2483. if (pRgn != (LPRGNDATA)&myRgnBuffer)
  2484. {
  2485. MemFree(pRgn); // this clip region was malloc'd
  2486. }
  2487. DONE_EXCLUDE();
  2488. DONE_BUSY();
  2489. LEAVE_BOTH();
  2490. return ddrval;
  2491. }
  2492. }
  2493. dest_lock_taken = TRUE;
  2494. }
  2495. if (surf_src && surf_src != surf_dest)
  2496. {
  2497. /*
  2498. * Is source surface in system memory or video memory?
  2499. */
  2500. if (surf_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  2501. {
  2502. /*
  2503. * Source surface is in system memory.
  2504. * If this surface was involved in a hardware op, we need to
  2505. * probe the driver to see if it's done. NOTE: This assumes
  2506. * that only one driver can be responsible for a system-memory
  2507. * operation. See comment with WaitForHardwareOp.
  2508. */
  2509. if (surf_src &&
  2510. surf_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY &&
  2511. surf_src->dwGlobalFlags & DDRAWISURFGBL_HARDWAREOPSTARTED)
  2512. {
  2513. WaitForHardwareOp(pdrv_lcl, surf_src_lcl);
  2514. }
  2515. src_lock_taken = FALSE;
  2516. }
  2517. else
  2518. {
  2519. /*
  2520. * Wait loop: Take lock on source surface in video memory.
  2521. */
  2522. while(1)
  2523. {
  2524. ddrval = InternalLock(surf_src_lcl, &src_bits, NULL, DDLOCK_READONLY);
  2525. if (ddrval == DD_OK)
  2526. {
  2527. GET_LPDDRAWSURFACE_GBL_MORE(surf_src)->fpNTAlias = (FLATPTR)src_bits;
  2528. break; // successfully locked source surface
  2529. }
  2530. if (ddrval != DDERR_WASSTILLDRAWING)
  2531. {
  2532. /*
  2533. * We can't lock the source surface. Fail the call.
  2534. */
  2535. if (dest_lock_taken)
  2536. {
  2537. InternalUnlock(surf_dest_lcl, NULL, NULL, 0);
  2538. }
  2539. if (pRgn != (LPRGNDATA)&myRgnBuffer)
  2540. {
  2541. MemFree(pRgn); // this clip region was malloc'd
  2542. }
  2543. DONE_EXCLUDE();
  2544. DONE_BUSY();
  2545. LEAVE_BOTH();
  2546. return ddrval;
  2547. }
  2548. }
  2549. src_lock_taken = TRUE;
  2550. }
  2551. }
  2552. /*
  2553. * Tell the HEL to perform the blit.
  2554. */
  2555. #ifdef WINNT
  2556. try_again:
  2557. #endif
  2558. DOHALCALL_NOWIN16(AlphaBlt, bltfn, bd, rc, sbi.helonly);
  2559. #ifdef WINNT
  2560. if (rc == DDHAL_DRIVER_HANDLED && bd.ddRVal == DDERR_VISRGNCHANGED)
  2561. {
  2562. DPF(5,"Resetting VisRgn for surface %x", surf_dest_lcl);
  2563. DdResetVisrgn(surf_dest_lcl, (HWND)0);
  2564. goto try_again;
  2565. }
  2566. #endif
  2567. }
  2568. /*
  2569. * If clip region was malloc'd, free it now.
  2570. */
  2571. if (pRgn != (LPRGNDATA)&myRgnBuffer)
  2572. {
  2573. MemFree(pRgn);
  2574. }
  2575. if(IsD3DManaged(surf_dest_lcl))
  2576. MarkDirty(surf_dest_lcl);
  2577. DONE_LOCKS();
  2578. /*
  2579. * Exclusion needs to happen after unlock call
  2580. */
  2581. DONE_EXCLUDE();
  2582. DONE_BUSY();
  2583. LEAVE_BOTH();
  2584. return bd.ddRVal;
  2585. }
  2586. EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  2587. {
  2588. DPF_ERR("Exception encountered doing alpha blt");
  2589. DONE_LOCKS();
  2590. DONE_EXCLUDE();
  2591. DONE_BUSY();
  2592. LEAVE_BOTH();
  2593. return DDERR_EXCEPTION;
  2594. }
  2595. } /* DD_Surface_AlphaBlt */