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.

2534 lines
74 KiB

  1. /*==========================================================================
  2. * Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved.
  3. *
  4. * File: ddsiunk.c
  5. * Content: DirectDraw surface IUnknown interface
  6. * Implements QueryInterface, AddRef, and Release
  7. * History:
  8. * Date By Reason
  9. * ==== == ======
  10. * 12-mar-95 craige split out of ddsurf.c; enhanced
  11. * 19-mar-95 craige use HRESULTs
  12. * 28-mar-95 craige use GETCURRPID
  13. * 01-apr-95 craige happy fun joy updated header file
  14. * 07-apr-95 craige bug 14 - check GUID ptr in QI
  15. * 09-apr-95 craige release Win16Lock
  16. * 06-may-95 craige use driver-level csects only
  17. * 12-may-95 craige check for real guids in QI
  18. * 19-may-95 craige free surface memory at the right time
  19. * 23-may-95 craige no longer use MapLS_Pool
  20. * 24-may-95 kylej add dirty rect when emulated overlay is released
  21. * 02-jun-95 craige redraw primary whenever a process does last release
  22. * 12-jun-95 craige new process list stuff
  23. * 16-jun-95 craige new surface structure
  24. * 18-jun-95 craige allow duplicate surfaces; creation of new interfaces
  25. * 20-jun-95 craige need to check fpVidMemOrig for deciding to flip
  26. * 21-jun-95 craige new streaming interface; work around compiler bug
  27. * 25-jun-95 craige one ddraw mutex
  28. * 26-jun-95 craige reorganized surface structure
  29. * 28-jun-95 craige ENTER_DDRAW at very start of fns; hide overlays
  30. * when destroyed if they're still visible
  31. * 30-jun-95 kylej don't free primary surface vidmem
  32. * 01-jul-95 craige removed streaming & composition stuff
  33. * 02-jul-95 craige fleshed out NewSurfaceInterface
  34. * 04-jul-95 craige YEEHAW: new driver struct; SEH
  35. * 08-jul-95 craige track invalid vs free
  36. * 19-jul-95 craige need to allow AddRef of lost surfaces
  37. * 17-aug-95 craige bug 557 - always turn off primay ptr in ddraw object
  38. * 05-sep-95 craige bug 902: only remove locks if lclrefcnt hits zero
  39. * 10-sep-95 craige bug 828: random vidmem heap free
  40. * 19-sep-95 craige bug 1205: free first vidmem destroyed
  41. * 10-nov-95 colinmc support for shared, AddRef'd palettes
  42. * 23-nov-95 colinmc now supports aggregatable Direct3D textures and
  43. * devices
  44. * 09-dec-95 colinmc added execute buffer support
  45. * 17-dec-95 colinmc added shared back and z buffer support
  46. * 22-dec-95 colinmc Direct3D support no longer conditional
  47. * 02-jan-96 kylej Handle new interface structs.
  48. * 10-jan-96 colinmc aggregated IUnknowns now maintained as a list
  49. * 13-jan-96 colinmc temporary hack to workround problem with Direct3D
  50. * cleanup
  51. * 26-jan-96 jeffno NT kernel object cleanup, FlipToGDISurface only 1 arg
  52. * 29-jan-96 colinmc Aggregated IUnknowns now contained in additional
  53. * surface local data structure
  54. * 08-feb-96 colinmc New D3D interface
  55. * 09-feb-96 colinmc Surface invalid flag moved from global to local
  56. * object
  57. * 13-mar-96 colinmc Added IID validation to QueryInterface
  58. * 16-mar-96 colinmc Fixed palette release problem (bug 13512)
  59. * 20-mar-96 colinmc Bug 13634: unidirectional attachments cause infinite
  60. * loop on cleanup
  61. * 23-mar-96 colinmc Bug 12252: Direct3D not cleaned up properly on
  62. * application termination
  63. * 24-mar-96 colinmc Bug 14321: not possible to specify back buffer and
  64. * mip-map count in a single call
  65. * 09-apr-96 colinmc Bug 16370: QueryInterface can fail with multiple
  66. * DirectDraw objects per process
  67. * 13-apr-96 colinmc Bug 17736: No notification to driver of flip to GDI
  68. * surface
  69. * 16-apr-96 kylej Bug 18103: Apps which use overlays can fault in
  70. * ProcessSurfaceCleanup
  71. * 29-apr-96 colinmc Bug 19954: Must query for Direct3D before textures
  72. * devices
  73. * 05-jul-96 colinmc Work Item: Remove requirement on taking Win16 lock
  74. * for VRAM surfaces (not primary)
  75. * 13-jan-97 jvanaken Basic support for IDirectDrawSurface3 interface
  76. * 29-jan-97 smac Update video port struct when surface is released
  77. * 22-feb-97 colinmc Enabled OWNDC for explicit system memory surfaces
  78. * 03-mar-97 smac Added kernel mode interface
  79. * 08-mar-97 colinmc Added function to allow surface pointer to be
  80. * overridden
  81. * 10-mar-97 smac Fixed bug 5211 by hiding overlays in DestroySurface
  82. * 11-mar-97 jeffno Asynchronous DMA support
  83. * 31-oct-97 johnstep Persistent-content surfaces for Windows 9x
  84. * 05-nov-97 jvanaken Support for master sprite list in SetSpriteDisplayList
  85. *
  86. ***************************************************************************/
  87. #include "ddrawpr.h"
  88. #ifdef WINNT
  89. #include "ddrawgdi.h"
  90. #endif
  91. // function in ddsprite.c to remove invalid surface from master sprite list
  92. extern void RemoveSpriteSurface(LPDDRAWI_DIRECTDRAW_GBL, LPDDRAWI_DDRAWSURFACE_INT);
  93. #ifdef REFTRACKING
  94. void AddRefTrack(LPVOID * p)
  95. {
  96. LPDDRAWI_DDRAWSURFACE_INT pInt = (LPDDRAWI_DDRAWSURFACE_INT) *p;
  97. LPDDRAWI_REFTRACKNODE pNode;
  98. pInt->RefTrack.pLastAddref = *(p-1); //This pulls the return address off the stack
  99. //Now store this addref in the linked list of addrefs/releases
  100. //Step 1: Search for previously existing addref/release with this ret address
  101. pNode = pInt->RefTrack.pHead;
  102. while (pNode)
  103. {
  104. if ( pNode->pReturnAddress == *(p-1) )
  105. {
  106. break;
  107. }
  108. pNode = pNode->pNext;
  109. }
  110. if (!pNode)
  111. {
  112. pNode = (LPDDRAWI_REFTRACKNODE) MemAlloc(sizeof(DDRAWI_REFTRACKNODE));
  113. pNode->pReturnAddress = *(p-1);
  114. pNode->pNext = pInt->RefTrack.pHead;
  115. pInt->RefTrack.pHead = pNode;
  116. }
  117. pNode->dwAddrefCount++;
  118. }
  119. void ReleaseTrack(LPVOID * p)
  120. {
  121. LPDDRAWI_DDRAWSURFACE_INT pInt = (LPDDRAWI_DDRAWSURFACE_INT) *p;
  122. LPDDRAWI_REFTRACKNODE pNode;
  123. pInt->RefTrack.pLastRelease = *(p-1); //This pulls the return address off the stack
  124. //Now store this release in the linked list of addrefs/releases
  125. //Step 1: Search for previously existing addref/release with this ret address
  126. pNode = pInt->RefTrack.pHead;
  127. while (pNode)
  128. {
  129. if ( pNode->pReturnAddress == *(p-1) )
  130. {
  131. break;
  132. }
  133. pNode = pNode->pNext;
  134. }
  135. if (!pNode)
  136. {
  137. pNode = (LPDDRAWI_REFTRACKNODE) MemAlloc(sizeof(DDRAWI_REFTRACKNODE));
  138. pNode->pReturnAddress = *(p-1);
  139. pNode->pNext = pInt->RefTrack.pHead;
  140. pInt->RefTrack.pHead = pNode;
  141. }
  142. pNode->dwReleaseCount++;
  143. }
  144. void DumpRefTrack(LPVOID p)
  145. {
  146. LPDDRAWI_DDRAWSURFACE_INT pInt = (LPDDRAWI_DDRAWSURFACE_INT) p;
  147. LPDDRAWI_REFTRACKNODE pNode;
  148. char msg[100];
  149. wsprintf(msg,"Interface %08x:\r\n LastAddRef:%08x\r\n Last Release:%08x\r\n",
  150. pInt,
  151. pInt->RefTrack.pLastAddref,
  152. pInt->RefTrack.pLastRelease);
  153. OutputDebugString(msg);
  154. pNode = pInt->RefTrack.pHead;
  155. while (pNode)
  156. {
  157. wsprintf(msg," Address %08x had %d Addrefs and %d Releases\r\n",
  158. pNode->pReturnAddress,
  159. pNode->dwAddrefCount,
  160. pNode->dwReleaseCount);
  161. OutputDebugString(msg);
  162. pNode = pNode->pNext;
  163. }
  164. }
  165. #endif //REFTRACKING
  166. /*
  167. * FindIUnknown
  168. *
  169. * Locate an aggredate IUnknown with the given IID (or NULL if no such
  170. * interface exists).
  171. */
  172. static IUnknown FAR *FindIUnknown(LPDDRAWI_DDRAWSURFACE_LCL pThisLCL, REFIID riid)
  173. {
  174. LPIUNKNOWN_LIST lpIUnknownNode;
  175. lpIUnknownNode = pThisLCL->lpSurfMore->lpIUnknowns;
  176. while( lpIUnknownNode != NULL )
  177. {
  178. if( IsEqualIID( riid, lpIUnknownNode->lpGuid ) )
  179. return lpIUnknownNode->lpIUnknown;
  180. lpIUnknownNode = lpIUnknownNode->lpLink;
  181. }
  182. return NULL;
  183. }
  184. /*
  185. * InsertIUnknown
  186. *
  187. * Insert a new IUnknown with its associated IID into the IUnknown list of the
  188. * given surface.
  189. */
  190. static LPIUNKNOWN_LIST InsertIUnknown(
  191. LPDDRAWI_DDRAWSURFACE_LCL pThisLCL,
  192. REFIID riid,
  193. IUnknown FAR *lpIUnknown)
  194. {
  195. LPIUNKNOWN_LIST lpIUnknownNode;
  196. DPF( 4, "Adding aggregated IUnknown %x", lpIUnknown );
  197. lpIUnknownNode = ( LPIUNKNOWN_LIST ) MemAlloc( sizeof( IUNKNOWN_LIST ) );
  198. if( lpIUnknownNode == NULL )
  199. return NULL;
  200. lpIUnknownNode->lpGuid = ( GUID FAR * ) MemAlloc( sizeof( GUID ) );
  201. if( lpIUnknownNode->lpGuid == NULL )
  202. {
  203. MemFree( lpIUnknownNode );
  204. return NULL;
  205. }
  206. memcpy( lpIUnknownNode->lpGuid, riid, sizeof( GUID ) );
  207. lpIUnknownNode->lpLink = pThisLCL->lpSurfMore->lpIUnknowns;
  208. lpIUnknownNode->lpIUnknown = lpIUnknown;
  209. pThisLCL->lpSurfMore->lpIUnknowns = lpIUnknownNode;
  210. return lpIUnknownNode;
  211. }
  212. /*
  213. * FreeIUnknowns
  214. *
  215. * Free all the nodes in the IUnknown list of the given local
  216. * surface object and NULL out the object's IUnknown list. If
  217. * fRelease is TRUE then release will be called on the IUnknown
  218. * interfaces.
  219. */
  220. static void FreeIUnknowns( LPDDRAWI_DDRAWSURFACE_LCL pThisLCL, BOOL fRelease )
  221. {
  222. LPIUNKNOWN_LIST lpIUnknownNode;
  223. LPIUNKNOWN_LIST lpLink;
  224. lpIUnknownNode = pThisLCL->lpSurfMore->lpIUnknowns;
  225. while( lpIUnknownNode != NULL )
  226. {
  227. lpLink = lpIUnknownNode->lpLink;
  228. if( fRelease )
  229. {
  230. DPF( 4, "Releasing aggregated IUnknown %x", lpIUnknownNode->lpIUnknown );
  231. lpIUnknownNode->lpIUnknown->lpVtbl->Release( lpIUnknownNode->lpIUnknown );
  232. }
  233. MemFree( lpIUnknownNode->lpGuid );
  234. MemFree( lpIUnknownNode );
  235. lpIUnknownNode = lpLink;
  236. }
  237. pThisLCL->lpSurfMore->lpIUnknowns = NULL;
  238. }
  239. /*
  240. * NewSurfaceLocal
  241. *
  242. * Construct a new surface local object.
  243. */
  244. //Note: lpVtbl doesnt, seem to be used
  245. LPDDRAWI_DDRAWSURFACE_LCL NewSurfaceLocal( LPDDRAWI_DDRAWSURFACE_LCL this_lcl, LPVOID lpvtbl )
  246. {
  247. LPDDRAWI_DDRAWSURFACE_LCL pnew_lcl;
  248. DWORD surf_size_lcl;
  249. DWORD surf_size;
  250. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  251. /*
  252. * NOTE: This single allocation can allocate space for local surface
  253. * structure (DDRAWI_DDRAWSURFACE_LCL) and the additional local surface
  254. * structure (DDRAWI_DDRAWSURFACE_MORE). As the local object can be
  255. * variable sized this can get pretty complex. The layout of the
  256. * various objects in the allocation is as follows:
  257. *
  258. * +-----------------+---------------+
  259. * | SURFACE_LCL | SURFACE_MORE |
  260. * | (variable) | |
  261. * +-----------------+---------------+
  262. * <- surf_size_lcl ->
  263. * <- surf_size --------------------->
  264. */
  265. if( this_lcl->dwFlags & DDRAWISURF_HASOVERLAYDATA )
  266. {
  267. DPF( 4, "OVERLAY DATA SPACE" );
  268. surf_size_lcl = sizeof( DDRAWI_DDRAWSURFACE_LCL );
  269. }
  270. else
  271. {
  272. surf_size_lcl = offsetof( DDRAWI_DDRAWSURFACE_LCL, ddckCKSrcOverlay );
  273. }
  274. surf_size = surf_size_lcl + sizeof( DDRAWI_DDRAWSURFACE_MORE );
  275. pnew_lcl = MemAlloc( surf_size );
  276. if( pnew_lcl == NULL )
  277. {
  278. return NULL;
  279. }
  280. pdrv = this_lcl->lpGbl->lpDD;
  281. /*
  282. * set up local data
  283. */
  284. pnew_lcl->lpSurfMore = (LPDDRAWI_DDRAWSURFACE_MORE) (((LPSTR) pnew_lcl) + surf_size_lcl);
  285. pnew_lcl->lpGbl = this_lcl->lpGbl;
  286. pnew_lcl->lpAttachList = NULL;
  287. pnew_lcl->lpAttachListFrom = NULL;
  288. pnew_lcl->dwProcessId = GetCurrentProcessId();
  289. pnew_lcl->dwLocalRefCnt = 0;
  290. pnew_lcl->dwFlags = this_lcl->dwFlags;
  291. pnew_lcl->ddsCaps = this_lcl->ddsCaps;
  292. pnew_lcl->lpDDPalette = NULL;
  293. pnew_lcl->lpDDClipper = NULL;
  294. pnew_lcl->lpSurfMore->lpDDIClipper = NULL;
  295. pnew_lcl->dwBackBufferCount = 0;
  296. pnew_lcl->ddckCKDestBlt.dwColorSpaceLowValue = 0;
  297. pnew_lcl->ddckCKDestBlt.dwColorSpaceHighValue = 0;
  298. pnew_lcl->ddckCKSrcBlt.dwColorSpaceLowValue = 0;
  299. pnew_lcl->ddckCKSrcBlt.dwColorSpaceHighValue = 0;
  300. pnew_lcl->dwReserved1 = this_lcl->dwReserved1;
  301. /*
  302. * set up overlay specific data
  303. */
  304. if( this_lcl->dwFlags & DDRAWISURF_HASOVERLAYDATA )
  305. {
  306. pnew_lcl->ddckCKDestOverlay.dwColorSpaceLowValue = 0;
  307. pnew_lcl->ddckCKDestOverlay.dwColorSpaceHighValue = 0;
  308. pnew_lcl->ddckCKSrcOverlay.dwColorSpaceLowValue = 0;
  309. pnew_lcl->ddckCKSrcOverlay.dwColorSpaceHighValue = 0;
  310. pnew_lcl->lpSurfaceOverlaying = NULL;
  311. pnew_lcl->rcOverlaySrc.top = 0;
  312. pnew_lcl->rcOverlaySrc.left = 0;
  313. pnew_lcl->rcOverlaySrc.bottom = 0;
  314. pnew_lcl->rcOverlaySrc.right = 0;
  315. pnew_lcl->rcOverlayDest.top = 0;
  316. pnew_lcl->rcOverlayDest.left = 0;
  317. pnew_lcl->rcOverlayDest.bottom = 0;
  318. pnew_lcl->rcOverlayDest.right = 0;
  319. pnew_lcl->dwClrXparent = 0;
  320. pnew_lcl->dwAlpha = 0;
  321. /*
  322. * if this is an overlay, link it in
  323. */
  324. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY )
  325. {
  326. pnew_lcl->dbnOverlayNode.next = pdrv->dbnOverlayRoot.next;
  327. pnew_lcl->dbnOverlayNode.prev = (LPVOID)(&(pdrv->dbnOverlayRoot));
  328. pdrv->dbnOverlayRoot.next = (LPVOID)(&(pnew_lcl->dbnOverlayNode));
  329. pnew_lcl->dbnOverlayNode.next->prev = (LPVOID)(&(pnew_lcl->dbnOverlayNode));
  330. // pnew_lcl->dbnOverlayNode.object = pnew_int;
  331. }
  332. }
  333. /*
  334. * turn off flags that aren't valid
  335. */
  336. pnew_lcl->dwFlags &= ~(DDRAWISURF_ATTACHED |
  337. DDRAWISURF_ATTACHED_FROM |
  338. DDRAWISURF_HASCKEYDESTOVERLAY |
  339. DDRAWISURF_HASCKEYDESTBLT |
  340. DDRAWISURF_HASCKEYSRCOVERLAY |
  341. DDRAWISURF_HASCKEYSRCBLT |
  342. DDRAWISURF_SW_CKEYDESTOVERLAY |
  343. DDRAWISURF_SW_CKEYDESTBLT |
  344. DDRAWISURF_SW_CKEYSRCOVERLAY |
  345. DDRAWISURF_SW_CKEYSRCBLT |
  346. DDRAWISURF_HW_CKEYDESTOVERLAY |
  347. DDRAWISURF_HW_CKEYDESTBLT |
  348. DDRAWISURF_HW_CKEYSRCOVERLAY |
  349. DDRAWISURF_HW_CKEYSRCBLT |
  350. DDRAWISURF_FRONTBUFFER |
  351. DDRAWISURF_BACKBUFFER );
  352. /*
  353. * Additional local surface data.
  354. */
  355. pnew_lcl->lpSurfMore->dwSize = sizeof( DDRAWI_DDRAWSURFACE_MORE );
  356. pnew_lcl->lpSurfMore->lpIUnknowns = NULL;
  357. pnew_lcl->lpSurfMore->lpDD_lcl = NULL;
  358. pnew_lcl->lpSurfMore->dwMipMapCount = 0UL;
  359. #ifdef WIN95
  360. pnew_lcl->dwModeCreatedIn = this_lcl->dwModeCreatedIn;
  361. #else
  362. pnew_lcl->lpSurfMore->dmiCreated = this_lcl->lpSurfMore->dmiCreated;
  363. #endif
  364. return pnew_lcl;
  365. } /* NewSurfaceLocal */
  366. /*
  367. * NewSurfaceInterface
  368. *
  369. * Construct a new surface interface and local object.
  370. */
  371. LPDDRAWI_DDRAWSURFACE_INT NewSurfaceInterface( LPDDRAWI_DDRAWSURFACE_LCL this_lcl, LPVOID lpvtbl )
  372. {
  373. LPDDRAWI_DDRAWSURFACE_INT pnew_int;
  374. LPDDRAWI_DDRAWSURFACE_INT curr_int;
  375. LPDDRAWI_DDRAWSURFACE_INT last_int;
  376. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  377. pdrv = this_lcl->lpGbl->lpDD;
  378. /*
  379. * try recycle the surface from list of all free interfeaces
  380. */
  381. curr_int = pdrv->dsFreeList;
  382. last_int = NULL;
  383. pnew_int = NULL;
  384. while( curr_int )
  385. {
  386. DDASSERT(0 == curr_int->dwIntRefCnt);
  387. if ( curr_int->lpLcl == this_lcl && curr_int->lpVtbl == lpvtbl)
  388. {
  389. pnew_int = curr_int;
  390. if (last_int)
  391. {
  392. last_int->lpLink = curr_int->lpLink;
  393. }
  394. else
  395. {
  396. pdrv->dsFreeList = curr_int->lpLink;
  397. }
  398. break;
  399. }
  400. last_int = curr_int;
  401. curr_int = curr_int->lpLink;
  402. }
  403. if ( NULL == pnew_int)
  404. {
  405. pnew_int = MemAlloc( sizeof( DDRAWI_DDRAWSURFACE_INT ) );
  406. if( NULL == pnew_int )
  407. return NULL;
  408. /*
  409. * set up interface data
  410. */
  411. pnew_int->lpVtbl = lpvtbl;
  412. pnew_int->lpLcl = this_lcl;
  413. }
  414. pnew_int->lpLink = pdrv->dsList;
  415. pdrv->dsList = pnew_int;
  416. pnew_int->dwIntRefCnt = 0;
  417. return pnew_int;
  418. } /* NewSurfaceInterface */
  419. #undef DPF_MODNAME
  420. #define DPF_MODNAME "QueryInterface"
  421. /*
  422. * getDDSInterface
  423. */
  424. LPDDRAWI_DDRAWSURFACE_INT getDDSInterface( LPDDRAWI_DIRECTDRAW_GBL pdrv,
  425. LPDDRAWI_DDRAWSURFACE_LCL this_lcl,
  426. LPVOID lpddcb )
  427. {
  428. LPDDRAWI_DDRAWSURFACE_INT curr_int;
  429. for( curr_int = pdrv->dsList; curr_int != NULL; curr_int = curr_int->lpLink )
  430. {
  431. if( (curr_int->lpLcl == this_lcl) &&
  432. (curr_int->lpVtbl == lpddcb) )
  433. {
  434. break;
  435. }
  436. }
  437. if( NULL == curr_int )
  438. {
  439. // Couldn't find an existing interface, create one.
  440. curr_int = NewSurfaceInterface( this_lcl, lpddcb );
  441. }
  442. return curr_int;
  443. }
  444. /*
  445. * DD_Surface_QueryInterface
  446. */
  447. HRESULT DDAPI DD_Surface_QueryInterface(
  448. LPDIRECTDRAWSURFACE lpDDSurface,
  449. REFIID riid,
  450. LPVOID FAR * ppvObj )
  451. {
  452. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  453. LPDDRAWI_DDRAWSURFACE_INT this_int;
  454. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  455. #ifdef STREAMING
  456. LPDDRAWI_DDRAWSURFACE_GBLSTREAMING psurf_streaming;
  457. #endif
  458. LPDDRAWI_DDRAWSURFACE_GBL this;
  459. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  460. LPDDRAWI_DIRECTDRAW_INT pdrv_int;
  461. D3DCreateTextProc lpfnD3DCreateTextProc;
  462. D3DCreateDeviceProc lpfnD3DCreateDeviceProc;
  463. HRESULT rval;
  464. IUnknown FAR* lpIUnknown;
  465. ENTER_DDRAW();
  466. DPF(2,A,"ENTERAPI: DD_Surface_QueryInterface");
  467. /*
  468. * validate parms
  469. */
  470. TRY
  471. {
  472. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  473. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  474. {
  475. DPF_ERR( "Invalid surface pointer" );
  476. LEAVE_DDRAW();
  477. return DDERR_INVALIDOBJECT;
  478. }
  479. this_lcl = this_int->lpLcl;
  480. if( !VALID_PTR_PTR( ppvObj ) )
  481. {
  482. DPF_ERR( "Invalid surface interface pointer" );
  483. LEAVE_DDRAW();
  484. return DDERR_INVALIDPARAMS;
  485. }
  486. *ppvObj = NULL;
  487. if( !VALIDEX_IID_PTR( riid ) )
  488. {
  489. DPF_ERR( "Invalid IID pointer" );
  490. LEAVE_DDRAW();
  491. return DDERR_INVALIDPARAMS;
  492. }
  493. this = this_lcl->lpGbl;
  494. pdrv = this->lpDD;
  495. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  496. pdrv_int = this_lcl->lpSurfMore->lpDD_int;
  497. }
  498. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  499. {
  500. DPF_ERR( "Exception encountered validating parameters" );
  501. LEAVE_DDRAW();
  502. return DDERR_INVALIDPARAMS;
  503. }
  504. /*
  505. * asking for IDirectDrawSurfaceNew?
  506. * Internal only: called by D3D after creating a vertex buffer so we
  507. * don't have to run the surface list only - which is pointless since we've just
  508. * created the surface
  509. */
  510. if( IsEqualIID(riid, &IID_IDirectDrawSurfaceNew) )
  511. {
  512. if( this_int->lpVtbl == (LPVOID) &ddSurfaceCallbacks )
  513. *ppvObj = (LPVOID) this_int;
  514. else
  515. *ppvObj = (LPVOID) NewSurfaceInterface( this_int->lpLcl, &ddSurfaceCallbacks );
  516. if( NULL == *ppvObj )
  517. {
  518. LEAVE_DDRAW();
  519. return E_NOINTERFACE;
  520. }
  521. else
  522. {
  523. DD_Surface_AddRef( *ppvObj );
  524. LEAVE_DDRAW();
  525. return DD_OK;
  526. }
  527. }
  528. /*
  529. * asking for IUnknown?
  530. */
  531. if( IsEqualIID(riid, &IID_IUnknown) ||
  532. IsEqualIID(riid, &IID_IDirectDrawSurface) )
  533. {
  534. /*
  535. * Our IUnknown interface is the same as our V1
  536. * interface. We must always return the V1 interface
  537. * if IUnknown is requested.
  538. */
  539. if( this_int->lpVtbl == &ddSurfaceCallbacks )
  540. *ppvObj = (LPVOID) this_int;
  541. else
  542. *ppvObj = (LPVOID) getDDSInterface( pdrv, this_int->lpLcl, &ddSurfaceCallbacks );
  543. if( NULL == *ppvObj )
  544. {
  545. LEAVE_DDRAW();
  546. return E_NOINTERFACE;
  547. }
  548. else
  549. {
  550. DD_Surface_AddRef( *ppvObj );
  551. LEAVE_DDRAW();
  552. return DD_OK;
  553. }
  554. }
  555. /*
  556. * asking for IDirectDrawSurface2?
  557. */
  558. if( IsEqualIID(riid, &IID_IDirectDrawSurface2) )
  559. {
  560. /*
  561. * if this is already an IDirectDrawSurface2 interface, just
  562. * addref and return
  563. */
  564. if( this_int->lpVtbl == (LPVOID) &ddSurface2Callbacks )
  565. *ppvObj = (LPVOID) this_int;
  566. else
  567. *ppvObj = (LPVOID) getDDSInterface( pdrv, this_int->lpLcl, &ddSurface2Callbacks );
  568. if( NULL == *ppvObj )
  569. {
  570. LEAVE_DDRAW();
  571. return E_NOINTERFACE;
  572. }
  573. else
  574. {
  575. DD_Surface_AddRef( *ppvObj );
  576. LEAVE_DDRAW();
  577. return DD_OK;
  578. }
  579. }
  580. /*
  581. * asking for IDirectDrawSurface3?
  582. */
  583. if( IsEqualIID(riid, &IID_IDirectDrawSurface3) )
  584. {
  585. /*
  586. * if this is already an IDirectDrawSurface3 interface, just
  587. * addref and return
  588. */
  589. if( this_int->lpVtbl == (LPVOID) &ddSurface3Callbacks )
  590. *ppvObj = (LPVOID) this_int;
  591. else
  592. *ppvObj = (LPVOID) getDDSInterface( pdrv, this_int->lpLcl, &ddSurface3Callbacks );
  593. if( NULL == *ppvObj )
  594. {
  595. LEAVE_DDRAW();
  596. return E_NOINTERFACE;
  597. }
  598. else
  599. {
  600. DD_Surface_AddRef( *ppvObj );
  601. LEAVE_DDRAW();
  602. return DD_OK;
  603. }
  604. }
  605. /*
  606. * asking for IDirectDrawSurface4?
  607. */
  608. if( IsEqualIID(riid, &IID_IDirectDrawSurface4) )
  609. {
  610. /*
  611. * if this is already an IDirectDrawSurface4 interface, just
  612. * addref and return
  613. */
  614. if( this_int->lpVtbl == (LPVOID) &ddSurface4Callbacks )
  615. *ppvObj = (LPVOID) this_int;
  616. else
  617. *ppvObj = (LPVOID) getDDSInterface( pdrv, this_int->lpLcl, &ddSurface4Callbacks );
  618. if( NULL == *ppvObj )
  619. {
  620. LEAVE_DDRAW();
  621. return E_NOINTERFACE;
  622. }
  623. else
  624. {
  625. DD_Surface_AddRef( *ppvObj );
  626. LEAVE_DDRAW();
  627. return DD_OK;
  628. }
  629. }
  630. /*
  631. * asking for IDirectDrawSurface7?
  632. */
  633. if( IsEqualIID(riid, &IID_IDirectDrawSurface7) )
  634. {
  635. /*
  636. * if this is already an IDirectDrawSurface7 interface, just
  637. * addref and return
  638. */
  639. if( this_int->lpVtbl == (LPVOID) &ddSurface7Callbacks )
  640. *ppvObj = (LPVOID) this_int;
  641. else
  642. *ppvObj = (LPVOID) getDDSInterface( pdrv, this_int->lpLcl, &ddSurface7Callbacks );
  643. if( NULL == *ppvObj )
  644. {
  645. LEAVE_DDRAW();
  646. return E_NOINTERFACE;
  647. }
  648. else
  649. {
  650. DD_Surface_AddRef( *ppvObj );
  651. LEAVE_DDRAW();
  652. return DD_OK;
  653. }
  654. }
  655. /*
  656. * asking for IDirectDrawColorControl
  657. */
  658. if( IsEqualIID(riid, &IID_IDirectDrawColorControl) )
  659. {
  660. /*
  661. * Color controls only work for an overlay/primary surface
  662. */
  663. if( this_int->lpLcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE )
  664. {
  665. if( !( pdrv->ddCaps.dwCaps2 & DDCAPS2_COLORCONTROLPRIMARY ) )
  666. {
  667. LEAVE_DDRAW();
  668. return E_NOINTERFACE;
  669. }
  670. }
  671. else if( this_int->lpLcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY )
  672. {
  673. if( !( pdrv->ddCaps.dwCaps2 & DDCAPS2_COLORCONTROLOVERLAY ) )
  674. {
  675. LEAVE_DDRAW();
  676. return E_NOINTERFACE;
  677. }
  678. }
  679. else
  680. {
  681. LEAVE_DDRAW();
  682. return E_NOINTERFACE;
  683. }
  684. /*
  685. * if this is already an IDirectDrawColorControl interface, just
  686. * addref and return
  687. */
  688. if( this_int->lpVtbl == (LPVOID) &ddColorControlCallbacks )
  689. *ppvObj = (LPVOID) this_int;
  690. else
  691. *ppvObj = (LPVOID) getDDSInterface( pdrv, this_int->lpLcl, &ddColorControlCallbacks );
  692. if( NULL == *ppvObj )
  693. {
  694. LEAVE_DDRAW();
  695. return E_NOINTERFACE;
  696. }
  697. else
  698. {
  699. DD_Surface_AddRef( *ppvObj );
  700. LEAVE_DDRAW();
  701. return DD_OK;
  702. }
  703. }
  704. /*
  705. * asking for IDirectDrawGammaControl
  706. */
  707. if( IsEqualIID(riid, &IID_IDirectDrawGammaControl) )
  708. {
  709. /*
  710. * if this is already an IDirectDrawGammaControl interface, just
  711. * addref and return
  712. */
  713. if( this_int->lpVtbl == (LPVOID) &ddGammaControlCallbacks )
  714. *ppvObj = (LPVOID) this_int;
  715. else
  716. *ppvObj = (LPVOID) getDDSInterface( pdrv, this_int->lpLcl, &ddGammaControlCallbacks );
  717. if( NULL == *ppvObj )
  718. {
  719. LEAVE_DDRAW();
  720. return E_NOINTERFACE;
  721. }
  722. else
  723. {
  724. DD_Surface_AddRef( *ppvObj );
  725. LEAVE_DDRAW();
  726. return DD_OK;
  727. }
  728. }
  729. /*
  730. * asking for IDirectDrawSurfaceKernel
  731. */
  732. if( IsEqualIID(riid, &IID_IDirectDrawSurfaceKernel) )
  733. {
  734. /*
  735. * Don't create the interface if the VDD didn't load or if we
  736. * don't have the DisplayDeviceHandle.
  737. */
  738. if( !IsKernelInterfaceSupported( pdrv_lcl ) )
  739. {
  740. DPF( 0, "Kernel Mode interface not supported" );
  741. LEAVE_DDRAW();
  742. return E_NOINTERFACE;
  743. }
  744. /*
  745. * if this is already an IDirectDrawSurfaceKernel interface, just
  746. * addref and return
  747. */
  748. if( this_int->lpVtbl == (LPVOID) &ddSurfaceKernelCallbacks )
  749. *ppvObj = (LPVOID) this_int;
  750. else
  751. *ppvObj = (LPVOID) getDDSInterface( pdrv, this_int->lpLcl, &ddSurfaceKernelCallbacks );
  752. if( NULL == *ppvObj )
  753. {
  754. LEAVE_DDRAW();
  755. return E_NOINTERFACE;
  756. }
  757. else
  758. {
  759. DD_Surface_AddRef( *ppvObj );
  760. LEAVE_DDRAW();
  761. return DD_OK;
  762. }
  763. }
  764. #ifdef POSTPONED
  765. /*
  766. * asking for IPersist
  767. */
  768. if( IsEqualIID(riid, &IID_IPersist) )
  769. {
  770. /*
  771. * if this is already an IID_IPersist interface, just
  772. * addref and return
  773. */
  774. if( this_int->lpVtbl == (LPVOID) &ddSurfacePersistCallbacks )
  775. *ppvObj = (LPVOID) this_int;
  776. else
  777. *ppvObj = (LPVOID) getDDSInterface( pdrv, this_int->lpLcl, &ddSurfacePersistCallbacks );
  778. if( NULL == *ppvObj )
  779. {
  780. LEAVE_DDRAW();
  781. return E_NOINTERFACE;
  782. }
  783. else
  784. {
  785. DD_Surface_AddRef( *ppvObj );
  786. LEAVE_DDRAW();
  787. return DD_OK;
  788. }
  789. }
  790. /*
  791. * asking for IPersistStream
  792. */
  793. if( IsEqualIID(riid, &IID_IPersistStream) )
  794. {
  795. /*
  796. * if this is already an IID_IPersist interface, just
  797. * addref and return
  798. */
  799. if( this_int->lpVtbl == (LPVOID) &ddSurfacePersistStreamCallbacks )
  800. *ppvObj = (LPVOID) this_int;
  801. else
  802. *ppvObj = (LPVOID) getDDSInterface( pdrv, this_int->lpLcl, &ddSurfacePersistStreamCallbacks );
  803. if( NULL == *ppvObj )
  804. {
  805. LEAVE_DDRAW();
  806. return E_NOINTERFACE;
  807. }
  808. else
  809. {
  810. DD_Surface_AddRef( *ppvObj );
  811. LEAVE_DDRAW();
  812. return DD_OK;
  813. }
  814. }
  815. /*
  816. * asking for IDirectDrawOptSurface
  817. */
  818. if( IsEqualIID(riid, &IID_IDirectDrawOptSurface) )
  819. {
  820. /*
  821. * if this is already an IID_IDirectDrawOptSurface interface, just
  822. * addref and return
  823. */
  824. if( this_int->lpVtbl == (LPVOID) &ddOptSurfaceCallbacks )
  825. *ppvObj = (LPVOID) this_int;
  826. else
  827. *ppvObj = (LPVOID) getDDSInterface( pdrv, this_int->lpLcl,
  828. &ddOptSurfaceCallbacks );
  829. if( NULL == *ppvObj )
  830. {
  831. LEAVE_DDRAW();
  832. return E_NOINTERFACE;
  833. }
  834. else
  835. {
  836. DD_Surface_AddRef( *ppvObj );
  837. LEAVE_DDRAW();
  838. return DD_OK;
  839. }
  840. }
  841. #endif //POSTPONED
  842. #ifdef STREAMING
  843. /*
  844. * asking for IDirectDrawSurfaceStreaming?
  845. */
  846. if( IsEqualIID(riid, &IID_IDirectDrawSurfaceStreaming) )
  847. {
  848. /*
  849. * if this is already an IDirectDrawSurfaceStreaming interface,
  850. * just addref and return
  851. */
  852. if( this_int->lpVtbl == (LPVOID) &ddSurfaceStreamingCallbacks )
  853. {
  854. DD_Surface_AddRef( (LPDIRECTDRAWSURFACE) this_int );
  855. *ppvObj = (LPVOID) this_int;
  856. }
  857. /*
  858. * not an IDirectDrawSurfaceStreaming interface, so we need to
  859. * create one
  860. */
  861. else
  862. {
  863. psurf_streaming = NewSurfaceInterface( this_lcl, &ddSurfaceStreamingCallbacks );
  864. if( psurf_streaming == NULL )
  865. {
  866. LEAVE_DDRAW();
  867. return DDERR_OUTOFMEMORY;
  868. }
  869. *ppvObj = (LPVOID) psurf_streaming;
  870. }
  871. LEAVE_DDRAW();
  872. return DD_OK;
  873. }
  874. #endif
  875. #ifdef COMPOSITION
  876. /*
  877. * asking for IDirectDrawSurfaceComposition?
  878. */
  879. if( IsEqualIID(riid, &IID_IDirectDrawSurfaceComposition) )
  880. {
  881. }
  882. #endif
  883. DPF( 4, "IID not understood by Surface QueryInterface - trying Direct3D" );
  884. /*
  885. * We maintain a list of IUnknowns aggregated by each surface.
  886. * These IUnknowns are lazily evaluated, i.e., we only create
  887. * the underlying aggregated object when someone requests the
  888. * the IUnknown via QueryInterface.
  889. *
  890. * We could just hardcode the Direct3D interfaces, check for
  891. * them here and create the appropriate interface but that's
  892. * inflexible and we would have to track new interfaces added
  893. * to Direct3D (a particularly big problem as there are likely
  894. * to be many Direct3DDevice interfaces for different device
  895. * types). So instead, we probe Direct3D but trying its create
  896. * functions with the IID we have been passed and seeing if
  897. * it suceeds or not.
  898. */
  899. /*
  900. * Do we have an existing aggregated IUnknown for this IID?
  901. */
  902. lpIUnknown = FindIUnknown( this_lcl, riid );
  903. if( lpIUnknown == NULL )
  904. {
  905. if (DDRAWILCL_DIRECTDRAW7 & pdrv_lcl->dwLocalFlags)
  906. {
  907. DPF(0,"running %s, no texture interface for Query", D3DDX7_DLLNAME);
  908. LEAVE_DDRAW();
  909. return E_NOINTERFACE;
  910. }
  911. if( !D3D_INITIALIZED( pdrv_lcl ) )
  912. {
  913. /*
  914. * Direct3D is not yet initialized. Before we can attempt
  915. * to query for the texture or device interface we must
  916. * initialize it.
  917. *
  918. * NOTE: Currently if initialization fails for any reason
  919. * we fail the QueryInterface() with the error returned
  920. * by InitD3D() (which will be E_NOINTERFACE if Direct3D
  921. * is not properly installed). If we ever end up aggregating
  922. * anything else then this is going to be WRONG as we may
  923. * end up failing a query for a completely unrelated
  924. * interface just because Direct3D failed to initialize.
  925. * Hence, we must rethink this if we end up aggregating
  926. * anything else.
  927. */
  928. rval = InitD3D( pdrv_int );
  929. if( FAILED( rval ) )
  930. {
  931. DPF_ERR( "Could not initialize Direct3D" );
  932. LEAVE_DDRAW();
  933. return rval;
  934. }
  935. }
  936. DDASSERT( D3D_INITIALIZED( pdrv_lcl ) );
  937. /*
  938. * No matching interface yet - is it a Direct3D texture IID?
  939. */
  940. lpfnD3DCreateTextProc = (D3DCreateTextProc) GetProcAddress( pdrv_lcl->hD3DInstance, D3DCREATETEXTURE_PROCNAME );
  941. if( lpfnD3DCreateTextProc != NULL )
  942. {
  943. DPF( 4, "Attempting to create Direct3D Texture interface" );
  944. rval = (*lpfnD3DCreateTextProc)( riid, lpDDSurface, &lpIUnknown, (LPUNKNOWN)lpDDSurface );
  945. if( rval == DD_OK )
  946. {
  947. /*
  948. * Found the interface. Add it to our list.
  949. */
  950. if( InsertIUnknown( this_lcl, riid, lpIUnknown ) == NULL )
  951. {
  952. /*
  953. * Insufficient memory. Discard the interface and fail.
  954. */
  955. DPF_ERR( "Insufficient memory to aggregate the Direct3D Texture interface" );
  956. lpIUnknown->lpVtbl->Release( lpIUnknown );
  957. LEAVE_DDRAW();
  958. return DDERR_OUTOFMEMORY;
  959. }
  960. }
  961. else if ( rval != E_NOINTERFACE )
  962. {
  963. /*
  964. * The CreateTexture call understood the IID but failed for some
  965. * other reason. Fail the QueryInterface.
  966. */
  967. DPF_ERR( "Direct3D CreateTexture with valid IID" );
  968. LEAVE_DDRAW();
  969. return rval;
  970. }
  971. }
  972. else
  973. {
  974. DPF( 0, "Could not locate the Direct3D CreateTexture entry point!" );
  975. }
  976. }
  977. if( lpIUnknown == NULL )
  978. {
  979. /*
  980. * Still no matching interface - is it a Direct3D device IID?
  981. */
  982. /*
  983. * NOTE: Don't need to verify that Direct3D is initialized. If we
  984. * got to here it must have been initialized (when we tried the
  985. * texture interface).
  986. */
  987. DDASSERT( D3D_INITIALIZED( pdrv_lcl ) );
  988. lpfnD3DCreateDeviceProc = (D3DCreateDeviceProc) GetProcAddress( pdrv_lcl->hD3DInstance, D3DCREATEDEVICE_PROCNAME );
  989. if( lpfnD3DCreateDeviceProc != NULL )
  990. {
  991. DPF( 4, "Attempting to create Direct3D Device interface" );
  992. rval = (*lpfnD3DCreateDeviceProc)( riid,
  993. pdrv_lcl->pD3DIUnknown,
  994. lpDDSurface, &lpIUnknown,
  995. (LPUNKNOWN)lpDDSurface, 1);
  996. if( rval == DD_OK )
  997. {
  998. /*
  999. * Found the interface. Add it to our list.
  1000. */
  1001. if( InsertIUnknown( this_lcl, riid, lpIUnknown ) == NULL )
  1002. {
  1003. /*
  1004. * Insufficient memory. Discard the interface and fail.
  1005. */
  1006. DPF_ERR( "Insufficient memory to aggregate the Direct3D Device interface" );
  1007. lpIUnknown->lpVtbl->Release( lpIUnknown );
  1008. LEAVE_DDRAW();
  1009. return DDERR_OUTOFMEMORY;
  1010. }
  1011. }
  1012. else if ( rval != E_NOINTERFACE )
  1013. {
  1014. /*
  1015. * The CreateDevice call understood the IID but failed for some
  1016. * other reason. Fail the QueryInterface.
  1017. */
  1018. DPF_ERR( "Direct3D CreateDevice with valid IID" );
  1019. LEAVE_DDRAW();
  1020. return rval;
  1021. }
  1022. }
  1023. else
  1024. {
  1025. DPF( 0, "Could not locate the Direct3D CreateDevice entry point!" );
  1026. }
  1027. }
  1028. if( lpIUnknown != NULL )
  1029. {
  1030. /*
  1031. * We have found an aggregated IID - pass the QueryInterface off
  1032. * on to it.
  1033. */
  1034. DPF( 4, "Passing query to aggregated (Direct3D) interface" );
  1035. rval = lpIUnknown->lpVtbl->QueryInterface( lpIUnknown, riid, ppvObj );
  1036. if( rval == DD_OK )
  1037. {
  1038. DPF( 4, "Aggregated (Direct3D) QueryInterface successful" );
  1039. LEAVE_DDRAW();
  1040. return DD_OK;
  1041. }
  1042. }
  1043. DPF_ERR( "IID not understood by DirectDraw" );
  1044. LEAVE_DDRAW();
  1045. return E_NOINTERFACE;
  1046. } /* DD_Surface_QueryInterface */
  1047. #undef DPF_MODNAME
  1048. #define DPF_MODNAME "AddRef"
  1049. /*
  1050. * DD_Surface_AddRef
  1051. */
  1052. ULONG DDAPI DD_Surface_AddRef( LPDIRECTDRAWSURFACE lpDDSurface )
  1053. {
  1054. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  1055. LPDDRAWI_DDRAWSURFACE_INT this_int;
  1056. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  1057. LPDDRAWI_DDRAWSURFACE_GBL this;
  1058. DWORD rcnt;
  1059. ENTER_DDRAW();
  1060. DPF(2,A,"ENTERAPI: DD_Surface_AddRef");
  1061. TRY
  1062. {
  1063. /*
  1064. * validate parms
  1065. */
  1066. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  1067. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  1068. {
  1069. DPF_ERR( "Invalid surface pointer" );
  1070. LEAVE_DDRAW();
  1071. return 0;
  1072. }
  1073. this_lcl = this_int->lpLcl;
  1074. this = this_lcl->lpGbl;
  1075. pdrv = this->lpDD;
  1076. // need to allow lost surfaces
  1077. #if 0
  1078. if( SURFACE_LOST( this_lcl ) )
  1079. {
  1080. LEAVE_DDRAW();
  1081. return 0;
  1082. }
  1083. #endif
  1084. }
  1085. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1086. {
  1087. DPF_ERR( "Exception encountered validating parameters" );
  1088. LEAVE_DDRAW();
  1089. return 0;
  1090. }
  1091. /*
  1092. * If this surface is already being freed, immediately return to
  1093. * prevent recursion.
  1094. */
  1095. if( this_lcl->dwFlags & DDRAWISURF_ISFREE )
  1096. {
  1097. DPF(4, "Leaving AddRef early to prevent recursion" );
  1098. LEAVE_DDRAW();
  1099. return 0;
  1100. }
  1101. /*
  1102. * update surface reference count
  1103. */
  1104. this->dwRefCnt++;
  1105. this_lcl->dwLocalRefCnt++;
  1106. this_int->dwIntRefCnt++;
  1107. ADDREFTRACK(lpDDSurface);
  1108. rcnt = this_lcl->dwLocalRefCnt & ~OBJECT_ISROOT;
  1109. DPF( 5, "DD_Surface_AddRef, Reference Count: Global = %ld Local = %ld Int = %ld",
  1110. this->dwRefCnt, rcnt, this_int->dwIntRefCnt );
  1111. LEAVE_DDRAW();
  1112. return this_int->dwIntRefCnt;
  1113. } /* DD_Surface_AddRef */
  1114. /*
  1115. * DestroySurface
  1116. *
  1117. * destroys a DirectDraw surface. does not unlink or free the surface struct.
  1118. * The driver object MUST be locked while making this call
  1119. */
  1120. extern void ReleaseSurfaceHandle(LPDWLIST lpSurfaceHandleList,DWORD handle);
  1121. void DestroySurface( LPDDRAWI_DDRAWSURFACE_LCL this_lcl )
  1122. {
  1123. LPDDRAWI_DDRAWSURFACE_GBL this;
  1124. DDHAL_DESTROYSURFACEDATA dsd;
  1125. DWORD rc;
  1126. BOOL free_vmem;
  1127. LPDDHALSURFCB_DESTROYSURFACE dsfn;
  1128. LPDDHALSURFCB_DESTROYSURFACE dshalfn;
  1129. BOOL emulation;
  1130. DWORD caps;
  1131. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  1132. this = this_lcl->lpGbl;
  1133. caps = this_lcl->ddsCaps.dwCaps;
  1134. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  1135. /*
  1136. * Wait for driver to finish with any pending DMA operations
  1137. */
  1138. if( this->dwGlobalFlags & DDRAWISURFGBL_HARDWAREOPSTARTED )
  1139. {
  1140. WaitForDriverToFinishWithSurface(pdrv_lcl, this_lcl);
  1141. }
  1142. /*
  1143. * Turn off video port hardware. It should already be off if it
  1144. * was called due by Release, but not if it was called by
  1145. * InvalidateSurface.
  1146. */
  1147. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOPORT )
  1148. {
  1149. LPDDRAWI_DDVIDEOPORT_LCL lpVP_lcl;
  1150. LPDDRAWI_DDVIDEOPORT_INT lpVP_int;
  1151. /*
  1152. * search all video ports to see if any are using this surface
  1153. */
  1154. lpVP_lcl = this_lcl->lpSurfMore->lpVideoPort;
  1155. lpVP_int = pdrv_lcl->lpGbl->dvpList;
  1156. while( lpVP_int != NULL )
  1157. {
  1158. if( ( lpVP_int->lpLcl == lpVP_lcl ) &&
  1159. !( lpVP_int->dwFlags & DDVPCREATE_NOTIFY) )
  1160. {
  1161. if( lpVP_int->dwFlags & DDVPCREATE_VBIONLY )
  1162. {
  1163. if( ( lpVP_lcl->lpVBISurface != NULL ) &&
  1164. ( lpVP_lcl->lpVBISurface->lpLcl == this_lcl ) )
  1165. {
  1166. DD_VP_StopVideo( (LPDIRECTDRAWVIDEOPORT)lpVP_int );
  1167. if( ( lpVP_lcl->lpVBISurface != NULL ) &&
  1168. ( lpVP_lcl->lpVBISurface->dwIntRefCnt > 0 ) )
  1169. {
  1170. DecrementRefCounts( lpVP_lcl->lpVBISurface );
  1171. }
  1172. lpVP_lcl->lpVBISurface = NULL;
  1173. }
  1174. }
  1175. else if( lpVP_int->dwFlags & DDVPCREATE_VIDEOONLY )
  1176. {
  1177. if( ( lpVP_lcl->lpSurface != NULL ) &&
  1178. ( lpVP_lcl->lpSurface->lpLcl == this_lcl ) )
  1179. {
  1180. DD_VP_StopVideo( (LPDIRECTDRAWVIDEOPORT)lpVP_int );
  1181. if( ( lpVP_lcl->lpSurface != NULL ) &&
  1182. ( lpVP_lcl->lpSurface->dwIntRefCnt > 0 ) )
  1183. {
  1184. DecrementRefCounts( lpVP_lcl->lpSurface );
  1185. }
  1186. lpVP_lcl->lpSurface = NULL;
  1187. }
  1188. }
  1189. else if( ( lpVP_lcl->lpSurface != NULL ) &&
  1190. ( lpVP_lcl->lpSurface->lpLcl == this_lcl ) )
  1191. {
  1192. DD_VP_StopVideo( (LPDIRECTDRAWVIDEOPORT)lpVP_int );
  1193. if( ( lpVP_lcl->lpSurface != NULL ) &&
  1194. ( lpVP_lcl->lpSurface->dwIntRefCnt > 0 ) )
  1195. {
  1196. DecrementRefCounts( lpVP_lcl->lpSurface );
  1197. }
  1198. lpVP_lcl->lpSurface = NULL;
  1199. if( ( lpVP_lcl->lpVBISurface != NULL ) &&
  1200. ( lpVP_lcl->lpVBISurface->dwIntRefCnt > 0 ) )
  1201. {
  1202. DecrementRefCounts( lpVP_lcl->lpVBISurface );
  1203. }
  1204. lpVP_lcl->lpVBISurface = NULL;
  1205. }
  1206. }
  1207. lpVP_int = lpVP_int->lpLink;
  1208. }
  1209. }
  1210. /*
  1211. * Release the kernel handle if one has been allocated
  1212. */
  1213. InternalReleaseKernelSurfaceHandle( this_lcl, TRUE );
  1214. /*
  1215. * Restore the color controls if they were changed.
  1216. */
  1217. ReleaseColorControl( this_lcl );
  1218. RestoreGamma( this_lcl, pdrv_lcl );
  1219. /*
  1220. * Turn off the overlay. If this function was called by Release,
  1221. * the ovelray should already be off by now; however, it will not
  1222. * if called because the surface was lost.
  1223. */
  1224. if( (this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY) &&
  1225. (this_lcl->ddsCaps.dwCaps & DDSCAPS_VISIBLE) &&
  1226. (this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) )
  1227. {
  1228. LPDDHALSURFCB_UPDATEOVERLAY uohalfn;
  1229. LPDDHALSURFCB_UPDATEOVERLAY uofn;
  1230. DWORD rc;
  1231. DDHAL_UPDATEOVERLAYDATA uod;
  1232. uofn = pdrv_lcl->lpDDCB->HALDDSurface.UpdateOverlay;
  1233. uohalfn = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.UpdateOverlay;
  1234. DDASSERT( uohalfn != NULL );
  1235. DPF( 2, "Turning off hardware overlay" );
  1236. uod.UpdateOverlay = uohalfn;
  1237. uod.lpDD = this_lcl->lpSurfMore->lpDD_lcl->lpGbl;
  1238. uod.lpDDSrcSurface = this_lcl;
  1239. uod.lpDDDestSurface = this_lcl->lpSurfaceOverlaying->lpLcl;
  1240. uod.dwFlags = DDOVER_HIDE;
  1241. DOHALCALL( UpdateOverlay, uofn, uod, rc, FALSE );
  1242. DDASSERT( ( rc == DDHAL_DRIVER_HANDLED ) &&
  1243. (( uod.ddRVal == DD_OK ) || ( uod.ddRVal == DDERR_SURFACELOST )) );
  1244. this_lcl->ddsCaps.dwCaps &= ~DDSCAPS_VISIBLE;
  1245. }
  1246. /*
  1247. * see if we need to free video memory
  1248. *
  1249. * We don't if its already free, if it was allocated by the client (and
  1250. * the client didn't specifically make DDraw responsible for freeing it),
  1251. * or if it is the video memory GDI surface.
  1252. */
  1253. #if 0 // DDRAWISURFGBL_DDFREESCLIENTMEM is gone
  1254. if((this->dwGlobalFlags & DDRAWISURFGBL_MEMFREE) ||
  1255. (this->dwGlobalFlags & DDRAWISURFGBL_ISCLIENTMEM &&
  1256. !(this->dwGlobalFlags & DDRAWISURFGBL_DDFREESCLIENTMEM)) ||
  1257. ((this->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE) && //((this->fpVidMem == this->lpDD->fpPrimaryOrig) &&
  1258. (this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) ) )
  1259. #else
  1260. #ifdef WINNT
  1261. // On Win2K we don't see any reason why the video memory primary
  1262. // should not be freed. Actually, we don't see any reason on Win9x
  1263. // as well, but we are not going to touch Win9x given that this is
  1264. // March 2001.
  1265. if((this->dwGlobalFlags & DDRAWISURFGBL_MEMFREE))
  1266. #else
  1267. if((this->dwGlobalFlags & DDRAWISURFGBL_MEMFREE) ||
  1268. ((this->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE) && //((this->fpVidMem == this->lpDD->fpPrimaryOrig) &&
  1269. (this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) ) )
  1270. #endif // WINNT
  1271. #endif // 0
  1272. {
  1273. free_vmem = FALSE;
  1274. }
  1275. else
  1276. {
  1277. free_vmem = TRUE;
  1278. }
  1279. if( free_vmem )
  1280. {
  1281. /*
  1282. * ask the driver to free its video memory...
  1283. */
  1284. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
  1285. {
  1286. if( caps & DDSCAPS_EXECUTEBUFFER )
  1287. dsfn = pdrv_lcl->lpDDCB->HELDDExeBuf.DestroyExecuteBuffer;
  1288. else
  1289. dsfn = pdrv_lcl->lpDDCB->HELDDSurface.DestroySurface;
  1290. dshalfn = dsfn;
  1291. emulation = TRUE;
  1292. }
  1293. else
  1294. {
  1295. if( caps & DDSCAPS_EXECUTEBUFFER )
  1296. {
  1297. dsfn = pdrv_lcl->lpDDCB->HALDDExeBuf.DestroyExecuteBuffer;
  1298. dshalfn = pdrv_lcl->lpDDCB->cbDDExeBufCallbacks.DestroyExecuteBuffer;
  1299. }
  1300. else
  1301. {
  1302. dsfn = pdrv_lcl->lpDDCB->HALDDSurface.DestroySurface;
  1303. dshalfn = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.DestroySurface;
  1304. }
  1305. emulation = FALSE;
  1306. }
  1307. rc = DDHAL_DRIVER_NOTHANDLED;
  1308. if( dshalfn != NULL )
  1309. {
  1310. DWORD save;
  1311. dsd.DestroySurface = dshalfn;
  1312. dsd.lpDD = this->lpDD;
  1313. dsd.lpDDSurface = this_lcl;
  1314. if(this_lcl->dwFlags & DDRAWISURF_DRIVERMANAGED)
  1315. {
  1316. save = this_lcl->dwFlags & DDRAWISURF_INVALID;
  1317. this_lcl->dwFlags &= ~DDRAWISURF_INVALID;
  1318. }
  1319. /*
  1320. * NOTE: THE DRIVER _CANNOT_ FAIL THIS CALL. ddrval is ignored.
  1321. */
  1322. if( caps & DDSCAPS_EXECUTEBUFFER )
  1323. {
  1324. DOHALCALL( DestroyExecuteBuffer, dsfn, dsd, rc, emulation );
  1325. }
  1326. else
  1327. {
  1328. DOHALCALL( DestroySurface, dsfn, dsd, rc, emulation );
  1329. }
  1330. if(this_lcl->dwFlags & DDRAWISURF_DRIVERMANAGED)
  1331. {
  1332. this_lcl->dwFlags |= save;
  1333. }
  1334. }
  1335. /*
  1336. * free the video memory ourselves
  1337. */
  1338. if( rc == DDHAL_DRIVER_NOTHANDLED )
  1339. {
  1340. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY )
  1341. {
  1342. #ifndef WINNT
  1343. if( this->lpVidMemHeap != NULL )
  1344. {
  1345. VidMemFree( this->lpVidMemHeap, this->fpVidMem );
  1346. }
  1347. #endif
  1348. }
  1349. }
  1350. this->lpVidMemHeap = NULL;
  1351. this->fpVidMem = 0;
  1352. this->dwGlobalFlags |= DDRAWISURFGBL_MEMFREE;
  1353. }
  1354. } /* DestroySurface */
  1355. #undef DPF_MODNAME
  1356. #define DPF_MODNAME "LooseManagedSurface"
  1357. /*
  1358. * LooseManagedSurface
  1359. *
  1360. */
  1361. void LooseManagedSurface( LPDDRAWI_DDRAWSURFACE_LCL this_lcl )
  1362. {
  1363. LPDDRAWI_DDRAWSURFACE_GBL this;
  1364. DDHAL_DESTROYSURFACEDATA dsd;
  1365. DWORD rc;
  1366. LPDDHALSURFCB_DESTROYSURFACE dsfn;
  1367. LPDDHALSURFCB_DESTROYSURFACE dshalfn;
  1368. BOOL emulation;
  1369. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  1370. DWORD save;
  1371. this = this_lcl->lpGbl;
  1372. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  1373. dsfn = pdrv_lcl->lpDDCB->HALDDSurface.DestroySurface;
  1374. dshalfn = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.DestroySurface;
  1375. emulation = FALSE;
  1376. rc = DDHAL_DRIVER_NOTHANDLED;
  1377. dsd.DestroySurface = dshalfn;
  1378. dsd.lpDD = this->lpDD;
  1379. dsd.lpDDSurface = this_lcl;
  1380. save = this_lcl->dwFlags & DDRAWISURF_INVALID;
  1381. this_lcl->dwFlags |= DDRAWISURF_INVALID;
  1382. /*
  1383. * NOTE: THE DRIVER _CANNOT_ FAIL THIS CALL. ddrval is ignored.
  1384. */
  1385. DOHALCALL( DestroySurface, dsfn, dsd, rc, emulation );
  1386. this_lcl->dwFlags &= ~DDRAWISURF_INVALID;
  1387. this_lcl->dwFlags |= save;
  1388. } /* LooseManagedSurface */
  1389. #undef DPF_MODNAME
  1390. #define DPF_MODNAME "Release"
  1391. /*
  1392. * NOTE: These two functions are hacks to get around a compiler bug
  1393. * that caused an infinite loop.
  1394. */
  1395. LPVOID GetAttachList( LPDDRAWI_DDRAWSURFACE_LCL this_lcl )
  1396. {
  1397. return this_lcl->lpAttachList;
  1398. }
  1399. LPVOID GetAttachListFrom( LPDDRAWI_DDRAWSURFACE_LCL this_lcl )
  1400. {
  1401. return this_lcl->lpAttachListFrom;
  1402. }
  1403. /*
  1404. * findOtherInterface
  1405. *
  1406. * Finds another interface to the lcl surface object different than this_int.
  1407. * Returns NULL if no other interface is found.
  1408. *
  1409. */
  1410. LPDDRAWI_DDRAWSURFACE_INT findOtherInterface(LPDDRAWI_DDRAWSURFACE_INT this_int,
  1411. LPDDRAWI_DDRAWSURFACE_LCL this_lcl,
  1412. LPDDRAWI_DIRECTDRAW_GBL pdrv)
  1413. {
  1414. LPDDRAWI_DDRAWSURFACE_INT psurf = pdrv->dsList;
  1415. while(psurf != NULL)
  1416. {
  1417. if( (psurf != this_int) && (psurf->lpLcl == this_lcl) )
  1418. {
  1419. return psurf;
  1420. }
  1421. psurf = psurf->lpLink;
  1422. }
  1423. return NULL;
  1424. }
  1425. /*
  1426. * InternalSurfaceRelease
  1427. *
  1428. * Done with a surface. if no one else is using it, then we can free it.
  1429. * Also called by ProcessSurfaceCleanup, EnumSurfaces and DD_Release.
  1430. *
  1431. * Assumes the lock is taken on the driver.
  1432. */
  1433. DWORD InternalSurfaceRelease( LPDDRAWI_DDRAWSURFACE_INT this_int, BOOL bLightweight, BOOL bDX8 )
  1434. {
  1435. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  1436. LPDDRAWI_DDRAWSURFACE_GBL this;
  1437. LPATTACHLIST pattachlist;
  1438. DWORD intrefcnt;
  1439. DWORD lclrefcnt;
  1440. DWORD gblrefcnt;
  1441. DWORD pid;
  1442. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  1443. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  1444. BOOL root_object_deleted;
  1445. BOOL do_free;
  1446. DWORD caps;
  1447. IUnknown * pOwner = NULL;
  1448. LPDDRAWI_DDRAWSURFACE_INT curr_int;
  1449. LPDDRAWI_DDRAWSURFACE_INT last_int;
  1450. BOOL bPrimaryChain = FALSE;
  1451. this_lcl = this_int->lpLcl;
  1452. this = this_lcl->lpGbl;
  1453. if (this_lcl->dwFlags & DDRAWISURF_PARTOFPRIMARYCHAIN)
  1454. {
  1455. bPrimaryChain = TRUE;
  1456. }
  1457. /*
  1458. * check owner of surface
  1459. */
  1460. pid = GETCURRPID();
  1461. /*
  1462. * don't allow someone to free an implicitly created surface
  1463. */
  1464. if( (this->dwRefCnt == 1) && (this_lcl->dwFlags & DDRAWISURF_IMPLICITCREATE) )
  1465. {
  1466. DPF_ERR( "Cannot free an implicitly created surface" );
  1467. return 0;
  1468. }
  1469. /*
  1470. * remove locks taken on this surface by the current process
  1471. */
  1472. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  1473. pdrv = pdrv_lcl->lpGbl;
  1474. if( (this_lcl->dwLocalRefCnt & ~OBJECT_ISROOT) == 1 )
  1475. {
  1476. RemoveProcessLocks( pdrv_lcl, this_lcl, pid );
  1477. }
  1478. /*
  1479. * decrement the reference count. if it hits zero, free the surface
  1480. */
  1481. this->dwRefCnt--;
  1482. gblrefcnt = this->dwRefCnt;
  1483. this_lcl->dwLocalRefCnt--;
  1484. lclrefcnt = this_lcl->dwLocalRefCnt & ~OBJECT_ISROOT;
  1485. this_int->dwIntRefCnt--;
  1486. intrefcnt = this_int->dwIntRefCnt;
  1487. DPF( 5, "DD_Surface_Release, Reference Count: Global = %ld Local = %ld Int = %ld",
  1488. gblrefcnt, lclrefcnt, intrefcnt );
  1489. #ifdef POSTPONED2
  1490. /*
  1491. * If the reference count on the interface object has now gone to
  1492. * zero and that object is referenced in the master sprite list,
  1493. * remove the reference to that object from the master sprite list.
  1494. */
  1495. if (intrefcnt == 0 && this_lcl->dwFlags & DDRAWISURF_INMASTERSPRITELIST)
  1496. {
  1497. RemoveSpriteSurface(pdrv, this_int);
  1498. }
  1499. #endif //POSTPONED2
  1500. /*
  1501. * local object at zero?
  1502. */
  1503. root_object_deleted = FALSE;
  1504. if ( 0 == lclrefcnt )
  1505. {
  1506. LPDDRAWI_DDRAWSURFACE_INT curr_int;
  1507. LPDDRAWI_DDRAWSURFACE_LCL curr_lcl;
  1508. LPDDRAWI_DDRAWSURFACE_GBL curr;
  1509. DWORD refcnt;
  1510. // Do not call FlushD3DStates on DDHelp thread; if the app has died, then
  1511. // D3DIM will be gone.
  1512. if (dwHelperPid != GetCurrentProcessId())
  1513. {
  1514. FlushD3DStates(this_lcl);
  1515. /* If there exists a D3D texture object, then we need to kill it */
  1516. if(this_lcl->lpSurfMore->lpTex)
  1517. {
  1518. DDASSERT(pdrv_lcl->pD3DDestroyTexture);
  1519. pdrv_lcl->pD3DDestroyTexture(this_lcl->lpSurfMore->lpTex);
  1520. }
  1521. }
  1522. /*
  1523. * see if we are deleting the root object
  1524. */
  1525. if( this_lcl->dwLocalRefCnt & OBJECT_ISROOT )
  1526. {
  1527. root_object_deleted = TRUE;
  1528. }
  1529. /*
  1530. * reset if primary surface is the one being released
  1531. */
  1532. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE )
  1533. {
  1534. /*
  1535. * restore GDI stuff if this is the GDI driver
  1536. */
  1537. if( pdrv->dwFlags & DDRAWI_DISPLAYDRV )
  1538. {
  1539. if( !SURFACE_LOST( this_lcl ) )
  1540. {
  1541. DPF( 2, "Resetting primary surface");
  1542. /*
  1543. * flip to the original primary surface if not emulated
  1544. */
  1545. if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
  1546. {
  1547. FlipToGDISurface( pdrv_lcl, this_int ); //, pdrv->fpPrimaryOrig );
  1548. }
  1549. }
  1550. /*
  1551. * Cause the GDI surface to be redrawn if the mode was ever changed.
  1552. */
  1553. if (pdrv_lcl->dwLocalFlags & DDRAWILCL_MODEHASBEENCHANGED)
  1554. RedrawWindow( NULL, NULL, NULL, RDW_INVALIDATE | RDW_ERASE |
  1555. RDW_ALLCHILDREN );
  1556. }
  1557. }
  1558. /*
  1559. * hide a hardware overlay...
  1560. */
  1561. if( (this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY) &&
  1562. (this_lcl->ddsCaps.dwCaps & DDSCAPS_VISIBLE) &&
  1563. (this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) )
  1564. {
  1565. LPDDHALSURFCB_UPDATEOVERLAY uohalfn;
  1566. LPDDHALSURFCB_UPDATEOVERLAY uofn;
  1567. DWORD rc;
  1568. DDHAL_UPDATEOVERLAYDATA uod;
  1569. uofn = pdrv_lcl->lpDDCB->HALDDSurface.UpdateOverlay;
  1570. uohalfn = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.UpdateOverlay;
  1571. if( (uohalfn != NULL) && (NULL != this_lcl->lpSurfaceOverlaying) )
  1572. {
  1573. DPF( 2, "Turning off hardware overlay" );
  1574. uod.UpdateOverlay = uohalfn;
  1575. uod.lpDD = pdrv;
  1576. uod.lpDDSrcSurface = this_lcl;
  1577. uod.lpDDDestSurface = this_lcl->lpSurfaceOverlaying->lpLcl;
  1578. uod.dwFlags = DDOVER_HIDE;
  1579. DOHALCALL( UpdateOverlay, uofn, uod, rc, FALSE );
  1580. this_lcl->ddsCaps.dwCaps &= ~DDSCAPS_VISIBLE;
  1581. }
  1582. }
  1583. /*
  1584. * if an overlay, remove surface from the overlay Z order list
  1585. */
  1586. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY )
  1587. {
  1588. // Remove surface from doubly linked list
  1589. this_lcl->dbnOverlayNode.prev->next = this_lcl->dbnOverlayNode.next;
  1590. this_lcl->dbnOverlayNode.next->prev = this_lcl->dbnOverlayNode.prev;
  1591. // If this surface is overlaying an emulated surface, we must notify
  1592. // the HEL that it needs to eventually update the part of the surface
  1593. // touched by this overlay.
  1594. if( this_lcl->lpSurfaceOverlaying != NULL )
  1595. {
  1596. LPDIRECTDRAWSURFACE lpTempSurface;
  1597. // We have a pointer to the surface being overlayed, check to
  1598. // see if it is being emulated.
  1599. if( this_lcl->lpSurfaceOverlaying->lpLcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
  1600. {
  1601. // Mark the destination region of this overlay as dirty.
  1602. DD_Surface_AddOverlayDirtyRect(
  1603. (LPDIRECTDRAWSURFACE)(this_lcl->lpSurfaceOverlaying),
  1604. &(this_lcl->rcOverlayDest) );
  1605. }
  1606. lpTempSurface = (LPDIRECTDRAWSURFACE)(this_lcl->lpSurfaceOverlaying);
  1607. this_lcl->lpSurfaceOverlaying = NULL;
  1608. DD_Surface_Release( lpTempSurface );
  1609. }
  1610. }
  1611. if( (this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY) &&
  1612. ( this_lcl->lpSurfMore->lpddOverlayFX != NULL ) )
  1613. {
  1614. MemFree( this_lcl->lpSurfMore->lpddOverlayFX );
  1615. this_lcl->lpSurfMore->lpddOverlayFX = NULL;
  1616. }
  1617. /*
  1618. * turn off video port hardware...
  1619. */
  1620. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOPORT )
  1621. {
  1622. LPDDRAWI_DDVIDEOPORT_INT lpVideoPort;
  1623. LPDDRAWI_DDVIDEOPORT_LCL lpVideoPort_lcl;
  1624. /*
  1625. * search all video ports to see if any are using this surface
  1626. */
  1627. lpVideoPort = pdrv->dvpList;
  1628. while( ( NULL != lpVideoPort ) &&
  1629. !( lpVideoPort->dwFlags & DDVPCREATE_NOTIFY ) )
  1630. {
  1631. lpVideoPort_lcl = lpVideoPort->lpLcl;
  1632. if( lpVideoPort_lcl->lpSurface == this_int )
  1633. {
  1634. DD_VP_StopVideo( (LPDIRECTDRAWVIDEOPORT)lpVideoPort );
  1635. lpVideoPort_lcl->lpSurface = NULL;
  1636. }
  1637. if( lpVideoPort_lcl->lpVBISurface == this_int )
  1638. {
  1639. DD_VP_StopVideo( (LPDIRECTDRAWVIDEOPORT)lpVideoPort );
  1640. lpVideoPort_lcl->lpVBISurface = NULL;
  1641. }
  1642. lpVideoPort = lpVideoPort->lpLink;
  1643. }
  1644. }
  1645. /*
  1646. * If is has a gamma ramp, release it now
  1647. */
  1648. ReleaseGammaControl( this_lcl );
  1649. /*
  1650. * Free the nodes in the IUnknown list and release all the interfaces.
  1651. */
  1652. FreeIUnknowns( this_lcl, TRUE );
  1653. /*
  1654. * release all implicitly created attached surfaces
  1655. */
  1656. pattachlist = GetAttachList( this_lcl );
  1657. this_lcl->dwFlags |= DDRAWISURF_ISFREE;
  1658. while( pattachlist != NULL )
  1659. {
  1660. BOOL was_implicit;
  1661. /*
  1662. * break all attachments
  1663. */
  1664. curr_int = pattachlist->lpIAttached;
  1665. if( pattachlist->dwFlags & DDAL_IMPLICIT )
  1666. was_implicit = TRUE;
  1667. else
  1668. was_implicit = FALSE;
  1669. DPF(5, "Deleting attachment from %08lx to %08lx (implicit = %d)",
  1670. curr_int, this_int, was_implicit);
  1671. DeleteOneAttachment( this_int, curr_int, TRUE, DOA_DELETEIMPLICIT );
  1672. // If the attachment was not implicit then curr_int may possibly have
  1673. // been destroyed as a result of DeleteOneAttachment.
  1674. if( was_implicit )
  1675. {
  1676. curr_lcl = curr_int->lpLcl;
  1677. curr = curr_lcl->lpGbl;
  1678. /*
  1679. * release an implicitly created surface
  1680. */
  1681. if( !(curr_lcl->dwFlags & DDRAWISURF_ISFREE) )
  1682. {
  1683. if( curr_lcl->dwFlags & DDRAWISURF_IMPLICITCREATE )
  1684. {
  1685. refcnt = curr_int->dwIntRefCnt;
  1686. curr_lcl->dwFlags &= ~DDRAWISURF_IMPLICITCREATE;
  1687. while( refcnt > 0 )
  1688. {
  1689. InternalSurfaceRelease( curr_int, bLightweight, bDX8 );
  1690. refcnt--;
  1691. }
  1692. }
  1693. }
  1694. }
  1695. /*
  1696. * start again at the beginning of the list because
  1697. * DeleteOneAttachment may have modified the attachment list.
  1698. * HACKHACK: this fn call is needed to get around a compiler bug
  1699. */
  1700. pattachlist = GetAttachList( this_lcl );
  1701. }
  1702. /* at this point all D3DDevice must have detached themselves
  1703. unless if this is being called by DDHELP */
  1704. #if DBG
  1705. if(dwHelperPid != GetCurrentProcessId())
  1706. {
  1707. DDASSERT(NULL == this_lcl->lpSurfMore->lpD3DDevIList);
  1708. }
  1709. #endif
  1710. /*
  1711. * If a palette is attached to this surface remove it (and, as a
  1712. * side effect, release it). Use SetPaletteAlways just in case the
  1713. * surface has been lost.
  1714. */
  1715. if( this_lcl->lpDDPalette )
  1716. SetPaletteAlways( this_int, NULL );
  1717. /*
  1718. * Release the attached clipper (if any).
  1719. */
  1720. if( this_lcl->lpSurfMore->lpDDIClipper )
  1721. DD_Clipper_Release( (LPDIRECTDRAWCLIPPER)this_lcl->lpSurfMore->lpDDIClipper );
  1722. /*
  1723. * remove all attachments to us from other surfaces
  1724. */
  1725. pattachlist = this_lcl->lpAttachListFrom;
  1726. while( pattachlist != NULL )
  1727. {
  1728. curr_int = pattachlist->lpIAttached;
  1729. DPF( 5, "Deleting attachment from %08lx", curr_int );
  1730. DeleteOneAttachment( curr_int, this_int, TRUE, DOA_DELETEIMPLICIT );
  1731. /*
  1732. * start again at the beginning of the list because
  1733. * DeleteOneAttachment may have modified the attachment list.
  1734. * HACKHACK: this fn call is needed to get around a compiler bug
  1735. */
  1736. pattachlist = GetAttachListFrom( this_lcl );
  1737. }
  1738. /*
  1739. * Remove any association with a DC. This will tend to mean
  1740. * that someone has orphaned a windows DC.
  1741. */
  1742. if( this_lcl->dwFlags & DDRAWISURF_HASDC )
  1743. {
  1744. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC )
  1745. {
  1746. HRESULT ddrval;
  1747. DDASSERT( this->dwGlobalFlags & DDRAWISURFGBL_SYSMEMREQUESTED );
  1748. DDASSERT( this_lcl->hDC != 0UL );
  1749. /*
  1750. * If this is an OWNDC surface the HDC lives as long as the surface
  1751. * so release it now.
  1752. */
  1753. ddrval = InternalReleaseDC( this_lcl, (HDC)this_lcl->hDC
  1754. #ifdef WIN95
  1755. , TRUE
  1756. #endif //WIN95
  1757. );
  1758. DDASSERT( !FAILED(ddrval) );
  1759. }
  1760. else
  1761. {
  1762. /*
  1763. * If its not an OWNDC surface then the HDC should have been released before
  1764. * we ever got here.
  1765. */
  1766. DPF( 1, "HDC Leaked! Surface should only be released after DC is released" );
  1767. // Remove DC from the list
  1768. InternalRemoveDCFromList( NULL, this_lcl );
  1769. // Clear flags
  1770. this_lcl->dwFlags &= ~(DDRAWISURF_HASDC | DDRAWISURF_GETDCNULL);
  1771. }
  1772. }
  1773. /*
  1774. * Remove private data
  1775. */
  1776. FreeAllPrivateData( &this_lcl->lpSurfMore->pPrivateDataHead );
  1777. /*
  1778. * Region lists should be freed
  1779. */
  1780. if(IsD3DManaged(this_lcl))
  1781. {
  1782. MemFree(this_lcl->lpSurfMore->lpRegionList);
  1783. }
  1784. /*
  1785. * If the ddraw interface which created this surface caused the surface to addref the ddraw
  1786. * object, then we need to release that addref now.
  1787. * We don't release ddraw object for implicitly created surfaces, since
  1788. * that surface never took an addref.
  1789. */
  1790. if (this_lcl->lpSurfMore->lpDD_int)
  1791. {
  1792. pOwner = this_lcl->lpSurfMore->pAddrefedThisOwner;
  1793. }
  1794. if (!bLightweight)
  1795. {
  1796. MemFree(this_lcl->lpSurfMore->pCreatedDDSurfaceDesc2);
  1797. MemFree(this_lcl->lpSurfMore->slist);
  1798. }
  1799. this_lcl->dwFlags &= ~DDRAWISURF_ISFREE;
  1800. }
  1801. /*
  1802. * root object at zero?
  1803. */
  1804. do_free = FALSE;
  1805. if( gblrefcnt == 0 )
  1806. {
  1807. #ifdef WINNT
  1808. if (this->dwGlobalFlags & DDRAWISURFGBL_NOTIFYWHENUNLOCKED)
  1809. {
  1810. if (--dwNumLockedWhenModeSwitched == 0)
  1811. {
  1812. NotifyDriverOfFreeAliasedLocks();
  1813. }
  1814. this->dwGlobalFlags &= ~DDRAWISURFGBL_NOTIFYWHENUNLOCKED;
  1815. }
  1816. #endif
  1817. /*
  1818. * get rid of all memory associated with this surface
  1819. */
  1820. DestroySurface( this_lcl );
  1821. if (0 != this_lcl->lpSurfMore->dwSurfaceHandle)
  1822. {
  1823. #ifdef WIN95
  1824. // need to notify the driver that this system memory surface is not associated to
  1825. // this surface handle anymore
  1826. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  1827. {
  1828. DDASSERT(0UL == this->fpVidMem);
  1829. // For now, simply warn that the driver failed to associate the surface with the
  1830. // token and continue
  1831. DDASSERT( pdrv_lcl == this_lcl->lpSurfMore->lpDD_lcl);
  1832. createsurfaceEx(this_lcl);
  1833. }
  1834. #endif
  1835. ReleaseSurfaceHandle(&SURFACEHANDLELIST(pdrv_lcl),this_lcl->lpSurfMore->dwSurfaceHandle);
  1836. //DPF(0,"Release lpSurfMore->dwSurfaceHandle=%08lx",this_lcl->lpSurfMore->dwSurfaceHandle);
  1837. this_lcl->lpSurfMore->dwSurfaceHandle=0;
  1838. }
  1839. this_lcl->dwFlags |= DDRAWISURF_INVALID;
  1840. do_free = TRUE;
  1841. #ifdef WIN95
  1842. //
  1843. // Free persistent-content memory, if any
  1844. //
  1845. if (this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_PERSISTENTCONTENTS)
  1846. {
  1847. FreeSurfaceContents(this_lcl);
  1848. }
  1849. #endif
  1850. /*
  1851. * if this was the final delete, but this wasn't the root object,
  1852. * then we need to delete the dangling object
  1853. */
  1854. if( !root_object_deleted )
  1855. {
  1856. LPDDRAWI_DDRAWSURFACE_LCL root_lcl;
  1857. /*
  1858. * Get the start of the root global data object. Since the
  1859. * global data always follows the local data, we just need
  1860. * to back up the size of the local data to get the start of
  1861. * the allocated block.
  1862. *
  1863. * NOTE: The local surface allocation now includes the
  1864. * additional local surface structure (DDRAWI_DDRAWSURFACE_MORE).
  1865. * So we need to back up by the size of that structure also.
  1866. * And also need to move back 4 bytes for the extra pointer
  1867. * to the GBL_MORE.
  1868. *
  1869. * Since all duplicated surfaces have the same local data,
  1870. * we just need to test this surface for overlay data to determine
  1871. * if the root object had overlay data.
  1872. */
  1873. if( this_lcl->dwFlags & DDRAWISURF_HASOVERLAYDATA )
  1874. {
  1875. root_lcl = (LPVOID) (((LPSTR) this) - ( sizeof( DDRAWI_DDRAWSURFACE_LCL ) +
  1876. sizeof( DDRAWI_DDRAWSURFACE_MORE ) +
  1877. sizeof( LPDDRAWI_DDRAWSURFACE_GBL_MORE ) ) );
  1878. }
  1879. else
  1880. {
  1881. root_lcl = (LPVOID) (((LPSTR) this) - ( offsetof( DDRAWI_DDRAWSURFACE_LCL, ddckCKSrcOverlay ) +
  1882. sizeof( DDRAWI_DDRAWSURFACE_MORE ) +
  1883. sizeof( LPDDRAWI_DDRAWSURFACE_GBL_MORE ) ) );
  1884. }
  1885. if (!bLightweight)
  1886. {
  1887. MemFree( root_lcl );
  1888. }
  1889. }
  1890. }
  1891. else if( lclrefcnt == 0 )
  1892. {
  1893. /*
  1894. * only remove the object if it wasn't the root. if it
  1895. * was the root, we must leave it dangling until the last
  1896. * object referencing it goes away.
  1897. */
  1898. if( !root_object_deleted )
  1899. {
  1900. do_free = TRUE;
  1901. }
  1902. }
  1903. caps = this_lcl->ddsCaps.dwCaps;
  1904. /*
  1905. * If we are releasing an interface to a primary surface, update the pointer to the primary
  1906. * surface stored in the local driver object. If another interface to the primary surface exists,
  1907. * store that one. Otherwise, set the pointer to NULL.
  1908. */
  1909. if( intrefcnt == 0 )
  1910. {
  1911. /*
  1912. * If the video port is using this interface, make it stop
  1913. */
  1914. if( ( this_lcl->lpSurfMore->lpVideoPort != NULL ) &&
  1915. ( this_lcl->lpSurfMore->lpVideoPort->lpSurface == this_int ) )
  1916. {
  1917. this_lcl->lpSurfMore->lpVideoPort->lpSurface = NULL;
  1918. }
  1919. /*
  1920. * The following code is to work around a design flaw.
  1921. * The implicitly created surfaces are not freed until the LCL is
  1922. * freed, but the attached list references the INT. Therefore, we
  1923. * can release an INT now and then try to reference it later when
  1924. * releasing the LCL. This happens most often when a second
  1925. * interface is created for the same LCL, such as ColorControl,
  1926. * Kernel, Surface2, etc.
  1927. */
  1928. if( ( lclrefcnt > 0 ) &&
  1929. ( ( GetAttachList( this_lcl ) != NULL ) ||
  1930. ( GetAttachListFrom( this_lcl ) != NULL ) ) )
  1931. {
  1932. LPDDRAWI_DDRAWSURFACE_INT new_int;
  1933. LPATTACHLIST ptr1, ptr2;
  1934. /*
  1935. * Find the other INT that is using the LCL
  1936. */
  1937. new_int = findOtherInterface(this_int, this_lcl, pdrv);
  1938. DDASSERT( new_int != NULL );
  1939. /*
  1940. * Update the surfaces attachements.
  1941. * We first go to all interfaces we are attached to and change
  1942. * their AttachListFrom to reference our new interface.
  1943. */
  1944. ptr1 = GetAttachList( this_lcl );
  1945. while( ptr1 != NULL )
  1946. {
  1947. DDASSERT( ptr1->lpIAttached != this_int );
  1948. ptr2 = ptr1->lpAttached->lpAttachListFrom;
  1949. while( ptr2 != NULL )
  1950. {
  1951. if( ptr2->lpIAttached == this_int )
  1952. {
  1953. ptr2->lpIAttached = new_int;
  1954. }
  1955. ptr2 = ptr2->lpLink;
  1956. }
  1957. ptr1 = ptr1->lpLink;
  1958. }
  1959. /*
  1960. * We now go to all interfaces we are attached from and change
  1961. * their AttachList to reference our new interface.
  1962. */
  1963. ptr1 = this_lcl->lpAttachListFrom;
  1964. while( ptr1 != NULL )
  1965. {
  1966. DDASSERT( ptr1->lpIAttached != this_int );
  1967. ptr2 = GetAttachList( ptr1->lpAttached );
  1968. while( ptr2 != NULL )
  1969. {
  1970. if( ptr2->lpIAttached == this_int )
  1971. {
  1972. ptr2->lpIAttached = new_int;
  1973. }
  1974. ptr2 = ptr2->lpLink;
  1975. }
  1976. ptr1 = ptr1->lpLink;
  1977. }
  1978. }
  1979. if( caps & DDSCAPS_PRIMARYSURFACE )
  1980. {
  1981. LPDDRAWI_DDRAWSURFACE_INT temp_int;
  1982. if( this_lcl->lpSurfMore->lpDD_lcl )
  1983. {
  1984. this_lcl->lpSurfMore->lpDD_lcl->lpPrimary = findOtherInterface(this_int, this_lcl, pdrv);
  1985. }
  1986. /*
  1987. * If an overlay is overlaying this surface, either make it use
  1988. * a new primary surface int or turn it off
  1989. */
  1990. temp_int = pdrv->dsList;
  1991. while( temp_int != NULL )
  1992. {
  1993. if( temp_int->lpLcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY )
  1994. {
  1995. if( temp_int->lpLcl->lpSurfaceOverlaying == this_int )
  1996. {
  1997. if( lclrefcnt > 0 )
  1998. {
  1999. temp_int->lpLcl->lpSurfaceOverlaying =
  2000. findOtherInterface(this_int, this_lcl, pdrv);
  2001. DDASSERT( temp_int != NULL );
  2002. }
  2003. else
  2004. {
  2005. temp_int->lpLcl->lpSurfaceOverlaying = NULL;
  2006. }
  2007. if( ( temp_int->lpLcl->lpSurfaceOverlaying == NULL ) &&
  2008. ( temp_int->lpLcl->ddsCaps.dwCaps & DDSCAPS_VISIBLE ))
  2009. {
  2010. LPDDHALSURFCB_UPDATEOVERLAY uohalfn;
  2011. LPDDHALSURFCB_UPDATEOVERLAY uofn;
  2012. DWORD rc;
  2013. DDHAL_UPDATEOVERLAYDATA uod;
  2014. /*
  2015. * Turn off the overlay
  2016. */
  2017. uofn = pdrv_lcl->lpDDCB->HALDDSurface.UpdateOverlay;
  2018. uohalfn = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.UpdateOverlay;
  2019. DDASSERT( uohalfn != NULL );
  2020. DPF( 2, "Turning off hardware overlay" );
  2021. uod.UpdateOverlay = uohalfn;
  2022. uod.lpDD = pdrv;
  2023. uod.lpDDSrcSurface = temp_int->lpLcl;
  2024. uod.lpDDDestSurface = NULL;
  2025. uod.dwFlags = DDOVER_HIDE;
  2026. DOHALCALL( UpdateOverlay, uofn, uod, rc, FALSE );
  2027. temp_int->lpLcl->ddsCaps.dwCaps &= ~DDSCAPS_VISIBLE;
  2028. }
  2029. }
  2030. }
  2031. temp_int = temp_int->lpLink;
  2032. }
  2033. }
  2034. #ifdef SHAREDZ
  2035. if( caps & DDSCAPS_SHAREDBACKBUFFER )
  2036. {
  2037. if( this_lcl->lpSurfMore->lpDD_lcl )
  2038. {
  2039. this_lcl->lpSurfMore->lpDD_lcl->lpSharedBack = findOtherInterface(this_int, this_lcl, pdrv);
  2040. }
  2041. }
  2042. if( caps & DDSCAPS_SHAREDZBUFFER )
  2043. {
  2044. if( this_lcl->lpSurfMore->lpDD_lcl )
  2045. {
  2046. this_lcl->lpSurfMore->lpDD_lcl->lpSharedZ = findOtherInterface(this_int, this_lcl, pdrv);
  2047. }
  2048. }
  2049. #endif
  2050. }
  2051. /*
  2052. * free the object if needed
  2053. */
  2054. if( do_free && !bLightweight )
  2055. {
  2056. this_lcl->lpGbl = NULL;
  2057. #ifdef WINNT
  2058. /*
  2059. * Free the associated NT kernel-mode object only if it is a vram surface, it is not
  2060. * an execute buffer, and it has not yet been freed in the kernel
  2061. */
  2062. if (!(caps & (DDSCAPS_SYSTEMMEMORY) ) && this_lcl->hDDSurface )
  2063. {
  2064. DPF(5,"Deleting NT kernel-mode object handle %08x",this_lcl->hDDSurface);
  2065. if (!DdDeleteSurfaceObject(this_lcl))
  2066. DPF(5,"DdDeleteSurfaceObject failed");
  2067. }
  2068. #endif
  2069. MemFree( this_lcl );
  2070. }
  2071. /*
  2072. * interface at zero?
  2073. */
  2074. if(( intrefcnt == 0) && (!bDX8 || bPrimaryChain))
  2075. {
  2076. /*
  2077. * remove surface from list of all surfaces
  2078. */
  2079. curr_int = pdrv->dsList;
  2080. last_int = NULL;
  2081. while( curr_int != this_int )
  2082. {
  2083. last_int = curr_int;
  2084. curr_int = curr_int->lpLink;
  2085. if( curr_int == NULL )
  2086. {
  2087. DPF_ERR( "Surface not in list!" );
  2088. return 0;
  2089. }
  2090. }
  2091. if( last_int == NULL )
  2092. {
  2093. pdrv->dsList = pdrv->dsList->lpLink;
  2094. }
  2095. else
  2096. {
  2097. last_int->lpLink = curr_int->lpLink;
  2098. }
  2099. curr_int->lpLink = pdrv->dsFreeList;
  2100. pdrv->dsFreeList = curr_int;
  2101. DUMPREFTRACK(this_int);
  2102. }
  2103. if (( 0 == lclrefcnt) && !bLightweight )
  2104. {
  2105. if (!bDX8 || bPrimaryChain)
  2106. {
  2107. /*
  2108. * remove surface from list of all surfaces
  2109. */
  2110. curr_int = pdrv->dsFreeList;
  2111. last_int = NULL;
  2112. while( curr_int )
  2113. {
  2114. LPDDRAWI_DDRAWSURFACE_INT temp_int = curr_int->lpLink;
  2115. DDASSERT(0 == curr_int->dwIntRefCnt);
  2116. if (curr_int->lpLcl == this_lcl)
  2117. {
  2118. if( last_int == NULL )
  2119. {
  2120. pdrv->dsFreeList = temp_int;
  2121. }
  2122. else
  2123. {
  2124. last_int->lpLink = temp_int;
  2125. }
  2126. /*
  2127. * just in case someone comes back in with this pointer, set
  2128. * an invalid vtbl & data ptr.
  2129. */
  2130. curr_int->lpVtbl = NULL;
  2131. curr_int->lpLcl = NULL;
  2132. MemFree( curr_int );
  2133. }
  2134. else
  2135. {
  2136. last_int = curr_int;
  2137. }
  2138. curr_int = temp_int;
  2139. }
  2140. }
  2141. else
  2142. {
  2143. this_int->lpVtbl = NULL;
  2144. this_int->lpLcl = NULL;
  2145. MemFree( this_int );
  2146. }
  2147. }
  2148. /*
  2149. * If the surface took a ref count on the ddraw object that created it,
  2150. * release that ref now as the very last thing.
  2151. * We don't want to do this on ddhelp's thread cuz it really mucks up the
  2152. * process cleanup stuff.
  2153. */
  2154. if (pOwner && (dwHelperPid != GetCurrentProcessId()) )
  2155. {
  2156. pOwner->lpVtbl->Release(pOwner);
  2157. }
  2158. return intrefcnt;
  2159. } /* InternalSurfaceRelease */
  2160. /*
  2161. * DD_Surface_Release
  2162. *
  2163. * Done with a surface. if no one else is using it, then we can free it.
  2164. */
  2165. ULONG DDAPI DD_Surface_Release( LPDIRECTDRAWSURFACE lpDDSurface )
  2166. {
  2167. LPDDRAWI_DDRAWSURFACE_INT this_int;
  2168. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  2169. DWORD rc;
  2170. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  2171. LPDDRAWI_DDRAWSURFACE_INT pparentsurf_int;
  2172. ENTER_DDRAW();
  2173. DPF(2,A,"ENTERAPI: DD_Surface_Release");
  2174. TRY
  2175. {
  2176. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  2177. if( !VALIDEX_DIRECTDRAWSURFACE_PTR( this_int ) )
  2178. {
  2179. DPF_ERR( "Invalid surface pointer" );
  2180. LEAVE_DDRAW();
  2181. return 0;
  2182. }
  2183. this_lcl = this_int->lpLcl;
  2184. pdrv = this_lcl->lpGbl->lpDD;
  2185. }
  2186. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2187. {
  2188. DPF_ERR( "Exception encountered validating parameters" );
  2189. LEAVE_DDRAW();
  2190. return 0;
  2191. }
  2192. /*
  2193. * If this surface is already being freed, immediately return to
  2194. * prevent recursion.
  2195. */
  2196. if( this_lcl->dwFlags & DDRAWISURF_ISFREE )
  2197. {
  2198. DPF(4, "Leaving Release early to prevent recursion" );
  2199. LEAVE_DDRAW();
  2200. return 0;
  2201. }
  2202. if ( this_int->dwIntRefCnt == 0 )
  2203. {
  2204. DPF_ERR( "Interface pointer has 0 ref count!" );
  2205. LEAVE_DDRAW();
  2206. return 0;
  2207. }
  2208. /*
  2209. * If this surface is part of a mip-map chain then we will need
  2210. * to update its parent map's mip-map count.
  2211. */
  2212. pparentsurf_int = NULL;
  2213. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_MIPMAP )
  2214. pparentsurf_int = FindParentMipMap( this_int );
  2215. rc = InternalSurfaceRelease( this_int, FALSE, FALSE );
  2216. #ifdef REFTRACKING
  2217. if (rc)
  2218. {
  2219. RELEASETRACK(lpDDSurface);
  2220. }
  2221. #endif
  2222. /*
  2223. * Update the parent's mip-map count if necessary
  2224. * (if the surface really has gone and if the mip-map
  2225. * has a parent).
  2226. */
  2227. if( ( rc == 0UL ) && ( pparentsurf_int != NULL ) )
  2228. UpdateMipMapCount( pparentsurf_int );
  2229. LEAVE_DDRAW();
  2230. return rc;
  2231. } /* DD_Surface_Release */
  2232. /*
  2233. * ProcessSurfaceCleanup
  2234. *
  2235. * A process is done, clean up any surfaces that it may have locked.
  2236. *
  2237. * NOTE: we enter with a lock taken on the DIRECTDRAW object.
  2238. */
  2239. void ProcessSurfaceCleanup( LPDDRAWI_DIRECTDRAW_GBL pdrv, DWORD pid, LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
  2240. {
  2241. LPDDRAWI_DDRAWSURFACE_INT psurf_int;
  2242. LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
  2243. LPDDRAWI_DDRAWSURFACE_GBL psurf;
  2244. LPDDRAWI_DDRAWSURFACE_INT psnext_int;
  2245. DWORD rcnt;
  2246. ULONG rc;
  2247. /*
  2248. * run through all surfaces owned by the driver object, and find ones
  2249. * that have been accessed by this process. If the pdrv_lcl parameter
  2250. * is non-null, only delete surfaces created by that local driver object.
  2251. */
  2252. psurf_int = pdrv->dsList;
  2253. DPF( 4, "ProcessSurfaceCleanup" );
  2254. while( psurf_int != NULL )
  2255. {
  2256. psurf_lcl = psurf_int->lpLcl;
  2257. psurf = psurf_lcl->lpGbl;
  2258. psnext_int = psurf_int->lpLink;
  2259. rc = 1;
  2260. if( ( psurf_lcl->dwProcessId == pid ) &&
  2261. ( (NULL == pdrv_lcl) || (psurf_lcl->lpSurfMore->lpDD_lcl == pdrv_lcl) ) )
  2262. {
  2263. if( NULL == pdrv_lcl )
  2264. {
  2265. /*
  2266. * If no local driver object is passed in then we are being called
  2267. * due to process termination. In this case we can't release
  2268. * the Direct3D objects as they no longer exist (Direct3D is a
  2269. * local DLL and dies with the application along with its objects)
  2270. * Hence, free all the nodes on the IUnknown list and NULL the
  2271. * list out to prevent InternalSurfaceRelease() from trying to
  2272. * free them.
  2273. */
  2274. DPF( 4, "Discarding Direct3D surface interfaces - process terminated" );
  2275. FreeIUnknowns( psurf_lcl, FALSE );
  2276. }
  2277. /*
  2278. * release the references by this process
  2279. */
  2280. rcnt = psurf_int->dwIntRefCnt;
  2281. DPF( 5, "Process %08lx had %ld accesses to surface %08lx", pid, rcnt, psurf_int );
  2282. while( rcnt > 0 )
  2283. {
  2284. if(!(psurf_lcl->dwFlags & DDRAWISURF_IMPLICITCREATE) )
  2285. {
  2286. rc = InternalSurfaceRelease( psurf_int, FALSE, FALSE );
  2287. // Multiple surfaces may be released in the call to InternalSurfaceRelease
  2288. // so we must start again at the beginning of the list.
  2289. psnext_int = pdrv->dsList;
  2290. if( rc == 0 )
  2291. {
  2292. break;
  2293. }
  2294. }
  2295. rcnt--;
  2296. }
  2297. }
  2298. else
  2299. {
  2300. DPF( 5, "Process %08lx had no accesses to surface %08lx", pid, psurf_int );
  2301. }
  2302. psurf_int = psnext_int;
  2303. }
  2304. DPF( 4, "Leaving ProcessSurfaceCleanup");
  2305. } /* ProcessSurfaceCleanup */
  2306. void FreeD3DSurfaceIUnknowns( LPDDRAWI_DIRECTDRAW_GBL pdrv, DWORD pid, LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
  2307. {
  2308. LPDDRAWI_DDRAWSURFACE_INT psurf_int = pdrv->dsList;
  2309. while( psurf_int != NULL )
  2310. {
  2311. LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl = psurf_int->lpLcl;
  2312. LPDDRAWI_DDRAWSURFACE_INT psnext_int = psurf_int->lpLink;
  2313. if( ( psurf_lcl->dwProcessId == pid ) &&
  2314. (psurf_lcl->lpSurfMore->lpDD_lcl == pdrv_lcl) )
  2315. {
  2316. DPF( 4, "Release Direct3D surface interfaces" );
  2317. FreeIUnknowns( psurf_lcl, TRUE );
  2318. }
  2319. psurf_int = psnext_int;
  2320. }
  2321. } /* FreeD3DSurfaceIUnknowns */