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.

3096 lines
102 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: ddraw.c
  6. * Content: DirectDraw object support
  7. * History:
  8. * Date By Reason
  9. * ==== == ======
  10. * 25-dec-94 craige initial implementation
  11. * 13-jan-95 craige re-worked to updated spec + ongoing work
  12. * 21-jan-95 craige made 32-bit + ongoing work
  13. * 31-jan-95 craige and even more ongoing work...
  14. * 21-feb-95 craige disconnect anyone who forgot to do it themselves
  15. * 27-feb-95 craige new sync. macros
  16. * 01-mar-95 craige flags to Get/SetExclusiveMode
  17. * 03-mar-95 craige DuplicateSurface
  18. * 08-mar-95 craige GetFourCCCodes, FreeAllSurfaces, GarbageCollect
  19. * 19-mar-95 craige use HRESULTs
  20. * 20-mar-95 craige new CSECT work
  21. * 26-mar-95 craige driver wide color keys for overlays
  22. * 28-mar-95 craige added FlipToGDISurface; removed Get/SetColorKey
  23. * 01-apr-95 craige happy fun joy updated header file
  24. * 06-apr-95 craige fill in free video memory
  25. * 13-apr-95 craige EricEng's little contribution to our being late
  26. * 15-apr-95 craige implement FlipToGDISurface
  27. * 06-may-95 craige use driver-level csects only
  28. * 14-may-95 craige disable CTRL_ALT_DEL if exclusive fullscreen
  29. * 19-may-95 craige check DDSEMO_ALLOWREBOOT before disabling CAD
  30. * 22-may-95 craige use MemAlloc16 for sel. allocation
  31. * 23-may-95 craige have GetCaps return HEL caps
  32. * 28-may-95 craige implement FreeAllSurfaces; unicode support;
  33. * HAL cleanup: entry for GetScanLine
  34. * 05-jun-95 craige removed GetVersion, FreeAllSurfaces, DefWindowProc;
  35. * change GarbageCollect to Compact
  36. * 07-jun-95 craige added StartExclusiveMode
  37. * 12-jun-95 craige new process list stuff
  38. * 16-jun-95 craige removed fpVidMemOrig
  39. * 17-jun-95 craige new surface structure
  40. * 18-jun-95 craige new DuplicateSurface code
  41. * 20-jun-95 craige need to check fpVidMemOrig for deciding to flip
  42. * 24-jun-95 craige don't hide/show cursor - up to app
  43. * 25-jun-95 craige pay attention to DDCKEY_COLORSPACE; allow NULL ckey;
  44. * one ddraw mutex
  45. * 26-jun-95 craige reorganized surface structure
  46. * 27-jun-95 craige return num of 4cc codes if NULL array specified.
  47. * 28-jun-95 craige ENTER_DDRAW at very start of fns
  48. * 30-jun-95 kylej use GetProcessPrimary instead of lpPrimarySurface,
  49. * invalid all primaries when starting exclusive mode
  50. * 30-jun-95 craige turn off all hot keys
  51. * 01-jul-95 craige require fullscreen for excl. mode
  52. * 03-jul-95 craige YEEHAW: new driver struct; SEH
  53. * 05-jul-95 craige added internal FlipToGDISurface
  54. * 06-jul-95 craige added Initialize
  55. * 08-jul-95 craige added FindProcessDDObject
  56. * 08-jul-95 kylej Handle exclusive mode palettes correctly
  57. * 09-jul-95 craige SetExclusiveMode->SetCooperativeLevel;
  58. * flush all service when exclusive mode set;
  59. * check style for SetCooperativeLevel
  60. * 16-jul-95 craige hook hwnd always
  61. * 17-jul-95 craige return unsupported from GetMonitorFrequency if not avail
  62. * 20-jul-95 craige don't set palette unless palettized
  63. * 22-jul-95 craige bug 230 - unsupported starting modes
  64. * 01-aug-95 craige bug 286 - GetCaps should fail if both parms NULL
  65. * 13-aug-95 craige new parms to flip
  66. * 13-aug-95 toddla added DDSCL_DONTHOOKHWND
  67. * 20-aug-95 toddla added DDSCL_ALLOWMODEX
  68. * 21-aug-95 craige mode X support
  69. * 25-aug-95 craige bug 671
  70. * 26-aug-95 craige bug 717
  71. * 26-aug-95 craige bug 738
  72. * 04-sep-95 craige bug 895: toggle GetVerticalBlankStatus result in emul.
  73. * 22-sep-95 craige bug 1275: return # of 4cc codes copied
  74. * 15-nov-95 jeffno Initial NT changes: ifdef out all but last routine
  75. * 27-nov-95 colinmc new member to return the available vram of a given
  76. * type (defined by DDSCAPS).
  77. * 10-dec-95 colinmc added execute buffer support
  78. * 18-dec-95 colinmc additional surface caps checking for
  79. * GetAvailableVidMem member
  80. * 26-dec-95 craige implement DD_Initialize
  81. * 02-jan-96 kylej handle new interface structures
  82. * 26-jan-96 jeffno Teensy change in DoneExclusiveMode: bug when only 1 mode avail.
  83. * 14-feb-96 kylej Allow NULL hwnd for non-exclusive SetCooperativeLevel
  84. * 05-mar-96 colinmc Bug 11928: Fixed DuplicateSurface problem caused by
  85. * failing to initialize the back pointer to the
  86. * DirectDraw object
  87. * 13-mar-96 craige Bug 7528: hw that doesn't have modex
  88. * 22-mar-96 colinmc Bug 13316: uninitialized interfaces
  89. * 10-apr-96 colinmc Bug 16903: HEL uses obsolete FindProcessDDObject
  90. * 13-apr-96 colinmc Bug 17736: No driver notification of flip to GDI
  91. * 14-apr-96 colinmc Bug 16855: Can't pass NULL to initialize
  92. * 03-may-96 kylej Bug 19125: Preserve V1 SetCooperativeLevel behaviour
  93. * 27-may-96 colinmc Bug 24465: SetCooperativeLevel(..., DDSCL_NORMAL)
  94. * needs to ensure we are looking at the GDI surface
  95. * 01-oct-96 ketand Use GetAvailDriverMemory to free/total vidmem estimates
  96. * 12-oct-96 colinmc Improvements to Win16 locking code to reduce virtual
  97. * memory usage
  98. * 21-jan-97 ketand Deleted unused Get/SetColorKey. Put existing DDraw windowed
  99. * apps into emulation on multi-mon systems.
  100. * 30-jan-97 colinmc Work item 4125: Need time bomb for final
  101. * 29-jan-97 jeffno Mode13 support. Just debugging changes.
  102. * 07-feb-97 ketand Fix Multi-Mon when running EMULATION_ONLY and going full-screen
  103. * 08-mar-97 colinmc Support for DMA model AGP parts
  104. * 24-mar-97 jeffno Optimized Surfaces
  105. * 30-sep-97 jeffno IDirectDraw4
  106. *
  107. ***************************************************************************/
  108. #include "ddrawpr.h"
  109. #include "dx8priv.h"
  110. /*
  111. * Caps bits that we don't allow to be specified when asking for
  112. * available video memory. These are bits which don't effect the
  113. * allocation of the surface in a vram heap.
  114. */
  115. #define AVAILVIDMEM_BADSCAPS (DDSCAPS_BACKBUFFER | \
  116. DDSCAPS_FRONTBUFFER | \
  117. DDSCAPS_COMPLEX | \
  118. DDSCAPS_FLIP | \
  119. DDSCAPS_OWNDC | \
  120. DDSCAPS_PALETTE | \
  121. DDSCAPS_SYSTEMMEMORY | \
  122. DDSCAPS_VISIBLE | \
  123. DDSCAPS_WRITEONLY)
  124. extern BYTE szDeviceWndClass[];
  125. extern LRESULT WINAPI DeviceWindowProc( HWND, UINT, WPARAM, LPARAM );
  126. #undef DPF_MODNAME
  127. #define DPF_MODNAME "GetVerticalBlankStatus"
  128. #if defined(WIN95) || defined(NT_FIX)
  129. __inline static BOOL IN_VBLANK( void )
  130. {
  131. BOOL rc;
  132. _asm
  133. {
  134. xor eax,eax
  135. mov dx,03dah ;status reg. port on color card
  136. in al,dx ;read the status
  137. and al,8 ;test whether beam is currently in retrace
  138. mov rc,eax
  139. }
  140. return rc;
  141. }
  142. #define IN_DISPLAY() (!IN_VBLANK())
  143. #endif
  144. /*
  145. * DD_GetVerticalBlankStatus
  146. */
  147. HRESULT DDAPI DD_GetVerticalBlankStatus(
  148. LPDIRECTDRAW lpDD,
  149. LPBOOL lpbIsInVB )
  150. {
  151. LPDDRAWI_DIRECTDRAW_INT this_int;
  152. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  153. LPDDRAWI_DIRECTDRAW_GBL this;
  154. LPDDHAL_WAITFORVERTICALBLANK wfvbhalfn;
  155. LPDDHAL_WAITFORVERTICALBLANK wfvbfn;
  156. ENTER_DDRAW();
  157. /* Removed because too many: DPF(2,A,"ENTERAPI: DD_GetVerticalBlankStatus"); */
  158. TRY
  159. {
  160. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  161. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  162. {
  163. LEAVE_DDRAW();
  164. return DDERR_INVALIDOBJECT;
  165. }
  166. this_lcl = this_int->lpLcl;
  167. this = this_lcl->lpGbl;
  168. #ifdef WINNT
  169. // Update DDraw handle in driver GBL object.
  170. this->hDD = this_lcl->hDD;
  171. #endif //WINNT
  172. if( !VALID_BOOL_PTR( lpbIsInVB ) )
  173. {
  174. DPF_ERR( "Invalid BOOL pointer" );
  175. LEAVE_DDRAW();
  176. return DDERR_INVALIDPARAMS;
  177. }
  178. }
  179. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  180. {
  181. DPF_ERR( "Exception encountered validating parameters" );
  182. LEAVE_DDRAW();
  183. return DDERR_INVALIDPARAMS;
  184. }
  185. /*
  186. * ask the driver test the VB status
  187. */
  188. #pragma message( REMIND( "Need HEL WaitForVerticalBlank (for NT too!)" ))
  189. #if defined (WIN95) || defined ( NT_FIX )
  190. if( this->dwFlags & DDRAWI_MODEX )
  191. {
  192. *lpbIsInVB = FALSE;
  193. if( IN_VBLANK() )
  194. {
  195. *lpbIsInVB = TRUE;
  196. }
  197. LEAVE_DDRAW();
  198. return DD_OK;
  199. }
  200. else
  201. #endif
  202. {
  203. wfvbfn = this_lcl->lpDDCB->HALDD.WaitForVerticalBlank;
  204. wfvbhalfn = this_lcl->lpDDCB->cbDDCallbacks.WaitForVerticalBlank;
  205. if( wfvbhalfn != NULL )
  206. {
  207. DDHAL_WAITFORVERTICALBLANKDATA wfvbd;
  208. DWORD rc;
  209. wfvbd.WaitForVerticalBlank = wfvbhalfn;
  210. wfvbd.lpDD = this;
  211. wfvbd.dwFlags = DDWAITVB_I_TESTVB;
  212. wfvbd.hEvent = 0;
  213. DOHALCALL( WaitForVerticalBlank, wfvbfn, wfvbd, rc, FALSE );
  214. if( rc == DDHAL_DRIVER_HANDLED )
  215. {
  216. *lpbIsInVB = wfvbd.bIsInVB;
  217. LEAVE_DDRAW();
  218. return wfvbd.ddRVal;
  219. }
  220. }
  221. }
  222. /*
  223. * no hardware support, so just pretend it works
  224. */
  225. {
  226. static BOOL bLast=FALSE;
  227. *lpbIsInVB = bLast;
  228. bLast = !bLast;
  229. }
  230. LEAVE_DDRAW();
  231. return DD_OK;
  232. } /* DD_GetVerticalBlankStatus */
  233. #undef DPF_MODNAME
  234. #define DPF_MODNAME "GetScanLine"
  235. /*
  236. * DD_GetScanLine
  237. */
  238. HRESULT DDAPI DD_GetScanLine(
  239. LPDIRECTDRAW lpDD,
  240. LPDWORD lpdwScanLine )
  241. {
  242. LPDDRAWI_DIRECTDRAW_INT this_int;
  243. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  244. LPDDRAWI_DIRECTDRAW_GBL this;
  245. LPDDHAL_GETSCANLINE gslhalfn;
  246. LPDDHAL_GETSCANLINE gslfn;
  247. ENTER_DDRAW();
  248. DPF(2,A,"ENTERAPI: DD_GetScanLine");
  249. TRY
  250. {
  251. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  252. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  253. {
  254. LEAVE_DDRAW();
  255. return DDERR_INVALIDOBJECT;
  256. }
  257. this_lcl = this_int->lpLcl;
  258. this = this_lcl->lpGbl;
  259. #ifdef WINNT
  260. // Update DDraw handle in driver GBL object.
  261. this->hDD = this_lcl->hDD;
  262. #endif //WINNT
  263. if( !VALID_DWORD_PTR( lpdwScanLine ) )
  264. {
  265. DPF_ERR( "Invalid scan line pointer" );
  266. LEAVE_DDRAW();
  267. return DDERR_INVALIDPARAMS;
  268. }
  269. }
  270. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  271. {
  272. DPF_ERR( "Exception encountered validating parameters" );
  273. LEAVE_DDRAW();
  274. return DDERR_INVALIDPARAMS;
  275. }
  276. /*
  277. * ask the driver to get the current scanline
  278. */
  279. #pragma message( REMIND( "Need HEL GetScanLine" ))
  280. gslfn = this_lcl->lpDDCB->HALDD.GetScanLine;
  281. gslhalfn = this_lcl->lpDDCB->cbDDCallbacks.GetScanLine;
  282. if( gslhalfn != NULL )
  283. {
  284. DDHAL_GETSCANLINEDATA gsld;
  285. DWORD rc;
  286. gsld.GetScanLine = gslhalfn;
  287. gsld.lpDD = this;
  288. DOHALCALL( GetScanLine, gslfn, gsld, rc, FALSE );
  289. if( rc == DDHAL_DRIVER_HANDLED )
  290. {
  291. *lpdwScanLine = gsld.dwScanLine;
  292. LEAVE_DDRAW();
  293. return gsld.ddRVal;
  294. }
  295. }
  296. *lpdwScanLine = 0;
  297. LEAVE_DDRAW();
  298. return DDERR_UNSUPPORTED;
  299. } /* DD_GetScanLine */
  300. #undef DPF_MODNAME
  301. #define DPF_MODNAME "BuildDDCAPS"
  302. /*
  303. * Build a fullsized, API visible DDCAPS structure from the multiple internal
  304. * caps structures in the global driver object.
  305. */
  306. static void BuildDDCAPS( LPDDCAPS lpddcaps, LPDDRAWI_DIRECTDRAW_GBL pdrv, BOOL bHEL )
  307. {
  308. LPDDCORECAPS lpddcorecaps;
  309. LPDDNONLOCALVIDMEMCAPS lpddnlvcaps;
  310. LPDDMORECAPS lpddmorecaps;
  311. LPDDSCAPSEX lpddsExCaps;
  312. DDASSERT( NULL != lpddcaps );
  313. DDASSERT( NULL != pdrv );
  314. lpddcorecaps = ( bHEL ? &( pdrv->ddHELCaps ) : &( pdrv->ddCaps ) );
  315. lpddnlvcaps = ( bHEL ? pdrv->lpddNLVHELCaps : pdrv->lpddNLVCaps );
  316. lpddmorecaps = ( bHEL ? pdrv->lpddHELMoreCaps : pdrv->lpddMoreCaps );
  317. lpddsExCaps = ( bHEL ? &pdrv->ddsHELCapsMore : &pdrv->ddsCapsMore );
  318. memset( lpddcaps, 0, sizeof( DDCAPS ) );
  319. memcpy( lpddcaps, lpddcorecaps, sizeof( DDCORECAPS ) );
  320. if( NULL != lpddnlvcaps )
  321. {
  322. lpddcaps->dwNLVBCaps = lpddnlvcaps->dwNLVBCaps;
  323. lpddcaps->dwNLVBCaps2 = lpddnlvcaps->dwNLVBCaps2;
  324. lpddcaps->dwNLVBCKeyCaps = lpddnlvcaps->dwNLVBCKeyCaps;
  325. lpddcaps->dwNLVBFXCaps = lpddnlvcaps->dwNLVBFXCaps;
  326. memcpy( &( lpddcaps->dwNLVBRops[0] ), &( lpddnlvcaps->dwNLVBRops[0] ), DD_ROP_SPACE * sizeof( DWORD ) );
  327. }
  328. lpddcaps->ddsCaps.dwCaps = lpddcorecaps->ddsCaps.dwCaps;
  329. memcpy(&lpddcaps->ddsCaps.ddsCapsEx, lpddsExCaps, sizeof(lpddcaps->ddsCaps.ddsCapsEx) );
  330. if (lpddmorecaps != NULL)
  331. {
  332. #ifdef POSTPONED2
  333. lpddcaps->dwAlphaCaps = lpddmorecaps->dwAlphaCaps;
  334. lpddcaps->dwSVBAlphaCaps = lpddmorecaps->dwSVBAlphaCaps;
  335. lpddcaps->dwVSBAlphaCaps = lpddmorecaps->dwVSBAlphaCaps;
  336. lpddcaps->dwSSBAlphaCaps = lpddmorecaps->dwSSBAlphaCaps;
  337. lpddcaps->dwFilterCaps = lpddmorecaps->dwFilterCaps;
  338. lpddcaps->dwSVBFilterCaps = lpddmorecaps->dwSVBFilterCaps;
  339. lpddcaps->dwVSBFilterCaps = lpddmorecaps->dwVSBFilterCaps;
  340. lpddcaps->dwSSBFilterCaps = lpddmorecaps->dwSSBFilterCaps;
  341. lpddcaps->dwTransformCaps = lpddmorecaps->dwTransformCaps;
  342. lpddcaps->dwSVBTransformCaps = lpddmorecaps->dwSVBTransformCaps;
  343. lpddcaps->dwVSBTransformCaps = lpddmorecaps->dwVSBTransformCaps;
  344. lpddcaps->dwSSBTransformCaps = lpddmorecaps->dwSSBTransformCaps;
  345. lpddcaps->dwBltAffineMinifyLimit = lpddmorecaps->dwBltAffineMinifyLimit;
  346. lpddcaps->dwOverlayAffineMinifyLimit = lpddmorecaps->dwOverlayAffineMinifyLimit;
  347. #endif //POSTPONED2
  348. }
  349. lpddcaps->dwSize = sizeof( DDCAPS );
  350. } /* BuildDDCAPS */
  351. #undef DPF_MODNAME
  352. #define DPF_MODNAME "GetCaps"
  353. /*
  354. * DD_GetCaps
  355. *
  356. * Retrieve all driver capabilites
  357. */
  358. HRESULT DDAPI DD_GetCaps(
  359. LPDIRECTDRAW lpDD,
  360. LPDDCAPS lpDDDriverCaps,
  361. LPDDCAPS lpDDHELCaps )
  362. {
  363. LPDDRAWI_DIRECTDRAW_INT this_int;
  364. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  365. LPDDRAWI_DIRECTDRAW_GBL this;
  366. DWORD dwSize;
  367. DDCAPS ddcaps;
  368. DDSCAPS ddscaps;
  369. ENTER_DDRAW();
  370. DPF(2,A,"ENTERAPI: DD_GetCaps");
  371. TRY
  372. {
  373. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  374. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  375. {
  376. LEAVE_DDRAW();
  377. return DDERR_INVALIDOBJECT;
  378. }
  379. this_lcl = this_int->lpLcl;
  380. this = this_lcl->lpGbl;
  381. if( (lpDDDriverCaps == NULL) && (lpDDHELCaps == NULL) )
  382. {
  383. DPF_ERR( "Must specify at least one of driver or emulation caps" );
  384. LEAVE_DDRAW();
  385. return DDERR_INVALIDPARAMS;
  386. }
  387. if( lpDDDriverCaps != NULL )
  388. {
  389. if( !VALID_DDCAPS_PTR( lpDDDriverCaps ) )
  390. {
  391. DPF_ERR( "Invalid driver caps pointer" );
  392. LEAVE_DDRAW();
  393. return DDERR_INVALIDPARAMS;
  394. }
  395. }
  396. if( lpDDHELCaps != NULL )
  397. {
  398. if( !VALID_DDCAPS_PTR( lpDDHELCaps ) )
  399. {
  400. DPF_ERR( "Invalid hel caps pointer" );
  401. LEAVE_DDRAW();
  402. return DDERR_INVALIDPARAMS;
  403. }
  404. }
  405. }
  406. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  407. {
  408. DPF_ERR( "Exception encountered validating parameters" );
  409. LEAVE_DDRAW();
  410. return DDERR_INVALIDPARAMS;
  411. }
  412. /*
  413. * fill in caps fields
  414. */
  415. if( lpDDDriverCaps != NULL)
  416. {
  417. /*
  418. * We now have to assemble the final, API visible caps from multiple
  419. * sub-components scattered through the driver object. To make the size
  420. * computation simple we just build a full, API sized DDCAPS and then
  421. * just copy the appropritate portion of it. Cheesy in that involves an
  422. * extra copy of the data but very simple. This should not be performance
  423. * critical code to start with.
  424. */
  425. BuildDDCAPS( &ddcaps, this, FALSE );
  426. dwSize = lpDDDriverCaps->dwSize;
  427. ZeroMemory( lpDDDriverCaps, dwSize);
  428. memcpy( lpDDDriverCaps, &ddcaps, dwSize );
  429. lpDDDriverCaps->dwSize = dwSize;
  430. /*
  431. * Execute buffers are invisible to the user level API
  432. * so mask that caps bit off.
  433. */
  434. if (dwSize >= sizeof(DDCAPS))
  435. {
  436. /*
  437. * Only mask off the extended caps if they were queried for.
  438. */
  439. lpDDDriverCaps->ddsCaps.dwCaps &= ~DDSCAPS_EXECUTEBUFFER;
  440. }
  441. lpDDDriverCaps->ddsOldCaps.dwCaps &= ~DDSCAPS_EXECUTEBUFFER;
  442. /*
  443. * get amount of free video memory
  444. * Yes, I know I'm ignoring the return code. This is a conscious choice not to engender any
  445. * regression risks by changing return codes.
  446. */
  447. ZeroMemory(&ddscaps,sizeof(ddscaps));
  448. ddscaps.dwCaps = DDSCAPS_VIDEOMEMORY;
  449. DD_GetAvailableVidMem( lpDD, &ddscaps, &lpDDDriverCaps->dwVidMemTotal, &lpDDDriverCaps->dwVidMemFree );
  450. }
  451. /*
  452. * fill in hel caps
  453. */
  454. if( lpDDHELCaps != NULL )
  455. {
  456. /*
  457. * We now have to assemble the final, API visible caps from multiple
  458. * sub-components scattered through the driver object. To make the size
  459. * computation simple we just build a full, API sized DDCAPS and then
  460. * just copy the appropritate portion of it. Cheesy in that involves an
  461. * extra copy of the data but very simple. This should not be performance
  462. * critical code to start with.
  463. */
  464. BuildDDCAPS( &ddcaps, this, TRUE );
  465. dwSize = lpDDHELCaps->dwSize;
  466. ZeroMemory( lpDDHELCaps, dwSize);
  467. memcpy( lpDDHELCaps, &ddcaps, dwSize );
  468. lpDDHELCaps->dwSize = dwSize;
  469. /*
  470. * Again, execute buffers are invisible to the user level API
  471. * so mask that caps bit off.
  472. */
  473. if (dwSize >= sizeof(DDCAPS))
  474. {
  475. /*
  476. * Only mask off the extended caps if they were queried for.
  477. */
  478. lpDDHELCaps->ddsCaps.dwCaps &= ~DDSCAPS_EXECUTEBUFFER;
  479. }
  480. lpDDHELCaps->ddsOldCaps.dwCaps &= ~DDSCAPS_EXECUTEBUFFER;
  481. lpDDHELCaps->dwVidMemFree = 0;
  482. }
  483. LEAVE_DDRAW();
  484. return DD_OK;
  485. } /* DD_GetCaps */
  486. #undef DPF_MODNAME
  487. #define DPF_MODNAME "WaitForVerticalBlank"
  488. /*
  489. * ModeX_WaitForVerticalBlank
  490. */
  491. static void ModeX_WaitForVerticalBlank( DWORD dwFlags )
  492. {
  493. #if defined (WIN95) || defined ( NT_FIX )
  494. switch( dwFlags )
  495. {
  496. case DDWAITVB_BLOCKBEGIN:
  497. /*
  498. * if blockbegin is requested we wait until the vertical retrace
  499. * is over, and then wait for the display period to end.
  500. */
  501. while(IN_VBLANK());
  502. while(IN_DISPLAY());
  503. break;
  504. case DDWAITVB_BLOCKEND:
  505. /*
  506. * if blockend is requested we wait for the vblank interval to end.
  507. */
  508. if( IN_VBLANK() )
  509. {
  510. while( IN_VBLANK() );
  511. }
  512. else
  513. {
  514. while(IN_DISPLAY());
  515. while(IN_VBLANK());
  516. }
  517. break;
  518. }
  519. #endif
  520. } /* ModeX_WaitForVerticalBlank */
  521. /*
  522. * DD_WaitForVerticalBlank
  523. */
  524. HRESULT DDAPI DD_WaitForVerticalBlank(
  525. LPDIRECTDRAW lpDD,
  526. DWORD dwFlags,
  527. HANDLE hEvent )
  528. {
  529. LPDDRAWI_DIRECTDRAW_INT this_int;
  530. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  531. LPDDRAWI_DIRECTDRAW_GBL this;
  532. LPDDHAL_WAITFORVERTICALBLANK wfvbhalfn;
  533. LPDDHAL_WAITFORVERTICALBLANK wfvbfn;
  534. ENTER_DDRAW();
  535. DPF(2,A,"ENTERAPI: DD_WaitForVerticalBlank");
  536. TRY
  537. {
  538. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  539. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  540. {
  541. LEAVE_DDRAW();
  542. return DDERR_INVALIDOBJECT;
  543. }
  544. this_lcl = this_int->lpLcl;
  545. this = this_lcl->lpGbl;
  546. #ifdef WINNT
  547. // Update DDraw handle in driver GBL object.
  548. this->hDD = this_lcl->hDD;
  549. #endif //WINNT
  550. if( (dwFlags & DDWAITVB_BLOCKBEGINEVENT) || (hEvent != NULL) )
  551. {
  552. DPF_ERR( "Event's not currently supported" );
  553. LEAVE_DDRAW();
  554. return DDERR_UNSUPPORTED;
  555. }
  556. if( (dwFlags != DDWAITVB_BLOCKBEGIN) && (dwFlags != DDWAITVB_BLOCKEND) )
  557. {
  558. DPF_ERR( "Invalid dwFlags" );
  559. LEAVE_DDRAW();
  560. return DDERR_INVALIDPARAMS;
  561. }
  562. }
  563. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  564. {
  565. DPF_ERR( "Exception encountered validating parameters" );
  566. LEAVE_DDRAW();
  567. return DDERR_INVALIDPARAMS;
  568. }
  569. /*
  570. * ask the driver to wait for the vertical blank
  571. */
  572. if( this->dwFlags & DDRAWI_MODEX )
  573. {
  574. ModeX_WaitForVerticalBlank( dwFlags );
  575. }
  576. else
  577. {
  578. #pragma message( REMIND( "Need HEL WaitForVerticalBlank" ))
  579. wfvbfn = this_lcl->lpDDCB->HALDD.WaitForVerticalBlank;
  580. wfvbhalfn = this_lcl->lpDDCB->cbDDCallbacks.WaitForVerticalBlank;
  581. if( wfvbhalfn != NULL )
  582. {
  583. DDHAL_WAITFORVERTICALBLANKDATA wfvbd;
  584. DWORD rc;
  585. wfvbd.WaitForVerticalBlank = wfvbhalfn;
  586. wfvbd.lpDD = this;
  587. wfvbd.dwFlags = dwFlags;
  588. wfvbd.hEvent = (ULONG_PTR) hEvent;
  589. DOHALCALL( WaitForVerticalBlank, wfvbfn, wfvbd, rc, FALSE );
  590. if( rc == DDHAL_DRIVER_HANDLED )
  591. {
  592. LEAVE_DDRAW();
  593. return wfvbd.ddRVal;
  594. }
  595. }
  596. }
  597. LEAVE_DDRAW();
  598. return DDERR_UNSUPPORTED;
  599. } /* DD_WaitForVerticalBlank */
  600. #undef DPF_MODNAME
  601. #define DPF_MODNAME "GetMonitorFrequency"
  602. /*
  603. * DD_GetMonitorFrequency
  604. */
  605. HRESULT DDAPI DD_GetMonitorFrequency(
  606. LPDIRECTDRAW lpDD,
  607. LPDWORD lpdwFrequency)
  608. {
  609. LPDDRAWI_DIRECTDRAW_INT this_int;
  610. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  611. LPDDRAWI_DIRECTDRAW_GBL this;
  612. ENTER_DDRAW();
  613. DPF(2,A,"ENTERAPI: DD_GetMonitorFrequency");
  614. TRY
  615. {
  616. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  617. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  618. {
  619. LEAVE_DDRAW();
  620. return DDERR_INVALIDOBJECT;
  621. }
  622. this_lcl = this_int->lpLcl;
  623. this = this_lcl->lpGbl;
  624. if( !VALID_DWORD_PTR( lpdwFrequency ) )
  625. {
  626. DPF_ERR( "Invalid frequency pointer" );
  627. LEAVE_DDRAW();
  628. return DDERR_INVALIDPARAMS;
  629. }
  630. if( this->dwMonitorFrequency == 0 )
  631. {
  632. LEAVE_DDRAW();
  633. return DDERR_UNSUPPORTED;
  634. }
  635. *lpdwFrequency = this->dwMonitorFrequency;
  636. }
  637. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  638. {
  639. DPF_ERR( "Exception encountered validating parameters" );
  640. LEAVE_DDRAW();
  641. return DDERR_INVALIDPARAMS;
  642. }
  643. LEAVE_DDRAW();
  644. return DD_OK;
  645. } /* DD_GetMonitorFrequency */
  646. DWORD gdwSetIME = 0;
  647. /*
  648. * DoneExclusiveMode
  649. */
  650. void DoneExclusiveMode( LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
  651. {
  652. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  653. DDHAL_SETEXCLUSIVEMODEDATA semd;
  654. LPDDHAL_SETEXCLUSIVEMODE semfn;
  655. LPDDHAL_SETEXCLUSIVEMODE semhalfn;
  656. HRESULT rc;
  657. DPF( 4, "DoneExclusiveMode" );
  658. pdrv = pdrv_lcl->lpGbl;
  659. if( (pdrv->dwFlags & DDRAWI_FULLSCREEN) &&
  660. (pdrv->dwFlags & DDRAWI_DISPLAYDRV) )
  661. {
  662. DPF( 4, "Enabling error mode, hotkeys" );
  663. SetErrorMode( pdrv_lcl->dwErrorMode );
  664. if( !( pdrv_lcl->dwAppHackFlags & DDRAW_APPCOMPAT_SCREENSAVER ) )
  665. {
  666. BOOL old;
  667. SystemParametersInfo( SPI_SCREENSAVERRUNNING, FALSE, &old, 0 );
  668. }
  669. #ifdef WINNT
  670. // Restore cursor shadow coming out of fullscreen
  671. SystemParametersInfo( SPI_SETCURSORSHADOW, 0, (LPVOID)ULongToPtr(pdrv_lcl->dwCursorShadow), 0 );
  672. #endif
  673. // Restore reactive menus coming out of fullscreen:
  674. SystemParametersInfo( SPI_SETHOTTRACKING, 0, (LPVOID)ULongToPtr(pdrv_lcl->dwHotTracking), 0 );
  675. InterlockedExchange(&gdwSetIME, pdrv_lcl->dwIMEState + 1);
  676. }
  677. pdrv->dwFlags &= ~(DDRAWI_FULLSCREEN);
  678. /*
  679. * Driver is no longer flipped to GDI surface.
  680. * NOTE: This does not mean its not showing the GDI surface just that
  681. * its no longer showing the GDI surface as a result of a FlipToGDISurface
  682. */
  683. pdrv->dwFlags &= ~(DDRAWI_FLIPPEDTOGDI);
  684. // restore the GDI palette
  685. // we let GDI do this by calling SetSystemPaletteUse() this will send
  686. // the right (ie what GDI thinks...) colors down to the device
  687. // this also flushes GDIs palette xlat cache.
  688. #ifdef WIN95
  689. if( pdrv->dwModeIndex != DDUNSUPPORTEDMODE && NULL != pdrv->lpModeInfo)
  690. #else
  691. if (NULL != pdrv->lpModeInfo)
  692. #endif
  693. {
  694. if( pdrv->lpModeInfo[ pdrv->dwModeIndex ].wFlags & DDMODEINFO_PALETTIZED )
  695. {
  696. HDC hdc;
  697. if( pdrv->cMonitors > 1 )
  698. {
  699. SetSystemPaletteUse( (HDC) (pdrv_lcl->hDC), SYSPAL_STATIC);
  700. DPF(4,"SetSystemPaletteUse STATICS ON (DoneExclusiveMode)");
  701. }
  702. else
  703. {
  704. hdc = GetDC(NULL);
  705. SetSystemPaletteUse(hdc, SYSPAL_STATIC);
  706. DPF(4,"SetSystemPaletteUse STATICS ON (DoneExclusiveMode)");
  707. ReleaseDC(NULL, hdc);
  708. }
  709. // if we have a primary
  710. if (pdrv_lcl->lpPrimary)
  711. {
  712. if (pdrv_lcl->lpPrimary->lpLcl->lpDDPalette) //if that primary has a palette
  713. {
  714. pdrv_lcl->lpPrimary->lpLcl->lpDDPalette->lpLcl->lpGbl->dwFlags &= ~DDRAWIPAL_EXCLUSIVE;
  715. DPF(5,"Setting non-exclusive for palette %08x",pdrv_lcl->lpPrimary->lpLcl->lpDDPalette->lpLcl);
  716. }
  717. }
  718. }
  719. #ifdef WINNT
  720. // this fixes DOS Box colors on NT. We need to do this even in non-
  721. // palettized modes.
  722. PostMessage(HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM)pdrv_lcl->hWnd, 0);
  723. #endif
  724. }
  725. /*
  726. * Restore the display mode in case it was changed while
  727. * in exclusive mode.
  728. * Only do this if we are not adhering to the v1 behaviour
  729. */
  730. if( !(pdrv_lcl->dwLocalFlags & DDRAWILCL_V1SCLBEHAVIOUR) )
  731. {
  732. RestoreDisplayMode( pdrv_lcl, TRUE );
  733. }
  734. /*
  735. * If the primary has a gamma ramp associated w/ it, set it now
  736. */
  737. if( ( pdrv_lcl->lpPrimary != NULL ) &&
  738. ( pdrv_lcl->lpPrimary->lpLcl->lpSurfMore->lpOriginalGammaRamp != NULL ) )
  739. {
  740. RestoreGamma( pdrv_lcl->lpPrimary->lpLcl, pdrv_lcl );
  741. }
  742. /*
  743. * Notify the driver that we are leaving exclusive mode.
  744. * NOTE: This is a HAL only call - the HEL does not get to
  745. * see it.
  746. * NOTE: We don't allow the driver to fail this call. This is
  747. * a notification callback only.
  748. */
  749. semfn = pdrv_lcl->lpDDCB->HALDD.SetExclusiveMode;
  750. semhalfn = pdrv_lcl->lpDDCB->cbDDCallbacks.SetExclusiveMode;
  751. if( NULL != semhalfn )
  752. {
  753. semd.SetExclusiveMode = semhalfn;
  754. semd.lpDD = pdrv;
  755. semd.dwEnterExcl = FALSE;
  756. semd.dwReserved = 0UL;
  757. DOHALCALL( SetExclusiveMode, semfn, semd, rc, FALSE );
  758. //
  759. // This assert has fired and confused many devs. Seems like the 3dfx and the pvr both
  760. // bounce us a failure code. It's clearly not serving its original purpose of making
  761. // driver devs return an ok code, so let's yank it.
  762. //
  763. //DDASSERT( ( DDHAL_DRIVER_HANDLED == rc ) && ( !FAILED( semd.ddRVal ) ) );
  764. }
  765. pdrv->lpExclusiveOwner = NULL;
  766. /*
  767. * changes to lpExclusiveOwner can only be made while the exclusive mode mutex is owned by this process
  768. */
  769. RELEASE_EXCLUSIVEMODE_MUTEX;
  770. ClipTheCursor(pdrv_lcl, NULL);
  771. // If we are going into window'ed mode and we are
  772. // emulated then we might need to turn on the VirtualDesktop flag.
  773. // We don't do this for 3Dfx, and we don't do this if the app
  774. // has chosen a monitor explicitly.
  775. if( ( pdrv->cMonitors > 1 ) &&
  776. (pdrv->dwFlags & DDRAWI_DISPLAYDRV) )
  777. {
  778. pdrv->dwFlags |= DDRAWI_VIRTUALDESKTOP;
  779. // We need to update our device rect
  780. UpdateRectFromDevice( pdrv );
  781. }
  782. } /* DoneExclusiveMode */
  783. /*
  784. * StartExclusiveMode
  785. */
  786. void StartExclusiveMode( LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl, DWORD dwFlags, DWORD pid )
  787. {
  788. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  789. DDHAL_SETEXCLUSIVEMODEDATA semd;
  790. LPDDHAL_SETEXCLUSIVEMODE semfn;
  791. LPDDHAL_SETEXCLUSIVEMODE semhalfn;
  792. DWORD dwWaitResult;
  793. HRESULT rc;
  794. DPF( 4, "StartExclusiveMode" );
  795. pdrv = pdrv_lcl->lpGbl;
  796. #if _WIN32_WINNT >= 0x0501
  797. {
  798. //Turn off ghosting for any exclusive-mode app
  799. //(Whistler onwards only)
  800. typedef void (WINAPI *PFN_NOGHOST)( void );
  801. HINSTANCE hInst = NULL;
  802. hInst = LoadLibrary( "user32.dll" );
  803. if( hInst )
  804. {
  805. PFN_NOGHOST pfnNoGhost = NULL;
  806. pfnNoGhost = (PFN_NOGHOST)GetProcAddress( (HMODULE)hInst, "DisableProcessWindowsGhosting" );
  807. if( pfnNoGhost )
  808. {
  809. pfnNoGhost();
  810. }
  811. FreeLibrary( hInst );
  812. }
  813. }
  814. #endif // _WIN32_WINNT >= 0x0501
  815. /*
  816. * Preceeding code should have taken this mutex already.
  817. */
  818. #if defined(WINNT) && defined(DEBUG)
  819. dwWaitResult = WaitForSingleObject(hExclusiveModeMutex, 0);
  820. DDASSERT(dwWaitResult == WAIT_OBJECT_0);
  821. ReleaseMutex(hExclusiveModeMutex);
  822. #endif
  823. pdrv->lpExclusiveOwner = pdrv_lcl;
  824. if( (pdrv->dwFlags & DDRAWI_FULLSCREEN) &&
  825. (pdrv->dwFlags & DDRAWI_DISPLAYDRV) )
  826. {
  827. pdrv_lcl->dwErrorMode = SetErrorMode( SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX );
  828. {
  829. BOOL old;
  830. /*
  831. * Don't send kepyboard events while the screen saver is running
  832. * or else USER gets confused
  833. */
  834. if( !( pdrv_lcl->dwAppHackFlags & DDRAW_APPCOMPAT_SCREENSAVER ) )
  835. {
  836. #ifdef WIN95
  837. // If the user has just switched to us, and then quickly
  838. // switched away from us, we may be in the Alt+Tab switch box.
  839. // If we are, then we need to get out of it or the user will
  840. // be forced to reboot the system. So we check to see if the
  841. // Alt key is down, and if so, force it up. Hacking is fun.
  842. if (GetAsyncKeyState(VK_MENU) & 0x80000000)
  843. {
  844. keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
  845. }
  846. #endif
  847. SystemParametersInfo( SPI_SCREENSAVERRUNNING, TRUE, &old, 0 );
  848. }
  849. #ifdef WINNT
  850. // Save current cursor shadow setting
  851. SystemParametersInfo( SPI_GETCURSORSHADOW, 0, (LPVOID) &(pdrv_lcl->dwCursorShadow), 0 );
  852. SystemParametersInfo( SPI_SETCURSORSHADOW, 0, 0, 0 );
  853. #endif
  854. // Save current hot-tracking setting
  855. SystemParametersInfo( SPI_GETHOTTRACKING, 0, (LPVOID) &(pdrv_lcl->dwHotTracking), 0 );
  856. SystemParametersInfo( SPI_GETSHOWIMEUI, 0, (LPVOID) &(pdrv_lcl->dwIMEState), 0 );
  857. //And turn it off as we go into exclusive mode
  858. SystemParametersInfo( SPI_SETHOTTRACKING, 0, 0, 0 );
  859. InterlockedExchange(&gdwSetIME, FALSE + 1);
  860. #ifdef WIN95
  861. if( dwFlags & DDSCL_ALLOWREBOOT )
  862. {
  863. /*
  864. * re-enable reboot after SPI_SCREENSAVERRUNNING, it disables it
  865. */
  866. DD16_EnableReboot( TRUE );
  867. }
  868. #endif
  869. }
  870. }
  871. /*
  872. * invalidate all primary surfaces. This includes the primary surface
  873. * for the current process if it was created before exclusive mode was
  874. * entered.
  875. *
  876. * we must invalidate ALL surfaces in case the app doesn't switch the
  877. * mode. - craige 7/9/95
  878. */
  879. InvalidateAllSurfaces( pdrv, (HANDLE) pdrv_lcl->hDDVxd, TRUE );
  880. /*
  881. * If the primary has a gamma ramp associated w/ it, set it now
  882. */
  883. if( ( pdrv_lcl->lpPrimary != NULL ) &&
  884. ( pdrv_lcl->lpPrimary->lpLcl->lpSurfMore->lpGammaRamp != NULL ) )
  885. {
  886. SetGamma( pdrv_lcl->lpPrimary->lpLcl, pdrv_lcl );
  887. }
  888. /*
  889. * Notify the driver that we are entering exclusive mode.
  890. * NOTE: This is a HAL only call - the HEL does not get to
  891. * see it.
  892. * NOTE: We don't allow the driver to fail this call. This is
  893. * a notification callback only.
  894. */
  895. semfn = pdrv_lcl->lpDDCB->HALDD.SetExclusiveMode;
  896. semhalfn = pdrv_lcl->lpDDCB->cbDDCallbacks.SetExclusiveMode;
  897. if( NULL != semhalfn )
  898. {
  899. semd.SetExclusiveMode = semhalfn;
  900. semd.lpDD = pdrv;
  901. semd.dwEnterExcl = TRUE;
  902. semd.dwReserved = 0UL;
  903. DOHALCALL( SetExclusiveMode, semfn, semd, rc, FALSE );
  904. //
  905. // This assert has fired and confused many devs. Seems like the 3dfx and the pvr both
  906. // bounce us a failure code. It's clearly not serving its original purpose of making
  907. // driver devs return an ok code, so let's yank it.
  908. //
  909. //DDASSERT( ( DDHAL_DRIVER_HANDLED == rc ) && ( !FAILED( semd.ddRVal ) ) );
  910. }
  911. // If we are going into fullscreen mode
  912. // Then we might need to turn off the VirtualDesktop flag
  913. if( pdrv->cMonitors > 1 )
  914. {
  915. pdrv->dwFlags &= ~DDRAWI_VIRTUALDESKTOP;
  916. // We need to update our device rect
  917. UpdateRectFromDevice( pdrv );
  918. }
  919. } /* StartExclusiveMode */
  920. #undef DPF_MODNAME
  921. #define DPF_MODNAME "SetCooperativeLevel"
  922. /*
  923. * DD_SetCooperativeLevel
  924. */
  925. HRESULT DDAPI DD_SetCooperativeLevel(
  926. LPDIRECTDRAW lpDD,
  927. HWND hWnd,
  928. DWORD dwFlags )
  929. {
  930. LPDDRAWI_DIRECTDRAW_INT this_int;
  931. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  932. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  933. LPDDRAWI_DIRECTDRAW_GBL this;
  934. DWORD pid;
  935. HRESULT ddrval;
  936. DWORD style;
  937. HWND old_hwnd;
  938. HWND hTemp;
  939. BOOL excl_exists;
  940. BOOL is_excl;
  941. ENTER_DDRAW();
  942. DPF(2,A,"ENTERAPI: DD_SetCooperativeLevel");
  943. TRY
  944. {
  945. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  946. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  947. {
  948. LEAVE_DDRAW();
  949. return DDERR_INVALIDOBJECT;
  950. }
  951. this_lcl = this_int->lpLcl;
  952. this = this_lcl->lpGbl;
  953. if( dwFlags & ~DDSCL_VALID )
  954. {
  955. DPF_ERR( "Invalid flags specified" );
  956. LEAVE_DDRAW();
  957. return DDERR_INVALIDPARAMS;
  958. }
  959. if ((dwFlags & DDSCL_FPUSETUP) && (dwFlags & DDSCL_FPUPRESERVE))
  960. {
  961. DPF_ERR( "Only one DDSCL_FPU* flag can be specified" );
  962. LEAVE_DDRAW();
  963. return DDERR_INVALIDPARAMS;
  964. }
  965. /*
  966. * If the device isn't attached to the desktop, we don't want
  967. * to mess w/ it's window because we'll get it wrong.
  968. */
  969. if( !( this->dwFlags & DDRAWI_ATTACHEDTODESKTOP ) )
  970. {
  971. dwFlags |= DDSCL_NOWINDOWCHANGES;
  972. }
  973. if( !(dwFlags & (DDSCL_EXCLUSIVE|DDSCL_NORMAL) ) &&
  974. !(dwFlags & DDSCL_SETFOCUSWINDOW ) )
  975. {
  976. DPF_ERR( "Must specify one of EXCLUSIVE or NORMAL" );
  977. LEAVE_DDRAW();
  978. return DDERR_INVALIDPARAMS;
  979. }
  980. if( (dwFlags & DDSCL_EXCLUSIVE) && !(dwFlags & DDSCL_FULLSCREEN) )
  981. {
  982. DPF_ERR( "Must specify fullscreen for exclusive mode" );
  983. LEAVE_DDRAW();
  984. return DDERR_INVALIDPARAMS;
  985. }
  986. if( (dwFlags & DDSCL_ALLOWMODEX) && !(dwFlags & DDSCL_FULLSCREEN) )
  987. {
  988. DPF_ERR( "Must specify fullscreen for modex" );
  989. LEAVE_DDRAW();
  990. return DDERR_INVALIDPARAMS;
  991. }
  992. if( (hWnd != NULL) && !IsWindow( hWnd ) )
  993. {
  994. DPF_ERR( "Hwnd passed is not a valid window" );
  995. LEAVE_DDRAW();
  996. return DDERR_INVALIDPARAMS;
  997. }
  998. if( (dwFlags & DDSCL_DONTHOOKHWND) && (dwFlags & DDSCL_EXCLUSIVE) )
  999. {
  1000. DPF_ERR( "we must hook the window in exclusive mode" );
  1001. LEAVE_DDRAW();
  1002. return DDERR_INVALIDPARAMS;
  1003. }
  1004. if( dwFlags & DDSCL_SETFOCUSWINDOW )
  1005. {
  1006. if( !( dwFlags & DDSCL_CREATEDEVICEWINDOW) &&
  1007. ( dwFlags & ~(DDSCL_SETFOCUSWINDOW | DDSCL_ALLOWMODEX
  1008. | DDSCL_DX8APP | DDSCL_NOWINDOWCHANGES) ) )
  1009. {
  1010. DPF_ERR( "Flags invalid with DDSCL_SETFOCUSWINDOW" );
  1011. LEAVE_DDRAW();
  1012. return DDERR_INVALIDPARAMS;
  1013. }
  1014. if( this_lcl->dwLocalFlags & DDRAWILCL_HASEXCLUSIVEMODE )
  1015. {
  1016. DPF_ERR( "Cannot reset focus window while exclusive mode is owned" );
  1017. LEAVE_DDRAW();
  1018. return DDERR_HWNDALREADYSET;
  1019. }
  1020. }
  1021. if( dwFlags & DDSCL_SETDEVICEWINDOW )
  1022. {
  1023. if( dwFlags & (DDSCL_SETFOCUSWINDOW | DDSCL_CREATEDEVICEWINDOW) )
  1024. {
  1025. DPF_ERR( "Flags invalid with DDSCL_SETDEVICEWINDOW" );
  1026. LEAVE_DDRAW();
  1027. return DDERR_INVALIDPARAMS;
  1028. }
  1029. if( hWnd != NULL )
  1030. {
  1031. if( this_lcl->hFocusWnd == 0 )
  1032. {
  1033. DPF_ERR( "Focus window has not been set" );
  1034. LEAVE_DDRAW();
  1035. return DDERR_NOFOCUSWINDOW;
  1036. }
  1037. }
  1038. }
  1039. if( ( dwFlags & DDSCL_CREATEDEVICEWINDOW ) &&
  1040. ( this_lcl->hWnd != 0 ) &&
  1041. !( this_lcl->dwLocalFlags & DDRAWILCL_CREATEDWINDOW ) )
  1042. {
  1043. DPF_ERR( "HWND already set - DDSCL_CREATEDEVICEWINDOW flag not valid" );
  1044. LEAVE_DDRAW();
  1045. return DDERR_INVALIDPARAMS;
  1046. }
  1047. if( ( dwFlags & DDSCL_CREATEDEVICEWINDOW ) &&
  1048. !( dwFlags & DDSCL_EXCLUSIVE ) )
  1049. {
  1050. DPF_ERR( "DDSCL_CREATEDEVICEWINDOW only valid with DDSCL_EXCLUSIVE" );
  1051. LEAVE_DDRAW();
  1052. return DDERR_INVALIDPARAMS;
  1053. }
  1054. if( ( dwFlags & DDSCL_CREATEDEVICEWINDOW ) &&
  1055. ( this_lcl->hWnd == 0 ) )
  1056. {
  1057. if( !( dwFlags & DDSCL_SETFOCUSWINDOW ) )
  1058. {
  1059. if( hWnd != NULL )
  1060. {
  1061. DPF_ERR( "hWnd specified with DDSCL_CREATEDEVICEWINDOW" );
  1062. LEAVE_DDRAW();
  1063. return DDERR_INVALIDPARAMS;
  1064. }
  1065. if( this_lcl->hFocusWnd == 0 )
  1066. {
  1067. DPF_ERR( "Focus window has not been set" );
  1068. LEAVE_DDRAW();
  1069. return DDERR_NOFOCUSWINDOW;
  1070. }
  1071. }
  1072. }
  1073. if( ( dwFlags & DDSCL_EXCLUSIVE ) &&
  1074. !( dwFlags & DDSCL_CREATEDEVICEWINDOW ) )
  1075. {
  1076. if( NULL == hWnd )
  1077. {
  1078. DPF_ERR( "Hwnd must be specified for exclusive mode" );
  1079. LEAVE_DDRAW();
  1080. return DDERR_INVALIDPARAMS;
  1081. }
  1082. if( (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) )
  1083. {
  1084. DPF_ERR( "Hwnd must be a top level window" );
  1085. LEAVE_DDRAW();
  1086. return DDERR_INVALIDPARAMS;
  1087. }
  1088. }
  1089. pid = GETCURRPID();
  1090. }
  1091. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1092. {
  1093. DPF_ERR( "Exception encountered validating parameters" );
  1094. LEAVE_DDRAW();
  1095. return DDERR_INVALIDPARAMS;
  1096. }
  1097. /*
  1098. * In v1, we allowed an app to set the mode while in exclusive mode but
  1099. * we didn't restore the mode if the app lost exclusive mode. We have
  1100. * changed this behaviour in v2 to cause the display mode to be restored
  1101. * when exclusive mode is lost. If the v1 SetCooperativeLevel is ever
  1102. * called then we revert back to the v1 behaviour to avoid breaking
  1103. * existing apps.
  1104. */
  1105. if( this_int->lpVtbl == &ddCallbacks )
  1106. {
  1107. // This is the V1 SetCooperativeLevel
  1108. this_lcl->dwLocalFlags |= DDRAWILCL_V1SCLBEHAVIOUR;
  1109. }
  1110. /*
  1111. * don't mess with dialogs, this is a hack for DDTEST and DDCAPS.
  1112. * Don't do this if the app specified the
  1113. * SETDEVICEWINDOW/CREATEDEVICEWINDOW flags.
  1114. */
  1115. if( ( NULL != hWnd ) &&
  1116. !( dwFlags & (DDSCL_SETDEVICEWINDOW|DDSCL_CREATEDEVICEWINDOW) ) )
  1117. {
  1118. style = GetWindowLong(hWnd, GWL_STYLE);
  1119. if ((style & WS_CAPTION) == WS_DLGFRAME)
  1120. {
  1121. DPF( 2, "setting DDSCL_NOWINDOWCHANGES for caller" );
  1122. dwFlags |= DDSCL_NOWINDOWCHANGES;
  1123. }
  1124. }
  1125. if( dwFlags & DDSCL_EXCLUSIVE )
  1126. {
  1127. /*
  1128. * This is one of exactly two cases where we keep the exclusive mode mutex (the other is
  1129. * in dddefwp, wherein we are activated by alt-tab). We have to be careful to release the
  1130. * mutex properly in failure modes.
  1131. */
  1132. if( !( dwFlags & DDSCL_SETFOCUSWINDOW ) )
  1133. {
  1134. hTemp = (HWND) this_lcl->hFocusWnd;
  1135. }
  1136. else
  1137. {
  1138. hTemp = hWnd;
  1139. }
  1140. CheckExclusiveMode(this_lcl, &excl_exists, &is_excl, TRUE, hTemp, TRUE );
  1141. if( (excl_exists) &&
  1142. (!is_excl) )
  1143. {
  1144. if( ( dwFlags & DDSCL_CREATEDEVICEWINDOW ) &&
  1145. ( this_lcl->hWnd == 0 ) &&
  1146. ( hWnd ) )
  1147. {
  1148. DestroyWindow(hWnd);
  1149. }
  1150. LEAVE_DDRAW();
  1151. return DDERR_EXCLUSIVEMODEALREADYSET;
  1152. }
  1153. }
  1154. /*
  1155. * If we are only setting the focus window, save it now
  1156. */
  1157. if( dwFlags & DDSCL_SETFOCUSWINDOW )
  1158. {
  1159. this_lcl->hFocusWnd = (ULONG_PTR) hWnd;
  1160. if( ( this_lcl->hWnd != 0 ) &&
  1161. ( this_lcl->dwLocalFlags & DDRAWILCL_CREATEDWINDOW ) &&
  1162. IsWindow( (HWND) this_lcl->hWnd ) )
  1163. {
  1164. SetWindowLongPtr( (HWND) this_lcl->hWnd, 0, (LONG_PTR) hWnd );
  1165. }
  1166. if( !( dwFlags & DDSCL_CREATEDEVICEWINDOW ) )
  1167. {
  1168. if (dwFlags & DDSCL_MULTITHREADED)
  1169. this_lcl->dwLocalFlags |= DDRAWILCL_MULTITHREADED;
  1170. if (dwFlags & DDSCL_FPUSETUP)
  1171. this_lcl->dwLocalFlags |= DDRAWILCL_FPUSETUP;
  1172. if (dwFlags & DDSCL_FPUPRESERVE)
  1173. this_lcl->dwLocalFlags |= DDRAWILCL_FPUPRESERVE;
  1174. /*
  1175. * It's ok to always release the mutex here, because the only way we can get here is if we just took
  1176. * exclusive mode, i.e. we didn't already have exclusive mode before this SetCoop call was made.
  1177. */
  1178. if( dwFlags & DDSCL_EXCLUSIVE )
  1179. {
  1180. RELEASE_EXCLUSIVEMODE_MUTEX;
  1181. }
  1182. LEAVE_DDRAW();
  1183. return DD_OK;
  1184. }
  1185. }
  1186. /*
  1187. * Create the window now if we need to
  1188. */
  1189. if( ( dwFlags & DDSCL_CREATEDEVICEWINDOW ) &&
  1190. ( this_lcl->hWnd == 0 ) )
  1191. {
  1192. WNDCLASS cls;
  1193. if( !GetClassInfo( hModule, szDeviceWndClass, &cls ) )
  1194. {
  1195. cls.lpszClassName = szDeviceWndClass;
  1196. cls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  1197. cls.hInstance = hModule;
  1198. cls.hIcon = NULL;
  1199. cls.hCursor = NULL;
  1200. cls.lpszMenuName = NULL;
  1201. cls.style = CS_DBLCLKS;
  1202. cls.lpfnWndProc = DeviceWindowProc;
  1203. cls.cbWndExtra = sizeof( INT_PTR );
  1204. cls.cbClsExtra = 0;
  1205. if( RegisterClass(&cls) == 0 )
  1206. {
  1207. DPF_ERR( "RegisterClass failed" );
  1208. RELEASE_EXCLUSIVEMODE_MUTEX;
  1209. LEAVE_DDRAW();
  1210. return DDERR_GENERIC;
  1211. }
  1212. }
  1213. hWnd = CreateWindow(
  1214. szDeviceWndClass,
  1215. szDeviceWndClass,
  1216. WS_OVERLAPPED|WS_POPUP|WS_VISIBLE,
  1217. this->rectDevice.left,
  1218. this->rectDevice.top,
  1219. this->rectDevice.right - this->rectDevice.left,
  1220. this->rectDevice.bottom - this->rectDevice.top,
  1221. (HWND)this_lcl->hFocusWnd, NULL,
  1222. hModule,
  1223. (LPVOID) (this_lcl->hFocusWnd) );
  1224. if( hWnd == NULL )
  1225. {
  1226. DPF_ERR( "Unable to create the device window" );
  1227. RELEASE_EXCLUSIVEMODE_MUTEX;
  1228. LEAVE_DDRAW();
  1229. return DDERR_INVALIDPARAMS;
  1230. }
  1231. }
  1232. // Destroy the old window if we created it ourselves
  1233. if( ( hWnd != (HWND) this_lcl->hWnd ) &&
  1234. IsWindow( (HWND) this_lcl->hWnd ) &&
  1235. ( this_lcl->dwLocalFlags & DDRAWILCL_CREATEDWINDOW ) )
  1236. {
  1237. DestroyWindow( (HWND) this_lcl->hWnd );
  1238. this_lcl->hWnd = 0;
  1239. this_lcl->dwLocalFlags &= ~DDRAWILCL_CREATEDWINDOW;
  1240. }
  1241. // Save the hwnd in the local object for later reference
  1242. old_hwnd = (HWND)this_lcl->hWnd;
  1243. if( dwFlags & (DDSCL_SETDEVICEWINDOW | DDSCL_CREATEDEVICEWINDOW) )
  1244. {
  1245. (HWND) this_lcl->hWnd = hWnd;
  1246. if( dwFlags & DDSCL_CREATEDEVICEWINDOW )
  1247. {
  1248. this_lcl->dwLocalFlags |= DDRAWILCL_CREATEDWINDOW;
  1249. }
  1250. }
  1251. else
  1252. {
  1253. (HWND) this_lcl->hWnd = hWnd;
  1254. (HWND) this_lcl->hFocusWnd = hWnd;
  1255. }
  1256. /*
  1257. * allow modex modes?
  1258. */
  1259. if( (dwFlags & DDSCL_ALLOWMODEX) &&
  1260. !( this->dwFlags & DDRAWI_MODEXILLEGAL ) )
  1261. {
  1262. DPF( 2, "*********** ALLOWING MODE X AND VGA MODES" );
  1263. this_lcl->dwLocalFlags |= DDRAWILCL_ALLOWMODEX;
  1264. }
  1265. else
  1266. {
  1267. DPF( 2, "*********** NOT!! ALLOWING MODE X AND VGA MODES" );
  1268. this_lcl->dwLocalFlags &= ~DDRAWILCL_ALLOWMODEX;
  1269. }
  1270. /*
  1271. * exclusive mode?
  1272. */
  1273. if( dwFlags & DDSCL_EXCLUSIVE )
  1274. {
  1275. if( dwFlags & DDSCL_FULLSCREEN )
  1276. {
  1277. this->dwFlags |= DDRAWI_FULLSCREEN;
  1278. this_lcl->dwLocalFlags |= DDRAWILCL_ISFULLSCREEN;
  1279. }
  1280. // Only hook if exclusive mode requested
  1281. if( !(dwFlags & DDSCL_DONTHOOKHWND) )
  1282. {
  1283. ddrval = SetAppHWnd( this_lcl, hWnd, dwFlags );
  1284. if( ddrval != DD_OK )
  1285. {
  1286. DPF( 1, "Could not hook HWND!" );
  1287. //We don't release the exclusive mode mutex here, because we are already committed to owning
  1288. //it by the lines just above.
  1289. LEAVE_DDRAW();
  1290. return ddrval;
  1291. }
  1292. this_lcl->dwLocalFlags |= DDRAWILCL_HOOKEDHWND;
  1293. }
  1294. if( !is_excl )
  1295. {
  1296. StartExclusiveMode( this_lcl, dwFlags, pid );
  1297. this_lcl->dwLocalFlags |= DDRAWILCL_ACTIVEYES;
  1298. this_lcl->dwLocalFlags &=~DDRAWILCL_ACTIVENO;
  1299. if( hWnd != NULL )
  1300. {
  1301. extern void InternalSetForegroundWindow(HWND hWnd);
  1302. InternalSetForegroundWindow(hWnd);
  1303. }
  1304. this_lcl->dwLocalFlags |= DDRAWILCL_HASEXCLUSIVEMODE;
  1305. ClipTheCursor(this_lcl, &(this->rectDevice));
  1306. }
  1307. }
  1308. /*
  1309. * no, must be regular
  1310. */
  1311. else
  1312. {
  1313. if( this_lcl->dwLocalFlags & DDRAWILCL_HASEXCLUSIVEMODE )
  1314. {
  1315. /*
  1316. * If we are leaving exclusive mode ensure we are
  1317. * looking at the GDI surface.
  1318. */
  1319. DD_FlipToGDISurface( lpDD );
  1320. DoneExclusiveMode( this_lcl );
  1321. this_lcl->dwLocalFlags &= ~(DDRAWILCL_ISFULLSCREEN |
  1322. DDRAWILCL_ALLOWMODEX |
  1323. DDRAWILCL_HASEXCLUSIVEMODE);
  1324. // Lost exclusive mode, need to remove window hook?
  1325. if( this_lcl->dwLocalFlags & DDRAWILCL_HOOKEDHWND )
  1326. {
  1327. ddrval = SetAppHWnd( this_lcl, NULL, dwFlags );
  1328. if( ddrval != DD_OK )
  1329. {
  1330. DPF( 1, "Could not unhook HWND!" );
  1331. //No need to release excl mutex here, since DoneExclusiveMode does it.
  1332. LEAVE_DDRAW();
  1333. HIDESHOW_IME(); //Show/hide the IME OUTSIDE of the ddraw critsect.
  1334. return ddrval;
  1335. }
  1336. this_lcl->dwLocalFlags &= ~DDRAWILCL_HOOKEDHWND;
  1337. }
  1338. /*
  1339. * make the window non-topmost
  1340. */
  1341. if (!(dwFlags & DDSCL_NOWINDOWCHANGES) && (IsWindow(old_hwnd)))
  1342. {
  1343. SetWindowPos(old_hwnd, HWND_NOTOPMOST,
  1344. 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
  1345. }
  1346. }
  1347. // If we are going into window'ed mode and we are
  1348. // emulated then we might need to turn on the VirtualDesktop flag.
  1349. // We don't do this for 3Dfx, and we don't do this if the app
  1350. // has chosen a monitor explicitly.
  1351. if( ( this->cMonitors > 1 ) &&
  1352. (this->dwFlags & DDRAWI_DISPLAYDRV) )
  1353. {
  1354. this->dwFlags |= DDRAWI_VIRTUALDESKTOP;
  1355. // We need to update our device rect
  1356. UpdateRectFromDevice( this );
  1357. }
  1358. }
  1359. // Allow other DD objects to be created now.
  1360. this_lcl->dwLocalFlags |= DDRAWILCL_SETCOOPCALLED;
  1361. if (dwFlags & DDSCL_MULTITHREADED)
  1362. this_lcl->dwLocalFlags |= DDRAWILCL_MULTITHREADED;
  1363. if (dwFlags & DDSCL_FPUSETUP)
  1364. this_lcl->dwLocalFlags |= DDRAWILCL_FPUSETUP;
  1365. if (dwFlags & DDSCL_FPUPRESERVE)
  1366. this_lcl->dwLocalFlags |= DDRAWILCL_FPUPRESERVE;
  1367. LEAVE_DDRAW();
  1368. HIDESHOW_IME(); //Show/hide the IME OUTSIDE of the ddraw critsect.
  1369. return DD_OK;
  1370. } /* DD_SetCooperativeLevel */
  1371. #undef DPF_MODNAME
  1372. #define DPF_MODNAME "DuplicateSurface"
  1373. /*
  1374. * DD_DuplicateSurface
  1375. *
  1376. * Create a duplicate surface from an existing one.
  1377. * The surface will have the same properties and point to the same
  1378. * video memory.
  1379. */
  1380. HRESULT DDAPI DD_DuplicateSurface(
  1381. LPDIRECTDRAW lpDD,
  1382. LPDIRECTDRAWSURFACE lpDDSurface,
  1383. LPDIRECTDRAWSURFACE FAR *lplpDupDDSurface )
  1384. {
  1385. LPDDRAWI_DIRECTDRAW_INT this_int;
  1386. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  1387. LPDDRAWI_DIRECTDRAW_GBL this;
  1388. LPDDRAWI_DDRAWSURFACE_LCL orig_surf_lcl;
  1389. LPDDRAWI_DDRAWSURFACE_LCL new_surf_lcl;
  1390. LPDDRAWI_DDRAWSURFACE_INT orig_surf_int;
  1391. LPDDRAWI_DDRAWSURFACE_INT new_surf_int;
  1392. ENTER_DDRAW();
  1393. DPF(2,A,"ENTERAPI: DD_DuplicateSurface");
  1394. TRY
  1395. {
  1396. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  1397. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  1398. {
  1399. LEAVE_DDRAW();
  1400. return DDERR_INVALIDOBJECT;
  1401. }
  1402. this_lcl = this_int->lpLcl;
  1403. this = this_lcl->lpGbl;
  1404. orig_surf_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  1405. if( !VALID_DIRECTDRAWSURFACE_PTR( orig_surf_int ) )
  1406. {
  1407. LEAVE_DDRAW();
  1408. return DDERR_INVALIDOBJECT;
  1409. }
  1410. orig_surf_lcl = orig_surf_int->lpLcl;
  1411. if( SURFACE_LOST( orig_surf_lcl ) )
  1412. {
  1413. LEAVE_DDRAW();
  1414. return DDERR_SURFACELOST;
  1415. }
  1416. if( !VALID_PTR_PTR( lplpDupDDSurface ) )
  1417. {
  1418. DPF_ERR( "Invalid dup surface pointer" );
  1419. LEAVE_DDRAW();
  1420. return DDERR_INVALIDPARAMS;
  1421. }
  1422. *lplpDupDDSurface = NULL;
  1423. /*
  1424. * make sure we can duplicate this baby
  1425. */
  1426. if( orig_surf_lcl->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE) )
  1427. {
  1428. DPF_ERR( "Can't duplicate primary surface" );
  1429. LEAVE_DDRAW();
  1430. return DDERR_CANTDUPLICATE;
  1431. }
  1432. if( orig_surf_lcl->dwFlags & (DDRAWISURF_IMPLICITCREATE) )
  1433. {
  1434. DPF_ERR( "Can't duplicate implicitly created surfaces" );
  1435. LEAVE_DDRAW();
  1436. return DDERR_CANTDUPLICATE;
  1437. }
  1438. }
  1439. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1440. {
  1441. DPF_ERR( "Exception encountered validating parameters" );
  1442. LEAVE_DDRAW();
  1443. return DDERR_INVALIDPARAMS;
  1444. }
  1445. /*
  1446. * go make ourselves a new interface for this surface...
  1447. */
  1448. new_surf_lcl = NewSurfaceLocal( orig_surf_lcl, orig_surf_int->lpVtbl );
  1449. if( NULL == new_surf_lcl )
  1450. {
  1451. LEAVE_DDRAW();
  1452. return DDERR_OUTOFMEMORY;
  1453. }
  1454. /*
  1455. * NewSurfaceLocal does not initialize the lpDD_lcl field of the
  1456. * local surface object's lpSurfMore data structure. Need to do
  1457. * this here as it is needed by Release.
  1458. */
  1459. new_surf_lcl->lpSurfMore->lpDD_lcl = this_lcl;
  1460. new_surf_lcl->lpSurfMore->lpDD_int = this_int;
  1461. new_surf_int = NewSurfaceInterface( new_surf_lcl, orig_surf_int->lpVtbl );
  1462. if( new_surf_int == NULL )
  1463. {
  1464. MemFree(new_surf_lcl);
  1465. LEAVE_DDRAW();
  1466. return DDERR_OUTOFMEMORY;
  1467. }
  1468. DD_Surface_AddRef( (LPDIRECTDRAWSURFACE)new_surf_int );
  1469. if( new_surf_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY )
  1470. {
  1471. new_surf_lcl->dbnOverlayNode.object = new_surf_lcl;
  1472. new_surf_lcl->dbnOverlayNode.object_int = new_surf_int;
  1473. }
  1474. LEAVE_DDRAW();
  1475. *lplpDupDDSurface = (LPDIRECTDRAWSURFACE) new_surf_int;
  1476. return DD_OK;
  1477. } /* DD_DuplicateSurface */
  1478. #undef DPF_MODNAME
  1479. #define DPF_MODNAME "GetGDISurface"
  1480. /*
  1481. * DD_GetGDISurface
  1482. *
  1483. * Get the current surface associated with GDI
  1484. */
  1485. HRESULT DDAPI DD_GetGDISurface(
  1486. LPDIRECTDRAW lpDD,
  1487. LPDIRECTDRAWSURFACE FAR *lplpGDIDDSurface )
  1488. {
  1489. LPDDRAWI_DIRECTDRAW_INT this_int;
  1490. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  1491. LPDDRAWI_DIRECTDRAW_GBL this;
  1492. LPDDRAWI_DDRAWSURFACE_INT psurf_int;
  1493. LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
  1494. LPDDRAWI_DDRAWSURFACE_GBL psurf;
  1495. LPDDRAWI_DDRAWSURFACE_INT next_int;
  1496. LPDDRAWI_DDRAWSURFACE_LCL next_lcl;
  1497. LPDDRAWI_DDRAWSURFACE_GBL next;
  1498. ENTER_DDRAW();
  1499. DPF(2,A,"ENTERAPI: DD_GetGDISurface");
  1500. TRY
  1501. {
  1502. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  1503. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  1504. {
  1505. LEAVE_DDRAW();
  1506. return DDERR_INVALIDOBJECT;
  1507. }
  1508. this_lcl = this_int->lpLcl;
  1509. this = this_lcl->lpGbl;
  1510. if( !VALID_PTR_PTR( lplpGDIDDSurface ) )
  1511. {
  1512. DPF_ERR( "Invalid gdi surface pointer" );
  1513. LEAVE_DDRAW();
  1514. return DDERR_INVALIDPARAMS;
  1515. }
  1516. *lplpGDIDDSurface = NULL;
  1517. }
  1518. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1519. {
  1520. DPF_ERR( "Exception encountered validating parameters" );
  1521. LEAVE_DDRAW();
  1522. return DDERR_INVALIDPARAMS;
  1523. }
  1524. /*
  1525. * go find the surface. start at the primary, look at all attached...
  1526. */
  1527. psurf_int = this_lcl->lpPrimary;
  1528. if( psurf_int != NULL )
  1529. {
  1530. psurf_lcl = psurf_int->lpLcl;
  1531. psurf = psurf_lcl->lpGbl;
  1532. if( !(psurf->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE) ) //psurf->fpVidMem != this->fpPrimaryOrig )
  1533. {
  1534. next_int = FindAttachedFlip( psurf_int );
  1535. if( next_int != NULL && next_int != psurf_int )
  1536. {
  1537. next_lcl = next_int->lpLcl;
  1538. next = next_lcl->lpGbl;
  1539. do
  1540. {
  1541. if( next->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE ) //next->fpVidMem == this->fpPrimaryOrig )
  1542. {
  1543. /*
  1544. * DirectDraw's COM behavior has changed with IDD4:
  1545. * IDD4 returns IDDSurface4 and IDD5 returns IDDSurface7.
  1546. * Create the new surface interface object only if we need to.
  1547. */
  1548. if ( !LOWERTHANDDRAW4(this_int) )
  1549. {
  1550. // This is IDD4 or above. Assume IDD4 initially:
  1551. LPVOID pddSurfCB = &ddSurface4Callbacks;
  1552. if (this_int->lpVtbl == &dd7Callbacks)
  1553. {
  1554. // This is IDD7, so we must return IDDSurface7.
  1555. pddSurfCB = &ddSurface7Callbacks;
  1556. }
  1557. if (next_int->lpVtbl != pddSurfCB)
  1558. {
  1559. // Need to make IDDSurface? level match IDD? level.
  1560. next_int = NewSurfaceInterface( next_lcl, pddSurfCB );
  1561. }
  1562. }
  1563. DD_Surface_AddRef( (LPDIRECTDRAWSURFACE) next_int );
  1564. *lplpGDIDDSurface = (LPDIRECTDRAWSURFACE) next_int;
  1565. LEAVE_DDRAW();
  1566. return DD_OK;
  1567. }
  1568. next_int = FindAttachedFlip( next_int );
  1569. } while( next_int != psurf_int );
  1570. }
  1571. DPF_ERR( "Not found" );
  1572. }
  1573. else
  1574. {
  1575. /*
  1576. * DirectDraw's COM behavior has changed with IDD4:
  1577. * IDD4 returns IDDSurface4 and IDD7 returns IDDSurface7.
  1578. * Create the new surface interface object only if we need to.
  1579. */
  1580. if ( !LOWERTHANDDRAW4(this_int) )
  1581. {
  1582. // This is IDD4 or above. Assume IDD4 initially:
  1583. LPVOID pddSurfCB = &ddSurface4Callbacks;
  1584. if (this_int->lpVtbl == &dd7Callbacks)
  1585. {
  1586. // This is IDD7, so we must return IDDSurface7.
  1587. pddSurfCB = &ddSurface7Callbacks;
  1588. }
  1589. if (psurf_int->lpVtbl != pddSurfCB)
  1590. {
  1591. // Need to make IDDSurface? level match IDD? level.
  1592. psurf_int = NewSurfaceInterface( psurf_lcl, pddSurfCB );
  1593. }
  1594. }
  1595. DD_Surface_AddRef( (LPDIRECTDRAWSURFACE) psurf_int );
  1596. *lplpGDIDDSurface = (LPDIRECTDRAWSURFACE) psurf_int;
  1597. LEAVE_DDRAW();
  1598. return DD_OK;
  1599. }
  1600. }
  1601. else
  1602. {
  1603. DPF_ERR( "No Primary Surface" );
  1604. }
  1605. LEAVE_DDRAW();
  1606. return DDERR_NOTFOUND;
  1607. } /* DD_GetGDISurface */
  1608. #undef DPF_MODNAME
  1609. #define DPF_MODNAME "FlipToGDISurface"
  1610. /*
  1611. * FlipToGDISurface
  1612. */
  1613. HRESULT FlipToGDISurface( LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl,
  1614. LPDDRAWI_DDRAWSURFACE_INT psurf_int) //, FLATPTR fpprim )
  1615. {
  1616. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  1617. LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
  1618. LPDDRAWI_DDRAWSURFACE_INT attached_int;
  1619. DDHAL_FLIPTOGDISURFACEDATA ftgsd;
  1620. LPDDHAL_FLIPTOGDISURFACE ftgsfn;
  1621. LPDDHAL_FLIPTOGDISURFACE ftgshalfn;
  1622. HRESULT ddrval;
  1623. pdrv = pdrv_lcl->lpGbl;
  1624. psurf_lcl = psurf_int->lpLcl;
  1625. if( psurf_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
  1626. return DD_OK;
  1627. /*
  1628. * Notify the driver that we are about to flip to GDI
  1629. * surface.
  1630. * NOTE: This is a HAL only call - it means nothing to the
  1631. * HEL.
  1632. * NOTE: If the driver handles this call then we do not
  1633. * attempt to do the actual flip. This is to support cards
  1634. * which do not have GDI surfaces. If the driver does not
  1635. * handle the call we will continue on and do the flip.
  1636. */
  1637. ftgsfn = pdrv_lcl->lpDDCB->HALDD.FlipToGDISurface;
  1638. ftgshalfn = pdrv_lcl->lpDDCB->cbDDCallbacks.FlipToGDISurface;
  1639. if( NULL != ftgshalfn )
  1640. {
  1641. ftgsd.FlipToGDISurface = ftgshalfn;
  1642. ftgsd.lpDD = pdrv;
  1643. ftgsd.dwToGDI = TRUE;
  1644. ftgsd.dwReserved = 0UL;
  1645. DOHALCALL( FlipToGDISurface, ftgsfn, ftgsd, ddrval, FALSE );
  1646. if( DDHAL_DRIVER_HANDLED == ddrval )
  1647. {
  1648. if( !FAILED( ftgsd.ddRVal ) )
  1649. {
  1650. /*
  1651. * The driver is not showing the GDI surface as a
  1652. * result of a flip to GDI operation.
  1653. */
  1654. pdrv->dwFlags |= DDRAWI_FLIPPEDTOGDI;
  1655. DPF( 4, "Driver handled FlipToGDISurface" );
  1656. return ftgsd.ddRVal;
  1657. }
  1658. else
  1659. {
  1660. DPF_ERR( "Driver failed FlipToGDISurface" );
  1661. return ftgsd.ddRVal;
  1662. }
  1663. }
  1664. }
  1665. /*
  1666. * We used to only call this function if the flip was actaully needed,
  1667. * but 3DFX requested that we always call them, so now this fucntion
  1668. * is always called. If we make it this far, it's not a 3DFX and we don't
  1669. * need to do anything more if the GDI surface is already visible.
  1670. */
  1671. if( psurf_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE)
  1672. {
  1673. return DD_OK;
  1674. }
  1675. /*
  1676. * No HAL entry point. If this is not a GDI driver we will
  1677. * fail the call with NOGDI.
  1678. */
  1679. if( ( NULL == ftgshalfn ) && !( pdrv->dwFlags & DDRAWI_DISPLAYDRV ) )
  1680. {
  1681. DPF( 0, "Not a GDI driver" );
  1682. return DDERR_NOGDI;
  1683. }
  1684. /*
  1685. * Driver did not handle FlipToGDISurface so do the default action
  1686. * (the actual flip).
  1687. *
  1688. * go find our partner in the attachment list
  1689. */
  1690. attached_int = FindAttachedFlip( psurf_int );
  1691. if( attached_int == NULL )
  1692. {
  1693. return DDERR_NOTFOUND;
  1694. }
  1695. while( attached_int != psurf_int )
  1696. {
  1697. if( attached_int->lpLcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE) //->lpGbl->fpVidMem == fpprim )
  1698. {
  1699. break;
  1700. }
  1701. attached_int = FindAttachedFlip( attached_int );
  1702. }
  1703. /*
  1704. * flip between the two buddies
  1705. */
  1706. ddrval = DD_Surface_Flip( (LPDIRECTDRAWSURFACE) psurf_int,
  1707. (LPDIRECTDRAWSURFACE) attached_int, DDFLIP_WAIT );
  1708. if( ddrval != DD_OK )
  1709. {
  1710. DPF_ERR( "Couldn't do the flip!" );
  1711. DPF( 5, "Error = %08lx (%ld)", ddrval, LOWORD( ddrval ) );
  1712. }
  1713. /*
  1714. * The driver is now showing the GDI surface as a result of a
  1715. * FlipToGDISurface operation.
  1716. */
  1717. pdrv->dwFlags |= DDRAWI_FLIPPEDTOGDI;
  1718. return ddrval;
  1719. } /* FlipToGDISurface */
  1720. /*
  1721. * DD_FlipToGDISurface
  1722. *
  1723. * Get the current surface associated with GDI
  1724. */
  1725. HRESULT DDAPI DD_FlipToGDISurface( LPDIRECTDRAW lpDD )
  1726. {
  1727. LPDDRAWI_DIRECTDRAW_INT this_int;
  1728. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  1729. LPDDRAWI_DIRECTDRAW_GBL this;
  1730. LPDDRAWI_DDRAWSURFACE_INT psurf_int;
  1731. LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
  1732. LPDDRAWI_DDRAWSURFACE_GBL psurf;
  1733. HRESULT ddrval;
  1734. // FLATPTR fpprim;
  1735. ENTER_DDRAW();
  1736. DPF(2,A,"ENTERAPI: DD_FlipToGDISurface");
  1737. TRY
  1738. {
  1739. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  1740. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  1741. {
  1742. LEAVE_DDRAW();
  1743. return DDERR_INVALIDOBJECT;
  1744. }
  1745. this_lcl = this_int->lpLcl;
  1746. this = this_lcl->lpGbl;
  1747. }
  1748. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1749. {
  1750. DPF_ERR( "Exception encountered validating parameters" );
  1751. LEAVE_DDRAW();
  1752. return DDERR_INVALIDPARAMS;
  1753. }
  1754. psurf_int = this_lcl->lpPrimary;
  1755. if( psurf_int == NULL )
  1756. {
  1757. DPF(2, "No Primary Surface" );
  1758. LEAVE_DDRAW();
  1759. return DDERR_NOTFOUND;
  1760. }
  1761. psurf_lcl = psurf_int->lpLcl;
  1762. psurf = psurf_lcl->lpGbl;
  1763. if( !(psurf_lcl->ddsCaps.dwCaps & DDSCAPS_FLIP) )
  1764. {
  1765. DPF_ERR( "Primary surface isn't flippable" );
  1766. LEAVE_DDRAW();
  1767. return DDERR_NOTFLIPPABLE;
  1768. }
  1769. /*
  1770. * Always call FlipToGDISurface because it benefits 3DFX
  1771. */
  1772. // fpprim = this->fpPrimaryOrig;
  1773. ddrval = FlipToGDISurface( this_lcl, psurf_int); //, fpprim );
  1774. LEAVE_DDRAW();
  1775. return ddrval;
  1776. } /* DD_FlipToGDISurface */
  1777. #undef DPF_MODNAME
  1778. #define DPF_MODNAME "GetFourCCCodes"
  1779. /*
  1780. * DD_GetFourCCCodes
  1781. */
  1782. HRESULT DDAPI DD_GetFourCCCodes(
  1783. LPDIRECTDRAW lpDD,
  1784. DWORD FAR *lpNumCodes,
  1785. DWORD FAR *lpCodes )
  1786. {
  1787. LPDDRAWI_DIRECTDRAW_INT this_int;
  1788. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  1789. LPDDRAWI_DIRECTDRAW_GBL this;
  1790. int numcodes;
  1791. int i;
  1792. ENTER_DDRAW();
  1793. DPF(2,A,"ENTERAPI: DD_GetFourCCCodes");
  1794. TRY
  1795. {
  1796. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  1797. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  1798. {
  1799. LEAVE_DDRAW();
  1800. return DDERR_INVALIDOBJECT;
  1801. }
  1802. this_lcl = this_int->lpLcl;
  1803. this = this_lcl->lpGbl;
  1804. if( !VALID_DWORD_PTR( lpNumCodes ) )
  1805. {
  1806. DPF_ERR( "Invalid number of codes pointer" );
  1807. LEAVE_DDRAW();
  1808. return DDERR_INVALIDPARAMS;
  1809. }
  1810. if( (*lpNumCodes > 0) && (lpCodes != NULL) )
  1811. {
  1812. if( !VALID_DWORD_ARRAY( lpCodes, *lpNumCodes ) )
  1813. {
  1814. DPF_ERR( "Invalid array of codes" );
  1815. LEAVE_DDRAW();
  1816. return DDERR_INVALIDPARAMS;
  1817. }
  1818. }
  1819. if( lpCodes == NULL )
  1820. {
  1821. *lpNumCodes = this->dwNumFourCC;
  1822. }
  1823. else
  1824. {
  1825. numcodes = min( *lpNumCodes, this->dwNumFourCC );
  1826. *lpNumCodes = numcodes;
  1827. for( i=0;i<numcodes;i++ )
  1828. {
  1829. lpCodes[i] = this->lpdwFourCC[i];
  1830. }
  1831. }
  1832. }
  1833. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1834. {
  1835. DPF_ERR( "Exception encountered validating parameters" );
  1836. LEAVE_DDRAW();
  1837. return DDERR_INVALIDPARAMS;
  1838. }
  1839. LEAVE_DDRAW();
  1840. return DD_OK;
  1841. } /* DD_GetFourCCCodes */
  1842. #undef DPF_MODNAME
  1843. #define DPF_MODNAME "Compact"
  1844. /*
  1845. * DD_Compact
  1846. */
  1847. HRESULT DDAPI DD_Compact( LPDIRECTDRAW lpDD )
  1848. {
  1849. LPDDRAWI_DIRECTDRAW_INT this_int;
  1850. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  1851. LPDDRAWI_DIRECTDRAW_GBL this;
  1852. ENTER_DDRAW();
  1853. DPF(2,A,"ENTERAPI: DD_Compact");
  1854. TRY
  1855. {
  1856. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  1857. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  1858. {
  1859. LEAVE_DDRAW();
  1860. return DDERR_INVALIDOBJECT;
  1861. }
  1862. this_lcl = this_int->lpLcl;
  1863. this = this_lcl->lpGbl;
  1864. if( this->lpExclusiveOwner != this_lcl )
  1865. {
  1866. LEAVE_DDRAW();
  1867. return DDERR_NOEXCLUSIVEMODE;
  1868. }
  1869. }
  1870. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1871. {
  1872. DPF_ERR( "Exception encountered validating parameters" );
  1873. LEAVE_DDRAW();
  1874. return DDERR_INVALIDPARAMS;
  1875. }
  1876. #pragma message( REMIND( "Compact not implemented in Rev 1" ) )
  1877. LEAVE_DDRAW();
  1878. return DD_OK;
  1879. }/* DD_Compact */
  1880. #undef DPF_MODNAME
  1881. #define DPF_MODNAME "GetAvailableVidMem"
  1882. /*
  1883. * DD_GetAvailableVidMem
  1884. */
  1885. HRESULT DDAPI DD_GetAvailableVidMem( LPDIRECTDRAW lpDD, LPDDSCAPS lpDDSCaps, LPDWORD lpdwTotal, LPDWORD lpdwFree )
  1886. {
  1887. LPDDRAWI_DIRECTDRAW_INT this_int;
  1888. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  1889. LPDDRAWI_DIRECTDRAW_GBL this;
  1890. DDSCAPS2 ddscaps2 = {0,0,0,0};
  1891. HRESULT hr=DD_OK;
  1892. ENTER_DDRAW();
  1893. DPF(2,A,"ENTERAPI: DD_GetAvailableVidMem");
  1894. TRY
  1895. {
  1896. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  1897. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  1898. {
  1899. LEAVE_DDRAW();
  1900. return DDERR_INVALIDOBJECT;
  1901. }
  1902. this_lcl = this_int->lpLcl;
  1903. this = this_lcl->lpGbl;
  1904. /*
  1905. * This call only considers vram so if running in emulation
  1906. * only there really is no point.
  1907. */
  1908. if( this->dwFlags & DDRAWI_NOHARDWARE )
  1909. {
  1910. DPF_ERR( "No video memory - running emulation only" );
  1911. LEAVE_DDRAW();
  1912. return DDERR_NODIRECTDRAWHW;
  1913. }
  1914. ddscaps2.dwCaps = lpDDSCaps->dwCaps;
  1915. }
  1916. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1917. {
  1918. DPF_ERR( "Invalid DDSCAPS pointer" );
  1919. LEAVE_DDRAW();
  1920. return DDERR_INVALIDPARAMS;
  1921. }
  1922. hr = DD_GetAvailableVidMem4(lpDD, & ddscaps2, lpdwTotal, lpdwFree);
  1923. LEAVE_DDRAW();
  1924. return hr;
  1925. }
  1926. HRESULT DDAPI DD_GetAvailableVidMem4( LPDIRECTDRAW lpDD, LPDDSCAPS2 lpDDSCaps, LPDWORD lpdwTotal, LPDWORD lpdwFree )
  1927. {
  1928. LPDDRAWI_DIRECTDRAW_INT this_int;
  1929. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  1930. LPDDRAWI_DIRECTDRAW_GBL this;
  1931. DWORD dwLocalFree;
  1932. DWORD dwNonLocalFree;
  1933. DWORD dwLocalTotal;
  1934. DWORD dwNonLocalTotal;
  1935. #ifndef WINNT
  1936. LPVIDMEM pvm;
  1937. int i;
  1938. #endif
  1939. LPDDHAL_GETAVAILDRIVERMEMORY gadmfn;
  1940. ENTER_DDRAW();
  1941. DPF(2,A,"ENTERAPI: DD_GetAvailableVidMem4");
  1942. TRY
  1943. {
  1944. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  1945. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  1946. {
  1947. LEAVE_DDRAW();
  1948. return DDERR_INVALIDOBJECT;
  1949. }
  1950. this_lcl = this_int->lpLcl;
  1951. this = this_lcl->lpGbl;
  1952. #ifdef WINNT
  1953. // Update DDraw handle in driver GBL object.
  1954. this->hDD = this_lcl->hDD;
  1955. #endif //WINNT
  1956. /*
  1957. * This call only considers vram so if running in emulation
  1958. * only there really is no point.
  1959. */
  1960. if( this->dwFlags & DDRAWI_NOHARDWARE )
  1961. {
  1962. DPF_ERR( "No video memory - running emulation only" );
  1963. LEAVE_DDRAW();
  1964. return DDERR_NODIRECTDRAWHW;
  1965. }
  1966. if( !VALID_DDSCAPS2_PTR( lpDDSCaps ) )
  1967. {
  1968. LEAVE_DDRAW();
  1969. return DDERR_INVALIDPARAMS;
  1970. }
  1971. /*
  1972. * Check for generically bogus caps.
  1973. */
  1974. if( lpDDSCaps->dwCaps & ~DDSCAPS_VALID )
  1975. {
  1976. DPF_ERR( "Invalid surface caps specified" );
  1977. LEAVE_DDRAW();
  1978. return DDERR_INVALIDCAPS;
  1979. }
  1980. if( lpDDSCaps->dwCaps2 & ~DDSCAPS2_VALID )
  1981. {
  1982. DPF_ERR( "Invalid surface caps2 specified" );
  1983. LEAVE_DDRAW();
  1984. return DDERR_INVALIDCAPS;
  1985. }
  1986. if( lpDDSCaps->dwCaps3 & ~DDSCAPS3_VALID )
  1987. {
  1988. DPF_ERR( "Invalid surface caps3 specified" );
  1989. LEAVE_DDRAW();
  1990. return DDERR_INVALIDCAPS;
  1991. }
  1992. if( lpDDSCaps->dwCaps4 & ~DDSCAPS4_VALID )
  1993. {
  1994. DPF_ERR( "Invalid surface caps4 specified" );
  1995. LEAVE_DDRAW();
  1996. return DDERR_INVALIDCAPS;
  1997. }
  1998. /*
  1999. * !!! NOTE: Consider using the capability checking code
  2000. * of CreateSurface here to ensure no strange bit combinations
  2001. * are passed in.
  2002. */
  2003. if( lpDDSCaps->dwCaps & AVAILVIDMEM_BADSCAPS )
  2004. {
  2005. DPF_ERR( "Invalid surface capability bits specified" );
  2006. LEAVE_DDRAW();
  2007. return DDERR_INVALIDPARAMS;
  2008. }
  2009. /*
  2010. * The caller can pass NULL for lpdwTotal or lpdwFree if
  2011. * they are not interested in that info. However, they
  2012. * can't pass NULL for both.
  2013. */
  2014. if( ( lpdwTotal == NULL ) && ( lpdwFree == NULL ) )
  2015. {
  2016. DPF_ERR( "Can't specify NULL for both total and free memory" );
  2017. LEAVE_DDRAW();
  2018. return DDERR_INVALIDPARAMS;
  2019. }
  2020. if( ( lpdwTotal != NULL ) && !VALID_DWORD_PTR( lpdwTotal ) )
  2021. {
  2022. LEAVE_DDRAW();
  2023. return DDERR_INVALIDPARAMS;
  2024. }
  2025. if( ( lpdwFree != NULL ) && !VALID_DWORD_PTR( lpdwFree ) )
  2026. {
  2027. LEAVE_DDRAW();
  2028. return DDERR_INVALIDPARAMS;
  2029. }
  2030. }
  2031. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2032. {
  2033. DPF_ERR( "Exception encountered validating parameters" );
  2034. LEAVE_DDRAW();
  2035. return DDERR_INVALIDPARAMS;
  2036. }
  2037. // Initialize values
  2038. dwLocalFree = 0UL;
  2039. dwNonLocalFree = 0UL;
  2040. dwLocalTotal = 0UL;
  2041. dwNonLocalTotal = 0UL;
  2042. if( lpdwTotal != NULL )
  2043. {
  2044. *lpdwTotal = 0UL;
  2045. }
  2046. if( lpdwFree != NULL )
  2047. {
  2048. *lpdwFree = 0UL;
  2049. }
  2050. DPF(5,"GetAvailableVidmem called for:");
  2051. DPF_STRUCT(5,V,DDSCAPS2,lpDDSCaps);
  2052. #ifndef WINNT
  2053. for( i=0;i<(int)this->vmiData.dwNumHeaps;i++ )
  2054. {
  2055. pvm = &this->vmiData.pvmList[i];
  2056. /*
  2057. * We use ddsCapsAlt as we wish to return the total amount
  2058. * of memory of the given type it is possible to allocate
  2059. * regardless of whether is is desirable to allocate that
  2060. * type of memory from a given heap or not.
  2061. * We need to keep a separate count of what's in nonlocal,
  2062. * since we may need to cap that amount to respect the commit policy.
  2063. */
  2064. if( (lpDDSCaps->dwCaps & pvm->ddsCapsAlt.dwCaps) == 0 )
  2065. {
  2066. if ( pvm->dwFlags & VIDMEM_ISNONLOCAL )
  2067. {
  2068. DPF(5,V,"Heap number %d adds %08x (%d) free bytes of nonlocal",i,VidMemAmountFree( pvm->lpHeap ),VidMemAmountFree( pvm->lpHeap ));
  2069. DPF(5,V,"Heap number %d adds %08x (%d) allocated bytes of nonlocal",i,VidMemAmountAllocated( pvm->lpHeap ),VidMemAmountAllocated( pvm->lpHeap ));
  2070. dwNonLocalFree += VidMemAmountFree( pvm->lpHeap );
  2071. dwNonLocalTotal += VidMemAmountAllocated( pvm->lpHeap );
  2072. }
  2073. else
  2074. {
  2075. DPF(5,V,"Heap number %d adds %08x free bytes of local",i,VidMemAmountFree( pvm->lpHeap ));
  2076. DPF(5,V,"Heap number %d adds %08x (%d) allocated bytes of local",i,VidMemAmountAllocated( pvm->lpHeap ),VidMemAmountAllocated( pvm->lpHeap ));
  2077. dwLocalFree += VidMemAmountFree( pvm->lpHeap );
  2078. dwLocalTotal += VidMemAmountAllocated( pvm->lpHeap );
  2079. }
  2080. }
  2081. }
  2082. dwLocalTotal += dwLocalFree;
  2083. dwNonLocalTotal += dwNonLocalFree;
  2084. #endif //not WINNT
  2085. // Try asking the driver
  2086. gadmfn = this_lcl->lpDDCB->HALDDMiscellaneous.GetAvailDriverMemory;
  2087. /*
  2088. * Only ask the driver about nonlocal vidmem if it understands the concept.
  2089. */
  2090. if( (gadmfn != NULL) &&
  2091. (((lpDDSCaps->dwCaps & DDSCAPS_NONLOCALVIDMEM) == 0) || (this->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM))
  2092. )
  2093. {
  2094. DDHAL_GETAVAILDRIVERMEMORYDATA gadmd;
  2095. DWORD rc;
  2096. DDASSERT( VALIDEX_CODE_PTR( gadmfn ) );
  2097. gadmd.lpDD = this;
  2098. gadmd.DDSCaps.dwCaps = lpDDSCaps->dwCaps;
  2099. gadmd.ddsCapsEx = lpDDSCaps->ddsCapsEx;
  2100. DOHALCALL( GetAvailDriverMemory, gadmfn, gadmd, rc, FALSE );
  2101. if( rc == DDHAL_DRIVER_HANDLED )
  2102. {
  2103. if( lpDDSCaps->dwCaps & DDSCAPS_NONLOCALVIDMEM )
  2104. {
  2105. DPF(5,V,"Driver adds %08x private free nonlocal bytes",gadmd.dwFree);
  2106. DPF(5,V,"Driver adds %08x private total nonlocal bytes",gadmd.dwTotal);
  2107. dwNonLocalFree += gadmd.dwFree;
  2108. dwNonLocalTotal += gadmd.dwTotal;
  2109. }
  2110. else
  2111. {
  2112. DPF(5,V,"Driver adds %08x (%d) private free local bytes",gadmd.dwFree,gadmd.dwFree);
  2113. DPF(5,V,"Driver adds %08x (%d) private total local bytes",gadmd.dwTotal,gadmd.dwTotal);
  2114. dwLocalFree += gadmd.dwFree;
  2115. dwLocalTotal += gadmd.dwTotal;
  2116. }
  2117. }
  2118. else
  2119. {
  2120. DPF_ERR( "GetAvailDriverMemory failed!" );
  2121. }
  2122. }
  2123. if( lpdwFree != NULL )
  2124. {
  2125. *lpdwFree = dwLocalFree;
  2126. if (lpDDSCaps->dwCaps & DDSCAPS_NONLOCALVIDMEM)
  2127. {
  2128. //report nonlocal if it was asked for
  2129. *lpdwFree += dwNonLocalFree;
  2130. }
  2131. else if ( ((this->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEMCAPS) == 0) ||
  2132. ((this_lcl->lpGbl->lpD3DGlobalDriverData) &&
  2133. (this_lcl->lpGbl->lpD3DGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_TEXTURENONLOCALVIDMEM ) &&
  2134. (lpDDSCaps->dwCaps & DDSCAPS_TEXTURE) )
  2135. )
  2136. {
  2137. //If nonlocal wasn't asked for, then report it only if it's either execute model, or the app is asking
  2138. //for textures, and the part can texture nonlocal
  2139. *lpdwFree += dwNonLocalFree;
  2140. }
  2141. }
  2142. if( lpdwTotal != NULL )
  2143. {
  2144. *lpdwTotal = dwLocalTotal;
  2145. if (lpDDSCaps->dwCaps & DDSCAPS_NONLOCALVIDMEM)
  2146. {
  2147. //report nonlocal if it was asked for
  2148. *lpdwTotal += dwNonLocalTotal;
  2149. }
  2150. else if ( ((this->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEMCAPS) == 0) ||
  2151. ((this_lcl->lpGbl->lpD3DGlobalDriverData) &&
  2152. (this_lcl->lpGbl->lpD3DGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_TEXTURENONLOCALVIDMEM ) &&
  2153. (lpDDSCaps->dwCaps & DDSCAPS_TEXTURE) )
  2154. )
  2155. {
  2156. //If nonlocal wasn't asked for, then report it only if it's either execute model, or the app is asking
  2157. //for textures, and the part can texture nonlocal
  2158. *lpdwTotal += dwNonLocalTotal;
  2159. }
  2160. }
  2161. LEAVE_DDRAW();
  2162. return DD_OK;
  2163. } /* DD_GetAvailableVidMem */
  2164. #undef DPF_MODNAME
  2165. #define DPF_MODNAME "DD_Initialize"
  2166. /*
  2167. * DD_Initialize
  2168. *
  2169. * Initialize a DirectDraw object that was created via the class factory
  2170. */
  2171. HRESULT DDAPI DD_Initialize( LPDIRECTDRAW lpDD, GUID FAR * lpGUID )
  2172. {
  2173. LPDDRAWI_DIRECTDRAW_INT this_int;
  2174. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  2175. HRESULT hr;
  2176. LPDIRECTDRAW tmplpdd;
  2177. LPVOID lpOldCallbacks;
  2178. IUnknown *lpOldIUnknown=NULL;
  2179. BOOL bDX7=FALSE;
  2180. ENTER_DDRAW();
  2181. DPF(2,A,"ENTERAPI: DD_Initialize");
  2182. /* DPF_ENTERAPI(lpDD); */
  2183. DPF( 5, "****** DirectDraw::Initialize( 0x%08lx ) ******", lpGUID );
  2184. TRY
  2185. {
  2186. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  2187. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  2188. {
  2189. LEAVE_DDRAW();
  2190. return DDERR_INVALIDOBJECT;
  2191. }
  2192. this_lcl = this_int->lpLcl;
  2193. if( this_lcl->lpGbl != NULL )
  2194. {
  2195. DPF_ERR( "Already initialized." );
  2196. LEAVE_DDRAW();
  2197. return DDERR_ALREADYINITIALIZED;
  2198. }
  2199. }
  2200. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2201. {
  2202. DPF_ERR( "Exception encountered validating parameters" );
  2203. LEAVE_DDRAW();
  2204. return DDERR_INVALIDPARAMS;
  2205. }
  2206. /*
  2207. * If the object is uninitialized put the real vtable in place.
  2208. */
  2209. lpOldCallbacks = NULL;
  2210. if( this_int->lpVtbl == &ddUninitCallbacks )
  2211. {
  2212. lpOldCallbacks = this_int->lpVtbl;
  2213. this_int->lpVtbl = &ddCallbacks;
  2214. }
  2215. else if( this_int->lpVtbl == &dd2UninitCallbacks )
  2216. {
  2217. lpOldCallbacks = this_int->lpVtbl;
  2218. this_int->lpVtbl = &dd2Callbacks;
  2219. }
  2220. else if( this_int->lpVtbl == &dd4UninitCallbacks )
  2221. {
  2222. lpOldCallbacks = this_int->lpVtbl;
  2223. this_int->lpVtbl = &dd4Callbacks;
  2224. }
  2225. else if( this_int->lpVtbl == &dd7UninitCallbacks )
  2226. {
  2227. lpOldCallbacks = this_int->lpVtbl;
  2228. this_int->lpVtbl = &dd7Callbacks;
  2229. bDX7=TRUE;
  2230. }
  2231. /*
  2232. * Note that a call to Initialize off of the uninitnondelegatingiunknown vtbl
  2233. * is not possible, since the Initialize method doesn't exist in that interface
  2234. */
  2235. #ifdef POSTPONED
  2236. /*
  2237. * Also need to fix up the owning unknown to point to the initialized non delegating unknown
  2238. * This is the non-aggregated case. In the aggregated case, the owning IUnknown will
  2239. * not have our vtable, and we also don't need to mess with it.
  2240. */
  2241. lpOldIUnknown = this_int->lpLcl->pUnkOuter;
  2242. if (this_int->lpLcl->pUnkOuter == (IUnknown*) &UninitNonDelegatingIUnknownInterface )
  2243. {
  2244. this_int->lpLcl->pUnkOuter = (IUnknown*) &NonDelegatingIUnknownInterface;
  2245. }
  2246. #endif
  2247. hr = InternalDirectDrawCreate( (GUID *)lpGUID, &tmplpdd, this_int, bDX7 ? DDRAWILCL_DIRECTDRAW7 : 0UL, NULL );
  2248. if( FAILED( hr ) && ( lpOldCallbacks != NULL ) )
  2249. {
  2250. /*
  2251. * As initialization has failed put the vtable and the owner back the way it was
  2252. * before.
  2253. */
  2254. this_int->lpVtbl = lpOldCallbacks;
  2255. #ifdef POSTPONED
  2256. this_int->lpLcl->pUnkOuter = lpOldIUnknown;
  2257. #endif
  2258. }
  2259. LEAVE_DDRAW();
  2260. return hr;
  2261. } /* DD_Initialize */
  2262. #ifdef WINNT
  2263. BOOL IsWinlogonThread (void)
  2264. {
  2265. BOOL fResult = FALSE;
  2266. DWORD dwLengthNeeded;
  2267. TCHAR szThreadDesktopName[256];
  2268. if (GetUserObjectInformation(GetThreadDesktop(GetCurrentThreadId()),
  2269. UOI_NAME,
  2270. szThreadDesktopName,
  2271. sizeof(szThreadDesktopName),
  2272. &dwLengthNeeded))
  2273. {
  2274. fResult = (BOOL)(lstrcmpi(szThreadDesktopName, TEXT("winlogon")) == 0);
  2275. if (fResult)
  2276. DPF(0,"Is winlogon thread");
  2277. }
  2278. return fResult;
  2279. }
  2280. #endif
  2281. BOOL DesktopIsVisible()
  2282. {
  2283. #ifdef WINNT
  2284. BOOL retval=FALSE;
  2285. HDC hdc = GetDC(NULL);
  2286. if (hdc)
  2287. {
  2288. HRGN hrgn = CreateRectRgn(0, 0, 0, 0);
  2289. if (hrgn)
  2290. {
  2291. if (GetRandomRgn(hdc, hrgn, SYSRGN) == 1)
  2292. {
  2293. RECT rect;
  2294. retval = (BOOL) (GetRgnBox(hrgn, &rect) != NULLREGION);
  2295. if (!retval)
  2296. {
  2297. if (IsWinlogonThread())
  2298. {
  2299. //We must be on winlogon's process... so desktop IS visible...
  2300. retval = TRUE;
  2301. }
  2302. }
  2303. }
  2304. DeleteObject(hrgn);
  2305. }
  2306. ReleaseDC(NULL, hdc);
  2307. }
  2308. return retval;
  2309. #else
  2310. return TRUE;
  2311. #endif
  2312. }
  2313. HRESULT DDAPI DD_TestCooperativeLevel(LPDIRECTDRAW lpDD)
  2314. {
  2315. LPDDRAWI_DIRECTDRAW_INT this_int;
  2316. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  2317. LPDDRAWI_DIRECTDRAW_GBL this;
  2318. HRESULT hr;
  2319. BOOL has_excl;
  2320. BOOL excl_exists;
  2321. ENTER_DDRAW();
  2322. DPF(2,A,"ENTERAPI: DD_TestCooperativeLevel");
  2323. TRY
  2324. {
  2325. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  2326. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  2327. {
  2328. LEAVE_DDRAW();
  2329. return DDERR_INVALIDOBJECT;
  2330. }
  2331. this_lcl = this_int->lpLcl;
  2332. this = this_lcl->lpGbl;
  2333. /*
  2334. * If we're in a fullscreen DOS box, we need to let them know that
  2335. * they don't have it and that they can't get it.
  2336. */
  2337. if( *(this->lpwPDeviceFlags) & BUSY )
  2338. {
  2339. if ( this_lcl->dwLocalFlags & DDRAWILCL_HASEXCLUSIVEMODE )
  2340. {
  2341. hr = DDERR_NOEXCLUSIVEMODE;
  2342. }
  2343. else
  2344. {
  2345. hr = DDERR_EXCLUSIVEMODEALREADYSET;
  2346. }
  2347. LEAVE_DDRAW();
  2348. return hr;
  2349. }
  2350. }
  2351. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2352. {
  2353. DPF_ERR( "Exception encountered validating parameters" );
  2354. LEAVE_DDRAW();
  2355. return DDERR_INVALIDPARAMS;
  2356. }
  2357. CheckExclusiveMode(this_lcl, &excl_exists, &has_excl, FALSE, NULL, FALSE);
  2358. if ( this_lcl->dwLocalFlags & DDRAWILCL_HASEXCLUSIVEMODE )
  2359. {
  2360. /*
  2361. * Either the app has exclusive mode or it does not
  2362. */
  2363. if ( has_excl && DesktopIsVisible() )
  2364. {
  2365. hr = DD_OK;
  2366. }
  2367. else
  2368. {
  2369. hr = DDERR_NOEXCLUSIVEMODE;
  2370. }
  2371. }
  2372. else
  2373. {
  2374. if ( excl_exists || !DesktopIsVisible() )
  2375. {
  2376. hr = DDERR_EXCLUSIVEMODEALREADYSET;
  2377. }
  2378. else
  2379. {
  2380. #ifdef WIN95
  2381. if ( this->dwModeIndex == this_lcl->dwPreferredMode )
  2382. #else
  2383. if (EQUAL_DISPLAYMODE(this->dmiCurrent, this_lcl->dmiPreferred))
  2384. #endif
  2385. {
  2386. hr = DD_OK;
  2387. }
  2388. else
  2389. {
  2390. hr = DDERR_WRONGMODE;
  2391. }
  2392. }
  2393. }
  2394. LEAVE_DDRAW();
  2395. return hr;
  2396. } /* DD_TestCooperativeLevel */
  2397. #ifdef DEBUG
  2398. /*
  2399. * These are the DPF structure dumpers.
  2400. * If you want to dump a structure, add a function with the prototype
  2401. * void DUMP_<structure-name> (DWORD level, DWORD topic, LP<structure-name> lpStruct);
  2402. *
  2403. */
  2404. /*
  2405. * Dump a DDPIXELFORMAT
  2406. */
  2407. void DUMP_DDPIXELFORMAT (DWORD level, DWORD topic, LPDDPIXELFORMAT lpDDPF)
  2408. {
  2409. if (!lpDDPF)
  2410. {
  2411. DPF(level,topic," DDPIXELFORMAT NULL");
  2412. return;
  2413. }
  2414. DPF(level,topic,"Flags:");
  2415. if (lpDDPF->dwFlags & DDPF_ALPHAPIXELS )
  2416. DPF(level,topic," DDPF_ALPHAPIXELS");
  2417. if (lpDDPF->dwFlags & DDPF_ALPHA )
  2418. DPF(level,topic," DDPF_ALPHA ");
  2419. if (lpDDPF->dwFlags & DDPF_FOURCC )
  2420. DPF(level,topic," DDPF_FOURCC = %08x",lpDDPF->dwFourCC);
  2421. if (lpDDPF->dwFlags & DDPF_PALETTEINDEXED4 )
  2422. DPF(level,topic," DDPF_PALETTEINDEXED4 ");
  2423. if (lpDDPF->dwFlags & DDPF_PALETTEINDEXEDTO8)
  2424. DPF(level,topic," DDPF_PALETTEINDEXEDTO8");
  2425. if (lpDDPF->dwFlags & DDPF_PALETTEINDEXED8 )
  2426. DPF(level,topic," DDPF_PALETTEINDEXED8 ");
  2427. if (lpDDPF->dwFlags & DDPF_RGB )
  2428. DPF(level,topic," DDPF_RGB ");
  2429. if (lpDDPF->dwFlags & DDPF_COMPRESSED )
  2430. DPF(level,topic," DDPF_COMPRESSED ");
  2431. if (lpDDPF->dwFlags & DDPF_RGBTOYUV )
  2432. DPF(level,topic," DDPF_RGBTOYUV ");
  2433. if (lpDDPF->dwFlags & DDPF_YUV )
  2434. DPF(level,topic," DDPF_YUV ");
  2435. if (lpDDPF->dwFlags & DDPF_ZBUFFER )
  2436. DPF(level,topic," DDPF_ZBUFFER ");
  2437. if (lpDDPF->dwFlags & DDPF_PALETTEINDEXED1 )
  2438. DPF(level,topic," DDPF_PALETTEINDEXED1 ");
  2439. if (lpDDPF->dwFlags & DDPF_PALETTEINDEXED2 )
  2440. DPF(level,topic," DDPF_PALETTEINDEXED2 ");
  2441. if (lpDDPF->dwFlags & DDPF_ZPIXELS )
  2442. DPF(level,topic," DDPF_ZPIXELS ");
  2443. if (lpDDPF->dwFlags & DDPF_STENCILBUFFER )
  2444. DPF(level,topic," DDPF_STENCILBUFFER ");
  2445. DPF(level,topic," BitCount:%d",lpDDPF->dwRGBBitCount);
  2446. DPF(level,topic," Bitmasks: R/Y/StencDepth:%08x, G/U/ZMask:%08x, B/V/StencMask:%08x, Alpha/Z:%08x",
  2447. lpDDPF->dwRBitMask,
  2448. lpDDPF->dwGBitMask,
  2449. lpDDPF->dwBBitMask,
  2450. lpDDPF->dwRGBAlphaBitMask);
  2451. }
  2452. /*
  2453. * Dump a ddscaps
  2454. */
  2455. void DUMP_DDSCAPS (DWORD level, DWORD topic, LPDDSCAPS lpDDSC)
  2456. {
  2457. if (!lpDDSC)
  2458. {
  2459. DPF(level,topic," DDSCAPS NULL");
  2460. return;
  2461. }
  2462. if (lpDDSC->dwCaps & DDSCAPS_ALPHA)
  2463. DPF(level,topic," DDSCAPS_ALPHA");
  2464. if (lpDDSC->dwCaps & DDSCAPS_BACKBUFFER)
  2465. DPF(level,topic," DDSCAPS_BACKBUFFER");
  2466. if (lpDDSC->dwCaps & DDSCAPS_COMPLEX)
  2467. DPF(level,topic," DDSCAPS_COMPLEX");
  2468. if (lpDDSC->dwCaps & DDSCAPS_FLIP)
  2469. DPF(level,topic," DDSCAPS_FLIP");
  2470. if (lpDDSC->dwCaps & DDSCAPS_FRONTBUFFER)
  2471. DPF(level,topic," DDSCAPS_FRONTBUFFER");
  2472. if (lpDDSC->dwCaps & DDSCAPS_OFFSCREENPLAIN)
  2473. DPF(level,topic," DDSCAPS_OFFSCREENPLAIN");
  2474. if (lpDDSC->dwCaps & DDSCAPS_OVERLAY)
  2475. DPF(level,topic," DDSCAPS_OVERLAY");
  2476. if (lpDDSC->dwCaps & DDSCAPS_PALETTE)
  2477. DPF(level,topic," DDSCAPS_PALETTE");
  2478. if (lpDDSC->dwCaps & DDSCAPS_PRIMARYSURFACE)
  2479. DPF(level,topic," DDSCAPS_PRIMARYSURFACE");
  2480. if (lpDDSC->dwCaps & DDSCAPS_PRIMARYSURFACELEFT)
  2481. DPF(level,topic," DDSCAPS_PRIMARYSURFACELEFT");
  2482. if (lpDDSC->dwCaps & DDSCAPS_SYSTEMMEMORY)
  2483. DPF(level,topic," DDSCAPS_SYSTEMMEMORY");
  2484. if (lpDDSC->dwCaps & DDSCAPS_TEXTURE)
  2485. DPF(level,topic," DDSCAPS_TEXTURE");
  2486. if (lpDDSC->dwCaps & DDSCAPS_3DDEVICE)
  2487. DPF(level,topic," DDSCAPS_3DDEVICE");
  2488. if (lpDDSC->dwCaps & DDSCAPS_VIDEOMEMORY)
  2489. DPF(level,topic," DDSCAPS_VIDEOMEMORY");
  2490. if (lpDDSC->dwCaps & DDSCAPS_VISIBLE)
  2491. DPF(level,topic," DDSCAPS_VISIBLE");
  2492. if (lpDDSC->dwCaps & DDSCAPS_WRITEONLY)
  2493. DPF(level,topic," DDSCAPS_WRITEONLY");
  2494. if (lpDDSC->dwCaps & DDSCAPS_ZBUFFER)
  2495. DPF(level,topic," DDSCAPS_ZBUFFER");
  2496. if (lpDDSC->dwCaps & DDSCAPS_OWNDC)
  2497. DPF(level,topic," DDSCAPS_OWNDC");
  2498. if (lpDDSC->dwCaps & DDSCAPS_LIVEVIDEO)
  2499. DPF(level,topic," DDSCAPS_LIVEVIDEO");
  2500. if (lpDDSC->dwCaps & DDSCAPS_HWCODEC)
  2501. DPF(level,topic," DDSCAPS_HWCODEC");
  2502. if (lpDDSC->dwCaps & DDSCAPS_MODEX)
  2503. DPF(level,topic," DDSCAPS_MODEX");
  2504. if (lpDDSC->dwCaps & DDSCAPS_MIPMAP)
  2505. DPF(level,topic," DDSCAPS_MIPMAP");
  2506. #ifdef SHAREDZ
  2507. if (lpDDSC->dwCaps & DDSCAPS_SHAREDZBUFFER)
  2508. DPF(level,topic," DDSCAPS_SHAREDZBUFFER");
  2509. if (lpDDSC->dwCaps & DDSCAPS_SHAREDBACKBUFFER)
  2510. DPF(level,topic," DDSCAPS_SHAREDBACKBUFFER");
  2511. #endif
  2512. if (lpDDSC->dwCaps & DDSCAPS_ALLOCONLOAD)
  2513. DPF(level,topic," DDSCAPS_ALLOCONLOAD");
  2514. if (lpDDSC->dwCaps & DDSCAPS_VIDEOPORT)
  2515. DPF(level,topic," DDSCAPS_VIDEOPORT");
  2516. if (lpDDSC->dwCaps & DDSCAPS_LOCALVIDMEM)
  2517. DPF(level,topic," DDSCAPS_LOCALVIDMEM");
  2518. if (lpDDSC->dwCaps & DDSCAPS_NONLOCALVIDMEM)
  2519. DPF(level,topic," DDSCAPS_NONLOCALVIDMEM");
  2520. if (lpDDSC->dwCaps & DDSCAPS_STANDARDVGAMODE)
  2521. DPF(level,topic," DDSCAPS_STANDARDVGAMODE");
  2522. if (lpDDSC->dwCaps & DDSCAPS_OPTIMIZED)
  2523. DPF(level,topic," DDSCAPS_OPTIMIZED");
  2524. }
  2525. /*
  2526. * Dump a DDSCAPS2
  2527. */
  2528. void DUMP_DDSCAPS2 (DWORD level, DWORD topic, LPDDSCAPS2 lpDDSC)
  2529. {
  2530. DUMP_DDSCAPS(level,topic,(LPDDSCAPS)lpDDSC);
  2531. //no more to dump yet
  2532. }
  2533. /*
  2534. * Dump a DDSURFACEDESC
  2535. */
  2536. void DUMP_DDSURFACEDESC (DWORD level, DWORD topic, LPDDSURFACEDESC lpDDSD)
  2537. {
  2538. if (!lpDDSD)
  2539. {
  2540. DPF(level,topic," DDSURFACEDESC NULL");
  2541. return;
  2542. }
  2543. if (lpDDSD->dwFlags & DDSD_HEIGHT)
  2544. DPF(level,topic," DDSURFACEDESC->dwHeight = %d",lpDDSD->dwHeight);
  2545. if (lpDDSD->dwFlags & DDSD_WIDTH)
  2546. DPF(level,topic," DDSURFACEDESC->dwWidth = %d",lpDDSD->dwWidth);
  2547. if (lpDDSD->dwFlags & DDSD_PITCH)
  2548. DPF(level,topic," DDSURFACEDESC->lPitch = %d",lpDDSD->lPitch);
  2549. if (lpDDSD->dwFlags & DDSD_BACKBUFFERCOUNT)
  2550. DPF(level,topic," DDSURFACEDESC->dwBackBufferCount = %d",lpDDSD->dwBackBufferCount);
  2551. if (lpDDSD->dwFlags & DDSD_ZBUFFERBITDEPTH)
  2552. DPF(level,topic," DDSURFACEDESC->dwZBufferBitDepth = %d",lpDDSD->dwZBufferBitDepth);
  2553. if (lpDDSD->dwFlags & DDSD_MIPMAPCOUNT)
  2554. DPF(level,topic," DDSURFACEDESC->dwMipMapCount = %d",lpDDSD->dwMipMapCount);
  2555. if (lpDDSD->dwFlags & DDSD_REFRESHRATE)
  2556. DPF(level,topic," DDSURFACEDESC->dwRefreshRate = %d",lpDDSD->dwRefreshRate);
  2557. /*if (lpDDSD->dwFlags & DDSD_LPSURFACE)*/
  2558. DPF(level,topic," DDSURFACEDESC->lpSurface = %08x",lpDDSD->lpSurface);
  2559. if (lpDDSD->dwFlags & DDSD_PIXELFORMAT)
  2560. DUMP_DDPIXELFORMAT(level,topic, &lpDDSD->ddpfPixelFormat);
  2561. if (lpDDSD->dwFlags & DDSD_CAPS)
  2562. DUMP_DDSCAPS(level,topic, &lpDDSD->ddsCaps);
  2563. }
  2564. /*
  2565. * Dump a DDSURFACEDESC2
  2566. */
  2567. void DUMP_DDSURFACEDESC2 (DWORD level, DWORD topic, LPDDSURFACEDESC2 lpDDSD)
  2568. {
  2569. if (!lpDDSD)
  2570. {
  2571. DPF(level,topic," DDSURFACEDESC2 NULL");
  2572. return;
  2573. }
  2574. if (lpDDSD->dwFlags & DDSD_HEIGHT)
  2575. DPF(level,topic," DDSURFACEDESC2->dwHeight = %d",lpDDSD->dwHeight);
  2576. if (lpDDSD->dwFlags & DDSD_WIDTH)
  2577. DPF(level,topic," DDSURFACEDESC2->dwWidth = %d",lpDDSD->dwWidth);
  2578. if (lpDDSD->dwFlags & DDSD_PITCH)
  2579. DPF(level,topic," DDSURFACEDESC2->lPitch = %d",lpDDSD->lPitch);
  2580. if (lpDDSD->dwFlags & DDSD_BACKBUFFERCOUNT)
  2581. DPF(level,topic," DDSURFACEDESC2->dwBackBufferCount = %d",lpDDSD->dwBackBufferCount);
  2582. if (lpDDSD->dwFlags & DDSD_MIPMAPCOUNT)
  2583. DPF(level,topic," DDSURFACEDESC2->dwMipMapCount = %d",lpDDSD->dwMipMapCount);
  2584. if (lpDDSD->dwFlags & DDSD_REFRESHRATE)
  2585. DPF(level,topic," DDSURFACEDESC2->dwRefreshRate = %d",lpDDSD->dwRefreshRate);
  2586. /*if (lpDDSD->dwFlags & DDSD_LPSURFACE)*/
  2587. DPF(level,topic," DDSURFACEDESC2->lpSurface = %08x",lpDDSD->lpSurface);
  2588. if (lpDDSD->dwFlags & DDSD_PIXELFORMAT)
  2589. DUMP_DDPIXELFORMAT(level,topic, &lpDDSD->ddpfPixelFormat);
  2590. if (lpDDSD->dwFlags & DDSD_CAPS)
  2591. DUMP_DDSCAPS2(level,topic, &lpDDSD->ddsCaps);
  2592. }
  2593. /*
  2594. * Dump a DDOPTSURFACEDESC
  2595. */
  2596. void DUMP_DDOPTSURFACEDESC (DWORD level, DWORD topic, LPDDOPTSURFACEDESC lpDDSD)
  2597. {
  2598. if (!lpDDSD)
  2599. {
  2600. DPF(level,topic," DDOPTSURFACEDESC NULL");
  2601. return;
  2602. }
  2603. #if 0
  2604. if (lpDDSD->dwFlags & DDOSD_GUID)
  2605. DPF(level,topic," DDOPTSURFACEDESC->guid = %08x, %08x, %08x, %08x",lpDDSD->dwHeight);
  2606. #endif
  2607. if (lpDDSD->dwFlags & DDOSD_COMPRESSION_RATIO)
  2608. DPF(level,topic," DDOPTSURFACEDESC->dwCompressionRatio = %d",lpDDSD->dwCompressionRatio);
  2609. }
  2610. #endif //def DEBUG
  2611. /*
  2612. * GetInternalPointer
  2613. * This function can be called with a ULONG_PTR ordinal value, and will return
  2614. * a ULONG_PTR value.
  2615. */
  2616. ULONG_PTR __stdcall GetOLEThunkData(ULONG_PTR dwOrdinal)
  2617. {
  2618. extern DWORD dwLastFrameRate;
  2619. switch(dwOrdinal)
  2620. {
  2621. case 0x1:
  2622. return dwLastFrameRate;
  2623. case 0x2:
  2624. return (ULONG_PTR) lpDriverObjectList;
  2625. case 0x3:
  2626. return (ULONG_PTR) lpAttachedProcesses;
  2627. case 0x4:
  2628. return 0;
  2629. case 0x5:
  2630. return (ULONG_PTR) CheckExclusiveMode;
  2631. case 6:
  2632. RELEASE_EXCLUSIVEMODE_MUTEX;
  2633. return 0;
  2634. }
  2635. return 0;
  2636. }
  2637. /*
  2638. * Check if exclusive mode is owned, and if so if it is owned by this ddraw local.
  2639. * This routine only works if the calling thread owns the ddraw critical section (which is assumed
  2640. * to at least own ddraw for all threads in this process.)
  2641. *
  2642. * We are only allowed to test for this ddraw object owning exclusive mode if this process
  2643. * owns the exclusive mode mutex. If it does, then the ddraw csect allows us to know that
  2644. * this thread can check the lpExclusiveOwner in the ddraw gbl thread-safely.
  2645. *
  2646. * The routine can optionally hold the exclusive mode mutex. This is done when the caller wishes to
  2647. * change the state of the ddraw gbl lpExclusiveOwner.
  2648. *
  2649. * Note that this routine will ONLY take the mutex if it's possible that this local can own exclusive mode.
  2650. * This means that callers only need to worry about releasing the mutex if
  2651. */
  2652. void CheckExclusiveMode(LPDDRAWI_DIRECTDRAW_LCL this_lcl, LPBOOL pbExclusiveExists, LPBOOL pbThisLclOwnsExclusive, BOOL bKeepMutex, HWND hwnd, BOOL bCanGetIt)
  2653. {
  2654. LPDDRAWI_DIRECTDRAW_GBL this_gbl;
  2655. DWORD dwWaitResult;
  2656. this_gbl = this_lcl->lpGbl;
  2657. #ifdef WINNT
  2658. WaitForSingleObject( hCheckExclusiveModeMutex, INFINITE );
  2659. dwWaitResult = WaitForSingleObject(hExclusiveModeMutex, 0);
  2660. if (dwWaitResult == WAIT_OBJECT_0)
  2661. {
  2662. #endif
  2663. /*
  2664. * OK, so this process owns the exlusive mode object,
  2665. * are we the process (really the ddraw lcl) with exclusive mode?
  2666. */
  2667. if (pbExclusiveExists)
  2668. *pbExclusiveExists = (BOOL)( NULL != this_gbl->lpExclusiveOwner );
  2669. if (pbThisLclOwnsExclusive)
  2670. *pbThisLclOwnsExclusive = (BOOL) ( this_gbl->lpExclusiveOwner == this_lcl );
  2671. /*
  2672. * It is possible that another app has set exclusive mode
  2673. * on another monitor, or that the same app is calling w/o first
  2674. */
  2675. if( pbExclusiveExists )
  2676. {
  2677. if( !( *pbExclusiveExists ) )
  2678. {
  2679. LPDDRAWI_DIRECTDRAW_INT pdrv_int;
  2680. pdrv_int = lpDriverObjectList;
  2681. while (pdrv_int != NULL )
  2682. {
  2683. if( ( pdrv_int->lpLcl->lpGbl != this_gbl ) &&
  2684. ( pdrv_int->lpLcl->dwLocalFlags & DDRAWILCL_HASEXCLUSIVEMODE ) &&
  2685. ( pdrv_int->lpLcl->lpGbl->lpExclusiveOwner == pdrv_int->lpLcl ) )
  2686. {
  2687. if( bCanGetIt )
  2688. {
  2689. if( ( pdrv_int->lpLcl->hFocusWnd != PtrToUlong(hwnd) ) &&
  2690. ( pdrv_int->lpLcl->lpGbl->dwFlags & DDRAWI_DISPLAYDRV ) &&
  2691. ( this_gbl->dwFlags & DDRAWI_DISPLAYDRV ) )
  2692. {
  2693. *pbExclusiveExists = TRUE;
  2694. break;
  2695. }
  2696. }
  2697. else
  2698. {
  2699. *pbExclusiveExists = TRUE;
  2700. break;
  2701. }
  2702. }
  2703. pdrv_int = pdrv_int->lpLink;
  2704. }
  2705. }
  2706. }
  2707. #ifdef WINNT
  2708. /*
  2709. * Undo the temporary ref we just took on the mutex to check its state, if we're not actually
  2710. * taking ownership. We are not taking ownership if we already have ownership. This means this routine
  2711. * doesn't allow more than one ref on the exclusive mode mutex.
  2712. */
  2713. if (!bKeepMutex || *pbThisLclOwnsExclusive)
  2714. {
  2715. ReleaseMutex( hExclusiveModeMutex );
  2716. }
  2717. }
  2718. else if (dwWaitResult == WAIT_TIMEOUT)
  2719. {
  2720. /*
  2721. * Some other thread owns the exclusive mode mutex. If that other thread took the mutex
  2722. * on this_lcl as well, then the current thread owns excl. mode.
  2723. *
  2724. * We can still check if the exclusive owner is us, because all we're doing is checking
  2725. * pointers that can only be set by whoever owns the mutex. The owner pointer will be 0
  2726. * until it becomes (until the mutex is released) some pointer. Thus we will never get
  2727. * a false positive when this thread asks if it owns excl. mode here.
  2728. */
  2729. if (this_gbl->lpExclusiveOwner == this_lcl)
  2730. {
  2731. if (pbExclusiveExists)
  2732. *pbExclusiveExists = TRUE;
  2733. if (pbThisLclOwnsExclusive)
  2734. *pbThisLclOwnsExclusive = TRUE;
  2735. }
  2736. else
  2737. {
  2738. if (pbExclusiveExists)
  2739. *pbExclusiveExists = TRUE;
  2740. if (pbThisLclOwnsExclusive)
  2741. *pbThisLclOwnsExclusive = FALSE;
  2742. }
  2743. }
  2744. else if (dwWaitResult == WAIT_ABANDONED)
  2745. {
  2746. /*
  2747. * Some other thread lost exclusive mode. We have now picked it up.
  2748. */
  2749. if (pbExclusiveExists)
  2750. *pbExclusiveExists = FALSE;
  2751. if (pbThisLclOwnsExclusive)
  2752. *pbThisLclOwnsExclusive = FALSE;
  2753. /*
  2754. * Undo the temporary ref we just took on the mutex to check its state, if we're not actually
  2755. * taking ownership.
  2756. */
  2757. if (!bKeepMutex)
  2758. {
  2759. ReleaseMutex( hExclusiveModeMutex );
  2760. }
  2761. }
  2762. else
  2763. {
  2764. DPF(0, "Unexpected return from WaitForSingleObject.");
  2765. DDASSERT(FALSE);
  2766. if (pbExclusiveExists)
  2767. *pbExclusiveExists = TRUE;
  2768. if (pbThisLclOwnsExclusive)
  2769. *pbThisLclOwnsExclusive = FALSE;
  2770. }
  2771. ReleaseMutex( hCheckExclusiveModeMutex );
  2772. #endif
  2773. }