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.

5010 lines
203 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: ddsblt.c
  6. * Content: DirectDraw Surface support for blt
  7. * History:
  8. * Date By Reason
  9. * ==== == ======
  10. * 24-jan-95 craige split out of ddsurf.c, enhanced
  11. * 31-jan-95 craige and even more ongoing work...
  12. * 03-feb-95 craige performance tuning, ongoing work
  13. * 21-feb-95 craige work work work
  14. * 27-feb-95 craige new sync. macros
  15. * 08-mar-95 craige new stretch flags
  16. * 11-mar-95 craige take Win16 lock on Win95 before calling 32-bit fns
  17. * 15-mar-95 craige HEL integration
  18. * 19-mar-95 craige use HRESULTs
  19. * 29-mar-95 craige make colorfill work
  20. * 01-apr-95 craige happy fun joy updated header file
  21. * 03-apr-95 craige off by one when rect specified; need to validate
  22. * rectangles against surfaces
  23. * 12-apr-95 craige pulled out clipped stretching code optimization for now
  24. * 15-apr-95 craige can't allow source surface with colorfill; don't
  25. * allow < 0 left, top coords
  26. * 06-may-95 craige use driver-level csects only
  27. * 11-jun-95 craige check for locked surface before blt
  28. * 21-jun-95 kylej lock non-emulated surfaces before calling HEL blt
  29. * 21-jun-95 craige clipping changes
  30. * 24-jun-95 kylej move video memory source surfaces to system memory
  31. * if there is no hardware blt support.
  32. * 25-jun-95 craige one ddraw mutex
  33. * 26-jun-95 craige reorganized surface structure
  34. * 27-jun-95 craige use clipper to do clipping; started BltBatch;
  35. * moved CheckBltStretching back in
  36. * 28-jun-95 craige ENTER_DDRAW at very start of fns; disabled alpha & Z blt
  37. * 04-jul-95 craige YEEHAW: new driver struct; SEH
  38. * 05-jul-95 kylej debugged clipping code and added clipped stretched blts
  39. * 07-jul-95 craige added test for BUSY
  40. * 07-jul-95 kylej replace inline code with call to XformRect
  41. * 08-jul-95 craige BltFast: need to use HEL if src or dest is in
  42. * system memory!
  43. * 09-jul-95 craige hasvram flag in MoveToSystemMemory; handle loss
  44. * of color key resource after blt
  45. * 10-jul-95 kylej added mirroring caps checks in Blt
  46. * 13-jul-95 craige ENTER_DDRAW is now the win16 lock
  47. * 16-jul-95 craige check DDRAWISURF_HELCB
  48. * 27-jul-95 craige check for color fill support in hardware!
  49. * 31-jul-95 craige check Lock calls for WASSTILLDRAWING;
  50. * test for valid flags
  51. * 01-aug-95 craige hold win16 early to keep busy bit test valid
  52. * 01-aug-95 toddla added DD16_Exclude and DD16_Unexclude
  53. * 04-aug-95 craige use InternalLock/Unlock
  54. * 06-aug-95 craige do DD16_Exclude before lock, unexclude after unlock
  55. * 10-aug-95 toddla added DDBLT_WAIT and DDBLTFAST_WAIT flags
  56. * 12-aug-95 craige use_full_lock parm for MoveToSystemMemory and
  57. * ChangeToSoftwareColorKey
  58. * 23-aug-95 craige wasn't unlocking surfaces or unexcluding cursor on
  59. * a few error conditions
  60. * 16-sep-95 craige bug 1175: set return code if NULL clip list
  61. * 02-jan-96 kylej handle new interface structures
  62. * 04-jan-96 colinmc added DDBLT_DEPTHFILL for clearing Z-buffers
  63. * 01-feb-96 jeffno NT: pass user-mode ptrs to vram surfaces to HEL
  64. * in Blt and BltFast
  65. * 12-feb-96 colinmc Surface lost flag moved from global to local object
  66. * 29-feb-96 kylej Enable System->Video bltting
  67. * 03-mar-96 colinmc Fixed a couple of nasty bugs causing blts to system
  68. * memory to be done by hardware
  69. * 21-mar-96 colinmc Bug 14011: Insufficient parameter validation on
  70. * BltFast
  71. * 26-mar-96 jeffno Handle visrgn changes under NT
  72. * 20-apr-96 colinmc Fixed problem with releasePageLocks spinning on
  73. * busy bit
  74. * 23-apr-96 kylej Bug 10196: Added check for software dest blt
  75. * 17-may-96 craige bug 21499: perf problems with BltFast
  76. * 14-jun-96 kylej NT Bug 38227: Internal lock was not correctly reporting
  77. * when the visrgn had changed.
  78. * 13-aug-96 colinmc Bug 3194: Blitting through a clipper without
  79. * DDBLT_WAIT could cause infinite loop in app.
  80. * 01-oct-96 ketand Perf for clipped blits
  81. * 21-jan-97 ketand Fix rectangle checking for multi-mon systems. Clip blits to
  82. * the destination surface if a clipper is used.
  83. * 31-jan-97 colinmc Bug 5457: Fixed Win16 lock problem causing hang
  84. * with mutliple AMovie instances on old cards
  85. * 03-mar-97 jeffno Bug #5061: Trashing fpVidMem on blt.
  86. * 08-mar-97 colinmc Support for DMA style AGP parts
  87. * 11-mar-97 jeffno Asynchronous DMA support
  88. * 24-mar-97 jeffno Optimized Surfaces
  89. *
  90. ***************************************************************************/
  91. #include "ddrawpr.h"
  92. #define DONE_BUSY() \
  93. (*pdflags) &= ~BUSY; \
  94. #define LEAVE_BOTH_NOBUSY() \
  95. { if(pdflags)\
  96. (*pdflags) &= ~BUSY; \
  97. } \
  98. LEAVE_BOTH();
  99. #define DONE_LOCKS() \
  100. if( dest_lock_taken ) \
  101. { \
  102. if (subrect_lock_taken) \
  103. { \
  104. InternalUnlock( this_dest_lcl, NULL, &subrect_lock_rect, 0); \
  105. subrect_lock_taken = FALSE; \
  106. } \
  107. else \
  108. { \
  109. InternalUnlock( this_dest_lcl,NULL,NULL,0 ); \
  110. } \
  111. dest_lock_taken = FALSE; \
  112. } \
  113. if( src_lock_taken && this_src_lcl) \
  114. { \
  115. InternalUnlock( this_src_lcl,NULL,NULL,0 ); \
  116. src_lock_taken = FALSE; \
  117. }
  118. #undef DPF_MODNAME
  119. #define DPF_MODNAME "BltFast"
  120. DWORD dwSVBHack;
  121. // turns off SEH for bltfast
  122. #define FASTFAST
  123. typedef struct _bltcaps
  124. {
  125. LPDWORD dwCaps;
  126. LPDWORD dwFXCaps;
  127. LPDWORD dwCKeyCaps;
  128. LPDWORD dwRops;
  129. LPDWORD dwHELCaps;
  130. LPDWORD dwHELFXCaps;
  131. LPDWORD dwHELCKeyCaps;
  132. LPDWORD dwHELRops;
  133. LPDWORD dwBothCaps;
  134. LPDWORD dwBothFXCaps;
  135. LPDWORD dwBothCKeyCaps;
  136. LPDWORD dwBothRops;
  137. BOOL bHALSeesSysmem;
  138. BOOL bSourcePagelockTaken;
  139. BOOL bDestPagelockTaken;
  140. } BLTCAPS, *LPBLTCAPS;
  141. void initBltCaps( DWORD dwDstCaps, DWORD dwDstFlags, DWORD dwSrcCaps, LPDDRAWI_DIRECTDRAW_GBL pdrv, LPBLTCAPS lpbc, LPBOOL helonly )
  142. {
  143. #ifdef WINNT
  144. BOOL bPrimaryHack = FALSE;
  145. #endif
  146. if (lpbc)
  147. {
  148. /*
  149. * Not really expecting lpbc to be null, but this is late and I'm paranoid
  150. */
  151. lpbc->bSourcePagelockTaken = FALSE;
  152. lpbc->bDestPagelockTaken = FALSE;
  153. }
  154. #ifdef WINNT
  155. // On NT, the kernel needs to handle blts from system to the primary
  156. // surface, otherwise the sprite stuff won't work
  157. if( ( dwDstFlags & DDRAWISURFGBL_ISGDISURFACE ) &&
  158. ( dwDstCaps & DDSCAPS_VIDEOMEMORY ) &&
  159. ( dwSrcCaps & DDSCAPS_SYSTEMMEMORY ) &&
  160. !(pdrv->ddCaps.dwCaps & DDCAPS_CANBLTSYSMEM) &&
  161. ( pdrv->ddCaps.dwCaps & DDCAPS_BLT ) )
  162. {
  163. bPrimaryHack = TRUE;
  164. pdrv->ddCaps.dwCaps |= DDCAPS_CANBLTSYSMEM;
  165. }
  166. #endif
  167. if( ( ( dwSrcCaps & DDSCAPS_NONLOCALVIDMEM ) || ( dwDstCaps & DDSCAPS_NONLOCALVIDMEM ) ) &&
  168. ( pdrv->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEMCAPS ) )
  169. {
  170. /*
  171. * At least one of the surfaces is non local and the device exports
  172. * different capabilities for non-local video memory. If this is non-local
  173. * to local transfer then check the appropriate caps. Otherwise force
  174. * emulation.
  175. */
  176. if( ( dwSrcCaps & DDSCAPS_NONLOCALVIDMEM ) && ( dwDstCaps & DDSCAPS_LOCALVIDMEM ) )
  177. {
  178. /*
  179. * Non-local to local video memory transfer.
  180. */
  181. DDASSERT( NULL != pdrv->lpddNLVCaps );
  182. DDASSERT( NULL != pdrv->lpddNLVHELCaps );
  183. DDASSERT( NULL != pdrv->lpddNLVBothCaps );
  184. /*
  185. * We have specific caps. Use them
  186. */
  187. lpbc->dwCaps = &(pdrv->lpddNLVCaps->dwNLVBCaps);
  188. lpbc->dwFXCaps = &(pdrv->lpddNLVCaps->dwNLVBFXCaps);
  189. lpbc->dwCKeyCaps = &(pdrv->lpddNLVCaps->dwNLVBCKeyCaps);
  190. lpbc->dwRops = pdrv->lpddNLVCaps->dwNLVBRops;
  191. lpbc->dwHELCaps = &(pdrv->lpddNLVHELCaps->dwNLVBCaps);
  192. lpbc->dwHELFXCaps = &(pdrv->lpddNLVHELCaps->dwNLVBFXCaps);
  193. lpbc->dwHELCKeyCaps = &(pdrv->lpddNLVHELCaps->dwNLVBCKeyCaps);
  194. lpbc->dwHELRops = pdrv->lpddNLVHELCaps->dwNLVBRops;
  195. lpbc->dwBothCaps = &(pdrv->lpddNLVBothCaps->dwNLVBCaps);
  196. lpbc->dwBothFXCaps = &(pdrv->lpddNLVBothCaps->dwNLVBFXCaps);
  197. lpbc->dwBothCKeyCaps = &(pdrv->lpddNLVBothCaps->dwNLVBCKeyCaps);
  198. lpbc->dwBothRops = pdrv->lpddNLVBothCaps->dwNLVBRops;
  199. lpbc->bHALSeesSysmem = FALSE;
  200. return;
  201. }
  202. else if( ( dwSrcCaps & DDSCAPS_SYSTEMMEMORY ) && ( dwDstCaps & DDSCAPS_NONLOCALVIDMEM )
  203. && ( pdrv->ddCaps.dwCaps2 & DDCAPS2_SYSTONONLOCAL_AS_SYSTOLOCAL ) )
  204. {
  205. /*
  206. * See the definition of the above caps bit in ddrawp.h for more details
  207. */
  208. DPF(4,"System to non-local Blt is a candidate for passing to driver.");
  209. lpbc->dwCaps = &(pdrv->ddCaps.dwSVBCaps);
  210. lpbc->dwFXCaps = &(pdrv->ddCaps.dwSVBFXCaps);
  211. lpbc->dwCKeyCaps = &(pdrv->ddCaps.dwSVBCKeyCaps);
  212. lpbc->dwRops = pdrv->ddCaps.dwSVBRops;
  213. lpbc->dwHELCaps = &(pdrv->ddHELCaps.dwSVBCaps);
  214. lpbc->dwHELFXCaps = &(pdrv->ddHELCaps.dwSVBFXCaps);
  215. lpbc->dwHELCKeyCaps = &(pdrv->ddHELCaps.dwSVBCKeyCaps);
  216. lpbc->dwHELRops = pdrv->ddHELCaps.dwSVBRops;
  217. lpbc->dwBothCaps = &(pdrv->ddBothCaps.dwSVBCaps);
  218. lpbc->dwBothFXCaps = &(pdrv->ddBothCaps.dwSVBFXCaps);
  219. lpbc->dwBothCKeyCaps = &(pdrv->ddBothCaps.dwSVBCKeyCaps);
  220. lpbc->dwBothRops = pdrv->ddBothCaps.dwSVBRops;
  221. lpbc->bHALSeesSysmem = TRUE;
  222. return;
  223. }
  224. else
  225. {
  226. /*
  227. * Non-local to non-local or local to non-local transfer. Force emulation.
  228. */
  229. *helonly = TRUE;
  230. }
  231. }
  232. if( !(pdrv->ddCaps.dwCaps & DDCAPS_CANBLTSYSMEM) )
  233. {
  234. if( (dwSrcCaps & DDSCAPS_SYSTEMMEMORY) || (dwDstCaps & DDSCAPS_SYSTEMMEMORY) )
  235. {
  236. *helonly = TRUE;
  237. }
  238. }
  239. if( ( (dwSrcCaps & DDSCAPS_VIDEOMEMORY) && (dwDstCaps & DDSCAPS_VIDEOMEMORY) ) ||
  240. !( pdrv->ddCaps.dwCaps & DDCAPS_CANBLTSYSMEM ) )
  241. {
  242. lpbc->dwCaps = &(pdrv->ddCaps.dwCaps);
  243. lpbc->dwFXCaps = &(pdrv->ddCaps.dwFXCaps);
  244. lpbc->dwCKeyCaps = &(pdrv->ddCaps.dwCKeyCaps);
  245. lpbc->dwRops = pdrv->ddCaps.dwRops;
  246. lpbc->dwHELCaps = &(pdrv->ddHELCaps.dwCaps);
  247. lpbc->dwHELFXCaps = &(pdrv->ddHELCaps.dwFXCaps);
  248. lpbc->dwHELCKeyCaps = &(pdrv->ddHELCaps.dwCKeyCaps);
  249. lpbc->dwHELRops = pdrv->ddHELCaps.dwRops;
  250. lpbc->dwBothCaps = &(pdrv->ddBothCaps.dwCaps);
  251. lpbc->dwBothFXCaps = &(pdrv->ddBothCaps.dwFXCaps);
  252. lpbc->dwBothCKeyCaps = &(pdrv->ddBothCaps.dwCKeyCaps);
  253. lpbc->dwBothRops = pdrv->ddBothCaps.dwRops;
  254. lpbc->bHALSeesSysmem = FALSE;
  255. }
  256. else if( (dwSrcCaps & DDSCAPS_SYSTEMMEMORY) && (dwDstCaps & DDSCAPS_VIDEOMEMORY) )
  257. {
  258. lpbc->dwCaps = &(pdrv->ddCaps.dwSVBCaps);
  259. lpbc->dwFXCaps = &(pdrv->ddCaps.dwSVBFXCaps);
  260. lpbc->dwCKeyCaps = &(pdrv->ddCaps.dwSVBCKeyCaps);
  261. lpbc->dwRops = pdrv->ddCaps.dwSVBRops;
  262. lpbc->dwHELCaps = &(pdrv->ddHELCaps.dwSVBCaps);
  263. lpbc->dwHELFXCaps = &(pdrv->ddHELCaps.dwSVBFXCaps);
  264. lpbc->dwHELCKeyCaps = &(pdrv->ddHELCaps.dwSVBCKeyCaps);
  265. lpbc->dwHELRops = pdrv->ddHELCaps.dwSVBRops;
  266. lpbc->dwBothCaps = &(pdrv->ddBothCaps.dwSVBCaps);
  267. lpbc->dwBothFXCaps = &(pdrv->ddBothCaps.dwSVBFXCaps);
  268. lpbc->dwBothCKeyCaps = &(pdrv->ddBothCaps.dwSVBCKeyCaps);
  269. lpbc->dwBothRops = pdrv->ddBothCaps.dwSVBRops;
  270. lpbc->bHALSeesSysmem = TRUE;
  271. }
  272. else if( (dwSrcCaps & DDSCAPS_VIDEOMEMORY) && (dwDstCaps & DDSCAPS_SYSTEMMEMORY) )
  273. {
  274. lpbc->dwCaps = &(pdrv->ddCaps.dwVSBCaps);
  275. lpbc->dwFXCaps = &(pdrv->ddCaps.dwVSBFXCaps);
  276. lpbc->dwCKeyCaps = &(pdrv->ddCaps.dwVSBCKeyCaps);
  277. lpbc->dwRops = pdrv->ddCaps.dwVSBRops;
  278. lpbc->dwHELCaps = &(pdrv->ddHELCaps.dwVSBCaps);
  279. lpbc->dwHELFXCaps = &(pdrv->ddHELCaps.dwVSBFXCaps);
  280. lpbc->dwHELCKeyCaps = &(pdrv->ddHELCaps.dwVSBCKeyCaps);
  281. lpbc->dwHELRops = pdrv->ddHELCaps.dwVSBRops;
  282. lpbc->dwBothCaps = &(pdrv->ddBothCaps.dwVSBCaps);
  283. lpbc->dwBothFXCaps = &(pdrv->ddBothCaps.dwVSBFXCaps);
  284. lpbc->dwBothCKeyCaps = &(pdrv->ddBothCaps.dwVSBCKeyCaps);
  285. lpbc->dwBothRops = pdrv->ddBothCaps.dwVSBRops;
  286. lpbc->bHALSeesSysmem = TRUE;
  287. }
  288. else if( (dwSrcCaps & DDSCAPS_SYSTEMMEMORY) && (dwDstCaps & DDSCAPS_SYSTEMMEMORY) )
  289. {
  290. lpbc->dwCaps = &(pdrv->ddCaps.dwSSBCaps);
  291. lpbc->dwFXCaps = &(pdrv->ddCaps.dwSSBFXCaps);
  292. lpbc->dwCKeyCaps = &(pdrv->ddCaps.dwSSBCKeyCaps);
  293. lpbc->dwRops = pdrv->ddCaps.dwSSBRops;
  294. lpbc->dwHELCaps = &(pdrv->ddHELCaps.dwSSBCaps);
  295. lpbc->dwHELFXCaps = &(pdrv->ddHELCaps.dwSSBFXCaps);
  296. lpbc->dwHELCKeyCaps = &(pdrv->ddHELCaps.dwSSBCKeyCaps);
  297. lpbc->dwHELRops = pdrv->ddHELCaps.dwSSBRops;
  298. lpbc->dwBothCaps = &(pdrv->ddBothCaps.dwSSBCaps);
  299. lpbc->dwBothFXCaps = &(pdrv->ddBothCaps.dwSSBFXCaps);
  300. lpbc->dwBothCKeyCaps = &(pdrv->ddBothCaps.dwSSBCKeyCaps);
  301. lpbc->dwBothRops = pdrv->ddBothCaps.dwSSBRops;
  302. lpbc->bHALSeesSysmem = TRUE;
  303. }
  304. #ifdef WINNT
  305. if( bPrimaryHack )
  306. {
  307. pdrv->ddCaps.dwCaps &= ~DDCAPS_CANBLTSYSMEM;
  308. dwSVBHack = DDCAPS_BLT;
  309. lpbc->dwCaps = &dwSVBHack;
  310. lpbc->dwBothCaps = &dwSVBHack;
  311. }
  312. #endif
  313. }
  314. __inline void initBltCapsFast(
  315. DWORD dwDstCaps,
  316. DWORD dwSrcCaps,
  317. LPDDRAWI_DIRECTDRAW_GBL pdrv,
  318. LPBLTCAPS lpbc )
  319. {
  320. if (lpbc)
  321. {
  322. /*
  323. * Not really expecting lpbc to be null, but this is late and I'm paranoid
  324. */
  325. lpbc->bSourcePagelockTaken = FALSE;
  326. lpbc->bDestPagelockTaken = FALSE;
  327. }
  328. if( ( ( dwSrcCaps & DDSCAPS_NONLOCALVIDMEM ) && ( dwDstCaps && DDSCAPS_LOCALVIDMEM ) ) &&
  329. ( pdrv->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEMCAPS ) )
  330. {
  331. DDASSERT( NULL != pdrv->lpddNLVCaps );
  332. lpbc->dwCaps = &(pdrv->lpddNLVCaps->dwNLVBCaps);
  333. lpbc->dwHELCaps = &(pdrv->lpddNLVHELCaps->dwNLVBCaps);
  334. lpbc->dwBothCaps = &(pdrv->lpddNLVBothCaps->dwNLVBCaps);
  335. lpbc->dwCKeyCaps = &(pdrv->lpddNLVCaps->dwNLVBCKeyCaps);
  336. lpbc->dwHELCKeyCaps = &(pdrv->lpddNLVHELCaps->dwNLVBCKeyCaps);
  337. lpbc->dwBothCKeyCaps = &(pdrv->lpddNLVBothCaps->dwNLVBCKeyCaps);
  338. lpbc->bHALSeesSysmem = FALSE;
  339. }
  340. else if( ( (dwSrcCaps & DDSCAPS_VIDEOMEMORY) && (dwDstCaps & DDSCAPS_VIDEOMEMORY) ) ||
  341. !( pdrv->ddCaps.dwCaps & DDCAPS_CANBLTSYSMEM ) )
  342. {
  343. lpbc->dwCaps = &(pdrv->ddCaps.dwCaps);
  344. lpbc->dwHELCaps = &(pdrv->ddHELCaps.dwCaps);
  345. lpbc->dwBothCaps = &(pdrv->ddBothCaps.dwCaps);
  346. lpbc->dwCKeyCaps = &(pdrv->ddCaps.dwCKeyCaps);
  347. lpbc->dwHELCKeyCaps = &(pdrv->ddHELCaps.dwCKeyCaps);
  348. lpbc->dwBothCKeyCaps = &(pdrv->ddBothCaps.dwCKeyCaps);
  349. lpbc->bHALSeesSysmem = FALSE;
  350. }
  351. else if( (dwSrcCaps & DDSCAPS_SYSTEMMEMORY) && (dwDstCaps & DDSCAPS_VIDEOMEMORY) )
  352. {
  353. lpbc->dwCaps = &(pdrv->ddCaps.dwSVBCaps);
  354. lpbc->dwHELCaps = &(pdrv->ddHELCaps.dwSVBCaps);
  355. lpbc->dwBothCaps = &(pdrv->ddBothCaps.dwSVBCaps);
  356. lpbc->dwCKeyCaps = &(pdrv->ddCaps.dwSVBCKeyCaps);
  357. lpbc->dwHELCKeyCaps = &(pdrv->ddHELCaps.dwSVBCKeyCaps);
  358. lpbc->dwBothCKeyCaps = &(pdrv->ddBothCaps.dwSVBCKeyCaps);
  359. lpbc->bHALSeesSysmem = TRUE;
  360. }
  361. else if( (dwSrcCaps & DDSCAPS_VIDEOMEMORY) && (dwDstCaps & DDSCAPS_SYSTEMMEMORY) )
  362. {
  363. lpbc->dwCaps = &(pdrv->ddCaps.dwVSBCaps);
  364. lpbc->dwHELCaps = &(pdrv->ddHELCaps.dwVSBCaps);
  365. lpbc->dwBothCaps = &(pdrv->ddBothCaps.dwVSBCaps);
  366. lpbc->dwCKeyCaps = &(pdrv->ddCaps.dwVSBCKeyCaps);
  367. lpbc->dwHELCKeyCaps = &(pdrv->ddHELCaps.dwVSBCKeyCaps);
  368. lpbc->dwBothCKeyCaps = &(pdrv->ddBothCaps.dwVSBCKeyCaps);
  369. lpbc->bHALSeesSysmem = TRUE;
  370. }
  371. else if( (dwSrcCaps & DDSCAPS_SYSTEMMEMORY) && (dwDstCaps & DDSCAPS_SYSTEMMEMORY) )
  372. {
  373. lpbc->dwCaps = &(pdrv->ddCaps.dwSSBCaps);
  374. lpbc->dwHELCaps = &(pdrv->ddHELCaps.dwSSBCaps);
  375. lpbc->dwBothCaps = &(pdrv->ddBothCaps.dwSSBCaps);
  376. lpbc->dwCKeyCaps = &(pdrv->ddCaps.dwSSBCKeyCaps);
  377. lpbc->dwHELCKeyCaps = &(pdrv->ddHELCaps.dwSSBCKeyCaps);
  378. lpbc->dwBothCKeyCaps = &(pdrv->ddBothCaps.dwSSBCKeyCaps);
  379. lpbc->bHALSeesSysmem = TRUE;
  380. }
  381. }
  382. /*
  383. * OverlapsDevices
  384. *
  385. * This function checks for Blts that are on the destop, but not entirely
  386. * on the device. When found, we will emulate the Blt (punting to GDI).
  387. */
  388. BOOL OverlapsDevices( LPDDRAWI_DDRAWSURFACE_LCL lpSurf_lcl, LPRECT lpRect )
  389. {
  390. LPDDRAWI_DIRECTDRAW_GBL lpGbl;
  391. RECT rect;
  392. lpGbl = lpSurf_lcl->lpSurfMore->lpDD_lcl->lpGbl;
  393. /*
  394. * If the device was explicitly specified, assume that they know
  395. * what they're doing.
  396. */
  397. if( lpSurf_lcl->lpSurfMore->lpDD_lcl->dwLocalFlags & DDRAWILCL_EXPLICITMONITOR )
  398. {
  399. return FALSE;
  400. }
  401. /*
  402. * Do a real quick check w/o accounting for the clipper
  403. */
  404. if( ( lpRect->top < lpGbl->rectDevice.top ) ||
  405. ( lpRect->left < lpGbl->rectDevice.left ) ||
  406. ( lpRect->right > lpGbl->rectDevice.right ) ||
  407. ( lpRect->bottom > lpGbl->rectDevice.bottom ) )
  408. {
  409. /*
  410. * It may only be that part of the rect is off of the desktop,
  411. * in which case we don't neccesarily need to drop to emulation.
  412. */
  413. IntersectRect( &rect, lpRect, &lpGbl->rectDesktop );
  414. if( ( rect.top < lpGbl->rectDevice.top ) ||
  415. ( rect.left < lpGbl->rectDevice.left ) ||
  416. ( rect.right > lpGbl->rectDevice.right ) ||
  417. ( rect.bottom > lpGbl->rectDevice.bottom ) )
  418. {
  419. return TRUE;
  420. }
  421. }
  422. return FALSE;
  423. }
  424. /*
  425. * WaitForDriverToFinishWithSurface
  426. *
  427. * This function waits for the hardware driver to report that it has finished
  428. * operating on the given surface. We should only call this function if the
  429. * surface was a system memory surface involved in a DMA/busmastering transfer.
  430. * Note this function clears the DDRAWISURFGBL_HARDWAREOPSTARTED flags (both
  431. * of them).
  432. */
  433. void WaitForDriverToFinishWithSurface(LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl, LPDDRAWI_DDRAWSURFACE_LCL this_lcl)
  434. {
  435. HRESULT hr;
  436. #ifdef DEBUG
  437. DWORD dwStart;
  438. BOOL bSentMessage=FALSE;
  439. dwStart = GetTickCount();
  440. #endif
  441. DDASSERT( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY );
  442. DPF(4,"Waiting for driver to finish with %08x",this_lcl->lpGbl);
  443. do
  444. {
  445. hr = InternalGetBltStatus( pdrv_lcl , this_lcl , DDGBS_ISBLTDONE );
  446. #ifdef DEBUG
  447. if ( GetTickCount() -dwStart >= 10000 )
  448. {
  449. if (!bSentMessage)
  450. {
  451. bSentMessage = TRUE;
  452. DPF_ERR("Driver reports operation still pending on surface after 5s! Driver error!");
  453. }
  454. }
  455. #endif
  456. } while (hr == DDERR_WASSTILLDRAWING);
  457. DDASSERT(hr == DD_OK);
  458. DPF(5,B,"Driver finished with that surface");
  459. this_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_HARDWAREOPSTARTED;
  460. }
  461. /*
  462. * DD_Surface_BltFast
  463. *
  464. * Bit Blt from one surface to another FAST
  465. */
  466. HRESULT DDAPI DD_Surface_BltFast(
  467. LPDIRECTDRAWSURFACE lpDDDestSurface,
  468. DWORD dwX,
  469. DWORD dwY,
  470. LPDIRECTDRAWSURFACE lpDDSrcSurface,
  471. LPRECT lpSrcRect,
  472. DWORD dwTrans )
  473. {
  474. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  475. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  476. LPDDRAWI_DDRAWSURFACE_INT this_src_int;
  477. LPDDRAWI_DDRAWSURFACE_INT this_dest_int;
  478. LPDDRAWI_DDRAWSURFACE_LCL this_src_lcl;
  479. LPDDRAWI_DDRAWSURFACE_LCL this_dest_lcl;
  480. LPDDRAWI_DDRAWSURFACE_GBL this_src;
  481. LPDDRAWI_DDRAWSURFACE_GBL this_dest;
  482. DDHAL_BLTDATA bd;
  483. DWORD rc;
  484. LPDDHALSURFCB_BLT bltfn;
  485. BOOL halonly;
  486. BOOL helonly;
  487. BOOL gdiblt;
  488. int src_height;
  489. int src_width;
  490. BOOL dest_lock_taken=FALSE;
  491. BOOL src_lock_taken=FALSE;
  492. LPVOID dest_bits;
  493. LPVOID src_bits;
  494. HRESULT ddrval;
  495. BLTCAPS bc;
  496. LPBLTCAPS lpbc = &bc;
  497. LPWORD pdflags=0;
  498. DWORD dwSourceLockFlags=0;
  499. DWORD dwDestLockFlags=0;
  500. BOOL subrect_lock_taken = FALSE;
  501. RECT subrect_lock_rect;
  502. ENTER_BOTH();
  503. DPF(2,A,"ENTERAPI: DD_Surface_BltFast");
  504. /* DPF_ENTERAPI(lpDDDestSurface); */
  505. /*
  506. * prepare parameters. An exception here is considered a bad parameter
  507. */
  508. #ifndef FASTFAST
  509. TRY
  510. #endif
  511. {
  512. ZeroMemory(&bd, sizeof(bd)); // initialize to zero
  513. this_dest_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDDestSurface;
  514. if( !VALID_DIRECTDRAWSURFACE_PTR( this_dest_int ) )
  515. {
  516. LEAVE_BOTH()
  517. return DDERR_INVALIDOBJECT;
  518. }
  519. this_dest_lcl = this_dest_int->lpLcl;
  520. this_dest = this_dest_lcl->lpGbl;
  521. if( SURFACE_LOST( this_dest_lcl ) )
  522. {
  523. DPF( 1, "Destination (%08lx) is lost", this_dest_int );
  524. LEAVE_BOTH();
  525. return DDERR_SURFACELOST;
  526. }
  527. this_src_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSrcSurface;
  528. if( !VALID_DIRECTDRAWSURFACE_PTR( this_src_int ) )
  529. {
  530. LEAVE_BOTH();
  531. return DDERR_INVALIDOBJECT;
  532. }
  533. this_src_lcl = this_src_int->lpLcl;
  534. this_src = this_src_lcl->lpGbl;
  535. if( SURFACE_LOST( this_src_lcl ) )
  536. {
  537. DPF( 1, "Source (%08lx) is lost", this_src_int );
  538. LEAVE_BOTH();
  539. return DDERR_SURFACELOST;
  540. }
  541. if( lpSrcRect != NULL )
  542. {
  543. if( !VALID_RECT_PTR( lpSrcRect ) )
  544. {
  545. LEAVE_BOTH()
  546. return DDERR_INVALIDPARAMS;
  547. }
  548. }
  549. if( dwTrans & ~DDBLTFAST_VALID )
  550. {
  551. DPF_ERR( "Invalid flags") ;
  552. LEAVE_BOTH();
  553. return DDERR_INVALIDPARAMS;
  554. }
  555. //
  556. // If either surface is optimized, quit
  557. //
  558. if (this_src_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  559. {
  560. DPF_ERR( "Can't blt from an optimized surface") ;
  561. LEAVE_BOTH();
  562. return DDERR_INVALIDPARAMS;
  563. }
  564. if (this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  565. {
  566. DPF_ERR( "Can't blt to optimized surfaces") ;
  567. LEAVE_BOTH();
  568. return DDERR_INVALIDPARAMS;
  569. }
  570. /*
  571. * BEHAVIOUR CHANGE FOR DX5
  572. *
  573. * We do not allow bltting between surfaces created with different DirectDraw
  574. * objects.
  575. */
  576. if (this_dest_lcl->lpSurfMore->lpDD_lcl->lpGbl != this_src_lcl->lpSurfMore->lpDD_lcl->lpGbl)
  577. {
  578. if ((this_dest_lcl->lpSurfMore->lpDD_lcl->lpGbl->dwFlags & DDRAWI_DISPLAYDRV) &&
  579. (this_src_lcl->lpSurfMore->lpDD_lcl->lpGbl->dwFlags & DDRAWI_DISPLAYDRV))
  580. {
  581. DPF_ERR("Can't blt surfaces between different direct draw devices");
  582. LEAVE_BOTH();
  583. return DDERR_DEVICEDOESNTOWNSURFACE;
  584. }
  585. }
  586. pdrv = this_dest->lpDD;
  587. pdrv_lcl = this_dest_lcl->lpSurfMore->lpDD_lcl;
  588. #ifdef WINNT
  589. // Update DDraw handle in driver GBL object.
  590. pdrv->hDD = pdrv_lcl->hDD;
  591. #endif
  592. /*
  593. * DX5 or greater drivers get to know about read/write only locks
  594. * Note that dwDestFlags may later be zeroed for dest color key.
  595. * We pass read+write if the blt goes to/from the same buffer, of course.
  596. */
  597. if (pdrv->dwInternal1 >= 0x500 && this_src != this_dest )
  598. {
  599. dwSourceLockFlags = DDLOCK_READONLY;
  600. dwDestLockFlags = DDLOCK_WRITEONLY;
  601. }
  602. #ifdef USE_ALIAS
  603. if( pdrv->dwBusyDueToAliasedLock > 0 )
  604. {
  605. /*
  606. * Aliased locks (the ones that don't take the Win16 lock) don't
  607. * set the busy bit either (it can't or USER get's very confused).
  608. * However, we must prevent blits happening via DirectDraw as
  609. * otherwise we get into the old host talking to VRAM while
  610. * blitter does at the same time. Bad. So fail if there is an
  611. * outstanding aliased lock just as if the BUST bit had been
  612. * set.
  613. */
  614. DPF_ERR( "Graphics adapter is busy (due to a DirectDraw lock)" );
  615. LEAVE_BOTH();
  616. return DDERR_SURFACEBUSY;
  617. }
  618. #endif /* USE_ALIAS */
  619. /*
  620. * Behavior change: In DX7, the default is to wait unless DDFASTBLT_DONOTWAIT=1.
  621. * In earlier releases, the default was to NOT wait unless DDFASTBLT_WAIT=1.
  622. * (The DDFASTBLT_DONOTWAIT flag was not defined until the DX7 release.)
  623. */
  624. if (!LOWERTHANSURFACE7(this_dest_int))
  625. {
  626. if (dwTrans & DDBLTFAST_DONOTWAIT)
  627. {
  628. if (dwTrans & DDBLTFAST_WAIT)
  629. {
  630. DPF_ERR( "WAIT and DONOTWAIT flags are mutually exclusive" );
  631. LEAVE_BOTH();
  632. return DDERR_INVALIDPARAMS;
  633. }
  634. }
  635. else
  636. {
  637. dwTrans |= DDBLTFAST_WAIT;
  638. }
  639. }
  640. FlushD3DStates(this_src_lcl); // Need to flush src because it could be a rendertarget
  641. FlushD3DStates(this_dest_lcl);
  642. // Test and set the busy bit. If it was already set, bail.
  643. {
  644. BOOL isbusy = 0;
  645. pdflags = pdrv->lpwPDeviceFlags;
  646. #ifdef WIN95
  647. _asm
  648. {
  649. mov eax, pdflags
  650. bts word ptr [eax], BUSY_BIT
  651. adc byte ptr isbusy,0
  652. }
  653. #else
  654. isbusy -= (InterlockedExchange((LPDWORD)pdflags,
  655. *((LPDWORD)pdflags) | (1<<BUSY_BIT) ) == (1<<BUSY_BIT) );
  656. #endif
  657. if( isbusy )
  658. {
  659. DPF( 1, "BUSY - BltFast" );
  660. LEAVE_BOTH();
  661. return DDERR_SURFACEBUSY;
  662. }
  663. }
  664. /*
  665. * The following code was added to keep all of the HALs from
  666. * changing their Blt() code when they add video port support.
  667. * If the video port was using this surface but was recently
  668. * flipped, we will make sure that the flip actually occurred
  669. * before allowing access. This allows double buffered capture
  670. * w/o tearing.
  671. */
  672. if( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOPORT )
  673. {
  674. LPDDRAWI_DDVIDEOPORT_INT lpVideoPort;
  675. LPDDRAWI_DDVIDEOPORT_LCL lpVideoPort_lcl;
  676. // Look at all video ports to see if any of them recently
  677. // flipped from this surface.
  678. lpVideoPort = pdrv->dvpList;
  679. while( NULL != lpVideoPort )
  680. {
  681. lpVideoPort_lcl = lpVideoPort->lpLcl;
  682. if( lpVideoPort_lcl->fpLastFlip == this_src->fpVidMem )
  683. {
  684. // This can potentially tear - check the flip status
  685. LPDDHALVPORTCB_GETFLIPSTATUS pfn;
  686. DDHAL_GETVPORTFLIPSTATUSDATA GetFlipData;
  687. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  688. pdrv_lcl = this_src_lcl->lpSurfMore->lpDD_lcl;
  689. pfn = pdrv_lcl->lpDDCB->HALDDVideoPort.GetVideoPortFlipStatus;
  690. if( pfn != NULL ) // Will simply tear if function not supproted
  691. {
  692. GetFlipData.lpDD = pdrv_lcl;
  693. GetFlipData.fpSurface = this_src->fpVidMem;
  694. KeepTrying:
  695. rc = DDHAL_DRIVER_NOTHANDLED;
  696. DOHALCALL_NOWIN16( GetVideoPortFlipStatus, pfn, GetFlipData, rc, 0 );
  697. if( ( DDHAL_DRIVER_HANDLED == rc ) &&
  698. ( DDERR_WASSTILLDRAWING == GetFlipData.ddRVal ) )
  699. {
  700. if( dwTrans & DDBLTFAST_WAIT)
  701. {
  702. goto KeepTrying;
  703. }
  704. LEAVE_BOTH_NOBUSY();
  705. return DDERR_WASSTILLDRAWING;
  706. }
  707. }
  708. }
  709. lpVideoPort = lpVideoPort->lpLink;
  710. }
  711. }
  712. RESTART_BLTFAST:
  713. /*
  714. * Remove any cached RLE stuff for source surface
  715. */
  716. if( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
  717. {
  718. extern void FreeRleData(LPDDRAWI_DDRAWSURFACE_LCL psurf); //in fasthel.c
  719. FreeRleData( this_dest_lcl );
  720. }
  721. BUMP_SURFACE_STAMP(this_dest);
  722. /*
  723. * is either surface locked?
  724. */
  725. if( this_src->dwUsageCount > 0 || this_dest->dwUsageCount > 0 )
  726. {
  727. DPF_ERR( "Surface is locked" );
  728. LEAVE_BOTH_NOBUSY()
  729. return DDERR_SURFACEBUSY;
  730. }
  731. /*
  732. * It is possible this function could be called in the middle
  733. * of a mode, in which case we could trash the frame buffer.
  734. * To avoid regression, we will simply succeed the call without
  735. * actually doing anything.
  736. */
  737. if( ( pdrv->dwFlags & DDRAWI_CHANGINGMODE ) &&
  738. !( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) )
  739. {
  740. LEAVE_BOTH_NOBUSY()
  741. return DD_OK;
  742. }
  743. // no restrictions yet
  744. halonly = FALSE;
  745. helonly = FALSE;
  746. gdiblt = FALSE;
  747. // initialize the blit caps according to the surface types
  748. initBltCapsFast( this_dest_lcl->ddsCaps.dwCaps, this_src_lcl->ddsCaps.dwCaps, pdrv, lpbc );
  749. if( !( pdrv->ddCaps.dwCaps & DDCAPS_CANBLTSYSMEM ) &&
  750. ( ( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) ||
  751. ( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) ) )
  752. {
  753. lpbc->bHALSeesSysmem = FALSE;
  754. helonly = TRUE;
  755. #ifdef WINNT
  756. // On NT, the kernel needs to handle blts from system to the primary
  757. // surface, otherwise the sprite stuff won't work
  758. if( ( this_dest->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE ) &&
  759. ( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY ) &&
  760. ( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) )
  761. {
  762. // However, there are several cases that the kernel
  763. // emulation will not handle, so filter these out:
  764. if (((dwTrans & DDBLTFAST_COLORKEY_MASK) == 0) &&
  765. doPixelFormatsMatch(&this_src->ddpfSurface,
  766. &this_dest->lpDD->vmiData.ddpfDisplay))
  767. {
  768. lpbc->bHALSeesSysmem = TRUE;
  769. helonly = FALSE;
  770. }
  771. }
  772. #endif
  773. }
  774. if( ( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM ) &&
  775. ( pdrv->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEMCAPS ) )
  776. {
  777. /*
  778. * All blits where the destination is non-local are emulated,
  779. * unless its sys->NL, in which case we let the driver see it
  780. * if it set DDCAPS2_SYSTONONLOCAL_AS_SYSTOLOCAL.
  781. * initBltFastCaps() set up the correct caps for emulation as
  782. * both surfaces are video memory so all we need to do is to force
  783. * on emulation
  784. */
  785. if (! ((this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  786. (pdrv->ddCaps.dwCaps2 & DDCAPS2_SYSTONONLOCAL_AS_SYSTOLOCAL )) )
  787. {
  788. lpbc->bHALSeesSysmem = FALSE;
  789. helonly = TRUE;
  790. }
  791. }
  792. /*
  793. * check for HEL composition buffer
  794. */
  795. if( (this_dest_lcl->dwFlags & DDRAWISURF_HELCB) ||
  796. (this_src_lcl->dwFlags & DDRAWISURF_HELCB) )
  797. {
  798. lpbc->bHALSeesSysmem = FALSE;
  799. helonly = TRUE;
  800. }
  801. /*
  802. * does the driver even allow bltting?
  803. */
  804. if( !(*(lpbc->dwBothCaps) & DDCAPS_BLT) )
  805. {
  806. BOOL fail;
  807. fail = FALSE;
  808. GETFAILCODEBLT( *(lpbc->dwCaps),
  809. *(lpbc->dwHELCaps),
  810. halonly,
  811. helonly,
  812. DDCAPS_BLT );
  813. if( fail )
  814. {
  815. DPF_ERR( "Blt not supported" );
  816. LEAVE_BOTH_NOBUSY()
  817. return DDERR_NOBLTHW;
  818. }
  819. }
  820. /*
  821. * Check for special cases involving FOURCC surfaces:
  822. * -- Copy blits between surfaces with identical FOURCC formats
  823. * -- Compression/decompression of DXT* compressed textures
  824. */
  825. {
  826. DWORD dwDest4CC = 0;
  827. DWORD dwSrc4CC = 0;
  828. /*
  829. * Does either the source or dest surface have a FOURCC format?
  830. */
  831. if ((this_dest_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT) &&
  832. (this_dest->ddpfSurface.dwFlags & DDPF_FOURCC))
  833. {
  834. dwDest4CC = this_dest->ddpfSurface.dwFourCC; // dest FOURCC format
  835. }
  836. if ((this_src_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT) &&
  837. (this_src->ddpfSurface.dwFlags & DDPF_FOURCC))
  838. {
  839. dwSrc4CC = this_src->ddpfSurface.dwFourCC; // source FOURCC format
  840. }
  841. if (dwDest4CC | dwSrc4CC)
  842. {
  843. /*
  844. * Yes, at least one of the two surfaces has a FOURCC format.
  845. * Do the source and dest surfaces have precisely the same
  846. * FOURCC format? (If so, this is a FOURCC copy blit.)
  847. */
  848. if (dwDest4CC == dwSrc4CC)
  849. {
  850. // Yes, this is a FOURCC copy blit. Can the driver handle this?
  851. if ((pdrv->ddCaps.dwCaps2 & DDCAPS2_COPYFOURCC) == 0)
  852. {
  853. // The driver cannot handle FOURCC copy blits.
  854. helonly = TRUE;
  855. }
  856. }
  857. else
  858. {
  859. /*
  860. * No, the two surfaces have different pixel formats.
  861. * Now determine if either surface has a DXT* FOURCC format.
  862. * The rule for the Blt API call is that the HEL _ALWAYS_
  863. * performs a blit involving a DXT* source or dest surface.
  864. * Hardware acceleration for DXT* blits is available only
  865. * with the AlphaBlt API call. We now enforce this rule:
  866. */
  867. switch (dwDest4CC)
  868. {
  869. case MAKEFOURCC('D','X','T','1'):
  870. case MAKEFOURCC('D','X','T','2'):
  871. case MAKEFOURCC('D','X','T','3'):
  872. case MAKEFOURCC('D','X','T','4'):
  873. case MAKEFOURCC('D','X','T','5'):
  874. // This is a blit to a DXT*-formatted surface.
  875. helonly = TRUE;
  876. break;
  877. default:
  878. break;
  879. }
  880. switch (dwSrc4CC)
  881. {
  882. case MAKEFOURCC('D','X','T','1'):
  883. case MAKEFOURCC('D','X','T','2'):
  884. case MAKEFOURCC('D','X','T','3'):
  885. case MAKEFOURCC('D','X','T','4'):
  886. case MAKEFOURCC('D','X','T','5'):
  887. // This is a blit from a DXT*-formatted surface.
  888. helonly = TRUE;
  889. break;
  890. default:
  891. break;
  892. }
  893. }
  894. }
  895. }
  896. /*
  897. * get src rectangle
  898. */
  899. if( lpSrcRect == NULL )
  900. {
  901. MAKE_SURF_RECT( this_src, this_src_lcl, bd.rSrc );
  902. src_height = this_src->wHeight;
  903. src_width = this_src->wWidth;
  904. }
  905. else
  906. {
  907. bd.rSrc = *(LPRECTL)lpSrcRect;
  908. src_height = (bd.rSrc.bottom-bd.rSrc.top);
  909. src_width = (bd.rSrc.right-bd.rSrc.left);
  910. if( (src_height <= 0) || ((int)src_width <= 0) )
  911. {
  912. DPF_ERR( "BLTFAST error. Can't have non-positive height or width for source rect" );
  913. LEAVE_BOTH_NOBUSY();
  914. return DDERR_INVALIDRECT;
  915. }
  916. // Multi-mon: is this the primary for the desktop? This
  917. // is the only case where the upper-left coord of the surface is not
  918. // (0,0)
  919. if( (this_src->lpDD->dwFlags & DDRAWI_VIRTUALDESKTOP) &&
  920. (this_src_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) )
  921. {
  922. if( (bd.rSrc.left < this_src->lpDD->rectDesktop.left) ||
  923. (bd.rSrc.top < this_src->lpDD->rectDesktop.top) ||
  924. (bd.rSrc.right > this_src->lpDD->rectDesktop.right)||
  925. (bd.rSrc.bottom > this_src->lpDD->rectDesktop.bottom) )
  926. {
  927. DPF_ERR( "BltFast Source dimensions doesn't fit on Desktop" );
  928. LEAVE_BOTH_NOBUSY();
  929. return DDERR_INVALIDRECT;
  930. }
  931. if( OverlapsDevices( this_src_lcl, (LPRECT) &bd.rSrc ) )
  932. {
  933. helonly = gdiblt = TRUE;
  934. }
  935. }
  936. else
  937. {
  938. if( (int)bd.rSrc.left < 0 ||
  939. (int)bd.rSrc.top < 0 ||
  940. (DWORD)bd.rSrc.bottom > (DWORD)this_src->wHeight ||
  941. (DWORD)bd.rSrc.right > (DWORD)this_src->wWidth )
  942. {
  943. DPF_ERR( "Invalid BltFast Source dimensions" );
  944. LEAVE_BOTH_NOBUSY();
  945. return DDERR_INVALIDRECT;
  946. }
  947. }
  948. }
  949. /*
  950. * get destination rectangle
  951. */
  952. bd.rDest.top = dwY;
  953. bd.rDest.left = dwX;
  954. bd.rDest.bottom = dwY + (DWORD) src_height;
  955. bd.rDest.right = dwX + (DWORD) src_width;
  956. /*
  957. * Ensure the destination offsets are valid.
  958. */
  959. // Multi-mon: is this the primary for the desktop? This
  960. // is the only case where the upper-left coord of the surface is not
  961. // (0,0)
  962. if( (pdrv->dwFlags & DDRAWI_VIRTUALDESKTOP) &&
  963. (this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) )
  964. {
  965. if( (bd.rDest.left < pdrv->rectDesktop.left) ||
  966. (bd.rDest.top < pdrv->rectDesktop.top) ||
  967. (bd.rDest.right > pdrv->rectDesktop.right)||
  968. (bd.rDest.bottom > pdrv->rectDesktop.bottom) )
  969. {
  970. DPF_ERR( "BltFast Destination doesn't fit on Desktop And No Clipper was specified" );
  971. LEAVE_BOTH_NOBUSY();
  972. return DDERR_INVALIDRECT;
  973. }
  974. if( OverlapsDevices( this_dest_lcl, (LPRECT) &bd.rDest ) )
  975. {
  976. helonly = gdiblt = TRUE;
  977. }
  978. }
  979. else
  980. {
  981. if( (int)bd.rDest.left < 0 ||
  982. (int)bd.rDest.top < 0 ||
  983. (DWORD)bd.rDest.bottom > (DWORD)this_dest->wHeight ||
  984. (DWORD)bd.rDest.right > (DWORD)this_dest->wWidth )
  985. {
  986. DPF_ERR( "Invalid BltFast destination dimensions" );
  987. LEAVE_BOTH_NOBUSY();
  988. return DDERR_INVALIDRECT;
  989. }
  990. }
  991. /*
  992. * transparent?
  993. */
  994. switch( dwTrans & DDBLTFAST_COLORKEY_MASK )
  995. {
  996. case DDBLTFAST_NOCOLORKEY:
  997. bd.dwFlags = DDBLT_ROP;
  998. break;
  999. case DDBLTFAST_SRCCOLORKEY:
  1000. if( !(this_src_lcl->dwFlags & DDRAWISURF_HASCKEYSRCBLT) )
  1001. {
  1002. DPF_ERR( "No colorkey on source" );
  1003. LEAVE_BOTH_NOBUSY()
  1004. return DDERR_INVALIDPARAMS;
  1005. }
  1006. if( !(*(lpbc->dwBothCKeyCaps) & DDCKEYCAPS_SRCBLT) )
  1007. {
  1008. BOOL fail;
  1009. fail = FALSE;
  1010. GETFAILCODEBLT( *(lpbc->dwCKeyCaps),
  1011. *(lpbc->dwHELCKeyCaps),
  1012. halonly,
  1013. helonly,
  1014. DDCKEYCAPS_SRCBLT );
  1015. if( fail )
  1016. {
  1017. DPF_ERR( "KEYSRC specified, not supported" );
  1018. LEAVE_BOTH_NOBUSY();
  1019. return DDERR_NOCOLORKEYHW;
  1020. }
  1021. }
  1022. bd.bltFX.ddckSrcColorkey = this_src_lcl->ddckCKSrcBlt;
  1023. bd.dwFlags = DDBLT_ROP | DDBLT_KEYSRCOVERRIDE;
  1024. break;
  1025. case DDBLTFAST_DESTCOLORKEY:
  1026. if( !(this_dest_lcl->dwFlags & DDRAWISURF_HASCKEYDESTBLT) )
  1027. {
  1028. DPF_ERR( "No colorkey on dest" );
  1029. LEAVE_BOTH_NOBUSY()
  1030. return DDERR_INVALIDPARAMS;
  1031. }
  1032. if( !(*(lpbc->dwBothCKeyCaps) & DDCKEYCAPS_DESTBLT) )
  1033. {
  1034. BOOL fail;
  1035. fail = FALSE;
  1036. GETFAILCODEBLT( *(lpbc->dwCKeyCaps),
  1037. *(lpbc->dwHELCKeyCaps),
  1038. halonly,
  1039. helonly,
  1040. DDCKEYCAPS_DESTBLT );
  1041. if( fail )
  1042. {
  1043. DPF_ERR( "KEYDEST specified, not supported" );
  1044. LEAVE_BOTH_NOBUSY();
  1045. return DDERR_NOCOLORKEYHW;
  1046. }
  1047. }
  1048. bd.bltFX.ddckDestColorkey = this_dest_lcl->ddckCKDestBlt;
  1049. bd.dwFlags = DDBLT_ROP | DDBLT_KEYDESTOVERRIDE;
  1050. dwDestLockFlags = 0; //this means read/write
  1051. break;
  1052. }
  1053. }
  1054. #ifndef FASTFAST
  1055. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1056. {
  1057. DPF_ERR( "Exception encountered validating parameters" );
  1058. LEAVE_BOTH_NOBUSY()
  1059. return DDERR_INVALIDPARAMS;
  1060. }
  1061. #endif
  1062. /*
  1063. * do the blt
  1064. */
  1065. #ifndef FASTFAST
  1066. TRY
  1067. #endif
  1068. {
  1069. bd.bltFX.dwROP = SRCCOPY;
  1070. bd.lpDDDestSurface = this_dest_lcl;
  1071. bd.lpDDSrcSurface = this_src_lcl;
  1072. if( helonly && halonly )
  1073. {
  1074. DPF_ERR( "BLT not supported in software or hardware" );
  1075. LEAVE_BOTH_NOBUSY()
  1076. return DDERR_NOBLTHW;
  1077. }
  1078. // Did the mode change since ENTER_DDRAW?
  1079. #ifdef WINNT
  1080. if ( DdQueryDisplaySettingsUniqueness() != uDisplaySettingsUnique )
  1081. {
  1082. // mode changed, don't do the blt
  1083. DPF_ERR( "Mode changed between ENTER_DDRAW and HAL call" );
  1084. LEAVE_BOTH_NOBUSY()
  1085. return DDERR_SURFACELOST;
  1086. }
  1087. if( !helonly )
  1088. {
  1089. if (!this_src_lcl->hDDSurface
  1090. && !CompleteCreateSysmemSurface(this_src_lcl))
  1091. {
  1092. DPF_ERR("Can't blt from SYSTEM surface w/o Kernel Object");
  1093. LEAVE_BOTH_NOBUSY()
  1094. return DDERR_GENERIC;
  1095. }
  1096. if (!this_dest_lcl->hDDSurface
  1097. && !CompleteCreateSysmemSurface(this_dest_lcl))
  1098. {
  1099. DPF_ERR("Can't blt to SYSTEM surface w/o Kernel Object");
  1100. LEAVE_BOTH_NOBUSY()
  1101. return DDERR_GENERIC;
  1102. }
  1103. }
  1104. #endif
  1105. if( helonly ) // must be HEL call
  1106. {
  1107. DPF( 4, "Software FastBlt");
  1108. bltfn = pdrv_lcl->lpDDCB->HELDDSurface.Blt;
  1109. // take locks on vram surfaces
  1110. if( ( ( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) == 0) &&
  1111. ( !gdiblt || !( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) ) )
  1112. {
  1113. while( 1 )
  1114. {
  1115. ddrval = InternalLock( this_dest_lcl, &dest_bits, NULL, dwDestLockFlags );
  1116. if( ddrval == DD_OK )
  1117. {
  1118. GET_LPDDRAWSURFACE_GBL_MORE(this_dest)->fpNTAlias = (FLATPTR) dest_bits;
  1119. break;
  1120. }
  1121. if( ddrval == DDERR_WASSTILLDRAWING )
  1122. {
  1123. continue;
  1124. }
  1125. LEAVE_BOTH_NOBUSY()
  1126. return ddrval;
  1127. }
  1128. dest_lock_taken = TRUE;
  1129. }
  1130. else
  1131. {
  1132. /*
  1133. * If either surface was involved in a hardware op, we need to
  1134. * probe the driver to see if it's done. NOTE this assumes
  1135. * that only one driver can be responsible for a system memory
  1136. * operation.
  1137. */
  1138. if( this_dest->dwGlobalFlags & DDRAWISURFGBL_HARDWAREOPSTARTED )
  1139. {
  1140. WaitForDriverToFinishWithSurface(pdrv_lcl, this_dest_lcl );
  1141. }
  1142. dest_lock_taken = FALSE;
  1143. }
  1144. if( (lpDDSrcSurface != lpDDDestSurface) &&
  1145. ( ( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) == 0) )
  1146. {
  1147. if( MoveToSystemMemory( this_src_int, TRUE, FALSE ) == DD_OK )
  1148. {
  1149. /*
  1150. * Don't need to check for continuing hardware op here because
  1151. * MoveToSystemMemory does InternalLock
  1152. */
  1153. src_lock_taken = FALSE;
  1154. }
  1155. else
  1156. {
  1157. while( 1 )
  1158. {
  1159. ddrval = InternalLock( this_src_lcl, &src_bits, NULL, dwSourceLockFlags );
  1160. if( ddrval == DD_OK )
  1161. {
  1162. GET_LPDDRAWSURFACE_GBL_MORE(this_src)->fpNTAlias = (FLATPTR) src_bits;
  1163. break;
  1164. }
  1165. if( ddrval == DDERR_WASSTILLDRAWING )
  1166. {
  1167. continue;
  1168. }
  1169. if( dest_lock_taken )
  1170. {
  1171. InternalUnlock( this_dest_lcl, NULL, NULL, 0 );
  1172. }
  1173. LEAVE_BOTH_NOBUSY()
  1174. return ddrval;
  1175. }
  1176. src_lock_taken = TRUE;
  1177. }
  1178. }
  1179. else
  1180. {
  1181. if( ( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) &&
  1182. (this_src->dwGlobalFlags & DDRAWISURFGBL_HARDWAREOPSTARTED ) )
  1183. {
  1184. WaitForDriverToFinishWithSurface(pdrv_lcl, this_src_lcl );
  1185. }
  1186. src_lock_taken = FALSE;
  1187. }
  1188. }
  1189. else
  1190. {
  1191. DPF( 4, "Hardware FastBlt");
  1192. bltfn = pdrv_lcl->lpDDCB->HALDDSurface.Blt;
  1193. bd.Blt = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.Blt;
  1194. /*
  1195. * Take pagelocks if required.
  1196. * If we take the pagelocks, then the blt becomes synchronous.
  1197. * A failure taking the pagelocks is pretty catastrophic, so no attempt
  1198. * is made to fail over to software.
  1199. */
  1200. lpbc->bSourcePagelockTaken=FALSE;
  1201. lpbc->bDestPagelockTaken=FALSE;
  1202. if ( lpbc->bHALSeesSysmem )
  1203. {
  1204. /*
  1205. * If the HAL requires page locks...
  1206. */
  1207. if ( !( pdrv->ddCaps.dwCaps2 & DDCAPS2_NOPAGELOCKREQUIRED ) )
  1208. {
  1209. HRESULT hr;
  1210. /*
  1211. * ...then setup to take them if they're not already pagelocked.
  1212. */
  1213. if ( ( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY &&
  1214. this_dest_lcl->lpSurfMore->dwPageLockCount == 0 ) )
  1215. {
  1216. hr = InternalPageLock( this_dest_lcl, pdrv_lcl );
  1217. if (FAILED(hr))
  1218. {
  1219. LEAVE_BOTH_NOBUSY()
  1220. return hr;
  1221. }
  1222. else
  1223. {
  1224. lpbc->bDestPagelockTaken=TRUE;
  1225. }
  1226. }
  1227. if ( ( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY &&
  1228. this_src_lcl->lpSurfMore->dwPageLockCount == 0 ))
  1229. {
  1230. hr = InternalPageLock( this_src_lcl, pdrv_lcl );
  1231. if (FAILED(hr))
  1232. {
  1233. if (lpbc->bDestPagelockTaken)
  1234. InternalPageUnlock( this_dest_lcl, pdrv_lcl );
  1235. LEAVE_BOTH_NOBUSY()
  1236. return hr;
  1237. }
  1238. else
  1239. {
  1240. lpbc->bSourcePagelockTaken=TRUE;
  1241. }
  1242. }
  1243. /*
  1244. {
  1245. if (pdrv->dwFlags & DDRAWI_DISPLAYDRV)
  1246. {
  1247. lpbc->bHALSeesSysmem = FALSE;
  1248. helonly = TRUE;
  1249. }
  1250. } */
  1251. }
  1252. }
  1253. }
  1254. bd.lpDD = pdrv;
  1255. bd.bltFX.dwSize = sizeof( bd.bltFX );
  1256. if( this_dest_lcl->lpDDClipper == NULL )
  1257. {
  1258. bd.IsClipped = FALSE; // no clipping in BltFast
  1259. try_again:
  1260. if( helonly )
  1261. {
  1262. // Release busy now or GDI blt will fail
  1263. DONE_BUSY();
  1264. }
  1265. DOHALCALL_NOWIN16( Blt, bltfn, bd, rc, helonly );
  1266. #ifdef WINNT
  1267. if (rc == DDHAL_DRIVER_HANDLED && bd.ddRVal == DDERR_VISRGNCHANGED)
  1268. {
  1269. DPF(5,"Resetting VisRgn for surface %x", this_dest_lcl);
  1270. DdResetVisrgn(this_dest_lcl, (HWND)0);
  1271. goto try_again;
  1272. }
  1273. #endif
  1274. if ( (dwTrans & DDBLTFAST_WAIT) &&
  1275. rc == DDHAL_DRIVER_HANDLED &&
  1276. bd.ddRVal == DDERR_WASSTILLDRAWING )
  1277. {
  1278. DPF(4, "Waiting...");
  1279. goto try_again;
  1280. }
  1281. DPF(5,"Driver returned %08x",bd.ddRVal);
  1282. /*
  1283. * Note that the !helonly here is pretty much an assert.
  1284. * Thought it safer to actually test it, since that is actually what we mean.
  1285. */
  1286. if( !helonly && lpbc->bHALSeesSysmem && rc == DDHAL_DRIVER_HANDLED && bd.ddRVal == DD_OK)
  1287. {
  1288. DPF(5,B,"Tagging surfaces %08x and %08x",this_dest,this_src);
  1289. if( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  1290. this_dest->dwGlobalFlags |= DDRAWISURFGBL_HARDWAREOPDEST;
  1291. if( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  1292. this_src->dwGlobalFlags |= DDRAWISURFGBL_HARDWAREOPSOURCE;
  1293. }
  1294. }
  1295. else
  1296. {
  1297. DPF_ERR( "Can't clip in BltFast" );
  1298. bd.ddRVal = DDERR_BLTFASTCANTCLIP;
  1299. rc = DDHAL_DRIVER_HANDLED;
  1300. }
  1301. if( helonly )
  1302. {
  1303. DONE_LOCKS();
  1304. }
  1305. if( rc != DDHAL_DRIVER_HANDLED )
  1306. {
  1307. /*
  1308. * did the driver run out of hardware color key resources?
  1309. */
  1310. if( (rc == DDHAL_DRIVER_NOCKEYHW) &&
  1311. ((dwTrans & DDBLTFAST_COLORKEY_MASK) == DDBLTFAST_SRCCOLORKEY) )
  1312. {
  1313. ddrval = ChangeToSoftwareColorKey( this_src_int, FALSE );
  1314. if( ddrval == DD_OK )
  1315. {
  1316. halonly = FALSE;
  1317. helonly = FALSE;
  1318. if (lpbc->bSourcePagelockTaken)
  1319. {
  1320. lpbc->bSourcePagelockTaken = FALSE;
  1321. InternalPageUnlock(this_src_lcl, pdrv_lcl);
  1322. }
  1323. if (lpbc->bDestPagelockTaken)
  1324. {
  1325. lpbc->bDestPagelockTaken = FALSE;
  1326. InternalPageUnlock(this_dest_lcl, pdrv_lcl);
  1327. }
  1328. goto RESTART_BLTFAST;
  1329. }
  1330. else
  1331. {
  1332. bd.ddRVal = DDERR_NOCOLORKEYHW;
  1333. }
  1334. }
  1335. else
  1336. {
  1337. bd.ddRVal = DDERR_UNSUPPORTED;
  1338. }
  1339. }
  1340. DONE_BUSY();
  1341. /*
  1342. * Maintain old behaviour for old drivers (which do not export the
  1343. * GetSysmemBltStatus HAL call) and just spin until they're done.
  1344. * Any alternative could exercise new code paths in the driver
  1345. * (e.g. reentered for a DMA operation)
  1346. * We also spin if we had to take either pagelock ourselves.
  1347. */
  1348. if ( lpbc->bHALSeesSysmem &&
  1349. (NULL == pdrv_lcl->lpDDCB->HALDDMiscellaneous.GetSysmemBltStatus || lpbc->bDestPagelockTaken || lpbc->bSourcePagelockTaken)
  1350. )
  1351. {
  1352. if( this_src->dwGlobalFlags & DDRAWISURFGBL_HARDWAREOPSTARTED )
  1353. {
  1354. /*
  1355. * Wait on the destination surface only
  1356. */
  1357. DDASSERT(this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY);
  1358. while (DDERR_WASSTILLDRAWING == InternalGetBltStatus(pdrv_lcl, this_dest_lcl, DDGBS_ISBLTDONE))
  1359. ;
  1360. this_src_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_HARDWAREOPSTARTED;
  1361. this_dest_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_HARDWAREOPSTARTED;
  1362. }
  1363. /*
  1364. * Unpagelock if we took the pagelocks
  1365. */
  1366. if (lpbc->bDestPagelockTaken )
  1367. InternalPageUnlock(this_dest_lcl, pdrv_lcl);
  1368. if (lpbc->bSourcePagelockTaken)
  1369. InternalPageUnlock(this_src_lcl, pdrv_lcl);
  1370. }
  1371. LEAVE_BOTH();
  1372. if(IsD3DManaged(this_dest_lcl))
  1373. {
  1374. LPREGIONLIST lpRegionList = this_dest_lcl->lpSurfMore->lpRegionList;
  1375. MarkDirty(this_dest_lcl);
  1376. if(lpRegionList->rdh.nCount != NUM_RECTS_IN_REGIONLIST)
  1377. {
  1378. lpRegionList->rect[(lpRegionList->rdh.nCount)++] = bd.rDest;
  1379. lpRegionList->rdh.nRgnSize += sizeof(RECT);
  1380. if(bd.rDest.left < lpRegionList->rdh.rcBound.left)
  1381. lpRegionList->rdh.rcBound.left = bd.rDest.left;
  1382. if(bd.rDest.right > lpRegionList->rdh.rcBound.right)
  1383. lpRegionList->rdh.rcBound.right = bd.rDest.right;
  1384. if(bd.rDest.top < lpRegionList->rdh.rcBound.top)
  1385. lpRegionList->rdh.rcBound.top = bd.rDest.top;
  1386. if(bd.rDest.bottom > lpRegionList->rdh.rcBound.bottom)
  1387. lpRegionList->rdh.rcBound.bottom = bd.rDest.bottom;
  1388. }
  1389. }
  1390. return bd.ddRVal;
  1391. }
  1392. #ifndef FASTFAST
  1393. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1394. {
  1395. DPF_ERR( "Exception encountered processing blt" );
  1396. DONE_LOCKS();
  1397. DONE_BUSY();
  1398. /*
  1399. * Maintain old behaviour for old drivers (which do not export the
  1400. * GetSysmemBltStatus HAL call) and just spin until they're done.
  1401. * Any alternative could exercise new code paths in the driver
  1402. * (e.g. reentered for a DMA operation)
  1403. */
  1404. if ( lpbc->bHALSeesSysmem &&
  1405. (NULL == pdrv_lcl->lpDDCB->HALDDMiscellaneous.GetSysmemBltStatus || lpbc->bDestPagelockTaken || lpbc->bSourcePagelockTaken)
  1406. )
  1407. {
  1408. if( this_src->dwGlobalFlags & DDRAWISURFGBL_HARDWAREOPSTARTED )
  1409. {
  1410. /*
  1411. * Wait on the destination surface only
  1412. */
  1413. DDASSERT(this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY);
  1414. while (DDERR_WASSTILLDRAWING == InternalGetBltStatus(pdrv_lcl, this_dest_lcl, DDGBS_ISBLTDONE))
  1415. ;
  1416. this_src_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_HARDWAREOPSTARTED;
  1417. this_dest_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_HARDWAREOPSTARTED;
  1418. }
  1419. /*
  1420. * Unpagelock if we took the pagelocks
  1421. */
  1422. if (lpbc->bDestPagelockTaken )
  1423. InternalPageUnlock(this_dest_lcl, pdrv_lcl);
  1424. if (lpbc->bSourcePagelockTaken)
  1425. InternalPageUnlock(this_src_lcl, pdrv_lcl);
  1426. }
  1427. LEAVE_BOTH();
  1428. return DDERR_EXCEPTION;
  1429. }
  1430. #endif
  1431. } /* DD_Surface_BltFast */
  1432. #undef DPF_MODNAME
  1433. #define DPF_MODNAME "Blt"
  1434. /*
  1435. * ROP table
  1436. *
  1437. * tells which ROPS require pattern surfaces and/or source surfaces
  1438. */
  1439. static char cROPTable[] = {
  1440. 0, // 00 0 BLACKNESS
  1441. ROP_HAS_SOURCEPATTERN, // 01 DPSoon
  1442. ROP_HAS_SOURCEPATTERN, // 02 DPSona
  1443. ROP_HAS_SOURCEPATTERN, // 03 PSon
  1444. ROP_HAS_SOURCEPATTERN, // 04 SDPona
  1445. ROP_HAS_PATTERN, // 05 DPon
  1446. ROP_HAS_SOURCEPATTERN, // 06 PDSxnon
  1447. ROP_HAS_SOURCEPATTERN, // 07 PDSaon
  1448. ROP_HAS_SOURCEPATTERN, // 08 SDPnaa
  1449. ROP_HAS_SOURCEPATTERN, // 09 PDSxon
  1450. ROP_HAS_PATTERN, // 0A DPna
  1451. ROP_HAS_SOURCEPATTERN, // 0B PSDnaon
  1452. ROP_HAS_SOURCEPATTERN, // 0C SPna
  1453. ROP_HAS_SOURCEPATTERN, // 0D PDSnaon
  1454. ROP_HAS_SOURCEPATTERN, // 0E PDSonon
  1455. ROP_HAS_PATTERN, // 0F Pn
  1456. ROP_HAS_SOURCEPATTERN, // 10 PDSona
  1457. ROP_HAS_SOURCE, // 11 DSon NOTSRCERASE
  1458. ROP_HAS_SOURCEPATTERN, // 12 SDPxnon
  1459. ROP_HAS_SOURCEPATTERN, // 13 SDPaon
  1460. ROP_HAS_SOURCEPATTERN, // 14 DPSxnon
  1461. ROP_HAS_SOURCEPATTERN, // 15 DPSaon
  1462. ROP_HAS_SOURCEPATTERN, // 16 PSDPSanaxx
  1463. ROP_HAS_SOURCEPATTERN, // 17 SSPxDSxaxn
  1464. ROP_HAS_SOURCEPATTERN, // 18 SPxPDxa
  1465. ROP_HAS_SOURCEPATTERN, // 19 SDPSanaxn
  1466. ROP_HAS_SOURCEPATTERN, // 1A PDSPaox
  1467. ROP_HAS_SOURCEPATTERN, // 1B SDPSxaxn
  1468. ROP_HAS_SOURCEPATTERN, // 1C PSDPaox
  1469. ROP_HAS_SOURCEPATTERN, // 1D DSPDxaxn
  1470. ROP_HAS_SOURCEPATTERN, // 1E PDSox
  1471. ROP_HAS_SOURCEPATTERN, // 1F PDSoan
  1472. ROP_HAS_SOURCEPATTERN, // 20 DPSnaa
  1473. ROP_HAS_SOURCEPATTERN, // 21 SDPxon
  1474. ROP_HAS_SOURCE, // 22 DSna
  1475. ROP_HAS_SOURCEPATTERN, // 23 SPDnaon
  1476. ROP_HAS_SOURCEPATTERN, // 24 SPxDSxa
  1477. ROP_HAS_SOURCEPATTERN, // 25 PDSPanaxn
  1478. ROP_HAS_SOURCEPATTERN, // 26 SDPSaox
  1479. ROP_HAS_SOURCEPATTERN, // 27 SDPSxnox
  1480. ROP_HAS_SOURCEPATTERN, // 28 DPSxa
  1481. ROP_HAS_SOURCEPATTERN, // 29 PSDPSaoxxn
  1482. ROP_HAS_SOURCEPATTERN, // 2A DPSana
  1483. ROP_HAS_SOURCEPATTERN, // 2B SSPxPDxaxn
  1484. ROP_HAS_SOURCEPATTERN, // 2C SPDSoax
  1485. ROP_HAS_SOURCEPATTERN, // 2D PSDnox
  1486. ROP_HAS_SOURCEPATTERN, // 2E PSDPxox
  1487. ROP_HAS_SOURCEPATTERN, // 2F PSDnoan
  1488. ROP_HAS_SOURCEPATTERN, // 30 PSna
  1489. ROP_HAS_SOURCEPATTERN, // 31 SDPnaon
  1490. ROP_HAS_SOURCEPATTERN, // 32 SDPSoox
  1491. ROP_HAS_SOURCE, // 33 Sn NOTSRCCOPY
  1492. ROP_HAS_SOURCEPATTERN, // 34 SPDSaox
  1493. ROP_HAS_SOURCEPATTERN, // 35 SPDSxnox
  1494. ROP_HAS_SOURCEPATTERN, // 36 SDPox
  1495. ROP_HAS_SOURCEPATTERN, // 37 SDPoan
  1496. ROP_HAS_SOURCEPATTERN, // 38 PSDPoax
  1497. ROP_HAS_SOURCEPATTERN, // 39 SPDnox
  1498. ROP_HAS_SOURCEPATTERN, // 3A SPDSxox
  1499. ROP_HAS_SOURCEPATTERN, // 3B SPDnoan
  1500. ROP_HAS_SOURCEPATTERN, // 3C PSx
  1501. ROP_HAS_SOURCEPATTERN, // 3D SPDSonox
  1502. ROP_HAS_SOURCEPATTERN, // 3E SPDSnaox
  1503. ROP_HAS_SOURCEPATTERN, // 3F PSan
  1504. ROP_HAS_SOURCEPATTERN, // 40 PSDnaa
  1505. ROP_HAS_SOURCEPATTERN, // 41 DPSxon
  1506. ROP_HAS_SOURCEPATTERN, // 42 SDxPDxa
  1507. ROP_HAS_SOURCEPATTERN, // 43 SPDSanaxn
  1508. ROP_HAS_SOURCE, // 44 SDna SRCERASE
  1509. ROP_HAS_SOURCEPATTERN, // 45 DPSnaon
  1510. ROP_HAS_SOURCEPATTERN, // 46 DSPDaox
  1511. ROP_HAS_SOURCEPATTERN, // 47 PSDPxaxn
  1512. ROP_HAS_SOURCEPATTERN, // 48 SDPxa
  1513. ROP_HAS_SOURCEPATTERN, // 49 PDSPDaoxxn
  1514. ROP_HAS_SOURCEPATTERN, // 4A DPSDoax
  1515. ROP_HAS_SOURCEPATTERN, // 4B PDSnox
  1516. ROP_HAS_SOURCEPATTERN, // 4C SDPana
  1517. ROP_HAS_SOURCEPATTERN, // 4D SSPxDSxoxn
  1518. ROP_HAS_SOURCEPATTERN, // 4E PDSPxox
  1519. ROP_HAS_SOURCEPATTERN, // 4F PDSnoan
  1520. ROP_HAS_PATTERN, // 50 PDna
  1521. ROP_HAS_SOURCEPATTERN, // 51 DSPnaon
  1522. ROP_HAS_SOURCEPATTERN, // 52 DPSDaox
  1523. ROP_HAS_SOURCEPATTERN, // 53 SPDSxaxn
  1524. ROP_HAS_SOURCEPATTERN, // 54 DPSonon
  1525. 0, // 55 Dn DSTINVERT
  1526. ROP_HAS_SOURCEPATTERN, // 56 DPSox
  1527. ROP_HAS_SOURCEPATTERN, // 57 DPSoan
  1528. ROP_HAS_SOURCEPATTERN, // 58 PDSPoax
  1529. ROP_HAS_SOURCEPATTERN, // 59 DPSnox
  1530. ROP_HAS_PATTERN, // 5A DPx PATINVERT
  1531. ROP_HAS_SOURCEPATTERN, // 5B DPSDonox
  1532. ROP_HAS_SOURCEPATTERN, // 5C DPSDxox
  1533. ROP_HAS_SOURCEPATTERN, // 5D DPSnoan
  1534. ROP_HAS_SOURCEPATTERN, // 5E DPSDnaox
  1535. ROP_HAS_PATTERN, // 5F DPan
  1536. ROP_HAS_SOURCEPATTERN, // 60 PDSxa
  1537. ROP_HAS_SOURCEPATTERN, // 61 DSPDSaoxxn
  1538. ROP_HAS_SOURCEPATTERN, // 62 DSPDoax
  1539. ROP_HAS_SOURCEPATTERN, // 63 SDPnox
  1540. ROP_HAS_SOURCEPATTERN, // 64 SDPSoax
  1541. ROP_HAS_SOURCEPATTERN, // 65 DSPnox
  1542. ROP_HAS_SOURCE, // 66 DSx SRCINVERT
  1543. ROP_HAS_SOURCEPATTERN, // 67 SDPSonox
  1544. ROP_HAS_SOURCEPATTERN, // 68 DSPDSonoxxn
  1545. ROP_HAS_SOURCEPATTERN, // 69 PDSxxn
  1546. ROP_HAS_SOURCEPATTERN, // 6A DPSax
  1547. ROP_HAS_SOURCEPATTERN, // 6B PSDPSoaxxn
  1548. ROP_HAS_SOURCEPATTERN, // 6C SDPax
  1549. ROP_HAS_SOURCEPATTERN, // 6D PDSPDoaxxn
  1550. ROP_HAS_SOURCEPATTERN, // 6E SDPSnoax
  1551. ROP_HAS_SOURCEPATTERN, // 6F PDSxnan
  1552. ROP_HAS_SOURCEPATTERN, // 70 PDSana
  1553. ROP_HAS_SOURCEPATTERN, // 71 SSDxPDxaxn
  1554. ROP_HAS_SOURCEPATTERN, // 72 SDPSxox
  1555. ROP_HAS_SOURCEPATTERN, // 73 SDPnoan
  1556. ROP_HAS_SOURCEPATTERN, // 74 DSPDxox
  1557. ROP_HAS_SOURCEPATTERN, // 75 DSPnoan
  1558. ROP_HAS_SOURCEPATTERN, // 76 SDPSnaox
  1559. ROP_HAS_SOURCE, // 77 DSan
  1560. ROP_HAS_SOURCEPATTERN, // 78 PDSax
  1561. ROP_HAS_SOURCEPATTERN, // 79 DSPDSoaxxn
  1562. ROP_HAS_SOURCEPATTERN, // 7A DPSDnoax
  1563. ROP_HAS_SOURCEPATTERN, // 7B SDPxnan
  1564. ROP_HAS_SOURCEPATTERN, // 7C SPDSnoax
  1565. ROP_HAS_SOURCEPATTERN, // 7D DPSxnan
  1566. ROP_HAS_SOURCEPATTERN, // 7E SPxDSxo
  1567. ROP_HAS_SOURCEPATTERN, // 7F DPSaan
  1568. ROP_HAS_SOURCEPATTERN, // 80 DPSaa
  1569. ROP_HAS_SOURCEPATTERN, // 81 SPxDSxon
  1570. ROP_HAS_SOURCEPATTERN, // 82 DPSxna
  1571. ROP_HAS_SOURCEPATTERN, // 83 SPDSnoaxn
  1572. ROP_HAS_SOURCEPATTERN, // 84 SDPxna
  1573. ROP_HAS_SOURCEPATTERN, // 85 PDSPnoaxn
  1574. ROP_HAS_SOURCEPATTERN, // 86 DSPDSoaxx
  1575. ROP_HAS_SOURCEPATTERN, // 87 PDSaxn
  1576. ROP_HAS_SOURCE, // 88 DSa SRCAND
  1577. ROP_HAS_SOURCEPATTERN, // 89 SDPSnaoxn
  1578. ROP_HAS_SOURCEPATTERN, // 8A DSPnoa
  1579. ROP_HAS_SOURCEPATTERN, // 8B DSPDxoxn
  1580. ROP_HAS_SOURCEPATTERN, // 8C SDPnoa
  1581. ROP_HAS_SOURCEPATTERN, // 8D SDPSxoxn
  1582. ROP_HAS_SOURCEPATTERN, // 8E SSDxPDxax
  1583. ROP_HAS_SOURCEPATTERN, // 8F PDSanan
  1584. ROP_HAS_SOURCEPATTERN, // 90 PDSxna
  1585. ROP_HAS_SOURCEPATTERN, // 91 SDPSnoaxn
  1586. ROP_HAS_SOURCEPATTERN, // 92 DPSDPoaxx
  1587. ROP_HAS_SOURCEPATTERN, // 93 SPDaxn
  1588. ROP_HAS_SOURCEPATTERN, // 94 PSDPSoaxx
  1589. ROP_HAS_SOURCEPATTERN, // 95 DPSaxn
  1590. ROP_HAS_SOURCEPATTERN, // 96 DPSxx
  1591. ROP_HAS_SOURCEPATTERN, // 97 PSDPSonoxx
  1592. ROP_HAS_SOURCEPATTERN, // 98 SDPSonoxn
  1593. ROP_HAS_SOURCE, // 99 DSxn
  1594. ROP_HAS_SOURCEPATTERN, // 9A DPSnax
  1595. ROP_HAS_SOURCEPATTERN, // 9B SDPSoaxn
  1596. ROP_HAS_SOURCEPATTERN, // 9C SPDnax
  1597. ROP_HAS_SOURCEPATTERN, // 9D DSPDoaxn
  1598. ROP_HAS_SOURCEPATTERN, // 9E DSPDSaoxx
  1599. ROP_HAS_SOURCEPATTERN, // 9F PDSxan
  1600. ROP_HAS_PATTERN, // A0 DPa
  1601. ROP_HAS_SOURCEPATTERN, // A1 PDSPnaoxn
  1602. ROP_HAS_SOURCEPATTERN, // A2 DPSnoa
  1603. ROP_HAS_SOURCEPATTERN, // A3 DPSDxoxn
  1604. ROP_HAS_SOURCEPATTERN, // A4 PDSPonoxn
  1605. ROP_HAS_PATTERN, // A5 PDxn
  1606. ROP_HAS_SOURCEPATTERN, // A6 DSPnax
  1607. ROP_HAS_SOURCEPATTERN, // A7 PDSPoaxn
  1608. ROP_HAS_SOURCEPATTERN, // A8 DPSoa
  1609. ROP_HAS_SOURCEPATTERN, // A9 DPSoxn
  1610. 0, // AA D
  1611. ROP_HAS_SOURCEPATTERN, // AB DPSono
  1612. ROP_HAS_SOURCEPATTERN, // AC SPDSxax
  1613. ROP_HAS_SOURCEPATTERN, // AD DPSDaoxn
  1614. ROP_HAS_SOURCEPATTERN, // AE DSPnao
  1615. ROP_HAS_PATTERN, // AF DPno
  1616. ROP_HAS_SOURCEPATTERN, // B0 PDSnoa
  1617. ROP_HAS_SOURCEPATTERN, // B1 PDSPxoxn
  1618. ROP_HAS_SOURCEPATTERN, // B2 SSPxDSxox
  1619. ROP_HAS_SOURCEPATTERN, // B3 SDPanan
  1620. ROP_HAS_SOURCEPATTERN, // B4 PSDnax
  1621. ROP_HAS_SOURCEPATTERN, // B5 DPSDoaxn
  1622. ROP_HAS_SOURCEPATTERN, // B6 DPSDPaoxx
  1623. ROP_HAS_SOURCEPATTERN, // B7 SDPxan
  1624. ROP_HAS_SOURCEPATTERN, // B8 PSDPxax
  1625. ROP_HAS_SOURCEPATTERN, // B9 DSPDaoxn
  1626. ROP_HAS_SOURCEPATTERN, // BA DPSnao
  1627. ROP_HAS_SOURCE, // BB DSno MERGEPAINT
  1628. ROP_HAS_SOURCEPATTERN, // BC SPDSanax
  1629. ROP_HAS_SOURCEPATTERN, // BD SDxPDxan
  1630. ROP_HAS_SOURCEPATTERN, // BE DPSxo
  1631. ROP_HAS_SOURCEPATTERN, // BF DPSano MERGECOPY
  1632. ROP_HAS_SOURCEPATTERN, // C0 PSa
  1633. ROP_HAS_SOURCEPATTERN, // C1 SPDSnaoxn
  1634. ROP_HAS_SOURCEPATTERN, // C2 SPDSonoxn
  1635. ROP_HAS_SOURCEPATTERN, // C3 PSxn
  1636. ROP_HAS_SOURCEPATTERN, // C4 SPDnoa
  1637. ROP_HAS_SOURCEPATTERN, // C5 SPDSxoxn
  1638. ROP_HAS_SOURCEPATTERN, // C6 SDPnax
  1639. ROP_HAS_SOURCEPATTERN, // C7 PSDPoaxn
  1640. ROP_HAS_SOURCEPATTERN, // C8 SDPoa
  1641. ROP_HAS_SOURCEPATTERN, // C9 SPDoxn
  1642. ROP_HAS_SOURCEPATTERN, // CA DPSDxax
  1643. ROP_HAS_SOURCEPATTERN, // CB SPDSaoxn
  1644. ROP_HAS_SOURCE, // CC S SRCCOPY
  1645. ROP_HAS_SOURCEPATTERN, // CD SDPono
  1646. ROP_HAS_SOURCEPATTERN, // CE SDPnao
  1647. ROP_HAS_SOURCEPATTERN, // CF SPno
  1648. ROP_HAS_SOURCEPATTERN, // D0 PSDnoa
  1649. ROP_HAS_SOURCEPATTERN, // D1 PSDPxoxn
  1650. ROP_HAS_SOURCEPATTERN, // D2 PDSnax
  1651. ROP_HAS_SOURCEPATTERN, // D3 SPDSoaxn
  1652. ROP_HAS_SOURCEPATTERN, // D4 SSPxPDxax
  1653. ROP_HAS_SOURCEPATTERN, // D5 DPSanan
  1654. ROP_HAS_SOURCEPATTERN, // D6 PSDPSaoxx
  1655. ROP_HAS_SOURCEPATTERN, // D7 DPSxan
  1656. ROP_HAS_SOURCEPATTERN, // D8 PDSPxax
  1657. ROP_HAS_SOURCEPATTERN, // D9 SDPSaoxn
  1658. ROP_HAS_SOURCEPATTERN, // DA DPSDanax
  1659. ROP_HAS_SOURCEPATTERN, // DB SPxDSxan
  1660. ROP_HAS_SOURCEPATTERN, // DC SPDnao
  1661. ROP_HAS_SOURCE, // DD SDno
  1662. ROP_HAS_SOURCEPATTERN, // DE SDPxo
  1663. ROP_HAS_SOURCEPATTERN, // DF SDPano
  1664. ROP_HAS_SOURCEPATTERN, // E0 PDSoa
  1665. ROP_HAS_SOURCEPATTERN, // E1 PDSoxn
  1666. ROP_HAS_SOURCEPATTERN, // E2 DSPDxax
  1667. ROP_HAS_SOURCEPATTERN, // E3 PSDPaoxn
  1668. ROP_HAS_SOURCEPATTERN, // E4 SDPSxax
  1669. ROP_HAS_SOURCEPATTERN, // E5 PDSPaoxn
  1670. ROP_HAS_SOURCEPATTERN, // E6 SDPSanax
  1671. ROP_HAS_SOURCEPATTERN, // E7 SPxPDxan
  1672. ROP_HAS_SOURCEPATTERN, // E8 SSPxDSxax
  1673. ROP_HAS_SOURCEPATTERN, // E9 DSPDSanaxxn
  1674. ROP_HAS_SOURCEPATTERN, // EA DPSao
  1675. ROP_HAS_SOURCEPATTERN, // EB DPSxno
  1676. ROP_HAS_SOURCEPATTERN, // EC SDPao
  1677. ROP_HAS_SOURCEPATTERN, // ED SDPxno
  1678. ROP_HAS_SOURCE, // EE DSo SRCPAINT
  1679. ROP_HAS_SOURCEPATTERN, // EF SDPnoo
  1680. ROP_HAS_PATTERN, // F0 P PATCOPY
  1681. ROP_HAS_SOURCEPATTERN, // F1 PDSono
  1682. ROP_HAS_SOURCEPATTERN, // F2 PDSnao
  1683. ROP_HAS_SOURCEPATTERN, // F3 PSno
  1684. ROP_HAS_SOURCEPATTERN, // F4 PSDnao
  1685. ROP_HAS_PATTERN, // F5 PDno
  1686. ROP_HAS_SOURCEPATTERN, // F6 PDSxo
  1687. ROP_HAS_SOURCEPATTERN, // F7 PDSano
  1688. ROP_HAS_SOURCEPATTERN, // F8 PDSao
  1689. ROP_HAS_SOURCEPATTERN, // F9 PDSxno
  1690. ROP_HAS_PATTERN, // FA DPo
  1691. ROP_HAS_SOURCEPATTERN, // FB DPSnoo PATPAINT
  1692. ROP_HAS_SOURCEPATTERN, // FC PSo
  1693. ROP_HAS_SOURCEPATTERN, // FD PSDnoo
  1694. ROP_HAS_SOURCEPATTERN, // FE DPSoo
  1695. 0 // FF 1 WHITENESS
  1696. };
  1697. /*
  1698. * checkBltStretching
  1699. *
  1700. * check and see if we can stretch or not
  1701. */
  1702. HRESULT checkBltStretching(
  1703. LPBLTCAPS lpbc,
  1704. LPSPECIAL_BLT_DATA psbd )
  1705. {
  1706. DWORD caps;
  1707. BOOL fail;
  1708. fail = FALSE;
  1709. /*
  1710. * can we even stretch at all?
  1711. */
  1712. if( !(*(lpbc->dwBothCaps) & DDCAPS_BLTSTRETCH))
  1713. {
  1714. GETFAILCODEBLT( *(lpbc->dwCaps),
  1715. *(lpbc->dwHELCaps),
  1716. psbd->halonly,
  1717. psbd->helonly,
  1718. DDCAPS_BLTSTRETCH );
  1719. if( fail )
  1720. {
  1721. return DDERR_NOSTRETCHHW;
  1722. }
  1723. }
  1724. if (psbd->helonly)
  1725. caps = *(lpbc->dwHELFXCaps);
  1726. else
  1727. caps = *(lpbc->dwFXCaps);
  1728. /*
  1729. * verify height
  1730. */
  1731. if( psbd->src_height != psbd->dest_height )
  1732. {
  1733. if( psbd->src_height > psbd->dest_height )
  1734. {
  1735. /*
  1736. * can we shrink Y arbitrarily?
  1737. */
  1738. if( !(caps & (DDFXCAPS_BLTSHRINKY) ) )
  1739. {
  1740. /*
  1741. * see if this is a non-integer shrink
  1742. */
  1743. if( (psbd->src_height % psbd->dest_height) != 0 )
  1744. {
  1745. GETFAILCODEBLT( *(lpbc->dwFXCaps),
  1746. *(lpbc->dwHELFXCaps),
  1747. psbd->halonly,
  1748. psbd->helonly,
  1749. DDFXCAPS_BLTSHRINKY );
  1750. if( fail )
  1751. {
  1752. return DDERR_NOSTRETCHHW;
  1753. }
  1754. /*
  1755. * see if we can integer shrink
  1756. */
  1757. }
  1758. else if( !(caps & DDFXCAPS_BLTSHRINKYN) )
  1759. {
  1760. GETFAILCODEBLT( *(lpbc->dwFXCaps),
  1761. *(lpbc->dwHELFXCaps),
  1762. psbd->halonly,
  1763. psbd->helonly,
  1764. DDFXCAPS_BLTSHRINKYN );
  1765. if( fail )
  1766. {
  1767. return DDERR_NOSTRETCHHW;
  1768. }
  1769. }
  1770. }
  1771. }
  1772. else
  1773. {
  1774. if( !(caps & DDFXCAPS_BLTSTRETCHY) )
  1775. {
  1776. /*
  1777. * see if this is a non-integer stretch
  1778. */
  1779. if( (psbd->dest_height % psbd->src_height) != 0 )
  1780. {
  1781. GETFAILCODEBLT( *(lpbc->dwFXCaps),
  1782. *(lpbc->dwHELFXCaps),
  1783. psbd->halonly,
  1784. psbd->helonly,
  1785. DDFXCAPS_BLTSTRETCHY );
  1786. if( fail )
  1787. {
  1788. return DDERR_NOSTRETCHHW;
  1789. }
  1790. /*
  1791. * see if we can integer stretch
  1792. */
  1793. }
  1794. else if( !(caps & DDFXCAPS_BLTSTRETCHYN) )
  1795. {
  1796. GETFAILCODEBLT( *(lpbc->dwFXCaps),
  1797. *(lpbc->dwHELFXCaps),
  1798. psbd->halonly,
  1799. psbd->helonly,
  1800. DDFXCAPS_BLTSTRETCHYN );
  1801. if( fail )
  1802. {
  1803. return DDERR_NOSTRETCHHW;
  1804. }
  1805. }
  1806. }
  1807. }
  1808. }
  1809. /*
  1810. * verify width
  1811. */
  1812. if( psbd->src_width != psbd->dest_width )
  1813. {
  1814. if( psbd->src_width > psbd->dest_width )
  1815. {
  1816. if( !(caps & DDFXCAPS_BLTSHRINKX) )
  1817. {
  1818. /*
  1819. * see if this is a non-integer shrink
  1820. */
  1821. if( (psbd->src_width % psbd->dest_width) != 0 )
  1822. {
  1823. GETFAILCODEBLT( *(lpbc->dwFXCaps),
  1824. *(lpbc->dwHELFXCaps),
  1825. psbd->halonly,
  1826. psbd->helonly,
  1827. DDFXCAPS_BLTSHRINKX );
  1828. if( fail )
  1829. {
  1830. return DDERR_NOSTRETCHHW;
  1831. }
  1832. /*
  1833. * see if we can integer shrink
  1834. */
  1835. }
  1836. else if( !(caps & DDFXCAPS_BLTSHRINKXN) )
  1837. {
  1838. GETFAILCODEBLT( *(lpbc->dwFXCaps),
  1839. *(lpbc->dwHELFXCaps),
  1840. psbd->halonly,
  1841. psbd->helonly,
  1842. DDFXCAPS_BLTSHRINKXN );
  1843. if( fail )
  1844. {
  1845. return DDERR_NOSTRETCHHW;
  1846. }
  1847. }
  1848. }
  1849. }
  1850. else
  1851. {
  1852. if( !(caps & DDFXCAPS_BLTSTRETCHX) )
  1853. {
  1854. /*
  1855. * see if this is a non-integer stretch
  1856. */
  1857. if( (psbd->dest_width % psbd->src_width) != 0 )
  1858. {
  1859. GETFAILCODEBLT( *(lpbc->dwFXCaps),
  1860. *(lpbc->dwHELFXCaps),
  1861. psbd->halonly,
  1862. psbd->helonly,
  1863. DDFXCAPS_BLTSTRETCHX );
  1864. if( fail )
  1865. {
  1866. return DDERR_NOSTRETCHHW;
  1867. }
  1868. }
  1869. if( !(caps & DDFXCAPS_BLTSTRETCHXN) )
  1870. {
  1871. GETFAILCODEBLT( *(lpbc->dwFXCaps),
  1872. *(lpbc->dwHELFXCaps),
  1873. psbd->halonly,
  1874. psbd->helonly,
  1875. DDFXCAPS_BLTSTRETCHXN );
  1876. if( fail )
  1877. {
  1878. return DDERR_NOSTRETCHHW;
  1879. }
  1880. }
  1881. }
  1882. }
  1883. }
  1884. return DD_OK;
  1885. } /* checkBltStretching */
  1886. /*
  1887. * FindAttached
  1888. *
  1889. * find an attached surface with particular caps
  1890. */
  1891. LPDDRAWI_DDRAWSURFACE_LCL FindAttached( LPDDRAWI_DDRAWSURFACE_LCL ptr_lcl, DWORD caps )
  1892. {
  1893. LPATTACHLIST pal;
  1894. LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
  1895. pal = ptr_lcl->lpAttachList;
  1896. while( pal != NULL )
  1897. {
  1898. psurf_lcl = pal->lpAttached;
  1899. if( psurf_lcl->ddsCaps.dwCaps & caps )
  1900. {
  1901. return psurf_lcl;
  1902. }
  1903. pal = pal->lpLink;
  1904. }
  1905. return NULL;
  1906. } /* FindAttached */
  1907. #if defined(WIN95)
  1908. #define DONE_EXCLUDE() \
  1909. if( this_dest_lcl->lpDDClipper != NULL ) \
  1910. { \
  1911. if ( (pdrv->dwFlags & DDRAWI_DISPLAYDRV) && pdrv->dwPDevice && \
  1912. !(*pdrv->lpwPDeviceFlags & HARDWARECURSOR)) \
  1913. { \
  1914. DD16_Unexclude(pdrv->dwPDevice); \
  1915. } \
  1916. }
  1917. #elif defined(WINNT)
  1918. #define DONE_EXCLUDE() ;
  1919. #endif
  1920. /*
  1921. * DD_Surface_Blt
  1922. *
  1923. * Bit Blt from one surface to another
  1924. */
  1925. HRESULT DDAPI DD_Surface_Blt(
  1926. LPDIRECTDRAWSURFACE lpDDDestSurface,
  1927. LPRECT lpDestRect,
  1928. LPDIRECTDRAWSURFACE lpDDSrcSurface,
  1929. LPRECT lpSrcRect,
  1930. DWORD dwFlags,
  1931. LPDDBLTFX lpDDBltFX )
  1932. {
  1933. DWORD rc;
  1934. DWORD rop;
  1935. LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
  1936. LPDDRAWI_DDRAWSURFACE_INT psurf_int;
  1937. LPDDRAWI_DDRAWSURFACE_LCL this_src_lcl;
  1938. LPDDRAWI_DDRAWSURFACE_LCL this_dest_lcl;
  1939. LPDDRAWI_DDRAWSURFACE_GBL this_src;
  1940. LPDDRAWI_DDRAWSURFACE_GBL this_dest;
  1941. LPDDRAWI_DDRAWSURFACE_INT this_src_int;
  1942. LPDDRAWI_DDRAWSURFACE_INT this_dest_int;
  1943. BOOL need_pat;
  1944. SPECIAL_BLT_DATA sbd;
  1945. BOOL stretch_blt;
  1946. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  1947. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  1948. DDHAL_BLTDATA bd;
  1949. RECT DestRect;
  1950. BOOL fail;
  1951. BOOL dest_lock_taken=FALSE;
  1952. BOOL src_lock_taken=FALSE;
  1953. BOOL dest_pagelock_taken=FALSE;
  1954. BOOL src_pagelock_taken=FALSE;
  1955. LPVOID dest_bits;
  1956. LPVOID src_bits;
  1957. HRESULT ddrval;
  1958. BLTCAPS bc;
  1959. LPBLTCAPS lpbc=&bc;
  1960. LPWORD pdflags=0;
  1961. DWORD dwSourceLockFlags=0;
  1962. DWORD dwDestLockFlags=0;
  1963. BOOL gdiblt;
  1964. LPDDPIXELFORMAT pddpf;
  1965. BOOL subrect_lock_taken = FALSE;
  1966. RECT subrect_lock_rect;
  1967. ENTER_BOTH();
  1968. DPF(2,A,"ENTERAPI: DD_Surface_Blt");
  1969. TRY
  1970. {
  1971. ZeroMemory(&bd, sizeof(bd)); // initialize to zero
  1972. /*
  1973. * validate surface ptrs
  1974. */
  1975. this_dest_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDDestSurface;
  1976. this_src_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSrcSurface;
  1977. if( !VALID_DIRECTDRAWSURFACE_PTR( this_dest_int ) )
  1978. {
  1979. DPF_ERR( "Invalid dest specified") ;
  1980. LEAVE_BOTH();
  1981. return DDERR_INVALIDOBJECT;
  1982. }
  1983. this_dest_lcl = this_dest_int->lpLcl;
  1984. this_dest = this_dest_lcl->lpGbl;
  1985. if( SURFACE_LOST( this_dest_lcl ) )
  1986. {
  1987. DPF( 1, "Dest lost") ;
  1988. LEAVE_BOTH();
  1989. return DDERR_SURFACELOST;
  1990. }
  1991. if( this_src_int != NULL )
  1992. {
  1993. if( !VALID_DIRECTDRAWSURFACE_PTR( this_src_int ) )
  1994. {
  1995. DPF_ERR( "Invalid source specified" );
  1996. LEAVE_BOTH();
  1997. return DDERR_INVALIDOBJECT;
  1998. }
  1999. this_src_lcl = this_src_int->lpLcl;
  2000. this_src = this_src_lcl->lpGbl;
  2001. if( SURFACE_LOST( this_src_lcl ) )
  2002. {
  2003. DPF_ERR( "Src lost") ;
  2004. LEAVE_BOTH();
  2005. return DDERR_SURFACELOST;
  2006. }
  2007. }
  2008. else
  2009. {
  2010. this_src_lcl = NULL;
  2011. this_src = NULL;
  2012. }
  2013. if ( ( DDBLT_DX8ORHIGHER & dwFlags ) && ( DDBLT_WINDOWCLIP & dwFlags ) )
  2014. {
  2015. LPDDRAWI_DDRAWCLIPPER_INT lpDDIClipper =
  2016. this_dest_lcl->lpSurfMore->lpDDIClipper;
  2017. if (lpDDIClipper && (DDSCAPS_PRIMARYSURFACE &
  2018. this_dest_lcl->ddsCaps.dwCaps))
  2019. {
  2020. HWND hWnd = (HWND)lpDDIClipper->lpLcl->lpGbl->hWnd;
  2021. if (GetClientRect(hWnd, &DestRect))
  2022. {
  2023. if(( lpDestRect != NULL ) && VALID_RECT_PTR( lpDestRect ))
  2024. {
  2025. if (DestRect.right > lpDestRect->right)
  2026. DestRect.right = lpDestRect->right;
  2027. if (DestRect.bottom > lpDestRect->bottom)
  2028. DestRect.bottom = lpDestRect->bottom;
  2029. if (0 < lpDestRect->left)
  2030. DestRect.left = lpDestRect->left;
  2031. if (0 < lpDestRect->top)
  2032. DestRect.top = lpDestRect->top;
  2033. if (DestRect.top >= DestRect.bottom ||
  2034. DestRect.left >= DestRect.right)
  2035. {
  2036. // in case of insane RECT, fail it
  2037. DPF_ERR("Unable to Blt with invalid dest RECT");
  2038. LEAVE_BOTH();
  2039. return DDERR_INVALIDPARAMS;
  2040. }
  2041. }
  2042. if (!ClientToScreen(hWnd,(POINT*)&DestRect))
  2043. DPF_ERR("ClientToScreen Failed on DestRect?");
  2044. if (!ClientToScreen(hWnd,(POINT*)&DestRect.right))
  2045. DPF_ERR("ClientToScreen Failed on DestRect.right?");
  2046. // in DX8 we always have DDRAWILCL_EXPLICITMONITOR so
  2047. // DestRect must be checked and adjusted against DeviceRect
  2048. pdrv = this_dest->lpDD;
  2049. /*
  2050. * Do a real quick check w/o accounting for the clipper
  2051. */
  2052. if( ( DestRect.top < pdrv->rectDevice.top ) ||
  2053. ( DestRect.left < pdrv->rectDevice.left ) ||
  2054. ( DestRect.right > pdrv->rectDevice.right ) ||
  2055. ( DestRect.bottom > pdrv->rectDevice.bottom ) )
  2056. {
  2057. RECT rect;
  2058. /*
  2059. * It may only be that part of the rect is off of the desktop,
  2060. * in which case we don't neccesarily need to drop to emulation.
  2061. */
  2062. IntersectRect( &rect, &DestRect, &pdrv->rectDesktop );
  2063. if( ( rect.top < pdrv->rectDevice.top ) ||
  2064. ( rect.left < pdrv->rectDevice.left ) ||
  2065. ( rect.right > pdrv->rectDevice.right ) ||
  2066. ( rect.bottom > pdrv->rectDevice.bottom ) )
  2067. {
  2068. // fail crossdevice blt and let GDI do it in DdBlt()
  2069. LEAVE_BOTH();
  2070. return DDERR_INVALIDPARAMS;
  2071. }
  2072. }
  2073. if (!OffsetRect(&DestRect, -pdrv->rectDevice.left,
  2074. -pdrv->rectDevice.top))
  2075. DPF_ERR("OffsetRect Failed on DestRect?");
  2076. lpDestRect = &DestRect; // replace it with new Rect
  2077. DPF(10,"Got a new dest RECT !!");
  2078. if (DDBLT_COPYVSYNC & dwFlags)
  2079. {
  2080. DWORD msCurrentTime = 0;
  2081. DWORD msStartTime = GetTickCount();
  2082. LPDDHAL_GETSCANLINE gslhalfn;
  2083. LPDDHAL_GETSCANLINE gslfn;
  2084. LPDDRAWI_DIRECTDRAW_LCL this_lcl =
  2085. this_dest_lcl->lpSurfMore->lpDD_lcl;
  2086. gslfn = this_lcl->lpDDCB->HALDD.GetScanLine;
  2087. gslhalfn = this_lcl->lpDDCB->cbDDCallbacks.GetScanLine;
  2088. if( gslhalfn != NULL )
  2089. {
  2090. DDHAL_GETSCANLINEDATA gsld;
  2091. DWORD rc;
  2092. gsld.GetScanLine = gslhalfn;
  2093. gsld.lpDD = this_lcl->lpGbl;
  2094. do
  2095. {
  2096. DOHALCALL_NOWIN16( GetScanLine, gslfn, gsld, rc, FALSE );
  2097. if ( DD_OK != gsld.ddRVal )
  2098. break;
  2099. if ( (LONG)gsld.dwScanLine >= DestRect.bottom )
  2100. break;
  2101. msCurrentTime = GetTickCount();
  2102. // If we've been spinning here for 30ms
  2103. // then blt anyway; probably something
  2104. // taking up CPU cycles
  2105. if ( (msCurrentTime - msStartTime) > 30 )
  2106. {
  2107. break;
  2108. }
  2109. } while ( DDHAL_DRIVER_HANDLED == rc );
  2110. }
  2111. }
  2112. }
  2113. else
  2114. {
  2115. DPF_ERR("GetClientRect Failed ?");
  2116. }
  2117. }
  2118. // Don't let these DX8-only flags propagate to driver (or rest of Blt code)
  2119. // since they alias other existing flags.
  2120. dwFlags &= ~(DDBLT_WINDOWCLIP | DDBLT_COPYVSYNC | DDBLT_DX8ORHIGHER);
  2121. }
  2122. if( dwFlags & ~DDBLT_VALID )
  2123. {
  2124. DPF_ERR( "Invalid flags") ;
  2125. LEAVE_BOTH();
  2126. return DDERR_INVALIDPARAMS;
  2127. }
  2128. /*
  2129. * BEHAVIOUR CHANGE FOR DX5
  2130. *
  2131. * We do not allow bltting between surfaces created with different DirectDraw
  2132. * objects.
  2133. */
  2134. if (this_src)
  2135. {
  2136. if (this_dest_lcl->lpSurfMore->lpDD_lcl->lpGbl != this_src_lcl->lpSurfMore->lpDD_lcl->lpGbl)
  2137. {
  2138. if ((this_dest_lcl->lpSurfMore->lpDD_lcl->lpGbl->dwFlags & DDRAWI_DISPLAYDRV) &&
  2139. (this_src_lcl->lpSurfMore->lpDD_lcl->lpGbl->dwFlags & DDRAWI_DISPLAYDRV))
  2140. {
  2141. DPF_ERR("Can't blt surfaces between different direct draw devices");
  2142. LEAVE_BOTH();
  2143. return DDERR_DEVICEDOESNTOWNSURFACE;
  2144. }
  2145. }
  2146. }
  2147. //
  2148. // If either surface is optimized, quit
  2149. //
  2150. if (this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  2151. {
  2152. DPF_ERR( "Can't blt optimized surfaces") ;
  2153. LEAVE_BOTH();
  2154. return DDERR_INVALIDPARAMS;
  2155. }
  2156. if (this_src)
  2157. {
  2158. if (this_src_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  2159. {
  2160. DPF_ERR( "Can't blt optimized surfaces") ;
  2161. LEAVE_BOTH();
  2162. return DDERR_INVALIDPARAMS;
  2163. }
  2164. }
  2165. /*
  2166. * Since Z Blts are currently turned off, we might as well give some
  2167. * hint that this is the case.
  2168. */
  2169. #ifdef DEBUG
  2170. if( dwFlags & ( DDBLT_ZBUFFER | DDBLT_ZBUFFERDESTCONSTOVERRIDE |
  2171. DDBLT_ZBUFFERDESTOVERRIDE | DDBLT_ZBUFFERSRCCONSTOVERRIDE |
  2172. DDBLT_ZBUFFERSRCOVERRIDE ) )
  2173. {
  2174. DPF_ERR( "Z aware BLTs are not currently supported" );
  2175. LEAVE_BOTH();
  2176. return DDERR_NOZBUFFERHW;
  2177. }
  2178. #endif
  2179. pdrv = this_dest->lpDD;
  2180. pdrv_lcl = this_dest_lcl->lpSurfMore->lpDD_lcl;
  2181. #ifdef WINNT
  2182. // Update DDraw handle in driver GBL object.
  2183. pdrv->hDD = pdrv_lcl->hDD;
  2184. #endif
  2185. /*
  2186. * DX5 or greater drivers get to know about read/write only locks
  2187. * Note that dwDestFlags may later be modified for dest color key.
  2188. * Pass zero for both flags unless:
  2189. * -it's a color fill, in which case turn on writeonly for dest.
  2190. * -the blt goes from/to different surfaces,
  2191. */
  2192. if ( (pdrv->dwInternal1 >= 0x500)
  2193. && ((this_src == NULL) || (this_src != this_dest) ) )
  2194. {
  2195. dwSourceLockFlags = DDLOCK_READONLY;
  2196. dwDestLockFlags = DDLOCK_WRITEONLY;
  2197. }
  2198. }
  2199. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2200. {
  2201. DPF_ERR( "Exception encountered validating parameters" );
  2202. LEAVE_BOTH();
  2203. return DDERR_INVALIDPARAMS;
  2204. }
  2205. #ifdef USE_ALIAS
  2206. if( pdrv->dwBusyDueToAliasedLock > 0 )
  2207. {
  2208. /*
  2209. * Aliased locks (the ones that don't take the Win16 lock) don't
  2210. * set the busy bit either (it can't or USER get's very confused).
  2211. * However, we must prevent blits happening via DirectDraw as
  2212. * otherwise we get into the old host talking to VRAM while
  2213. * blitter does at the same time. Bad. So fail if there is an
  2214. * outstanding aliased lock just as if the BUST bit had been
  2215. * set.
  2216. */
  2217. DPF_ERR( "Graphics adapter is busy (due to a DirectDraw lock)" );
  2218. LEAVE_BOTH();
  2219. return DDERR_SURFACEBUSY;
  2220. }
  2221. #endif /* USE_ALIAS */
  2222. /*
  2223. * Behavior change: In DX7, the default is to wait unless DDBLT_DONOTWAIT=1.
  2224. * In earlier releases, the default was to NOT wait unless DDBLT_WAIT=1.
  2225. * (The DDBLT_DONOTWAIT flag was not defined until the DX7 release.)
  2226. */
  2227. if (!LOWERTHANSURFACE7(this_dest_int))
  2228. {
  2229. if (dwFlags & DDBLT_DONOTWAIT)
  2230. {
  2231. if (dwFlags & DDBLT_WAIT)
  2232. {
  2233. DPF_ERR( "WAIT and DONOTWAIT flags are mutually exclusive" );
  2234. LEAVE_BOTH();
  2235. return DDERR_INVALIDPARAMS;
  2236. }
  2237. }
  2238. else
  2239. {
  2240. dwFlags |= DDBLT_WAIT;
  2241. }
  2242. }
  2243. if(this_src_lcl)
  2244. FlushD3DStates(this_src_lcl); // Need to flush src because it could be a rendertarget
  2245. FlushD3DStates(this_dest_lcl);
  2246. // Test and set the busy bit. If it was already set, bail.
  2247. {
  2248. BOOL isbusy = 0;
  2249. pdflags = pdrv->lpwPDeviceFlags;
  2250. #ifdef WIN95
  2251. _asm
  2252. {
  2253. mov eax, pdflags
  2254. bts word ptr [eax], BUSY_BIT
  2255. adc byte ptr isbusy,0
  2256. }
  2257. #else
  2258. isbusy -= (InterlockedExchange((LPDWORD)pdflags,
  2259. *((LPDWORD)pdflags) | (1<<BUSY_BIT) ) == (1<<BUSY_BIT) );
  2260. #endif
  2261. if( isbusy )
  2262. {
  2263. DPF( 1, "BUSY - Blt" );
  2264. LEAVE_BOTH();
  2265. return DDERR_SURFACEBUSY;
  2266. }
  2267. }
  2268. /*
  2269. * The following code was added to keep all of the HALs from
  2270. * changing their Blt() code when they add video port support.
  2271. * If the video port was using this surface but was recently
  2272. * flipped, we will make sure that the flip actually occurred
  2273. * before allowing access. This allows double buffered capture
  2274. * w/o tearing.
  2275. */
  2276. if( ( this_src_lcl != NULL ) &&
  2277. ( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOPORT ) )
  2278. {
  2279. LPDDRAWI_DDVIDEOPORT_INT lpVideoPort;
  2280. LPDDRAWI_DDVIDEOPORT_LCL lpVideoPort_lcl;
  2281. // Look at all video ports to see if any of them recently
  2282. // flipped from this surface.
  2283. lpVideoPort = pdrv->dvpList;
  2284. while( NULL != lpVideoPort )
  2285. {
  2286. lpVideoPort_lcl = lpVideoPort->lpLcl;
  2287. if( lpVideoPort_lcl->fpLastFlip == this_src->fpVidMem )
  2288. {
  2289. // This can potentially tear - check the flip status
  2290. LPDDHALVPORTCB_GETFLIPSTATUS pfn;
  2291. DDHAL_GETVPORTFLIPSTATUSDATA GetFlipData;
  2292. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  2293. pdrv_lcl = this_src_lcl->lpSurfMore->lpDD_lcl;
  2294. pfn = pdrv_lcl->lpDDCB->HALDDVideoPort.GetVideoPortFlipStatus;
  2295. if( pfn != NULL ) // Will simply tear if function not supproted
  2296. {
  2297. GetFlipData.lpDD = pdrv_lcl;
  2298. GetFlipData.fpSurface = this_src->fpVidMem;
  2299. KeepTrying:
  2300. rc = DDHAL_DRIVER_NOTHANDLED;
  2301. DOHALCALL_NOWIN16( GetVideoPortFlipStatus, pfn, GetFlipData, rc, 0 );
  2302. if( ( DDHAL_DRIVER_HANDLED == rc ) &&
  2303. ( DDERR_WASSTILLDRAWING == GetFlipData.ddRVal ) )
  2304. {
  2305. if( dwFlags & DDBLT_WAIT)
  2306. {
  2307. goto KeepTrying;
  2308. }
  2309. LEAVE_BOTH_NOBUSY();
  2310. return DDERR_WASSTILLDRAWING;
  2311. }
  2312. }
  2313. }
  2314. lpVideoPort = lpVideoPort->lpLink;
  2315. }
  2316. }
  2317. RESTART_BLT:
  2318. TRY
  2319. {
  2320. /*
  2321. * Remove any cached RLE stuff for source surface
  2322. */
  2323. if( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
  2324. {
  2325. extern void FreeRleData(LPDDRAWI_DDRAWSURFACE_LCL psurf); //in fasthel.c
  2326. FreeRleData( this_dest_lcl );
  2327. }
  2328. /*
  2329. * is either surface locked?
  2330. */
  2331. if( (this_dest->dwUsageCount > 0) ||
  2332. ((this_src != NULL) && (this_src->dwUsageCount > 0)) )
  2333. {
  2334. DPF_ERR( "Surface is locked" );
  2335. LEAVE_BOTH_NOBUSY();
  2336. return DDERR_SURFACEBUSY;
  2337. }
  2338. BUMP_SURFACE_STAMP(this_dest);
  2339. /*
  2340. * It is possible this function could be called in the middle
  2341. * of a mode, in which case we could trash the frame buffer.
  2342. * To avoid regression, we will simply succeed the call without
  2343. * actually doing anything.
  2344. */
  2345. if( ( pdrv->dwFlags & DDRAWI_CHANGINGMODE ) &&
  2346. !( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) )
  2347. {
  2348. LEAVE_BOTH_NOBUSY()
  2349. return DD_OK;
  2350. }
  2351. sbd.halonly = FALSE;
  2352. sbd.helonly = FALSE;
  2353. gdiblt = FALSE;
  2354. if( this_src != NULL )
  2355. {
  2356. // initialize the blit caps according to the surface types
  2357. initBltCaps(
  2358. this_dest_lcl->ddsCaps.dwCaps,
  2359. this_dest->dwGlobalFlags,
  2360. this_src_lcl->ddsCaps.dwCaps, pdrv, lpbc, &(sbd.helonly) );
  2361. }
  2362. else
  2363. {
  2364. // no source surface, use vram->vram caps and determine hal or hel
  2365. // based on system memory status of destination surface
  2366. // if the destination is non-local we also force emulation as we
  2367. // don't currently support accelerated operation with non-local
  2368. // video memory are a target
  2369. initBltCaps( DDSCAPS_VIDEOMEMORY, 0, DDSCAPS_VIDEOMEMORY, pdrv, lpbc, &sbd.helonly );
  2370. if( ( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) ||
  2371. ( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM ) )
  2372. {
  2373. lpbc->bHALSeesSysmem = FALSE;
  2374. sbd.helonly = TRUE;
  2375. }
  2376. }
  2377. fail = FALSE;
  2378. /*
  2379. * can we really blt?
  2380. */
  2381. if( !(*(lpbc->dwBothCaps) & DDCAPS_BLT) )
  2382. {
  2383. if( *(lpbc->dwCaps) & DDCAPS_BLT )
  2384. {
  2385. sbd.halonly = TRUE;
  2386. }
  2387. else if( *(lpbc->dwHELCaps) & DDCAPS_BLT )
  2388. {
  2389. lpbc->bHALSeesSysmem = FALSE;
  2390. sbd.helonly = TRUE;
  2391. }
  2392. else
  2393. {
  2394. DPF_ERR( "Driver does not support Blt" );
  2395. LEAVE_BOTH_NOBUSY();
  2396. return DDERR_NOBLTHW;
  2397. }
  2398. }
  2399. /*
  2400. * Check for special cases involving FOURCC surfaces:
  2401. * -- Copy blits between surfaces with identical FOURCC formats
  2402. * -- Compression/decompression of DXT* compressed textures
  2403. */
  2404. {
  2405. DWORD dwDest4CC = 0;
  2406. DWORD dwSrc4CC = 0;
  2407. /*
  2408. * Does either the source or dest surface have a FOURCC format?
  2409. */
  2410. if ((this_dest_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT) &&
  2411. (this_dest->ddpfSurface.dwFlags & DDPF_FOURCC))
  2412. {
  2413. dwDest4CC = this_dest->ddpfSurface.dwFourCC; // dest FOURCC format
  2414. }
  2415. if ((this_src_lcl != NULL) &&
  2416. (this_src_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT) &&
  2417. (this_src->ddpfSurface.dwFlags & DDPF_FOURCC))
  2418. {
  2419. dwSrc4CC = this_src->ddpfSurface.dwFourCC; // source FOURCC format
  2420. }
  2421. if (dwDest4CC | dwSrc4CC)
  2422. {
  2423. /*
  2424. * Yes, at least one of the two surfaces has a FOURCC format.
  2425. * Do the source and dest surfaces have precisely the same
  2426. * FOURCC format? (If so, this is a FOURCC copy blit.)
  2427. */
  2428. if (dwDest4CC == dwSrc4CC)
  2429. {
  2430. // Yes, this is a FOURCC copy blit. Can the driver handle this?
  2431. if ((pdrv->ddCaps.dwCaps2 & DDCAPS2_COPYFOURCC) == 0)
  2432. {
  2433. // The driver cannot handle FOURCC copy blits.
  2434. sbd.helonly = TRUE;
  2435. }
  2436. }
  2437. else
  2438. {
  2439. /*
  2440. * No, the two surfaces have different pixel formats.
  2441. * Now determine if either surface has a DXT* FOURCC format.
  2442. * The rule for the Blt API call is that the HEL _ALWAYS_
  2443. * performs a blit involving a DXT* source or dest surface.
  2444. * Hardware acceleration for DXT* blits is available only
  2445. * with the AlphaBlt API call. We now enforce this rule:
  2446. */
  2447. switch (dwDest4CC)
  2448. {
  2449. case MAKEFOURCC('D','X','T','1'):
  2450. case MAKEFOURCC('D','X','T','2'):
  2451. case MAKEFOURCC('D','X','T','3'):
  2452. case MAKEFOURCC('D','X','T','4'):
  2453. case MAKEFOURCC('D','X','T','5'):
  2454. // This is a blit to a DXT*-formatted surface.
  2455. sbd.helonly = TRUE;
  2456. break;
  2457. default:
  2458. break;
  2459. }
  2460. switch (dwSrc4CC)
  2461. {
  2462. case MAKEFOURCC('D','X','T','1'):
  2463. case MAKEFOURCC('D','X','T','2'):
  2464. case MAKEFOURCC('D','X','T','3'):
  2465. case MAKEFOURCC('D','X','T','4'):
  2466. case MAKEFOURCC('D','X','T','5'):
  2467. // This is a blit from a DXT*-formatted surface.
  2468. sbd.helonly = TRUE;
  2469. break;
  2470. default:
  2471. break;
  2472. }
  2473. }
  2474. }
  2475. }
  2476. /*
  2477. * check for HEL composition buffer
  2478. */
  2479. if( (this_dest_lcl->dwFlags & DDRAWISURF_HELCB) ||
  2480. ((this_src_lcl != NULL) && (this_src_lcl->dwFlags & DDRAWISURF_HELCB)) )
  2481. {
  2482. lpbc->bHALSeesSysmem = FALSE;
  2483. sbd.helonly = TRUE;
  2484. }
  2485. bd.lpDD = pdrv;
  2486. /*
  2487. * make sure BltFX struct is OK
  2488. */
  2489. bd.bltFX.dwSize = sizeof( bd.bltFX );
  2490. if( lpDDBltFX != NULL )
  2491. {
  2492. if( !VALID_DDBLTFX_PTR( lpDDBltFX ) )
  2493. {
  2494. DPF_ERR( "Invalid BLTFX specified" );
  2495. LEAVE_BOTH_NOBUSY();
  2496. return DDERR_INVALIDPARAMS;
  2497. }
  2498. }
  2499. else
  2500. {
  2501. if( dwFlags & ( DDBLT_ALPHASRCCONSTOVERRIDE |
  2502. DDBLT_ALPHADESTCONSTOVERRIDE |
  2503. DDBLT_ALPHASRCSURFACEOVERRIDE |
  2504. DDBLT_ALPHADESTSURFACEOVERRIDE |
  2505. DDBLT_COLORFILL |
  2506. DDBLT_DDFX |
  2507. DDBLT_DDROPS |
  2508. DDBLT_DEPTHFILL |
  2509. DDBLT_KEYDESTOVERRIDE |
  2510. DDBLT_KEYSRCOVERRIDE |
  2511. DDBLT_ROP |
  2512. DDBLT_ROTATIONANGLE |
  2513. DDBLT_ZBUFFERDESTCONSTOVERRIDE |
  2514. DDBLT_ZBUFFERDESTOVERRIDE |
  2515. DDBLT_ZBUFFERSRCCONSTOVERRIDE |
  2516. DDBLT_ZBUFFERSRCOVERRIDE ) )
  2517. {
  2518. DPF_ERR( "BltFX required but not specified" );
  2519. LEAVE_BOTH_NOBUSY();
  2520. return DDERR_INVALIDPARAMS;
  2521. }
  2522. }
  2523. /*
  2524. * make sure flags & associated bd.bltFX are specified OK
  2525. */
  2526. need_pat = FALSE;
  2527. if( dwFlags & ~DDBLT_WAIT )
  2528. {
  2529. /*
  2530. * isolate lower use tests together
  2531. */
  2532. if( dwFlags & (DDBLT_KEYSRCOVERRIDE|
  2533. DDBLT_KEYDESTOVERRIDE|
  2534. DDBLT_KEYSRC |
  2535. DDBLT_KEYDEST ) )
  2536. {
  2537. #pragma message( REMIND( "Alpha turned off in Rev 1" ) )
  2538. #pragma message( REMIND( "Set read/write flags for alpha and Z" ) )
  2539. #if 0
  2540. /*
  2541. * verify ALPHA
  2542. */
  2543. if( dwFlags & DDBLT_ANYALPHA )
  2544. {
  2545. BOOL no_alpha;
  2546. no_alpha = TRUE;
  2547. // check to see if alpha is supported
  2548. if( !(*(lpbc->dwBothCaps) & DDCAPS_ALPHA) )
  2549. {
  2550. GETFAILCODEBLT( *(lpbc->dwCaps),
  2551. *(lpbc->dwHELCaps),
  2552. sbd.halonly,
  2553. sbd.helonly,
  2554. DDCAPS_ALPHA );
  2555. if( fail )
  2556. {
  2557. DPF_ERR( "Alpha blt requested, not supported" );
  2558. LEAVE_BOTH_NOBUSY();
  2559. return DDERR_NOALPHAHW;
  2560. }
  2561. }
  2562. /*
  2563. * dest alpha
  2564. */
  2565. if( dwFlags & DDBLT_ALPHADEST )
  2566. {
  2567. if( dwFlags & ( DDBLT_ALPHADESTCONSTOVERRIDE |
  2568. DDBLT_ALPHADESTSURFACEOVERRIDE) )
  2569. {
  2570. DPF_ERR( "ALPHADEST and other alpha dests specified" );
  2571. LEAVE_BOTH_NOBUSY();
  2572. return DDERR_INVALIDPARAMS;
  2573. }
  2574. psurf_lcl = FindAttached( this_dest_lcl, DDSCAPS_ALPHA );
  2575. if( psurf_lcl == NULL )
  2576. {
  2577. DPF_ERR( "ALPHADEST requires an attached alpha to the dest" );
  2578. LEAVE_BOTH_NOBUSY();
  2579. return DDERR_INVALIDPARAMS;
  2580. }
  2581. dwFlags &= ~DDBLT_ALPHADEST;
  2582. dwFlags |= DDBLT_ALPHADESTSURFACEOVERRIDE;
  2583. bd.bltFX.lpDDSAlphaDest = (LPDIRECTDRAWSURFACE) psurf_lcl;
  2584. no_alpha = FALSE;
  2585. // check to see if alpha surfaces are supported
  2586. if( !(*(lpbc->dwBothCaps) & DDFXCAPS_ALPHASURFACES) )
  2587. {
  2588. GETFAILCODEBLT( *(lpbc->dwFXCaps),
  2589. *(lpbc->dwHELFXCaps),
  2590. sbd.halonly,
  2591. sbd.helonly,
  2592. DDFXCAPS_ALPHASURFACES );
  2593. if( fail )
  2594. {
  2595. DPF_ERR( "AlphaDest surface requested, not supported" );
  2596. LEAVE_BOTH_NOBUSY();
  2597. return DDERR_NOALPHAHW;
  2598. }
  2599. }
  2600. }
  2601. else if( dwFlags & DDBLT_ALPHADESTCONSTOVERRIDE )
  2602. {
  2603. if( dwFlags & ( DDBLT_ALPHADESTSURFACEOVERRIDE ))
  2604. {
  2605. DPF_ERR( "ALPHADESTCONSTOVERRIDE and other alpha sources specified" );
  2606. LEAVE_BOTH_NOBUSY();
  2607. return DDERR_INVALIDPARAMS;
  2608. }
  2609. bd.bltFX.dwConstAlphaDest = lpDDBltFX->dwConstAlphaDest;
  2610. no_alpha = FALSE;
  2611. }
  2612. else if( dwFlags & DDBLT_ALPHADESTSURFACEOVERRIDE )
  2613. {
  2614. psurf_lcl = (LPDDRAWI_DDRAWSURFACE_LCL) lpDDBltFX->lpDDSAlphaDest;
  2615. if( !VALID_DIRECTDRAWSURFACE_PTR( psurf_lcl ) )
  2616. {
  2617. DPF_ERR( "ALPHASURFACEOVERRIDE requires surface ptr" );
  2618. LEAVE_BOTH_NOBUSY();
  2619. return DDERR_INVALIDPARAMS;
  2620. }
  2621. if( SURFACE_LOST( psurf_lcl ) )
  2622. {
  2623. LEAVE_BOTH_NOBUSY();
  2624. return DDERR_SURFACELOST;
  2625. }
  2626. bd.bltFX.lpDDSAlphaDest = (LPDIRECTDRAWSURFACE) psurf_lcl;
  2627. no_alpha = FALSE;
  2628. // check to see if alpha surfaces are supported
  2629. if( !(*(lpbc->dwBothCaps) & DDFXCAPS_ALPHASURFACES) )
  2630. {
  2631. GETFAILCODEBLT( *(lpbc->dwFXCaps),
  2632. *(lpbc->dwHELFXCaps),
  2633. sbd.halonly,
  2634. sbd.helonly,
  2635. DDFXCAPS_ALPHASURFACES );
  2636. if( fail )
  2637. {
  2638. DPF_ERR( "AlphaDestOvr surface requested, not supported" );
  2639. LEAVE_BOTH_NOBUSY();
  2640. return DDERR_NOALPHAHW;
  2641. }
  2642. }
  2643. }
  2644. /*
  2645. * source alpha
  2646. */
  2647. if( dwFlags & DDBLT_ALPHASRC )
  2648. {
  2649. if( dwFlags & (DDBLT_ALPHASRCCONSTOVERRIDE|
  2650. DDBLT_ALPHASRCSURFACEOVERRIDE) )
  2651. {
  2652. DPF_ERR( "ALPHASRC and other alpha sources specified" );
  2653. LEAVE_BOTH_NOBUSY();
  2654. return DDERR_INVALIDPARAMS;
  2655. }
  2656. if( this_src == NULL )
  2657. {
  2658. DPF_ERR( "ALPHASRC requires a source surface" );
  2659. LEAVE_BOTH_NOBUSY();
  2660. return DDERR_INVALIDPARAMS;
  2661. }
  2662. psurf_lcl = FindAttached( this_src_lcl, DDSCAPS_ALPHA );
  2663. if( psurf_lcl == NULL )
  2664. {
  2665. DPF_ERR( "ALPHASRC requires an attached alpha to the src" );
  2666. LEAVE_BOTH_NOBUSY();
  2667. return DDERR_INVALIDPARAMS;
  2668. }
  2669. dwFlags &= ~DDBLT_ALPHASRC;
  2670. dwFlags |= DDBLT_ALPHASRCSURFACEOVERRIDE;
  2671. bd.bltFX.lpDDSAlphaSrc = (LPDIRECTDRAWSURFACE) psurf_lcl;
  2672. no_alpha = FALSE;
  2673. // check to see if alpha surfaces are supported
  2674. if( !(*(lpbc->dwBothCaps) & DDFXCAPS_ALPHASURFACES) )
  2675. {
  2676. GETFAILCODEBLT( *(lpbc->dwFXCaps),
  2677. *(lpbc->dwHELFXCaps),
  2678. sbd.halonly,
  2679. sbd.helonly,
  2680. DDFXCAPS_ALPHASURFACES );
  2681. if( fail )
  2682. {
  2683. DPF_ERR( "AlphaSrc surface requested, not supported" );
  2684. LEAVE_BOTH_NOBUSY();
  2685. return DDERR_NOALPHAHW;
  2686. }
  2687. }
  2688. }
  2689. else if( dwFlags & DDBLT_ALPHASRCCONSTOVERRIDE )
  2690. {
  2691. if( dwFlags & ( DDBLT_ALPHASRCSURFACEOVERRIDE ))
  2692. {
  2693. DPF_ERR( "ALPHASRCCONSTOVERRIDE and other alpha sources specified" );
  2694. LEAVE_BOTH_NOBUSY();
  2695. return DDERR_INVALIDPARAMS;
  2696. }
  2697. bd.bltFX.dwConstAlphaSrc = lpDDBltFX->dwConstAlphaSrc;
  2698. no_alpha = FALSE;
  2699. }
  2700. else if( dwFlags & DDBLT_ALPHASRCSURFACEOVERRIDE )
  2701. {
  2702. psurf_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDBltFX->lpDDSAlphaSrc;
  2703. if( !VALID_DIRECTDRAWSURFACE_PTR( psurf_int ) )
  2704. {
  2705. DPF_ERR( "ALPHASURFACEOVERRIDE requires surface ptr" );
  2706. LEAVE_BOTH_NOBUSY();
  2707. return DDERR_INVALIDPARAMS;
  2708. }
  2709. psurf_lcl = psurf_int->lpLcl;
  2710. if( SURFACE_LOST( psurf_lcl ) )
  2711. {
  2712. LEAVE_BOTH_NOBUSY();
  2713. return DDERR_SURFACELOST;
  2714. }
  2715. bd.bltFX.lpDDSAlphaSrc = (LPDIRECTDRAWSURFACE) psurf_lcl;
  2716. no_alpha = FALSE;
  2717. // check to see if alpha surfaces are supported
  2718. if( !(*(lpbc->dwBothCaps) & DDFXCAPS_ALPHASURFACES) )
  2719. {
  2720. GETFAILCODEBLT( *(lpbc->dwFXCaps),
  2721. *(lpbc->dwHELFXCaps),
  2722. sbd.halonly,
  2723. sbd.helonly,
  2724. DDFXCAPS_ALPHASURFACES );
  2725. if( fail )
  2726. {
  2727. DPF_ERR( "AlphaSrcOvr surface requested, not supported" );
  2728. LEAVE_BOTH_NOBUSY();
  2729. return DDERR_NOALPHAHW;
  2730. }
  2731. }
  2732. }
  2733. if( no_alpha )
  2734. {
  2735. DPF_ERR( "ALPHA specified with no alpha surface to use" );
  2736. LEAVE_BOTH_NOBUSY();
  2737. return DDERR_INVALIDPARAMS;
  2738. }
  2739. }
  2740. #endif
  2741. #pragma message( REMIND( "Z blts turned off in Rev 1" ) )
  2742. #if 0
  2743. /*
  2744. * verify Z Buffer
  2745. */
  2746. if( dwFlags & DDBLT_ZBUFFER )
  2747. {
  2748. if( this_src_lcl == NULL )
  2749. {
  2750. DPF_ERR( "ZBUFFER specified, but no source data" );
  2751. LEAVE_BOTH_NOBUSY();
  2752. return DDERR_INVALIDPARAMS;
  2753. }
  2754. // check to see if the driver supports zbuffer blts
  2755. if( !(*(lpbc->dwBothCaps) & DDCAPS_ZBLTS) )
  2756. {
  2757. GETFAILCODEBLT( *(lpbc->dwCaps),
  2758. *(lpbc->dwHELCaps),
  2759. sbd.halonly,
  2760. sbd.helonly,
  2761. DDCAPS_ZBLTS );
  2762. if( fail )
  2763. {
  2764. DPF_ERR( "ZBuffer blt requested, not supported" );
  2765. LEAVE_BOTH_NOBUSY();
  2766. return DDERR_NOZBUFFERHW;
  2767. }
  2768. }
  2769. bd.bltFX.dwZBufferOpCode = lpDDBltFX->dwZBufferOpCode;
  2770. if( dwFlags & DDBLT_ZBUFFERCONSTDESTOVERRIDE )
  2771. {
  2772. if( dwFlags & (DDBLT_ZBUFFERDESTOVERRIDE) )
  2773. {
  2774. DPF_ERR( "ZBUFFERCONSTDESTOVERRIDE and z surface specified" );
  2775. LEAVE_BOTH_NOBUSY();
  2776. return DDERR_INVALIDPARAMS;
  2777. }
  2778. bd.bltFX.dwConstZDest = lpDDBltFX->dwConstZDest;
  2779. }
  2780. else if( dwFlags & DDBLT_ZBUFFERDESTOVERRIDE )
  2781. {
  2782. psurf_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDBltFX->lpDDSZBufferDest;
  2783. if( !VALID_DIRECTDRAWSURFACE_PTR( psurf_int ) )
  2784. {
  2785. DPF_ERR( "ZBUFFERSURFACEDESTOVERRIDE requires surface ptr" );
  2786. LEAVE_BOTH_NOBUSY();
  2787. return DDERR_INVALIDPARAMS;
  2788. }
  2789. psurf_lcl = psurf_int->lpLcl;
  2790. if( SURFACE_LOST( psurf_lcl ) )
  2791. {
  2792. LEAVE_BOTH_NOBUSY();
  2793. return DDERR_SURFACELOST;
  2794. }
  2795. bd.bltFX.lpDDSZBufferDest = (LPDIRECTDRAWSURFACE) psurf_lcl;
  2796. }
  2797. else
  2798. {
  2799. psurf_lcl = FindAttached( this_dest_lcl, DDSCAPS_ZBUFFER );
  2800. if( psurf_lcl == NULL )
  2801. {
  2802. DPF_ERR( "ZBUFFER requires an attached Z to dest" );
  2803. LEAVE_BOTH_NOBUSY();
  2804. return DDERR_INVALIDPARAMS;
  2805. }
  2806. dwFlags |= DDBLT_ZBUFFERDESTOVERRIDE;
  2807. bd.bltFX.lpDDSZBufferDest = (LPDIRECTDRAWSURFACE) psurf_lcl;
  2808. }
  2809. if( dwFlags & DDBLT_ZBUFFERCONSTSRCOVERRIDE )
  2810. {
  2811. if( dwFlags & (DDBLT_ZBUFFERSRCOVERRIDE) )
  2812. {
  2813. DPF_ERR( "ZBUFFERCONSTSRCOVERRIDE and z surface specified" );
  2814. LEAVE_BOTH_NOBUSY();
  2815. return DDERR_INVALIDPARAMS;
  2816. }
  2817. bd.bltFX.dwConstZSrc = lpDDBltFX->dwConstZSrc;
  2818. } else if( dwFlags & DDBLT_ZBUFFERSRCOVERRIDE )
  2819. {
  2820. psurf_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDBltFX->lpDDSZBufferSrc;
  2821. if( !VALID_DIRECTDRAWSURFACE_PTR( psurf_int ) )
  2822. {
  2823. DPF_ERR( "ZBUFFERSURFACESRCOVERRIDE requires surface ptr" );
  2824. LEAVE_BOTH_NOBUSY();
  2825. return DDERR_INVALIDPARAMS;
  2826. }
  2827. psurf_lcl = psurf_int->lpLcl
  2828. if( SURFACE_LOST( psurf_lcl ) )
  2829. {
  2830. LEAVE_BOTH_NOBUSY();
  2831. return DDERR_SURFACELOST;
  2832. }
  2833. bd.bltFX.lpDDSZBufferSrc = (LPDIRECTDRAWSURFACE) psurf_lcl;
  2834. }
  2835. else
  2836. {
  2837. psurf_lcl = FindAttached( this_src_lcl, DDSCAPS_ZBUFFER );
  2838. if( psurf_lcl == NULL )
  2839. {
  2840. DPF_ERR( "ZBUFFER requires an attached Z to src" );
  2841. LEAVE_BOTH_NOBUSY();
  2842. return DDERR_INVALIDPARAMS;
  2843. }
  2844. dwFlags |= DDBLT_ZBUFFERSRCOVERRIDE;
  2845. bd.bltFX.lpDDSZBufferSrc = (LPDIRECTDRAWSURFACE) psurf_lcl;
  2846. }
  2847. }
  2848. #endif
  2849. /*
  2850. * verify color key overrides
  2851. */
  2852. if( dwFlags & (DDBLT_KEYSRCOVERRIDE|DDBLT_KEYDESTOVERRIDE) )
  2853. {
  2854. // see if the driver supports color key blts
  2855. if( !(*(lpbc->dwBothCaps) & DDCAPS_COLORKEY) )
  2856. {
  2857. GETFAILCODEBLT( *(lpbc->dwCaps),
  2858. *(lpbc->dwHELCaps),
  2859. sbd.halonly,
  2860. sbd.helonly,
  2861. DDCAPS_COLORKEY );
  2862. if( fail )
  2863. {
  2864. DPF_ERR( "KEYOVERRIDE specified, not supported" );
  2865. LEAVE_BOTH_NOBUSY();
  2866. return DDERR_NOCOLORKEYHW;
  2867. }
  2868. }
  2869. if( dwFlags & DDBLT_KEYSRCOVERRIDE )
  2870. {
  2871. if( !(*(lpbc->dwBothCKeyCaps) & DDCKEYCAPS_SRCBLT) )
  2872. {
  2873. GETFAILCODEBLT( *(lpbc->dwCKeyCaps),
  2874. *(lpbc->dwHELCKeyCaps),
  2875. sbd.halonly,
  2876. sbd.helonly,
  2877. DDCKEYCAPS_SRCBLT );
  2878. if( fail )
  2879. {
  2880. DPF_ERR( "KEYSRCOVERRIDE specified, not supported" );
  2881. LEAVE_BOTH_NOBUSY();
  2882. return DDERR_NOCOLORKEYHW;
  2883. }
  2884. }
  2885. bd.bltFX.ddckSrcColorkey = lpDDBltFX->ddckSrcColorkey;
  2886. }
  2887. if( dwFlags & DDBLT_KEYDESTOVERRIDE )
  2888. {
  2889. if( !(*(lpbc->dwBothCKeyCaps) & DDCKEYCAPS_DESTBLT) )
  2890. {
  2891. GETFAILCODEBLT( *(lpbc->dwCKeyCaps),
  2892. *(lpbc->dwHELCKeyCaps),
  2893. sbd.halonly,
  2894. sbd.helonly,
  2895. DDCKEYCAPS_DESTBLT );
  2896. if( fail )
  2897. {
  2898. DPF_ERR( "KEYDESTOVERRIDE specified, not supported" );
  2899. LEAVE_BOTH_NOBUSY();
  2900. return DDERR_NOCOLORKEYHW;
  2901. }
  2902. }
  2903. bd.bltFX.ddckDestColorkey = lpDDBltFX->ddckDestColorkey;
  2904. dwDestLockFlags = 0; //meaning read/write
  2905. }
  2906. }
  2907. /*
  2908. * verify src color key
  2909. */
  2910. if( dwFlags & DDBLT_KEYSRC )
  2911. {
  2912. if( this_src == NULL )
  2913. {
  2914. DPF_ERR( "KEYSRC specified, but no source data" );
  2915. LEAVE_BOTH_NOBUSY();
  2916. return DDERR_INVALIDOBJECT;
  2917. }
  2918. if( dwFlags & DDBLT_KEYSRCOVERRIDE )
  2919. {
  2920. DPF_ERR( "KEYSRC specified with KEYSRCOVERRIDE" );
  2921. LEAVE_BOTH_NOBUSY();
  2922. return DDERR_INVALIDPARAMS;
  2923. }
  2924. if( !(this_src_lcl->dwFlags & DDRAWISURF_HASCKEYSRCBLT) )
  2925. {
  2926. DPF_ERR( "KEYSRC specified, but no color key" );
  2927. DPF( 1, "srcFlags = %08lx", this_src_lcl->dwFlags );
  2928. LEAVE_BOTH_NOBUSY();
  2929. return DDERR_INVALIDPARAMS;
  2930. }
  2931. // make sure we can do this
  2932. if( !(*(lpbc->dwBothCKeyCaps) & DDCKEYCAPS_SRCBLT) )
  2933. {
  2934. GETFAILCODEBLT( *(lpbc->dwCKeyCaps),
  2935. *(lpbc->dwHELCKeyCaps),
  2936. sbd.halonly,
  2937. sbd.helonly,
  2938. DDCKEYCAPS_SRCBLT );
  2939. if( fail )
  2940. {
  2941. DPF_ERR( "KEYSRC specified, not supported" );
  2942. LEAVE_BOTH_NOBUSY();
  2943. return DDERR_NOCOLORKEYHW;
  2944. }
  2945. }
  2946. bd.bltFX.ddckSrcColorkey = this_src_lcl->ddckCKSrcBlt;
  2947. dwFlags &= ~DDBLT_KEYSRC;
  2948. dwFlags |= DDBLT_KEYSRCOVERRIDE;
  2949. }
  2950. /*
  2951. * verify dest color key
  2952. */
  2953. if( dwFlags & DDBLT_KEYDEST )
  2954. {
  2955. if( dwFlags & DDBLT_KEYDESTOVERRIDE )
  2956. {
  2957. DPF_ERR( "KEYDEST specified with KEYDESTOVERRIDE" );
  2958. LEAVE_BOTH_NOBUSY();
  2959. return DDERR_INVALIDPARAMS;
  2960. }
  2961. if( !(this_dest_lcl->dwFlags & DDRAWISURF_HASCKEYDESTBLT) )
  2962. {
  2963. DPF_ERR( "KEYDEST specified, but no color key" );
  2964. LEAVE_BOTH_NOBUSY();
  2965. return DDERR_INVALIDPARAMS;
  2966. }
  2967. // make sure we can do this
  2968. if( !(*(lpbc->dwBothCKeyCaps) & DDCKEYCAPS_DESTBLT) )
  2969. {
  2970. GETFAILCODEBLT( *(lpbc->dwCKeyCaps),
  2971. *(lpbc->dwHELCKeyCaps),
  2972. sbd.halonly,
  2973. sbd.helonly,
  2974. DDCKEYCAPS_DESTBLT );
  2975. if( fail )
  2976. {
  2977. DPF_ERR( "KEYDEST specified, not supported" );
  2978. LEAVE_BOTH_NOBUSY();
  2979. return DDERR_NOCOLORKEYHW;
  2980. }
  2981. }
  2982. /*
  2983. * This next part is bug that has existed since DX1.
  2984. * We'd like to fix it, but we fear regression, so we
  2985. * only fix it for surface 3 interfaces.
  2986. */
  2987. if( ( this_src_int->lpVtbl == &ddSurfaceCallbacks ) ||
  2988. ( this_src_int->lpVtbl == &ddSurface2Callbacks ) )
  2989. {
  2990. bd.bltFX.ddckDestColorkey = this_src_lcl->ddckCKDestBlt;
  2991. }
  2992. else
  2993. {
  2994. bd.bltFX.ddckDestColorkey = this_dest_lcl->ddckCKDestBlt;
  2995. }
  2996. dwFlags &= ~DDBLT_KEYDEST;
  2997. dwFlags |= DDBLT_KEYDESTOVERRIDE;
  2998. dwDestLockFlags = 0; //meaning read/write
  2999. }
  3000. }
  3001. /*
  3002. * verify various flags
  3003. */
  3004. if( !(dwFlags &(DDBLT_ROP |
  3005. DDBLT_COLORFILL |
  3006. DDBLT_DDROPS |
  3007. DDBLT_DEPTHFILL |
  3008. DDBLT_ROTATIONANGLE |
  3009. DDBLT_DDFX) ) )
  3010. {
  3011. if( this_src == NULL )
  3012. {
  3013. DPF_ERR( "Need a source for blt" );
  3014. LEAVE_BOTH_NOBUSY();
  3015. return DDERR_INVALIDPARAMS;
  3016. }
  3017. dwFlags |= DDBLT_ROP;
  3018. bd.bltFX.dwROP = SRCCOPY;
  3019. }
  3020. /*
  3021. * verify ROP
  3022. */
  3023. else if( dwFlags & DDBLT_ROP )
  3024. {
  3025. DWORD idx;
  3026. DWORD bit;
  3027. if( dwFlags & (DDBLT_DDFX |
  3028. DDBLT_COLORFILL|
  3029. DDBLT_DEPTHFILL|
  3030. DDBLT_ROTATIONANGLE|
  3031. DDBLT_DDROPS))
  3032. {
  3033. DPF_ERR( "Invalid flags specified with ROP" );
  3034. LEAVE_BOTH_NOBUSY();
  3035. return DDERR_INVALIDPARAMS;
  3036. }
  3037. bd.bltFX.dwROP = lpDDBltFX->dwROP;
  3038. rop = (DWORD) LOBYTE( HIWORD( bd.bltFX.dwROP ) );
  3039. idx = rop/32;
  3040. bit = 1 << (rop % 32 );
  3041. DPF( 4, "Trying ROP %d, idx=%d, bit=%08lx", rop, idx, bit );
  3042. /*
  3043. * We disable ROP flags on NT, so don't fail if they're only doing a SRCCOPY
  3044. */
  3045. if( lpDDBltFX->dwROP != SRCCOPY )
  3046. {
  3047. /*
  3048. * see if both HEL & HAL support the ROP
  3049. */
  3050. if( !(lpbc->dwBothRops[idx] & bit ) )
  3051. {
  3052. GETFAILCODEBLT( lpbc->dwRops[idx],
  3053. lpbc->dwHELRops[idx],
  3054. sbd.halonly,
  3055. sbd.helonly,
  3056. bit );
  3057. if( fail )
  3058. {
  3059. DPF_ERR( "ROP not supported" );
  3060. LEAVE_BOTH_NOBUSY();
  3061. return DDERR_NORASTEROPHW;
  3062. }
  3063. }
  3064. }
  3065. bd.dwROPFlags = cROPTable[ rop ];
  3066. if( bd.dwROPFlags & ROP_HAS_SOURCE )
  3067. {
  3068. if( this_src == NULL )
  3069. {
  3070. DPF_ERR( "ROP required a surface" );
  3071. LEAVE_BOTH_NOBUSY();
  3072. return DDERR_INVALIDPARAMS;
  3073. }
  3074. }
  3075. if( bd.dwROPFlags & ROP_HAS_PATTERN )
  3076. {
  3077. need_pat = TRUE;
  3078. }
  3079. }
  3080. /*
  3081. * verify COLORFILL
  3082. */
  3083. else if( dwFlags & DDBLT_COLORFILL )
  3084. {
  3085. if( this_src != NULL )
  3086. {
  3087. DPF_ERR( "COLORFILL specified along with source surface" );
  3088. LEAVE_BOTH_NOBUSY();
  3089. return DDERR_INVALIDPARAMS;
  3090. }
  3091. /*
  3092. * You cannot use COLORFILL to clear Z-buffers anymore. You must
  3093. * explicitly use DEPTHFILL. Disallow Z-buffer destinations.
  3094. */
  3095. if( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_ZBUFFER )
  3096. {
  3097. DPF_ERR( "Z-Buffer cannot be target of a color fill blt" );
  3098. LEAVE_BOTH_NOBUSY();
  3099. return DDERR_INVALIDPARAMS;
  3100. }
  3101. if( !(*(lpbc->dwBothCaps) & DDCAPS_BLTCOLORFILL) )
  3102. {
  3103. GETFAILCODEBLT( *(lpbc->dwCaps),
  3104. *(lpbc->dwHELCaps),
  3105. sbd.halonly,
  3106. sbd.helonly,
  3107. DDCAPS_BLTCOLORFILL );
  3108. if( fail )
  3109. {
  3110. DPF_ERR( "COLORFILL specified, not supported" );
  3111. LEAVE_BOTH_NOBUSY();
  3112. return DDERR_UNSUPPORTED;
  3113. }
  3114. }
  3115. /*
  3116. * Maks off the high order bits of the colorfill
  3117. * value since some drivers will fail if they're set.
  3118. */
  3119. GET_PIXEL_FORMAT( this_dest_lcl, this_dest, pddpf );
  3120. if( pddpf->dwRGBBitCount <= 8 )
  3121. {
  3122. lpDDBltFX->dwFillColor &= 0x00ff;
  3123. }
  3124. else if( pddpf->dwRGBBitCount == 16 )
  3125. {
  3126. lpDDBltFX->dwFillColor &= 0x00ffff;
  3127. }
  3128. else if( pddpf->dwRGBBitCount == 24 )
  3129. {
  3130. lpDDBltFX->dwFillColor &= 0x00ffffff;
  3131. }
  3132. bd.bltFX.dwFillColor = lpDDBltFX->dwFillColor;
  3133. }
  3134. /*
  3135. * verify DEPTHFILL
  3136. */
  3137. else if( dwFlags & DDBLT_DEPTHFILL )
  3138. {
  3139. if( this_src != NULL )
  3140. {
  3141. DPF_ERR( "DEPTHFILL specified along with source surface" );
  3142. LEAVE_BOTH_NOBUSY();
  3143. return DDERR_INVALIDPARAMS;
  3144. }
  3145. /*
  3146. * Ensure the destination is a z-buffer.
  3147. */
  3148. if( !( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_ZBUFFER ) )
  3149. {
  3150. DPF_ERR( "DEPTHFILL specified but destination is not a Z-buffer" );
  3151. LEAVE_BOTH_NOBUSY();
  3152. return DDERR_INVALIDPARAMS;
  3153. }
  3154. if( !(*(lpbc->dwBothCaps) & DDCAPS_BLTDEPTHFILL) )
  3155. {
  3156. GETFAILCODEBLT( *(lpbc->dwCaps),
  3157. *(lpbc->dwHELCaps),
  3158. sbd.halonly,
  3159. sbd.helonly,
  3160. DDCAPS_BLTDEPTHFILL );
  3161. if( fail )
  3162. {
  3163. DPF_ERR( "DEPTHFILL specified, not supported" );
  3164. LEAVE_BOTH_NOBUSY();
  3165. return DDERR_UNSUPPORTED;
  3166. }
  3167. }
  3168. bd.bltFX.dwFillDepth = lpDDBltFX->dwFillDepth;
  3169. // hack to pass DepthBlt WriteMask to BlitLib
  3170. bd.bltFX.dwZDestConstBitDepth = lpDDBltFX->dwZDestConstBitDepth;
  3171. }
  3172. /*
  3173. * verify DDROPS
  3174. */
  3175. else if( dwFlags & DDBLT_DDROPS )
  3176. {
  3177. if( dwFlags & (DDBLT_DDFX |
  3178. DDBLT_COLORFILL|
  3179. DDBLT_DEPTHFILL|
  3180. DDBLT_ROTATIONANGLE) )
  3181. {
  3182. DPF_ERR( "Invalid flags specified with DDROPS" );
  3183. LEAVE_BOTH_NOBUSY();
  3184. return DDERR_INVALIDPARAMS;
  3185. }
  3186. bd.bltFX.dwDDROP = lpDDBltFX->dwDDROP;
  3187. DPF_ERR( "DDROPS unsupported" );
  3188. LEAVE_BOTH_NOBUSY();
  3189. return DDERR_NODDROPSHW;
  3190. }
  3191. /*
  3192. * verify DDFX
  3193. */
  3194. else if( dwFlags & DDBLT_DDFX )
  3195. {
  3196. if( dwFlags & (DDBLT_COLORFILL |
  3197. DDBLT_DEPTHFILL |
  3198. DDBLT_ROTATIONANGLE) )
  3199. {
  3200. DPF_ERR( "Invalid flags specified with DDFX" );
  3201. LEAVE_BOTH_NOBUSY();
  3202. return DDERR_INVALIDPARAMS;
  3203. }
  3204. if( lpDDBltFX->dwDDFX & ( DDBLTFX_ARITHSTRETCHY ) )
  3205. {
  3206. DPF_ERR( "DDBLTFX_ARITHSTRETCHY unsupported" );
  3207. LEAVE_BOTH_NOBUSY();
  3208. return DDERR_NOSTRETCHHW;
  3209. }
  3210. if( lpDDBltFX->dwDDFX & ( DDBLTFX_MIRRORLEFTRIGHT ) )
  3211. {
  3212. GETFAILCODEBLT( *(lpbc->dwFXCaps),
  3213. *(lpbc->dwHELFXCaps),
  3214. sbd.halonly,
  3215. sbd.helonly,
  3216. DDFXCAPS_BLTMIRRORLEFTRIGHT );
  3217. if( fail )
  3218. {
  3219. DPF_ERR( "Mirroring along vertical axis not supported" );
  3220. LEAVE_BOTH_NOBUSY();
  3221. return DDERR_NOMIRRORHW;
  3222. }
  3223. }
  3224. if( lpDDBltFX->dwDDFX & ( DDBLTFX_MIRRORUPDOWN ) )
  3225. {
  3226. GETFAILCODEBLT( *(lpbc->dwFXCaps),
  3227. *(lpbc->dwHELFXCaps),
  3228. sbd.halonly,
  3229. sbd.helonly,
  3230. DDFXCAPS_BLTMIRRORUPDOWN );
  3231. if( fail )
  3232. {
  3233. DPF_ERR( "Mirroring along horizontal axis not supported" );
  3234. LEAVE_BOTH_NOBUSY();
  3235. return DDERR_NOMIRRORHW;
  3236. }
  3237. }
  3238. if( lpDDBltFX->dwDDFX & ( DDBLTFX_ROTATE90 | DDBLTFX_ROTATE180 | DDBLTFX_ROTATE270 ) )
  3239. {
  3240. GETFAILCODEBLT( *(lpbc->dwFXCaps),
  3241. *(lpbc->dwHELFXCaps),
  3242. sbd.halonly,
  3243. sbd.helonly,
  3244. DDFXCAPS_BLTROTATION90 );
  3245. if( fail )
  3246. {
  3247. DPF_ERR( "90-degree rotations not supported" );
  3248. LEAVE_BOTH_NOBUSY();
  3249. return DDERR_NOROTATIONHW;
  3250. }
  3251. }
  3252. bd.bltFX.dwDDFX = lpDDBltFX->dwDDFX;
  3253. dwFlags |= DDBLT_ROP;
  3254. bd.bltFX.dwROP = SRCCOPY;
  3255. /*
  3256. * verify ROTATIONANGLE
  3257. */
  3258. }
  3259. else if( dwFlags & DDBLT_ROTATIONANGLE )
  3260. {
  3261. if( dwFlags & (DDBLT_COLORFILL | DDBLT_DEPTHFILL) )
  3262. {
  3263. DPF_ERR( "Invalid flags specified with ROTATIONANGLE" );
  3264. LEAVE_BOTH_NOBUSY();
  3265. return DDERR_INVALIDPARAMS;
  3266. }
  3267. bd.bltFX.dwRotationAngle = lpDDBltFX->dwRotationAngle;
  3268. DPF_ERR( "ROTATIONANGLE unsupported" );
  3269. LEAVE_BOTH_NOBUSY();
  3270. return DDERR_NOROTATIONHW;
  3271. /*
  3272. * you should have told me SOMETHING!
  3273. */
  3274. }
  3275. else
  3276. {
  3277. DPF_ERR( "no blt type specified!" );
  3278. LEAVE_BOTH_NOBUSY();
  3279. return DDERR_INVALIDPARAMS;
  3280. }
  3281. /*
  3282. * no flags, we are doing a generic SRCCOPY
  3283. */
  3284. }
  3285. else
  3286. {
  3287. if( this_src == NULL )
  3288. {
  3289. DPF_ERR( "Need a source for blt" );
  3290. LEAVE_BOTH_NOBUSY();
  3291. return DDERR_INVALIDPARAMS;
  3292. }
  3293. dwFlags |= DDBLT_ROP;
  3294. bd.bltFX.dwROP = SRCCOPY;
  3295. }
  3296. /*
  3297. * verify pattern
  3298. */
  3299. if( need_pat )
  3300. {
  3301. psurf_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDBltFX->lpDDSPattern;
  3302. if( !VALID_DIRECTDRAWSURFACE_PTR( psurf_int ) )
  3303. {
  3304. DPF_ERR( "Invalid pattern surface specified" );
  3305. LEAVE_BOTH_NOBUSY();
  3306. return DDERR_INVALIDOBJECT;
  3307. }
  3308. psurf_lcl = psurf_int->lpLcl;
  3309. bd.bltFX.lpDDSPattern = (LPDIRECTDRAWSURFACE) psurf_lcl;
  3310. if( SURFACE_LOST( psurf_lcl ) )
  3311. {
  3312. LEAVE_BOTH_NOBUSY();
  3313. return DDERR_SURFACELOST;
  3314. }
  3315. #pragma message( REMIND( "What about general (non-8x8) patterns?" ))
  3316. if( psurf_lcl->lpGbl->wHeight != 8 || psurf_lcl->lpGbl->wWidth != 8 )
  3317. {
  3318. DPF_ERR( "Pattern surface must be 8 by 8" );
  3319. LEAVE_BOTH_NOBUSY();
  3320. return DDERR_INVALIDPARAMS;
  3321. }
  3322. dwFlags |= DDBLT_PRIVATE_ALIASPATTERN;
  3323. }
  3324. /*
  3325. * make sure dest rect is OK
  3326. */
  3327. if( lpDestRect != NULL )
  3328. {
  3329. if( !VALID_RECT_PTR( lpDestRect ) )
  3330. {
  3331. DPF_ERR( "Invalid dest rect specified" );
  3332. LEAVE_BOTH_NOBUSY();
  3333. return DDERR_INVALIDRECT;
  3334. }
  3335. bd.rDest = *(LPRECTL)lpDestRect;
  3336. }
  3337. else
  3338. {
  3339. MAKE_SURF_RECT( this_dest, this_dest_lcl, bd.rDest );
  3340. }
  3341. /*
  3342. * make sure src rect is OK
  3343. */
  3344. if( lpSrcRect != NULL )
  3345. {
  3346. if( !VALID_RECT_PTR( lpSrcRect ) )
  3347. {
  3348. DPF_ERR( "Invalid src rect specified" );
  3349. LEAVE_BOTH_NOBUSY();
  3350. return DDERR_INVALIDRECT;
  3351. }
  3352. bd.rSrc = *(LPRECTL)lpSrcRect;
  3353. }
  3354. else
  3355. {
  3356. if( this_src != NULL )
  3357. {
  3358. MAKE_SURF_RECT( this_src, this_src_lcl, bd.rSrc );
  3359. }
  3360. }
  3361. /*
  3362. * get dimensions & check them
  3363. */
  3364. stretch_blt = FALSE;
  3365. sbd.dest_height = bd.rDest.bottom - bd.rDest.top;
  3366. sbd.dest_width = bd.rDest.right - bd.rDest.left;
  3367. // Need positive heights/widths
  3368. if( ((int)sbd.dest_height <= 0) || ((int)sbd.dest_width <= 0) )
  3369. {
  3370. DPF_ERR( "Invalid destination dimensions: Zero/Negative Heights and/or Widths not allowed");
  3371. DPF(0,"Erroneous dest dimensions were: (wid %d, hgt %d)",(int)sbd.dest_width,(int)sbd.dest_height);
  3372. LEAVE_BOTH_NOBUSY();
  3373. return DDERR_INVALIDRECT;
  3374. }
  3375. // Is there a clipper? If so no more checks.
  3376. if( this_dest_lcl->lpDDClipper == NULL )
  3377. {
  3378. // Multi-mon: is this the primary for the desktop? This
  3379. // is the only case where the upper-left coord of the surface is not
  3380. // (0,0)
  3381. if( (pdrv->dwFlags & DDRAWI_VIRTUALDESKTOP) &&
  3382. (this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) )
  3383. {
  3384. if( (bd.rDest.left < pdrv->rectDesktop.left) ||
  3385. (bd.rDest.top < pdrv->rectDesktop.top) ||
  3386. (bd.rDest.right > pdrv->rectDesktop.right)||
  3387. (bd.rDest.bottom > pdrv->rectDesktop.bottom) )
  3388. {
  3389. DPF_ERR( "Blt Destination doesn't fit on Desktop And No Clipper was specified" );
  3390. LEAVE_BOTH_NOBUSY();
  3391. return DDERR_INVALIDRECT;
  3392. }
  3393. if( OverlapsDevices( this_dest_lcl, (LPRECT) &bd.rDest ) )
  3394. {
  3395. sbd.helonly = gdiblt = TRUE;
  3396. }
  3397. }
  3398. else
  3399. {
  3400. if( (int)bd.rDest.left < 0 ||
  3401. (int)bd.rDest.top < 0 ||
  3402. (DWORD)bd.rDest.bottom > (DWORD)this_dest->wHeight ||
  3403. (DWORD)bd.rDest.right > (DWORD)this_dest->wWidth )
  3404. {
  3405. DPF_ERR( "Invalid Blt destination dimensions" );
  3406. DPF(0, "width/height = %d x %d, dest rect = (%d, %d)-(%d, %d)",
  3407. this_dest->wWidth, this_dest->wHeight,
  3408. bd.rDest.left, bd.rDest.top, bd.rDest.right, bd.rDest.bottom);
  3409. LEAVE_BOTH_NOBUSY();
  3410. return DDERR_INVALIDRECT;
  3411. }
  3412. }
  3413. }
  3414. else if( (pdrv->dwFlags & DDRAWI_VIRTUALDESKTOP) &&
  3415. (this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) )
  3416. {
  3417. if( OverlapsDevices( this_dest_lcl, (LPRECT) &bd.rDest ) )
  3418. {
  3419. sbd.helonly = gdiblt = TRUE;
  3420. }
  3421. }
  3422. if( this_src != NULL )
  3423. {
  3424. sbd.src_height = bd.rSrc.bottom - bd.rSrc.top;
  3425. sbd.src_width = bd.rSrc.right - bd.rSrc.left;
  3426. if( ((int)sbd.src_height <= 0) || ((int)sbd.src_width <= 0) )
  3427. {
  3428. DPF_ERR( "BLT error. Can't have non-positive height or width" );
  3429. LEAVE_BOTH_NOBUSY();
  3430. return DDERR_INVALIDRECT;
  3431. }
  3432. // Multi-mon: is this the primary for the desktop? This
  3433. // is the only case where the upper-left coord of the surface is not
  3434. // (0,0)
  3435. if( (this_src->lpDD->dwFlags & DDRAWI_VIRTUALDESKTOP) &&
  3436. (this_src_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) )
  3437. {
  3438. if( (bd.rSrc.left < this_src->lpDD->rectDesktop.left) ||
  3439. (bd.rSrc.top < this_src->lpDD->rectDesktop.top) ||
  3440. (bd.rSrc.right > this_src->lpDD->rectDesktop.right)||
  3441. (bd.rSrc.bottom > this_src->lpDD->rectDesktop.bottom) )
  3442. {
  3443. DPF_ERR( "Blt Source dimension doesn't fit on Desktop" );
  3444. LEAVE_BOTH_NOBUSY();
  3445. return DDERR_INVALIDRECT;
  3446. }
  3447. if( OverlapsDevices( this_src_lcl, (LPRECT) &bd.rSrc ) )
  3448. {
  3449. sbd.helonly = gdiblt = TRUE;
  3450. }
  3451. }
  3452. else
  3453. {
  3454. if( (int)bd.rSrc.left < 0 ||
  3455. (int)bd.rSrc.top < 0 ||
  3456. (DWORD)bd.rSrc.bottom > (DWORD)this_src->wHeight ||
  3457. (DWORD)bd.rSrc.right > (DWORD)this_src->wWidth )
  3458. {
  3459. DPF_ERR( "Invalid Blt Source dimensions" );
  3460. LEAVE_BOTH_NOBUSY();
  3461. return DDERR_INVALIDRECT;
  3462. }
  3463. }
  3464. /*
  3465. * verify stretching...
  3466. *
  3467. */
  3468. if( sbd.src_height != sbd.dest_height || sbd.src_width != sbd.dest_width )
  3469. {
  3470. HRESULT ddrval;
  3471. ddrval = checkBltStretching( lpbc, &sbd );
  3472. if( ddrval != DD_OK )
  3473. {
  3474. DPF_ERR( "Failed checkBltStretching" );
  3475. LEAVE_BOTH_NOBUSY();
  3476. return ddrval;
  3477. }
  3478. stretch_blt = TRUE;
  3479. }
  3480. }
  3481. }
  3482. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  3483. {
  3484. DPF_ERR( "Exception encountered validating parameters" );
  3485. LEAVE_BOTH_NOBUSY();
  3486. return DDERR_INVALIDPARAMS;
  3487. }
  3488. /*
  3489. * now shovel the data...
  3490. */
  3491. TRY
  3492. {
  3493. /*
  3494. * final bits of blt data
  3495. */
  3496. bd.lpDDDestSurface = this_dest_lcl;
  3497. bd.lpDDSrcSurface = this_src_lcl;
  3498. bd.dwFlags = dwFlags;
  3499. /*
  3500. * Set up for a HAL or a HEL call
  3501. */
  3502. if( pdrv_lcl->lpDDCB->HALDDSurface.Blt == NULL )
  3503. {
  3504. sbd.helonly = TRUE;
  3505. }
  3506. if( sbd.helonly && sbd.halonly )
  3507. {
  3508. DPF_ERR( "BLT not supported in software or hardware" );
  3509. LEAVE_BOTH_NOBUSY();
  3510. return DDERR_NOBLTHW;
  3511. }
  3512. // Did the mode change since ENTER_DDRAW?
  3513. #ifdef WINNT
  3514. if ( DdQueryDisplaySettingsUniqueness() != uDisplaySettingsUnique )
  3515. {
  3516. // mode changed, don't do the blt
  3517. DPF_ERR( "Mode changed between ENTER_DDRAW and HAL call" );
  3518. LEAVE_BOTH_NOBUSY()
  3519. return DDERR_SURFACELOST;
  3520. }
  3521. if( !sbd.helonly )
  3522. {
  3523. if (this_src_lcl && !this_src_lcl->hDDSurface
  3524. && !CompleteCreateSysmemSurface(this_src_lcl))
  3525. {
  3526. DPF_ERR("Can't blt from SYSTEM surface w/o Kernel Object");
  3527. LEAVE_BOTH_NOBUSY()
  3528. return DDERR_GENERIC;
  3529. }
  3530. if (!this_dest_lcl->hDDSurface
  3531. && !CompleteCreateSysmemSurface(this_dest_lcl))
  3532. {
  3533. DPF_ERR("Can't blt to SYSTEM surface w/o Kernel Object");
  3534. LEAVE_BOTH_NOBUSY()
  3535. return DDERR_GENERIC;
  3536. }
  3537. }
  3538. #endif
  3539. /*
  3540. * Some drivers (like S3) do stuff in their BeginAccess call
  3541. * that screws up stuff that they did in their DDHAL Lock Call.
  3542. *
  3543. * Exclusion needs to happen BEFORE the lock call to prevent this.
  3544. *
  3545. */
  3546. #if defined(WIN95)
  3547. if( this_dest_lcl->lpDDClipper != NULL )
  3548. {
  3549. /*
  3550. * exclude the mouse cursor.
  3551. *
  3552. * we only need to do this for the windows display driver
  3553. *
  3554. * we only need to do this if we are blting to or from the
  3555. * primary surface.
  3556. *
  3557. * we only do this in the clipping case, we figure if the
  3558. * app cares enough to not scribble all over other windows
  3559. * he also cares enough to not to wipe out the cursor.
  3560. *
  3561. * we only need to do this if the driver is using a
  3562. * software cursor.
  3563. *
  3564. * NOTE
  3565. * we should check and only do this on the primary?
  3566. * we should make sure the clipper is window based?
  3567. * we should check for the source being the primary?
  3568. *
  3569. */
  3570. if ( (pdrv->dwFlags & DDRAWI_DISPLAYDRV) && pdrv->dwPDevice &&
  3571. !(*pdrv->lpwPDeviceFlags & HARDWARECURSOR) &&
  3572. (this_dest->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE) )
  3573. {
  3574. if ( lpDDDestSurface == lpDDSrcSurface )
  3575. {
  3576. RECTL rcl;
  3577. UnionRect((RECT*)&rcl, (RECT*)&bd.rDest, (RECT*)&bd.rSrc);
  3578. DD16_Exclude(pdrv->dwPDevice, &rcl);
  3579. }
  3580. else
  3581. {
  3582. DD16_Exclude(pdrv->dwPDevice, &bd.rDest);
  3583. }
  3584. }
  3585. }
  3586. #endif
  3587. if( !sbd.helonly ) // must not be HEL call
  3588. {
  3589. DPF( 4, "Hardware Blt");
  3590. sbd.bltfn = pdrv_lcl->lpDDCB->HALDDSurface.Blt;
  3591. bd.Blt = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.Blt;
  3592. /*
  3593. * Take pagelocks if required
  3594. */
  3595. dest_lock_taken = FALSE;
  3596. src_lock_taken = FALSE;
  3597. dest_pagelock_taken = FALSE;
  3598. src_pagelock_taken = FALSE;
  3599. if ( lpbc->bHALSeesSysmem )
  3600. {
  3601. /*
  3602. * If the HAL requires page locks...
  3603. */
  3604. if ( !( pdrv->ddCaps.dwCaps2 & DDCAPS2_NOPAGELOCKREQUIRED ) )
  3605. {
  3606. HRESULT hr;
  3607. /*
  3608. * ...then setup to take them if they're not already pagelocked.
  3609. */
  3610. if ( ( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY &&
  3611. this_dest_lcl->lpSurfMore->dwPageLockCount == 0 ) )
  3612. {
  3613. hr = InternalPageLock( this_dest_lcl, pdrv_lcl );
  3614. if (FAILED(hr))
  3615. {
  3616. LEAVE_BOTH_NOBUSY()
  3617. return hr;
  3618. }
  3619. else
  3620. {
  3621. dest_pagelock_taken=TRUE;
  3622. }
  3623. }
  3624. if ( this_src_lcl && ( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY &&
  3625. this_src_lcl->lpSurfMore->dwPageLockCount == 0 ))
  3626. {
  3627. hr = InternalPageLock( this_src_lcl, pdrv_lcl );
  3628. if (FAILED(hr))
  3629. {
  3630. if (dest_pagelock_taken)
  3631. InternalPageUnlock( this_dest_lcl, pdrv_lcl );
  3632. LEAVE_BOTH_NOBUSY()
  3633. return hr;
  3634. }
  3635. else
  3636. {
  3637. src_pagelock_taken=TRUE;
  3638. }
  3639. }
  3640. }
  3641. }
  3642. }
  3643. /*
  3644. * Blt the unclipped case
  3645. */
  3646. if( this_dest_lcl->lpDDClipper == NULL )
  3647. {
  3648. bd.IsClipped = FALSE; // no clipping
  3649. // if hel only, check and take locks on video mem surfaces.
  3650. if( sbd.helonly )
  3651. {
  3652. sbd.bltfn = pdrv_lcl->lpDDCB->HELDDSurface.Blt;
  3653. /*
  3654. * take locks on vram surfaces
  3655. */
  3656. if( !(this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  3657. ( !gdiblt || !( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) ) )
  3658. {
  3659. while( 1 )
  3660. {
  3661. ddrval = InternalLock( this_dest_lcl, &dest_bits , NULL, dwDestLockFlags );
  3662. if( ddrval == DD_OK )
  3663. {
  3664. GET_LPDDRAWSURFACE_GBL_MORE(this_dest)->fpNTAlias = (FLATPTR) dest_bits;
  3665. break;
  3666. }
  3667. if( ddrval == DDERR_WASSTILLDRAWING )
  3668. {
  3669. continue;
  3670. }
  3671. DONE_EXCLUDE();
  3672. (*pdflags) &= ~BUSY;
  3673. LEAVE_BOTH();
  3674. return ddrval;
  3675. }
  3676. dest_lock_taken = TRUE;
  3677. }
  3678. else
  3679. {
  3680. /*
  3681. * If this surface was involved in a hardware op, we need to
  3682. * probe the driver to see if it's done. NOTE this assumes
  3683. * that only one driver can be responsible for a system memory
  3684. * operation. See comment with WaitForDriverToFinishWithSurface.
  3685. */
  3686. if( this_dest->dwGlobalFlags & DDRAWISURFGBL_HARDWAREOPSTARTED )
  3687. {
  3688. WaitForDriverToFinishWithSurface(pdrv_lcl, this_dest_lcl );
  3689. }
  3690. dest_lock_taken = FALSE;
  3691. }
  3692. if( ( this_src != NULL) && (lpDDSrcSurface != lpDDDestSurface) &&
  3693. ( ( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) == 0) )
  3694. {
  3695. while( 1 )
  3696. {
  3697. ddrval = InternalLock( this_src_lcl, &src_bits, NULL, dwSourceLockFlags );
  3698. if( ddrval == DD_OK )
  3699. {
  3700. GET_LPDDRAWSURFACE_GBL_MORE(this_src)->fpNTAlias = (FLATPTR) src_bits;
  3701. break;
  3702. }
  3703. if( ddrval == DDERR_WASSTILLDRAWING )
  3704. {
  3705. continue;
  3706. }
  3707. if( dest_lock_taken )
  3708. {
  3709. InternalUnlock( this_dest_lcl,NULL,NULL,0 );
  3710. dest_lock_taken=FALSE;
  3711. }
  3712. DONE_EXCLUDE();
  3713. (*pdflags) &= ~BUSY;
  3714. LEAVE_BOTH();
  3715. return ddrval;
  3716. }
  3717. src_lock_taken = TRUE;
  3718. }
  3719. else
  3720. {
  3721. /*
  3722. * If this surface was involved in a hardware op, we need to
  3723. * probe the driver to see if it's done. NOTE this assumes
  3724. * that only one driver can be responsible for a system memory
  3725. * operation. See comment with WaitForDriverToFinishWithSurface.
  3726. */
  3727. if( this_src && ( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
  3728. && (this_src->dwGlobalFlags & DDRAWISURFGBL_HARDWAREOPSTARTED) )
  3729. {
  3730. WaitForDriverToFinishWithSurface(pdrv_lcl, this_src_lcl );
  3731. }
  3732. src_lock_taken = FALSE;
  3733. }
  3734. }
  3735. /*
  3736. * Add a rect to the region list if this is a managed surface
  3737. */
  3738. if(IsD3DManaged(this_dest_lcl))
  3739. {
  3740. LPREGIONLIST lpRegionList = this_dest_lcl->lpSurfMore->lpRegionList;
  3741. if(lpDestRect)
  3742. {
  3743. if(lpRegionList->rdh.nCount != NUM_RECTS_IN_REGIONLIST)
  3744. {
  3745. lpRegionList->rect[(lpRegionList->rdh.nCount)++] = bd.rDest;
  3746. lpRegionList->rdh.nRgnSize += sizeof(RECT);
  3747. if(bd.rDest.left < lpRegionList->rdh.rcBound.left)
  3748. lpRegionList->rdh.rcBound.left = bd.rDest.left;
  3749. if(bd.rDest.right > lpRegionList->rdh.rcBound.right)
  3750. lpRegionList->rdh.rcBound.right = bd.rDest.right;
  3751. if(bd.rDest.top < lpRegionList->rdh.rcBound.top)
  3752. lpRegionList->rdh.rcBound.top = bd.rDest.top;
  3753. if(bd.rDest.bottom > lpRegionList->rdh.rcBound.bottom)
  3754. lpRegionList->rdh.rcBound.bottom = bd.rDest.bottom;
  3755. }
  3756. }
  3757. else
  3758. {
  3759. /* Mark everything dirty */
  3760. lpRegionList->rdh.nCount = NUM_RECTS_IN_REGIONLIST;
  3761. }
  3762. }
  3763. try_again:
  3764. if( sbd.helonly )
  3765. {
  3766. // Release busy now or GDI blt will fail
  3767. DONE_BUSY();
  3768. }
  3769. if (bd.dwFlags & DDBLT_PRESENTATION)
  3770. {
  3771. bd.dwFlags |= DDBLT_LAST_PRESENTATION;
  3772. }
  3773. DOHALCALL_NOWIN16( Blt, sbd.bltfn, bd, rc, sbd.helonly );
  3774. #ifdef WINNT
  3775. if (rc == DDHAL_DRIVER_HANDLED && bd.ddRVal == DDERR_VISRGNCHANGED)
  3776. {
  3777. DPF(5,"Resetting VisRgn for surface %x", this_dest_lcl);
  3778. DdResetVisrgn(this_dest_lcl, (HWND)0);
  3779. goto try_again;
  3780. }
  3781. #endif
  3782. if ( rc == DDHAL_DRIVER_HANDLED )
  3783. {
  3784. if ( (dwFlags & DDBLT_WAIT) &&
  3785. bd.ddRVal == DDERR_WASSTILLDRAWING )
  3786. {
  3787. DPF(4, "Waiting.....");
  3788. goto try_again;
  3789. }
  3790. /*
  3791. * Note that the !helonly here is pretty much an assert.
  3792. * Thought it safer to actually test it, since that is actually what we mean.
  3793. */
  3794. if( !sbd.helonly && lpbc->bHALSeesSysmem && (bd.ddRVal == DD_OK) )
  3795. {
  3796. DPF(5,B,"Tagging surface %08x",this_dest);
  3797. if (this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  3798. this_dest->dwGlobalFlags |= DDRAWISURFGBL_HARDWAREOPDEST;
  3799. if (this_src)
  3800. {
  3801. DPF(5,B,"Tagging surface %08x",this_src);
  3802. if (this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  3803. this_src->dwGlobalFlags |= DDRAWISURFGBL_HARDWAREOPSOURCE;
  3804. }
  3805. }
  3806. }
  3807. }
  3808. else
  3809. {
  3810. /*
  3811. * Blt when the destination is clipped
  3812. */
  3813. DWORD cnt;
  3814. DWORD total;
  3815. LPRECT prect;
  3816. DWORD size;
  3817. LPRGNDATA prd=(LPRGNDATA)0;
  3818. int x_offset;
  3819. int y_offset;
  3820. DWORD scale_x;
  3821. DWORD scale_y;
  3822. RECT rSurfDst;
  3823. // Keep a flag to indicate whether we need to free 'prd' or not
  3824. BOOL fMustFreeRegion = FALSE;
  3825. // Use a stack buffer for most clipping cases
  3826. BYTE buffer[sizeof(RGNDATAHEADER) + NUM_RECTS_IN_REGIONLIST * sizeof(RECTL)];
  3827. bd.rOrigSrc = bd.rSrc;
  3828. bd.rOrigDest = bd.rDest;
  3829. #ifdef WINNT
  3830. // For NT, we need to deal with a clip-list change
  3831. // at many different points of the BLT
  3832. get_clipping_info:
  3833. if ( fMustFreeRegion )
  3834. {
  3835. MemFree( prd );
  3836. prd = NULL;
  3837. fMustFreeRegion = FALSE;
  3838. }
  3839. #endif
  3840. bd.IsClipped = TRUE; // yes, we are clipping
  3841. // Call the internal GetClipList which avoids the checking
  3842. DDASSERT( !fMustFreeRegion );
  3843. prd = (LPRGNDATA)&buffer[0];
  3844. size = sizeof(buffer);
  3845. ddrval = InternalGetClipList(
  3846. (LPDIRECTDRAWCLIPPER) this_dest_lcl->lpSurfMore->lpDDIClipper,
  3847. (LPRECT)&bd.rOrigDest, prd, &size, pdrv );
  3848. // Fatal error?
  3849. if( ddrval != DD_OK && ddrval != DDERR_REGIONTOOSMALL )
  3850. {
  3851. DPF_ERR( "GetClipList FAILED" );
  3852. DONE_LOCKS();
  3853. DONE_EXCLUDE();
  3854. if (dest_pagelock_taken)
  3855. InternalPageUnlock( this_dest_lcl, pdrv_lcl );
  3856. if (src_pagelock_taken)
  3857. InternalPageUnlock( this_src_lcl, pdrv_lcl );
  3858. LEAVE_BOTH_NOBUSY();
  3859. return ddrval;
  3860. }
  3861. if ( size <= sizeof(RGNDATA) )
  3862. {
  3863. DPF( 4, "Totally clipped" );
  3864. rc = DDHAL_DRIVER_HANDLED;
  3865. bd.ddRVal = DD_OK;
  3866. goto null_clip_rgn;
  3867. }
  3868. // If the clip region is larger than our stack buffer,
  3869. // then allocate a buffer
  3870. if ( size > sizeof(buffer) )
  3871. {
  3872. DDASSERT( !fMustFreeRegion );
  3873. prd = MemAlloc( size );
  3874. if( prd == NULL )
  3875. {
  3876. DONE_LOCKS();
  3877. DONE_EXCLUDE();
  3878. if (dest_pagelock_taken)
  3879. InternalPageUnlock( this_dest_lcl, pdrv_lcl );
  3880. if (src_pagelock_taken)
  3881. InternalPageUnlock( this_src_lcl, pdrv_lcl );
  3882. LEAVE_BOTH_NOBUSY();
  3883. return DDERR_OUTOFMEMORY;
  3884. }
  3885. fMustFreeRegion = TRUE;
  3886. ddrval = InternalGetClipList(
  3887. (LPDIRECTDRAWCLIPPER) this_dest_lcl->lpSurfMore->lpDDIClipper,
  3888. (LPRECT)&bd.rOrigDest, prd, &size, pdrv );
  3889. if( ddrval != DD_OK )
  3890. {
  3891. #ifdef WINNT
  3892. if( ddrval == DDERR_REGIONTOOSMALL )
  3893. {
  3894. // the visrgn changed between the first and second calls to GetClipList.
  3895. // try again.
  3896. DDASSERT( fMustFreeRegion );
  3897. MemFree( prd );
  3898. prd = NULL;
  3899. fMustFreeRegion = FALSE;
  3900. goto get_clipping_info;
  3901. }
  3902. #else
  3903. // Region can't change size on Win95! We took a lock!
  3904. DDASSERT( ddrval != DDERR_REGIONTOOSMALL );
  3905. #endif
  3906. DPF_ERR( "GetClipList FAILED" );
  3907. DDASSERT( fMustFreeRegion );
  3908. MemFree( prd );
  3909. DONE_LOCKS();
  3910. DONE_EXCLUDE();
  3911. if (dest_pagelock_taken)
  3912. InternalPageUnlock( this_dest_lcl, pdrv_lcl );
  3913. if (src_pagelock_taken)
  3914. InternalPageUnlock( this_src_lcl, pdrv_lcl );
  3915. LEAVE_BOTH_NOBUSY();
  3916. return ddrval;
  3917. }
  3918. }
  3919. // Clip region to surface dimensions
  3920. MAKE_SURF_RECT( this_dest, this_dest_lcl, rSurfDst );
  3921. // Clip the regiondata the we have down to
  3922. // the surface that we care about. Prevents
  3923. // memory trashing.
  3924. if( !gdiblt )
  3925. {
  3926. ClipRgnToRect( &rSurfDst, prd );
  3927. }
  3928. total = prd->rdh.nCount;
  3929. DPF( 5, "total vis rects = %ld", total );
  3930. prect = (LPRECT) &prd->Buffer[0];
  3931. rc = DDHAL_DRIVER_HANDLED;
  3932. bd.ddRVal = DD_OK;
  3933. // if hel only, check and take locks on video mem surfaces.
  3934. if( sbd.helonly )
  3935. {
  3936. sbd.bltfn = pdrv_lcl->lpDDCB->HELDDSurface.Blt;
  3937. /*
  3938. * take locks on vram surfaces
  3939. */
  3940. if( !(this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  3941. ( !gdiblt || !( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) ) )
  3942. {
  3943. while( 1 )
  3944. {
  3945. DPF(5,"Locking dest: %x", this_dest_lcl);
  3946. #ifdef WINNT
  3947. /*
  3948. * On Win2K, locking the entire primary is expensive as it often causes GDI
  3949. * to needlessly rebuild it's sprites. Hence, we will only lock the rect
  3950. * that we actually care about.
  3951. */
  3952. if( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE )
  3953. {
  3954. ddrval = InternalLock( this_dest_lcl, &dest_bits, (LPRECT)&bd.rDest,
  3955. DDLOCK_FAILONVISRGNCHANGED | dwDestLockFlags );
  3956. if( ddrval == DD_OK )
  3957. {
  3958. subrect_lock_taken = TRUE;
  3959. subrect_lock_rect.left = bd.rDest.left;
  3960. subrect_lock_rect.right = bd.rDest.right;
  3961. subrect_lock_rect.top = bd.rDest.top;
  3962. subrect_lock_rect.bottom = bd.rDest.bottom;
  3963. }
  3964. }
  3965. else
  3966. {
  3967. #endif
  3968. ddrval = InternalLock( this_dest_lcl, &dest_bits , NULL, DDLOCK_FAILONVISRGNCHANGED | dwDestLockFlags );
  3969. #ifdef WINNT
  3970. }
  3971. if (ddrval == DDERR_VISRGNCHANGED)
  3972. {
  3973. DPF(5,"Resetting VisRgn for surface %x", this_dest_lcl);
  3974. DdResetVisrgn(this_dest_lcl, (HWND)0);
  3975. DONE_LOCKS(); //should do nothing... here for ortho
  3976. goto get_clipping_info;
  3977. }
  3978. #endif
  3979. if( ddrval == DD_OK )
  3980. {
  3981. GET_LPDDRAWSURFACE_GBL_MORE(this_dest)->fpNTAlias = (FLATPTR) dest_bits;
  3982. break;
  3983. }
  3984. if( ddrval == DDERR_WASSTILLDRAWING )
  3985. {
  3986. continue;
  3987. }
  3988. if( fMustFreeRegion )
  3989. MemFree( prd );
  3990. DONE_LOCKS();
  3991. DONE_EXCLUDE();
  3992. (*pdflags) &= ~BUSY;
  3993. LEAVE_BOTH();
  3994. return ddrval;
  3995. }
  3996. dest_lock_taken = TRUE;
  3997. }
  3998. else
  3999. {
  4000. /*
  4001. * If this surface was involved in a hardware op, we need to
  4002. * probe the driver to see if it's done. NOTE this assumes
  4003. * that only one driver can be responsible for a system memory
  4004. * operation. See comment with WaitForDriverToFinishWithSurface.
  4005. */
  4006. if( (this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  4007. (this_dest->dwGlobalFlags & DDRAWISURFGBL_HARDWAREOPSTARTED) )
  4008. {
  4009. WaitForDriverToFinishWithSurface(pdrv_lcl, this_dest_lcl );
  4010. }
  4011. dest_lock_taken = FALSE;
  4012. }
  4013. if( ( this_src != NULL) && (lpDDSrcSurface != lpDDDestSurface) &&
  4014. ( ( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) == 0) )
  4015. {
  4016. while( 1 )
  4017. {
  4018. DPF(5,"Locking src: %x", this_src_lcl);
  4019. ddrval = InternalLock( this_src_lcl, &src_bits , NULL, DDLOCK_FAILONVISRGNCHANGED | dwSourceLockFlags );
  4020. #ifdef WINNT
  4021. if (ddrval == DDERR_VISRGNCHANGED)
  4022. {
  4023. DPF(5,"Resetting VisRgn for surface %x", this_dest_lcl);
  4024. DdResetVisrgn(this_dest_lcl, (HWND)0);
  4025. DONE_LOCKS();
  4026. goto get_clipping_info;
  4027. }
  4028. #endif
  4029. if( ddrval == DD_OK )
  4030. {
  4031. GET_LPDDRAWSURFACE_GBL_MORE(this_src)->fpNTAlias = (FLATPTR) src_bits;
  4032. break;
  4033. }
  4034. if( ddrval == DDERR_WASSTILLDRAWING )
  4035. {
  4036. continue;
  4037. }
  4038. if( fMustFreeRegion )
  4039. MemFree( prd );
  4040. DONE_LOCKS();
  4041. DONE_EXCLUDE();
  4042. (*pdflags) &= ~BUSY;
  4043. LEAVE_BOTH();
  4044. return ddrval;
  4045. }
  4046. src_lock_taken = TRUE;
  4047. }
  4048. else
  4049. {
  4050. /*
  4051. * If this surface was involved in a hardware op, we need to
  4052. * probe the driver to see if it's done. NOTE this assumes
  4053. * that only one driver can be responsible for a system memory
  4054. * operation. See comment with WaitForDriverToFinishWithSurface.
  4055. */
  4056. if( this_src && (this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  4057. (this_src->dwGlobalFlags & DDRAWISURFGBL_HARDWAREOPSTARTED) )
  4058. {
  4059. WaitForDriverToFinishWithSurface(pdrv_lcl, this_src_lcl );
  4060. }
  4061. src_lock_taken = FALSE;
  4062. }
  4063. }
  4064. /*
  4065. * See if the driver wants to do the clipping
  4066. */
  4067. if( (stretch_blt && (*(lpbc->dwCaps) & DDCAPS_CANCLIPSTRETCHED)) ||
  4068. (!stretch_blt && (*(lpbc->dwCaps) & DDCAPS_CANCLIP)) )
  4069. {
  4070. // The driver will do the clipping
  4071. bd.dwRectCnt = total;
  4072. bd.prDestRects = prect;
  4073. if(IsD3DManaged(this_dest_lcl))
  4074. {
  4075. /* We don't want to deal with this mess, so mark everything dirty */
  4076. this_dest_lcl->lpSurfMore->lpRegionList->rdh.nCount = NUM_RECTS_IN_REGIONLIST;
  4077. }
  4078. /*
  4079. * pass the whole mess off to the driver
  4080. */
  4081. drvclip_try_again:
  4082. if( sbd.helonly )
  4083. {
  4084. // Release busy now or GDI blt will fail
  4085. DONE_BUSY();
  4086. }
  4087. if (bd.dwFlags & DDBLT_PRESENTATION)
  4088. {
  4089. bd.dwFlags |= DDBLT_LAST_PRESENTATION;
  4090. }
  4091. #ifdef WINNT
  4092. if (subrect_lock_taken)
  4093. {
  4094. // If we took a subrect lock on the primary, we need
  4095. // to adjust the dest rect so the HEL will draw it
  4096. // in the right spot. We couldn't do it before because
  4097. // the above stretch code reuqires the corfrect rect.
  4098. bd.rDest.right -= subrect_lock_rect.left;
  4099. bd.rDest.left -= subrect_lock_rect.left;
  4100. bd.rDest.bottom -= subrect_lock_rect.top;
  4101. bd.rDest.top -= subrect_lock_rect.top;
  4102. }
  4103. #endif
  4104. DOHALCALL_NOWIN16( Blt, sbd.bltfn, bd, rc, sbd.helonly );
  4105. #ifdef WINNT
  4106. if (subrect_lock_taken)
  4107. {
  4108. // Adjust it back so we don't screw anything up.
  4109. bd.rDest.right += subrect_lock_rect.left;
  4110. bd.rDest.left += subrect_lock_rect.left;
  4111. bd.rDest.bottom += subrect_lock_rect.top;
  4112. bd.rDest.top += subrect_lock_rect.top;
  4113. }
  4114. #endif
  4115. if( rc == DDHAL_DRIVER_HANDLED )
  4116. {
  4117. #ifdef WINNT
  4118. if (bd.ddRVal == DDERR_VISRGNCHANGED)
  4119. {
  4120. DONE_LOCKS();
  4121. DPF(5,"Resetting VisRgn for surface %x", this_dest_lcl);
  4122. DdResetVisrgn(this_dest_lcl, (HWND)0);
  4123. goto get_clipping_info;
  4124. }
  4125. #endif
  4126. if ( (dwFlags & DDBLT_WAIT) &&
  4127. bd.ddRVal == DDERR_WASSTILLDRAWING )
  4128. {
  4129. DPF(4, "Waiting.....");
  4130. goto drvclip_try_again;
  4131. }
  4132. /*
  4133. * Only mark the surface as in use by the hardware if we didn't wait for it
  4134. * to finish and it succeeded. Don't mark it if it's HEL, since
  4135. * the HEL will never be asynchronous.
  4136. */
  4137. if( !sbd.helonly && lpbc->bHALSeesSysmem && (bd.ddRVal == DD_OK) )
  4138. {
  4139. DPF(5,B,"Tagging surface %08x",this_dest);
  4140. if (this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  4141. this_dest->dwGlobalFlags |= DDRAWISURFGBL_HARDWAREOPDEST;
  4142. if (this_src)
  4143. {
  4144. DPF(5,B,"Tagging surface %08x",this_src);
  4145. if (this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  4146. this_src->dwGlobalFlags |= DDRAWISURFGBL_HARDWAREOPSOURCE;
  4147. }
  4148. }
  4149. }
  4150. }
  4151. else
  4152. {
  4153. // We will do the clipping
  4154. bd.dwRectCnt =1;
  4155. bd.prDestRects = (LPVOID)&(bd.rDest);
  4156. // precalculate a couple of variables
  4157. if( !stretch_blt )
  4158. {
  4159. x_offset = bd.rSrc.left - bd.rDest.left;
  4160. y_offset = bd.rSrc.top - bd.rDest.top;
  4161. }
  4162. else
  4163. {
  4164. // scale_x and scale_y are fixed point variables scaled
  4165. // 16.16 (16 integer bits and 16 fractional bits)
  4166. scale_x = ((bd.rSrc.right - bd.rSrc.left) << 16) /
  4167. (bd.rDest.right - bd.rDest.left);
  4168. scale_y = ((bd.rSrc.bottom - bd.rSrc.top) << 16) /
  4169. (bd.rDest.bottom - bd.rDest.top);
  4170. }
  4171. /*
  4172. * traverse the visible rect list and send each piece to
  4173. * the driver to blit.
  4174. */
  4175. for( cnt=0;cnt<total;cnt++ )
  4176. {
  4177. /*
  4178. * find out where on the src rect we need to get
  4179. * the data from.
  4180. */
  4181. if( !stretch_blt )
  4182. {
  4183. // no stretch
  4184. // one-to-one mapping from source to destination
  4185. bd.rDest.left = prect->left;
  4186. bd.rDest.right = prect->right;
  4187. bd.rDest.top = prect->top;
  4188. bd.rDest.bottom = prect->bottom;
  4189. bd.rSrc.left = bd.rDest.left + x_offset;
  4190. bd.rSrc.right = bd.rDest.right + x_offset;
  4191. bd.rSrc.top = bd.rDest.top + y_offset;
  4192. bd.rSrc.bottom = bd.rDest.bottom + y_offset;
  4193. }
  4194. else
  4195. {
  4196. // stretching
  4197. // linear mapping from source to destination
  4198. bd.rDest.left = prect->left;
  4199. bd.rDest.right = prect->right;
  4200. bd.rDest.top = prect->top;
  4201. bd.rDest.bottom = prect->bottom;
  4202. // calculate the source rect which transforms to the
  4203. // dest rect
  4204. XformRect( (RECT *)&(bd.rOrigSrc), (RECT *)&(bd.rOrigDest), (RECT *)prect,
  4205. (RECT *)&(bd.rSrc), scale_x, scale_y );
  4206. }
  4207. /*
  4208. * Add a rect to the region list if this is a managed surface
  4209. */
  4210. if(IsD3DManaged(this_dest_lcl))
  4211. {
  4212. LPREGIONLIST lpRegionList = this_dest_lcl->lpSurfMore->lpRegionList;
  4213. if(lpRegionList->rdh.nCount != NUM_RECTS_IN_REGIONLIST)
  4214. {
  4215. lpRegionList->rect[(lpRegionList->rdh.nCount)++] = bd.rDest;
  4216. lpRegionList->rdh.nRgnSize += sizeof(RECT);
  4217. if(bd.rDest.left < lpRegionList->rdh.rcBound.left)
  4218. lpRegionList->rdh.rcBound.left = bd.rDest.left;
  4219. if(bd.rDest.right > lpRegionList->rdh.rcBound.right)
  4220. lpRegionList->rdh.rcBound.right = bd.rDest.right;
  4221. if(bd.rDest.top < lpRegionList->rdh.rcBound.top)
  4222. lpRegionList->rdh.rcBound.top = bd.rDest.top;
  4223. if(bd.rDest.bottom > lpRegionList->rdh.rcBound.bottom)
  4224. lpRegionList->rdh.rcBound.bottom = bd.rDest.bottom;
  4225. }
  4226. }
  4227. /*
  4228. * blt this little piece
  4229. */
  4230. clip_try_again:
  4231. if( sbd.helonly )
  4232. {
  4233. // Release busy now or GDI blt will fail
  4234. DONE_BUSY();
  4235. }
  4236. // If mirror Blt, we must fix up source rect here!
  4237. if (bd.dwFlags & DDBLT_DDFX)
  4238. {
  4239. int temp;
  4240. if (bd.bltFX.dwDDFX & DDBLTFX_MIRRORLEFTRIGHT)
  4241. {
  4242. temp = bd.rSrc.left;
  4243. bd.rSrc.left = bd.rOrigSrc.left + bd.rOrigSrc.right - bd.rSrc.right;
  4244. bd.rSrc.right = bd.rOrigSrc.left + bd.rOrigSrc.right - temp;
  4245. }
  4246. if (bd.bltFX.dwDDFX & DDBLTFX_MIRRORUPDOWN)
  4247. {
  4248. temp = bd.rSrc.top;
  4249. bd.rSrc.top = bd.rOrigSrc.top + bd.rOrigSrc.bottom - bd.rSrc.bottom;
  4250. bd.rSrc.bottom = bd.rOrigSrc.top + bd.rOrigSrc.bottom - temp;
  4251. }
  4252. }
  4253. if (bd.dwFlags & DDBLT_PRESENTATION)
  4254. {
  4255. if (cnt == total-1)
  4256. {
  4257. bd.dwFlags |= DDBLT_LAST_PRESENTATION;
  4258. }
  4259. }
  4260. #ifdef WINNT
  4261. if (subrect_lock_taken)
  4262. {
  4263. // Adjust the dest rect so the HEL will draw to the
  4264. // right place.
  4265. bd.rDest.right -= subrect_lock_rect.left;
  4266. bd.rDest.left -= subrect_lock_rect.left;
  4267. bd.rDest.bottom -= subrect_lock_rect.top;
  4268. bd.rDest.top -= subrect_lock_rect.top;
  4269. }
  4270. #endif
  4271. DOHALCALL_NOWIN16( Blt, sbd.bltfn, bd, rc, sbd.helonly );
  4272. #ifdef WINNT
  4273. if (subrect_lock_taken)
  4274. {
  4275. // Adjust it back so we don't screw anything up.
  4276. bd.rDest.right += subrect_lock_rect.left;
  4277. bd.rDest.left += subrect_lock_rect.left;
  4278. bd.rDest.bottom += subrect_lock_rect.top;
  4279. bd.rDest.top += subrect_lock_rect.top;
  4280. }
  4281. #endif
  4282. if( rc == DDHAL_DRIVER_HANDLED )
  4283. {
  4284. #ifdef WINNT
  4285. if (bd.ddRVal == DDERR_VISRGNCHANGED)
  4286. {
  4287. DONE_LOCKS();
  4288. DPF(5,"Resetting VisRgn for surface %x", this_dest_lcl);
  4289. DdResetVisrgn(this_dest_lcl, (HWND)0);
  4290. /*
  4291. * restore original source rect if vis region
  4292. * changed, for mirrored/clipped cases
  4293. */
  4294. bd.rSrc=bd.rOrigSrc;
  4295. bd.rDest=bd.rOrigDest;
  4296. goto get_clipping_info;
  4297. }
  4298. #endif
  4299. /*
  4300. * NOTE: If clipping has introduced more than
  4301. * one rectangle we behave as if DDBLT_WAIT
  4302. * was specified on all rectangles after the
  4303. * first. This is necessary as the first
  4304. * rectangle will probably cause the accelerator
  4305. * to be busy. Hence, the attempt to blit the
  4306. * second rectangle will fail with
  4307. * DDERR_WASSTILLDRAWING. If we pass this to
  4308. * the application (rather than busy waiting)
  4309. * the application is likely to retry the blit
  4310. * (which will fail on the second rectangle again)
  4311. * and we have an application sitting in an
  4312. * infinite loop).
  4313. */
  4314. if ( ( (dwFlags & DDBLT_WAIT) || (cnt > 0) ) &&
  4315. bd.ddRVal == DDERR_WASSTILLDRAWING )
  4316. {
  4317. DPF(4, "Waiting.....");
  4318. goto clip_try_again;
  4319. }
  4320. if( bd.ddRVal != DD_OK )
  4321. {
  4322. break;
  4323. }
  4324. /*
  4325. * Only mark the surface as in use by the hardware if we didn't wait for it
  4326. * to finish and it succeeded. Only mark surfaces if it's not the HEL
  4327. * because the HEL is never async.
  4328. */
  4329. if( !sbd.helonly && lpbc->bHALSeesSysmem )
  4330. {
  4331. DPF(5,B,"Tagging surface %08x",this_dest);
  4332. if (this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  4333. this_dest->dwGlobalFlags |= DDRAWISURFGBL_HARDWAREOPDEST;
  4334. if (this_src)
  4335. {
  4336. DPF(5,B,"Tagging surface %08x",this_src);
  4337. if (this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  4338. this_src->dwGlobalFlags |= DDRAWISURFGBL_HARDWAREOPSOURCE;
  4339. }
  4340. }
  4341. }
  4342. /*
  4343. * next clipping rect
  4344. */
  4345. prect++;
  4346. }
  4347. }
  4348. if( fMustFreeRegion )
  4349. MemFree( prd );
  4350. null_clip_rgn:
  4351. ;
  4352. }
  4353. DONE_LOCKS();
  4354. /*
  4355. * Exclusion needs to happen after unlock call
  4356. */
  4357. DONE_EXCLUDE();
  4358. if( rc != DDHAL_DRIVER_HANDLED )
  4359. {
  4360. /*
  4361. * did the driver run out of hardware color key resources?
  4362. */
  4363. if( (rc == DDHAL_DRIVER_NOCKEYHW) && (dwFlags & DDBLT_KEYSRCOVERRIDE) )
  4364. {
  4365. ddrval = ChangeToSoftwareColorKey( this_src_int, FALSE );
  4366. if( ddrval == DD_OK )
  4367. {
  4368. sbd.halonly = FALSE;
  4369. sbd.helonly = FALSE;
  4370. if (src_pagelock_taken)
  4371. {
  4372. src_pagelock_taken = FALSE;
  4373. InternalPageUnlock(this_src_lcl, pdrv_lcl);
  4374. }
  4375. if (dest_pagelock_taken)
  4376. {
  4377. dest_pagelock_taken = FALSE;
  4378. InternalPageUnlock(this_dest_lcl, pdrv_lcl);
  4379. }
  4380. goto RESTART_BLT;
  4381. }
  4382. else
  4383. {
  4384. bd.ddRVal = DDERR_NOCOLORKEYHW;
  4385. }
  4386. }
  4387. else
  4388. {
  4389. bd.ddRVal = DDERR_UNSUPPORTED;
  4390. }
  4391. }
  4392. DONE_BUSY();
  4393. /*
  4394. * Maintain old behaviour for old drivers (which do not export the
  4395. * GetSysmemBltStatus HAL call) and just spin until they're done.
  4396. * Any alternative could exercise new code paths in the driver
  4397. * (e.g. reentered for a DMA operation)
  4398. */
  4399. if ( lpbc->bHALSeesSysmem &&
  4400. (NULL == pdrv_lcl->lpDDCB->HALDDMiscellaneous.GetSysmemBltStatus || dest_pagelock_taken || src_pagelock_taken)
  4401. )
  4402. {
  4403. if( this_src->dwGlobalFlags & DDRAWISURFGBL_HARDWAREOPSTARTED )
  4404. {
  4405. /*
  4406. * Wait on the destination surface only
  4407. */
  4408. DDASSERT(this_src && this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY);
  4409. while (DDERR_WASSTILLDRAWING == InternalGetBltStatus(pdrv_lcl, this_dest_lcl, DDGBS_ISBLTDONE))
  4410. ;
  4411. this_src_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_HARDWAREOPSTARTED;
  4412. this_dest_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_HARDWAREOPSTARTED;
  4413. }
  4414. /*
  4415. * Unpagelock if we took the pagelocks
  4416. */
  4417. if (dest_pagelock_taken)
  4418. InternalPageUnlock(this_dest_lcl, pdrv_lcl);
  4419. if (src_pagelock_taken)
  4420. InternalPageUnlock(this_src_lcl, pdrv_lcl);
  4421. }
  4422. if(IsD3DManaged(this_dest_lcl))
  4423. MarkDirty(this_dest_lcl);
  4424. LEAVE_BOTH();
  4425. return bd.ddRVal;
  4426. }
  4427. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  4428. {
  4429. DPF_ERR( "Exception encountered doing blt" );
  4430. DONE_LOCKS();
  4431. DONE_EXCLUDE();
  4432. DONE_BUSY();
  4433. /*
  4434. * Maintain old behaviour for old drivers (which do not export the
  4435. * GetSysmemBltStatus HAL call) and just spin until they're done.
  4436. * Any alternative could exercise new code paths in the driver
  4437. * (e.g. reentered for a DMA operation)
  4438. */
  4439. if ( lpbc->bHALSeesSysmem &&
  4440. (NULL == pdrv_lcl->lpDDCB->HALDDMiscellaneous.GetSysmemBltStatus || dest_pagelock_taken || src_pagelock_taken)
  4441. )
  4442. {
  4443. if( this_src->dwGlobalFlags & DDRAWISURFGBL_HARDWAREOPSTARTED )
  4444. {
  4445. /*
  4446. * Wait on the destination surface only
  4447. */
  4448. DDASSERT(this_src && this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY);
  4449. while (DDERR_WASSTILLDRAWING == InternalGetBltStatus(pdrv_lcl, this_dest_lcl, DDGBS_ISBLTDONE))
  4450. ;
  4451. this_src_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_HARDWAREOPSTARTED;
  4452. this_dest_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_HARDWAREOPSTARTED;
  4453. }
  4454. /*
  4455. * Unpagelock if we took the pagelocks
  4456. */
  4457. if (dest_pagelock_taken)
  4458. InternalPageUnlock(this_dest_lcl, pdrv_lcl);
  4459. if (src_pagelock_taken)
  4460. InternalPageUnlock(this_src_lcl, pdrv_lcl);
  4461. }
  4462. LEAVE_BOTH();
  4463. return DDERR_EXCEPTION;
  4464. }
  4465. } /* DD_Surface_Blt */
  4466. #undef DPF_MODNAME
  4467. #define DPF_MODNAME "BltBatch"
  4468. /*
  4469. * DD_Surface_BltBatch
  4470. *
  4471. * BitBlt a whole pile of surfaces
  4472. */
  4473. HRESULT DDAPI DD_Surface_BltBatch(
  4474. LPDIRECTDRAWSURFACE lpDDDestSurface,
  4475. LPDDBLTBATCH lpDDBltBatch,
  4476. DWORD dwCount,
  4477. DWORD dwFlags )
  4478. {
  4479. LPDDRAWI_DDRAWSURFACE_LCL this_src_lcl;
  4480. LPDDRAWI_DDRAWSURFACE_LCL this_dest_lcl;
  4481. LPDDRAWI_DDRAWSURFACE_INT this_src_int;
  4482. LPDDRAWI_DDRAWSURFACE_INT this_dest_int;
  4483. HRESULT ddrval;
  4484. int i;
  4485. ENTER_BOTH();
  4486. DPF(2,A,"ENTERAPI: DD_Surface_BltBatch");
  4487. /*
  4488. * validate surface ptrs
  4489. */
  4490. this_dest_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDDestSurface;
  4491. if( !VALID_DIRECTDRAWSURFACE_PTR( this_dest_int ) )
  4492. {
  4493. DPF_ERR( "Invalid dest specified") ;
  4494. LEAVE_BOTH();
  4495. return DDERR_INVALIDOBJECT;
  4496. }
  4497. this_dest_lcl = this_dest_int->lpLcl;
  4498. if( SURFACE_LOST( this_dest_lcl ) )
  4499. {
  4500. DPF( 1, "Dest lost") ;
  4501. LEAVE_BOTH();
  4502. return DDERR_SURFACELOST;
  4503. }
  4504. if( this_dest_lcl->lpGbl->dwUsageCount > 0 )
  4505. {
  4506. DPF( 1, "Dest surface %08lx is still locked", this_dest_int );
  4507. LEAVE_BOTH();
  4508. return DDERR_SURFACEBUSY;
  4509. }
  4510. /*
  4511. * validate BltBatch ptr
  4512. */
  4513. if( !VALID_DDBLTBATCH_PTR( lpDDBltBatch ) )
  4514. {
  4515. DPF( 1, "Invalid Blt batch ptr" );
  4516. LEAVE_BOTH();
  4517. return DDERR_INVALIDPARAMS;
  4518. }
  4519. /*
  4520. * validate blt batch params
  4521. */
  4522. for( i=0;i<(int)dwCount;i++ )
  4523. {
  4524. /*
  4525. * validate dest rect
  4526. */
  4527. if( lpDDBltBatch[i].lprDest != NULL )
  4528. {
  4529. if( !VALID_RECT_PTR(lpDDBltBatch[i].lprDest) )
  4530. {
  4531. DPF( 1, "dest rectangle invalid, entry %d", i );
  4532. LEAVE_BOTH();
  4533. return DDERR_INVALIDRECT;
  4534. }
  4535. }
  4536. /*
  4537. * validate source surface
  4538. */
  4539. this_src_int = (LPDDRAWI_DDRAWSURFACE_INT)lpDDBltBatch[i].lpDDSSrc;
  4540. if( this_src_int != NULL )
  4541. {
  4542. if( !VALID_DIRECTDRAWSURFACE_PTR( this_src_int ) )
  4543. {
  4544. DPF( 1, "Invalid source specified, entry %d", i );
  4545. LEAVE_BOTH();
  4546. return DDERR_INVALIDOBJECT;
  4547. }
  4548. this_src_lcl = this_src_int->lpLcl;
  4549. if( SURFACE_LOST( this_src_lcl ) )
  4550. {
  4551. DPF( 1, "Src lost, entry %d", i) ;
  4552. LEAVE_BOTH();
  4553. return DDERR_SURFACELOST;
  4554. }
  4555. if( this_src_lcl->lpGbl->dwUsageCount > 0 )
  4556. {
  4557. DPF( 2, "Source surface %08lx is still locked, entry %d", this_src_int, i );
  4558. LEAVE_BOTH();
  4559. return DDERR_SURFACEBUSY;
  4560. }
  4561. if (this_src_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  4562. {
  4563. DPF_ERR( "It is an optimized surface" );
  4564. LEAVE_DDRAW();
  4565. return DDERR_ISOPTIMIZEDSURFACE;
  4566. }
  4567. }
  4568. if (this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  4569. {
  4570. DPF_ERR( "It is an optimized surface" );
  4571. LEAVE_DDRAW();
  4572. return DDERR_ISOPTIMIZEDSURFACE;
  4573. }
  4574. /*
  4575. * validate src rect
  4576. */
  4577. if( lpDDBltBatch[i].lprSrc != NULL )
  4578. {
  4579. if( !VALID_RECT_PTR(lpDDBltBatch[i].lprSrc) )
  4580. {
  4581. DPF( 1, "src rectangle invalid, entry %d", i );
  4582. LEAVE_BOTH();
  4583. return DDERR_INVALIDRECT;
  4584. }
  4585. }
  4586. /*
  4587. * validate bltfx ptr
  4588. */
  4589. if( lpDDBltBatch[i].lpDDBltFx != NULL )
  4590. {
  4591. if( !VALID_DDBLTFX_PTR( lpDDBltBatch[i].lpDDBltFx ) )
  4592. {
  4593. DPF( 1, "Invalid BLTFX specified, entry %d", i );
  4594. LEAVE_BOTH();
  4595. return DDERR_INVALIDPARAMS;
  4596. }
  4597. }
  4598. else
  4599. {
  4600. if( lpDDBltBatch[i].dwFlags
  4601. & ( DDBLT_ALPHASRCCONSTOVERRIDE |
  4602. DDBLT_ALPHADESTCONSTOVERRIDE |
  4603. DDBLT_ALPHASRCSURFACEOVERRIDE |
  4604. DDBLT_ALPHADESTSURFACEOVERRIDE |
  4605. DDBLT_COLORFILL |
  4606. DDBLT_DDFX |
  4607. DDBLT_DDROPS |
  4608. DDBLT_DEPTHFILL |
  4609. DDBLT_KEYDESTOVERRIDE |
  4610. DDBLT_KEYSRCOVERRIDE |
  4611. DDBLT_ROP |
  4612. DDBLT_ROTATIONANGLE |
  4613. DDBLT_ZBUFFERDESTCONSTOVERRIDE |
  4614. DDBLT_ZBUFFERDESTOVERRIDE |
  4615. DDBLT_ZBUFFERSRCCONSTOVERRIDE |
  4616. DDBLT_ZBUFFERSRCOVERRIDE ) )
  4617. {
  4618. DPF( 1, "BltFX required but not specified, entry %d", i );
  4619. LEAVE_BOTH();
  4620. return DDERR_INVALIDPARAMS;
  4621. }
  4622. }
  4623. }
  4624. ddrval = DDERR_UNSUPPORTED;
  4625. for( i=0;i<(int)dwCount;i++ )
  4626. {
  4627. #if 0
  4628. while( 1 )
  4629. {
  4630. ddrval = doBlt( this_dest_lcl,
  4631. lpDDBltBatch[i].lprDest,
  4632. lpDDBltBatch[i].lpDDSSrc,
  4633. lpDDBltBatch[i].lprSrc,
  4634. lpDDBltBatch[i].dwFlags,
  4635. lpDDBltBatch[i].lpDDBltFX );
  4636. if( ddrval != DDERR_WASSTILLDRAWING )
  4637. {
  4638. break;
  4639. }
  4640. }
  4641. #endif
  4642. if( ddrval != DD_OK )
  4643. {
  4644. break;
  4645. }
  4646. }
  4647. LEAVE_BOTH();
  4648. return ddrval;
  4649. } /* BltBatch */
  4650. /*
  4651. * XformRect
  4652. *
  4653. * Transform a clipped rect in destination space to the corresponding clipped
  4654. * rect in src space. So, if we're stretching from src to dest, this yields
  4655. * the unstretched clipping rect in src space.
  4656. *
  4657. * PARAMETERS:
  4658. * prcSrc - unclipped rect in the source space
  4659. * prcDest - unclipped rect in the destination space
  4660. * prcClippedDest - the rect we want to transform
  4661. * prcClippedSrc - the resulting rect in the source space. return value.
  4662. * scale_x - 16.16 fixed point src/dest width ratio
  4663. * scale_y - 16.16 fixed point src/dest height ratio
  4664. *
  4665. * DESCRIPTION:
  4666. * Given an rect in source space and a rect in destination space, and a
  4667. * clipped rectangle in the destination space (prcClippedDest), return
  4668. * the rectangle in the source space (prcClippedSrc) that maps to
  4669. * prcClippedDest.
  4670. *
  4671. * Use 16.16 fixed point math for more accuracy. (Shift left, do math,
  4672. * shift back (w/ round))
  4673. *
  4674. * RETURNS:
  4675. * DD_OK always. prcClippedSrc is the mapped rectangle.
  4676. *
  4677. */
  4678. HRESULT XformRect(RECT * prcSrc, RECT * prcDest, RECT * prcClippedDest,
  4679. RECT * prcClippedSrc, DWORD scale_x, DWORD scale_y)
  4680. {
  4681. /*
  4682. * This first calculation is done with fixed point arithmetic (16.16).
  4683. * The result is converted to (32.0) below. Scale back into source space
  4684. */
  4685. prcClippedSrc->left = (prcClippedDest->left - prcDest->left) * scale_x;
  4686. prcClippedSrc->right = (prcClippedDest->right - prcDest->left) * scale_x;
  4687. prcClippedSrc->top = (prcClippedDest->top - prcDest->top) * scale_y;
  4688. prcClippedSrc->bottom = (prcClippedDest->bottom - prcDest->top) * scale_y;
  4689. /*
  4690. * now round (adding 0x8000 rounds) and translate (offset by the
  4691. * src offset)
  4692. */
  4693. prcClippedSrc->left = (((DWORD)prcClippedSrc->left + 0x8000) >> 16) + prcSrc->left;
  4694. prcClippedSrc->right = (((DWORD)prcClippedSrc->right + 0x8000) >> 16) + prcSrc->left;
  4695. prcClippedSrc->top = (((DWORD)prcClippedSrc->top + 0x8000) >> 16) + prcSrc->top;
  4696. prcClippedSrc->bottom = (((DWORD)prcClippedSrc->bottom + 0x8000) >> 16) + prcSrc->top;
  4697. /*
  4698. * Check for zero-sized source rect dimensions and bump if necessary
  4699. */
  4700. if (prcClippedSrc->left == prcClippedSrc->right)
  4701. {
  4702. if (prcClippedSrc->right == prcSrc->right)
  4703. {
  4704. (prcClippedSrc->left)--;
  4705. }
  4706. else
  4707. {
  4708. (prcClippedSrc->right)++;
  4709. }
  4710. }
  4711. if (prcClippedSrc->top == prcClippedSrc->bottom)
  4712. {
  4713. if (prcClippedSrc->bottom == prcSrc->bottom)
  4714. {
  4715. (prcClippedSrc->top)--;
  4716. }
  4717. else
  4718. {
  4719. (prcClippedSrc->bottom)++;
  4720. }
  4721. }
  4722. return DD_OK;
  4723. } /* XformRect */