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.

6982 lines
210 KiB

  1. /*==========================================================================
  2. * Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved.
  3. *
  4. * File: ddsurf.c
  5. * Content: DirectDraw engine surface support
  6. * History:
  7. * Date By Reason
  8. * ==== == ======
  9. * 25-dec-94 craige initial implementation
  10. * 13-jan-95 craige re-worked to updated spec + ongoing work
  11. * 21-jan-95 craige made 32-bit + ongoing work
  12. * 31-jan-95 craige and even more ongoing work...
  13. * 06-feb-95 craige performance tuning, ongoing work
  14. * 27-feb-95 craige new sync. macros
  15. * 07-mar-95 craige keep track of flippable surfaces
  16. * 11-mar-95 craige palette stuff, keep track of process surface usage
  17. * 15-mar-95 craige HEL
  18. * 19-mar-95 craige use HRESULTs
  19. * 20-mar-95 craige allow NULL rect to disable cliplist
  20. * 31-mar-95 craige don't allow hWnd to be updated if in exclusive mode
  21. * and requesting process isn't the holder
  22. * 01-apr-95 craige happy fun joy updated header file
  23. * 12-apr-95 craige proper call order for csects
  24. * 15-apr-95 craige flags for GetFlipStatus, added GetBltStatus
  25. * 16-apr-95 craige flip between two specific surfaces was broken
  26. * 06-may-95 craige use driver-level csects only
  27. * 23-may-95 craige no longer use MapLS_Pool
  28. * 24-may-95 craige added Restore
  29. * 28-may-95 craige cleaned up HAL: added GetBltStatus; GetFlipStatus
  30. * 04-jun-95 craige flesh out Restore; check for SURFACE_LOST inside csect;
  31. * added IsLost
  32. * 11-jun-95 craige prevent restoration of primary if different mode
  33. * 12-jun-95 craige new process list stuff
  34. * 13-jun-95 kylej moved FindAttachedFlip to misc.c
  35. * 17-jun-95 craige new surface structure
  36. * 19-jun-95 craige split out surface notification methods
  37. * 20-jun-95 craige go get current clip list if user didn't specify one
  38. * 24-jun-95 kylej added MoveToSystemMemory
  39. * 25-jun-95 craige one ddraw mutex
  40. * 26-jun-95 craige reorganized surface structure
  41. * 27-jun-95 craige don't let surfaces be restored if the mode is different
  42. * 28-jun-95 craige fixed flip for overlays; ENTER_DDRAW at start of fns
  43. * 30-jun-95 kylej only allow flip in exclusive mode, only allow surface
  44. * restore in same video mode it was created, force
  45. * primary to match existing primaries upon restore if
  46. * not exclusive, added GetProcessPrimary,
  47. * InvalidateAllPrimarySurfaces, FindGlobalPrimary,
  48. * and MatchPrimary
  49. * 30-jun-95 craige use DDRAWI_HASPIXELFORMAT/HASOVERLAYDATA
  50. * 01-jul-95 craige allow flip always - just fail creation of flipping
  51. * 04-jul-95 craige YEEHAW: new driver struct; SEH; redid Primary fns;
  52. * fixes to MoveToSystemMemory; fixes to
  53. * InvalidateAllPrimarySurfaces
  54. * 05-jul-95 craige added Initialize
  55. * 07-jul-95 craige added test for BUSY
  56. * 08-jul-95 craige return DD_OK from Restore if surface is not lost;
  57. * added InvalidateAllSurfaces
  58. * 09-jul-95 craige Restore needs to reset pitch to aligned width before
  59. * asking driver to reallocate; make MoveToSystemMemory
  60. * recreate without VRAM so Restore can restore to sysmem
  61. * 11-jul-95 craige GetDC fixes: no GetDC(NULL); need flag to check if
  62. * DC has been allocated
  63. * 15-jul-95 craige fixed flipping to move heap along with ptr
  64. * 15-jul-95 ericeng SetCompression if0 out, obsolete
  65. * 20-jul-95 toddla fixed MoveToSystemMemory for 16bpp
  66. * 01-aug-95 craige hold win16 lock at start of Flip
  67. * 04-aug-95 craige have MoveToSystemMemory use InternalLock/Unlock
  68. * 10-aug-95 toddla added DDFLIP_WAIT flag, but it is not turned on
  69. * 12-aug-95 craige added use_full_lock in MoveToSystemMemory
  70. * 13-aug-95 craige turned on DDFLIP_WAIT
  71. * 26-aug-95 craige bug 717
  72. * 05-sep-95 craige bug 894: don't invalidate SYSMEMREQUESTED surfaces
  73. * 10-sep-95 craige bug 828: random vidmem heap free
  74. * 22-sep-95 craige bug 1268,1269: getbltstatus/getflipstatus flags wrong
  75. * 09-dec-95 colinmc added execute buffer support
  76. * 17-dec-95 colinmc added shared back and z-buffer support
  77. * 02-jan-96 kylej handle new interface structs
  78. * 26-jan-96 jeffno NT kernel conversation. NT Get/Release DC, flip GDI flag
  79. * 09-feb-96 colinmc surface invalid flag moved from the global to local
  80. * surface object
  81. * 17-feb-96 colinmc removed execute buffer size limitation
  82. * 26-feb-96 jeffno GetDC for emulated offscreen now returns a new dc
  83. * 13-mar-96 kylej Added DD_Surface_GetDDInterface
  84. * 17-mar-96 colinmc Bug 13124: flippable mip-maps
  85. * 14-apr-96 colinmc Bug 17736: No driver notification of flip to GDI
  86. * surface
  87. * 26-mar-96 jeffno Handle mode changes before flip (NT)
  88. * 05-sep-96 craige added code to display frame rate to debug monitor
  89. * 05-jul-96 colinmc Work Item: Remove requirement on taking Win16 lock
  90. * for VRAM surfaces (not primary)
  91. * 07-oct-96 ketand Change PageLock/Unlock to cache Physical Addresses
  92. * 12-oct-96 colinmc Improvements to Win16 locking code to reduce virtual
  93. * memory usage
  94. * 19-nov-96 colinmc Bug 4987: Fixed problems with Flip on the
  95. * IDirectDrawSurface2 interface
  96. * 10-jan-97 jeffno Flip the primary chain flags so that GDI<==>Primary
  97. * after a ctrl-alt-del on NT.
  98. * 12-jan-97 colinmc More Win16 lock work
  99. * 18-jan-97 colinmc AGP support
  100. * 31-jan-97 colinmc Bug 5457: Fixed aliased locking (no Win16 lock)
  101. * problem with playing multiple AMovie clips at once.
  102. * 22-feb-97 colinmc Enabled OWNDC support for explicit system memory
  103. * surfaces
  104. * 03-mar-97 smac Added kernel mode interface
  105. * 04-mar-97 smac Bug 1987: Fixed bug flipping overlays when the
  106. * surface didn't own the hardware
  107. * 08-mar-97 colinmc Added function to let surface pointer be overridden
  108. * 11-mar-97 jeffno Asynchronous DMA support
  109. * 24-mar-97 jeffno Optimized Surfaces
  110. * 30-sep-97 jeffno IDirectDraw4
  111. * 03-oct-97 jeffno DDSCAPS2 and DDSURFACEDESC2
  112. * 31-oct-97 johnstep Persistent-content surfaces for Windows 9x
  113. * 11-nov-97 jvanaken New API call "Resize"
  114. * 18-dec-97 jvanaken SetSurfDesc will free client-alloc'd surface memory.
  115. * 25-may-00 RichGr IA64: Change debug output to use %p format specifier
  116. * instead of %x for 32/64-bit pointers.
  117. *
  118. ***************************************************************************/
  119. #include "ddrawpr.h"
  120. #ifdef WINNT
  121. #include "ddrawgdi.h"
  122. #endif
  123. #define DPF_MODNAME "GetCaps"
  124. /* Shorter name makes flip code a little easier to understand */
  125. #define GBLMORE(lpGbl) GET_LPDDRAWSURFACE_GBL_MORE(lpGbl)
  126. /*
  127. * DD_Surface_GetCaps
  128. */
  129. HRESULT DDAPI DD_Surface_GetCaps(
  130. LPDIRECTDRAWSURFACE lpDDSurface,
  131. LPDDSCAPS lpDDSCaps )
  132. {
  133. DDSCAPS2 ddscaps2 = {0,0,0,0};
  134. HRESULT hr;
  135. DPF(2,A,"ENTERAPI: DD_Surface_GetCaps");
  136. hr = DD_Surface_GetCaps4(lpDDSurface, & ddscaps2 );
  137. if (hr == DD_OK)
  138. {
  139. TRY
  140. {
  141. lpDDSCaps->dwCaps = ddscaps2.dwCaps;
  142. }
  143. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  144. {
  145. DPF_ERR( "Invalid DDSCAPS pointer" );
  146. return DDERR_INVALIDPARAMS;
  147. }
  148. }
  149. return hr;
  150. }
  151. HRESULT DDAPI DD_Surface_GetCaps4(
  152. LPDIRECTDRAWSURFACE lpDDSurface,
  153. LPDDSCAPS2 lpDDSCaps )
  154. {
  155. LPDDRAWI_DDRAWSURFACE_INT this_int;
  156. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  157. LPDDRAWI_DDRAWSURFACE_GBL this;
  158. ENTER_DDRAW();
  159. DPF(2,A,"ENTERAPI: DD_Surface_GetCaps4");
  160. TRY
  161. {
  162. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  163. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  164. {
  165. LEAVE_DDRAW();
  166. return DDERR_INVALIDOBJECT;
  167. }
  168. if( !VALID_DDSCAPS2_PTR( lpDDSCaps ) )
  169. {
  170. LEAVE_DDRAW();
  171. return DDERR_INVALIDPARAMS;
  172. }
  173. this_lcl = this_int->lpLcl;
  174. this = this_lcl->lpGbl;
  175. lpDDSCaps->dwCaps = this_lcl->ddsCaps.dwCaps;
  176. lpDDSCaps->ddsCapsEx = this_lcl->lpSurfMore->ddsCapsEx;
  177. }
  178. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  179. {
  180. DPF_ERR( "Exception encountered validating parameters" );
  181. LEAVE_DDRAW();
  182. return DDERR_INVALIDPARAMS;
  183. }
  184. LEAVE_DDRAW();
  185. return DD_OK;
  186. } /* DD_Surface_GetCaps */
  187. #undef DPF_MODNAME
  188. #define DPF_MODNAME "GetFlipStatus"
  189. /*
  190. * DD_Surface_GetFlipStatus
  191. */
  192. HRESULT DDAPI DD_Surface_GetFlipStatus(
  193. LPDIRECTDRAWSURFACE lpDDSurface,
  194. DWORD dwFlags )
  195. {
  196. LPDDRAWI_DDRAWSURFACE_INT this_int;
  197. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  198. LPDDRAWI_DDRAWSURFACE_GBL this;
  199. LPDDHALSURFCB_GETFLIPSTATUS gfshalfn;
  200. LPDDHALSURFCB_GETFLIPSTATUS gfsfn;
  201. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  202. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  203. ENTER_DDRAW();
  204. DPF(2,A,"ENTERAPI: DD_Surface_GetFlipStatus");
  205. TRY
  206. {
  207. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  208. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  209. {
  210. LEAVE_DDRAW();
  211. return DDERR_INVALIDOBJECT;
  212. }
  213. if( dwFlags & ~DDGFS_VALID )
  214. {
  215. DPF_ERR( "Invalid flags" );
  216. LEAVE_DDRAW();
  217. return DDERR_INVALIDPARAMS;
  218. }
  219. if( dwFlags )
  220. {
  221. if( (dwFlags & (DDGFS_CANFLIP|DDGFS_ISFLIPDONE)) ==
  222. (DDGFS_CANFLIP|DDGFS_ISFLIPDONE) )
  223. {
  224. DPF_ERR( "Invalid flags" );
  225. LEAVE_DDRAW();
  226. return DDERR_INVALIDPARAMS;
  227. }
  228. }
  229. else
  230. {
  231. DPF_ERR( "Invalid flags - no flag specified" );
  232. LEAVE_DDRAW();
  233. return DDERR_INVALIDPARAMS;
  234. }
  235. this_lcl = this_int->lpLcl;
  236. this = this_lcl->lpGbl;
  237. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  238. pdrv = pdrv_lcl->lpGbl;
  239. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
  240. {
  241. DPF_ERR( "Invalid surface type: can't get flip status" );
  242. LEAVE_DDRAW();
  243. return DDERR_INVALIDSURFACETYPE;
  244. }
  245. if( SURFACE_LOST( this_lcl ) )
  246. {
  247. LEAVE_DDRAW();
  248. return DDERR_SURFACELOST;
  249. }
  250. #ifdef USE_ALIAS
  251. if( pdrv->dwBusyDueToAliasedLock > 0 )
  252. {
  253. /*
  254. * Aliased locks (the ones that don't take the Win16 lock) don't
  255. * set the busy bit either (it can't or USER get's very confused).
  256. * However, we must prevent blits happening via DirectDraw as
  257. * otherwise we get into the old host talking to VRAM while
  258. * blitter does at the same time. Bad. So fail if there is an
  259. * outstanding aliased lock just as if the BUST bit had been
  260. * set.
  261. */
  262. DPF_ERR( "Graphics adapter is busy (due to a DirectDraw lock)" );
  263. LEAVE_DDRAW();
  264. return DDERR_SURFACEBUSY;
  265. }
  266. #endif /* USE_ALIAS */
  267. /*
  268. * device busy?
  269. */
  270. if( *(pdrv->lpwPDeviceFlags) & BUSY )
  271. {
  272. DPF( 0, "BUSY" );
  273. LEAVE_DDRAW()
  274. return DDERR_SURFACEBUSY;
  275. }
  276. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
  277. {
  278. LEAVE_DDRAW()
  279. return DD_OK;
  280. }
  281. }
  282. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  283. {
  284. DPF_ERR( "Exception encountered validating parameters" );
  285. LEAVE_DDRAW();
  286. return DDERR_INVALIDPARAMS;
  287. }
  288. /*
  289. * ask the driver to get the current flip status
  290. */
  291. gfsfn = pdrv_lcl->lpDDCB->HALDDSurface.GetFlipStatus;
  292. gfshalfn = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.GetFlipStatus;
  293. if( gfshalfn != NULL )
  294. {
  295. DDHAL_GETFLIPSTATUSDATA gfsd;
  296. DWORD rc;
  297. gfsd.GetFlipStatus = gfshalfn;
  298. gfsd.lpDD = pdrv;
  299. gfsd.dwFlags = dwFlags;
  300. gfsd.lpDDSurface = this_lcl;
  301. DOHALCALL( GetFlipStatus, gfsfn, gfsd, rc, FALSE );
  302. if( rc == DDHAL_DRIVER_HANDLED )
  303. {
  304. LEAVE_DDRAW();
  305. return gfsd.ddRVal;
  306. }
  307. }
  308. LEAVE_DDRAW();
  309. // if you have to ask the hel, it's already done
  310. return DD_OK;
  311. } /* DD_Surface_GetFlipStatus */
  312. #undef DPF_MODNAME
  313. #define DPF_MODNAME "InternalGetBltStatus"
  314. HRESULT InternalGetBltStatus(LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl, LPDDRAWI_DDRAWSURFACE_LCL this_lcl , DWORD dwFlags )
  315. {
  316. DDHAL_GETBLTSTATUSDATA gbsd;
  317. LPDDHALSURFCB_GETBLTSTATUS gbsfn;
  318. /*
  319. * Ask the driver to get the current blt status
  320. *
  321. */
  322. if ( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
  323. {
  324. gbsfn = pdrv_lcl->lpDDCB->HALDDMiscellaneous.GetSysmemBltStatus;
  325. gbsd.GetBltStatus = pdrv_lcl->lpDDCB->HALDDMiscellaneous.GetSysmemBltStatus;
  326. }
  327. else
  328. {
  329. gbsfn = pdrv_lcl->lpDDCB->HALDDSurface.GetBltStatus;
  330. gbsd.GetBltStatus = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.GetBltStatus;
  331. }
  332. if( gbsd.GetBltStatus != NULL )
  333. {
  334. DWORD rc;
  335. gbsd.lpDD = pdrv_lcl->lpGbl;
  336. gbsd.dwFlags = dwFlags;
  337. gbsd.lpDDSurface = this_lcl;
  338. DOHALCALL( GetBltStatus, gbsfn, gbsd, rc, FALSE );
  339. if( rc == DDHAL_DRIVER_HANDLED )
  340. {
  341. return gbsd.ddRVal;
  342. }
  343. }
  344. return DD_OK;
  345. }
  346. #undef DPF_MODNAME
  347. #define DPF_MODNAME "GetBltStatus"
  348. /*
  349. * DD_Surface_GetBltStatus
  350. */
  351. HRESULT DDAPI DD_Surface_GetBltStatus(
  352. LPDIRECTDRAWSURFACE lpDDSurface,
  353. DWORD dwFlags )
  354. {
  355. LPDDRAWI_DDRAWSURFACE_INT this_int;
  356. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  357. LPDDRAWI_DDRAWSURFACE_GBL this;
  358. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  359. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  360. HRESULT ddrval;
  361. ENTER_DDRAW();
  362. DPF(2,A,"ENTERAPI: DD_Surface_GetBltStatus");
  363. TRY
  364. {
  365. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  366. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  367. {
  368. LEAVE_DDRAW();
  369. return DDERR_INVALIDOBJECT;
  370. }
  371. this_lcl = this_int->lpLcl;
  372. if( dwFlags & ~DDGBS_VALID )
  373. {
  374. DPF_ERR( "Invalid flags" );
  375. LEAVE_DDRAW();
  376. return DDERR_INVALIDPARAMS;
  377. }
  378. if( dwFlags )
  379. {
  380. if( (dwFlags & (DDGBS_CANBLT|DDGBS_ISBLTDONE)) ==
  381. (DDGBS_CANBLT|DDGBS_ISBLTDONE) )
  382. {
  383. DPF_ERR( "Invalid flags" );
  384. LEAVE_DDRAW();
  385. return DDERR_INVALIDPARAMS;
  386. }
  387. }
  388. else
  389. {
  390. DPF_ERR( "Invalid flags - no flag specified" );
  391. LEAVE_DDRAW();
  392. return DDERR_INVALIDPARAMS;
  393. }
  394. this = this_lcl->lpGbl;
  395. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  396. pdrv = pdrv_lcl->lpGbl;
  397. if( SURFACE_LOST( this_lcl ) )
  398. {
  399. LEAVE_DDRAW();
  400. return DDERR_SURFACELOST;
  401. }
  402. #ifdef USE_ALIAS
  403. if( pdrv->dwBusyDueToAliasedLock > 0 )
  404. {
  405. /*
  406. * Aliased locks (the ones that don't take the Win16 lock) don't
  407. * set the busy bit either (it can't or USER get's very confused).
  408. * However, we must prevent blits happening via DirectDraw as
  409. * otherwise we get into the old host talking to VRAM while
  410. * blitter does at the same time. Bad. So fail if there is an
  411. * outstanding aliased lock just as if the BUST bit had been
  412. * set.
  413. */
  414. DPF_ERR( "Graphics adapter is busy (due to a DirectDraw lock)" );
  415. LEAVE_DDRAW();
  416. return DDERR_SURFACEBUSY;
  417. }
  418. #endif /* USE_ALIAS */
  419. /*
  420. * device busy?
  421. */
  422. if( *(pdrv->lpwPDeviceFlags) & BUSY )
  423. {
  424. DPF( 0, "BUSY" );
  425. LEAVE_DDRAW()
  426. return DDERR_SURFACEBUSY;
  427. }
  428. // If DDCAPS_CANBLTSYSMEM is set, we have to let the driver tell us
  429. // whether a system memory surface is currently being blitted
  430. if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) &&
  431. !( pdrv->ddCaps.dwCaps & DDCAPS_CANBLTSYSMEM ) )
  432. {
  433. LEAVE_DDRAW()
  434. return DD_OK;
  435. }
  436. }
  437. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  438. {
  439. DPF_ERR( "Exception encountered validating parameters" );
  440. LEAVE_DDRAW();
  441. return DDERR_INVALIDPARAMS;
  442. }
  443. //
  444. // If the current surface is optimized, quit
  445. //
  446. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  447. {
  448. DPF_ERR( "It is an optimized surface" );
  449. LEAVE_DDRAW();
  450. return DDERR_ISOPTIMIZEDSURFACE;
  451. }
  452. ddrval = InternalGetBltStatus( pdrv_lcl, this_lcl, dwFlags );
  453. LEAVE_DDRAW();
  454. return ddrval;
  455. } /* DD_Surface_GetBltStatus */
  456. #if 0
  457. /*
  458. * DD_Surface_Flush
  459. */
  460. HRESULT DDAPI DD_Surface_Flush(
  461. LPDIRECTDRAWSURFACE lpDDSurface,
  462. DWORD dwFlags )
  463. {
  464. LPDDRAWI_DDRAWSURFACE_INT this_int;
  465. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  466. LPDDRAWI_DDRAWSURFACE_GBL this;
  467. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  468. ENTER_DDRAW();
  469. DPF(2,A,"ENTERAPI: DD_Surface_Flush");
  470. TRY
  471. {
  472. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  473. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  474. {
  475. LEAVE_DDRAW();
  476. return DDERR_INVALIDOBJECT;
  477. }
  478. this_lcl = this_int->lpLcl;
  479. this = this_lcl->lpGbl;
  480. pdrv = this->lpDD;
  481. if( SURFACE_LOST( this_lcl ) )
  482. {
  483. LEAVE_DDRAW();
  484. return DDERR_SURFACELOST;
  485. }
  486. }
  487. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  488. {
  489. DPF_ERR( "Exception encountered validating parameters" );
  490. LEAVE_DDRAW();
  491. return DDERR_INVALIDPARAMS;
  492. }
  493. LEAVE_DDRAW();
  494. return DD_OK;
  495. } /* DD_Surface_Flush */
  496. #endif
  497. #undef DPF_MODNAME
  498. #define DPF_MODNAME "Flip"
  499. /*
  500. * FlipMipMapChain
  501. *
  502. * Flip a chain of mip-map surfaces.
  503. */
  504. static HRESULT FlipMipMapChain( LPDIRECTDRAWSURFACE lpDDSurface,
  505. LPDIRECTDRAWSURFACE lpDDSurfaceDest,
  506. DWORD dwFlags )
  507. {
  508. LPDDRAWI_DDRAWSURFACE_INT this_int;
  509. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  510. LPDDRAWI_DDRAWSURFACE_GBL this;
  511. LPDDRAWI_DDRAWSURFACE_INT next_int;
  512. LPDDRAWI_DDRAWSURFACE_LCL next_lcl;
  513. LPDDRAWI_DDRAWSURFACE_GBL next;
  514. LPDDRAWI_DDRAWSURFACE_INT attached_int;
  515. FLATPTR vidmem;
  516. LPVMEMHEAP vidmemheap;
  517. ULONG_PTR reserved;
  518. DWORD gdi_flag;
  519. ULONG_PTR handle;
  520. BOOL toplevel;
  521. int destindex;
  522. int thisindex;
  523. BOOL destfound;
  524. #ifdef USE_ALIAS
  525. FLATPTR aliasvidmem;
  526. FLATPTR aliasofvidmem;
  527. #endif /* USE_ALIAS */
  528. FLATPTR physicalvidmem;
  529. ULONG_PTR driverreserved;
  530. TRY
  531. {
  532. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  533. /*
  534. * We validate each level of the mip-map before we do any
  535. * flipping. This is in an effort to prevent half flipped
  536. * surfaces.
  537. */
  538. toplevel = TRUE;
  539. do
  540. {
  541. /*
  542. * At this point this_int points to the front buffer
  543. * of a flippable chain of surface for this level of
  544. * the mip-map.
  545. */
  546. /*
  547. * Invalid source surface?
  548. */
  549. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  550. {
  551. DPF_ERR( "Invalid front buffer for flip" );
  552. return DDERR_INVALIDOBJECT;
  553. }
  554. this_lcl = this_int->lpLcl;
  555. this = this_lcl->lpGbl;
  556. /*
  557. * Source surface lost?
  558. */
  559. if( SURFACE_LOST( this_lcl ) )
  560. {
  561. DPF_ERR( "Can't flip - front buffer is lost" );
  562. return DDERR_SURFACELOST;
  563. }
  564. /*
  565. * Source surface flippable?
  566. */
  567. if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER) )
  568. {
  569. DPF_ERR( "Can't flip - first surface is not a front buffer" );
  570. return DDERR_NOTFLIPPABLE;
  571. }
  572. if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_FLIP) )
  573. {
  574. DPF_ERR( "Surface is not flippable" );
  575. return DDERR_NOTFLIPPABLE;
  576. }
  577. /*
  578. * Source surface locked?
  579. */
  580. if( this->dwUsageCount > 0 )
  581. {
  582. DPF_ERR( "Can't flip - surface is locked" );
  583. return DDERR_SURFACEBUSY;
  584. }
  585. /*
  586. * Validate destination surfaces of flip.
  587. */
  588. next_int = FindAttachedFlip( this_int );
  589. if( next_int == NULL )
  590. {
  591. DPF_ERR( "Can't flip - no surface to flip to" );
  592. return DDERR_NOTFLIPPABLE;
  593. }
  594. /*
  595. * If this is the top level of the mip-map and a destination
  596. * surface has been provided then we need to find out which
  597. * buffer (by index) the supplied destination is so that we
  598. * can flip to the matching buffers in the lower-level maps.
  599. */
  600. if( NULL != lpDDSurfaceDest )
  601. {
  602. thisindex = 0;
  603. destfound = FALSE;
  604. if( toplevel )
  605. destindex = -1;
  606. }
  607. do
  608. {
  609. /*
  610. * If a destination surface has been supplied then is this
  611. * it?
  612. */
  613. if( NULL != lpDDSurfaceDest )
  614. {
  615. if( toplevel )
  616. {
  617. /*
  618. * As we may have multiple interfaces pointing to the same
  619. * object we need to compare objects not interface pointers
  620. */
  621. if( next_int->lpLcl == ( (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurfaceDest )->lpLcl )
  622. {
  623. destindex = thisindex;
  624. destfound = TRUE;
  625. }
  626. }
  627. else
  628. {
  629. if( thisindex == destindex )
  630. {
  631. destfound = TRUE;
  632. }
  633. }
  634. }
  635. /*
  636. * Invalid destination surface?
  637. */
  638. if( !VALID_DIRECTDRAWSURFACE_PTR( next_int ) )
  639. {
  640. DPF_ERR( "Can't flip - invalid back buffer" );
  641. return DDERR_INVALIDOBJECT;
  642. }
  643. next_lcl = next_int->lpLcl;
  644. next = next_lcl->lpGbl;
  645. /*
  646. * Destination surface lost?
  647. */
  648. if( SURFACE_LOST( next_lcl ) )
  649. {
  650. DPF_ERR( "Can't flip - back buffer is lost" );
  651. return DDERR_SURFACELOST;
  652. }
  653. /*
  654. * Destination surface locked?
  655. */
  656. if( next->dwUsageCount > 0 )
  657. {
  658. DPF_ERR( "Can't flip - back buffer is locked" );
  659. return DDERR_SURFACEBUSY;
  660. }
  661. /*
  662. * Ensure that both source and destination surfaces reside
  663. * in the same kind of memory.
  664. */
  665. if( ( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) &&
  666. ( next_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY ) ) ||
  667. ( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY ) &&
  668. ( next_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) ) )
  669. {
  670. DPF_ERR( "Can't flip between system/video memory surfaces" );
  671. return DDERR_INVALIDPARAMS;
  672. }
  673. /*
  674. * Next destination surface.
  675. */
  676. next_int = FindAttachedFlip( next_int );
  677. thisindex++;
  678. } while( next_int->lpLcl != this_int->lpLcl );
  679. /*
  680. * If a destination was supplied did we find it?
  681. */
  682. if( ( NULL != lpDDSurfaceDest ) && !destfound )
  683. {
  684. /*
  685. * Could not find the destination.
  686. */
  687. DPF_ERR( "Can't flip - destination surface not found in flippable chain" );
  688. return DDERR_NOTFLIPPABLE;
  689. }
  690. DDASSERT( destindex != -1 );
  691. /*
  692. * Next mip-map level.
  693. */
  694. this_int = FindAttachedMipMap( this_int );
  695. toplevel = FALSE;
  696. } while( this_int != NULL );
  697. }
  698. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  699. {
  700. DPF_ERR( "Exception encountered validating parameters" );
  701. return DDERR_INVALIDPARAMS;
  702. }
  703. /*
  704. * Now actually flip each level of the mip-map.
  705. */
  706. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  707. do
  708. {
  709. /*
  710. * Process one level of the mip-map.
  711. */
  712. this_lcl = this_int->lpLcl;
  713. this = this_lcl->lpGbl;
  714. /*
  715. * Find the first destination surface of the flip.
  716. */
  717. next_int = FindAttachedFlip( this_int );
  718. if( NULL != lpDDSurfaceDest )
  719. {
  720. /*
  721. * If an override destination has been provided find the
  722. * appropriate back destination surface.
  723. */
  724. for( thisindex = 0; thisindex < destindex; thisindex++ )
  725. next_int = FindAttachedFlip( next_int );
  726. }
  727. DDASSERT( NULL != next_int );
  728. next_lcl = next_int->lpLcl;
  729. /*
  730. * save the old values
  731. */
  732. vidmem = next_lcl->lpGbl->fpVidMem;
  733. #ifdef USE_ALIAS
  734. aliasvidmem = GBLMORE(next_lcl->lpGbl)->fpAliasedVidMem;
  735. aliasofvidmem = GBLMORE(next_lcl->lpGbl)->fpAliasOfVidMem;
  736. #endif /* USE_ALIAS */
  737. physicalvidmem = GBLMORE(next_lcl->lpGbl)->fpPhysicalVidMem;
  738. driverreserved = GBLMORE(next_lcl->lpGbl)->dwDriverReserved;
  739. vidmemheap = next_lcl->lpGbl->lpVidMemHeap;
  740. reserved = next_lcl->lpGbl->dwReserved1;
  741. gdi_flag = next_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
  742. handle = next_lcl->hDDSurface;
  743. /*
  744. * If a destination override was provided then find that destination surface
  745. * and flip to it explicitly.
  746. */
  747. if( NULL != lpDDSurfaceDest )
  748. {
  749. next_lcl->lpGbl->lpVidMemHeap = this->lpVidMemHeap;
  750. next_lcl->lpGbl->fpVidMem = this->fpVidMem;
  751. #ifdef USE_ALIAS
  752. GBLMORE(next_lcl->lpGbl)->fpAliasedVidMem = GBLMORE(this)->fpAliasedVidMem;
  753. GBLMORE(next_lcl->lpGbl)->fpAliasOfVidMem = GBLMORE(this)->fpAliasOfVidMem;
  754. #endif /* USE_ALIAS */
  755. GBLMORE(next_lcl->lpGbl)->fpPhysicalVidMem = GBLMORE(this)->fpPhysicalVidMem;
  756. GBLMORE(next_lcl->lpGbl)->dwDriverReserved = GBLMORE(this)->dwDriverReserved;
  757. next_lcl->lpGbl->dwReserved1 = this->dwReserved1;
  758. next_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
  759. next_lcl->lpGbl->dwGlobalFlags |= this->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
  760. next_lcl->hDDSurface = this_lcl->hDDSurface;
  761. }
  762. else
  763. {
  764. do
  765. {
  766. /*
  767. * Remaining buffers in the chain (including copying the source surface's
  768. * data.
  769. */
  770. attached_int = FindAttachedFlip( next_int );
  771. next_lcl->lpGbl->fpVidMem = attached_int->lpLcl->lpGbl->fpVidMem;
  772. #ifdef USE_ALIAS
  773. GBLMORE(next_lcl->lpGbl)->fpAliasedVidMem = GBLMORE(attached_int->lpLcl->lpGbl)->fpAliasedVidMem;
  774. GBLMORE(next_lcl->lpGbl)->fpAliasOfVidMem = GBLMORE(attached_int->lpLcl->lpGbl)->fpAliasOfVidMem;
  775. #endif /* USE_ALIAS */
  776. GBLMORE(next_lcl->lpGbl)->fpPhysicalVidMem = GBLMORE(attached_int->lpLcl->lpGbl)->fpPhysicalVidMem;
  777. GBLMORE(next_lcl->lpGbl)->dwDriverReserved = GBLMORE(attached_int->lpLcl->lpGbl)->dwDriverReserved;
  778. next_lcl->lpGbl->lpVidMemHeap = attached_int->lpLcl->lpGbl->lpVidMemHeap;
  779. next_lcl->lpGbl->dwReserved1 = attached_int->lpLcl->lpGbl->dwReserved1;
  780. next_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
  781. next_lcl->lpGbl->dwGlobalFlags |= attached_int->lpLcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
  782. next_lcl->hDDSurface = attached_int->lpLcl->hDDSurface;
  783. next_int = attached_int;
  784. next_lcl = next_int->lpLcl;
  785. /*
  786. * NOTE: We must compare objects not interfaces (there may be many
  787. * different interfaces pointing to the same objects) to prevent a
  788. * infinite loop.
  789. */
  790. } while( next_int->lpLcl != this_int->lpLcl );
  791. }
  792. this->fpVidMem = vidmem;
  793. #ifdef USE_ALIAS
  794. GBLMORE(this)->fpAliasedVidMem = aliasvidmem;
  795. GBLMORE(this)->fpAliasOfVidMem = aliasofvidmem;
  796. #endif /* USE_ALIAS */
  797. GBLMORE(this)->fpPhysicalVidMem = physicalvidmem;
  798. GBLMORE(this)->dwDriverReserved = driverreserved;
  799. this->lpVidMemHeap = vidmemheap;
  800. this->dwReserved1 = reserved;
  801. this->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
  802. this->dwGlobalFlags |= gdi_flag;
  803. this_lcl->hDDSurface = handle;
  804. /*
  805. * Next level of the mip-map.
  806. */
  807. this_int = FindAttachedMipMap( this_int );
  808. } while( this_int != NULL );
  809. return DD_OK;
  810. } /* FlipMipMapChain */
  811. DWORD dwLastFrameRate = 0;
  812. /*
  813. * updateFrameRate
  814. */
  815. static void updateFrameRate( void )
  816. {
  817. static DWORD dwFlipCnt;
  818. static DWORD dwFlipTime=0xffffffff;
  819. /*
  820. * work out the frame rate if required...
  821. */
  822. if( dwFlipTime == 0xffffffff )
  823. {
  824. dwFlipTime = GetTickCount();
  825. }
  826. dwFlipCnt++;
  827. if( dwFlipCnt >= 120 )
  828. {
  829. DWORD time2;
  830. DWORD fps;
  831. char buff[256];
  832. time2 = GetTickCount() - dwFlipTime;
  833. fps = (dwFlipCnt*10000)/time2;
  834. wsprintf( buff, "FPS = %ld.%01ld\r\n", fps/10, fps % 10 );
  835. dwLastFrameRate = fps;
  836. /*
  837. * OINK32 whines about OutputDebugString, so hide it...
  838. */
  839. {
  840. HANDLE h;
  841. h = LoadLibrary( "KERNEL32.DLL" );
  842. if( h != NULL )
  843. {
  844. VOID (WINAPI *lpOutputDebugStringA)(LPCSTR) = (LPVOID)
  845. GetProcAddress( h, "OutputDebugStringA" );
  846. if( lpOutputDebugStringA != NULL )
  847. {
  848. lpOutputDebugStringA( buff );
  849. }
  850. FreeLibrary( h );
  851. }
  852. }
  853. dwFlipTime = GetTickCount();
  854. dwFlipCnt = 0;
  855. }
  856. } /* updateFrameRate */
  857. /*
  858. * DD_Surface_Flip
  859. *
  860. * Page flip to the next surface. Only valid for surfaces which are
  861. * flippable.
  862. */
  863. #undef DPF_MODNAME
  864. #define DPF_MODNAME "Flip"
  865. HRESULT DDAPI DD_Surface_Flip(
  866. LPDIRECTDRAWSURFACE lpDDSurface,
  867. LPDIRECTDRAWSURFACE lpDDSurfaceDest,
  868. DWORD dwFlags )
  869. {
  870. LPDDRAWI_DDRAWSURFACE_INT this_int;
  871. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  872. LPDDRAWI_DDRAWSURFACE_INT this_dest_int;
  873. LPDDRAWI_DDRAWSURFACE_LCL this_dest_lcl;
  874. LPDDRAWI_DDRAWSURFACE_INT next_int;
  875. LPDDRAWI_DDRAWSURFACE_LCL next_lcl;
  876. LPDDRAWI_DDRAWSURFACE_INT next_save_int;
  877. LPDDRAWI_DDRAWSURFACE_INT attached_int;
  878. LPDDRAWI_DDRAWSURFACE_GBL this;
  879. LPDDRAWI_DDRAWSURFACE_GBL this_dest;
  880. DWORD rc;
  881. BOOL found_dest;
  882. DDHAL_FLIPTOGDISURFACEDATA ftgsd;
  883. LPDDHAL_FLIPTOGDISURFACE ftgshalfn;
  884. LPDDHAL_FLIPTOGDISURFACE ftgsfn;
  885. DDHAL_FLIPDATA fd;
  886. LPDDHALSURFCB_FLIP fhalfn;
  887. LPDDHALSURFCB_FLIP ffn;
  888. BOOL emulation;
  889. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  890. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  891. DWORD caps;
  892. DWORD caps2;
  893. DWORD dwNumSkipped;
  894. DWORD dwCnt;
  895. LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
  896. BOOL bStereo;
  897. ENTER_BOTH();
  898. DPF(2,A,"ENTERAPI: DD_Surface_Flip");
  899. /* DPF_ENTERAPI(lpDDSurface); */
  900. // 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  901. DPF(3,A," Dest surface: 0x%p, flags: 0x%08x", lpDDSurfaceDest, dwFlags);
  902. TRY
  903. {
  904. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  905. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  906. {
  907. LEAVE_BOTH();
  908. return DDERR_INVALIDOBJECT;
  909. }
  910. this_lcl = this_int->lpLcl;
  911. this = this_lcl->lpGbl;
  912. this_dest_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurfaceDest;
  913. if( this_dest_int != NULL )
  914. {
  915. if( !VALID_DIRECTDRAWSURFACE_PTR( this_dest_int ) )
  916. {
  917. LEAVE_BOTH();
  918. return DDERR_INVALIDOBJECT;
  919. }
  920. this_dest_lcl = this_dest_int->lpLcl;
  921. this_dest = this_dest_lcl->lpGbl;
  922. }
  923. else
  924. {
  925. this_dest_lcl = NULL;
  926. this_dest = NULL;
  927. }
  928. if( dwFlags & ~DDFLIP_VALID )
  929. {
  930. DPF_ERR( "Invalid flags") ;
  931. LEAVE_BOTH();
  932. return DDERR_INVALIDPARAMS;
  933. }
  934. if (!LOWERTHANSURFACE7(this_int))
  935. {
  936. if (dwFlags & DDFLIP_DONOTWAIT)
  937. {
  938. dwFlags &= ~DDFLIP_WAIT;
  939. }
  940. else
  941. {
  942. dwFlags |= DDFLIP_WAIT;
  943. }
  944. }
  945. if( ( dwFlags & ( DDFLIP_EVEN | DDFLIP_ODD ) ) &&
  946. !( this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY ) )
  947. {
  948. DPF_ERR( "Invalid flags") ;
  949. LEAVE_BOTH();
  950. return DDERR_INVALIDPARAMS;
  951. }
  952. if ( (dwFlags & DDFLIP_NOVSYNC) && (dwFlags & DDFLIP_INTERVALMASK) )
  953. {
  954. DPF_ERR( "Flip: DDFLIP_NOVSYNC and DDFLIP_INTERVALn are mutually exclusive") ;
  955. LEAVE_BOTH();
  956. return DDERR_INVALIDPARAMS;
  957. }
  958. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  959. pdrv = pdrv_lcl->lpGbl;
  960. #ifdef WIN95
  961. if( !( pdrv_lcl->dwAppHackFlags & DDRAW_APPCOMPAT_SCREENSAVER ) ||
  962. !( pdrv_lcl->dwLocalFlags & DDRAWILCL_POWEREDDOWN ) )
  963. {
  964. #endif
  965. if( SURFACE_LOST( this_lcl ) )
  966. {
  967. LEAVE_BOTH();
  968. return DDERR_SURFACELOST;
  969. }
  970. if( this_dest != NULL )
  971. {
  972. if( SURFACE_LOST( this_dest_lcl ) )
  973. {
  974. LEAVE_BOTH();
  975. return DDERR_SURFACELOST;
  976. }
  977. }
  978. #ifdef WIN95
  979. }
  980. #endif
  981. /*
  982. * device busy?
  983. */
  984. #ifdef USE_ALIAS
  985. if( pdrv->dwBusyDueToAliasedLock > 0 )
  986. {
  987. /*
  988. * Aliased locks (the ones that don't take the Win16 lock) don't
  989. * set the busy bit either (it can't or USER get's very confused).
  990. * However, we must prevent blits happening via DirectDraw as
  991. * otherwise we get into the old host talking to VRAM while
  992. * blitter does at the same time. Bad. So fail if there is an
  993. * outstanding aliased lock just as if the BUST bit had been
  994. * set.
  995. */
  996. DPF_ERR( "Graphics adapter is busy (due to a DirectDraw lock)" );
  997. LEAVE_BOTH();
  998. return DDERR_SURFACEBUSY;
  999. }
  1000. #endif /* USE_ALIAS */
  1001. if( *(pdrv->lpwPDeviceFlags) & BUSY )
  1002. {
  1003. DPF( 0, "BUSY - Flip" );
  1004. LEAVE_BOTH()
  1005. return DDERR_SURFACEBUSY;
  1006. }
  1007. /*
  1008. * make sure that it's OK to flip this surface
  1009. */
  1010. // DX7Stereo
  1011. if(dwFlags & DDFLIP_STEREO)
  1012. {
  1013. if (!(this_lcl->dwFlags & DDRAWISURF_STEREOSURFACELEFT))
  1014. {
  1015. DPF_ERR( "Invalid DDFLIP_STEREO flag on non stereo flipping chain") ;
  1016. LEAVE_BOTH();
  1017. return DDERR_INVALIDPARAMS;
  1018. }
  1019. }
  1020. if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER) )
  1021. {
  1022. DPF_ERR("Can't flip because surface is not a front buffer");
  1023. LEAVE_BOTH();
  1024. return DDERR_NOTFLIPPABLE; // ACKACK: real error??
  1025. }
  1026. if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_FLIP) )
  1027. {
  1028. DPF_ERR("Can't flip because surface is not a DDSCAPS_FLIP surface");
  1029. LEAVE_BOTH();
  1030. return DDERR_NOTFLIPPABLE; // ACKACK: real error??
  1031. }
  1032. if( this->dwUsageCount > 0 )
  1033. {
  1034. DPF_ERR( "Can't flip because surface is locked" );
  1035. LEAVE_BOTH();
  1036. return DDERR_SURFACEBUSY;
  1037. }
  1038. if( (this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) &&
  1039. (pdrv->lpExclusiveOwner != pdrv_lcl ) )
  1040. {
  1041. DPF_ERR( "Can't flip without exclusive access." );
  1042. LEAVE_BOTH();
  1043. return DDERR_NOEXCLUSIVEMODE;
  1044. }
  1045. }
  1046. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1047. {
  1048. DPF_ERR( "Exception encountered validating parameters" );
  1049. LEAVE_BOTH();
  1050. return DDERR_INVALIDPARAMS;
  1051. }
  1052. /*
  1053. * Mip-map chain? In which case take special action.
  1054. */
  1055. if( (this_lcl->ddsCaps.dwCaps & DDSCAPS_MIPMAP) &&
  1056. (0==(this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)) )
  1057. {
  1058. rc = FlipMipMapChain( lpDDSurface, lpDDSurfaceDest, dwFlags );
  1059. LEAVE_BOTH();
  1060. return rc;
  1061. }
  1062. /*
  1063. * If this is the primary and the driver had previously flipped
  1064. * to display the GDI surface then we are now flipping away from
  1065. * the GDI surface so we need to let the driver know.
  1066. */
  1067. if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) &&
  1068. ( pdrv->dwFlags & DDRAWI_FLIPPEDTOGDI ) )
  1069. {
  1070. /*
  1071. * Notify the driver that we are about to flip away from the
  1072. * GDI surface.
  1073. *
  1074. * NOTE: This is a HAL only call - it means nothing to
  1075. * the HEL.
  1076. *
  1077. * NOTE: If the driver handles this call then we do not
  1078. * attempt to do the actual flip. This is to support cards
  1079. * which do not have GDI surfaces. If the driver does not
  1080. * handle the call we will continue on and do the flip.
  1081. */
  1082. ftgsfn = pdrv_lcl->lpDDCB->HALDD.FlipToGDISurface;
  1083. ftgshalfn = pdrv_lcl->lpDDCB->cbDDCallbacks.FlipToGDISurface;
  1084. if( NULL != ftgshalfn )
  1085. {
  1086. ftgsd.FlipToGDISurface = ftgshalfn;
  1087. ftgsd.lpDD = pdrv;
  1088. ftgsd.dwToGDI = FALSE;
  1089. ftgsd.dwReserved = 0UL;
  1090. DOHALCALL( FlipToGDISurface, ftgsfn, ftgsd, rc, FALSE );
  1091. if( DDHAL_DRIVER_HANDLED == rc )
  1092. {
  1093. if( !FAILED( ftgsd.ddRVal ) )
  1094. {
  1095. /*
  1096. * Driver is no longer flipped to the GDI surface.
  1097. */
  1098. pdrv->dwFlags &= ~DDRAWI_FLIPPEDTOGDI;
  1099. DPF( 4, "Driver handled the flip away from the GDI surface" );
  1100. LEAVE_BOTH();
  1101. return ftgsd.ddRVal;
  1102. }
  1103. else
  1104. {
  1105. DPF_ERR( "Driver failed the flip away from the GDI surface" );
  1106. LEAVE_BOTH();
  1107. return ftgsd.ddRVal;
  1108. }
  1109. }
  1110. }
  1111. }
  1112. /*
  1113. * make sure no surfaces are in use
  1114. */
  1115. found_dest = FALSE;
  1116. if( ( lpDDSurface == lpDDSurfaceDest ) &&
  1117. ( dwFlags & (DDFLIP_EVEN | DDFLIP_ODD) ) )
  1118. {
  1119. next_save_int = next_int = this_int;
  1120. dwCnt = dwNumSkipped = 0;
  1121. }
  1122. else
  1123. {
  1124. next_save_int = next_int = FindAttachedFlip( this_int );
  1125. dwCnt = dwNumSkipped = 1;
  1126. }
  1127. if( next_int == NULL )
  1128. {
  1129. DPF_ERR("Can't flip: No attached flippable surface");
  1130. LEAVE_BOTH();
  1131. return DDERR_NOTFLIPPABLE; // ACKACK: real error?
  1132. }
  1133. do
  1134. {
  1135. if( SURFACE_LOST( next_int->lpLcl ) )
  1136. {
  1137. DPF_ERR( "Can't flip - back buffer is lost" );
  1138. LEAVE_BOTH();
  1139. return DDERR_SURFACELOST;
  1140. }
  1141. if( next_int->lpLcl->lpGbl->dwUsageCount != 0 )
  1142. {
  1143. /*
  1144. * Previously we didn't allow Flips to suceed if any of the surfaces
  1145. * are lost, but DShow really wants to be able to do this so now we'll
  1146. * allow it as long as we aren't going to rotate the memory pointers, etc.
  1147. * for the locked surface.
  1148. */
  1149. if( ( this_dest_lcl == NULL ) ||
  1150. ( this_dest_lcl == next_int->lpLcl ) ||
  1151. ( this_lcl == next_int->lpLcl ) )
  1152. {
  1153. LEAVE_BOTH();
  1154. return DDERR_SURFACEBUSY;
  1155. }
  1156. }
  1157. /*
  1158. * Do not allow flipping if any of the surfaces are used in kernel
  1159. * mode because we don't want the pointers to rotate.
  1160. */
  1161. lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( next_int->lpLcl->lpGbl );
  1162. if( lpSurfGblMore->hKernelSurface != 0 )
  1163. {
  1164. DPF_ERR( "Can't flip - kernel mode is using surface" );
  1165. LEAVE_BOTH();
  1166. return DDERR_SURFACEBUSY;
  1167. }
  1168. /*
  1169. * NOTE: Do NOT compare interface pointers here as we may
  1170. * well have multiple interfaces to the same surface object (i.e.,
  1171. * V1, V2, V3 etc.). Compare against the LOCAL object. This is the
  1172. * real object being handled.
  1173. */
  1174. if( ( NULL != this_dest_int ) && ( this_dest_int->lpLcl == next_int->lpLcl ) )
  1175. {
  1176. dwNumSkipped = dwCnt;
  1177. found_dest = TRUE;
  1178. }
  1179. dwCnt++;
  1180. next_int = FindAttachedFlip( next_int );
  1181. } while( next_int->lpLcl != this_int->lpLcl );
  1182. /*
  1183. * see if we can use the specified destination
  1184. */
  1185. if( this_dest_int != NULL )
  1186. {
  1187. if( !found_dest )
  1188. {
  1189. DPF_ERR( "Destination not part of flipping chain!" );
  1190. LEAVE_BOTH();
  1191. return DDERR_NOTFLIPPABLE; // ACKACK: real error?
  1192. }
  1193. next_save_int = this_dest_int;
  1194. }
  1195. /*
  1196. * found the linked surface we want to flip to
  1197. */
  1198. next_int = next_save_int;
  1199. /*
  1200. * don't allow two destinations to be different (in case of a mixed chain)
  1201. */
  1202. next_lcl = next_int->lpLcl;
  1203. if( ((next_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  1204. (this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) ||
  1205. ((next_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
  1206. (this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)) )
  1207. {
  1208. DPF_ERR( "Can't flip between video/system memory surfaces" );
  1209. LEAVE_BOTH();
  1210. return DDERR_INVALIDPARAMS;
  1211. }
  1212. // DPF(9," flip (%d) Source Kernel handle is %08x, dest is %08x",__LINE__,this_lcl->hDDSurface,next_lcl->hDDSurface);
  1213. // DPF(9," flip source vidmem is %08x, dest is %08x",this->fpVidMem,next_lcl->lpGbl->fpVidMem);
  1214. /*
  1215. * is this an emulation surface or driver surface?
  1216. */
  1217. if( (this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
  1218. {
  1219. ffn = pdrv_lcl->lpDDCB->HELDDSurface.Flip;
  1220. fhalfn = ffn;
  1221. emulation = TRUE;
  1222. caps = pdrv->ddHELCaps.dwCaps;
  1223. caps2 = pdrv->ddHELCaps.dwCaps2;
  1224. }
  1225. else
  1226. {
  1227. ffn = pdrv_lcl->lpDDCB->HALDDSurface.Flip;
  1228. fhalfn = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.Flip;
  1229. emulation = FALSE;
  1230. caps = pdrv->ddCaps.dwCaps;
  1231. caps2 = pdrv->ddCaps.dwCaps2;
  1232. }
  1233. /*
  1234. * If the surface is fed by a video port, also flip the video port
  1235. */
  1236. if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOPORT) && dwNumSkipped )
  1237. {
  1238. rc = FlipVideoPortSurface( this_int, dwNumSkipped );
  1239. if( rc != DD_OK )
  1240. {
  1241. LEAVE_BOTH();
  1242. return DDERR_INVALIDPARAMS;
  1243. }
  1244. }
  1245. #ifdef WINNT
  1246. /*
  1247. * If ~ 50 seconds have passed (assuming a 10Hz flip rate)
  1248. * and this is a primary surface, then make a magic call to
  1249. * disable screen savers.
  1250. * This isn't needed on 9x since we make a SPI call on that OS
  1251. * to disable screen savers.
  1252. * We don't do this if the app is itself a screen-saver, since
  1253. * that would also disable the power-down.
  1254. */
  1255. if( !( pdrv_lcl->dwAppHackFlags & DDRAW_APPCOMPAT_SCREENSAVER ))
  1256. {
  1257. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE )
  1258. {
  1259. static DWORD dwMagicTime = 0;
  1260. dwMagicTime++;
  1261. if (dwMagicTime > (50*10) )
  1262. {
  1263. DWORD dw=60*15;
  1264. dwMagicTime = 0;
  1265. SystemParametersInfo(SPI_GETSCREENSAVETIMEOUT,0,&dw,0);
  1266. SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT,dw,0,0);
  1267. }
  1268. }
  1269. }
  1270. #endif
  1271. /*
  1272. * Driver should be told its cache is invalid if the surface was flipped
  1273. */
  1274. BUMP_SURFACE_STAMP(this);
  1275. BUMP_SURFACE_STAMP(next_lcl->lpGbl);
  1276. /*
  1277. * ask the driver to flip to the new surface if we are flipping
  1278. * a primary surface (or if we are flipping an overlay surface and
  1279. * the driver supports overlays.)
  1280. */
  1281. bStereo = (BOOL) (this_lcl->dwFlags & DDRAWISURF_STEREOSURFACELEFT);
  1282. if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) ||
  1283. ( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY ) &&
  1284. ( caps & DDCAPS_OVERLAY ) &&
  1285. ( this_lcl->ddsCaps.dwCaps & DDSCAPS_VISIBLE ) ) )
  1286. {
  1287. if( fhalfn != NULL )
  1288. {
  1289. fd.Flip = fhalfn;
  1290. fd.lpDD = pdrv;
  1291. fd.dwFlags = (dwFlags & ~DDFLIP_WAIT);
  1292. fd.lpSurfCurr = this_lcl;
  1293. fd.lpSurfTarg = next_lcl;
  1294. // DX7Stereo
  1295. fd.lpSurfCurrLeft = NULL;
  1296. fd.lpSurfTargLeft = NULL;
  1297. if (bStereo &&
  1298. fd.dwFlags & DDFLIP_STEREO )
  1299. {
  1300. LPDDRAWI_DDRAWSURFACE_INT temp_this_int;
  1301. LPDDRAWI_DDRAWSURFACE_INT temp_next_int;
  1302. temp_this_int = FindAttachedSurfaceLeft(this_int);
  1303. temp_next_int = FindAttachedSurfaceLeft(next_int);
  1304. // oops, error
  1305. if (temp_this_int!=NULL && temp_next_int!=NULL)
  1306. {
  1307. fd.lpSurfCurrLeft = temp_this_int->lpLcl;
  1308. fd.lpSurfTargLeft = temp_next_int->lpLcl;
  1309. }
  1310. if (fd.lpSurfCurrLeft==NULL || fd.lpSurfTargLeft==NULL)
  1311. {
  1312. fd.lpSurfCurrLeft = NULL;
  1313. fd.lpSurfTargLeft = NULL;
  1314. fd.dwFlags &= ~DDFLIP_STEREO;
  1315. }
  1316. }
  1317. if (DDRAW_REGFLAGS_FLIPNONVSYNC & dwRegFlags)
  1318. {
  1319. fd.dwFlags &= ~DDFLIP_INTERVALMASK;
  1320. fd.dwFlags |= DDFLIP_NOVSYNC;
  1321. }
  1322. if (caps2 & DDCAPS2_FLIPINTERVAL)
  1323. {
  1324. //if the user didn't specify a flip interval, give the driver 'one'
  1325. //Also, make the interval consistent with FLIPNOVSYNC: if FLIPNOVSYNC is set,
  1326. //then we should keep the interval set to 0.
  1327. if ( ((fd.dwFlags & DDFLIP_INTERVALMASK) == 0) && ((dwFlags & DDFLIP_NOVSYNC)==0) )
  1328. {
  1329. fd.dwFlags |= DDFLIP_INTERVAL1;
  1330. }
  1331. }
  1332. else
  1333. {
  1334. //don't let old drivers see the flip intervals
  1335. fd.dwFlags &= ~DDFLIP_INTERVALMASK;
  1336. }
  1337. //don't let old drivers see novsync
  1338. if ( (caps2 & DDCAPS2_FLIPNOVSYNC) == 0 )
  1339. {
  1340. fd.dwFlags &= ~DDFLIP_NOVSYNC;
  1341. }
  1342. try_again:
  1343. DOHALCALL_NOWIN16( Flip, ffn, fd, rc, emulation );
  1344. if( rc == DDHAL_DRIVER_HANDLED )
  1345. {
  1346. if( fd.ddRVal != DD_OK )
  1347. {
  1348. if( (dwFlags & DDFLIP_WAIT) && fd.ddRVal == DDERR_WASSTILLDRAWING )
  1349. {
  1350. DPF(4,"Waiting.....");
  1351. goto try_again;
  1352. }
  1353. LEAVE_BOTH();
  1354. return fd.ddRVal;
  1355. }
  1356. /*
  1357. * emulation, does not need the pointers rotated we are done
  1358. *
  1359. * NOTE we should do this with a special return code or
  1360. * even a rester cap, but for now this is as good as any.
  1361. */
  1362. if( emulation )
  1363. {
  1364. LEAVE_WIN16LOCK();
  1365. if( dwRegFlags & DDRAW_REGFLAGS_SHOWFRAMERATE )
  1366. {
  1367. updateFrameRate();
  1368. }
  1369. LEAVE_DDRAW();
  1370. return DD_OK;
  1371. }
  1372. }
  1373. }
  1374. else
  1375. {
  1376. LEAVE_BOTH();
  1377. return DDERR_NOFLIPHW;
  1378. }
  1379. }
  1380. /*
  1381. * save the old values
  1382. */
  1383. if( dwNumSkipped )
  1384. {
  1385. #ifdef USE_ALIAS
  1386. FLATPTR aliasvidmem;
  1387. FLATPTR aliasofvidmem;
  1388. #endif /* USE_ALIAS */
  1389. FLATPTR vidmem;
  1390. LPVMEMHEAP vidmemheap;
  1391. FLATPTR physicalvidmem;
  1392. ULONG_PTR driverreserved;
  1393. ULONG_PTR reserved;
  1394. DWORD gdi_flag;
  1395. ULONG_PTR handle;
  1396. // same stack for left surface if we rotate stereo buffers
  1397. #ifdef USE_ALIAS
  1398. FLATPTR leftaliasvidmem;
  1399. FLATPTR leftaliasofvidmem;
  1400. #endif /* USE_ALIAS */
  1401. FLATPTR leftvidmem;
  1402. LPVMEMHEAP leftvidmemheap;
  1403. FLATPTR leftphysicalvidmem;
  1404. ULONG_PTR leftdriverreserved;
  1405. DWORD leftgdi_flag;
  1406. ULONG_PTR leftreserved;
  1407. ULONG_PTR lefthandle;
  1408. DWORD dwSurfaceHandle;
  1409. DWORD dwLeftSurfaceHandle;
  1410. LPDDRAWI_DDRAWSURFACE_INT next_left_int;
  1411. LPDDRAWI_DDRAWSURFACE_LCL next_left_lcl;
  1412. DPF(4,"Flip:rotating pointers etc");
  1413. vidmem = next_lcl->lpGbl->fpVidMem;
  1414. #ifdef USE_ALIAS
  1415. aliasvidmem = GBLMORE(next_lcl->lpGbl)->fpAliasedVidMem;
  1416. aliasofvidmem = GBLMORE(next_lcl->lpGbl)->fpAliasOfVidMem;
  1417. #endif /* USE_ALIAS */
  1418. physicalvidmem = GBLMORE(next_lcl->lpGbl)->fpPhysicalVidMem;
  1419. driverreserved = GBLMORE(next_lcl->lpGbl)->dwDriverReserved;
  1420. vidmemheap = next_lcl->lpGbl->lpVidMemHeap;
  1421. reserved = next_lcl->lpGbl->dwReserved1;
  1422. gdi_flag = next_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
  1423. handle = next_lcl->hDDSurface;
  1424. dwSurfaceHandle = next_lcl->lpSurfMore->dwSurfaceHandle;
  1425. // DX7Stereo: save also left buffers
  1426. if (bStereo)
  1427. {
  1428. DPF(4,"Flip:rotating also stereo pointers etc");
  1429. next_left_int = FindAttachedSurfaceLeft(next_int);
  1430. if (next_left_int!=NULL)
  1431. {
  1432. next_left_lcl = next_left_int->lpLcl;
  1433. leftvidmem = next_left_lcl->lpGbl->fpVidMem;
  1434. #ifdef USE_ALIAS
  1435. leftaliasvidmem = GBLMORE(next_left_lcl->lpGbl)->fpAliasedVidMem;
  1436. leftaliasofvidmem = GBLMORE(next_left_lcl->lpGbl)->fpAliasOfVidMem;
  1437. #endif /* USE_ALIAS */
  1438. leftphysicalvidmem = GBLMORE(next_left_lcl->lpGbl)->fpPhysicalVidMem;
  1439. leftdriverreserved = GBLMORE(next_left_lcl->lpGbl)->dwDriverReserved;
  1440. leftvidmemheap = next_left_lcl->lpGbl->lpVidMemHeap;
  1441. leftreserved = next_left_lcl->lpGbl->dwReserved1;
  1442. leftgdi_flag = next_left_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
  1443. lefthandle = next_left_lcl->hDDSurface;
  1444. dwLeftSurfaceHandle = next_left_lcl->lpSurfMore->dwSurfaceHandle;
  1445. } else
  1446. {
  1447. DPF(0,"Flip:rotating stereo pointers failed, dest. left surfaces invalid");
  1448. bStereo=FALSE;
  1449. }
  1450. }
  1451. /*
  1452. * set the new primary surface pointer
  1453. */
  1454. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE )
  1455. {
  1456. pdrv->vmiData.fpPrimary = vidmem;
  1457. }
  1458. /*
  1459. * rotate the memory pointers
  1460. */
  1461. if( this_dest_lcl != NULL )
  1462. {
  1463. next_lcl->lpGbl->lpVidMemHeap = this->lpVidMemHeap;
  1464. next_lcl->lpGbl->fpVidMem = this->fpVidMem;
  1465. #ifdef USE_ALIAS
  1466. GBLMORE(next_lcl->lpGbl)->fpAliasedVidMem = GBLMORE(this)->fpAliasedVidMem;
  1467. GBLMORE(next_lcl->lpGbl)->fpAliasOfVidMem = GBLMORE(this)->fpAliasOfVidMem;
  1468. #endif /* USE_ALIAS */
  1469. GBLMORE(next_lcl->lpGbl)->fpPhysicalVidMem = GBLMORE(this)->fpPhysicalVidMem;
  1470. GBLMORE(next_lcl->lpGbl)->dwDriverReserved = GBLMORE(this)->dwDriverReserved;
  1471. next_lcl->lpGbl->dwReserved1 = this->dwReserved1;
  1472. next_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
  1473. next_lcl->lpGbl->dwGlobalFlags |= this->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
  1474. next_lcl->hDDSurface = this_lcl->hDDSurface;
  1475. next_lcl->lpSurfMore->dwSurfaceHandle = this_lcl->lpSurfMore->dwSurfaceHandle;
  1476. if (this_lcl->lpSurfMore->dwSurfaceHandle)
  1477. {
  1478. // Since the SurfaceHandle was updated, update the mapping array
  1479. SURFACEHANDLELIST(pdrv_lcl).dwList[this_lcl->lpSurfMore->dwSurfaceHandle].lpSurface = next_lcl;
  1480. }
  1481. if (bStereo)
  1482. {
  1483. LPDDRAWI_DDRAWSURFACE_INT this_left_int;
  1484. LPDDRAWI_DDRAWSURFACE_LCL this_left_lcl;
  1485. this_left_int = FindAttachedSurfaceLeft(this_int);
  1486. this_left_lcl = this_left_int->lpLcl;
  1487. next_left_lcl->lpGbl->lpVidMemHeap = this_left_lcl->lpGbl->lpVidMemHeap;
  1488. next_left_lcl->lpGbl->fpVidMem = this_left_lcl->lpGbl->fpVidMem;
  1489. #ifdef USE_ALIAS
  1490. GBLMORE(next_left_lcl->lpGbl)->fpAliasedVidMem = GBLMORE(this_left_lcl->lpGbl)->fpAliasedVidMem;
  1491. GBLMORE(next_left_lcl->lpGbl)->fpAliasOfVidMem = GBLMORE(this_left_lcl->lpGbl)->fpAliasOfVidMem;
  1492. #endif /* USE_ALIAS */
  1493. GBLMORE(next_left_lcl->lpGbl)->fpPhysicalVidMem = GBLMORE(this_left_lcl->lpGbl)->fpPhysicalVidMem;
  1494. GBLMORE(next_left_lcl->lpGbl)->dwDriverReserved = GBLMORE(this_left_lcl->lpGbl)->dwDriverReserved;
  1495. next_left_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
  1496. next_left_lcl->lpGbl->dwGlobalFlags |= this_left_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
  1497. next_left_lcl->lpGbl->dwReserved1 = this_left_lcl->lpGbl->dwReserved1;
  1498. next_left_lcl->hDDSurface = this_left_lcl->hDDSurface;
  1499. next_left_lcl->lpSurfMore->dwSurfaceHandle = this_left_lcl->lpSurfMore->dwSurfaceHandle;
  1500. if (this_left_lcl->lpSurfMore->dwSurfaceHandle)
  1501. {
  1502. // Since the SurfaceHandle was updated, update the mapping array
  1503. SURFACEHANDLELIST(pdrv_lcl).dwList[this_left_lcl->lpSurfMore->dwSurfaceHandle].lpSurface = next_left_lcl;
  1504. }
  1505. }
  1506. }
  1507. else
  1508. {
  1509. do
  1510. {
  1511. attached_int = FindAttachedFlip( next_int );
  1512. next_lcl = next_int->lpLcl;
  1513. next_lcl->lpGbl->lpVidMemHeap = attached_int->lpLcl->lpGbl->lpVidMemHeap;
  1514. next_lcl->lpGbl->fpVidMem = attached_int->lpLcl->lpGbl->fpVidMem;
  1515. #ifdef USE_ALIAS
  1516. GBLMORE(next_lcl->lpGbl)->fpAliasedVidMem = GBLMORE(attached_int->lpLcl->lpGbl)->fpAliasedVidMem;
  1517. GBLMORE(next_lcl->lpGbl)->fpAliasOfVidMem = GBLMORE(attached_int->lpLcl->lpGbl)->fpAliasOfVidMem;
  1518. #endif /* USE_ALIAS */
  1519. GBLMORE(next_lcl->lpGbl)->fpPhysicalVidMem = GBLMORE(attached_int->lpLcl->lpGbl)->fpPhysicalVidMem;
  1520. GBLMORE(next_lcl->lpGbl)->dwDriverReserved = GBLMORE(attached_int->lpLcl->lpGbl)->dwDriverReserved;
  1521. next_lcl->lpGbl->dwReserved1 = attached_int->lpLcl->lpGbl->dwReserved1;
  1522. next_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
  1523. next_lcl->lpGbl->dwGlobalFlags |= attached_int->lpLcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
  1524. next_lcl->hDDSurface = attached_int->lpLcl->hDDSurface;
  1525. next_lcl->lpSurfMore->dwSurfaceHandle = attached_int->lpLcl->lpSurfMore->dwSurfaceHandle;
  1526. if (attached_int->lpLcl->lpSurfMore->dwSurfaceHandle)
  1527. {
  1528. // Since the SurfaceHandle was updated, update the mapping array
  1529. SURFACEHANDLELIST(pdrv_lcl).dwList[attached_int->lpLcl->lpSurfMore->dwSurfaceHandle].lpSurface = next_lcl;
  1530. }
  1531. if (bStereo)
  1532. {
  1533. LPDDRAWI_DDRAWSURFACE_INT attached_left_int;
  1534. LPDDRAWI_DDRAWSURFACE_LCL attached_left_lcl;
  1535. attached_left_int = FindAttachedSurfaceLeft(attached_int);
  1536. next_left_int = FindAttachedSurfaceLeft(next_int);
  1537. if (attached_left_int!=NULL && next_left_int!=NULL)
  1538. {
  1539. attached_left_lcl=attached_left_int->lpLcl;
  1540. next_left_lcl=next_left_int->lpLcl;
  1541. next_left_lcl->lpGbl->lpVidMemHeap = attached_left_int->lpLcl->lpGbl->lpVidMemHeap;
  1542. next_left_lcl->lpGbl->fpVidMem = attached_left_int->lpLcl->lpGbl->fpVidMem;
  1543. #ifdef USE_ALIAS
  1544. GBLMORE(next_left_lcl->lpGbl)->fpAliasedVidMem = GBLMORE(attached_left_int->lpLcl->lpGbl)->fpAliasedVidMem;
  1545. GBLMORE(next_left_lcl->lpGbl)->fpAliasOfVidMem = GBLMORE(attached_left_int->lpLcl->lpGbl)->fpAliasOfVidMem;
  1546. #endif /* USE_ALIAS */
  1547. GBLMORE(next_left_lcl->lpGbl)->fpPhysicalVidMem = GBLMORE(attached_left_int->lpLcl->lpGbl)->fpPhysicalVidMem;
  1548. GBLMORE(next_left_lcl->lpGbl)->dwDriverReserved = GBLMORE(attached_left_int->lpLcl->lpGbl)->dwDriverReserved;
  1549. next_left_lcl->lpGbl->dwReserved1 = attached_left_int->lpLcl->lpGbl->dwReserved1;
  1550. next_left_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
  1551. next_left_lcl->lpGbl->dwGlobalFlags |= attached_left_int->lpLcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
  1552. next_left_lcl->hDDSurface = attached_left_int->lpLcl->hDDSurface;
  1553. next_left_lcl->lpSurfMore->dwSurfaceHandle = attached_left_int->lpLcl->lpSurfMore->dwSurfaceHandle;
  1554. if (attached_left_int->lpLcl->lpSurfMore->dwSurfaceHandle)
  1555. {
  1556. // Since the SurfaceHandle was updated, update the mapping array
  1557. SURFACEHANDLELIST(pdrv_lcl).dwList[attached_left_int->lpLcl->lpSurfMore->dwSurfaceHandle].lpSurface =
  1558. next_left_lcl;
  1559. }
  1560. } else
  1561. {
  1562. DPF(0,"Flip:left surface pointers corrupted");
  1563. bStereo=FALSE;
  1564. }
  1565. }
  1566. next_int = attached_int;
  1567. /*
  1568. * NOTE: Again, do NOT compare against interface pointers. We may
  1569. * have multiple interfaces to a single surface object leading to
  1570. * an infinite loop. Compare against the LOCAL object not the
  1571. * interface pointers.
  1572. */
  1573. } while( next_int->lpLcl != this_int->lpLcl );
  1574. }
  1575. this->fpVidMem = vidmem;
  1576. #ifdef USE_ALIAS
  1577. GBLMORE(this)->fpAliasedVidMem = aliasvidmem;
  1578. GBLMORE(this)->fpAliasOfVidMem = aliasofvidmem;
  1579. #endif /* USE_ALIAS */
  1580. GBLMORE(this)->fpPhysicalVidMem = physicalvidmem;
  1581. GBLMORE(this)->dwDriverReserved = driverreserved;
  1582. this->lpVidMemHeap = vidmemheap;
  1583. this->dwReserved1 = reserved;
  1584. this->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
  1585. this->dwGlobalFlags |= gdi_flag;
  1586. this_lcl->hDDSurface = handle;
  1587. this_lcl->lpSurfMore->dwSurfaceHandle=dwSurfaceHandle;
  1588. if (dwSurfaceHandle)
  1589. {
  1590. // Since the SurfaceHandle was updated, update the mapping array
  1591. SURFACEHANDLELIST(pdrv_lcl).dwList[dwSurfaceHandle].lpSurface = this_lcl;
  1592. }
  1593. if (bStereo)
  1594. {
  1595. LPDDRAWI_DDRAWSURFACE_INT this_left_int;
  1596. LPDDRAWI_DDRAWSURFACE_LCL this_left_lcl;
  1597. this_left_int = FindAttachedSurfaceLeft(this_int);
  1598. if (this_left_int!=NULL)
  1599. {
  1600. this_left_lcl = this_left_int->lpLcl;
  1601. this_left_lcl->lpGbl->fpVidMem = leftvidmem;
  1602. #ifdef USE_ALIAS
  1603. GBLMORE(this_left_lcl->lpGbl)->fpAliasedVidMem = leftaliasvidmem;
  1604. GBLMORE(this_left_lcl->lpGbl)->fpAliasOfVidMem = leftaliasofvidmem;
  1605. #endif /* USE_ALIAS */
  1606. GBLMORE(this_left_lcl->lpGbl)->fpPhysicalVidMem = leftphysicalvidmem;
  1607. GBLMORE(this_left_lcl->lpGbl)->dwDriverReserved = leftdriverreserved;
  1608. this_left_lcl->lpGbl->lpVidMemHeap = leftvidmemheap;
  1609. this_left_lcl->lpGbl->dwReserved1 = leftreserved;
  1610. this_left_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
  1611. this_left_lcl->lpGbl->dwGlobalFlags |= leftgdi_flag;
  1612. this_left_lcl->hDDSurface = lefthandle;
  1613. this_left_lcl->lpSurfMore->dwSurfaceHandle=dwLeftSurfaceHandle;
  1614. if (dwLeftSurfaceHandle)
  1615. {
  1616. // Since the SurfaceHandle was updated, update the mapping array
  1617. SURFACEHANDLELIST(pdrv_lcl).dwList[dwLeftSurfaceHandle].lpSurface = this_left_lcl;
  1618. }
  1619. }
  1620. }
  1621. }
  1622. if ((GetCurrentProcessId() == GETCURRPID()) &&
  1623. (pdrv_lcl->pSurfaceFlipNotify))
  1624. {
  1625. DDASSERT(pdrv_lcl->pD3DIUnknown != NULL);
  1626. pdrv_lcl->pSurfaceFlipNotify(pdrv_lcl->pD3DIUnknown);
  1627. }
  1628. /*
  1629. * If the driver was flipped to the GDI surface and we just flipped the
  1630. * primary chain then we are no longer showing the GDI surface.
  1631. */
  1632. if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) &&
  1633. ( pdrv->dwFlags & DDRAWI_FLIPPEDTOGDI ) )
  1634. {
  1635. pdrv->dwFlags &= ~DDRAWI_FLIPPEDTOGDI;
  1636. }
  1637. LEAVE_WIN16LOCK();
  1638. if( dwRegFlags & DDRAW_REGFLAGS_SHOWFRAMERATE )
  1639. {
  1640. updateFrameRate();
  1641. }
  1642. LEAVE_DDRAW();
  1643. return DD_OK;
  1644. } /* DD_Surface_Flip */
  1645. #undef DPF_MODNAME
  1646. #define DPF_MODNAME "GetPixelFormat"
  1647. /*
  1648. * DD_Surface_GetPixelFormat
  1649. */
  1650. HRESULT DDAPI DD_Surface_GetPixelFormat(
  1651. LPDIRECTDRAWSURFACE lpDDSurface,
  1652. LPDDPIXELFORMAT lpDDPixelFormat )
  1653. {
  1654. LPDDRAWI_DDRAWSURFACE_INT this_int;
  1655. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  1656. LPDDRAWI_DDRAWSURFACE_GBL this;
  1657. LPDDPIXELFORMAT pddpf;
  1658. ENTER_DDRAW();
  1659. DPF(2,A,"ENTERAPI: DD_Surface_GetPixelFormat");
  1660. TRY
  1661. {
  1662. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  1663. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  1664. {
  1665. LEAVE_DDRAW();
  1666. return DDERR_INVALIDOBJECT;
  1667. }
  1668. this_lcl = this_int->lpLcl;
  1669. if( !VALID_DDPIXELFORMAT_PTR( lpDDPixelFormat ) )
  1670. {
  1671. LEAVE_DDRAW();
  1672. return DDERR_INVALIDPARAMS;
  1673. }
  1674. /*
  1675. * Execute buffers don't have a pixel format.
  1676. */
  1677. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
  1678. {
  1679. DPF_ERR( "Invalid surface type: can't get pixel format" );
  1680. LEAVE_DDRAW();
  1681. return DDERR_INVALIDSURFACETYPE;
  1682. }
  1683. this = this_lcl->lpGbl;
  1684. GET_PIXEL_FORMAT( this_lcl, this, pddpf );
  1685. *lpDDPixelFormat = *pddpf;
  1686. }
  1687. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1688. {
  1689. DPF_ERR( "Exception encountered validating parameters" );
  1690. LEAVE_DDRAW();
  1691. return DDERR_INVALIDPARAMS;
  1692. }
  1693. LEAVE_DDRAW();
  1694. return DD_OK;
  1695. } /* DD_Surface_GetPixelFormat */
  1696. #if 0
  1697. /* GEE: removed this, obsolete */
  1698. /*
  1699. * DD_Surface_SetCompression
  1700. */
  1701. HRESULT DDAPI DD_Surface_SetCompression(
  1702. LPDIRECTDRAWSURFACE lpDDSurface,
  1703. LPDDPIXELFORMAT lpDDPixelFormat )
  1704. {
  1705. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  1706. LPDDRAWI_DDRAWSURFACE_GBL this;
  1707. ENTER_DDRAW();
  1708. DPF(2,A,"ENTERAPI: DD_Surface_SetCompression");
  1709. TRY
  1710. {
  1711. this_lcl = (LPDDRAWI_DDRAWSURFACE_LCL) lpDDSurface;
  1712. if( !VALID_DIRECTDRAWSURFACE_PTR( this_lcl ) )
  1713. {
  1714. LEAVE_DDRAW();
  1715. return DDERR_INVALIDOBJECT;
  1716. }
  1717. if( !VALID_DDPIXELFORMAT_PTR( lpDDPixelFormat ) )
  1718. {
  1719. LEAVE_DDRAW();
  1720. return DDERR_INVALIDPARAMS;
  1721. }
  1722. this = this_lcl->lpGbl;
  1723. }
  1724. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1725. {
  1726. DPF_ERR( "Exception encountered validating parameters" );
  1727. LEAVE_DDRAW();
  1728. return DDERR_INVALIDPARAMS;
  1729. }
  1730. LEAVE_DDRAW();
  1731. return DDERR_UNSUPPORTED;
  1732. } /* DD_Surface_SetCompression */
  1733. #endif
  1734. #undef DPF_MODNAME
  1735. #define DPF_MODNAME "GetSurfaceDesc"
  1736. /*
  1737. * DD_Surface_GetSurfaceDesc
  1738. */
  1739. HRESULT DDAPI DD_Surface_GetSurfaceDesc(
  1740. LPDIRECTDRAWSURFACE lpDDSurface,
  1741. LPDDSURFACEDESC lpDDSurfaceDesc )
  1742. {
  1743. LPDDRAWI_DDRAWSURFACE_INT this_int;
  1744. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  1745. LPDDRAWI_DDRAWSURFACE_GBL this;
  1746. ENTER_DDRAW();
  1747. DPF(2,A,"ENTERAPI: DD_Surface_GetSurfaceDesc");
  1748. TRY
  1749. {
  1750. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  1751. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  1752. {
  1753. LEAVE_DDRAW();
  1754. return DDERR_INVALIDOBJECT;
  1755. }
  1756. this_lcl = this_int->lpLcl;
  1757. if( !VALID_DDSURFACEDESC_PTR( lpDDSurfaceDesc ) )
  1758. {
  1759. LEAVE_DDRAW();
  1760. return DDERR_INVALIDPARAMS;
  1761. }
  1762. this = this_lcl->lpGbl;
  1763. FillDDSurfaceDesc( this_lcl, lpDDSurfaceDesc );
  1764. }
  1765. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1766. {
  1767. DPF_ERR( "Exception encountered validating parameters" );
  1768. LEAVE_DDRAW();
  1769. return DDERR_INVALIDPARAMS;
  1770. }
  1771. LEAVE_DDRAW();
  1772. return DD_OK;
  1773. } /* DD_Surface_GetSurfaceDesc */
  1774. /*
  1775. * DD_Surface_GetSurfaceDesc4
  1776. */
  1777. HRESULT DDAPI DD_Surface_GetSurfaceDesc4(
  1778. LPDIRECTDRAWSURFACE lpDDSurface,
  1779. LPDDSURFACEDESC2 lpDDSurfaceDesc )
  1780. {
  1781. LPDDRAWI_DDRAWSURFACE_INT this_int;
  1782. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  1783. LPDDRAWI_DDRAWSURFACE_GBL this;
  1784. ENTER_DDRAW();
  1785. DPF(2,A,"ENTERAPI: DD_Surface_GetSurfaceDesc4");
  1786. TRY
  1787. {
  1788. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  1789. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  1790. {
  1791. DPF_ERR("Bad IDirectDrawSurfaceX pointer");
  1792. LEAVE_DDRAW();
  1793. return DDERR_INVALIDOBJECT;
  1794. }
  1795. this_lcl = this_int->lpLcl;
  1796. if( !VALID_DDSURFACEDESC2_PTR( lpDDSurfaceDesc ) )
  1797. {
  1798. DPF_ERR("Bad DDSURFACEDESC pointer");
  1799. LEAVE_DDRAW();
  1800. return DDERR_INVALIDPARAMS;
  1801. }
  1802. this = this_lcl->lpGbl;
  1803. FillDDSurfaceDesc2( this_lcl, lpDDSurfaceDesc );
  1804. }
  1805. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1806. {
  1807. DPF_ERR( "Exception encountered validating parameters" );
  1808. LEAVE_DDRAW();
  1809. return DDERR_INVALIDPARAMS;
  1810. }
  1811. LEAVE_DDRAW();
  1812. return DD_OK;
  1813. } /* DD_Surface_GetSurfaceDesc4 */
  1814. #ifdef WIN95
  1815. #undef DPF_MODNAME
  1816. #define DPF_MODNAME "InternalGetDC"
  1817. /*
  1818. * BIsValidDCFormat
  1819. *
  1820. * We should only try to get a DC on a format that GDI undersatnds
  1821. */
  1822. BOOL bIsValidDCFormat( LPDDPIXELFORMAT lpPf )
  1823. {
  1824. //
  1825. // Must be an RGB format
  1826. //
  1827. if( !(lpPf->dwFlags & DDPF_RGB ) )
  1828. {
  1829. return FALSE;
  1830. }
  1831. //
  1832. // Assume that 1, 4, and 8bpp surfaces are OK
  1833. //
  1834. if( ( lpPf->dwRGBBitCount == 8 ) ||
  1835. ( lpPf->dwRGBBitCount == 4 ) ||
  1836. ( lpPf->dwRGBBitCount == 1 ) )
  1837. {
  1838. return TRUE;
  1839. }
  1840. //
  1841. // If it's 16bpp, it must be 5:5:5 or 5:6:5
  1842. //
  1843. if( lpPf->dwRGBBitCount == 16 )
  1844. {
  1845. if( ( lpPf->dwRBitMask == 0xf800 ) &&
  1846. ( lpPf->dwGBitMask == 0x07e0 ) &&
  1847. ( lpPf->dwBBitMask == 0x001f ) )
  1848. {
  1849. // 5:6:5
  1850. return TRUE;
  1851. }
  1852. else if( ( lpPf->dwRBitMask == 0x7c00 ) &&
  1853. ( lpPf->dwGBitMask == 0x03e0 ) &&
  1854. ( lpPf->dwBBitMask == 0x001f ) )
  1855. {
  1856. // 5:5:5
  1857. return TRUE;
  1858. }
  1859. }
  1860. else if( ( lpPf->dwRGBBitCount == 24 ) ||
  1861. ( lpPf->dwRGBBitCount == 32 ) )
  1862. {
  1863. if( ( lpPf->dwBBitMask == 0x0000FF ) &&
  1864. ( lpPf->dwGBitMask == 0x00FF00 ) &&
  1865. ( lpPf->dwRBitMask == 0xFF0000 ) )
  1866. {
  1867. // 8:8:8
  1868. return TRUE;
  1869. }
  1870. }
  1871. return FALSE;
  1872. }
  1873. /*
  1874. * InternalGetDC
  1875. *
  1876. * This is the Windows 95 version of this function. The code paths are so radically
  1877. * different that we have broken this stuff out into two different functions.
  1878. *
  1879. * This functions assumes the DDRAW critical section is already held.
  1880. *
  1881. * This function will not return the OWNDC for an OWNDC surface. It always allocates
  1882. * a new DC.
  1883. */
  1884. HRESULT InternalGetDC( LPDDRAWI_DDRAWSURFACE_INT this_int, HDC FAR* lphdc, BOOL bWin16Lock)
  1885. {
  1886. LPDDRAWI_DDRAWSURFACE_GBL this;
  1887. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  1888. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  1889. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  1890. HRESULT ddrval;
  1891. HRESULT tmprval;
  1892. DDSURFACEDESC ddsd;
  1893. LPVOID pbits;
  1894. DWORD dwLockFlags = bWin16Lock ? DDLOCK_TAKE_WIN16 : 0;
  1895. DDASSERT( NULL != this_int );
  1896. DDASSERT( NULL != lphdc );
  1897. this_lcl = this_int->lpLcl;
  1898. DDASSERT( NULL != this_lcl );
  1899. this = this_lcl->lpGbl;
  1900. DDASSERT( NULL != this );
  1901. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  1902. DDASSERT( NULL != pdrv_lcl );
  1903. pdrv = pdrv_lcl->lpGbl;
  1904. DDASSERT( NULL != pdrv );
  1905. *lphdc = NULL;
  1906. /* Get a pointer to the bits of the surface */
  1907. ddrval = InternalLock( this_lcl, &pbits, NULL , DDLOCK_WAIT | dwLockFlags );
  1908. if( ddrval == DD_OK )
  1909. {
  1910. LPDDRAWI_DDRAWPALETTE_INT ppal;
  1911. DPF( 4,"GetDC: Lock succeeded." );
  1912. ddsd.dwSize = sizeof(ddsd);
  1913. FillDDSurfaceDesc( this_lcl, &ddsd );
  1914. ddsd.lpSurface = pbits;
  1915. ppal = this_lcl->lpDDPalette;
  1916. if( ( NULL != ppal ) && !( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) )
  1917. *lphdc = DD16_GetDC( (HDC)pdrv_lcl->hDC, &ddsd, ppal->lpLcl->lpGbl->lpColorTable );
  1918. else
  1919. *lphdc = DD16_GetDC( (HDC)pdrv_lcl->hDC, &ddsd, NULL );
  1920. if( NULL == *lphdc )
  1921. {
  1922. tmprval = InternalUnlock( this_lcl, NULL, NULL, dwLockFlags );
  1923. DDASSERT( !FAILED(tmprval) );
  1924. DPF_ERR( "Could not obtain DC" );
  1925. ddrval = DDERR_CANTCREATEDC;
  1926. }
  1927. else
  1928. {
  1929. ddrval = InternalAssociateDC( *lphdc, this_lcl );
  1930. if( FAILED( ddrval ) )
  1931. {
  1932. DPF_ERR( "Could not associate DC" );
  1933. DD16_ReleaseDC( *lphdc );
  1934. tmprval = InternalUnlock( this_lcl, NULL, NULL, dwLockFlags );
  1935. DDASSERT( !FAILED(tmprval) );
  1936. *lphdc = NULL;
  1937. }
  1938. else
  1939. {
  1940. this_lcl->dwFlags |= DDRAWISURF_HASDC;
  1941. /*
  1942. * Currenlty OWNDC is only valid for EXPLICIT system
  1943. * memory surfaces so we don't need to hold the lock
  1944. * (cause the surface can't be lost).
  1945. *
  1946. * This is an OWNDC surface so we don't hold a lock
  1947. * for the duration. Unlock the surface now.
  1948. */
  1949. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC )
  1950. {
  1951. tmprval = InternalUnlock( this_lcl, NULL, NULL, dwLockFlags );
  1952. DDASSERT( !FAILED(tmprval) );
  1953. }
  1954. }
  1955. }
  1956. } //if InternalLock succeeded
  1957. // We could not lock the primary surface. This is because the
  1958. // primary is already locked (and we should wait until it is
  1959. // unlocked) or we have no ddraw support AND no DCI support in
  1960. // the driver (in which case the HEL has created the primary
  1961. // and we will NEVER be able to lock it. In this case, we are
  1962. // on an emulated primary and the lock failed with
  1963. // DDERR_GENERIC.
  1964. else if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) &&
  1965. ( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) &&
  1966. ( ddrval != DD_OK ) )
  1967. {
  1968. #ifdef GETDC_NULL
  1969. DPF( 4, "GetDC: Returning GetDC(NULL).");
  1970. *lphdc = GetDC( NULL );
  1971. #else
  1972. DPF( 4, "GetDC: Returning device DC.");
  1973. DDASSERT( GetObjectType( (HDC)pdrv_lcl->hDC ) == OBJ_DC );
  1974. *lphdc = (HDC)pdrv_lcl->hDC;
  1975. #endif
  1976. if( NULL != *lphdc )
  1977. {
  1978. ddrval = InternalAssociateDC( *lphdc, this_lcl );
  1979. if( FAILED( ddrval ) )
  1980. {
  1981. DPF_ERR( "Could not associate DC" );
  1982. #ifdef GETDC_NULL
  1983. ReleaseDC( NULL, *lphdc );
  1984. #endif
  1985. *lphdc = NULL;
  1986. }
  1987. else
  1988. {
  1989. // signal to ourselves that we gave a DC without
  1990. // locking.
  1991. this_lcl->dwFlags |= ( DDRAWISURF_GETDCNULL | DDRAWISURF_HASDC );
  1992. if( !( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC ) )
  1993. {
  1994. this->dwUsageCount++;
  1995. CHANGE_GLOBAL_CNT( pdrv, this, 1 );
  1996. }
  1997. }
  1998. }
  1999. else
  2000. {
  2001. DPF_ERR( "Could not obtain DC" );
  2002. ddrval = DDERR_CANTCREATEDC;
  2003. }
  2004. }
  2005. else
  2006. {
  2007. /*
  2008. * InternalLock failed, and the surface wasn't an emulated primary
  2009. */
  2010. DPF_ERR( "Could not obtain DC" );
  2011. ddrval = DDERR_CANTCREATEDC;
  2012. }
  2013. /*
  2014. * If we managed to get a DC and we are an OWNDC surface then stash the HDC away
  2015. * for future reference.
  2016. */
  2017. if( ( !FAILED(ddrval) ) && ( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC ) )
  2018. {
  2019. DDASSERT( NULL != *lphdc );
  2020. DDASSERT( 0UL == this_lcl->hDC );
  2021. this_lcl->hDC = (DWORD)*lphdc;
  2022. }
  2023. return ddrval;
  2024. } /* InternalGetDC */
  2025. #undef DPF_MODNAME
  2026. #define DPF_MODNAME "InternalReleaseDC"
  2027. /*
  2028. * InternalReleaseDC - Windows 95 version
  2029. *
  2030. * Assumes the DirectDraw critical section is already held
  2031. */
  2032. HRESULT InternalReleaseDC( LPDDRAWI_DDRAWSURFACE_LCL this_lcl, HDC hdc, BOOL bWin16Lock )
  2033. {
  2034. LPDDRAWI_DDRAWSURFACE_GBL this;
  2035. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  2036. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  2037. HRESULT ddrval;
  2038. #ifdef WINNT
  2039. GdiFlush();
  2040. #endif
  2041. DDASSERT( NULL != this_lcl );
  2042. DDASSERT( NULL != hdc );
  2043. this = this_lcl->lpGbl;
  2044. DDASSERT( NULL != this );
  2045. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  2046. DDASSERT( NULL != pdrv_lcl );
  2047. pdrv = pdrv_lcl->lpGbl;
  2048. DDASSERT( NULL != pdrv );
  2049. ddrval = DD_OK;
  2050. if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) &&
  2051. ( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) &&
  2052. ( this_lcl->dwFlags & DDRAWISURF_GETDCNULL ) )
  2053. {
  2054. DPF( 4, "ReleaseDC: ReleaseDC(NULL)" );
  2055. if( !( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC ) )
  2056. {
  2057. this->dwUsageCount--;
  2058. CHANGE_GLOBAL_CNT( pdrv, this, -1 );
  2059. }
  2060. #ifdef GETDC_NULL
  2061. /*
  2062. * Only actually free the HDC if we are running in the
  2063. * application's context and not DDHELP's (if we are
  2064. * running on DDHELP's the HDC is already gone)
  2065. */
  2066. if( GetCurrentProcessId() == GETCURRPID() )
  2067. ReleaseDC( NULL, hdc );
  2068. #endif
  2069. this_lcl->dwFlags &= ~DDRAWISURF_GETDCNULL;
  2070. }
  2071. else
  2072. {
  2073. DPF( 4, "ReleaseDC: DD16_ReleaseDC()");
  2074. /*
  2075. * Free the thing to give DDraw16 a chance
  2076. * to clean up what it's messed with. We can do this on
  2077. * the helper thread because DCs that are created by
  2078. * DD16_GetDC are 'alive' until DDRAW16 gets unloaded.
  2079. * However, they are dangerous because they point to data
  2080. * that might have been freed by the current app.
  2081. */
  2082. DD16_ReleaseDC( hdc );
  2083. /*
  2084. * Only unlock if its not an OWNDC surface as OWNDC surfaces
  2085. * don't hold the lock while the HDC is out.
  2086. */
  2087. if( !( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC ) )
  2088. {
  2089. ddrval = InternalUnlock( this_lcl, NULL, NULL, bWin16Lock ? DDLOCK_TAKE_WIN16 : 0);
  2090. DDASSERT( !FAILED( ddrval ) );
  2091. }
  2092. }
  2093. this_lcl->dwFlags &= ~DDRAWISURF_HASDC;
  2094. // Remove this DC from our list
  2095. InternalRemoveDCFromList( hdc, this_lcl );
  2096. /*
  2097. * If this is an OWNDC surface then remove it from the HDC cache
  2098. * in the local object.
  2099. */
  2100. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC )
  2101. this_lcl->hDC = 0UL;
  2102. return ddrval;
  2103. } /* InternalReleaseDC */
  2104. #else /* WIN95 */
  2105. #undef DPF_MODNAME
  2106. #define DPF_MODNAME "InternalGetDC"
  2107. /*
  2108. * InternalGetDC - WinNT version
  2109. *
  2110. * This is the Windows NT version of this function. The code paths are so radically
  2111. * different that we have broken this stuff out into two different functions.
  2112. *
  2113. * This functions assumes the DDRAW mutex is already held.
  2114. *
  2115. * This function will not return the OWNDC for an OWNDC surface. It always allocates
  2116. * a new DC.
  2117. */
  2118. HRESULT InternalGetDC( LPDDRAWI_DDRAWSURFACE_INT this_int, HDC FAR* lphDC )
  2119. {
  2120. LPDDRAWI_DDRAWSURFACE_GBL this;
  2121. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  2122. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  2123. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  2124. HRESULT ddrval;
  2125. DDASSERT( NULL != this_int );
  2126. DDASSERT( NULL != lphDC );
  2127. this_lcl = this_int->lpLcl;
  2128. DDASSERT( NULL != this_lcl );
  2129. this = this_lcl->lpGbl;
  2130. DDASSERT( NULL != this );
  2131. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  2132. DDASSERT( NULL != pdrv_lcl );
  2133. pdrv = pdrv_lcl->lpGbl;
  2134. DDASSERT( NULL != pdrv );
  2135. *lphDC = NULL;
  2136. ddrval = DD_OK;
  2137. FlushD3DStates(this_lcl);
  2138. #if COLLECTSTATS
  2139. if(this_lcl->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
  2140. ++this_lcl->lpSurfMore->lpDD_lcl->dwNumTexGetDCs;
  2141. #endif
  2142. if( (this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) &&
  2143. (this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
  2144. {
  2145. #ifdef GETDC_NULL
  2146. DPF( 4, "GetDC(NULL)" );
  2147. *lphDC = GetDC( NULL );
  2148. #else
  2149. DPF( 4, "GetDC: Returning device DC." );
  2150. DDASSERT( GetObjectType( (HDC)this_lcl->lpSurfMore->lpDD_lcl->hDC ) == OBJ_DC );
  2151. if (this_lcl->lpSurfMore->lpDD_lcl->dwLocalFlags & DDRAWILCL_DIRTYDC)
  2152. {
  2153. HDC hdc;
  2154. /*
  2155. * We need to destroy and recreate the device DC because a ChangeDisplaySettings
  2156. * will have messed up the vis rgn associated with that DC. We need to create
  2157. * the new DC before we destroy the old one just in case the destroy caused an
  2158. * unload of the driver
  2159. */
  2160. hdc = DD_CreateDC( this_lcl->lpSurfMore->lpDD_lcl->lpGbl->cDriverName );
  2161. DeleteDC((HDC) this_lcl->lpSurfMore->lpDD_lcl->hDC);
  2162. this_lcl->lpSurfMore->lpDD_lcl->hDC = (ULONG_PTR) hdc;
  2163. if( this_lcl->lpDDPalette )
  2164. {
  2165. SelectPalette(hdc, (HPALETTE) this_lcl->lpDDPalette->lpLcl->lpGbl->dwReserved1, FALSE);
  2166. RealizePalette(hdc);
  2167. }
  2168. this_lcl->lpSurfMore->lpDD_lcl->dwLocalFlags &= ~DDRAWILCL_DIRTYDC;
  2169. }
  2170. *lphDC = (HDC)this_lcl->lpSurfMore->lpDD_lcl->hDC;
  2171. #endif
  2172. }
  2173. else
  2174. {
  2175. LPDDRAWI_DDRAWPALETTE_INT ppal;
  2176. DPF( 4, "DdGetDC" );
  2177. ppal = this_lcl->lpDDPalette;
  2178. if (this_lcl->hDDSurface || CompleteCreateSysmemSurface(this_lcl))
  2179. {
  2180. if( ( NULL != ppal ) && !( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) )
  2181. *lphDC = DdGetDC( this_lcl, ppal->lpLcl->lpGbl->lpColorTable );
  2182. else
  2183. *lphDC = DdGetDC( this_lcl, NULL );
  2184. }
  2185. }
  2186. if( NULL == *lphDC )
  2187. {
  2188. DPF_ERR( "Could not obtain DC" );
  2189. ddrval = DDERR_CANTCREATEDC;
  2190. }
  2191. else
  2192. {
  2193. ddrval = InternalAssociateDC( *lphDC, this_lcl );
  2194. if( FAILED( ddrval ) )
  2195. {
  2196. DPF_ERR( "Could not associate DC" );
  2197. if( (this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) &&
  2198. (this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
  2199. {
  2200. #ifdef GETDC_NULL
  2201. ReleaseDC( NULL, *lphDC );
  2202. #endif
  2203. }
  2204. else
  2205. {
  2206. DdReleaseDC( this_lcl );
  2207. }
  2208. *lphDC = NULL;
  2209. }
  2210. else
  2211. {
  2212. this_lcl->dwFlags |= DDRAWISURF_HASDC;
  2213. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC )
  2214. {
  2215. /*
  2216. * OWNDC surfaces don't hold a lock while the HDC is available.
  2217. */
  2218. /*
  2219. * If this is an OWNDC surface then we need to stash the HDC
  2220. * away in the surface for future reference.
  2221. */
  2222. DDASSERT( this->dwGlobalFlags & DDRAWISURFGBL_SYSMEMREQUESTED );
  2223. DDASSERT( 0UL == this_lcl->hDC );
  2224. this_lcl->hDC = (ULONG_PTR) *lphDC;
  2225. }
  2226. else
  2227. {
  2228. /*
  2229. * On NT we don't lock the surface to take the HDC. However, we
  2230. * want the semantics on both NT and 95 (where the lock is taken)
  2231. * to be the same so we* bump the usage counts and hold the mutex.
  2232. */
  2233. this->dwUsageCount++;
  2234. CHANGE_GLOBAL_CNT( pdrv, this, 1 );
  2235. ENTER_DDRAW();
  2236. }
  2237. }
  2238. }
  2239. // Remove any cached RLE stuff for the surface
  2240. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
  2241. {
  2242. extern void FreeRleData(LPDDRAWI_DDRAWSURFACE_LCL psurf);
  2243. FreeRleData( this_lcl );
  2244. }
  2245. if(IsD3DManaged(this_lcl))
  2246. {
  2247. /* Mark everything dirty */
  2248. MarkDirty(this_lcl);
  2249. this_lcl->lpSurfMore->lpRegionList->rdh.nCount = NUM_RECTS_IN_REGIONLIST;
  2250. }
  2251. return ddrval;
  2252. } /* InternalGetDC */
  2253. #undef DPF_MODNAME
  2254. #define DPF_MODNAME "InternalReleaseDC"
  2255. /*
  2256. * InternalReleaseDC - Windows NT version
  2257. *
  2258. * Assumes the DirectDraw mutex is already held
  2259. *
  2260. * This function
  2261. */
  2262. HRESULT InternalReleaseDC( LPDDRAWI_DDRAWSURFACE_LCL this_lcl, HDC hdc )
  2263. {
  2264. LPDDRAWI_DDRAWSURFACE_GBL this;
  2265. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  2266. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  2267. HRESULT ddrval;
  2268. DDASSERT( NULL != this_lcl );
  2269. DDASSERT( NULL != hdc );
  2270. this = this_lcl->lpGbl;
  2271. DDASSERT( NULL != this );
  2272. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  2273. DDASSERT( NULL != pdrv_lcl );
  2274. pdrv = pdrv_lcl->lpGbl;
  2275. DDASSERT( NULL != pdrv );
  2276. ddrval = DD_OK;
  2277. /*
  2278. * Since this function already marks the surface as not having a DC even if
  2279. * a failure is encountered destroying the DC, we always reduce the surface's
  2280. * usage count.
  2281. * This usage count decrement is done because we didn't call InternalLock on the
  2282. * GetDC, so we don't call InternalUnlock here, but we still mucked with the flags
  2283. * to ensure that ddraw.dll didn't hand out a lock while someone had a DC.
  2284. *
  2285. * NOTE: If this is an OWNDC surface we never even spoofed the lock so don't unspoof
  2286. * now.
  2287. */
  2288. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC )
  2289. {
  2290. DDASSERT( this->dwGlobalFlags & DDRAWISURFGBL_SYSMEMREQUESTED );
  2291. DDASSERT( 0UL != this_lcl->hDC );
  2292. this_lcl->hDC = 0UL;
  2293. }
  2294. else
  2295. {
  2296. /*
  2297. * Undo the pseudo-lock we took to make NT behave like '95.
  2298. * The LEAVE_DDRAW may appear strange but we know we already
  2299. * have another reference to the mutex when we call this function.
  2300. */
  2301. this->dwUsageCount--;
  2302. CHANGE_GLOBAL_CNT( pdrv, this, -1 );
  2303. LEAVE_DDRAW();
  2304. }
  2305. if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) &&
  2306. ( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) )
  2307. {
  2308. #ifdef GETDC_NULL
  2309. DPF( 4, "NT emulation releasing primary DC" );
  2310. ReleaseDC( NULL, hdc );
  2311. #endif
  2312. }
  2313. else
  2314. {
  2315. if( !DdReleaseDC( this_lcl ) )
  2316. {
  2317. DPF( 0, "DDreleaseDC fails!" );
  2318. ddrval = DDERR_GENERIC;
  2319. }
  2320. }
  2321. this_lcl->dwFlags &= ~DDRAWISURF_HASDC;
  2322. // Remove this DC from our list
  2323. InternalRemoveDCFromList( hdc, this_lcl );
  2324. return ddrval;
  2325. }
  2326. #endif /* WIN95 */
  2327. #undef DPF_MODNAME
  2328. #define DPF_MODNAME "DD_Surface_GetDC"
  2329. /*
  2330. * DD_Surface_GetDC
  2331. */
  2332. HRESULT DDAPI DD_Surface_GetDC(
  2333. LPDIRECTDRAWSURFACE lpDDSurface,
  2334. HDC FAR *lphDC )
  2335. {
  2336. LPDDRAWI_DDRAWSURFACE_INT this_int;
  2337. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  2338. LPDDRAWI_DDRAWSURFACE_GBL this;
  2339. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  2340. HRESULT ddrval;
  2341. ENTER_DDRAW();
  2342. DPF(2,A,"ENTERAPI: DD_Surface_GetDC");
  2343. /* DPF_ENTERAPI(lpDDSurface); */
  2344. // 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  2345. DPF(3,A," lphDC = 0x%p", lphDC);
  2346. TRY
  2347. {
  2348. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  2349. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  2350. {
  2351. LEAVE_DDRAW();
  2352. return DDERR_INVALIDOBJECT;
  2353. }
  2354. this_lcl = this_int->lpLcl;
  2355. if( !VALID_HDC_PTR( lphDC ) )
  2356. {
  2357. LEAVE_DDRAW();
  2358. return DDERR_INVALIDPARAMS;
  2359. }
  2360. this = this_lcl->lpGbl;
  2361. pdrv = this->lpDD;
  2362. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER ||
  2363. this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED )
  2364. {
  2365. DPF_ERR( "Invalid surface type: can't get DC" );
  2366. LEAVE_DDRAW();
  2367. return DDERR_INVALIDSURFACETYPE;
  2368. }
  2369. if( SURFACE_LOST( this_lcl ) )
  2370. {
  2371. LEAVE_DDRAW();
  2372. DPF(3,A,"Returning DDERR_SURFACELOST");
  2373. return DDERR_SURFACELOST;
  2374. }
  2375. // DC already returned for this surface? We don't need to
  2376. // check this if the surface is OWNDC. If so then we can
  2377. // hand out (the same) HDC as many times as we like.
  2378. if( ( this_lcl->dwFlags & DDRAWISURF_HASDC ) &&
  2379. !( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC ) )
  2380. {
  2381. DPF_ERR( "Can only return one DC per surface" );
  2382. LEAVE_DDRAW();
  2383. return DDERR_DCALREADYCREATED;
  2384. }
  2385. // default value is null:
  2386. *lphDC = (HDC) 0;
  2387. //
  2388. // For now, if the current surface is optimized, quit
  2389. //
  2390. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  2391. {
  2392. DPF_ERR( "It is an optimized surface" );
  2393. LEAVE_DDRAW();
  2394. return DDERR_ISOPTIMIZEDSURFACE;
  2395. }
  2396. //
  2397. // Fail if GDI doesn't understand the format
  2398. //
  2399. #ifdef WIN95
  2400. if (!LOWERTHANDDRAW7( this_lcl->lpSurfMore->lpDD_int ) )
  2401. {
  2402. LPDDPIXELFORMAT lpPf;
  2403. GET_PIXEL_FORMAT( this_lcl, this, lpPf );
  2404. if( !bIsValidDCFormat( lpPf ) )
  2405. {
  2406. DPF_ERR( "DCs cannot be used with this surface format" );
  2407. LEAVE_DDRAW();
  2408. return DDERR_INVALIDPIXELFORMAT;
  2409. }
  2410. }
  2411. #endif
  2412. }
  2413. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2414. {
  2415. DPF_ERR( "Exception encountered validating parameters" );
  2416. LEAVE_DDRAW();
  2417. return DDERR_INVALIDPARAMS;
  2418. }
  2419. /*
  2420. * If this is an OWNDC surface and we currently have an HDC
  2421. * then just use that.
  2422. */
  2423. if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC ) &&
  2424. ( 0UL != this_lcl->hDC ) )
  2425. {
  2426. /*
  2427. * We currently only support OWNDC for explicit system
  2428. * memory surfaces.
  2429. */
  2430. DDASSERT( this->dwGlobalFlags & DDRAWISURFGBL_SYSMEMREQUESTED );
  2431. *lphDC = (HDC)this_lcl->hDC;
  2432. LEAVE_DDRAW();
  2433. return DD_OK;
  2434. }
  2435. ddrval = InternalGetDC( this_int, lphDC
  2436. #ifdef WIN95
  2437. , TRUE
  2438. #endif //WIN95
  2439. );
  2440. LEAVE_DDRAW();
  2441. return ddrval;
  2442. } /* DD_Surface_GetDC */
  2443. #undef DPF_MODNAME
  2444. #define DPF_MODNAME "ReleaseDC"
  2445. /*
  2446. * DD_Surface_ReleaseDC
  2447. *
  2448. * NOTE: This function does not actually release the HDC for an OWNDC surface.
  2449. * The HDC is only toasted when the surface is finally destroyed.
  2450. */
  2451. HRESULT DDAPI DD_Surface_ReleaseDC(
  2452. LPDIRECTDRAWSURFACE lpDDSurface,
  2453. HDC hdc )
  2454. {
  2455. LPDDRAWI_DDRAWSURFACE_INT this_int;
  2456. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  2457. LPDDRAWI_DDRAWSURFACE_GBL this;
  2458. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  2459. HRESULT ddrval;
  2460. BOOL bFound;
  2461. DCINFO *pdcinfo;
  2462. DCINFO *pdcinfoPrev = NULL;
  2463. ENTER_DDRAW();
  2464. DPF(2,A,"ENTERAPI: DD_Surface_ReleaseDC");
  2465. TRY
  2466. {
  2467. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  2468. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  2469. {
  2470. LEAVE_DDRAW();
  2471. return DDERR_INVALIDOBJECT;
  2472. }
  2473. this_lcl = this_int->lpLcl;
  2474. this = this_lcl->lpGbl;
  2475. pdrv = this->lpDD;
  2476. #ifdef WIN95
  2477. if( SURFACE_LOST( this_lcl ) )
  2478. {
  2479. LEAVE_DDRAW();
  2480. return DDERR_SURFACELOST;
  2481. }
  2482. #endif
  2483. if( !(this_lcl->dwFlags & DDRAWISURF_HASDC) )
  2484. {
  2485. DPF_ERR( "No DC allocated" );
  2486. LEAVE_DDRAW();
  2487. return DDERR_NODC;
  2488. }
  2489. //
  2490. // For now, if the current surface is optimized, quit
  2491. //
  2492. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  2493. {
  2494. DPF_ERR( "It is an optimized surface" );
  2495. LEAVE_DDRAW();
  2496. return DDERR_ISOPTIMIZEDSURFACE;
  2497. }
  2498. /*
  2499. * Check for an invalid DC. Prior to DX5, we didn't check so it was
  2500. * possible to 1) release an DC that we didn't create and 2) release a
  2501. * DC that wasn't associated with the surface, causing things to get
  2502. * messed up.
  2503. */
  2504. bFound = FALSE;
  2505. for( pdcinfo = g_pdcinfoHead; pdcinfo != NULL;
  2506. pdcinfoPrev = pdcinfo, pdcinfo = pdcinfo->pdcinfoNext )
  2507. {
  2508. DDASSERT( pdcinfo->pdds_lcl != NULL );
  2509. if( hdc == pdcinfo->hdc )
  2510. {
  2511. bFound = TRUE;
  2512. if( this_lcl != pdcinfo->pdds_lcl )
  2513. {
  2514. bFound = FALSE;
  2515. }
  2516. break;
  2517. }
  2518. }
  2519. if( !bFound )
  2520. {
  2521. if( ( this_int->lpVtbl == &ddSurfaceCallbacks ) ||
  2522. ( this_int->lpVtbl == &ddSurface2Callbacks ) )
  2523. {
  2524. DPF_ERR( "********************************************************************" );
  2525. DPF_ERR( "* Invalid DC specified in ReleaseDC - not associate with the surface" );
  2526. DPF_ERR( "********************************************************************" );
  2527. }
  2528. else
  2529. {
  2530. DPF_ERR( "Invalid DC specified in ReleaseDC" );
  2531. LEAVE_DDRAW();
  2532. return DDERR_INVALIDPARAMS;
  2533. }
  2534. }
  2535. }
  2536. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2537. {
  2538. DPF_ERR( "Exception encountered validating parameters" );
  2539. LEAVE_DDRAW();
  2540. return DDERR_INVALIDPARAMS;
  2541. }
  2542. /*
  2543. * If this is an OWNDC surface then just check to make sure we
  2544. * were given back the correct HDC and return.
  2545. */
  2546. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC )
  2547. {
  2548. DDASSERT( this->dwGlobalFlags & DDRAWISURFGBL_SYSMEMREQUESTED );
  2549. if( hdc != (HDC)this_lcl->hDC )
  2550. {
  2551. DPF_ERR( "ReleaseDC called with wrong HDC for OWNDC surface" );
  2552. LEAVE_DDRAW();
  2553. return DDERR_INVALIDPARAMS;
  2554. }
  2555. LEAVE_DDRAW();
  2556. return DD_OK;
  2557. }
  2558. ddrval = InternalReleaseDC( this_lcl, hdc
  2559. #ifdef WIN95
  2560. , TRUE
  2561. #endif //WIN95
  2562. );
  2563. BUMP_SURFACE_STAMP(this);
  2564. LEAVE_DDRAW();
  2565. return ddrval;
  2566. } /* DD_Surface_ReleaseDC */
  2567. #undef DPF_MODNAME
  2568. #define DPF_MODNAME "IsLost"
  2569. /*
  2570. * DD_Surface_IsLost
  2571. */
  2572. HRESULT DDAPI DD_Surface_IsLost( LPDIRECTDRAWSURFACE lpDDSurface )
  2573. {
  2574. LPDDRAWI_DDRAWSURFACE_INT this_int;
  2575. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  2576. LPDDRAWI_DDRAWSURFACE_GBL this;
  2577. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  2578. ENTER_DDRAW();
  2579. DPF(2,A,"ENTERAPI: DD_Surface_IsLost");
  2580. TRY
  2581. {
  2582. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  2583. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  2584. {
  2585. LEAVE_DDRAW();
  2586. return DDERR_INVALIDOBJECT;
  2587. }
  2588. this_lcl = this_int->lpLcl;
  2589. this = this_lcl->lpGbl;
  2590. pdrv = this->lpDD;
  2591. if( SURFACE_LOST( this_lcl ) )
  2592. {
  2593. LEAVE_DDRAW();
  2594. return DDERR_SURFACELOST;
  2595. }
  2596. }
  2597. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2598. {
  2599. DPF_ERR( "Exception encountered validating parameters" );
  2600. LEAVE_DDRAW();
  2601. return DDERR_INVALIDPARAMS;
  2602. }
  2603. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  2604. {
  2605. if (this->dwGlobalFlags & DDRAWISURFGBL_MEMFREE)
  2606. {
  2607. LEAVE_DDRAW();
  2608. return DDERR_NOTLOADED;
  2609. }
  2610. #if 0 //Old code
  2611. if (this->dwGlobalFlags & DDRAWISURFGBL_MEMFREE)
  2612. {
  2613. LEAVE_DDRAW();
  2614. return DDERR_NOTLOADED;
  2615. }
  2616. #endif //0
  2617. }
  2618. LEAVE_DDRAW();
  2619. return DD_OK;
  2620. } /* DD_Surface_IsLost */
  2621. #undef DPF_MODNAME
  2622. #define DPF_MODNAME "Initialize"
  2623. /*
  2624. * DD_Surface_Initialize
  2625. */
  2626. HRESULT DDAPI DD_Surface_Initialize(
  2627. LPDIRECTDRAWSURFACE lpDDSurface,
  2628. LPDIRECTDRAW lpDD,
  2629. LPDDSURFACEDESC lpDDSurfaceDesc )
  2630. {
  2631. DPF(2,A,"ENTERAPI: DD_Surface_Initialize");
  2632. DPF_ERR( "DirectDrawSurface: Already initialized." );
  2633. return DDERR_ALREADYINITIALIZED;
  2634. } /* DD_Surface_Initialize */
  2635. HRESULT AtomicRestoreSurface(LPDDRAWI_DDRAWSURFACE_INT this_int)
  2636. {
  2637. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  2638. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  2639. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  2640. LPDDRAWI_DDRAWSURFACE_GBL this;
  2641. DDHAL_CREATESURFACEDATA csd;
  2642. LPDDHAL_CREATESURFACE csfn;
  2643. LPDDHAL_CREATESURFACE cshalfn;
  2644. DWORD rc;
  2645. HRESULT ddrval = DD_OK;
  2646. UINT bpp;
  2647. LONG pitch;
  2648. BOOL do_alloc=TRUE;
  2649. BOOL emulation = FALSE;
  2650. DWORD scnt;
  2651. DDSURFACEDESC2 ddsd2;
  2652. this_lcl = this_int->lpLcl;
  2653. this = this_lcl->lpGbl;
  2654. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  2655. pdrv = pdrv_lcl->lpGbl;
  2656. #ifdef WINNT
  2657. // Update DDraw handle in driver GBL object.
  2658. pdrv->hDD = pdrv_lcl->hDD;
  2659. #endif //WINNT
  2660. DDASSERT( SURFACE_LOST( this_lcl ) );
  2661. #ifndef WINNT
  2662. if( this_lcl->dwModeCreatedIn != pdrv->dwModeIndex )
  2663. #else
  2664. if (!EQUAL_DISPLAYMODE(this_lcl->lpSurfMore->dmiCreated, pdrv->dmiCurrent))
  2665. #endif
  2666. {
  2667. DPF_ERR( "Surface was not created in the current mode" );
  2668. return DDERR_WRONGMODE;
  2669. }
  2670. if(this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  2671. {
  2672. emulation = TRUE;
  2673. }
  2674. #ifdef WINNT
  2675. if (this->dwGlobalFlags & DDRAWISURFGBL_NOTIFYWHENUNLOCKED)
  2676. {
  2677. if (--dwNumLockedWhenModeSwitched == 0)
  2678. {
  2679. NotifyDriverOfFreeAliasedLocks();
  2680. }
  2681. this->dwGlobalFlags &= ~DDRAWISURFGBL_NOTIFYWHENUNLOCKED;
  2682. }
  2683. #endif
  2684. if( emulation )
  2685. {
  2686. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
  2687. {
  2688. csfn = pdrv_lcl->lpDDCB->HELDDExeBuf.CreateExecuteBuffer;
  2689. }
  2690. else
  2691. {
  2692. csfn = pdrv_lcl->lpDDCB->HELDD.CreateSurface;
  2693. }
  2694. cshalfn = csfn;
  2695. }
  2696. else
  2697. {
  2698. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
  2699. {
  2700. csfn = pdrv_lcl->lpDDCB->HALDDExeBuf.CreateExecuteBuffer;
  2701. cshalfn = pdrv_lcl->lpDDCB->cbDDExeBufCallbacks.CreateExecuteBuffer;
  2702. }
  2703. else
  2704. {
  2705. csfn = pdrv_lcl->lpDDCB->HALDD.CreateSurface;
  2706. cshalfn = pdrv_lcl->lpDDCB->cbDDCallbacks.CreateSurface;
  2707. }
  2708. }
  2709. csd.CreateSurface = cshalfn;
  2710. csd.lpDD = pdrv;
  2711. if (this_lcl->dwFlags & DDRAWISURF_IMPLICITROOT)
  2712. {
  2713. //
  2714. // This is a complex surface, so we recorded the createsurface data
  2715. // at CS time.
  2716. //
  2717. DDASSERT(this_lcl->lpSurfMore->pCreatedDDSurfaceDesc2);
  2718. DDASSERT(this_lcl->lpSurfMore->slist);
  2719. DDASSERT(this_lcl->lpSurfMore->cSurfaces);
  2720. csd.lpDDSurfaceDesc = (LPDDSURFACEDESC) this_lcl->lpSurfMore->pCreatedDDSurfaceDesc2;
  2721. csd.lplpSList = this_lcl->lpSurfMore->slist;
  2722. csd.dwSCnt = this_lcl->lpSurfMore->cSurfaces;
  2723. //
  2724. // we record the surfacedesc for any complex surface except pure mipmaps
  2725. //
  2726. if ((this_lcl->ddsCaps.dwCaps & DDSCAPS_MIPMAP) &&
  2727. ((this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_CUBEMAP)==0) )
  2728. {
  2729. DDASSERT(0 == this_lcl->lpSurfMore->pCreatedDDSurfaceDesc2);
  2730. FillDDSurfaceDesc2( this_lcl, &ddsd2 );
  2731. csd.lpDDSurfaceDesc = (LPDDSURFACEDESC) &ddsd2;
  2732. }
  2733. }
  2734. else
  2735. {
  2736. //
  2737. // this is a single non-complex surface.
  2738. // Setup the createsurface data structure to reflect it
  2739. //
  2740. FillDDSurfaceDesc2( this_lcl, &ddsd2 );
  2741. csd.lpDDSurfaceDesc = (LPDDSURFACEDESC) &ddsd2;
  2742. csd.lplpSList = &this_lcl;
  2743. csd.dwSCnt = 1;
  2744. }
  2745. //
  2746. // Note, those surfaces for whom MEMFREE (i.e. the GDI surface) is not set also pass through
  2747. // this code path and are passed to the driver's createsurface
  2748. // This is different from the process for non-dx7 drivers.
  2749. // The non-dx7 driver restore path actually has a bug: the alias for the GDI surface
  2750. // is not restored.
  2751. //
  2752. for( scnt=0; scnt<csd.dwSCnt; scnt++ )
  2753. {
  2754. if (csd.lplpSList[scnt]->lpGbl->fpVidMem != 0xFFBADBAD)
  2755. csd.lplpSList[scnt]->lpGbl->fpVidMem = 0;
  2756. if( !( csd.lplpSList[scnt]->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER ) )
  2757. {
  2758. if( csd.lplpSList[scnt]->dwFlags & DDRAWISURF_HASPIXELFORMAT )
  2759. {
  2760. bpp = csd.lplpSList[scnt]->lpGbl->ddpfSurface.dwRGBBitCount;
  2761. }
  2762. else
  2763. {
  2764. bpp = pdrv->vmiData.ddpfDisplay.dwRGBBitCount;
  2765. }
  2766. pitch = (LONG) ComputePitch( pdrv, csd.lplpSList[scnt]->ddsCaps.dwCaps,
  2767. (DWORD) csd.lplpSList[scnt]->lpGbl->wWidth, bpp );
  2768. csd.lplpSList[scnt]->lpGbl->lPitch = pitch;
  2769. }
  2770. }
  2771. #ifdef WIN95
  2772. /* Copy the VXD handle from the per process local structure to global.
  2773. * This handle will be used by DDHAL32_VidMemAlloc(), rather than creating
  2774. * a new one using GetDXVxdHandle(). The assumptions here are:
  2775. * 1) Only one process can enter createSurface(), 2) Deferred calls to
  2776. * DDHAL32_VidMemAlloc() will result in the slow path, ie getting
  2777. * the VXD handle using GetDXVxdHandle().
  2778. * (snene 2/23/98)
  2779. */
  2780. pdrv->hDDVxd = pdrv_lcl->hDDVxd;
  2781. #endif /* WIN95 */
  2782. /*
  2783. * NOTE: Different HAL entry points for execute buffers and
  2784. * conventional surfaces.
  2785. */
  2786. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
  2787. {
  2788. DOHALCALL( CreateExecuteBuffer, csfn, csd, rc, emulation );
  2789. }
  2790. else
  2791. {
  2792. DOHALCALL( CreateSurface, csfn, csd, rc, emulation );
  2793. }
  2794. #ifdef WIN95
  2795. /* Restore the handle to INVALID_HANDLE_VALUE so that non-createSurface()
  2796. * calls using DDHAL32_VidMemAlloc() or deferred calls (possibly from other
  2797. * processes) will correctly recreate the handle using GetDXVxdHandle().
  2798. * (snene 2/23/98)
  2799. */
  2800. pdrv->hDDVxd = (DWORD)INVALID_HANDLE_VALUE;
  2801. #endif /* WIN95 */
  2802. if( rc == DDHAL_DRIVER_HANDLED )
  2803. {
  2804. if( csd.ddRVal != DD_OK )
  2805. {
  2806. #ifdef DEBUG
  2807. if( emulation )
  2808. {
  2809. DPF( 1, "Restore: Emulation won't let surface be created, rc=%08lx (%ld)",
  2810. csd.ddRVal, LOWORD( csd.ddRVal ) );
  2811. }
  2812. else
  2813. {
  2814. DPF( 1, "Restore: Driver won't let surface be created, rc=%08lx (%ld)",
  2815. csd.ddRVal, LOWORD( csd.ddRVal ) );
  2816. }
  2817. #endif
  2818. return csd.ddRVal;
  2819. }
  2820. }
  2821. /*
  2822. * now, allocate any unallocated surfaces
  2823. */
  2824. ddrval = AllocSurfaceMem( pdrv_lcl, csd.lplpSList, csd.dwSCnt );
  2825. if( ddrval != DD_OK )
  2826. {
  2827. return ddrval;
  2828. }
  2829. for( scnt=0; scnt<csd.dwSCnt; scnt++ )
  2830. {
  2831. LPDDRAWI_DDRAWSURFACE_GBL_MORE lpGblMore;
  2832. csd.lplpSList[scnt]->dwFlags &= ~DDRAWISURF_INVALID;
  2833. csd.lplpSList[scnt]->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_MEMFREE;
  2834. #ifdef USE_ALIAS
  2835. /*
  2836. * If this device has heap aliases then precompute the pointer
  2837. * alias for the video memory returned at creation time. This
  2838. * is by far the most likely pointer we are going to be handing
  2839. * out at lock time so we are going to make lock a lot faster
  2840. * by precomputing this then at lock time all we need to do is
  2841. * compare the pointer we got from the driver with fpVidMem. If
  2842. * they are equal then we can just return this cached pointer.
  2843. */
  2844. lpGblMore = GET_LPDDRAWSURFACE_GBL_MORE( csd.lplpSList[scnt]->lpGbl );
  2845. if( csd.lplpSList[scnt]->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY )
  2846. {
  2847. lpGblMore->fpAliasedVidMem = GetAliasedVidMem( pdrv_lcl, csd.lplpSList[scnt],
  2848. csd.lplpSList[scnt]->lpGbl->fpVidMem );
  2849. // If we succeeded in getting an alias, cache it for future use. Also store the original
  2850. // fpVidMem to compare with before using the cached pointer to make sure the cached value
  2851. // is still valid
  2852. if (lpGblMore->fpAliasedVidMem)
  2853. lpGblMore->fpAliasOfVidMem = csd.lplpSList[scnt]->lpGbl->fpVidMem;
  2854. else
  2855. lpGblMore->fpAliasOfVidMem = 0;
  2856. }
  2857. else
  2858. {
  2859. lpGblMore->fpAliasedVidMem = 0UL;
  2860. lpGblMore->fpAliasOfVidMem = 0UL;
  2861. }
  2862. #endif /* USE_ALIAS */
  2863. #ifdef WIN95
  2864. if (csd.lplpSList[scnt]->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_PERSISTENTCONTENTS)
  2865. {
  2866. ddrval = RestoreSurfaceContents(csd.lplpSList[scnt]);
  2867. }
  2868. #endif
  2869. /*
  2870. * If a D3D texture managed surface is being restored,
  2871. * then we need to mark the corresponding system memory
  2872. * surface dirty, so that it is automatically refreshed
  2873. * prior to rendering.
  2874. */
  2875. if (SUCCEEDED(ddrval))
  2876. {
  2877. if(!IsD3DManaged(csd.lplpSList[scnt]) && csd.lplpSList[scnt]->lpSurfMore->lpRegionList)
  2878. {
  2879. MarkDirty(csd.lplpSList[scnt]);
  2880. csd.lplpSList[scnt]->lpSurfMore->lpRegionList->rdh.nCount = NUM_RECTS_IN_REGIONLIST;
  2881. }
  2882. }
  2883. }
  2884. if (
  2885. #ifdef WINNT
  2886. // on NT side, we still call CreateSurfaceEx if HW driver isn't called
  2887. emulation && this_lcl->hDDSurface &&
  2888. #endif //WINNT
  2889. TRUE
  2890. )
  2891. {
  2892. DDASSERT( pdrv_lcl == this_lcl->lpSurfMore->lpDD_lcl);
  2893. createsurfaceEx(this_lcl);
  2894. }
  2895. // If D3D Vertex Buffer, notify D3D
  2896. if ( (this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) &&
  2897. (this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
  2898. (this_lcl->lpGbl->dwUsageCount > 0) &&
  2899. (GetCurrentProcessId() == GETCURRPID()) &&
  2900. (this_lcl->lpSurfMore->lpDD_lcl->pBreakVBLock) &&
  2901. (this_lcl->lpSurfMore->lpVB) )
  2902. {
  2903. {
  2904. this_lcl->lpSurfMore->lpDD_lcl->pBreakVBLock(this_lcl->lpSurfMore->lpVB);
  2905. }
  2906. }
  2907. return ddrval;
  2908. }
  2909. #undef DPF_MODNAME
  2910. #define DPF_MODNAME "Restore"
  2911. /*
  2912. * restoreSurface
  2913. *
  2914. * restore the vidmem of one surface
  2915. */
  2916. static HRESULT restoreSurface( LPDDRAWI_DDRAWSURFACE_INT this_int )
  2917. {
  2918. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  2919. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  2920. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  2921. LPDDRAWI_DDRAWSURFACE_GBL this;
  2922. LPDDRAWI_DDRAWSURFACE_LCL slistx[1];
  2923. LPDDRAWI_DDRAWSURFACE_GBL slist[1];
  2924. DDHAL_CREATESURFACEDATA csd;
  2925. LPDDHAL_CREATESURFACE csfn;
  2926. LPDDHAL_CREATESURFACE cshalfn;
  2927. DDSURFACEDESC2 ddsd;
  2928. DWORD rc;
  2929. HRESULT ddrval;
  2930. UINT bpp;
  2931. LONG pitch = 0;
  2932. BOOL do_alloc=TRUE;
  2933. this_lcl = this_int->lpLcl;
  2934. this = this_lcl->lpGbl;
  2935. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  2936. pdrv = pdrv_lcl->lpGbl;
  2937. #ifdef WINNT
  2938. // Update DDraw handle in driver GBL object.
  2939. pdrv->hDD = pdrv_lcl->hDD;
  2940. #endif //WINNT
  2941. /*
  2942. * If we made it to here the local surface should be marked invalid.
  2943. */
  2944. DDASSERT( SURFACE_LOST( this_lcl ) );
  2945. #ifndef WINNT
  2946. if( this_lcl->dwModeCreatedIn != pdrv->dwModeIndex )
  2947. #else
  2948. if (!EQUAL_DISPLAYMODE(this_lcl->lpSurfMore->dmiCreated, pdrv->dmiCurrent))
  2949. #endif
  2950. {
  2951. DPF_ERR( "Surface was not created in the current mode" );
  2952. return DDERR_WRONGMODE;
  2953. }
  2954. #ifdef WINNT
  2955. if (this->dwGlobalFlags & DDRAWISURFGBL_NOTIFYWHENUNLOCKED)
  2956. {
  2957. if (--dwNumLockedWhenModeSwitched == 0)
  2958. {
  2959. NotifyDriverOfFreeAliasedLocks();
  2960. }
  2961. this->dwGlobalFlags &= ~DDRAWISURFGBL_NOTIFYWHENUNLOCKED;
  2962. }
  2963. #endif
  2964. DPF(5,"RestoreSurface. GDI Flag is %d, MemFree flag is %d, Primary flag is %d",
  2965. this->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE,
  2966. this->dwGlobalFlags & DDRAWISURFGBL_MEMFREE,
  2967. this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE
  2968. );
  2969. /*
  2970. * Two cases where we don't want to allocate any memory:
  2971. * -optimized surfaces
  2972. * -surfaces for which was just marked as invalid.
  2973. * If this is an optimized surface, Restore is basically a noop
  2974. * since memory is allocated at optimize time, not restore time.
  2975. */
  2976. if(( (!(this->dwGlobalFlags & DDRAWISURFGBL_MEMFREE))
  2977. #ifdef WINNT
  2978. /*
  2979. * We need to call CreateSurface HAL callback on NT
  2980. */
  2981. && (((this->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE) == 0)
  2982. || (this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY))
  2983. #endif
  2984. ) || (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED) )
  2985. {
  2986. this_lcl->dwFlags &= ~DDRAWISURF_INVALID;
  2987. ddrval = DD_OK;
  2988. do_alloc = FALSE;
  2989. }
  2990. else
  2991. {
  2992. slistx[0] = this_lcl;
  2993. slist[0] = this;
  2994. if (this->fpVidMem != 0xFFBADBAD)
  2995. this->fpVidMem = 0;
  2996. // 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  2997. DPF( 4, "Restoring 0x%p", this_lcl );
  2998. /*
  2999. * Execute buffers are handled very differently
  3000. * from ordinary surfaces. They have no width and
  3001. * height and store a linear size instead of a pitch.
  3002. * Note, the linear size includes any alignment
  3003. * requirements (added by ComputePitch on surface
  3004. * creation) so we do not recompute the pitch at this
  3005. * point. The surface structure as it stands is all we
  3006. * need.
  3007. */
  3008. if( !( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER ) )
  3009. {
  3010. if( this_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT )
  3011. {
  3012. bpp = this->ddpfSurface.dwRGBBitCount;
  3013. }
  3014. else
  3015. {
  3016. bpp = pdrv->vmiData.ddpfDisplay.dwRGBBitCount;
  3017. }
  3018. pitch = (LONG) ComputePitch( pdrv, this_lcl->ddsCaps.dwCaps,
  3019. (DWORD) this->wWidth, bpp );
  3020. this->lPitch = pitch;
  3021. }
  3022. /*
  3023. * first, give the driver an opportunity to create it...
  3024. */
  3025. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
  3026. {
  3027. cshalfn = pdrv_lcl->lpDDCB->cbDDExeBufCallbacks.CreateExecuteBuffer;
  3028. csfn = pdrv_lcl->lpDDCB->HALDDExeBuf.CreateExecuteBuffer;
  3029. }
  3030. else
  3031. {
  3032. cshalfn = pdrv_lcl->lpDDCB->cbDDCallbacks.CreateSurface;
  3033. csfn = pdrv_lcl->lpDDCB->HALDD.CreateSurface;
  3034. }
  3035. if( cshalfn != NULL )
  3036. {
  3037. DPF(4,"HAL CreateSurface to be called");
  3038. /*
  3039. * construct a new surface description
  3040. */
  3041. FillDDSurfaceDesc2( this_lcl, &ddsd );
  3042. /*
  3043. * call the driver
  3044. */
  3045. csd.CreateSurface = cshalfn;
  3046. csd.lpDD = pdrv;
  3047. csd.lpDDSurfaceDesc = (LPDDSURFACEDESC)&ddsd;
  3048. csd.lplpSList = slistx;
  3049. csd.dwSCnt = 1;
  3050. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
  3051. {
  3052. DOHALCALL( CreateExecuteBuffer, csfn, csd, rc, FALSE );
  3053. }
  3054. else
  3055. {
  3056. DOHALCALL( CreateSurface, csfn, csd, rc, FALSE );
  3057. }
  3058. if( rc == DDHAL_DRIVER_HANDLED )
  3059. {
  3060. if( csd.ddRVal != DD_OK )
  3061. {
  3062. do_alloc = FALSE;
  3063. ddrval = csd.ddRVal;
  3064. }
  3065. }
  3066. }
  3067. /*
  3068. * On NT, we will hit this code path for the GDI surface.
  3069. * We could probably just not do the alloc, but to avoid hard-to-test code paths
  3070. * I'll let the AllocSurfaceMem trivially allocate for the GDI surface.
  3071. */
  3072. if( do_alloc )
  3073. {
  3074. /*
  3075. * allocate the memory now...
  3076. */
  3077. ddrval = AllocSurfaceMem( pdrv_lcl, slistx, 1 );
  3078. if( ddrval != DD_OK )
  3079. {
  3080. this->lPitch = pitch;
  3081. DPF(2,"Moving to system memory");
  3082. ddrval = MoveToSystemMemory( this_int, FALSE, TRUE );
  3083. }
  3084. if( ddrval == DD_OK )
  3085. {
  3086. this_lcl->dwFlags &= ~DDRAWISURF_INVALID;
  3087. this->dwGlobalFlags &= ~DDRAWISURFGBL_MEMFREE;
  3088. }
  3089. }
  3090. }
  3091. #ifdef USE_ALIAS
  3092. {
  3093. LPDDRAWI_DDRAWSURFACE_GBL_MORE lpGblMore;
  3094. lpGblMore = GET_LPDDRAWSURFACE_GBL_MORE( this );
  3095. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY )
  3096. {
  3097. lpGblMore->fpAliasedVidMem = GetAliasedVidMem( pdrv_lcl, this_lcl, this_lcl->lpGbl->fpVidMem );
  3098. // If we succeeded in getting an alias, cache it for future use. Also store the original
  3099. // fpVidMem to compare with before using the cached pointer to make sure the cached value
  3100. // is still valid
  3101. if (lpGblMore->fpAliasedVidMem)
  3102. lpGblMore->fpAliasOfVidMem = this_lcl->lpGbl->fpVidMem;
  3103. else
  3104. lpGblMore->fpAliasOfVidMem = 0;
  3105. }
  3106. else
  3107. {
  3108. lpGblMore->fpAliasedVidMem = 0UL;
  3109. lpGblMore->fpAliasOfVidMem = 0UL;
  3110. }
  3111. }
  3112. #endif /* USE_ALIAS */
  3113. #ifdef WIN95
  3114. if (SUCCEEDED(ddrval) && (this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_PERSISTENTCONTENTS))
  3115. {
  3116. ddrval = RestoreSurfaceContents(this_lcl);
  3117. }
  3118. #endif
  3119. /*
  3120. * If a D3D texture managed surface is being restored,
  3121. * then we need to mark the corresponding system memory
  3122. * surface dirty, so that it is automatically refreshed
  3123. * prior to rendering.
  3124. */
  3125. if(!IsD3DManaged(this_lcl) && this_lcl->lpSurfMore->lpRegionList)
  3126. {
  3127. MarkDirty(this_lcl);
  3128. this_lcl->lpSurfMore->lpRegionList->rdh.nCount = NUM_RECTS_IN_REGIONLIST;
  3129. }
  3130. return ddrval;
  3131. } /* restoreSurface */
  3132. /*
  3133. * restoreAttachments
  3134. *
  3135. * restore all attachments to a surface
  3136. */
  3137. static HRESULT restoreAttachments( LPDDRAWI_DDRAWSURFACE_LCL this_lcl )
  3138. {
  3139. LPATTACHLIST pattachlist;
  3140. LPDDRAWI_DDRAWSURFACE_INT curr_int;
  3141. LPDDRAWI_DDRAWSURFACE_LCL curr_lcl;
  3142. LPDDRAWI_DDRAWSURFACE_GBL curr;
  3143. HRESULT ddrval;
  3144. pattachlist = this_lcl->lpAttachList;
  3145. while( pattachlist != NULL )
  3146. {
  3147. curr_int = pattachlist->lpIAttached;
  3148. curr_lcl = curr_int->lpLcl;
  3149. curr = curr_lcl->lpGbl;
  3150. if( curr_lcl->dwFlags & DDRAWISURF_IMPLICITCREATE )
  3151. {
  3152. ddrval = restoreSurface( curr_int );
  3153. if( ddrval != DD_OK )
  3154. {
  3155. DPF( 2, "restoreSurface failed: %08lx (%ld)", ddrval, LOWORD( ddrval ) );
  3156. return ddrval;
  3157. }
  3158. ddrval = restoreAttachments( curr_lcl );
  3159. if( ddrval != DD_OK )
  3160. {
  3161. DPF( 2, "restoreAttachents failed: %08lx (%ld)", ddrval, LOWORD( ddrval ) );
  3162. return ddrval;
  3163. }
  3164. }
  3165. pattachlist = pattachlist->lpLink;
  3166. }
  3167. return DD_OK;
  3168. } /* restoreAttachments */
  3169. /*
  3170. * DD_Surface_Restore
  3171. *
  3172. * Restore an invalidated surface
  3173. */
  3174. #undef DPF_MODNAME
  3175. #define DPF_MODNAME "DD_Surface_Restore"
  3176. HRESULT DDAPI DD_Surface_Restore( LPDIRECTDRAWSURFACE lpDDSurface )
  3177. {
  3178. LPDDRAWI_DDRAWSURFACE_INT this_int;
  3179. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  3180. LPDDRAWI_DDRAWSURFACE_GBL this;
  3181. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  3182. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  3183. HRESULT ddrval;
  3184. BOOL has_excl;
  3185. BOOL excl_exists;
  3186. DDSURFACEDESC2 ddsd;
  3187. ENTER_DDRAW();
  3188. DPF(2,A,"ENTERAPI: DD_Surface_Restore");
  3189. /* DPF_ENTERAPI(lpDDSurface); */
  3190. /*
  3191. * validate parameters
  3192. */
  3193. TRY
  3194. {
  3195. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  3196. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  3197. {
  3198. DPF_ERR( "Invalid surface pointer" );
  3199. LEAVE_DDRAW();
  3200. DPF_APIRETURNS(DDERR_INVALIDOBJECT);
  3201. return DDERR_INVALIDOBJECT;
  3202. }
  3203. this_lcl = this_int->lpLcl;
  3204. this = this_lcl->lpGbl;
  3205. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  3206. pdrv = pdrv_lcl->lpGbl;
  3207. if( (this_lcl->dwFlags & DDRAWISURF_ISFREE) )
  3208. {
  3209. LEAVE_DDRAW();
  3210. DPF_APIRETURNS( DDERR_INVALIDOBJECT);
  3211. return DDERR_INVALIDOBJECT;
  3212. }
  3213. #ifdef WIN95
  3214. if( ( pdrv_lcl->dwAppHackFlags & DDRAW_APPCOMPAT_SCREENSAVER ) &&
  3215. ( pdrv_lcl->dwLocalFlags & DDRAWILCL_POWEREDDOWN ) )
  3216. {
  3217. LEAVE_DDRAW();
  3218. return DDERR_SURFACELOST;
  3219. }
  3220. #endif
  3221. if( !SURFACE_LOST( this_lcl ) )
  3222. {
  3223. LEAVE_DDRAW();
  3224. DPF(2,"Returning DD_OK since not lost");
  3225. return DD_OK;;
  3226. }
  3227. }
  3228. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  3229. {
  3230. DPF_ERR( "Exception encountered validating parameters" );
  3231. LEAVE_DDRAW();
  3232. DPF_APIRETURNS(DDERR_INVALIDPARAMS);
  3233. return DDERR_INVALIDPARAMS;
  3234. }
  3235. // For now, disallow it for optimized surfaces
  3236. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  3237. {
  3238. DPF_ERR( "It is an optimized surface" );
  3239. LEAVE_DDRAW();
  3240. return DDERR_ISOPTIMIZEDSURFACE;
  3241. }
  3242. /*
  3243. * don't allow restoration of implicit surfaces
  3244. */
  3245. if( (this_lcl->dwFlags & DDRAWISURF_IMPLICITCREATE) )
  3246. {
  3247. DPF_ERR( "Can't restore implicitly created surfaces" );
  3248. LEAVE_DDRAW();
  3249. DPF_APIRETURNS(DDERR_IMPLICITLYCREATED);
  3250. return DDERR_IMPLICITLYCREATED;
  3251. }
  3252. /*
  3253. * make sure we are in the same mode the surface was created in
  3254. */
  3255. #ifdef WIN95
  3256. if( pdrv->dwModeIndex != this_lcl->dwModeCreatedIn )
  3257. #else
  3258. if (!EQUAL_DISPLAYMODE(this_lcl->lpSurfMore->dmiCreated, pdrv->dmiCurrent))
  3259. #endif
  3260. {
  3261. DPF(1, "Cannot restore surface, not in original mode");
  3262. LEAVE_DDRAW();
  3263. DPF_APIRETURNS(DDERR_WRONGMODE);
  3264. return DDERR_WRONGMODE;
  3265. }
  3266. /*
  3267. * If the device has an exclusive owner, we must not restore any surface
  3268. * in the device's video memory unless we are the device's exclusive owner.
  3269. * DDERR_WRONGMODE is returned to avoid regression problems by mimicking
  3270. * Restore() behavior in the case in which the device's exclusive owner has
  3271. * changed to a mode that's different from the one the surface was created in.
  3272. *
  3273. * We also handle the case where an exclusive mode app tries to restore
  3274. * surfaces while no one has exclusive mode (for example, when the app is
  3275. * minimized). The restore would commonly fail due to the app running in a
  3276. * different display mode from the current display mode. However, if the
  3277. * is running in the same display mode, we would previously allow the
  3278. * restore to succeed. As mentioned above, we'll return DDERR_WRONGMODE,
  3279. * to avoid regression problems, even though DDERR_NOEXCLUSIVEMODE would
  3280. * make more sense.
  3281. */
  3282. CheckExclusiveMode(this_lcl->lpSurfMore->lpDD_lcl, &excl_exists , &has_excl, FALSE,
  3283. NULL, FALSE);
  3284. if((excl_exists && !has_excl) ||
  3285. (!excl_exists && (pdrv_lcl->dwLocalFlags & DDRAWILCL_HASEXCLUSIVEMODE)))
  3286. {
  3287. DPF_ERR("Another app has assumed exclusive ownership of device");
  3288. LEAVE_DDRAW();
  3289. DPF_APIRETURNS(DDERR_WRONGMODE);
  3290. return DDERR_WRONGMODE;
  3291. }
  3292. /*
  3293. * make sure we are not in the middle of a mode change, in which case
  3294. * DirectDraw is confused about the mode it is in
  3295. */
  3296. if( pdrv->dwFlags & DDRAWI_CHANGINGMODE )
  3297. {
  3298. /*
  3299. * We really should fail this altogether since we are only
  3300. * asking for trouble, but we fear that regression risk might
  3301. * be worse, so we only fail this for a surface 3 interface.
  3302. * In the cases we do not fail, we handle the Blt case by not
  3303. * doing anything, but we're still vulnerable to Lock and GetDC.
  3304. */
  3305. if( !( ( this_int->lpVtbl == &ddSurfaceCallbacks ) ||
  3306. ( this_int->lpVtbl == &ddSurface2Callbacks ) ) )
  3307. {
  3308. DPF_ERR("Cannot restore surface, in the middle of a mode change");
  3309. LEAVE_DDRAW();
  3310. DPF_APIRETURNS(DDERR_WRONGMODE);
  3311. return DDERR_WRONGMODE;
  3312. }
  3313. else
  3314. {
  3315. /*
  3316. * Always output a message here. This serves two purposes:
  3317. * 1) Let us no why a stress failure occured,
  3318. * 2) Inform developers why they are seeing bugs.
  3319. */
  3320. OutputDebugString( "WARNING: Restoring surface during a mode change!\n" );
  3321. }
  3322. }
  3323. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE )
  3324. {
  3325. /*
  3326. * are we the process with exclusive mode?
  3327. */
  3328. if( excl_exists && !has_excl )
  3329. {
  3330. DPF_ERR( "Cannot restore primary surface, not exclusive owner" );
  3331. LEAVE_DDRAW();
  3332. DPF_APIRETURNS(DDERR_NOEXCLUSIVEMODE);
  3333. return DDERR_NOEXCLUSIVEMODE;
  3334. }
  3335. else if( !excl_exists )
  3336. {
  3337. /*
  3338. * no exclusive mode
  3339. */
  3340. FillDDSurfaceDesc2( this_lcl, &ddsd );
  3341. if( !MatchPrimary( pdrv, &ddsd ) )
  3342. {
  3343. DPF_ERR( "Can't restore primary, incompatible with current primary" );
  3344. LEAVE_DDRAW();
  3345. DPF_APIRETURNS(DDERR_INCOMPATIBLEPRIMARY);
  3346. return DDERR_INCOMPATIBLEPRIMARY;
  3347. }
  3348. }
  3349. /*
  3350. * otherwise, it is OK to restore primary
  3351. */
  3352. #ifdef WINNT
  3353. /*
  3354. * Ctrl-Alt-Del on NT gives us no notice and so no FlipToGDISurface has been done.
  3355. * This means that the DDSCAPS_PRIMARY and DDRAWISURFGBL_ISGDISURFACE tags may
  3356. * not be on the same surface object (which is what FlipToGDISurface does).
  3357. * The NT user-side code expects that DDSCAPS_PRIMARY means DDRAWISURFGBL_ISGDISURFACE
  3358. * which it normally would, and should (i.e. GDI's surface should be the visible surface
  3359. * immediately before a switch back to a fullscreen app.)
  3360. * We force this situation here by running the attachment list for a primary and
  3361. * finding the GDI surface, then doing a surface-object-only flip (i.e. exchange
  3362. * these two objects' MEMFREE status, dwReserved and Kernel handle fields.
  3363. * I shall be extra paranoid and only attempt this if the primary doesn't have
  3364. * IS_GDISURFACE set. It should be safe to assume that the only way the GDI and
  3365. * PRIMARY flags got mismatched is via a flip that wasn't undone.
  3366. * This situation should never happen for an emulated primary (since Flip drops
  3367. * out early before doing the flag rotation).
  3368. */
  3369. if ( !( this->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE ) )
  3370. {
  3371. /*
  3372. * Run the attachments looking for the surface with the GDI flag
  3373. */
  3374. LPDDRAWI_DDRAWSURFACE_INT curr_int;
  3375. DDASSERT( (this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) == 0);
  3376. DDASSERT(this_lcl->lpAttachList);
  3377. curr_int = FindAttachedFlip(this_int);
  3378. while( curr_int->lpLcl != this_lcl )
  3379. {
  3380. if( curr_int->lpLcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE )
  3381. {
  3382. /*
  3383. * Found the GDI tagged surface
  3384. */
  3385. break;
  3386. }
  3387. DDASSERT(curr_int->lpLcl->lpAttachList);
  3388. curr_int = FindAttachedFlip(curr_int);
  3389. }
  3390. if (curr_int->lpLcl != this_lcl)
  3391. {
  3392. /*
  3393. * curr_lcl != this_lcl means we found an attached surface with GDI set,
  3394. * so pseudo-flip them.
  3395. */
  3396. DWORD memfreeflag;
  3397. ULONG_PTR reserved,handle;
  3398. LPDDRAWI_DDRAWSURFACE_GBL curr_gbl = curr_int->lpLcl->lpGbl;
  3399. DDASSERT(0 == curr_gbl->fpVidMem);
  3400. DDASSERT(NULL == curr_gbl->lpVidMemHeap);
  3401. /*
  3402. * The primary (this) needs to get the GDI flag set, and the other
  3403. * (the old GDI surface) needs to get GDI reset.
  3404. */
  3405. curr_gbl->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
  3406. this->dwGlobalFlags |= DDRAWISURFGBL_ISGDISURFACE;
  3407. /*
  3408. * The two surfaces must trade their MEMFREE status.
  3409. */
  3410. memfreeflag = curr_gbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
  3411. curr_gbl->dwGlobalFlags = (curr_gbl->dwGlobalFlags & ~DDRAWISURFGBL_MEMFREE)
  3412. | (this->dwGlobalFlags & DDRAWISURFGBL_MEMFREE);
  3413. this->dwGlobalFlags = (this->dwGlobalFlags & ~DDRAWISURFGBL_MEMFREE)
  3414. | memfreeflag;
  3415. /*
  3416. * Swap reserved field and kernel handle
  3417. */
  3418. reserved = curr_gbl->dwReserved1;
  3419. curr_gbl->dwReserved1 = this->dwReserved1;
  3420. this->dwReserved1 = reserved;
  3421. handle = curr_int->lpLcl->hDDSurface;
  3422. curr_int->lpLcl->hDDSurface = this_lcl->hDDSurface;
  3423. this_lcl->hDDSurface = handle;
  3424. }
  3425. }
  3426. #endif
  3427. } /* if primary surface */
  3428. if (NULL == pdrv->lpDDCBtmp->HALDDMiscellaneous2.CreateSurfaceEx)
  3429. {
  3430. //
  3431. // Non DX7 driver gets piece-meal restore
  3432. //
  3433. /*
  3434. * restore this surface
  3435. */
  3436. ddrval = restoreSurface( this_int );
  3437. if( ddrval != DD_OK )
  3438. {
  3439. DPF( 1, "restoreSurface failed, rc=%08lx (%ld)", ddrval, LOWORD( ddrval ) );
  3440. LEAVE_DDRAW();
  3441. DPF_APIRETURNS(ddrval);
  3442. return ddrval;
  3443. }
  3444. /*
  3445. * restore all surfaces in an implicit chain
  3446. */
  3447. if( this_lcl->dwFlags & DDRAWISURF_IMPLICITROOT )
  3448. {
  3449. ddrval = restoreAttachments( this_lcl );
  3450. }
  3451. }
  3452. else
  3453. {
  3454. //
  3455. // DX7 driver gets atomic restore
  3456. //
  3457. ddrval = AtomicRestoreSurface(this_int);
  3458. }
  3459. LEAVE_DDRAW();
  3460. DPF_APIRETURNS(ddrval);
  3461. return ddrval;
  3462. } /* DD_Surface_Restore */
  3463. /*
  3464. * MoveToSystemMemory
  3465. *
  3466. * if possible, deallocate the video memory associated with this surface
  3467. * and allocate system memory instead. This is useful for drivers which have
  3468. * hardware flip and video memory capability but no blt capability. By
  3469. * moving the offscreen surfaces to system memory, we reduce the lock overhead
  3470. * and also reduce the bus bandwidth requirements.
  3471. *
  3472. * This function assumes the DRIVER LOCK HAS BEEN TAKEN.
  3473. */
  3474. HRESULT MoveToSystemMemory(
  3475. LPDDRAWI_DDRAWSURFACE_INT this_int,
  3476. BOOL hasvram,
  3477. BOOL use_full_lock )
  3478. {
  3479. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  3480. LPDDRAWI_DDRAWSURFACE_GBL this;
  3481. ULONG_PTR newreserved;
  3482. ULONG_PTR newreserved_lcl;
  3483. // LPVOID newvidmemheap;
  3484. LONG newpitch;
  3485. FLATPTR newvidmem;
  3486. DWORD newddscaps;
  3487. ULONG_PTR newhddsurface;
  3488. ULONG_PTR savereserved;
  3489. ULONG_PTR savereserved_lcl;
  3490. LPVOID savevidmemheap;
  3491. LONG savepitch;
  3492. FLATPTR savevidmem;
  3493. DWORD saveddscaps;
  3494. ULONG_PTR savehddsurface;
  3495. DDHAL_CREATESURFACEDATA csd;
  3496. DWORD rc;
  3497. DDSURFACEDESC2 ddsd;
  3498. LPDDRAWI_DDRAWSURFACE_LCL slistx;
  3499. LPBYTE lpvidmem;
  3500. LPBYTE lpsysmem;
  3501. DWORD bytecount;
  3502. DWORD line;
  3503. HRESULT ddrval;
  3504. LPVOID pbits;
  3505. WORD wHeight;
  3506. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  3507. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  3508. this_lcl = this_int->lpLcl;
  3509. this = this_lcl->lpGbl;
  3510. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  3511. pdrv = pdrv_lcl->lpGbl;
  3512. //
  3513. // We don't move to system memory on DX7 drivers, since this process doesn't
  3514. // inform them of the new sysmem surface
  3515. //
  3516. if (NULL != pdrv->lpDDCBtmp->HALDDMiscellaneous2.CreateSurfaceEx)
  3517. {
  3518. //this error code never percolates up to apps.
  3519. return DDERR_GENERIC;
  3520. }
  3521. #ifdef WINNT
  3522. {
  3523. // Update DDraw handle in driver GBL object.
  3524. pdrv->hDD = pdrv_lcl->hDD;
  3525. }
  3526. #endif //WINNT
  3527. if(hasvram && SURFACE_LOST( this_lcl ) )
  3528. {
  3529. return DDERR_SURFACELOST;
  3530. }
  3531. if( ( this_lcl->lpAttachList != NULL ) ||
  3532. ( this_lcl->lpAttachListFrom != NULL ) ||
  3533. ( this->dwUsageCount != 0 ) ||
  3534. ( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) ||
  3535. ( this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY ) ||
  3536. ( this_lcl->dwFlags & (DDRAWISURF_HASPIXELFORMAT|DDRAWISURF_PARTOFPRIMARYCHAIN) ) )
  3537. {
  3538. /*
  3539. * can't move it to system memory
  3540. */
  3541. // 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  3542. DPF( 2, "Unable to move surface 0x%p to system memory", this_int );
  3543. #ifdef DEBUG
  3544. if( this_lcl->lpAttachList != NULL )
  3545. {
  3546. DPF( 4, "AttachList is non-NULL" );
  3547. }
  3548. if( this_lcl->lpAttachListFrom != NULL )
  3549. {
  3550. DPF( 4, "AttachListFrom is non-NULL" );
  3551. }
  3552. if( this->dwUsageCount != 0 )
  3553. {
  3554. DPF( 4, "dwusageCount=%ld", this->dwUsageCount );
  3555. }
  3556. if( this_lcl->dwFlags & DDRAWISURF_PARTOFPRIMARYCHAIN )
  3557. {
  3558. DPF( 4, "part of the primary chain" );
  3559. }
  3560. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY )
  3561. {
  3562. DPF( 4, "Is a hardware overlay" );
  3563. }
  3564. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
  3565. {
  3566. DPF( 4, "Is already in system memory" );
  3567. }
  3568. if( this_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT )
  3569. {
  3570. DPF( 4, "Has a different pixel format" );
  3571. }
  3572. #endif
  3573. return DDERR_GENERIC;
  3574. }
  3575. /*
  3576. * save the current state just in case the HEL
  3577. * CreateSurface call fails.
  3578. */
  3579. savevidmem = this->fpVidMem;
  3580. savevidmemheap = this->lpVidMemHeap;
  3581. savereserved = this->dwReserved1;
  3582. savereserved_lcl= this_lcl->dwReserved1;
  3583. savepitch = this->lPitch;
  3584. saveddscaps = this_lcl->ddsCaps.dwCaps;
  3585. savehddsurface = this_lcl->hDDSurface;
  3586. /*
  3587. * lock the vram
  3588. */
  3589. if( hasvram )
  3590. {
  3591. while( 1 )
  3592. {
  3593. if( use_full_lock )
  3594. {
  3595. ddsd.dwSize = sizeof( ddsd );
  3596. ddrval = DD_Surface_Lock(
  3597. (LPDIRECTDRAWSURFACE) this_int,
  3598. NULL,
  3599. (LPDDSURFACEDESC)&ddsd,
  3600. 0,
  3601. NULL );
  3602. if( ddrval == DD_OK )
  3603. {
  3604. pbits = ddsd.lpSurface;
  3605. }
  3606. }
  3607. else
  3608. {
  3609. ddrval = InternalLock( this_lcl, &pbits, NULL, 0 );
  3610. }
  3611. if( ddrval == DDERR_WASSTILLDRAWING )
  3612. {
  3613. continue;
  3614. }
  3615. break;
  3616. }
  3617. if( ddrval != DD_OK )
  3618. {
  3619. DPF( 0, "*** MoveToSystemMemory: Lock failed! rc = %08lx", ddrval );
  3620. return ddrval;
  3621. }
  3622. }
  3623. /*
  3624. * mark this object as system memory. NT needs this done before the
  3625. * CreateSurface HEL call, otherwise it gets confused about whether
  3626. * it's supposed to be a video memory or system memory surface.
  3627. */
  3628. this_lcl->ddsCaps.dwCaps &= ~(DDSCAPS_VIDEOMEMORY|DDSCAPS_NONLOCALVIDMEM|DDSCAPS_LOCALVIDMEM);
  3629. this_lcl->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
  3630. /*
  3631. * set up for a call to the HEL
  3632. */
  3633. FillDDSurfaceDesc2( this_lcl, &ddsd );
  3634. slistx = this_lcl;
  3635. csd.lpDD = this->lpDD;
  3636. csd.lpDDSurfaceDesc = (LPDDSURFACEDESC)&ddsd;
  3637. csd.lplpSList = &slistx;
  3638. csd.dwSCnt = 1;
  3639. rc = this_lcl->lpSurfMore->lpDD_lcl->lpDDCB->HELDD.CreateSurface( &csd );
  3640. if( (rc == DDHAL_DRIVER_NOTHANDLED) || (csd.ddRVal != DD_OK) )
  3641. {
  3642. this->fpVidMem = savevidmem;
  3643. this->lpVidMemHeap = savevidmemheap;
  3644. this->lPitch = savepitch;
  3645. this->dwReserved1 = savereserved;
  3646. this_lcl->dwReserved1 = savereserved_lcl;
  3647. this_lcl->ddsCaps.dwCaps = saveddscaps;
  3648. this_lcl->hDDSurface = savehddsurface;
  3649. if( hasvram )
  3650. {
  3651. if( use_full_lock )
  3652. {
  3653. DD_Surface_Unlock( (LPDIRECTDRAWSURFACE) this_int, NULL );
  3654. }
  3655. else
  3656. {
  3657. InternalUnlock( this_lcl, NULL, NULL, 0 );
  3658. }
  3659. }
  3660. DPF( 0, "*** MoveToSystemMemory: HEL CreateSurface failed! rc = %08lx", csd.ddRVal );
  3661. return csd.ddRVal;
  3662. }
  3663. /*
  3664. * copy the bits from vidmem to systemmem
  3665. */
  3666. if( hasvram )
  3667. {
  3668. lpvidmem = (LPBYTE)pbits;
  3669. lpsysmem = (LPBYTE)this_lcl->lpGbl->fpVidMem;
  3670. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
  3671. {
  3672. bytecount = this->dwLinearSize;
  3673. wHeight = 1;
  3674. }
  3675. else
  3676. {
  3677. bytecount = this->wWidth * ddsd.ddpfPixelFormat.dwRGBBitCount / 8;
  3678. wHeight = this->wHeight;
  3679. }
  3680. TRY
  3681. {
  3682. for( line=0; line<wHeight; line++)
  3683. {
  3684. memcpy( lpsysmem, lpvidmem, bytecount );
  3685. lpvidmem += savepitch;
  3686. lpsysmem += this->lPitch;
  3687. }
  3688. }
  3689. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  3690. {
  3691. DPF_ERR( "Exception encountered moving from video to system memory" );
  3692. this->fpVidMem = savevidmem;
  3693. this->lpVidMemHeap = savevidmemheap;
  3694. this->lPitch = savepitch;
  3695. this->dwReserved1 = savereserved;
  3696. this_lcl->dwReserved1 = savereserved_lcl;
  3697. this_lcl->ddsCaps.dwCaps = saveddscaps;
  3698. this_lcl->hDDSurface = savehddsurface;
  3699. if( hasvram )
  3700. {
  3701. if( use_full_lock )
  3702. {
  3703. DD_Surface_Unlock( (LPDIRECTDRAWSURFACE) this_int, NULL );
  3704. }
  3705. else
  3706. {
  3707. InternalUnlock( this_lcl, NULL, NULL, 0 );
  3708. }
  3709. }
  3710. return DDERR_EXCEPTION;
  3711. }
  3712. }
  3713. /*
  3714. * it worked, temporarily reset values and unlock surface
  3715. */
  3716. if( hasvram )
  3717. {
  3718. newvidmem = this->fpVidMem;
  3719. // newvidmemheap = this->lpVidMemHeap; THIS IS NOT SET BY THE HEL
  3720. newreserved = this->dwReserved1;
  3721. newreserved_lcl = this_lcl->dwReserved1;
  3722. newpitch = this->lPitch;
  3723. newddscaps = this_lcl->ddsCaps.dwCaps;
  3724. newhddsurface = this_lcl->hDDSurface;
  3725. this->fpVidMem = savevidmem;
  3726. this->lpVidMemHeap = savevidmemheap;
  3727. this->lPitch = savepitch;
  3728. this->dwReserved1 = savereserved;
  3729. this_lcl->dwReserved1 = savereserved_lcl;
  3730. this_lcl->ddsCaps.dwCaps = saveddscaps;
  3731. this_lcl->hDDSurface = savehddsurface;
  3732. if( use_full_lock )
  3733. {
  3734. DD_Surface_Unlock( (LPDIRECTDRAWSURFACE) this_int, NULL );
  3735. }
  3736. else
  3737. {
  3738. InternalUnlock( this_lcl, NULL, NULL, 0 );
  3739. }
  3740. // Free the video memory, allow the driver to destroy the surface
  3741. DestroySurface( this_lcl );
  3742. // We just freed the memory but system memory surfaces never have
  3743. // this flag set so unset it.
  3744. this_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_MEMFREE;
  3745. this->fpVidMem = newvidmem;
  3746. // this->lpVidMemHeap = newvidmemheap;
  3747. this->lpVidMemHeap = NULL; // should be NULL after HEL
  3748. this->lPitch = newpitch;
  3749. this->dwReserved1 = newreserved;
  3750. this_lcl->dwReserved1 = newreserved_lcl;
  3751. this_lcl->ddsCaps.dwCaps = newddscaps;
  3752. this_lcl->hDDSurface = newhddsurface;
  3753. }
  3754. /*
  3755. * the hel needs to know we touched the memory
  3756. */
  3757. if( use_full_lock )
  3758. {
  3759. DD_Surface_Lock( (LPDIRECTDRAWSURFACE) this_int, NULL,
  3760. (LPDDSURFACEDESC)&ddsd, 0, NULL );
  3761. DD_Surface_Unlock( (LPDIRECTDRAWSURFACE) this_int, NULL );
  3762. }
  3763. else
  3764. {
  3765. InternalLock( this_lcl, &pbits, NULL, 0 );
  3766. InternalUnlock( this_lcl, NULL, NULL, 0 );
  3767. }
  3768. // 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  3769. DPF( 2, "Moved surface 0x%p to system memory", this_int );
  3770. return DD_OK;
  3771. } /* MoveToSystemMemory */
  3772. /*
  3773. * invalidateSurface
  3774. *
  3775. * invalidate one surface
  3776. */
  3777. void invalidateSurface( LPDDRAWI_DDRAWSURFACE_LCL this_lcl )
  3778. {
  3779. if( !SURFACE_LOST( this_lcl ) )
  3780. {
  3781. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY )
  3782. {
  3783. #ifdef USE_ALIAS
  3784. /*
  3785. * If the surface is locked then break the locks now.
  3786. * When a broken lock is finally unlocked by the API the
  3787. * driver is not called. So we get Create->Lock->Destroy
  3788. * rather than Create->Lock->Destroy->Unlock. Thus, drivers
  3789. * must be able to cope with Destroy undo any pending locks
  3790. * at the driver level but they should be able to cope with
  3791. * this as it could happen even before the alias changes.
  3792. */
  3793. if(!(this_lcl->dwFlags & DDRAWISURF_DRIVERMANAGED) ||
  3794. (this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_DONOTPERSIST))
  3795. {
  3796. if( this_lcl->lpGbl->dwUsageCount > 0)
  3797. {
  3798. // 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  3799. DPF( 4, "Breaking locks held on the surface 0x%p", this_lcl );
  3800. BreakSurfaceLocks( this_lcl->lpGbl );
  3801. }
  3802. }
  3803. #endif /* USE_ALIAS */
  3804. if (!(this_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_SYSMEMEXECUTEBUFFER))
  3805. {
  3806. if((this_lcl->dwFlags & DDRAWISURF_DRIVERMANAGED) &&
  3807. !(this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_DONOTPERSIST))
  3808. {
  3809. LooseManagedSurface( this_lcl );
  3810. return;
  3811. }
  3812. else
  3813. DestroySurface( this_lcl );
  3814. }
  3815. }
  3816. if( (!(this_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_SYSMEMREQUESTED) ||
  3817. (this_lcl->dwFlags & DDRAWISURF_PARTOFPRIMARYCHAIN) ) &&
  3818. (!(this_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_SYSMEMEXECUTEBUFFER)) )
  3819. {
  3820. this_lcl->dwFlags |= DDRAWISURF_INVALID;
  3821. BUMP_SURFACE_STAMP(this_lcl->lpGbl);
  3822. }
  3823. }
  3824. } /* invalidateSurface */
  3825. /*
  3826. * invalidateAttachments
  3827. *
  3828. * invalidate all attachments to a surface
  3829. */
  3830. static void invalidateAttachments( LPDDRAWI_DDRAWSURFACE_LCL this_lcl )
  3831. {
  3832. LPATTACHLIST pattachlist;
  3833. LPDDRAWI_DDRAWSURFACE_INT curr_int;
  3834. pattachlist = this_lcl->lpAttachList;
  3835. while( pattachlist != NULL )
  3836. {
  3837. curr_int = pattachlist->lpIAttached;
  3838. if( curr_int->lpLcl->dwFlags & DDRAWISURF_IMPLICITCREATE )
  3839. {
  3840. invalidateSurface( curr_int->lpLcl );
  3841. invalidateAttachments( curr_int->lpLcl );
  3842. }
  3843. pattachlist = pattachlist->lpLink;
  3844. }
  3845. } /* invalidateAttachments */
  3846. /*
  3847. * InvalidateAllPrimarySurfaces
  3848. *
  3849. * Traverses the driver object list and sets the invalid bit on all primary
  3850. * surfaces.
  3851. */
  3852. void InvalidateAllPrimarySurfaces( LPDDRAWI_DIRECTDRAW_GBL this )
  3853. {
  3854. LPDDRAWI_DIRECTDRAW_LCL curr_lcl;
  3855. DPF(4, "******** invalidating all primary surfaces");
  3856. /*
  3857. * traverse the driver object list and invalidate all primaries for
  3858. * the specificed driver
  3859. */
  3860. curr_lcl = lpDriverLocalList;
  3861. while( curr_lcl != NULL )
  3862. {
  3863. if( curr_lcl->lpGbl == this )
  3864. {
  3865. if( curr_lcl->lpPrimary != NULL )
  3866. {
  3867. invalidateSurface( curr_lcl->lpPrimary->lpLcl );
  3868. invalidateAttachments( curr_lcl->lpPrimary->lpLcl );
  3869. }
  3870. }
  3871. curr_lcl = curr_lcl->lpLink;
  3872. }
  3873. } /* InvalidateAllPrimarySurfaces */
  3874. #undef DPF_MODNAME
  3875. #define DPF_MODNAME "InvalidateAllSurfaces"
  3876. /*
  3877. * We define the page lock IOCTLs here so that we don't have to include ddvxd.h.
  3878. * These must match the corresponding entries in ddvxd.h
  3879. */
  3880. #define DDVXD_IOCTL_MEMPAGELOCK 28
  3881. #define DDVXD_IOCTL_MEMPAGEUNLOCK 29
  3882. /*
  3883. * InvalidateAllSurfaces
  3884. */
  3885. void InvalidateAllSurfaces( LPDDRAWI_DIRECTDRAW_GBL this, HANDLE hDDVxd, BOOL fRebuildAliases )
  3886. {
  3887. LPDDRAWI_DDRAWSURFACE_INT psurf_int;
  3888. LPDDRAWI_DDRAWSURFACE_LCL pTempLcl;
  3889. #pragma message( REMIND( "Failure conditions on InvalidateAllSurfaces need to be considered" ) )
  3890. #ifdef WIN95
  3891. BackupAllSurfaces(this);
  3892. CleanupD3D8(this, FALSE, 0);
  3893. #endif
  3894. DPF(4, "******** invalidating all surfaces");
  3895. #ifdef USE_ALIAS
  3896. /*
  3897. * As surface memory is about to be destroyed we need to ensure that
  3898. * anyone with outstanding locks is talking to dummy memory rather
  3899. * than real video memory
  3900. *
  3901. * NOTE: Not a lot we can do on failure here.
  3902. */
  3903. if( ( NULL != this->phaiHeapAliases ) && ( this->phaiHeapAliases->dwRefCnt > 1UL ) )
  3904. {
  3905. DDASSERT( INVALID_HANDLE_VALUE != hDDVxd );
  3906. if( FAILED( MapHeapAliasesToDummyMem( hDDVxd, this->phaiHeapAliases ) ) )
  3907. {
  3908. // 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  3909. DPF( 0, "Could not map heap aliases for driver object 0x%p", this );
  3910. DDASSERT( FALSE );
  3911. }
  3912. if( fRebuildAliases )
  3913. {
  3914. ReleaseHeapAliases( hDDVxd, this->phaiHeapAliases );
  3915. this->phaiHeapAliases = NULL;
  3916. if( FAILED( CreateHeapAliases( hDDVxd, this ) ) )
  3917. {
  3918. // 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  3919. DPF( 0, "Could not create the heap aliases for driver object 0x%p", this );
  3920. DDASSERT( FALSE );
  3921. /*
  3922. * Not much we can do if anything goes wrong so simply fail over to needing
  3923. * to hold the Win16 lock.
  3924. */
  3925. this->dwFlags |= DDRAWI_NEEDSWIN16FORVRAMLOCK;
  3926. }
  3927. }
  3928. }
  3929. #endif /* USE_ALIAS */
  3930. psurf_int = this->dsList;
  3931. while( psurf_int != NULL )
  3932. {
  3933. pTempLcl = psurf_int->lpLcl;
  3934. psurf_int = psurf_int->lpLink;
  3935. invalidateSurface( pTempLcl );
  3936. }
  3937. } /* InvalidateAllSurfaces */
  3938. /*
  3939. * FindGlobalPrimary
  3940. *
  3941. * Traverses the driver object list and looks for a primary surface (it doesn't
  3942. * matter if it is invalid). If it finds one, it returns a pointer to the
  3943. * global portion of that surface. If it doesn't, it returns NULL
  3944. */
  3945. LPDDRAWI_DDRAWSURFACE_GBL FindGlobalPrimary( LPDDRAWI_DIRECTDRAW_GBL this )
  3946. {
  3947. LPDDRAWI_DIRECTDRAW_LCL curr_lcl;
  3948. LPDDRAWI_DDRAWSURFACE_INT psurf_int;
  3949. curr_lcl = lpDriverLocalList;
  3950. while( curr_lcl != NULL )
  3951. {
  3952. if( curr_lcl->lpGbl == this )
  3953. {
  3954. psurf_int = curr_lcl->lpPrimary;
  3955. if( psurf_int && !SURFACE_LOST( psurf_int->lpLcl ) )
  3956. {
  3957. return psurf_int->lpLcl->lpGbl;
  3958. }
  3959. }
  3960. curr_lcl = curr_lcl->lpLink;
  3961. }
  3962. return NULL;
  3963. } /* FindGlobalPrimary */
  3964. #ifdef SHAREDZ
  3965. /*
  3966. * FindGlobalZBuffer
  3967. *
  3968. * Traverses the driver object list and looks for a global shared Z. If it
  3969. * finds one, it returns a pointer to the global portion of that surface.
  3970. * If it doesn't, it returns NULL.
  3971. *
  3972. * NOTE: This function will return a shared Z buffer even if it has been lost.
  3973. * However, it will only return a shared Z buffer if it was created in the
  3974. * current mode. The idea being that there is one shared Z-buffer per mode
  3975. * and we will only return the shared Z-buffer for the current mode.
  3976. */
  3977. LPDDRAWI_DDRAWSURFACE_GBL FindGlobalZBuffer( LPDDRAWI_DIRECTDRAW_GBL this )
  3978. {
  3979. LPDDRAWI_DIRECTDRAW_LCL curr_lcl;
  3980. LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
  3981. curr_lcl = lpDriverLocalList;
  3982. while( curr_lcl != NULL )
  3983. {
  3984. if( curr_lcl->lpGbl == this )
  3985. {
  3986. psurf_lcl = curr_lcl->lpSharedZ;
  3987. if( psurf_lcl && ( psurf_lcl->dwModeCreatedIn == this->dwModeIndex ) )
  3988. {
  3989. return psurf_lcl->lpGbl;
  3990. }
  3991. }
  3992. curr_lcl = curr_lcl->lpLink;
  3993. }
  3994. return NULL;
  3995. } /* FindGlobalZBuffer */
  3996. /*
  3997. * FindGlobalBackBuffer
  3998. *
  3999. * Traverses the driver object list and looks for a global shared back-buffer.
  4000. * If it finds one, it returns a pointer to the global portion of that surface.
  4001. * If it doesn't, it returns NULL.
  4002. *
  4003. * NOTE: This function will return a shared back buffer even if it has been lost.
  4004. * However, it will only return a shared back buffer if it was created in the
  4005. * current mode. The idea being that there is one shared back-buffer per mode and
  4006. * we will only return the shared back-buffer for the current mode.
  4007. */
  4008. LPDDRAWI_DDRAWSURFACE_GBL FindGlobalBackBuffer( LPDDRAWI_DIRECTDRAW_GBL this )
  4009. {
  4010. LPDDRAWI_DIRECTDRAW_LCL curr_lcl;
  4011. LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
  4012. curr_lcl = lpDriverLocalList;
  4013. while( curr_lcl != NULL )
  4014. {
  4015. if( curr_lcl->lpGbl == this )
  4016. {
  4017. psurf_lcl = curr_lcl->lpSharedBack;
  4018. if( psurf_lcl && ( psurf_lcl->dwModeCreatedIn == this->dwModeIndex ) )
  4019. {
  4020. return psurf_lcl->lpGbl;
  4021. }
  4022. }
  4023. curr_lcl = curr_lcl->lpLink;
  4024. }
  4025. return NULL;
  4026. } /* FindGlobalBackBuffer */
  4027. #endif
  4028. /*
  4029. * MatchPrimary
  4030. *
  4031. * Traverses the driver object list and looks for valid primary surfaces. If
  4032. * a valid primary surface is found, it attempts to verify that the
  4033. * surface described by lpDDSD is compatible with the existing primary. If
  4034. * it is, the process continues until all valid primary surfaces have been
  4035. * checked. If a primary surface is not compatible, lpDDSD is modified to
  4036. * show a surface description which would have succeeded and FALSE is returned.
  4037. */
  4038. BOOL MatchPrimary( LPDDRAWI_DIRECTDRAW_GBL pdrv, LPDDSURFACEDESC2 lpDDSD )
  4039. {
  4040. /*
  4041. * right now, the only requirement for two primary surfaces to be
  4042. * compatible is that they must both be allocated in video memory or in
  4043. * system memory. Traverse the driver object list until a valid primary
  4044. * surface is found. If a surface is found, verify that it is compatible
  4045. * with the requested surface. If no valid primary surface is found,
  4046. * return TRUE.
  4047. */
  4048. LPDDRAWI_DDRAWSURFACE_INT psurf_int;
  4049. LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
  4050. LPDDRAWI_DIRECTDRAW_LCL curr_lcl;
  4051. curr_lcl = lpDriverLocalList;
  4052. while( curr_lcl != NULL )
  4053. {
  4054. /*
  4055. * is this object pointing to the same driver data?
  4056. */
  4057. if( curr_lcl->lpGbl == pdrv )
  4058. {
  4059. psurf_int = curr_lcl->lpPrimary;
  4060. if( psurf_int && !SURFACE_LOST( psurf_int->lpLcl ) )
  4061. {
  4062. psurf_lcl = psurf_int->lpLcl;
  4063. if( (psurf_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  4064. (lpDDSD->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) )
  4065. {
  4066. lpDDSD->ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
  4067. lpDDSD->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
  4068. return FALSE;
  4069. }
  4070. if( (psurf_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
  4071. (lpDDSD->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
  4072. {
  4073. lpDDSD->ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
  4074. lpDDSD->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
  4075. return FALSE;
  4076. }
  4077. break;
  4078. }
  4079. }
  4080. curr_lcl = curr_lcl->lpLink;
  4081. }
  4082. return TRUE;
  4083. } /* MatchPrimary */
  4084. #ifdef SHAREDZ
  4085. /*
  4086. * MatchSharedZBuffer
  4087. *
  4088. * Traverses the driver object list and looks for valid shared Z buffers. If
  4089. * a valid shared Z buffer is found, it attempts to verify that the
  4090. * surface described by lpDDSD is compatible with the existing shared Z buffer.
  4091. * If it is, the process continues until all valid shared Z buffers have been
  4092. * checked. If a shared Z buffer is not compatible, lpDDSD is modified to
  4093. * show a surface description which would have succeeded and FALSE is returned.
  4094. */
  4095. BOOL MatchSharedZBuffer( LPDDRAWI_DIRECTDRAW_GBL pdrv, LPDDSURFACEDESC lpDDSD )
  4096. {
  4097. /*
  4098. * Currently we allow one shared Z-buffer per mode. So we don't care if we
  4099. * don't match against any other shared Z-buffers in different modes. We
  4100. * only need to match against shared Z-buffers created in the current mode.
  4101. *
  4102. * If we do come across another shared Z-buffer in the same mode then we
  4103. * check to ensure that its in the same type of memory (SYSTEM or VIDEO)
  4104. * and that the requested depths match.
  4105. */
  4106. LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
  4107. LPDDRAWI_DDRAWSURFACE_GBL psurf;
  4108. LPDDRAWI_DIRECTDRAW_LCL curr_lcl;
  4109. LPDDPIXELFORMAT lpddpf;
  4110. curr_lcl = lpDriverLocalList;
  4111. while( curr_lcl != NULL )
  4112. {
  4113. /*
  4114. * is this object pointing to the same driver data?
  4115. */
  4116. if( curr_lcl->lpGbl == pdrv )
  4117. {
  4118. psurf_lcl = curr_lcl->lpSharedZ;
  4119. if( psurf_lcl && ( psurf_lcl->dwModeCreatedIn == pdrv->dwModeIndex ) )
  4120. {
  4121. if( (psurf_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  4122. (lpDDSD->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) )
  4123. {
  4124. lpDDSD->ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
  4125. lpDDSD->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
  4126. return FALSE;
  4127. }
  4128. if( (psurf_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
  4129. (lpDDSD->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
  4130. {
  4131. lpDDSD->ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
  4132. lpDDSD->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
  4133. return FALSE;
  4134. }
  4135. psurf = psurf_lcl->lpGbl;
  4136. /*
  4137. * !!! NOTE: For when I finally get round to putting
  4138. * asserts in the code.
  4139. * ASSERT( psurf != NULL );
  4140. */
  4141. GET_PIXEL_FORMAT( psurf_lcl, psurf, lpddpf );
  4142. /*
  4143. * ASSERT( lpddpf != NULL );
  4144. * ASSERT( lpddpf->dwFlags & DDPF_ZBUFFER );
  4145. */
  4146. if( lpddpf->dwZBufferBitDepth != lpDDSD->dwZBufferBitDepth )
  4147. {
  4148. lpDDSD->dwZBufferBitDepth = lpddpf->dwZBufferBitDepth;
  4149. return FALSE;
  4150. }
  4151. break;
  4152. }
  4153. }
  4154. curr_lcl = curr_lcl->lpLink;
  4155. }
  4156. return TRUE;
  4157. } /* MatchSharedZBuffer */
  4158. /*
  4159. * MatchSharedBackBuffer
  4160. *
  4161. * Traverses the driver object list and looks for valid shared back buffers. If
  4162. * a valid shared back buffer is found, it attempts to verify that the
  4163. * surface described by lpDDSD is compatible with the existing shared back buffer.
  4164. * If it is, the process continues until all valid shared back buffers have been
  4165. * checked. If a shared back buffer is not compatible, lpDDSD is modified to
  4166. * show a surface description which would have succeeded and FALSE is returned.
  4167. */
  4168. BOOL MatchSharedBackBuffer( LPDDRAWI_DIRECTDRAW_GBL pdrv, LPDDSURFACEDESC lpDDSD )
  4169. {
  4170. /*
  4171. * Currently we allow one shared back-buffer per mode. So we don't care if we
  4172. * don't match against any other shared back-buffers in different modes. We
  4173. * only need to match against shared back-buffers created in the current mode.
  4174. *
  4175. * If we do come across another shared back-buffer in the same mode then we
  4176. * check to ensure that its in the same type of memory (SYSTEM or VIDEO)
  4177. * and that its pixel format matches.
  4178. */
  4179. LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
  4180. LPDDRAWI_DDRAWSURFACE_GBL psurf;
  4181. LPDDRAWI_DIRECTDRAW_LCL curr_lcl;
  4182. LPDDPIXELFORMAT lpddpf1;
  4183. LPDDPIXELFORMAT lpddpf2;
  4184. if( lpDDSD->dwFlags & DDSD_PIXELFORMAT )
  4185. lpddpf2 = &lpDDSD->ddpfPixelFormat;
  4186. else
  4187. lpddpf2 = &pdrv->vmiData.ddpfDisplay;
  4188. curr_lcl = lpDriverLocalList;
  4189. while( curr_lcl != NULL )
  4190. {
  4191. /*
  4192. * is this object pointing to the same driver data?
  4193. */
  4194. if( curr_lcl->lpGbl == pdrv )
  4195. {
  4196. psurf_lcl = curr_lcl->lpSharedBack;
  4197. if( psurf_lcl && ( psurf_lcl->dwModeCreatedIn == pdrv->dwModeIndex ) )
  4198. {
  4199. if( (psurf_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  4200. (lpDDSD->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) )
  4201. {
  4202. lpDDSD->ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
  4203. lpDDSD->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
  4204. return FALSE;
  4205. }
  4206. if( (psurf_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
  4207. (lpDDSD->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
  4208. {
  4209. lpDDSD->ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
  4210. lpDDSD->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
  4211. return FALSE;
  4212. }
  4213. psurf = psurf_lcl->lpGbl;
  4214. /*
  4215. * !!! NOTE: For when I finally get round to putting
  4216. * asserts in the code.
  4217. * ASSERT( psurf != NULL );
  4218. */
  4219. GET_PIXEL_FORMAT( psurf_lcl, psurf, lpddpf1 );
  4220. /*
  4221. * ASSERT( lpddpf1 != NULL );
  4222. */
  4223. if( IsDifferentPixelFormat( lpddpf1, lpddpf2 ) )
  4224. {
  4225. lpDDSD->dwFlags |= DDSD_PIXELFORMAT;
  4226. memcpy( &lpDDSD->ddpfPixelFormat, lpddpf1, sizeof( DDPIXELFORMAT ) );
  4227. return FALSE;
  4228. }
  4229. break;
  4230. }
  4231. }
  4232. curr_lcl = curr_lcl->lpLink;
  4233. }
  4234. return TRUE;
  4235. } /* MatchSharedBackBuffer */
  4236. #endif
  4237. #undef DPF_MODNAME
  4238. #define DPF_MODNAME "PageLock"
  4239. /*
  4240. * DD_Surface_PageLock
  4241. *
  4242. * Prevents a system memory surface from being paged out.
  4243. */
  4244. HRESULT DDAPI DD_Surface_PageLock(
  4245. LPDIRECTDRAWSURFACE lpDDSurface,
  4246. DWORD dwFlags )
  4247. {
  4248. LPDDRAWI_DDRAWSURFACE_INT this_int;
  4249. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  4250. LPDDRAWI_DDRAWSURFACE_GBL this;
  4251. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  4252. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  4253. HRESULT hr;
  4254. ENTER_DDRAW();
  4255. DPF(2,A,"ENTERAPI: DD_Surface_PageLock");
  4256. /* DPF_ENTERAPI(lpDDSurface); */
  4257. TRY
  4258. {
  4259. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  4260. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  4261. {
  4262. LEAVE_DDRAW();
  4263. return DDERR_INVALIDOBJECT;
  4264. }
  4265. this_lcl = this_int->lpLcl;
  4266. this = this_lcl->lpGbl;
  4267. if( dwFlags & ~DDPAGELOCK_VALID )
  4268. {
  4269. DPF_ERR( "Invalid flags") ;
  4270. LEAVE_DDRAW();
  4271. return DDERR_INVALIDPARAMS;
  4272. }
  4273. if( SURFACE_LOST( this_lcl ) )
  4274. {
  4275. LEAVE_DDRAW();
  4276. return DDERR_SURFACELOST;
  4277. }
  4278. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  4279. pdrv = pdrv_lcl->lpGbl;
  4280. }
  4281. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  4282. {
  4283. DPF_ERR( "Exception encountered validating parameters" );
  4284. LEAVE_DDRAW();
  4285. return DDERR_INVALIDPARAMS;
  4286. }
  4287. //
  4288. // For now, if the current surface is optimized, quit
  4289. //
  4290. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  4291. {
  4292. DPF_ERR( "It is an optimized surface" );
  4293. LEAVE_DDRAW();
  4294. return DDERR_ISOPTIMIZEDSURFACE;
  4295. }
  4296. // Don't pagelock video memory or emulated primary surface
  4297. if( (this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) &&
  4298. !(this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) )
  4299. {
  4300. hr = InternalPageLock(this_lcl, pdrv_lcl);
  4301. }
  4302. else
  4303. {
  4304. // Succeed but don't do anything if surface has video memory
  4305. // or if this is the emulated primary surface
  4306. hr = DD_OK;
  4307. }
  4308. LEAVE_DDRAW();
  4309. return hr;
  4310. }
  4311. #undef DPF_MODNAME
  4312. #define DPF_MODNAME "PageUnlock"
  4313. /*
  4314. * DD_Surface_PageUnlock
  4315. */
  4316. HRESULT DDAPI DD_Surface_PageUnlock(
  4317. LPDIRECTDRAWSURFACE lpDDSurface,
  4318. DWORD dwFlags )
  4319. {
  4320. LPDDRAWI_DDRAWSURFACE_INT this_int;
  4321. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  4322. LPDDRAWI_DDRAWSURFACE_GBL this;
  4323. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  4324. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  4325. HRESULT hr;
  4326. ENTER_DDRAW();
  4327. DPF(2,A,"ENTERAPI: DD_Surface_PageUnlock");
  4328. /* DPF_ENTERAPI(lpDDSurface); */
  4329. TRY
  4330. {
  4331. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  4332. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  4333. {
  4334. LEAVE_DDRAW();
  4335. return DDERR_INVALIDOBJECT;
  4336. }
  4337. this_lcl = this_int->lpLcl;
  4338. this = this_lcl->lpGbl;
  4339. if( dwFlags & ~DDPAGEUNLOCK_VALID )
  4340. {
  4341. DPF_ERR( "Invalid flags") ;
  4342. LEAVE_DDRAW();
  4343. return DDERR_INVALIDPARAMS;
  4344. }
  4345. if( SURFACE_LOST( this_lcl ) )
  4346. {
  4347. LEAVE_DDRAW();
  4348. return DDERR_SURFACELOST;
  4349. }
  4350. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  4351. pdrv = pdrv_lcl->lpGbl;
  4352. }
  4353. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  4354. {
  4355. DPF_ERR( "Exception encountered validating parameters" );
  4356. LEAVE_DDRAW();
  4357. return DDERR_INVALIDPARAMS;
  4358. }
  4359. //
  4360. // For now, if the current surface is optimized, quit
  4361. //
  4362. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  4363. {
  4364. DPF_ERR( "It is an optimized surface" );
  4365. LEAVE_DDRAW();
  4366. return DDERR_ISOPTIMIZEDSURFACE;
  4367. }
  4368. // Don't pageunlock video memory or emulated primary surface
  4369. if( (this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) &&
  4370. !(this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) )
  4371. {
  4372. hr = InternalPageUnlock(this_lcl, pdrv_lcl);
  4373. }
  4374. else
  4375. {
  4376. // Succeed but don't do anything if surface has video memory
  4377. // or if this is the emulated primary surface
  4378. hr = DD_OK;
  4379. }
  4380. LEAVE_DDRAW();
  4381. return hr;
  4382. }
  4383. /*
  4384. * InternalPageLock
  4385. *
  4386. * Assumes driver lock is taken
  4387. */
  4388. HRESULT InternalPageLock( LPDDRAWI_DDRAWSURFACE_LCL this_lcl,
  4389. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
  4390. {
  4391. BOOL rc;
  4392. DWORD cbReturned;
  4393. DWORD dwReturn;
  4394. LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE(this_lcl->lpGbl);
  4395. struct _PLin
  4396. {
  4397. LPVOID pMem;
  4398. DWORD cbBuffer;
  4399. DWORD dwFlags;
  4400. LPDWORD pdwTable;
  4401. LPDWORD ppTable;
  4402. } PLin;
  4403. #ifndef WINNT
  4404. // If we're already locked; then just increment the count
  4405. if( this_lcl->lpSurfMore->dwPageLockCount )
  4406. {
  4407. this_lcl->lpSurfMore->dwPageLockCount++;
  4408. return DD_OK;
  4409. }
  4410. // Sanity Check
  4411. DDASSERT( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY );
  4412. DDASSERT( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) );
  4413. // Initialize Parameters to pass to VXD
  4414. PLin.pMem = (LPVOID)this_lcl->lpGbl->fpVidMem;
  4415. DDASSERT( PLin.pMem );
  4416. PLin.cbBuffer = this_lcl->lpSurfMore->dwBytesAllocated;
  4417. DDASSERT( PLin.cbBuffer );
  4418. PLin.dwFlags = 0;
  4419. PLin.pdwTable = &lpSurfGblMore->dwPhysicalPageTable;
  4420. PLin.ppTable = (LPDWORD) &lpSurfGblMore->pPageTable;
  4421. DDASSERT( pdrv_lcl->hDDVxd );
  4422. rc = DeviceIoControl( (HANDLE)(pdrv_lcl->hDDVxd),
  4423. DDVXD_IOCTL_MEMPAGELOCK,
  4424. &PLin,
  4425. sizeof( PLin ),
  4426. &dwReturn,
  4427. sizeof( dwReturn ),
  4428. &cbReturned,
  4429. NULL );
  4430. if( !rc )
  4431. {
  4432. lpSurfGblMore->dwPhysicalPageTable = 0;
  4433. lpSurfGblMore->pPageTable = 0;
  4434. lpSurfGblMore->cPages = 0;
  4435. return DDERR_CANTPAGELOCK;
  4436. }
  4437. DDASSERT( cbReturned == sizeof(dwReturn));
  4438. DDASSERT( *PLin.pdwTable && *PLin.ppTable );
  4439. DDASSERT( lpSurfGblMore->dwPhysicalPageTable && lpSurfGblMore->pPageTable );
  4440. // Massage Table
  4441. {
  4442. unsigned i;
  4443. DWORD *rgdwPhysical = lpSurfGblMore->pPageTable;
  4444. // Compute the number of pages
  4445. DWORD cPages = (((DWORD)PLin.pMem & 0xFFF) + 0xFFF + PLin.cbBuffer)/4096;
  4446. // Set the number of pages
  4447. lpSurfGblMore->cPages = cPages;
  4448. // Mask out the page-table flags
  4449. for( i = 0; i < cPages; i++ )
  4450. {
  4451. // Check that the page is present, user-accessible, and read/write
  4452. DDASSERT( rgdwPhysical[i] & 0x7 );
  4453. // Clear out the low bits
  4454. rgdwPhysical[i] &= 0xFFFFF000;
  4455. }
  4456. // Fix the first entry to point to the starting address
  4457. rgdwPhysical[0] |= ((DWORD)PLin.pMem & 0xFFF);
  4458. }
  4459. this_lcl->lpSurfMore->dwPageLockCount++;
  4460. DDASSERT( this_lcl->lpSurfMore->dwPageLockCount == 1 );
  4461. // 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  4462. DPF( 5, "Page Locked %d bytes at 0x%p (count=%d)", PLin.cbBuffer, PLin.pMem,
  4463. this_lcl->lpSurfMore->dwPageLockCount );
  4464. #endif
  4465. return DD_OK;
  4466. }
  4467. HRESULT InternalPageUnlock( LPDDRAWI_DDRAWSURFACE_LCL this_lcl,
  4468. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
  4469. {
  4470. BOOL rc;
  4471. DWORD cbReturned;
  4472. DWORD dwReturn;
  4473. struct _PLin
  4474. {
  4475. LPVOID pMem;
  4476. DWORD cbBuffer;
  4477. DWORD dwFlags;
  4478. LPDWORD pTable;
  4479. } PLin;
  4480. #ifndef WINNT
  4481. LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE(this_lcl->lpGbl);
  4482. DDASSERT( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY );
  4483. DDASSERT( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) );
  4484. if( this_lcl->lpSurfMore->dwPageLockCount <= 0 )
  4485. {
  4486. return DDERR_NOTPAGELOCKED;
  4487. }
  4488. // If we're already locked more than once; then just decrement the count
  4489. if( this_lcl->lpSurfMore->dwPageLockCount > 1 )
  4490. {
  4491. this_lcl->lpSurfMore->dwPageLockCount--;
  4492. return DD_OK;
  4493. }
  4494. /*
  4495. * If it's a system memory surface, better wait for any pending DMA operations
  4496. * to finish.
  4497. */
  4498. if( this_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_HARDWAREOPSTARTED )
  4499. {
  4500. WaitForDriverToFinishWithSurface( pdrv_lcl, this_lcl );
  4501. }
  4502. PLin.pMem = (LPVOID)this_lcl->lpGbl->fpVidMem;
  4503. DDASSERT( PLin.pMem );
  4504. PLin.cbBuffer = this_lcl->lpSurfMore->dwBytesAllocated;
  4505. DDASSERT( PLin.cbBuffer );
  4506. PLin.dwFlags = 0;
  4507. PLin.pTable = lpSurfGblMore->pPageTable;
  4508. DDASSERT( pdrv_lcl->hDDVxd );
  4509. rc = DeviceIoControl((HANDLE)(pdrv_lcl->hDDVxd),
  4510. DDVXD_IOCTL_MEMPAGEUNLOCK,
  4511. &PLin,
  4512. sizeof( PLin ),
  4513. &dwReturn,
  4514. sizeof( dwReturn ),
  4515. &cbReturned,
  4516. NULL);
  4517. if( !rc )
  4518. return DDERR_CANTPAGEUNLOCK;
  4519. DDASSERT( cbReturned == sizeof(dwReturn) );
  4520. this_lcl->lpSurfMore->dwPageLockCount--;
  4521. DDASSERT( this_lcl->lpSurfMore->dwPageLockCount == 0 );
  4522. lpSurfGblMore->dwPhysicalPageTable = 0;
  4523. lpSurfGblMore->pPageTable = 0;
  4524. lpSurfGblMore->cPages = 0;
  4525. // 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  4526. DPF(5, "Page Unlocked %d bytes at 0x%p (count=%d)", PLin.cbBuffer, PLin.pMem,
  4527. this_lcl->lpSurfMore->dwPageLockCount);
  4528. // Increment a timestamp counter; this will help
  4529. // a driver determine if the physical addresses have
  4530. // changed between the time that they have cached it
  4531. // and the time of the Blt/Render call
  4532. lpSurfGblMore->cPageUnlocks++;
  4533. #endif
  4534. return DD_OK;
  4535. }
  4536. HRESULT DDAPI DD_Surface_GetDDInterface(
  4537. LPDIRECTDRAWSURFACE lpDDSurface,
  4538. LPVOID FAR *lplpDD )
  4539. {
  4540. LPDDRAWI_DDRAWSURFACE_INT this_int;
  4541. LPDDRAWI_DIRECTDRAW_INT pdrv_int;
  4542. ENTER_DDRAW();
  4543. DPF(2,A,"ENTERAPI: DD_Surface_GetDDInterface");
  4544. TRY
  4545. {
  4546. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  4547. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  4548. {
  4549. LEAVE_DDRAW();
  4550. return DDERR_INVALIDOBJECT;
  4551. }
  4552. if( !VALID_PTR_PTR( lplpDD ) )
  4553. {
  4554. DPF_ERR( "Invalid DirectDraw Interface ptr ptr" );
  4555. LEAVE_DDRAW();
  4556. return DDERR_INVALIDPARAMS;
  4557. }
  4558. pdrv_int = this_int->lpLcl->lpSurfMore->lpDD_int;
  4559. *lplpDD = pdrv_int;
  4560. }
  4561. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  4562. {
  4563. DPF_ERR( "Exception encountered validating parameters" );
  4564. LEAVE_DDRAW();
  4565. return DDERR_INVALIDPARAMS;
  4566. }
  4567. // Addref the interface before giving it back to the app
  4568. DD_AddRef( (LPDIRECTDRAW)pdrv_int );
  4569. LEAVE_DDRAW();
  4570. return DD_OK;
  4571. } /* DD_Surface_GetDDInterface */
  4572. HRESULT InternalAssociateDC(
  4573. HDC hdc,
  4574. LPDDRAWI_DDRAWSURFACE_LCL pdds_lcl )
  4575. {
  4576. DCINFO *pdcinfo;
  4577. DDASSERT( hdc != NULL );
  4578. DDASSERT( pdds_lcl != NULL );
  4579. pdcinfo = (DCINFO *)MemAlloc( sizeof( DCINFO ) );
  4580. if( pdcinfo == NULL )
  4581. {
  4582. return DDERR_OUTOFMEMORY;
  4583. }
  4584. // initialize element
  4585. pdcinfo->hdc = hdc;
  4586. pdcinfo->pdds_lcl = pdds_lcl;
  4587. // Add element to front of list
  4588. pdcinfo->pdcinfoNext = g_pdcinfoHead;
  4589. g_pdcinfoHead = pdcinfo;
  4590. return DD_OK;
  4591. }
  4592. HRESULT InternalRemoveDCFromList(
  4593. HDC hdc,
  4594. LPDDRAWI_DDRAWSURFACE_LCL pdds_lcl )
  4595. {
  4596. // We may or may not have an hdc passed in.
  4597. // However, this lets us do an error check for
  4598. // some bad parameter cases.
  4599. DCINFO *pdcinfo;
  4600. DCINFO *pdcinfoPrev = NULL;
  4601. DDASSERT( pdds_lcl != NULL );
  4602. for( pdcinfo = g_pdcinfoHead; pdcinfo != NULL;
  4603. pdcinfoPrev = pdcinfo, pdcinfo = pdcinfo->pdcinfoNext )
  4604. {
  4605. DDASSERT( pdcinfo->pdds_lcl != NULL );
  4606. if( pdds_lcl == pdcinfo->pdds_lcl || hdc == pdcinfo->hdc )
  4607. {
  4608. // Check that punk & hdc are in synch -or-
  4609. // we didn't have an hdc passed in..
  4610. DDASSERT( hdc == NULL || (pdds_lcl == pdcinfo->pdds_lcl && hdc == pdcinfo->hdc) );
  4611. // Release this DC. We do this because it is dangerous
  4612. // to leave it around for windows to use because it points
  4613. // surface that we have just freed.
  4614. //
  4615. // However, don't release DCs that were created with the
  4616. // GetDC flag since that is automatically cleaned up by
  4617. // Windows. (Moreover, it wasn't allocated by DD16 who'll
  4618. // get confused.)
  4619. if( hdc == NULL && !(pdds_lcl->dwFlags & DDRAWISURF_GETDCNULL) )
  4620. {
  4621. DDASSERT( pdcinfo->hdc != NULL );
  4622. // 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  4623. DPF( 1, "Releasing Leaked DC = 0x%p", pdcinfo->hdc );
  4624. #ifdef WIN95
  4625. DD16_ReleaseDC( pdcinfo->hdc );
  4626. #else
  4627. if( ( pdds_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY ) ||
  4628. !( pdds_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) )
  4629. {
  4630. DdReleaseDC( pdds_lcl );
  4631. }
  4632. #endif
  4633. }
  4634. // Remove this dcinfo from the list.
  4635. if( pdcinfoPrev == NULL )
  4636. g_pdcinfoHead = pdcinfo->pdcinfoNext;
  4637. else
  4638. pdcinfoPrev->pdcinfoNext = pdcinfo->pdcinfoNext;
  4639. // Free this DcInfo
  4640. MemFree( pdcinfo );
  4641. return DD_OK;
  4642. }
  4643. // Not us? Then just sanity check the object we did find
  4644. DDASSERT( pdcinfo->pdds_lcl->dwFlags & DDRAWISURF_HASDC );
  4645. }
  4646. DPF_ERR( "DC/Surface association not found?" );
  4647. DDASSERT( 0 );
  4648. return DDERR_NOTFOUND;
  4649. }
  4650. HRESULT InternalGetSurfaceFromDC(
  4651. HDC hdc,
  4652. LPDIRECTDRAWSURFACE *ppdds,
  4653. HDC *phdcDriver,
  4654. LPVOID pCallbacks)
  4655. {
  4656. HRESULT ddrval = DDERR_INVALIDPARAMS;
  4657. ENTER_DDRAW();
  4658. DPF(2,A,"ENTERAPI: GetSurfaceFromDC");
  4659. TRY
  4660. {
  4661. DCINFO *pdcinfo;
  4662. if( !VALID_PTR_PTR( ppdds ) )
  4663. {
  4664. DPF_ERR( "Invalid IDirectDrawSurface Interface ptr ptr" );
  4665. LEAVE_DDRAW();
  4666. return DDERR_INVALIDPARAMS;
  4667. }
  4668. // Default value
  4669. *ppdds = NULL;
  4670. *phdcDriver = NULL;
  4671. ddrval = DDERR_GENERIC;
  4672. for ( pdcinfo = g_pdcinfoHead; pdcinfo != NULL; pdcinfo = pdcinfo->pdcinfoNext )
  4673. {
  4674. if( pdcinfo->hdc == hdc )
  4675. {
  4676. DDASSERT( pdcinfo->pdds_lcl != NULL );
  4677. DDASSERT( pdcinfo->pdds_lcl->dwFlags & DDRAWISURF_HASDC );
  4678. *ppdds = (LPVOID)getDDSInterface( pdcinfo->pdds_lcl->lpGbl->lpDD,
  4679. pdcinfo->pdds_lcl, pCallbacks );
  4680. if( *ppdds == NULL )
  4681. {
  4682. DPF_ERR( "GetSurfaceFromDC couldn't allocate interface" );
  4683. ddrval = DDERR_OUTOFMEMORY;
  4684. }
  4685. else
  4686. {
  4687. *phdcDriver = (HDC)pdcinfo->pdds_lcl->lpSurfMore->lpDD_lcl->hDC;
  4688. DD_Surface_AddRef( *ppdds );
  4689. ddrval = DD_OK;
  4690. }
  4691. LEAVE_DDRAW();
  4692. return ddrval;
  4693. }
  4694. }
  4695. DPF( 1, "GetSurfaceFromDC didn't find HDC" );
  4696. ddrval = DDERR_NOTFOUND;
  4697. }
  4698. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  4699. {
  4700. #ifdef DEBUG
  4701. if (ddrval == DDERR_INVALIDPARAMS)
  4702. DPF_ERR( "Exception encountered validating parameters" );
  4703. else
  4704. {
  4705. DPF_ERR( "Unexpected error during GetSurfaceFromDC" );
  4706. DDASSERT( 0 );
  4707. }
  4708. #endif
  4709. }
  4710. LEAVE_DDRAW();
  4711. return ddrval;
  4712. }
  4713. HRESULT EXTERN_DDAPI DD_GetSurfaceFromDC( LPDIRECTDRAW lpDD, HDC hdc, LPDIRECTDRAWSURFACE * pDDS)
  4714. {
  4715. HDC hdcTemp;
  4716. lpDD;
  4717. DPF(2,A,"ENTERAPI: DD_GetSurfaceFromDC");
  4718. if (LOWERTHANDDRAW7( ((LPDDRAWI_DIRECTDRAW_INT)lpDD)) )
  4719. return InternalGetSurfaceFromDC(hdc, pDDS, &hdcTemp, &ddSurfaceCallbacks);
  4720. return InternalGetSurfaceFromDC(hdc, pDDS, &hdcTemp, &ddSurface7Callbacks);
  4721. }
  4722. HRESULT EXTERN_DDAPI GetSurfaceFromDC(
  4723. HDC hdc,
  4724. LPDIRECTDRAWSURFACE *ppdds,
  4725. HDC *phdcDriver )
  4726. {
  4727. return InternalGetSurfaceFromDC(hdc, ppdds, phdcDriver, (LPVOID) &ddSurfaceCallbacks );
  4728. }
  4729. #ifdef WIN95
  4730. void InitColorTable( RGBQUAD *rgColors, LPPALETTEENTRY lpPalette )
  4731. {
  4732. int i;
  4733. for( i = 0; i < 256; i++ )
  4734. {
  4735. rgColors[i].rgbBlue = lpPalette[i].peBlue;
  4736. rgColors[i].rgbGreen = lpPalette[i].peGreen;
  4737. rgColors[i].rgbRed = lpPalette[i].peRed;
  4738. rgColors[i].rgbReserved = 0;
  4739. }
  4740. return;
  4741. }
  4742. // This function walks the list of outstanding DCs and figures out
  4743. // if the DC's colortable needs to be updated. It may be called in two ways:
  4744. //
  4745. // surface+pal -> this means that pal was attached to a surface
  4746. // just a surface -> this means that a palette was removed from a surface
  4747. void UpdateOutstandingDC( LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl, LPDDRAWI_DDRAWPALETTE_GBL ppal_gbl )
  4748. {
  4749. BOOL fColorsInited = FALSE;
  4750. RGBQUAD rgColors[256];
  4751. PALETTEENTRY rgPalEntry[256];
  4752. LPDDPIXELFORMAT pddpf;
  4753. DCINFO *pdcinfo;
  4754. LPDDPIXELFORMAT pddpf_curr;
  4755. DDASSERT( psurf_lcl );
  4756. // Quick check to see if there are any DCs outstanding
  4757. // If not, then we don't have to do all this work
  4758. if( g_pdcinfoHead == NULL )
  4759. return;
  4760. GET_PIXEL_FORMAT( psurf_lcl, psurf_lcl->lpGbl, pddpf );
  4761. // Ignore non-8bit surfaces
  4762. if( !(pddpf->dwFlags & DDPF_PALETTEINDEXED8) )
  4763. return;
  4764. if( (psurf_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) )
  4765. {
  4766. // Primary?
  4767. // If it is, then we need to find all the outstanding
  4768. // DCs that are sharing the palette; and update them
  4769. for ( pdcinfo = g_pdcinfoHead; pdcinfo != NULL; pdcinfo = pdcinfo->pdcinfoNext )
  4770. {
  4771. DDASSERT( pdcinfo->pdds_lcl != NULL );
  4772. DDASSERT( pdcinfo->pdds_lcl->dwFlags & DDRAWISURF_HASDC );
  4773. GET_PIXEL_FORMAT( pdcinfo->pdds_lcl, pdcinfo->pdds_lcl->lpGbl, pddpf_curr );
  4774. // Ignore non palette-indexed 8-bit surfaces
  4775. if( !(pddpf_curr->dwFlags & DDPF_PALETTEINDEXED8) )
  4776. continue;
  4777. // Ignore DCs handed out by other direct draw interfaces
  4778. if( pdcinfo->pdds_lcl->lpGbl->lpDD != psurf_lcl->lpGbl->lpDD )
  4779. continue;
  4780. // Ignore surfaces that have their own palettes
  4781. // (except for our surface that is..)
  4782. if( pdcinfo->pdds_lcl->lpDDPalette != NULL &&
  4783. pdcinfo->pdds_lcl != psurf_lcl )
  4784. continue;
  4785. // We don't need to touch palettes that are of the
  4786. // DCNULL kind (it's already been updated
  4787. // because the DC isn't one of the ones we cooked ourselves)
  4788. if( pdcinfo->pdds_lcl->dwFlags & DDRAWISURF_GETDCNULL )
  4789. continue;
  4790. // Ok, this DC needs updating
  4791. // 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  4792. DPF( 3, "Updating colortable for HDC(0x%p)", pdcinfo->hdc );
  4793. // Have we init'ed our colors?
  4794. if( !fColorsInited )
  4795. {
  4796. if( ppal_gbl && ppal_gbl->dwFlags & DDRAWIPAL_EXCLUSIVE )
  4797. {
  4798. // If we're exclusive then use our colors as is
  4799. InitColorTable( rgColors, ppal_gbl->lpColorTable );
  4800. }
  4801. else
  4802. {
  4803. // Else, use the colors from current system palette
  4804. int n = GetSystemPaletteEntries( (HDC)psurf_lcl->lpSurfMore->lpDD_lcl->hDC,
  4805. 0, 256, rgPalEntry );
  4806. DDASSERT( n == 256 );
  4807. InitColorTable( rgColors, rgPalEntry );
  4808. }
  4809. fColorsInited = TRUE;
  4810. }
  4811. // Set the colors into the DC, this will have the
  4812. // extra effect of resetting any cached translation tables
  4813. // so GDI won't use a wrong one inadvertently.
  4814. DPF(5, "Dib Color Table entry #50 == 0x%x", rgColors[50]);
  4815. SetDIBColorTable( pdcinfo->hdc, 0, 256, rgColors);
  4816. }
  4817. }
  4818. else
  4819. {
  4820. // Ordinary surface? Then find it in our list
  4821. for ( pdcinfo = g_pdcinfoHead; pdcinfo != NULL; pdcinfo = pdcinfo->pdcinfoNext )
  4822. {
  4823. DDASSERT( pdcinfo->pdds_lcl != NULL );
  4824. DDASSERT( pdcinfo->pdds_lcl->dwFlags & DDRAWISURF_HASDC );
  4825. // Ignored surfaces that have different global objects
  4826. if( pdcinfo->pdds_lcl->lpGbl != psurf_lcl->lpGbl )
  4827. continue;
  4828. // Ignore non palette-indexed 8-bit surfaces
  4829. GET_PIXEL_FORMAT( pdcinfo->pdds_lcl, pdcinfo->pdds_lcl->lpGbl, pddpf_curr );
  4830. if( !(pddpf_curr->dwFlags & DDPF_PALETTEINDEXED8) )
  4831. continue;
  4832. // Ok, this DC needs updating
  4833. // 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  4834. DPF( 3, "Updating colortable for non-primary HDC(0x%p)", pdcinfo->hdc );
  4835. if( !fColorsInited )
  4836. {
  4837. if( ppal_gbl )
  4838. {
  4839. // New color table for this offscreen surface?
  4840. // Use them directly
  4841. InitColorTable( rgColors, ppal_gbl->lpColorTable );
  4842. fColorsInited = TRUE;
  4843. }
  4844. else
  4845. {
  4846. int n;
  4847. // Someone is removing a palette from an offscreen surface?
  4848. // Then if the primary is at 8bpp, then we should
  4849. // steal the colors from it.
  4850. LPDDRAWI_DDRAWSURFACE_INT lpPrimary = pdcinfo->pdds_lcl->lpSurfMore->lpDD_lcl->lpPrimary;
  4851. if( lpPrimary )
  4852. {
  4853. // Check that the primary is 8bpp. If it is not,
  4854. // then we leave this surface alone.
  4855. GET_PIXEL_FORMAT( lpPrimary->lpLcl, lpPrimary->lpLcl->lpGbl, pddpf_curr );
  4856. if( !(pddpf_curr->dwFlags & DDPF_PALETTEINDEXED8) )
  4857. return;
  4858. }
  4859. else
  4860. {
  4861. // There is no primary surface attached to this
  4862. // DDraw. So we have no where useful to get colors from
  4863. // so return.
  4864. return;
  4865. }
  4866. DDASSERT( lpPrimary != NULL );
  4867. DDASSERT( pddpf_curr->dwFlags & DDPF_PALETTEINDEXED8 );
  4868. // Else, use the colors from current system palette
  4869. n = GetSystemPaletteEntries( (HDC)lpPrimary->lpLcl->lpSurfMore->lpDD_lcl->hDC,
  4870. 0, 256, rgPalEntry );
  4871. DDASSERT( n == 256 );
  4872. InitColorTable( rgColors, rgPalEntry );
  4873. }
  4874. }
  4875. // Set the colors into the DC, this will have the
  4876. // extra effect of reseting any cached translation tables
  4877. // so GDI won't use a wrong one inadvertantly.
  4878. DPF(5, "Dib Color Table entry #50 == 0x%x", rgColors[50]);
  4879. SetDIBColorTable( pdcinfo->hdc, 0, 256, rgColors);
  4880. }
  4881. }
  4882. return;
  4883. }
  4884. // This function handles the case when the entries of a
  4885. // palette have changed. We need to search for all the surfaces
  4886. // that may be affected and do something. However, we only
  4887. void UpdateDCOnPaletteChanges( LPDDRAWI_DDRAWPALETTE_GBL ppal_gbl )
  4888. {
  4889. DCINFO *pdcinfo;
  4890. DDASSERT( ppal_gbl != NULL );
  4891. // Quick check to see if there are any DCs outstanding
  4892. // If not, then we don't have to do all this work
  4893. if( g_pdcinfoHead == NULL )
  4894. return;
  4895. // Is this palette attached to our primary?
  4896. // We have to do this explicitly without regard to the outstanding
  4897. // DC list because the primary itself may have no outstanding DCs
  4898. // but offscreen surfaces may be logically 'sharing' the primary's palette
  4899. if( ppal_gbl->lpDD_lcl->lpPrimary &&
  4900. ppal_gbl->lpDD_lcl->lpPrimary->lpLcl->lpDDPalette &&
  4901. ppal_gbl->lpDD_lcl->lpPrimary->lpLcl->lpDDPalette->lpLcl->lpGbl == ppal_gbl )
  4902. {
  4903. // Update the palette for DCs associated with this primary
  4904. UpdateOutstandingDC( ppal_gbl->lpDD_lcl->lpPrimary->lpLcl, ppal_gbl );
  4905. }
  4906. // We walk all outstanding DCs looking for
  4907. // surfaces that are DIRECTLY affected this set entries.
  4908. for ( pdcinfo = g_pdcinfoHead; pdcinfo != NULL; pdcinfo = pdcinfo->pdcinfoNext )
  4909. {
  4910. DDASSERT( pdcinfo->pdds_lcl != NULL );
  4911. DDASSERT( pdcinfo->pdds_lcl->dwFlags & DDRAWISURF_HASDC );
  4912. // Ignore surfaces that don't have a palette;
  4913. // (If a surface doesn't have a palette, then that means
  4914. // it's using the palette from the primary. We handle that case
  4915. // above when we deal with the primary.)
  4916. if( pdcinfo->pdds_lcl->lpDDPalette == NULL )
  4917. continue;
  4918. // Ignore surfaces that aren't connected to us
  4919. if( pdcinfo->pdds_lcl->lpDDPalette->lpLcl->lpGbl != ppal_gbl )
  4920. continue;
  4921. // Ignore the primary that we already updated above
  4922. if( ppal_gbl->lpDD_lcl->lpPrimary &&
  4923. ppal_gbl->lpDD_lcl->lpPrimary->lpLcl == pdcinfo->pdds_lcl )
  4924. continue;
  4925. UpdateOutstandingDC( pdcinfo->pdds_lcl, ppal_gbl );
  4926. }
  4927. return;
  4928. }
  4929. #endif /* WIN95 */
  4930. #undef DPF_MODNAME
  4931. #define DPF_MODNAME "GetTopLevel"
  4932. LPDDRAWI_DDRAWSURFACE_LCL GetTopLevel(LPDDRAWI_DDRAWSURFACE_LCL lpLcl)
  4933. {
  4934. // loop to find the top level surface of a mipmap chain
  4935. for(; (lpLcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL) != 0;
  4936. lpLcl = lpLcl->lpAttachListFrom->lpAttached);
  4937. // if the top level surface is a cubemap face
  4938. if((lpLcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_CUBEMAP) != 0)
  4939. // then we need to return the top level surface of the cubemap
  4940. // The assumption here is that a cubemap is only one level deep
  4941. // and a cubemap subface is attached from ONLY a cubemap top level face
  4942. if(lpLcl->lpAttachListFrom != NULL)
  4943. lpLcl = lpLcl->lpAttachListFrom->lpAttached;
  4944. return lpLcl;
  4945. }
  4946. #undef DPF_MODNAME
  4947. #define DPF_MODNAME "DD_Surface_SetSurfaceDesc"
  4948. /*
  4949. * NOTE: There is a significant amount of code in this function that
  4950. * deals with video memory surfaces yet you will notice a check explicitly
  4951. * failing this function for surfaces which are not explicit system
  4952. * memory. This is deliberate. The intention is to mutate this function
  4953. * to work with video memory surfaces over time. The code is in place
  4954. * to start this process however unresolved issues remain.
  4955. */
  4956. HRESULT DDAPI DD_Surface_SetSurfaceDesc(
  4957. LPDIRECTDRAWSURFACE3 lpDDSurface,
  4958. LPDDSURFACEDESC lpddsd,
  4959. DWORD dwFlags )
  4960. {
  4961. DDSURFACEDESC2 ddsd2 = {sizeof(ddsd2)};
  4962. DPF(2,A,"ENTERAPI: DD_Surface_SetSurfaceDesc");
  4963. ZeroMemory(&ddsd2,sizeof(ddsd2));
  4964. TRY
  4965. {
  4966. if( !VALID_DIRECTDRAWSURFACE_PTR( ((LPDDRAWI_DDRAWSURFACE_INT)lpDDSurface) ) )
  4967. {
  4968. DPF_ERR( "Invalid surface description passed" );
  4969. DPF_APIRETURNS(DDERR_INVALIDOBJECT);
  4970. return DDERR_INVALIDOBJECT;
  4971. }
  4972. if( 0UL != dwFlags )
  4973. {
  4974. DPF_ERR( "No flags are currently specified - 0 must be passed" );
  4975. DPF_APIRETURNS(DDERR_INVALIDPARAMS);
  4976. return DDERR_INVALIDPARAMS;
  4977. }
  4978. if( !VALID_DDSURFACEDESC_PTR( lpddsd ) )
  4979. {
  4980. DPF_ERR( "Invalid surface description. Did you set the dwSize member?" );
  4981. DPF_APIRETURNS(DDERR_INVALIDPARAMS);
  4982. return DDERR_INVALIDPARAMS;
  4983. }
  4984. memcpy(&ddsd2,lpddsd,sizeof(*lpddsd));
  4985. }
  4986. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  4987. {
  4988. DPF_ERR( "Exception encountered validating parameters: Bad LPDDSURFACEDESC" );
  4989. DPF_APIRETURNS(DDERR_INVALIDPARAMS);
  4990. return DDERR_INVALIDPARAMS;
  4991. }
  4992. ddsd2.dwSize = sizeof(ddsd2);
  4993. return DD_Surface_SetSurfaceDesc4(lpDDSurface, &ddsd2, dwFlags);
  4994. }
  4995. HRESULT DDAPI DD_Surface_SetSurfaceDesc4(
  4996. LPDIRECTDRAWSURFACE3 lpDDSurface,
  4997. LPDDSURFACEDESC2 lpddsd,
  4998. DWORD dwFlags )
  4999. {
  5000. LPDDRAWI_DDRAWSURFACE_INT this_int;
  5001. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  5002. LPDDRAWI_DDRAWSURFACE_GBL this;
  5003. LPDDRAWI_DIRECTDRAW_INT pdrv_int;
  5004. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  5005. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  5006. BOOL emulation;
  5007. DWORD dwDummyFlags;
  5008. HRESULT ddres;
  5009. DDSURFACEDESC2 ddsd;
  5010. DDHAL_CANCREATESURFACEDATA ccsd;
  5011. LPDDHAL_CANCREATESURFACE ccsfn;
  5012. LPDDHAL_CANCREATESURFACE ccshalfn;
  5013. WORD wOldWidth;
  5014. WORD wOldHeight;
  5015. LONG lOldPitch;
  5016. DDPIXELFORMAT ddpfOldPixelFormat;
  5017. BOOL bIsCompressedTexture = FALSE;
  5018. WORD realwidth;
  5019. WORD realheight;
  5020. DWORD realsurfsize;
  5021. ENTER_DDRAW();
  5022. DPF(2,A,"ENTERAPI: DD_Surface_SetSurfaceDesc4");
  5023. TRY
  5024. {
  5025. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  5026. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  5027. {
  5028. DPF_ERR( "Invalid surface description passed" );
  5029. LEAVE_DDRAW();
  5030. return DDERR_INVALIDOBJECT;
  5031. }
  5032. this_lcl = this_int->lpLcl;
  5033. DDASSERT( NULL != this_lcl );
  5034. this = this_lcl->lpGbl;
  5035. DDASSERT( NULL != this );
  5036. pdrv_int = this_lcl->lpSurfMore->lpDD_int;
  5037. DDASSERT( NULL != pdrv_int );
  5038. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  5039. DDASSERT( NULL != pdrv_lcl );
  5040. pdrv = pdrv_lcl->lpGbl;
  5041. DDASSERT( NULL != pdrv );
  5042. //
  5043. // For now, if the current surface is optimized, quit
  5044. //
  5045. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  5046. {
  5047. DPF_ERR( "It is an optimized surface" );
  5048. LEAVE_DDRAW();
  5049. return DDERR_ISOPTIMIZEDSURFACE;
  5050. }
  5051. if( 0UL != dwFlags )
  5052. {
  5053. DPF_ERR( "No flags are currently specified - 0 must be passed" );
  5054. LEAVE_DDRAW();
  5055. return DDERR_INVALIDPARAMS;
  5056. }
  5057. if( !VALID_DDSURFACEDESC2_PTR( lpddsd ) )
  5058. {
  5059. DPF_ERR( "Surface description is invalid" );
  5060. LEAVE_DDRAW();
  5061. return DDERR_INVALIDPARAMS;
  5062. }
  5063. if( SURFACE_LOST( this_lcl ) )
  5064. {
  5065. DPF_ERR( "Could not set surface pointer - surface is lost" );
  5066. LEAVE_DDRAW();
  5067. return DDERR_SURFACELOST;
  5068. }
  5069. if( this->dwUsageCount > 0UL )
  5070. {
  5071. DPF_ERR( "Could not set surface pointer - surface is locked" );
  5072. LEAVE_DDRAW();
  5073. return DDERR_SURFACEBUSY;
  5074. }
  5075. /*
  5076. * Currently we don't allow anything but explicit system memory surfaces to
  5077. * have thier surface description (and pointer modified).
  5078. */
  5079. #pragma message( REMIND( "Look into making SetSurfaceDesc work for video memory" ) )
  5080. if( !( this->dwGlobalFlags & DDRAWISURFGBL_SYSMEMREQUESTED ) )
  5081. {
  5082. DPF_ERR( "Could not set surface pointer - surface is not explicit system memory" );
  5083. LEAVE_DDRAW();
  5084. return DDERR_INVALIDSURFACETYPE;
  5085. }
  5086. DDASSERT( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY );
  5087. if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) ||
  5088. ( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACELEFT ) ||
  5089. ( this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY ) ||
  5090. ( this_lcl->ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD ) ||
  5091. ( this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_TEXTUREMANAGE ) ||
  5092. ( this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_D3DTEXTUREMANAGE ))
  5093. {
  5094. DPF_ERR( "Could not set surface pointer - surface is primary, overlay or device specific" );
  5095. LEAVE_DDRAW();
  5096. return DDERR_INVALIDSURFACETYPE;
  5097. }
  5098. /*
  5099. * Don't mess with anything that is part of the primary chain. That could get
  5100. * very nasty (destroying the primary surface pointer and replacing it with
  5101. * some app. specific garbage).
  5102. */
  5103. if( this_lcl->dwFlags & DDRAWISURF_PARTOFPRIMARYCHAIN )
  5104. {
  5105. DPF_ERR( "Cannot set surface pointer - surface is part of the primary chain" );
  5106. LEAVE_DDRAW();
  5107. return DDERR_INVALIDSURFACETYPE;
  5108. }
  5109. if( lpddsd->dwFlags & ~( DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH |
  5110. DDSD_LPSURFACE | DDSD_PIXELFORMAT ) )
  5111. {
  5112. DPF_ERR( "Can only specify caps, width, height, pitch, surface ptr and pixel format" );
  5113. LEAVE_DDRAW();
  5114. return DDERR_INVALIDPARAMS;
  5115. }
  5116. if( ( lpddsd->dwFlags & DDSD_WIDTH ) && ( 0UL == lpddsd->dwWidth ) )
  5117. {
  5118. DPF_ERR( "Invalid surface width specified" );
  5119. LEAVE_DDRAW();
  5120. return DDERR_INVALIDPARAMS;
  5121. }
  5122. if( ( lpddsd->dwFlags & DDSD_HEIGHT ) && ( 0UL == lpddsd->dwHeight ) )
  5123. {
  5124. DPF_ERR( "Invalid surface height specified" );
  5125. LEAVE_DDRAW();
  5126. return DDERR_INVALIDPARAMS;
  5127. }
  5128. if( ( lpddsd->dwFlags & DDSD_PITCH ) && (( lpddsd->lPitch <= 0L ) || (lpddsd->lPitch % 4)) )
  5129. {
  5130. DPF_ERR( "Invalid surface pitch specified" );
  5131. LEAVE_DDRAW();
  5132. return DDERR_INVALIDPARAMS;
  5133. }
  5134. if( lpddsd->dwFlags & DDSD_PIXELFORMAT )
  5135. {
  5136. if( !( this_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT ) )
  5137. {
  5138. /*
  5139. * This is very cheesy but the alternative is pretty nasty.
  5140. * Reallocting the global object with a pixel format if it
  5141. * does not already have one.
  5142. */
  5143. DPF_ERR( "Cannot change the pixel format of a surface which does not have one" );
  5144. LEAVE_DDRAW();
  5145. return DDERR_INVALIDPARAMS;
  5146. }
  5147. if( !VALID_DDPIXELFORMAT_PTR( ( &(this->ddpfSurface) ) ) )
  5148. {
  5149. DPF_ERR( "Specifed pixel format is invalid" );
  5150. LEAVE_DDRAW();
  5151. return DDERR_INVALIDPARAMS;
  5152. }
  5153. }
  5154. if( ( ( lpddsd->dwFlags & DDSD_WIDTH ) && !( lpddsd->dwFlags & DDSD_PITCH ) ) ||
  5155. ( ( lpddsd->dwFlags & DDSD_PITCH ) && !( lpddsd->dwFlags & DDSD_WIDTH ) ) )
  5156. {
  5157. DPF_ERR( "If width or pitch is specified then both width AND pitch must be specified" );
  5158. LEAVE_DDRAW();
  5159. return DDERR_INVALIDPARAMS;
  5160. }
  5161. if( !( lpddsd->dwFlags & DDSD_LPSURFACE ) )
  5162. {
  5163. DPF_ERR( "Must specify a surface memory pointer" );
  5164. LEAVE_DDRAW();
  5165. return DDERR_INVALIDPARAMS;
  5166. }
  5167. if( NULL == lpddsd->lpSurface )
  5168. {
  5169. DPF_ERR( "Surface memory pointer can't be NULL" );
  5170. LEAVE_DDRAW();
  5171. return DDERR_INVALIDPARAMS;
  5172. }
  5173. if( lpddsd->dwFlags & DDSD_CAPS )
  5174. {
  5175. if( lpddsd->ddsCaps.dwCaps != 0 )
  5176. {
  5177. DPF_ERR( "Illegal to set ddsCaps.dwCaps bits in surface desc" );
  5178. LEAVE_DDRAW();
  5179. return DDERR_INVALIDCAPS;
  5180. }
  5181. #if 0 // DDSCAPS2_LOCALALLOC, DDSCAPS2_COTASKMEM and DDRAWISURFGBL_DDFREESCLIENTMEM are gone
  5182. if( lpddsd->ddsCaps.dwCaps2 & ~(DDSCAPS2_LOCALALLOC | DDSCAPS2_COTASKMEM) )
  5183. {
  5184. DPF_ERR( "The only legal DDSCAPS2 flags are LOCALALLOC and COTASKMEM" );
  5185. LEAVE_DDRAW();
  5186. return DDERR_INVALIDCAPS;
  5187. }
  5188. if( !(~lpddsd->ddsCaps.dwCaps2 & (DDSCAPS2_LOCALALLOC | DDSCAPS2_COTASKMEM)) )
  5189. {
  5190. // Illegal to set LOCALALLOC and COTASKMEM flags simultaneously.
  5191. DPF_ERR( "DDSCAPS2 flags LOCALALLOC and COTASKMEM are mutually exclusive" );
  5192. LEAVE_DDRAW();
  5193. return DDERR_INVALIDCAPS;
  5194. }
  5195. #endif // 0
  5196. if( lpddsd->ddsCaps.dwCaps3 != 0 )
  5197. {
  5198. DPF_ERR( "Illegal to set ddsCaps.dwCaps3 bits in surface desc" );
  5199. LEAVE_DDRAW();
  5200. return DDERR_INVALIDCAPS;
  5201. }
  5202. if( lpddsd->ddsCaps.dwCaps4 != 0 )
  5203. {
  5204. DPF_ERR( "Illegal to set ddsCaps.dwCaps4 bits in surface desc" );
  5205. LEAVE_DDRAW();
  5206. return DDERR_INVALIDCAPS;
  5207. }
  5208. }
  5209. }
  5210. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  5211. {
  5212. DPF_ERR( "Exception encountered validating parameters" );
  5213. LEAVE_DDRAW();
  5214. return DDERR_INVALIDPARAMS;
  5215. }
  5216. /*
  5217. * Build a new surface description for the surface and fill in
  5218. * the new width, height and pitch.
  5219. */
  5220. FillDDSurfaceDesc2( this_lcl, &ddsd );
  5221. if( lpddsd->dwFlags & DDSD_WIDTH )
  5222. ddsd.dwWidth = lpddsd->dwWidth;
  5223. if( lpddsd->dwFlags & DDSD_HEIGHT )
  5224. ddsd.dwHeight = lpddsd->dwHeight;
  5225. if( lpddsd->dwFlags & DDSD_PITCH )
  5226. ddsd.lPitch = lpddsd->lPitch;
  5227. if( lpddsd->dwFlags & DDSD_PIXELFORMAT )
  5228. ddsd.ddpfPixelFormat = lpddsd->ddpfPixelFormat;
  5229. emulation = ddsd.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
  5230. /*
  5231. * Validate that the new surface description makes some remote kind of
  5232. * sense.
  5233. */
  5234. ddres = checkSurfaceDesc( &ddsd,
  5235. pdrv,
  5236. &dwDummyFlags,
  5237. emulation,
  5238. this->dwGlobalFlags & DDRAWISURFGBL_SYSMEMREQUESTED,
  5239. pdrv_int );
  5240. if( FAILED( ddres ) )
  5241. {
  5242. DPF_ERR( "Invalid surface description passed" );
  5243. LEAVE_DDRAW();
  5244. return ddres;
  5245. }
  5246. /*
  5247. * Ask the driver if it likes the look of this surface. We need to ask
  5248. * the driver again (even though we already did it when the surface was
  5249. * created) as the surface has changed size.
  5250. */
  5251. if( emulation )
  5252. {
  5253. if( ddsd.ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
  5254. {
  5255. ccsfn = pdrv_lcl->lpDDCB->HELDDExeBuf.CanCreateExecuteBuffer;
  5256. }
  5257. else
  5258. {
  5259. ccsfn = pdrv_lcl->lpDDCB->HELDD.CanCreateSurface;
  5260. }
  5261. ccshalfn = ccsfn;
  5262. }
  5263. else
  5264. {
  5265. if( ddsd.ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
  5266. {
  5267. ccsfn = pdrv_lcl->lpDDCB->HALDDExeBuf.CanCreateExecuteBuffer;
  5268. ccshalfn = pdrv_lcl->lpDDCB->cbDDExeBufCallbacks.CanCreateExecuteBuffer;
  5269. }
  5270. else
  5271. {
  5272. ccsfn = pdrv_lcl->lpDDCB->HALDD.CanCreateSurface;
  5273. ccshalfn = pdrv_lcl->lpDDCB->cbDDCallbacks.CanCreateSurface;
  5274. }
  5275. }
  5276. if( ccshalfn != NULL )
  5277. {
  5278. BOOL is_diff;
  5279. HRESULT rc;
  5280. if( ddsd.dwFlags & DDSD_PIXELFORMAT )
  5281. {
  5282. is_diff = IsDifferentPixelFormat( &pdrv->vmiData.ddpfDisplay, &ddsd.ddpfPixelFormat );
  5283. }
  5284. else
  5285. {
  5286. is_diff = FALSE;
  5287. }
  5288. ccsd.CanCreateSurface = ccshalfn;
  5289. ccsd.lpDD = pdrv;
  5290. ccsd.lpDDSurfaceDesc = (LPDDSURFACEDESC)&ddsd;
  5291. ccsd.bIsDifferentPixelFormat = is_diff;
  5292. if( ddsd.ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
  5293. {
  5294. DOHALCALL( CanCreateExecuteBuffer, ccsfn, ccsd, rc, emulation );
  5295. }
  5296. else
  5297. {
  5298. DOHALCALL( CanCreateSurface, ccsfn, ccsd, rc, emulation );
  5299. }
  5300. if( rc == DDHAL_DRIVER_HANDLED )
  5301. {
  5302. if( ccsd.ddRVal != DD_OK )
  5303. {
  5304. DPF_ERR( "Driver says surface can't be created" );
  5305. LEAVE_DDRAW();
  5306. return ccsd.ddRVal;
  5307. }
  5308. }
  5309. }
  5310. /*
  5311. * Stash away the surface settings to we can put them back if anything
  5312. * foes wrong.
  5313. *
  5314. * NOTE: We don't store away the heap or vid mem pointer if an error happens
  5315. * after this point the surface ends up lost and will need to be restored.
  5316. */
  5317. wOldWidth = this->wWidth;
  5318. wOldHeight = this->wHeight;
  5319. lOldPitch = this->lPitch;
  5320. if( this_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT )
  5321. ddpfOldPixelFormat = this->ddpfSurface;
  5322. /* There could be pending TexBlts and stuff, so Sync with the token stream */
  5323. FlushD3DStates( this_lcl );
  5324. /*
  5325. * The driver has okayed the creation so toast the existing surface memory.
  5326. */
  5327. DestroySurface( this_lcl );
  5328. /*
  5329. * Remove any cached RLE stuff for source surface
  5330. */
  5331. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
  5332. {
  5333. extern void FreeRleData(LPDDRAWI_DDRAWSURFACE_LCL); //in junction.c
  5334. FreeRleData( this_lcl );
  5335. }
  5336. /*
  5337. * Now mutate the surface into its new form. Kind of spooky isn't it... a bit
  5338. * like The Fly. Stash away the original settings in case we need to put them back
  5339. * if something goes wrong.
  5340. */
  5341. if( lpddsd->dwFlags & DDSD_WIDTH )
  5342. this->wWidth = (WORD)lpddsd->dwWidth;
  5343. if( lpddsd->dwFlags & DDSD_HEIGHT )
  5344. this->wHeight = (WORD)lpddsd->dwHeight;
  5345. if( lpddsd->dwFlags & DDSD_PITCH )
  5346. this->lPitch = lpddsd->lPitch;
  5347. if( lpddsd->dwFlags & DDSD_PIXELFORMAT )
  5348. {
  5349. this->ddpfSurface = lpddsd->ddpfPixelFormat;
  5350. // Now that the pixel format may have changed, we need to reset the pixel-format
  5351. // index that was previously cached by the HEL's AlphaBlt emulation routine.
  5352. this_lcl->lpSurfMore->dwPFIndex = PFINDEX_UNINITIALIZED;
  5353. // ATTENTION: If pixel format has changed, are old color keys still valid?
  5354. }
  5355. this->lpVidMemHeap = NULL;
  5356. this->fpVidMem = (FLATPTR)lpddsd->lpSurface;
  5357. #if 0 // DDRAWISURFGBL_DDFREESCLIENTMEM is gone
  5358. this->dwGlobalFlags &= ~(DDRAWISURFGBL_MEMFREE | DDRAWISURFGBL_DDFREESCLIENTMEM);
  5359. #else
  5360. this->dwGlobalFlags &= ~(DDRAWISURFGBL_MEMFREE);
  5361. #endif // 0
  5362. this->dwGlobalFlags |= DDRAWISURFGBL_ISCLIENTMEM;
  5363. this_lcl->dwFlags &= ~DDRAWISURF_INVALID;
  5364. #if 0 // DDSCAPS2_LOCALALLOC, DDSCAPS2_COTASKMEM and DDRAWISURFGBL_DDFREESCLIENTMEM are gone
  5365. this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 &= ~(DDSCAPS2_LOCALALLOC | DDSCAPS2_COTASKMEM);
  5366. if( lpddsd->dwFlags & DDSD_CAPS &&
  5367. lpddsd->ddsCaps.dwCaps2 & (DDSCAPS2_LOCALALLOC | DDSCAPS2_COTASKMEM) )
  5368. {
  5369. /*
  5370. * Remember that DirectDraw will be responsible for freeing the
  5371. * client-allocated surface memory when it's no longer needed.
  5372. */
  5373. this->dwGlobalFlags |= DDRAWISURFGBL_DDFREESCLIENTMEM;
  5374. this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 |=
  5375. lpddsd->ddsCaps.dwCaps2 & (DDSCAPS2_LOCALALLOC | DDSCAPS2_COTASKMEM);
  5376. }
  5377. #endif // 0
  5378. #ifdef USE_ALIAS
  5379. {
  5380. /*
  5381. * If this is a video memory surface then we need to recompute the alias offset of
  5382. * the surface for locking purposes.
  5383. */
  5384. LPDDRAWI_DDRAWSURFACE_GBL_MORE lpGblMore;
  5385. lpGblMore = GET_LPDDRAWSURFACE_GBL_MORE( this );
  5386. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY )
  5387. {
  5388. lpGblMore->fpAliasedVidMem = GetAliasedVidMem( pdrv_lcl, this_lcl, this_lcl->lpGbl->fpVidMem );
  5389. // If we succeeded in getting an alias, cache it for future use. Also store the original
  5390. // fpVidMem to compare with before using the cached pointer to make sure the cached value
  5391. // is still valid
  5392. if (lpGblMore->fpAliasedVidMem)
  5393. lpGblMore->fpAliasOfVidMem = this_lcl->lpGbl->fpVidMem;
  5394. else
  5395. lpGblMore->fpAliasOfVidMem = 0;
  5396. }
  5397. else
  5398. {
  5399. lpGblMore->fpAliasedVidMem = 0UL;
  5400. lpGblMore->fpAliasOfVidMem = 0UL;
  5401. }
  5402. }
  5403. #endif /* USE_ALIAS */
  5404. #if 0
  5405. if( lpddsd->dwFlags & DDSD_LPSURFACE )
  5406. {
  5407. #endif //0
  5408. /*
  5409. * Set the access counter to zero (which means ddraw has no information on the moment
  5410. * to moment contents of the surface, so the driver should not cache).
  5411. */
  5412. GET_LPDDRAWSURFACE_GBL_MORE(this)->dwContentsStamp = 0;
  5413. #if 0
  5414. }
  5415. else
  5416. {
  5417. /*
  5418. * Something probably changed
  5419. */
  5420. BUMP_SURFACE_STAMP(this);
  5421. }
  5422. #endif //0
  5423. #ifdef WINNT
  5424. // The DDCreateSurfaceObject call fails when we
  5425. // specify a FOURCC system memory surface with pitch = 0
  5426. // and bits/pixel = 0. We must ensure these parameters
  5427. // are nonzero for the call.
  5428. if ((this_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT) &&
  5429. (this->ddpfSurface.dwFlags & DDPF_FOURCC) &&
  5430. (GetDxtBlkSize(this->ddpfSurface.dwFourCC) != 0))
  5431. {
  5432. LONG blksize;
  5433. WORD dx, dy;
  5434. /*
  5435. * This surface uses a FOURCC format that we understand.
  5436. * Figure out how much memory we allocated for it.
  5437. */
  5438. blksize = GetDxtBlkSize(this->ddpfSurface.dwFourCC);
  5439. DDASSERT(blksize != 0);
  5440. DDASSERT(this->ddpfSurface.dwRGBBitCount == 0);
  5441. DDASSERT(this_lcl->ddsCaps.dwCaps & DDSCAPS_TEXTURE);
  5442. bIsCompressedTexture = TRUE;
  5443. // Save the surface's real width and height so we can restore them.
  5444. realwidth = this->wWidth;
  5445. realheight = this->wHeight;
  5446. realsurfsize = this->dwLinearSize; // union with lPitch
  5447. // The NT kernel won't let us create this surface unless we lie.
  5448. // We have to make up a width, height, pitch, and pixel size
  5449. // that GDI will accept as valid.
  5450. dx = (WORD)((realwidth + 3) >> 2); // number of 4x4 blocks in a row
  5451. dy = (WORD)((realheight + 3) >> 2); // number of 4x4 blocks in a column
  5452. this->wHeight = dy; // lie about height
  5453. this->lPitch = dx*blksize; // lie about pitch
  5454. this->wWidth = (WORD)this->lPitch; // lie about width
  5455. this->ddpfSurface.dwRGBBitCount = 8; // lie about pixel size
  5456. // GDI will reserve lpsurf->wWidth*lpsurf->lPitch bytes of virtual
  5457. // memory for the surface. This had better be equal to the amount
  5458. // of memory we actually allocated for the surface. What a pain.
  5459. DDASSERT(this_lcl->lpSurfMore->dwBytesAllocated ==
  5460. (DWORD)this->wHeight*this->lPitch);
  5461. }
  5462. else if ((this->ddpfSurface.dwFourCC == MAKEFOURCC('U','Y','V','Y')) ||
  5463. (this->ddpfSurface.dwFourCC == MAKEFOURCC('Y','U','Y','2')))
  5464. {
  5465. // These formats are really 8bpp; so we need to adjust
  5466. // the bits-per-pixel parameter to make NT happy
  5467. this->ddpfSurface.dwRGBBitCount = 16;
  5468. }
  5469. /*
  5470. * We deleted the surface object above, so we must create a new
  5471. * surface object before we return.
  5472. */
  5473. if (!DdCreateSurfaceObject(this_lcl, FALSE))
  5474. {
  5475. if(!(DDSCAPS_SYSTEMMEMORY & this_lcl->ddsCaps.dwCaps))
  5476. {
  5477. DPF_ERR("GDI failed to create surface object!");
  5478. LEAVE_DDRAW();
  5479. return DDERR_INVALIDPARAMS;
  5480. }
  5481. }
  5482. if (bIsCompressedTexture)
  5483. {
  5484. // Restore the FOURCC surface's actual width, height, etc.
  5485. this->wWidth = (WORD)realwidth;
  5486. this->wHeight = (WORD)realheight;
  5487. this->dwLinearSize = realsurfsize;
  5488. }
  5489. //(Fix for Manbug 40941)-->
  5490. // The delete also killed any attachments the kernel may have to neighbouring surfaces.
  5491. //If this is a mipmap, then we need to recreate the attachments now, before the CSEx
  5492. //is called.
  5493. //ISSUE: This fix doesn't address:
  5494. // -cubemaps or other more complex attachments
  5495. // -How do we guarantee the right linked list order in the kernel? We'll have
  5496. // to destroy all attachments, then re-attach them again. (The app in question runs
  5497. // the mipmap chain in the correct order to re-create attachments in the kernel's
  5498. // linked list in the right order.)
  5499. // let the kernel know about the attachment only if the driver isn't emulated...
  5500. if ( pdrv->hDD )
  5501. {
  5502. LPATTACHLIST pal;
  5503. // The current surface has been disassociated from the two
  5504. // neighbouring levels. We need to repair two attachments:
  5505. // the next highst level to this level, and then this level
  5506. // to the next lowest level.
  5507. pal = this_lcl->lpAttachList;
  5508. if(pal) //while(pal) might be a better fix
  5509. {
  5510. DdAttachSurface( this_lcl, pal->lpAttached );
  5511. }
  5512. pal = this_lcl->lpAttachListFrom;
  5513. if(pal) //while(pal) might be a better fix
  5514. {
  5515. DdAttachSurface( pal->lpAttached, this_lcl );
  5516. }
  5517. }
  5518. //<--(End fix for Manbug 40941)
  5519. #endif //WINNT
  5520. if(this_lcl->lpSurfMore->dwSurfaceHandle != 0)
  5521. {
  5522. LPDDRAWI_DDRAWSURFACE_LCL lpLcl = GetTopLevel(this_lcl);
  5523. HRESULT HRet;
  5524. DDASSERT( pdrv_lcl == lpLcl->lpSurfMore->lpDD_lcl);
  5525. HRet = createsurfaceEx(lpLcl);
  5526. if (DD_OK != HRet)
  5527. {
  5528. LEAVE_DDRAW();
  5529. return HRet;
  5530. }
  5531. }
  5532. LEAVE_DDRAW();
  5533. return DD_OK;
  5534. } /* DD_Surface_SetSurfaceDesc */
  5535. /*
  5536. * GetNextMipMap
  5537. */
  5538. LPDIRECTDRAWSURFACE GetNextMipMap(
  5539. LPDIRECTDRAWSURFACE lpLevel)
  5540. {
  5541. DDSCAPS ddsCaps;
  5542. LPDDRAWI_DDRAWSURFACE_LCL lpLcl;
  5543. LPATTACHLIST pal;
  5544. if (!lpLevel)
  5545. return NULL;
  5546. lpLcl = ((LPDDRAWI_DDRAWSURFACE_INT)lpLevel)->lpLcl;
  5547. ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
  5548. pal = lpLcl->lpAttachList;
  5549. while( pal != NULL )
  5550. {
  5551. if ( ((pal->lpAttached->ddsCaps.dwCaps) & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
  5552. == (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP) )
  5553. {
  5554. /*
  5555. * Got both the right caps
  5556. */
  5557. return (LPDIRECTDRAWSURFACE) pal->lpIAttached;
  5558. }
  5559. pal = pal->lpLink;
  5560. }
  5561. return NULL;
  5562. }
  5563. /*
  5564. * LateAllocateSurfaceMem
  5565. *
  5566. * Called by the D3D to allocate memory for a compressed surface.
  5567. * The input lpDDSurface must have certain state:
  5568. * -DDSCAPS_VIDEOMEMORY or DDSCAPS_SYSTEMMEMORY are allowed.
  5569. * -DDSCAPS_OPTIMIZED required.
  5570. * -fpVidMem must be either DDHAL_PLEASEALLOC_BLOCKSIZE, DDHAL_PLEASEALLOC_NOMEMORY or DDHAL_PLEASEALLOC_LINEARSIZE
  5571. * -If BLOCKSIZE, the blocksizes must be filled,
  5572. * -If LINEARSIZE, the dwLinearSize must be filled.
  5573. * -If LINEARSIZE is specified. Only the linear heaps will be traversed.
  5574. */
  5575. #undef DPF_MODNAME
  5576. #define DPF_MODNAME "LateAllocateSurfaceMem"
  5577. HRESULT DDAPI LateAllocateSurfaceMem(LPDIRECTDRAWSURFACE lpDDSurface, DWORD dwAllocationType, DWORD dwWidthOrSize, DWORD dwHeight)
  5578. {
  5579. HRESULT ddrval;
  5580. LPDDRAWI_DDRAWSURFACE_INT psurf_int;
  5581. LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
  5582. LPDDRAWI_DDRAWSURFACE_GBL psurf_gbl;
  5583. LPDDRAWI_DDRAWSURFACE_LCL surflist[1];
  5584. LONG lSurfacePitch;
  5585. DPF(2,A,"ENTERAPI: LateAllocSurfaceMem");
  5586. DDASSERT( lpDDSurface != 0 );
  5587. DDASSERT((dwAllocationType == DDHAL_PLEASEALLOC_BLOCKSIZE) || (dwAllocationType == DDHAL_PLEASEALLOC_LINEARSIZE));
  5588. psurf_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  5589. psurf_lcl = psurf_int->lpLcl;
  5590. psurf_gbl = psurf_lcl->lpGbl;
  5591. /*
  5592. * If driver has already filled in some memory for the surface then we'll just clean
  5593. * up some state and return
  5594. */
  5595. if (psurf_gbl->fpVidMem)
  5596. {
  5597. DPF(4,V,"Driver has already allocated some space.");
  5598. psurf_gbl->dwGlobalFlags &= ~DDRAWISURFGBL_MEMFREE;
  5599. psurf_gbl->dwGlobalFlags &= ~DDRAWISURFGBL_LATEALLOCATELINEAR;
  5600. if (dwAllocationType == DDHAL_PLEASEALLOC_LINEARSIZE)
  5601. {
  5602. psurf_gbl->dwGlobalFlags |= DDRAWISURFGBL_LATEALLOCATELINEAR;
  5603. }
  5604. return DD_OK;
  5605. }
  5606. /*
  5607. * If the driver hasn't filled in itself, then we'd better have some sensible
  5608. * input to decide what to do.
  5609. */
  5610. DDASSERT(dwWidthOrSize != 0);
  5611. DDASSERT(dwAllocationType == DDHAL_PLEASEALLOC_LINEARSIZE || dwHeight != 0);
  5612. /*
  5613. * Assert some things that we don't want AllocSurfaceMem to see.
  5614. */
  5615. DDASSERT( (psurf_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) == 0);
  5616. DDASSERT( (psurf_gbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE) == 0);
  5617. if (dwAllocationType == DDHAL_PLEASEALLOC_BLOCKSIZE)
  5618. {
  5619. /*
  5620. * Surface can be allocated in either rectangular or linear heaps.
  5621. * (That's what the FALSE passed to AllocSurfaceMem means)
  5622. */
  5623. psurf_gbl->fpVidMem = (FLATPTR) DDHAL_PLEASEALLOC_BLOCKSIZE;
  5624. psurf_gbl->dwBlockSizeX = dwWidthOrSize;
  5625. psurf_gbl->dwBlockSizeY = dwHeight;
  5626. if (psurf_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
  5627. {
  5628. surflist[0] = psurf_lcl;
  5629. ddrval = AllocSurfaceMem(psurf_lcl->lpSurfMore->lpDD_lcl, surflist, 1 );
  5630. }
  5631. else
  5632. {
  5633. DWORD dwSurfaceSize;
  5634. DDASSERT(psurf_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY);
  5635. ddrval = DDERR_OUTOFMEMORY;
  5636. psurf_gbl->fpVidMem = (FLATPTR) HELAllocateSurfaceSysMem(
  5637. psurf_lcl,
  5638. psurf_gbl->dwBlockSizeX ,
  5639. psurf_gbl->dwBlockSizeY,
  5640. &dwSurfaceSize,
  5641. &lSurfacePitch );
  5642. /*
  5643. * Clean up overloaded fields
  5644. */
  5645. psurf_gbl->lpRectList = NULL;
  5646. psurf_gbl->lpVidMemHeap = NULL;
  5647. }
  5648. if (psurf_gbl->fpVidMem)
  5649. {
  5650. psurf_gbl->dwGlobalFlags &= ~DDRAWISURFGBL_MEMFREE;
  5651. ddrval = DD_OK;
  5652. }
  5653. else
  5654. {
  5655. DPF(0,"Out of memory in LateAllocateSurfaceMem");
  5656. }
  5657. return ddrval;
  5658. }
  5659. else if (dwAllocationType == DDHAL_PLEASEALLOC_LINEARSIZE)
  5660. {
  5661. DWORD dwSurfaceConsumption;
  5662. if (0 == dwWidthOrSize)
  5663. {
  5664. /*
  5665. * Bad driver!
  5666. */
  5667. DPF_ERR("Linear size set to 0 for a DDHAL_PLEASEALLOC_LINEARSIZE surface");
  5668. return DDERR_INVALIDPARAMS;
  5669. }
  5670. dwSurfaceConsumption = dwWidthOrSize;
  5671. psurf_gbl->dwGlobalFlags |= DDRAWISURFGBL_LATEALLOCATELINEAR;
  5672. /*
  5673. * Surface can only live in linear heaps.
  5674. * (That's what the TRUE passed to AllocSurfaceMem means)
  5675. */
  5676. if (psurf_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
  5677. {
  5678. /*
  5679. * Fool around with surface global data so that AllocSurfaceMem
  5680. * will allocate the correct linear size.
  5681. */
  5682. psurf_gbl->dwLinearSize = dwWidthOrSize;
  5683. psurf_gbl->wHeight = 1;
  5684. psurf_gbl->fpVidMem = DDHAL_PLEASEALLOC_LINEARSIZE;
  5685. surflist[0] = psurf_lcl;
  5686. ddrval = AllocSurfaceMem(psurf_lcl->lpSurfMore->lpDD_lcl, surflist, 1 );
  5687. }
  5688. else
  5689. {
  5690. ddrval = DDERR_OUTOFMEMORY;
  5691. DDASSERT(psurf_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY);
  5692. psurf_gbl->fpVidMem = (FLATPTR) HELAllocateSurfaceSysMem(
  5693. psurf_lcl,
  5694. dwWidthOrSize,
  5695. 1 ,
  5696. &dwSurfaceConsumption,
  5697. &lSurfacePitch );
  5698. psurf_gbl->dwLinearSize = dwSurfaceConsumption;
  5699. /*
  5700. * Clean up overloaded fields
  5701. */
  5702. psurf_gbl->lpVidMemHeap = NULL;
  5703. psurf_gbl->lpRectList = NULL;
  5704. }
  5705. if (psurf_gbl->fpVidMem)
  5706. {
  5707. psurf_gbl->dwGlobalFlags &= ~DDRAWISURFGBL_MEMFREE;
  5708. /*
  5709. * The surface's size will be calculated using dwLinearSize
  5710. */
  5711. ddrval = DD_OK;
  5712. }
  5713. else
  5714. {
  5715. /*
  5716. * Failed for some reason.
  5717. */
  5718. psurf_gbl->dwGlobalFlags &= ~DDRAWISURFGBL_LATEALLOCATELINEAR;
  5719. DPF(0,"Out of memory in LateAllocateSurfaceMem");
  5720. }
  5721. return ddrval;
  5722. }
  5723. else
  5724. return DDERR_GENERIC;
  5725. }
  5726. #undef DPF_MODNAME
  5727. #define DPF_MODNAME "Resize"
  5728. #ifdef POSTPONED2
  5729. /*
  5730. * DD_Surface_Resize
  5731. */
  5732. HRESULT DDAPI DD_Surface_Resize(
  5733. LPDIRECTDRAWSURFACE lpDDSurface,
  5734. DWORD dwFlags,
  5735. DWORD dwWidth,
  5736. DWORD dwHeight)
  5737. {
  5738. DWORD rc;
  5739. LPDDHAL_RESIZE pfn;
  5740. DDHAL_RESIZEDATA rszd;
  5741. LPDDRAWI_DDRAWSURFACE_INT this_int;
  5742. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  5743. LPDDRAWI_DDRAWSURFACE_GBL this_gbl;
  5744. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  5745. LPDDRAWI_DIRECTDRAW_GBL pdrv_gbl;
  5746. ENTER_DDRAW();
  5747. DPF(2,A,"ENTERAPI: DD_Surface_Resize");
  5748. TRY
  5749. {
  5750. this_int = (LPDDRAWI_DDRAWSURFACE_INT)lpDDSurface;
  5751. /*
  5752. * Validate surface pointer.
  5753. */
  5754. if (!VALID_DIRECTDRAWSURFACE_PTR(this_int))
  5755. {
  5756. DPF_ERR("Invalid surface object");
  5757. LEAVE_DDRAW();
  5758. return DDERR_INVALIDOBJECT;
  5759. }
  5760. this_lcl = this_int->lpLcl; // internal local surface object
  5761. this_gbl = this_lcl->lpGbl; // internal global surface object
  5762. /*
  5763. * If this surface is in the process of being freed, return immediately.
  5764. */
  5765. if( this_lcl->dwFlags & DDRAWISURF_ISFREE )
  5766. {
  5767. DPF(0, "Can't resize surface that's being freed" );
  5768. LEAVE_DDRAW();
  5769. return DDERR_GENERIC;
  5770. }
  5771. /*
  5772. * Avoid trying to resize an optimized surface.
  5773. */
  5774. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  5775. {
  5776. DPF_ERR( "Can't resize an optimized surface" );
  5777. LEAVE_DDRAW();
  5778. return DDERR_ISOPTIMIZEDSURFACE;
  5779. }
  5780. /*
  5781. * Avoid resizing a primary surface, a texture surface, a surface that is part of a
  5782. * flipping chain or any other complex surface, or a surface that is currently visible.
  5783. */
  5784. if (this_lcl->ddsCaps.dwCaps & (DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_VIDEOPORT |
  5785. DDSCAPS_PRIMARYSURFACE | DDSCAPS_PRIMARYSURFACELEFT |
  5786. DDSCAPS_TEXTURE | DDSCAPS_MIPMAP | // redundant?
  5787. DDSCAPS_EXECUTEBUFFER | DDSCAPS_VISIBLE))
  5788. {
  5789. DPF_ERR("Can't resize visible surface, texture surface, complex surface, or execute buffer");
  5790. LEAVE_DDRAW();
  5791. return DDERR_INVALIDSURFACETYPE;
  5792. }
  5793. /*
  5794. * Avoid resizing an attached surface or a surface that has attached surfaces.
  5795. * (Note: Could have checked DDRAWISURF_ATTACHED and DDRAWISURF_ATTACHED_FROM
  5796. * bits in this_lcl->dwFlags, but these don't appear to be maintained properly.)
  5797. */
  5798. if (this_lcl->lpAttachList != NULL || this_lcl->lpAttachListFrom != NULL)
  5799. {
  5800. DPF_ERR( "Can't resize surface that is attached or that has attached surfaces" );
  5801. LEAVE_DDRAW();
  5802. return DDERR_INVALIDSURFACETYPE;
  5803. }
  5804. /*
  5805. * Avoid resizing a surface to which a D3D device is still attached.
  5806. */
  5807. if (this_lcl->lpSurfMore->lpD3DDevIList != NULL)
  5808. {
  5809. DPF_ERR( "Can't resize a surface that a Direct3D device is still attached to" );
  5810. LEAVE_DDRAW();
  5811. return DDERR_INVALIDSURFACETYPE;
  5812. }
  5813. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl; // internal local DD object
  5814. pdrv_gbl = pdrv_lcl->lpGbl; // internal global DD object
  5815. #ifdef WINNT
  5816. // Update DDraw handle in driver GBL object.
  5817. pdrv_gbl->hDD = pdrv_lcl->hDD;
  5818. #endif //WINNT
  5819. /*
  5820. * Wait for driver to finish with any pending DMA operations
  5821. */
  5822. if( this_gbl->dwGlobalFlags & DDRAWISURFGBL_HARDWAREOPSTARTED )
  5823. {
  5824. WaitForDriverToFinishWithSurface(pdrv_lcl, this_lcl);
  5825. }
  5826. /*
  5827. * Get pointer to driver's HAL callback Resize routine.
  5828. */
  5829. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
  5830. {
  5831. /*
  5832. * Surface resides in video memory. Use hardware driver callback.
  5833. */
  5834. pfn = pdrv_lcl->lpDDCB->HALDDMiscellaneous2.Resize;
  5835. }
  5836. else
  5837. {
  5838. /*
  5839. * Surface resides in system memory. Use HEL emulation routine.
  5840. */
  5841. pfn = pdrv_lcl->lpDDCB->HELDDMiscellaneous2.Resize;
  5842. }
  5843. if (pfn == NULL)
  5844. {
  5845. DPF_ERR("No driver support for Resize");
  5846. LEAVE_DDRAW();
  5847. return DDERR_UNSUPPORTED;
  5848. }
  5849. }
  5850. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  5851. {
  5852. DPF_ERR("Exception encountered validating parameters");
  5853. LEAVE_DDRAW();
  5854. return DDERR_INVALIDPARAMS;
  5855. }
  5856. /*
  5857. * Currently, no flags are defined for the Resize call.
  5858. */
  5859. if (dwFlags)
  5860. {
  5861. DPF_ERR( "dwFlags arg must be zero" );
  5862. LEAVE_DDRAW();
  5863. return DDERR_INVALIDPARAMS;
  5864. }
  5865. /*
  5866. * Validate width and height parameters.
  5867. */
  5868. if (dwWidth < 1 || dwHeight < 1)
  5869. {
  5870. DPF_ERR("Invalid surface width or height specified");
  5871. LEAVE_DDRAW();
  5872. return DDERR_INVALIDPARAMS;
  5873. }
  5874. /*
  5875. * Don't allow implicit surface to be resized.
  5876. */
  5877. if (this_lcl->dwFlags & DDRAWISURF_IMPLICITCREATE)
  5878. {
  5879. DPF_ERR("Can't resize implicitly created surface");
  5880. LEAVE_DDRAW();
  5881. return DDERR_IMPLICITLYCREATED;
  5882. }
  5883. /*
  5884. * Don't allow source surface for visible overlay sprite to be resized.
  5885. */
  5886. if (this_lcl->dwFlags & DDRAWISURF_INMASTERSPRITELIST)
  5887. {
  5888. DPF_ERR("Can't resize source surface for visible overlay sprite");
  5889. LEAVE_DDRAW();
  5890. return DDERR_INVALIDSURFACETYPE;
  5891. }
  5892. /*
  5893. * Don't allow client-allocated surface memory to be resized.
  5894. */
  5895. if (this_gbl->dwGlobalFlags & DDRAWISURFGBL_ISCLIENTMEM)
  5896. {
  5897. DPF_ERR("Can't resize surface with client-allocated memory");
  5898. LEAVE_DDRAW();
  5899. return DDERR_INVALIDSURFACETYPE;
  5900. }
  5901. /*
  5902. * Make sure we are in the same mode the surface was created in.
  5903. */
  5904. #ifdef WIN95
  5905. if (pdrv_gbl->dwModeIndex != this_lcl->dwModeCreatedIn)
  5906. #else
  5907. if (!EQUAL_DISPLAYMODE(pdrv_gbl->dmiCurrent, this_lcl->lpSurfMore->dmiCreated))
  5908. #endif
  5909. {
  5910. DPF_ERR("Not in mode in which surface was created");
  5911. LEAVE_DDRAW();
  5912. return DDERR_WRONGMODE;
  5913. }
  5914. /*
  5915. * Device busy?
  5916. */
  5917. if (*(pdrv_gbl->lpwPDeviceFlags) & BUSY)
  5918. {
  5919. DPF_ERR("Can't resize locked surface");
  5920. LEAVE_DDRAW();
  5921. return DDERR_SURFACEBUSY;
  5922. }
  5923. BUMP_SURFACE_STAMP(this_gbl);
  5924. #ifdef WINNT
  5925. /*
  5926. * Once we delete the surface object, we are committed to
  5927. * creating a new surface object before we return. This is true
  5928. * regardless of whether we succeed in resizing the surface.
  5929. */
  5930. if (!DdDeleteSurfaceObject(this_lcl))
  5931. {
  5932. /*
  5933. * Something is terribly wrong with GDI and/or DDraw!
  5934. */
  5935. DPF_ERR("GDI failed to delete surface object!");
  5936. LEAVE_DDRAW();
  5937. return DDERR_GENERIC;
  5938. }
  5939. #endif //WINNT
  5940. /*
  5941. * Now call the driver to resize the surface for us.
  5942. */
  5943. rszd.lpDD = pdrv_gbl;
  5944. rszd.lpDDSurface = this_lcl;
  5945. rszd.dwFlags = dwFlags;
  5946. rszd.dwWidth = dwWidth;
  5947. rszd.dwHeight = dwHeight;
  5948. rszd.ddRVal = 0;
  5949. // The following definition allows DOHALCALL to be used
  5950. // with thunkless, 32-bit callback.
  5951. #define _DDHAL_Resize NULL
  5952. DOHALCALL(Resize, pfn, rszd, rc, 0);
  5953. /*
  5954. * If driver callback succeeded, DirectDraw is responsible for
  5955. * updating the surface's width, height, etc.
  5956. */
  5957. if (rszd.ddRVal == DD_OK)
  5958. {
  5959. // Driver should have set these parameters itself:
  5960. DDASSERT(this_gbl->fpVidMem != (FLATPTR)NULL);
  5961. DDASSERT(this_lcl->lpSurfMore->dwBytesAllocated != 0);
  5962. // Update surface parameters.
  5963. this_gbl->wWidth = (WORD)dwWidth;
  5964. this_gbl->wHeight = (WORD)dwHeight;
  5965. this_lcl->dwFlags &= ~DDRAWISURF_INVALID;
  5966. this_gbl->dwGlobalFlags &= ~DDRAWISURFGBL_MEMFREE;
  5967. }
  5968. #ifdef WINNT
  5969. /*
  5970. * We deleted the surface object above, so we must create a new
  5971. * surface object before we return. This is true regardless of
  5972. * whether the driver call succeeded in resizing the surface.
  5973. */
  5974. if (!DdCreateSurfaceObject(this_lcl, FALSE))
  5975. {
  5976. if(!(DDSCAPS_SYSTEMMEMORY & this_lcl->ddsCaps.dwCaps))
  5977. {
  5978. /*
  5979. * We hope this is rare and pathological condition because we
  5980. * just destroyed the surface object the client gave us. Oops.
  5981. */
  5982. DPF_ERR("GDI failed to create surface object!");
  5983. rszd.ddRVal = DDERR_GENERIC;
  5984. }
  5985. }
  5986. #endif //WINNT
  5987. if (rc != DDHAL_DRIVER_HANDLED)
  5988. {
  5989. DPF_ERR("Driver wouldn't handle callback");
  5990. LEAVE_DDRAW();
  5991. return DDERR_UNSUPPORTED;
  5992. }
  5993. LEAVE_DDRAW();
  5994. return rszd.ddRVal;
  5995. } /* DD_Surface_Resize */
  5996. #endif //POSTPONED2
  5997. #undef DPF_MODNAME
  5998. #define DPF_MODNAME "SetPriority"
  5999. HRESULT DDAPI DD_Surface_SetPriority(LPDIRECTDRAWSURFACE7 lpDDSurface, DWORD dwPriority)
  6000. {
  6001. HRESULT rc;
  6002. LPDDRAWI_DDRAWSURFACE_INT this_int;
  6003. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  6004. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  6005. #if DBG
  6006. DPF(2,A,"ENTERAPI: DD_Surface_SetPriority");
  6007. TRY
  6008. {
  6009. #endif
  6010. this_int = (LPDDRAWI_DDRAWSURFACE_INT)lpDDSurface;
  6011. #if DBG
  6012. /*
  6013. * Validate surface pointer.
  6014. */
  6015. if (!VALID_DIRECTDRAWSURFACE_PTR(this_int))
  6016. {
  6017. DPF_ERR("Invalid surface object");
  6018. return DDERR_INVALIDOBJECT;
  6019. }
  6020. #endif
  6021. this_lcl = this_int->lpLcl; // internal local surface object
  6022. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl; // internal local DD object
  6023. #if DBG
  6024. }
  6025. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  6026. {
  6027. DPF_ERR("Exception encountered validating parameters");
  6028. return DDERR_INVALIDPARAMS;
  6029. }
  6030. if(!IsToplevel(this_lcl))
  6031. {
  6032. DPF_ERR( "Cannot set priority on a mipmap sublevel or a cubemap subface" );
  6033. return DDERR_INVALIDPARAMS;
  6034. }
  6035. if(this_lcl->lpSurfMore->lpTex == NULL)
  6036. {
  6037. DPF_ERR("SetPriority can only be called on a managed texture");
  6038. return DDERR_INVALIDOBJECT;
  6039. }
  6040. if( pdrv_lcl->pD3DSetPriority == NULL )
  6041. {
  6042. DPF_ERR("D3D is not yet initialized or app didn't use DirectDrawCreateEx");
  6043. return DDERR_D3DNOTINITIALIZED;
  6044. }
  6045. #endif
  6046. if(pdrv_lcl->dwLocalFlags & DDRAWILCL_MULTITHREADED)
  6047. {
  6048. ENTER_DDRAW();
  6049. rc = pdrv_lcl->pD3DSetPriority(this_lcl->lpSurfMore->lpTex, dwPriority);
  6050. LEAVE_DDRAW();
  6051. }
  6052. else
  6053. {
  6054. rc = pdrv_lcl->pD3DSetPriority(this_lcl->lpSurfMore->lpTex, dwPriority);
  6055. }
  6056. return rc;
  6057. }
  6058. #undef DPF_MODNAME
  6059. #define DPF_MODNAME "GetPriority"
  6060. HRESULT DDAPI DD_Surface_GetPriority(LPDIRECTDRAWSURFACE7 lpDDSurface, LPDWORD lpdwPriority)
  6061. {
  6062. HRESULT rc;
  6063. LPDDRAWI_DDRAWSURFACE_INT this_int;
  6064. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  6065. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  6066. ENTER_DDRAW();
  6067. DPF(2,A,"ENTERAPI: DD_Surface_GetPriority");
  6068. TRY
  6069. {
  6070. this_int = (LPDDRAWI_DDRAWSURFACE_INT)lpDDSurface;
  6071. /*
  6072. * Validate surface pointer.
  6073. */
  6074. if (!VALID_DIRECTDRAWSURFACE_PTR(this_int))
  6075. {
  6076. DPF_ERR("Invalid surface object");
  6077. LEAVE_DDRAW();
  6078. return DDERR_INVALIDOBJECT;
  6079. }
  6080. /*
  6081. * Validate DWORD pointer.
  6082. */
  6083. if (!VALID_DWORD_PTR( lpdwPriority ))
  6084. {
  6085. DPF_ERR("Invalid DWORD pointer");
  6086. LEAVE_DDRAW();
  6087. return DDERR_INVALIDOBJECT;
  6088. }
  6089. this_lcl = this_int->lpLcl; // internal local surface object
  6090. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl; // internal local DD object
  6091. }
  6092. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  6093. {
  6094. DPF_ERR("Exception encountered validating parameters");
  6095. LEAVE_DDRAW();
  6096. return DDERR_INVALIDPARAMS;
  6097. }
  6098. if(!IsToplevel(this_lcl))
  6099. {
  6100. DPF_ERR( "Cannot get priority from a mipmap sublevel or a cubemap subface" );
  6101. LEAVE_DDRAW();
  6102. return DDERR_INVALIDPARAMS;
  6103. }
  6104. if(this_lcl->lpSurfMore->lpTex == NULL)
  6105. {
  6106. DPF_ERR("GetPriority can only be called on a managed texture");
  6107. LEAVE_DDRAW();
  6108. return DDERR_INVALIDOBJECT;
  6109. }
  6110. if( pdrv_lcl->pD3DGetPriority == NULL )
  6111. {
  6112. DPF_ERR("D3D is not yet initialized or app didn't use DirectDrawCreateEx");
  6113. LEAVE_DDRAW();
  6114. return DDERR_D3DNOTINITIALIZED;
  6115. }
  6116. rc = pdrv_lcl->pD3DGetPriority(this_lcl->lpSurfMore->lpTex, lpdwPriority);
  6117. LEAVE_DDRAW();
  6118. return rc;
  6119. }
  6120. #undef DPF_MODNAME
  6121. #define DPF_MODNAME "SetLOD"
  6122. HRESULT DDAPI DD_Surface_SetLOD(LPDIRECTDRAWSURFACE7 lpDDSurface, DWORD dwLOD)
  6123. {
  6124. HRESULT rc;
  6125. LPDDRAWI_DDRAWSURFACE_INT this_int;
  6126. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  6127. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  6128. ENTER_DDRAW();
  6129. DPF(2,A,"ENTERAPI: DD_Surface_SetLOD");
  6130. TRY
  6131. {
  6132. this_int = (LPDDRAWI_DDRAWSURFACE_INT)lpDDSurface;
  6133. /*
  6134. * Validate surface pointer.
  6135. */
  6136. if (!VALID_DIRECTDRAWSURFACE_PTR(this_int))
  6137. {
  6138. DPF_ERR("Invalid surface object");
  6139. LEAVE_DDRAW();
  6140. return DDERR_INVALIDOBJECT;
  6141. }
  6142. this_lcl = this_int->lpLcl; // internal local surface object
  6143. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl; // internal local DD object
  6144. }
  6145. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  6146. {
  6147. DPF_ERR("Exception encountered validating parameters");
  6148. LEAVE_DDRAW();
  6149. return DDERR_INVALIDPARAMS;
  6150. }
  6151. if(!IsToplevel(this_lcl))
  6152. {
  6153. DPF_ERR( "Cannot set LOD on a mipmap sublevel or a cubemap subface" );
  6154. LEAVE_DDRAW();
  6155. return DDERR_INVALIDPARAMS;
  6156. }
  6157. if(this_lcl->lpSurfMore->lpTex == NULL)
  6158. {
  6159. DPF_ERR("SetLOD can only be called on a managed texture");
  6160. LEAVE_DDRAW();
  6161. return DDERR_INVALIDOBJECT;
  6162. }
  6163. if( pdrv_lcl->pD3DSetLOD == NULL )
  6164. {
  6165. DPF_ERR("D3D is not yet initialized or app didn't use DirectDrawCreateEx");
  6166. LEAVE_DDRAW();
  6167. return DDERR_D3DNOTINITIALIZED;
  6168. }
  6169. rc = pdrv_lcl->pD3DSetLOD(this_lcl->lpSurfMore->lpTex, dwLOD);
  6170. LEAVE_DDRAW();
  6171. return rc;
  6172. }
  6173. #undef DPF_MODNAME
  6174. #define DPF_MODNAME "GetLOD"
  6175. HRESULT DDAPI DD_Surface_GetLOD(LPDIRECTDRAWSURFACE7 lpDDSurface, LPDWORD lpdwLOD)
  6176. {
  6177. HRESULT rc;
  6178. LPDDRAWI_DDRAWSURFACE_INT this_int;
  6179. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  6180. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  6181. ENTER_DDRAW();
  6182. DPF(2,A,"ENTERAPI: DD_Surface_GetLOD");
  6183. TRY
  6184. {
  6185. this_int = (LPDDRAWI_DDRAWSURFACE_INT)lpDDSurface;
  6186. /*
  6187. * Validate surface pointer.
  6188. */
  6189. if (!VALID_DIRECTDRAWSURFACE_PTR(this_int))
  6190. {
  6191. DPF_ERR("Invalid surface object");
  6192. LEAVE_DDRAW();
  6193. return DDERR_INVALIDOBJECT;
  6194. }
  6195. /*
  6196. * Validate DWORD pointer.
  6197. */
  6198. if (!VALID_DWORD_PTR( lpdwLOD ))
  6199. {
  6200. DPF_ERR("Invalid DWORD pointer");
  6201. LEAVE_DDRAW();
  6202. return DDERR_INVALIDOBJECT;
  6203. }
  6204. this_lcl = this_int->lpLcl; // internal local surface object
  6205. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl; // internal local DD object
  6206. }
  6207. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  6208. {
  6209. DPF_ERR("Exception encountered validating parameters");
  6210. LEAVE_DDRAW();
  6211. return DDERR_INVALIDPARAMS;
  6212. }
  6213. if(!IsToplevel(this_lcl))
  6214. {
  6215. DPF_ERR( "Cannot get LOD from a mipmap sublevel or a cubemap subface" );
  6216. LEAVE_DDRAW();
  6217. return DDERR_INVALIDPARAMS;
  6218. }
  6219. if(this_lcl->lpSurfMore->lpTex == NULL)
  6220. {
  6221. DPF_ERR("GetLOD can only be called on a managed texture");
  6222. LEAVE_DDRAW();
  6223. return DDERR_INVALIDOBJECT;
  6224. }
  6225. if( pdrv_lcl->pD3DGetLOD == NULL )
  6226. {
  6227. DPF_ERR("D3D is not yet initialized or app didn't use DirectDrawCreateEx");
  6228. LEAVE_DDRAW();
  6229. return DDERR_D3DNOTINITIALIZED;
  6230. }
  6231. rc = pdrv_lcl->pD3DGetLOD(this_lcl->lpSurfMore->lpTex, lpdwLOD);
  6232. LEAVE_DDRAW();
  6233. return rc;
  6234. }