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.

3360 lines
106 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1994-1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: ddsprite.c
  6. * Content: DirectDraw Surface support for sprite display lists:
  7. * SetSpriteDisplayList
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 03-nov-97 jvanaken Original version
  12. *
  13. ***************************************************************************/
  14. #include "ddrawpr.h"
  15. // function from ddraw module ddclip.c
  16. extern HRESULT InternalGetClipList(LPDIRECTDRAWCLIPPER,
  17. LPRECT,
  18. LPRGNDATA,
  19. LPDWORD,
  20. LPDDRAWI_DIRECTDRAW_GBL);
  21. #define _DDHAL_SetSpriteDisplayList NULL
  22. /*
  23. * Masks for distinguishing driver's blit caps from driver's overlay caps.
  24. */
  25. #define DDFXCAPS_BLTBITS \
  26. (DDFXCAPS_BLTALPHA|DDFXCAPS_BLTFILTER|DDFXCAPS_BLTTRANSFORM)
  27. #define DDFXCAPS_OVERLAYBITS \
  28. (DDFXCAPS_OVERLAYALPHA|DDFXCAPS_OVERLAYFILTER|DDFXCAPS_OVERLAYTRANSFORM)
  29. #define DDCKEYCAPS_BLTBITS (DDCKEYCAPS_SRCBLT|DDCKEYCAPS_DESTBLT)
  30. #define DDCKEYCAPS_OVERLAYBITS (DDCKEYCAPS_SRCOVERLAY|DDCKEYCAPS_DESTOVERLAY)
  31. #define DDALPHACAPS_BLTBITS \
  32. (DDALPHACAPS_BLTSATURATE|DDALPHACAPS_BLTPREMULT| \
  33. DDALPHACAPS_BLTNONPREMULT|DDALPHACAPS_BLTRGBASCALE1F| \
  34. DDALPHACAPS_BLTRGBASCALE2F|DDALPHACAPS_BLTRGBASCALE4F)
  35. #define DDALPHACAPS_OVERLAYBITS \
  36. (DDALPHACAPS_OVERLAYSATURATE|DDALPHACAPS_OVERLAYPREMULT| \
  37. DDALPHACAPS_OVERLAYNONPREMULT|DDALPHACAPS_OVERLAYRGBASCALE1F| \
  38. DDALPHACAPS_OVERLAYRGBASCALE2F|DDALPHACAPS_OVERLAYRGBASCALE4F)
  39. #define DDFILTCAPS_BLTBITS \
  40. (DDFILTCAPS_BLTBILINEARFILTER|DDFILTCAPS_BLTBLURFILTER| \
  41. DDFILTCAPS_BLTFLATFILTER)
  42. #define DDFILTCAPS_OVERLAYBITS \
  43. (DDFILTCAPS_OVERLAYBILINEARFILTER|DDFILTCAPS_OVERLAYBLURFILTER| \
  44. DDFILTCAPS_OVERLAYFLATFILTER)
  45. #define DDTFRMCAPS_BLTBITS (DDTFRMCAPS_BLTAFFINETRANSFORM)
  46. #define DDTFRMCAPS_OVERLAYBITS (DDTFRMCAPS_OVERLAYAFFINETRANSFORM)
  47. #undef DPF_MODNAME
  48. #define DPF_MODNAME "SetSpriteDisplayList"
  49. /*
  50. * Driver capabilities for handling current sprite
  51. */
  52. typedef struct
  53. {
  54. // caps for hardware driver
  55. //DWORD dwCaps;
  56. DWORD dwCKeyCaps;
  57. DWORD dwFXCaps;
  58. DWORD dwAlphaCaps;
  59. DWORD dwFilterCaps;
  60. DWORD dwTransformCaps;
  61. // caps for HEL
  62. //DWORD dwHELCaps;
  63. DWORD dwHELCKeyCaps;
  64. DWORD dwHELFXCaps;
  65. DWORD dwHELAlphaCaps;
  66. DWORD dwHELFilterCaps;
  67. DWORD dwHELTransformCaps;
  68. // surface caps
  69. DWORD dwDestSurfCaps;
  70. DWORD dwSrcSurfCaps;
  71. // minification limit
  72. DWORD dwMinifyLimit;
  73. DWORD dwHELMinifyLimit;
  74. BOOL bNoHAL; // TRUE disqualifies hardware driver
  75. BOOL bNoHEL; // TRUE disqualifies HEL
  76. // TRUE=overlay sprite, FALSE=blitted sprite
  77. BOOL bOverlay;
  78. } SPRITE_CAPS, *LPSPRITE_CAPS;
  79. /*
  80. * The master sprite display list consists of some number of sublists.
  81. * Each sublist contains all the overlay sprites that are displayed
  82. * within a particular window. Only the first member of the variable-
  83. * size sprite[] array appears explicitly in the structure definition
  84. * below, but dwSize takes into account the ENTIRE sprite[] array.
  85. * The pRgn member points to the dynamically allocated buffer that
  86. * contains the clipping region.
  87. */
  88. typedef struct _SPRITESUBLIST
  89. {
  90. DWORD dwSize; // size of this sublist (in bytes)
  91. LPDIRECTDRAWSURFACE pPrimary; // primary surface
  92. LPDIRECTDRAWCLIPPER pClipper; // clipper for window (NULL = full screen)
  93. DWORD dwProcessId; // process ID (in case pClipper is NULL)
  94. LPRGNDATA pRgn; // pointer to clipping region data
  95. DWORD dwCount; // number of sprites in sublist
  96. DDSPRITEI sprite[1]; // array of sprites (first member)
  97. } SPRITESUBLIST, *LPSPRITESUBLIST;
  98. /*
  99. * Buffer used to hold temporary sprite display list passed to driver.
  100. * Only the first member of the variable-size pSprites[] array appears
  101. * explicitly in the structure definition below, but the dwSize value
  102. * takes into account the ENTIRE pSprite[] array.
  103. */
  104. typedef struct _BUFFER
  105. {
  106. DWORD dwSize; // size of this buffer (in bytes)
  107. DDHAL_SETSPRITEDISPLAYLISTDATA HalData; // HAL data for sprite display list
  108. LPDDSPRITEI pSprite[1]; // array of pointers to sprites
  109. } BUFFER, *LPBUFFER;
  110. /*
  111. * Master sprite display list -- Contains copies of the overlay-sprite
  112. * display lists for all windows that currently display overlay sprites.
  113. * Only the first member of the variable-size spriteSubList[] array
  114. * appears explicitly in the structure definition below. Each sublist
  115. * contains all the overlay sprites displayed within a particular window.
  116. */
  117. #define MAXNUMSPRITESUBLISTS (16)
  118. typedef struct _MASTERSPRITELIST
  119. {
  120. //DWORD dwSize; // size of master list (in bytes)
  121. LPDDRAWI_DIRECTDRAW_GBL pdrv; // global DDraw object
  122. LPDDRAWI_DDRAWSURFACE_LCL surf_lcl; // primary surface (local object)
  123. RECT rcPrimary; // rectangle = entire primary surface
  124. DWORD dwFlags; // latest caller's DDSSDL_WAIT flag
  125. #ifdef WIN95
  126. DWORD dwModeCreatedIn; // valid only in this video mode
  127. #else
  128. DISPLAYMODEINFO dmiCreated; // valid only in this video mode
  129. #endif
  130. LPBUFFER pBuffer; // buffer storage
  131. DWORD dwNumSubLists; // number of sprite sublists
  132. LPSPRITESUBLIST pSubList[MAXNUMSPRITESUBLISTS]; // array of sublists (fixed size)
  133. } MASTERSPRITELIST, *LPMASTERSPRITELIST;
  134. /*
  135. * Return the dwFlags member from the DDPIXELFORMAT structure
  136. * that describes the specified surface's pixel format.
  137. */
  138. static DWORD getPixelFormatFlags(LPDDRAWI_DDRAWSURFACE_LCL surf_lcl)
  139. {
  140. LPDDPIXELFORMAT pDDPF;
  141. if (surf_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT)
  142. {
  143. // surface contains explicitly defined pixel format
  144. pDDPF = &surf_lcl->lpGbl->ddpfSurface;
  145. }
  146. else
  147. {
  148. // surface's pixel format is implicit -- same as primary's
  149. pDDPF = &surf_lcl->lpSurfMore->lpDD_lcl->lpGbl->vmiData.ddpfDisplay;
  150. }
  151. return pDDPF->dwFlags;
  152. } /* getPixelFormatFlags */
  153. /*
  154. * Initialize SPRITE_CAPS structure according to whether source and
  155. * dest surfaces are in system or video (local or nonlocal) memory.
  156. */
  157. static void initSpriteCaps(LPSPRITE_CAPS pcaps, LPDDRAWI_DIRECTDRAW_GBL pdrv)
  158. {
  159. DDASSERT(pcaps != NULL);
  160. if (pcaps->bOverlay)
  161. {
  162. // Get minification limits for overlays.
  163. pcaps->dwMinifyLimit = pdrv->lpddMoreCaps->dwOverlayAffineMinifyLimit;
  164. pcaps->dwHELMinifyLimit = pdrv->lpddHELMoreCaps->dwOverlayAffineMinifyLimit;
  165. }
  166. else
  167. {
  168. // Get minification limits for blits.
  169. pcaps->dwMinifyLimit = pdrv->lpddMoreCaps->dwBltAffineMinifyLimit;
  170. pcaps->dwHELMinifyLimit = pdrv->lpddHELMoreCaps->dwBltAffineMinifyLimit;
  171. }
  172. if (pcaps->dwSrcSurfCaps & DDSCAPS_NONLOCALVIDMEM &&
  173. pdrv->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEMCAPS)
  174. {
  175. /*
  176. * A driver that specifies nonlocal video-memory caps that differ
  177. * from its local video-memory caps is automatically disqualified
  178. * because the currently specified nonlocal vidmem caps do not
  179. * include alpha, filter, or transform caps. Should we fix this?
  180. */
  181. pcaps->bNoHAL = TRUE;
  182. }
  183. if ((pcaps->dwSrcSurfCaps | pcaps->dwDestSurfCaps) & DDSCAPS_SYSTEMMEMORY &&
  184. !(pdrv->ddCaps.dwCaps & DDCAPS_CANBLTSYSMEM))
  185. {
  186. pcaps->bNoHAL = TRUE; // H/W driver can't blit to/from system memory
  187. }
  188. if (pcaps->dwSrcSurfCaps & pcaps->dwDestSurfCaps & DDSCAPS_VIDEOMEMORY)
  189. {
  190. //pcaps->dwCaps = pdrv->ddCaps.dwCaps;
  191. pcaps->dwCKeyCaps = pdrv->ddCaps.dwCKeyCaps;
  192. pcaps->dwFXCaps = pdrv->ddCaps.dwFXCaps;
  193. if (pdrv->lpddMoreCaps)
  194. {
  195. pcaps->dwAlphaCaps = pdrv->lpddMoreCaps->dwAlphaCaps;
  196. pcaps->dwFilterCaps = pdrv->lpddMoreCaps->dwFilterCaps;
  197. pcaps->dwTransformCaps = pdrv->lpddMoreCaps->dwTransformCaps;
  198. }
  199. //pcaps->dwHELCaps = pdrv->ddHELCaps.dwCaps;
  200. pcaps->dwHELCKeyCaps = pdrv->ddHELCaps.dwCKeyCaps;
  201. pcaps->dwHELFXCaps = pdrv->ddHELCaps.dwFXCaps;
  202. if (pdrv->lpddHELMoreCaps)
  203. {
  204. pcaps->dwHELAlphaCaps = pdrv->lpddHELMoreCaps->dwAlphaCaps;
  205. pcaps->dwHELFilterCaps = pdrv->lpddHELMoreCaps->dwFilterCaps;
  206. pcaps->dwHELTransformCaps = pdrv->lpddHELMoreCaps->dwTransformCaps;
  207. }
  208. }
  209. else if (pcaps->dwSrcSurfCaps & DDSCAPS_SYSTEMMEMORY &&
  210. pcaps->dwDestSurfCaps & DDSCAPS_VIDEOMEMORY)
  211. {
  212. //pcaps->dwCaps = pdrv->ddCaps.dwSVBCaps;
  213. pcaps->dwCKeyCaps = pdrv->ddCaps.dwSVBCKeyCaps;
  214. pcaps->dwFXCaps = pdrv->ddCaps.dwSVBFXCaps;
  215. if (pdrv->lpddMoreCaps)
  216. {
  217. pcaps->dwAlphaCaps = pdrv->lpddMoreCaps->dwSVBAlphaCaps;
  218. pcaps->dwFilterCaps = pdrv->lpddMoreCaps->dwSVBFilterCaps;
  219. pcaps->dwTransformCaps = pdrv->lpddMoreCaps->dwSVBTransformCaps;
  220. }
  221. //pcaps->dwHELCaps = pdrv->ddHELCaps.dwSVBCaps;
  222. pcaps->dwHELCKeyCaps = pdrv->ddHELCaps.dwSVBCKeyCaps;
  223. pcaps->dwHELFXCaps = pdrv->ddHELCaps.dwSVBFXCaps;
  224. if (pdrv->lpddHELMoreCaps)
  225. {
  226. pcaps->dwHELAlphaCaps = pdrv->lpddHELMoreCaps->dwSVBAlphaCaps;
  227. pcaps->dwHELFilterCaps = pdrv->lpddHELMoreCaps->dwSVBFilterCaps;
  228. pcaps->dwHELTransformCaps = pdrv->lpddHELMoreCaps->dwSVBTransformCaps;
  229. }
  230. }
  231. else if (pcaps->dwSrcSurfCaps & DDSCAPS_VIDEOMEMORY &&
  232. pcaps->dwDestSurfCaps & DDSCAPS_SYSTEMMEMORY)
  233. {
  234. //pcaps->dwCaps = pdrv->ddCaps.dwVSBCaps;
  235. pcaps->dwCKeyCaps = pdrv->ddCaps.dwVSBCKeyCaps;
  236. pcaps->dwFXCaps = pdrv->ddCaps.dwVSBFXCaps;
  237. if (pdrv->lpddMoreCaps)
  238. {
  239. pcaps->dwAlphaCaps = pdrv->lpddMoreCaps->dwVSBAlphaCaps;
  240. pcaps->dwFilterCaps = pdrv->lpddMoreCaps->dwVSBFilterCaps;
  241. pcaps->dwTransformCaps = pdrv->lpddMoreCaps->dwVSBTransformCaps;
  242. }
  243. //pcaps->dwHELCaps = pdrv->ddHELCaps.dwVSBCaps;
  244. pcaps->dwHELCKeyCaps = pdrv->ddHELCaps.dwVSBCKeyCaps;
  245. pcaps->dwHELFXCaps = pdrv->ddHELCaps.dwVSBFXCaps;
  246. if (pdrv->lpddHELMoreCaps)
  247. {
  248. pcaps->dwHELAlphaCaps = pdrv->lpddHELMoreCaps->dwVSBAlphaCaps;
  249. pcaps->dwHELFilterCaps = pdrv->lpddHELMoreCaps->dwVSBFilterCaps;
  250. pcaps->dwHELTransformCaps = pdrv->lpddHELMoreCaps->dwVSBTransformCaps;
  251. }
  252. }
  253. else if (pcaps->dwSrcSurfCaps & pcaps->dwDestSurfCaps & DDSCAPS_SYSTEMMEMORY)
  254. {
  255. //pcaps->dwCaps = pdrv->ddCaps.dwSSBCaps;
  256. pcaps->dwCKeyCaps = pdrv->ddCaps.dwSSBCKeyCaps;
  257. pcaps->dwFXCaps = pdrv->ddCaps.dwSSBFXCaps;
  258. if (pdrv->lpddMoreCaps)
  259. {
  260. pcaps->dwAlphaCaps = pdrv->lpddMoreCaps->dwSSBAlphaCaps;
  261. pcaps->dwFilterCaps = pdrv->lpddMoreCaps->dwSSBFilterCaps;
  262. pcaps->dwTransformCaps = pdrv->lpddMoreCaps->dwSSBTransformCaps;
  263. }
  264. //pcaps->dwHELCaps = pdrv->ddHELCaps.dwSSBCaps;
  265. pcaps->dwHELCKeyCaps = pdrv->ddHELCaps.dwSSBCKeyCaps;
  266. pcaps->dwHELFXCaps = pdrv->ddHELCaps.dwSSBFXCaps;
  267. if (pdrv->lpddHELMoreCaps)
  268. {
  269. pcaps->dwHELAlphaCaps = pdrv->lpddHELMoreCaps->dwSSBAlphaCaps;
  270. pcaps->dwHELFilterCaps = pdrv->lpddHELMoreCaps->dwSSBFilterCaps;
  271. pcaps->dwHELTransformCaps = pdrv->lpddHELMoreCaps->dwSSBTransformCaps;
  272. }
  273. }
  274. if (pcaps->bOverlay)
  275. {
  276. // Isolate overlay bits by masking off all blit-related bits.
  277. //pcaps->dwCaps &= DDCAPS_OVERLAYBITS;
  278. pcaps->dwCKeyCaps &= DDCKEYCAPS_OVERLAYBITS;
  279. pcaps->dwFXCaps &= DDFXCAPS_OVERLAYBITS;
  280. pcaps->dwAlphaCaps &= DDALPHACAPS_OVERLAYBITS;
  281. pcaps->dwFilterCaps &= DDFILTCAPS_OVERLAYBITS;
  282. pcaps->dwTransformCaps &= DDTFRMCAPS_OVERLAYBITS;
  283. //pcaps->dwHELCaps &= DDCAPS_OVERLAYBITS;
  284. pcaps->dwHELCKeyCaps &= DDCKEYCAPS_OVERLAYBITS;
  285. pcaps->dwHELFXCaps &= DDFXCAPS_OVERLAYBITS;
  286. pcaps->dwHELAlphaCaps &= DDALPHACAPS_OVERLAYBITS;
  287. pcaps->dwHELFilterCaps &= DDFILTCAPS_OVERLAYBITS;
  288. pcaps->dwHELTransformCaps &= DDTFRMCAPS_OVERLAYBITS;
  289. }
  290. else
  291. {
  292. // Isolate blit bits by masking off all overlay-related bits.
  293. //pcaps->dwCaps &= DDCAPS_BLTBITS;
  294. pcaps->dwCKeyCaps &= DDCKEYCAPS_BLTBITS;
  295. pcaps->dwFXCaps &= DDFXCAPS_BLTBITS;
  296. pcaps->dwAlphaCaps &= DDALPHACAPS_BLTBITS;
  297. pcaps->dwFilterCaps &= DDFILTCAPS_BLTBITS;
  298. pcaps->dwTransformCaps &= DDTFRMCAPS_BLTBITS;
  299. //pcaps->dwHELCaps &= DDCAPS_BLTBITS;
  300. pcaps->dwHELCKeyCaps &= DDCKEYCAPS_BLTBITS;
  301. pcaps->dwHELFXCaps &= DDFXCAPS_BLTBITS;
  302. pcaps->dwHELAlphaCaps &= DDALPHACAPS_BLTBITS;
  303. pcaps->dwHELFilterCaps &= DDFILTCAPS_BLTBITS;
  304. pcaps->dwHELTransformCaps &= DDTFRMCAPS_BLTBITS;
  305. }
  306. } /* initSpriteCaps */
  307. /*
  308. * Verify that affine transform does not exceed driver's minification
  309. * limit. Arg pdrv is a pointer to the global DirectDraw object. Arg
  310. * lpDDSpriteFX points to a DDSPRITEFX structure containing 4x4 matrix.
  311. * Arg overlay is TRUE for overlay sprites, and FALSE for blitted
  312. * sprites. Arg emulation is TRUE if the overlay is to be emulated.
  313. * Returns DD_OK if specified affine transform is within limits.
  314. */
  315. static void checkMinification(LPDDSPRITEFX lpDDSpriteFX,
  316. LPSPRITE_CAPS pcaps)
  317. {
  318. int i;
  319. for (i = 0; i < 2; ++i)
  320. {
  321. FLOAT a00, a01, a10, a11, det, amax;
  322. DWORD minlim;
  323. /*
  324. * Get driver's minification limit.
  325. */
  326. if (i == 0)
  327. {
  328. // Get hardware driver's minification limit.
  329. minlim = pcaps->dwMinifyLimit;
  330. if (pcaps->bNoHAL || minlim == 0) // minlim = 0 means no limit
  331. {
  332. continue;
  333. }
  334. }
  335. else
  336. {
  337. // Get HEL's minification limit.
  338. minlim = pcaps->dwHELMinifyLimit;
  339. if (pcaps->bNoHEL || minlim == 0)
  340. {
  341. continue;
  342. }
  343. }
  344. /*
  345. * Check transformation matrix against driver's minification limit.
  346. */
  347. a00 = lpDDSpriteFX->fTransform[0][0];
  348. a01 = lpDDSpriteFX->fTransform[0][1];
  349. a10 = lpDDSpriteFX->fTransform[1][0];
  350. a11 = lpDDSpriteFX->fTransform[1][1];
  351. // Calculate determinant of Jacobian.
  352. det = a00*a11 - a10*a01;
  353. // Get absolute values of the 4 Jacobian coefficients.
  354. if (a00 < 0) // could have used fabs() here
  355. a00 = -a00;
  356. if (a01 < 0)
  357. a01 = -a01;
  358. if (a10 < 0)
  359. a10 = -a10;
  360. if (a11 < 0)
  361. a11 = -a11;
  362. if (det < 0)
  363. det = -det;
  364. // Find biggest coefficient in Jacobian.
  365. amax = a00;
  366. if (a01 > amax)
  367. amax = a01;
  368. if (a10 > amax)
  369. amax = a10;
  370. if (a11 > amax)
  371. amax = a11;
  372. // Test the minification level against the driver's limit.
  373. if (1000*amax >= det*minlim)
  374. {
  375. // Affine transform exceeds driver's minification limit.
  376. if (i == 0)
  377. {
  378. pcaps->bNoHAL = TRUE; // disqualify hardware driver
  379. }
  380. else
  381. {
  382. pcaps->bNoHEL = TRUE; // disqualify HEL
  383. }
  384. }
  385. }
  386. } /* checkMinification */
  387. /*
  388. * Validate the DDSPRITE structure. Arg pSprite is a pointer to a
  389. * DDSPRITE structure. Arg pdrv is a pointer to the dest surface's
  390. * DirectDraw object. Arg dest_lcl is a pointer to the destination
  391. * surface. Arg pcaps is a pointer to a structure containing the
  392. * driver's capabilities. Returns DD_OK if successful.
  393. */
  394. static HRESULT validateSprite(LPDDSPRITE pSprite,
  395. LPDDRAWI_DIRECTDRAW_GBL pdrv,
  396. LPDDRAWI_DDRAWSURFACE_LCL surf_dest_lcl,
  397. LPSPRITE_CAPS pcaps,
  398. DWORD dwDDPFDestFlags)
  399. {
  400. LPDDRAWI_DDRAWSURFACE_INT surf_src_int;
  401. LPDDRAWI_DDRAWSURFACE_LCL surf_src_lcl;
  402. LPDDRAWI_DDRAWSURFACE_GBL surf_src;
  403. DWORD dwDDPFSrcFlags;
  404. LPRECT prSrc;
  405. LPRECT prDest;
  406. DWORD dest_width = 0;
  407. DWORD dest_height = 0;
  408. DWORD src_width = 0;
  409. DWORD src_height = 0;
  410. DDASSERT(!(pcaps->bNoHAL && pcaps->bNoHEL));
  411. /*
  412. * Validate the DDSPRITE pointer. (A caller that does not use the
  413. * embedded DDSPRITEFX structure must still alloc space for it.)
  414. */
  415. if (IsBadWritePtr((LPVOID)pSprite, (UINT)sizeof(DDSPRITE)))
  416. {
  417. DPF_ERR("Bad pointer to DDSPRITE structure...");
  418. return DDERR_INVALIDPARAMS;
  419. }
  420. /*
  421. * If the caller doesn't use the embedded DDSPRITEFX struct,
  422. * we'll fill it in ourselves before passing it to the driver.
  423. */
  424. if (!(pSprite->dwFlags & DDSPRITE_DDSPRITEFX))
  425. {
  426. if (pSprite->dwFlags & (DDSPRITE_KEYDESTOVERRIDE | DDSPRITE_KEYSRCOVERRIDE))
  427. {
  428. DPF_ERR("Illegal to set color-key override if DDSPRITEFX is invalid");
  429. return DDERR_INVALIDPARAMS;
  430. }
  431. pSprite->ddSpriteFX.dwSize = sizeof(DDSPRITEFX);
  432. pSprite->ddSpriteFX.dwDDFX = 0;
  433. pSprite->dwFlags |= DDSPRITE_DDSPRITEFX;
  434. }
  435. /*
  436. * Validate the source surface for the sprite.
  437. */
  438. surf_src_int = (LPDDRAWI_DDRAWSURFACE_INT)pSprite->lpDDSSrc;
  439. if (!VALID_DIRECTDRAWSURFACE_PTR(surf_src_int))
  440. {
  441. DPF_ERR("Invalid source surface pointer...");
  442. return DDERR_INVALIDOBJECT;
  443. }
  444. surf_src_lcl = surf_src_int->lpLcl;
  445. surf_src = surf_src_lcl->lpGbl;
  446. if (SURFACE_LOST(surf_src_lcl))
  447. {
  448. DPF_ERR("Lost source surface...");
  449. return DDERR_SURFACELOST;
  450. }
  451. /*
  452. * We cannot use source and destination surfaces that were
  453. * created with different DirectDraw objects.
  454. */
  455. if (surf_src->lpDD != pdrv
  456. && surf_src->lpDD->dwFlags & DDRAWI_DISPLAYDRV &&
  457. pdrv->dwFlags & DDRAWI_DISPLAYDRV)
  458. {
  459. DPF_ERR("Source and dest surfaces must have same DirectDraw device...");
  460. LEAVE_BOTH();
  461. return DDERR_DEVICEDOESNTOWNSURFACE;
  462. }
  463. /*
  464. * Validate destination rectangle.
  465. */
  466. prDest = &pSprite->rcDest;
  467. if (pSprite->dwFlags & DDSPRITE_RECTDEST)
  468. {
  469. // Validate destination rectangle specified in rcDest member.
  470. dest_height = prDest->bottom - prDest->top;
  471. dest_width = prDest->right - prDest->left;
  472. if ((int)dest_height <= 0 || (int)dest_width <= 0)
  473. {
  474. DPF_ERR("Invalid destination rectangle...");
  475. return DDERR_INVALIDRECT;
  476. }
  477. if (pSprite->ddSpriteFX.dwDDFX & DDSPRITEFX_AFFINETRANSFORM)
  478. {
  479. DPF_ERR("Illegal to specify both dest rect and affine transform...");
  480. return DDERR_INVALIDPARAMS;
  481. }
  482. }
  483. else if (!(pSprite->ddSpriteFX.dwDDFX & DDSPRITEFX_AFFINETRANSFORM))
  484. {
  485. /*
  486. * The implicit destination is the entire dest surface. Substitute
  487. * an explicit destination rectangle that covers the dest surface.
  488. */
  489. MAKE_SURF_RECT(surf_dest_lcl->lpGbl, surf_dest_lcl, pSprite->rcDest);
  490. pSprite->dwFlags |= DDSPRITE_RECTDEST;
  491. }
  492. /*
  493. * Validate source rectangle.
  494. */
  495. prSrc = &pSprite->rcSrc;
  496. if (pSprite->dwFlags & DDSPRITE_RECTSRC)
  497. {
  498. // Validate source rectangle specified in rcSrc member.
  499. src_height = prSrc->bottom - prSrc->top;
  500. src_width = prSrc->right - prSrc->left;
  501. if (((int)src_height <= 0) || ((int)src_width <= 0) ||
  502. ((int)prSrc->top < 0) || ((int)prSrc->left < 0) ||
  503. ((DWORD) prSrc->bottom > (DWORD) surf_src->wHeight) ||
  504. ((DWORD) prSrc->right > (DWORD) surf_src->wWidth))
  505. {
  506. DPF_ERR("Invalid source rectangle...");
  507. return DDERR_INVALIDRECT;
  508. }
  509. }
  510. else
  511. {
  512. /*
  513. * The implicit source rect is the entire dest surface. Substitute
  514. * an explicit source rectangle that covers the source surface.
  515. */
  516. MAKE_SURF_RECT(surf_src, surf_src_lcl, pSprite->rcSrc);
  517. pSprite->dwFlags |= DDSPRITE_RECTSRC;
  518. }
  519. /*
  520. * Validate memory alignment of source and dest rectangles.
  521. */
  522. if (pdrv->ddCaps.dwCaps & (DDCAPS_ALIGNBOUNDARYDEST | DDCAPS_ALIGNSIZEDEST |
  523. DDCAPS_ALIGNBOUNDARYSRC | DDCAPS_ALIGNSIZESRC))
  524. {
  525. if (pdrv->ddCaps.dwCaps & DDCAPS_ALIGNBOUNDARYDEST &&
  526. (prDest->left % pdrv->ddCaps.dwAlignBoundaryDest) != 0)
  527. {
  528. DPF_ERR("Destination left misaligned...");
  529. return DDERR_XALIGN;
  530. }
  531. if (pdrv->ddCaps.dwCaps & DDCAPS_ALIGNBOUNDARYSRC &&
  532. (prSrc->left % pdrv->ddCaps.dwAlignBoundarySrc) != 0)
  533. {
  534. DPF_ERR("Source left misaligned...");
  535. return DDERR_XALIGN;
  536. }
  537. if (pdrv->ddCaps.dwCaps & DDCAPS_ALIGNSIZEDEST &&
  538. (dest_width % pdrv->ddCaps.dwAlignSizeDest) != 0)
  539. {
  540. DPF_ERR("Destination width misaligned...");
  541. return DDERR_XALIGN;
  542. }
  543. if (pdrv->ddCaps.dwCaps & DDCAPS_ALIGNSIZESRC &&
  544. (src_width % pdrv->ddCaps.dwAlignSizeSrc) != 0)
  545. {
  546. DPF_ERR("Source width misaligned...");
  547. return DDERR_XALIGN;
  548. }
  549. }
  550. /*
  551. * Are the source surface's caps the same as those of the previous sprite?
  552. */
  553. if ((surf_src_lcl->ddsCaps.dwCaps ^ pcaps->dwSrcSurfCaps) &
  554. (DDSCAPS_SYSTEMMEMORY | DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM))
  555. {
  556. /*
  557. * This source surface's memory type differs from that of the
  558. * previous source surface, so we need to get a new set of caps.
  559. */
  560. pcaps->dwSrcSurfCaps = surf_src_lcl->ddsCaps.dwCaps;
  561. initSpriteCaps(pcaps, pdrv);
  562. }
  563. /*
  564. * Get pixel-format flags for source surface.
  565. */
  566. dwDDPFSrcFlags = getPixelFormatFlags(surf_src_lcl);
  567. /*
  568. * If the source surface is palette-indexed, make sure a palette
  569. * is attached to it.
  570. */
  571. if (dwDDPFSrcFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
  572. DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8) &&
  573. (surf_src_lcl->lpDDPalette == NULL ||
  574. surf_src_lcl->lpDDPalette->lpLcl->lpGbl->lpColorTable == NULL))
  575. {
  576. DPF_ERR( "No palette associated with palette-indexed surface..." );
  577. LEAVE_BOTH();
  578. return DDERR_NOPALETTEATTACHED;
  579. }
  580. /*
  581. * Is any color keying required for this sprite?
  582. */
  583. if (pSprite->dwFlags & (DDSPRITE_KEYSRC | DDSPRITE_KEYSRCOVERRIDE |
  584. DDSPRITE_KEYDEST | DDSPRITE_KEYDESTOVERRIDE))
  585. {
  586. /*
  587. * Validate source color-key flag.
  588. */
  589. if (pSprite->dwFlags & (DDSPRITE_KEYSRC | DDSPRITE_KEYSRCOVERRIDE))
  590. {
  591. if (!(pcaps->dwCKeyCaps & (DDCKEYCAPS_SRCBLT | DDCKEYCAPS_SRCOVERLAY)))
  592. {
  593. pcaps->bNoHAL = TRUE; // disqualify hardware driver
  594. }
  595. if (!(pcaps->dwHELCKeyCaps & (DDCKEYCAPS_SRCBLT | DDCKEYCAPS_SRCOVERLAY)))
  596. {
  597. pcaps->bNoHEL = TRUE; // disqualify HEL
  598. }
  599. if (dwDDPFSrcFlags & DDPF_ALPHAPIXELS)
  600. {
  601. DPF_ERR("KEYSRC* illegal with source alpha channel...");
  602. return DDERR_INVALIDPARAMS;
  603. }
  604. if (pSprite->dwFlags & DDSPRITE_KEYSRC)
  605. {
  606. if (!(!pcaps->bOverlay && surf_src_lcl->dwFlags & DDRAWISURF_HASCKEYSRCBLT ||
  607. pcaps->bOverlay && surf_src_lcl->dwFlags & DDRAWISURF_HASCKEYSRCOVERLAY))
  608. {
  609. DPF_ERR("KEYSRC specified, but no color key...");
  610. return DDERR_INVALIDPARAMS;
  611. }
  612. if (pSprite->dwFlags & DDSPRITE_KEYSRCOVERRIDE)
  613. {
  614. DPF_ERR("Illegal to specify both KEYSRC and KEYSRCOVERRIDE...");
  615. return DDERR_INVALIDPARAMS;
  616. }
  617. // Copy color key value from surface into DDSPRITEFX struct.
  618. pSprite->ddSpriteFX.ddckSrcColorkey = (pcaps->bOverlay) ?
  619. surf_src_lcl->ddckCKSrcOverlay :
  620. surf_src_lcl->ddckCKSrcBlt;
  621. // Turn off KEYSRC, turn on KEYSRCOVERRIDE.
  622. pSprite->dwFlags ^= DDSPRITE_KEYSRC | DDSPRITE_KEYSRCOVERRIDE;
  623. }
  624. }
  625. /*
  626. * Validate destination color-key flag.
  627. */
  628. if (pSprite->dwFlags & (DDSPRITE_KEYDEST | DDSPRITE_KEYDESTOVERRIDE))
  629. {
  630. if (!(pcaps->dwCKeyCaps & (DDCKEYCAPS_DESTBLT | DDCKEYCAPS_DESTOVERLAY)))
  631. {
  632. pcaps->bNoHAL = TRUE; // disqualify hardware driver
  633. }
  634. if (!(pcaps->dwHELCKeyCaps & (DDCKEYCAPS_DESTBLT | DDCKEYCAPS_DESTOVERLAY)))
  635. {
  636. pcaps->bNoHEL = TRUE; // disqualify HEL
  637. }
  638. if (dwDDPFDestFlags & DDPF_ALPHAPIXELS)
  639. {
  640. DPF_ERR("KEYDEST* illegal with dest alpha channel...");
  641. return DDERR_INVALIDPARAMS;
  642. }
  643. if (pSprite->dwFlags & DDSPRITE_KEYDEST)
  644. {
  645. if (!(!pcaps->bOverlay && surf_dest_lcl->dwFlags & DDRAWISURF_HASCKEYDESTBLT ||
  646. pcaps->bOverlay && surf_dest_lcl->dwFlags & DDRAWISURF_HASCKEYDESTOVERLAY))
  647. {
  648. DPF_ERR("KEYDEST specified, but no color key...");
  649. return DDERR_INVALIDPARAMS;
  650. }
  651. if (pSprite->dwFlags & DDSPRITE_KEYDESTOVERRIDE)
  652. {
  653. DPF_ERR("Illegal to specify both KEYDEST and KEYDESTOVERRIDE...");
  654. return DDERR_INVALIDPARAMS;
  655. }
  656. // Copy color key value from surface into DDSPRITEFX struct.
  657. pSprite->ddSpriteFX.ddckDestColorkey = (pcaps->bOverlay) ?
  658. surf_src_lcl->ddckCKDestOverlay :
  659. surf_src_lcl->ddckCKDestBlt;
  660. // Turn off KEYDEST, turn on KEYDESTOVERRIDE.
  661. pSprite->dwFlags ^= DDSPRITE_KEYDEST | DDSPRITE_KEYDESTOVERRIDE;
  662. }
  663. }
  664. if (pcaps->bNoHAL && pcaps->bNoHEL)
  665. {
  666. DPF_ERR("No driver support for specified color-key operation");
  667. return DDERR_UNSUPPORTED;
  668. }
  669. }
  670. /*
  671. * Assume hardware unable to handle sprite in system memory.
  672. * (Will this assumption remain true for future hardware?)
  673. */
  674. if (pcaps->bOverlay)
  675. {
  676. if (pcaps->dwSrcSurfCaps & DDSCAPS_SYSTEMMEMORY)
  677. {
  678. pcaps->bNoHAL = TRUE; // can't use hardware
  679. if (pcaps->bNoHEL) // but can we still emulate?
  680. {
  681. // Nope, we can't emulate either, so fail the call.
  682. DPF_ERR("Driver can't handle sprite in system memory");
  683. return DDERR_UNSUPPORTED;
  684. }
  685. }
  686. }
  687. /*
  688. * We do not allow blits or overlays with an optimized surface.
  689. */
  690. if (pcaps->dwSrcSurfCaps & DDSCAPS_OPTIMIZED)
  691. {
  692. DPF_ERR("Can't do blits or overlays with optimized surfaces...") ;
  693. return DDERR_INVALIDPARAMS;
  694. }
  695. /*
  696. * Validate dwSize field in embedded DDSPRITEFX structure.
  697. */
  698. if (pSprite->ddSpriteFX.dwSize != sizeof(DDSPRITEFX))
  699. {
  700. DPF_ERR("Invalid dwSize value in DDSPRITEFX structure...");
  701. return DDERR_INVALIDPARAMS;
  702. }
  703. /*
  704. * If the RGBA scaling factors are effectively disabled by all being
  705. * set to 255 (all ones), just clear the RGBASCALING flag.
  706. */
  707. if (pSprite->ddSpriteFX.dwDDFX & DDSPRITEFX_RGBASCALING &&
  708. *(LPDWORD)&pSprite->ddSpriteFX.ddrgbaScaleFactors == ~0UL)
  709. {
  710. pSprite->ddSpriteFX.dwDDFX &= ~DDSPRITEFX_RGBASCALING;
  711. }
  712. /*
  713. * Is any kind of alpha blending required for this sprite?
  714. */
  715. if (dwDDPFSrcFlags & DDPF_ALPHAPIXELS ||
  716. !(pSprite->ddSpriteFX.dwDDFX & DDSPRITEFX_DEGRADERGBASCALING) &&
  717. pSprite->ddSpriteFX.dwDDFX & DDSPRITEFX_RGBASCALING)
  718. {
  719. /*
  720. * Yes, this sprite requires some form of alpha blending.
  721. * Does the driver support any kind of alpha blending at all?
  722. */
  723. if (!(pcaps->dwFXCaps & (DDFXCAPS_BLTALPHA | DDFXCAPS_OVERLAYALPHA)))
  724. {
  725. pcaps->bNoHAL = TRUE; // disqualify hardware driver
  726. }
  727. if (!(pcaps->dwHELFXCaps & (DDFXCAPS_BLTALPHA | DDFXCAPS_OVERLAYALPHA)))
  728. {
  729. pcaps->bNoHEL = TRUE; // disqualify HEL
  730. }
  731. if (pcaps->bNoHAL && pcaps->bNoHEL)
  732. {
  733. DPF_ERR("Driver can't do any kind of alpha blending at all...");
  734. return DDERR_UNSUPPORTED;
  735. }
  736. /*
  737. * Does source surface have an alpha channel?
  738. */
  739. if (dwDDPFSrcFlags & DDPF_ALPHAPIXELS)
  740. {
  741. /*
  742. * Can the driver handle this surface's alpha-channel format?
  743. */
  744. if (dwDDPFSrcFlags & DDPF_ALPHAPREMULT)
  745. {
  746. // The source is in premultiplied-alpha format.
  747. if (!(pcaps->dwAlphaCaps & (DDALPHACAPS_BLTPREMULT |
  748. DDALPHACAPS_OVERLAYPREMULT)))
  749. {
  750. pcaps->bNoHAL = TRUE; // disqualify hardware driver
  751. }
  752. if (!(pcaps->dwHELAlphaCaps & (DDALPHACAPS_BLTPREMULT |
  753. DDALPHACAPS_OVERLAYPREMULT)))
  754. {
  755. pcaps->bNoHEL = TRUE; // disqualify HEL
  756. }
  757. }
  758. else
  759. {
  760. // The source is in NON-premultiplied-alpha format.
  761. if (!(pcaps->dwAlphaCaps & (DDALPHACAPS_BLTNONPREMULT |
  762. DDALPHACAPS_OVERLAYNONPREMULT)))
  763. {
  764. pcaps->bNoHAL = TRUE; // disqualify hardware driver
  765. }
  766. if (!(pcaps->dwHELAlphaCaps & (DDALPHACAPS_BLTNONPREMULT |
  767. DDALPHACAPS_OVERLAYNONPREMULT)))
  768. {
  769. pcaps->bNoHEL = TRUE; // disqualify HEL
  770. }
  771. }
  772. if (pcaps->bNoHAL && pcaps->bNoHEL)
  773. {
  774. DPF_ERR("Driver can't handle alpha channel in source surface...");
  775. return DDERR_NOALPHAHW;
  776. }
  777. }
  778. /*
  779. * Does the destination surface have an alpha channel?
  780. */
  781. if (dwDDPFDestFlags & DDPF_ALPHAPIXELS)
  782. {
  783. /*
  784. * Verify that destination surface has a premultiplied-
  785. * alpha pixel format. Non-premultiplied alpha won't do.
  786. */
  787. if (!(dwDDPFDestFlags & DDPF_ALPHAPREMULT))
  788. {
  789. DPF_ERR("Illegal to use non-premultiplied alpha in dest surface...");
  790. return DDERR_INVALIDPARAMS;
  791. }
  792. /*
  793. * Can the driver handle this surface's alpha-channel format?
  794. */
  795. if (!(pcaps->dwAlphaCaps & (DDALPHACAPS_BLTPREMULT |
  796. DDALPHACAPS_OVERLAYPREMULT)))
  797. {
  798. pcaps->bNoHAL = TRUE; // disqualify hardware driver
  799. }
  800. if (!(pcaps->dwHELAlphaCaps & (DDALPHACAPS_BLTPREMULT |
  801. DDALPHACAPS_OVERLAYPREMULT)))
  802. {
  803. pcaps->bNoHEL = TRUE; // disqualify HEL
  804. }
  805. if (pcaps->bNoHAL && pcaps->bNoHEL)
  806. {
  807. DPF_ERR("Driver can't handle alpha channel in dest surface...");
  808. return DDERR_NOALPHAHW;
  809. }
  810. }
  811. /*
  812. * Are the RGBA scaling factors enabled for this sprite?
  813. */
  814. if (!(pSprite->ddSpriteFX.dwDDFX & DDSPRITEFX_DEGRADERGBASCALING) &&
  815. *(LPDWORD)&pSprite->ddSpriteFX.ddrgbaScaleFactors != ~0UL)
  816. {
  817. DDRGBA val = pSprite->ddSpriteFX.ddrgbaScaleFactors;
  818. /*
  819. * Yes, RGBA scaling is enabled. Does driver support it?
  820. */
  821. if (!(pcaps->dwAlphaCaps & (DDALPHACAPS_BLTRGBASCALE1F | DDALPHACAPS_OVERLAYRGBASCALE1F |
  822. DDALPHACAPS_BLTRGBASCALE2F | DDALPHACAPS_OVERLAYRGBASCALE2F |
  823. DDALPHACAPS_BLTRGBASCALE4F | DDALPHACAPS_OVERLAYRGBASCALE4F)))
  824. {
  825. pcaps->bNoHAL = TRUE; // disqualify hardware driver
  826. }
  827. if (!(pcaps->dwHELAlphaCaps & (DDALPHACAPS_BLTRGBASCALE1F | DDALPHACAPS_OVERLAYRGBASCALE1F |
  828. DDALPHACAPS_BLTRGBASCALE2F | DDALPHACAPS_OVERLAYRGBASCALE2F |
  829. DDALPHACAPS_BLTRGBASCALE4F | DDALPHACAPS_OVERLAYRGBASCALE4F)))
  830. {
  831. pcaps->bNoHEL = TRUE; // disqualify HEL
  832. }
  833. if (pcaps->bNoHAL && pcaps->bNoHEL)
  834. {
  835. DPF_ERR("Driver can't do any kind of RGBA scaling at all...");
  836. return DDERR_UNSUPPORTED;
  837. }
  838. if (val.red > val.alpha || val.green > val.alpha || val.blue > val.alpha)
  839. {
  840. if (!(pcaps->dwAlphaCaps & (DDALPHACAPS_BLTSATURATE |
  841. DDALPHACAPS_OVERLAYSATURATE)))
  842. {
  843. pcaps->bNoHAL = TRUE; // disqualify hardware driver
  844. }
  845. if (!(pcaps->dwHELAlphaCaps & (DDALPHACAPS_BLTSATURATE |
  846. DDALPHACAPS_OVERLAYSATURATE)))
  847. {
  848. pcaps->bNoHEL = TRUE; // disqualify HEL
  849. }
  850. }
  851. if (val.red != val.green || val.red != val.blue)
  852. {
  853. if (!(pcaps->dwAlphaCaps & (DDALPHACAPS_BLTRGBASCALE4F |
  854. DDALPHACAPS_OVERLAYRGBASCALE4F)))
  855. {
  856. pcaps->bNoHAL = TRUE; // disqualify hardware driver
  857. }
  858. if (!(pcaps->dwHELAlphaCaps & (DDALPHACAPS_BLTRGBASCALE4F |
  859. DDALPHACAPS_OVERLAYRGBASCALE4F)))
  860. {
  861. pcaps->bNoHEL = TRUE; // disqualify HEL
  862. }
  863. } else if (*(LPDWORD)&val != val.alpha*0x01010101UL)
  864. {
  865. if (!(pcaps->dwAlphaCaps & (DDALPHACAPS_BLTRGBASCALE2F |
  866. DDALPHACAPS_OVERLAYRGBASCALE2F)))
  867. {
  868. pcaps->bNoHAL = TRUE; // disqualify hardware driver
  869. }
  870. if (!(pcaps->dwHELAlphaCaps & (DDALPHACAPS_BLTRGBASCALE2F |
  871. DDALPHACAPS_OVERLAYRGBASCALE2F)))
  872. {
  873. pcaps->bNoHEL = TRUE; // disqualify HEL
  874. }
  875. }
  876. if (pcaps->bNoHAL && pcaps->bNoHEL)
  877. {
  878. DPF_ERR("Driver can't handle specified RGBA scaling factors...");
  879. return DDERR_UNSUPPORTED;
  880. }
  881. }
  882. }
  883. /*
  884. * Is any kind of filtering required for this sprite?
  885. */
  886. if (!(pSprite->ddSpriteFX.dwDDFX & DDSPRITEFX_DEGRADEFILTER) &&
  887. pSprite->ddSpriteFX.dwDDFX & (DDSPRITEFX_BILINEARFILTER |
  888. DDSPRITEFX_BLURFILTER |
  889. DDSPRITEFX_FLATFILTER))
  890. {
  891. /*
  892. * The bilinear-, blur-, and flat-filtering options are mutually
  893. * exclusive. Make sure only one of these flags is set.
  894. */
  895. DWORD fflags = pSprite->ddSpriteFX.dwDDFX & (DDSPRITEFX_BILINEARFILTER |
  896. DDSPRITEFX_BLURFILTER |
  897. DDSPRITEFX_FLATFILTER);
  898. if (fflags & (fflags - 1))
  899. {
  900. DPF_ERR("Two mutually exclusive filtering options were both specified");
  901. return DDERR_INVALIDPARAMS;
  902. }
  903. /*
  904. * Yes, this sprite requires some form of filtering.
  905. * Does the driver support any kind of filtering at all?
  906. */
  907. if (!(pcaps->dwFXCaps & (DDFXCAPS_BLTFILTER | DDFXCAPS_OVERLAYFILTER)))
  908. {
  909. pcaps->bNoHAL = TRUE; // disqualify hardware driver
  910. }
  911. if (!(pcaps->dwHELFXCaps & (DDFXCAPS_BLTFILTER | DDFXCAPS_OVERLAYFILTER)))
  912. {
  913. pcaps->bNoHEL = TRUE; // disqualify HEL
  914. }
  915. if (pcaps->bNoHAL && pcaps->bNoHEL)
  916. {
  917. DPF_ERR("Driver can't do any kind of filtering at all");
  918. return DDERR_UNSUPPORTED;
  919. }
  920. if (pSprite->ddSpriteFX.dwDDFX & DDSPRITEFX_BILINEARFILTER)
  921. {
  922. if (!(pcaps->dwFilterCaps & (DDFILTCAPS_BLTBILINEARFILTER |
  923. DDFILTCAPS_OVERLAYBILINEARFILTER)))
  924. {
  925. pcaps->bNoHAL = TRUE; // disqualify hardware driver
  926. }
  927. if (!(pcaps->dwHELFilterCaps & (DDFILTCAPS_BLTBILINEARFILTER |
  928. DDFILTCAPS_OVERLAYBILINEARFILTER)))
  929. {
  930. pcaps->bNoHEL = TRUE; // disqualify HEL
  931. }
  932. }
  933. if (pSprite->ddSpriteFX.dwDDFX & DDSPRITEFX_BLURFILTER)
  934. {
  935. if (!(pcaps->dwFilterCaps & (DDFILTCAPS_BLTBLURFILTER |
  936. DDFILTCAPS_OVERLAYBLURFILTER)))
  937. {
  938. pcaps->bNoHAL = TRUE; // disqualify hardware driver
  939. }
  940. if (!(pcaps->dwHELFilterCaps & (DDFILTCAPS_BLTBLURFILTER |
  941. DDFILTCAPS_OVERLAYBLURFILTER)))
  942. {
  943. pcaps->bNoHEL = TRUE; // disqualify HEL
  944. }
  945. }
  946. if (pSprite->ddSpriteFX.dwDDFX & DDSPRITEFX_FLATFILTER)
  947. {
  948. if (!(pcaps->dwFilterCaps & (DDFILTCAPS_BLTFLATFILTER |
  949. DDFILTCAPS_OVERLAYFLATFILTER)))
  950. {
  951. pcaps->bNoHAL = TRUE; // disqualify hardware driver
  952. }
  953. if (!(pcaps->dwHELFilterCaps & (DDFILTCAPS_BLTFLATFILTER |
  954. DDFILTCAPS_OVERLAYFLATFILTER)))
  955. {
  956. pcaps->bNoHEL = TRUE; // disqualify HEL
  957. }
  958. }
  959. if (pcaps->bNoHAL && pcaps->bNoHEL)
  960. {
  961. DPF_ERR("Driver can't do specified filtering operation...");
  962. return DDERR_UNSUPPORTED;
  963. }
  964. }
  965. /*
  966. * Can the driver handle the specified affine transformation?
  967. */
  968. if (pSprite->ddSpriteFX.dwDDFX & DDSPRITEFX_AFFINETRANSFORM)
  969. {
  970. /*
  971. * Can the driver do any affine transformations at all?
  972. */
  973. if (!pcaps->bNoHAL &&
  974. (!(pcaps->dwFXCaps & (DDFXCAPS_BLTTRANSFORM | DDFXCAPS_OVERLAYTRANSFORM)) ||
  975. !(pcaps->dwTransformCaps & (DDTFRMCAPS_BLTAFFINETRANSFORM |
  976. DDTFRMCAPS_OVERLAYAFFINETRANSFORM))))
  977. {
  978. pcaps->bNoHAL = TRUE; // disqualify hardware driver
  979. }
  980. if (!pcaps->bNoHEL &&
  981. (!(pcaps->dwHELFXCaps & (DDFXCAPS_BLTTRANSFORM | DDFXCAPS_OVERLAYTRANSFORM)) ||
  982. !(pcaps->dwHELTransformCaps & (DDTFRMCAPS_BLTAFFINETRANSFORM |
  983. DDTFRMCAPS_OVERLAYAFFINETRANSFORM))))
  984. {
  985. pcaps->bNoHEL = TRUE; // disqualify HEL
  986. }
  987. if (pcaps->bNoHAL && pcaps->bNoHEL)
  988. {
  989. DPF_ERR("Driver can't do any affine transformations...");
  990. return DDERR_UNSUPPORTED;
  991. }
  992. /*
  993. * Check affine transformation against driver's minification limits.
  994. */
  995. checkMinification(&pSprite->ddSpriteFX, pcaps);
  996. if (pcaps->bNoHAL && pcaps->bNoHEL)
  997. {
  998. DPF_ERR("Affine transform exceeds driver's minification limit...");
  999. return DDERR_INVALIDPARAMS;
  1000. }
  1001. }
  1002. /*
  1003. * If necessary, degrade specified filtering and RGBA-scaling operations
  1004. * to operations that the driver is capable of handling.
  1005. */
  1006. if (pSprite->ddSpriteFX.dwDDFX & DDSPRITEFX_DEGRADEFILTER)
  1007. {
  1008. DWORD caps;
  1009. DWORD ddfx = pSprite->ddSpriteFX.dwDDFX; // sprite FX flags
  1010. // driver's FX caps
  1011. caps = (pcaps->bNoHAL) ? pcaps->dwHELFXCaps : pcaps->dwFXCaps;
  1012. if (!(caps && (DDFXCAPS_BLTFILTER | DDFXCAPS_OVERLAYFILTER)))
  1013. {
  1014. // Driver can't do any kind of filtering, so just disable it.
  1015. ddfx &= ~(DDSPRITEFX_BILINEARFILTER | DDSPRITEFX_BLURFILTER |
  1016. DDSPRITEFX_FLATFILTER | DDSPRITEFX_DEGRADEFILTER);
  1017. }
  1018. else
  1019. {
  1020. // Get driver's filter caps.
  1021. caps = (pcaps->bNoHAL) ? pcaps->dwHELFilterCaps : pcaps->dwFilterCaps;
  1022. // If blur filter is specified, can driver handle it?
  1023. if (ddfx & DDSPRITEFX_BLURFILTER &&
  1024. !(caps & (DDFILTCAPS_BLTBLURFILTER |
  1025. DDFILTCAPS_OVERLAYBLURFILTER)))
  1026. {
  1027. // Degrade blur filter to bilinear filter.
  1028. ddfx &= ~DDSPRITEFX_BLURFILTER;
  1029. ddfx |= DDSPRITEFX_BILINEARFILTER;
  1030. }
  1031. // If flat filter is specified, can driver handle it?
  1032. if (ddfx & DDSPRITEFX_FLATFILTER &&
  1033. !(caps & (DDFILTCAPS_BLTFLATFILTER |
  1034. DDFILTCAPS_OVERLAYFLATFILTER)))
  1035. {
  1036. // Degrade flat filter to bilinear filter.
  1037. ddfx &= ~DDSPRITEFX_FLATFILTER;
  1038. ddfx |= DDSPRITEFX_BILINEARFILTER;
  1039. }
  1040. // If bilinear filter is specified, can driver handle it?
  1041. if (ddfx & DDSPRITEFX_BILINEARFILTER &&
  1042. !(caps & (DDFILTCAPS_BLTBILINEARFILTER |
  1043. DDFILTCAPS_OVERLAYBILINEARFILTER)))
  1044. {
  1045. // Degrade bilinear filtering to no filtering.
  1046. ddfx &= ~DDSPRITEFX_BILINEARFILTER;
  1047. }
  1048. }
  1049. pSprite->ddSpriteFX.dwDDFX = ddfx & ~DDSPRITEFX_DEGRADEFILTER;
  1050. }
  1051. /*
  1052. * If necessary, degrade specified RGBA scaling factors to values
  1053. * that the driver is capable of handling.
  1054. */
  1055. if (pSprite->ddSpriteFX.dwDDFX & DDSPRITEFX_DEGRADERGBASCALING &&
  1056. *(LPDWORD)&pSprite->ddSpriteFX.ddrgbaScaleFactors != ~0UL)
  1057. {
  1058. DDRGBA val = pSprite->ddSpriteFX.ddrgbaScaleFactors;
  1059. DWORD caps;
  1060. // driver's alpha caps
  1061. caps = (pcaps->bNoHAL) ? pcaps->dwHELAlphaCaps : pcaps->dwAlphaCaps;
  1062. /*
  1063. * We permit the RGB scaling factors to exceed the alpha scaling
  1064. * factor only if the driver can do saturated alpha arithmetic to
  1065. * prevent the destination color components from overflowing.
  1066. */
  1067. if ((val.red > val.alpha || val.green > val.alpha || val.blue > val.alpha) &&
  1068. !(caps & (DDALPHACAPS_BLTSATURATE | DDALPHACAPS_OVERLAYSATURATE)))
  1069. {
  1070. // Driver can't handle saturated arithmetic during alpha blending.
  1071. if (val.red > val.alpha)
  1072. {
  1073. val.red = val.alpha; // clamp red to alpha value
  1074. }
  1075. if (val.green > val.alpha)
  1076. {
  1077. val.green = val.alpha; // clamp green to alpha value
  1078. }
  1079. if (val.blue > val.alpha)
  1080. {
  1081. val.blue = val.alpha; // clamp blue to alpha value
  1082. }
  1083. }
  1084. /*
  1085. * Can driver perform 1-, 2-, or 4-factor RGBA scaling?
  1086. */
  1087. if (!(caps & (DDALPHACAPS_BLTRGBASCALE1F | DDALPHACAPS_OVERLAYRGBASCALE1F |
  1088. DDALPHACAPS_BLTRGBASCALE2F | DDALPHACAPS_OVERLAYRGBASCALE2F |
  1089. DDALPHACAPS_BLTRGBASCALE4F | DDALPHACAPS_OVERLAYRGBASCALE4F)))
  1090. {
  1091. // Driver can't do any kind of RGBA scaling at all.
  1092. *(LPDWORD)&val = ~0UL; // disable RGBA scaling altogether
  1093. }
  1094. else if (*(LPDWORD)&val != val.alpha*0x01010101UL &&
  1095. !(caps & (DDALPHACAPS_BLTRGBASCALE2F | DDALPHACAPS_OVERLAYRGBASCALE2F |
  1096. DDALPHACAPS_BLTRGBASCALE4F | DDALPHACAPS_OVERLAYRGBASCALE4F)))
  1097. {
  1098. // Driver can handle only 1-factor RGBA scaling.
  1099. *(LPDWORD)&val = val.alpha*0x01010101UL; // set RGB factors = alpha factor
  1100. }
  1101. else if ((val.red != val.green || val.red != val.blue) &&
  1102. !(caps & (DDALPHACAPS_BLTRGBASCALE4F | DDALPHACAPS_OVERLAYRGBASCALE4F)))
  1103. {
  1104. /*
  1105. * Degrade the specified 4-factor RGBA-scaling operation to a 2-factor
  1106. * RGBA scaling operation that the driver can handle. Set all three
  1107. * color factors to weighted average M of the specified color factors
  1108. * (Mr,Mg,Mb): M = .299*Mr + .587*Mg + .114*Mb
  1109. */
  1110. DWORD M = 19595UL*val.red + 38470UL*val.green + 7471UL*val.blue;
  1111. val.red = val.green = val.blue = (BYTE)(M >> 16);
  1112. }
  1113. pSprite->ddSpriteFX.ddrgbaScaleFactors = val;
  1114. pSprite->ddSpriteFX.dwDDFX &= ~DDSPRITEFX_DEGRADERGBASCALING;
  1115. }
  1116. /*
  1117. * If the embedded DDSPRITEFX structure is unused, clear DDSPRITEFX flag.
  1118. */
  1119. if (!(pSprite->dwFlags & (DDSPRITE_KEYDESTOVERRIDE | DDSPRITE_KEYSRCOVERRIDE)) &&
  1120. pSprite->ddSpriteFX.dwDDFX == 0)
  1121. {
  1122. pSprite->dwFlags &= ~DDSPRITE_DDSPRITEFX;
  1123. }
  1124. DDASSERT(!(pcaps->bNoHAL && pcaps->bNoHEL));
  1125. return DD_OK;
  1126. } /* validateSprite */
  1127. /*
  1128. * Obtain clipping region for a destination surface and its attached
  1129. * clipper. (In the case of overlay sprites in the master sprite
  1130. * list, though, pClipper points to the clipper that WAS attached to
  1131. * the destination surface at the time of the SetSpriteDisplayList
  1132. * call; it may no longer be if an app manages multiple windows.)
  1133. * If pClipper is NULL, just use the whole dest surf as the clip rect.
  1134. * A NULL return value always means DDERR_OUTOFMEMORY.
  1135. */
  1136. static LPRGNDATA GetRgnData(LPDIRECTDRAWCLIPPER pClipper, LPRECT prcDestSurf,
  1137. LPDDRAWI_DIRECTDRAW_GBL pdrv, LPRGNDATA pRgn)
  1138. {
  1139. DWORD rgnSize;
  1140. /*
  1141. * How big a buffer will we need to contain the clipping region?
  1142. */
  1143. if (pClipper == NULL)
  1144. {
  1145. /*
  1146. * The destination surface has (or HAD) no attached clipper,
  1147. * so the effective clip region is a single rectangle the width
  1148. * and height of the primary surface. Calculate the size of
  1149. * the region buffer we'll need.
  1150. */
  1151. rgnSize = sizeof(RGNDATAHEADER) + sizeof(RECT);
  1152. }
  1153. else
  1154. {
  1155. /*
  1156. * The dest surface has (or HAD) an attached clipper. Get
  1157. * the clip list. This first call to InternalGetClipList
  1158. * just gets the size of the region so we know how much
  1159. * storage to allocate for it.
  1160. */
  1161. HRESULT ddrval = InternalGetClipList(pClipper,
  1162. prcDestSurf,
  1163. NULL, // we just want rgnSize
  1164. &rgnSize,
  1165. pdrv);
  1166. DDASSERT(ddrval == DD_OK); // the call above should never fail
  1167. }
  1168. /*
  1169. * Now we know how big a region buffer we'll need. Did the caller
  1170. * pass in a region buffer? If so, is it the correct size?
  1171. */
  1172. if (pRgn != NULL)
  1173. {
  1174. /*
  1175. * The caller DID pass in a region buffer. Before using it,
  1176. * let's make sure it's just the right size.
  1177. */
  1178. DWORD bufSize = pRgn->rdh.dwSize + pRgn->rdh.nRgnSize;
  1179. if (bufSize != rgnSize)
  1180. {
  1181. // Can't use region buffer passed in by caller.
  1182. pRgn = NULL;
  1183. }
  1184. }
  1185. /*
  1186. * Now we know whether we'll have to alloc our own region buffer.
  1187. */
  1188. if (pRgn == NULL)
  1189. {
  1190. /*
  1191. * Yes, we must alloc our own region buffer.
  1192. */
  1193. pRgn = (LPRGNDATA)MemAlloc(rgnSize);
  1194. if (!pRgn)
  1195. {
  1196. return NULL; // error -- out of memory
  1197. }
  1198. // We'll fill in the following fields in case the caller
  1199. // passes this same buffer to us again later.
  1200. pRgn->rdh.dwSize = sizeof(RGNDATAHEADER);
  1201. pRgn->rdh.nRgnSize = rgnSize - sizeof(RGNDATAHEADER);
  1202. }
  1203. /*
  1204. * Okay, now we have a region buffer that's the right size.
  1205. * Load the region data into the buffer.
  1206. */
  1207. if (pClipper == NULL)
  1208. {
  1209. // Set the single clip rect to cover the full dest surface.
  1210. pRgn->rdh.nCount = 1; // a single clip rect
  1211. memcpy((LPRECT)&pRgn->Buffer, prcDestSurf, sizeof(RECT));
  1212. }
  1213. else
  1214. {
  1215. // This call actually retrieves the clip region info.
  1216. HRESULT ddrval = InternalGetClipList(pClipper,
  1217. prcDestSurf,
  1218. pRgn,
  1219. &rgnSize,
  1220. pdrv);
  1221. DDASSERT(ddrval == DD_OK); // the call above should never fail
  1222. }
  1223. return (pRgn); // return pointer to region info
  1224. } /* GetRgnData */
  1225. /*
  1226. * Validate the window handle associated with the specified clipper.
  1227. * If the window handle is not valid, return FALSE. Otherwise,
  1228. * return TRUE. Note that this function returns TRUE if either
  1229. * pClipper is null or the associated window handle is null.
  1230. */
  1231. static BOOL validClipperWindow(LPDIRECTDRAWCLIPPER pClipper)
  1232. {
  1233. if (pClipper != NULL)
  1234. {
  1235. LPDDRAWI_DDRAWCLIPPER_INT pclip_int = (LPDDRAWI_DDRAWCLIPPER_INT)pClipper;
  1236. LPDDRAWI_DDRAWCLIPPER_LCL pclip_lcl = pclip_int->lpLcl;
  1237. LPDDRAWI_DDRAWCLIPPER_GBL pclip = pclip_lcl->lpGbl;
  1238. HWND hWnd = (HWND)pclip->hWnd;
  1239. if (hWnd != 0 && !IsWindow(hWnd))
  1240. {
  1241. /*
  1242. * This window handle is no longer valid.
  1243. */
  1244. return FALSE;
  1245. }
  1246. }
  1247. return TRUE;
  1248. } /* validClipperWindow */
  1249. /*
  1250. * Helper function for managing sublists within the master sprite
  1251. * list. If any sprites in the specified sublist have source surface
  1252. * pointers that are null, remove those sprites and move the rest of
  1253. * the sprite array downward to eliminate the gaps in the array.
  1254. */
  1255. static DWORD scrunchSubList(LPSPRITESUBLIST pSubList)
  1256. {
  1257. DWORD i, j;
  1258. // Number of sprites in sublist
  1259. DWORD dwNumSprites = pSubList->dwCount;
  1260. // Pointer to first sprite in array of sprites
  1261. LPDDSPRITEI pSprite = &pSubList->sprite[0];
  1262. // Find first null surface in sprite array.
  1263. for (i = 0; i < dwNumSprites; ++i)
  1264. {
  1265. if (pSprite[i].lpDDSSrc == NULL) // null surface ptr?
  1266. {
  1267. break; // found first null surface in sprite array
  1268. }
  1269. }
  1270. // Scrunch together remainder of sprite array to fill in gaps.
  1271. for (j = i++; i < dwNumSprites; ++i)
  1272. {
  1273. if (pSprite[i].lpDDSSrc != NULL) // valid surface ptr?
  1274. {
  1275. pSprite[j++] = pSprite[i]; // copy next valid sprite
  1276. }
  1277. }
  1278. // Return number of sprites in scrunched array.
  1279. return (pSubList->dwCount = j);
  1280. } /* scrunchSubList */
  1281. /*
  1282. * Helper function for managing master sprite list. If any of the
  1283. * sublist pointers in the master-sprite-list header are NULL,
  1284. * remove those pointers and move the rest of the sublist-
  1285. * pointer array downward to eliminate the gaps in the array.
  1286. */
  1287. static DWORD scrunchMasterSpriteList(LPMASTERSPRITELIST pMaster)
  1288. {
  1289. DWORD i, j;
  1290. // Number of sublists in master sprite list
  1291. DWORD dwNumSubLists = pMaster->dwNumSubLists;
  1292. // Pointer to first pointer in array of sublist pointers
  1293. LPSPRITESUBLIST *ppSubList = &pMaster->pSubList[0];
  1294. // Find first null pointer in sublist-pointer array.
  1295. for (i = 0; i < dwNumSubLists; ++i)
  1296. {
  1297. if (ppSubList[i] == NULL) // null pointer?
  1298. {
  1299. break; // found first null pointer in array
  1300. }
  1301. }
  1302. // Scrunch together remainder of sublist-pointer array to fill in gaps.
  1303. for (j = i++; i < dwNumSubLists; ++i)
  1304. {
  1305. if (ppSubList[i] != NULL) // valid pointer?
  1306. {
  1307. ppSubList[j++] = ppSubList[i]; // copy next valid pointer
  1308. }
  1309. }
  1310. // Return number of sublist pointers in scrunched array.
  1311. return (pMaster->dwNumSubLists = j);
  1312. } /* scrunchMasterSpriteList */
  1313. /*
  1314. * Helper function for managing master sprite list. Mark all surface
  1315. * and clipper objects that are referenced in the master sprite list.
  1316. * When a marked surface or clipper object is released, the master
  1317. * sprite list is immediately updated to eliminate invalid references.
  1318. * The master sprite list contains pointers to surface and clipper
  1319. * interface objects, but marks the surfaces and clippers by setting
  1320. * flags in the local surface and global clipper objects. Because
  1321. * the master sprite list may contain multiple instances of the same
  1322. * surface or clipper object, we mark and unmark all such objects in
  1323. * unison to avoid errors.
  1324. */
  1325. static void markSpriteObjects(LPMASTERSPRITELIST pMaster)
  1326. {
  1327. DWORD i;
  1328. if (pMaster == NULL)
  1329. {
  1330. return; // nothing to do -- bye!
  1331. }
  1332. /*
  1333. * Set the DDRAWISURF/CLIP_INMASTERSPRITELIST flag in each local
  1334. * surface object and global clipper object in the master sprite
  1335. * list. Each iteration marks the objects in one sublist.
  1336. */
  1337. for (i = 0; i < pMaster->dwNumSubLists; ++i)
  1338. {
  1339. LPDDRAWI_DDRAWSURFACE_INT surf_int;
  1340. LPDDRAWI_DDRAWSURFACE_LCL surf_lcl;
  1341. LPDDRAWI_DDRAWCLIPPER_INT pclip_int;
  1342. LPSPRITESUBLIST pSubList = pMaster->pSubList[i];
  1343. LPDDSPRITEI sprite = &pSubList->sprite[0];
  1344. DWORD dwNumSprites = pSubList->dwCount;
  1345. DWORD j;
  1346. /*
  1347. * Mark the primary surface object associated with this sublist.
  1348. */
  1349. surf_int = (LPDDRAWI_DDRAWSURFACE_INT)pSubList->pPrimary;
  1350. surf_lcl = surf_int->lpLcl;
  1351. surf_lcl->dwFlags |= DDRAWISURF_INMASTERSPRITELIST;
  1352. /*
  1353. * If a clipper is associated with this sublist, mark it.
  1354. */
  1355. pclip_int = (LPDDRAWI_DDRAWCLIPPER_INT)pSubList->pClipper;
  1356. if (pclip_int != NULL)
  1357. {
  1358. LPDDRAWI_DDRAWCLIPPER_LCL pclip_lcl = pclip_int->lpLcl;
  1359. LPDDRAWI_DDRAWCLIPPER_GBL pclip = pclip_lcl->lpGbl;
  1360. pclip->dwFlags |= DDRAWICLIP_INMASTERSPRITELIST;
  1361. }
  1362. /*
  1363. * Mark the source surface for each sprite in this sublist.
  1364. */
  1365. for (j = 0; j < dwNumSprites; ++j)
  1366. {
  1367. LPDDRAWI_DDRAWSURFACE_INT surf_int;
  1368. LPDDRAWI_DDRAWSURFACE_LCL surf_lcl;
  1369. LPDDSPRITEI pSprite = &sprite[j];
  1370. surf_int = (LPDDRAWI_DDRAWSURFACE_INT)pSprite->lpDDSSrc;
  1371. surf_lcl = surf_int->lpLcl;
  1372. surf_lcl->dwFlags |= DDRAWISURF_INMASTERSPRITELIST;
  1373. }
  1374. }
  1375. } /* markSpriteObjects */
  1376. /*
  1377. * Helper function for managing master sprite list.
  1378. * Mark all surfaces in the master sprite list as no longer
  1379. * referenced by the master sprite list.
  1380. */
  1381. static void unmarkSpriteObjects(LPMASTERSPRITELIST pMaster)
  1382. {
  1383. DWORD i;
  1384. if (pMaster == NULL)
  1385. {
  1386. return; // nothing to do -- bye!
  1387. }
  1388. /*
  1389. * Clear the DDRAWISURF/CLIP_INMASTERSPRITELIST flag in each local
  1390. * surface object and global clipper object in the master sprite
  1391. * list. Each iteration unmarks the objects in one sublist.
  1392. */
  1393. for (i = 0; i < pMaster->dwNumSubLists; ++i)
  1394. {
  1395. LPDDRAWI_DDRAWSURFACE_INT surf_int;
  1396. LPDDRAWI_DDRAWSURFACE_LCL surf_lcl;
  1397. LPDDRAWI_DDRAWCLIPPER_INT pclip_int;
  1398. LPSPRITESUBLIST pSubList = pMaster->pSubList[i];
  1399. LPDDSPRITEI sprite = &pSubList->sprite[0];
  1400. DWORD dwNumSprites = pSubList->dwCount;
  1401. DWORD j;
  1402. /*
  1403. * Unmark the primary surface object associated with this sublist.
  1404. */
  1405. surf_int = (LPDDRAWI_DDRAWSURFACE_INT)pSubList->pPrimary;
  1406. surf_lcl = surf_int->lpLcl;
  1407. surf_lcl->dwFlags &= ~DDRAWISURF_INMASTERSPRITELIST;
  1408. /*
  1409. * If a clipper is associated with this sublist, unmark it.
  1410. */
  1411. pclip_int = (LPDDRAWI_DDRAWCLIPPER_INT)pSubList->pClipper;
  1412. if (pclip_int != NULL)
  1413. {
  1414. LPDDRAWI_DDRAWCLIPPER_LCL pclip_lcl = pclip_int->lpLcl;
  1415. LPDDRAWI_DDRAWCLIPPER_GBL pclip = pclip_lcl->lpGbl;
  1416. pclip->dwFlags &= ~DDRAWICLIP_INMASTERSPRITELIST;
  1417. }
  1418. /*
  1419. * Mark all of the surfaces referenced in this sublist.
  1420. */
  1421. for (j = 0; j < dwNumSprites; ++j)
  1422. {
  1423. LPDDRAWI_DDRAWSURFACE_INT surf_int;
  1424. LPDDRAWI_DDRAWSURFACE_LCL surf_lcl;
  1425. LPDDSPRITEI pSprite = &sprite[j];
  1426. surf_int = (LPDDRAWI_DDRAWSURFACE_INT)pSprite->lpDDSSrc;
  1427. surf_lcl = surf_int->lpLcl;
  1428. surf_lcl->dwFlags &= ~DDRAWISURF_INMASTERSPRITELIST;
  1429. }
  1430. }
  1431. } /* unmarkSpriteObjects */
  1432. /*
  1433. * Helper function for managing master sprite list. This function
  1434. * frees the master sprite list for the specified DirectDraw object.
  1435. */
  1436. void FreeMasterSpriteList(LPDDRAWI_DIRECTDRAW_GBL pdrv)
  1437. {
  1438. DWORD i;
  1439. LPMASTERSPRITELIST pMaster = (LPMASTERSPRITELIST)(pdrv->lpMasterSpriteList);
  1440. if (pMaster == NULL)
  1441. {
  1442. return;
  1443. }
  1444. /*
  1445. * Clear flags in surface and clipper objects that indicate
  1446. * that these objects are referenced in master sprite list.
  1447. */
  1448. unmarkSpriteObjects(pMaster);
  1449. /*
  1450. * Free all the individual sublists within the master sprite list.
  1451. */
  1452. for (i = 0; i < pMaster->dwNumSubLists; ++i)
  1453. {
  1454. LPSPRITESUBLIST pSubList = pMaster->pSubList[i];
  1455. MemFree(pSubList->pRgn); // Free clip region buffer
  1456. MemFree(pSubList); // Free the sublist itself
  1457. }
  1458. MemFree(pMaster->pBuffer); // Free temp display list buffer
  1459. MemFree(pMaster); // Free master sprite list header
  1460. pdrv->lpMasterSpriteList = NULL;
  1461. } /* FreeMasterSpriteList */
  1462. /*
  1463. * This is a helper function for updateMasterSpriteList(). It builds
  1464. * a temporary display list that contains all the sprites currently in
  1465. * the master sprite display list. This is the display list that we
  1466. * will pass to the driver upon return from updateMasterSpriteList().
  1467. */
  1468. static DDHAL_SETSPRITEDISPLAYLISTDATA *buildTempDisplayList(
  1469. LPMASTERSPRITELIST pMaster)
  1470. {
  1471. DWORD size;
  1472. LPBUFFER pbuf;
  1473. LPDDSPRITEI *ppSprite;
  1474. DDHAL_SETSPRITEDISPLAYLISTDATA *pHalData;
  1475. DWORD dwNumSubLists = pMaster->dwNumSubLists; // number of sublists
  1476. DWORD dwNumSprites = 0;
  1477. DWORD i;
  1478. /*
  1479. * Update the clipping region for the sprites within each sublist.
  1480. * In general, each sublist has a different clipping region. If
  1481. * a sublist has a clipper and that clipper has an hWnd, the clip
  1482. * region may have changed since the last time we were called.
  1483. */
  1484. for (i = 0; i < dwNumSubLists; ++i)
  1485. {
  1486. DWORD j;
  1487. LPRGNDATA pRgn;
  1488. DWORD dwRectCnt;
  1489. LPRECT pRect;
  1490. LPSPRITESUBLIST pSubList = pMaster->pSubList[i];
  1491. LPDDSPRITEI sprite = &(pSubList->sprite[0]);
  1492. DWORD dwCount = pSubList->dwCount; // number of sprites in sublist
  1493. /*
  1494. * Get clipping region for window this sprite display list is in.
  1495. */
  1496. pRgn = GetRgnData(pSubList->pClipper, &pMaster->rcPrimary,
  1497. pMaster->pdrv, pSubList->pRgn);
  1498. if (pRgn == NULL)
  1499. {
  1500. return (NULL); // error -- out of memory
  1501. }
  1502. if (pRgn != pSubList->pRgn)
  1503. {
  1504. /*
  1505. * GetRgnData() allocated a new region buffer instead of using
  1506. * the old buffer. We need to free the old buffer ourselves.
  1507. */
  1508. MemFree(pSubList->pRgn);
  1509. }
  1510. pSubList->pRgn = pRgn; // save ptr to region buffer
  1511. /*
  1512. * All sprites in the sublist share the same clipping region.
  1513. */
  1514. dwRectCnt = pRgn->rdh.nCount; // number of rects in region
  1515. pRect = (LPRECT)&pRgn->Buffer; // list of clip rects
  1516. for (j = 0; j < dwCount; ++j)
  1517. {
  1518. sprite[j].dwRectCnt = dwRectCnt;
  1519. sprite[j].lpRect = pRect;
  1520. }
  1521. /*
  1522. * Add the sprites in this sublist to our running tally of
  1523. * the total number of sprites in the master sprite list.
  1524. */
  1525. dwNumSprites += dwCount;
  1526. }
  1527. /*
  1528. * If we can, we'll build our temporary sprite display list in the
  1529. * existing buffer (pMaster->pBuffer). But if it doesn't exist or
  1530. * is too big or too small, we'll have to allocate a new buffer.
  1531. */
  1532. size = sizeof(BUFFER) + (dwNumSprites-1)*sizeof(LPDDSPRITEI);
  1533. pbuf = pMaster->pBuffer; // try to re-use this buffer
  1534. if (pbuf == NULL || pbuf->dwSize < size ||
  1535. pbuf->dwSize > size + 8*sizeof(LPDDSPRITEI))
  1536. {
  1537. /*
  1538. * We have to allocate a new buffer. First, free the old one.
  1539. */
  1540. MemFree(pbuf);
  1541. /*
  1542. * We'll alloc a slightly larger buffer than is absolutely
  1543. * necessary so that we'll have room to grow in.
  1544. */
  1545. size += 4*sizeof(LPDDSPRITEI); // add some padding
  1546. pbuf = (LPBUFFER)MemAlloc(size);
  1547. pMaster->pBuffer = pbuf;
  1548. if (pbuf == NULL)
  1549. {
  1550. return NULL; // error -- out of memory
  1551. }
  1552. pbuf->dwSize = size;
  1553. }
  1554. /*
  1555. * Initialize values in HAL data structure to be passed to driver.
  1556. */
  1557. pHalData = &(pbuf->HalData);
  1558. pHalData->lpDD = pMaster->pdrv;
  1559. pHalData->lpDDSurface = pMaster->surf_lcl; // primary surface (local object)
  1560. pHalData->lplpDDSprite = &(pbuf->pSprite[0]);
  1561. pHalData->dwCount = dwNumSprites;
  1562. pHalData->dwSize = sizeof(DDSPRITEI);
  1563. pHalData->dwFlags = pMaster->dwFlags;
  1564. pHalData->lpDDTargetSurface = NULL; // can't flip shared surface
  1565. pHalData->dwRectCnt = 0;
  1566. pHalData->lpRect = NULL; // each sprite has its own clip region
  1567. pHalData->ddRVal = 0;
  1568. //pHalData->SetSpriteDisplayList = NULL; // no thunk (32-bit callback)
  1569. /*
  1570. * Load the sprite-pointer array with the pointers to
  1571. * all the sprites contained in the various sublists.
  1572. */
  1573. ppSprite = &pbuf->pSprite[0];
  1574. for (i = 0; i < dwNumSubLists; ++i)
  1575. {
  1576. LPSPRITESUBLIST pSubList = pMaster->pSubList[i];
  1577. LPDDSPRITEI sprite = &pSubList->sprite[0];
  1578. DWORD dwCount = pSubList->dwCount; // number of sprites in sublist i
  1579. DWORD j;
  1580. for (j = 0; j < dwCount; ++j)
  1581. {
  1582. /*
  1583. * Copy address of next sprite into pointer array.
  1584. */
  1585. *ppSprite++ = &sprite[j];
  1586. }
  1587. }
  1588. return (&pbuf->HalData); // return temp sprite display list
  1589. } /* buildTempDisplayList */
  1590. /*
  1591. * Global function for managing master sprite list. This function
  1592. * is called by CurrentProcessCleanup to remove from the master
  1593. * sprite list all references to a process that is being terminated.
  1594. * The function also checks for lost surfaces in the master sprite
  1595. * list. If any changes are made to the master sprite list, the
  1596. * driver is told to display those changes immediately.
  1597. */
  1598. void ProcessSpriteCleanup(LPDDRAWI_DIRECTDRAW_GBL pdrv, DWORD pid)
  1599. {
  1600. LPMASTERSPRITELIST pMaster = (LPMASTERSPRITELIST)pdrv->lpMasterSpriteList;
  1601. LPDIRECTDRAWSURFACE pPrimary;
  1602. DWORD dwNumSubLists;
  1603. BOOL bDeleteSubList = FALSE;
  1604. BOOL bChangesMade = FALSE;
  1605. DWORD i;
  1606. if (pMaster == NULL)
  1607. {
  1608. return; // master sprite list does not exist
  1609. }
  1610. pPrimary = pMaster->pSubList[0]->pPrimary;
  1611. dwNumSubLists = pMaster->dwNumSubLists;
  1612. /*
  1613. * Before making changes to the master sprite list, we first
  1614. * unmark all clipper and surface objects in the list. After
  1615. * the changes are completed, we will again mark the objects
  1616. * that are referenced in the revised master sprite list.
  1617. */
  1618. unmarkSpriteObjects(pMaster);
  1619. /*
  1620. * Each sublist of the master sprite list contains all the sprites
  1621. * that are to appear within a particular window of a shared primary.
  1622. * Associated with each sublist is the process ID for the window.
  1623. * Compare this process ID with argument pid. If they match,
  1624. * delete the sublist from the master sprite list.
  1625. */
  1626. for (i = 0; i < dwNumSubLists; ++i)
  1627. {
  1628. LPSPRITESUBLIST pSubList = pMaster->pSubList[i];
  1629. LPDIRECTDRAWSURFACE pPrimary = pSubList->pPrimary;
  1630. LPDDRAWI_DDRAWSURFACE_INT surf_int = (LPDDRAWI_DDRAWSURFACE_INT)pPrimary;
  1631. LPDDRAWI_DDRAWSURFACE_LCL surf_lcl = surf_int->lpLcl;
  1632. /*
  1633. * Is process associated with this sublist being terminated?
  1634. * (We also check for lost surfaces and delete any we find.)
  1635. */
  1636. if (pSubList->dwProcessId != pid &&
  1637. validClipperWindow(pSubList->pClipper) &&
  1638. !SURFACE_LOST(surf_lcl))
  1639. {
  1640. DWORD dwNumSprites = pSubList->dwCount;
  1641. LPDDSPRITEI sprite = &pSubList->sprite[0];
  1642. BOOL bDeleteSprite = FALSE;
  1643. DWORD j;
  1644. /*
  1645. * No, the process for this sublist is NOT being terminated.
  1646. * Check if the source surfaces for any sprites are lost.
  1647. */
  1648. for (j = 0; j < dwNumSprites; ++j)
  1649. {
  1650. LPDIRECTDRAWSURFACE pSrcSurf = sprite[j].lpDDSSrc;
  1651. LPDDRAWI_DDRAWSURFACE_INT surf_src_int = (LPDDRAWI_DDRAWSURFACE_INT)pSrcSurf;
  1652. LPDDRAWI_DDRAWSURFACE_LCL surf_src_lcl = surf_src_int->lpLcl;
  1653. if (SURFACE_LOST(surf_src_lcl))
  1654. {
  1655. /*
  1656. * This surface is lost, so delete the reference.
  1657. */
  1658. sprite[j].lpDDSSrc = NULL; // mark surface as null
  1659. bDeleteSprite = TRUE; // remember sprite array needs fix-up
  1660. }
  1661. }
  1662. /*
  1663. * If the source-surface pointer for any sprite in the sublist
  1664. * was set to null, remove the sprite from the sublist by moving
  1665. * the rest of the sprite array downward to fill the gap.
  1666. */
  1667. if (bDeleteSprite == TRUE)
  1668. {
  1669. dwNumSprites = scrunchSubList(pSubList);
  1670. bChangesMade = TRUE; // remember change to master sprite list
  1671. }
  1672. if (dwNumSprites != 0)
  1673. {
  1674. /*
  1675. * The sublist still contains sprites, so don't delete it.
  1676. */
  1677. continue; // go to next sublist
  1678. }
  1679. }
  1680. /*
  1681. * Delete the sublist. The reason is that (1) the process that
  1682. * owns the sublist is being terminated, or (2) the sublist is
  1683. * associated with an invalid window, or (3) the source surface
  1684. * for every sprite in the sublist is a lost surface.
  1685. */
  1686. MemFree(pSubList->pRgn);
  1687. MemFree(pSubList);
  1688. pMaster->pSubList[i] = NULL; // mark sublist as null
  1689. bDeleteSubList = TRUE; // remember we deleted sublist
  1690. }
  1691. /*
  1692. * If the sublist pointer for any sublist in the master sprite
  1693. * list was set to null, remove the null from the pointer array by
  1694. * moving the rest of the pointer array downward to fill the gap.
  1695. */
  1696. if (bDeleteSubList)
  1697. {
  1698. dwNumSubLists = scrunchMasterSpriteList(pMaster);
  1699. bChangesMade = TRUE;
  1700. }
  1701. /*
  1702. * If any changes have been made to the master sprite list, tell
  1703. * the driver to make the changes visible on the screen.
  1704. */
  1705. if (bChangesMade)
  1706. {
  1707. DWORD rc;
  1708. LPDDHAL_SETSPRITEDISPLAYLIST pfn;
  1709. DDHAL_SETSPRITEDISPLAYLISTDATA *pHalData;
  1710. LPDDRAWI_DDRAWSURFACE_INT surf_int = (LPDDRAWI_DDRAWSURFACE_INT)pPrimary;
  1711. LPDDRAWI_DDRAWSURFACE_LCL surf_lcl = surf_int->lpLcl;
  1712. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl = surf_lcl->lpSurfMore->lpDD_lcl;
  1713. /*
  1714. * Build a temporary display list that contains all the sprites
  1715. * in the revised master sprite list.
  1716. */
  1717. pMaster->surf_lcl = surf_lcl; // used by buildTempDisplayList
  1718. #if 0
  1719. pMaster->dwFlags = DDSSDL_BLTSPRITES; // debug !!
  1720. #else
  1721. pMaster->dwFlags = DDSSDL_OVERLAYSPRITES; // used by buildTempDisplayList
  1722. #endif
  1723. pHalData = buildTempDisplayList(pMaster);
  1724. /*
  1725. * Pass the temp display list to the driver.
  1726. */
  1727. #if 0
  1728. pfn = pdrv_lcl->lpDDCB->HELDDMiscellaneous2.SetSpriteDisplayList; // debug !!
  1729. #else
  1730. pfn = pdrv_lcl->lpDDCB->HALDDMiscellaneous2.SetSpriteDisplayList;
  1731. #endif
  1732. DOHALCALL(SetSpriteDisplayList, pfn, *pHalData, rc, 0);
  1733. }
  1734. if (dwNumSubLists == 0)
  1735. {
  1736. /*
  1737. * We deleted ALL the sublists from the master sprite list,
  1738. * so now we need to delete the master sprite list too.
  1739. */
  1740. FreeMasterSpriteList(pdrv);
  1741. return;
  1742. }
  1743. markSpriteObjects(pMaster);
  1744. } /* ProcessSpriteCleanup */
  1745. /*
  1746. * Global function for managing master sprite list. This function is
  1747. * called by InternalSurfaceRelease to remove all references in the
  1748. * master sprite list to a surface interface object that is being
  1749. * released. The function also checks for lost surfaces in the
  1750. * master sprite list. If any changes are made to the master sprite
  1751. * list, the driver is told to display those changes immediately.
  1752. */
  1753. void RemoveSpriteSurface(LPDDRAWI_DIRECTDRAW_GBL pdrv,
  1754. LPDDRAWI_DDRAWSURFACE_INT surf_int)
  1755. {
  1756. LPMASTERSPRITELIST pMaster = (LPMASTERSPRITELIST)pdrv->lpMasterSpriteList;
  1757. LPDIRECTDRAWSURFACE pSurface = (LPDIRECTDRAWSURFACE)surf_int;
  1758. LPDIRECTDRAWSURFACE pPrimary = pMaster->pSubList[0]->pPrimary;
  1759. DWORD dwNumSubLists = pMaster->dwNumSubLists;
  1760. BOOL bDeleteSubList = FALSE;
  1761. BOOL bChangesMade = FALSE;
  1762. DWORD i;
  1763. DDASSERT(pMaster != NULL); // error -- surface shouldn't be marked!
  1764. /*
  1765. * Before making changes to the master sprite list, we first
  1766. * unmark all clipper and surface objects in the list. After
  1767. * the changes are completed, we will again mark the objects
  1768. * that are referenced in the revised master sprite list.
  1769. */
  1770. unmarkSpriteObjects(pMaster);
  1771. /*
  1772. * Each sublist of the master sprite list contains all the sprites
  1773. * that are to appear within a particular window of a shared primary.
  1774. * Stored with each sublist is the primary surface object for the
  1775. * window, and also the source surface objects for each sprite in the
  1776. * sublist. These surfaces are checked against pSurface and if a
  1777. * match is found, the surface reference is deleted from the sublist.
  1778. */
  1779. for (i = 0; i < dwNumSubLists; ++i)
  1780. {
  1781. LPSPRITESUBLIST pSubList = pMaster->pSubList[i];
  1782. LPDIRECTDRAWSURFACE pDestSurf = pSubList->pPrimary;
  1783. LPDDRAWI_DDRAWSURFACE_INT surf_dest_int = (LPDDRAWI_DDRAWSURFACE_INT)pDestSurf;
  1784. LPDDRAWI_DDRAWSURFACE_LCL surf_dest_lcl = surf_dest_int->lpLcl;
  1785. /*
  1786. * If this sublist's primary surface object is being released, delete
  1787. * the sublist. We also check for lost surfaces and delete any we find.
  1788. */
  1789. if (pDestSurf != pSurface && validClipperWindow(pSubList->pClipper) &&
  1790. !SURFACE_LOST(surf_dest_lcl))
  1791. {
  1792. DWORD dwNumSprites = pSubList->dwCount;
  1793. LPDDSPRITEI sprite = &pSubList->sprite[0];
  1794. BOOL bDeleteSprite = FALSE;
  1795. DWORD j;
  1796. /*
  1797. * No, the primary surface object for this sublist is NOT
  1798. * being released, but perhaps the source surface for one
  1799. * or more of the sprites in this sublist is being released.
  1800. */
  1801. for (j = 0; j < dwNumSprites; ++j)
  1802. {
  1803. LPDIRECTDRAWSURFACE pSrcSurf = sprite[j].lpDDSSrc;
  1804. LPDDRAWI_DDRAWSURFACE_INT surf_src_int = (LPDDRAWI_DDRAWSURFACE_INT)pSrcSurf;
  1805. LPDDRAWI_DDRAWSURFACE_LCL surf_src_lcl = surf_src_int->lpLcl;
  1806. if (pSrcSurf == pSurface || SURFACE_LOST(surf_src_lcl))
  1807. {
  1808. /*
  1809. * This surface either is being released or is lost.
  1810. * In either case, we delete the reference.
  1811. */
  1812. sprite[j].lpDDSSrc = NULL; // mark surface as null
  1813. bDeleteSprite = TRUE; // remember sprite array needs fix-up
  1814. }
  1815. }
  1816. /*
  1817. * If the source-surface pointer for any sprite in the sublist
  1818. * was set to null, remove the sprite from the sublist by moving
  1819. * the rest of the sprite array downward to fill the gap.
  1820. */
  1821. if (bDeleteSprite == TRUE)
  1822. {
  1823. dwNumSprites = scrunchSubList(pSubList);
  1824. bChangesMade = TRUE; // remember change to master sprite list
  1825. }
  1826. if (dwNumSprites != 0)
  1827. {
  1828. /*
  1829. * The sublist still contains sprites, so don't delete it.
  1830. */
  1831. continue; // go to next sublist
  1832. }
  1833. }
  1834. /*
  1835. * Delete the sublist. The reason is that (1) the primary surface
  1836. * object for the sublist is being released, or (2) the sublist is
  1837. * associated with an invalid window, or (3) the source surface
  1838. * for every sprite in the sublist is either being released or is
  1839. * a lost surface.
  1840. */
  1841. MemFree(pSubList->pRgn);
  1842. MemFree(pSubList);
  1843. pMaster->pSubList[i] = NULL; // mark sublist as null
  1844. bDeleteSubList = TRUE; // remember we deleted sublist
  1845. }
  1846. /*
  1847. * If the sublist pointer for any sublist in the master sprite
  1848. * list was set to null, remove the null from the pointer array by
  1849. * moving the rest of the pointer array downward to fill the gap.
  1850. */
  1851. if (bDeleteSubList)
  1852. {
  1853. dwNumSubLists = scrunchMasterSpriteList(pMaster);
  1854. bChangesMade = TRUE;
  1855. }
  1856. /*
  1857. * If any changes have been made to the master sprite list, tell
  1858. * the driver to make the changes visible on the screen.
  1859. */
  1860. if (bChangesMade)
  1861. {
  1862. DWORD rc;
  1863. LPDDHAL_SETSPRITEDISPLAYLIST pfn;
  1864. DDHAL_SETSPRITEDISPLAYLISTDATA *pHalData;
  1865. LPDDRAWI_DDRAWSURFACE_INT surf_int = (LPDDRAWI_DDRAWSURFACE_INT)pPrimary;
  1866. LPDDRAWI_DDRAWSURFACE_LCL surf_lcl = surf_int->lpLcl;
  1867. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl = surf_lcl->lpSurfMore->lpDD_lcl;
  1868. /*
  1869. * Build a temporary display list that contains all the sprites
  1870. * in the revised master sprite list.
  1871. */
  1872. pMaster->surf_lcl = surf_lcl; // used by buildTempDisplayList
  1873. #if 0
  1874. pMaster->dwFlags = DDSSDL_BLTSPRITES; // debug !!
  1875. #else
  1876. pMaster->dwFlags = DDSSDL_OVERLAYSPRITES; // used by buildTempDisplayList
  1877. #endif
  1878. pHalData = buildTempDisplayList(pMaster);
  1879. /*
  1880. * Pass the temp display list to the driver.
  1881. */
  1882. #if 0
  1883. pfn = pdrv_lcl->lpDDCB->HELDDMiscellaneous2.SetSpriteDisplayList; // debug !!
  1884. #else
  1885. pfn = pdrv_lcl->lpDDCB->HALDDMiscellaneous2.SetSpriteDisplayList;
  1886. #endif
  1887. DOHALCALL(SetSpriteDisplayList, pfn, *pHalData, rc, 0);
  1888. }
  1889. if (dwNumSubLists == 0)
  1890. {
  1891. /*
  1892. * We deleted ALL the sublists from the master sprite list,
  1893. * so now we need to delete the master sprite list too.
  1894. */
  1895. FreeMasterSpriteList(pdrv);
  1896. return;
  1897. }
  1898. markSpriteObjects(pMaster);
  1899. } /* RemoveSpriteSurface */
  1900. /*
  1901. * Global function for managing master sprite list. This function is
  1902. * called by InternalClipperRelease to remove all references in the
  1903. * master sprite list to a clipper object that is being released.
  1904. * The function also checks for lost surfaces in the master sprite
  1905. * list. If any changes are made to the master sprite list, the
  1906. * driver is told to display those changes immediately.
  1907. */
  1908. void RemoveSpriteClipper(LPDDRAWI_DIRECTDRAW_GBL pdrv,
  1909. LPDDRAWI_DDRAWCLIPPER_INT pclip_int)
  1910. {
  1911. LPMASTERSPRITELIST pMaster = (LPMASTERSPRITELIST)pdrv->lpMasterSpriteList;
  1912. LPDIRECTDRAWSURFACE pPrimary = pMaster->pSubList[0]->pPrimary;
  1913. LPDIRECTDRAWCLIPPER pClipper = (LPDIRECTDRAWCLIPPER)pclip_int;
  1914. DWORD dwNumSubLists = pMaster->dwNumSubLists;
  1915. BOOL bDeleteSubList = FALSE;
  1916. BOOL bChangesMade = FALSE;
  1917. DWORD i;
  1918. DDASSERT(pMaster != NULL); // error -- surface shouldn't be marked!
  1919. /*
  1920. * Before making changes to the master sprite list, we first
  1921. * unmark all clipper and surface objects in the list. After
  1922. * the changes are completed, we will again mark the objects
  1923. * that are referenced in the revised master sprite list.
  1924. */
  1925. unmarkSpriteObjects(pMaster);
  1926. /*
  1927. * Each sublist of the master sprite list contains all the sprites
  1928. * that are to appear within a particular window of a shared primary.
  1929. * Each sublist has a clipper (which may be NULL) to specify the
  1930. * window's clip region. Each sublist's clipper pointer is compared
  1931. * with the specified pClipper pointer. If a match is found, the
  1932. * sublist and its clipper are removed from the master sprite list.
  1933. */
  1934. for (i = 0; i < dwNumSubLists; ++i)
  1935. {
  1936. LPSPRITESUBLIST pSubList = pMaster->pSubList[i];
  1937. LPDIRECTDRAWSURFACE pDestSurf = pSubList->pPrimary;
  1938. LPDDRAWI_DDRAWSURFACE_INT surf_dest_int = (LPDDRAWI_DDRAWSURFACE_INT)pDestSurf;
  1939. LPDDRAWI_DDRAWSURFACE_LCL surf_dest_lcl = surf_dest_int->lpLcl;
  1940. /*
  1941. * If clipper object for this sublist is being released, delete it.
  1942. * (We also check for lost surfaces and delete any we find.)
  1943. */
  1944. if (pSubList->pClipper != pClipper &&
  1945. validClipperWindow(pSubList->pClipper) &&
  1946. !SURFACE_LOST(surf_dest_lcl))
  1947. {
  1948. DWORD dwNumSprites = pSubList->dwCount;
  1949. LPDDSPRITEI sprite = &pSubList->sprite[0];
  1950. BOOL bDeleteSprite = FALSE;
  1951. DWORD j;
  1952. /*
  1953. * No, the clipper for this sublist is NOT being released.
  1954. * Check if the source surfaces for any sprites are lost.
  1955. */
  1956. for (j = 0; j < dwNumSprites; ++j)
  1957. {
  1958. LPDIRECTDRAWSURFACE pSrcSurf = sprite[j].lpDDSSrc;
  1959. LPDDRAWI_DDRAWSURFACE_INT surf_src_int = (LPDDRAWI_DDRAWSURFACE_INT)pSrcSurf;
  1960. LPDDRAWI_DDRAWSURFACE_LCL surf_src_lcl = surf_src_int->lpLcl;
  1961. if (SURFACE_LOST(surf_src_lcl))
  1962. {
  1963. /*
  1964. * This surface is lost, so delete the reference.
  1965. */
  1966. sprite[j].lpDDSSrc = NULL; // mark surface as null
  1967. bDeleteSprite = TRUE; // remember sprite array needs fix-up
  1968. }
  1969. }
  1970. /*
  1971. * If the source-surface pointer for any sprite in the sublist
  1972. * was set to null, remove the sprite from the sublist by moving
  1973. * the rest of the sprite array downward to fill the gap.
  1974. */
  1975. if (bDeleteSprite == TRUE)
  1976. {
  1977. dwNumSprites = scrunchSubList(pSubList);
  1978. bChangesMade = TRUE; // remember change to master sprite list
  1979. }
  1980. if (dwNumSprites != 0)
  1981. {
  1982. /*
  1983. * The sublist still contains sprites, so don't delete it.
  1984. */
  1985. continue; // go to next sublist
  1986. }
  1987. }
  1988. /*
  1989. * Delete the sublist. The reason is that (1) the clipper for the
  1990. * sublist is being released, (2) the sublist is associated with an
  1991. * invalid window, or (3) the source surface for every sprite in
  1992. * the sublist is a lost surface.
  1993. */
  1994. MemFree(pSubList->pRgn);
  1995. MemFree(pSubList);
  1996. pMaster->pSubList[i] = NULL; // mark sublist as null
  1997. bDeleteSubList = TRUE; // remember we deleted sublist
  1998. }
  1999. /*
  2000. * If the sublist pointer for any sublist in the master sprite
  2001. * list was set to null, remove the null from the pointer array by
  2002. * moving the rest of the pointer array downward to fill the gap.
  2003. */
  2004. if (bDeleteSubList)
  2005. {
  2006. dwNumSubLists = scrunchMasterSpriteList(pMaster);
  2007. bChangesMade = TRUE;
  2008. }
  2009. /*
  2010. * If any changes have been made to the master sprite list, tell
  2011. * the driver to make the changes visible on the screen.
  2012. */
  2013. if (bChangesMade)
  2014. {
  2015. DWORD rc;
  2016. LPDDHAL_SETSPRITEDISPLAYLIST pfn;
  2017. DDHAL_SETSPRITEDISPLAYLISTDATA *pHalData;
  2018. LPDDRAWI_DDRAWSURFACE_INT surf_int = (LPDDRAWI_DDRAWSURFACE_INT)pPrimary;
  2019. LPDDRAWI_DDRAWSURFACE_LCL surf_lcl = surf_int->lpLcl;
  2020. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl = surf_lcl->lpSurfMore->lpDD_lcl;
  2021. /*
  2022. * Build a temporary display list that contains all the sprites
  2023. * in the revised master sprite list.
  2024. */
  2025. pMaster->surf_lcl = surf_lcl; // used by buildTempDisplayList
  2026. #if 0
  2027. pMaster->dwFlags = DDSSDL_BLTSPRITES; // debug !!
  2028. #else
  2029. pMaster->dwFlags = DDSSDL_OVERLAYSPRITES; // used by buildTempDisplayList
  2030. #endif
  2031. pHalData = buildTempDisplayList(pMaster);
  2032. /*
  2033. * Pass the temp display list to the driver.
  2034. */
  2035. #if 0
  2036. pfn = pdrv_lcl->lpDDCB->HELDDMiscellaneous2.SetSpriteDisplayList; // debug !!
  2037. #else
  2038. pfn = pdrv_lcl->lpDDCB->HALDDMiscellaneous2.SetSpriteDisplayList;
  2039. #endif
  2040. DOHALCALL(SetSpriteDisplayList, pfn, *pHalData, rc, 0);
  2041. }
  2042. if (dwNumSubLists == 0)
  2043. {
  2044. /*
  2045. * We deleted ALL the sublists from the master sprite list,
  2046. * so now we need to delete the master sprite list too.
  2047. */
  2048. FreeMasterSpriteList(pdrv);
  2049. return;
  2050. }
  2051. markSpriteObjects(pMaster);
  2052. } /* RemoveSpriteClipper */
  2053. /*
  2054. * Helper function for managing master sprite list. Check each sprite
  2055. * to see if its surface has been lost. Also check each sublist to
  2056. * see if its window still exists. Sprites with lost surfaces are
  2057. * deleted from the master sprite list. Also, sublists with defunct
  2058. * windows are deleted. Before calling this function, call
  2059. * unmarkSpriteObjects().
  2060. */
  2061. static void removeLostSpriteSurfaces(LPDDRAWI_DIRECTDRAW_GBL pdrv)
  2062. {
  2063. DWORD i;
  2064. DWORD dwNumSubLists;
  2065. LPMASTERSPRITELIST pMaster = pdrv->lpMasterSpriteList;
  2066. BOOL bDeleteSubList = FALSE;
  2067. if (pMaster == NULL)
  2068. {
  2069. return; // nothing to do -- bye!
  2070. }
  2071. dwNumSubLists = pMaster->dwNumSubLists;
  2072. DDASSERT(dwNumSubLists != 0);
  2073. /*
  2074. * Each iteration checks all the sprites in one sublist
  2075. * to see if their source surfaces have been lost.
  2076. */
  2077. for (i = 0; i < dwNumSubLists; ++i)
  2078. {
  2079. LPSPRITESUBLIST pSubList = pMaster->pSubList[i];
  2080. /*
  2081. * Verify that clipper for this sublist has a valid window handle.
  2082. */
  2083. if (validClipperWindow(pSubList->pClipper))
  2084. {
  2085. LPDDSPRITEI sprite = &pSubList->sprite[0];
  2086. DWORD dwNumSprites = pSubList->dwCount;
  2087. BOOL bDeleteSprite = FALSE;
  2088. DWORD j;
  2089. DDASSERT(dwNumSprites != 0);
  2090. /*
  2091. * Yes, clipper's window handle is valid. Now check to see if
  2092. * any of the sprites in the sublist have lost source surfaces.
  2093. */
  2094. for (j = 0; j < dwNumSprites; ++j)
  2095. {
  2096. LPDIRECTDRAWSURFACE pSrcSurf = sprite[j].lpDDSSrc;
  2097. LPDDRAWI_DDRAWSURFACE_INT surf_src_int = (LPDDRAWI_DDRAWSURFACE_INT)pSrcSurf;
  2098. LPDDRAWI_DDRAWSURFACE_LCL surf_src_lcl = surf_src_int->lpLcl;
  2099. if (SURFACE_LOST(surf_src_lcl)) // is this surface lost?
  2100. {
  2101. sprite[j].lpDDSSrc = NULL; // yes, set surface ptr to null
  2102. bDeleteSprite = TRUE; // remember sublist needs fix-up
  2103. }
  2104. }
  2105. /*
  2106. * If the source-surface pointer for any sprite in the sublist
  2107. * was set to null, remove the sprite from the sublist by moving
  2108. * the rest of the sprite array downward to fill the gap.
  2109. */
  2110. if (bDeleteSprite == TRUE)
  2111. {
  2112. dwNumSprites = scrunchSubList(pSubList);
  2113. }
  2114. if (dwNumSprites != 0)
  2115. {
  2116. /*
  2117. * The sublist still contains sprites, so don't delete it.
  2118. */
  2119. continue; // go to next sublist
  2120. }
  2121. }
  2122. /*
  2123. * Delete the sublist. The reason is either that the window
  2124. * handle associated with this sublist's clipper is not valid,
  2125. * or that all the sprites in the sublist have been deleted.
  2126. */
  2127. MemFree(pSubList->pRgn);
  2128. MemFree(pSubList);
  2129. pMaster->pSubList[i] = NULL; // mark sublist as null
  2130. bDeleteSubList = TRUE; // remember we deleted sublist
  2131. }
  2132. /*
  2133. * If the sublist pointer for any sublist in the master sprite
  2134. * list was set to null, remove the null from the pointer array by
  2135. * moving the rest of the pointer array downward to fill the gap.
  2136. */
  2137. if (bDeleteSubList)
  2138. {
  2139. scrunchMasterSpriteList(pMaster);
  2140. if (pMaster->dwNumSubLists == 0)
  2141. {
  2142. FreeMasterSpriteList(pdrv); // delete master sprite list
  2143. }
  2144. }
  2145. } /* removeLostSpriteSurfaces */
  2146. /*
  2147. * This is a helper function for updateMasterSpriteList(). It alloc's
  2148. * a sublist and copies the new sprite display list into the sublist.
  2149. * If pSubList already points to a buffer that is large enough, the new
  2150. * sublist will be created in this buffer. Otherwise, a new buffer
  2151. * will be alloc'd (but the old buffer isn't freed -- that's left up to
  2152. * the caller). Arg pHalData points to the sprite display list from
  2153. * the app. The return value is a pointer to the new sublist.
  2154. */
  2155. static LPSPRITESUBLIST createSpriteSubList(LPSPRITESUBLIST pSubList,
  2156. DDHAL_SETSPRITEDISPLAYLISTDATA *pHalData,
  2157. LPDIRECTDRAWSURFACE pPrimary)
  2158. {
  2159. LPDDSPRITEI *ppSprite;
  2160. LPDDSPRITEI sprite;
  2161. // pointers to local and global surface objects
  2162. LPDDRAWI_DDRAWSURFACE_LCL surf_lcl = pHalData->lpDDSurface;
  2163. LPDDRAWI_DDRAWSURFACE_GBL surf = surf_lcl->lpGbl;
  2164. // number of sprites in new display list:
  2165. DWORD dwNumSprites = pHalData->dwCount;
  2166. // size (in bytes) of new sublist:
  2167. DWORD size = sizeof(SPRITESUBLIST) +
  2168. (dwNumSprites-1)*sizeof(DDSPRITEI);
  2169. DDASSERT(dwNumSprites != 0);
  2170. /*
  2171. * If old sublist buffer is null or too small or too big,
  2172. * allocate a new sublist buffer that's the correct size.
  2173. */
  2174. if (pSubList == NULL || pSubList->dwSize < size ||
  2175. pSubList->dwSize > size + 8*sizeof(DDSPRITEI))
  2176. {
  2177. /*
  2178. * Allocate a new sublist that's just a tad larger than
  2179. * necessary so that we have a little room to grow in.
  2180. */
  2181. size += 4*sizeof(DDSPRITEI); // add some padding
  2182. pSubList = (LPSPRITESUBLIST)MemAlloc(size);
  2183. if (pSubList == NULL)
  2184. {
  2185. return NULL; // error -- out of memory
  2186. }
  2187. pSubList->dwSize = size; // remember how big buffer is
  2188. }
  2189. /*
  2190. * Initialize sublist buffer.
  2191. */
  2192. pSubList->pPrimary = pPrimary; // primary surface (interface object)
  2193. pSubList->pClipper = (LPDIRECTDRAWCLIPPER)surf_lcl->lpSurfMore->lpDDIClipper;
  2194. pSubList->dwProcessId = GETCURRPID();
  2195. pSubList->dwCount = dwNumSprites; // number of sprites in sublist
  2196. pSubList->pRgn = NULL;
  2197. /*
  2198. * To keep things simple, the master sprite display list always stores
  2199. * sprites in front-to-back order, regardless of how callers order them.
  2200. * The loop below copies the sprites into a contiguous array of sprites.
  2201. */
  2202. sprite = &pSubList->sprite[0]; // array of sprites
  2203. ppSprite = pHalData->lplpDDSprite; // array of sprite pointers
  2204. if (pHalData->dwFlags & DDSSDL_BACKTOFRONT)
  2205. {
  2206. int i, j;
  2207. // Reverse original back-to-front ordering of sprites.
  2208. for (i = 0, j = (int)dwNumSprites-1; j >= 0; ++i, --j)
  2209. {
  2210. memcpy(&sprite[i], ppSprite[j], sizeof(DDSPRITEI));
  2211. }
  2212. }
  2213. else
  2214. {
  2215. int i;
  2216. // Preserve original front-to-back ordering of sprites.
  2217. for (i = 0; i < (int)dwNumSprites; ++i)
  2218. {
  2219. memcpy(&sprite[i], ppSprite[i], sizeof(DDSPRITEI));
  2220. }
  2221. }
  2222. return (pSubList); // return completed sublist
  2223. } /* createSpriteSubList */
  2224. /*
  2225. * This routine adds a new display list to the master sprite display list,
  2226. * which keeps track of all overlay sprites currently displayed on the shared
  2227. * primary. Don't call it if (1) the sprites are blitted or (2) the primary
  2228. * is not shared. The update replaces the display list for the affected
  2229. * window, but leaves the display lists for all other windows unchanged.
  2230. * Arg surf_lcl points to the primary. Input arg **ppHalData is the HAL
  2231. * callback struct that specifies the new display list. If the original
  2232. * sprite display list in **ppHalData can be used in place of a master
  2233. * display list without zapping sprites in other windows. Otherwise, the
  2234. * routine sets *ppHalData to point to a master sprite list that contains
  2235. * the overlay sprites for all windows.
  2236. */
  2237. static HRESULT updateMasterSpriteList(LPDIRECTDRAWSURFACE pPrimary,
  2238. DDHAL_SETSPRITEDISPLAYLISTDATA **ppHalData)
  2239. {
  2240. DWORD i;
  2241. LPDIRECTDRAWCLIPPER pClipper;
  2242. DDHAL_SETSPRITEDISPLAYLISTDATA *pHalData;
  2243. LPDDRAWI_DDRAWSURFACE_INT surf_int = (LPDDRAWI_DDRAWSURFACE_INT)pPrimary;
  2244. LPDDRAWI_DDRAWSURFACE_LCL surf_lcl = surf_int->lpLcl;
  2245. LPDDRAWI_DDRAWSURFACE_MORE surf_more = surf_lcl->lpSurfMore;
  2246. LPDDRAWI_DIRECTDRAW_GBL pdrv = surf_more->lpDD_lcl->lpGbl;
  2247. DWORD dwProcessId;
  2248. LPMASTERSPRITELIST pMaster;
  2249. LPSPRITESUBLIST pSubList;
  2250. DWORD dwNumSprites = (*ppHalData)->dwCount; // number of sprites in display list
  2251. /*
  2252. * Get pointer to master sprite list.
  2253. */
  2254. pMaster = (LPMASTERSPRITELIST)pdrv->lpMasterSpriteList;
  2255. if (pMaster != NULL)
  2256. {
  2257. /*
  2258. * A master sprite list already exists.
  2259. */
  2260. #ifdef WIN95
  2261. if (pMaster->dwModeCreatedIn != pdrv->dwModeIndex) // current mode index
  2262. #else
  2263. if (!EQUAL_DISPLAYMODE(pMaster->dmiCreated, pdrv->dmiCurrent))
  2264. #endif
  2265. {
  2266. /*
  2267. * The master sprite list was created in a different video mode
  2268. * and is therefore no longer valid. We rely on the mini-vdd
  2269. * driver remembering to turn off all overlay sprites when a
  2270. * mode change occurs, so they should already be turned off.
  2271. * All we do here is to update our internal data structures.
  2272. */
  2273. FreeMasterSpriteList(pdrv);
  2274. pMaster = NULL;
  2275. }
  2276. else
  2277. {
  2278. /*
  2279. * Between calls to SetSpriteDisplayList, all surface and clipper
  2280. * objects in the master sprite list are marked so that we will be
  2281. * notified if any of these objects are released, invalidating our
  2282. * references to them. We now unmark all surface/clipper objects
  2283. * in the master sprite list so we can update the references.
  2284. */
  2285. unmarkSpriteObjects(pMaster);
  2286. /*
  2287. * Remove any references to lost surfaces from master sprite list.
  2288. */
  2289. removeLostSpriteSurfaces(pdrv); // can delete master sprite list
  2290. /*
  2291. * Just in case the call above deleted the master sprite list...
  2292. */
  2293. pMaster = (LPMASTERSPRITELIST)pdrv->lpMasterSpriteList;
  2294. }
  2295. }
  2296. /*
  2297. * Has the master sprite list been created yet?
  2298. */
  2299. if (pMaster == NULL)
  2300. {
  2301. LPDDRAWI_DDRAWSURFACE_GBL surf = surf_lcl->lpGbl;
  2302. /*
  2303. * No, the master sprite list has not been created.
  2304. */
  2305. if (dwNumSprites == 0)
  2306. {
  2307. /*
  2308. * The new display list is empty, so don't bother
  2309. * to create the master sprite list.
  2310. */
  2311. return (DD_OK); // nothing to do -- bye!
  2312. }
  2313. /*
  2314. * The new display list is not empty, so we will now
  2315. * create the master sprite list and copy the new display
  2316. * list into the initial sublist of the master sprite list.
  2317. */
  2318. pMaster = (LPMASTERSPRITELIST)MemAlloc(sizeof(MASTERSPRITELIST));
  2319. if (pMaster == NULL)
  2320. {
  2321. return (DDERR_OUTOFMEMORY); // error -- out of memory
  2322. }
  2323. /*
  2324. * Initialize the values in the master list header structure.
  2325. */
  2326. pMaster->pdrv = pdrv;
  2327. pMaster->surf_lcl = surf_lcl; // primary surface (local object)
  2328. SetRect(&pMaster->rcPrimary, 0, 0, surf->wWidth, surf->wHeight);
  2329. pMaster->dwFlags = (*ppHalData)->dwFlags & (DDSSDL_WAIT |
  2330. #if 0
  2331. DDSSDL_BLTSPRITES); // debug!!
  2332. #else
  2333. DDSSDL_OVERLAYSPRITES);
  2334. #endif
  2335. #ifdef WIN95
  2336. pMaster->dwModeCreatedIn = pdrv->dwModeIndex; // current mode index
  2337. #else
  2338. pMaster->dmiCreated = pdrv->dmiCurrent;
  2339. #endif
  2340. pMaster->pBuffer = NULL;
  2341. /*
  2342. * Copy the new sprite display list into the initial sublist.
  2343. */
  2344. pMaster->dwNumSubLists = 1;
  2345. pMaster->pSubList[0] = createSpriteSubList(NULL, *ppHalData, pPrimary);
  2346. if (pMaster->pSubList[0] == NULL)
  2347. {
  2348. MemFree(pMaster);
  2349. return (DDERR_OUTOFMEMORY);
  2350. }
  2351. /*
  2352. * Mark all the surface and clipper objects that are
  2353. * referenced in the new master sprite list.
  2354. */
  2355. markSpriteObjects(pMaster);
  2356. /*
  2357. * We've succeeded in creating a master sprite list. Load the
  2358. * pointer to the master list into the global DirectDraw object.
  2359. */
  2360. pdrv->lpMasterSpriteList = (LPVOID)pMaster;
  2361. return (DD_OK); // new master sprite list completed
  2362. }
  2363. /*
  2364. * The master sprite list was created previously. There are
  2365. * three possibilities at this point (#1 is most likely):
  2366. * 1) We're REPLACING a sublist in the master sprite list.
  2367. * In this case, the new display list contains one or
  2368. * more sprites and the pClipper and ProcessId of the new
  2369. * display list will match those stored in a sublist.
  2370. * 2) We're ADDING a new sublist to the master sprite list.
  2371. * In this case, the new display list contains one or
  2372. * more sprites but the pClipper and ProcessId of the
  2373. * new display list don't match those of any sublist.
  2374. * 3) We're DELETING a sublist from the master sprite list.
  2375. * In this case, the new display list is empty (sprite
  2376. * count = 0) and the pClipper and ProcessId of the new
  2377. * display list match those stored with a sublist.
  2378. */
  2379. pClipper = (LPDIRECTDRAWCLIPPER)(surf_more->lpDDIClipper);
  2380. dwProcessId = GETCURRPID();
  2381. pMaster->surf_lcl = surf_lcl; // primary surface (local object)
  2382. pMaster->dwFlags = (*ppHalData)->dwFlags & (DDSSDL_WAIT |
  2383. #if 0
  2384. DDSSDL_BLTSPRITES); // debug !!
  2385. #else
  2386. DDSSDL_OVERLAYSPRITES);
  2387. #endif
  2388. for (i = 0; i < pMaster->dwNumSubLists; ++i)
  2389. {
  2390. /*
  2391. * Look for a sublist with a pointer to the same clipper object.
  2392. * To handle the case pClipper = NULL, we compare process IDs also.
  2393. */
  2394. if (pMaster->pSubList[i]->pClipper == pClipper &&
  2395. pMaster->pSubList[i]->dwProcessId == dwProcessId)
  2396. {
  2397. break; // found a sublist with matching pClipper and dwProcessId
  2398. }
  2399. }
  2400. if (i == pMaster->dwNumSubLists)
  2401. {
  2402. /*
  2403. * The pClipper and Process ID of the new display list don't
  2404. * match those of any of the current sublists. This means
  2405. * that a new window has begun displaying overlay sprites.
  2406. */
  2407. if (dwNumSprites == 0)
  2408. {
  2409. /*
  2410. * The new display list is empty, so don't bother adding
  2411. * a new (empty) sublist to the master sprite list.
  2412. */
  2413. markSpriteObjects(pMaster);
  2414. return (DD_OK); // nothing to do -- bye!
  2415. }
  2416. /*
  2417. * Add a new sublist to the master sprite list and copy the
  2418. * new display list into the new sublist.
  2419. */
  2420. pSubList = createSpriteSubList(NULL, *ppHalData, pPrimary);
  2421. if (pSubList == NULL)
  2422. {
  2423. return (DDERR_OUTOFMEMORY); // error -- out of memory
  2424. }
  2425. if (i != MAXNUMSPRITESUBLISTS)
  2426. {
  2427. /*
  2428. * Add the new sublist to the master sprite list.
  2429. */
  2430. pMaster->dwNumSubLists++;
  2431. pMaster->pSubList[i] = pSubList;
  2432. }
  2433. else
  2434. {
  2435. /*
  2436. * Oops. The master sprite list already contains the maximum
  2437. * number of sublists. I guess I'll just delete one of the
  2438. * other sublists so I can add the new sublist. (If anybody
  2439. * complains loud enough, we can get rid of the fixed limit.)
  2440. */
  2441. MemFree(pMaster->pSubList[i-1]);
  2442. pMaster->pSubList[i-1] = pSubList;
  2443. }
  2444. }
  2445. else
  2446. {
  2447. /*
  2448. * We've found an existing sublist that matches the new display list's
  2449. * pClipper and ProcessId (the sublist contains the old display list
  2450. * for the window in which the new display list is to appear).
  2451. */
  2452. if (dwNumSprites != 0)
  2453. {
  2454. /*
  2455. * Since the new display list is not empty, we will copy it
  2456. * into the sublist that contains the old display list for
  2457. * the same window, overwriting the old display list.
  2458. */
  2459. pSubList = createSpriteSubList(pMaster->pSubList[i],
  2460. *ppHalData, pPrimary);
  2461. if (pSubList == NULL)
  2462. {
  2463. /*
  2464. * An allocation error has occurred. (Note: The original
  2465. * value of pMaster->pSubList[i] has not been altered.)
  2466. */
  2467. return (DDERR_OUTOFMEMORY); // error -- out of memory
  2468. }
  2469. if (pSubList != pMaster->pSubList[i])
  2470. {
  2471. /*
  2472. * The createSpriteSubList call had to allocate a new
  2473. * sublist, so now we need to free the old one.
  2474. */
  2475. MemFree(pMaster->pSubList[i]);
  2476. pMaster->pSubList[i] = pSubList;
  2477. }
  2478. if (pMaster->dwNumSubLists == 1)
  2479. {
  2480. /*
  2481. * Only one window is displaying overlay sprites, so the
  2482. * new display list contains the same sprites as the master
  2483. * sprite list. Don't bother to construct a temp display
  2484. * list to contain all the sprites in the master sprite list.
  2485. */
  2486. return (DD_OK);
  2487. }
  2488. }
  2489. else
  2490. {
  2491. /*
  2492. * The new display list is empty. In this case, we just delete
  2493. * the sublist containing the old display list for the same window.
  2494. * This will leave a hole in the array of sublist pointers that we
  2495. * fill by moving all the higher members in the array down by one.
  2496. */
  2497. MemFree(pMaster->pSubList[i]); // free sublist
  2498. if (pMaster->dwNumSubLists == 1)
  2499. {
  2500. /*
  2501. * We have just deleted the only sublist, so the master sprite
  2502. * list is now empty. Free the master sprite list and return.
  2503. */
  2504. FreeMasterSpriteList(pdrv);
  2505. return (DD_OK);
  2506. }
  2507. // Delete the sublist from the master sprite list.
  2508. pMaster->pSubList[i] = NULL;
  2509. scrunchMasterSpriteList(pMaster);
  2510. }
  2511. }
  2512. /*
  2513. * We have finished updating the master sprite list. Mark all
  2514. * surface and clipper objects referenced in the master sprite list.
  2515. */
  2516. markSpriteObjects(pMaster);
  2517. /*
  2518. * The final step is to build a temporary display list that
  2519. * contains all the sprites in the master sprite list.
  2520. * The caller can then pass this display list to the driver.
  2521. */
  2522. pHalData = buildTempDisplayList(pMaster);
  2523. if (!pHalData)
  2524. {
  2525. return (DDERR_OUTOFMEMORY); // error -- out of memory
  2526. }
  2527. *ppHalData = pHalData; // update caller's display-list pointer
  2528. return (DD_OK);
  2529. } /* updateMasterSpriteList */
  2530. /*
  2531. * IDirectDrawSurface4::SetSpriteDisplayList -- API call
  2532. */
  2533. HRESULT DDAPI DD_Surface_SetSpriteDisplayList(
  2534. LPDIRECTDRAWSURFACE lpDDDestSurface,
  2535. LPDDSPRITE *lplpDDSprite,
  2536. DWORD dwCount,
  2537. DWORD dwSize,
  2538. LPDIRECTDRAWSURFACE lpDDTargetSurface,
  2539. DWORD dwFlags)
  2540. {
  2541. /*
  2542. * Fixed-size buffer for containing clip region data
  2543. */
  2544. struct
  2545. {
  2546. RGNDATAHEADER rdh;
  2547. RECT clipRect[6];
  2548. } myRgnBuffer;
  2549. DWORD rc;
  2550. DDHAL_SETSPRITEDISPLAYLISTDATA ssdld;
  2551. DDHAL_SETSPRITEDISPLAYLISTDATA *pHalData;
  2552. LPDDHAL_SETSPRITEDISPLAYLIST pfn;
  2553. LPDDRAWI_DDRAWSURFACE_INT this_int;
  2554. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  2555. LPDDRAWI_DDRAWSURFACE_GBL this;
  2556. LPDDRAWI_DDRAWSURFACE_INT targ_int;
  2557. LPDDRAWI_DDRAWSURFACE_LCL targ_lcl;
  2558. LPDDRAWI_DDRAWSURFACE_GBL targ;
  2559. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  2560. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  2561. LPDIRECTDRAWCLIPPER pClipper;
  2562. DWORD dwDDPFDestFlags;
  2563. SPRITE_CAPS caps;
  2564. LPRGNDATA pRgn;
  2565. RECT rcDestSurf;
  2566. DWORD ifirst;
  2567. int i;
  2568. DDASSERT(sizeof(DDRGBA)==sizeof(DWORD)); // we rely on this
  2569. DDASSERT(sizeof(DDSPRITEI)==sizeof(DDSPRITE)); // and this
  2570. ENTER_BOTH();
  2571. DPF(2,A,"ENTERAPI: DD_Surface_SetSpriteDisplayList");
  2572. /*
  2573. * Validate parameters
  2574. */
  2575. TRY
  2576. {
  2577. /*
  2578. * Validate destination surface.
  2579. */
  2580. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDDestSurface;
  2581. if (!VALID_DIRECTDRAWSURFACE_PTR(this_int))
  2582. {
  2583. DPF_ERR("Invalid dest surface");
  2584. LEAVE_BOTH();
  2585. return DDERR_INVALIDOBJECT;
  2586. }
  2587. this_lcl = this_int->lpLcl;
  2588. this = this_lcl->lpGbl;
  2589. /*
  2590. * Check for lost dest surface.
  2591. */
  2592. if (SURFACE_LOST(this_lcl))
  2593. {
  2594. DPF_ERR("Dest surface lost");
  2595. LEAVE_BOTH();
  2596. return DDERR_SURFACELOST;
  2597. }
  2598. #if 0
  2599. if (!dwCount)
  2600. {
  2601. lplpDDSprite = NULL; // necessary?
  2602. }
  2603. #endif
  2604. /*
  2605. * Perform initial validation of arguments.
  2606. */
  2607. if (dwCount && !lplpDDSprite || // if count nonzero, is ptr valid?
  2608. dwSize != sizeof(DDSPRITE) || // structure size ok?
  2609. dwFlags & ~DDSSDL_VALID || // any bogus flag bits set?
  2610. dwFlags & DDSSDL_PAGEFLIP && dwFlags & DDSSDL_BLTSPRITES || // no flip if blt
  2611. !(dwFlags & (DDSSDL_OVERLAYSPRITES | DDSSDL_BLTSPRITES)) || // neither flag set?
  2612. !(~dwFlags & (DDSSDL_OVERLAYSPRITES | DDSSDL_BLTSPRITES))) // both flags set?
  2613. {
  2614. DPF_ERR("Invalid arguments") ;
  2615. LEAVE_BOTH();
  2616. return DDERR_INVALIDPARAMS;
  2617. }
  2618. /*
  2619. * The dest surface is not allowed to be palette-indexed.
  2620. */
  2621. dwDDPFDestFlags = getPixelFormatFlags(this_lcl);
  2622. if (dwDDPFDestFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
  2623. DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8))
  2624. {
  2625. DPF_ERR( "Dest surface must not be palette-indexed" );
  2626. LEAVE_BOTH();
  2627. return DDERR_INVALIDSURFACETYPE;
  2628. }
  2629. pdrv = this->lpDD;
  2630. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  2631. /*
  2632. * Is device busy?
  2633. */
  2634. if (*(pdrv->lpwPDeviceFlags) & BUSY)
  2635. {
  2636. DPF(2, "BUSY");
  2637. LEAVE_BOTH();
  2638. return DDERR_SURFACEBUSY;
  2639. }
  2640. /*
  2641. * Determine whether the sprites are to be overlayed or blitted.
  2642. */
  2643. caps.bOverlay = !(dwFlags & DDSSDL_BLTSPRITES);
  2644. if (caps.bOverlay)
  2645. {
  2646. /*
  2647. * Dest surface for overlay sprite must be primary surface.
  2648. */
  2649. if (!(this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
  2650. {
  2651. DPF_ERR("Dest is not primary surface");
  2652. LEAVE_BOTH();
  2653. return DDERR_INVALIDPARAMS; // not primary surface
  2654. }
  2655. }
  2656. else
  2657. {
  2658. /*
  2659. * We do not allow blitting to an optimized surface.
  2660. */
  2661. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  2662. {
  2663. DPF_ERR("Can't blt optimized surfaces") ;
  2664. LEAVE_BOTH();
  2665. return DDERR_INVALIDPARAMS;
  2666. }
  2667. }
  2668. /*
  2669. * Will this call flip the primary surface?
  2670. */
  2671. if (!(dwFlags & DDSSDL_PAGEFLIP))
  2672. {
  2673. // no flip
  2674. targ_lcl = NULL;
  2675. }
  2676. else
  2677. {
  2678. LPDDRAWI_DDRAWSURFACE_INT next_int;
  2679. LPDDRAWI_DDRAWSURFACE_GBL_MORE targmore;
  2680. /*
  2681. * Yes, a page flip is requested. Make sure the destination
  2682. * surface is a front buffer and is flippable.
  2683. */
  2684. if (~this_lcl->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP))
  2685. {
  2686. DPF_ERR("Dest surface is not flippable");
  2687. LEAVE_BOTH();
  2688. return DDERR_NOTFLIPPABLE;
  2689. }
  2690. if (this->dwUsageCount > 0)
  2691. {
  2692. DPF_ERR("Can't flip locked surface");
  2693. LEAVE_BOTH();
  2694. return DDERR_SURFACEBUSY;
  2695. }
  2696. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE &&
  2697. pdrv->lpExclusiveOwner != pdrv_lcl)
  2698. {
  2699. DPF_ERR("Can't flip without exclusive access");
  2700. LEAVE_BOTH();
  2701. return DDERR_NOEXCLUSIVEMODE;
  2702. }
  2703. /*
  2704. * Get backbuffer surface attached to dest surface.
  2705. */
  2706. next_int = FindAttachedFlip(this_int);
  2707. if (next_int == NULL)
  2708. {
  2709. DPF_ERR("No backbuffer surface to flip to");
  2710. LEAVE_BOTH();
  2711. return DDERR_NOTFLIPPABLE;
  2712. }
  2713. /*
  2714. * Validate flip override surface, if one is specified.
  2715. */
  2716. targ_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDTargetSurface;
  2717. if (targ_int != NULL)
  2718. {
  2719. if (!VALID_DIRECTDRAWSURFACE_PTR(targ_int))
  2720. {
  2721. DPF_ERR("Invalid flip override surface");
  2722. LEAVE_BOTH();
  2723. return DDERR_INVALIDOBJECT;
  2724. }
  2725. targ_lcl = targ_int->lpLcl;
  2726. targ = targ_lcl->lpGbl;
  2727. /*
  2728. * Verify that the flip override surface is part of the destination
  2729. * surface's flipping chain. Note that next_int already points to
  2730. * the first buffer in the flipping chain.
  2731. */
  2732. while (next_int != this_int && next_int->lpLcl != targ_lcl)
  2733. {
  2734. next_int = FindAttachedFlip(this_int);
  2735. }
  2736. if (next_int == this_int)
  2737. {
  2738. // failed to find override surface in flipping chain
  2739. DPF_ERR("Flip override surface not part of flipping chain");
  2740. LEAVE_BOTH();
  2741. return DDERR_NOTFLIPPABLE;
  2742. }
  2743. }
  2744. else
  2745. {
  2746. /*
  2747. * No flip override surface is specified so use
  2748. * next backbuffer as target flip surface.
  2749. */
  2750. targ_int = next_int;
  2751. targ_lcl = targ_int->lpLcl;
  2752. targ = targ_lcl->lpGbl;
  2753. }
  2754. /*
  2755. * Make sure target flip surface is not lost or busy.
  2756. */
  2757. if (SURFACE_LOST(targ_lcl))
  2758. {
  2759. DPF_ERR("Can't flip -- backbuffer surface is lost");
  2760. LEAVE_BOTH();
  2761. return DDERR_SURFACELOST;
  2762. }
  2763. targmore = GET_LPDDRAWSURFACE_GBL_MORE(targ);
  2764. #if 0
  2765. if (targmore->hKernelSurface != 0)
  2766. {
  2767. DPF_ERR("Can't flip -- kernel mode is using surface");
  2768. LEAVE_BOTH();
  2769. return DDERR_SURFACEBUSY;
  2770. }
  2771. #endif
  2772. /*
  2773. * Make sure front and back buffers are in same memory.
  2774. */
  2775. if ((this_lcl->ddsCaps.dwCaps & (DDSCAPS_SYSTEMMEMORY |
  2776. DDSCAPS_VIDEOMEMORY)) !=
  2777. (targ_lcl->ddsCaps.dwCaps & (DDSCAPS_SYSTEMMEMORY |
  2778. DDSCAPS_VIDEOMEMORY)))
  2779. {
  2780. DPF_ERR("Can't flip between system/video memory surfaces");
  2781. LEAVE_BOTH();
  2782. return DDERR_INVALIDPARAMS;
  2783. }
  2784. } /* page flip */
  2785. /*
  2786. * Validate display list pointer lplpSpriteDisplayList.
  2787. */
  2788. if ( IsBadWritePtr((LPVOID)lplpDDSprite,
  2789. (UINT)dwCount*sizeof(LPDDSPRITE)) )
  2790. {
  2791. DPF_ERR("Bad pointer to sprite display list");
  2792. LEAVE_BOTH();
  2793. return DDERR_INVALIDPARAMS;
  2794. }
  2795. /*
  2796. * Initialize structure containing caps bits for sprites.
  2797. */
  2798. memset(&caps, 0, sizeof(SPRITE_CAPS));
  2799. caps.dwDestSurfCaps = this_lcl->ddsCaps.dwCaps; // dest surface caps
  2800. caps.bOverlay = dwFlags & DDSSDL_OVERLAYSPRITES; // TRUE if overlay sprites
  2801. /*
  2802. * Initialize status variables bNoHEL and bNoHAL. If bNoHEL is
  2803. * TRUE, this disqualifies the HEL from handling the driver call.
  2804. * If bNoHAL is TRUE, this disqualifies the hardware driver.
  2805. */
  2806. caps.bNoHEL = dwFlags & (DDSSDL_HARDWAREONLY | DDSSDL_OVERLAYSPRITES);
  2807. caps.bNoHAL = FALSE;
  2808. /*
  2809. * A driver that specifies nonlocal video-memory caps that differ
  2810. * from its local video-memory caps is automatically disqualified
  2811. * because the currently specified nonlocal vidmem caps do not
  2812. * include alpha, filter, or transform caps. Should we fix this?
  2813. */
  2814. if (caps.dwDestSurfCaps & DDSCAPS_NONLOCALVIDMEM &&
  2815. pdrv->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEMCAPS)
  2816. {
  2817. caps.bNoHAL = TRUE;
  2818. }
  2819. /*
  2820. * The assumption here is that the display list can be handled by
  2821. * the display hardware only if the dest surface and all the
  2822. * sprites are in video memory. If one or more surfaces are in
  2823. * system memory, emulation is the only option. We check the
  2824. * dest surface just below. Later, we'll check each sprite in
  2825. * the list. (Will this assumption still be valid in the future?)
  2826. */
  2827. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  2828. {
  2829. caps.bNoHAL = TRUE;
  2830. if (caps.bNoHEL)
  2831. {
  2832. DPF_ERR("Hardware can't show sprites on dest surface in system memory");
  2833. LEAVE_BOTH();
  2834. return DDERR_UNSUPPORTED;
  2835. }
  2836. }
  2837. DDASSERT(!(caps.bNoHEL && caps.bNoHAL));
  2838. /*
  2839. * Each iteration of the for-loop below validates the DDSPRITE
  2840. * structure for the next sprite in the display list.
  2841. */
  2842. for (i = 0; i < (int)dwCount; ++i)
  2843. {
  2844. HRESULT ddrval = validateSprite(lplpDDSprite[i],
  2845. pdrv,
  2846. this_lcl,
  2847. &caps,
  2848. dwDDPFDestFlags);
  2849. if (ddrval != DD_OK)
  2850. {
  2851. DPF(1, "...failed at sprite display list index = %d", i);
  2852. LEAVE_BOTH();
  2853. return ddrval;
  2854. }
  2855. }
  2856. DDASSERT(!(caps.bNoHEL && caps.bNoHAL));
  2857. /*
  2858. * Will the sprites be blitted? If so, they will alter dest surface.
  2859. */
  2860. if (dwFlags & DDSSDL_BLTSPRITES)
  2861. {
  2862. /*
  2863. * Remove any cached run-length-encoded data for the source surface.
  2864. */
  2865. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  2866. {
  2867. extern void FreeRleData(LPDDRAWI_DDRAWSURFACE_LCL); //in fasthel.c
  2868. FreeRleData(this_lcl);
  2869. }
  2870. BUMP_SURFACE_STAMP(this);
  2871. }
  2872. }
  2873. EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  2874. {
  2875. DPF_ERR("Exception encountered validating parameters");
  2876. LEAVE_BOTH();
  2877. return DDERR_INVALIDPARAMS;
  2878. }
  2879. /*
  2880. * Determine clipping region for destination surface.
  2881. */
  2882. // GetRgnData() call needs clipper and width/height of dest surface.
  2883. pClipper = (LPDIRECTDRAWCLIPPER)this_lcl->lpSurfMore->lpDDIClipper;
  2884. SetRect(&rcDestSurf, 0, 0, this->wWidth, this->wHeight);
  2885. // We'll pass in a region buffer for GetRgnData() to use.
  2886. myRgnBuffer.rdh.dwSize = sizeof(RGNDATAHEADER);
  2887. myRgnBuffer.rdh.nRgnSize = sizeof(myRgnBuffer) - sizeof(RGNDATAHEADER);
  2888. pRgn = GetRgnData(pClipper, &rcDestSurf, pdrv, (LPRGNDATA)&myRgnBuffer);
  2889. if (pRgn == NULL)
  2890. {
  2891. DPF_ERR("Can't alloc memory for clipping region");
  2892. LEAVE_BOTH();
  2893. return DDERR_OUTOFMEMORY;
  2894. }
  2895. /*
  2896. * Set up the HAL callback data for the sprite display list. This
  2897. * data structure will be passed directly to the driver either if
  2898. * the sprites are blitted or if no other window or clipping region
  2899. * contains overlay sprites. Otherwise, the driver will receive a
  2900. * temporary display list constructed by updateMasterSpriteList()
  2901. * that contains all the overlay sprites in the master sprite list.
  2902. */
  2903. //ssdld.SetSpriteDisplayList = pfn; // debug aid only -- no thunk
  2904. ssdld.lpDD = pdrv;
  2905. ssdld.lpDDSurface = this_lcl;
  2906. ssdld.lplpDDSprite = (LPDDSPRITEI*)lplpDDSprite;
  2907. ssdld.dwCount = dwCount;
  2908. ssdld.dwSize = dwSize;
  2909. ssdld.dwFlags = dwFlags & ~DDSSDL_WAIT;
  2910. ssdld.dwRectCnt = pRgn->rdh.nCount; // number of clip rects in region
  2911. ssdld.lpRect = (LPRECT)&pRgn->Buffer; // array of clip rects
  2912. ssdld.lpDDTargetSurface = targ_lcl;
  2913. /*
  2914. * The "master sprite list" keeps track of the overlay sprites in all
  2915. * the windows on a shared primary surface. (It also keeps track of
  2916. * the overlay sprites in all the clip regions of a full-screen app.)
  2917. * The master sprite list keeps a record of the active overlay sprites
  2918. * in each window (or clip region), as identified by its clipper object.
  2919. * Whenever any window updates its overlay sprites, the update is first
  2920. * recorded in the master sprite list. Next, a temporary display list
  2921. * containing all the overlay sprites in the master sprite list is passed
  2922. * to the driver. That way, the driver itself never has to keep track of
  2923. * more than one overlay-sprite display list at a time. The alternative
  2924. * would be for the driver itself to keep track of the overlay sprites
  2925. * for each window. We have chosen to keep the driver code simple by
  2926. * moving this bookkeeping into the DirectDraw runtime.
  2927. */
  2928. pHalData = &ssdld;
  2929. #if 0
  2930. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) // debug only !!
  2931. #else
  2932. if (dwFlags & DDSSDL_OVERLAYSPRITES)
  2933. #endif
  2934. {
  2935. /*
  2936. * The new display list specifies overlay sprites, so we
  2937. * need to update the master sprite list.
  2938. */
  2939. HRESULT ddrval = updateMasterSpriteList(lpDDDestSurface, &pHalData);
  2940. if (ddrval != DD_OK)
  2941. {
  2942. DPF_ERR( "Failed to update master sprite list" );
  2943. LEAVE_BOTH();
  2944. return ddrval;
  2945. }
  2946. }
  2947. TRY
  2948. {
  2949. /*
  2950. * Given the choice, we would prefer to use the hardware driver
  2951. * rather than software emulation to process this display list.
  2952. */
  2953. if (!caps.bNoHAL)
  2954. {
  2955. /*
  2956. * Yes, we can use the hardware. Get pointer to HAL callback.
  2957. */
  2958. pfn = pdrv_lcl->lpDDCB->HALDDMiscellaneous2.SetSpriteDisplayList;
  2959. if (!pfn)
  2960. {
  2961. caps.bNoHAL = TRUE; // no hardware driver is available
  2962. }
  2963. else
  2964. {
  2965. /*
  2966. * Tell the driver to begin processing the sprite display
  2967. * list. We may have to wait if the driver is still busy
  2968. * with a previously requested drawing operation.
  2969. */
  2970. do
  2971. {
  2972. DOHALCALL_NOWIN16(SetSpriteDisplayList, pfn, *pHalData, rc, 0); // caps.bNoHAL);
  2973. #ifdef WINNT
  2974. DDASSERT(! (rc == DDHAL_DRIVER_HANDLED && pHalData->ddRVal == DDERR_VISRGNCHANGED));
  2975. #endif
  2976. if (rc != DDHAL_DRIVER_HANDLED || pHalData->ddRVal != DDERR_WASSTILLDRAWING)
  2977. {
  2978. break; // driver's finished for better or worse...
  2979. }
  2980. DPF(4, "Waiting...");
  2981. } while (dwFlags & DDSSDL_WAIT);
  2982. if (rc != DDHAL_DRIVER_HANDLED || pHalData->ddRVal == DDERR_UNSUPPORTED)
  2983. {
  2984. caps.bNoHAL = TRUE; // hardware driver couldn't handle callback
  2985. }
  2986. else if (pHalData->ddRVal != DD_OK)
  2987. {
  2988. /*
  2989. * We want to just return with this error code instead
  2990. * of asking the HEL to process the display list.
  2991. */
  2992. caps.bNoHEL = TRUE; // disqualify HEL routine
  2993. }
  2994. }
  2995. }
  2996. /*
  2997. * If the hardware was unable to handle the display list, we may
  2998. * have to let the HEL process it for us.
  2999. */
  3000. if (caps.bNoHAL && !caps.bNoHEL)
  3001. {
  3002. /*
  3003. * Have to use HEL support. Get pointer to HEL emulation routine.
  3004. */
  3005. pfn = pdrv_lcl->lpDDCB->HELDDMiscellaneous2.SetSpriteDisplayList;
  3006. DDASSERT(pfn != NULL);
  3007. DOHALCALL_NOWIN16(SetSpriteDisplayList, pfn, *pHalData, rc, 0); // caps.bNoHAL);
  3008. }
  3009. }
  3010. EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  3011. {
  3012. DPF_ERR("Exception encountered during sprite rendering");
  3013. LEAVE_BOTH();
  3014. return DDERR_EXCEPTION;
  3015. }
  3016. /*
  3017. * If the previous GetRgnData() call had to dynamically alloc
  3018. * a region buffer, we need to remember to free it now.
  3019. */
  3020. if (pRgn != (LPRGNDATA)&myRgnBuffer)
  3021. {
  3022. MemFree(pRgn);
  3023. }
  3024. // Was there any driver support at all for this call?
  3025. if (caps.bNoHAL && caps.bNoHEL)
  3026. {
  3027. DPF_ERR("No driver support for this call");
  3028. LEAVE_BOTH();
  3029. return DDERR_UNSUPPORTED;
  3030. }
  3031. // Did driver handle callback?
  3032. if (rc != DDHAL_DRIVER_HANDLED)
  3033. {
  3034. DPF_ERR("Driver wouldn't handle callback");
  3035. LEAVE_BOTH();
  3036. return DDERR_UNSUPPORTED;
  3037. }
  3038. // Return now if driver handled callback without error.
  3039. if (pHalData->ddRVal == DD_OK || pHalData->ddRVal == DDERR_WASSTILLDRAWING)
  3040. {
  3041. LEAVE_BOTH();
  3042. return pHalData->ddRVal;
  3043. }
  3044. /*
  3045. * An error prevented the driver from showing all the sprites
  3046. * in the list. Which sprites did get shown?
  3047. */
  3048. if (pHalData->dwCount == dwCount)
  3049. {
  3050. // None of the sprites got shown
  3051. DPF(1, "Driver failed to show any sprites in display list");
  3052. LEAVE_BOTH();
  3053. return pHalData->ddRVal;
  3054. }
  3055. DPF(1, "Driver failed sprite at disp list index #%d", pHalData->dwCount);
  3056. DDASSERT(pHalData->dwCount < dwCount);
  3057. if (pHalData->dwFlags & DDSSDL_BACKTOFRONT)
  3058. {
  3059. // Driver showed sprites from (dwCount-1) down to (pHalData->dwCount+1).
  3060. ifirst = dwCount - 1; // driver started at last sprite in list
  3061. }
  3062. else
  3063. {
  3064. // Driver showed sprites from 0 up to (pHalData->dwCount-1).
  3065. ifirst = 0; // driver started at first sprite in list
  3066. }
  3067. DPF(1, "Driver started with sprite at disp list index #%d", ifirst);
  3068. LEAVE_BOTH();
  3069. return pHalData->ddRVal;
  3070. } /* DD_Surface_SetSpriteDisplayList */