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.

1082 lines
32 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: ddesurf.c
  6. * Content: DirectDraw EnumSurfaces support
  7. * History:
  8. * Date By Reason
  9. * ==== == ======
  10. * 25-jan-95 craige split out of ddraw.c, enhanced
  11. * 31-jan-95 craige and even more ongoing work...
  12. * 27-feb-95 craige new sync. macros
  13. * 19-mar-95 craige use HRESULTs
  14. * 01-apr-95 craige happy fun joy updated header file
  15. * 14-may-95 craige cleaned out obsolete junk
  16. * 24-may-95 kylej removed references to obsolete ZOrder variables
  17. * 07-jun-95 craige only allow enumeration of surfaces that belong to
  18. * the calling process
  19. * 12-jun-95 craige new process list stuff
  20. * 16-jun-95 craige removed fpVidMemOrig
  21. * 25-jun-95 craige one ddraw mutex
  22. * 26-jun-95 craige reorganized surface structure
  23. * 28-jun-95 craige ENTER_DDRAW at very start of fns
  24. * 30-jun-95 craige use DDRAWI_HASPIXELFORMAT/HASOVERLAYDATA
  25. * 01-jul-95 craige comment out compostion stuff
  26. * 03-jul-95 kylej rewrote the CANBECREATED iteration
  27. * 04-jul-95 craige YEEHAW: new driver struct; SEH
  28. * 19-jul-95 craige EnumSurfaces wasn't wrapping all parm validation
  29. * 31-jul-95 craige flag validation
  30. * 09-dec-95 colinmc added execute buffer support
  31. * 15-dec-95 colinmc fixed bug when filling surface description
  32. * 18-dec-95 colinmc additional caps bit checking in EnumSurfaces
  33. * 05-jan-95 kylej added interface structures
  34. * 17-feb-96 colinmc fixed problem limiting size of execute buffers
  35. * 24-mar-96 colinmc Bug 14321: not possible to specify back buffer and
  36. * mip-map count in a single call
  37. * 29-apr-96 colinmc Bug 20063: incorrect surface description returned
  38. * for z-buffer
  39. * 24-mar-97 jeffno Optimized Surfaces
  40. * 03-oct-97 jeffno DDSCAPS2 and DDSURFACEDESC2
  41. *
  42. ***************************************************************************/
  43. #include "ddrawpr.h"
  44. #include "dx8priv.h"
  45. #undef DPF_MODNAME
  46. #define DPF_MODNAME "GetSurfaceDesc"
  47. /*
  48. * FillDDSurfaceDesc
  49. *
  50. * NOTE: Special cases execute buffers as they have no pixel format or height.
  51. * You may wonder why this function is execute buffer aware when execute
  52. * buffers are skipped by EnumSurfaces. Well, FillDDSurfaceDesc is not simply
  53. * used when enumerating surfaces. It is also used when locking a surface so
  54. * it needs to fill in the correct stuff for execute buffers.
  55. */
  56. void FillEitherDDSurfaceDesc(
  57. LPDDRAWI_DDRAWSURFACE_LCL lpDDSurfaceX,
  58. LPDDSURFACEDESC2 lpDDSurfaceDesc )
  59. {
  60. LPDDRAWI_DDRAWSURFACE_GBL lpDDSurface;
  61. DDASSERT(lpDDSurfaceDesc);
  62. DDASSERT(lpDDSurfaceDesc->dwSize == sizeof(DDSURFACEDESC) || lpDDSurfaceDesc->dwSize == sizeof(DDSURFACEDESC2) );
  63. lpDDSurface = lpDDSurfaceX->lpGbl;
  64. lpDDSurfaceDesc->dwFlags = DDSD_CAPS;
  65. lpDDSurfaceDesc->ddsCaps.dwCaps = lpDDSurfaceX->ddsCaps.dwCaps;
  66. if (lpDDSurfaceDesc->dwSize >= sizeof (DDSURFACEDESC2))
  67. {
  68. lpDDSurfaceDesc->ddsCaps.ddsCapsEx = lpDDSurfaceX->lpSurfMore->ddsCapsEx;
  69. if (DDSD_TEXTURESTAGE & lpDDSurfaceX->lpSurfMore->dwTextureStage)
  70. {
  71. lpDDSurfaceDesc->dwFlags |= DDSD_TEXTURESTAGE;
  72. lpDDSurfaceDesc->dwTextureStage = (lpDDSurfaceX->lpSurfMore->dwTextureStage & ~DDSD_TEXTURESTAGE);
  73. }
  74. else
  75. lpDDSurfaceDesc->dwTextureStage = 0;
  76. lpDDSurfaceDesc->dwFVF = lpDDSurfaceX->lpSurfMore->dwFVF;
  77. if (lpDDSurfaceX->lpSurfMore->dwFVF)
  78. {
  79. lpDDSurfaceDesc->dwFlags |= DDSD_FVF;
  80. }
  81. }
  82. lpDDSurfaceDesc->lpSurface = (FLATPTR) NULL;
  83. if( lpDDSurfaceX->dwFlags & DDRAWISURF_HASCKEYDESTBLT )
  84. {
  85. lpDDSurfaceDesc->dwFlags |= DDSD_CKDESTBLT;
  86. lpDDSurfaceDesc->ddckCKDestBlt = lpDDSurfaceX->ddckCKDestBlt;
  87. }
  88. if( lpDDSurfaceX->dwFlags & DDRAWISURF_HASCKEYSRCBLT )
  89. {
  90. lpDDSurfaceDesc->dwFlags |= DDSD_CKSRCBLT;
  91. lpDDSurfaceDesc->ddckCKSrcBlt = lpDDSurfaceX->ddckCKSrcBlt;
  92. }
  93. if( lpDDSurfaceX->dwFlags & DDRAWISURF_FRONTBUFFER )
  94. {
  95. lpDDSurfaceDesc->dwFlags |= DDSD_BACKBUFFERCOUNT;
  96. lpDDSurfaceDesc->dwBackBufferCount = lpDDSurfaceX->dwBackBufferCount;
  97. }
  98. if( lpDDSurfaceX->ddsCaps.dwCaps & DDSCAPS_MIPMAP )
  99. {
  100. DDASSERT( lpDDSurfaceX->lpSurfMore != NULL );
  101. lpDDSurfaceDesc->dwFlags |= DDSD_MIPMAPCOUNT;
  102. lpDDSurfaceDesc->dwMipMapCount = lpDDSurfaceX->lpSurfMore->dwMipMapCount;
  103. }
  104. /*
  105. * Initialize the width, height and pitch of the surface description.
  106. */
  107. if( (lpDDSurfaceX->dwFlags & DDRAWISURF_HASPIXELFORMAT) &&
  108. (lpDDSurface->ddpfSurface.dwFlags & DDPF_FOURCC) )
  109. {
  110. lpDDSurfaceDesc->dwFlags |= ( DDSD_WIDTH | DDSD_HEIGHT );
  111. lpDDSurfaceDesc->dwWidth = (DWORD) lpDDSurface->wWidth;
  112. lpDDSurfaceDesc->dwHeight = (DWORD) lpDDSurface->wHeight;
  113. switch (lpDDSurface->ddpfSurface.dwFourCC)
  114. {
  115. case FOURCC_DXT1:
  116. case FOURCC_DXT2:
  117. case FOURCC_DXT3:
  118. case FOURCC_DXT4:
  119. case FOURCC_DXT5:
  120. /*
  121. * A compressed texture surface is allocated as an integral number
  122. * of blocks of 4x4 pixels. It has no pixel pitch as such, so we
  123. * return the linear size of the storage allocated for the surface.
  124. */
  125. lpDDSurfaceDesc->dwFlags |= DDSD_LINEARSIZE;
  126. lpDDSurfaceDesc->dwLinearSize = lpDDSurface->dwLinearSize;
  127. break;
  128. default:
  129. // This is what we've always done for FOURCCs, but is it correct?
  130. lpDDSurfaceDesc->dwFlags |= DDSD_PITCH;
  131. lpDDSurfaceDesc->lPitch = lpDDSurface->lPitch;
  132. break;
  133. }
  134. }
  135. else if( lpDDSurfaceX->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
  136. {
  137. /*
  138. * For execute buffer the height is not valid and both the width
  139. * and pitch are set to the linear size of the execute buffer.
  140. */
  141. lpDDSurfaceDesc->dwFlags |= ( DDSD_WIDTH | DDSD_PITCH );
  142. lpDDSurfaceDesc->dwWidth = lpDDSurface->dwLinearSize;
  143. lpDDSurfaceDesc->dwHeight = 0UL;
  144. lpDDSurfaceDesc->lPitch = (LONG) lpDDSurface->dwLinearSize;
  145. }
  146. #if 0 //Old code
  147. else if ( lpDDSurfaceX->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED )
  148. {
  149. lpDDSurfaceDesc->dwFlags |= ( DDSD_WIDTH | DDSD_HEIGHT );
  150. lpDDSurfaceDesc->dwWidth = (DWORD) lpDDSurface->wWidth;
  151. lpDDSurfaceDesc->dwHeight = (DWORD) lpDDSurface->wHeight;
  152. if ( !(lpDDSurfaceX->lpGbl->dwGlobalFlags & DDRAWISURFGBL_MEMFREE ) )
  153. {
  154. if (lpDDSurfaceX->lpGbl->dwGlobalFlags & DDRAWISURFGBL_LATEALLOCATELINEAR)
  155. {
  156. /*
  157. * Surface was allocated as a formless chunk.
  158. */
  159. lpDDSurfaceDesc->dwFlags |= DDSD_LINEARSIZE;
  160. lpDDSurfaceDesc->dwLinearSize = lpDDSurfaceX->lpGbl->dwLinearSize;
  161. }
  162. else
  163. {
  164. lpDDSurfaceDesc->dwFlags |= DDSD_PITCH;
  165. lpDDSurfaceDesc->lPitch = lpDDSurface->lPitch;
  166. }
  167. }
  168. }
  169. #endif //0
  170. else
  171. {
  172. lpDDSurfaceDesc->dwFlags |= ( DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH );
  173. lpDDSurfaceDesc->dwWidth = (DWORD) lpDDSurface->wWidth;
  174. lpDDSurfaceDesc->dwHeight = (DWORD) lpDDSurface->wHeight;
  175. lpDDSurfaceDesc->lPitch = lpDDSurface->lPitch;
  176. }
  177. /*
  178. * Initialize the pixel format.
  179. */
  180. if( lpDDSurfaceX->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
  181. {
  182. /*
  183. * Dummy pixel format for execute buffers.
  184. */
  185. memset(&lpDDSurfaceDesc->ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT));
  186. lpDDSurfaceDesc->ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
  187. if (lpDDSurfaceDesc->dwSize >= sizeof (DDSURFACEDESC2))
  188. {
  189. if (lpDDSurfaceX->lpSurfMore->dwFVF)
  190. {
  191. lpDDSurfaceDesc->dwFVF = lpDDSurfaceX->lpSurfMore->dwFVF;
  192. lpDDSurfaceDesc->dwFlags |= DDSD_FVF;
  193. }
  194. }
  195. }
  196. else if( lpDDSurfaceX->ddsCaps.dwCaps & DDSCAPS_ZBUFFER )
  197. {
  198. DDASSERT( lpDDSurfaceX->dwFlags & DDRAWISURF_HASPIXELFORMAT );
  199. DDASSERT( lpDDSurface->ddpfSurface.dwFlags & DDPF_ZBUFFER );
  200. DDASSERT( lpDDSurface->ddpfSurface.dwZBufferBitDepth !=0);
  201. // Note: DX5 copied the pixfmt from the surface but left the DDSD_PIXELFORMAT
  202. // flag off because CreateSurface couldn't handle ZBuffers with pxfmts
  203. // (because of Complex Surfaces). Now it can, so I'm turning it on for dx6 apps
  204. // copy info to SD pixfmt. This is what DX5 did too.
  205. lpDDSurfaceDesc->ddpfPixelFormat = lpDDSurface->ddpfSurface;
  206. // for pre-dx6 apps, fill in legacy SD ZBufferBitDepth field, but don't set pixfmt flag
  207. if (lpDDSurfaceDesc->dwSize == sizeof (DDSURFACEDESC)) {
  208. ((DDSURFACEDESC *)lpDDSurfaceDesc)->dwZBufferBitDepth=lpDDSurface->ddpfSurface.dwZBufferBitDepth;
  209. lpDDSurfaceDesc->dwFlags |= DDSD_ZBUFFERBITDEPTH;
  210. } else {
  211. // for dx6 apps, set PIXFMT flag, but not legacy SD ZBufferBitDepth field
  212. lpDDSurfaceDesc->dwFlags |= DDSD_PIXELFORMAT;
  213. }
  214. }
  215. else
  216. {
  217. lpDDSurfaceDesc->dwFlags |= DDSD_PIXELFORMAT;
  218. if( lpDDSurfaceX->dwFlags & DDRAWISURF_HASPIXELFORMAT )
  219. {
  220. lpDDSurfaceDesc->ddpfPixelFormat=lpDDSurface->ddpfSurface;
  221. }
  222. else
  223. {
  224. lpDDSurfaceDesc->ddpfPixelFormat=lpDDSurface->lpDD->vmiData.ddpfDisplay;
  225. }
  226. }
  227. if( lpDDSurfaceX->dwFlags & DDRAWISURF_HASOVERLAYDATA )
  228. {
  229. if( lpDDSurfaceX->dwFlags & DDRAWISURF_HASCKEYDESTOVERLAY )
  230. {
  231. lpDDSurfaceDesc->dwFlags |= DDSD_CKDESTOVERLAY;
  232. lpDDSurfaceDesc->ddckCKDestOverlay = lpDDSurfaceX->ddckCKDestOverlay;
  233. }
  234. if( lpDDSurfaceX->dwFlags & DDRAWISURF_HASCKEYSRCOVERLAY )
  235. {
  236. lpDDSurfaceDesc->dwFlags |= DDSD_CKSRCOVERLAY;
  237. lpDDSurfaceDesc->ddckCKSrcOverlay = lpDDSurfaceX->ddckCKSrcOverlay;
  238. }
  239. }
  240. else
  241. {
  242. lpDDSurfaceDesc->ddckCKDestOverlay.dwColorSpaceLowValue = 0;
  243. lpDDSurfaceDesc->ddckCKDestOverlay.dwColorSpaceHighValue = 0;
  244. lpDDSurfaceDesc->ddckCKSrcOverlay.dwColorSpaceLowValue = 0;
  245. lpDDSurfaceDesc->ddckCKSrcOverlay.dwColorSpaceHighValue = 0;
  246. }
  247. } /* FillEitherDDSurfaceDesc */
  248. void FillDDSurfaceDesc(
  249. LPDDRAWI_DDRAWSURFACE_LCL lpDDSurfaceX,
  250. LPDDSURFACEDESC lpDDSurfaceDesc )
  251. {
  252. memset(lpDDSurfaceDesc,0, sizeof( DDSURFACEDESC ));
  253. lpDDSurfaceDesc->dwSize = sizeof( DDSURFACEDESC );
  254. FillEitherDDSurfaceDesc(lpDDSurfaceX, (LPDDSURFACEDESC2) lpDDSurfaceDesc);
  255. }
  256. void FillDDSurfaceDesc2(
  257. LPDDRAWI_DDRAWSURFACE_LCL lpDDSurfaceX,
  258. LPDDSURFACEDESC2 lpDDSurfaceDesc )
  259. {
  260. memset(lpDDSurfaceDesc,0, sizeof( DDSURFACEDESC2 ));
  261. lpDDSurfaceDesc->dwSize = sizeof( DDSURFACEDESC2 );
  262. FillEitherDDSurfaceDesc(lpDDSurfaceX, lpDDSurfaceDesc);
  263. }
  264. /*
  265. * tryMatch
  266. *
  267. * tries to match a surface description with a surface object
  268. */
  269. static BOOL tryMatch( LPDDRAWI_DDRAWSURFACE_LCL curr_lcl, LPDDSURFACEDESC2 psd )
  270. {
  271. DWORD flags;
  272. BOOL no_match;
  273. LPDDRAWI_DDRAWSURFACE_GBL curr;
  274. curr = curr_lcl->lpGbl;
  275. flags = psd->dwFlags;
  276. no_match = FALSE;
  277. if( flags & DDSD_CAPS )
  278. {
  279. if (curr_lcl->ddsCaps.dwCaps != psd->ddsCaps.dwCaps)
  280. {
  281. return FALSE;
  282. }
  283. if( memcmp( &curr_lcl->lpSurfMore->ddsCapsEx, &psd->ddsCaps.ddsCapsEx, sizeof( DDSCAPSEX ) ) )
  284. {
  285. return FALSE;
  286. }
  287. }
  288. if( flags & DDSD_HEIGHT )
  289. {
  290. if( (DWORD) curr->wHeight != psd->dwHeight )
  291. {
  292. return FALSE;
  293. }
  294. }
  295. if( flags & DDSD_WIDTH )
  296. {
  297. if( (DWORD) curr->wWidth != psd->dwWidth )
  298. {
  299. return FALSE;
  300. }
  301. }
  302. if( flags & DDSD_LPSURFACE )
  303. {
  304. if( (LPVOID) curr->fpVidMem != psd->lpSurface )
  305. {
  306. return FALSE;
  307. }
  308. }
  309. if( flags & DDSD_CKDESTBLT )
  310. {
  311. if( memcmp( &curr_lcl->ddckCKDestBlt, &psd->ddckCKDestBlt, sizeof( DDCOLORKEY ) ) )
  312. {
  313. return FALSE;
  314. }
  315. }
  316. if( flags & DDSD_CKSRCBLT )
  317. {
  318. if( memcmp( &curr_lcl->ddckCKSrcBlt, &psd->ddckCKSrcBlt, sizeof( DDCOLORKEY ) ) )
  319. {
  320. return FALSE;
  321. }
  322. }
  323. if( flags & DDSD_BACKBUFFERCOUNT )
  324. {
  325. if( curr_lcl->dwBackBufferCount != psd->dwBackBufferCount )
  326. {
  327. return FALSE;
  328. }
  329. }
  330. if( flags & DDSD_MIPMAPCOUNT )
  331. {
  332. DDASSERT( curr_lcl->lpSurfMore != NULL );
  333. if( curr_lcl->lpSurfMore->dwMipMapCount != psd->dwMipMapCount )
  334. {
  335. return FALSE;
  336. }
  337. }
  338. /*
  339. * these fields are not always present
  340. */
  341. if( flags & DDSD_PIXELFORMAT )
  342. {
  343. if( curr_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT )
  344. {
  345. if( memcmp( &curr->ddpfSurface, &psd->ddpfPixelFormat, sizeof( DDPIXELFORMAT ) ) )
  346. {
  347. return FALSE;
  348. }
  349. }
  350. else
  351. {
  352. // surface description specifies pixel format but there is no
  353. // pixel format in the surface.
  354. return FALSE;
  355. }
  356. }
  357. if( curr_lcl->dwFlags & DDRAWISURF_HASOVERLAYDATA )
  358. {
  359. if( flags & DDSD_CKDESTOVERLAY )
  360. {
  361. if( memcmp( &curr_lcl->ddckCKDestOverlay, &psd->ddckCKDestOverlay, sizeof( DDCOLORKEY ) ) )
  362. {
  363. return FALSE;
  364. }
  365. }
  366. if( flags & DDSD_CKSRCOVERLAY )
  367. {
  368. if( memcmp( &curr_lcl->ddckCKSrcOverlay, &psd->ddckCKSrcOverlay, sizeof( DDCOLORKEY ) ) )
  369. {
  370. return FALSE;
  371. }
  372. }
  373. }
  374. else
  375. {
  376. if( ( flags & DDSD_CKDESTOVERLAY ) ||
  377. ( flags & DDSD_CKSRCOVERLAY ) )
  378. {
  379. return FALSE;
  380. }
  381. }
  382. return TRUE;
  383. } /* tryMatch */
  384. /*
  385. * What can we create? The popular question asked by the application.
  386. *
  387. * We will permute through the following items for each surface description:
  388. *
  389. * - FOURCC codes (dwFourCC)
  390. * - dimensions (dwHeight, dwWidth - based on modes avail only)
  391. * - RGB formats
  392. */
  393. #define ENUM_FOURCC 0x000000001
  394. #define ENUM_DIMENSIONS 0x000000002
  395. #define ENUM_RGB 0x000000004
  396. #undef DPF_MODNAME
  397. #define DPF_MODNAME "EnumSurfaces"
  398. /*
  399. * DD_EnumSurfaces
  400. */
  401. HRESULT DDAPI DD_EnumSurfaces(
  402. LPDIRECTDRAW lpDD,
  403. DWORD dwFlags,
  404. LPDDSURFACEDESC lpDDSD,
  405. LPVOID lpContext,
  406. LPDDENUMSURFACESCALLBACK lpEnumCallback )
  407. {
  408. DDSURFACEDESC2 ddsd2;
  409. DPF(2,A,"ENTERAPI: DD_EnumSurfaces");
  410. TRY
  411. {
  412. if( lpDDSD != NULL )
  413. {
  414. if( !VALID_DDSURFACEDESC_PTR( lpDDSD ) )
  415. {
  416. DPF_ERR( "Invalid surface description. Did you set the dwSize member to sizeof(DDSURFACEDESC)?" );
  417. DPF_APIRETURNS(DDERR_INVALIDPARAMS);
  418. return DDERR_INVALIDPARAMS;
  419. }
  420. ZeroMemory(&ddsd2,sizeof(ddsd2));
  421. memcpy(&ddsd2,lpDDSD,sizeof(*lpDDSD));
  422. }
  423. }
  424. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  425. {
  426. DPF_ERR( "Exception encountered validating parameters: Bad LPDDSURFACEDESC" );
  427. DPF_APIRETURNS(DDERR_INVALIDPARAMS);
  428. return DDERR_INVALIDPARAMS;
  429. }
  430. ddsd2.dwSize = sizeof(ddsd2);
  431. if (lpDDSD)
  432. return DD_EnumSurfaces4(lpDD,dwFlags, &ddsd2, lpContext, (LPDDENUMSURFACESCALLBACK2) lpEnumCallback);
  433. else
  434. return DD_EnumSurfaces4(lpDD,dwFlags, NULL, lpContext, (LPDDENUMSURFACESCALLBACK2) lpEnumCallback);
  435. }
  436. /*
  437. * DD_EnumSurfaces4
  438. */
  439. HRESULT DDAPI DD_EnumSurfaces4(
  440. LPDIRECTDRAW lpDD,
  441. DWORD dwFlags,
  442. LPDDSURFACEDESC2 lpDDSD,
  443. LPVOID lpContext,
  444. LPDDENUMSURFACESCALLBACK2 lpEnumCallback )
  445. {
  446. LPDDRAWI_DIRECTDRAW_INT this_int;
  447. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  448. LPDDRAWI_DIRECTDRAW_GBL this;
  449. LPDDRAWI_DDRAWSURFACE_INT curr_int;
  450. LPDDRAWI_DDRAWSURFACE_LCL curr_lcl;
  451. LPDDRAWI_DDRAWSURFACE_GBL curr;
  452. DWORD rc;
  453. BOOL needit;
  454. DDSURFACEDESC2 dsd;
  455. LPDDSURFACEDESC2 pdsd;
  456. DWORD flags;
  457. HRESULT ddrval;
  458. LPDIRECTDRAWSURFACE psurf;
  459. DWORD caps;
  460. DDSCAPSEX capsEx;
  461. ENTER_DDRAW();
  462. DPF(2,A,"ENTERAPI: DD_EnumSurfaces4");
  463. /*
  464. * validate parameters
  465. */
  466. TRY
  467. {
  468. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  469. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  470. {
  471. LEAVE_DDRAW();
  472. return DDERR_INVALIDOBJECT;
  473. }
  474. this_lcl = this_int->lpLcl;
  475. this = this_lcl->lpGbl;
  476. if( !VALIDEX_CODE_PTR( lpEnumCallback ) )
  477. {
  478. DPF_ERR( "Invalid callback routine" );
  479. LEAVE_DDRAW();
  480. return DDERR_INVALIDPARAMS;
  481. }
  482. if( dwFlags & ~DDENUMSURFACES_VALID )
  483. {
  484. DPF_ERR( "Invalid flags" );
  485. LEAVE_DDRAW();
  486. return DDERR_INVALIDPARAMS;
  487. }
  488. if( lpDDSD != NULL )
  489. {
  490. if( !VALID_DDSURFACEDESC2_PTR( lpDDSD ) )
  491. {
  492. DPF_ERR("Bad DDSURFACEDESC2 ptr.. did you set the dwSize?");
  493. LEAVE_DDRAW();
  494. return DDERR_INVALIDPARAMS;
  495. }
  496. caps = lpDDSD->ddsCaps.dwCaps;
  497. capsEx = lpDDSD->ddsCaps.ddsCapsEx;
  498. }
  499. /*
  500. * are flags OK?
  501. */
  502. if( (dwFlags & DDENUMSURFACES_ALL) )
  503. {
  504. if( dwFlags & (DDENUMSURFACES_MATCH | DDENUMSURFACES_NOMATCH) )
  505. {
  506. DPF_ERR( "can't match or nomatch DDENUMSURFACES_ALL" );
  507. LEAVE_DDRAW();
  508. return DDERR_INVALIDPARAMS;
  509. }
  510. }
  511. else
  512. {
  513. if( lpDDSD == NULL )
  514. {
  515. DPF_ERR( "No surface description" );
  516. LEAVE_DDRAW();
  517. return DDERR_INVALIDPARAMS;
  518. }
  519. if( (dwFlags & DDENUMSURFACES_MATCH) && (dwFlags & DDENUMSURFACES_NOMATCH) )
  520. {
  521. DPF_ERR( "can't match and nomatch together" );
  522. LEAVE_DDRAW();
  523. return DDERR_INVALIDPARAMS;
  524. }
  525. }
  526. if( dwFlags & DDENUMSURFACES_CANBECREATED )
  527. {
  528. if( !(dwFlags & DDENUMSURFACES_MATCH) ||
  529. (dwFlags & (DDENUMSURFACES_ALL | DDENUMSURFACES_NOMATCH) ) )
  530. {
  531. DPF_ERR( "can only use MATCH for CANBECREATED" );
  532. LEAVE_DDRAW();
  533. return DDERR_INVALIDPARAMS;
  534. }
  535. }
  536. if( lpDDSD != NULL )
  537. {
  538. /*
  539. * validate surface descriptions...
  540. */
  541. pdsd = lpDDSD;
  542. flags = pdsd->dwFlags;
  543. /*
  544. * read-only flags
  545. */
  546. if( flags & DDSD_LPSURFACE )
  547. {
  548. DPF_ERR( "Read-only flag specified in surface desc" );
  549. LEAVE_DDRAW();
  550. return DDERR_INVALIDPARAMS;
  551. }
  552. /*
  553. * Check for bogus caps bits.
  554. */
  555. if( caps & ~DDSCAPS_VALID )
  556. {
  557. DPF_ERR( "Invalid surface capability bits specified" );
  558. LEAVE_DDRAW();
  559. return DDERR_INVALIDPARAMS;
  560. }
  561. if( caps & DDSCAPS_OPTIMIZED )
  562. {
  563. DPF_ERR( "Optimized surfaces cannot be enumerated" );
  564. LEAVE_DDRAW();
  565. // ATTENTION: Should be an error, but we return DD_OK for
  566. // App-Compat reasons.
  567. return DD_OK;
  568. }
  569. if (capsEx.dwCaps2 & ~DDSCAPS2_VALID)
  570. {
  571. DPF_ERR( "invalid DDSURFACEDESC.DDSCAPS.dwSCaps2 specified" );
  572. LEAVE_DDRAW();
  573. return DDERR_INVALIDCAPS;
  574. }
  575. if (capsEx.dwCaps3 & ~DDSCAPS3_VALID)
  576. {
  577. DPF_ERR( "invalid DDSURFACEDESC.DDSCAPS.dwSCaps3 specified" );
  578. LEAVE_DDRAW();
  579. return DDERR_INVALIDCAPS;
  580. }
  581. if (capsEx.dwCaps4 & ~DDSCAPS4_VALID)
  582. {
  583. DPF_ERR( "invalid DDSURFACEDESC.DDSCAPS.dwSCaps4 specified" );
  584. LEAVE_DDRAW();
  585. return DDERR_INVALIDCAPS;
  586. }
  587. /*
  588. * You cannot enumerate over execute buffers (they are
  589. * not visible through the user level API).
  590. */
  591. if( caps & DDSCAPS_EXECUTEBUFFER )
  592. {
  593. DPF_ERR( "Invalid surface capability bit specified in surface desc" );
  594. LEAVE_DDRAW();
  595. return DDERR_INVALIDPARAMS;
  596. }
  597. /*
  598. * check height/width
  599. */
  600. if( ((flags & DDSD_HEIGHT) && !(flags & DDSD_WIDTH)) ||
  601. (!(flags & DDSD_HEIGHT) && (flags & DDSD_WIDTH)) )
  602. {
  603. DPF_ERR( "Specify both height & width in surface desc" );
  604. LEAVE_DDRAW();
  605. return DDERR_INVALIDPARAMS;
  606. }
  607. /*
  608. * certain things you can and can't look for during CANBECREATED
  609. */
  610. if( dwFlags & DDENUMSURFACES_CANBECREATED )
  611. {
  612. if( flags & (DDSD_CKDESTOVERLAY|
  613. DDSD_CKDESTBLT|
  614. DDSD_CKSRCOVERLAY|
  615. #ifdef COMPOSITION
  616. DDSD_COMPOSITIONORDER |
  617. #endif
  618. DDSD_CKSRCBLT ))
  619. {
  620. DPF_ERR( "Invalid flags specfied with CANBECREATED" );
  621. LEAVE_DDRAW();
  622. return DDERR_INVALIDPARAMS;
  623. }
  624. if( !(flags & DDSD_CAPS) )
  625. {
  626. flags |= DDSD_CAPS; // assume this...
  627. }
  628. }
  629. }
  630. }
  631. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  632. {
  633. DPF_ERR( "Exception encountered validating parameters" );
  634. LEAVE_DDRAW();
  635. return DDERR_INVALIDPARAMS;
  636. }
  637. /*
  638. * if this is a request for what can be created, do it.
  639. */
  640. if( dwFlags & DDENUMSURFACES_CANBECREATED )
  641. {
  642. BOOL do_rgb=FALSE;
  643. BOOL do_fourcc=FALSE;
  644. BOOL do_dim=FALSE;
  645. LPDDPIXELFORMAT pdpf;
  646. DWORD i;
  647. DWORD mode;
  648. DWORD dimension_cnt;
  649. struct _dim
  650. {
  651. DWORD dwWidth;
  652. DWORD dwHeight;
  653. } *dim;
  654. DWORD fourcc_cnt;
  655. struct _fourcc
  656. {
  657. DWORD fourcc;
  658. BOOL is_fourcc;
  659. BOOL is_rgb;
  660. DWORD dwBPP;
  661. DWORD dwRBitMask;
  662. DWORD dwGBitMask;
  663. DWORD dwBBitMask;
  664. DWORD dwAlphaBitMask;
  665. } *fourcc;
  666. BOOL done;
  667. BOOL is_primary;
  668. DWORD dwNumModes;
  669. LPDDHALMODEINFO lpModeInfo;
  670. #ifndef WIN95
  671. LPCTSTR pszDevice;
  672. DEVMODE dm;
  673. DWORD dwMaxModes;
  674. if (_stricmp(this->cDriverName, "DISPLAY"))
  675. {
  676. pszDevice = this->cDriverName;
  677. }
  678. else
  679. {
  680. pszDevice = NULL;
  681. }
  682. dwMaxModes = 256;
  683. lpModeInfo = MemAlloc(dwMaxModes * sizeof (*lpModeInfo));
  684. if (lpModeInfo == NULL)
  685. {
  686. LEAVE_DDRAW();
  687. return DDERR_OUTOFMEMORY;
  688. }
  689. ZeroMemory(&dm, sizeof dm);
  690. dm.dmSize = sizeof dm;
  691. for (mode = 0, dwNumModes = 0;
  692. EnumDisplaySettings(pszDevice, mode, &dm); mode++)
  693. {
  694. if (dm.dmBitsPerPel >= 8)
  695. {
  696. lpModeInfo[dwNumModes].dwWidth = (WORD)dm.dmPelsWidth;
  697. lpModeInfo[dwNumModes].dwHeight = (WORD)dm.dmPelsHeight;
  698. lpModeInfo[dwNumModes].dwBPP = (WORD)dm.dmBitsPerPel;
  699. lpModeInfo[dwNumModes].wRefreshRate = (WORD)dm.dmDisplayFrequency;
  700. switch (dm.dmBitsPerPel)
  701. {
  702. case 8:
  703. break;
  704. case 15:
  705. lpModeInfo[dwNumModes].dwRBitMask = 0x7C00;
  706. lpModeInfo[dwNumModes].dwGBitMask = 0x03E0;
  707. lpModeInfo[dwNumModes].dwBBitMask = 0x001F;
  708. lpModeInfo[dwNumModes].dwAlphaBitMask = 0;
  709. lpModeInfo[dwNumModes].dwBPP = 16;
  710. break;
  711. case 16:
  712. if (this->lpModeInfo->dwBPP == 16)
  713. {
  714. lpModeInfo[dwNumModes].dwRBitMask = this->lpModeInfo->dwRBitMask;
  715. lpModeInfo[dwNumModes].dwGBitMask = this->lpModeInfo->dwGBitMask;
  716. lpModeInfo[dwNumModes].dwBBitMask = this->lpModeInfo->dwBBitMask;
  717. lpModeInfo[dwNumModes].dwAlphaBitMask = this->lpModeInfo->dwAlphaBitMask;
  718. }
  719. else
  720. {
  721. lpModeInfo[dwNumModes].dwRBitMask = 0xF800;
  722. lpModeInfo[dwNumModes].dwGBitMask = 0x07E0;
  723. lpModeInfo[dwNumModes].dwBBitMask = 0x001F;
  724. lpModeInfo[dwNumModes].dwAlphaBitMask = 0;
  725. }
  726. break;
  727. case 24:
  728. case 32:
  729. lpModeInfo[dwNumModes].dwRBitMask = 0x00FF0000;
  730. lpModeInfo[dwNumModes].dwGBitMask = 0x0000FF00;
  731. lpModeInfo[dwNumModes].dwBBitMask = 0x000000FF;
  732. lpModeInfo[dwNumModes].dwAlphaBitMask = 0;
  733. break;
  734. }
  735. dwNumModes++;
  736. if (dwNumModes >= dwMaxModes)
  737. {
  738. LPDDHALMODEINFO p = lpModeInfo;
  739. dwMaxModes <<= 1;
  740. lpModeInfo = MemAlloc(dwMaxModes * sizeof (*lpModeInfo));
  741. if (lpModeInfo != NULL)
  742. {
  743. CopyMemory(lpModeInfo, p,
  744. (dwMaxModes >> 1) * sizeof(*lpModeInfo));
  745. }
  746. MemFree(p);
  747. if (lpModeInfo == NULL)
  748. {
  749. LEAVE_DDRAW();
  750. return DDERR_OUTOFMEMORY;
  751. }
  752. }
  753. }
  754. }
  755. #else
  756. dwNumModes = this->dwNumModes;
  757. lpModeInfo = this->lpModeInfo;
  758. #endif
  759. dim = MemAlloc( sizeof(*dim) * dwNumModes );
  760. fourcc = MemAlloc( sizeof(*fourcc) * (dwNumModes+this->dwNumFourCC) );
  761. if( ( lpDDSD->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) == 0 )
  762. {
  763. is_primary = FALSE;
  764. }
  765. else
  766. {
  767. is_primary = TRUE;
  768. }
  769. pdpf = &(lpDDSD->ddpfPixelFormat);
  770. if( lpDDSD->dwFlags & DDSD_PIXELFORMAT )
  771. {
  772. if( pdpf->dwFlags & DDPF_YUV )
  773. {
  774. do_fourcc = TRUE;
  775. }
  776. if( pdpf->dwFlags & DDPF_RGB )
  777. {
  778. do_rgb = TRUE;
  779. }
  780. }
  781. if( !(lpDDSD->dwFlags & DDSD_HEIGHT) && !is_primary )
  782. {
  783. do_dim = TRUE;
  784. }
  785. // set up dimension iteration
  786. dimension_cnt = 0;
  787. if( do_dim )
  788. {
  789. for(mode=0, dimension_cnt = 0; mode < dwNumModes; mode++)
  790. {
  791. for(i=0; i<dimension_cnt; i++)
  792. {
  793. if( ( lpModeInfo[mode].dwWidth == dim[i].dwWidth ) &&
  794. ( lpModeInfo[mode].dwHeight == dim[i].dwHeight ) )
  795. {
  796. break;
  797. }
  798. }
  799. if( i == dimension_cnt )
  800. {
  801. // we found a new height and width
  802. dim[dimension_cnt].dwWidth = lpModeInfo[mode].dwWidth;
  803. dim[dimension_cnt].dwHeight = lpModeInfo[mode].dwHeight;
  804. dimension_cnt++;
  805. }
  806. }
  807. }
  808. else
  809. {
  810. // No dimension iteration required.
  811. dimension_cnt = 1;
  812. dim[0].dwWidth = lpDDSD->dwWidth;
  813. dim[0].dwHeight = lpDDSD->dwHeight;
  814. }
  815. // set up fourcc/rgb iteration
  816. fourcc_cnt = 0;
  817. if( do_rgb )
  818. {
  819. for(mode=0; mode < dwNumModes; mode++)
  820. {
  821. for(i=0; i<fourcc_cnt; i++)
  822. {
  823. if( ( lpModeInfo[mode].dwBPP == (WORD)fourcc[i].dwBPP) &&
  824. ( lpModeInfo[mode].dwRBitMask = fourcc[i].dwRBitMask ) &&
  825. ( lpModeInfo[mode].dwGBitMask = fourcc[i].dwGBitMask ) &&
  826. ( lpModeInfo[mode].dwBBitMask = fourcc[i].dwBBitMask ) &&
  827. ( lpModeInfo[mode].dwAlphaBitMask = fourcc[i].dwAlphaBitMask ) )
  828. {
  829. break;
  830. }
  831. }
  832. if( i == fourcc_cnt )
  833. {
  834. // we found a rgb format
  835. fourcc[fourcc_cnt].dwBPP = (DWORD)lpModeInfo[mode].dwBPP;
  836. fourcc[fourcc_cnt].dwRBitMask = lpModeInfo[mode].dwRBitMask;
  837. fourcc[fourcc_cnt].dwGBitMask = lpModeInfo[mode].dwGBitMask;
  838. fourcc[fourcc_cnt].dwBBitMask = lpModeInfo[mode].dwBBitMask;
  839. fourcc[fourcc_cnt].dwAlphaBitMask = lpModeInfo[mode].dwAlphaBitMask;
  840. fourcc[fourcc_cnt].is_fourcc = FALSE;
  841. fourcc[fourcc_cnt].is_rgb = TRUE;
  842. fourcc_cnt++;
  843. }
  844. }
  845. }
  846. if( do_fourcc )
  847. {
  848. for(mode=0; mode < this->dwNumFourCC; mode++)
  849. {
  850. // store the new fourcc code
  851. fourcc[fourcc_cnt].fourcc = this->lpdwFourCC[ mode ];
  852. fourcc[fourcc_cnt].is_fourcc = TRUE;
  853. fourcc[fourcc_cnt].is_rgb = FALSE;
  854. fourcc_cnt++;
  855. }
  856. }
  857. if( fourcc_cnt == 0 )
  858. {
  859. fourcc_cnt = 1;
  860. fourcc[0].is_rgb = FALSE;
  861. fourcc[0].is_fourcc = FALSE;
  862. }
  863. // iterate through all the possibilities...
  864. if( !is_primary )
  865. {
  866. lpDDSD->dwFlags |= DDSD_HEIGHT;
  867. lpDDSD->dwFlags |= DDSD_WIDTH;
  868. }
  869. done = FALSE;
  870. for(mode=0; mode<dimension_cnt; mode++)
  871. {
  872. lpDDSD->dwWidth = dim[mode].dwWidth;
  873. lpDDSD->dwHeight = dim[mode].dwHeight;
  874. for(i=0; i<fourcc_cnt; i++)
  875. {
  876. if( fourcc[i].is_fourcc )
  877. {
  878. pdpf->dwFlags = DDPF_YUV;
  879. pdpf->dwFourCC = fourcc[i].fourcc;
  880. }
  881. else if( fourcc[i].is_rgb )
  882. {
  883. pdpf->dwFlags = DDPF_RGB;
  884. if( fourcc[i].dwBPP == 8 )
  885. {
  886. pdpf->dwFlags |= DDPF_PALETTEINDEXED8;
  887. }
  888. pdpf->dwRGBBitCount = fourcc[i].dwBPP;
  889. pdpf->dwRBitMask = fourcc[i].dwRBitMask;
  890. pdpf->dwGBitMask = fourcc[i].dwGBitMask;
  891. pdpf->dwBBitMask = fourcc[i].dwBBitMask;
  892. pdpf->dwRGBAlphaBitMask = fourcc[i].dwAlphaBitMask;
  893. }
  894. done = FALSE;
  895. // The surface desc is set up, now try to create the surface
  896. // This will create a surface4-vtabled surface if on IDirectDraw4 int or higher
  897. ddrval = InternalCreateSurface( this_lcl, lpDDSD, &psurf, this_int, NULL, 0 );
  898. if( ddrval == DD_OK )
  899. {
  900. FillDDSurfaceDesc2( ((LPDDRAWI_DDRAWSURFACE_INT)psurf)->lpLcl, &dsd );
  901. /*
  902. * Possible regression risk: make sure only DDSURFACEDESC size passed to
  903. * old interfaces
  904. */
  905. if (LOWERTHANDDRAW4(this_int))
  906. {
  907. dsd.dwSize = sizeof(DDSURFACEDESC);
  908. }
  909. rc = lpEnumCallback( NULL, &dsd, lpContext );
  910. InternalSurfaceRelease((LPDDRAWI_DDRAWSURFACE_INT)psurf, FALSE, FALSE );
  911. }
  912. if( done )
  913. {
  914. break;
  915. }
  916. }
  917. if( done )
  918. {
  919. break;
  920. }
  921. }
  922. LEAVE_DDRAW();
  923. MemFree( dim );
  924. MemFree( fourcc );
  925. #ifndef WIN95
  926. MemFree( lpModeInfo );
  927. #endif
  928. return DD_OK;
  929. }
  930. /*
  931. * if it isn't a request for what exists already, then FAIL
  932. */
  933. if( !(dwFlags & DDENUMSURFACES_DOESEXIST) )
  934. {
  935. DPF(0,"Invalid Flags. You must specify at least DDENUMSURFACES_DOESEXIST or DDENUMSURFACES_CANBECREATED");
  936. LEAVE_DDRAW();
  937. return DDERR_INVALIDPARAMS;
  938. }
  939. /*
  940. * run through all surfaces, seeing which ones we need
  941. */
  942. curr_int = this->dsList;
  943. while( curr_int != NULL )
  944. {
  945. curr_lcl = curr_int->lpLcl;
  946. curr = curr_lcl->lpGbl;
  947. // only enumerate the surface if it belongs to the calling local object
  948. if( curr_lcl->lpSurfMore->lpDD_lcl == this_lcl )
  949. {
  950. needit = FALSE;
  951. /*
  952. * Execute buffers are invisible to the user level API so
  953. * ensure we never show the user one of those.
  954. */
  955. if( !( curr_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER ) )
  956. {
  957. if( dwFlags & DDENUMSURFACES_ALL )
  958. {
  959. needit = TRUE;
  960. }
  961. else
  962. {
  963. needit = tryMatch( curr_lcl, lpDDSD );
  964. if( dwFlags & DDENUMSURFACES_NOMATCH )
  965. {
  966. needit = !needit;
  967. }
  968. }
  969. }
  970. if( needit )
  971. {
  972. LPDIRECTDRAWSURFACE4 returnedInt = (LPDIRECTDRAWSURFACE4) curr_int;
  973. FillDDSurfaceDesc2( curr_lcl, &dsd );
  974. if (LOWERTHANDDRAW4(this_int))
  975. {
  976. DD_Surface_QueryInterface( (LPDIRECTDRAWSURFACE) curr_int , &IID_IDirectDrawSurface, (void**) & returnedInt);
  977. dsd.dwSize = sizeof(DDSURFACEDESC);
  978. }
  979. else if (this_int->lpVtbl == &dd4Callbacks)
  980. {
  981. DD_Surface_QueryInterface( (LPDIRECTDRAWSURFACE) curr_int , &IID_IDirectDrawSurface4, (void**) & returnedInt);
  982. }
  983. else
  984. {
  985. DD_Surface_QueryInterface( (LPDIRECTDRAWSURFACE) curr_int , &IID_IDirectDrawSurface7, (void**) & returnedInt);
  986. }
  987. rc = lpEnumCallback( returnedInt, &dsd, lpContext );
  988. if( rc == 0 )
  989. {
  990. break;
  991. }
  992. }
  993. }
  994. curr_int = curr_int->lpLink;
  995. }
  996. LEAVE_DDRAW();
  997. return DD_OK;
  998. } /* DD_EnumSurfaces */