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.

1694 lines
53 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: ddsatch.c
  6. * Content: DirectDraw attached surface support.
  7. * AddAttachedSurface, DeleteAttachedSurface,
  8. * EnumAttachedSurfaces, GetAttachedSurface
  9. * History:
  10. * Date By Reason
  11. * ==== == ======
  12. * 14-jan-95 craige initial implementation
  13. * 22-jan-95 craige made 32-bit + ongoing work
  14. * 31-jan-95 craige and even more ongoing work...
  15. * 27-feb-95 craige new sync. macros
  16. * 03-mar-95 craige GetAttachedSurface code
  17. * 19-mar-95 craige use HRESULTs
  18. * 23-mar-95 craige expanded functionality
  19. * 01-apr-95 craige happy fun joy updated header file
  20. * 12-apr-95 craige proper csect call order
  21. * 06-may-95 craige use driver-level csects only
  22. * 11-jun-95 craige comment out fliplist code
  23. * 13-jun-95 kylej added flippable chain side-effects for
  24. * AddAttachedSurface and DeleteAttachedSurface
  25. * added DeleteOneLink, added a cleanup parameter to
  26. * DeleteOneAttachment
  27. * 16-jun-95 craige removed fpVidMemOrig
  28. * 17-jun-95 craige new surface structure
  29. * 20-jun-95 kylej prevent detachments of implicit attachments
  30. * 25-jun-95 craige one ddraw mutex
  31. * 26-jun-95 craige reorganized surface structure
  32. * 28-jun-95 craige ENTER_DDRAW at very start of fns
  33. * 04-jul-95 craige YEEHAW: new driver struct; SEH
  34. * 31-jul-95 craige validate flags
  35. * 05-dec-95 colinmc changed DDSCAPS_TEXTUREMAP => DDSCAPS_TEXTURE for
  36. * consistency with Direct3D
  37. * 07-dec-95 colinmc added mip-map support
  38. * 18-dec-95 colinmc added ability to add system memory z-buffer as
  39. * attachement to video memory surface.
  40. * 18-dec-95 colinmc additional caps bit checking in GetAttachedSurface
  41. * 02-jan-96 kylej handle new interface structs
  42. * 12-feb-96 colinmc surface lost flag moved from global to local object
  43. * 20-mar-96 colinmc Bug 13634: Unidirectional attached surfaces can
  44. * cause infinite loop on cleanup
  45. * 12-may-96 colinmc Bug 22401: Missing return from DeleteOneAttachment
  46. * 03-oct-97 jeffno DDSCAPS2 and DDSURFACEDESC2
  47. *
  48. ***************************************************************************/
  49. #include "ddrawpr.h"
  50. #undef DPF_MODNAME
  51. #define DPF_MODNAME "UpdateMipMapCount"
  52. /*
  53. * UpdateMipMapCount
  54. *
  55. * When we add or remove levels from a mip-map the mip-map count changes for
  56. * those levels left in the original chain (as the mip-map count gives the
  57. * number of levels in the chain). Hence we need to recompute the mip-map
  58. * level count when a mip-map is added or removed from a chain.
  59. */
  60. void UpdateMipMapCount( LPDDRAWI_DDRAWSURFACE_INT psurf_int )
  61. {
  62. LPDDRAWI_DDRAWSURFACE_INT pparentsurf_int;
  63. DWORD dwLevels;
  64. /*
  65. * Find the top most level mip-map in the chain.
  66. */
  67. pparentsurf_int = psurf_int;
  68. while( pparentsurf_int != NULL )
  69. {
  70. psurf_int = pparentsurf_int;
  71. pparentsurf_int = FindParentMipMap( psurf_int );
  72. }
  73. pparentsurf_int = psurf_int;
  74. /*
  75. * We have the top most level in the mip-map chain. Lowe count
  76. * the levels in the chain.
  77. */
  78. dwLevels = 0UL;
  79. while( psurf_int != NULL )
  80. {
  81. dwLevels++;
  82. psurf_int = FindAttachedMipMap( psurf_int );
  83. }
  84. /*
  85. * Now update all the levels with their new mip-map count.
  86. */
  87. psurf_int = pparentsurf_int;
  88. while( psurf_int != NULL )
  89. {
  90. psurf_int->lpLcl->lpSurfMore->dwMipMapCount = dwLevels;
  91. dwLevels--;
  92. psurf_int = FindAttachedMipMap( psurf_int );
  93. }
  94. DDASSERT( dwLevels == 0UL );
  95. } /* UpdateMipMapCount */
  96. /*
  97. * AddAttachedSurface
  98. *
  99. * Add an attached surface to another.
  100. * Assumes that all parameters coming in are VALID!
  101. */
  102. HRESULT AddAttachedSurface( LPDDRAWI_DDRAWSURFACE_INT psurf_from_int,
  103. LPDDRAWI_DDRAWSURFACE_INT psurf_to_int,
  104. BOOL implicit )
  105. {
  106. LPATTACHLIST pal_from;
  107. LPATTACHLIST pal_to;
  108. LPDDRAWI_DDRAWSURFACE_GBL psurf_from;
  109. LPDDRAWI_DDRAWSURFACE_LCL psurf_from_lcl;
  110. LPDDRAWI_DDRAWSURFACE_GBL psurf_to;
  111. LPDDRAWI_DDRAWSURFACE_LCL psurf_to_lcl;
  112. psurf_from_lcl = psurf_from_int->lpLcl;
  113. psurf_from = psurf_from_lcl->lpGbl;
  114. psurf_to_lcl = psurf_to_int->lpLcl;
  115. psurf_to = psurf_to_lcl->lpGbl;
  116. /*
  117. * allocate attachment structures
  118. */
  119. pal_from = MemAlloc( sizeof( ATTACHLIST ) );
  120. if( pal_from == NULL )
  121. {
  122. return DDERR_OUTOFMEMORY;
  123. }
  124. pal_to = MemAlloc( sizeof( ATTACHLIST ) );
  125. if( pal_to == NULL )
  126. {
  127. MemFree( pal_from );
  128. return DDERR_OUTOFMEMORY;
  129. }
  130. #ifdef WINNT
  131. /*
  132. * let the kernel know about the attachment
  133. * ...only if the driver isn't emulated
  134. */
  135. if ( psurf_from_lcl->lpSurfMore->lpDD_lcl->lpGbl->hDD )
  136. {
  137. if ( !DdAttachSurface(psurf_from_lcl, psurf_to_lcl) )
  138. {
  139. /*
  140. * ATTENTION
  141. * Hack o rama for NT5 b1. The kernel will fail this attach for the primary chain if
  142. * it ends up in system memory due to an out of vidmem. The kernel doesn't like
  143. * the user-mode address '0xffbadbad'. Wonder why?
  144. * For now, we'll just carry on regardless.
  145. */
  146. DPF(0,"DdAttachSurface failed!");
  147. //MemFree( pal_from );
  148. //MemFree( pal_to );
  149. //return DDERR_OUTOFMEMORY;
  150. }
  151. }
  152. #endif
  153. /*
  154. * mark as implicit if created as part of an initial complex structure
  155. */
  156. if( implicit )
  157. {
  158. pal_from->dwFlags |= DDAL_IMPLICIT;
  159. pal_to->dwFlags |= DDAL_IMPLICIT;
  160. }
  161. else
  162. {
  163. // The surface being attached to holds a reference count on the surface
  164. // attached from if the attachment is not implicit.
  165. DD_Surface_AddRef( (LPDIRECTDRAWSURFACE)psurf_to_int );
  166. DPF(3, "Attachment ADDREF %08lx", psurf_to_int);
  167. }
  168. /*
  169. * connect the surfaces
  170. */
  171. pal_from->lpIAttached = psurf_to_int;
  172. pal_from->lpAttached = psurf_to_lcl;
  173. pal_from->lpLink = psurf_from_lcl->lpAttachList;
  174. psurf_from_lcl->lpAttachList = pal_from;
  175. psurf_from_lcl->dwFlags |= DDRAWISURF_ATTACHED;
  176. pal_to->lpIAttached = psurf_from_int;
  177. pal_to->lpAttached = psurf_from_lcl;
  178. pal_to->lpLink = psurf_to_lcl->lpAttachListFrom;
  179. psurf_to_lcl->lpAttachListFrom = pal_to;
  180. psurf_to_lcl->dwFlags |= DDRAWISURF_ATTACHED_FROM;
  181. return DD_OK;
  182. } /* AddAttachedSurface */
  183. #undef DPF_MODNAME
  184. #define DPF_MODNAME "AddAttachedSurface"
  185. BOOL isImplicitAttachment( LPDDRAWI_DDRAWSURFACE_INT this_int,
  186. LPDDRAWI_DDRAWSURFACE_INT pattsurf_int)
  187. {
  188. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  189. LPDDRAWI_DDRAWSURFACE_LCL pattsurf_lcl;
  190. LPATTACHLIST curr;
  191. this_lcl = this_int->lpLcl;
  192. pattsurf_lcl = pattsurf_int->lpLcl;
  193. /*
  194. * see if specified surface is attached
  195. */
  196. curr = this_lcl->lpAttachList;
  197. while( curr != NULL )
  198. {
  199. if( curr->lpIAttached == pattsurf_int )
  200. {
  201. break;
  202. }
  203. curr = curr->lpLink;
  204. }
  205. if( (curr != NULL) && (curr->dwFlags & DDAL_IMPLICIT) )
  206. return TRUE;
  207. return FALSE;
  208. }
  209. /*
  210. * DD_Surface_AddAttachedSurface
  211. */
  212. HRESULT DDAPI DD_Surface_AddAttachedSurface(
  213. LPDIRECTDRAWSURFACE lpDDSurface,
  214. LPDIRECTDRAWSURFACE lpDDAttachedSurface )
  215. {
  216. LPDDRAWI_DDRAWSURFACE_INT this_int;
  217. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  218. LPDDRAWI_DDRAWSURFACE_INT this_attached_int;
  219. LPDDRAWI_DDRAWSURFACE_LCL this_attached_lcl;
  220. LPDDRAWI_DDRAWSURFACE_GBL this;
  221. LPDDRAWI_DDRAWSURFACE_GBL this_attached;
  222. DWORD rc;
  223. LPATTACHLIST pal;
  224. LPATTACHLIST pal_next;
  225. LPDDHALSURFCB_ADDATTACHEDSURFACE aasfn;
  226. LPDDHALSURFCB_ADDATTACHEDSURFACE aashalfn;
  227. DDHAL_ADDATTACHEDSURFACEDATA aasd;
  228. DWORD caps;
  229. DWORD hitcaps;
  230. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  231. BOOL emulation;
  232. BOOL was_implicit;
  233. BOOL has_excl;
  234. ENTER_DDRAW();
  235. DPF(2,A,"ENTERAPI: DD_Surface_AddAttachedSurface");
  236. /*
  237. * validate parameters
  238. */
  239. TRY
  240. {
  241. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  242. this_attached_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDAttachedSurface;
  243. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  244. {
  245. LEAVE_DDRAW();
  246. return DDERR_INVALIDOBJECT;
  247. }
  248. this_lcl = this_int->lpLcl;
  249. if( !VALID_DIRECTDRAWSURFACE_PTR( this_attached_int ) )
  250. {
  251. LEAVE_DDRAW();
  252. return DDERR_INVALIDOBJECT;
  253. }
  254. this_attached_lcl = this_attached_int->lpLcl;
  255. this = this_lcl->lpGbl;
  256. this_attached = this_attached_lcl->lpGbl;
  257. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  258. //
  259. // For DX7, we will DISALLOW any attachment that doesn't involve a z buffer.
  260. // The exact rule is: exactly one of the two surfaces must be a Z buffer, AND
  261. // exactly one of the two surfaces must NOT be a Z buffer.
  262. //
  263. if (!LOWERTHANSURFACE7(this_int))
  264. {
  265. DWORD dwBothCaps;
  266. dwBothCaps = this_lcl->ddsCaps.dwCaps ^ this_attached_lcl->ddsCaps.dwCaps;
  267. if (0 == (dwBothCaps & DDSCAPS_ZBUFFER) )
  268. {
  269. DPF(0,"You can only attach Z buffers in DX7. No other surface type can be attached.");
  270. DPF(0,"Mipmaps, flipping chains and cube maps must be created by ONE call to CreateSurface.");
  271. LEAVE_DDRAW();
  272. return DDERR_CANNOTATTACHSURFACE;
  273. }
  274. }
  275. /*
  276. * Can't attach execute buffers to anything.
  277. *
  278. * !!! NOTE; Look into this. Would there be any value
  279. * in being able to attach execute buffers to each other.
  280. * Batch system to video memory transfer perhaps?
  281. */
  282. if( ( this_lcl->ddsCaps.dwCaps | this_attached_lcl->ddsCaps.dwCaps ) & DDSCAPS_EXECUTEBUFFER )
  283. {
  284. DPF_ERR( "Invalid surface types: can't attach surface" );
  285. LEAVE_DDRAW();
  286. return DDERR_CANNOTATTACHSURFACE;
  287. }
  288. /*
  289. * Cubemaps can't be attached. period
  290. */
  291. if( (( this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_CUBEMAP ) && (0==(this_attached_lcl->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)) ) )
  292. {
  293. DPF_ERR( "Can only attach zbuffers to cubemap surfaces" );
  294. LEAVE_DDRAW();
  295. return DDERR_CANNOTATTACHSURFACE;
  296. }
  297. //
  298. // If it is an Optimized surface, then continue only if:
  299. // 1) The current and the attached surface are non-empty
  300. // 2) Both are texture & mipmap
  301. // 3) Both have the same optimization caps
  302. //
  303. // For now, if the current surface is optimized, quit
  304. if ((this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED) ||
  305. (this_attached_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED))
  306. {
  307. DPF_ERR( "Cannot attach to an optimized surface" );
  308. LEAVE_DDRAW();
  309. return DDERR_CANNOTATTACHSURFACE;
  310. }
  311. /*
  312. * Can't attach a backbuffer to a non-exclusive or non-fullscreen primary
  313. */
  314. CheckExclusiveMode(this_lcl->lpSurfMore->lpDD_lcl, NULL , &has_excl, FALSE,
  315. NULL, FALSE);
  316. if( (this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
  317. && ( (!has_excl)
  318. || !(this->lpDD->dwFlags & DDRAWI_FULLSCREEN) ) )
  319. {
  320. DPF_ERR( "Must be in full-screen exclusive mode to create a flipping primary surface" );
  321. LEAVE_DDRAW();
  322. return DDERR_NOEXCLUSIVEMODE;
  323. }
  324. /*
  325. * same surface?
  326. */
  327. if( this_lcl == this_attached_lcl )
  328. {
  329. DPF_ERR( "Can't attach surface to itself" );
  330. LEAVE_DDRAW();
  331. return DDERR_CANNOTATTACHSURFACE;
  332. }
  333. if( SURFACE_LOST( this_lcl ) )
  334. {
  335. LEAVE_DDRAW();
  336. return DDERR_SURFACELOST;
  337. }
  338. if( SURFACE_LOST( this_attached_lcl ) )
  339. {
  340. LEAVE_DDRAW();
  341. return DDERR_SURFACELOST;
  342. }
  343. /*
  344. * are the surfaces already attached?
  345. */
  346. pal = this_lcl->lpAttachList;
  347. while( pal != NULL )
  348. {
  349. if( pal->lpIAttached == this_attached_int )
  350. {
  351. DPF_ERR( "Surface already attached" );
  352. LEAVE_DDRAW();
  353. return DDERR_SURFACEALREADYATTACHED;
  354. }
  355. pal = pal->lpLink;
  356. }
  357. /*
  358. * BEHAVIOUR CHANGE FOR DX5
  359. *
  360. * We do not allow attaching surfaces created with different
  361. * DirectDraw objects.
  362. */
  363. if (this_lcl->lpSurfMore->lpDD_lcl->lpGbl != this_attached_lcl->lpSurfMore->lpDD_lcl->lpGbl)
  364. {
  365. /*
  366. * Don't check if either device isn't a display driver (i.e. 3dfx)
  367. * since that's a back-compat hole.
  368. */
  369. if ( (this->lpDD->dwFlags & DDRAWI_DISPLAYDRV) &&
  370. (this_attached->lpDD->dwFlags & DDRAWI_DISPLAYDRV) )
  371. {
  372. DPF_ERR("Can't attach surfaces between different direct draw devices");
  373. LEAVE_DDRAW();
  374. return DDERR_DEVICEDOESNTOWNSURFACE;
  375. }
  376. }
  377. /*
  378. * Do sizes match?
  379. */
  380. if( ( ( this_lcl->ddsCaps.dwCaps & this_attached_lcl->ddsCaps.dwCaps ) & ( DDSCAPS_TEXTURE | DDSCAPS_MIPMAP ) ) ==
  381. ( DDSCAPS_TEXTURE | DDSCAPS_MIPMAP ) )
  382. {
  383. /*
  384. * If attaching a mip-map we ensure that the child is no bigger than the
  385. * parent. We don't insist on strict power of 2 smaller as a mip-map
  386. * may have missing levels.
  387. */
  388. if( ( this->wWidth < this_attached->wWidth ) ||
  389. ( this->wHeight < this_attached->wHeight ) )
  390. {
  391. DPF_ERR( "Attached mip-map must be no larger than parent map" );
  392. LEAVE_DDRAW();
  393. return DDERR_CANNOTATTACHSURFACE;
  394. }
  395. }
  396. else
  397. {
  398. if( !(!(this_lcl->ddsCaps.dwCaps & DDSCAPS_TEXTURE) &&
  399. (this_attached_lcl->ddsCaps.dwCaps & DDSCAPS_TEXTURE)) &&
  400. !((this_lcl->ddsCaps.dwCaps & DDSCAPS_TEXTURE) &&
  401. !(this_attached_lcl->ddsCaps.dwCaps & DDSCAPS_TEXTURE)) )
  402. {
  403. if( (this->wHeight != this_attached->wHeight) ||
  404. (this->wWidth != this_attached->wWidth) )
  405. {
  406. DPF_ERR( "Can't attach surfaces of differing sizes" );
  407. LEAVE_DDRAW();
  408. return DDERR_CANNOTATTACHSURFACE;
  409. }
  410. }
  411. }
  412. /*
  413. * don't allow multiple of the same type of surface to be attached to a surface
  414. */
  415. caps = this_attached_lcl->ddsCaps.dwCaps & (DDSCAPS_TEXTURE|DDSCAPS_MIPMAP|
  416. DDSCAPS_ALPHA|DDSCAPS_ZBUFFER);
  417. if( caps )
  418. {
  419. pal = this_lcl->lpAttachList;
  420. while( pal != NULL )
  421. {
  422. hitcaps = pal->lpAttached->ddsCaps.dwCaps & caps;
  423. if( hitcaps )
  424. {
  425. /*
  426. * Horrible special case. We can attach more than one texture
  427. * to a surface as long as one of them is a mip-map and the other
  428. * isn't.
  429. */
  430. if( !( hitcaps & DDSCAPS_TEXTURE ) ||
  431. !( ( pal->lpAttached->ddsCaps.dwCaps ^ caps ) & DDSCAPS_MIPMAP ) )
  432. {
  433. DPF_ERR( "Can't attach 2 or more of the same type of surface to one surface" );
  434. LEAVE_DDRAW();
  435. return DDERR_CANNOTATTACHSURFACE;
  436. }
  437. }
  438. pal_next = pal->lpLink;
  439. pal = pal_next;
  440. }
  441. }
  442. /*
  443. * If the attached surface could be part of a flippable chain with the
  444. * original surface but it is already flippable, we cannot attach it.
  445. * (It would create a non-simple flipping chain).
  446. */
  447. if( ( this_attached_lcl->ddsCaps.dwCaps & DDSCAPS_FLIP ) &&
  448. CanBeFlippable( this_lcl, this_attached_lcl ) )
  449. {
  450. DPF_ERR( "Can't attach a flippable surface to another flippable surface of the same type");
  451. LEAVE_DDRAW();
  452. return DDERR_CANNOTATTACHSURFACE;
  453. }
  454. /*
  455. * Don't allow an emulated surface to be attached to a non-emulated
  456. * surface.
  457. */
  458. if( ( (this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  459. !(this_attached_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)) ||
  460. (!(this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  461. (this_attached_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) ) )
  462. {
  463. /*
  464. * Special case: We allow s system memory z-buffer to be attached to
  465. * a video memory surface. This to keep the software rendering people
  466. * happy. They want to use a video memory surface as rendering target
  467. * so they get the benefit from page flipping but they don't want to
  468. * have a z-buffer in VRAM as they have to read from it and thats
  469. * slooowwww... Its also really useful to have the z-buffer as an
  470. * attachment. So just to be nice...
  471. *
  472. * !!! NOTE: This means that we are going to invoke the
  473. * AddAttachedSurface HAL member with one system and one video
  474. * memory surface. What are the impliciations of this.
  475. */
  476. if( !( ( this_attached_lcl->ddsCaps.dwCaps & DDSCAPS_ZBUFFER ) &&
  477. ( this_attached_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) ) )
  478. {
  479. DPF_ERR( "Can't attach an emulated surface to a non-emulated surface.");
  480. LEAVE_DDRAW();
  481. return DDERR_CANNOTATTACHSURFACE;
  482. }
  483. }
  484. /*
  485. * Check to see if both surfaces are emulated or not
  486. */
  487. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
  488. {
  489. aasfn = pdrv_lcl->lpDDCB->HELDDSurface.AddAttachedSurface;
  490. aashalfn = aasfn;
  491. emulation = TRUE;
  492. }
  493. else
  494. {
  495. aashalfn = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.AddAttachedSurface;
  496. aasfn = pdrv_lcl->lpDDCB->HALDDSurface.AddAttachedSurface;
  497. emulation = FALSE;
  498. }
  499. }
  500. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  501. {
  502. DPF_ERR( "Exception encountered validating parameters" );
  503. LEAVE_DDRAW();
  504. return DDERR_INVALIDPARAMS;
  505. }
  506. /*
  507. * ask driver if it is OK to attach these surfaces
  508. */
  509. if( aashalfn != NULL)
  510. {
  511. aasd.AddAttachedSurface = aashalfn;
  512. aasd.lpDD = pdrv_lcl->lpGbl;
  513. aasd.lpDDSurface = this_lcl;
  514. aasd.lpSurfAttached = this_attached_lcl;
  515. DOHALCALL( AddAttachedSurface, aasfn, aasd, rc, emulation );
  516. if( rc == DDHAL_DRIVER_HANDLED )
  517. {
  518. if( aasd.ddRVal != DD_OK )
  519. {
  520. LEAVE_DDRAW();
  521. return aasd.ddRVal;
  522. }
  523. }
  524. }
  525. // Check to see if we need to add this surface to a flippable chain
  526. // or if we need to form a new flippable chain. If the attached
  527. // surface is already part of a flippable chain, we will attach it but
  528. // we won't try to form another flippable chain.
  529. if( !CanBeFlippable( this_lcl, this_attached_lcl ) ||
  530. ( this_attached_lcl->ddsCaps.dwCaps & DDSCAPS_FLIP ) )
  531. {
  532. // no flippable chain can be formed.
  533. // go ahead and attach the surface
  534. AddAttachedSurface( this_int, this_attached_int, FALSE );
  535. DPF( 2, "Attached surface, no flippable chain formed" );
  536. if( this_attached_int->lpLcl->ddsCaps.dwCaps & DDSCAPS_MIPMAP )
  537. {
  538. // This is a mip-map chain. We have added new levels so
  539. // we need to update the mip-map level count on each
  540. // level
  541. DPF( 2, "Updating mip-map level count" );
  542. UpdateMipMapCount( this_int );
  543. }
  544. }
  545. else
  546. {
  547. // These surfaces can be combined to form a flippable chain.
  548. // Check to see if this surface is already flippable
  549. if( !( this_lcl->ddsCaps.dwCaps & DDSCAPS_FLIP ) )
  550. {
  551. // neither surface is flippable.
  552. // attach the surfaces to form a two-member flippable chain
  553. rc = AddAttachedSurface( this_int, this_attached_int, FALSE );
  554. if( rc == DD_OK )
  555. {
  556. // We are performing this attachment for the app even though it
  557. // wasn't explicitly requested so make it implicit.
  558. rc = AddAttachedSurface( this_attached_int, this_int, TRUE );
  559. }
  560. if( rc != DD_OK )
  561. {
  562. DPF_ERR( "Unable to attach surface, AddAttachedSurface failed.");
  563. LEAVE_DDRAW();
  564. return DDERR_CANNOTATTACHSURFACE;
  565. }
  566. // now decide which will be front and which will be back
  567. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_BACKBUFFER )
  568. {
  569. // make attached surface the front buffer
  570. this_attached_lcl->ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
  571. this_attached_lcl->dwBackBufferCount = 1;
  572. }
  573. else
  574. {
  575. // make attached surface the back buffer
  576. this_attached_lcl->ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
  577. this_lcl->ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
  578. this_lcl->dwBackBufferCount = 1;
  579. }
  580. this_lcl->ddsCaps.dwCaps |= DDSCAPS_FLIP;
  581. this_attached_lcl->ddsCaps.dwCaps |= DDSCAPS_FLIP;
  582. DPF( 2, "Attached surface, two surface flippable chain formed" );
  583. }
  584. else
  585. {
  586. // this_attached will be made part of the flippable chain
  587. // add this_attached to the flippable chain that the current
  588. // surface is already part of. Find the next surface in the
  589. // chain after the current surface.
  590. LPDDRAWI_DDRAWSURFACE_INT next_int;
  591. LPDDRAWI_DDRAWSURFACE_LCL next_lcl;
  592. LPDDRAWI_DDRAWSURFACE_GBL next;
  593. LPDDRAWI_DDRAWSURFACE_INT front_int;
  594. LPDDRAWI_DDRAWSURFACE_LCL front_lcl;
  595. LPDDRAWI_DDRAWSURFACE_GBL front;
  596. LPDDRAWI_DDRAWSURFACE_INT current_int;
  597. LPDDRAWI_DDRAWSURFACE_LCL current_lcl;
  598. LPDDRAWI_DDRAWSURFACE_GBL current;
  599. front_int = NULL;
  600. next_int = FindAttachedFlip( this_int );
  601. // traverse the flippable chain to find the front buffer
  602. for(current_int = next_int;
  603. current_int != NULL;
  604. current_int = FindAttachedFlip( current_int ) )
  605. {
  606. current_lcl = current_int->lpLcl;
  607. current = current_lcl->lpGbl;
  608. if( current_lcl->ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER )
  609. {
  610. front_int = current_int;
  611. break;
  612. }
  613. }
  614. if( ( next_int == NULL ) || ( front_int == NULL ) )
  615. {
  616. DPF_ERR( "Invalid flippable chain, surface not attached" );
  617. LEAVE_DDRAW();
  618. return DDERR_CANNOTATTACHSURFACE;
  619. }
  620. front_lcl = front_int->lpLcl;
  621. front = front_lcl->lpGbl;
  622. next_lcl = next_int->lpLcl;
  623. next = next_lcl->lpGbl;
  624. // get rid of any previous front or backbuffer caps. They will
  625. // be restored when this surface is again removed from the chain.
  626. this_attached_lcl->ddsCaps.dwCaps &=
  627. ~( DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER );
  628. // Find out where the new surface fits in the chain
  629. // if the surface we are attaching to is the back buffer or
  630. // a plain surface, then the attached surface is
  631. // a plain surface. If the surface we are attaching
  632. // to is a frontbuffer then the attached surface becomes a
  633. // backbuffer and the previous backbuffer becomes a plain
  634. // surface.
  635. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER )
  636. {
  637. // this_attached becomes the backbuffer. The previous
  638. // backbuffer becomes a plain offscreen surface
  639. this_attached_lcl->ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
  640. next_lcl->ddsCaps.dwCaps &= ~DDSCAPS_BACKBUFFER;
  641. }
  642. this_attached_lcl->ddsCaps.dwCaps |= DDSCAPS_FLIP;
  643. front_lcl->dwBackBufferCount++;
  644. // detach the next surface from the current surface and then
  645. // insert the attached surface.
  646. was_implicit = isImplicitAttachment( this_int, next_int );
  647. /*
  648. * AddRef next_int so that it doesn't go away when we temporarily
  649. * disconnect it.
  650. */
  651. DD_Surface_AddRef( (LPDIRECTDRAWSURFACE)next_int );
  652. rc = DeleteOneAttachment( this_int, next_int, FALSE, DOA_DELETEIMPLICIT );
  653. if( rc == DD_OK )
  654. {
  655. rc = AddAttachedSurface( this_int, this_attached_int, FALSE );
  656. if( rc == DD_OK )
  657. {
  658. // if the attachment of next_int to this_int was implicit, make
  659. // the attachment of next_int to this_attached_int implicit.
  660. rc = AddAttachedSurface( this_attached_int, next_int, was_implicit );
  661. }
  662. }
  663. DD_Surface_Release( (LPDIRECTDRAWSURFACE)next_int );
  664. if( rc != DD_OK )
  665. {
  666. DPF_ERR( "Unable to attach surface, AddAttachedSurface failed.");
  667. LEAVE_DDRAW();
  668. return DDERR_CANNOTATTACHSURFACE;
  669. }
  670. DPF( 2, "Attached surface, flippable chain lengthened" );
  671. }
  672. }
  673. LEAVE_DDRAW();
  674. return DD_OK;
  675. } /* DD_Surface_AddAttachedSurface */
  676. #undef DPF_MODNAME
  677. #define DPF_MODNAME "DeleteAttachedSurfaces"
  678. /*
  679. * DeleteOneAttachment
  680. *
  681. * delete a single attachment from surface.
  682. * performs flippable chain cleanup if the cleanup parameter is TRUE
  683. * ASSUMES DRIVER LOCK IS TAKEN!
  684. *
  685. * If delete_implicit is TRUE then DeleteOneAttachment will break
  686. * implicit attachments. Otherwise, it is an error to call this
  687. * function to delete an implicit attachment.
  688. */
  689. HRESULT DeleteOneAttachment( LPDDRAWI_DDRAWSURFACE_INT this_int,
  690. LPDDRAWI_DDRAWSURFACE_INT pattsurf_int,
  691. BOOL cleanup,
  692. BOOL delete_implicit )
  693. {
  694. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  695. LPDDRAWI_DDRAWSURFACE_GBL this;
  696. LPDDRAWI_DDRAWSURFACE_LCL pattsurf_lcl;
  697. LPDDRAWI_DDRAWSURFACE_GBL pattsurf;
  698. LPATTACHLIST curr;
  699. LPATTACHLIST last;
  700. BOOL addrefed_pattsurf = FALSE;
  701. BOOL addrefed_this = FALSE;
  702. BOOL addrefed_next = FALSE;
  703. HRESULT rc;
  704. LPDDRAWI_DDRAWSURFACE_INT next_int;
  705. DPF( 4, "DeleteOneAttachment: %08lx,%08lx", this_int, pattsurf_int );
  706. this_lcl = this_int->lpLcl;
  707. this = this_lcl->lpGbl;
  708. pattsurf_lcl = pattsurf_int->lpLcl;
  709. pattsurf = pattsurf_lcl->lpGbl;
  710. if( pattsurf_lcl->ddsCaps.dwCaps & DDSCAPS_ZBUFFER )
  711. {
  712. if (dwHelperPid != GetCurrentProcessId())
  713. {
  714. if(pattsurf_lcl->lpSurfMore->lpDD_lcl->pD3DIUnknown)
  715. pattsurf_lcl->lpSurfMore->lpDD_lcl->pFlushD3DDevices2(pattsurf_lcl);
  716. }
  717. }
  718. /*
  719. * see if specified surface is attached
  720. */
  721. curr = this_lcl->lpAttachList;
  722. last = NULL;
  723. while( curr != NULL )
  724. {
  725. if( curr->lpIAttached == pattsurf_int )
  726. {
  727. break;
  728. }
  729. last = curr;
  730. curr = curr->lpLink;
  731. }
  732. if( curr == NULL )
  733. {
  734. return DDERR_SURFACENOTATTACHED;
  735. }
  736. // don't allow implicitly created attachments to be detached.
  737. if( ( curr->dwFlags & DDAL_IMPLICIT ) && ( !delete_implicit ) )
  738. {
  739. DPF_ERR( "Cannot delete an implicit attachment" );
  740. return DDERR_CANNOTDETACHSURFACE;
  741. }
  742. if( cleanup )
  743. {
  744. LPDDRAWI_DDRAWSURFACE_INT next_next_int;
  745. LPDDRAWI_DDRAWSURFACE_LCL next_lcl;
  746. LPDDRAWI_DDRAWSURFACE_GBL next;
  747. LPDDRAWI_DDRAWSURFACE_INT front_int;
  748. LPDDRAWI_DDRAWSURFACE_LCL front_lcl;
  749. LPDDRAWI_DDRAWSURFACE_GBL front;
  750. LPDDRAWI_DDRAWSURFACE_INT current_int;
  751. LPDDRAWI_DDRAWSURFACE_LCL current_lcl;
  752. LPDDRAWI_DDRAWSURFACE_INT prev_int;
  753. BOOL was_implicit;
  754. front_int = NULL;
  755. next_int = FindAttachedFlip( this_int );
  756. // if next is not equal to pattsurf then this link is not part
  757. // of a flippable chain. No other cleanup is necessary.
  758. if( next_int == pattsurf_int )
  759. {
  760. // find the front buffer in the chain
  761. next_int = FindAttachedFlip( pattsurf_int );
  762. for(current_int = next_int;
  763. (current_int != NULL);
  764. (current_int = FindAttachedFlip( current_int ) ) )
  765. {
  766. current_lcl = current_int->lpLcl;
  767. if( current_lcl->ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER )
  768. {
  769. front_int = current_int;
  770. front = front_int->lpLcl->lpGbl;
  771. }
  772. if( current_int == pattsurf_int )
  773. {
  774. break;
  775. }
  776. prev_int = current_int;
  777. }
  778. // if the frontbuffer was not found, don't do any cleanup
  779. if( ( next_int != NULL ) && ( front_int != NULL ) )
  780. {
  781. next_lcl = next_int->lpLcl;
  782. next = next_lcl->lpGbl;
  783. front_lcl = front_int->lpLcl;
  784. front_lcl->dwBackBufferCount--;
  785. if( front_lcl->dwBackBufferCount == 0 )
  786. {
  787. // this detachment will destroy the flippable chain
  788. next_lcl->ddsCaps.dwCaps &=
  789. ~(DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER );
  790. // restore BACKBUFFER CAP if it was originally created that way
  791. if( next_lcl->dwFlags & DDRAWISURF_BACKBUFFER )
  792. {
  793. next_lcl->ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
  794. }
  795. // restore FRONTBUFFER CAP if it was originally created that way
  796. if( next_lcl->dwFlags & DDRAWISURF_FRONTBUFFER )
  797. {
  798. next_lcl->ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
  799. }
  800. addrefed_pattsurf = TRUE;
  801. DD_Surface_AddRef( (LPDIRECTDRAWSURFACE)pattsurf_int );
  802. addrefed_this = TRUE;
  803. DD_Surface_AddRef( (LPDIRECTDRAWSURFACE)this_int );
  804. // remove one of the links
  805. DeleteOneLink( pattsurf_int, this_int );
  806. }
  807. else
  808. {
  809. // create a link from the previous surface to the
  810. // next surface, bypassing pattsurf
  811. was_implicit = isImplicitAttachment( this_int, pattsurf_int );
  812. AddAttachedSurface( prev_int, next_int, was_implicit );
  813. addrefed_pattsurf = TRUE;
  814. DD_Surface_AddRef( (LPDIRECTDRAWSURFACE)pattsurf_int );
  815. addrefed_this = TRUE;
  816. DD_Surface_AddRef( (LPDIRECTDRAWSURFACE)this_int );
  817. addrefed_next = TRUE;
  818. DD_Surface_AddRef( (LPDIRECTDRAWSURFACE)next_int );
  819. // delete the link from pattsurf to next
  820. DeleteOneLink( pattsurf_int, next_int );
  821. // pattsurf will now be completely removed from the
  822. // flippable chain once the final link is deleted.
  823. // this detachment will reduce the flippable chain by one
  824. // If pattsurf was a backbuffer, make the next surface
  825. // in the chain a backbuffer.
  826. if( pattsurf_lcl->ddsCaps.dwCaps & DDSCAPS_BACKBUFFER )
  827. {
  828. next_lcl->ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
  829. }
  830. // If pattsurf was a frontbuffer, make the next surface
  831. // in the chain a frontbuffer, and the next surface a
  832. // backbuffer.
  833. else if( pattsurf_lcl->ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER )
  834. {
  835. next_lcl->ddsCaps.dwCaps &= ~DDSCAPS_BACKBUFFER;
  836. next_lcl->ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
  837. next_lcl->dwBackBufferCount = front_lcl->dwBackBufferCount;
  838. next_next_int = FindAttachedFlip( next_int );
  839. if( next_next_int != NULL)
  840. {
  841. next_next_int->lpLcl->ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
  842. }
  843. front_lcl->dwBackBufferCount = 0;
  844. }
  845. }
  846. // reset the flags on the detached surface to indicate
  847. // that it is no longer part of a flippable chain.
  848. pattsurf_lcl->ddsCaps.dwCaps &=
  849. ~(DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER );
  850. // restore BACKBUFFER CAP if it was originally created that way
  851. if( pattsurf_lcl->dwFlags & DDRAWISURF_BACKBUFFER )
  852. {
  853. pattsurf_lcl->ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
  854. }
  855. // restore FRONTBUFFER CAP if it was originally created that way
  856. if( pattsurf_lcl->dwFlags & DDRAWISURF_FRONTBUFFER )
  857. {
  858. pattsurf_lcl->ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
  859. }
  860. }
  861. }
  862. }
  863. /*
  864. * delete the attached surface
  865. */
  866. rc = DeleteOneLink( this_int, pattsurf_int );
  867. if( addrefed_pattsurf )
  868. DD_Surface_Release( (LPDIRECTDRAWSURFACE)pattsurf_int);
  869. if( addrefed_this )
  870. DD_Surface_Release( (LPDIRECTDRAWSURFACE)this_int );
  871. if( addrefed_next )
  872. DD_Surface_Release( (LPDIRECTDRAWSURFACE)next_int );
  873. return rc;
  874. } /* DeleteOneAttachment */
  875. /*
  876. * DeleteOneLink
  877. *
  878. * delete a single attachment from surface.
  879. * ASSUMES DRIVER LOCK IS TAKEN!
  880. */
  881. HRESULT DeleteOneLink( LPDDRAWI_DDRAWSURFACE_INT this_int,
  882. LPDDRAWI_DDRAWSURFACE_INT pattsurf_int )
  883. {
  884. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  885. LPDDRAWI_DDRAWSURFACE_GBL this;
  886. LPDDRAWI_DDRAWSURFACE_LCL pattsurf_lcl;
  887. LPDDRAWI_DDRAWSURFACE_GBL pattsurf;
  888. LPATTACHLIST curr;
  889. LPATTACHLIST last;
  890. DPF( 4, "DeleteOneLink: %08lx,%08lx", this_int, pattsurf_int );
  891. this_lcl = this_int->lpLcl;
  892. this = this_lcl->lpGbl;
  893. pattsurf_lcl = pattsurf_int->lpLcl;
  894. pattsurf = pattsurf_lcl->lpGbl;
  895. /*
  896. * see if specified surface is attached
  897. */
  898. curr = this_lcl->lpAttachList;
  899. last = NULL;
  900. while( curr != NULL )
  901. {
  902. if( curr->lpIAttached == pattsurf_int )
  903. {
  904. break;
  905. }
  906. last = curr;
  907. curr = curr->lpLink;
  908. }
  909. if( curr == NULL )
  910. {
  911. return DDERR_SURFACENOTATTACHED;
  912. }
  913. #ifdef WINNT
  914. /*
  915. * let the kernel know
  916. * ...only if there's a kernel ddraw object.
  917. */
  918. if ( this_lcl->lpSurfMore->lpDD_lcl->lpGbl->hDD )
  919. {
  920. DdUnattachSurface( this_lcl, pattsurf_lcl );
  921. }
  922. #endif
  923. /*
  924. * delete the attached from link
  925. */
  926. if( last == NULL )
  927. {
  928. this_lcl->lpAttachList = curr->lpLink;
  929. }
  930. else
  931. {
  932. last->lpLink = curr->lpLink;
  933. }
  934. MemFree( curr );
  935. /*
  936. * remove the attached to link
  937. */
  938. curr = pattsurf_lcl->lpAttachListFrom;
  939. last = NULL;
  940. while( curr != NULL )
  941. {
  942. if( curr->lpIAttached == this_int )
  943. {
  944. break;
  945. }
  946. last = curr;
  947. curr = curr->lpLink;
  948. }
  949. if( curr == NULL )
  950. {
  951. return DDERR_SURFACENOTATTACHED;
  952. }
  953. /*
  954. * delete the attached to link
  955. */
  956. if( last == NULL )
  957. {
  958. pattsurf_lcl->lpAttachListFrom = curr->lpLink;
  959. }
  960. else
  961. {
  962. last->lpLink = curr->lpLink;
  963. }
  964. if( !(curr->dwFlags & DDAL_IMPLICIT))
  965. {
  966. DD_Surface_Release( (LPDIRECTDRAWSURFACE)pattsurf_int );
  967. }
  968. MemFree( curr );
  969. return DD_OK;
  970. } /* DeleteOneLink */
  971. /*
  972. * DD_Surface_DeleteAttachedSurfaces
  973. */
  974. HRESULT DDAPI DD_Surface_DeleteAttachedSurfaces(
  975. LPDIRECTDRAWSURFACE lpDDSurface,
  976. DWORD dwFlags,
  977. LPDIRECTDRAWSURFACE lpDDAttachedSurface )
  978. {
  979. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  980. LPDDRAWI_DDRAWSURFACE_INT this_int;
  981. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  982. LPDDRAWI_DDRAWSURFACE_GBL this;
  983. LPDDRAWI_DDRAWSURFACE_INT pattsurf_int;
  984. LPDDRAWI_DDRAWSURFACE_LCL pattsurf_lcl;
  985. LPDDRAWI_DDRAWSURFACE_GBL pattsurf;
  986. LPATTACHLIST curr;
  987. LPATTACHLIST next;
  988. HRESULT ddrval;
  989. ENTER_DDRAW();
  990. DPF(2,A,"ENTERAPI: DD_Surface_DeleteAttachedSurfaces");
  991. TRY
  992. {
  993. /*
  994. * validate parameters
  995. */
  996. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  997. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  998. {
  999. LEAVE_DDRAW();
  1000. return DDERR_INVALIDOBJECT;
  1001. }
  1002. this_lcl = this_int->lpLcl;
  1003. if( dwFlags )
  1004. {
  1005. DPF_ERR( "Invalid flags" );
  1006. LEAVE_DDRAW();
  1007. return DDERR_INVALIDPARAMS;
  1008. }
  1009. this = this_lcl->lpGbl;
  1010. pdrv = this->lpDD;
  1011. if( SURFACE_LOST( this_lcl ) )
  1012. {
  1013. LEAVE_DDRAW();
  1014. return DDERR_SURFACELOST;
  1015. }
  1016. pattsurf_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDAttachedSurface;
  1017. if( pattsurf_int != NULL )
  1018. {
  1019. if( !VALID_DIRECTDRAWSURFACE_PTR( pattsurf_int ) )
  1020. {
  1021. LEAVE_DDRAW();
  1022. return DDERR_INVALIDOBJECT;
  1023. }
  1024. pattsurf_lcl = pattsurf_int->lpLcl;
  1025. pattsurf = pattsurf_lcl->lpGbl;
  1026. if( SURFACE_LOST( pattsurf_lcl ) )
  1027. {
  1028. LEAVE_DDRAW();
  1029. return DDERR_SURFACELOST;
  1030. }
  1031. }
  1032. else
  1033. {
  1034. pattsurf_lcl = NULL;
  1035. pattsurf = NULL;
  1036. }
  1037. //
  1038. // If it is an Optimized surface, then continue only if:
  1039. // 1) The current and the attached surface are non-empty
  1040. // 2) Both are texture & mipmap
  1041. // 3) Both have the same optimization caps
  1042. //
  1043. // For now, if the current surface is optimized, quit
  1044. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  1045. {
  1046. DPF_ERR( "It is an optimized surface" );
  1047. LEAVE_DDRAW();
  1048. return DDERR_ISOPTIMIZEDSURFACE;
  1049. }
  1050. /*
  1051. * delete a single attachment
  1052. */
  1053. if( pattsurf != NULL )
  1054. {
  1055. ddrval = DeleteOneAttachment( this_int, pattsurf_int, TRUE, DOA_DONTDELETEIMPLICIT );
  1056. if( ddrval != DD_OK )
  1057. {
  1058. LEAVE_DDRAW();
  1059. return ddrval;
  1060. }
  1061. }
  1062. /*
  1063. * delete all attachments
  1064. */
  1065. else
  1066. {
  1067. curr = this_lcl->lpAttachList;
  1068. while( curr != NULL )
  1069. {
  1070. next = curr->lpLink;
  1071. ddrval = DeleteOneAttachment( this_int, curr->lpIAttached, TRUE, DOA_DONTDELETEIMPLICIT );
  1072. if( ddrval != DD_OK )
  1073. {
  1074. LEAVE_DDRAW();
  1075. return ddrval;
  1076. }
  1077. curr = next;
  1078. }
  1079. }
  1080. /*
  1081. * If the surface whose attachments were removed is a mip-map then
  1082. * it may have lost mip-map levels. Therefore we need to update its
  1083. * level count.
  1084. */
  1085. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_MIPMAP )
  1086. UpdateMipMapCount( this_int );
  1087. }
  1088. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1089. {
  1090. DPF_ERR( "Exception encountered validating parameters" );
  1091. LEAVE_DDRAW();
  1092. return DDERR_INVALIDPARAMS;
  1093. }
  1094. LEAVE_DDRAW();
  1095. return DD_OK;
  1096. } /* DD_Surface_DeleteAttachedSurfaces */
  1097. /*
  1098. * DeleteAttachedSurfaceLists
  1099. *
  1100. * Delete all attached surface lists from a surface
  1101. * Assumes that all parameters coming in are VALID!
  1102. */
  1103. void DeleteAttachedSurfaceLists( LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl )
  1104. {
  1105. LPATTACHLIST curr;
  1106. LPATTACHLIST next;
  1107. curr = psurf_lcl->lpAttachList;
  1108. while( curr != NULL )
  1109. {
  1110. next = curr->lpLink;
  1111. MemFree( curr );
  1112. curr = next;
  1113. }
  1114. curr = psurf_lcl->lpAttachListFrom;
  1115. while( curr != NULL )
  1116. {
  1117. next = curr->lpLink;
  1118. MemFree( curr );
  1119. curr = next;
  1120. }
  1121. psurf_lcl->lpAttachList = NULL;
  1122. psurf_lcl->lpAttachListFrom = NULL;
  1123. } /* DeleteAttachedSurfaceLists */
  1124. /*
  1125. * DD_Surface_EnumAttachedSurfaces
  1126. */
  1127. HRESULT DDAPI DD_Surface_EnumAttachedSurfaces(
  1128. LPDIRECTDRAWSURFACE lpDDSurface,
  1129. LPVOID lpContext,
  1130. LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback )
  1131. {
  1132. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  1133. LPDDRAWI_DDRAWSURFACE_INT this_int;
  1134. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  1135. LPDDRAWI_DDRAWSURFACE_GBL this;
  1136. LPATTACHLIST pal;
  1137. DDSURFACEDESC2 dsd;
  1138. DWORD rc;
  1139. ENTER_DDRAW();
  1140. DPF(2,A,"ENTERAPI: DD_Surface_EnumAttachedSurfaces");
  1141. TRY
  1142. {
  1143. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  1144. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  1145. {
  1146. LEAVE_DDRAW();
  1147. return DDERR_INVALIDOBJECT;
  1148. }
  1149. this_lcl = this_int->lpLcl;
  1150. if( !VALIDEX_CODE_PTR( lpEnumSurfacesCallback ) )
  1151. {
  1152. LEAVE_DDRAW();
  1153. return DDERR_INVALIDPARAMS;
  1154. }
  1155. /*
  1156. * take driver lock just in case callback comes into us
  1157. */
  1158. this = this_lcl->lpGbl;
  1159. pdrv = this->lpDD;
  1160. if( SURFACE_LOST( this_lcl ) )
  1161. {
  1162. LEAVE_DDRAW();
  1163. return DDERR_SURFACELOST;
  1164. }
  1165. }
  1166. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1167. {
  1168. DPF_ERR( "Exception encountered validating parameters" );
  1169. LEAVE_DDRAW();
  1170. return DDERR_INVALIDPARAMS;
  1171. }
  1172. /*
  1173. * run the attached list, calling the user's fn each time
  1174. */
  1175. pal = this_lcl->lpAttachList;
  1176. while( pal != NULL )
  1177. {
  1178. LPDIRECTDRAWSURFACE4 intReturned = (LPDIRECTDRAWSURFACE4) pal->lpIAttached;
  1179. FillDDSurfaceDesc2( pal->lpAttached, &dsd );
  1180. if (LOWERTHANSURFACE4(this_int))
  1181. {
  1182. dsd.dwSize = sizeof(DDSURFACEDESC);
  1183. DD_Surface_QueryInterface( (LPDIRECTDRAWSURFACE) pal->lpIAttached , & IID_IDirectDrawSurface, (void**) &intReturned );
  1184. }
  1185. else if (this_int->lpVtbl == &ddSurface4Callbacks)
  1186. {
  1187. DD_Surface_QueryInterface( (LPDIRECTDRAWSURFACE) pal->lpIAttached , & IID_IDirectDrawSurface4, (void**) &intReturned );
  1188. }
  1189. else
  1190. {
  1191. DD_Surface_QueryInterface( (LPDIRECTDRAWSURFACE) pal->lpIAttached , & IID_IDirectDrawSurface7, (void**) &intReturned );
  1192. }
  1193. rc = lpEnumSurfacesCallback( (LPDIRECTDRAWSURFACE) intReturned, (LPDDSURFACEDESC) &dsd, lpContext );
  1194. if( rc == 0 )
  1195. {
  1196. break;
  1197. }
  1198. pal = pal->lpLink;
  1199. }
  1200. LEAVE_DDRAW();
  1201. return DD_OK;
  1202. } /* DD_Surface_EnumAttachedSurfaces */
  1203. HRESULT DDAPI Internal_GetAttachedSurface(
  1204. REFIID riid,
  1205. LPDIRECTDRAWSURFACE4 lpDDSurface,
  1206. LPDDSCAPS2 lpDDSCaps,
  1207. LPVOID *lplpDDAttachedSurface)
  1208. {
  1209. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  1210. LPDDRAWI_DDRAWSURFACE_INT this_int;
  1211. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  1212. LPDDRAWI_DDRAWSURFACE_GBL this;
  1213. LPATTACHLIST pal;
  1214. DWORD caps;
  1215. DWORD testcaps;
  1216. DWORD ucaps;
  1217. DWORD caps2;
  1218. DWORD testcaps2;
  1219. DWORD ucaps2;
  1220. DWORD caps3;
  1221. DWORD testcaps3;
  1222. DWORD ucaps3;
  1223. DWORD caps4;
  1224. DWORD testcaps4;
  1225. DWORD ucaps4;
  1226. BOOL ok;
  1227. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  1228. this_lcl = this_int->lpLcl;
  1229. this = this_lcl->lpGbl;
  1230. *lplpDDAttachedSurface = NULL;
  1231. pdrv = this->lpDD;
  1232. /*
  1233. * look for the surface
  1234. */
  1235. pal = this_lcl->lpAttachList;
  1236. testcaps = lpDDSCaps->dwCaps;
  1237. testcaps2 = lpDDSCaps->dwCaps2;
  1238. testcaps3 = lpDDSCaps->dwCaps3;
  1239. testcaps4 = lpDDSCaps->dwCaps4;
  1240. while( pal != NULL )
  1241. {
  1242. ok = TRUE;
  1243. caps = pal->lpAttached->ddsCaps.dwCaps;
  1244. caps2 = pal->lpAttached->lpSurfMore->ddsCapsEx.dwCaps2;
  1245. caps3 = pal->lpAttached->lpSurfMore->ddsCapsEx.dwCaps3;
  1246. caps4 = pal->lpAttached->lpSurfMore->ddsCapsEx.dwCaps4;
  1247. ucaps = caps & testcaps;
  1248. ucaps2 = caps2 & testcaps2;
  1249. ucaps3 = caps3 & testcaps3;
  1250. ucaps4 = caps4 & testcaps4;
  1251. if( ucaps | ucaps2 | ucaps3 | ucaps4 )
  1252. {
  1253. /*
  1254. * there are caps in common, make sure that the caps to test
  1255. * were all there
  1256. */
  1257. if( (ucaps & testcaps) == testcaps &&
  1258. (ucaps2 & testcaps2) == testcaps2 &&
  1259. (ucaps3 & testcaps3) == testcaps3 &&
  1260. (ucaps4 & testcaps4) == testcaps4 )
  1261. {
  1262. }
  1263. else
  1264. {
  1265. ok = FALSE;
  1266. }
  1267. }
  1268. else
  1269. {
  1270. ok = FALSE;
  1271. }
  1272. if( ok )
  1273. {
  1274. /*
  1275. * QI for the appropriate Surface interface and return it
  1276. */
  1277. DD_Surface_QueryInterface(
  1278. (LPDIRECTDRAWSURFACE) pal->lpIAttached,
  1279. riid,
  1280. lplpDDAttachedSurface);
  1281. // DD_Surface_AddRef( (LPDIRECTDRAWSURFACE) pal->lpIAttached );
  1282. // *lplpDDAttachedSurface = (LPDIRECTDRAWSURFACE) pal->lpIAttached;
  1283. return DD_OK;
  1284. }
  1285. pal = pal->lpLink;
  1286. }
  1287. return DDERR_NOTFOUND;
  1288. } /* Internal_GetAttachedSurface */
  1289. HRESULT WINAPI DDGetAttachedSurfaceLcl(
  1290. LPDDRAWI_DDRAWSURFACE_LCL this_lcl,
  1291. LPDDSCAPS2 lpDDSCaps,
  1292. LPDDRAWI_DDRAWSURFACE_LCL *lplpDDAttachedSurfaceLcl)
  1293. {
  1294. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  1295. LPDDRAWI_DDRAWSURFACE_GBL this;
  1296. LPATTACHLIST pal;
  1297. DWORD caps;
  1298. DWORD testcaps;
  1299. DWORD ucaps;
  1300. DWORD caps2;
  1301. DWORD testcaps2;
  1302. DWORD ucaps2;
  1303. DWORD caps3;
  1304. DWORD testcaps3;
  1305. DWORD ucaps3;
  1306. DWORD caps4;
  1307. DWORD testcaps4;
  1308. DWORD ucaps4;
  1309. BOOL ok;
  1310. this = this_lcl->lpGbl;
  1311. *lplpDDAttachedSurfaceLcl = NULL;
  1312. pdrv = this->lpDD;
  1313. /*
  1314. * look for the surface
  1315. */
  1316. pal = this_lcl->lpAttachList;
  1317. testcaps = lpDDSCaps->dwCaps;
  1318. testcaps2 = lpDDSCaps->dwCaps2;
  1319. testcaps3 = lpDDSCaps->dwCaps3;
  1320. testcaps4 = lpDDSCaps->dwCaps4;
  1321. while( pal != NULL )
  1322. {
  1323. ok = TRUE;
  1324. caps = pal->lpAttached->ddsCaps.dwCaps;
  1325. caps2 = pal->lpAttached->lpSurfMore->ddsCapsEx.dwCaps2;
  1326. caps3 = pal->lpAttached->lpSurfMore->ddsCapsEx.dwCaps3;
  1327. caps4 = pal->lpAttached->lpSurfMore->ddsCapsEx.dwCaps4;
  1328. ucaps = caps & testcaps;
  1329. ucaps2 = caps2 & testcaps2;
  1330. ucaps3 = caps3 & testcaps3;
  1331. ucaps4 = caps4 & testcaps4;
  1332. if( ucaps | ucaps2 | ucaps3 | ucaps4 )
  1333. {
  1334. /*
  1335. * there are caps in common, make sure that the caps to test
  1336. * were all there
  1337. */
  1338. if( (ucaps & testcaps) == testcaps &&
  1339. (ucaps2 & testcaps2) == testcaps2 &&
  1340. (ucaps3 & testcaps3) == testcaps3 &&
  1341. (ucaps4 & testcaps4) == testcaps4 )
  1342. {
  1343. }
  1344. else
  1345. {
  1346. ok = FALSE;
  1347. }
  1348. }
  1349. else
  1350. {
  1351. ok = FALSE;
  1352. }
  1353. if( ok )
  1354. {
  1355. *lplpDDAttachedSurfaceLcl = pal->lpAttached;
  1356. return DD_OK;
  1357. }
  1358. pal = pal->lpLink;
  1359. }
  1360. return DDERR_NOTFOUND;
  1361. } /* DDGetAttachedSurfaceLcl */
  1362. /*
  1363. * DD_Surface_GetAttachedSurface
  1364. *
  1365. * Search for an attached surface with a cap set. The caps specified
  1366. * all have to be in the caps of the surface (but the surface can have
  1367. * additional caps)
  1368. */
  1369. HRESULT DDAPI DD_Surface_GetAttachedSurface(
  1370. LPDIRECTDRAWSURFACE lpDDSurface,
  1371. LPDDSCAPS lpDDSCaps,
  1372. LPDIRECTDRAWSURFACE FAR * lplpDDAttachedSurface)
  1373. {
  1374. HRESULT hr;
  1375. DDSCAPS2 ddscaps2 = {0,0,0,0};
  1376. LPDDRAWI_DDRAWSURFACE_INT this_int;
  1377. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  1378. ENTER_DDRAW();
  1379. DPF(2,A,"ENTERAPI: DD_Surface_GetAttachedSurface");
  1380. TRY
  1381. {
  1382. /*
  1383. * Have to duplicate all error checks which come before the lpDDSCaps
  1384. * checks because
  1385. * otherwise we might pass different error returns to the app in error
  1386. * conditions.
  1387. */
  1388. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  1389. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  1390. {
  1391. LEAVE_DDRAW();
  1392. return DDERR_INVALIDOBJECT;
  1393. }
  1394. this_lcl = this_int->lpLcl;
  1395. if( SURFACE_LOST( this_lcl ) )
  1396. {
  1397. LEAVE_DDRAW();
  1398. return DDERR_SURFACELOST;
  1399. }
  1400. if( !VALID_DDSCAPS_PTR( lpDDSCaps ) )
  1401. {
  1402. LEAVE_DDRAW();
  1403. return DDERR_INVALIDPARAMS;
  1404. }
  1405. ddscaps2.dwCaps = lpDDSCaps->dwCaps;
  1406. }
  1407. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1408. {
  1409. DPF_ERR( "Invalid DDSCAPS pointer" );
  1410. LEAVE_DDRAW();
  1411. return DDERR_INVALIDPARAMS;
  1412. }
  1413. hr = Internal_GetAttachedSurface(
  1414. &IID_IDirectDrawSurface,
  1415. (LPDIRECTDRAWSURFACE4)lpDDSurface,
  1416. &ddscaps2,
  1417. (LPVOID *)lplpDDAttachedSurface
  1418. );
  1419. LEAVE_DDRAW();
  1420. return hr;
  1421. }
  1422. /*
  1423. * IDirectDrawSurface4::GetAttachedSurface
  1424. */
  1425. HRESULT DDAPI DD_Surface_GetAttachedSurface4(
  1426. LPDIRECTDRAWSURFACE4 lpDDSurface,
  1427. LPDDSCAPS2 lpDDSCaps,
  1428. LPDIRECTDRAWSURFACE4 FAR * lplpDDAttachedSurface)
  1429. {
  1430. HRESULT hr;
  1431. LPDDRAWI_DDRAWSURFACE_INT this_int;
  1432. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  1433. DDSCAPS2 ddsCaps2;
  1434. ENTER_DDRAW();
  1435. DPF(2,A,"ENTERAPI: DD_Surface_GetAttachedSurface4");
  1436. TRY
  1437. {
  1438. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  1439. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  1440. {
  1441. LEAVE_DDRAW();
  1442. return DDERR_INVALIDOBJECT;
  1443. }
  1444. this_lcl = this_int->lpLcl;
  1445. if( SURFACE_LOST( this_lcl ) )
  1446. {
  1447. LEAVE_DDRAW();
  1448. return DDERR_SURFACELOST;
  1449. }
  1450. if( !VALID_DDSCAPS2_PTR( lpDDSCaps ) )
  1451. {
  1452. LEAVE_DDRAW();
  1453. return DDERR_INVALIDPARAMS;
  1454. }
  1455. if( lpDDSCaps->dwCaps & ~DDSCAPS_VALID )
  1456. {
  1457. DPF_ERR( "Invalid caps specified" );
  1458. LEAVE_DDRAW();
  1459. return DDERR_INVALIDCAPS;
  1460. }
  1461. if( !VALID_PTR_PTR( lplpDDAttachedSurface ) )
  1462. {
  1463. LEAVE_DDRAW();
  1464. return DDERR_INVALIDPARAMS;
  1465. }
  1466. *lplpDDAttachedSurface = NULL;
  1467. ddsCaps2 = *lpDDSCaps;
  1468. }
  1469. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1470. {
  1471. DPF_ERR( "Exception encountered validating parameters" );
  1472. LEAVE_DDRAW();
  1473. return DDERR_INVALIDPARAMS;
  1474. }
  1475. DDASSERT(this_int->lpVtbl == &ddSurface4Callbacks);
  1476. /*
  1477. * mistake in DX6: Internal_GetAttachedSurface never tested the extended caps.
  1478. * To avoid regression in DX7, we have to make IGAS respond the same now that it does
  1479. * test the extended caps. We do this by copying the app's caps and zeroing out the
  1480. * extended ones.
  1481. */
  1482. ddsCaps2.dwCaps2 = ddsCaps2.dwCaps3 = ddsCaps2.dwCaps4 = 0;
  1483. hr = Internal_GetAttachedSurface(
  1484. &IID_IDirectDrawSurface4,
  1485. lpDDSurface,
  1486. &ddsCaps2,
  1487. (LPVOID *)lplpDDAttachedSurface
  1488. );
  1489. LEAVE_DDRAW();
  1490. return hr;
  1491. } /* DD_Surface_GetAttachedSurface4 */
  1492. /*
  1493. * IDirectDrawSurface7::GetAttachedSurface
  1494. */
  1495. HRESULT DDAPI DD_Surface_GetAttachedSurface7(
  1496. LPDIRECTDRAWSURFACE7 lpDDSurface,
  1497. LPDDSCAPS2 lpDDSCaps,
  1498. LPDIRECTDRAWSURFACE7 FAR * lplpDDAttachedSurface)
  1499. {
  1500. HRESULT hr;
  1501. LPDDRAWI_DDRAWSURFACE_INT this_int;
  1502. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  1503. ENTER_DDRAW();
  1504. DPF(2,A,"ENTERAPI: DD_Surface_GetAttachedSurface7");
  1505. TRY
  1506. {
  1507. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  1508. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  1509. {
  1510. LEAVE_DDRAW();
  1511. return DDERR_INVALIDOBJECT;
  1512. }
  1513. this_lcl = this_int->lpLcl;
  1514. if( SURFACE_LOST( this_lcl ) )
  1515. {
  1516. LEAVE_DDRAW();
  1517. return DDERR_SURFACELOST;
  1518. }
  1519. if( !VALID_DDSCAPS2_PTR( lpDDSCaps ) )
  1520. {
  1521. LEAVE_DDRAW();
  1522. return DDERR_INVALIDPARAMS;
  1523. }
  1524. if( lpDDSCaps->dwCaps & ~DDSCAPS_VALID )
  1525. {
  1526. DPF_ERR( "Invalid caps specified" );
  1527. LEAVE_DDRAW();
  1528. return DDERR_INVALIDCAPS;
  1529. }
  1530. if( !VALID_PTR_PTR( lplpDDAttachedSurface ) )
  1531. {
  1532. LEAVE_DDRAW();
  1533. return DDERR_INVALIDPARAMS;
  1534. }
  1535. *lplpDDAttachedSurface = NULL;
  1536. }
  1537. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1538. {
  1539. DPF_ERR( "Exception encountered validating parameters" );
  1540. LEAVE_DDRAW();
  1541. return DDERR_INVALIDPARAMS;
  1542. }
  1543. DDASSERT(this_int->lpVtbl == &ddSurface7Callbacks);
  1544. hr = Internal_GetAttachedSurface(
  1545. &IID_IDirectDrawSurface7,
  1546. (LPDIRECTDRAWSURFACE4)lpDDSurface,
  1547. lpDDSCaps,
  1548. (LPVOID *)lplpDDAttachedSurface
  1549. );
  1550. LEAVE_DDRAW();
  1551. return hr;
  1552. } /* DD_Surface_GetAttachedSurface7 */