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.

1960 lines
58 KiB

  1. //-------------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1994-1997 Microsoft Corporation. All Rights Reserved.
  4. //
  5. // File: ddoptsur.c
  6. // Content: DirectDraw Optimized Surface support
  7. // History:
  8. // Date By Reason
  9. // ==== == ======
  10. // 2-nov-97 anankan Original implementation
  11. //
  12. //-------------------------------------------------------------------------------
  13. #include "ddrawpr.h"
  14. //-------------------------------------------------------------------------------
  15. //
  16. // IsRecognizedOptSurfaceGUID
  17. //
  18. // Checks to see if the GUID passed is recognized by the driver.
  19. // This is done by looking at the list maintained in LPDDRAWI_DIRECTDRAW_GBL
  20. //
  21. //-------------------------------------------------------------------------------
  22. BOOL
  23. IsRecognizedOptSurfaceGUID(
  24. LPDDRAWI_DIRECTDRAW_GBL this,
  25. LPGUID pGuid)
  26. {
  27. int i;
  28. LPDDOPTSURFACEINFO pOptSurfInfo;
  29. pOptSurfInfo = this->lpDDOptSurfaceInfo;
  30. for (i = 0; i < (int)pOptSurfInfo->dwNumGuids; i++)
  31. {
  32. if (IsEqualIID(pGuid, &(pOptSurfInfo->lpGuidArray[i])))
  33. return TRUE;
  34. }
  35. return FALSE;
  36. }
  37. //-------------------------------------------------------------------------------
  38. //
  39. // ValidateSurfDesc
  40. //
  41. // Fill in correct surf desc to be passed to the driver
  42. //
  43. //-------------------------------------------------------------------------------
  44. HRESULT
  45. ValidateSurfDesc(
  46. LPDDSURFACEDESC2 pOrigSurfDesc
  47. )
  48. {
  49. DWORD caps = pOrigSurfDesc->ddsCaps.dwCaps;
  50. //
  51. // check for no caps at all!
  52. //
  53. if( caps == 0 )
  54. {
  55. DPF_ERR( "no caps specified" );
  56. return DDERR_INVALIDCAPS;
  57. }
  58. //
  59. // check for bogus caps.
  60. //
  61. if( caps & ~DDSCAPS_VALID )
  62. {
  63. DPF_ERR( "Create surface: invalid caps specified" );
  64. return DDERR_INVALIDCAPS;
  65. }
  66. //
  67. // Anything other than a texture is not allowed
  68. // ATTENTION: some more flags need to be checked
  69. //
  70. if(caps & (DDSCAPS_EXECUTEBUFFER |
  71. DDSCAPS_BACKBUFFER |
  72. DDSCAPS_FRONTBUFFER |
  73. DDSCAPS_OFFSCREENPLAIN |
  74. DDSCAPS_PRIMARYSURFACE |
  75. DDSCAPS_PRIMARYSURFACELEFT |
  76. DDSCAPS_VIDEOPORT |
  77. DDSCAPS_ZBUFFER |
  78. DDSCAPS_OWNDC |
  79. DDSCAPS_OVERLAY |
  80. DDSCAPS_3DDEVICE |
  81. DDSCAPS_ALLOCONLOAD)
  82. )
  83. {
  84. DPF_ERR( "currently only textures can be optimized" );
  85. return DDERR_INVALIDCAPS;
  86. }
  87. if( !(caps & DDSCAPS_TEXTURE) )
  88. {
  89. DPF_ERR( "DDSCAPS_TEXTURE needs to be set" );
  90. return DDERR_INVALIDCAPS;
  91. }
  92. // Pixelformat not specified ?
  93. if (!(pOrigSurfDesc->dwFlags & DDSD_PIXELFORMAT))
  94. {
  95. DPF_ERR( "Pixel format needs to be set" );
  96. return DDERR_INVALIDCAPS;
  97. }
  98. return DD_OK;
  99. }
  100. //-------------------------------------------------------------------------------
  101. //
  102. // DD_CanOptimizeSurface
  103. //
  104. // Check to see if a surface given the description be optimized.
  105. //
  106. //-------------------------------------------------------------------------------
  107. HRESULT
  108. EXTERN_DDAPI
  109. DD_CanOptimizeSurface(
  110. LPDIRECTDRAW pDD,
  111. LPDDSURFACEDESC2 pDDSurfDesc,
  112. LPDDOPTSURFACEDESC pDDOptSurfDesc,
  113. BOOL *bTrue
  114. )
  115. {
  116. LPDDRAWI_DIRECTDRAW_INT this_int;
  117. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  118. LPDDRAWI_DIRECTDRAW_GBL this;
  119. DDHAL_CANOPTIMIZESURFACEDATA ddhal_cosd;
  120. LPDDOPTSURFACEINFO pDDOptSurfInfo = NULL;
  121. HRESULT ddrval = DD_OK;
  122. ENTER_DDRAW();
  123. DPF(2,A,"ENTERAPI: DD_CanOptimizeSurface");
  124. //
  125. // Setup DPF stuff
  126. //
  127. DPF_ENTERAPI(pDD);
  128. //
  129. // Parameter validation
  130. //
  131. TRY
  132. {
  133. this_int = (LPDDRAWI_DIRECTDRAW_INT) pDD;
  134. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  135. {
  136. DPF_ERR( "Invalid driver object passed" );
  137. DPF_APIRETURNS(DDERR_INVALIDOBJECT);
  138. LEAVE_DDRAW();
  139. return DDERR_INVALIDOBJECT;
  140. }
  141. this_lcl = this_int->lpLcl;
  142. this = this_lcl->lpGbl;
  143. if( this->dwModeIndex == DDUNSUPPORTEDMODE )
  144. {
  145. DPF_ERR( "Driver is in an unsupported mode" );
  146. LEAVE_DDRAW();
  147. DPF_APIRETURNS(DDERR_UNSUPPORTEDMODE);
  148. return DDERR_UNSUPPORTEDMODE;
  149. }
  150. if( !VALID_DDSURFACEDESC2_PTR( pDDSurfDesc ) )
  151. {
  152. DPF_ERR( "Invalid surface description. Did you set the dwSize member?" );
  153. LEAVE_DDRAW();
  154. DPF_APIRETURNS(DDERR_INVALIDPARAMS);
  155. return DDERR_INVALIDPARAMS;
  156. }
  157. if( !VALID_DDOPTSURFACEDESC_PTR( pDDOptSurfDesc ) )
  158. {
  159. DPF_ERR( "Invalid optimized surface description. Did you set the dwSize member?" );
  160. LEAVE_DDRAW();
  161. DPF_APIRETURNS(DDERR_INVALIDPARAMS);
  162. return DDERR_INVALIDPARAMS;
  163. }
  164. if( !VALID_PTR( bTrue, sizeof (*bTrue)) )
  165. {
  166. DPF_ERR( "Invalid Boolean pointer" );
  167. LEAVE_DDRAW();
  168. return DDERR_INVALIDPARAMS;
  169. }
  170. *bTrue = TRUE;
  171. }
  172. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  173. {
  174. DPF_ERR( "Exception encountered validating parameters" );
  175. LEAVE_DDRAW();
  176. DPF_APIRETURNS(DDERR_INVALIDPARAMS);
  177. return DDERR_INVALIDPARAMS;
  178. }
  179. //
  180. // Quit with error if:
  181. // 1) No hardware
  182. // 2) Hardware doesnt support optimized surfaces
  183. // 3) pSurfDesc does not provide useful information
  184. // 4) Is the guid one of the recognized ones
  185. // 5) The driver fails for some reason
  186. //
  187. // 1)
  188. if( this->dwFlags & DDRAWI_NOHARDWARE )
  189. {
  190. DPF_ERR ("No hardware present");
  191. LEAVE_DDRAW();
  192. return DDERR_NODIRECTDRAWHW;
  193. }
  194. // 2)
  195. if ((0 == this->lpDDOptSurfaceInfo) ||
  196. !(this->ddCaps.dwCaps2 & DDCAPS2_OPTIMIZEDSURFACES))
  197. {
  198. DPF_ERR ("Optimized surfaces not supported");
  199. LEAVE_DDRAW();
  200. return DDERR_NOOPTSURFACESUPPORT;
  201. }
  202. // 3)
  203. ddrval = ValidateSurfDesc (pDDSurfDesc);
  204. if (ddrval != DD_OK)
  205. {
  206. DPF_ERR ("Invalid surface description");
  207. LEAVE_DDRAW();
  208. return ddrval;
  209. }
  210. // 4)
  211. if (!IsRecognizedOptSurfaceGUID (this, &(pDDOptSurfDesc->guid)))
  212. {
  213. DPF_ERR( "Not a recognized GUID" );
  214. LEAVE_DDRAW();
  215. return DDERR_UNRECOGNIZEDGUID;
  216. }
  217. // Call the driver
  218. ZeroMemory (&ddhal_cosd, sizeof (ddhal_cosd));
  219. ddhal_cosd.lpDD = this_lcl;
  220. ddhal_cosd.ddOptSurfDesc = *pDDOptSurfDesc;
  221. ddhal_cosd.ddSurfaceDesc = *pDDSurfDesc;
  222. // Make the HAL call
  223. pDDOptSurfInfo = this->lpDDOptSurfaceInfo;
  224. DOHALCALL(CanOptimizeSurface, pDDOptSurfInfo->CanOptimizeSurface, ddhal_cosd, ddrval, FALSE );
  225. if (ddrval != DD_OK)
  226. {
  227. DPF_ERR ("LoadUnOptSurface failed in the driver");
  228. LEAVE_DDRAW();
  229. return ddrval;
  230. }
  231. if (ddhal_cosd.bCanOptimize != 0)
  232. {
  233. *bTrue = TRUE;
  234. }
  235. else
  236. {
  237. *bTrue = FALSE;
  238. }
  239. LEAVE_DDRAW();
  240. return DD_OK;
  241. }
  242. //-------------------------------------------------------------------------------
  243. //
  244. // CreateAndLinkUninitializedSurface
  245. //
  246. // Create a surface, and link it into the chain.
  247. // We create a single surface place-holder here, real work is done at the
  248. // Load/Copy time.
  249. //
  250. //-------------------------------------------------------------------------------
  251. HRESULT
  252. CreateAndLinkUnintializedSurface(
  253. LPDDRAWI_DIRECTDRAW_LCL this_lcl,
  254. LPDDRAWI_DIRECTDRAW_INT this_int,
  255. LPDIRECTDRAWSURFACE FAR *ppDDSurface
  256. )
  257. {
  258. LPDDRAWI_DIRECTDRAW_GBL this;
  259. LPDDRAWI_DDRAWSURFACE_INT pSurf_int;
  260. LPDDRAWI_DDRAWSURFACE_LCL pSurf_lcl;
  261. LPDDRAWI_DDRAWSURFACE_GBL pSurf;
  262. LPVOID *ppSurf_gbl_more;
  263. DDSCAPS caps;
  264. DDPIXELFORMAT ddpf;
  265. int surf_size;
  266. int surf_size_lcl;
  267. int surf_size_lcl_more;
  268. #ifdef WIN95
  269. DWORD ptr16;
  270. #endif
  271. HRESULT ddrval = DD_OK;
  272. // DDraw-global
  273. this = this_lcl->lpGbl;
  274. #ifdef WINNT
  275. // Update DDraw handle in driver GBL object.
  276. this->hDD = this_lcl->hDD;
  277. #endif //WINNT
  278. //
  279. // Zero the caps
  280. //
  281. ZeroMemory (&caps, sizeof (DDCAPS));
  282. //
  283. // PixelFormat: Mark it as an empty surface
  284. //
  285. ZeroMemory (&ddpf, sizeof (ddpf));
  286. ddpf.dwSize = sizeof (ddpf);
  287. ddpf.dwFlags = DDPF_EMPTYSURFACE;
  288. //
  289. // Allocate the internal Surface structure and initialize the fields
  290. //
  291. //
  292. // fail requests for non-local video memory allocations if the driver does
  293. // not support non-local video memory.
  294. //
  295. // NOTE: Should we really do this or just let the allocation fail from
  296. // naturalcauses?
  297. //
  298. // ALSO NOTE: Don't have to worry about emulation as no emulated surface
  299. // should
  300. // ever get this far with DDSCAPS_NONLOCALVIDMEM set.
  301. //
  302. // ALSO ALSO NOTE: Should we also fail DDSCAPS_LOCALVIDMEM if the driver does
  303. // not support DDSCAPS_NONLOCALVIDMEM. My feeling is that we should allow.
  304. // DDSCAPS_LOCALVIDMEM is legal with a non AGP driver - redundant but legal.
  305. //
  306. //
  307. // allocate the surface struct, allowing for overlay and pixel
  308. // format data
  309. //
  310. // NOTE: This single allocation can allocate space for local surface
  311. // structure (DDRAWI_DDRAWSURFACE_LCL), the additional local surface
  312. // structure (DDRAWI_DDRAWSURFACE_MORE) and the global surface structure
  313. // (DDRAWI_DDRAWSURFACE_GBL). And now the global surface more
  314. // structure too (DDRAWI_DDRAWSURFACE_GBL_MORE). As both the local and
  315. // global objects can be variable sized this can get pretty complex.
  316. // Additionally, we have 4 bytes just before the surface_gbl that points to
  317. // the surface_gbl_more.
  318. //
  319. // CAVEAT: All future surfaces that share this global all point to this
  320. // allocation. The last surface's release has to free it. During
  321. // InternalSurfaceRelease (in ddsiunk.c) a calculation is made to determine
  322. // the start of this memory allocation. If the surface being released is
  323. // the first one, then freeing "this_lcl" will free the whole thing. If
  324. // not, then "this_lcl->lpGbl - (Surface_lcl + surface_more + more_ptr)"
  325. // is computed. Keep this layout in synch with code in ddsiunk.c.
  326. //
  327. // The layout of the various objects in the allocation is as follows:
  328. //
  329. // +-----------------+---------------+----+------------+-----------------+
  330. // | SURFACE_LCL | SURFACE_MORE |More| SURFACE_GBL| SURFACE_GBL_MORE|
  331. // | (variable) | |Ptr | (variable) | |
  332. // +-----------------+---------------+----+------------+-----------------+
  333. // <- surf_size_lcl -> | |
  334. // <- surf_size_lcl_more ------------> |
  335. // <- surf_size --------------------------------------------------------->
  336. //
  337. //
  338. // ATTENTION: Currently ignores to account for the overlays
  339. #if 0
  340. surf_size_lcl = sizeof( DDRAWI_DDRAWSURFACE_LCL );
  341. #endif
  342. surf_size_lcl = offsetof( DDRAWI_DDRAWSURFACE_LCL, ddckCKSrcOverlay );
  343. surf_size_lcl_more = surf_size_lcl + sizeof( DDRAWI_DDRAWSURFACE_MORE );
  344. // Assume that the pixelformat is present for allocating the GBL
  345. surf_size = surf_size_lcl_more + sizeof( DDRAWI_DDRAWSURFACE_GBL );
  346. #if 0
  347. surf_size = surf_size_lcl_more + offsetof( DDRAWI_DDRAWSURFACE_GBL,
  348. ddpfSurface );
  349. #endif
  350. // Need to allocate a pointer just before the SURFACE_GBL to
  351. // point to the beginning of the GBL_MORE.
  352. surf_size += sizeof( LPDDRAWI_DDRAWSURFACE_GBL_MORE );
  353. // Need to allocate a SURFACE_GBL_MORE too
  354. surf_size += sizeof( DDRAWI_DDRAWSURFACE_GBL_MORE );
  355. DPF( 8, "Allocating struct (%ld)", surf_size );
  356. #ifdef WIN95
  357. pSurf_lcl = (LPDDRAWI_DDRAWSURFACE_LCL) MemAlloc16 (surf_size, &ptr16);
  358. #else
  359. pSurf_lcl = (LPDDRAWI_DDRAWSURFACE_LCL) MemAlloc (surf_size);
  360. #endif
  361. if (pSurf_lcl == NULL)
  362. {
  363. DPF_ERR ("Failed to allocate internal surface structure");
  364. ddrval = DDERR_OUTOFMEMORY;
  365. goto error_exit_create_link;
  366. }
  367. // Initialize SURFACE_GBL pointer
  368. // skipping 4 bytes for a pointer to the GBL_MORE
  369. ZeroMemory (pSurf_lcl, surf_size);
  370. pSurf_lcl->lpGbl = (LPVOID) (((LPSTR) pSurf_lcl) + surf_size_lcl_more +
  371. sizeof (LPVOID));
  372. // Initialize GBL_MORE pointer
  373. ppSurf_gbl_more = (LPVOID *)((LPBYTE)pSurf_lcl->lpGbl - sizeof (LPVOID));
  374. *ppSurf_gbl_more = (LPVOID) ((LPBYTE)pSurf_lcl + surf_size
  375. - sizeof (DDRAWI_DDRAWSURFACE_GBL_MORE));
  376. // Sanity Check
  377. DDASSERT( *ppSurf_gbl_more ==
  378. (LPVOID) GET_LPDDRAWSURFACE_GBL_MORE(pSurf_lcl->lpGbl));
  379. //
  380. // 1) Initialize GBL_MORE structure
  381. //
  382. GET_LPDDRAWSURFACE_GBL_MORE(pSurf_lcl->lpGbl)->dwSize =
  383. sizeof( DDRAWI_DDRAWSURFACE_GBL_MORE );
  384. // Init the contents stamp to 0 means the surface's contents can
  385. // change at any time.
  386. GET_LPDDRAWSURFACE_GBL_MORE( pSurf_lcl->lpGbl )->dwContentsStamp = 0;
  387. //
  388. // 2) Initialize DDRAWI_DDRAWSURFACE_GBL structure
  389. //
  390. pSurf = pSurf_lcl->lpGbl;
  391. pSurf->ddpfSurface = ddpf;
  392. pSurf->lpDD = this;
  393. //
  394. // 3) Allocate and initialize DDRAWI_DDRAWSURFACE_INT structure
  395. //
  396. pSurf_int = (LPDDRAWI_DDRAWSURFACE_INT)
  397. MemAlloc( sizeof(DDRAWI_DDRAWSURFACE_INT));
  398. if( NULL == pSurf_int )
  399. {
  400. DPF_ERR ("Failed allocation of DDRAWI_DDRAWSURFACE_INT");
  401. ddrval = DDERR_OUTOFMEMORY;
  402. goto error_exit_create_link;
  403. }
  404. // fill surface specific stuff
  405. ZeroMemory (pSurf_int, sizeof(DDRAWI_DDRAWSURFACE_INT));
  406. pSurf_int->lpLcl = pSurf_lcl;
  407. pSurf_int->lpVtbl = NULL;
  408. //
  409. // 4) Initialize DDRAWI_DDRAWSURFACE_LCL structure
  410. //
  411. pSurf_lcl->dwLocalRefCnt = OBJECT_ISROOT;
  412. pSurf_lcl->dwProcessId = GetCurrentProcessId();
  413. #ifdef WIN95
  414. pSurf_lcl->dwModeCreatedIn = this->dwModeIndex;
  415. #else
  416. pSurf_lcl->dmiCreated = this->dmiCurrent;
  417. #endif
  418. pSurf_lcl->dwBackBufferCount = 0;
  419. // Flag it as an:
  420. // 1) empty surface
  421. // 2) Front surface
  422. // 3) Has a pixelformat
  423. pSurf_lcl->dwFlags = (DDRAWISURF_EMPTYSURFACE |
  424. DDRAWISURF_FRONTBUFFER |
  425. DDRAWISURF_HASPIXELFORMAT);
  426. //
  427. // 5) Initialize DDRAWI_DDRAWSURFACE_MORE structure
  428. //
  429. pSurf_lcl->lpSurfMore = (LPDDRAWI_DDRAWSURFACE_MORE) (((LPSTR) pSurf_lcl) +
  430. surf_size_lcl );
  431. pSurf_lcl->lpSurfMore->dwSize = sizeof( DDRAWI_DDRAWSURFACE_MORE );
  432. pSurf_lcl->lpSurfMore->lpIUnknowns = NULL;
  433. pSurf_lcl->lpSurfMore->lpDD_lcl = this_lcl;
  434. pSurf_lcl->lpSurfMore->lpDD_int = this_int;
  435. pSurf_lcl->lpSurfMore->dwMipMapCount = 0UL;
  436. pSurf_lcl->lpSurfMore->lpddOverlayFX = NULL;
  437. pSurf_lcl->lpSurfMore->lpD3DDevIList = NULL;
  438. pSurf_lcl->lpSurfMore->dwPFIndex = PFINDEX_UNINITIALIZED;
  439. // fill in the current caps
  440. pSurf_lcl->ddsCaps = caps;
  441. #ifdef WINNT
  442. //
  443. // NT kernel needs to know about surface
  444. //
  445. //don't let NT kernel know about exec buffers
  446. DPF(8,"Attempting to create NT kernel mode surface object");
  447. if (!DdCreateSurfaceObject(pSurf_lcl, FALSE))
  448. {
  449. DPF_ERR("NT kernel mode stuff won't create its surface object!");
  450. ddrval = DDERR_GENERIC;
  451. goto error_exit_create_link;
  452. }
  453. DPF(9,"Kernel mode handle is %08x", pSurf_lcl->hDDSurface);
  454. #endif
  455. //
  456. // Link the newly created surface to the DDraw surface chain
  457. //
  458. pSurf_int->lpLink = this->dsList;
  459. this->dsList = pSurf_int;
  460. //
  461. // AddRef the newly created surface
  462. //
  463. DD_Surface_AddRef( (LPDIRECTDRAWSURFACE) pSurf_int );
  464. //
  465. // Now assign it to the ptr-to-ptr passed in
  466. //
  467. *ppDDSurface = (LPDIRECTDRAWSURFACE) pSurf_int;
  468. return DD_OK;
  469. error_exit_create_link:
  470. //
  471. // Free any allocated memory
  472. //
  473. // 1) The allocated SURFACE_LCL
  474. if (pSurf_lcl)
  475. {
  476. MemFree (pSurf_lcl);
  477. }
  478. // 2) The Surface_int
  479. if (pSurf_int)
  480. {
  481. MemFree (pSurf_int);
  482. }
  483. return ddrval;
  484. }
  485. //-------------------------------------------------------------------------------
  486. //
  487. // createAndLinkOptSurface
  488. //
  489. // Create a surface, and link it into the chain.
  490. // We create a single surface place-holder here, real work is done at the
  491. // Load/Copy time.
  492. //
  493. //-------------------------------------------------------------------------------
  494. HRESULT
  495. createAndLinkOptSurface(
  496. LPDDRAWI_DIRECTDRAW_LCL this_lcl,
  497. LPDDRAWI_DIRECTDRAW_INT this_int,
  498. LPDDOPTSURFACEDESC pDDOptSurfaceDesc,
  499. LPDIRECTDRAWSURFACE FAR *ppDDSurface
  500. )
  501. {
  502. LPDDRAWI_DIRECTDRAW_GBL this;
  503. LPDDRAWI_DDRAWSURFACE_INT new_surf_int;
  504. LPDDRAWI_DDRAWSURFACE_LCL new_surf_lcl;
  505. LPDDRAWI_DDRAWSURFACE_GBL new_surf;
  506. LPDDRAWI_DDRAWSURFACE_GBL_MORE new_surf_gbl_more;
  507. DDSCAPS2 caps2;
  508. LPDDOPTSURFACEDESC pOptSurfDesc;
  509. DDPIXELFORMAT ddpf;
  510. HRESULT ddrval = DD_OK;
  511. // DDraw-global
  512. this = this_lcl->lpGbl;
  513. //
  514. // Fix the caps
  515. //
  516. ZeroMemory (&caps2, sizeof (DDSCAPS));
  517. caps2.dwCaps = DDSCAPS_OPTIMIZED;
  518. if (pDDOptSurfaceDesc->ddSCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  519. caps2.dwCaps |= DDSCAPS_SYSTEMMEMORY;
  520. if (pDDOptSurfaceDesc->ddSCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
  521. caps2.dwCaps |= DDSCAPS_VIDEOMEMORY;
  522. if (pDDOptSurfaceDesc->ddSCaps.dwCaps & DDSCAPS_LOCALVIDMEM)
  523. caps2.dwCaps |= DDSCAPS_LOCALVIDMEM;
  524. if (pDDOptSurfaceDesc->ddSCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM)
  525. caps2.dwCaps |= DDSCAPS_NONLOCALVIDMEM;
  526. // Quit is the memory type is not supported
  527. if (caps2.dwCaps & DDSCAPS_NONLOCALVIDMEM)
  528. {
  529. if (!(this->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM))
  530. {
  531. DPF_ERR( "Driver does not support non-local video memory" );
  532. ddrval = DDERR_NONONLOCALVIDMEM;
  533. goto error_exit_create_opt;
  534. }
  535. }
  536. #if 0
  537. // Quit if textures are not supported
  538. if (!(this->ddCaps.dwCaps & DDSCAPS_TEXTURE))
  539. {
  540. DPF_ERR( "Driver does not support textures" );
  541. return DDERR_NOTEXTUREHW;
  542. }
  543. #endif
  544. //
  545. // PixelFormat: Mark it as an empty surface
  546. //
  547. ZeroMemory (&ddpf, sizeof (ddpf));
  548. ddpf.dwSize = sizeof (ddpf);
  549. ddpf.dwFlags = DDPF_EMPTYSURFACE;
  550. //
  551. // OptSurfaceDesc
  552. //
  553. pOptSurfDesc = MemAlloc (sizeof (DDOPTSURFACEDESC));
  554. if (NULL == pOptSurfDesc)
  555. {
  556. DPF_ERR ("Memory allocation failed for opt surface descriptor");
  557. ddrval = DDERR_OUTOFMEMORY;
  558. goto error_exit_create_opt;
  559. }
  560. ZeroMemory (pOptSurfDesc, sizeof (*pOptSurfDesc));
  561. CopyMemory (pOptSurfDesc, pDDOptSurfaceDesc, sizeof (DDOPTSURFACEDESC));
  562. // Create and link an uninitialized surface
  563. ddrval = CreateAndLinkUnintializedSurface (this_lcl,
  564. this_int,
  565. ppDDSurface);
  566. if (ddrval != DD_OK)
  567. {
  568. DPF_ERR ("createAndLinkUninitializedSurface failed");
  569. goto error_exit_create_opt;
  570. }
  571. //
  572. // 1) Update GBL_MORE structure
  573. //
  574. new_surf_int = (LPDDRAWI_DDRAWSURFACE_INT)*ppDDSurface;
  575. new_surf_lcl = new_surf_int->lpLcl;
  576. new_surf = new_surf_lcl->lpGbl;
  577. new_surf_gbl_more = GET_LPDDRAWSURFACE_GBL_MORE(new_surf);
  578. new_surf_gbl_more->lpDDOptSurfaceDesc = pOptSurfDesc;
  579. // Init the contents stamp to 0 means the surface's contents can
  580. // change at any time.
  581. new_surf_gbl_more->dwContentsStamp = 0;
  582. //
  583. // 2) Update DDRAWI_DDRAWSURFACE_GBL structure
  584. //
  585. new_surf->ddpfSurface = ddpf;
  586. //
  587. // 3) Update DDRAWI_DDRAWSURFACE_INT structure
  588. //
  589. new_surf_int->lpVtbl = &ddOptSurfaceCallbacks;
  590. //
  591. // 4) Update DDRAWI_DDRAWSURFACE_LCL structure
  592. //
  593. // Flag it as an:
  594. // 1) empty surface
  595. // 2) Front surface
  596. // 3) Has a pixelformat
  597. new_surf_lcl->dwFlags = (DDRAWISURF_EMPTYSURFACE |
  598. DDRAWISURF_FRONTBUFFER |
  599. DDRAWISURF_HASPIXELFORMAT);
  600. // fill in the current caps
  601. CopyMemory (&new_surf_lcl->ddsCaps, &caps2, sizeof(new_surf_lcl->ddsCaps));
  602. return DD_OK;
  603. error_exit_create_opt:
  604. //
  605. // Free any allocated memory
  606. //
  607. // 1) The allocated OPTSURFDESC
  608. if (pOptSurfDesc)
  609. {
  610. MemFree (pOptSurfDesc);
  611. }
  612. return ddrval;
  613. }
  614. //-------------------------------------------------------------------------------
  615. //
  616. // InternalCreateOptSurface
  617. //
  618. // Create the surface.
  619. // This is the internal way of doing this; used by EnumSurfaces.
  620. // Assumes the directdraw lock has been taken.
  621. //
  622. //-------------------------------------------------------------------------------
  623. HRESULT
  624. InternalCreateOptSurface(
  625. LPDDRAWI_DIRECTDRAW_LCL this_lcl,
  626. LPDDOPTSURFACEDESC pDDOptSurfaceDesc,
  627. LPDIRECTDRAWSURFACE FAR *ppDDSurface,
  628. LPDDRAWI_DIRECTDRAW_INT this_int )
  629. {
  630. DDSCAPS2 caps2;
  631. DDOSCAPS ocaps;
  632. HRESULT ddrval;
  633. LPDDRAWI_DIRECTDRAW_GBL this;
  634. this = this_lcl->lpGbl;
  635. // Validate Caps
  636. caps2 = pDDOptSurfaceDesc->ddSCaps;
  637. if (caps2.dwCaps & ~DDOSDCAPS_VALIDSCAPS)
  638. {
  639. DPF_ERR( "Unrecognized optimized surface caps" );
  640. return DDERR_INVALIDCAPS;
  641. }
  642. ocaps = pDDOptSurfaceDesc->ddOSCaps;
  643. if (ocaps.dwCaps & ~DDOSDCAPS_VALIDOSCAPS)
  644. {
  645. DPF_ERR( "Unrecognized optimized surface caps" );
  646. return DDERR_INVALIDCAPS;
  647. }
  648. //
  649. // valid memory caps?
  650. //
  651. if ((caps2.dwCaps & DDSCAPS_SYSTEMMEMORY)
  652. && (caps2.dwCaps & DDSCAPS_VIDEOMEMORY))
  653. {
  654. DPF_ERR( "Can't specify SYSTEMMEMORY and VIDEOMEMORY" );
  655. return DDERR_INVALIDCAPS;
  656. }
  657. //
  658. // If DDSCAPS_LOCALVIDMEM or DDSCAPS_NONLOCALVIDMEM are specified
  659. // then DDSCAPS_VIDOEMEMORY must be explicity specified. Note, we
  660. // can't dely this check until checkCaps() as by that time the heap
  661. // scanning software may well have turned on DDSCAPS_VIDOEMEMORY.
  662. //
  663. if ((caps2.dwCaps & (DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM)) &&
  664. !(caps2.dwCaps & DDSCAPS_VIDEOMEMORY))
  665. {
  666. DPF_ERR( "DDOSDCAPS_VIDEOMEMORY must be specified with DDSCAPS_LOCALVIDMEM or DDSCAPS_NONLOCALVIDMEM" );
  667. return DDERR_INVALIDCAPS;
  668. }
  669. //
  670. // have to specify if it is sys-mem or vid-mem
  671. //
  672. if ((caps2.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY)) == 0)
  673. {
  674. DPF_ERR( "Need to specify the memory type" );
  675. return DDERR_INVALIDCAPS;
  676. }
  677. //
  678. // Validate optimization type caps
  679. //
  680. if ((ocaps.dwCaps & (DDOSDCAPS_OPTCOMPRESSED | DDOSDCAPS_OPTREORDERED)) == 0)
  681. {
  682. DPF_ERR ("Not specified whether compressed or reordered, let the driver choose");
  683. }
  684. // Cannot be both compresses and reordered
  685. if ((ocaps.dwCaps & DDOSDCAPS_OPTCOMPRESSED)
  686. && (ocaps.dwCaps & DDOSDCAPS_OPTREORDERED))
  687. {
  688. DPF_ERR ("Cannot be both compresses and reordered");
  689. return DDERR_INVALIDCAPS;
  690. }
  691. ddrval = createAndLinkOptSurface (this_lcl, this_int, pDDOptSurfaceDesc,
  692. ppDDSurface);
  693. return ddrval;
  694. }
  695. //-------------------------------------------------------------------------------
  696. //
  697. // CreateOptSurface method of IDirectDrawSurface4
  698. //
  699. // Create an optimized surface given the Optimized surface descriptor
  700. //
  701. //-------------------------------------------------------------------------------
  702. HRESULT
  703. EXTERN_DDAPI
  704. DD_CreateOptSurface(
  705. LPDIRECTDRAW pDD,
  706. LPDDOPTSURFACEDESC pDDOptSurfaceDesc,
  707. LPDIRECTDRAWSURFACE FAR *ppDDS,
  708. IUnknown FAR *pUnkOuter )
  709. {
  710. LPDDRAWI_DIRECTDRAW_INT this_int;
  711. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  712. LPDDRAWI_DIRECTDRAW_GBL this;
  713. DDOPTSURFACEDESC ddosd;
  714. HRESULT ddrval;
  715. ZeroMemory(&ddosd,sizeof(ddosd));
  716. ddosd.dwSize = sizeof (ddosd);
  717. //
  718. // Return error if aggregation expected
  719. //
  720. if( pUnkOuter != NULL )
  721. {
  722. return CLASS_E_NOAGGREGATION;
  723. }
  724. ENTER_DDRAW();
  725. DPF(2,A,"ENTERAPI: DD_CreateOptSurface");
  726. //
  727. // Setup DPF stuff
  728. //
  729. DPF_ENTERAPI(pDD);
  730. //
  731. // Parameter validation
  732. //
  733. TRY
  734. {
  735. this_int = (LPDDRAWI_DIRECTDRAW_INT) pDD;
  736. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  737. {
  738. DPF_ERR( "Invalid driver object passed" );
  739. DPF_APIRETURNS(DDERR_INVALIDOBJECT);
  740. LEAVE_DDRAW();
  741. return DDERR_INVALIDOBJECT;
  742. }
  743. this_lcl = this_int->lpLcl;
  744. this = this_lcl->lpGbl;
  745. // verify that cooperative level is set
  746. if( !(this_lcl->dwLocalFlags & DDRAWILCL_SETCOOPCALLED) )
  747. {
  748. DPF_ERR( "Must call SetCooperativeLevel before calling Create functions" );
  749. LEAVE_DDRAW();
  750. DPF_APIRETURNS(DDERR_NOCOOPERATIVELEVELSET);
  751. return DDERR_NOCOOPERATIVELEVELSET;
  752. }
  753. if( this->dwModeIndex == DDUNSUPPORTEDMODE )
  754. {
  755. DPF_ERR( "Driver is in an unsupported mode" );
  756. LEAVE_DDRAW();
  757. DPF_APIRETURNS(DDERR_UNSUPPORTEDMODE);
  758. return DDERR_UNSUPPORTEDMODE;
  759. }
  760. if( !VALID_DDOPTSURFACEDESC_PTR( pDDOptSurfaceDesc ) )
  761. {
  762. DPF_ERR( "Invalid optimized surface description. Did you set the dwSize member?" );
  763. LEAVE_DDRAW();
  764. DPF_APIRETURNS(DDERR_INVALIDPARAMS);
  765. return DDERR_INVALIDPARAMS;
  766. }
  767. memcpy(&ddosd, pDDOptSurfaceDesc, sizeof(*pDDOptSurfaceDesc));
  768. *ppDDS = NULL;
  769. }
  770. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  771. {
  772. DPF_ERR( "Exception encountered validating parameters" );
  773. LEAVE_DDRAW();
  774. DPF_APIRETURNS(DDERR_INVALIDPARAMS);
  775. return DDERR_INVALIDPARAMS;
  776. }
  777. // Quit if there is no hardware present
  778. if( this->dwFlags & DDRAWI_NOHARDWARE )
  779. {
  780. ddrval = DDERR_NODIRECTDRAWHW;
  781. goto exit_create;
  782. }
  783. // Assert that: (0 == this->lpDDOptSurfaceInfo) <==> (if and only if)
  784. // (this->ddCaps.dwCaps2 & DDCAPS2_OPTIMIZEDSURFACES)
  785. //Check to see if the driver supports OptSurface
  786. if ((0 == this->lpDDOptSurfaceInfo) // GetDriverInfo failed for some reason
  787. || !(this->ddCaps.dwCaps2 & DDCAPS2_OPTIMIZEDSURFACES))
  788. {
  789. ddrval = DDERR_NOOPTSURFACESUPPORT;
  790. goto exit_create;
  791. }
  792. //
  793. // Check if the GUID passed is a recognized optimized surface GUID
  794. // The compression ratio is more a hint.
  795. //
  796. if (!IsRecognizedOptSurfaceGUID (this, &(pDDOptSurfaceDesc->guid)))
  797. {
  798. DPF_ERR( "Not a recognized GUID" );
  799. ddrval = DDERR_UNRECOGNIZEDGUID;
  800. goto exit_create;
  801. }
  802. //
  803. // Now create the Optimized surface
  804. //
  805. ddrval = InternalCreateOptSurface(this_lcl, &ddosd, ppDDS, this_int);
  806. exit_create:
  807. DPF_APIRETURNS(ddrval);
  808. LEAVE_DDRAW();
  809. return ddrval;
  810. }
  811. //-------------------------------------------------------------------------------
  812. //
  813. // CreateOptSurface method of IDirectDrawSurface4
  814. //
  815. // Create an optimized surface given the Optimized surface descriptor
  816. //
  817. //-------------------------------------------------------------------------------
  818. HRESULT
  819. EXTERN_DDAPI
  820. DD_ListOptSurfaceGUIDS(
  821. LPDIRECTDRAW pDD,
  822. DWORD *pNumGuids,
  823. LPGUID pGuidArray )
  824. {
  825. LPDDRAWI_DIRECTDRAW_INT this_int;
  826. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  827. LPDDRAWI_DIRECTDRAW_GBL this;
  828. HRESULT ddrval = DD_OK;
  829. LPGUID pRetGuids = NULL;
  830. LPDDOPTSURFACEINFO pOptSurfInfo;
  831. ENTER_DDRAW();
  832. DPF(2,A,"ENTERAPI: DD_ListOptSurfaceGUIDS");
  833. //
  834. // Parameter validation
  835. //
  836. TRY
  837. {
  838. this_int = (LPDDRAWI_DIRECTDRAW_INT) pDD;
  839. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  840. {
  841. DPF_ERR( "Invalid driver object passed" );
  842. DPF_APIRETURNS(DDERR_INVALIDOBJECT);
  843. LEAVE_DDRAW();
  844. return DDERR_INVALIDOBJECT;
  845. }
  846. this_lcl = this_int->lpLcl;
  847. this = this_lcl->lpGbl;
  848. if( !VALID_PTR( pGuidArray, sizeof (GUID) ))
  849. {
  850. DPF_ERR( "Invalid GuidArray pointer" );
  851. LEAVE_DDRAW();
  852. return DDERR_INVALIDPARAMS;
  853. }
  854. pGuidArray = NULL;
  855. if( !VALID_PTR( pNumGuids, sizeof (*pNumGuids)) )
  856. {
  857. DPF_ERR( "Invalid GuidArray pointer" );
  858. LEAVE_DDRAW();
  859. return DDERR_INVALIDPARAMS;
  860. }
  861. *pNumGuids = 0;
  862. }
  863. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  864. {
  865. DPF_ERR( "Exception encountered validating parameters" );
  866. LEAVE_DDRAW();
  867. DPF_APIRETURNS(DDERR_INVALIDPARAMS);
  868. return DDERR_INVALIDPARAMS;
  869. }
  870. pOptSurfInfo = this->lpDDOptSurfaceInfo;
  871. // Assert that: (0 == this->lpDDOptSurfaceInfo) <==> (if and only if)
  872. // (this->ddCaps.dwCaps2 & DDCAPS2_OPTIMIZEDSURFACES)
  873. //Check to see if the driver supports OptSurface
  874. if ((0 == pOptSurfInfo) // GetDriverInfo failed for some reason
  875. || !(this->ddCaps.dwCaps2 & DDCAPS2_OPTIMIZEDSURFACES))
  876. {
  877. ddrval = DDERR_NOOPTSURFACESUPPORT;
  878. goto list_exit;
  879. }
  880. // If there are no GUIDS reported by the driver,
  881. // return the nulled out out-params.
  882. if (pOptSurfInfo->dwNumGuids == 0)
  883. {
  884. ddrval = DD_OK;
  885. goto list_exit;
  886. }
  887. // Allocate the array of GUIDS
  888. // ATTENTION: Incomplete allocation?
  889. pRetGuids = MemAlloc(pOptSurfInfo->dwNumGuids * sizeof(GUID));
  890. if( NULL == pRetGuids )
  891. {
  892. ddrval = DDERR_OUTOFMEMORY;
  893. goto list_exit;
  894. }
  895. // Copy the GUID array to be returned
  896. CopyMemory ((PVOID)pRetGuids, (PVOID)pOptSurfInfo->lpGuidArray,
  897. pOptSurfInfo->dwNumGuids * sizeof(GUID));
  898. pGuidArray = pRetGuids;
  899. *pNumGuids = pOptSurfInfo->dwNumGuids;
  900. list_exit:
  901. LEAVE_DDRAW();
  902. return ddrval;
  903. }
  904. //-------------------------------------------------------------------------------
  905. //
  906. // GetOptSurfaceDesc method of IDirectDrawOptSurface
  907. //
  908. // Get the Optimized surface description
  909. //
  910. //-------------------------------------------------------------------------------
  911. HRESULT
  912. EXTERN_DDAPI
  913. DD_OptSurface_GetOptSurfaceDesc(
  914. LPDIRECTDRAWSURFACE pDDS,
  915. LPDDOPTSURFACEDESC pDDOptSurfDesc)
  916. {
  917. LPDDRAWI_DDRAWSURFACE_INT this_int;
  918. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  919. LPDDRAWI_DDRAWSURFACE_GBL this;
  920. LPDDRAWI_DDRAWSURFACE_GBL_MORE this_gbl_more;
  921. LPDDOPTSURFACEDESC pDDRetOptSurfDesc = NULL;
  922. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  923. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  924. ENTER_DDRAW();
  925. DPF(2,A,"ENTERAPI: DD_OptSurface_GetOptSurfaceDesc");
  926. TRY
  927. {
  928. this_int = (LPDDRAWI_DDRAWSURFACE_INT) pDDS;
  929. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  930. {
  931. LEAVE_DDRAW();
  932. return DDERR_INVALIDOBJECT;
  933. }
  934. this_lcl = this_int->lpLcl;
  935. this = this_lcl->lpGbl;
  936. this_gbl_more = GET_LPDDRAWSURFACE_GBL_MORE(this);
  937. if( SURFACE_LOST( this_lcl ) )
  938. {
  939. LEAVE_DDRAW();
  940. return DDERR_SURFACELOST;
  941. }
  942. if( !VALID_DDOPTSURFACEDESC_PTR( pDDOptSurfDesc ) )
  943. {
  944. DPF_ERR( "Invalid optimized surface description. Did you set the dwSize member?" );
  945. LEAVE_DDRAW();
  946. DPF_APIRETURNS(DDERR_INVALIDPARAMS);
  947. return DDERR_INVALIDPARAMS;
  948. }
  949. pDDOptSurfDesc = NULL;
  950. }
  951. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  952. {
  953. DPF_ERR( "Exception encountered validating parameters" );
  954. LEAVE_DDRAW();
  955. return DDERR_INVALIDPARAMS;
  956. }
  957. //
  958. // Quit with error if:
  959. // 1) No hardware
  960. // 2) Hardware doesnt support optimized surfaces
  961. // 3) Surface is an unoptimized surface
  962. //
  963. // DDraw Gbl pointer
  964. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  965. pdrv = pdrv_lcl->lpGbl;
  966. // Assert that: (0 == this->lpDDOptSurfaceInfo) <==> (if and only if)
  967. // (this->ddCaps.dwCaps2 & DDCAPS2_OPTIMIZEDSURFACES)
  968. // 1)
  969. if( pdrv->dwFlags & DDRAWI_NOHARDWARE )
  970. {
  971. DPF_ERR ("No hardware present");
  972. LEAVE_DDRAW();
  973. return DDERR_NODIRECTDRAWHW;
  974. }
  975. // 2)
  976. if ((0 == pdrv->lpDDOptSurfaceInfo) ||
  977. !(pdrv->ddCaps.dwCaps2 & DDCAPS2_OPTIMIZEDSURFACES))
  978. {
  979. DPF_ERR ("Optimized surfaces not supported");
  980. LEAVE_DDRAW();
  981. return DDERR_NOOPTSURFACESUPPORT;
  982. }
  983. // 3)
  984. if (!(this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED))
  985. {
  986. DPF_ERR ("Current surface is not an optimized surface");
  987. LEAVE_DDRAW();
  988. return DDERR_NOTANOPTIMIZEDSURFACE;
  989. }
  990. pDDRetOptSurfDesc = MemAlloc (sizeof (*pDDRetOptSurfDesc));
  991. if (!pDDRetOptSurfDesc)
  992. {
  993. DPF_ERR ("Memory allocation failed");
  994. LEAVE_DDRAW();
  995. return DDERR_OUTOFMEMORY;
  996. }
  997. ZeroMemory (pDDRetOptSurfDesc, sizeof (*pDDRetOptSurfDesc));
  998. CopyMemory (pDDRetOptSurfDesc, this_gbl_more->lpDDOptSurfaceDesc,
  999. sizeof (*pDDRetOptSurfDesc));
  1000. pDDOptSurfDesc = pDDRetOptSurfDesc;
  1001. LEAVE_DDRAW();
  1002. return DD_OK;
  1003. }
  1004. //-------------------------------------------------------------------------------
  1005. //
  1006. // DoLoadUnOptSurf
  1007. //
  1008. // Actually make the HAL call and update data-structures if the call
  1009. // succeeds.
  1010. //
  1011. //-------------------------------------------------------------------------------
  1012. HRESULT
  1013. DoLoadUnOptSurf(
  1014. LPDDRAWI_DDRAWSURFACE_LCL this_lcl,
  1015. LPDDRAWI_DDRAWSURFACE_GBL this,
  1016. LPDDRAWI_DDRAWSURFACE_LCL src_lcl,
  1017. LPDDRAWI_DDRAWSURFACE_GBL src
  1018. )
  1019. {
  1020. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  1021. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  1022. DDHAL_OPTIMIZESURFACEDATA ddhal_osd;
  1023. LPDDOPTSURFACEINFO pDDOptSurfInfo = NULL;
  1024. LPDDRAWI_DDRAWSURFACE_GBL_MORE this_gbl_more, src_gbl_more;
  1025. HRESULT ddrval = DD_OK;
  1026. // Get the ddraw pointers
  1027. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  1028. pdrv = pdrv_lcl->lpGbl;
  1029. pDDOptSurfInfo = pdrv->lpDDOptSurfaceInfo;
  1030. this_gbl_more = GET_LPDDRAWSURFACE_GBL_MORE (this);
  1031. // Setup data to pass to the driver
  1032. ZeroMemory (&ddhal_osd, sizeof (DDHAL_COPYOPTSURFACEDATA));
  1033. ddhal_osd.lpDD = pdrv_lcl;
  1034. ddhal_osd.ddOptSurfDesc = *(this_gbl_more->lpDDOptSurfaceDesc);
  1035. ddhal_osd.lpDDSSrc = src_lcl;
  1036. ddhal_osd.lpDDSDest = this_lcl;
  1037. // Make the HAL call
  1038. DOHALCALL(OptimizeSurface, pDDOptSurfInfo->OptimizeSurface, ddhal_osd, ddrval, FALSE );
  1039. if (ddrval != DD_OK)
  1040. {
  1041. DPF_ERR ("LoadUnOptSurface failed in the driver");
  1042. return ddrval;
  1043. }
  1044. // ATTENTION: Should the driver do these updates ?
  1045. // 1) Update the DDRAWI_DDRAWSURFACE_LCL structure
  1046. // Color key stuff is ignored for now
  1047. this_lcl->dwFlags = src_lcl->dwFlags;
  1048. this_lcl->dwFlags &= ~DDRAWISURF_EMPTYSURFACE;
  1049. this_lcl->ddsCaps = src_lcl->ddsCaps;
  1050. this_lcl->ddsCaps.dwCaps |= DDSCAPS_OPTIMIZED;
  1051. #ifdef WIN95
  1052. this_lcl->dwModeCreatedIn = src_lcl->dwModeCreatedIn;
  1053. #else
  1054. this_lcl->dmiCreated = src_lcl->dmiCreated;
  1055. #endif
  1056. this_lcl->dwBackBufferCount = src_lcl->dwBackBufferCount;
  1057. // 2) Update the DDRAWI_DDRAWSURFACE_MORE structure
  1058. this_lcl->lpSurfMore->dwMipMapCount = src_lcl->lpSurfMore->dwMipMapCount;
  1059. this_lcl->lpSurfMore->ddsCapsEx = src_lcl->lpSurfMore->ddsCapsEx;
  1060. // 3) Update the DDRAWI_DDRAWSURFACE_GBL structure
  1061. this->dwGlobalFlags = src->dwGlobalFlags;
  1062. this->wHeight = src->wHeight;
  1063. this->wWidth = src->wWidth;
  1064. this->ddpfSurface = src->ddpfSurface;
  1065. // 4) Update the DDRAWI_DDRAWSURFACE_GBL_MORE structure
  1066. this_gbl_more = GET_LPDDRAWSURFACE_GBL_MORE (this);
  1067. src_gbl_more = GET_LPDDRAWSURFACE_GBL_MORE (src);
  1068. this_gbl_more->dwContentsStamp = src_gbl_more->dwContentsStamp;
  1069. CopyMemory (this_gbl_more->lpDDOptSurfaceDesc,
  1070. src_gbl_more->lpDDOptSurfaceDesc,
  1071. sizeof (DDOPTSURFACEDESC));
  1072. return ddrval;
  1073. }
  1074. //-------------------------------------------------------------------------------
  1075. //
  1076. // FilterSurfCaps
  1077. //
  1078. // Check to see if the surface is can be optimized
  1079. //
  1080. //-------------------------------------------------------------------------------
  1081. HRESULT
  1082. FilterSurfCaps(
  1083. LPDDRAWI_DDRAWSURFACE_LCL surf_lcl,
  1084. LPDDRAWI_DDRAWSURFACE_GBL surf)
  1085. {
  1086. DWORD caps = surf_lcl->ddsCaps.dwCaps;
  1087. //
  1088. // check for no caps at all!
  1089. //
  1090. if( caps == 0 )
  1091. {
  1092. DPF_ERR( "no caps specified" );
  1093. return DDERR_INVALIDCAPS;
  1094. }
  1095. //
  1096. // check for bogus caps.
  1097. //
  1098. if( caps & ~DDSCAPS_VALID )
  1099. {
  1100. DPF_ERR( "Create surface: invalid caps specified" );
  1101. return DDERR_INVALIDCAPS;
  1102. }
  1103. //
  1104. // Anything other than a texture is not allowed
  1105. // ATTENTION: some more flags need to be checked
  1106. //
  1107. if(caps & (DDSCAPS_EXECUTEBUFFER |
  1108. DDSCAPS_BACKBUFFER |
  1109. DDSCAPS_FRONTBUFFER |
  1110. DDSCAPS_OFFSCREENPLAIN |
  1111. DDSCAPS_PRIMARYSURFACE |
  1112. DDSCAPS_PRIMARYSURFACELEFT |
  1113. DDSCAPS_VIDEOPORT |
  1114. DDSCAPS_ZBUFFER |
  1115. DDSCAPS_OWNDC |
  1116. DDSCAPS_OVERLAY |
  1117. DDSCAPS_3DDEVICE |
  1118. DDSCAPS_ALLOCONLOAD)
  1119. )
  1120. {
  1121. DPF_ERR( "currently only textures can be optimized" );
  1122. return DDERR_INVALIDCAPS;
  1123. }
  1124. if( !(caps & DDSCAPS_TEXTURE) )
  1125. {
  1126. DPF_ERR( "DDSCAPS_TEXTURE needs to be set" );
  1127. return DDERR_INVALIDCAPS;
  1128. }
  1129. return DD_OK;
  1130. }
  1131. //-------------------------------------------------------------------------------
  1132. //
  1133. // LoadUnoptimizedSurf method of IDirectDrawOptSurface
  1134. //
  1135. // Load an unoptimized surface. This is a way to optimize a surface.
  1136. //
  1137. // The Surface's PIXELFORMAT will be that of the pDDSSrc in case the call
  1138. // succeeds.
  1139. //
  1140. //-------------------------------------------------------------------------------
  1141. HRESULT
  1142. EXTERN_DDAPI
  1143. DD_OptSurface_LoadUnoptimizedSurf(
  1144. LPDIRECTDRAWSURFACE pDDS,
  1145. LPDIRECTDRAWSURFACE pDDSSrc)
  1146. {
  1147. LPDDRAWI_DDRAWSURFACE_INT this_int;
  1148. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  1149. LPDDRAWI_DDRAWSURFACE_GBL this;
  1150. LPDDRAWI_DDRAWSURFACE_INT src_int;
  1151. LPDDRAWI_DDRAWSURFACE_LCL src_lcl;
  1152. LPDDRAWI_DDRAWSURFACE_GBL src;
  1153. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  1154. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  1155. HRESULT ddrval = DD_OK;
  1156. ENTER_DDRAW();
  1157. DPF(2,A,"ENTERAPI: DD_OptSurface_LoadUnoptimizedSurf");
  1158. TRY
  1159. {
  1160. this_int = (LPDDRAWI_DDRAWSURFACE_INT) pDDS;
  1161. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  1162. {
  1163. LEAVE_DDRAW();
  1164. return DDERR_INVALIDOBJECT;
  1165. }
  1166. this_lcl = this_int->lpLcl;
  1167. this = this_lcl->lpGbl;
  1168. if( SURFACE_LOST( this_lcl ) )
  1169. {
  1170. LEAVE_DDRAW();
  1171. return DDERR_SURFACELOST;
  1172. }
  1173. src_int = (LPDDRAWI_DDRAWSURFACE_INT) pDDSSrc;
  1174. if( !VALID_DIRECTDRAWSURFACE_PTR( src_int ) )
  1175. {
  1176. LEAVE_DDRAW();
  1177. return DDERR_INVALIDOBJECT;
  1178. }
  1179. src_lcl = src_int->lpLcl;
  1180. if( SURFACE_LOST( src_lcl ) )
  1181. {
  1182. LEAVE_DDRAW();
  1183. return DDERR_SURFACELOST;
  1184. }
  1185. src = src_lcl->lpGbl;
  1186. }
  1187. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1188. {
  1189. DPF_ERR( "Exception encountered validating parameters" );
  1190. LEAVE_DDRAW();
  1191. return DDERR_INVALIDPARAMS;
  1192. }
  1193. //ATTENTION: Should src be AddRef'd ?
  1194. //
  1195. // Quit with error if:
  1196. // 1) No hardware
  1197. // 2) Hardware doesnt support optimized surfaces
  1198. // 3) Surface is an unoptimized surface
  1199. // 4) Src is an optimized surface
  1200. // 5) Current surface is not empty (should we enforce it, or let the driver
  1201. // deal with it ?)
  1202. // 6) The surface is not the "right" type
  1203. // 7) The driver fails for some reason
  1204. //
  1205. // DDraw Gbl pointer
  1206. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  1207. pdrv = pdrv_lcl->lpGbl;
  1208. // 1)
  1209. if( pdrv->dwFlags & DDRAWI_NOHARDWARE )
  1210. {
  1211. DPF_ERR ("No hardware present");
  1212. LEAVE_DDRAW();
  1213. return DDERR_NODIRECTDRAWHW;
  1214. }
  1215. // 2)
  1216. if ((0 == pdrv->lpDDOptSurfaceInfo) ||
  1217. !(pdrv->ddCaps.dwCaps2 & DDCAPS2_OPTIMIZEDSURFACES))
  1218. {
  1219. DPF_ERR ("Optimized surfaces not supported");
  1220. LEAVE_DDRAW();
  1221. return DDERR_NOOPTSURFACESUPPORT;
  1222. }
  1223. // 3)
  1224. if (!(this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED))
  1225. {
  1226. DPF_ERR ("Current surface is not an optimized surface");
  1227. LEAVE_DDRAW();
  1228. return DDERR_NOTANOPTIMIZEDSURFACE;
  1229. }
  1230. // 4)
  1231. if (src_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  1232. {
  1233. DPF_ERR ("Source surface is an optimized surface");
  1234. LEAVE_DDRAW();
  1235. return DDERR_ISOPTIMIZEDSURFACE;
  1236. }
  1237. // 5)
  1238. if (!(this_lcl->dwFlags & DDRAWISURF_EMPTYSURFACE))
  1239. {
  1240. DPF_ERR ("Current surface is not an empty optimized surface");
  1241. LEAVE_DDRAW();
  1242. return DDERR_NOTANEMPTYOPTIMIZEDSURFACE;
  1243. }
  1244. // 6)
  1245. ddrval = FilterSurfCaps (src_lcl, src);
  1246. if (ddrval != DD_OK)
  1247. {
  1248. DPF_ERR ("Source surface cannot be optimized");
  1249. LEAVE_DDRAW();
  1250. return DDERR_NOTANEMPTYOPTIMIZEDSURFACE;
  1251. }
  1252. // Now attempt the actual load
  1253. ddrval = DoLoadUnOptSurf (this_lcl, this, src_lcl, src);
  1254. LEAVE_DDRAW();
  1255. return ddrval;
  1256. }
  1257. //-------------------------------------------------------------------------------
  1258. //
  1259. // DoCopyOptSurf
  1260. //
  1261. // Actually make the HAL call and update data-structures if the call
  1262. // succeeds.
  1263. //
  1264. //-------------------------------------------------------------------------------
  1265. HRESULT
  1266. DoCopyOptSurf(
  1267. LPDDRAWI_DDRAWSURFACE_LCL this_lcl,
  1268. LPDDRAWI_DDRAWSURFACE_GBL this,
  1269. LPDDRAWI_DDRAWSURFACE_LCL src_lcl,
  1270. LPDDRAWI_DDRAWSURFACE_GBL src
  1271. )
  1272. {
  1273. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  1274. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  1275. DDHAL_COPYOPTSURFACEDATA ddhal_cosd;
  1276. LPDDOPTSURFACEINFO pDDOptSurfInfo = NULL;
  1277. LPDDRAWI_DDRAWSURFACE_GBL_MORE this_gbl_more, src_gbl_more;
  1278. HRESULT ddrval = DD_OK;
  1279. // Get the ddraw pointers
  1280. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  1281. pdrv = pdrv_lcl->lpGbl;
  1282. pDDOptSurfInfo = pdrv->lpDDOptSurfaceInfo;
  1283. // Setup data to pass to the driver
  1284. ZeroMemory (&ddhal_cosd, sizeof (DDHAL_COPYOPTSURFACEDATA));
  1285. ddhal_cosd.lpDD = pdrv_lcl;
  1286. ddhal_cosd.lpDDSSrc = src_lcl;
  1287. ddhal_cosd.lpDDSDest = this_lcl;
  1288. DOHALCALL(CopyOptSurface, pDDOptSurfInfo->CopyOptSurface, ddhal_cosd, ddrval, FALSE );
  1289. // If the driver call succeeds, then copy the surface description and
  1290. // pixel format etc.
  1291. if (ddrval != DD_OK)
  1292. {
  1293. DPF_ERR ("CopyOptSurface failed in the driver");
  1294. return ddrval;
  1295. }
  1296. // ATTENTION: Should the driver do these updates ?
  1297. // 1) Update the DDRAWI_DDRAWSURFACE_LCL structure
  1298. // Color key stuff is ignored for now
  1299. this_lcl->dwFlags = src_lcl->dwFlags;
  1300. this_lcl->ddsCaps = src_lcl->ddsCaps;
  1301. #ifdef WIN95
  1302. this_lcl->dwModeCreatedIn = src_lcl->dwModeCreatedIn;
  1303. #else
  1304. this_lcl->dmiCreated = src_lcl->dmiCreated;
  1305. #endif
  1306. this_lcl->dwBackBufferCount = src_lcl->dwBackBufferCount;
  1307. // 2) Update the DDRAWI_DDRAWSURFACE_MORE structure
  1308. this_lcl->lpSurfMore->dwMipMapCount = src_lcl->lpSurfMore->dwMipMapCount;
  1309. this_lcl->lpSurfMore->ddsCapsEx = src_lcl->lpSurfMore->ddsCapsEx;
  1310. // 3) Update the DDRAWI_DDRAWSURFACE_GBL structure
  1311. this->dwGlobalFlags = src->dwGlobalFlags;
  1312. this->wHeight = src->wHeight;
  1313. this->wWidth = src->wWidth;
  1314. this->ddpfSurface = src->ddpfSurface;
  1315. // 4) Update the DDRAWI_DDRAWSURFACE_GBL_MORE structure
  1316. this_gbl_more = GET_LPDDRAWSURFACE_GBL_MORE (this);
  1317. src_gbl_more = GET_LPDDRAWSURFACE_GBL_MORE (src);
  1318. this_gbl_more->dwContentsStamp = src_gbl_more->dwContentsStamp;
  1319. CopyMemory (this_gbl_more->lpDDOptSurfaceDesc,
  1320. src_gbl_more->lpDDOptSurfaceDesc,
  1321. sizeof (DDOPTSURFACEDESC));
  1322. return ddrval;
  1323. }
  1324. //-------------------------------------------------------------------------------
  1325. //
  1326. // CopyOptimizedSurf method of IDirectDrawOptSurface
  1327. //
  1328. // Copy an optimized surface.
  1329. //
  1330. // The Surface's PIXELFORMAT will be that of the pDDSSrc in case the call
  1331. // succeeds.
  1332. //
  1333. //-------------------------------------------------------------------------------
  1334. HRESULT
  1335. EXTERN_DDAPI
  1336. DD_OptSurface_CopyOptimizedSurf(
  1337. LPDIRECTDRAWSURFACE pDDS,
  1338. LPDIRECTDRAWSURFACE pDDSSrc)
  1339. {
  1340. LPDDRAWI_DDRAWSURFACE_INT this_int;
  1341. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  1342. LPDDRAWI_DDRAWSURFACE_GBL this;
  1343. LPDDRAWI_DDRAWSURFACE_INT src_int;
  1344. LPDDRAWI_DDRAWSURFACE_LCL src_lcl;
  1345. LPDDRAWI_DDRAWSURFACE_GBL src;
  1346. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  1347. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  1348. HRESULT ddrval = DD_OK;
  1349. ENTER_DDRAW();
  1350. DPF(2,A,"ENTERAPI: DD_OptSurface_CopyOptimizedSurf");
  1351. TRY
  1352. {
  1353. this_int = (LPDDRAWI_DDRAWSURFACE_INT) pDDS;
  1354. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  1355. {
  1356. LEAVE_DDRAW();
  1357. return DDERR_INVALIDOBJECT;
  1358. }
  1359. this_lcl = this_int->lpLcl;
  1360. this = this_lcl->lpGbl;
  1361. if( SURFACE_LOST( this_lcl ) )
  1362. {
  1363. LEAVE_DDRAW();
  1364. return DDERR_SURFACELOST;
  1365. }
  1366. src_int = (LPDDRAWI_DDRAWSURFACE_INT) pDDSSrc;
  1367. if( !VALID_DIRECTDRAWSURFACE_PTR( src_int ) )
  1368. {
  1369. LEAVE_DDRAW();
  1370. return DDERR_INVALIDOBJECT;
  1371. }
  1372. src_lcl = src_int->lpLcl;
  1373. src = src_lcl->lpGbl;
  1374. }
  1375. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1376. {
  1377. DPF_ERR( "Exception encountered validating parameters" );
  1378. LEAVE_DDRAW();
  1379. return DDERR_INVALIDPARAMS;
  1380. }
  1381. //ATTENTION: Should src be AddRef'd ?
  1382. //
  1383. // Quit with error if:
  1384. // 1) No hardware
  1385. // 2) Hardware doesnt support optimized surfaces
  1386. // 3) Surface is an unoptimized surface
  1387. // 4) Src is an unoptimized surface
  1388. // 5) Src is an empty optimized surface
  1389. // 6) Current surface is not empty (should we enforce it, or let the driver
  1390. // deal with it ?)
  1391. // 7) The driver fails for some reason
  1392. //
  1393. // DDraw Gbl pointer
  1394. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  1395. pdrv = pdrv_lcl->lpGbl;
  1396. // 1)
  1397. if( pdrv->dwFlags & DDRAWI_NOHARDWARE )
  1398. {
  1399. DPF_ERR ("No hardware present");
  1400. LEAVE_DDRAW();
  1401. return DDERR_NODIRECTDRAWHW;
  1402. }
  1403. // 2)
  1404. if ((0 == pdrv->lpDDOptSurfaceInfo) ||
  1405. !(pdrv->ddCaps.dwCaps2 & DDCAPS2_OPTIMIZEDSURFACES))
  1406. {
  1407. DPF_ERR ("Optimized surfaces not supported");
  1408. LEAVE_DDRAW();
  1409. return DDERR_NOOPTSURFACESUPPORT;
  1410. }
  1411. // 3)
  1412. if (!(this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED))
  1413. {
  1414. DPF_ERR ("Current surface is not an optimized surface");
  1415. LEAVE_DDRAW();
  1416. return DDERR_NOTANOPTIMIZEDSURFACE;
  1417. }
  1418. // 4)
  1419. if (!(src_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED))
  1420. {
  1421. DPF_ERR ("Source surface is not an optimized surface");
  1422. LEAVE_DDRAW();
  1423. return DDERR_NOTANOPTIMIZEDSURFACE;
  1424. }
  1425. // 5)
  1426. if (src_lcl->dwFlags & DDRAWISURF_EMPTYSURFACE)
  1427. {
  1428. DPF_ERR ("Source surface is an empty optimized surface");
  1429. LEAVE_DDRAW();
  1430. return DDERR_ISANEMPTYOPTIMIZEDSURFACE;
  1431. }
  1432. // 6)
  1433. if (!(this_lcl->dwFlags & DDRAWISURF_EMPTYSURFACE))
  1434. {
  1435. DPF_ERR ("Current surface is not an empty optimized surface");
  1436. LEAVE_DDRAW();
  1437. return DDERR_NOTANEMPTYOPTIMIZEDSURFACE;
  1438. }
  1439. // Now attempt the actual copy
  1440. ddrval = DoCopyOptSurf (this_lcl, this, src_lcl, src);
  1441. LEAVE_DDRAW();
  1442. return ddrval;
  1443. }
  1444. //-------------------------------------------------------------------------------
  1445. //
  1446. // DoUnOptimize
  1447. //
  1448. // Actually make the HAL call and update data-structures if the call
  1449. // succeeds.
  1450. //
  1451. //-------------------------------------------------------------------------------
  1452. HRESULT
  1453. DoUnOptimize(
  1454. LPDDSURFACEDESC2 pSurfDesc,
  1455. LPDDRAWI_DDRAWSURFACE_LCL this_lcl,
  1456. LPDDRAWI_DDRAWSURFACE_GBL this,
  1457. LPDIRECTDRAWSURFACE FAR *ppDDSDest
  1458. )
  1459. {
  1460. LPDDRAWI_DIRECTDRAW_INT pdrv_int;
  1461. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  1462. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  1463. LPDDRAWI_DDRAWSURFACE_LCL new_surf_lcl;
  1464. LPDDRAWI_DDRAWSURFACE_INT new_surf_int;
  1465. LPDDRAWI_DDRAWSURFACE_GBL new_surf;
  1466. LPDDRAWI_DDRAWSURFACE_GBL_MORE new_surf_gbl_more;
  1467. DDPIXELFORMAT ddpf;
  1468. DDSCAPS caps;
  1469. DDHAL_UNOPTIMIZESURFACEDATA ddhal_uosd;
  1470. LPDDOPTSURFACEINFO pDDOptSurfInfo = NULL;
  1471. LPDDRAWI_DDRAWSURFACE_INT pSurf_int, prev_int;
  1472. HRESULT ddrval = DD_OK;
  1473. // Get the ddraw pointers
  1474. pdrv_int = this_lcl->lpSurfMore->lpDD_int;
  1475. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  1476. pdrv = pdrv_lcl->lpGbl;
  1477. //
  1478. // Fix the caps
  1479. //
  1480. ZeroMemory (&caps, sizeof (DDSCAPS));
  1481. if (pSurfDesc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  1482. caps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
  1483. if (pSurfDesc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
  1484. caps.dwCaps |= DDSCAPS_VIDEOMEMORY;
  1485. if (pSurfDesc->ddsCaps.dwCaps & DDSCAPS_LOCALVIDMEM)
  1486. caps.dwCaps |= DDSCAPS_LOCALVIDMEM;
  1487. if (pSurfDesc->ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM)
  1488. caps.dwCaps |= DDSCAPS_NONLOCALVIDMEM;
  1489. // Quit if the memory type is not supported
  1490. if (caps.dwCaps & DDSCAPS_NONLOCALVIDMEM)
  1491. {
  1492. if (!(pdrv->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM))
  1493. {
  1494. DPF_ERR( "Driver does not support non-local video memory" );
  1495. return DDERR_NONONLOCALVIDMEM;
  1496. }
  1497. }
  1498. #if 0
  1499. // Quit if textures are not supported
  1500. if (!(pdrv->ddCaps.dwCaps & DDCAPS_TEXTURE))
  1501. {
  1502. DPF_ERR( "Driver does not support textures" );
  1503. return DDERR_NOTEXTUREHW;
  1504. }
  1505. #endif
  1506. //
  1507. // PixelFormat: Mark it as an empty surface
  1508. //
  1509. ZeroMemory (&ddpf, sizeof (ddpf));
  1510. ddpf.dwSize = sizeof (ddpf);
  1511. ddpf.dwFlags = DDPF_EMPTYSURFACE;
  1512. // Make a new uninitialized surface
  1513. ddrval = CreateAndLinkUnintializedSurface (pdrv_lcl, pdrv_int, ppDDSDest);
  1514. if (ddrval != DD_OK)
  1515. {
  1516. DPF_ERR ("createAndLinkUnintializedSurface failed");
  1517. return ddrval;
  1518. }
  1519. //
  1520. // 1) Update GBL_MORE structure
  1521. //
  1522. new_surf_int = (LPDDRAWI_DDRAWSURFACE_INT)*ppDDSDest;
  1523. new_surf_lcl = new_surf_int->lpLcl;
  1524. new_surf = new_surf_lcl->lpGbl;
  1525. new_surf_gbl_more = GET_LPDDRAWSURFACE_GBL_MORE (new_surf);
  1526. // Init the contents stamp to 0 means the surface's contents can
  1527. // change at any time.
  1528. new_surf_gbl_more->dwContentsStamp = 0;
  1529. //
  1530. // 2) Update DDRAWI_DDRAWSURFACE_GBL structure
  1531. //
  1532. new_surf->ddpfSurface = this->ddpfSurface;
  1533. //
  1534. // 3) Update DDRAWI_DDRAWSURFACE_INT structure
  1535. //
  1536. new_surf_int->lpVtbl = &ddSurface4Callbacks;
  1537. //
  1538. // 4) Update DDRAWI_DDRAWSURFACE_LCL structure
  1539. //
  1540. // Flag it as an:
  1541. // 1) empty surface
  1542. // 2) Front surface
  1543. // 3) Has a pixelformat
  1544. new_surf_lcl->dwFlags = (DDRAWISURF_EMPTYSURFACE |
  1545. DDRAWISURF_FRONTBUFFER |
  1546. DDRAWISURF_HASPIXELFORMAT);
  1547. // fill in the current caps
  1548. new_surf_lcl->ddsCaps = caps;
  1549. // Try the unoptimize
  1550. pDDOptSurfInfo = pdrv->lpDDOptSurfaceInfo;
  1551. // Setup data to pass to the driver
  1552. ZeroMemory (&ddhal_uosd, sizeof (DDHAL_UNOPTIMIZESURFACEDATA));
  1553. ddhal_uosd.lpDD = pdrv_lcl;
  1554. ddhal_uosd.lpDDSSrc = this_lcl;
  1555. ddhal_uosd.lpDDSDest = new_surf_lcl;
  1556. DOHALCALL(UnOptimizeSurface, pDDOptSurfInfo->UnOptimizeSurface, ddhal_uosd, ddrval, FALSE );
  1557. if (ddrval == DD_OK)
  1558. {
  1559. return DD_OK;
  1560. }
  1561. // If there was an error, then destroy the surface
  1562. // Since it is an empty surface, all we need to do is:
  1563. // i) unlink the surface from the ddraw-chain
  1564. // ii) on NT, inform the kernel
  1565. // iii) free all the allocated memory
  1566. // i)
  1567. prev_int = NULL;
  1568. pSurf_int = pdrv->dsList;
  1569. while ((pSurf_int != NULL) && (pSurf_int != new_surf_int))
  1570. {
  1571. prev_int = pSurf_int;
  1572. pSurf_int = pSurf_int->lpLink;
  1573. }
  1574. if (pSurf_int == new_surf_int)
  1575. {
  1576. prev_int->lpLink = new_surf_int->lpLink;
  1577. }
  1578. // ii)
  1579. #ifdef WINNT
  1580. DPF(8,"Attempting to destroy NT kernel mode surface object");
  1581. if (!DdDeleteSurfaceObject (new_surf_lcl))
  1582. {
  1583. DPF_ERR("NT kernel mode stuff won't delete its surface object!");
  1584. ddrval = DDERR_GENERIC;
  1585. }
  1586. #endif
  1587. // iii)
  1588. MemFree (new_surf_lcl);
  1589. return ddrval;
  1590. }
  1591. //-------------------------------------------------------------------------------
  1592. //
  1593. // Unoptimize method of IDirectDrawOptSurface
  1594. //
  1595. // Unoptimize an optimized surface. In doing so, it creates a new surface.
  1596. //
  1597. // The pDDSDest surface's PIXELFORMAT will be that of the pDDS in case the call
  1598. // succeeds. This means that the pixelformat of the original surface that was
  1599. // loaded is restored.
  1600. //
  1601. //-------------------------------------------------------------------------------
  1602. HRESULT
  1603. EXTERN_DDAPI
  1604. DD_OptSurface_Unoptimize(
  1605. LPDIRECTDRAWSURFACE pDDS,
  1606. LPDDSURFACEDESC2 pSurfDesc,
  1607. LPDIRECTDRAWSURFACE FAR *ppDDSDest,
  1608. IUnknown FAR *pUnkOuter)
  1609. {
  1610. LPDDRAWI_DDRAWSURFACE_INT this_int;
  1611. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  1612. LPDDRAWI_DDRAWSURFACE_GBL this;
  1613. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  1614. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  1615. HRESULT ddrval = DD_OK;
  1616. if( pUnkOuter != NULL )
  1617. {
  1618. return CLASS_E_NOAGGREGATION;
  1619. }
  1620. ENTER_DDRAW();
  1621. DPF(2,A,"ENTERAPI: DD_OptSurface_Unoptimize");
  1622. TRY
  1623. {
  1624. if( !VALID_DDSURFACEDESC2_PTR( pSurfDesc ) )
  1625. {
  1626. DPF_ERR( "Invalid surface description. Did you set the dwSize member?" );
  1627. LEAVE_DDRAW();
  1628. DPF_APIRETURNS(DDERR_INVALIDPARAMS);
  1629. return DDERR_INVALIDPARAMS;
  1630. }
  1631. this_int = (LPDDRAWI_DDRAWSURFACE_INT) pDDS;
  1632. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  1633. {
  1634. LEAVE_DDRAW();
  1635. return DDERR_INVALIDOBJECT;
  1636. }
  1637. this_lcl = this_int->lpLcl;
  1638. this = this_lcl->lpGbl;
  1639. if( SURFACE_LOST( this_lcl ) )
  1640. {
  1641. LEAVE_DDRAW();
  1642. return DDERR_SURFACELOST;
  1643. }
  1644. if( !VALID_PTR_PTR( ppDDSDest ) )
  1645. {
  1646. DPF_ERR( "Invalid dest. surface pointer" );
  1647. LEAVE_DDRAW();
  1648. return DDERR_INVALIDPARAMS;
  1649. }
  1650. *ppDDSDest = NULL;
  1651. }
  1652. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1653. {
  1654. DPF_ERR( "Exception encountered validating parameters" );
  1655. LEAVE_DDRAW();
  1656. return DDERR_INVALIDPARAMS;
  1657. }
  1658. //
  1659. // Quit with error if:
  1660. // 0) pSurfaceDesc not understood
  1661. // 1) No hardware
  1662. // 2) Hardware doesnt support optimized surfaces
  1663. // 3) Surface is an unoptimized surface
  1664. // 4) Surface is an empty optimized surface
  1665. // 5) The driver fails for some reason
  1666. //
  1667. // DDraw Gbl pointer
  1668. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  1669. pdrv = pdrv_lcl->lpGbl;
  1670. // 0)
  1671. if (pSurfDesc->ddsCaps.dwCaps & ~(DDSCAPS_SYSTEMMEMORY |
  1672. DDSCAPS_VIDEOMEMORY |
  1673. DDSCAPS_NONLOCALVIDMEM |
  1674. DDSCAPS_LOCALVIDMEM))
  1675. {
  1676. DPF_ERR ("Invalid flags");
  1677. LEAVE_DDRAW();
  1678. return DDERR_INVALIDCAPS;
  1679. }
  1680. // 1)
  1681. if( pdrv->dwFlags & DDRAWI_NOHARDWARE )
  1682. {
  1683. DPF_ERR ("No hardware present");
  1684. LEAVE_DDRAW();
  1685. return DDERR_NODIRECTDRAWHW;
  1686. }
  1687. // 2)
  1688. if ((0 == pdrv->lpDDOptSurfaceInfo) ||
  1689. !(pdrv->ddCaps.dwCaps2 & DDCAPS2_OPTIMIZEDSURFACES))
  1690. {
  1691. DPF_ERR ("Optimized surfaces not supported");
  1692. LEAVE_DDRAW();
  1693. return DDERR_NOOPTSURFACESUPPORT;
  1694. }
  1695. // 3)
  1696. if (!(this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED))
  1697. {
  1698. DPF_ERR ("Current surface is not an optimized surface");
  1699. LEAVE_DDRAW();
  1700. return DDERR_NOTANOPTIMIZEDSURFACE;
  1701. }
  1702. // 4)
  1703. if (this_lcl->dwFlags & DDRAWISURF_EMPTYSURFACE)
  1704. {
  1705. DPF_ERR ("Current surface is an empty optimized surface");
  1706. LEAVE_DDRAW();
  1707. return DDERR_ISANEMPTYOPTIMIZEDSURFACE;
  1708. }
  1709. // Do the actual unoptimize
  1710. ddrval = DoUnOptimize (pSurfDesc, this_lcl, this, ppDDSDest);
  1711. LEAVE_DDRAW();
  1712. return ddrval;
  1713. }