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.

13680 lines
480 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: ddraw.cxx
  3. *
  4. * Contains all of GDI's private DirectDraw APIs.
  5. *
  6. * Created: 3-Dec-1995
  7. * Author: J. Andrew Goossen [andrewgo]
  8. *
  9. * Copyright (c) 1995-1999 Microsoft Corporation
  10. *
  11. \**************************************************************************/
  12. #include "precomp.hxx"
  13. #if 0
  14. #define DBG_DDKHEAP
  15. #define DDKHEAP(Args) KdPrint(Args)
  16. #else
  17. #define DDKHEAP(Args)
  18. #endif
  19. #if 0
  20. #define DBG_DDKSURF
  21. #define DDKSURF(Args) KdPrint(Args)
  22. #else
  23. #define DDKSURF(Args)
  24. #endif
  25. // Several AGP routines take an hdev that is some cookie useful in
  26. // AGP operations. On NT, it's a pointer to the EDD_DIRECTDRAW_GLOBAL.
  27. // This macro is largely just a marker in case it changes in the
  28. // future.
  29. #define AGP_HDEV(peDirectDrawGlobal) ((HANDLE)peDirectDrawGlobal)
  30. // This variable is kept for stress debugging purposes. When a mode change
  31. // or desktop change is pending and an application has outstanding locks
  32. // on the frame buffer, we will by default wait up to 7 seconds for the
  33. // application to release its locks, before we will unmap the view anyway.
  34. // 'gfpUnmap' will be user-mode address of the unmapped frame buffer, which
  35. // will be useful for determining in stress whether an application had its
  36. // frame buffer access rescinded, or whether it was using a completely bogus
  37. // frame buffer pointer to begin with:
  38. FLATPTR gfpUnmap = 0;
  39. // The following global variables are kept only for debugging purposes, to
  40. // aid in tracking DC drawing to surfaces that have been lost:
  41. HDC ghdcGetDC;
  42. HDC ghdcCantLose;
  43. #ifdef DX_REDIRECTION
  44. // The following global variable is kept the boolean value if system are in
  45. // redirection mode or not.
  46. //
  47. // If system is in redirection mode, we disable ...
  48. //
  49. // + Overlay.
  50. // + Primary surface lock (LATER).
  51. //
  52. // !!! Currently this is 'per system' status, so that we can have global variable
  53. // !!! simply here, but it could be 'per process' or 'per hWnd' in later version.
  54. // !!! (it's up to how Window manager manage its status)
  55. BOOL gbDxRedirection = FALSE;
  56. #endif // DX_REDIRECTION
  57. #if DBG
  58. /******************************Public*Routine******************************\
  59. * VOID vDdAssertDevlock
  60. *
  61. * Debug code for verifying that the devlock is currently held.
  62. *
  63. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  64. * Wrote it.
  65. \**************************************************************************/
  66. VOID
  67. vDdAssertShareDevlock()
  68. {
  69. #if 0 // TODO: DBG - IsSem...
  70. ASSERTGDI(GreIsSemaphoreOwnedByCurrentThread(ghsemShareDevLock),
  71. "DD_ASSERTSHAREDEVLOCK failed");
  72. #endif
  73. }
  74. VOID
  75. vDdAssertDevlock(
  76. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal
  77. )
  78. {
  79. ASSERTGDI(DxEngIsHdevLockedByCurrentThread(peDirectDrawGlobal->hdev),
  80. "DD_ASSERTDEVLOCK failed because Devlock is not held");
  81. }
  82. /******************************Public*Routine******************************\
  83. * VOID vDdAssertNoDevlock
  84. *
  85. * Debug code for verifying that the devlock is currently not held.
  86. *
  87. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  88. * Wrote it.
  89. \**************************************************************************/
  90. VOID
  91. vDdAssertNoDevlock(
  92. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal
  93. )
  94. {
  95. ASSERTGDI(!DxEngIsHdevLockedByCurrentThread(peDirectDrawGlobal->hdev),
  96. "DD_ASSERTNODEVLOCK failed because Devlock held but shouldn't be!");
  97. }
  98. #endif // DBG
  99. /******************************Public*Routine******************************\
  100. * BOOL bDdIntersect
  101. *
  102. * Ubiquitous lower-right exclusive intersection detection.
  103. *
  104. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  105. * Wrote it.
  106. \**************************************************************************/
  107. inline
  108. BOOL
  109. bDdIntersect(
  110. RECTL* pA,
  111. RECTL* pB
  112. )
  113. {
  114. return((pA->left < pB->right) &&
  115. (pA->top < pB->bottom) &&
  116. (pA->right > pB->left) &&
  117. (pA->bottom > pB->top));
  118. }
  119. /******************************Public*Routine******************************\
  120. * BOOL bDdValidateDriverData
  121. *
  122. * Performs some parameter validation on the info DirectDraw info returned
  123. * from the driver.
  124. *
  125. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  126. * Wrote it.
  127. \**************************************************************************/
  128. BOOL
  129. bDdValidateDriverData(
  130. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal
  131. )
  132. {
  133. BOOL b;
  134. DDNTCORECAPS* pCaps;
  135. b = TRUE;
  136. if ((peDirectDrawGlobal->HalInfo.vmiData.ddpfDisplay.dwRGBBitCount != 8) &&
  137. (peDirectDrawGlobal->HalInfo.vmiData.ddpfDisplay.dwRGBBitCount != 16) &&
  138. (peDirectDrawGlobal->HalInfo.vmiData.ddpfDisplay.dwRGBBitCount != 24) &&
  139. (peDirectDrawGlobal->HalInfo.vmiData.ddpfDisplay.dwRGBBitCount != 32))
  140. {
  141. RIP("HalInfo.vmiData.ddpfDisplay.dwRGBBitCount not 8, 16, 24 or 32");
  142. b = FALSE;
  143. }
  144. if (peDirectDrawGlobal->HalInfo.vmiData.lDisplayPitch == 0)
  145. {
  146. RIP("HalInfo.vmiData.lDisplayPitch is 0");
  147. b = FALSE;
  148. }
  149. pCaps = &peDirectDrawGlobal->HalInfo.ddCaps;
  150. // Check to see if 'Blt' must be hooked:
  151. if (pCaps->dwCaps & (DDCAPS_BLT
  152. | DDCAPS_BLTCOLORFILL
  153. | DDCAPS_COLORKEY))
  154. {
  155. if (!(peDirectDrawGlobal->SurfaceCallBacks.dwFlags & DDHAL_SURFCB32_BLT) ||
  156. (peDirectDrawGlobal->SurfaceCallBacks.Blt == NULL))
  157. {
  158. RIP("HalInfo.ddCaps.dwCaps indicate driver must hook Blt\n");
  159. b = FALSE;
  160. }
  161. }
  162. // We only permit a subset of the DirectDraw capabilities to be hooked
  163. // by the driver, because the kernel-mode code paths for any other
  164. // capabilities have not been tested:
  165. if (pCaps->dwCaps & (DDCAPS_GDI
  166. | DDCAPS_PALETTE
  167. | DDCAPS_ZOVERLAYS
  168. | DDCAPS_BANKSWITCHED))
  169. {
  170. RIP("HalInfo.ddCaps.dwCaps has capabilities set that aren't supported by NT\n");
  171. b = FALSE;
  172. }
  173. if (pCaps->dwCaps2 & (DDCAPS2_CERTIFIED))
  174. {
  175. RIP("HalInfo.ddCaps.dwCaps2 has capabilities set that aren't supported by NT\n");
  176. b = FALSE;
  177. }
  178. if (pCaps->ddsCaps.dwCaps & (DDSCAPS_SYSTEMMEMORY
  179. | DDSCAPS_WRITEONLY
  180. | DDSCAPS_OWNDC
  181. | DDSCAPS_MODEX))
  182. {
  183. RIP("HalInfo.ddCaps.ddsCaps.dwCaps has capabilities set that aren't supported by NT\n");
  184. b = FALSE;
  185. }
  186. if (pCaps->dwFXCaps & ( DDFXCAPS_BLTROTATION
  187. | DDFXCAPS_BLTROTATION90))
  188. {
  189. RIP("HalInfo.ddCaps.dwFXCaps has capabilities set that aren't supported by NT\n");
  190. b = FALSE;
  191. }
  192. /*
  193. * WINBUG #55100 2-1-2000 bhouse Alpha restrictions need to be revisited when AlphaBlt DDI is enabled.
  194. * We used to check and fail on the presence of either of the following bits:
  195. * DDFXALPHACAPS_BLTALPHASURFACES 0x00000008l
  196. * DDFXALPHACAPS_OVERLAYALPHASURFACES 0x00000100l
  197. */
  198. if (pCaps->dwPalCaps != 0)
  199. {
  200. RIP("HalInfo.ddCaps.dwPalCaps has capabilities set that aren't supported by NT\n");
  201. b = FALSE;
  202. }
  203. // GDI will handle the emulation of system-memory to video-memory blts.
  204. // Page-locking from user-mode is not allowed on NT, so
  205. // DDSCAPS2_NOPAGELOCKEDREQUIRED should always be set:
  206. if (!(pCaps->dwCaps & DDCAPS_CANBLTSYSMEM) &&
  207. (peDirectDrawGlobal->SurfaceCallBacks.dwFlags & DDHAL_SURFCB32_BLT) &&
  208. (peDirectDrawGlobal->SurfaceCallBacks.Blt != NULL))
  209. {
  210. peDirectDrawGlobal->flDriver |= DD_DRIVER_FLAG_EMULATE_SYSTEM_TO_VIDEO;
  211. pCaps->dwCaps2 |= DDCAPS2_NOPAGELOCKREQUIRED;
  212. }
  213. return(b);
  214. }
  215. /******************************Public*Routine******************************\
  216. * BOOL bDdGetDriverInfo
  217. *
  218. * Assumes devlock already held.
  219. *
  220. * In case the driver partially filled in the structure before it decided
  221. * to fail, we always zero the buffer in the event of failure.
  222. *
  223. * 16-Feb-1997 -by- J. Andrew Goossen [andrewgo]
  224. * Wrote it.
  225. \**************************************************************************/
  226. BOOL
  227. bDdGetDriverInfo(
  228. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal,
  229. const GUID* pGuid,
  230. VOID* pvBuffer,
  231. ULONG cjSize,
  232. ULONG* pjSizeReturned
  233. )
  234. {
  235. PDD_GETDRIVERINFO pfnGetDriverInfo;
  236. DD_GETDRIVERINFODATA GetDriverInfoData;
  237. DWORD dwRet = DDHAL_DRIVER_NOTHANDLED;
  238. DWORD dwSize;
  239. DD_ASSERTDEVLOCK(peDirectDrawGlobal);
  240. pfnGetDriverInfo = peDirectDrawGlobal->HalInfo.GetDriverInfo;
  241. if( ( pfnGetDriverInfo != NULL ) &&
  242. (peDirectDrawGlobal->HalInfo.dwFlags & DDHALINFO_GETDRIVERINFOSET))
  243. {
  244. RtlZeroMemory(&GetDriverInfoData, sizeof(GetDriverInfoData));
  245. GetDriverInfoData.dhpdev = peDirectDrawGlobal->dhpdev;
  246. GetDriverInfoData.dwSize = sizeof(GetDriverInfoData);
  247. GetDriverInfoData.guidInfo = *pGuid;
  248. GetDriverInfoData.dwExpectedSize = cjSize;
  249. GetDriverInfoData.lpvData = pvBuffer;
  250. GetDriverInfoData.ddRVal = DDERR_CURRENTLYNOTAVAIL;
  251. dwRet = pfnGetDriverInfo(&GetDriverInfoData);
  252. }
  253. if (dwRet == DDHAL_DRIVER_HANDLED &&
  254. GetDriverInfoData.ddRVal == DD_OK)
  255. {
  256. if (pjSizeReturned != NULL)
  257. {
  258. *pjSizeReturned = GetDriverInfoData.dwActualSize;
  259. }
  260. return TRUE;
  261. }
  262. else
  263. {
  264. RtlZeroMemory(pvBuffer, cjSize);
  265. if (pjSizeReturned != NULL)
  266. {
  267. *pjSizeReturned = 0;
  268. }
  269. return FALSE;
  270. }
  271. }
  272. /******************************Public*Routine******************************\
  273. * BOOL bDdIoQueryInterface
  274. *
  275. * 12-Feb-1998 -by- Drew Bliss [drewb]
  276. * Made vDdQueryMiniportDxApiSupport generic for QI requests.
  277. \**************************************************************************/
  278. BOOL
  279. bDdIoQueryInterface(
  280. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal,
  281. const GUID* pguid,
  282. DWORD cjInterface,
  283. DWORD dwDesiredVersion,
  284. INTERFACE* pInterface
  285. )
  286. {
  287. BOOL bSuccess;
  288. PDEVICE_OBJECT hDevice;
  289. KEVENT event;
  290. PIRP pIrp;
  291. IO_STATUS_BLOCK Iosb;
  292. PIO_STACK_LOCATION stack;
  293. DDGETIRQINFO GetIrqInfo;
  294. bSuccess = FALSE; // Assume failure
  295. DD_ASSERTDEVLOCK(peDirectDrawGlobal); // Synchronize call into miniport
  296. PDEVOBJ po(peDirectDrawGlobal->hdev);
  297. hDevice = (PDEVICE_OBJECT) po.hScreen();
  298. KeInitializeEvent(&event, SynchronizationEvent, FALSE);
  299. pIrp = IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS,
  300. hDevice,
  301. NULL,
  302. 0,
  303. NULL,
  304. &event,
  305. &Iosb);
  306. if (pIrp != NULL)
  307. {
  308. pIrp->IoStatus.Status = Iosb.Status = STATUS_NOT_SUPPORTED;
  309. stack = IoGetNextIrpStackLocation(pIrp);
  310. stack->MajorFunction
  311. = IRP_MJ_PNP;
  312. stack->MinorFunction
  313. = IRP_MN_QUERY_INTERFACE;
  314. stack->Parameters.QueryInterface.InterfaceType
  315. = pguid;
  316. stack->Parameters.QueryInterface.Size
  317. = (USHORT)cjInterface;
  318. stack->Parameters.QueryInterface.Version
  319. = (USHORT)dwDesiredVersion;
  320. stack->Parameters.QueryInterface.Interface
  321. = pInterface;
  322. stack->Parameters.QueryInterface.InterfaceSpecificData
  323. = NULL;
  324. // Note that we allow newer interfaces to work with older system
  325. // code so that new drivers can run on older systems.
  326. if (NT_SUCCESS(IoCallDriver(hDevice, pIrp)))
  327. {
  328. if ((pInterface->Version >= dwDesiredVersion) &&
  329. (pInterface->Size >= cjInterface) &&
  330. (pInterface->Context != NULL))
  331. {
  332. bSuccess = TRUE;
  333. }
  334. else
  335. {
  336. WARNING("bDdIoQueryInterface: "
  337. "Driver returned invalid QueryInterface data.");
  338. }
  339. }
  340. }
  341. else
  342. {
  343. WARNING("bDdIoQueryInterface: Unable to build request.");
  344. }
  345. return bSuccess;
  346. }
  347. /******************************Public*Routine******************************\
  348. * BOOL bDdGetAllDriverInfo
  349. *
  350. * Makes GetDriverInfo HAL calls to determine capabilities of the device,
  351. * such as for Direct3D or VPE.
  352. *
  353. * Assumes devlock already held.
  354. *
  355. * 16-Feb-1997 -by- J. Andrew Goossen [andrewgo]
  356. * Wrote it.
  357. \**************************************************************************/
  358. BOOL
  359. bDdGetAllDriverInfo(
  360. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal
  361. )
  362. {
  363. DWORD dwMaxVideoPorts;
  364. ULONG cjMaxVideoPorts;
  365. DDVIDEOPORTCAPS* pVideoPortCaps;
  366. ULONG i;
  367. DWORD dwRet;
  368. DWORD dwOverride;
  369. DD_ASSERTDEVLOCK(peDirectDrawGlobal);
  370. PDEVOBJ po(peDirectDrawGlobal->hdev);
  371. // Get driver override info:
  372. dwOverride = po.dwDriverCapableOverride();
  373. // Get DXAPI info:
  374. vDdQueryMiniportDxApiSupport(peDirectDrawGlobal);
  375. // Get AGP info:
  376. if (!bDdIoQueryInterface(peDirectDrawGlobal,
  377. &GUID_AGP_INTERFACE,
  378. sizeof(AGP_INTERFACE),
  379. AGP_INTERFACE_VERSION,
  380. (INTERFACE *)
  381. &peDirectDrawGlobal->AgpInterface))
  382. {
  383. RtlZeroMemory(&peDirectDrawGlobal->AgpInterface,
  384. sizeof(peDirectDrawGlobal->AgpInterface));
  385. }
  386. if ((peDirectDrawGlobal->HalInfo.GetDriverInfo != NULL) &&
  387. (peDirectDrawGlobal->HalInfo.dwFlags & DDHALINFO_GETDRIVERINFOSET))
  388. {
  389. // DX5 callbacks are never used on NT so we do not bother to ask the driver for them
  390. // We simply zero them out
  391. RtlZeroMemory(&peDirectDrawGlobal->D3dCallBacks2,
  392. sizeof(peDirectDrawGlobal->D3dCallBacks2));
  393. // Get D3DCallbacks3. If this fails the callbacks will
  394. // be NULL. Also check if this driver is capable of doing D3D or not
  395. if ((!(dwOverride & DRIVER_NOT_CAPABLE_D3D))
  396. &&bDdGetDriverInfo(peDirectDrawGlobal,
  397. &GUID_D3DCallbacks3,
  398. &peDirectDrawGlobal->D3dCallBacks3,
  399. sizeof(peDirectDrawGlobal->D3dCallBacks3),
  400. NULL))
  401. {
  402. // It needs to accept a new GUID
  403. if (bDdGetDriverInfo(peDirectDrawGlobal,
  404. &GUID_D3DParseUnknownCommandCallback,
  405. &D3DParseUnknownCommand, 0, NULL))
  406. {
  407. peDirectDrawGlobal->flDriverInfo |= DD_DRIVERINFO_D3DCALLBACKS3;
  408. }
  409. else
  410. {
  411. // If the GUID is not recognized, stub out Callbacks3
  412. WARNING("vDdGetAllDriverInfo: Driver failed GUID_D3DParseUnknownCommandCallback but understood GUID_D3DCallbacks3");
  413. RtlZeroMemory(&peDirectDrawGlobal->D3dCallBacks3,
  414. sizeof(peDirectDrawGlobal->D3dCallBacks3));
  415. return FALSE;
  416. }
  417. }
  418. // Note: GUID_ZPixelFormats is not queried because kernel doesn't need to
  419. // store the DDPIXELFORMATS data
  420. // Get DXAPI ("Kernel-Mode") capabilities.
  421. dwRet = DXERR_GENERIC;
  422. if (bDdGetDriverInfo(peDirectDrawGlobal,
  423. &GUID_KernelCaps,
  424. &peDirectDrawGlobal->DDKernelCaps,
  425. sizeof(peDirectDrawGlobal->DDKernelCaps),
  426. NULL))
  427. {
  428. /*
  429. * They may have said that they have IRQ capabilites, but
  430. * we need to make sure this is really the case. For this,
  431. * we can call the GetIRQInfo function in the miniport.
  432. */
  433. if( peDirectDrawGlobal->DxApiInterface.DxGetIrqInfo != NULL )
  434. {
  435. DDGETIRQINFO GetIRQInfo;
  436. dwRet = peDirectDrawGlobal->DxApiInterface.DxGetIrqInfo(
  437. peDirectDrawGlobal->HwDeviceExtension,
  438. NULL,
  439. &GetIRQInfo);
  440. if( GetIRQInfo.dwFlags != IRQINFO_HANDLED )
  441. {
  442. dwRet = DXERR_GENERIC;
  443. }
  444. }
  445. }
  446. if( dwRet != DX_OK )
  447. {
  448. peDirectDrawGlobal->DDKernelCaps.dwIRQCaps = 0;
  449. peDirectDrawGlobal->DDKernelCaps.dwCaps &= ~( DDKERNELCAPS_AUTOFLIP |
  450. DDKERNELCAPS_CAPTURE_SYSMEM | DDKERNELCAPS_CAPTURE_NONLOCALVIDMEM );
  451. }
  452. // Get VPE info:
  453. dwMaxVideoPorts = peDirectDrawGlobal->HalInfo.ddCaps.dwMaxVideoPorts;
  454. if (dwMaxVideoPorts != 0)
  455. {
  456. if (bDdGetDriverInfo(peDirectDrawGlobal,
  457. &GUID_VideoPortCallbacks,
  458. &peDirectDrawGlobal->VideoPortCallBacks,
  459. sizeof(peDirectDrawGlobal->VideoPortCallBacks),
  460. NULL))
  461. {
  462. cjMaxVideoPorts = sizeof(DDVIDEOPORTCAPS) * dwMaxVideoPorts;
  463. pVideoPortCaps = (DDVIDEOPORTCAPS*) PALLOCMEM(cjMaxVideoPorts,
  464. 'pddG');
  465. if (pVideoPortCaps != NULL)
  466. {
  467. if (bDdGetDriverInfo(peDirectDrawGlobal,
  468. &GUID_VideoPortCaps,
  469. pVideoPortCaps,
  470. cjMaxVideoPorts,
  471. NULL))
  472. {
  473. peDirectDrawGlobal->HalInfo.ddCaps.dwMaxVideoPorts
  474. = dwMaxVideoPorts;
  475. peDirectDrawGlobal->lpDDVideoPortCaps
  476. = pVideoPortCaps;
  477. peDirectDrawGlobal->flDriverInfo
  478. |= DD_DRIVERINFO_VIDEOPORT;
  479. for (i = 0; i < dwMaxVideoPorts; i++)
  480. {
  481. if (peDirectDrawGlobal->DDKernelCaps.dwIRQCaps
  482. & (DDIRQ_VPORT0_VSYNC << (i * 2)) &&
  483. (peDirectDrawGlobal->DDKernelCaps.dwCaps
  484. & DDKERNELCAPS_AUTOFLIP))
  485. {
  486. // Can do software autoflipping.
  487. pVideoPortCaps[i].dwCaps |= DDVPCAPS_AUTOFLIP;
  488. pVideoPortCaps[i].dwNumAutoFlipSurfaces
  489. = MAX_AUTOFLIP_BUFFERS;
  490. if (pVideoPortCaps[i].dwCaps & DDVPCAPS_VBISURFACE)
  491. {
  492. pVideoPortCaps[i].dwNumVBIAutoFlipSurfaces
  493. = MAX_AUTOFLIP_BUFFERS;
  494. }
  495. }
  496. }
  497. }
  498. else
  499. {
  500. RIP("vDdGetAllDriverInfo: Driver failed GUID_VideoPortCaps");
  501. RtlZeroMemory(&peDirectDrawGlobal->VideoPortCallBacks,
  502. sizeof(peDirectDrawGlobal->VideoPortCallBacks));
  503. VFREEMEM(pVideoPortCaps);
  504. }
  505. }
  506. }
  507. }
  508. // Get ColorControl info:
  509. if (bDdGetDriverInfo(peDirectDrawGlobal,
  510. &GUID_ColorControlCallbacks,
  511. &peDirectDrawGlobal->ColorControlCallBacks,
  512. sizeof(peDirectDrawGlobal->ColorControlCallBacks),
  513. NULL))
  514. {
  515. peDirectDrawGlobal->flDriverInfo |= DD_DRIVERINFO_COLORCONTROL;
  516. }
  517. // Get Miscellaneous info:
  518. if (bDdGetDriverInfo(peDirectDrawGlobal,
  519. &GUID_MiscellaneousCallbacks,
  520. &peDirectDrawGlobal->MiscellaneousCallBacks,
  521. sizeof(peDirectDrawGlobal->MiscellaneousCallBacks),
  522. NULL))
  523. {
  524. peDirectDrawGlobal->flDriverInfo |= DD_DRIVERINFO_MISCELLANEOUS;
  525. }
  526. // Get Miscellaneous2 info:
  527. if (bDdGetDriverInfo(peDirectDrawGlobal,
  528. &GUID_Miscellaneous2Callbacks,
  529. &peDirectDrawGlobal->Miscellaneous2CallBacks,
  530. sizeof(peDirectDrawGlobal->Miscellaneous2CallBacks),
  531. NULL))
  532. {
  533. peDirectDrawGlobal->flDriverInfo |= DD_DRIVERINFO_MISCELLANEOUS2;
  534. }
  535. else
  536. {
  537. // If the GUID is not recognized, stub out D3DCallbacks3...
  538. RtlZeroMemory(&peDirectDrawGlobal->D3dCallBacks3,
  539. sizeof(peDirectDrawGlobal->D3dCallBacks3));
  540. // ... and clear the bit
  541. peDirectDrawGlobal->flDriverInfo &= ~DD_DRIVERINFO_D3DCALLBACKS3;
  542. // Stub out all other d3d driver info
  543. RtlZeroMemory(&peDirectDrawGlobal->D3dDriverData,
  544. sizeof(peDirectDrawGlobal->D3dDriverData));
  545. RtlZeroMemory(&peDirectDrawGlobal->D3dCallBacks,
  546. sizeof(peDirectDrawGlobal->D3dCallBacks));
  547. RtlZeroMemory(&peDirectDrawGlobal->D3dBufCallbacks,
  548. sizeof(peDirectDrawGlobal->D3dBufCallbacks));
  549. }
  550. // Get NT info:
  551. if (bDdGetDriverInfo(peDirectDrawGlobal,
  552. &GUID_NTCallbacks,
  553. &peDirectDrawGlobal->NTCallBacks,
  554. sizeof(peDirectDrawGlobal->NTCallBacks),
  555. NULL))
  556. {
  557. peDirectDrawGlobal->flDriverInfo |= DD_DRIVERINFO_NT;
  558. }
  559. // Get MoreCaps info:
  560. if (bDdGetDriverInfo(peDirectDrawGlobal,
  561. &GUID_DDMoreCaps,
  562. &peDirectDrawGlobal->MoreCaps,
  563. sizeof(peDirectDrawGlobal->MoreCaps),
  564. NULL))
  565. {
  566. peDirectDrawGlobal->flDriverInfo |= DD_DRIVERINFO_MORECAPS;
  567. }
  568. // Get PrivateDriverCaps info. If the driver is not capable of D3D
  569. // then don't do it
  570. if ((!(dwOverride & DRIVER_NOT_CAPABLE_D3D))
  571. &&(bDdGetDriverInfo(peDirectDrawGlobal,
  572. &GUID_NTPrivateDriverCaps,
  573. &peDirectDrawGlobal->PrivateCaps,
  574. sizeof(peDirectDrawGlobal->PrivateCaps),
  575. NULL)))
  576. {
  577. peDirectDrawGlobal->flDriverInfo |= DD_DRIVERINFO_PRIVATECAPS;
  578. }
  579. // Get DXAPI ("Kernel-Mode") call-backs. Note that we don't bother
  580. // with a flag because user-mode never needs to know whether the
  581. // driver has actually hooked these or not.
  582. bDdGetDriverInfo(peDirectDrawGlobal,
  583. &GUID_KernelCallbacks,
  584. &peDirectDrawGlobal->DxApiCallBacks,
  585. sizeof(peDirectDrawGlobal->DxApiCallBacks),
  586. NULL);
  587. // Get MotionComp info:
  588. if (bDdGetDriverInfo(peDirectDrawGlobal,
  589. &GUID_MotionCompCallbacks,
  590. &peDirectDrawGlobal->MotionCompCallbacks,
  591. sizeof(peDirectDrawGlobal->MotionCompCallbacks),
  592. NULL))
  593. {
  594. peDirectDrawGlobal->flDriverInfo |= DD_DRIVERINFO_MOTIONCOMP;
  595. }
  596. }
  597. // Determine if the device supports gamma ramps or not
  598. peDirectDrawGlobal->HalInfo.ddCaps.dwCaps2 &= ~DDCAPS2_PRIMARYGAMMA;
  599. if ((po.iDitherFormat() == BMF_8BPP) ||
  600. ((PPFNVALID(po, IcmSetDeviceGammaRamp)) &&
  601. (po.flGraphicsCaps2() & GCAPS2_CHANGEGAMMARAMP)))
  602. {
  603. peDirectDrawGlobal->HalInfo.ddCaps.dwCaps2 |= DDCAPS2_PRIMARYGAMMA;
  604. }
  605. // Squish any ROP caps that the driver may have set so apps will
  606. // know that they're not supported.
  607. RtlZeroMemory(peDirectDrawGlobal->HalInfo.ddCaps.dwRops,
  608. sizeof( peDirectDrawGlobal->HalInfo.ddCaps.dwRops ) );
  609. RtlZeroMemory(peDirectDrawGlobal->HalInfo.ddCaps.dwSVBRops,
  610. sizeof( peDirectDrawGlobal->HalInfo.ddCaps.dwSVBRops ) );
  611. RtlZeroMemory(peDirectDrawGlobal->HalInfo.ddCaps.dwVSBRops,
  612. sizeof( peDirectDrawGlobal->HalInfo.ddCaps.dwVSBRops ) );
  613. RtlZeroMemory(peDirectDrawGlobal->HalInfo.ddCaps.dwSSBRops,
  614. sizeof( peDirectDrawGlobal->HalInfo.ddCaps.dwSSBRops ) );
  615. return TRUE;
  616. }
  617. /******************************Public*Routine******************************\
  618. * DWORD dwDdSetAGPPolicy()
  619. *
  620. * Reads the DirectDraw AGP policy value from the registry and adjusts as
  621. * necessary.
  622. *
  623. * Note: This policy only restricts the size per heap. If the driver exposes
  624. * more than 1 heap, it should do extra work to determine reasonable heap
  625. * sizes based on total physical memory and perhaps other data.
  626. *
  627. * 28-Sep-1999 -by- John Stephens [johnstep]
  628. * Copied from llDdAssertModeTimeout().
  629. \**************************************************************************/
  630. #define AGP_BASE_MEMORY_PAGES ((64 * 1024 * 1024) / PAGE_SIZE)
  631. // The following are the limits of an AGP reservation:
  632. #define AGP_MINIMUM_MAX_PAGES ((8 * 1024 * 1024) / PAGE_SIZE)
  633. #define AGP_MAXIMUM_MAX_PAGES ((256 * 1024 * 1024) / PAGE_SIZE)
  634. DWORD
  635. dwDdSetAgpPolicy(
  636. )
  637. {
  638. HANDLE hkRegistry;
  639. OBJECT_ATTRIBUTES ObjectAttributes;
  640. UNICODE_STRING UnicodeString;
  641. NTSTATUS status;
  642. DWORD Length;
  643. DWORD Policy;
  644. PKEY_VALUE_FULL_INFORMATION Information;
  645. SYSTEM_BASIC_INFORMATION BasicInfo;
  646. SYSINF_PAGE_COUNT PageCount;
  647. status = ZwQuerySystemInformation(SystemBasicInformation,
  648. (VOID*) &BasicInfo,
  649. sizeof BasicInfo,
  650. NULL);
  651. if (!NT_SUCCESS(status) ||
  652. (BasicInfo.NumberOfPhysicalPages < AGP_MINIMUM_MAX_PAGES))
  653. {
  654. return 0;
  655. }
  656. // By default, we let them use all of the memory minus 64 Meg
  657. PageCount = BasicInfo.NumberOfPhysicalPages - AGP_BASE_MEMORY_PAGES;
  658. if (PageCount < AGP_MAXIMUM_MAX_PAGES) {
  659. Policy = (DWORD)PageCount;
  660. } else {
  661. Policy = AGP_MAXIMUM_MAX_PAGES;
  662. }
  663. if ((Policy < AGP_MINIMUM_MAX_PAGES) ||
  664. (BasicInfo.NumberOfPhysicalPages < AGP_BASE_MEMORY_PAGES))
  665. {
  666. // But some drivers (nvidia) really need to have at least 8 Meg, so we
  667. // need to give them at least that much.
  668. Policy = AGP_MINIMUM_MAX_PAGES;
  669. }
  670. RtlInitUnicodeString(&UnicodeString,
  671. L"\\Registry\\Machine\\System\\CurrentControlSet\\"
  672. L"Control\\GraphicsDrivers");
  673. InitializeObjectAttributes(&ObjectAttributes,
  674. &UnicodeString,
  675. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  676. NULL,
  677. NULL);
  678. status = ZwOpenKey(&hkRegistry, GENERIC_READ, &ObjectAttributes);
  679. if (NT_SUCCESS(status))
  680. {
  681. RtlInitUnicodeString(&UnicodeString, L"AGPPolicyMaxPages");
  682. Length = sizeof(KEY_VALUE_FULL_INFORMATION) + sizeof(L"AGPPolicyMaxPages") +
  683. sizeof(DWORD);
  684. Information = (PKEY_VALUE_FULL_INFORMATION) PALLOCMEM(Length, ' ddG');
  685. if (Information)
  686. {
  687. status = ZwQueryValueKey(hkRegistry,
  688. &UnicodeString,
  689. KeyValueFullInformation,
  690. Information,
  691. Length,
  692. &Length);
  693. if (NT_SUCCESS(status))
  694. {
  695. Policy = *( (LPDWORD) ((((PUCHAR)Information) +
  696. Information->DataOffset)) );
  697. }
  698. VFREEMEM(Information);
  699. }
  700. ZwCloseKey(hkRegistry);
  701. }
  702. // Clamp policy maximum pages:
  703. if (Policy < AGP_MINIMUM_MAX_PAGES)
  704. {
  705. Policy = 0;
  706. }
  707. else
  708. {
  709. Policy = min(Policy, AGP_MAXIMUM_MAX_PAGES);
  710. if (BasicInfo.NumberOfPhysicalPages > AGP_BASE_MEMORY_PAGES)
  711. {
  712. Policy = (DWORD)min( Policy,
  713. (BasicInfo.NumberOfPhysicalPages -
  714. AGP_BASE_MEMORY_PAGES));
  715. }
  716. // Round down to the nearest 64 KB multiple and convert to bytes:
  717. Policy = (Policy & ~0xF) * PAGE_SIZE;
  718. }
  719. return Policy;
  720. }
  721. /******************************Public*Routine******************************\
  722. * VOID vDdInitHeaps
  723. *
  724. * Initializes video memory heaps returned by the driver.
  725. *
  726. * Assumes devlock already held and AGP functions queried.
  727. *
  728. * 6-Feb-1998 -by- Drew Bliss [drewb]
  729. * Wrote it.
  730. \**************************************************************************/
  731. VOID
  732. vDdInitHeaps(EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal)
  733. {
  734. DWORD dwHeap;
  735. VIDEOMEMORY* pHeap;
  736. DDKHEAP(("DDKHEAP: Initializing %d heaps\n",
  737. peDirectDrawGlobal->dwNumHeaps));
  738. // Set the AGP policy here:
  739. dwAGPPolicyMaxBytes = dwDdSetAgpPolicy();
  740. // Initialize heaps which aren't preallocated.
  741. pHeap = peDirectDrawGlobal->pvmList;
  742. for (dwHeap = 0;
  743. dwHeap < peDirectDrawGlobal->dwNumHeaps;
  744. pHeap++, dwHeap++)
  745. {
  746. // If the current heap is an AGP heap but we were unable to
  747. // get access to the AGP control functions then we can't use it,
  748. // so remove it from the list.
  749. //
  750. // The heap is also disabled in the case where a driver reports
  751. // a non-local heap but doesn't report non-local vidmem caps.
  752. if ((pHeap->dwFlags & VIDMEM_ISNONLOCAL) &&
  753. (peDirectDrawGlobal->AgpInterface.Context == NULL ||
  754. (peDirectDrawGlobal->HalInfo.ddCaps.dwCaps2 &
  755. DDCAPS2_NONLOCALVIDMEM) == 0))
  756. {
  757. DDKHEAP(("DDKHEAP: Disabling AGP heap %d\n", dwHeap));
  758. pHeap->dwFlags |= VIDMEM_HEAPDISABLED;
  759. }
  760. else if (!(pHeap->dwFlags & VIDMEM_ISHEAP))
  761. {
  762. // Get any heap alignment restrictions from driver:
  763. DD_GETHEAPALIGNMENTDATA GetHeapAlignmentData;
  764. HEAPALIGNMENT* pHeapAlignment = NULL;
  765. RtlZeroMemory(&GetHeapAlignmentData, sizeof GetHeapAlignmentData);
  766. GetHeapAlignmentData.dwInstance =
  767. (ULONG_PTR) peDirectDrawGlobal->dhpdev;
  768. GetHeapAlignmentData.dwHeap = dwHeap;
  769. GetHeapAlignmentData.ddRVal = DDERR_GENERIC;
  770. GetHeapAlignmentData.Alignment.dwSize =
  771. sizeof GetHeapAlignmentData.Alignment;
  772. if (bDdGetDriverInfo(peDirectDrawGlobal,
  773. &GUID_GetHeapAlignment,
  774. &GetHeapAlignmentData,
  775. sizeof GetHeapAlignmentData,
  776. NULL))
  777. {
  778. pHeapAlignment = &GetHeapAlignmentData.Alignment;
  779. }
  780. DDKHEAP(("DDKHEAP: Initializing heap %d, flags %X\n",
  781. dwHeap, pHeap->dwFlags));
  782. if (HeapVidMemInit(pHeap,
  783. peDirectDrawGlobal->
  784. HalInfo.vmiData.lDisplayPitch,
  785. AGP_HDEV(peDirectDrawGlobal),
  786. pHeapAlignment) == NULL)
  787. {
  788. DDKHEAP(("DDKHEAP: Heap %d failed init\n", dwHeap));
  789. pHeap->dwFlags |= VIDMEM_HEAPDISABLED;
  790. }
  791. else
  792. {
  793. DDKHEAP(("DDKHEAP: Heap %d is %08X\n",
  794. dwHeap, pHeap->lpHeap));
  795. if (pHeap->dwFlags & VIDMEM_ISNONLOCAL)
  796. {
  797. pHeap->lpHeap->hdevAGP = AGP_HDEV(peDirectDrawGlobal);
  798. }
  799. }
  800. }
  801. }
  802. {
  803. ULONG ulHeaps=peDirectDrawGlobal->dwNumHeaps;
  804. ULONG cjData=sizeof(DD_MORESURFACECAPS)-sizeof(DDSCAPSEX)*2+
  805. ulHeaps*sizeof(DDSCAPSEX)*2;
  806. // allocate memory in ddraw style, add some junk after data strucure
  807. // so that not well behaved driver does not break the kernel.
  808. PDD_MORESURFACECAPS pDDMoreSurfaceCaps=(PDD_MORESURFACECAPS)
  809. PALLOCMEM(cjData+0x400,'pddG');
  810. RtlZeroMemory(&peDirectDrawGlobal->MoreSurfaceCaps,
  811. sizeof(peDirectDrawGlobal->MoreSurfaceCaps));
  812. if (pDDMoreSurfaceCaps!=NULL)
  813. {
  814. RtlZeroMemory(pDDMoreSurfaceCaps, cjData);
  815. pDDMoreSurfaceCaps->dwSize=cjData;
  816. if (bDdGetDriverInfo(peDirectDrawGlobal,
  817. &GUID_DDMoreSurfaceCaps,
  818. pDDMoreSurfaceCaps,
  819. cjData,
  820. &cjData))
  821. {
  822. // now fill ddscaps into heaps
  823. // directdraw runtime does not expect the heap restrictions
  824. ULONG cjCopy= (ULONG)min(sizeof(DD_MORESURFACECAPS)-sizeof(DDSCAPSEX)*2,cjData);
  825. pDDMoreSurfaceCaps->dwSize=cjCopy;
  826. RtlCopyMemory(&peDirectDrawGlobal->MoreSurfaceCaps,
  827. pDDMoreSurfaceCaps,
  828. cjCopy);
  829. // now Copy ddxCapsex/ExAlt members to heaps...
  830. pHeap = peDirectDrawGlobal->pvmList;
  831. for (dwHeap = 0;
  832. dwHeap < ulHeaps;
  833. pHeap++, dwHeap++)
  834. {
  835. if (!(pHeap->dwFlags&VIDMEM_HEAPDISABLED))
  836. {
  837. RtlCopyMemory(
  838. &pHeap->lpHeap->ddsCapsEx,
  839. &pDDMoreSurfaceCaps->ddsExtendedHeapRestrictions[dwHeap].ddsCapsEx,
  840. sizeof(DDSCAPSEX));
  841. RtlCopyMemory(
  842. &pHeap->lpHeap->ddsCapsExAlt,
  843. &pDDMoreSurfaceCaps->ddsExtendedHeapRestrictions[dwHeap].ddsCapsExAlt,
  844. sizeof(DDSCAPSEX));
  845. }
  846. }
  847. peDirectDrawGlobal->flDriverInfo |= DD_DRIVERINFO_MORESURFACECAPS;
  848. }
  849. VFREEMEM(pDDMoreSurfaceCaps);
  850. }
  851. }
  852. }
  853. /******************************Public*Routine******************************\
  854. * VOID UpdateNonLocalHeap
  855. *
  856. * Notifies the driver when the AGP heap information changes.
  857. *
  858. * 2-Mar-2001 -by- Scott MacDonald [smac]
  859. * Wrote it.
  860. \**************************************************************************/
  861. void UpdateNonLocalHeap(
  862. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal,
  863. DWORD dwHeapIndex
  864. )
  865. {
  866. DD_UPDATENONLOCALHEAPDATA UpdateNonLocalHeapData;
  867. LPVIDMEM lpVidMem = &(peDirectDrawGlobal->pvmList[dwHeapIndex]);
  868. UpdateNonLocalHeapData.lpDD = peDirectDrawGlobal;
  869. UpdateNonLocalHeapData.dwHeap = dwHeapIndex;
  870. UpdateNonLocalHeapData.fpGARTLin = lpVidMem->lpHeap->fpGARTLin;
  871. UpdateNonLocalHeapData.fpGARTDev = lpVidMem->lpHeap->fpGARTDev;
  872. UpdateNonLocalHeapData.ulPolicyMaxBytes = 0;
  873. UpdateNonLocalHeapData.ddRVal = DDERR_GENERIC;
  874. bDdGetDriverInfo(peDirectDrawGlobal,
  875. &GUID_UpdateNonLocalHeap,
  876. &UpdateNonLocalHeapData,
  877. sizeof UpdateNonLocalHeapData,
  878. NULL);
  879. }
  880. /******************************Public*Routine******************************\
  881. * VOID InitAgpHeap
  882. *
  883. * We do not want to call AGPReserve in HeapVidMemInit since it is called on
  884. * every mode change, so instead we have a seperate function that reserves the
  885. * AGP memory and it is called after the rest of the heap is initialized.
  886. *
  887. * 22-Feb-2001 -by- Scott MacDonald [smac]
  888. * Wrote it.
  889. \**************************************************************************/
  890. VOID
  891. InitAgpHeap(
  892. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal,
  893. DWORD dwHeapIndex,
  894. HANDLE hdev
  895. )
  896. {
  897. DWORD dwSize;
  898. FLATPTR fpLinStart;
  899. LARGE_INTEGER liDevStart;
  900. PVOID pvReservation;
  901. BOOL fIsUC;
  902. BOOL fIsWC;
  903. DWORD dwSizeReserved = 0;
  904. LPVIDMEM lpVidMem = &(peDirectDrawGlobal->pvmList[dwHeapIndex]);
  905. /*
  906. * Compute the size of the heap.
  907. */
  908. dwSize = lpVidMem->lpHeap->dwTotalSize;
  909. DDASSERT( 0UL != dwSize );
  910. if( lpVidMem->dwFlags & VIDMEM_ISWC )
  911. {
  912. fIsUC = FALSE;
  913. fIsWC = TRUE;
  914. }
  915. else
  916. {
  917. fIsUC = TRUE;
  918. fIsWC = FALSE;
  919. }
  920. /*
  921. * Allocate a bit mask to keep track of which pages have been
  922. * committed or not.
  923. */
  924. lpVidMem->lpHeap->dwAgpCommitMaskSize =
  925. (GetHeapSizeInPages(lpVidMem, lpVidMem->lpHeap->stride) / BITS_IN_BYTE) + 1;
  926. lpVidMem->lpHeap->pAgpCommitMask =
  927. (BYTE*) PALLOCMEM(lpVidMem->lpHeap->dwAgpCommitMaskSize, 'pddG');
  928. if( lpVidMem->lpHeap->pAgpCommitMask == NULL )
  929. {
  930. lpVidMem->dwFlags |= VIDMEM_HEAPDISABLED;
  931. return;
  932. }
  933. if( !(dwSizeReserved = AGPReserve( hdev, dwSize, fIsUC, fIsWC,
  934. &fpLinStart, &liDevStart,
  935. &pvReservation )) )
  936. {
  937. VDPF(( 0, V, "Could not reserve a GART address range for a "
  938. "linear heap of size 0x%08x", dwSize ));
  939. VFREEMEM(lpVidMem->lpHeap->pAgpCommitMask);
  940. lpVidMem->lpHeap->pAgpCommitMask = NULL;
  941. lpVidMem->dwFlags |= VIDMEM_HEAPDISABLED;
  942. return;
  943. }
  944. else
  945. {
  946. VDPF((4,V, "Allocated a GART address range starting at "
  947. "0x%08x (linear) 0x%08x:0x%08x (physical) of size %d",
  948. fpLinStart, liDevStart.HighPart, liDevStart.LowPart,
  949. dwSizeReserved ));
  950. }
  951. if (dwSizeReserved != dwSize)
  952. {
  953. VDPF((0,V,"WARNING! This system required that the full "
  954. "nonlocal aperture could not be reserved!"));
  955. VDPF((0,V," Requested aperture:%08x, "
  956. "Reserved aperture:%08x", dwSize, dwSizeReserved));
  957. }
  958. /*
  959. * Update the heap for the new start address
  960. * (and end address for a linear heap).
  961. */
  962. lpVidMem->fpStart = fpLinStart;
  963. if( lpVidMem->dwFlags & VIDMEM_ISLINEAR )
  964. {
  965. LPVMEML plh;
  966. lpVidMem->fpEnd = ( fpLinStart + dwSizeReserved ) - 1UL;
  967. lpVidMem->lpHeap->dwTotalSize = dwSizeReserved;
  968. plh = (LPVMEML)lpVidMem->lpHeap->freeList;
  969. if( ( plh != NULL ) && ( plh->ptr == 0 ) )
  970. {
  971. plh->ptr = lpVidMem->fpStart;
  972. plh->size = dwSizeReserved;
  973. }
  974. }
  975. else
  976. {
  977. LPVMEMR prh;
  978. DWORD dwHeight;
  979. DDASSERT( lpVidMem->dwFlags & VIDMEM_ISRECTANGULAR );
  980. dwHeight = dwSizeReserved / lpVidMem->lpHeap->stride;
  981. lpVidMem->lpHeap->dwTotalSize = dwHeight * lpVidMem->lpHeap->stride;
  982. prh = (LPVMEMR)lpVidMem->lpHeap->freeList;
  983. if( ( prh != NULL ) && ( prh->cy != 0x7fffffff ) )
  984. {
  985. prh->ptr = lpVidMem->fpStart;
  986. prh->cy = dwHeight;
  987. prh->size = (lpVidMem->dwWidth << 16 ) | dwHeight;
  988. }
  989. }
  990. lpVidMem->lpHeap->fpGARTLin = fpLinStart;
  991. // Fill in partial physical address for Win9x.
  992. lpVidMem->lpHeap->fpGARTDev = liDevStart.LowPart;
  993. // Fill in complete physical address for NT.
  994. lpVidMem->lpHeap->liPhysAGPBase = liDevStart;
  995. lpVidMem->lpHeap->pvPhysRsrv = pvReservation;
  996. UpdateNonLocalHeap( peDirectDrawGlobal, dwHeapIndex );
  997. } /* InitAgpHeap */
  998. /******************************Public*Routine******************************\
  999. * VOID CheckAgpHeaps
  1000. *
  1001. * This funtion is called periodically to make sure that we initialize any
  1002. * uninitialized AGP heaps.
  1003. *
  1004. * 22-Feb-2001 -by- Scott MacDonald [smac]
  1005. * Wrote it.
  1006. \**************************************************************************/
  1007. void CheckAgpHeaps(
  1008. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal
  1009. )
  1010. {
  1011. LPVIDMEM pHeap;
  1012. DWORD i;
  1013. pHeap = peDirectDrawGlobal->pvmList;
  1014. for( i = 0; i < peDirectDrawGlobal->dwNumHeaps; pHeap++, i++)
  1015. {
  1016. if ((pHeap->dwFlags & VIDMEM_ISNONLOCAL) &&
  1017. !(pHeap->dwFlags & VIDMEM_ISHEAP) &&
  1018. !(pHeap->dwFlags & VIDMEM_HEAPDISABLED) &&
  1019. (pHeap->lpHeap->pvPhysRsrv == NULL))
  1020. {
  1021. InitAgpHeap( peDirectDrawGlobal,
  1022. i,
  1023. AGP_HDEV(peDirectDrawGlobal));
  1024. }
  1025. }
  1026. }
  1027. /******************************Public*Routine******************************\
  1028. * VOID MapAllAgpHeaps
  1029. *
  1030. * This funtion is virtually map all AGP heaps. It also virtually commits
  1031. * them to everything that is physically committed.
  1032. *
  1033. * 25-Apr-2001 -by- Scott MacDonald [smac]
  1034. * Wrote it.
  1035. \**************************************************************************/
  1036. void MapAllAgpHeaps(
  1037. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal
  1038. )
  1039. {
  1040. if (peDirectDrawLocal->ppeMapAgp != NULL)
  1041. {
  1042. VIDEOMEMORY* pvmHeap;
  1043. DWORD i;
  1044. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  1045. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  1046. for (i = 0; i < peDirectDrawGlobal->dwNumHeaps; i++)
  1047. {
  1048. pvmHeap = &peDirectDrawGlobal->pvmList[i];
  1049. if ((pvmHeap->dwFlags & VIDMEM_ISNONLOCAL) &&
  1050. !(pvmHeap->dwFlags & VIDMEM_ISHEAP) &&
  1051. !(pvmHeap->dwFlags & VIDMEM_HEAPDISABLED) &&
  1052. (pvmHeap->lpHeap != NULL) &&
  1053. (pvmHeap->lpHeap->pvPhysRsrv != NULL) &&
  1054. (peDirectDrawLocal->ppeMapAgp[i] == NULL))
  1055. {
  1056. // Reserve address space for the heap:
  1057. if (bDdMapAgpHeap(peDirectDrawLocal, pvmHeap))
  1058. {
  1059. if (peDirectDrawLocal->ppeMapAgp[i] != NULL)
  1060. {
  1061. AGPCommitAllVirtual (peDirectDrawLocal, pvmHeap, i);
  1062. }
  1063. }
  1064. }
  1065. }
  1066. }
  1067. }
  1068. /******************************Public*Routine******************************\
  1069. * VOID vDdDisableDriver
  1070. *
  1071. * Frees and destroys all driver state. Note that this may be called
  1072. * even while the driver is still only partially enabled.
  1073. *
  1074. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  1075. * Wrote it.
  1076. \**************************************************************************/
  1077. VOID
  1078. vDdDisableDriver(
  1079. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal
  1080. )
  1081. {
  1082. PDEVOBJ po(peDirectDrawGlobal->hdev);
  1083. DD_ASSERTDEVLOCK(peDirectDrawGlobal);
  1084. if (peDirectDrawGlobal->pvmList != NULL)
  1085. {
  1086. DWORD dwHeap;
  1087. VIDEOMEMORY* pHeap;
  1088. // Shut down heaps.
  1089. DDKHEAP(("DDKHEAP: Shutting down %d heaps\n",
  1090. peDirectDrawGlobal->dwNumHeaps));
  1091. pHeap = peDirectDrawGlobal->pvmList;
  1092. for (dwHeap = 0;
  1093. dwHeap < peDirectDrawGlobal->dwNumHeaps;
  1094. pHeap++, dwHeap++)
  1095. {
  1096. if ((pHeap->dwFlags & VIDMEM_HEAPDISABLED) == 0 &&
  1097. pHeap->lpHeap != NULL)
  1098. {
  1099. DDKHEAP(("DDKHEAP: Uninitializing heap %d\n", dwHeap));
  1100. HeapVidMemFini(pHeap, AGP_HDEV(peDirectDrawGlobal));
  1101. }
  1102. }
  1103. VFREEMEM(peDirectDrawGlobal->pvmList);
  1104. peDirectDrawGlobal->pvmList = NULL;
  1105. }
  1106. if (peDirectDrawGlobal->pdwFourCC != NULL)
  1107. {
  1108. VFREEMEM(peDirectDrawGlobal->pdwFourCC);
  1109. peDirectDrawGlobal->pdwFourCC = NULL;
  1110. }
  1111. if (peDirectDrawGlobal->lpDDVideoPortCaps != NULL)
  1112. {
  1113. VFREEMEM(peDirectDrawGlobal->lpDDVideoPortCaps);
  1114. peDirectDrawGlobal->lpDDVideoPortCaps = NULL;
  1115. }
  1116. if (peDirectDrawGlobal->hDxApi != NULL)
  1117. {
  1118. vDdUnloadDxApiImage(peDirectDrawGlobal);
  1119. }
  1120. if (peDirectDrawGlobal->hdcCache != NULL)
  1121. {
  1122. // need to chage to 'current' since while it's in cache, it's 'none'
  1123. DxEngSetDCOwner((HDC) peDirectDrawGlobal->hdcCache, OBJECT_OWNER_CURRENT);
  1124. DxEngDeleteDC((HDC) peDirectDrawGlobal->hdcCache, TRUE);
  1125. peDirectDrawGlobal->hdcCache = NULL;
  1126. }
  1127. if (peDirectDrawGlobal->fl & DD_GLOBAL_FLAG_DRIVER_ENABLED)
  1128. {
  1129. peDirectDrawGlobal->fl &= ~DD_GLOBAL_FLAG_DRIVER_ENABLED;
  1130. (*PPFNDRV(po, DisableDirectDraw))(po.dhpdev());
  1131. }
  1132. RtlZeroMemory((DD_DIRECTDRAW_GLOBAL_DRIVER_DATA*) peDirectDrawGlobal,
  1133. sizeof(DD_DIRECTDRAW_GLOBAL_DRIVER_DATA));
  1134. }
  1135. /******************************Public*Routine******************************\
  1136. * VOID vDdEnableDriver
  1137. *
  1138. * Calls the driver's DrvGetDirectDrawInfo and DrvEnableDirectDraw
  1139. * functions to enable and initialize the driver and mode dependent
  1140. * portions of the global DirectDraw object.
  1141. *
  1142. * Assumes devlock already held.
  1143. *
  1144. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  1145. * Wrote it.
  1146. \**************************************************************************/
  1147. VOID
  1148. vDdEnableDriver(
  1149. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal
  1150. )
  1151. {
  1152. BOOL bSuccess;
  1153. PFN_DrvGetDirectDrawInfo pfnGetDirectDrawInfo;
  1154. PFN_DrvEnableDirectDraw pfnEnableDirectDraw;
  1155. PFN_DrvDisableDirectDraw pfnDisableDirectDraw;
  1156. DWORD dwNumHeaps;
  1157. DWORD dwNumFourCC;
  1158. VIDEOMEMORY* pvmList;
  1159. DWORD* pdwFourCC;
  1160. ULONG iDitherFormat;
  1161. DWORD dw;
  1162. PDEVOBJ po(peDirectDrawGlobal->hdev);
  1163. EDD_DEVLOCK eDevLock(peDirectDrawGlobal);
  1164. // Call the driver to see what it can do:
  1165. pfnGetDirectDrawInfo = PPFNDRV(po, GetDirectDrawInfo);
  1166. pfnEnableDirectDraw = PPFNDRV(po, EnableDirectDraw);
  1167. pfnDisableDirectDraw = PPFNDRV(po, DisableDirectDraw);
  1168. // To support DirectDraw, the driver must hook all three required
  1169. // DirectDraw functions.
  1170. bSuccess = ((pfnGetDirectDrawInfo != NULL) &&
  1171. (pfnEnableDirectDraw != NULL) &&
  1172. (pfnDisableDirectDraw != NULL));
  1173. dwNumHeaps = 0;
  1174. dwNumFourCC = 0;
  1175. peDirectDrawGlobal->fl &= ~DD_GLOBAL_FLAG_DRIVER_ENABLED;
  1176. // Do the first DrvGetDirectDrawInfo query for this PDEV to
  1177. // determine the number of heaps and the number of FourCC
  1178. // codes that the driver supports, so that we know how
  1179. // much memory to allocate:
  1180. if ((bSuccess) &&
  1181. (pfnGetDirectDrawInfo((DHPDEV) peDirectDrawGlobal->dhpdev,
  1182. &peDirectDrawGlobal->HalInfo,
  1183. &dwNumHeaps,
  1184. NULL,
  1185. &dwNumFourCC,
  1186. NULL)))
  1187. {
  1188. pvmList = NULL;
  1189. pdwFourCC = NULL;
  1190. DDKHEAP(("DDKHEAP: Driver reports dwNumHeaps %d\n", dwNumHeaps));
  1191. if (dwNumHeaps != 0)
  1192. {
  1193. pvmList = (VIDEOMEMORY*)
  1194. PALLOCMEM(sizeof(VIDEOMEMORY) * dwNumHeaps, 'vddG');
  1195. peDirectDrawGlobal->dwNumHeaps = dwNumHeaps;
  1196. peDirectDrawGlobal->pvmList = pvmList;
  1197. if (pvmList == NULL)
  1198. bSuccess = FALSE;
  1199. }
  1200. if (dwNumFourCC != 0)
  1201. {
  1202. pdwFourCC = (DWORD*)
  1203. PALLOCMEM(sizeof(DWORD) * dwNumFourCC, 'fddG');
  1204. peDirectDrawGlobal->dwNumFourCC = dwNumFourCC;
  1205. peDirectDrawGlobal->pdwFourCC = pdwFourCC;
  1206. if (pdwFourCC == NULL)
  1207. bSuccess = FALSE;
  1208. }
  1209. if (bSuccess)
  1210. {
  1211. // Do the second DrvGetDirectDrawInfo that actually
  1212. // gets all the data:
  1213. if (pfnGetDirectDrawInfo((DHPDEV) peDirectDrawGlobal->dhpdev,
  1214. &peDirectDrawGlobal->HalInfo,
  1215. &dwNumHeaps,
  1216. pvmList,
  1217. &dwNumFourCC,
  1218. pdwFourCC))
  1219. {
  1220. // Ensure that the driver doesn't give us an invalid address
  1221. // for its primary surface (like a user-mode address or NULL):
  1222. if (peDirectDrawGlobal->HalInfo.vmiData.pvPrimary != NULL)
  1223. {
  1224. dw = *((volatile DWORD *) peDirectDrawGlobal->HalInfo.vmiData.pvPrimary);
  1225. *((volatile DWORD *) peDirectDrawGlobal->HalInfo.vmiData.pvPrimary) = 0xabcdabcd;
  1226. *((volatile DWORD *) peDirectDrawGlobal->HalInfo.vmiData.pvPrimary) = dw;
  1227. if (pfnEnableDirectDraw((DHPDEV) peDirectDrawGlobal->dhpdev,
  1228. &peDirectDrawGlobal->CallBacks,
  1229. &peDirectDrawGlobal->SurfaceCallBacks,
  1230. &peDirectDrawGlobal->PaletteCallBacks))
  1231. {
  1232. // Check the driver's capability status
  1233. DWORD dwOverride = po.dwDriverCapableOverride();
  1234. // check for D3D support here
  1235. if ( (!(dwOverride & DRIVER_NOT_CAPABLE_D3D))
  1236. &&(peDirectDrawGlobal->HalInfo.dwSize == sizeof(DD_HALINFO)) )
  1237. {
  1238. // for ease of porting, NT5 HALINFO has the same pointers
  1239. // to D3D data as DX5
  1240. if(peDirectDrawGlobal->HalInfo.lpD3DGlobalDriverData != NULL &&
  1241. ((D3DNTHAL_GLOBALDRIVERDATA*)
  1242. peDirectDrawGlobal->HalInfo.lpD3DGlobalDriverData)->dwSize ==
  1243. sizeof(D3DNTHAL_GLOBALDRIVERDATA))
  1244. {
  1245. peDirectDrawGlobal->D3dDriverData =
  1246. *(D3DNTHAL_GLOBALDRIVERDATA*)peDirectDrawGlobal->HalInfo.lpD3DGlobalDriverData;
  1247. if( peDirectDrawGlobal->HalInfo.lpD3DHALCallbacks != NULL &&
  1248. ((D3DNTHAL_CALLBACKS*)peDirectDrawGlobal->HalInfo.lpD3DHALCallbacks)->dwSize ==
  1249. sizeof(D3DNTHAL_CALLBACKS))
  1250. {
  1251. peDirectDrawGlobal->D3dCallBacks =
  1252. *(D3DNTHAL_CALLBACKS*)peDirectDrawGlobal->HalInfo.lpD3DHALCallbacks;
  1253. if( peDirectDrawGlobal->HalInfo.lpD3DBufCallbacks != NULL &&
  1254. ((PDD_D3DBUFCALLBACKS)peDirectDrawGlobal->HalInfo.lpD3DBufCallbacks)->dwSize ==
  1255. sizeof(DD_D3DBUFCALLBACKS))
  1256. {
  1257. peDirectDrawGlobal->D3dBufCallbacks =
  1258. *(PDD_D3DBUFCALLBACKS)peDirectDrawGlobal->HalInfo.lpD3DBufCallbacks;
  1259. }
  1260. }
  1261. else
  1262. {
  1263. // D3DCaps succeeded but D3DCallbacks didn't, so we
  1264. // must zero D3DCaps:
  1265. RtlZeroMemory(&peDirectDrawGlobal->D3dDriverData,
  1266. sizeof(peDirectDrawGlobal->D3dDriverData));
  1267. }
  1268. }
  1269. }
  1270. // Use the GetDriverInfo HAL call to query any
  1271. // additional capabilities such as for Direct3D or
  1272. // VPE:
  1273. if (bDdGetAllDriverInfo(peDirectDrawGlobal))
  1274. {
  1275. if (bDdValidateDriverData(peDirectDrawGlobal))
  1276. {
  1277. // Initialize as many heaps as possible.
  1278. vDdInitHeaps(peDirectDrawGlobal);
  1279. peDirectDrawGlobal->fl |= DD_GLOBAL_FLAG_DRIVER_ENABLED;
  1280. return;
  1281. }
  1282. }
  1283. pfnDisableDirectDraw((DHPDEV) peDirectDrawGlobal->dhpdev);
  1284. }
  1285. }
  1286. else
  1287. {
  1288. WARNING("vDdEnableDriver: Driver returned invalid vmiData.pvPrimary\n");
  1289. }
  1290. }
  1291. }
  1292. }
  1293. // Something didn't work, so zero out all of the caps that we may have
  1294. // gotten before the failure occurred.
  1295. peDirectDrawGlobal->flDriver = 0;
  1296. peDirectDrawGlobal->flDriverInfo = 0;
  1297. if (peDirectDrawGlobal->pdwFourCC != NULL)
  1298. {
  1299. VFREEMEM(peDirectDrawGlobal->pdwFourCC);
  1300. peDirectDrawGlobal->pdwFourCC = NULL;
  1301. }
  1302. peDirectDrawGlobal->dwNumFourCC = 0;
  1303. if (peDirectDrawGlobal->pvmList != NULL)
  1304. {
  1305. VFREEMEM(peDirectDrawGlobal->pvmList);
  1306. peDirectDrawGlobal->pvmList = NULL;
  1307. }
  1308. peDirectDrawGlobal->dwNumHeaps = 0;
  1309. RtlZeroMemory( &peDirectDrawGlobal->DxApiInterface,
  1310. sizeof( peDirectDrawGlobal->DxApiInterface ) );
  1311. RtlZeroMemory( &peDirectDrawGlobal->AgpInterface,
  1312. sizeof( peDirectDrawGlobal->AgpInterface ) );
  1313. RtlZeroMemory( &peDirectDrawGlobal->DDKernelCaps,
  1314. sizeof( peDirectDrawGlobal->DDKernelCaps ) );
  1315. RtlZeroMemory( &peDirectDrawGlobal->DxApiCallBacks,
  1316. sizeof( peDirectDrawGlobal->DxApiCallBacks ) );
  1317. RtlZeroMemory(&peDirectDrawGlobal->D3dDriverData,
  1318. sizeof(peDirectDrawGlobal->D3dDriverData));
  1319. RtlZeroMemory(&peDirectDrawGlobal->CallBacks,
  1320. sizeof(peDirectDrawGlobal->CallBacks));
  1321. RtlZeroMemory(&peDirectDrawGlobal->D3dCallBacks,
  1322. sizeof(peDirectDrawGlobal->D3dCallBacks));
  1323. RtlZeroMemory(&peDirectDrawGlobal->D3dBufCallbacks,
  1324. sizeof(peDirectDrawGlobal->D3dBufCallbacks));
  1325. RtlZeroMemory(&peDirectDrawGlobal->SurfaceCallBacks,
  1326. sizeof(peDirectDrawGlobal->SurfaceCallBacks));
  1327. RtlZeroMemory(&peDirectDrawGlobal->PaletteCallBacks,
  1328. sizeof(peDirectDrawGlobal->PaletteCallBacks));
  1329. RtlZeroMemory(&peDirectDrawGlobal->HalInfo,
  1330. sizeof(peDirectDrawGlobal->HalInfo));
  1331. peDirectDrawGlobal->HalInfo.dwSize =
  1332. sizeof(peDirectDrawGlobal->HalInfo);
  1333. peDirectDrawGlobal->HalInfo.ddCaps.dwSize =
  1334. sizeof(peDirectDrawGlobal->HalInfo.ddCaps);
  1335. peDirectDrawGlobal->HalInfo.ddCaps.dwCaps = DDCAPS_NOHARDWARE;
  1336. // Okay, we can't use the driver. Initialize what information we need
  1337. // from the PDEV so that system memory surfaces may still be used:
  1338. iDitherFormat = po.iDitherFormat();
  1339. if (iDitherFormat == BMF_4BPP)
  1340. {
  1341. peDirectDrawGlobal->HalInfo.vmiData.ddpfDisplay.dwRGBBitCount = 4;
  1342. }
  1343. else if (iDitherFormat == BMF_8BPP)
  1344. {
  1345. peDirectDrawGlobal->HalInfo.vmiData.ddpfDisplay.dwRGBBitCount = 8;
  1346. }
  1347. else if (iDitherFormat == BMF_16BPP)
  1348. {
  1349. peDirectDrawGlobal->HalInfo.vmiData.ddpfDisplay.dwRGBBitCount = 16;
  1350. }
  1351. else if (iDitherFormat == BMF_24BPP)
  1352. {
  1353. peDirectDrawGlobal->HalInfo.vmiData.ddpfDisplay.dwRGBBitCount = 24;
  1354. }
  1355. else if (iDitherFormat == BMF_32BPP)
  1356. {
  1357. peDirectDrawGlobal->HalInfo.vmiData.ddpfDisplay.dwRGBBitCount = 32;
  1358. }
  1359. else
  1360. {
  1361. RIP("Invalid iDitherFormat()");
  1362. }
  1363. }
  1364. /******************************Public*Routine******************************\
  1365. * VOID vDdIncrementReferenceCount
  1366. *
  1367. * Devlock must be held.
  1368. *
  1369. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  1370. * Wrote it.
  1371. \**************************************************************************/
  1372. VOID
  1373. vDdIncrementReferenceCount(
  1374. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal
  1375. )
  1376. {
  1377. DD_ASSERTDEVLOCK(peDirectDrawGlobal);
  1378. peDirectDrawGlobal->cDriverReferences++;
  1379. if (peDirectDrawGlobal->cDriverReferences == 1)
  1380. {
  1381. PDEVOBJ po(peDirectDrawGlobal->hdev);
  1382. // Add a reference to the PDEV so that it won't be deleted
  1383. // until the last D3D structure is freed. We do this
  1384. // so that on dynamic mode changes, we can keep the active
  1385. // DirectDraw driver state around. This is so that if we ever
  1386. // return to the original mode, we can resume any Direct3D
  1387. // accelerations exactly where we were originally.
  1388. //
  1389. // The DirectDraw convention is that if an accelerated Direct3D
  1390. // application is started at 640x480, and the mode changes to
  1391. // 800x600, the application stops drawing (unless it recreates
  1392. // all its execute buffers and all other DirectX state). But if
  1393. // the display is returned back to the original 640x480 mode, all
  1394. // the application has to do is 'restore' its surfaces, and it can
  1395. // keep running.
  1396. //
  1397. // To allow this we have to keep around the driver's 640x480
  1398. // instance even when the display is 800x600. But if the
  1399. // application terminated while at 800x600, we would have to clean
  1400. // up the 640x480 driver instance. Once that happens, the 640x480
  1401. // PDEV can be completely deleted. This is why we reference
  1402. // count the PDEV:
  1403. po.vReferencePdev();
  1404. }
  1405. }
  1406. /******************************Public*Routine******************************\
  1407. * VOID vDdDecrementReferenceCount
  1408. *
  1409. * Devlock must not be held entering the function if PDEV may be unloaded.
  1410. *
  1411. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  1412. * Wrote it.
  1413. \**************************************************************************/
  1414. VOID
  1415. vDdDecrementReferenceCount(
  1416. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal
  1417. )
  1418. {
  1419. BOOL bUnreference = FALSE;
  1420. {
  1421. EDD_DEVLOCK eDevlock(peDirectDrawGlobal->hdev);
  1422. ASSERTGDI(peDirectDrawGlobal->cDriverReferences > 0,
  1423. "Weird reference count");
  1424. if (--peDirectDrawGlobal->cDriverReferences == 0)
  1425. {
  1426. bUnreference = TRUE;
  1427. }
  1428. }
  1429. if (bUnreference)
  1430. {
  1431. PDEVOBJ po(peDirectDrawGlobal->hdev);
  1432. // If this dev lock is not held then we may free this driver.
  1433. po.vUnreferencePdev();
  1434. }
  1435. }
  1436. /******************************Public*Routine******************************\
  1437. * LONGLONG llDdAssertModeTimeout()
  1438. *
  1439. * Reads the DirectDraw timeout value from the registry.
  1440. *
  1441. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  1442. * Lifted it from AndreVa's code.
  1443. \**************************************************************************/
  1444. LONGLONG
  1445. llDdAssertModeTimeout(
  1446. )
  1447. {
  1448. HANDLE hkRegistry;
  1449. OBJECT_ATTRIBUTES ObjectAttributes;
  1450. UNICODE_STRING UnicodeString;
  1451. NTSTATUS status;
  1452. LONGLONG llTimeout;
  1453. DWORD Length;
  1454. PKEY_VALUE_FULL_INFORMATION Information;
  1455. llTimeout = 0;
  1456. RtlInitUnicodeString(&UnicodeString,
  1457. L"\\Registry\\Machine\\System\\CurrentControlSet\\"
  1458. L"Control\\GraphicsDrivers\\DCI");
  1459. InitializeObjectAttributes(&ObjectAttributes,
  1460. &UnicodeString,
  1461. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  1462. NULL,
  1463. NULL);
  1464. status = ZwOpenKey(&hkRegistry, GENERIC_READ, &ObjectAttributes);
  1465. if (NT_SUCCESS(status))
  1466. {
  1467. RtlInitUnicodeString(&UnicodeString, L"Timeout");
  1468. Length = sizeof(KEY_VALUE_FULL_INFORMATION) + sizeof(L"Timeout") +
  1469. sizeof(DWORD);
  1470. Information = (PKEY_VALUE_FULL_INFORMATION) PALLOCMEM(Length, ' ddG');
  1471. if (Information)
  1472. {
  1473. status = ZwQueryValueKey(hkRegistry,
  1474. &UnicodeString,
  1475. KeyValueFullInformation,
  1476. Information,
  1477. Length,
  1478. &Length);
  1479. if (NT_SUCCESS(status))
  1480. {
  1481. llTimeout = ((LONGLONG) -10000) * 1000 * (
  1482. *(LPDWORD) ((((PUCHAR)Information) +
  1483. Information->DataOffset)));
  1484. }
  1485. VFREEMEM(Information);
  1486. }
  1487. ZwCloseKey(hkRegistry);
  1488. }
  1489. return(llTimeout);
  1490. }
  1491. /******************************Public*Routine******************************\
  1492. * BOOL bDdMapAgpHeap
  1493. *
  1494. * Maps an AGP heap into a virtual address space.
  1495. *
  1496. * 25-Aug-1999 -by- John Stephens [johnstep]
  1497. * Wrote it.
  1498. \**************************************************************************/
  1499. BOOL
  1500. bDdMapAgpHeap(
  1501. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal,
  1502. VIDEOMEMORY* pvmHeap
  1503. )
  1504. {
  1505. BOOL bSuccess = FALSE;
  1506. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  1507. EDD_VMEMMAPPING* peMap;
  1508. BYTE* pAgpVirtualCommitMask;
  1509. DWORD dwAgpVirtualCommitMaskSize;
  1510. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  1511. DD_ASSERTDEVLOCK(peDirectDrawGlobal);
  1512. peMap = (EDD_VMEMMAPPING*) PALLOCMEM(sizeof(EDD_VMEMMAPPING), ' ddG');
  1513. dwAgpVirtualCommitMaskSize = pvmHeap->lpHeap->dwAgpCommitMaskSize;
  1514. if (dwAgpVirtualCommitMaskSize > 0)
  1515. {
  1516. pAgpVirtualCommitMask = (BYTE*)PALLOCMEM(dwAgpVirtualCommitMaskSize,
  1517. ' ddG');
  1518. }
  1519. else
  1520. {
  1521. pAgpVirtualCommitMask = NULL;
  1522. }
  1523. if (pAgpVirtualCommitMask == NULL)
  1524. {
  1525. VFREEMEM(peMap);
  1526. peMap = NULL;
  1527. }
  1528. if (peMap)
  1529. {
  1530. peMap->pvVirtAddr =
  1531. peDirectDrawGlobal->AgpInterface.AgpServices.
  1532. AgpReserveVirtual(peDirectDrawGlobal->AgpInterface.Context,
  1533. NtCurrentProcess(),
  1534. pvmHeap->lpHeap->pvPhysRsrv,
  1535. &peMap->pvReservation);
  1536. if (peMap->pvVirtAddr != NULL)
  1537. {
  1538. peMap->cReferences = 1;
  1539. peMap->fl = DD_VMEMMAPPING_FLAG_AGP;
  1540. peMap->ulMapped = 0;
  1541. peMap->iHeapIndex = (DWORD)
  1542. (pvmHeap - peDirectDrawGlobal->pvmList);
  1543. peMap->pAgpVirtualCommitMask = pAgpVirtualCommitMask;
  1544. peMap->dwAgpVirtualCommitMaskSize = dwAgpVirtualCommitMaskSize;
  1545. ASSERTGDI(peDirectDrawLocal->
  1546. ppeMapAgp[peMap->iHeapIndex] == NULL,
  1547. "Heap already mapped");
  1548. peDirectDrawLocal->ppeMapAgp[peMap->iHeapIndex] = peMap;
  1549. peDirectDrawLocal->iAgpHeapsMapped++;
  1550. DDKHEAP(("DDKHEAP: Res %08X reserved %08X, size %X\n",
  1551. peMap->pvReservation, peMap->pvVirtAddr,
  1552. pvmHeap->lpHeap->dwTotalSize));
  1553. bSuccess = TRUE;
  1554. }
  1555. else
  1556. {
  1557. VFREEMEM(peMap);
  1558. }
  1559. }
  1560. return bSuccess;
  1561. }
  1562. /******************************Public*Routine******************************\
  1563. * VOID vDdUnmapMemory
  1564. *
  1565. * Deletes the user mode mapping of the frame buffer.
  1566. * We may be in a different process from the one in which
  1567. * the mapping was initially created in.
  1568. *
  1569. * The devlock must be held to call this function.
  1570. *
  1571. * Note: This should only be called from vDdUnreferenceVirtualMap
  1572. *
  1573. * 1-Oct-1998 -by- Anuj Gosalia [anujg]
  1574. * Wrote it.
  1575. \**************************************************************************/
  1576. VOID
  1577. vDdUnmapMemory(
  1578. EDD_VMEMMAPPING* peMap,
  1579. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal,
  1580. HANDLE ProcessHandle
  1581. )
  1582. {
  1583. DD_MAPMEMORYDATA MapMemoryData;
  1584. DWORD dwRet;
  1585. NTSTATUS Status;
  1586. DDKHEAP(("vDdUnmapMemory: peDirectDrawGlobal=%x, fpProcess=%x\n",
  1587. peDirectDrawGlobal, peMap->fpProcess));
  1588. // Call driver to unmap memory:
  1589. MapMemoryData.lpDD = peDirectDrawGlobal;
  1590. MapMemoryData.bMap = FALSE;
  1591. MapMemoryData.hProcess = ProcessHandle;
  1592. MapMemoryData.fpProcess = peMap->fpProcess;
  1593. dwRet = peDirectDrawGlobal->CallBacks.MapMemory(&MapMemoryData);
  1594. ASSERTGDI((dwRet == DDHAL_DRIVER_NOTHANDLED) ||
  1595. (MapMemoryData.ddRVal == DD_OK),
  1596. "Driver failed DirectDraw memory unmap\n");
  1597. }
  1598. /******************************Public*Routine******************************\
  1599. * VOID vDdUnmapAgpHeap
  1600. *
  1601. * Decommits all virtual memory in an AGP heap, then releases the heap
  1602. * mapping. If the AGP heap is now empty, this function will decommit the
  1603. * physical memory as well.
  1604. *
  1605. * Note: This should only be called from vDdUnreferenceVirtualMap
  1606. *
  1607. * 19-Jan-1999 -by- John Stephens [johnstep]
  1608. * Wrote it.
  1609. \**************************************************************************/
  1610. VOID
  1611. vDdUnmapAgpHeap(
  1612. EDD_VMEMMAPPING* peMap,
  1613. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal,
  1614. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal
  1615. )
  1616. {
  1617. VIDEOMEMORY* pvmHeap;
  1618. ULONG ulOffs;
  1619. BOOL bSuccess;
  1620. ULONG ulPages;
  1621. ULONG ulHeapPages;
  1622. pvmHeap = peDirectDrawGlobal->pvmList + peMap->iHeapIndex;
  1623. ASSERTGDI(peMap != NULL,
  1624. "Request to unmap an AGP heap which has not been mapped");
  1625. ASSERTGDI(pvmHeap->lpHeap->pvPhysRsrv != NULL,
  1626. "AGP reservation context is NULL in heap");
  1627. if (!(peDirectDrawLocal->fl & DD_LOCAL_DISABLED))
  1628. {
  1629. bSuccess = AGPDecommitVirtual( peMap,
  1630. peDirectDrawGlobal,
  1631. peDirectDrawLocal,
  1632. pvmHeap->lpHeap->dwTotalSize);
  1633. peDirectDrawGlobal->AgpInterface.AgpServices.
  1634. AgpReleaseVirtual(peDirectDrawGlobal->AgpInterface.Context,
  1635. peMap->pvReservation);
  1636. peDirectDrawLocal->iAgpHeapsMapped--;
  1637. }
  1638. // If the heap is now empty but memory is still committed, go ahead and
  1639. // decommit all the physical AGP memory:
  1640. if ((pvmHeap->lpHeap->allocList == NULL) &&
  1641. (pvmHeap->lpHeap->dwCommitedSize > 0))
  1642. {
  1643. DWORD dwTemp;
  1644. EDD_DIRECTDRAW_LOCAL* peTempLocal;
  1645. EDD_VMEMMAPPING* peTempMap;
  1646. // We may have other processes that have virtual commits outstanding
  1647. // even though they didn't allocate any AGP memory, so we can
  1648. // decommit them now.
  1649. peTempLocal = peDirectDrawGlobal->peDirectDrawLocalList;
  1650. while (peTempLocal != NULL )
  1651. {
  1652. if (peTempLocal != peDirectDrawLocal)
  1653. {
  1654. if ((peTempLocal->ppeMapAgp != NULL) &&
  1655. !(peTempLocal->fl & DD_LOCAL_DISABLED))
  1656. {
  1657. peTempMap = peTempLocal->ppeMapAgp[peMap->iHeapIndex];
  1658. if (peTempMap != NULL)
  1659. {
  1660. AGPDecommitVirtual( peTempMap,
  1661. peDirectDrawGlobal,
  1662. peTempLocal,
  1663. pvmHeap->lpHeap->dwTotalSize);
  1664. }
  1665. }
  1666. }
  1667. peTempLocal = peTempLocal->peDirectDrawLocalNext;
  1668. }
  1669. bSuccess = AGPDecommitAll(
  1670. AGP_HDEV(peDirectDrawGlobal),
  1671. pvmHeap->lpHeap->pvPhysRsrv,
  1672. pvmHeap->lpHeap->pAgpCommitMask,
  1673. pvmHeap->lpHeap->dwAgpCommitMaskSize,
  1674. &dwTemp,
  1675. pvmHeap->lpHeap->dwTotalSize);
  1676. ASSERTGDI(bSuccess, "Failed to decommit AGP memory");
  1677. pvmHeap->lpHeap->dwCommitedSize = 0;
  1678. }
  1679. else
  1680. {
  1681. CleanupAgpCommits( pvmHeap, pvmHeap->lpHeap->hdevAGP,
  1682. peDirectDrawGlobal, peMap->iHeapIndex );
  1683. }
  1684. }
  1685. /******************************Public*Routine******************************\
  1686. * VOID vDdUnreferenceVirtualMap
  1687. *
  1688. * 24-Aug-1999 -by- John Stephens [johnstep]
  1689. * Wrote it.
  1690. \**************************************************************************/
  1691. VOID
  1692. vDdUnreferenceVirtualMap(
  1693. EDD_VMEMMAPPING* peMap,
  1694. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal,
  1695. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal,
  1696. HANDLE ProcessHandle,
  1697. BOOL bMapToDummyPage
  1698. )
  1699. {
  1700. BOOL bUnmapMemory = FALSE;
  1701. DD_ASSERTDEVLOCK(peDirectDrawGlobal);
  1702. // If this was the last surface holding a pointer in the mapping we can
  1703. // can free it now. This involves calling the driver since it was the
  1704. // one who created the mapping in the first place. If this is not the
  1705. // last reference, and the memory has not been aliased yet, do so now:
  1706. if (--(peMap->cReferences) == 0)
  1707. {
  1708. bUnmapMemory = TRUE;
  1709. }
  1710. else if (!(peMap->fl & DD_VMEMMAPPING_FLAG_ALIASED) && bMapToDummyPage)
  1711. {
  1712. NTSTATUS Status;
  1713. EngAcquireSemaphore(ghsemDummyPage);
  1714. if (gpDummyPage == NULL)
  1715. {
  1716. // Allocate dummy page which is used to map all disabled user
  1717. // mode vid mem mapping to:
  1718. gpDummyPage = ExAllocatePoolWithTag(
  1719. (POOL_TYPE)(SESSION_POOL_MASK | NonPagedPool),
  1720. PAGE_SIZE, 'DddG');
  1721. if (gpDummyPage == NULL)
  1722. {
  1723. WARNING("vDdUnreferenceVirtualMap: could not allocate dummy page");
  1724. Status = STATUS_UNSUCCESSFUL;
  1725. }
  1726. else
  1727. {
  1728. ASSERTGDI(((ULONG_PTR)gpDummyPage & (PAGE_SIZE - 1)) == 0,
  1729. "vDdUnreferenceVirtualMap: "
  1730. "Dummy page is not page aligned\n");
  1731. DDKHEAP(("Allocated dummy page\n"));
  1732. gcDummyPageRefCnt = 0;
  1733. }
  1734. }
  1735. if (gpDummyPage != NULL)
  1736. {
  1737. DDKHEAP(("vDdUnreferenceVirtualMap: "
  1738. "Attempting to remap vid mem to dummy page\n"));
  1739. // There are outstanding locks to this memory. Map it to a dummy
  1740. // page and proceed.
  1741. // Calling services while attached is never a good idea.
  1742. // However, MmMapUserAddressesToPage handles this case, so we
  1743. // can attach and call:
  1744. KeAttachProcess(PsGetProcessPcb(peDirectDrawLocal->Process));
  1745. if (!(peMap->fl & DD_VMEMMAPPING_FLAG_AGP))
  1746. {
  1747. Status = MmMapUserAddressesToPage(
  1748. (VOID*) peMap->fpProcess, 0, gpDummyPage);
  1749. }
  1750. else
  1751. {
  1752. Status = AGPMapToDummy (peMap, peDirectDrawGlobal, gpDummyPage);
  1753. }
  1754. if (!NT_SUCCESS(Status))
  1755. {
  1756. DDKHEAP(("MmMapUserAddressesToPage failed: %08X\n", Status));
  1757. }
  1758. KeDetachProcess();
  1759. }
  1760. if (!NT_SUCCESS(Status))
  1761. {
  1762. EDD_SURFACE* peSurface;
  1763. WARNING("vDdUnreferenceVirtualMap: "
  1764. "failed to map user addresses to dummy page\n");
  1765. // Something went wrong so we must unmap the memory and remove
  1766. // any references to this map:
  1767. bUnmapMemory = TRUE;
  1768. // We need to traverse the surfaces of this local and mark all
  1769. // pointers to this mapping as NULL:
  1770. peSurface = peDirectDrawLocal->peSurface_Enum(NULL);
  1771. while (peSurface)
  1772. {
  1773. if (peSurface->peMap == peMap)
  1774. {
  1775. peSurface->peMap = NULL;
  1776. // Each mapping took a reference count on the surface's
  1777. // DirectDraw global, so undo that here:
  1778. vDdDecrementReferenceCount(
  1779. peSurface->peVirtualMapDdGlobal);
  1780. peSurface->peVirtualMapDdGlobal = NULL;
  1781. }
  1782. peSurface = peDirectDrawLocal->peSurface_Enum(peSurface);
  1783. }
  1784. }
  1785. else
  1786. {
  1787. peMap->fl |= DD_VMEMMAPPING_FLAG_ALIASED;
  1788. gcDummyPageRefCnt++;
  1789. }
  1790. EngReleaseSemaphore(ghsemDummyPage);
  1791. }
  1792. if (bUnmapMemory)
  1793. {
  1794. if (!(peMap->fl & DD_VMEMMAPPING_FLAG_AGP))
  1795. {
  1796. vDdUnmapMemory(peMap, peDirectDrawGlobal, ProcessHandle);
  1797. }
  1798. else
  1799. {
  1800. vDdUnmapAgpHeap(peMap, peDirectDrawGlobal, peDirectDrawLocal);
  1801. }
  1802. EngAcquireSemaphore(ghsemDummyPage);
  1803. if (peMap->fl & DD_VMEMMAPPING_FLAG_ALIASED)
  1804. {
  1805. ASSERTGDI(gcDummyPageRefCnt > 0,
  1806. "Dummy page reference count will be < 0");
  1807. ASSERTGDI(gpDummyPage != NULL,
  1808. "Dereferencing dummy page which has not been allocated");
  1809. gcDummyPageRefCnt--;
  1810. }
  1811. if ((gpDummyPage != NULL) && (gcDummyPageRefCnt == 0))
  1812. {
  1813. ExFreePool(gpDummyPage);
  1814. gpDummyPage = NULL;
  1815. DDKHEAP(("Freed dummy page\n"));
  1816. }
  1817. EngReleaseSemaphore(ghsemDummyPage);
  1818. if (peMap->pAgpVirtualCommitMask != NULL)
  1819. {
  1820. VFREEMEM(peMap->pAgpVirtualCommitMask);
  1821. }
  1822. VFREEMEM(peMap);
  1823. }
  1824. }
  1825. /******************************Public*Routine******************************\
  1826. * BOOL DxDdEnableDirectDraw
  1827. *
  1828. * Allocates the global DirectDraw object and then enables the driver
  1829. * for DirectDraw.
  1830. *
  1831. * Assumes devlock already held.
  1832. *
  1833. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  1834. * Wrote it.
  1835. \**************************************************************************/
  1836. BOOL
  1837. DxDdEnableDirectDraw(
  1838. HDEV hdev,
  1839. BOOL bEnableDriver
  1840. )
  1841. {
  1842. BOOL bRet = FALSE; // Assume failure
  1843. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  1844. KEVENT* pAssertModeEvent;
  1845. PDEVOBJ po(hdev);
  1846. // Don't bother doing anything for printers.
  1847. if (!po.bDisplayPDEV())
  1848. {
  1849. return(TRUE);
  1850. }
  1851. // Note that this must be zero initialized, because we promised
  1852. // the driver that we would. Don't zero-initialize the driver
  1853. // state, though, because there may be some open references to
  1854. // it!
  1855. peDirectDrawGlobal = po.peDirectDrawGlobal();
  1856. RtlZeroMemory((_DD_DIRECTDRAW_LOCAL*) peDirectDrawGlobal,
  1857. sizeof(_DD_DIRECTDRAW_LOCAL));
  1858. RtlZeroMemory((_DD_DIRECTDRAW_GLOBAL*) peDirectDrawGlobal,
  1859. sizeof(_DD_DIRECTDRAW_GLOBAL));
  1860. RtlZeroMemory((DD_DIRECTDRAW_GLOBAL_PDEV_DATA*) peDirectDrawGlobal,
  1861. sizeof(DD_DIRECTDRAW_GLOBAL_PDEV_DATA));
  1862. // Initialize our private structures:
  1863. peDirectDrawGlobal->hdev = po.hdev();
  1864. peDirectDrawGlobal->dhpdev = po.dhpdev();
  1865. peDirectDrawGlobal->bSuspended = FALSE;
  1866. // The VideoPort HAL calls oddly reference PDD_DIRECTDRAW_LOCAL
  1867. // instead of PDD_DIRECTDRAW_GLOBAL. The driver will never reference
  1868. // anything in the local structure other than 'lpGbl', so we simply
  1869. // add a DIRECTDRAW_LOCAL structure to the definition of the
  1870. // DIRECTDRAW_GLOBAL structure that points to itself:
  1871. peDirectDrawGlobal->lpGbl = peDirectDrawGlobal;
  1872. peDirectDrawGlobal->llAssertModeTimeout
  1873. = llDdAssertModeTimeout();
  1874. // The event must live in non-paged pool:
  1875. pAssertModeEvent = (KEVENT*) PALLOCNONPAGED(sizeof(KEVENT),'eddG');
  1876. if (pAssertModeEvent != NULL)
  1877. {
  1878. peDirectDrawGlobal->pAssertModeEvent = pAssertModeEvent;
  1879. KeInitializeEvent(pAssertModeEvent,
  1880. SynchronizationEvent,
  1881. FALSE);
  1882. if (bEnableDriver)
  1883. {
  1884. vDdEnableDriver(peDirectDrawGlobal);
  1885. }
  1886. bRet = TRUE;
  1887. }
  1888. return(bRet);
  1889. }
  1890. /******************************Public*Routine******************************\
  1891. * VOID DxDdDisableDirectDraw
  1892. *
  1893. * Note: This function may be called without bDdEnableDirectDraw having
  1894. * first been called!
  1895. *
  1896. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  1897. * Wrote it.
  1898. \**************************************************************************/
  1899. VOID
  1900. DxDdDisableDirectDraw(
  1901. HDEV hdev,
  1902. BOOL bDisableDriver
  1903. )
  1904. {
  1905. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  1906. PDEVOBJ po(hdev);
  1907. peDirectDrawGlobal = po.peDirectDrawGlobal();
  1908. // Don't bother doing anything more if we were never enabled in the
  1909. // first place.
  1910. if ((peDirectDrawGlobal == NULL) ||
  1911. (peDirectDrawGlobal->hdev == NULL))
  1912. {
  1913. return;
  1914. }
  1915. EDD_DEVLOCK eDevLock(hdev);
  1916. if (bDisableDriver)
  1917. {
  1918. vDdDisableDriver(peDirectDrawGlobal);
  1919. }
  1920. if (peDirectDrawGlobal->pAssertModeEvent != NULL)
  1921. {
  1922. VFREEMEM(peDirectDrawGlobal->pAssertModeEvent);
  1923. }
  1924. RtlZeroMemory(peDirectDrawGlobal, sizeof(*peDirectDrawGlobal));
  1925. }
  1926. /******************************Public*Routine******************************\
  1927. * VOID vDdDisableDirectDrawObject
  1928. *
  1929. * Disables a DirectDraw object. This amounts to simply unmapping the
  1930. * view of the frame buffer.
  1931. *
  1932. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  1933. * Wrote it.
  1934. \**************************************************************************/
  1935. VOID
  1936. vDdDisableDirectDrawObject(
  1937. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal
  1938. )
  1939. {
  1940. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  1941. NTSTATUS Status;
  1942. OBJECT_ATTRIBUTES ObjectAttributes;
  1943. HANDLE ProcessHandle;
  1944. CLIENT_ID ClientId;
  1945. EDD_VIDEOPORT* peVideoPort;
  1946. BOOL bUnmapAgpHeaps;
  1947. bUnmapAgpHeaps = peDirectDrawLocal->iAgpHeapsMapped > 0;
  1948. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  1949. // We may be in a different process from the one in which the
  1950. // memory was originally mapped. Consequently, we have to open
  1951. // a handle to the process in which the mapping was created.
  1952. // We are guaranteed that the process will still exist because
  1953. // this view is always unmapped at process termination.
  1954. ProcessHandle = NULL;
  1955. if (bUnmapAgpHeaps ||
  1956. ((peDirectDrawLocal->fl & DD_LOCAL_FLAG_MEMORY_MAPPED) &&
  1957. (peDirectDrawGlobal->CallBacks.dwFlags & DDHAL_CB32_MAPMEMORY)))
  1958. {
  1959. ClientId.UniqueThread = (HANDLE) NULL;
  1960. ClientId.UniqueProcess = peDirectDrawLocal->UniqueProcess;
  1961. InitializeObjectAttributes(&ObjectAttributes,
  1962. NULL,
  1963. OBJ_INHERIT | OBJ_KERNEL_HANDLE,
  1964. NULL,
  1965. NULL);
  1966. Status = ZwOpenProcess(&ProcessHandle,
  1967. PROCESS_DUP_HANDLE,
  1968. &ObjectAttributes,
  1969. &ClientId);
  1970. if (!NT_SUCCESS(Status))
  1971. {
  1972. WARNING("vDdDisableDirectDrawObject: "
  1973. "Couldn't open process handle");
  1974. ProcessHandle = NULL;
  1975. }
  1976. }
  1977. if (peDirectDrawLocal->fl & DD_LOCAL_FLAG_MEMORY_MAPPED)
  1978. {
  1979. peDirectDrawLocal->fl &= ~DD_LOCAL_FLAG_MEMORY_MAPPED;
  1980. peDirectDrawGlobal->cMaps--;
  1981. ASSERTGDI(peDirectDrawGlobal->cMaps >= 0, "Invalid map count");
  1982. if ((peDirectDrawGlobal->CallBacks.dwFlags & DDHAL_CB32_MAPMEMORY) &&
  1983. ProcessHandle != NULL)
  1984. {
  1985. vDdUnreferenceVirtualMap(peDirectDrawLocal->peMapCurrent,
  1986. peDirectDrawGlobal,
  1987. peDirectDrawLocal,
  1988. ProcessHandle,
  1989. TRUE);
  1990. peDirectDrawLocal->peMapCurrent = NULL;
  1991. }
  1992. }
  1993. // Unmap AGP heaps if necessary:
  1994. if (bUnmapAgpHeaps && (ProcessHandle != NULL))
  1995. {
  1996. DWORD i;
  1997. EDD_VMEMMAPPING** ppeMapAgp;
  1998. ppeMapAgp = peDirectDrawLocal->ppeMapAgp;
  1999. for (i = 0; i < peDirectDrawGlobal->dwNumHeaps; i++, ppeMapAgp++)
  2000. {
  2001. if (*ppeMapAgp != NULL)
  2002. {
  2003. vDdUnreferenceVirtualMap(*ppeMapAgp,
  2004. peDirectDrawGlobal,
  2005. peDirectDrawLocal,
  2006. ProcessHandle,
  2007. TRUE);
  2008. *ppeMapAgp = NULL;
  2009. }
  2010. }
  2011. }
  2012. if (ProcessHandle != NULL)
  2013. {
  2014. Status = ZwClose(ProcessHandle);
  2015. ASSERTGDI(NT_SUCCESS(Status), "Failed close handle");
  2016. }
  2017. // Stop any active videoports:
  2018. for (peVideoPort = peDirectDrawLocal->peVideoPort_DdList;
  2019. peVideoPort != NULL;
  2020. peVideoPort = peVideoPort->peVideoPort_DdNext)
  2021. {
  2022. vDdStopVideoPort(peVideoPort);
  2023. }
  2024. }
  2025. /******************************Public*Routine******************************\
  2026. * HANDLE hDdCreateDirectDrawLocal
  2027. *
  2028. * Creates a new local DirectDraw object for a process attaching to
  2029. * a PDEV for which we've already enabled DirectDraw. Note that the
  2030. * DirectDraw user-mode process will actually think of this as its
  2031. * 'global' DirectDraw object.
  2032. *
  2033. * Assumes devlock already held.
  2034. *
  2035. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  2036. * Wrote it.
  2037. \**************************************************************************/
  2038. HANDLE
  2039. hDdCreateDirectDrawLocal(
  2040. PDEVOBJ& po
  2041. )
  2042. {
  2043. HANDLE h;
  2044. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  2045. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  2046. EDD_VMEMMAPPING** ppeMapAgp;
  2047. h = 0;
  2048. peDirectDrawGlobal = po.peDirectDrawGlobal();
  2049. DD_ASSERTDEVLOCK(peDirectDrawGlobal);
  2050. if (peDirectDrawGlobal->dwNumHeaps > 0)
  2051. {
  2052. // Allocate an array to hold per-process AGP heap information.
  2053. ppeMapAgp = (EDD_VMEMMAPPING**)
  2054. PALLOCMEM(sizeof(EDD_VMEMMAPPING*) *
  2055. peDirectDrawGlobal->dwNumHeaps,
  2056. 'pddG');
  2057. if (ppeMapAgp == NULL)
  2058. {
  2059. return h;
  2060. }
  2061. }
  2062. else
  2063. {
  2064. ppeMapAgp = NULL;
  2065. }
  2066. // We allocate this via the handle manager so that we can use the
  2067. // existing handle manager process clean-up mechanisms:
  2068. peDirectDrawLocal = (EDD_DIRECTDRAW_LOCAL*) DdHmgAlloc(
  2069. sizeof(EDD_DIRECTDRAW_LOCAL),
  2070. DD_DIRECTDRAW_TYPE,
  2071. HMGR_ALLOC_LOCK);
  2072. if (peDirectDrawLocal != NULL)
  2073. {
  2074. // Insert this object at the head of the object list:
  2075. peDirectDrawLocal->peDirectDrawLocalNext
  2076. = peDirectDrawGlobal->peDirectDrawLocalList;
  2077. peDirectDrawGlobal->peDirectDrawLocalList = peDirectDrawLocal;
  2078. // Initialize surface list:
  2079. InitializeListHead(&(peDirectDrawLocal->ListHead_eSurface));
  2080. // Initialize private GDI data:
  2081. peDirectDrawLocal->peDirectDrawGlobal = peDirectDrawGlobal;
  2082. peDirectDrawLocal->lpGbl = peDirectDrawGlobal;
  2083. peDirectDrawLocal->UniqueProcess = PsGetCurrentThreadProcessId();
  2084. peDirectDrawLocal->Process = PsGetCurrentProcess();
  2085. peDirectDrawLocal->ppeMapAgp = ppeMapAgp;
  2086. peDirectDrawLocal->peMapCurrent = NULL;
  2087. // This has reference to PDEVOBJ, so increment ref count of PDEVOBJ:
  2088. po.vReferencePdev();
  2089. // Do an HmgUnlock:
  2090. h = peDirectDrawLocal->hHmgr;
  2091. DEC_EXCLUSIVE_REF_CNT(peDirectDrawLocal);
  2092. // Setup the AGP heaps if the driver exposes any
  2093. MapAllAgpHeaps( peDirectDrawLocal );
  2094. }
  2095. else if (ppeMapAgp != NULL)
  2096. {
  2097. VFREEMEM(ppeMapAgp);
  2098. }
  2099. return(h);
  2100. }
  2101. /******************************Public*Routine******************************\
  2102. * BOOL bDdDeleteDirectDrawObject
  2103. *
  2104. * Deletes a kernel-mode representation of the DirectDraw object.
  2105. *
  2106. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  2107. * Wrote it.
  2108. \**************************************************************************/
  2109. BOOL
  2110. bDdDeleteDirectDrawObject(
  2111. HANDLE hDirectDrawLocal,
  2112. BOOL bProcessTermination
  2113. )
  2114. {
  2115. BOOL bRet;
  2116. BOOL b;
  2117. VOID* pRemove;
  2118. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  2119. EDD_DIRECTDRAW_LOCAL* peTmp;
  2120. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  2121. EDD_VIDEOPORT* peVideoPort;
  2122. EDD_VIDEOPORT* peVideoPortNext;
  2123. EDD_MOTIONCOMP* peMotionComp;
  2124. EDD_MOTIONCOMP* peMotionCompNext;
  2125. EDD_SURFACE* peSurface;
  2126. EDD_SURFACE* peSurfaceNext;
  2127. bRet = FALSE;
  2128. peDirectDrawLocal = (EDD_DIRECTDRAW_LOCAL*)
  2129. DdHmgLock((HDD_OBJ) hDirectDrawLocal, DD_DIRECTDRAW_TYPE, FALSE);
  2130. if (peDirectDrawLocal != NULL)
  2131. {
  2132. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  2133. PDEVOBJ po(peDirectDrawGlobal->hdev);
  2134. b = TRUE;
  2135. // Now, try to delete all videoports associated with this object:
  2136. for (peVideoPort = peDirectDrawLocal->peVideoPort_DdList;
  2137. peVideoPort != NULL;
  2138. peVideoPort = peVideoPortNext)
  2139. {
  2140. // Don't reference peVideoPort after it's been deleted!
  2141. peVideoPortNext = peVideoPort->peVideoPort_DdNext;
  2142. b &= bDdDeleteVideoPortObject(peVideoPort->hGet(), NULL);
  2143. }
  2144. for (peMotionComp = peDirectDrawLocal->peMotionComp_DdList;
  2145. peMotionComp != NULL;
  2146. peMotionComp = peMotionCompNext)
  2147. {
  2148. peMotionCompNext = peMotionComp->peMotionComp_DdNext;
  2149. b &= bDdDeleteMotionCompObject(peMotionComp->hGet(), NULL);
  2150. }
  2151. // Next, try to delete all surfaces associated with this object:
  2152. peSurface = peDirectDrawLocal->peSurface_Enum(NULL);
  2153. while (peSurface)
  2154. {
  2155. // Don't reference peSurface after it's been deleted!
  2156. peSurfaceNext = peDirectDrawLocal->peSurface_Enum(peSurface);
  2157. // Delete the surface
  2158. b &= bDdDeleteSurfaceObject(peSurface->hGet(), NULL);
  2159. // Move onto next one
  2160. peSurface = peSurfaceNext;
  2161. }
  2162. {
  2163. EDD_SHAREDEVLOCK eDevlock(peDirectDrawGlobal);
  2164. // If they set a gamma ramp, restore it now
  2165. if (peDirectDrawLocal->pGammaRamp != NULL)
  2166. {
  2167. DxEngSetDeviceGammaRamp(
  2168. po.hdev(),
  2169. peDirectDrawLocal->pGammaRamp,
  2170. TRUE);
  2171. VFREEMEM(peDirectDrawLocal->pGammaRamp);
  2172. peDirectDrawLocal->pGammaRamp = NULL;
  2173. }
  2174. if (peDirectDrawGlobal->Miscellaneous2CallBacks.DestroyDDLocal)
  2175. {
  2176. DWORD dwRet = DDHAL_DRIVER_NOTHANDLED;
  2177. DD_DESTROYDDLOCALDATA destDDLcl;
  2178. destDDLcl.dwFlags = 0;
  2179. destDDLcl.pDDLcl = peDirectDrawLocal;
  2180. dwRet = peDirectDrawGlobal->Miscellaneous2CallBacks.DestroyDDLocal(&destDDLcl);
  2181. if (dwRet == DDHAL_DRIVER_NOTHANDLED)
  2182. {
  2183. WARNING("bDdDeleteDirectDrawObject: failed DestroyDDLocal\n");
  2184. }
  2185. }
  2186. // Only delete the DirectDraw object if we successfully deleted
  2187. // all linked surface objects:
  2188. if (b)
  2189. {
  2190. DWORD dwHeap;
  2191. LPVIDMEM pHeap;
  2192. // Remove object from the handle manager:
  2193. pRemove = DdHmgRemoveObject((HDD_OBJ) hDirectDrawLocal,
  2194. 1,
  2195. 0,
  2196. TRUE,
  2197. DD_DIRECTDRAW_TYPE);
  2198. ASSERTGDI(pRemove != NULL, "Couldn't delete DirectDraw object");
  2199. vDdDisableDirectDrawObject(peDirectDrawLocal);
  2200. // Now that we've cleanup up the surfaces, now we will cleanup any
  2201. // agp commits that need to be.
  2202. pHeap = peDirectDrawGlobal->pvmList;
  2203. for (dwHeap = 0;
  2204. dwHeap < peDirectDrawGlobal->dwNumHeaps;
  2205. pHeap++, dwHeap++)
  2206. {
  2207. if (!(pHeap->dwFlags & VIDMEM_ISHEAP) &&
  2208. !(pHeap->dwFlags & VIDMEM_HEAPDISABLED) &&
  2209. (pHeap->dwFlags & VIDMEM_ISNONLOCAL) &&
  2210. (pHeap->lpHeap != NULL))
  2211. {
  2212. CleanupAgpCommits( pHeap, pHeap->lpHeap->hdevAGP,
  2213. peDirectDrawGlobal, dwHeap );
  2214. }
  2215. }
  2216. ////////////////////////////////////////////////////////////
  2217. // Remove the global DirectDraw object from the PDEV when
  2218. // the last associated local object is destroyed, and
  2219. // call the driver:
  2220. if (peDirectDrawGlobal->peDirectDrawLocalList == peDirectDrawLocal)
  2221. {
  2222. peDirectDrawGlobal->peDirectDrawLocalList
  2223. = peDirectDrawLocal->peDirectDrawLocalNext;
  2224. }
  2225. else
  2226. {
  2227. for (peTmp = peDirectDrawGlobal->peDirectDrawLocalList;
  2228. peTmp->peDirectDrawLocalNext != peDirectDrawLocal;
  2229. peTmp = peTmp->peDirectDrawLocalNext)
  2230. ;
  2231. peTmp->peDirectDrawLocalNext
  2232. = peDirectDrawLocal->peDirectDrawLocalNext;
  2233. }
  2234. // We're all done with this object, so free the memory and
  2235. // leave:
  2236. if (peDirectDrawLocal->ppeMapAgp != NULL)
  2237. {
  2238. VFREEMEM(peDirectDrawLocal->ppeMapAgp);
  2239. }
  2240. DdFreeObject(peDirectDrawLocal, DD_DIRECTDRAW_TYPE);
  2241. bRet = TRUE;
  2242. }
  2243. else
  2244. {
  2245. WARNING("bDdDeleteDirectDrawObject: A surface was busy\n");
  2246. if (bProcessTermination)
  2247. {
  2248. peDirectDrawLocal->fl |= DD_LOCAL_DISABLED;
  2249. }
  2250. }
  2251. }
  2252. if (bRet)
  2253. {
  2254. // Unreference PDEVOBJ - must not have devlock
  2255. po.vUnreferencePdev();
  2256. }
  2257. // Note that we can't force a repaint here by calling
  2258. // UserRedrawDesktop because we may be in a bad process context.
  2259. }
  2260. else
  2261. {
  2262. WARNING("bDdDeleteDirectDrawObject: Bad handle or object busy\n");
  2263. }
  2264. return(bRet);
  2265. }
  2266. /******************************Public*Routine******************************\
  2267. * VOID vDdRelinquishSurfaceOrBufferLock
  2268. *
  2269. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  2270. * Wrote it.
  2271. \**************************************************************************/
  2272. VOID
  2273. vDdRelinquishSurfaceOrBufferLock(
  2274. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal,
  2275. EDD_SURFACE* peSurface
  2276. )
  2277. {
  2278. DD_UNLOCKDATA UnlockData;
  2279. EDD_SURFACE* peTmp;
  2280. PDEVOBJ po(peDirectDrawGlobal->hdev);
  2281. DD_ASSERTDEVLOCK(peDirectDrawGlobal);
  2282. ASSERTGDI(peSurface->cLocks > 0, "Must have non-zero locks to relinquish");
  2283. if (peSurface->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER)
  2284. {
  2285. if (peDirectDrawGlobal->D3dBufCallbacks.UnlockD3DBuffer != NULL)
  2286. {
  2287. UnlockData.lpDD = peDirectDrawGlobal;
  2288. UnlockData.lpDDSurface = peSurface;
  2289. peDirectDrawGlobal->D3dBufCallbacks.UnlockD3DBuffer(&UnlockData);
  2290. }
  2291. }
  2292. else
  2293. {
  2294. if (peDirectDrawGlobal->SurfaceCallBacks.dwFlags &
  2295. DDHAL_SURFCB32_UNLOCK)
  2296. {
  2297. UnlockData.lpDD = peDirectDrawGlobal;
  2298. UnlockData.lpDDSurface = peSurface;
  2299. peDirectDrawGlobal->SurfaceCallBacks.Unlock(&UnlockData);
  2300. }
  2301. }
  2302. // An application may take multiple locks on the same surface:
  2303. if (--peSurface->cLocks == 0)
  2304. {
  2305. if (!(peSurface->dwFlags & DDRAWISURF_DRIVERMANAGED) ||
  2306. ((peSurface->dwFlags & DDRAWISURF_DRIVERMANAGED) &&
  2307. (peSurface->ddsCapsEx.dwCaps2 & DDSCAPS2_DONOTPERSIST)))
  2308. {
  2309. peDirectDrawGlobal->cSurfaceLocks--;
  2310. }
  2311. if (peSurface->peMap ||
  2312. (peSurface->fl & DD_SURFACE_FLAG_FAKE_ALIAS_LOCK))
  2313. {
  2314. peDirectDrawGlobal->cSurfaceAliasedLocks--;
  2315. peSurface->fl &= ~DD_SURFACE_FLAG_FAKE_ALIAS_LOCK;
  2316. }
  2317. // Primary surface unlocks require special handling for stuff like
  2318. // pointer exclusion:
  2319. if (peSurface->fl & DD_SURFACE_FLAG_PRIMARY)
  2320. {
  2321. // Since all locks for this surface have been relinquished, remove
  2322. // it from the locked surface list.
  2323. if (peDirectDrawGlobal->peSurface_PrimaryLockList == peSurface)
  2324. {
  2325. peDirectDrawGlobal->peSurface_PrimaryLockList
  2326. = peSurface->peSurface_PrimaryLockNext;
  2327. }
  2328. else
  2329. {
  2330. for (peTmp = peDirectDrawGlobal->peSurface_PrimaryLockList;
  2331. peTmp->peSurface_PrimaryLockNext != peSurface;
  2332. peTmp = peTmp->peSurface_PrimaryLockNext)
  2333. {
  2334. ASSERTGDI(peTmp != NULL, "Can't find surface in lock list");
  2335. }
  2336. peTmp->peSurface_PrimaryLockNext
  2337. = peSurface->peSurface_PrimaryLockNext;
  2338. }
  2339. peSurface->peSurface_PrimaryLockNext = NULL;
  2340. // Redraw any sprites:
  2341. DxEngSpUnTearDownSprites(peDirectDrawGlobal->hdev,
  2342. &peSurface->rclLock,
  2343. TRUE);
  2344. }
  2345. }
  2346. }
  2347. /******************************Public*Routine******************************\
  2348. * VOID vDdLooseManagedSurfaceObject
  2349. *
  2350. * Informs the driver that it should clean up any video memory allocated for
  2351. * a persistent managed surface since a mode switch has occured.
  2352. *
  2353. * 13-May-1999 -by- Sameer Nene [snene]
  2354. * Wrote it.
  2355. \**************************************************************************/
  2356. VOID
  2357. vDdLooseManagedSurfaceObject(
  2358. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal,
  2359. EDD_SURFACE* peSurface,
  2360. DWORD* pdwRet // For returning driver return code,
  2361. ) // may be NULL
  2362. {
  2363. DD_DESTROYSURFACEDATA DestroySurfaceData;
  2364. DD_ASSERTSHAREDEVLOCK();
  2365. DD_ASSERTDEVLOCK(peDirectDrawGlobal);
  2366. PDEVOBJ po(peDirectDrawGlobal->hdev);
  2367. DDKHEAP(("DDKHEAP: Loosing surface %X (%X)\n",
  2368. peSurface->hGet(), peSurface));
  2369. // Due to video mode change, this driver managed surface is lives in "different" video
  2370. // driver then what the driver actually "manage" this surface.
  2371. // So we don't do anything here, since it has been "loose" already since mode change happened.
  2372. if (!(peSurface->fl & DD_SURFACE_FLAG_WRONG_DRIVER))
  2373. {
  2374. DestroySurfaceData.lpDD = peDirectDrawGlobal;
  2375. DestroySurfaceData.lpDDSurface = peSurface;
  2376. DestroySurfaceData.lpDDSurface->dwFlags |= DDRAWISURF_INVALID;
  2377. if ((peSurface->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) &&
  2378. peDirectDrawGlobal->D3dBufCallbacks.DestroyD3DBuffer != NULL)
  2379. {
  2380. peDirectDrawGlobal->D3dBufCallbacks.DestroyD3DBuffer(&DestroySurfaceData);
  2381. }
  2382. else if (!(peSurface->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) &&
  2383. (peDirectDrawGlobal->SurfaceCallBacks.dwFlags & DDHAL_SURFCB32_DESTROYSURFACE))
  2384. {
  2385. peDirectDrawGlobal->SurfaceCallBacks.DestroySurface(&DestroySurfaceData);
  2386. }
  2387. DestroySurfaceData.lpDDSurface->dwFlags &= ~DDRAWISURF_INVALID;
  2388. }
  2389. else
  2390. {
  2391. // WARNING("vDdLooseManagedSurfaceObject: called with DD_SURFACE_FLAG_WRONG_DRIVER");
  2392. }
  2393. if (pdwRet != NULL)
  2394. {
  2395. *pdwRet = DDHAL_DRIVER_HANDLED;
  2396. }
  2397. }
  2398. /******************************Public*Routine******************************\
  2399. * VOID SafeFreeUserMem
  2400. *
  2401. * Frees user mem and switches to the correct process if required.
  2402. *
  2403. * 5-Apr-2001 -by- Scott MacDonald [smac]
  2404. * Wrote it.
  2405. \**************************************************************************/
  2406. VOID
  2407. SafeFreeUserMem(
  2408. PVOID pv,
  2409. PEPROCESS Process
  2410. )
  2411. {
  2412. if (PsGetCurrentProcess() == Process)
  2413. {
  2414. EngFreeUserMem(pv);
  2415. }
  2416. else
  2417. {
  2418. // Calling services while attached is never a good idea. However,
  2419. // free virtual memory handles this case, so we can attach and
  2420. // call.
  2421. //
  2422. // Note that the process must exist. We are guaranteed that this
  2423. // is the case because we automatically delete all surfaces on
  2424. // process deletion.
  2425. KeAttachProcess(PsGetProcessPcb(Process));
  2426. EngFreeUserMem(pv);
  2427. KeDetachProcess();
  2428. }
  2429. }
  2430. /******************************Public*Routine******************************\
  2431. * VOID DeferMemoryFree
  2432. *
  2433. * Places the memory into a list to be freed at a later time when it's safe.
  2434. *
  2435. * 5-Apr-2001 -by- Scott MacDonald [smac]
  2436. * Wrote it.
  2437. \**************************************************************************/
  2438. VOID
  2439. DeferMemoryFree(
  2440. PVOID pv,
  2441. EDD_SURFACE* peSurface
  2442. )
  2443. {
  2444. DD_USERMEM_DEFER* pDefer;
  2445. pDefer = (DD_USERMEM_DEFER*) PALLOCMEM(sizeof(DD_USERMEM_DEFER),
  2446. 'pddG');
  2447. if (pDefer != NULL)
  2448. {
  2449. pDefer->pUserMem = pv;
  2450. pDefer->peSurface = peSurface;
  2451. pDefer->pNext = peSurface->peDirectDrawLocal->peDirectDrawGlobal->pUserMemDefer;
  2452. peSurface->peDirectDrawLocal->peDirectDrawGlobal->pUserMemDefer = pDefer;
  2453. peSurface->fl |= DD_SURFACE_FLAG_DEFER_USERMEM;
  2454. }
  2455. }
  2456. /******************************Public*Routine******************************\
  2457. * VOID vDdDisableSurfaceObject
  2458. *
  2459. * Disables a kernel-mode representation of the surface. This is also
  2460. * known as marking the surface as 'lost'.
  2461. *
  2462. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  2463. * Wrote it.
  2464. \**************************************************************************/
  2465. VOID
  2466. vDdDisableSurfaceObject(
  2467. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal,
  2468. EDD_SURFACE* peSurface,
  2469. DWORD* pdwRet // For returning driver return code,
  2470. ) // may be NULL
  2471. {
  2472. DWORD dwRet;
  2473. DXOBJ* pDxObj;
  2474. DXOBJ* pDxObjNext;
  2475. DD_FLIPDATA FlipData;
  2476. EDD_SURFACE* peSurfaceCurrent;
  2477. EDD_SURFACE* peSurfacePrimary;
  2478. DD_DESTROYSURFACEDATA DestroySurfaceData;
  2479. DD_UPDATEOVERLAYDATA UpdateOverlayData;
  2480. DD_ASSERTSHAREDEVLOCK();
  2481. DD_ASSERTDEVLOCK(peDirectDrawGlobal);
  2482. dwRet = DDHAL_DRIVER_NOTHANDLED;
  2483. PDEVOBJ po(peDirectDrawGlobal->hdev);
  2484. DDKHEAP(("DDKHEAP: Disabling surface %X (%X)\n",
  2485. peSurface->hGet(), peSurface));
  2486. // If this surface is a destination surface for the videoport, turn it
  2487. // off:
  2488. if (peSurface->lpVideoPort != NULL)
  2489. {
  2490. vDdStopVideoPort(pedFromLp(peSurface->lpVideoPort));
  2491. ASSERTGDI(peSurface->lpVideoPort == NULL, "Expected surface clean-up");
  2492. }
  2493. // Mark the DXAPI instance of the surface as lost:
  2494. if (peSurface->hSurface != NULL)
  2495. {
  2496. vDdDxApiFreeSurface( (DXOBJ*) peSurface->hSurface, FALSE );
  2497. peSurface->hSurface = NULL;
  2498. }
  2499. if (peSurface->peDxSurface != NULL)
  2500. {
  2501. vDdLoseDxObjects(peDirectDrawGlobal,
  2502. peSurface->peDxSurface->pDxObj_List,
  2503. (PVOID) peSurface->peDxSurface,
  2504. LO_SURFACE );
  2505. }
  2506. if (peSurface->peDxSurface != NULL)
  2507. {
  2508. peDirectDrawGlobal->pfnLoseObject(peSurface->peDxSurface,
  2509. LO_SURFACE);
  2510. }
  2511. if (peSurface->hbmGdi != NULL)
  2512. {
  2513. // It's not always possible to delete the cached GDI
  2514. // bitmap here, because we might have to first un-select
  2515. // the bitmap from its DC, and doing so requires an
  2516. // exclusive lock on the DC, which may not be possible
  2517. // if another thread is currently in kernel mode with the
  2518. // DC locked, just waiting for us to release the devlock.
  2519. //
  2520. // But we desperately need to delete the driver's
  2521. // realization at this point, before a mode change happens
  2522. // which renders its associations invalid. So we do that
  2523. // now.
  2524. //
  2525. // This may leave the surface in an unusable state (which
  2526. // is true even for non-DrvDeriveSurface surfaces).
  2527. // That's okay, because the surface can't be selected into
  2528. // any other DC, and the DC is marked as 'disabled' in the
  2529. // following snibbet of code.
  2530. // Bug 330141 : sr(hbmGdi) does not work since it fails
  2531. // when we are called on a non-creating thread in mode
  2532. // change, thus not deleting the bitmap.
  2533. SURFOBJ* pso;
  2534. if ((pso = DxEngAltLockSurface(peSurface->hbmGdi)) != NULL)
  2535. {
  2536. if (pso->dhsurf != NULL)
  2537. {
  2538. (*PPFNDRV(po, DeleteDeviceBitmap))(pso->dhsurf);
  2539. pso->dhsurf = NULL;
  2540. }
  2541. EngUnlockSurface(pso);
  2542. }
  2543. }
  2544. if (peSurface->hdc != NULL)
  2545. {
  2546. // We've given out a DC to the application via GetDC that
  2547. // allows it to have GDI draw directly on the surface.
  2548. // The problem is that we want to unmap the application's
  2549. // view of the frame buffer -- but now we can have GDI
  2550. // drawing to it. So if we simply forced the unmap, GDI
  2551. // would access violate if the DC was ever used again.
  2552. //
  2553. // We also can't simply delete the DC, because there may
  2554. // be another thread already in kernel mode that has locked
  2555. // the DC and is waiting on the devlock -- which we have.
  2556. //
  2557. // Note that the DC can not simply be deleted here, because
  2558. // it may validly be in-use by another thread that has made
  2559. // it to the kernel. The DC deletion has to wait until
  2560. // bDdDeleteSurfaceObject.
  2561. if (!DxEngSetDCState(peSurface->hdc,DCSTATE_FULLSCREEN,(ULONG_PTR)TRUE))
  2562. {
  2563. WARNING("vDdDisableSurfaceObject: Couldn't mark DC as disabled.\n");
  2564. ghdcCantLose = peSurface->hdc;
  2565. #if DBG_HIDEYUKN
  2566. DbgBreakPoint();
  2567. #endif
  2568. }
  2569. }
  2570. if (peSurface->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  2571. {
  2572. // System-memory surfaces should only ever need to be disabled from
  2573. // the same process in which they were created:
  2574. if (peSurface->hSecure)
  2575. {
  2576. ASSERTGDI(peSurface->peDirectDrawLocal->Process
  2577. == PsGetCurrentProcess(),
  2578. "vDdDisableSurfaceObject: SYSMEM object disabled in wrong process");
  2579. MmUnsecureVirtualMemory(peSurface->hSecure);
  2580. peSurface->hSecure = NULL;
  2581. }
  2582. }
  2583. else
  2584. {
  2585. if (peSurface->cLocks != 0)
  2586. {
  2587. // We're unmapping the frame buffer view while there are outstanding
  2588. // frame buffer locks; keep track of the address for debugging
  2589. // purposes, since the application is undoubtedly about to access-
  2590. // violate:
  2591. gfpUnmap = peSurface->peDirectDrawLocal->fpProcess;
  2592. #if DBG
  2593. DbgPrint("GDI vDdDisableSurfaceObject: Preemptively unmapping application's\n");
  2594. DbgPrint(" frame buffer view at 0x%lx!\n\n", gfpUnmap);
  2595. #endif
  2596. }
  2597. // Remove any outstanding locks and repaint the mouse pointer:
  2598. while (peSurface->cLocks != 0)
  2599. {
  2600. vDdRelinquishSurfaceOrBufferLock(peDirectDrawGlobal, peSurface);
  2601. }
  2602. // If this surface is the currently visible one as a result of a flip,
  2603. // then switch back to the primary GDI surface:
  2604. peSurfaceCurrent = peDirectDrawGlobal->peSurfaceCurrent;
  2605. peSurfacePrimary = peDirectDrawGlobal->peSurfacePrimary;
  2606. if ((peSurfaceCurrent == peSurface) || (peSurfacePrimary == peSurface))
  2607. {
  2608. // We may be in a different process from the one that created the
  2609. // surface, so don't flip to the primary if it's a user-memory
  2610. // allocated surface:
  2611. if ((peSurfacePrimary != NULL) &&
  2612. !(peSurfacePrimary->fl & DD_SURFACE_FLAG_UMEM_ALLOCATED))
  2613. {
  2614. ASSERTGDI((peSurfaceCurrent != NULL) && (peSurfacePrimary != NULL),
  2615. "Both surfaces must be non-NULL");
  2616. ASSERTGDI(peSurfacePrimary->fl & DD_SURFACE_FLAG_PRIMARY,
  2617. "Primary flag is confused.");
  2618. if (peDirectDrawGlobal->SurfaceCallBacks.dwFlags & DDHAL_SURFCB32_FLIP)
  2619. {
  2620. // If the current isn't the primary, then swap back to the primary:
  2621. if (!(peSurfaceCurrent->fl & DD_SURFACE_FLAG_PRIMARY))
  2622. {
  2623. FlipData.ddRVal = DDERR_GENERIC;
  2624. FlipData.lpDD = peDirectDrawGlobal;
  2625. FlipData.lpSurfCurr = peSurfaceCurrent;
  2626. FlipData.lpSurfTarg = peSurfacePrimary;
  2627. FlipData.dwFlags = 0;
  2628. FlipData.lpSurfCurrLeft = NULL;
  2629. FlipData.lpSurfTargLeft = NULL;
  2630. peSurfacePrimary->ddsCaps.dwCaps |= DDSCAPS_PRIMARYSURFACE;
  2631. do {
  2632. dwRet = peDirectDrawGlobal->SurfaceCallBacks.Flip(&FlipData);
  2633. } while ((dwRet == DDHAL_DRIVER_HANDLED) &&
  2634. (FlipData.ddRVal == DDERR_WASSTILLDRAWING));
  2635. ASSERTGDI((dwRet == DDHAL_DRIVER_HANDLED) &&
  2636. (FlipData.ddRVal == DD_OK),
  2637. "Driver failed when cleaning up flip surfaces");
  2638. }
  2639. }
  2640. }
  2641. peDirectDrawGlobal->peSurfaceCurrent = NULL;
  2642. peDirectDrawGlobal->peSurfacePrimary = NULL;
  2643. }
  2644. // Make sure the overlay is marked as hidden before it's deleted, so
  2645. // that we don't have to rely on drivers doing it in their DestroySurface
  2646. // routine:
  2647. if ((peSurface->ddsCaps.dwCaps & DDSCAPS_OVERLAY) &&
  2648. (peDirectDrawGlobal->SurfaceCallBacks.dwFlags &
  2649. DDHAL_SURFCB32_UPDATEOVERLAY) &&
  2650. (peSurface->fl & DD_SURFACE_FLAG_UPDATE_OVERLAY_CALLED))
  2651. {
  2652. UpdateOverlayData.lpDD = peDirectDrawGlobal;
  2653. UpdateOverlayData.lpDDDestSurface = NULL;
  2654. UpdateOverlayData.lpDDSrcSurface = peSurface;
  2655. UpdateOverlayData.dwFlags = DDOVER_HIDE;
  2656. UpdateOverlayData.ddRVal = DDERR_GENERIC;
  2657. peDirectDrawGlobal->SurfaceCallBacks.UpdateOverlay(&UpdateOverlayData);
  2658. }
  2659. // If we allocated user-mode memory on the driver's behalf, we'll
  2660. // free it now. This is complicated by the fact that we may be
  2661. // in a different process context.
  2662. if (peSurface->fl & DD_SURFACE_FLAG_UMEM_ALLOCATED)
  2663. {
  2664. ASSERTGDI(peSurface->fpVidMem != NULL, "Expected non-NULL fpVidMem");
  2665. DDKHEAP(("DDKHEAP: Fre um %08X, surf %X (%X)\n",
  2666. peSurface->fpVidMem, peSurface->hGet(), peSurface));
  2667. if (peSurface->fl & DD_SURFACE_FLAG_ALIAS_LOCK)
  2668. {
  2669. DeferMemoryFree((PVOID)peSurface->fpVidMem, peSurface);
  2670. }
  2671. else
  2672. {
  2673. SafeFreeUserMem((PVOID)peSurface->fpVidMem, peSurface->peDirectDrawLocal->Process);
  2674. }
  2675. peSurface->fpVidMem = 0;
  2676. }
  2677. if (peSurface->fl & DD_SURFACE_FLAG_VMEM_ALLOCATED)
  2678. {
  2679. ASSERTGDI(peSurface->lpVidMemHeap != NULL &&
  2680. peSurface->lpVidMemHeap->lpHeap &&
  2681. peSurface->fpHeapOffset != NULL,
  2682. "Expected non-NULL lpVidMemHeap and fpHeapOffset");
  2683. DDKHEAP(("DDKHEAP: Fre vm %08X, o %08X, heap %X, surf %X (%X)\n",
  2684. peSurface->fpVidMem, peSurface->fpHeapOffset,
  2685. peSurface->lpVidMemHeap->lpHeap,
  2686. peSurface->hGet(), peSurface));
  2687. DxDdHeapVidMemFree(peSurface->lpVidMemHeap->lpHeap,
  2688. peSurface->fpHeapOffset);
  2689. peSurface->lpVidMemHeap = NULL;
  2690. peSurface->fpVidMem = 0;
  2691. peSurface->fpHeapOffset = 0;
  2692. }
  2693. // Delete the driver's surface instance. Note that we may be calling
  2694. // here from a process different from the one in which the surface was
  2695. // created, meaning that the driver cannot make function calls like
  2696. // EngFreeUserMem.
  2697. if (peSurface->fl & DD_SURFACE_FLAG_DRIVER_CREATED)
  2698. {
  2699. EDD_DIRECTDRAW_GLOBAL *peDdGlobalDriver;
  2700. if (peSurface->fl & DD_SURFACE_FLAG_WRONG_DRIVER)
  2701. {
  2702. WARNING("vDdDisableSurfaceObject: Call driver other than current.");
  2703. peDdGlobalDriver = peSurface->peDdGlobalCreator;
  2704. }
  2705. else
  2706. {
  2707. peDdGlobalDriver = peSurface->peDirectDrawGlobal;
  2708. }
  2709. DestroySurfaceData.lpDD = peDdGlobalDriver;
  2710. DestroySurfaceData.lpDDSurface = peSurface;
  2711. if ((peSurface->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) &&
  2712. peDdGlobalDriver->D3dBufCallbacks.DestroyD3DBuffer != NULL)
  2713. {
  2714. dwRet = peDdGlobalDriver->
  2715. D3dBufCallbacks.DestroyD3DBuffer(&DestroySurfaceData);
  2716. }
  2717. else if (!(peSurface->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) &&
  2718. (peDdGlobalDriver->SurfaceCallBacks.dwFlags &
  2719. DDHAL_SURFCB32_DESTROYSURFACE))
  2720. {
  2721. dwRet = peDdGlobalDriver->
  2722. SurfaceCallBacks.DestroySurface(&DestroySurfaceData);
  2723. }
  2724. // Drivers are supposed to return DDHAL_DRIVER_NOTHANDLED from
  2725. // DestroySurface if they returned DDHAL_DRIVER_NOTHANDLED from
  2726. // CreateSurface, which is the case for PLEASEALLOC_*. We
  2727. // munged the return code for PLEASEALLOC_* at CreateSurface
  2728. // time; we have to munge it now, too:
  2729. if ((dwRet == DDHAL_DRIVER_NOTHANDLED) &&
  2730. (peSurface->fl & (DD_SURFACE_FLAG_UMEM_ALLOCATED |
  2731. DD_SURFACE_FLAG_VMEM_ALLOCATED)))
  2732. {
  2733. dwRet = DDHAL_DRIVER_HANDLED;
  2734. }
  2735. // Decrement ref count on driver if driver managed surface.
  2736. if (peSurface->dwFlags & DDRAWISURF_DRIVERMANAGED)
  2737. {
  2738. ASSERTGDI(peSurface->fl & DD_SURFACE_FLAG_CREATE_COMPLETE,
  2739. "vDdDisableSurfaceObject: missing complete flag.");
  2740. vDdDecrementReferenceCount(peDdGlobalDriver);
  2741. }
  2742. }
  2743. }
  2744. // Mark the surface as lost and reset some flags now for if the
  2745. // surface gets reused:
  2746. if (!(peSurface->bLost))
  2747. {
  2748. peSurface->bLost = TRUE;
  2749. // If this surface is not lost formerly, but just lost here
  2750. // decrement active surface ref. count.
  2751. ASSERTGDI(peSurface->peDirectDrawLocal->cActiveSurface > 0,
  2752. "cActiveSurface will be negative");
  2753. peSurface->peDirectDrawLocal->cActiveSurface--;
  2754. }
  2755. // We used to zero the flags, but we need DD_SURFACE_FLAG_DEFER_USERMEM
  2756. // to survive until we call DeleteSurfaceObject.
  2757. peSurface->fl &= DD_SURFACE_FLAG_DEFER_USERMEM;
  2758. if (pdwRet != NULL)
  2759. {
  2760. *pdwRet = dwRet;
  2761. }
  2762. }
  2763. /******************************Public*Routine******************************\
  2764. * EDD_SURFACE* peSurfaceFindAttachedMipMap
  2765. *
  2766. * Transmogrified from misc.c's FindAttachedMipMap.
  2767. *
  2768. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  2769. * Wrote it.
  2770. \**************************************************************************/
  2771. inline
  2772. EDD_SURFACE*
  2773. peSurfaceFindAttachedMipMap(
  2774. EDD_SURFACE* peSurface
  2775. )
  2776. {
  2777. DD_ATTACHLIST* pAttachList;
  2778. EDD_SURFACE* peSurfaceAttached;
  2779. for (pAttachList = peSurface->lpAttachList;
  2780. pAttachList != NULL;
  2781. pAttachList = pAttachList->lpLink)
  2782. {
  2783. peSurfaceAttached = pedFromLp(pAttachList->lpAttached);
  2784. if (peSurfaceAttached->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
  2785. {
  2786. return(peSurfaceAttached);
  2787. }
  2788. }
  2789. return(NULL);
  2790. }
  2791. /******************************Public*Routine******************************\
  2792. * EDD_SURFACE* peSurfaceFindParentMipMap
  2793. *
  2794. * Transmogrified from misc.c's FindParentMipMap.
  2795. *
  2796. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  2797. * Wrote it.
  2798. \**************************************************************************/
  2799. inline
  2800. EDD_SURFACE*
  2801. peSurfaceFindParentMipMap(
  2802. EDD_SURFACE* peSurface
  2803. )
  2804. {
  2805. DD_ATTACHLIST* pAttachList;
  2806. EDD_SURFACE* peSurfaceAttached;
  2807. for (pAttachList = peSurface->lpAttachListFrom;
  2808. pAttachList != NULL;
  2809. pAttachList = pAttachList->lpLink)
  2810. {
  2811. peSurfaceAttached = pedFromLp(pAttachList->lpAttached);
  2812. if (peSurfaceAttached->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
  2813. {
  2814. return(peSurfaceAttached);
  2815. }
  2816. }
  2817. return(NULL);
  2818. }
  2819. /******************************Public*Routine******************************\
  2820. * VOID vDdUpdateMipMapCount
  2821. *
  2822. * Transmogrified from ddsatch.c's UpdateMipMapCount.
  2823. *
  2824. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  2825. * Wrote it.
  2826. \**************************************************************************/
  2827. VOID
  2828. vDdUpdateMipMapCount(
  2829. EDD_SURFACE* peSurface
  2830. )
  2831. {
  2832. EDD_SURFACE* peSurfaceParent;
  2833. DWORD dwLevels;
  2834. DD_ASSERTDEVLOCK(peSurface->peDirectDrawGlobal);
  2835. // Find the top most level mip-map in the chain:
  2836. peSurfaceParent = peSurface;
  2837. while (peSurfaceParent != NULL)
  2838. {
  2839. peSurface = peSurfaceParent;
  2840. peSurfaceParent = peSurfaceFindParentMipMap(peSurface);
  2841. }
  2842. peSurfaceParent = peSurface;
  2843. // We have the top-most level in the mip-map chain. Now count the
  2844. // levels in the chain:
  2845. dwLevels = 0;
  2846. while (peSurface != NULL)
  2847. {
  2848. dwLevels++;
  2849. peSurface = peSurfaceFindAttachedMipMap(peSurface);
  2850. }
  2851. // Now update all the levels with their new mip-map count:
  2852. peSurface = peSurfaceParent;
  2853. while (peSurface != NULL)
  2854. {
  2855. peSurface->dwMipMapCount = dwLevels;
  2856. dwLevels--;
  2857. peSurface = peSurfaceFindAttachedMipMap(peSurface);
  2858. }
  2859. ASSERTGDI(dwLevels == 0, "Unexpected ending surface count");
  2860. }
  2861. /******************************Public*Routine******************************\
  2862. * BOOL bDdRemoveAttachedSurface
  2863. *
  2864. * Transmogrified from ddsatch.c's DeleteOneLink.
  2865. *
  2866. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  2867. * Wrote it.
  2868. \**************************************************************************/
  2869. BOOL
  2870. bDdRemoveAttachedSurface(
  2871. EDD_SURFACE* peSurface,
  2872. EDD_SURFACE* peSurfaceAttached
  2873. )
  2874. {
  2875. BOOL bRet = FALSE;
  2876. DD_ATTACHLIST* pAttachCurrent;
  2877. DD_ATTACHLIST* pAttachLast;
  2878. // See if specified surface is attached:
  2879. pAttachCurrent = peSurface->lpAttachList;
  2880. pAttachLast = NULL;
  2881. while (pAttachCurrent != NULL)
  2882. {
  2883. if (pAttachCurrent->lpAttached == peSurfaceAttached)
  2884. break;
  2885. pAttachLast = pAttachCurrent;
  2886. pAttachCurrent = pAttachCurrent->lpLink;
  2887. }
  2888. if (pAttachCurrent != NULL)
  2889. {
  2890. // Delete the attached-from link:
  2891. if (pAttachLast == NULL)
  2892. {
  2893. peSurface->lpAttachList = pAttachCurrent->lpLink;
  2894. }
  2895. else
  2896. {
  2897. pAttachLast->lpLink = pAttachCurrent->lpLink;
  2898. }
  2899. VFREEMEM(pAttachCurrent);
  2900. // Remove the attached-to link:
  2901. pAttachCurrent = peSurfaceAttached->lpAttachListFrom;
  2902. pAttachLast = NULL;
  2903. while (pAttachCurrent != NULL)
  2904. {
  2905. if (pAttachCurrent->lpAttached == peSurface)
  2906. break;
  2907. pAttachLast = pAttachCurrent;
  2908. pAttachCurrent = pAttachCurrent->lpLink;
  2909. }
  2910. // Delete the attached-to link:
  2911. if (pAttachLast == NULL)
  2912. {
  2913. peSurfaceAttached->lpAttachListFrom = pAttachCurrent->lpLink;
  2914. }
  2915. else
  2916. {
  2917. pAttachLast->lpLink = pAttachCurrent->lpLink;
  2918. }
  2919. VFREEMEM(pAttachCurrent);
  2920. bRet = TRUE;
  2921. }
  2922. return(bRet);
  2923. }
  2924. /******************************Public*Routine******************************\
  2925. * VOID vDdDeleteReferringAttachments
  2926. *
  2927. * This surface is being deleted. Remove any attachments to or from other
  2928. * surfaces.
  2929. *
  2930. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  2931. * Wrote it.
  2932. \**************************************************************************/
  2933. VOID
  2934. vDdDeleteReferringAttachments(
  2935. EDD_SURFACE* peSurface
  2936. )
  2937. {
  2938. DD_ATTACHLIST* pAttachList;
  2939. EDD_SURFACE* peSurfaceAttachedTo;
  2940. EDD_SURFACE* peSurfaceAttachedFrom;
  2941. BOOL b;
  2942. while (peSurface->lpAttachList != NULL)
  2943. {
  2944. peSurfaceAttachedTo
  2945. = pedFromLp(peSurface->lpAttachList->lpAttached);
  2946. b = bDdRemoveAttachedSurface(peSurface, peSurfaceAttachedTo);
  2947. vDdUpdateMipMapCount(peSurfaceAttachedTo);
  2948. ASSERTGDI(b, "Unexpected bDdRemoveAttachedSurface failure\n");
  2949. }
  2950. while (peSurface->lpAttachListFrom != NULL)
  2951. {
  2952. peSurfaceAttachedFrom
  2953. = pedFromLp(peSurface->lpAttachListFrom->lpAttached);
  2954. b = bDdRemoveAttachedSurface(peSurfaceAttachedFrom, peSurface);
  2955. vDdUpdateMipMapCount(peSurfaceAttachedFrom);
  2956. ASSERTGDI(b, "Unexpected bDdRemoveAttachedSurface failure\n");
  2957. }
  2958. }
  2959. /******************************Public*Routine******************************\
  2960. * void vDdReleaseVirtualMap
  2961. *
  2962. * Released the reference a surface has on a VMEMMAPPING structure
  2963. *
  2964. * 28-Oct-1998 -by- Anuj Gosalia [anujg]
  2965. * Wrote it.
  2966. \**************************************************************************/
  2967. void vDdReleaseVirtualMap(EDD_SURFACE* peSurface)
  2968. {
  2969. EDD_DIRECTDRAW_GLOBAL* peVirtualMapDdGlobal;
  2970. // Hold share to prevent video mode change.
  2971. {
  2972. EDD_SHARELOCK eShareLock(TRUE);
  2973. peVirtualMapDdGlobal = peSurface->peVirtualMapDdGlobal;
  2974. DDKHEAP(("vDdReleaseVirtualMap: peSurface=%lx, "
  2975. "peVirtualMapDdGlobal=%lx, peDirectDrawGlobal=%lx\n",
  2976. peSurface, peVirtualMapDdGlobal,
  2977. peSurface->peDirectDrawGlobal));
  2978. // See peVirtualMapDdGlobal is still present, since
  2979. // video mode change occured before locking share
  2980. // lock at above, this will be null by mode change thread.
  2981. if (peVirtualMapDdGlobal)
  2982. {
  2983. EDD_DEVLOCK eDevlock(peVirtualMapDdGlobal);
  2984. vDdUnreferenceVirtualMap(peSurface->peMap,
  2985. peVirtualMapDdGlobal,
  2986. peSurface->peDirectDrawLocal,
  2987. NtCurrentProcess(),
  2988. FALSE);
  2989. peSurface->peMap = NULL;
  2990. peSurface->peVirtualMapDdGlobal = NULL;
  2991. }
  2992. }
  2993. if (peVirtualMapDdGlobal)
  2994. {
  2995. // Decrement the the driver instance
  2996. // Note: To free the driver instance we must not be holding the devlock:
  2997. vDdDecrementReferenceCount(peVirtualMapDdGlobal);
  2998. }
  2999. }
  3000. /******************************Public*Routine******************************\
  3001. * BOOL bDdDeleteSurfaceObject
  3002. *
  3003. * Deletes and frees a kernel-mode representation of the surface.
  3004. *
  3005. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  3006. * Wrote it.
  3007. \**************************************************************************/
  3008. BOOL
  3009. bDdDeleteSurfaceObject(
  3010. HANDLE hSurface,
  3011. DWORD* pdwRet // For returning driver return code, may be NULL
  3012. )
  3013. {
  3014. BOOL bRet;
  3015. EDD_SURFACE* peSurface;
  3016. EDD_SURFACE* peTmp;
  3017. VOID* pvRemove;
  3018. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  3019. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  3020. DWORD dwRet;
  3021. bRet = FALSE;
  3022. dwRet = DDHAL_DRIVER_NOTHANDLED;
  3023. peSurface = (EDD_SURFACE*) DdHmgLock((HDD_OBJ) hSurface, DD_SURFACE_TYPE, FALSE);
  3024. if (peSurface != NULL)
  3025. {
  3026. PDEVOBJ poSurface;
  3027. PDEVOBJ poMapping;
  3028. BOOL bUnrefMappingPdev = FALSE;
  3029. peDirectDrawLocal = peSurface->peDirectDrawLocal;
  3030. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  3031. {
  3032. EDD_SHAREDEVLOCK eDevLock(peDirectDrawGlobal);
  3033. // Prevent from deleting GDI's PDEV if this is last Virtual map refer it.
  3034. // We still need GDI's PDEV in order to call driver just below. so we
  3035. // -UN-reference it after we finish with driver.
  3036. poSurface.vInit(peDirectDrawGlobal->hdev);
  3037. poSurface.vReferencePdev();
  3038. // If we have "aliased" video memory mapping, take ref count on the owner
  3039. // of its mapping if it's different from current surface owner (due to video
  3040. // mode change)
  3041. if (peSurface->peMap)
  3042. {
  3043. // PDEVOBJ for owner of mapping
  3044. poMapping.vInit(peSurface->peVirtualMapDdGlobal->hdev);
  3045. // Is it different from current surface owner ?
  3046. if (poMapping.bValid() &&
  3047. (poMapping.hdev() != poSurface.hdev()))
  3048. {
  3049. poMapping.vReferencePdev();
  3050. bUnrefMappingPdev = TRUE;
  3051. }
  3052. }
  3053. // Note that 'bDdReleaseDC' and 'bDeleteSurface' may fail if
  3054. // another thread of the application is in the kernel using that
  3055. // DC. This can occur only if we're not currently doing the
  3056. // process cleanup code (because process cleanup ensures that
  3057. // only one thread from the process is still running). It's okay,
  3058. // because process-termination cleanup for the DC object itself
  3059. // will take care of cleanup.
  3060. if (peSurface->hdc)
  3061. {
  3062. // Note that any locks on behalf of the GetDC are taken care
  3063. // of in 'vDdDisableSurfaceObject'.
  3064. if (!bDdReleaseDC(peSurface, TRUE))
  3065. {
  3066. WARNING("bDdDeleteSurfaceObject: Couldn't release DC\n");
  3067. }
  3068. }
  3069. if (peSurface->hbmGdi)
  3070. {
  3071. // Delete the actual bitmap surface. We are doing this from
  3072. // the owning processes thread.
  3073. DxEngDeleteSurface((HSURF) peSurface->hbmGdi);
  3074. peSurface->hbmGdi = NULL;
  3075. if (peSurface->hpalGdi)
  3076. {
  3077. EngDeletePalette(peSurface->hpalGdi);
  3078. peSurface->hpalGdi = NULL;
  3079. }
  3080. }
  3081. DDKSURF(("DDKSURF: Removing %X (%X)\n", hSurface, peSurface));
  3082. pvRemove = DdHmgRemoveObject((HDD_OBJ) hSurface,
  3083. DdHmgQueryLock((HDD_OBJ) hSurface),
  3084. 0,
  3085. TRUE,
  3086. DD_SURFACE_TYPE);
  3087. ASSERTGDI(pvRemove != NULL, "Outstanding surfaces locks");
  3088. // Remove any attachments:
  3089. vDdDeleteReferringAttachments(peSurface);
  3090. // Uncompleted surfaces are marked as 'lost' until they're completed,
  3091. // but we still have to call the driver if that's the case:
  3092. if (!(peSurface->bLost) ||
  3093. !(peSurface->fl & DD_SURFACE_FLAG_CREATE_COMPLETE))
  3094. {
  3095. vDdDisableSurfaceObject(peDirectDrawGlobal, peSurface, &dwRet);
  3096. }
  3097. if (peSurface->peMap)
  3098. {
  3099. vDdReleaseVirtualMap(peSurface);
  3100. }
  3101. // Remove from the surface linked-list:
  3102. RemoveEntryList(&(peSurface->List_eSurface));
  3103. // Decrement number of surface in DirectDrawLocal.
  3104. peDirectDrawLocal->cSurface--;
  3105. // The surface object is about to be freed, call CreateSurfaceEx, to
  3106. // inform the driver to disassociate the cookie if the driver can
  3107. if ((peDirectDrawGlobal->Miscellaneous2CallBacks.CreateSurfaceEx)
  3108. && (peSurface->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  3109. && (peSurface->pGraphicsDeviceCreator == poSurface.pGraphicsDevice())
  3110. && (0 != peSurface->dwSurfaceHandle)
  3111. )
  3112. {
  3113. DD_CREATESURFACEEXDATA CreateSurfaceExData;
  3114. ASSERTGDI(NULL==peSurface->hSecure,
  3115. "bDdDeleteSurfaceObject: SYSMEM object not unsecured upon delete");
  3116. peSurface->fpVidMem = NULL;
  3117. CreateSurfaceExData.ddRVal = DDERR_GENERIC;
  3118. CreateSurfaceExData.dwFlags = 0;
  3119. CreateSurfaceExData.lpDDLcl = peDirectDrawLocal;
  3120. CreateSurfaceExData.lpDDSLcl = peSurface;
  3121. // just notify driver that this system memory surface has been freed
  3122. peDirectDrawGlobal->Miscellaneous2CallBacks.CreateSurfaceEx(&CreateSurfaceExData);
  3123. }
  3124. // If the surface has some outstanding system memory that needs
  3125. // to be freed, now's the time to do it.
  3126. if (peSurface->fl & DD_SURFACE_FLAG_DEFER_USERMEM)
  3127. {
  3128. DD_USERMEM_DEFER* pDefer = peDirectDrawGlobal->pUserMemDefer;
  3129. DD_USERMEM_DEFER* pLast = NULL;
  3130. DD_USERMEM_DEFER* pDeferTemp;
  3131. while (pDefer != NULL)
  3132. {
  3133. pDeferTemp = pDefer;
  3134. pDefer = pDefer->pNext;
  3135. if (pDeferTemp->peSurface == peSurface)
  3136. {
  3137. SafeFreeUserMem(pDeferTemp->pUserMem, peDirectDrawLocal->Process);
  3138. if (pLast == NULL)
  3139. {
  3140. peDirectDrawGlobal->pUserMemDefer = pDefer;
  3141. }
  3142. else
  3143. {
  3144. pLast->pNext = pDefer;
  3145. }
  3146. VFREEMEM(pDeferTemp);
  3147. }
  3148. else
  3149. {
  3150. pLast = pDeferTemp;
  3151. }
  3152. }
  3153. }
  3154. // We're all done with this object, so free the memory and
  3155. // leave:
  3156. DdFreeObject(peSurface, DD_SURFACE_TYPE);
  3157. }
  3158. // Now, we've done. release GDI's PDEV if this is last one.
  3159. if (bUnrefMappingPdev)
  3160. {
  3161. poMapping.vUnreferencePdev();
  3162. }
  3163. poSurface.vUnreferencePdev();
  3164. bRet = TRUE;
  3165. }
  3166. else
  3167. {
  3168. WARNING1("bDdDeleteSurfaceObject: Bad handle or object was busy\n");
  3169. }
  3170. if (pdwRet != NULL)
  3171. {
  3172. *pdwRet = dwRet;
  3173. }
  3174. return(bRet);
  3175. }
  3176. /******************************Public*Routine******************************\
  3177. * VOID vDdDisableAllDirectDrawObjects
  3178. *
  3179. * Temporarily disables all DirectDraw surfaces and local objects.
  3180. *
  3181. * NOTE: Caller must be holding User critical section.
  3182. *
  3183. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  3184. * Wrote it.
  3185. \**************************************************************************/
  3186. VOID
  3187. vDdDisableAllDirectDrawObjects(
  3188. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal
  3189. )
  3190. {
  3191. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  3192. EDD_DXDIRECTDRAW* peDxDirectDraw;
  3193. EDD_SURFACE* peSurface;
  3194. NTSTATUS status;
  3195. DD_ASSERTSHAREDEVLOCK();
  3196. DD_ASSERTDEVLOCK(peDirectDrawGlobal);
  3197. PDEVOBJ po(peDirectDrawGlobal->hdev);
  3198. // We may have to wait the standard 7 seconds for any locks to be
  3199. // released before we go ahead and let the mode change happen. We
  3200. // do this only when cDirectDrawDisableLocks() == 1 to allow the
  3201. // HDEV to be disabled recursively (i.e., this routine is re-entrant).
  3202. peDirectDrawGlobal->bSuspended = TRUE;
  3203. if (peDirectDrawGlobal->cSurfaceLocks >
  3204. peDirectDrawGlobal->cSurfaceAliasedLocks)
  3205. {
  3206. // Release the devlock while waiting on the event:
  3207. DxEngUnlockHdev(po.hdev());
  3208. status = KeWaitForSingleObject(peDirectDrawGlobal->pAssertModeEvent,
  3209. Executive,
  3210. KernelMode,
  3211. FALSE,
  3212. (LARGE_INTEGER*) &peDirectDrawGlobal->
  3213. llAssertModeTimeout);
  3214. ASSERTGDI(NT_SUCCESS(status), "Wait error\n");
  3215. DxEngLockHdev(po.hdev());
  3216. // Now that we have the devlock, reset the event to not-signaled
  3217. // for the next time we have to wait on someone's DirectDraw Lock
  3218. // (someone may have signaled the event after the time-out, but
  3219. // before we managed to acquire the devlock):
  3220. KeResetEvent(peDirectDrawGlobal->pAssertModeEvent);
  3221. }
  3222. // Mark all surfaces associated with this device as lost and unmap all
  3223. // views of the frame buffer:
  3224. for (peDirectDrawLocal = peDirectDrawGlobal->peDirectDrawLocalList;
  3225. peDirectDrawLocal != NULL;
  3226. peDirectDrawLocal = peDirectDrawLocal->peDirectDrawLocalNext)
  3227. {
  3228. peSurface = peDirectDrawLocal->peSurface_Enum(NULL);
  3229. while (peSurface)
  3230. {
  3231. if (!(peSurface->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY))
  3232. {
  3233. // Lost video memory surface.
  3234. if((peSurface->dwFlags & DDRAWISURF_DRIVERMANAGED) &&
  3235. !(peSurface->ddsCapsEx.dwCaps2 & DDSCAPS2_DONOTPERSIST))
  3236. {
  3237. vDdLooseManagedSurfaceObject(peDirectDrawGlobal,
  3238. peSurface,
  3239. NULL);
  3240. }
  3241. else
  3242. {
  3243. vDdDisableSurfaceObject(peDirectDrawGlobal,
  3244. peSurface,
  3245. NULL);
  3246. }
  3247. }
  3248. else if ((peDirectDrawGlobal->Miscellaneous2CallBacks.CreateSurfaceEx)
  3249. && (peSurface->pGraphicsDeviceCreator == po.pGraphicsDevice())
  3250. && (0 != peSurface->dwSurfaceHandle))
  3251. {
  3252. // Disassociate this system memory surface from driver.
  3253. DD_CREATESURFACEEXDATA CreateSurfaceExData;
  3254. FLATPTR fpVidMem = peSurface->fpVidMem; // keep backup
  3255. PDD_ATTACHLIST lpAttachList = peSurface->lpAttachList; // keep backup
  3256. PDD_ATTACHLIST lpAttachListFrom = peSurface->lpAttachListFrom; // keep backup
  3257. peSurface->fpVidMem = NULL;
  3258. peSurface->lpAttachList = NULL;
  3259. peSurface->lpAttachListFrom = NULL;
  3260. CreateSurfaceExData.ddRVal = DDERR_GENERIC;
  3261. CreateSurfaceExData.dwFlags = 0;
  3262. CreateSurfaceExData.lpDDLcl = peDirectDrawLocal;
  3263. CreateSurfaceExData.lpDDSLcl = peSurface;
  3264. peDirectDrawGlobal->Miscellaneous2CallBacks.CreateSurfaceEx(&CreateSurfaceExData);
  3265. peSurface->fpVidMem = fpVidMem; // restore backup
  3266. peSurface->lpAttachList = lpAttachList; // restore backup
  3267. peSurface->lpAttachListFrom = lpAttachListFrom; // restore backup
  3268. // workaround for smidisp.dll and just in case driver didn't clear-out dwReserved1
  3269. if (((DD_SURFACE_GLOBAL *)peSurface)->dwReserved1)
  3270. {
  3271. WARNING("Driver forget to clear SURFACE_GBL.dwReserved1 at CreateSurfaceEx()");
  3272. }
  3273. if (((DD_SURFACE_LOCAL *)peSurface)->dwReserved1)
  3274. {
  3275. WARNING("Driver forget to clear SURFACE_LCL.dwReserved1 at CreateSurfaceEx()");
  3276. }
  3277. ((DD_SURFACE_GLOBAL *)peSurface)->dwReserved1 = 0;
  3278. ((DD_SURFACE_LOCAL *)peSurface)->dwReserved1 = 0;
  3279. }
  3280. peSurface = peDirectDrawLocal->peSurface_Enum(peSurface);
  3281. }
  3282. vDdDisableDirectDrawObject(peDirectDrawLocal);
  3283. }
  3284. ASSERTGDI(peDirectDrawGlobal->cSurfaceLocks == 0,
  3285. "There was a mismatch between global count of locks and actual");
  3286. }
  3287. /******************************Public*Routine******************************\
  3288. * BOOL DxDdGetDirectDrawBounds
  3289. *
  3290. * Gets the accumulated blt access rectangle to the primary surface. Returns
  3291. * FALSE if a DirectDraw blt to the primary has not occurred.
  3292. *
  3293. * 4-Nov-1998 -by- John Stephens [johnstep]
  3294. * Wrote it.
  3295. \**************************************************************************/
  3296. BOOL
  3297. DxDdGetDirectDrawBounds(
  3298. HDEV hdev,
  3299. RECT* prcBounds
  3300. )
  3301. {
  3302. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  3303. PDEVOBJ po(hdev);
  3304. peDirectDrawGlobal = po.peDirectDrawGlobal();
  3305. DD_ASSERTDEVLOCK(peDirectDrawGlobal);
  3306. if (peDirectDrawGlobal->fl & DD_GLOBAL_FLAG_BOUNDS_SET)
  3307. {
  3308. // Return the bounds rectangle and reset the bounds flag:
  3309. *((RECTL*) prcBounds) = peDirectDrawGlobal->rclBounds;
  3310. peDirectDrawGlobal->fl &= ~DD_GLOBAL_FLAG_BOUNDS_SET;
  3311. return TRUE;
  3312. }
  3313. return FALSE;
  3314. }
  3315. /******************************Public*Routine******************************\
  3316. * VOID vDdRestoreSystemMemorySurface
  3317. *
  3318. * Reassociate dwSurfaceHandle to kernel surface by calling driver's CreateSurfaceEx
  3319. *
  3320. * 2-May-2002 -by- Hideyuki Nagase [hideyukn]
  3321. * Wrote it.
  3322. \**************************************************************************/
  3323. VOID
  3324. vDdRestoreSystemMemorySurface(
  3325. HDEV hdev
  3326. )
  3327. {
  3328. PDEVOBJ po(hdev);
  3329. EDD_DIRECTDRAW_GLOBAL *peDirectDrawGlobal = po.peDirectDrawGlobal();
  3330. // Reassociate system memory surface to driver (which disassociated by ResumeDirectDraw)
  3331. if (peDirectDrawGlobal->Miscellaneous2CallBacks.CreateSurfaceEx)
  3332. {
  3333. for (EDD_DIRECTDRAW_LOCAL *peDirectDrawLocal = peDirectDrawGlobal->peDirectDrawLocalList;
  3334. peDirectDrawLocal != NULL;
  3335. peDirectDrawLocal = peDirectDrawLocal->peDirectDrawLocalNext)
  3336. {
  3337. EDD_SURFACE *peSurface = peDirectDrawLocal->peSurface_Enum(NULL);
  3338. while (peSurface)
  3339. {
  3340. if ((peSurface->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  3341. && (peSurface->pGraphicsDeviceCreator == po.pGraphicsDevice())
  3342. && (0 != peSurface->dwSurfaceHandle)
  3343. && (peSurface->ddpfSurface.dwFlags & DDPF_FOURCC))
  3344. {
  3345. switch (peSurface->ddpfSurface.dwFourCC)
  3346. {
  3347. case FOURCC_DXT1:
  3348. case FOURCC_DXT2:
  3349. case FOURCC_DXT3:
  3350. case FOURCC_DXT4:
  3351. case FOURCC_DXT5:
  3352. peSurface->wWidth = peSurface->wWidthOriginal;
  3353. peSurface->wHeight = peSurface->wHeightOriginal;
  3354. }
  3355. }
  3356. peSurface = peDirectDrawLocal->peSurface_Enum(peSurface);
  3357. }
  3358. KeAttachProcess(PsGetProcessPcb(peDirectDrawLocal->Process));
  3359. peSurface = peDirectDrawLocal->peSurface_Enum(NULL);
  3360. while (peSurface)
  3361. {
  3362. // Only restore when this system memory surface previously
  3363. // called to this driver and we called CreateSurfaceEx.
  3364. if ((peSurface->fl & DD_SURFACE_FLAG_SYSMEM_CREATESURFACEEX)
  3365. && (peSurface->pGraphicsDeviceCreator == po.pGraphicsDevice()))
  3366. {
  3367. DD_CREATESURFACEEXDATA CreateSurfaceExData;
  3368. ASSERTGDI(peSurface->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY,
  3369. "DXG:ResumeDirectDraw: no system memory flag");
  3370. ASSERTGDI(peSurface->dwSurfaceHandle != 0,
  3371. "DXG:ResumeDirectDraw: dwSurfaceHandle is 0");
  3372. CreateSurfaceExData.dwFlags = 0;
  3373. CreateSurfaceExData.ddRVal = DDERR_GENERIC;
  3374. CreateSurfaceExData.lpDDLcl = peDirectDrawLocal;
  3375. CreateSurfaceExData.lpDDSLcl = peSurface;
  3376. po.peDirectDrawGlobal()->Miscellaneous2CallBacks.CreateSurfaceEx(&CreateSurfaceExData);
  3377. if (CreateSurfaceExData.ddRVal != DD_OK)
  3378. {
  3379. WARNING("DxDdResumeDirectDraw(): Reassociate system memory surface failed");
  3380. }
  3381. }
  3382. peSurface = peDirectDrawLocal->peSurface_Enum(peSurface);
  3383. }
  3384. KeDetachProcess();
  3385. }
  3386. }
  3387. }
  3388. /******************************Public*Routine******************************\
  3389. * VOID DxDdSuspendDirectDraw
  3390. *
  3391. * Temporarily disables DirectDraw for the specified device.
  3392. *
  3393. * NOTE: Caller must be holding User critical section.
  3394. *
  3395. * NOTE: Caller must NOT be holding devlock, unless DirectDraw is already
  3396. * disabled.
  3397. *
  3398. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  3399. * Wrote it.
  3400. \**************************************************************************/
  3401. VOID
  3402. DxDdSuspendDirectDraw(
  3403. HDEV hdev,
  3404. ULONG fl
  3405. )
  3406. {
  3407. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  3408. LONG* pl;
  3409. HDEV hdevCurrent;
  3410. BOOL bChildren = (fl & DXG_SR_DDRAW_CHILDREN);
  3411. // Bump the mode uniqueness to let user-mode DirectDraw know that
  3412. // someone else has done a mode change. (Full-screen switches count as
  3413. // full-screen, too). Do it interlocked because we're not holding a
  3414. // global lock:
  3415. INC_DISPLAY_UNIQUENESS();
  3416. // If bChildren is TRUE, make sure we've really got a meta driver:
  3417. if (bChildren)
  3418. {
  3419. PDEVOBJ po(hdev);
  3420. ASSERTGDI(po.bValid() && po.bDisplayPDEV(), "Invalid HDEV");
  3421. bChildren = po.bMetaDriver();
  3422. }
  3423. hdevCurrent = bChildren ? DxEngEnumerateHdev(NULL) : hdev;
  3424. do
  3425. {
  3426. PDEVOBJ po(hdevCurrent);
  3427. ASSERTGDI(po.bValid(), "Invalid HDEV");
  3428. ASSERTGDI(po.bDisplayPDEV(), "Not a display HDEV");
  3429. if (!bChildren || (po.hdevParent() == hdev))
  3430. {
  3431. peDirectDrawGlobal = po.peDirectDrawGlobal();
  3432. EDD_SHARELOCK eShareLock(FALSE);
  3433. if (fl & DXG_SR_DDRAW_MODECHANGE)
  3434. {
  3435. // ShareLock must be held by caller for video mode change.
  3436. DD_ASSERTSHAREDEVLOCK();
  3437. // We need to completely release the devlock soon, so we must not
  3438. // be called with the devlock already held. If we don't do this,
  3439. // any thread calling Unlock will be locked out until the timeout.
  3440. DD_ASSERTNODEVLOCK(peDirectDrawGlobal);
  3441. }
  3442. else
  3443. {
  3444. eShareLock.vLock();
  3445. }
  3446. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  3447. ASSERTGDI(peDirectDrawGlobal->hdev != NULL,
  3448. "Can't suspend DirectDraw on an HDEV that was never DDraw enabled!");
  3449. if (po.cDirectDrawDisableLocks() == 0)
  3450. {
  3451. // Notify any kernel-mode DXAPI clients that have hooked the
  3452. // relevant event:
  3453. vDdNotifyEvent(peDirectDrawGlobal, DDEVENT_PREDOSBOX);
  3454. // Disable all DirectDraw object.
  3455. vDdDisableAllDirectDrawObjects(peDirectDrawGlobal);
  3456. }
  3457. // Increment the disable lock-count event if a DirectDraw global
  3458. // object hasn't been created:
  3459. po.cDirectDrawDisableLocks(po.cDirectDrawDisableLocks() + 1);
  3460. }
  3461. if (bChildren)
  3462. {
  3463. hdevCurrent = DxEngEnumerateHdev(hdevCurrent);
  3464. }
  3465. } while (bChildren && hdevCurrent);
  3466. }
  3467. /******************************Public*Routine******************************\
  3468. * VOID DxDdResumeDirectDraw
  3469. *
  3470. * Permits DirectDraw to be reenabled for the specified device.
  3471. *
  3472. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  3473. * Wrote it.
  3474. \**************************************************************************/
  3475. VOID
  3476. DxDdResumeDirectDraw(
  3477. HDEV hdev,
  3478. ULONG fl
  3479. )
  3480. {
  3481. LONG* pl;
  3482. HDEV hdevCurrent;
  3483. BOOL bChildren = fl & DXG_SR_DDRAW_CHILDREN;
  3484. // Bump the mode uniqueness again. We do this both before and after
  3485. // the mode change actually occurs to give DirectDraw proper
  3486. // notification. If kernel-mode starts failing DdBlt calls because
  3487. // the mode has changed, this implies that we have to let DirectDraw
  3488. // know before the mode change occurs; but if we let DirectDraw know
  3489. // only before the mode change occurs, it might re-enable us before
  3490. // the new mode is actually set, so we also have to let it know after
  3491. // the mode change has occured.
  3492. INC_DISPLAY_UNIQUENESS();
  3493. // If bChildren is TRUE, make sure we've really got a meta driver:
  3494. if (bChildren)
  3495. {
  3496. PDEVOBJ po(hdev);
  3497. ASSERTGDI(po.bValid() && po.bDisplayPDEV(), "Invalid HDEV");
  3498. bChildren = po.bMetaDriver();
  3499. }
  3500. hdevCurrent = bChildren ? DxEngEnumerateHdev(NULL) : hdev;
  3501. do
  3502. {
  3503. PDEVOBJ po(hdevCurrent);
  3504. ASSERTGDI(po.bValid(), "Invalid HDEV");
  3505. ASSERTGDI(po.bDisplayPDEV(), "Not a display HDEV");
  3506. if (!bChildren || (po.hdevParent() == hdev))
  3507. {
  3508. // Decrement the disable lock-count even if a DirectDraw global object
  3509. // hasn't been created:
  3510. EDD_DEVLOCK eDevlock(po.hdev());
  3511. ASSERTGDI(po.cDirectDrawDisableLocks() != 0,
  3512. "Must have called disable previously to be able to enable DirectDraw.");
  3513. po.cDirectDrawDisableLocks(po.cDirectDrawDisableLocks() - 1);
  3514. if (po.cDirectDrawDisableLocks() == 0)
  3515. {
  3516. // Notify any kernel-mode DXAPI clients that have hooked the relevant
  3517. // event. Note that thie mode change is done, but DirectDraw is still
  3518. // in a suspended state. [Is that a problem?]
  3519. vDdNotifyEvent(po.peDirectDrawGlobal(), DDEVENT_POSTDOSBOX);
  3520. // Reassociate system memory surface if needed.
  3521. vDdRestoreSystemMemorySurface(po.hdev());
  3522. }
  3523. }
  3524. if (bChildren)
  3525. {
  3526. hdevCurrent = DxEngEnumerateHdev(hdevCurrent);
  3527. }
  3528. } while (bChildren && hdevCurrent);
  3529. }
  3530. /******************************Public*Routine******************************\
  3531. * VOID DxDdDynamicModeChange
  3532. *
  3533. * Transfers DirectDraw driver instances between two PDEVs.
  3534. *
  3535. * The devlock and handle manager semaphore must be held to call this function!
  3536. *
  3537. * NOTE: This is the last step that should be taken in the dynamic mode
  3538. * change process, so that in this routine we can assume that the
  3539. * call tables and the like for the respective HDEVs have already
  3540. * been swapped.
  3541. *
  3542. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  3543. * Wrote it.
  3544. \**************************************************************************/
  3545. VOID
  3546. DxDdDynamicModeChange(
  3547. HDEV hdevOld,
  3548. HDEV hdevNew,
  3549. ULONG fl
  3550. )
  3551. {
  3552. DD_DIRECTDRAW_GLOBAL_DRIVER_DATA GlobalDriverDataSwap;
  3553. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobalOld;
  3554. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobalNew;
  3555. D3DNTHAL_OBJECT* pdhobj;
  3556. EDD_SURFACE* peSurface;
  3557. HDD_OBJ hobj;
  3558. LONG cReferencesOld;
  3559. LONG cReferencesNew;
  3560. LONG cAdjustOld;
  3561. LONG cAdjustNew;
  3562. FLONG flOld;
  3563. FLONG flNew;
  3564. LPDDVIDEOPORTCAPS lpDDVideoPortCaps;
  3565. DWORD dwHeap;
  3566. VIDEOMEMORY* pHeap;
  3567. DWORD dwHeapNew;
  3568. VIDEOMEMORY* pHeapNew;
  3569. BOOL bSwappedAGP;
  3570. PDEVOBJ poOld(hdevOld);
  3571. PDEVOBJ poNew(hdevNew);
  3572. peDirectDrawGlobalOld = poOld.peDirectDrawGlobal();
  3573. peDirectDrawGlobalNew = poNew.peDirectDrawGlobal();
  3574. DDKHEAP(("peDDGOld=%lx, cDriverReferences=%d\n",
  3575. peDirectDrawGlobalOld, peDirectDrawGlobalOld->cDriverReferences));
  3576. DDKHEAP(("peDDGNew=%lx, cDriverReferences=%d\n",
  3577. peDirectDrawGlobalNew, peDirectDrawGlobalNew->cDriverReferences));
  3578. // Notify any kernel-mode DXAPI clients that have hooked the relevant
  3579. // events.
  3580. vDdNotifyEvent(peDirectDrawGlobalOld, DDEVENT_PRERESCHANGE);
  3581. vDdNotifyEvent(peDirectDrawGlobalOld, DDEVENT_POSTRESCHANGE);
  3582. vDdNotifyEvent(peDirectDrawGlobalNew, DDEVENT_PRERESCHANGE);
  3583. vDdNotifyEvent(peDirectDrawGlobalNew, DDEVENT_POSTRESCHANGE);
  3584. // The DD_GLOBAL_FLAG_DRIVER_ENABLED flag transfers to the new PDEV
  3585. // along with the driver instance:
  3586. flOld = peDirectDrawGlobalOld->fl;
  3587. flNew = peDirectDrawGlobalNew->fl;
  3588. peDirectDrawGlobalOld->fl = (flOld & ~DD_GLOBAL_FLAG_DRIVER_ENABLED)
  3589. | (flNew & DD_GLOBAL_FLAG_DRIVER_ENABLED)
  3590. | (DD_GLOBAL_FLAG_MODE_CHANGED);
  3591. peDirectDrawGlobalOld->bSuspended = TRUE;
  3592. peDirectDrawGlobalOld->dhpdev = poOld.dhpdev();
  3593. peDirectDrawGlobalOld->hdev = poOld.hdev();
  3594. peDirectDrawGlobalNew->fl = (flNew & ~DD_GLOBAL_FLAG_DRIVER_ENABLED)
  3595. | (flOld & DD_GLOBAL_FLAG_DRIVER_ENABLED)
  3596. | (DD_GLOBAL_FLAG_MODE_CHANGED);
  3597. peDirectDrawGlobalNew->bSuspended = TRUE;
  3598. peDirectDrawGlobalNew->dhpdev = poNew.dhpdev();
  3599. peDirectDrawGlobalNew->hdev = poNew.hdev();
  3600. // Transfer heap AGP 'handles':
  3601. //
  3602. // since AGP handle stay with its driver instance.
  3603. pHeap = peDirectDrawGlobalOld->pvmList;
  3604. for (dwHeap = 0;
  3605. dwHeap < peDirectDrawGlobalOld->dwNumHeaps;
  3606. pHeap++, dwHeap++)
  3607. {
  3608. if (!(pHeap->dwFlags & VIDMEM_ISHEAP) &&
  3609. !(pHeap->dwFlags & VIDMEM_HEAPDISABLED) &&
  3610. (pHeap->dwFlags & VIDMEM_ISNONLOCAL) &&
  3611. (pHeap->lpHeap != NULL) &&
  3612. (pHeap->lpHeap->hdevAGP == AGP_HDEV(peDirectDrawGlobalOld)))
  3613. {
  3614. pHeap->lpHeap->hdevAGP = AGP_HDEV(peDirectDrawGlobalNew);
  3615. }
  3616. }
  3617. pHeap = peDirectDrawGlobalNew->pvmList;
  3618. for (dwHeap = 0;
  3619. dwHeap < peDirectDrawGlobalNew->dwNumHeaps;
  3620. pHeap++, dwHeap++)
  3621. {
  3622. if (!(pHeap->dwFlags & VIDMEM_ISHEAP) &&
  3623. !(pHeap->dwFlags & VIDMEM_HEAPDISABLED) &&
  3624. (pHeap->dwFlags & VIDMEM_ISNONLOCAL) &&
  3625. (pHeap->lpHeap != NULL) &&
  3626. (pHeap->lpHeap->hdevAGP == AGP_HDEV(peDirectDrawGlobalNew)))
  3627. {
  3628. pHeap->lpHeap->hdevAGP = AGP_HDEV(peDirectDrawGlobalOld);
  3629. }
  3630. }
  3631. // DirectDraw objects and surfaces stay with the PDEV, but driver
  3632. // instances are swapped:
  3633. RtlCopyMemory(&GlobalDriverDataSwap,
  3634. (DD_DIRECTDRAW_GLOBAL_DRIVER_DATA*) peDirectDrawGlobalOld,
  3635. sizeof(DD_DIRECTDRAW_GLOBAL_DRIVER_DATA));
  3636. RtlCopyMemory((DD_DIRECTDRAW_GLOBAL_DRIVER_DATA*) peDirectDrawGlobalOld,
  3637. (DD_DIRECTDRAW_GLOBAL_DRIVER_DATA*) peDirectDrawGlobalNew,
  3638. sizeof(DD_DIRECTDRAW_GLOBAL_DRIVER_DATA));
  3639. RtlCopyMemory((DD_DIRECTDRAW_GLOBAL_DRIVER_DATA*) peDirectDrawGlobalNew,
  3640. &GlobalDriverDataSwap,
  3641. sizeof(DD_DIRECTDRAW_GLOBAL_DRIVER_DATA));
  3642. // If the old object had an initialized AGP heap, make sure that it stays
  3643. // with the old object (swap it back). We only want to do this if it's
  3644. // not a one-to-many or many-to-one mode change, however.
  3645. bSwappedAGP = FALSE;
  3646. if (!poNew.bMetaDriver() &&
  3647. !poOld.bMetaDriver() &&
  3648. (poNew.pldev() == poOld.pldev()))
  3649. {
  3650. pHeap = peDirectDrawGlobalOld->pvmList;
  3651. for (dwHeap = 0;
  3652. dwHeap < peDirectDrawGlobalOld->dwNumHeaps;
  3653. pHeap++, dwHeap++)
  3654. {
  3655. if (!(pHeap->dwFlags & VIDMEM_ISHEAP) &&
  3656. !(pHeap->dwFlags & VIDMEM_HEAPDISABLED) &&
  3657. (pHeap->dwFlags & VIDMEM_ISNONLOCAL) &&
  3658. (pHeap->lpHeap != NULL) &&
  3659. (pHeap->lpHeap->pvPhysRsrv == NULL))
  3660. {
  3661. // The old object has a heap, find the corresponding heap in the
  3662. // new object.
  3663. pHeapNew = peDirectDrawGlobalNew->pvmList;
  3664. for (dwHeapNew = 0;
  3665. dwHeapNew < peDirectDrawGlobalNew->dwNumHeaps;
  3666. pHeapNew++, dwHeapNew++)
  3667. {
  3668. if ((pHeapNew->dwFlags == pHeap->dwFlags) &&
  3669. (pHeapNew->lpHeap != NULL) &&
  3670. (pHeapNew->lpHeap->pvPhysRsrv != NULL))
  3671. {
  3672. SwapHeaps( pHeap, pHeapNew );
  3673. // We used to tear down the heap and create a new one
  3674. // with each mode change, but now we keep the one heap
  3675. // active acrross mode changes. This means that we don't
  3676. // need to notify the driver the driver of the heap change,
  3677. // but this is a behavior change and some drivers depend
  3678. // on this notification so we'll do it anyway.
  3679. UpdateNonLocalHeap( peDirectDrawGlobalOld, dwHeap );
  3680. bSwappedAGP = TRUE;
  3681. }
  3682. }
  3683. }
  3684. }
  3685. }
  3686. // Also swap video port caps, which are part of the DIRETCDRAW_GLOBAL
  3687. lpDDVideoPortCaps = peDirectDrawGlobalOld->lpDDVideoPortCaps;
  3688. peDirectDrawGlobalOld->lpDDVideoPortCaps = peDirectDrawGlobalNew->lpDDVideoPortCaps;
  3689. peDirectDrawGlobalNew->lpDDVideoPortCaps = lpDDVideoPortCaps;
  3690. cReferencesNew = 0;
  3691. cReferencesOld = 0;
  3692. cAdjustNew = 0;
  3693. cAdjustOld = 0;
  3694. // Transfer ownership of any Direct3D objects to its new PDEV:
  3695. //
  3696. // since it stay with its driver instance.
  3697. DdHmgAcquireHmgrSemaphore();
  3698. hobj = 0;
  3699. while (pdhobj = (D3DNTHAL_OBJECT*) DdHmgNextObjt(hobj, D3D_HANDLE_TYPE))
  3700. {
  3701. hobj = (HDD_OBJ) pdhobj->hGet();
  3702. if (pdhobj->peDdGlobal == peDirectDrawGlobalOld)
  3703. {
  3704. pdhobj->peDdGlobal = peDirectDrawGlobalNew;
  3705. cReferencesNew++;
  3706. }
  3707. else if (pdhobj->peDdGlobal == peDirectDrawGlobalNew)
  3708. {
  3709. pdhobj->peDdGlobal = peDirectDrawGlobalOld;
  3710. cReferencesOld++;
  3711. }
  3712. }
  3713. hobj = 0;
  3714. while (peSurface = (EDD_SURFACE*) DdHmgNextObjt(hobj, DD_SURFACE_TYPE))
  3715. {
  3716. hobj = (HDD_OBJ) peSurface->hGet();
  3717. // Transfer VMEMMAPPING structures
  3718. //
  3719. // since it stay with its driver instance. We do not switch these
  3720. // for AGP surfaces since we no longer switch the AGP heaps.
  3721. if (peSurface->peVirtualMapDdGlobal == peDirectDrawGlobalOld)
  3722. {
  3723. DDKHEAP(("vDdDynamicModeChange: %x->%x matches old global\n",
  3724. peSurface, peSurface->peVirtualMapDdGlobal));
  3725. if ((peSurface->peMap != NULL) &&
  3726. (peSurface->peMap->fl & DD_VMEMMAPPING_FLAG_AGP) &&
  3727. bSwappedAGP)
  3728. {
  3729. cAdjustOld++;
  3730. }
  3731. else
  3732. {
  3733. peSurface->peVirtualMapDdGlobal = peDirectDrawGlobalNew;
  3734. cReferencesNew++;
  3735. }
  3736. }
  3737. else if (peSurface->peVirtualMapDdGlobal == peDirectDrawGlobalNew)
  3738. {
  3739. DDKHEAP(("vDdDynamicModeChange: %x->%x matches new global\n",
  3740. peSurface, peSurface->peVirtualMapDdGlobal));
  3741. if ((peSurface->peMap != NULL) &&
  3742. (peSurface->peMap->fl & DD_VMEMMAPPING_FLAG_AGP) &&
  3743. bSwappedAGP)
  3744. {
  3745. cAdjustNew++;
  3746. }
  3747. else
  3748. {
  3749. peSurface->peVirtualMapDdGlobal = peDirectDrawGlobalOld;
  3750. cReferencesOld++;
  3751. }
  3752. }
  3753. // If surface is "driver managed"...
  3754. //
  3755. // driver managed surface will stay with its driver instance.
  3756. if (peSurface->dwFlags & DDRAWISURF_DRIVERMANAGED)
  3757. {
  3758. // And if we are doing mode change across "different" video drivers
  3759. // mark wrong driver flag while it live in there until go back
  3760. // to original creator driver.
  3761. //
  3762. // And peDdGlobalCreator should go with driver instance.
  3763. // If video mode change happen with same driver, surface with just stay where it is.
  3764. if (poOld.pldev() == poNew.pldev())
  3765. {
  3766. // Driver reference has been swapped, but this surface will continue to
  3767. // stick with same, so need adjust it (= transfer back).
  3768. if (peSurface->peDdGlobalCreator == peDirectDrawGlobalOld)
  3769. {
  3770. if (!(peSurface->bLost))
  3771. {
  3772. cAdjustOld++;
  3773. }
  3774. #if DBG_HIDEYUKN
  3775. KdPrint(("DXG: same pldev, stay with old\n"));
  3776. #endif
  3777. }
  3778. else if (peSurface->peDdGlobalCreator == peDirectDrawGlobalNew)
  3779. {
  3780. if (!(peSurface->bLost))
  3781. {
  3782. cAdjustNew++;
  3783. }
  3784. #if DBG_HIDEYUKN
  3785. KdPrint(("DXG: same pldev, stay with new\n"));
  3786. #endif
  3787. }
  3788. }
  3789. else // if (poOld.pldev() != poNew.poNew())
  3790. {
  3791. if (peSurface->peDdGlobalCreator == peDirectDrawGlobalOld)
  3792. {
  3793. // This surface is currently associated to old driver
  3794. // (= where actually will be new after swap)
  3795. // Transfer the surface to new (where it will be Old).
  3796. peSurface->peDdGlobalCreator = peDirectDrawGlobalNew;
  3797. if (peSurface->peDdGlobalCreator == peSurface->peDirectDrawGlobal)
  3798. {
  3799. peSurface->fl &= ~DD_SURFACE_FLAG_WRONG_DRIVER;
  3800. #if DBG_HIDEYUKN
  3801. KdPrint(("DXG: diff pldev, move to new, clear wrong driver\n"));
  3802. #endif
  3803. }
  3804. else
  3805. {
  3806. peSurface->fl |= DD_SURFACE_FLAG_WRONG_DRIVER;
  3807. #if DBG_HIDEYUKN
  3808. KdPrint(("DXG: diff pldev, move to new, set wrong driver\n"));
  3809. #endif
  3810. }
  3811. // Driver reference count has been swapped already in above. so new DdGlobal
  3812. // already has reference for this surface. Increment this for later verification.
  3813. if (!(peSurface->bLost))
  3814. {
  3815. cReferencesNew++;
  3816. }
  3817. }
  3818. else if (peSurface->peDdGlobalCreator == peDirectDrawGlobalNew)
  3819. {
  3820. // This surface is currently associated to new (where it will be old after swap)
  3821. // Transfer the surface to old (where it will be new).
  3822. peSurface->peDdGlobalCreator = peDirectDrawGlobalOld;
  3823. if (peSurface->peDdGlobalCreator == peSurface->peDirectDrawGlobal)
  3824. {
  3825. peSurface->fl &= ~DD_SURFACE_FLAG_WRONG_DRIVER;
  3826. #if DBG_HIDEYUKN
  3827. KdPrint(("DXG: diff pldev, move to old, clear wrong driver\n"));
  3828. #endif
  3829. }
  3830. else
  3831. {
  3832. peSurface->fl |= DD_SURFACE_FLAG_WRONG_DRIVER;
  3833. #if DBG_HIDEYUKN
  3834. KdPrint(("DXG: diff pldev, move to old, set wrong driver\n"));
  3835. #endif
  3836. }
  3837. // if surface is not losted, make sure reference is stay with old driver
  3838. // (this is for later assertion).
  3839. if (!(peSurface->bLost))
  3840. {
  3841. cReferencesOld++;
  3842. }
  3843. }
  3844. }
  3845. }
  3846. }
  3847. DdHmgReleaseHmgrSemaphore();
  3848. #if DBG_HIDEYUKN
  3849. KdPrint(("DXG:Reference Counts BEFORE Adjust\n"));
  3850. KdPrint(("DXG:DdGlobalOld->cDriverReference (%d) = cReferencesOld (%d) + cAdjustNew (%d)\n",
  3851. peDirectDrawGlobalOld->cDriverReferences,cReferencesOld,cAdjustNew));
  3852. KdPrint(("DXG:DdGlobalNew->cDriverReference (%d) = cReferencesNew (%d) + cAdjustOld (%d)\n",
  3853. peDirectDrawGlobalNew->cDriverReferences,cReferencesNew,cAdjustOld));
  3854. #endif
  3855. // We used to transfer all of the surfaces from the old PDEV to the new
  3856. // one, but now we only do that for the non-agp surfaces, which means that
  3857. // we need to adjust the cDriverReferences accordingly.
  3858. ASSERTGDI(cReferencesOld + cAdjustNew == peDirectDrawGlobalOld->cDriverReferences,
  3859. "Mis-match in old D3D driver references");
  3860. ASSERTGDI(cReferencesNew + cAdjustOld == peDirectDrawGlobalNew->cDriverReferences,
  3861. "Mis-match in new D3D driver references");
  3862. // Transfer the PDEV references:
  3863. //
  3864. // I'm going to try to explain this. DXG keeps a single ref count on each
  3865. // PDEV that either has a surface or a context associated with it, so on
  3866. // entering this funtion, we have a single ref count on the old PDEV.
  3867. // If we transfer all of the surfaces to the new PDEV, then we can decrement
  3868. // from the ref from the old PDEV and add on to the new PDEV. If some of the
  3869. // surfaces continue with the old PDEV, however, then we need to make sure
  3870. // that we keep ref on that PDEV as well.
  3871. peDirectDrawGlobalNew->cDriverReferences -= cAdjustOld;
  3872. peDirectDrawGlobalNew->cDriverReferences += cAdjustNew;
  3873. peDirectDrawGlobalOld->cDriverReferences -= cAdjustNew;
  3874. peDirectDrawGlobalOld->cDriverReferences += cAdjustOld;
  3875. #if DBG_HIDEYUKN
  3876. KdPrint(("DXG:Reference Counts AFTER Adjust\n"));
  3877. KdPrint(("DXG:DdGlobalOld->cDriverReferences = %d\n",peDirectDrawGlobalOld->cDriverReferences));
  3878. KdPrint(("DXG:DdGlobalNew->cDriverReferences = %d\n",peDirectDrawGlobalNew->cDriverReferences));
  3879. #endif
  3880. if (cReferencesNew || cAdjustOld)
  3881. {
  3882. // The old PDEV had references on it
  3883. if (peDirectDrawGlobalOld->cDriverReferences == 0)
  3884. {
  3885. //but it doesn't now, so remove it
  3886. poOld.vUnreferencePdev();
  3887. }
  3888. }
  3889. else
  3890. {
  3891. // The old PDEV did not have refernces on it
  3892. if (peDirectDrawGlobalOld->cDriverReferences > 0)
  3893. {
  3894. // but it does not, so add it
  3895. poOld.vReferencePdev();
  3896. }
  3897. }
  3898. if (cReferencesOld || cAdjustNew)
  3899. {
  3900. // The new PDEV had references on it
  3901. if (peDirectDrawGlobalNew->cDriverReferences == 0)
  3902. {
  3903. // but it doesn't now, so remove it
  3904. poNew.vUnreferencePdev();
  3905. }
  3906. }
  3907. else
  3908. {
  3909. // The new PDEV did not have references on it
  3910. if (peDirectDrawGlobalNew->cDriverReferences > 0)
  3911. {
  3912. // but it does now, so add it
  3913. poNew.vReferencePdev();
  3914. }
  3915. }
  3916. // Move DirectDraw lock count.
  3917. //
  3918. // - this point, the disabled flag has *NOT* been swapped YET, so
  3919. // we need to move the lock count to where it *will be* disabled "after this call"
  3920. // not the device currently disabled.
  3921. //
  3922. // So if poNew is disabled at here, GDI will make poOld disabled (after this call),
  3923. // thus transfer disabled lock to poOld.
  3924. if (!poNew.bMetaDriver() && !poOld.bMetaDriver())
  3925. {
  3926. // Mode change between display drivers.
  3927. if (poNew.bDisabled())
  3928. {
  3929. // These asserts make sure that nothing happens other than cLock count adjustment
  3930. ASSERTGDI(poOld.cDirectDrawDisableLocks() >= 1,"Old PDEV cDirectDrawLocks <= 0");
  3931. ASSERTGDI(poNew.cDirectDrawDisableLocks() >= 2,"New PDEV cDirectDrawLocks <= 1");
  3932. poOld.cDirectDrawDisableLocks(poOld.cDirectDrawDisableLocks() + 1);
  3933. poNew.cDirectDrawDisableLocks(poNew.cDirectDrawDisableLocks() - 1);
  3934. }
  3935. if (poOld.bDisabled())
  3936. {
  3937. // These asserts make sure that nothing happens other than cLock count adjustment
  3938. ASSERTGDI(poNew.cDirectDrawDisableLocks() >= 1,"New PDEV cDirectDrawLocks <= 0");
  3939. ASSERTGDI(poOld.cDirectDrawDisableLocks() >= 2,"Old PDEV cDirectDrawLocks <= 1");
  3940. poNew.cDirectDrawDisableLocks(poNew.cDirectDrawDisableLocks() + 1);
  3941. poOld.cDirectDrawDisableLocks(poOld.cDirectDrawDisableLocks() - 1);
  3942. }
  3943. }
  3944. else if (poNew.bMetaDriver() && poOld.bMetaDriver())
  3945. {
  3946. // Mode change between DDMLs, nothing need to do.
  3947. // Because the hdev for Meta driver is ALWAYS created newly, never reused.
  3948. // (see gre\drvsup\hCreateHDEV()).
  3949. }
  3950. else if (poOld.bMetaDriver() || poNew.bMetaDriver())
  3951. {
  3952. // Since at this point, the meta driver flag has been swapped.
  3953. //
  3954. // - when poOld is meta, we are doing 1 -> 2 mode change.
  3955. // - when poNew is meta, we are doing 2 -> 1 mode change.
  3956. if (poNew.bDisabled())
  3957. {
  3958. // These asserts make sure that nothing happens other than cLock count adjustment
  3959. //
  3960. // ASSERTGDI(poOld.cDirectDrawDisableLocks() >= 1,"A: Old PDEV cDirectDrawLocks <= 0");
  3961. // ASSERTGDI(poNew.cDirectDrawDisableLocks() >= 2,"B: New PDEV cDirectDrawLocks <= 1");
  3962. poOld.cDirectDrawDisableLocks(poOld.cDirectDrawDisableLocks() + 1);
  3963. poNew.cDirectDrawDisableLocks(poNew.cDirectDrawDisableLocks() - 1);
  3964. }
  3965. if (poOld.bDisabled())
  3966. {
  3967. // These asserts make sure that nothing happens other than cLock count adjustment
  3968. //
  3969. // ASSERTGDI(poNew.cDirectDrawDisableLocks() >= 1,"C: New PDEV cDirectDrawLocks <= 0");
  3970. // ASSERTGDI(poOld.cDirectDrawDisableLocks() >= 2,"D: Old PDEV cDirectDrawLocks <= 1");
  3971. poNew.cDirectDrawDisableLocks(poNew.cDirectDrawDisableLocks() + 1);
  3972. poOld.cDirectDrawDisableLocks(poOld.cDirectDrawDisableLocks() - 1);
  3973. }
  3974. }
  3975. }
  3976. /******************************Public*Routine******************************\
  3977. * VOID vDdMapMemory
  3978. *
  3979. * Creates a user-mode mapping of the device's entire frame buffer in the
  3980. * current process.
  3981. *
  3982. * The devlock must be held to call this function.
  3983. *
  3984. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  3985. * Wrote it.
  3986. \**************************************************************************/
  3987. VOID vDdMapMemory(
  3988. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal,
  3989. HRESULT* pResult
  3990. )
  3991. {
  3992. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  3993. DWORD dwRet;
  3994. DD_MAPMEMORYDATA MapMemoryData;
  3995. SIZE_T CommitSize;
  3996. HANDLE pSection;
  3997. HANDLE SectionHandle;
  3998. NTSTATUS Status;
  3999. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  4000. if (!(peDirectDrawGlobal->CallBacks.dwFlags & DDHAL_CB32_MAPMEMORY))
  4001. {
  4002. peDirectDrawLocal->fl |= DD_LOCAL_FLAG_MEMORY_MAPPED;
  4003. peDirectDrawGlobal->cMaps++;
  4004. }
  4005. else
  4006. {
  4007. MapMemoryData.lpDD = peDirectDrawGlobal;
  4008. MapMemoryData.bMap = TRUE;
  4009. MapMemoryData.hProcess = NtCurrentProcess();
  4010. MapMemoryData.fpProcess = NULL;
  4011. dwRet = peDirectDrawGlobal->CallBacks.MapMemory(&MapMemoryData);
  4012. *pResult = MapMemoryData.ddRVal;
  4013. if (*pResult == DD_OK)
  4014. {
  4015. // Allocate new EDD_VMEMMAPPING object
  4016. peDirectDrawLocal->peMapCurrent = (EDD_VMEMMAPPING*)
  4017. PALLOCMEM(sizeof(EDD_VMEMMAPPING), ' ddG');
  4018. if (peDirectDrawLocal->peMapCurrent)
  4019. {
  4020. peDirectDrawLocal->peMapCurrent->fpProcess =
  4021. MapMemoryData.fpProcess;
  4022. peDirectDrawLocal->peMapCurrent->cReferences = 1;
  4023. peDirectDrawLocal->fpProcess = MapMemoryData.fpProcess;
  4024. peDirectDrawLocal->fl |= DD_LOCAL_FLAG_MEMORY_MAPPED;
  4025. peDirectDrawGlobal->cMaps++;
  4026. ASSERTGDI(peDirectDrawLocal->fpProcess != 0,
  4027. "Expected non-NULL fpProcess value from MapMemory");
  4028. ASSERTGDI((ULONG) peDirectDrawLocal->fpProcess
  4029. < MM_USER_PROBE_ADDRESS,
  4030. "Expected user-mode fpProcess value from MapMemory");
  4031. }
  4032. else
  4033. {
  4034. WARNING("vDdMapMemory: "
  4035. "Could not allocate memory for peMapCurrent\n");
  4036. // Clean up the driver mapping since we are failing vDdMapMemory call!
  4037. MapMemoryData.lpDD = peDirectDrawGlobal;
  4038. MapMemoryData.bMap = FALSE;
  4039. MapMemoryData.hProcess = NtCurrentProcess();
  4040. // Keep fpProcess as what driver returned at above call.
  4041. //
  4042. // MapMemoryData.fpProcess = MapMemoryData.fpProcess;
  4043. // Don't really care if this succeeds. It's bad news anyway
  4044. peDirectDrawGlobal->CallBacks.MapMemory(&MapMemoryData);
  4045. return;
  4046. }
  4047. }
  4048. else
  4049. {
  4050. WARNING("vDdMapMemory: Driver failed DdMapMemory\n");
  4051. }
  4052. }
  4053. }
  4054. /******************************Public*Routine******************************\
  4055. * VOID pDdLockSurfaceOrBuffer
  4056. *
  4057. * Returns a user-mode pointer to the surface or D3D buffer.
  4058. *
  4059. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  4060. * Wrote it.
  4061. \**************************************************************************/
  4062. VOID*
  4063. pDdLockSurfaceOrBuffer(
  4064. EDD_SURFACE* peSurface,
  4065. BOOL bHasRect,
  4066. RECTL* pArea,
  4067. DWORD dwFlags, // DDLOCK_WAIT, DDLOCK_NOSYSLOCK
  4068. HRESULT* pResult // ddRVal result of call (may be NULL)
  4069. )
  4070. {
  4071. VOID* pvRet;
  4072. DD_LOCKDATA LockData;
  4073. DD_UNLOCKDATA UnlockData;
  4074. EDD_DIRECTDRAW_GLOBAL* peDdGlobalDriver;
  4075. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  4076. DWORD dwTmp;
  4077. DWORD dwRedraw;
  4078. PDD_SURFCB_LOCK pfnLock;
  4079. pvRet = NULL;
  4080. LockData.ddRVal = DDERR_GENERIC;
  4081. peDirectDrawLocal = peSurface->peDirectDrawLocal;
  4082. // Due to video mode change across different video driver, currently
  4083. // this "driver managed" surface is associated to different driver
  4084. // than the driver who actually manage it. So we must call the driver
  4085. // which actually manage the surface.
  4086. // Hold share lock and devlock for video mode change.
  4087. // peSurface->fl can be changed by mode change, so we need to access
  4088. // there under holding share lock.
  4089. EDD_SHARELOCK eSharelock(TRUE);
  4090. if (peSurface->fl & DD_SURFACE_FLAG_WRONG_DRIVER)
  4091. {
  4092. // If surface is owned by different driver, lock right driver.
  4093. if (peSurface->peDirectDrawGlobal != peSurface->peDdGlobalCreator)
  4094. {
  4095. peDdGlobalDriver = peSurface->peDdGlobalCreator;
  4096. }
  4097. // WARNING("pDdLockSurfaceOrBuffer: Lock on wrong driver");
  4098. }
  4099. else
  4100. {
  4101. peDdGlobalDriver = peSurface->peDirectDrawGlobal;
  4102. }
  4103. EDD_DEVLOCK eDevlock(peDdGlobalDriver);
  4104. // For system memory surface, just return here without involving driver.
  4105. if (peSurface->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  4106. {
  4107. pvRet = (VOID*) peSurface->fpVidMem;
  4108. LockData.ddRVal = DD_OK;
  4109. goto Exit;
  4110. }
  4111. // In case if videomode change just happened, make sure new mode
  4112. // has DirectDraw capability.
  4113. if (!(peDdGlobalDriver->fl & DD_GLOBAL_FLAG_DRIVER_ENABLED))
  4114. {
  4115. LockData.ddRVal = DDERR_SURFACELOST;
  4116. goto Exit;
  4117. }
  4118. // We have to check both to see if the surface is disabled and if
  4119. // DirectDraw is disabled. We have to do the latter because we may
  4120. // be in a situtation where we're denying locks, but all the
  4121. // individual surfaces have not yet been marked as disabled.
  4122. if (peSurface->bLost)
  4123. {
  4124. LockData.ddRVal = DDERR_SURFACELOST;
  4125. goto Exit;
  4126. }
  4127. if ((peDdGlobalDriver->bSuspended) ||
  4128. (peSurface->fl & DD_SURFACE_FLAG_WRONG_DRIVER))
  4129. {
  4130. // Only the "driver managed surface" surface has DDSCAPS2_DONOTPERSIST
  4131. // can be locked when driver is suspended or surface lives in different driver.
  4132. if ((peSurface->dwFlags & DDRAWISURF_DRIVERMANAGED) &&
  4133. !(peSurface->ddsCapsEx.dwCaps2 & DDSCAPS2_DONOTPERSIST))
  4134. {
  4135. // WARNING("pDdLockSurfaceOrBuffer: Call driver other than current to lock driver managed surface");
  4136. }
  4137. else
  4138. {
  4139. LockData.ddRVal = DDERR_SURFACELOST;
  4140. goto Exit;
  4141. }
  4142. }
  4143. LockData.dwFlags = dwFlags & (
  4144. DDLOCK_SURFACEMEMORYPTR |
  4145. DDLOCK_DISCARDCONTENTS |
  4146. DDLOCK_NOOVERWRITE |
  4147. DDLOCK_READONLY |
  4148. DDLOCK_WRITEONLY |
  4149. DDLOCK_HASVOLUMETEXTUREBOXRECT |
  4150. DDLOCK_NODIRTYUPDATE);
  4151. LockData.lpDD = peDdGlobalDriver;
  4152. LockData.lpDDSurface = peSurface;
  4153. LockData.bHasRect = bHasRect;
  4154. if (bHasRect)
  4155. {
  4156. // Validate lock area.
  4157. LONG left, top, right, bottom;
  4158. LONG front, back, SurfaceDepth;
  4159. if ((peSurface->ddsCapsEx.dwCaps2 & DDSCAPS2_VOLUME) &&
  4160. (LockData.dwFlags & DDLOCK_HASVOLUMETEXTUREBOXRECT))
  4161. {
  4162. left = pArea->left & 0xFFFF;
  4163. top = pArea->top;
  4164. right = pArea->right & 0xFFFF;
  4165. bottom = pArea->bottom;
  4166. front = (ULONG)(pArea->left) >> 16;
  4167. back = (ULONG)(pArea->right) >> 16;
  4168. SurfaceDepth = peSurface->dwBlockSizeY;
  4169. }
  4170. else
  4171. {
  4172. left = pArea->left;
  4173. top = pArea->top;
  4174. right = pArea->right;
  4175. bottom = pArea->bottom;
  4176. }
  4177. // Ensure that the driver and 'bSpTearDownSprites'
  4178. // don't fall over when given a bad rectangle:
  4179. if ((left >= right) ||
  4180. (top >= bottom) ||
  4181. (left < 0) ||
  4182. (top < 0) ||
  4183. (right > (LONG) peSurface->wWidth) ||
  4184. (bottom > (LONG) peSurface->wHeight))
  4185. {
  4186. if (!(left == 0 && right == 0 &&
  4187. (peSurface->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) &&
  4188. (peSurface->dwFlags & DDRAWISURF_DRIVERMANAGED)))
  4189. {
  4190. bHasRect = FALSE;
  4191. }
  4192. }
  4193. if ((peSurface->ddsCapsEx.dwCaps2 & DDSCAPS2_VOLUME) &&
  4194. (LockData.dwFlags & DDLOCK_HASVOLUMETEXTUREBOXRECT))
  4195. {
  4196. if ((front >= back) ||
  4197. (front < 0) ||
  4198. (back > SurfaceDepth))
  4199. {
  4200. bHasRect = FALSE;
  4201. }
  4202. }
  4203. }
  4204. if (!bHasRect)
  4205. {
  4206. // Lock entire surface. (all depth if volume).
  4207. LockData.rArea.left = 0;
  4208. LockData.rArea.top = 0;
  4209. LockData.rArea.right = peSurface->wWidth;
  4210. LockData.rArea.bottom = peSurface->wHeight;
  4211. // Mask off DDLOCK_HASVOLUMETEXTUREBOXRECT.
  4212. LockData.dwFlags &= ~DDLOCK_HASVOLUMETEXTUREBOXRECT;
  4213. }
  4214. else
  4215. {
  4216. LockData.rArea = *pArea;
  4217. }
  4218. if (peSurface->ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM)
  4219. {
  4220. // AGP surfaces don't need fpProcess:
  4221. LockData.fpProcess = 0;
  4222. }
  4223. else
  4224. {
  4225. if (peSurface->fl & DD_SURFACE_FLAG_WRONG_DRIVER)
  4226. {
  4227. // If this surface currently lives in different driver,
  4228. // don't do video memory mapping to usermode address.
  4229. // Driver should be able to lock surface without this.
  4230. // Unless otherwise, driver should fail in Lock.
  4231. LockData.fpProcess = 0;
  4232. }
  4233. else
  4234. {
  4235. // Map the memory into the application's address space if that
  4236. // hasn't already been done:
  4237. if (!(peDirectDrawLocal->fl & DD_LOCAL_FLAG_MEMORY_MAPPED))
  4238. {
  4239. vDdMapMemory(peDirectDrawLocal, &LockData.ddRVal);
  4240. }
  4241. // Only proceed if we were successful in mapping the memory:
  4242. if (!(peDirectDrawLocal->fl & DD_LOCAL_FLAG_MEMORY_MAPPED))
  4243. {
  4244. goto Exit;
  4245. }
  4246. LockData.fpProcess = peDirectDrawLocal->fpProcess;
  4247. }
  4248. }
  4249. // If the surface is driver managed, we don't want to create any aliases
  4250. // so we reset the NOSYSLOCK flag:
  4251. if ((peSurface->dwFlags & DDRAWISURF_DRIVERMANAGED) &&
  4252. !(peSurface->ddsCapsEx.dwCaps2 & DDSCAPS2_DONOTPERSIST))
  4253. {
  4254. dwFlags &= ~DDLOCK_NOSYSLOCK;
  4255. }
  4256. // We allow only one "aliased" lock at any time. Thus if there already
  4257. // exists an aliased lock (peMap !=NULL) then we fail all other requests
  4258. // for locks. Also if there are already non aliased locks then we fail
  4259. // any requests for aliased locks.
  4260. // All this restrictions are put in due to the fact that we do not keep
  4261. // track of access rects for each surface in the kernel. If we did, we
  4262. // would just store a peMap pointer per access rect and not require these
  4263. // checks.
  4264. if ((peSurface->peMap ||
  4265. (peSurface->fl & DD_SURFACE_FLAG_FAKE_ALIAS_LOCK)) ||
  4266. (peSurface->cLocks && (dwFlags & DDLOCK_NOSYSLOCK)))
  4267. {
  4268. WARNING("pDdLockSurfaceOrBuffer: Failing lock since we cannot have more than one aliased lock");
  4269. LockData.ddRVal = DDERR_SURFACEBUSY;
  4270. goto Exit;
  4271. }
  4272. // If the VisRgn has changed since the application last queried
  4273. // it, fail the call with a unique error code so that they know
  4274. // to requery the VisRgn and try again. We do this only if we
  4275. // haven't been asked to wait (we assume 'bWait' is equivalent
  4276. // to 'bInternal').
  4277. if (!(dwFlags & DDLOCK_WAIT) &&
  4278. (peSurface->fl & DD_SURFACE_FLAG_PRIMARY) &&
  4279. (peSurface->iVisRgnUniqueness != VISRGN_UNIQUENESS()))
  4280. {
  4281. LockData.ddRVal = DDERR_VISRGNCHANGED;
  4282. goto Exit;
  4283. }
  4284. dwTmp = DDHAL_DRIVER_NOTHANDLED;
  4285. // Pick the appropriate lock function.
  4286. if (peSurface->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER)
  4287. {
  4288. pfnLock = peDdGlobalDriver->D3dBufCallbacks.LockD3DBuffer;
  4289. }
  4290. else
  4291. {
  4292. if (peDdGlobalDriver->SurfaceCallBacks.dwFlags & DDHAL_SURFCB32_LOCK)
  4293. {
  4294. pfnLock = peDdGlobalDriver->SurfaceCallBacks.Lock;
  4295. }
  4296. else
  4297. {
  4298. pfnLock = NULL;
  4299. }
  4300. }
  4301. if (pfnLock != NULL)
  4302. {
  4303. do
  4304. {
  4305. dwTmp = pfnLock(&LockData);
  4306. } while ((dwFlags & DDLOCK_WAIT) &&
  4307. (dwTmp == DDHAL_DRIVER_HANDLED) &&
  4308. (LockData.ddRVal == DDERR_WASSTILLDRAWING));
  4309. }
  4310. if ((dwTmp == DDHAL_DRIVER_NOTHANDLED) ||
  4311. (LockData.ddRVal == DD_OK))
  4312. {
  4313. // We successfully did the lock!
  4314. //
  4315. // If this is the primary surface and no window has been
  4316. // associated with the surface via DdResetVisRgn, then
  4317. // we have to force a redraw at Unlock time if any
  4318. // VisRgn has changed since the first Lock.
  4319. //
  4320. // If there is a window associated with the surface, then
  4321. // we have already checked that peSurface->iVisRgnUniqueness
  4322. // == po.iVisRgnUniqueness().
  4323. if (peSurface->cLocks++ == 0)
  4324. {
  4325. // If the surface is driver managed, we don't bother to
  4326. // increment the global lock count since we don't want to break
  4327. // locks when "losing" surfaces.
  4328. if (!(peSurface->dwFlags & DDRAWISURF_DRIVERMANAGED) ||
  4329. ((peSurface->dwFlags & DDRAWISURF_DRIVERMANAGED) &&
  4330. (peSurface->ddsCapsEx.dwCaps2 & DDSCAPS2_DONOTPERSIST)))
  4331. {
  4332. peDdGlobalDriver->cSurfaceLocks++;
  4333. }
  4334. peSurface->iVisRgnUniqueness = VISRGN_UNIQUENESS();
  4335. }
  4336. else
  4337. {
  4338. if (peSurface->rclLock.left < LockData.rArea.left)
  4339. LockData.rArea.left = peSurface->rclLock.left;
  4340. if (peSurface->rclLock.top < LockData.rArea.top)
  4341. LockData.rArea.top = peSurface->rclLock.top;
  4342. if (peSurface->rclLock.right > LockData.rArea.right)
  4343. LockData.rArea.right = peSurface->rclLock.right;
  4344. if (peSurface->rclLock.bottom > LockData.rArea.bottom)
  4345. LockData.rArea.bottom = peSurface->rclLock.bottom;
  4346. }
  4347. // If this is the primary surface, then union the current DirectDraw
  4348. // bounds rectangle with the lock area rectangle.
  4349. if (peSurface->fl & DD_SURFACE_FLAG_PRIMARY)
  4350. {
  4351. if (peDdGlobalDriver->fl & DD_GLOBAL_FLAG_BOUNDS_SET)
  4352. {
  4353. if (LockData.rArea.left < peDdGlobalDriver->rclBounds.left)
  4354. peDdGlobalDriver->rclBounds.left = LockData.rArea.left;
  4355. if (LockData.rArea.top < peDdGlobalDriver->rclBounds.top)
  4356. peDdGlobalDriver->rclBounds.top = LockData.rArea.top;
  4357. if (LockData.rArea.right > peDdGlobalDriver->rclBounds.right)
  4358. peDdGlobalDriver->rclBounds.right = LockData.rArea.right;
  4359. if (LockData.rArea.bottom > peDdGlobalDriver->rclBounds.bottom)
  4360. peDdGlobalDriver->rclBounds.bottom = LockData.rArea.bottom;
  4361. }
  4362. else
  4363. {
  4364. peDdGlobalDriver->rclBounds = LockData.rArea;
  4365. peDdGlobalDriver->fl |= DD_GLOBAL_FLAG_BOUNDS_SET;
  4366. }
  4367. }
  4368. // If there was a flip pending, then there is not now.
  4369. if (peSurface->fl & DD_SURFACE_FLAG_FLIP_PENDING)
  4370. {
  4371. peSurface->fl &= ~DD_SURFACE_FLAG_FLIP_PENDING;
  4372. }
  4373. // Stash away surface lock data:
  4374. peSurface->rclLock = LockData.rArea;
  4375. if (peSurface->fl & DD_SURFACE_FLAG_PRIMARY)
  4376. {
  4377. if (peSurface->cLocks == 1)
  4378. {
  4379. // Add this surface to the head of the locked list:
  4380. peSurface->peSurface_PrimaryLockNext
  4381. = peDdGlobalDriver->peSurface_PrimaryLockList;
  4382. peDdGlobalDriver->peSurface_PrimaryLockList
  4383. = peSurface;
  4384. }
  4385. // If this is the primary surface, tear down any
  4386. // sprites that intersect with the specified
  4387. // rectangle:
  4388. if (DxEngSpTearDownSprites(peDdGlobalDriver->hdev,
  4389. &LockData.rArea,
  4390. TRUE))
  4391. {
  4392. // Here's some weirdness for you. That sprite
  4393. // tear-down we just did may have involved
  4394. // accelerator operations, which means the
  4395. // accelerator may be still in use if we
  4396. // immediately returned to the application,
  4397. // which of course is bad.
  4398. //
  4399. // You might think that a fix to this would
  4400. // be to put the sprite tear-down *before*
  4401. // the call to the driver's DdLock routine.
  4402. // But then you get the problem that DdLock
  4403. // would *always* return DDERR_WASSTILLDRAWING,
  4404. // and we would have to re-draw the sprites,
  4405. // meaning that the application would get into
  4406. // an endless loop if it was itself (like all
  4407. // of DirectDraw's HAL code) looping on
  4408. // DDERR_WASSTILLDRAWING.
  4409. //
  4410. // To solve this problem, we'll simply wait for
  4411. // accelerator idle after tearing-down the
  4412. // sprite. We do this by calling DdLock/DdUnlock
  4413. // again:
  4414. if (peDdGlobalDriver->SurfaceCallBacks.dwFlags
  4415. & DDHAL_SURFCB32_LOCK)
  4416. {
  4417. do
  4418. {
  4419. dwRedraw = peDdGlobalDriver->
  4420. SurfaceCallBacks.Lock(&LockData);
  4421. } while ((dwRedraw == DDHAL_DRIVER_HANDLED) &&
  4422. (LockData.ddRVal == DDERR_WASSTILLDRAWING));
  4423. }
  4424. if (peDdGlobalDriver->SurfaceCallBacks.dwFlags
  4425. & DDHAL_SURFCB32_UNLOCK)
  4426. {
  4427. UnlockData.lpDD = peDdGlobalDriver;
  4428. UnlockData.lpDDSurface = peSurface;
  4429. peDdGlobalDriver->
  4430. SurfaceCallBacks.Unlock(&UnlockData);
  4431. }
  4432. }
  4433. }
  4434. LockData.ddRVal = DD_OK;
  4435. if (dwTmp == DDHAL_DRIVER_HANDLED)
  4436. {
  4437. // If it says it handled the call, the driver is
  4438. // expected to have computed the address in the
  4439. // client's address space:
  4440. pvRet = (VOID*) LockData.lpSurfData;
  4441. ASSERTGDI(pvRet != NULL,
  4442. "Expected non-NULL lock pointer value (DRIVER_HANDLED)");
  4443. ASSERTGDI(pvRet < (PVOID) MM_USER_PROBE_ADDRESS,
  4444. "Expected user-mode lock pointer value (DRIVER_HANDLED)");
  4445. }
  4446. else
  4447. {
  4448. if (peSurface->ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM)
  4449. {
  4450. pvRet = (VOID*)peSurface->fpVidMem;
  4451. }
  4452. else
  4453. {
  4454. pvRet = (VOID*) (peDirectDrawLocal->fpProcess
  4455. + peSurface->fpVidMem);
  4456. }
  4457. ASSERTGDI(pvRet != NULL,
  4458. "Expected non-NULL lock pointer value (DRIVER_NOT_HANDLED)");
  4459. ASSERTGDI(pvRet < (PVOID) MM_USER_PROBE_ADDRESS,
  4460. "Expected user-mode lock pointer value (DRIVER_NOT_HANDLED)");
  4461. // DirectDraw has a goofy convention that when a
  4462. // driver returns DD_OK and DDHAL_DRIVER_HANDLED
  4463. // from a Lock, that the driver is also supposed to
  4464. // adjust the pointer to point to the upper left
  4465. // corner of the specified rectangle.
  4466. //
  4467. // This doesn't make a heck of a lot of sense for
  4468. // odd formats such as YUV surfaces, but oh well --
  4469. // since kernel-mode is acting like a driver to
  4470. // user-mode DirectDraw, we have to do the adjustment:
  4471. if (bHasRect)
  4472. {
  4473. pvRet = (VOID*)
  4474. ((BYTE*) pvRet
  4475. + (pArea->top * peSurface->lPitch)
  4476. + (pArea->left
  4477. * (peSurface->ddpfSurface.dwRGBBitCount >> 3)));
  4478. }
  4479. }
  4480. // If this was an "aliased" lock, we store the corresponding pointer
  4481. // to the EDD_VMEMMAPPING
  4482. if (dwFlags & DDLOCK_NOSYSLOCK)
  4483. {
  4484. if (!(peSurface->ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM))
  4485. {
  4486. peSurface->peMap = peDirectDrawLocal->peMapCurrent;
  4487. ASSERTGDI(peSurface->peMap != NULL,
  4488. "Expected video memory to be mapped into user space");
  4489. }
  4490. else
  4491. {
  4492. // If the non-local surface was not allocated from one of
  4493. // our managed heaps, then lpVidMemHeap will be NULL and
  4494. // we cannot alias the heap, so we don't do the aliased
  4495. // lock.
  4496. if (peSurface->lpVidMemHeap != NULL)
  4497. {
  4498. peSurface->peMap = peDirectDrawLocal->ppeMapAgp[
  4499. (peSurface->lpVidMemHeap -
  4500. peDdGlobalDriver->pvmList)];
  4501. }
  4502. }
  4503. // If the map pointer is NULL, then the surface lock cannot be
  4504. // aliased so proceed as if DDLOCK_NOSYSLOCK was not passed.
  4505. // Otherwise, take the appropriate reference counts now:
  4506. if (peSurface->peMap != NULL)
  4507. {
  4508. peSurface->fl |= DD_SURFACE_FLAG_ALIAS_LOCK;
  4509. peDdGlobalDriver->cSurfaceAliasedLocks++;
  4510. peSurface->peMap->cReferences++;
  4511. // Keep a reference of the driver instance used to create this mapping
  4512. peSurface->peVirtualMapDdGlobal = peDdGlobalDriver;
  4513. vDdIncrementReferenceCount(peDdGlobalDriver);
  4514. DDKHEAP(("Taken aliased lock: peSurface=%lx, peMap=%lx, "
  4515. "peDdGlobalDriver=%lx\n",
  4516. peSurface, peSurface->peMap, peDdGlobalDriver));
  4517. }
  4518. else
  4519. {
  4520. // We have a private driver cap that will enable us to treat
  4521. // AGP surface locks as aliased even though the driver doesn't
  4522. // expose an AGP heap. This is to enable drivers to work around
  4523. // anything that we happen to do wrong in our AGP code without
  4524. // them incurring the 7 second tiemout on every mode change.
  4525. if ((peSurface->ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM) &&
  4526. (peDdGlobalDriver->PrivateCaps.dwPrivateCaps & DDHAL_PRIVATECAP_RESERVED1))
  4527. {
  4528. peSurface->fl |= DD_SURFACE_FLAG_ALIAS_LOCK;
  4529. peDdGlobalDriver->cSurfaceAliasedLocks++;
  4530. peSurface->fl |= DD_SURFACE_FLAG_FAKE_ALIAS_LOCK;
  4531. }
  4532. // Just to avoid possible problems in the future, turn
  4533. // off the flag here:
  4534. dwFlags &= ~DDLOCK_NOSYSLOCK;
  4535. }
  4536. }
  4537. }
  4538. else
  4539. {
  4540. if (LockData.ddRVal != DDERR_WASSTILLDRAWING)
  4541. {
  4542. WARNING("pDdLockSurface: Driver failed DdLock\n");
  4543. }
  4544. }
  4545. Exit:
  4546. if (pResult)
  4547. {
  4548. *pResult = LockData.ddRVal;
  4549. }
  4550. return(pvRet);
  4551. }
  4552. /******************************Public*Routine******************************\
  4553. * BOOL bDdUnlockSurfaceOrBuffer
  4554. *
  4555. * DirectDraw unlock for surfaces and D3D buffers.
  4556. *
  4557. * Note that the Devlock MUST NOT be held when entering this function
  4558. * if the surface is the primary surface.
  4559. *
  4560. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  4561. * Wrote it.
  4562. \**************************************************************************/
  4563. BOOL
  4564. bDdUnlockSurfaceOrBuffer(
  4565. EDD_SURFACE* peSurface
  4566. )
  4567. {
  4568. BOOL b;
  4569. BOOL bRedraw;
  4570. BOOL bFreeVirtualMap = FALSE;
  4571. EDD_DIRECTDRAW_GLOBAL *peDdGlobalDriver;
  4572. if (peSurface->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  4573. {
  4574. return(TRUE);
  4575. }
  4576. peSurface->fl &= ~DD_SURFACE_FLAG_ALIAS_LOCK;
  4577. b = FALSE;
  4578. bRedraw = FALSE;
  4579. {
  4580. // Don't hold ShareLock togather (see vDdDisableAllDirectDrawObjects)
  4581. // Give a change to signal AssertMode event.
  4582. EDD_DEVLOCK eDevlock(peSurface->peDirectDrawGlobal);
  4583. // Due to video mode change across different video driver, currently
  4584. // this "driver managed" surface is associated to different driver
  4585. // than the driver who actually manage it. So we must call the driver
  4586. // which actually manage the surface.
  4587. //
  4588. // peSurface->fl can be changed by mode change, thus we access there
  4589. // under holding devlock.
  4590. if (peSurface->fl & DD_SURFACE_FLAG_WRONG_DRIVER)
  4591. {
  4592. // If surface is owned by different driver, lock right driver.
  4593. if (peSurface->peDirectDrawGlobal != peSurface->peDdGlobalCreator)
  4594. {
  4595. // Unlike DdLockSurfaceOrBuffer case, we can't just unlock and
  4596. // lock with new device. Because, we can't hold sharelock (see above)
  4597. // so when we unlock device, there is a chance to mode change happens.
  4598. // thus, after we relock the device, we have to make sure peDdGlobalCreator
  4599. // is continue to be save as before. Otherwise loop until it match.
  4600. do {
  4601. peDdGlobalDriver = peSurface->peDdGlobalCreator;
  4602. eDevlock.vUnlockDevice();
  4603. eDevlock.vUpdateDevice(peDdGlobalDriver);
  4604. eDevlock.vLockDevice();
  4605. } while (peDdGlobalDriver !=
  4606. ((EDD_DIRECTDRAW_GLOBAL volatile *)(peSurface->peDdGlobalCreator)));
  4607. // WARNING("pDdLockSurfaceOrBuffer: Unlock on wrong driver");
  4608. }
  4609. }
  4610. else
  4611. {
  4612. peDdGlobalDriver = peSurface->peDirectDrawGlobal;
  4613. }
  4614. // Make sure there was a previous lock:
  4615. if (peSurface->cLocks > 0)
  4616. {
  4617. if ((peSurface->dwFlags & DDRAWISURF_DRIVERMANAGED) &&
  4618. !(peSurface->ddsCapsEx.dwCaps2 & DDSCAPS2_DONOTPERSIST))
  4619. {
  4620. // Driver managed surface can be unlock ANYTIME.
  4621. // (even PDEV is disabled)
  4622. }
  4623. else
  4624. {
  4625. PDEVOBJ po(peDdGlobalDriver->hdev);
  4626. ASSERTGDI(!po.bDisabled(),
  4627. "Surface is disabled but there are outstanding locks?");
  4628. }
  4629. vDdRelinquishSurfaceOrBufferLock(peDdGlobalDriver, peSurface);
  4630. // Does lock went to 0 after "Relinquish" ?
  4631. if (peSurface->cLocks == 0)
  4632. {
  4633. // Was this an aliased lock ?
  4634. if (peSurface->peMap)
  4635. {
  4636. bFreeVirtualMap = TRUE;
  4637. }
  4638. // If the API-disabled flag is set and we got this far into
  4639. // Unlock, it means that there is a DdSuspendDirectDraw()
  4640. // call pending, and that thread is waiting for all surface
  4641. // locks related to the device to be released.
  4642. //
  4643. // If this is the last lock to be released, signal the event
  4644. // so that the AssertMode thread can continue on.
  4645. if ((peDdGlobalDriver->cSurfaceLocks == 0) &&
  4646. (peDdGlobalDriver->bSuspended))
  4647. {
  4648. KeSetEvent(peDdGlobalDriver->pAssertModeEvent,
  4649. 0,
  4650. FALSE);
  4651. }
  4652. // NOTE: This should really test if the surface has a clipper. But
  4653. // it can't because of comapatibility with Win95, where
  4654. // applications expect a primary surface lock to be atomic
  4655. // even if they haven't attached a clipper object.
  4656. // (Microsoft's own OPENGL32.DLL does this, that shipped
  4657. // in NT 5.0.) However, this means that applications
  4658. // that are full-screen double buffering can possibly
  4659. // be causing a whole bunch of repaints when it does a
  4660. // direct lock on (what is now) the back buffer.
  4661. //
  4662. // Potentially, this 'if' should have an additional
  4663. // condition, and that is not to do it if the application
  4664. // is in exclusive mode:
  4665. if (peSurface->fl & DD_SURFACE_FLAG_PRIMARY)
  4666. {
  4667. // If the VisRgn changed while the application was writing
  4668. // to the surface, it may have started drawing over the
  4669. // the wrong window, so fix it up.
  4670. //
  4671. // Alas, right now a DirectDraw application doesn't always
  4672. // tell us what window it was drawing to, so we can't fix
  4673. // up only the affected windows. Instead, we solve it the
  4674. // brute-force way and redraw *all* windows:
  4675. if (peSurface->iVisRgnUniqueness != VISRGN_UNIQUENESS())
  4676. {
  4677. // We can't call UserRedrawDesktop here because it
  4678. // grabs the User critical section, and we're already
  4679. // holding the devlock -- which could cause a possible
  4680. // deadlock. Since it's a posted message it obviously
  4681. // doesn't have to be done under the devlock.
  4682. bRedraw = TRUE;
  4683. // Note that we should not update peSurface->
  4684. // iVisRgnUniqueness here. That's because if the
  4685. // application has attached a window to the surface, it
  4686. // has to be notified that the clipping has changed --
  4687. // which is done by returning DDERR_VISRGNCHANGED on the
  4688. // next Lock or Blt call. And if the application has
  4689. // not attached a window, we automatically update the
  4690. // uniqueness at the next Lock time.
  4691. }
  4692. }
  4693. }
  4694. b = TRUE;
  4695. }
  4696. else // if (peSurface->cLocks == 0)
  4697. {
  4698. // The lock count is 0 but we may have a "broken" lock.
  4699. if (peSurface->peMap)
  4700. {
  4701. bFreeVirtualMap = TRUE;
  4702. }
  4703. else
  4704. {
  4705. WARNING("bDdUnlockSurfaceOrBuffer: Surface already unlocked\n");
  4706. }
  4707. }
  4708. }
  4709. if (bRedraw)
  4710. {
  4711. PDEVOBJ po(peDdGlobalDriver->hdev);
  4712. // We can redraw only if we're not holding the devlock, because
  4713. // User needs to acquire its critical section. The User lock
  4714. // must always be acquired before the devlock, which is why
  4715. // we can't call User if we're already holding the devlock.
  4716. //
  4717. // I don't trust any callers enough to merely assert that we're
  4718. // not holding the devlock; I'll actually check...
  4719. if (!DxEngIsHdevLockedByCurrentThread(po.hdev()))
  4720. {
  4721. DxEngRedrawDesktop();
  4722. }
  4723. }
  4724. if (bFreeVirtualMap)
  4725. {
  4726. // We can release virtual map if we're not holding the devlock,
  4727. // because it might release GDI's PDEV if this is last reference.
  4728. vDdReleaseVirtualMap(peSurface);
  4729. }
  4730. return(b);
  4731. }
  4732. /******************************Public*Routine******************************\
  4733. * HANDLE DxDdCreateDirectDrawObject
  4734. *
  4735. * Creates a DirectDraw object.
  4736. *
  4737. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  4738. * Wrote it.
  4739. \**************************************************************************/
  4740. HANDLE
  4741. APIENTRY
  4742. DxDdCreateDirectDrawObject(
  4743. HDC hdc
  4744. )
  4745. {
  4746. HANDLE hDirectDrawLocal;
  4747. hDirectDrawLocal = 0; // Assume failure
  4748. PVOID pvLockedDC = DxEngLockDC(hdc);
  4749. if (pvLockedDC)
  4750. {
  4751. PDEVOBJ po((HDEV)DxEngGetDCState(hdc,DCSTATE_HDEV));
  4752. if (po.bValid() && po.bDisplayPDEV())
  4753. {
  4754. // Note that we aren't checking to see if the PDEV is disabled,
  4755. // so that DirectDraw could be started even when full-screen:
  4756. EDD_DEVLOCK eDevlock(po.hdev());
  4757. if (!(po.bDisabled()))
  4758. {
  4759. CheckAgpHeaps(po.peDirectDrawGlobal());
  4760. }
  4761. // DirectDraw works only at 8bpp or higher:
  4762. if (po.iDitherFormat() >= BMF_8BPP)
  4763. {
  4764. hDirectDrawLocal = hDdCreateDirectDrawLocal(po);
  4765. }
  4766. }
  4767. DxEngUnlockDC(pvLockedDC);
  4768. }
  4769. else
  4770. {
  4771. WARNING("DxDdCreateDirectDrawObject: Bad DC\n");
  4772. }
  4773. return(hDirectDrawLocal);
  4774. }
  4775. /******************************Public*Routine******************************\
  4776. * BOOL DxDdDeleteDirectDrawObject
  4777. *
  4778. * Deletes a kernel-mode representation of the surface.
  4779. *
  4780. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  4781. * Wrote it.
  4782. \**************************************************************************/
  4783. BOOL
  4784. APIENTRY
  4785. DxDdDeleteDirectDrawObject(
  4786. HANDLE hDirectDrawLocal
  4787. )
  4788. {
  4789. return(bDdDeleteDirectDrawObject(hDirectDrawLocal, FALSE));
  4790. }
  4791. /******************************Public*Routine******************************\
  4792. * HANDLE DxDdQueryDirectDrawObject
  4793. *
  4794. * Queries a DirectDraw object.
  4795. *
  4796. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  4797. * Wrote it.
  4798. \**************************************************************************/
  4799. BOOL
  4800. APIENTRY
  4801. DxDdQueryDirectDrawObject(
  4802. HANDLE hDirectDrawLocal,
  4803. DD_HALINFO* pHalInfo,
  4804. DWORD* pCallBackFlags,
  4805. LPD3DNTHAL_CALLBACKS puD3dCallbacks,
  4806. LPD3DNTHAL_GLOBALDRIVERDATA puD3dDriverData,
  4807. PDD_D3DBUFCALLBACKS puD3dBufferCallbacks,
  4808. LPDDSURFACEDESC puD3dTextureFormats,
  4809. DWORD* puNumHeaps,
  4810. VIDEOMEMORY* puvmList,
  4811. DWORD* puNumFourCC,
  4812. DWORD* puFourCC
  4813. )
  4814. {
  4815. BOOL b;
  4816. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  4817. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  4818. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  4819. ULONG cBytes;
  4820. b = FALSE; // Assume failure
  4821. // The most fundamental basis of accelerated DirectDraw is that it
  4822. // allows direct access to the frame buffer by the application. If
  4823. // security permissions prohibit reading from the screen, we cannot
  4824. // allow accelerated DirectDraw:
  4825. if (DxEngScreenAccessCheck())
  4826. {
  4827. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDrawLocal);
  4828. if (peDirectDrawLocal != NULL)
  4829. {
  4830. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  4831. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  4832. // A registry timeout value of 'zero' signifies that DirectDraw
  4833. // accelerations cannot be enabled. Note that the timeout is
  4834. // non-positive because it's a relative time duration.
  4835. if (peDirectDrawGlobal->llAssertModeTimeout < 0)
  4836. {
  4837. DWORD dwOverride;
  4838. PDEVOBJ po(peDirectDrawGlobal->hdev);
  4839. // Get driver override info:
  4840. dwOverride = po.dwDriverCapableOverride();
  4841. __try
  4842. {
  4843. DD_HALINFO ddhi = peDirectDrawGlobal->HalInfo;
  4844. if ( dwOverride & DRIVER_NOT_CAPABLE_D3D )
  4845. {
  4846. // If the driver is not capable of doing D3D, turn the CAPS
  4847. // off
  4848. ddhi.ddCaps.dwCaps &= ~DDCAPS_3D;
  4849. ddhi.lpD3DGlobalDriverData = 0;
  4850. ddhi.lpD3DHALCallbacks = 0;
  4851. }
  4852. #ifdef DX_REDIRECTION
  4853. if ( gbDxRedirection )
  4854. {
  4855. // If we are in redirection mode, disable overlay.
  4856. ddhi.ddCaps.dwCaps &= ~DDCAPS_OVERLAY;
  4857. ddhi.ddCaps.dwMaxVisibleOverlays = 0;
  4858. }
  4859. #endif // DX_REDIRECTION
  4860. ProbeAndWriteStructure(pHalInfo,
  4861. ddhi,
  4862. DD_HALINFO);
  4863. ProbeForWrite(pCallBackFlags, 3 * sizeof(ULONG), sizeof(ULONG));
  4864. pCallBackFlags[0] = peDirectDrawGlobal->CallBacks.dwFlags;
  4865. pCallBackFlags[1] = peDirectDrawGlobal->SurfaceCallBacks.dwFlags;
  4866. pCallBackFlags[2] = peDirectDrawGlobal->PaletteCallBacks.dwFlags;
  4867. if (puD3dCallbacks != NULL)
  4868. {
  4869. ProbeAndWriteStructure(puD3dCallbacks,
  4870. peDirectDrawGlobal->D3dCallBacks,
  4871. D3DNTHAL_CALLBACKS);
  4872. }
  4873. if (puD3dDriverData != NULL)
  4874. {
  4875. ProbeAndWriteStructure(puD3dDriverData,
  4876. peDirectDrawGlobal->D3dDriverData,
  4877. D3DNTHAL_GLOBALDRIVERDATA);
  4878. }
  4879. if (puD3dBufferCallbacks != NULL)
  4880. {
  4881. ProbeAndWriteStructure(puD3dBufferCallbacks,
  4882. peDirectDrawGlobal->D3dBufCallbacks,
  4883. DD_D3DBUFCALLBACKS);
  4884. }
  4885. if (puD3dTextureFormats != NULL)
  4886. {
  4887. ProbeForWrite(puD3dTextureFormats,
  4888. peDirectDrawGlobal->D3dDriverData.dwNumTextureFormats*
  4889. sizeof(DDSURFACEDESC), sizeof(DWORD));
  4890. RtlCopyMemory(puD3dTextureFormats,
  4891. peDirectDrawGlobal->D3dDriverData.lpTextureFormats,
  4892. peDirectDrawGlobal->D3dDriverData.dwNumTextureFormats*
  4893. sizeof(DDSURFACEDESC));
  4894. }
  4895. ProbeAndWriteUlong(puNumFourCC, peDirectDrawGlobal->dwNumFourCC);
  4896. // Offscreen heap allocations are handled directly
  4897. // in the kernel so don't report any memory back to
  4898. // user mode.
  4899. ProbeAndWriteUlong(puNumHeaps, 0);
  4900. if (puFourCC != NULL)
  4901. {
  4902. cBytes = sizeof(ULONG) * peDirectDrawGlobal->dwNumFourCC;
  4903. ProbeForWrite(puFourCC, cBytes, sizeof(ULONG));
  4904. RtlCopyMemory(puFourCC, peDirectDrawGlobal->pdwFourCC, cBytes);
  4905. }
  4906. b = TRUE;
  4907. }
  4908. __except(EXCEPTION_EXECUTE_HANDLER)
  4909. {
  4910. WARNING("DxDdQueryDirectDrawObject: Passed bad pointers\n");
  4911. }
  4912. }
  4913. else
  4914. {
  4915. WARNING("DxDdQueryDirectDrawObject: DirectDraw disabled in registry\n");
  4916. }
  4917. }
  4918. else
  4919. {
  4920. WARNING("DxDdQueryDirectDrawObject: Bad handle or busy\n");
  4921. }
  4922. }
  4923. else
  4924. {
  4925. WARNING("DxDdCreateDirectDrawObject: Don't have screen read permission");
  4926. }
  4927. return(b);
  4928. }
  4929. /******************************Public*Routine******************************\
  4930. * EDD_SURFACE* peDdOpenNewSurfaceObject
  4931. *
  4932. * Creates a new kernel-mode surface by re-using the old surface if it's
  4933. * lost, or by allocating a new surface.
  4934. *
  4935. * NOTE: Leaves the surface exclusive locked!
  4936. *
  4937. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  4938. * Wrote it.
  4939. \**************************************************************************/
  4940. EDD_SURFACE*
  4941. peDdOpenNewSurfaceObject(
  4942. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal,
  4943. HANDLE hSurface,
  4944. DD_SURFACE_GLOBAL* pSurfaceGlobal,
  4945. DD_SURFACE_LOCAL* pSurfaceLocal,
  4946. DD_SURFACE_MORE* pSurfaceMore
  4947. )
  4948. {
  4949. EDD_SURFACE* peSurface;
  4950. BOOL bSurfaceAlloced = FALSE;
  4951. // First, try to resurrect the old surface if there is one:
  4952. peSurface = NULL;
  4953. if (hSurface != 0)
  4954. {
  4955. peSurface = (EDD_SURFACE*) DdHmgLock((HDD_OBJ) hSurface, DD_SURFACE_TYPE, FALSE);
  4956. if (peSurface == NULL)
  4957. {
  4958. WARNING("peDdOpenNewSurfaceObject: hDDSurface wasn't set to 0\n");
  4959. }
  4960. else if ((peSurface->peDirectDrawLocal != peDirectDrawLocal) ||
  4961. (!(peSurface->bLost)))
  4962. {
  4963. WARNING("peDdOpenNewSurfaceObject: Couldn't re-use surface\n");
  4964. DEC_EXCLUSIVE_REF_CNT(peSurface);
  4965. peSurface = NULL;
  4966. return(peSurface);
  4967. }
  4968. #if DBG
  4969. if (peSurface != NULL)
  4970. {
  4971. DDKSURF(("DDKSURF: Reusing %X (%X)\n", hSurface, peSurface));
  4972. }
  4973. #endif
  4974. }
  4975. if (peSurface == NULL)
  4976. {
  4977. peSurface = (EDD_SURFACE*) DdHmgAlloc(sizeof(EDD_SURFACE),
  4978. DD_SURFACE_TYPE,
  4979. HMGR_ALLOC_LOCK);
  4980. if (peSurface != NULL)
  4981. {
  4982. bSurfaceAlloced = TRUE;
  4983. // Win95's DirectDraw makes a number of allocations that represent
  4984. // a single surface, and have pointers between the different
  4985. // parts. We make just one allocation and so the pointers refer
  4986. // back to ourselves. Note that the power of C++ means that
  4987. // 'lpGbl = peSurface' assigns 'lpGbl' the address to the
  4988. // DD_SURFACE_GLOBAL part of 'peSurface':
  4989. peSurface->lpGbl = peSurface;
  4990. peSurface->lpSurfMore = peSurface;
  4991. peSurface->lpLcl = peSurface;
  4992. peSurface->peDirectDrawLocal = peDirectDrawLocal;
  4993. peSurface->peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  4994. // Remember original creator of this surface (in case for video mode change).
  4995. PDEVOBJ po(peSurface->peDirectDrawGlobal->hdev);
  4996. // and remember which graphics device has association.
  4997. peSurface->pldevCreator = po.pldev(); // driver
  4998. peSurface->pGraphicsDeviceCreator = po.pGraphicsDevice(); // hardware
  4999. // No locks yet
  5000. peSurface->peMap = NULL;
  5001. // This is new surface, so it keeps lost state initially.
  5002. // The surface will be marked as lost until 'vDdCompleteSurfaceObject'
  5003. // is called on it:
  5004. peSurface->bLost = TRUE;
  5005. DDKSURF(("DDKSURF: Created %X (%X)\n", peSurface->hGet(), peSurface));
  5006. }
  5007. }
  5008. if ((peSurface != NULL) &&
  5009. !(peSurface->fl & DD_SURFACE_FLAG_CREATE_COMPLETE))
  5010. {
  5011. // We do this under try ~ except, because pSurfaceGlobal/Local/More
  5012. // could be user mode buffer.
  5013. __try
  5014. {
  5015. peSurface->fpVidMem = pSurfaceGlobal->fpVidMem;
  5016. peSurface->lPitch = pSurfaceGlobal->lPitch;
  5017. peSurface->wWidth = pSurfaceGlobal->wWidth;
  5018. peSurface->wHeight = pSurfaceGlobal->wHeight;
  5019. peSurface->wWidthOriginal = pSurfaceGlobal->wWidth;
  5020. peSurface->wHeightOriginal = pSurfaceGlobal->wHeight;
  5021. peSurface->ddpfSurface = pSurfaceGlobal->ddpfSurface;
  5022. peSurface->ddsCaps = pSurfaceLocal->ddsCaps;
  5023. // Copy just the driver managed flag
  5024. peSurface->dwFlags &= ~DDRAWISURF_DRIVERMANAGED;
  5025. peSurface->dwFlags |= (pSurfaceLocal->dwFlags & DDRAWISURF_DRIVERMANAGED);
  5026. peSurface->ddsCapsEx = pSurfaceMore->ddsCapsEx;
  5027. peSurface->dwSurfaceHandle = pSurfaceMore->dwSurfaceHandle;
  5028. // Copy the slice pitch for sysmem volume textures
  5029. if ((peSurface->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  5030. (peSurface->ddsCapsEx.dwCaps2 & DDSCAPS2_VOLUME))
  5031. {
  5032. peSurface->dwBlockSizeY = pSurfaceGlobal->dwBlockSizeY;
  5033. }
  5034. if (!(peSurface->bLost))
  5035. {
  5036. peSurface->bLost = TRUE;
  5037. // Surface wasn't losted formerly, but here we put null to make it lost forcely.
  5038. // This might causes some leak in driver, but anyway we should decrement
  5039. // active surface count here.
  5040. ASSERTGDI(peSurface->peDirectDrawLocal->cActiveSurface > 0,
  5041. "cActiveSurface will be negative");
  5042. peSurface->peDirectDrawLocal->cActiveSurface--;
  5043. }
  5044. }
  5045. __except(EXCEPTION_EXECUTE_HANDLER)
  5046. {
  5047. if (bSurfaceAlloced)
  5048. {
  5049. DdFreeObject(peSurface, DD_SURFACE_TYPE);
  5050. }
  5051. else
  5052. {
  5053. DEC_EXCLUSIVE_REF_CNT(peSurface);
  5054. }
  5055. peSurface = NULL;
  5056. }
  5057. }
  5058. // if everything went fine, and this is newly allocated surface ...
  5059. if (peSurface && bSurfaceAlloced)
  5060. {
  5061. // Add this to the head of the surface list hanging off the
  5062. // local DirectDraw object.
  5063. //
  5064. // This list is protected because we have exclusive access to
  5065. // the local DirectDraw object:
  5066. InsertHeadList(&(peDirectDrawLocal->ListHead_eSurface),
  5067. &(peSurface->List_eSurface));
  5068. peDirectDrawLocal->cSurface++;
  5069. }
  5070. return(peSurface);
  5071. }
  5072. /******************************Public*Routine******************************\
  5073. * BOOL bDdValidateSurfaceDescription
  5074. *
  5075. * Validates surface description information.
  5076. * Can be used before surface actually exists to validate data
  5077. * prior to creation.
  5078. *
  5079. * 6-Feb-1998 -by- Drew Bliss [drewb]
  5080. * Split from bDdValidateSurfaceObject.
  5081. \**************************************************************************/
  5082. BOOL
  5083. bDdValidateSurfaceDescription(
  5084. DD_SURFACE_GLOBAL* pSurfaceGlobal,
  5085. DD_SURFACE_LOCAL* pSurfaceLocal
  5086. )
  5087. {
  5088. // Protect against math overflow:
  5089. if (!(pSurfaceLocal->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER))
  5090. {
  5091. if ((pSurfaceGlobal->wWidth > DD_MAXIMUM_COORDINATE) ||
  5092. (pSurfaceGlobal->wWidth <= 0) ||
  5093. (pSurfaceGlobal->wHeight > DD_MAXIMUM_COORDINATE) ||
  5094. (pSurfaceGlobal->wHeight <= 0))
  5095. {
  5096. WARNING("bDdValidateSurfaceDescription: Bad dimensions");
  5097. return(FALSE);
  5098. }
  5099. // dwRGBBitCount is overloaded with dwYUVBitCount:
  5100. if ((pSurfaceGlobal->ddpfSurface.dwRGBBitCount < 1) &&
  5101. !(pSurfaceGlobal->ddpfSurface.dwFlags & DDPF_FOURCC))
  5102. {
  5103. WARNING("bDdValidateSurfaceDescription: Bad bit count");
  5104. return(FALSE);
  5105. }
  5106. if (pSurfaceGlobal->ddpfSurface.dwFlags & DDPF_RGB)
  5107. {
  5108. if ((pSurfaceGlobal->ddpfSurface.dwRGBBitCount != 1) &&
  5109. (pSurfaceGlobal->ddpfSurface.dwRGBBitCount != 2) &&
  5110. (pSurfaceGlobal->ddpfSurface.dwRGBBitCount != 4) &&
  5111. (pSurfaceGlobal->ddpfSurface.dwRGBBitCount != 8) &&
  5112. (pSurfaceGlobal->ddpfSurface.dwRGBBitCount != 16) &&
  5113. (pSurfaceGlobal->ddpfSurface.dwRGBBitCount != 24) &&
  5114. (pSurfaceGlobal->ddpfSurface.dwRGBBitCount != 32))
  5115. {
  5116. WARNING("bDdValidateSurfaceDescription: "
  5117. "dwRGBBitCount not 1, 2, 4, 8, 16, 24 or 32");
  5118. return(FALSE);
  5119. }
  5120. }
  5121. }
  5122. return(TRUE);
  5123. }
  5124. /******************************Public*Routine******************************\
  5125. * BOOL bDdValidateSystemMemoryObject
  5126. *
  5127. * Checks surface description and parameters for an existing
  5128. * system-memory surface.
  5129. *
  5130. * Checks suitable for pre-creation testing should be in
  5131. * bDdValidateSurfaceDescription.
  5132. *
  5133. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  5134. * Wrote it.
  5135. \**************************************************************************/
  5136. BOOL
  5137. bDdValidateSystemMemoryObject(
  5138. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal,
  5139. EDD_SURFACE* peSurface
  5140. )
  5141. {
  5142. if (!bDdValidateSurfaceDescription(peSurface, peSurface))
  5143. {
  5144. return FALSE;
  5145. }
  5146. if (!(peSurface->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER))
  5147. {
  5148. if (ABS(peSurface->lPitch) > 4 * DD_MAXIMUM_COORDINATE)
  5149. {
  5150. WARNING("bDdValidateSurfaceObject: Bad dimensions");
  5151. return(FALSE);
  5152. }
  5153. // The width in bytes must not be more than the pitch.
  5154. if (peSurface->wWidth * peSurface->ddpfSurface.dwRGBBitCount >
  5155. (ULONG) 8 * ABS(peSurface->lPitch))
  5156. {
  5157. WARNING("bDdValidateSurfaceObject: Bad pitch");
  5158. return(FALSE);
  5159. }
  5160. }
  5161. if ((peSurface->fpVidMem & 3) || (peSurface->lPitch & 3))
  5162. {
  5163. WARNING("bDdValidateSurfaceObject: Bad alignment");
  5164. return(FALSE);
  5165. }
  5166. return(TRUE);
  5167. }
  5168. /******************************Public*Routine******************************\
  5169. * BOOL bDdSecureSystemMemorySurface
  5170. *
  5171. * For system-memory surfaces, the user-mode DirectDraw component allocates
  5172. * the actual bits for storage. Since we will need to access those bits
  5173. * from kernel mode for the duration of the life of the surface, we must
  5174. * ensure that they're valid user-mode bits and that the pages will never
  5175. * be decommitted until the kernel-mode surface is destroyed.
  5176. *
  5177. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  5178. * Wrote it.
  5179. \**************************************************************************/
  5180. BOOL
  5181. bDdSecureSystemMemorySurface(
  5182. EDD_SURFACE* peSurface
  5183. )
  5184. {
  5185. FLATPTR fpStart;
  5186. FLATPTR fpEnd;
  5187. DWORD dwHeight;
  5188. // Note that bDdValidateSurfaceObject has already ensured that
  5189. // lPitch, fpVidMem, and the dimensions are "reasonable".
  5190. if (!(peSurface->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER))
  5191. {
  5192. dwHeight = peSurface->wHeight;
  5193. }
  5194. else
  5195. {
  5196. dwHeight = 1;
  5197. }
  5198. if (peSurface->lPitch >= 0)
  5199. {
  5200. fpStart = peSurface->fpVidMem;
  5201. fpEnd = fpStart + dwHeight * peSurface->lPitch;
  5202. }
  5203. else
  5204. {
  5205. fpEnd = peSurface->fpVidMem - peSurface->lPitch;
  5206. fpStart = fpEnd + dwHeight * peSurface->lPitch;
  5207. }
  5208. ASSERTGDI(fpEnd >= fpStart, "Messed up fpStart and fpEnd");
  5209. __try
  5210. {
  5211. ProbeForWrite((VOID*) fpStart, (ULONG)(ULONG_PTR)((BYTE*)fpEnd - (BYTE*)fpStart),
  5212. sizeof(DWORD));
  5213. }
  5214. __except(EXCEPTION_EXECUTE_HANDLER)
  5215. {
  5216. WARNING("bDdSecureSystemMemorySurface: fpVidMem wasn't valid and writable");
  5217. return(FALSE);
  5218. }
  5219. peSurface->hSecure = MmSecureVirtualMemory((VOID*) fpStart,
  5220. fpEnd - fpStart,
  5221. PAGE_READWRITE);
  5222. return(peSurface->hSecure != 0);
  5223. }
  5224. /******************************Public*Routine******************************\
  5225. * VOID vDdCompleteSurfaceObject
  5226. *
  5227. * Add the object to the surface list and initialize some miscellaneous
  5228. * fields.
  5229. *
  5230. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  5231. * Wrote it.
  5232. \**************************************************************************/
  5233. VOID
  5234. vDdCompleteSurfaceObject(
  5235. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal,
  5236. EDD_SURFACE* peSurface
  5237. )
  5238. {
  5239. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  5240. FLATPTR fpStartOffset;
  5241. LONG lDisplayPitch;
  5242. DWORD dwDepth;
  5243. DWORD dwBitsPixel;
  5244. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  5245. // Calculate the 2-d coordinate 'hint' for 2-d cards so that
  5246. // hopefully they don't need to do these three divides each
  5247. // time they need to use the surface:
  5248. if (peSurface->ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM)
  5249. {
  5250. dwBitsPixel = peSurface->ddpfSurface.dwRGBBitCount;
  5251. if ((dwBitsPixel > 0) && (peSurface->lpVidMemHeap != NULL))
  5252. {
  5253. fpStartOffset =
  5254. peSurface->fpHeapOffset - peSurface->lpVidMemHeap->fpStart;
  5255. if (peSurface->lpVidMemHeap->dwFlags & VMEMHEAP_RECTANGULAR)
  5256. {
  5257. lDisplayPitch = peSurface->lpVidMemHeap->lpHeap->stride;
  5258. }
  5259. else
  5260. {
  5261. lDisplayPitch = 1;
  5262. }
  5263. }
  5264. else
  5265. {
  5266. fpStartOffset = 0;
  5267. lDisplayPitch = 1;
  5268. dwBitsPixel = 1;
  5269. }
  5270. }
  5271. else
  5272. {
  5273. fpStartOffset = peSurface->fpVidMem
  5274. - peDirectDrawGlobal->HalInfo.vmiData.fpPrimary;
  5275. lDisplayPitch = peDirectDrawGlobal->HalInfo.vmiData.lDisplayPitch;
  5276. dwBitsPixel =
  5277. peDirectDrawGlobal->HalInfo.vmiData.ddpfDisplay.dwRGBBitCount;
  5278. }
  5279. peSurface->yHint = (LONG) (fpStartOffset / lDisplayPitch);
  5280. peSurface->xHint =
  5281. (LONG) (8 * (fpStartOffset % lDisplayPitch) / dwBitsPixel);
  5282. // Make sure some other flags are correct:
  5283. peSurface->ddsCaps.dwCaps &= ~DDSCAPS_PRIMARYSURFACE;
  5284. if (peSurface->fl & DD_SURFACE_FLAG_PRIMARY)
  5285. {
  5286. peSurface->ddsCaps.dwCaps |= DDSCAPS_PRIMARYSURFACE;
  5287. }
  5288. // Remember who is creator (needed for driver managed surface).
  5289. peSurface->peDdGlobalCreator = peDirectDrawGlobal;
  5290. // And if this is driver managed surface, keep reference on driver.
  5291. if (peSurface->dwFlags & DDRAWISURF_DRIVERMANAGED)
  5292. {
  5293. ASSERTGDI(peSurface->fl & DD_SURFACE_FLAG_DRIVER_CREATED,
  5294. "vDdCompleteSurfaceObject: driver managed surface must be driver created.");
  5295. vDdIncrementReferenceCount(peDirectDrawGlobal);
  5296. }
  5297. // This denotes, among other things, that the surface has been added
  5298. // to the surface list, so on deletion it will have to ben removed
  5299. // from the surface list:
  5300. peSurface->fl |= DD_SURFACE_FLAG_CREATE_COMPLETE;
  5301. // We've had stress failures where there is some funky reuse of the
  5302. // surfaces and we assert because the hbmGdi wasn't cleaned up. We
  5303. // do it here since we're on the same process as a final check.
  5304. if (peSurface->hbmGdi)
  5305. {
  5306. DxEngDeleteSurface( (HSURF) peSurface->hbmGdi);
  5307. peSurface->hbmGdi = NULL;
  5308. if (peSurface->hpalGdi)
  5309. {
  5310. EngDeletePalette(peSurface->hpalGdi);
  5311. peSurface->hpalGdi = NULL;
  5312. }
  5313. }
  5314. }
  5315. /******************************Public*Routine******************************\
  5316. * HANDLE DxDdCreateSurfaceObject
  5317. *
  5318. * Creates a kernel-mode representation of the surface, given a location
  5319. * in off-screen memory allocated by user-mode DirectDraw.
  5320. *
  5321. * We expect DirectDraw to already have called DxDdCreateSurface, which
  5322. * gives the driver a chance at creating the surface. In the future, I expect
  5323. * all off-screen memory management to be moved to the kernel, with all surface
  5324. * allocations being handled via DxDdCreateSurface. This function call will
  5325. * then be extraneous.
  5326. *
  5327. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  5328. * Wrote it.
  5329. \**************************************************************************/
  5330. HANDLE
  5331. APIENTRY
  5332. DxDdCreateSurfaceObject(
  5333. HANDLE hDirectDrawLocal,
  5334. HANDLE hSurface,
  5335. PDD_SURFACE_LOCAL puSurfaceLocal,
  5336. PDD_SURFACE_MORE puSurfaceMore,
  5337. PDD_SURFACE_GLOBAL puSurfaceGlobal,
  5338. BOOL bComplete // TRUE if surface is now complete.
  5339. // FALSE if we're just creating a
  5340. // kernel handle to handle attaches;
  5341. // the surface will be filled-out
  5342. // and 'completed' in a later call
  5343. ) // to DxDdCreateSurfaceObject.
  5344. {
  5345. HANDLE hRet;
  5346. DD_SURFACE_LOCAL SurfaceLocal;
  5347. DD_SURFACE_MORE SurfaceMore;
  5348. DD_SURFACE_GLOBAL SurfaceGlobal;
  5349. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  5350. EDD_LOCK_SURFACE eLockSurface;
  5351. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  5352. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  5353. EDD_SURFACE* peSurface;
  5354. hRet = 0;
  5355. __try
  5356. {
  5357. SurfaceLocal = ProbeAndReadStructure(puSurfaceLocal, DD_SURFACE_LOCAL);
  5358. SurfaceMore = ProbeAndReadStructure(puSurfaceMore, DD_SURFACE_MORE);
  5359. SurfaceGlobal = ProbeAndReadStructure(puSurfaceGlobal, DD_SURFACE_GLOBAL);
  5360. }
  5361. __except(EXCEPTION_EXECUTE_HANDLER)
  5362. {
  5363. return(hRet);
  5364. }
  5365. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDrawLocal);
  5366. if (peDirectDrawLocal != NULL)
  5367. {
  5368. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  5369. if (SurfaceLocal.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  5370. {
  5371. // This is system memory
  5372. peSurface = peDdOpenNewSurfaceObject(peDirectDrawLocal,
  5373. hSurface,
  5374. &SurfaceGlobal,
  5375. &SurfaceLocal,
  5376. &SurfaceMore);
  5377. if (peSurface)
  5378. {
  5379. if (bComplete)
  5380. {
  5381. if ((bDdValidateSystemMemoryObject(peDirectDrawGlobal,
  5382. peSurface)) &&
  5383. (bDdSecureSystemMemorySurface(peSurface)))
  5384. {
  5385. ASSERTGDI(peSurface->hbmGdi == NULL,
  5386. "DxDdCreateSurfaceObject: Invalid cached bitmap");
  5387. // If this surface is in lost state, make it active.
  5388. if (peSurface->bLost)
  5389. {
  5390. peSurface->bLost = FALSE;
  5391. // Now this surface is ready to go, increment active surface ref. count.
  5392. peSurface->peDirectDrawLocal->cActiveSurface++;
  5393. ASSERTGDI(peSurface->peDirectDrawLocal->cActiveSurface <=
  5394. peSurface->peDirectDrawLocal->cSurface,
  5395. "cActiveSurface is > than cSurface");
  5396. }
  5397. // We were successful, so unlock the surface:
  5398. hRet = peSurface->hGet();
  5399. DEC_EXCLUSIVE_REF_CNT(peSurface); // Unlock
  5400. }
  5401. else
  5402. {
  5403. // Delete the surface. Note that it may or may not
  5404. // yet have been completed:
  5405. bDdDeleteSurfaceObject(peSurface->hGet(), NULL);
  5406. }
  5407. }
  5408. else
  5409. {
  5410. // This must be a complex surface (e.g. MipMap) that is getting called via the attach function.
  5411. // DDraw should call this again later to complete the surface.
  5412. hRet = peSurface->hGet();
  5413. DEC_EXCLUSIVE_REF_CNT(peSurface); // Unlock
  5414. }
  5415. }
  5416. }
  5417. else if (!(peDirectDrawGlobal->bSuspended))
  5418. {
  5419. // This is any video memory
  5420. peSurface = peDdOpenNewSurfaceObject(peDirectDrawLocal,
  5421. hSurface,
  5422. &SurfaceGlobal,
  5423. &SurfaceLocal,
  5424. &SurfaceMore);
  5425. if (peSurface != NULL)
  5426. {
  5427. if ((bComplete) &&
  5428. !(peSurface->fl & DD_SURFACE_FLAG_CREATE_COMPLETE))
  5429. {
  5430. // Only the kernel can create vidmem surface objects now, so
  5431. // if we're asked to 'complete' a surface that the kernel
  5432. // hasn't allocated, it's an error and no object should
  5433. // be completed. This weird code path is actually hit when
  5434. // user-mode DirectDraw tries to create a primary surface on
  5435. // a device whose driver doesn't support DirectDraw.
  5436. bDdDeleteSurfaceObject(peSurface->hGet(), NULL);
  5437. WARNING("DxDdCreateSurfaceObject: No DirectDraw driver");
  5438. }
  5439. else
  5440. {
  5441. if (bComplete)
  5442. {
  5443. ASSERTGDI(peSurface->hbmGdi == NULL,
  5444. "DxDdCreateSurfaceObject: Invalid cached bitmap");
  5445. // If this surface is in lost state, make it active.
  5446. if (peSurface->bLost)
  5447. {
  5448. peSurface->bLost = FALSE; // Surface can now be used
  5449. // Now this surface is ready to go, increment active surface ref. count.
  5450. peSurface->peDirectDrawLocal->cActiveSurface++;
  5451. ASSERTGDI(peSurface->peDirectDrawLocal->cActiveSurface <=
  5452. peSurface->peDirectDrawLocal->cSurface,
  5453. "cActiveSurface is > than cSurface");
  5454. }
  5455. }
  5456. // No need to call the CreateSurfaceEx here for this case
  5457. // We were successful, so unlock the surface:
  5458. hRet = peSurface->hGet();
  5459. DEC_EXCLUSIVE_REF_CNT(peSurface); // Unlock
  5460. }
  5461. }
  5462. }
  5463. else
  5464. {
  5465. WARNING("DxDdCreateSurfaceObject: "
  5466. "Can't create because disabled\n");
  5467. }
  5468. }
  5469. else
  5470. {
  5471. WARNING("DxDdCreateSurfaceObjec: Bad handle or busy\n");
  5472. }
  5473. return(hRet);
  5474. }
  5475. /******************************Public*Routine******************************\
  5476. * BOOL DxDdDeleteSurfaceObject
  5477. *
  5478. * Deletes a kernel-mode representation of the surface.
  5479. *
  5480. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  5481. * Wrote it.
  5482. \**************************************************************************/
  5483. BOOL
  5484. APIENTRY
  5485. DxDdDeleteSurfaceObject(
  5486. HANDLE hSurface
  5487. )
  5488. {
  5489. return(bDdDeleteSurfaceObject(hSurface, NULL));
  5490. }
  5491. /******************************Public*Routine******************************\
  5492. * ULONG DxDdResetVisrgn
  5493. *
  5494. * Registers a window for clipping.
  5495. *
  5496. * Remembers the current VisRgn state. Must be called before the VisRgn
  5497. * is downloaded and used.
  5498. *
  5499. * hwnd is currently not used.
  5500. *
  5501. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  5502. * Wrote it.
  5503. \**************************************************************************/
  5504. BOOL
  5505. APIENTRY
  5506. DxDdResetVisrgn(
  5507. HANDLE hSurface,
  5508. HWND hwnd // 0 indicates no window clipping
  5509. ) // -1 indicates any window can be written to
  5510. // otherwise indicates a particular window
  5511. {
  5512. BOOL bRet;
  5513. EDD_SURFACE* peSurface;
  5514. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  5515. EDD_LOCK_SURFACE eLockSurface;
  5516. bRet = FALSE;
  5517. peSurface = eLockSurface.peLock(hSurface);
  5518. if (peSurface != NULL)
  5519. {
  5520. peDirectDrawGlobal = peSurface->peDirectDrawGlobal;
  5521. // We only care about the changes to the primary
  5522. if (peSurface->fl & DD_SURFACE_FLAG_PRIMARY)
  5523. {
  5524. peSurface->iVisRgnUniqueness = VISRGN_UNIQUENESS();
  5525. }
  5526. bRet = TRUE;
  5527. }
  5528. return(bRet);
  5529. }
  5530. /******************************Public*Routine******************************\
  5531. * ULONG DxDdReenableDirectDrawObject
  5532. *
  5533. * Resets the DirectDraw object after a mode change or after full-screen.
  5534. *
  5535. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  5536. * Wrote it.
  5537. \**************************************************************************/
  5538. BOOL
  5539. APIENTRY
  5540. DxDdReenableDirectDrawObject(
  5541. HANDLE hDirectDrawLocal,
  5542. BOOL* pubNewMode
  5543. )
  5544. {
  5545. BOOL b;
  5546. HDC hdc;
  5547. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  5548. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  5549. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  5550. BOOL bModeChanged;
  5551. b = FALSE;
  5552. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDrawLocal);
  5553. if (peDirectDrawLocal != NULL)
  5554. {
  5555. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  5556. // Get a DC on this HDEV so we can determine if the app has
  5557. // access to it. A NULL vis-region will be returned whenever
  5558. // something like a desktop has switched.
  5559. hdc = DxEngGetDesktopDC(DCTYPE_DIRECT, FALSE, FALSE);
  5560. PDEVOBJ po(peDirectDrawGlobal->hdev);
  5561. {
  5562. EDD_SHAREDEVLOCK eDevlock(peDirectDrawGlobal);
  5563. if (DxEngGetDCState(hdc,DCSTATE_VISRGNCOMPLEX) != NULLREGION)
  5564. {
  5565. // DirectDraw can't be re-enabled while full-screen, or
  5566. // while USER has told us to disable DirectDraw, or when
  5567. // the colour depth is less than 8bpp:
  5568. if (!(po.bDisabled()) &&
  5569. !(po.bDeleted()) &&
  5570. (po.cDirectDrawDisableLocks() == 0) &&
  5571. (po.iDitherFormat() >= BMF_8BPP) &&
  5572. (peDirectDrawGlobal->fl & DD_GLOBAL_FLAG_DRIVER_ENABLED))
  5573. {
  5574. bModeChanged
  5575. = (peDirectDrawGlobal->fl & DD_GLOBAL_FLAG_MODE_CHANGED) != 0;
  5576. CheckAgpHeaps(peDirectDrawGlobal);
  5577. MapAllAgpHeaps(peDirectDrawLocal);
  5578. b = TRUE;
  5579. peDirectDrawGlobal->bSuspended = FALSE;
  5580. peDirectDrawGlobal->fl &= ~DD_GLOBAL_FLAG_MODE_CHANGED;
  5581. __try
  5582. {
  5583. ProbeAndWriteStructure(pubNewMode, bModeChanged, BOOL);
  5584. }
  5585. __except(EXCEPTION_EXECUTE_HANDLER)
  5586. {
  5587. }
  5588. }
  5589. }
  5590. }
  5591. if (hdc)
  5592. {
  5593. DxEngDeleteDC(hdc, FALSE);
  5594. }
  5595. }
  5596. else
  5597. {
  5598. WARNING("DxDdReenableDirectDrawObject: Bad handle or busy\n");
  5599. }
  5600. return(b);
  5601. }
  5602. /******************************Public*Routine******************************\
  5603. * HBITMAP hbmDdCreateAndLockGdiSurface
  5604. *
  5605. * Creates a GDI surface derived from a DirectDraw surface. This routine
  5606. * may call the driver's DdLock function if it hasn't hooked (or fails)
  5607. * the DrvDeriveSurface call which gets the driver to wrap a GDI surface
  5608. * around a DirectDraw surface.
  5609. *
  5610. * Note that for the primary (GDI) surface, we can't simply return a handle
  5611. * back to the surface stashed in the PDEV. There are a couple of reasons
  5612. * for this:
  5613. *
  5614. * o The surface contains the palette, and at 8bpp the palette for
  5615. * a DirectDraw GetDC surface must have the DIB-Section flag set
  5616. * for proper colour matching. But the primary device surface can
  5617. * not have its palette marked as a DIB-Section.
  5618. *
  5619. * o GreSelectBitmap doesn't allow one surface to be selected into more
  5620. * than one DC.
  5621. *
  5622. * 22-Feb-1998 -by- J. Andrew Goossen [andrewgo]
  5623. * Wrote it.
  5624. \**************************************************************************/
  5625. HBITMAP
  5626. hbmDdCreateAndLockGdiSurface(
  5627. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal,
  5628. EDD_SURFACE* peSurface,
  5629. PALETTEENTRY* puColorTable // Points to user-mode table
  5630. )
  5631. {
  5632. VOID* pvScan0;
  5633. VOID* pvBits;
  5634. LONG cjBits;
  5635. HBITMAP hbm;
  5636. ULONG iMode;
  5637. ULONG cColors;
  5638. ULONG i;
  5639. ULONG iFormat = 0;
  5640. // No color table is used for surfaces greater than 8bpp.
  5641. cColors = 0;
  5642. if (peSurface->ddpfSurface.dwRGBBitCount <= 8)
  5643. {
  5644. cColors = 1 << peSurface->ddpfSurface.dwRGBBitCount;
  5645. // Verify that the color table is safe to look at:
  5646. if (puColorTable != NULL)
  5647. {
  5648. __try
  5649. {
  5650. ProbeForRead(puColorTable, cColors * sizeof(PALETTEENTRY), 1);
  5651. }
  5652. __except(EXCEPTION_EXECUTE_HANDLER)
  5653. {
  5654. WARNING("hbmDdCreateAndLockGdiSurface: Bad color table pointer");
  5655. return(0);
  5656. }
  5657. }
  5658. // The bitmap's color table can be shared with the primary surface only
  5659. // if both are 8bpp:
  5660. if (puColorTable == NULL)
  5661. {
  5662. if ((peDirectDrawGlobal->HalInfo.vmiData.ddpfDisplay.dwRGBBitCount != 8) ||
  5663. (peSurface->ddpfSurface.dwRGBBitCount != 8))
  5664. {
  5665. WARNING("hbmDdCreateAndLockGdiSurface: Can't create shared palettes");
  5666. return(0);
  5667. }
  5668. }
  5669. }
  5670. PDEVOBJ po(peDirectDrawGlobal->hdev);
  5671. if (peSurface->hbmGdi != NULL)
  5672. {
  5673. // Ah ha, we already have a cached GDI surface. See if we need
  5674. // to call 'Lock', and then get out:
  5675. SURFOBJ* pso;
  5676. if ((pso = EngLockSurface((HSURF)(peSurface->hbmGdi))) != NULL)
  5677. {
  5678. if (peSurface->fl & DD_SURFACE_FLAG_BITMAP_NEEDS_LOCKING)
  5679. {
  5680. pvScan0 =
  5681. pDdLockSurfaceOrBuffer(peSurface, FALSE, NULL, DDLOCK_WAIT, NULL);
  5682. ASSERTGDI(pvScan0 != NULL,
  5683. "Driver failed lock call when it succeeded it before. Tsk, tsk");
  5684. // The driver�s allowed to move the surface around between locks, so
  5685. // update the bitmap address:
  5686. if ((pvScan0 != pso->pvScan0) &&
  5687. (pvScan0 != NULL))
  5688. {
  5689. pso->pvScan0 = pvScan0;
  5690. pso->pvBits = pvScan0;
  5691. }
  5692. }
  5693. // If it's 8bpp or less, we have to update the color table.
  5694. if (peSurface->ddpfSurface.dwRGBBitCount <= 8)
  5695. {
  5696. // Update the color table.
  5697. // Note that the scumy application might have delete the cached
  5698. // bitmap, so we have to check for bValid() here. (It's been a
  5699. // bad app, so we just protect against crashing, and don't bother
  5700. // to re-create a good bitmap for him.)
  5701. DxEngUploadPaletteEntryToSurface(po.hdev(),pso,puColorTable,cColors);
  5702. }
  5703. EngUnlockSurface(pso);
  5704. }
  5705. }
  5706. else
  5707. {
  5708. // Okay, we have to create a GDI surface on the spot.
  5709. //
  5710. // First, The DirectDraw surface must be marked as RGB (even at 8bpp).
  5711. // GDI doesn't (yet) support drawing to YUV surfaces or the like. It
  5712. // also doesn't support 2bpp surfaces.
  5713. if ((peSurface->ddpfSurface.dwFlags & DDPF_RGB) &&
  5714. (peSurface->ddpfSurface.dwRGBBitCount != 2))
  5715. {
  5716. // We have to have the devlock since we'll be grunging around in
  5717. // the PDEV:
  5718. DD_ASSERTDEVLOCK(peDirectDrawGlobal);
  5719. switch (peSurface->ddpfSurface.dwRGBBitCount)
  5720. {
  5721. case 1:
  5722. iFormat = BMF_1BPP; break;
  5723. case 4:
  5724. iFormat = BMF_4BPP; break;
  5725. case 8:
  5726. iFormat = BMF_8BPP; break;
  5727. case 16:
  5728. iFormat = BMF_16BPP; break;
  5729. case 24:
  5730. iFormat = BMF_24BPP; break;
  5731. case 32:
  5732. iFormat = BMF_32BPP; break;
  5733. default:
  5734. RIP("hbmDdCreateAndLockGdiSurface: Illegal dwRGBBitCount\n");
  5735. }
  5736. iMode = (iFormat <= BMF_8BPP) ? PAL_INDEXED : PAL_BITFIELDS;
  5737. HPALETTE hpal = EngCreatePalette(iMode,
  5738. cColors,
  5739. (ULONG*) puColorTable,
  5740. peSurface->ddpfSurface.dwRBitMask,
  5741. peSurface->ddpfSurface.dwGBitMask,
  5742. peSurface->ddpfSurface.dwBBitMask);
  5743. if (hpal)
  5744. {
  5745. if ((cColors == 256) && (puColorTable == NULL))
  5746. {
  5747. ASSERTGDI(po.bIsPalManaged(), "Expected palettized display");
  5748. // Make this palette share the same colour table as the
  5749. // screen, so that we always get identity blts:
  5750. DxEngSyncPaletteTableWithDevice(hpal,po.hdev());
  5751. }
  5752. hbm = 0;
  5753. // First, try getting the driver to create the surface, assuming
  5754. // it's a video memory surface.
  5755. if (!(peSurface->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  5756. PPFNVALID(po, DeriveSurface))
  5757. {
  5758. hbm = PPFNDRV(po, DeriveSurface)(peDirectDrawGlobal,
  5759. peSurface);
  5760. if (hbm)
  5761. {
  5762. SURFOBJ* pso = EngLockSurface((HSURF)hbm);
  5763. if (pso)
  5764. {
  5765. // Mark surface as DirectDraw surface.
  5766. DxEngMarkSurfaceAsDirectDraw(pso,peSurface->hGet());
  5767. // Select the created palette to surface palette.
  5768. DxEngSelectPaletteToSurface(pso,hpal);
  5769. EngUnlockSurface(pso);
  5770. }
  5771. else
  5772. {
  5773. EngDeleteSurface((HSURF)hbm);
  5774. hbm = 0;
  5775. }
  5776. }
  5777. }
  5778. // Next, try getting GDI to create the surface:
  5779. if (hbm == 0)
  5780. {
  5781. // Note that this lock will fail when the PDEV isn't active,
  5782. // meaning that GetDC will return 0 when full-screen.
  5783. // GDI won't barf on any calls where the HDC is passed in as
  5784. // 0, so this is okay.
  5785. pvScan0 = pDdLockSurfaceOrBuffer(peSurface, FALSE,
  5786. NULL, DDLOCK_WAIT, NULL);
  5787. if (pvScan0 != NULL)
  5788. {
  5789. FLONG fl;
  5790. SIZEL sizl;
  5791. sizl.cx = peSurface->wWidth;
  5792. sizl.cy = peSurface->wHeight;
  5793. fl = BMF_TOPDOWN;
  5794. pvBits = pvScan0;
  5795. cjBits = (LONG) peSurface->wHeight * peSurface->lPitch;
  5796. if (cjBits < 0)
  5797. {
  5798. fl = 0;
  5799. cjBits = -cjBits;
  5800. pvBits = (BYTE*) pvScan0 - cjBits - peSurface->lPitch;
  5801. }
  5802. hbm = EngCreateBitmap(sizl,
  5803. 0,
  5804. iFormat,
  5805. fl,
  5806. pvBits);
  5807. // Mark the palette as a DIB-Section so that any color-
  5808. // matching on the DC actually uses the entire device
  5809. // palette, NOT what the logical palette selected into
  5810. // the DC.
  5811. DxEngSetPaletteState(hpal,PALSTATE_DIBSECTION,(ULONG_PTR)TRUE);
  5812. if (hbm)
  5813. {
  5814. SURFOBJ* pso = EngLockSurface((HSURF) hbm);
  5815. if (pso)
  5816. {
  5817. peSurface->fl |= DD_SURFACE_FLAG_BITMAP_NEEDS_LOCKING;
  5818. // Select the created palette to surface palette.
  5819. DxEngSelectPaletteToSurface(pso,hpal);
  5820. // Mark surface as DirectDraw surface.
  5821. DxEngMarkSurfaceAsDirectDraw(pso,peSurface->hGet());
  5822. // Override some fields which we couldn't specify in
  5823. // the 'EngCreateBitmap' call. The following 3 are due to
  5824. // the fact that we couldn't pass in a stride:
  5825. pso->lDelta = peSurface->lPitch;
  5826. pso->pvScan0 = pvScan0;
  5827. pso->cjBits = cjBits;
  5828. pso->fjBitmap |= BMF_DONTCACHE;
  5829. if (!(peSurface->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY))
  5830. {
  5831. pso->fjBitmap |= BMF_NOTSYSMEM;
  5832. }
  5833. EngUnlockSurface(pso);
  5834. }
  5835. else
  5836. {
  5837. EngDeleteSurface((HSURF)hbm);
  5838. hbm = 0;
  5839. }
  5840. }
  5841. else
  5842. {
  5843. bDdUnlockSurfaceOrBuffer(peSurface);
  5844. }
  5845. }
  5846. }
  5847. if (hbm)
  5848. {
  5849. // Success, we're done!
  5850. //
  5851. // Set handle owner to current process.
  5852. DxEngSetBitmapOwner(hbm, OBJECT_OWNER_CURRENT);
  5853. peSurface->hbmGdi = hbm;
  5854. // TODO: Palette needs to be owned by this process.
  5855. peSurface->hpalGdi = hpal;
  5856. }
  5857. else
  5858. {
  5859. EngDeletePalette(hpal);
  5860. }
  5861. }
  5862. }
  5863. else if (!(peSurface->ddpfSurface.dwFlags & DDPF_ZBUFFER))
  5864. {
  5865. WARNING("hbbDdCreateAndLockGdiSurface: Invalid surface or RGB type\n");
  5866. }
  5867. }
  5868. return(peSurface->hbmGdi);
  5869. }
  5870. /******************************Public*Routine******************************\
  5871. * VOID vDdUnlockGdiSurface
  5872. *
  5873. * Unlocks the view required for the GDI bitmap if necessary (that is, if
  5874. * the driver didn't hook DrvDeriveSurface, or failed it).
  5875. *
  5876. * 22-Feb-1998 -by- J. Andrew Goossen [andrewgo]
  5877. * Wrote it.
  5878. \**************************************************************************/
  5879. VOID FASTCALL
  5880. vDdUnlockGdiSurface(
  5881. EDD_SURFACE* peSurface
  5882. )
  5883. {
  5884. if (peSurface->fl & DD_SURFACE_FLAG_BITMAP_NEEDS_LOCKING)
  5885. {
  5886. bDdUnlockSurfaceOrBuffer(peSurface);
  5887. }
  5888. }
  5889. /******************************Public*Routine******************************\
  5890. * HDC DxDdGetDC
  5891. *
  5892. * Creates a DC that can be used to draw to an off-screen DirectDraw
  5893. * surface.
  5894. *
  5895. * Essentially, this works as follows:
  5896. *
  5897. * o Do a DirectDraw Lock on the specified surface;
  5898. * o CreateDIBSection of the appropriate format pointing to that surface;
  5899. * o CreateCompatibleDC to get a DC;
  5900. * o Select the DIBSection into the compatible DC
  5901. *
  5902. * At 8bpp, however, the DIBSection is not a 'normal' DIBSection. It's
  5903. * created with no palette so that it it behaves as a device-dependent
  5904. * bitmap: the color table is the same as the display.
  5905. *
  5906. * GDI will do all drawing to the surface using the user-mode mapping of
  5907. * the frame buffer. Since all drawing to the created DC will occur in the
  5908. * context of the application's process, this is not a problem. We do have
  5909. * to watch out that we don't blow away the section view while a thread is
  5910. * in kernel-mode GDI drawing; however, this problem would have to be solved
  5911. * even if using a kernel-mode mapping of the section because we don't want
  5912. * any drawing intended for an old PDEV to get through to a new PDEV after
  5913. * a mode change has occured, for example.
  5914. *
  5915. * A tricky part of GetDC is how to blow away the surface lock while a thread
  5916. * could be in kernel-mode GDI about to draw using the surface pointer. We
  5917. * solve that problem by changing the DC's VisRgn to be an empty region when
  5918. * trying to blow away all the surface locks.
  5919. *
  5920. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  5921. * Wrote it.
  5922. \**************************************************************************/
  5923. HDC
  5924. APIENTRY
  5925. DxDdGetDC(
  5926. HANDLE hSurface,
  5927. PALETTEENTRY* puColorTable
  5928. )
  5929. {
  5930. EDD_LOCK_SURFACE eLockSurface;
  5931. EDD_SURFACE* peSurface;
  5932. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  5933. HDC hdc;
  5934. HBITMAP hbm;
  5935. peSurface = eLockSurface.peLock(hSurface);
  5936. if (peSurface != NULL)
  5937. {
  5938. // DirectDraw doesn't let an application have more than one active
  5939. // GetDC DC to a surface at a time:
  5940. if (peSurface->hdc != 0)
  5941. {
  5942. return(0);
  5943. }
  5944. peDirectDrawGlobal = peSurface->peDirectDrawGlobal;
  5945. // Grab the devlock because hbmDdCreateAndLockGdiSurface grunges
  5946. // around in the global data.
  5947. EDD_SHAREDEVLOCK eDevlock(peDirectDrawGlobal);
  5948. if (!peSurface->bLost)
  5949. {
  5950. // Note that 'hbmDdCreateAndLockGdiSurface' keeps a bitmap cache,
  5951. // so this should usually be pretty quick:
  5952. hbm = hbmDdCreateAndLockGdiSurface(peDirectDrawGlobal,
  5953. peSurface,
  5954. puColorTable);
  5955. if (hbm != NULL)
  5956. {
  5957. // First, try to get a DC from the cache:
  5958. hdc = (HDC) peDirectDrawGlobal->hdcCache;
  5959. if (hdc != NULL)
  5960. {
  5961. // This will succeed only if we atomically managed to
  5962. // grab the cached DC (there may be other threads
  5963. // calling 'bDdReleaseDC' at exactly the same time).
  5964. if (InterlockedCompareExchangePointer(
  5965. &peDirectDrawGlobal->hdcCache,
  5966. NULL,
  5967. (VOID*) hdc) == hdc)
  5968. {
  5969. // Set the DC's ownership to the current process so
  5970. // that it will get cleaned up if the process terminates
  5971. // unexpectedly.
  5972. BOOL bSet = DxEngSetDCOwner(hdc, OBJECT_OWNER_CURRENT);
  5973. ASSERTGDI(bSet, "DxDdGetDC: Cached DC was invalid");
  5974. }
  5975. else
  5976. {
  5977. hdc = NULL;
  5978. }
  5979. }
  5980. if (hdc == NULL)
  5981. {
  5982. // Now, create the DC for the actual drawing, owned by the
  5983. // current process.
  5984. hdc = DxEngCreateMemoryDC(peDirectDrawGlobal->hdev);
  5985. }
  5986. if (hdc)
  5987. {
  5988. // Finally, select our surface into the DC. It
  5989. // doesn't matter if this fails for some bizarre
  5990. // reason; the default bitmap will be stuck in there
  5991. // instead.
  5992. HBITMAP hbmOld = DxEngSelectBitmap(hdc, hbm);
  5993. ASSERTGDI(hbmOld, "DxDdGetDC: Invalid selection");
  5994. peSurface->hdc = hdc;
  5995. // I'm paranoid, so let's verify that we've set things
  5996. // up correctly:
  5997. #if 0 // TODO: DBG - DC
  5998. {
  5999. DCOBJ dco(hdc);
  6000. ASSERTGDI(dco.bValid(),
  6001. "DxDdGetDC: Should have a valid DC");
  6002. ASSERTGDI(!dco.bFullScreen(),
  6003. "DxDdGetDC: DC shouldn't be disabled");
  6004. ASSERTGDI(dco.bSynchronizeAccess(),
  6005. "DxDdGetDC: Should mark devlock needed");
  6006. ASSERTGDI(dco.pSurfaceEff()->bDirectDraw(),
  6007. "DxDdGetDC: Should mark as DDraw surface");
  6008. ASSERTGDI(dco.dctp() == DCTYPE_MEMORY,
  6009. "DxDdGetDC: Should be memory DC");
  6010. }
  6011. #endif
  6012. // For debugging purposes:
  6013. ghdcGetDC = hdc;
  6014. return(hdc);
  6015. }
  6016. vDdUnlockGdiSurface(peSurface);
  6017. }
  6018. else
  6019. {
  6020. WARNING("DxDdGetDC: hbmDdCreateAndLockGdiSurface failed\n");
  6021. }
  6022. }
  6023. }
  6024. else
  6025. {
  6026. WARNING("DxDdGetDC: Couldn't lock the surface\n");
  6027. }
  6028. return(0);
  6029. }
  6030. /******************************Public*Routine******************************\
  6031. * BOOL bDdReleaseDC
  6032. *
  6033. * Deletes a DC created via DdGetDC.
  6034. *
  6035. * The devlock should not be held when entering this function.
  6036. *
  6037. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  6038. * Wrote it.
  6039. \**************************************************************************/
  6040. BOOL
  6041. bDdReleaseDC(
  6042. EDD_SURFACE* peSurface,
  6043. BOOL bForce // True when cleaning up surface
  6044. )
  6045. {
  6046. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  6047. BOOL bRet = FALSE;
  6048. BOOL bClean;
  6049. HDC hdc;
  6050. hdc = peSurface->hdc;
  6051. if (hdc)
  6052. {
  6053. peDirectDrawGlobal = peSurface->peDirectDrawGlobal;
  6054. #if 0 // Temporary disable DC cache for bug 176728
  6055. // See if there's already a DC in the one-deep cache:
  6056. if (!peDirectDrawGlobal->hdcCache)
  6057. {
  6058. // Okay, it looks like we can cache this DC. Clean it up first,
  6059. // which among other things unselects the current DirectDraw
  6060. // GDI surface. Then set the owner to 'none' so that it
  6061. // doesn't get deleted when the current process terminates and
  6062. // no one can touch it until we pick up from cache.
  6063. if (DxEngCleanDC(hdc) &&
  6064. DxEngSetDCOwner(hdc, OBJECT_OWNER_NONE))
  6065. {
  6066. // Atomically try to stick the DC into the cache. Note that
  6067. // it's okay if this fails and we fall into 'bDeleteDCInternal',
  6068. //
  6069. // Note that we use 'InterlockedCompareExchangePointer' so that
  6070. // we can avoid acquiring the devlock in most cases through
  6071. // bDdReleaseDC. So if someone changes this code to acquire
  6072. // the devlock, there's really no pointer in doing this via
  6073. // an Interlocked method.
  6074. if (InterlockedCompareExchangePointer(
  6075. &peDirectDrawGlobal->hdcCache,
  6076. (VOID*) hdc,
  6077. NULL) == NULL)
  6078. {
  6079. // Success, we cached the DC!
  6080. hdc = NULL;
  6081. }
  6082. else
  6083. {
  6084. // Need to be belonging to current process in order to delete.
  6085. // since we already changed the owner to 'none' above.
  6086. DxEngSetDCOwner(hdc, OBJECT_OWNER_CURRENT);
  6087. }
  6088. }
  6089. else
  6090. {
  6091. WARNING("bDdReleaseDC: Not caching DC, app may have deleted it");
  6092. }
  6093. }
  6094. #endif
  6095. if (hdc)
  6096. {
  6097. // There's already a DC in the cache. So delete this one.
  6098. //
  6099. // Note that the application could have called DeleteObject(hdc)
  6100. // or SelectObject(hdc, hSomeOtherBitmap) with the DC we gave
  6101. // them. That's okay, though: nothing will crash, just some of
  6102. // the below operations may fail because they've already been
  6103. // done:
  6104. if (!DxEngDeleteDC(hdc, TRUE))
  6105. {
  6106. WARNING("bDdReleaseDC: Couldn't delete DC\n");
  6107. }
  6108. }
  6109. // Call the driver's DdUnlock if necessary:
  6110. vDdUnlockGdiSurface(peSurface);
  6111. peSurface->hdc = NULL;
  6112. bRet = TRUE;
  6113. }
  6114. return(bRet);
  6115. }
  6116. /******************************Public*Routine******************************\
  6117. * BOOL DxDdReleaseDC
  6118. *
  6119. * User-mode callable routine to delete a DC created via DdGetDC.
  6120. *
  6121. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  6122. * Wrote it.
  6123. \**************************************************************************/
  6124. BOOL
  6125. APIENTRY
  6126. DxDdReleaseDC(
  6127. HANDLE hSurface
  6128. )
  6129. {
  6130. BOOL bRet;
  6131. EDD_LOCK_SURFACE eLockSurface;
  6132. EDD_SURFACE* peSurface;
  6133. bRet = FALSE;
  6134. peSurface = eLockSurface.peLock(hSurface);
  6135. if (peSurface != NULL)
  6136. {
  6137. bRet = bDdReleaseDC(peSurface, FALSE);
  6138. }
  6139. return(bRet);
  6140. }
  6141. /******************************Public*Routine******************************\
  6142. * BOOL DxDdAttachSurface
  6143. *
  6144. * Transmogrified from Win95's ddsatch.c AddAttachedSurface. Don't blame
  6145. * me for this wonderful attach system; the attach links are used by drivers
  6146. * and so we have to be compatible with Win95.
  6147. *
  6148. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  6149. * Wrote it.
  6150. \**************************************************************************/
  6151. BOOL
  6152. APIENTRY
  6153. DxDdAttachSurface(
  6154. HANDLE hSurfaceFrom, // hSurfaceFrom will point 'to' hSurfaceTo
  6155. // (think of this as the main surface)
  6156. HANDLE hSurfaceTo // hSurfaceTo will point 'from' hSurfaceFrom
  6157. ) // (think of this as the secondary surface)
  6158. {
  6159. EDD_LOCK_SURFACE eLockSurfaceFrom;
  6160. EDD_LOCK_SURFACE eLockSurfaceTo;
  6161. EDD_SURFACE* peSurfaceFrom;
  6162. EDD_SURFACE* peSurfaceTo;
  6163. DD_ATTACHLIST* pAttachFrom;
  6164. DD_ATTACHLIST* pAttachTo;
  6165. DD_ATTACHLIST* pAttach;
  6166. DD_ATTACHLIST* pAttachTemp;
  6167. BOOL bAttach;
  6168. BOOL bRet;
  6169. bRet = FALSE; // Assume failure
  6170. peSurfaceFrom = eLockSurfaceFrom.peLock(hSurfaceFrom);
  6171. peSurfaceTo = eLockSurfaceTo.peLock(hSurfaceTo);
  6172. if ((peSurfaceFrom != NULL) && (peSurfaceTo != NULL))
  6173. {
  6174. if (peSurfaceFrom->peDirectDrawLocal == peSurfaceTo->peDirectDrawLocal)
  6175. {
  6176. // Use the devlock to synchronize additions and deletions to
  6177. // the attach list:
  6178. EDD_DEVLOCK eDevLock(peSurfaceFrom->peDirectDrawGlobal);
  6179. // First, see if the surface is already attached or in the
  6180. // chain. If so, don't add it again
  6181. bAttach = TRUE;
  6182. for (pAttach = peSurfaceFrom->lpAttachListFrom;
  6183. pAttach != NULL;
  6184. pAttach = pAttach->lpAttached->lpAttachListFrom)
  6185. {
  6186. for (pAttachTemp = pAttach;
  6187. pAttachTemp != NULL;
  6188. pAttachTemp = pAttachTemp->lpLink)
  6189. {
  6190. if (pedFromLp(pAttachTemp->lpAttached) == peSurfaceTo)
  6191. bAttach = FALSE;
  6192. }
  6193. }
  6194. for (pAttach = peSurfaceTo->lpAttachList;
  6195. pAttach != NULL;
  6196. pAttach = pAttach->lpAttached->lpAttachList)
  6197. {
  6198. for (pAttachTemp = pAttach;
  6199. pAttachTemp != NULL;
  6200. pAttachTemp = pAttachTemp->lpLink)
  6201. {
  6202. if (pedFromLp(pAttachTemp->lpAttached) == peSurfaceTo)
  6203. bAttach = FALSE;
  6204. }
  6205. }
  6206. if (bAttach)
  6207. {
  6208. pAttachFrom = (DD_ATTACHLIST*) PALLOCMEM(sizeof(*pAttachFrom),
  6209. 'addG');
  6210. if (pAttachFrom != NULL)
  6211. {
  6212. pAttachTo = (DD_ATTACHLIST*) PALLOCMEM(sizeof(*pAttachTo),
  6213. 'addG');
  6214. if (pAttachTo != NULL)
  6215. {
  6216. pAttachFrom->lpAttached = peSurfaceTo;
  6217. pAttachFrom->lpLink = peSurfaceFrom->lpAttachList;
  6218. peSurfaceFrom->lpAttachList = pAttachFrom;
  6219. pAttachTo->lpAttached = peSurfaceFrom;
  6220. pAttachTo->lpLink = peSurfaceTo->lpAttachListFrom;
  6221. peSurfaceTo->lpAttachListFrom = pAttachTo;
  6222. vDdUpdateMipMapCount(peSurfaceTo);
  6223. bRet = TRUE;
  6224. }
  6225. if (!bRet)
  6226. {
  6227. VFREEMEM(pAttachFrom);
  6228. }
  6229. }
  6230. }
  6231. else
  6232. {
  6233. WARNING("DxDdAttachSurface: Surfaces already attached");
  6234. bRet = TRUE;
  6235. }
  6236. }
  6237. else
  6238. {
  6239. WARNING("DxDdAttachSurface: Surfaces not for same device");
  6240. }
  6241. }
  6242. else
  6243. {
  6244. WARNING("DxDdAttachSurface: Invalid surface specified");
  6245. }
  6246. return(bRet);
  6247. }
  6248. /******************************Public*Routine******************************\
  6249. * VOID DxDdUnattachSurface
  6250. *
  6251. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  6252. * Wrote it.
  6253. \**************************************************************************/
  6254. VOID
  6255. APIENTRY
  6256. DxDdUnattachSurface(
  6257. HANDLE hSurface,
  6258. HANDLE hSurfaceAttached
  6259. )
  6260. {
  6261. EDD_LOCK_SURFACE eLockSurface;
  6262. EDD_LOCK_SURFACE eLockSurfaceAttached;
  6263. EDD_SURFACE* peSurface;
  6264. EDD_SURFACE* peSurfaceAttached;
  6265. peSurface = eLockSurface.peLock(hSurface);
  6266. peSurfaceAttached = eLockSurfaceAttached.peLock(hSurfaceAttached);
  6267. if ((peSurface != NULL) && (peSurfaceAttached != NULL))
  6268. {
  6269. // Use the devlock to synchronize additions and deletions to
  6270. // the attach list:
  6271. EDD_DEVLOCK eDevLock(peSurface->peDirectDrawGlobal);
  6272. if (bDdRemoveAttachedSurface(peSurface, peSurfaceAttached))
  6273. {
  6274. vDdUpdateMipMapCount(peSurface);
  6275. vDdUpdateMipMapCount(peSurfaceAttached);
  6276. }
  6277. else
  6278. {
  6279. WARNING("DxDdUnattachSurface: Surface not attached");
  6280. }
  6281. }
  6282. else
  6283. {
  6284. WARNING("DxDdUnattachSurface: Invalid surface specified");
  6285. }
  6286. }
  6287. /******************************Public*Routine******************************\
  6288. * DWORD dwDdBltViaGdi
  6289. *
  6290. * This routine will attempt to do a non-stretching, non-system-memory to
  6291. * non-system-memory blt, or system-memory to non-system-memory blt via the
  6292. * driver's CopyBits routine. The motivation for this is two-fold:
  6293. *
  6294. * 1. If the system-memory to video-memory blt has to be emulated, we can
  6295. * do a better emulation job here from the kernel than the HEL can from
  6296. * user-mode, where it has to call Lock/Unlock. We get a couple of
  6297. * benefits:
  6298. *
  6299. * o We can do the blt in one kernel-mode transition, instead
  6300. * of the two previously needed for the lock and unlock;
  6301. *
  6302. * o Because we don't have to hold from user-mode a DirectDraw Lock
  6303. * on the video memory, we don't run the risk of having to
  6304. * redraw if the clipping changes asynchronously;
  6305. *
  6306. * o We can handle blts underneath emulated sprites without having
  6307. * to tear down the sprites, by virtue of going through
  6308. * SpCopyBits. This means, among other things, that the
  6309. * cursor won't flash.
  6310. *
  6311. * 2. For non-system-memory to video-memory blts, we can handle blts to the
  6312. * underneath emulated sprites without having to tear down the sprites,
  6313. * by virtue of going through SpCopyBits.
  6314. *
  6315. * Returns DDHAL_DRIVER_HANDLED if GDI handled the blt; DDHAL_DRIVER_NOTHANDLED
  6316. * if the blt should be handled by the driver's HAL.
  6317. *
  6318. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  6319. * Wrote it.
  6320. \**************************************************************************/
  6321. DWORD
  6322. dwDdBltViaGdi(
  6323. EDD_SURFACE* peSurfaceDest,
  6324. EDD_SURFACE* peSurfaceSrc,
  6325. DD_BLTDATA* pBltData
  6326. )
  6327. {
  6328. DWORD dwRet = DDHAL_DRIVER_NOTHANDLED;
  6329. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  6330. HBITMAP hbmDest;
  6331. HBITMAP hbmSrc;
  6332. BOOL bGdiCandidate;
  6333. // If the sources are compatible, and the destination is video-memory,
  6334. // we may want to call the driver through GDI. We do this primarily
  6335. // to handle blts that occur underneath emulated sprites, so that we
  6336. // don't have to tear down the sprite.
  6337. if ((peSurfaceSrc != NULL) &&
  6338. (peSurfaceDest->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
  6339. {
  6340. peDirectDrawGlobal = peSurfaceDest->peDirectDrawGlobal;
  6341. PDEVOBJ po(peDirectDrawGlobal->hdev);
  6342. // We're acting as the HEL for system-memory to video-memory
  6343. // blts, and so those cases always have to go through GDI.
  6344. //
  6345. // Otherwise, we go through CopyBits only if:
  6346. //
  6347. // o The destination is the primary GDI surface;
  6348. // o Sprites are visible;
  6349. // o The source surface can be accelerated;
  6350. // o There isn't a stretch.
  6351. bGdiCandidate = FALSE;
  6352. // If we're emulating system-memory to video-memory blts, we have
  6353. // to take all system-memory to video-memory blts here (we never
  6354. // said we'd do stretches or anything weird, but we don't want to
  6355. // pass any system-memory to video-memory calls at all to the driver,
  6356. // since it may fall-over when it gets a surface type it doesn't
  6357. // expect).
  6358. if ((peSurfaceSrc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  6359. (peDirectDrawGlobal->flDriver & DD_DRIVER_FLAG_EMULATE_SYSTEM_TO_VIDEO) &&
  6360. (peSurfaceDest->fl & DD_SURFACE_FLAG_PRIMARY))
  6361. {
  6362. bGdiCandidate = TRUE;
  6363. // As a robustness thing, don't let *any* system-memory to video-
  6364. // memory blts down to the driver if it didn't ask for it.
  6365. dwRet = DDHAL_DRIVER_HANDLED;
  6366. }
  6367. // If the destination is the primary GDI surface and any sprites
  6368. // are visible, we also vector through GDI in order to be able to
  6369. // handle blts underneath sprites without flashing.
  6370. else if ((peSurfaceDest->fl & DD_SURFACE_FLAG_PRIMARY) &&
  6371. (DxEngSpSpritesVisible(peDirectDrawGlobal->hdev)) &&
  6372. ((PPFNVALID(po, DeriveSurface)) ||
  6373. (peSurfaceSrc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)))
  6374. {
  6375. bGdiCandidate = TRUE;
  6376. }
  6377. // Add cases where CopyBits can not handle the blit
  6378. //
  6379. // 1. color keying
  6380. // 2. FX blit(mirror)
  6381. // 3. Blit has color space conversion, e.g. YUV to RGB
  6382. if (bGdiCandidate)
  6383. {
  6384. bGdiCandidate=FALSE;
  6385. if (!(pBltData->dwFlags & (DDBLT_KEYSRCOVERRIDE |
  6386. DDBLT_KEYDESTOVERRIDE |
  6387. DDBLT_KEYSRC |
  6388. DDBLT_KEYDEST |
  6389. DDBLT_DDFX)) &&
  6390. (peSurfaceDest->ddpfSurface.dwRGBBitCount
  6391. == peSurfaceSrc->ddpfSurface.dwRGBBitCount))
  6392. {
  6393. DWORD dwDestFlags = peSurfaceDest->ddpfSurface.dwFlags;
  6394. DWORD dwSrcFlags = peSurfaceSrc->ddpfSurface.dwFlags;
  6395. dwDestFlags &= (DDPF_RGB|DDPF_PALETTEINDEXED8);
  6396. dwSrcFlags &= (DDPF_RGB|DDPF_PALETTEINDEXED8);
  6397. if ((dwDestFlags != 0) && (dwDestFlags==dwSrcFlags))
  6398. {
  6399. if (!(dwSrcFlags & DDPF_PALETTEINDEXED8))
  6400. {
  6401. if ((peSurfaceDest->ddpfSurface.dwRBitMask
  6402. == peSurfaceSrc->ddpfSurface.dwRBitMask) &&
  6403. (peSurfaceDest->ddpfSurface.dwGBitMask
  6404. == peSurfaceSrc->ddpfSurface.dwGBitMask) &&
  6405. (peSurfaceDest->ddpfSurface.dwBBitMask
  6406. == peSurfaceSrc->ddpfSurface.dwBBitMask))
  6407. {
  6408. bGdiCandidate=TRUE;
  6409. }
  6410. }
  6411. else
  6412. {
  6413. bGdiCandidate=TRUE;
  6414. }
  6415. }
  6416. }
  6417. }
  6418. if ((bGdiCandidate) &&
  6419. ((pBltData->rDest.right - pBltData->rDest.left)
  6420. == (pBltData->rSrc.right - pBltData->rSrc.left)) &&
  6421. ((pBltData->rDest.bottom - pBltData->rDest.top)
  6422. == (pBltData->rSrc.bottom - pBltData->rSrc.top)))
  6423. {
  6424. // At this point, GDI is definitely going to handle the
  6425. // blt (or die trying):
  6426. dwRet = DDHAL_DRIVER_HANDLED;
  6427. pBltData->ddRVal = DD_OK;
  6428. // If a hardware flip is pending on this surface, then wait for
  6429. // the flip to finish before continuing:
  6430. if (peSurfaceDest->fl & DD_SURFACE_FLAG_FLIP_PENDING)
  6431. {
  6432. ASSERTGDI(
  6433. (peDirectDrawGlobal->SurfaceCallBacks.dwFlags &
  6434. DDHAL_SURFCB32_GETFLIPSTATUS) &&
  6435. peDirectDrawGlobal->SurfaceCallBacks.GetFlipStatus,
  6436. "Flip pending but GetFlipStatus unsupported by driver?");
  6437. DD_GETFLIPSTATUSDATA GetFlipStatusData;
  6438. DWORD dwFlipRet;
  6439. GetFlipStatusData.lpDD = peDirectDrawGlobal;
  6440. GetFlipStatusData.lpDDSurface = peSurfaceDest;
  6441. GetFlipStatusData.dwFlags = DDGFS_ISFLIPDONE;
  6442. GetFlipStatusData.GetFlipStatus = NULL;
  6443. GetFlipStatusData.ddRVal = DDERR_GENERIC;
  6444. do
  6445. {
  6446. dwFlipRet = peDirectDrawGlobal->
  6447. SurfaceCallBacks.GetFlipStatus(&GetFlipStatusData);
  6448. } while (
  6449. (dwFlipRet == DDHAL_DRIVER_HANDLED) &&
  6450. (GetFlipStatusData.ddRVal == DDERR_WASSTILLDRAWING));
  6451. peSurfaceDest->fl &= ~DD_SURFACE_FLAG_FLIP_PENDING;
  6452. }
  6453. // If the surfaces are primary (GDI) surfaces, just use
  6454. // the GDI surface we have stashed in the PDEV:
  6455. hbmDest = (HBITMAP) po.hsurf();
  6456. hbmSrc = (HBITMAP) po.hsurf();
  6457. if (!(peSurfaceDest->fl & DD_SURFACE_FLAG_PRIMARY))
  6458. {
  6459. hbmDest = hbmDdCreateAndLockGdiSurface(peDirectDrawGlobal,
  6460. peSurfaceDest,
  6461. NULL);
  6462. }
  6463. if (!(peSurfaceSrc->fl & DD_SURFACE_FLAG_PRIMARY))
  6464. {
  6465. hbmSrc = hbmDdCreateAndLockGdiSurface(peDirectDrawGlobal,
  6466. peSurfaceSrc,
  6467. NULL);
  6468. }
  6469. SURFOBJ *psoDest = EngLockSurface((HSURF) hbmDest);
  6470. SURFOBJ *psoSrc = EngLockSurface((HSURF) hbmSrc);
  6471. if (psoDest && psoSrc)
  6472. {
  6473. PDEVOBJ po(peDirectDrawGlobal->hdev);
  6474. // A malicious app may have given us stretch values on
  6475. // system-memory to video-memory blts, so check:
  6476. if (((pBltData->rDest.right - pBltData->rDest.left)
  6477. == (pBltData->rSrc.right - pBltData->rSrc.left)) &&
  6478. ((pBltData->rDest.bottom - pBltData->rDest.top)
  6479. == (pBltData->rSrc.bottom - pBltData->rSrc.top)))
  6480. {
  6481. (*PPFNGET(po, CopyBits, SURFOBJ_HOOK(psoDest)))
  6482. (psoDest,
  6483. psoSrc,
  6484. NULL,
  6485. NULL,
  6486. &pBltData->rDest,
  6487. (POINTL*) &pBltData->rSrc);
  6488. }
  6489. }
  6490. if (psoDest)
  6491. {
  6492. EngUnlockSurface(psoDest);
  6493. }
  6494. if (psoSrc)
  6495. {
  6496. EngUnlockSurface(psoSrc);
  6497. }
  6498. if (!(peSurfaceDest->fl & DD_SURFACE_FLAG_PRIMARY))
  6499. {
  6500. vDdUnlockGdiSurface(peSurfaceDest);
  6501. }
  6502. if (!(peSurfaceSrc->fl & DD_SURFACE_FLAG_PRIMARY))
  6503. {
  6504. vDdUnlockGdiSurface(peSurfaceSrc);
  6505. }
  6506. }
  6507. }
  6508. return(dwRet);
  6509. }
  6510. /******************************Public*Routine******************************\
  6511. * DWORD DxDdBlt
  6512. *
  6513. * DirectDraw blt.
  6514. *
  6515. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  6516. * Wrote it.
  6517. \**************************************************************************/
  6518. DWORD
  6519. APIENTRY
  6520. DxDdBlt(
  6521. HANDLE hSurfaceDest,
  6522. HANDLE hSurfaceSrc,
  6523. PDD_BLTDATA puBltData
  6524. )
  6525. {
  6526. DWORD dwRet;
  6527. DD_BLTDATA BltData;
  6528. #ifdef DX_REDIRECTION
  6529. HWND hWnd;
  6530. #endif // DX_REDIRECTION
  6531. __try
  6532. {
  6533. ProbeForRead(puBltData, sizeof(DD_BLTDATA), sizeof(DWORD));
  6534. // To save some copying time, we copy only those fields which are
  6535. // supported for NT drivers:
  6536. BltData.rDest.left = puBltData->rDest.left;
  6537. BltData.rDest.top = puBltData->rDest.top;
  6538. BltData.rDest.right = puBltData->rDest.right;
  6539. BltData.rDest.bottom = puBltData->rDest.bottom;
  6540. BltData.rSrc.left = puBltData->rSrc.left;
  6541. BltData.rSrc.top = puBltData->rSrc.top;
  6542. BltData.rSrc.right = puBltData->rSrc.right;
  6543. BltData.rSrc.bottom = puBltData->rSrc.bottom;
  6544. BltData.dwFlags = puBltData->dwFlags;
  6545. BltData.bltFX.dwFillColor = puBltData->bltFX.dwFillColor;
  6546. BltData.bltFX.ddckSrcColorkey = puBltData->bltFX.ddckSrcColorkey;
  6547. BltData.bltFX.ddckDestColorkey= puBltData->bltFX.ddckDestColorkey;
  6548. BltData.bltFX.dwDDFX = puBltData->bltFX.dwDDFX;
  6549. #ifdef DX_REDIRECTION
  6550. // DD_BLTDATA.Blt member contains hWnd.
  6551. hWnd = (HWND)(puBltData->Blt);
  6552. #endif // DX_REDIRECTION
  6553. }
  6554. __except(EXCEPTION_EXECUTE_HANDLER)
  6555. {
  6556. return(DDHAL_DRIVER_NOTHANDLED);
  6557. }
  6558. dwRet = DDHAL_DRIVER_NOTHANDLED;
  6559. BltData.ddRVal = DDERR_GENERIC;
  6560. #ifdef DX_REDIRECTION
  6561. // if hWnd is given and redirection is enabled on the hWnd,
  6562. // we just fail this call here, and let ddraw runtime to uses
  6563. // emulation code, which eventually call GDI Blt functions.
  6564. if (hWnd)
  6565. {
  6566. if (DxEngGetRedirectionBitmap(hWnd))
  6567. {
  6568. return(dwRet);
  6569. }
  6570. }
  6571. #endif // DX_REDIRECTION
  6572. EDD_SURFACE* peSurfaceDest;
  6573. EDD_SURFACE* peSurfaceSrc;
  6574. DWORD dwFlags;
  6575. EDD_LOCK_SURFACE eLockSurfaceDest;
  6576. EDD_LOCK_SURFACE eLockSurfaceSrc;
  6577. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  6578. DWORD dwSrcCaps;
  6579. DWORD dwDestCaps;
  6580. DDNTCORECAPS* pCaps;
  6581. BOOL bUnTearDown;
  6582. peSurfaceDest = eLockSurfaceDest.peLock(hSurfaceDest);
  6583. BltData.lpDDDestSurface = peSurfaceDest;
  6584. if (peSurfaceDest != NULL)
  6585. {
  6586. peDirectDrawGlobal = peSurfaceDest->peDirectDrawGlobal;
  6587. // We support only a specific set of Blt calls down to the driver
  6588. // that we're willing to support and to test.
  6589. dwFlags = BltData.dwFlags;
  6590. if (((dwFlags & (DDBLT_ROTATIONANGLE)) == 0) &&
  6591. ((dwFlags & (DDBLT_ROP
  6592. | DDBLT_COLORFILL
  6593. | DDBLT_DEPTHFILL)) != 0))
  6594. {
  6595. // I think ROPs are goofy, so we always tell the application
  6596. // that our hardware can only do SRCCOPY blts, but we should
  6597. // make sure the driver doesn't fall over if it gets something
  6598. // unexpected. And they can look at this even if DDBLT_DDFX
  6599. // isn't set:
  6600. BltData.bltFX.dwROP = 0xCC0000; // SRCCOPY in DirectDraw format
  6601. // No support for IsClipped for now -- we would have to
  6602. // validate and copy the prDestRects array:
  6603. BltData.IsClipped = FALSE;
  6604. if (dwFlags & DDBLT_DDFX)
  6605. {
  6606. // The only DDBLT_DDFX functionality we allow down to the
  6607. // driver is DDBLTFX_NOTEARING:
  6608. // DDBLTFX_MIRRORLEFTRIGHT
  6609. // DDBLTFX_MIRRORUPDOWN
  6610. if (BltData.bltFX.dwDDFX & ~(DDBLTFX_NOTEARING
  6611. |DDBLTFX_MIRRORLEFTRIGHT
  6612. |DDBLTFX_MIRRORUPDOWN)
  6613. )
  6614. {
  6615. WARNING("DxDdBlt: Invalid dwDDFX\n");
  6616. return(dwRet);
  6617. }
  6618. }
  6619. if (dwFlags & (DDBLT_COLORFILL | DDBLT_DEPTHFILL))
  6620. {
  6621. // Do simpler stuff 'cause we don't need to lock a source:
  6622. BltData.lpDDSrcSurface = NULL;
  6623. peSurfaceSrc = NULL;
  6624. if (peSurfaceDest->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  6625. {
  6626. WARNING("DxDdBlt: Can't blt to system memory surface");
  6627. return(dwRet);
  6628. }
  6629. }
  6630. else
  6631. {
  6632. // Lock the source surface:
  6633. peSurfaceSrc = eLockSurfaceSrc.peLock(hSurfaceSrc);
  6634. BltData.lpDDSrcSurface = peSurfaceSrc;
  6635. // Ensure that both surfaces belong to the same DirectDraw
  6636. // object, and check source rectangle:
  6637. if ((peSurfaceSrc == NULL) ||
  6638. (peSurfaceSrc->peDirectDrawLocal !=
  6639. peSurfaceDest->peDirectDrawLocal) ||
  6640. (BltData.rSrc.left < 0) ||
  6641. (BltData.rSrc.top < 0) ||
  6642. (BltData.rSrc.right > (LONG) peSurfaceSrc->wWidth) ||
  6643. (BltData.rSrc.bottom > (LONG) peSurfaceSrc->wHeight) ||
  6644. (BltData.rSrc.left >= BltData.rSrc.right) ||
  6645. (BltData.rSrc.top >= BltData.rSrc.bottom))
  6646. {
  6647. WARNING("DxDdBlt: Invalid source surface or source rectangle\n");
  6648. return(dwRet);
  6649. }
  6650. // Make sure the blts are between surface types that the
  6651. // driver will expect, otherwise the driver may fall-over
  6652. // if called with NtCrash or some other malicious program.
  6653. dwSrcCaps = peSurfaceSrc->ddsCaps.dwCaps;
  6654. dwDestCaps = peSurfaceDest->ddsCaps.dwCaps;
  6655. pCaps = &peDirectDrawGlobal->HalInfo.ddCaps;
  6656. // If the dest surface is the primary, DDraw will
  6657. // ask the kernel to Blt from system to video memory
  6658. // even if the driver doesn't specify this capability
  6659. // because it knows that the kernel can emulate it properly.
  6660. // The kernel used to set this cap, be we changed it because
  6661. // it was eating up too many handles and creating inefficiencies.
  6662. if (((dwSrcCaps & DDSCAPS_VIDEOMEMORY) &&
  6663. (dwDestCaps & DDSCAPS_SYSTEMMEMORY) &&
  6664. !(pCaps->dwVSBCaps & DDCAPS_BLT)) ||
  6665. ((dwDestCaps & DDSCAPS_VIDEOMEMORY) &&
  6666. (dwSrcCaps & DDSCAPS_SYSTEMMEMORY) &&
  6667. (!(pCaps->dwSVBCaps & DDCAPS_BLT) &&
  6668. !(peSurfaceDest->fl & DD_SURFACE_FLAG_PRIMARY))) ||
  6669. ((dwSrcCaps & DDSCAPS_SYSTEMMEMORY) &&
  6670. (dwDestCaps & DDSCAPS_SYSTEMMEMORY) &&
  6671. !(pCaps->dwSSBCaps & DDCAPS_BLT)))
  6672. {
  6673. WARNING("DxDdBlt: Illegal system memory surface");
  6674. return(dwRet);
  6675. }
  6676. }
  6677. // Make sure that we weren't given rectangle coordinates
  6678. // which might cause the driver to crash. Note that we
  6679. // don't allow inverting stretch blts:
  6680. if ((BltData.rDest.left >= 0) &&
  6681. (BltData.rDest.top >= 0) &&
  6682. (BltData.rDest.right <= (LONG) peSurfaceDest->wWidth) &&
  6683. (BltData.rDest.bottom <= (LONG) peSurfaceDest->wHeight) &&
  6684. (BltData.rDest.left < BltData.rDest.right) &&
  6685. (BltData.rDest.top < BltData.rDest.bottom))
  6686. {
  6687. // Make sure that the surfaces aren't associated
  6688. // with a PDEV whose mode has gone away.
  6689. //
  6690. // Also ensure that there are no outstanding
  6691. // surface locks if running on a brain-dead video
  6692. // card that crashes if the accelerator runs at
  6693. // the same time the frame buffer is accessed.
  6694. EDD_SHAREDEVLOCK eDevlock(peDirectDrawGlobal);
  6695. // We will return SURFACELOST when ...
  6696. //
  6697. // 1) This device is suspended.
  6698. // 2) The driver managed surface is managed by other device.
  6699. // 3) One of surface is losted.
  6700. // 4) The visible region has been changed when surface is primary.
  6701. if (peDirectDrawGlobal->bSuspended) // 1)
  6702. {
  6703. dwRet = DDHAL_DRIVER_HANDLED;
  6704. BltData.ddRVal = DDERR_SURFACELOST;
  6705. }
  6706. else if ((peSurfaceDest->fl & DD_SURFACE_FLAG_WRONG_DRIVER) ||
  6707. ((peSurfaceSrc != NULL) &&
  6708. (peSurfaceSrc->fl & DD_SURFACE_FLAG_WRONG_DRIVER))) // 2)
  6709. {
  6710. dwRet = DDHAL_DRIVER_HANDLED;
  6711. BltData.ddRVal = DDERR_SURFACELOST;
  6712. }
  6713. else if ((peSurfaceDest->bLost) ||
  6714. ((peSurfaceSrc != NULL) && (peSurfaceSrc->bLost))) // 3)
  6715. {
  6716. dwRet = DDHAL_DRIVER_HANDLED;
  6717. BltData.ddRVal = DDERR_SURFACELOST;
  6718. }
  6719. else if ((peSurfaceDest->fl & DD_SURFACE_FLAG_PRIMARY) &&
  6720. (peSurfaceDest->iVisRgnUniqueness != VISRGN_UNIQUENESS())) // 4)
  6721. {
  6722. // The VisRgn changed since the application last queried
  6723. // it; fail the call with a unique error code so that
  6724. // they know to requery the VisRgn and try again:
  6725. dwRet = DDHAL_DRIVER_HANDLED;
  6726. BltData.ddRVal = DDERR_VISRGNCHANGED;
  6727. }
  6728. else
  6729. {
  6730. if (peDirectDrawGlobal->HalInfo.ddCaps.dwCaps & DDCAPS_BLT)
  6731. {
  6732. BltData.lpDD = peDirectDrawGlobal;
  6733. // Give GDI a crack at doing the Blt. GDI may handle
  6734. // the blt only for the following cases:
  6735. //
  6736. // o When the blt occurs underneath a simulated sprite;
  6737. // o To emulate system-memory to video-memory HEL blts.
  6738. dwRet = dwDdBltViaGdi(peSurfaceDest,
  6739. peSurfaceSrc,
  6740. &BltData);
  6741. if (dwRet != DDHAL_DRIVER_HANDLED)
  6742. {
  6743. // This is the normal code path. First, exclude the
  6744. // mouse pointer and any other sprites if necessary:
  6745. DEVEXCLUDERECT dxo;
  6746. if (peSurfaceDest->fl & DD_SURFACE_FLAG_PRIMARY)
  6747. {
  6748. dxo.vExclude(peDirectDrawGlobal->hdev,
  6749. &BltData.rDest);
  6750. }
  6751. // Call the driver to do the blt:
  6752. dwRet = peDirectDrawGlobal->SurfaceCallBacks.
  6753. Blt(&BltData);
  6754. // If there was a flip pending, and the hardware
  6755. // blt succeeded, then unset the flag:
  6756. if ((peSurfaceDest->fl & DD_SURFACE_FLAG_FLIP_PENDING) &&
  6757. (dwRet == DDHAL_DRIVER_HANDLED) &&
  6758. (BltData.ddRVal == DD_OK))
  6759. {
  6760. peSurfaceDest->fl &= ~DD_SURFACE_FLAG_FLIP_PENDING;
  6761. }
  6762. }
  6763. // If the destination surface is the primary, update
  6764. // the bounds rect for this device:
  6765. if ((peSurfaceDest->fl & DD_SURFACE_FLAG_PRIMARY) &&
  6766. (dwRet == DDHAL_DRIVER_HANDLED) &&
  6767. (BltData.ddRVal == DD_OK))
  6768. {
  6769. // Union the current DirectDraw bounds rectangle
  6770. // with the destination blt rectangle:
  6771. //
  6772. // BltData.IsClipped will always be FALSE since
  6773. // it is currently unsupported, so we only
  6774. // consider BltData.rDest:
  6775. if (peDirectDrawGlobal->fl & DD_GLOBAL_FLAG_BOUNDS_SET)
  6776. {
  6777. if (BltData.rDest.left < peDirectDrawGlobal->rclBounds.left)
  6778. peDirectDrawGlobal->rclBounds.left = BltData.rDest.left;
  6779. if (BltData.rDest.top < peDirectDrawGlobal->rclBounds.top)
  6780. peDirectDrawGlobal->rclBounds.top = BltData.rDest.top;
  6781. if (BltData.rDest.right > peDirectDrawGlobal->rclBounds.right)
  6782. peDirectDrawGlobal->rclBounds.right = BltData.rDest.right;
  6783. if (BltData.rDest.bottom > peDirectDrawGlobal->rclBounds.bottom)
  6784. peDirectDrawGlobal->rclBounds.bottom = BltData.rDest.bottom;
  6785. }
  6786. else
  6787. {
  6788. peDirectDrawGlobal->rclBounds = BltData.rDest;
  6789. peDirectDrawGlobal->fl |= DD_GLOBAL_FLAG_BOUNDS_SET;
  6790. }
  6791. }
  6792. }
  6793. }
  6794. }
  6795. else
  6796. {
  6797. WARNING("DxDdBlt: Invalid destination rectangle\n");
  6798. }
  6799. }
  6800. else
  6801. {
  6802. WARNING("DxDdBlt: Invalid dwFlags\n");
  6803. }
  6804. }
  6805. else
  6806. {
  6807. WARNING("DxDdBlt: Couldn't lock destination surface\n");
  6808. }
  6809. // We have to wrap this in another try-except because the user-mode
  6810. // memory containing the input may have been deallocated by now:
  6811. __try
  6812. {
  6813. ProbeAndWriteRVal(&puBltData->ddRVal, BltData.ddRVal);
  6814. }
  6815. __except(EXCEPTION_EXECUTE_HANDLER)
  6816. {
  6817. }
  6818. return(dwRet);
  6819. }
  6820. /******************************Public*Routine******************************\
  6821. * DWORD DxDdFlip
  6822. *
  6823. * DirectDraw flip.
  6824. *
  6825. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  6826. * Wrote it.
  6827. \**************************************************************************/
  6828. DWORD
  6829. APIENTRY
  6830. DxDdFlip(
  6831. HANDLE hSurfaceCurrent,
  6832. HANDLE hSurfaceTarget,
  6833. HANDLE hSurfaceCurrentLeft,
  6834. HANDLE hSurfaceTargetLeft,
  6835. PDD_FLIPDATA puFlipData
  6836. )
  6837. {
  6838. DWORD dwRet;
  6839. DD_FLIPDATA FlipData;
  6840. __try
  6841. {
  6842. FlipData = ProbeAndReadStructure(puFlipData, DD_FLIPDATA);
  6843. }
  6844. __except(EXCEPTION_EXECUTE_HANDLER)
  6845. {
  6846. return(DDHAL_DRIVER_NOTHANDLED);
  6847. }
  6848. dwRet = DDHAL_DRIVER_NOTHANDLED;
  6849. FlipData.ddRVal = DDERR_GENERIC;
  6850. EDD_SURFACE* peSurfaceCurrent;
  6851. EDD_SURFACE* peSurfaceCurrentLeft;
  6852. EDD_SURFACE* peSurfaceTarget;
  6853. EDD_SURFACE* peSurfaceTargetLeft;
  6854. EDD_LOCK_SURFACE eLockSurfaceCurrent;
  6855. EDD_LOCK_SURFACE eLockSurfaceCurrentLeft;
  6856. EDD_LOCK_SURFACE eLockSurfaceTarget;
  6857. EDD_LOCK_SURFACE eLockSurfaceTargetLeft;
  6858. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  6859. peSurfaceCurrent = eLockSurfaceCurrent.peLock(hSurfaceCurrent);
  6860. peSurfaceTarget = eLockSurfaceTarget.peLock(hSurfaceTarget);
  6861. BOOL bLeftSurfaceOk=FALSE;
  6862. if (FlipData.dwFlags & DDFLIP_STEREO)
  6863. {
  6864. peSurfaceTargetLeft = eLockSurfaceTargetLeft.peLock(hSurfaceTargetLeft);
  6865. peSurfaceCurrentLeft = eLockSurfaceCurrentLeft.peLock(hSurfaceCurrentLeft);
  6866. // first check if left surface is ok
  6867. // in stereo mode
  6868. if ((peSurfaceCurrentLeft != NULL) &&
  6869. (peSurfaceTargetLeft != NULL) &&
  6870. (peSurfaceCurrent != peSurfaceTargetLeft) &&
  6871. (peSurfaceCurrent != peSurfaceCurrentLeft) &&
  6872. (peSurfaceTarget != peSurfaceTargetLeft) &&
  6873. (peSurfaceTarget != peSurfaceCurrentLeft) &&
  6874. (peSurfaceCurrentLeft != peSurfaceTargetLeft) &&
  6875. (peSurfaceCurrent->peDirectDrawLocal ==
  6876. peSurfaceTargetLeft->peDirectDrawLocal) &&
  6877. (peSurfaceCurrent->peDirectDrawLocal ==
  6878. peSurfaceCurrentLeft->peDirectDrawLocal)
  6879. )
  6880. {
  6881. bLeftSurfaceOk=TRUE;
  6882. } else
  6883. {
  6884. peSurfaceTargetLeft = NULL;
  6885. peSurfaceCurrentLeft = NULL;
  6886. }
  6887. } else
  6888. {
  6889. peSurfaceTargetLeft = NULL;
  6890. peSurfaceCurrentLeft = NULL;
  6891. bLeftSurfaceOk=TRUE;
  6892. }
  6893. // Make sure surfaces belong to the same DirectDraw object and no
  6894. // bad commands are specified:
  6895. if ( bLeftSurfaceOk &&
  6896. (peSurfaceCurrent != NULL) &&
  6897. (peSurfaceTarget != NULL) &&
  6898. (peSurfaceCurrent->peDirectDrawLocal ==
  6899. peSurfaceTarget->peDirectDrawLocal) &&
  6900. ((FlipData.dwFlags & ~DDFLIP_VALID) == 0))
  6901. {
  6902. peDirectDrawGlobal = peSurfaceCurrent->peDirectDrawGlobal;
  6903. // Flipping to the same surface is OK as long as it's an overlay
  6904. // and the ODD/EVEN flag is specified and supported by the driver
  6905. if ((peSurfaceCurrent != peSurfaceTarget) ||
  6906. ((FlipData.dwFlags & (DDFLIP_EVEN|DDFLIP_ODD)) &&
  6907. ( peSurfaceCurrent->ddsCaps.dwCaps & DDSCAPS_OVERLAY ) &&
  6908. (peDirectDrawGlobal->HalInfo.ddCaps.dwCaps2 & DDCAPS2_CANFLIPODDEVEN)))
  6909. {
  6910. // Make sure that the target is flippable:
  6911. if (peSurfaceCurrentLeft != NULL && peSurfaceTargetLeft != NULL)
  6912. {
  6913. if (!((peSurfaceCurrent->wHeight == peSurfaceTargetLeft->wHeight) &&
  6914. (peSurfaceCurrent->wWidth == peSurfaceTargetLeft->wWidth) &&
  6915. (peSurfaceCurrentLeft->wHeight == peSurfaceTargetLeft->wHeight) &&
  6916. (peSurfaceCurrentLeft->wWidth == peSurfaceTargetLeft->wWidth) &&
  6917. !(peSurfaceCurrentLeft->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  6918. !(peSurfaceTargetLeft->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)))
  6919. {
  6920. bLeftSurfaceOk = FALSE;
  6921. }
  6922. }
  6923. if ( bLeftSurfaceOk &&
  6924. (peDirectDrawGlobal->SurfaceCallBacks.dwFlags & DDHAL_SURFCB32_FLIP) &&
  6925. (peSurfaceCurrent->wHeight == peSurfaceTarget->wHeight) &&
  6926. (peSurfaceCurrent->wWidth == peSurfaceTarget->wWidth) &&
  6927. !(peSurfaceCurrent->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  6928. !(peSurfaceTarget->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY))
  6929. {
  6930. FlipData.lpDD = peDirectDrawGlobal;
  6931. FlipData.lpSurfCurr = peSurfaceCurrent;
  6932. FlipData.lpSurfCurrLeft = peSurfaceCurrentLeft;
  6933. FlipData.lpSurfTarg = peSurfaceTarget;
  6934. FlipData.lpSurfTargLeft = peSurfaceTargetLeft;
  6935. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  6936. if (peSurfaceCurrentLeft != NULL && peSurfaceTargetLeft != NULL)
  6937. {
  6938. bLeftSurfaceOk =!(peSurfaceCurrentLeft->bLost) &&
  6939. !(peSurfaceTargetLeft->bLost);
  6940. }
  6941. if (!bLeftSurfaceOk ||
  6942. (peSurfaceCurrent->bLost) ||
  6943. (peSurfaceTarget->bLost))
  6944. {
  6945. dwRet = DDHAL_DRIVER_HANDLED;
  6946. FlipData.ddRVal = DDERR_SURFACELOST;
  6947. }
  6948. else
  6949. {
  6950. dwRet = peDirectDrawGlobal->SurfaceCallBacks.Flip(&FlipData);
  6951. // Remember this surface so that if it gets deleted, we can
  6952. // flip back to the GDI surface, assuming it's not an
  6953. // overlay surface:
  6954. if ((dwRet == DDHAL_DRIVER_HANDLED) &&
  6955. (FlipData.ddRVal == DD_OK))
  6956. {
  6957. // Keep track of the hardware flip on this surface so if
  6958. // we do emulated blts to it, we will wait for the flip
  6959. // to complete first:
  6960. if(peSurfaceCurrent != peSurfaceTarget)
  6961. {
  6962. peSurfaceCurrent->fl |= DD_SURFACE_FLAG_FLIP_PENDING;
  6963. }
  6964. if(peSurfaceTarget->ddsCaps.dwCaps & DDSCAPS_OVERLAY)
  6965. {
  6966. if(peSurfaceCurrent->fl & DD_SURFACE_FLAG_UPDATE_OVERLAY_CALLED)
  6967. {
  6968. peSurfaceTarget->fl |= DD_SURFACE_FLAG_UPDATE_OVERLAY_CALLED;
  6969. if(peSurfaceCurrent != peSurfaceTarget)
  6970. {
  6971. peSurfaceCurrent->fl &= ~DD_SURFACE_FLAG_UPDATE_OVERLAY_CALLED;
  6972. }
  6973. }
  6974. }
  6975. else
  6976. {
  6977. peSurfaceCurrent->ddsCaps.dwCaps &= ~DDSCAPS_PRIMARYSURFACE;
  6978. peSurfaceTarget->ddsCaps.dwCaps |= DDSCAPS_PRIMARYSURFACE;
  6979. peDirectDrawGlobal->peSurfaceCurrent = peSurfaceTarget;
  6980. if (peSurfaceCurrent->fl & DD_SURFACE_FLAG_PRIMARY)
  6981. {
  6982. peDirectDrawGlobal->peSurfacePrimary
  6983. = peSurfaceCurrent;
  6984. }
  6985. }
  6986. }
  6987. }
  6988. }
  6989. else
  6990. {
  6991. WARNING("DxDdFlip: Non-flippable surface\n");
  6992. }
  6993. }
  6994. else
  6995. {
  6996. WARNING("DxDdFlip: Invalid flip to same surface\n");
  6997. }
  6998. }
  6999. else
  7000. {
  7001. WARNING("DxDdFlip: Invalid surfaces or dwFlags\n");
  7002. }
  7003. // We have to wrap this in another try-except because the user-mode
  7004. // memory containing the input may have been deallocated by now:
  7005. __try
  7006. {
  7007. ProbeAndWriteRVal(&puFlipData->ddRVal, FlipData.ddRVal);
  7008. }
  7009. __except(EXCEPTION_EXECUTE_HANDLER)
  7010. {
  7011. }
  7012. return(dwRet);
  7013. }
  7014. /******************************Public*Routine******************************\
  7015. * DWORD DxDdLock
  7016. *
  7017. * DirectDraw function to return a user-mode pointer to the screen or
  7018. * off-screen surface.
  7019. *
  7020. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  7021. * Wrote it.
  7022. \**************************************************************************/
  7023. DWORD
  7024. APIENTRY
  7025. DxDdLock(
  7026. HANDLE hSurface,
  7027. PDD_LOCKDATA puLockData,
  7028. HDC hdcClip
  7029. )
  7030. {
  7031. DD_LOCKDATA LockData;
  7032. __try
  7033. {
  7034. LockData = ProbeAndReadStructure(puLockData, DD_LOCKDATA);
  7035. }
  7036. __except(EXCEPTION_EXECUTE_HANDLER)
  7037. {
  7038. return(DDHAL_DRIVER_HANDLED);
  7039. }
  7040. LockData.ddRVal = DDERR_GENERIC;
  7041. EDD_SURFACE* peSurface;
  7042. EDD_LOCK_SURFACE eLockSurface;
  7043. // Note that we have to let down DDLOCK_READONLY, DDLOCK_WRITE,
  7044. // and DDLOCK_WAIT for compatibility. Note also that a
  7045. // DDLOCK_SURFACEMEMORY flag also gets passed down by default.
  7046. peSurface = eLockSurface.peLock(hSurface);
  7047. if ((peSurface != NULL) &&
  7048. ((LockData.dwFlags & ~(DDLOCK_VALID)) == 0))
  7049. {
  7050. LockData.lpSurfData = pDdLockSurfaceOrBuffer(peSurface,
  7051. LockData.bHasRect,
  7052. &LockData.rArea,
  7053. // We remove the wait flag since it better to spin in user mode
  7054. LockData.dwFlags & (~DDLOCK_WAIT),
  7055. &LockData.ddRVal);
  7056. }
  7057. else
  7058. {
  7059. WARNING("DxDdLock: Invalid surface or flags\n");
  7060. }
  7061. // We have to wrap this in another try-except because the user-mode
  7062. // memory containing the input may have been deallocated by now:
  7063. __try
  7064. {
  7065. ProbeAndWriteHandle(&puLockData->lpSurfData, LockData.lpSurfData);
  7066. ProbeAndWriteRVal(&puLockData->ddRVal, LockData.ddRVal);
  7067. }
  7068. __except(EXCEPTION_EXECUTE_HANDLER)
  7069. {
  7070. }
  7071. // This function must always return DDHAL_DRIVER_HANDLED, otherwise
  7072. // DirectDraw will simply use the 'fpVidMem' value, which on NT is
  7073. // an offset and not a pointer:
  7074. return(DDHAL_DRIVER_HANDLED);
  7075. }
  7076. /******************************Public*Routine******************************\
  7077. * DWORD DxDdUnlock
  7078. *
  7079. * DirectDraw unlock.
  7080. *
  7081. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  7082. * Wrote it.
  7083. \**************************************************************************/
  7084. DWORD
  7085. APIENTRY
  7086. DxDdUnlock(
  7087. HANDLE hSurface,
  7088. PDD_UNLOCKDATA puUnlockData
  7089. )
  7090. {
  7091. DWORD dwRet;
  7092. DD_UNLOCKDATA UnlockData;
  7093. __try
  7094. {
  7095. UnlockData = ProbeAndReadStructure(puUnlockData, DD_UNLOCKDATA);
  7096. }
  7097. __except(EXCEPTION_EXECUTE_HANDLER)
  7098. {
  7099. return(DDHAL_DRIVER_HANDLED);
  7100. }
  7101. UnlockData.ddRVal = DDERR_GENERIC;
  7102. EDD_SURFACE* peSurface;
  7103. EDD_LOCK_SURFACE eLockSurface;
  7104. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  7105. peSurface = eLockSurface.peLock(hSurface);
  7106. if (peSurface != NULL)
  7107. {
  7108. if (bDdUnlockSurfaceOrBuffer(peSurface))
  7109. {
  7110. UnlockData.ddRVal = DD_OK;
  7111. }
  7112. }
  7113. else
  7114. {
  7115. WARNING("DxDdUnlock: Invalid surface\n");
  7116. }
  7117. // We have to wrap this in another try-except because the user-mode
  7118. // memory containing the input may have been deallocated by now:
  7119. __try
  7120. {
  7121. ProbeAndWriteRVal(&puUnlockData->ddRVal, UnlockData.ddRVal);
  7122. }
  7123. __except(EXCEPTION_EXECUTE_HANDLER)
  7124. {
  7125. }
  7126. return(DDHAL_DRIVER_HANDLED);
  7127. }
  7128. /******************************Public*Routine******************************\
  7129. * DWORD DxDdLockD3D
  7130. *
  7131. * DirectDraw function to return a user-mode pointer to the screen or
  7132. * off-screen surface.
  7133. *
  7134. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  7135. * Wrote it.
  7136. \**************************************************************************/
  7137. DWORD
  7138. APIENTRY
  7139. DxDdLockD3D(
  7140. HANDLE hSurface,
  7141. PDD_LOCKDATA puLockData
  7142. )
  7143. {
  7144. DD_LOCKDATA LockData;
  7145. __try
  7146. {
  7147. LockData = ProbeAndReadStructure(puLockData, DD_LOCKDATA);
  7148. }
  7149. __except(EXCEPTION_EXECUTE_HANDLER)
  7150. {
  7151. return(DDHAL_DRIVER_HANDLED);
  7152. }
  7153. LockData.ddRVal = DDERR_GENERIC;
  7154. EDD_SURFACE* peSurface;
  7155. EDD_LOCK_SURFACE eLockSurface;
  7156. // Note that we have to let down DDLOCK_READONLY, DDLOCK_WRITE,
  7157. // and DDLOCK_WAIT for compatibility. Note also that a
  7158. // DDLOCK_SURFACEMEMORY flag also gets passed down by default.
  7159. peSurface = eLockSurface.peLock(hSurface);
  7160. if ((peSurface != NULL) &&
  7161. ((LockData.dwFlags & ~(DDLOCK_VALID)) == 0))
  7162. {
  7163. LockData.lpSurfData = pDdLockSurfaceOrBuffer(peSurface,
  7164. LockData.bHasRect,
  7165. &LockData.rArea,
  7166. // We remove the wait flag since it better to spin in user mode
  7167. LockData.dwFlags & (~DDLOCK_WAIT),
  7168. &LockData.ddRVal);
  7169. }
  7170. else
  7171. {
  7172. WARNING("DxDdLockD3D: Invalid surface or flags\n");
  7173. }
  7174. // We have to wrap this in another try-except because the user-mode
  7175. // memory containing the input may have been deallocated by now:
  7176. __try
  7177. {
  7178. ProbeAndWriteHandle(&puLockData->lpSurfData, LockData.lpSurfData);
  7179. ProbeAndWriteRVal(&puLockData->ddRVal, LockData.ddRVal);
  7180. }
  7181. __except(EXCEPTION_EXECUTE_HANDLER)
  7182. {
  7183. }
  7184. // This function must always return DDHAL_DRIVER_HANDLED, otherwise
  7185. // DirectDraw will simply use the 'fpVidMem' value, which on NT is
  7186. // an offset and not a pointer:
  7187. return(DDHAL_DRIVER_HANDLED);
  7188. }
  7189. /******************************Public*Routine******************************\
  7190. * DWORD DxDdUnlockD3D
  7191. *
  7192. * DirectDraw unlock.
  7193. *
  7194. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  7195. * Wrote it.
  7196. \**************************************************************************/
  7197. DWORD
  7198. APIENTRY
  7199. DxDdUnlockD3D(
  7200. HANDLE hSurface,
  7201. PDD_UNLOCKDATA puUnlockData
  7202. )
  7203. {
  7204. DWORD dwRet;
  7205. DD_UNLOCKDATA UnlockData;
  7206. __try
  7207. {
  7208. UnlockData = ProbeAndReadStructure(puUnlockData, DD_UNLOCKDATA);
  7209. }
  7210. __except(EXCEPTION_EXECUTE_HANDLER)
  7211. {
  7212. return(DDHAL_DRIVER_HANDLED);
  7213. }
  7214. UnlockData.ddRVal = DDERR_GENERIC;
  7215. EDD_SURFACE* peSurface;
  7216. EDD_LOCK_SURFACE eLockSurface;
  7217. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  7218. peSurface = eLockSurface.peLock(hSurface);
  7219. if (peSurface != NULL)
  7220. {
  7221. if (bDdUnlockSurfaceOrBuffer(peSurface))
  7222. {
  7223. UnlockData.ddRVal = DD_OK;
  7224. }
  7225. }
  7226. else
  7227. {
  7228. WARNING("DxDdUnlockD3D: Invalid surface\n");
  7229. }
  7230. // We have to wrap this in another try-except because the user-mode
  7231. // memory containing the input may have been deallocated by now:
  7232. __try
  7233. {
  7234. ProbeAndWriteRVal(&puUnlockData->ddRVal, UnlockData.ddRVal);
  7235. }
  7236. __except(EXCEPTION_EXECUTE_HANDLER)
  7237. {
  7238. }
  7239. return(DDHAL_DRIVER_HANDLED);
  7240. }
  7241. /******************************Public*Routine******************************\
  7242. * DWORD DxDdGetFlipStatus
  7243. *
  7244. * DirectDraw API to get the page-flip status.
  7245. *
  7246. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  7247. * Wrote it.
  7248. \**************************************************************************/
  7249. DWORD
  7250. APIENTRY
  7251. DxDdGetFlipStatus(
  7252. HANDLE hSurface,
  7253. PDD_GETFLIPSTATUSDATA puGetFlipStatusData
  7254. )
  7255. {
  7256. DWORD dwRet;
  7257. DD_GETFLIPSTATUSDATA GetFlipStatusData;
  7258. __try
  7259. {
  7260. GetFlipStatusData = ProbeAndReadStructure(puGetFlipStatusData,
  7261. DD_GETFLIPSTATUSDATA);
  7262. }
  7263. __except(EXCEPTION_EXECUTE_HANDLER)
  7264. {
  7265. return(DDHAL_DRIVER_NOTHANDLED);
  7266. }
  7267. dwRet = DDHAL_DRIVER_NOTHANDLED;
  7268. GetFlipStatusData.ddRVal = DDERR_GENERIC;
  7269. EDD_SURFACE* peSurface;
  7270. EDD_LOCK_SURFACE eLockSurface;
  7271. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  7272. peSurface = eLockSurface.peLock(hSurface);
  7273. if ((peSurface != NULL) &&
  7274. !(peSurface->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  7275. ((GetFlipStatusData.dwFlags & ~(DDGFS_CANFLIP
  7276. | DDGFS_ISFLIPDONE)) == 0))
  7277. {
  7278. peDirectDrawGlobal = peSurface->peDirectDrawGlobal;
  7279. if (peDirectDrawGlobal->SurfaceCallBacks.dwFlags &
  7280. DDHAL_SURFCB32_GETFLIPSTATUS)
  7281. {
  7282. GetFlipStatusData.lpDD = peDirectDrawGlobal;
  7283. GetFlipStatusData.lpDDSurface = peSurface;
  7284. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  7285. if (peSurface->bLost)
  7286. {
  7287. dwRet = DDHAL_DRIVER_HANDLED;
  7288. GetFlipStatusData.ddRVal = DDERR_SURFACELOST;
  7289. }
  7290. else
  7291. {
  7292. dwRet = peDirectDrawGlobal->
  7293. SurfaceCallBacks.GetFlipStatus(&GetFlipStatusData);
  7294. // If a flip was pending, and has completed, then turn off
  7295. // the flag:
  7296. if ((peSurface->fl & DD_SURFACE_FLAG_FLIP_PENDING) &&
  7297. (GetFlipStatusData.dwFlags & DDGFS_ISFLIPDONE) &&
  7298. (dwRet == DDHAL_DRIVER_HANDLED) &&
  7299. (GetFlipStatusData.ddRVal == DD_OK))
  7300. {
  7301. peSurface->fl &= ~DD_SURFACE_FLAG_FLIP_PENDING;
  7302. }
  7303. }
  7304. }
  7305. }
  7306. else
  7307. {
  7308. WARNING("DxDdGetFlipStatus: Invalid surface or dwFlags\n");
  7309. }
  7310. // We have to wrap this in another try-except because the user-mode
  7311. // memory containing the input may have been deallocated by now:
  7312. __try
  7313. {
  7314. ProbeAndWriteRVal(&puGetFlipStatusData->ddRVal,
  7315. GetFlipStatusData.ddRVal);
  7316. }
  7317. __except(EXCEPTION_EXECUTE_HANDLER)
  7318. {
  7319. }
  7320. return(dwRet);
  7321. }
  7322. /******************************Public*Routine******************************\
  7323. * DWORD DxDdGetBltStatus
  7324. *
  7325. * DirectDraw API to get the accelerator's accelerator status.
  7326. *
  7327. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  7328. * Wrote it.
  7329. \**************************************************************************/
  7330. DWORD
  7331. APIENTRY
  7332. DxDdGetBltStatus(
  7333. HANDLE hSurface,
  7334. PDD_GETBLTSTATUSDATA puGetBltStatusData
  7335. )
  7336. {
  7337. DWORD dwRet;
  7338. DD_GETBLTSTATUSDATA GetBltStatusData;
  7339. __try
  7340. {
  7341. GetBltStatusData = ProbeAndReadStructure(puGetBltStatusData,
  7342. DD_GETBLTSTATUSDATA);
  7343. }
  7344. __except(EXCEPTION_EXECUTE_HANDLER)
  7345. {
  7346. return(DDHAL_DRIVER_NOTHANDLED);
  7347. }
  7348. dwRet = DDHAL_DRIVER_NOTHANDLED;
  7349. GetBltStatusData.ddRVal = DDERR_GENERIC;
  7350. EDD_SURFACE* peSurface;
  7351. EDD_LOCK_SURFACE eLockSurface;
  7352. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  7353. peSurface = eLockSurface.peLock(hSurface);
  7354. if ((peSurface != NULL) &&
  7355. !(peSurface->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  7356. ((GetBltStatusData.dwFlags & ~(DDGBS_CANBLT
  7357. | DDGBS_ISBLTDONE)) == 0))
  7358. {
  7359. peDirectDrawGlobal = peSurface->peDirectDrawGlobal;
  7360. if (peDirectDrawGlobal->SurfaceCallBacks.dwFlags &
  7361. DDHAL_SURFCB32_GETBLTSTATUS)
  7362. {
  7363. GetBltStatusData.lpDD = peDirectDrawGlobal;
  7364. GetBltStatusData.lpDDSurface = peSurface;
  7365. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  7366. if (peSurface->bLost)
  7367. {
  7368. dwRet = DDHAL_DRIVER_HANDLED;
  7369. GetBltStatusData.ddRVal = DDERR_SURFACELOST;
  7370. }
  7371. else
  7372. {
  7373. dwRet = peDirectDrawGlobal->
  7374. SurfaceCallBacks.GetBltStatus(&GetBltStatusData);
  7375. }
  7376. }
  7377. }
  7378. else
  7379. {
  7380. WARNING("DxDdGetBltStatus: Invalid surface or dwFlags\n");
  7381. }
  7382. // We have to wrap this in another try-except because the user-mode
  7383. // memory containing the input may have been deallocated by now:
  7384. __try
  7385. {
  7386. ProbeAndWriteRVal(&puGetBltStatusData->ddRVal, GetBltStatusData.ddRVal);
  7387. }
  7388. __except(EXCEPTION_EXECUTE_HANDLER)
  7389. {
  7390. }
  7391. return(dwRet);
  7392. }
  7393. /******************************Public*Routine******************************\
  7394. * DWORD DxDdWaitForVerticalBlank
  7395. *
  7396. * DirectDraw API to wait for vertical blank.
  7397. *
  7398. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  7399. * Wrote it.
  7400. \**************************************************************************/
  7401. DWORD
  7402. APIENTRY
  7403. DxDdWaitForVerticalBlank(
  7404. HANDLE hDirectDraw,
  7405. PDD_WAITFORVERTICALBLANKDATA puWaitForVerticalBlankData
  7406. )
  7407. {
  7408. DWORD dwRet;
  7409. DD_WAITFORVERTICALBLANKDATA WaitForVerticalBlankData;
  7410. __try
  7411. {
  7412. WaitForVerticalBlankData =
  7413. ProbeAndReadStructure(puWaitForVerticalBlankData,
  7414. DD_WAITFORVERTICALBLANKDATA);
  7415. }
  7416. __except(EXCEPTION_EXECUTE_HANDLER)
  7417. {
  7418. return(DDHAL_DRIVER_NOTHANDLED);
  7419. }
  7420. dwRet = DDHAL_DRIVER_NOTHANDLED;
  7421. WaitForVerticalBlankData.ddRVal = DDERR_GENERIC;
  7422. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  7423. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  7424. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  7425. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
  7426. if ((peDirectDrawLocal != NULL) &&
  7427. ((WaitForVerticalBlankData.dwFlags & ~(DDWAITVB_I_TESTVB
  7428. | DDWAITVB_BLOCKBEGIN
  7429. | DDWAITVB_BLOCKBEGINEVENT
  7430. | DDWAITVB_BLOCKEND)) == 0) &&
  7431. (WaitForVerticalBlankData.dwFlags != 0))
  7432. {
  7433. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  7434. if (peDirectDrawGlobal->CallBacks.dwFlags &
  7435. DDHAL_CB32_WAITFORVERTICALBLANK)
  7436. {
  7437. WaitForVerticalBlankData.lpDD = peDirectDrawGlobal;
  7438. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  7439. if (peDirectDrawGlobal->bSuspended)
  7440. {
  7441. dwRet = DDHAL_DRIVER_HANDLED;
  7442. WaitForVerticalBlankData.ddRVal = DDERR_SURFACELOST;
  7443. }
  7444. else
  7445. {
  7446. dwRet = peDirectDrawGlobal->
  7447. CallBacks.WaitForVerticalBlank(&WaitForVerticalBlankData);
  7448. }
  7449. }
  7450. }
  7451. else
  7452. {
  7453. WARNING("DxDdWaitForVerticalBlank: Invalid object or dwFlags\n");
  7454. }
  7455. // We have to wrap this in another try-except because the user-mode
  7456. // memory containing the input may have been deallocated by now:
  7457. __try
  7458. {
  7459. ProbeAndWriteRVal(&puWaitForVerticalBlankData->ddRVal,
  7460. WaitForVerticalBlankData.ddRVal);
  7461. ProbeAndWriteUlong(&puWaitForVerticalBlankData->bIsInVB,
  7462. WaitForVerticalBlankData.bIsInVB);
  7463. }
  7464. __except(EXCEPTION_EXECUTE_HANDLER)
  7465. {
  7466. }
  7467. return(dwRet);
  7468. }
  7469. /******************************Public*Routine******************************\
  7470. * DWORD dwDdCanCreateSurfaceOrBuffer
  7471. *
  7472. * Handles DxDdCanCreateSurface and DxDdCanCreateD3DBuffer.
  7473. *
  7474. * 3-Feb-1998 -by- Drew Bliss [drewb]
  7475. * Merged common code from calling routines.
  7476. \**************************************************************************/
  7477. DWORD
  7478. dwDdCanCreateSurfaceOrBuffer(
  7479. BOOL bSurface,
  7480. HANDLE hDirectDraw,
  7481. PDD_CANCREATESURFACEDATA puCanCreateSurfaceData
  7482. )
  7483. {
  7484. DWORD dwRet;
  7485. DD_CANCREATESURFACEDATA CanCreateSurfaceData;
  7486. DDSURFACEDESC2* puSurfaceDescription;
  7487. DDSURFACEDESC2 SurfaceDescription;
  7488. __try
  7489. {
  7490. CanCreateSurfaceData = ProbeAndReadStructure(puCanCreateSurfaceData,
  7491. DD_CANCREATESURFACEDATA);
  7492. puSurfaceDescription = (DDSURFACEDESC2 *)CanCreateSurfaceData.lpDDSurfaceDesc;
  7493. SurfaceDescription = ProbeAndReadStructure(puSurfaceDescription,
  7494. DDSURFACEDESC2);
  7495. CanCreateSurfaceData.lpDDSurfaceDesc = (DDSURFACEDESC*)&SurfaceDescription;
  7496. }
  7497. __except(EXCEPTION_EXECUTE_HANDLER)
  7498. {
  7499. return(DDHAL_DRIVER_NOTHANDLED);
  7500. }
  7501. // All video memory heaps are handled in the kernel so if
  7502. // this routine cannot create a surface then user-mode can't
  7503. // either. Always returns DRIVER_HANDLED to enforce this.
  7504. dwRet = DDHAL_DRIVER_HANDLED;
  7505. CanCreateSurfaceData.ddRVal = DDERR_GENERIC;
  7506. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  7507. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  7508. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  7509. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
  7510. if (peDirectDrawLocal != NULL)
  7511. {
  7512. // Choose function to call.
  7513. PDD_CANCREATESURFACE pfnCanCreate;
  7514. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  7515. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  7516. if (bSurface)
  7517. {
  7518. pfnCanCreate =
  7519. (peDirectDrawGlobal->CallBacks.dwFlags &
  7520. DDHAL_CB32_CANCREATESURFACE) ?
  7521. peDirectDrawGlobal->CallBacks.CanCreateSurface :
  7522. NULL;
  7523. }
  7524. else
  7525. {
  7526. pfnCanCreate =
  7527. peDirectDrawGlobal->D3dBufCallbacks.CanCreateD3DBuffer;
  7528. }
  7529. if (pfnCanCreate != NULL)
  7530. {
  7531. CanCreateSurfaceData.lpDD = peDirectDrawGlobal;
  7532. if (!peDirectDrawGlobal->bSuspended)
  7533. {
  7534. dwRet = pfnCanCreate(&CanCreateSurfaceData);
  7535. }
  7536. else
  7537. {
  7538. CanCreateSurfaceData.ddRVal = DDERR_SURFACELOST;
  7539. }
  7540. }
  7541. else
  7542. {
  7543. WARNING("dwDdCanCreateSurface: Driver doesn't hook call\n");
  7544. }
  7545. }
  7546. else
  7547. {
  7548. WARNING("dwDdCanCreateSurface: Invalid object\n");
  7549. }
  7550. // We have to wrap this in another try-except because the user-mode
  7551. // memory containing the input may have been deallocated by now:
  7552. __try
  7553. {
  7554. ProbeAndWriteRVal(&puCanCreateSurfaceData->ddRVal,
  7555. CanCreateSurfaceData.ddRVal);
  7556. ProbeAndWriteStructure(puSurfaceDescription,
  7557. SurfaceDescription,
  7558. DDSURFACEDESC);
  7559. // Driver can update ddpfPixelFormat.dwYUVBitCount
  7560. }
  7561. __except(EXCEPTION_EXECUTE_HANDLER)
  7562. {
  7563. }
  7564. return(dwRet);
  7565. }
  7566. /******************************Public*Routine******************************\
  7567. * DWORD DxDdCanCreateSurface
  7568. *
  7569. * Queries the driver to determine whether it can support a DirectDraw
  7570. * surface that is different from the primary display.
  7571. *
  7572. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  7573. * Wrote it.
  7574. \**************************************************************************/
  7575. DWORD
  7576. APIENTRY
  7577. DxDdCanCreateSurface(
  7578. HANDLE hDirectDraw,
  7579. PDD_CANCREATESURFACEDATA puCanCreateSurfaceData
  7580. )
  7581. {
  7582. return dwDdCanCreateSurfaceOrBuffer(TRUE, hDirectDraw,
  7583. puCanCreateSurfaceData);
  7584. }
  7585. /******************************Public*Routine******************************\
  7586. * DWORD DxDdCanCreateD3DBuffer
  7587. *
  7588. * Queries the driver to determine whether it can support a given D3D Buffer
  7589. *
  7590. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  7591. * Wrote it.
  7592. \**************************************************************************/
  7593. DWORD
  7594. APIENTRY
  7595. DxDdCanCreateD3DBuffer(
  7596. HANDLE hDirectDraw,
  7597. PDD_CANCREATESURFACEDATA puCanCreateSurfaceData
  7598. )
  7599. {
  7600. return dwDdCanCreateSurfaceOrBuffer(FALSE, hDirectDraw,
  7601. puCanCreateSurfaceData);
  7602. }
  7603. /******************************Public*Routine******************************\
  7604. * HRESULT hrDdCommitAgpSurface
  7605. *
  7606. * Ensures that user-mode addresses are reserved in the current process
  7607. * and commits pages for the given surface.
  7608. *
  7609. * 7-May-1998 -by- Drew Bliss [drewb]
  7610. * Wrote it.
  7611. \**************************************************************************/
  7612. HRESULT
  7613. hrDdCommitAgpSurface(
  7614. EDD_SURFACE* peSurface,
  7615. DWORD dwSurfaceSize
  7616. )
  7617. {
  7618. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  7619. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  7620. EDD_VMEMMAPPING* peMap;
  7621. VIDEOMEMORY* pvmHeap;
  7622. DWORD iHeapIndex;
  7623. peDirectDrawLocal = peSurface->peDirectDrawLocal;
  7624. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  7625. DD_ASSERTDEVLOCK(peDirectDrawGlobal);
  7626. pvmHeap = peSurface->lpVidMemHeap;
  7627. ASSERTGDI(peDirectDrawLocal->ppeMapAgp != NULL,
  7628. "Committing AGP surface with no heaps\n");
  7629. iHeapIndex = (DWORD) (pvmHeap - peDirectDrawGlobal->pvmList);
  7630. peMap = peDirectDrawLocal->ppeMapAgp[iHeapIndex];
  7631. if (peMap == NULL)
  7632. {
  7633. MapAllAgpHeaps(peDirectDrawLocal);
  7634. peMap = peDirectDrawLocal->ppeMapAgp[iHeapIndex];
  7635. if (peMap == NULL)
  7636. {
  7637. return DDERR_OUTOFMEMORY;
  7638. }
  7639. }
  7640. peSurface->fpVidMem =
  7641. (FLATPTR)(peMap->pvVirtAddr) +
  7642. (peSurface->fpHeapOffset - pvmHeap->fpStart);
  7643. return DD_OK;
  7644. }
  7645. /******************************Public*Routine******************************\
  7646. * HRESULT hrDdAllocSurface
  7647. *
  7648. * Allocates memory for the given surface.
  7649. *
  7650. * 3-Feb-1998 -by- Drew Bliss [drewb]
  7651. * Wrote it.
  7652. \**************************************************************************/
  7653. HRESULT
  7654. hrDdAllocSurface(
  7655. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal,
  7656. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal,
  7657. EDD_SURFACE* peSurface
  7658. )
  7659. {
  7660. HRESULT hr = DDERR_OUTOFVIDEOMEMORY;
  7661. BOOL bAllowNewPitch = TRUE;
  7662. DD_ASSERTDEVLOCK(peDirectDrawGlobal);
  7663. ASSERTGDI(!(peSurface->ddsCaps.dwCaps & (DDSCAPS_SYSTEMMEMORY |
  7664. DDSCAPS_PRIMARYSURFACE)),
  7665. "hrDdAllocSurface: System-memory or primary request");
  7666. // If 'fpVidMem' is DDHAL_PLEASEALLOC_USERMEM, that means
  7667. // the driver wants us to allocate a chunk of user-mode
  7668. // memory on the driver's behalf:
  7669. if (peSurface->fpVidMem == DDHAL_PLEASEALLOC_USERMEM)
  7670. {
  7671. // The driver was involved in this surface creation so
  7672. // mark it as such.
  7673. peSurface->fl |= DD_SURFACE_FLAG_DRIVER_CREATED;
  7674. peSurface->fpVidMem =
  7675. (FLATPTR) EngAllocUserMem(peSurface->dwUserMemSize, 'pddG');
  7676. if (peSurface->fpVidMem != 0)
  7677. {
  7678. peSurface->fl |= DD_SURFACE_FLAG_UMEM_ALLOCATED;
  7679. hr = DD_OK;
  7680. DDKHEAP(("DDKHEAP: New um %08X, surf %X (%X)\n",
  7681. peSurface->fpVidMem, peSurface->hGet(), peSurface));
  7682. }
  7683. else
  7684. {
  7685. hr = DDERR_OUTOFMEMORY;
  7686. }
  7687. // FIX: WINBUG #388284
  7688. //
  7689. // - MATROX G200: STRESS: dxg ASSERT when YV12 overlay surface gets created in system memory
  7690. //
  7691. // Set bAllowNewPitch to FALSE to avoid hitting assertion in below.
  7692. //
  7693. // Matrox G200 does not support YU12 overlay surface format, but they want to
  7694. // support this format for application compatibility, thus video driver ask us
  7695. // to allocate YU12 overlay surface in system memory, so that they can Blt
  7696. // with software emulation.
  7697. bAllowNewPitch = FALSE;
  7698. }
  7699. else
  7700. {
  7701. DWORD dwWidth, dwHeight;
  7702. DWORD dwSurfaceSize;
  7703. if (peSurface->fpVidMem == DDHAL_PLEASEALLOC_BLOCKSIZE)
  7704. {
  7705. // The driver wants a surface of a particular size to be
  7706. // allocated.
  7707. dwWidth = peSurface->dwBlockSizeX;
  7708. dwHeight = peSurface->dwBlockSizeY;
  7709. bAllowNewPitch = FALSE;
  7710. // The driver was involved in this surface creation so
  7711. // mark it as such.
  7712. peSurface->fl |= DD_SURFACE_FLAG_DRIVER_CREATED;
  7713. }
  7714. else
  7715. {
  7716. // The driver didn't specify a size so determine it from
  7717. // the surface dimensions.
  7718. if (peSurface->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER)
  7719. {
  7720. // Execute buffers are long, thin surfaces for the purposes
  7721. // of VM allocation.
  7722. dwWidth = peSurface->dwLinearSize;
  7723. dwHeight = 1;
  7724. }
  7725. else
  7726. {
  7727. // This lPitch may have been expanded by ComputePitch
  7728. // to cover global alignment restrictions.
  7729. dwWidth = labs(peSurface->lPitch);
  7730. dwHeight = peSurface->wHeight;
  7731. }
  7732. // The driver didn't do anything special for this allocation
  7733. // so don't call it when the surface is destroyed.
  7734. }
  7735. DWORD dwFlags = 0;
  7736. // In user mode DDHA_SKIPRECTANGULARHEAPS keys off of
  7737. // DDRAWISURFGBL_LATEALLOCATELINEAR. Right now we just leave
  7738. // it off.
  7739. if (peDirectDrawGlobal->HalInfo.ddCaps.dwCaps2 &
  7740. DDCAPS2_NONLOCALVIDMEMCAPS)
  7741. {
  7742. dwFlags |= DDHA_ALLOWNONLOCALMEMORY;
  7743. }
  7744. if (peDirectDrawGlobal->D3dDriverData.hwCaps.dwDevCaps &
  7745. D3DDEVCAPS_TEXTURENONLOCALVIDMEM)
  7746. {
  7747. dwFlags |= DDHA_ALLOWNONLOCALTEXTURES;
  7748. }
  7749. LONG lNewPitch = 0;
  7750. DWORD dwNewCaps = 0;
  7751. DWORD dwRet;
  7752. DD_FREEDRIVERMEMORYDATA FreeDriverMemoryData;
  7753. do {
  7754. dwRet = DDHAL_DRIVER_NOTHANDLED;
  7755. // Attempt to allocate the surface.
  7756. peSurface->fpHeapOffset =
  7757. DdHeapAlloc(peDirectDrawGlobal->dwNumHeaps,
  7758. peDirectDrawGlobal->pvmList,
  7759. AGP_HDEV(peDirectDrawGlobal),
  7760. &peDirectDrawGlobal->HalInfo.vmiData,
  7761. dwWidth,
  7762. dwHeight,
  7763. peSurface,
  7764. dwFlags,
  7765. &peSurface->lpVidMemHeap,
  7766. &lNewPitch,
  7767. &dwNewCaps,
  7768. &dwSurfaceSize);
  7769. // If the surface could not be allocated, try calling the
  7770. // driver to see if it can free up some room (such as by
  7771. // getting rid of GDI surfaces).
  7772. if ((peSurface->fpHeapOffset == 0) &&
  7773. !(peDirectDrawGlobal->bSuspended) &&
  7774. (peDirectDrawGlobal->NTCallBacks.dwFlags &
  7775. DDHAL_NTCB32_FREEDRIVERMEMORY))
  7776. {
  7777. DD_ASSERTDEVLOCK(peDirectDrawGlobal);
  7778. FreeDriverMemoryData.lpDD = peDirectDrawGlobal;
  7779. FreeDriverMemoryData.lpDDSurface = peSurface;
  7780. FreeDriverMemoryData.ddRVal = DDERR_GENERIC;
  7781. dwRet = peDirectDrawGlobal->NTCallBacks.
  7782. FreeDriverMemory(&FreeDriverMemoryData);
  7783. }
  7784. } while ((dwRet == DDHAL_DRIVER_HANDLED) &&
  7785. (FreeDriverMemoryData.ddRVal == DD_OK));
  7786. // If the surface could not be allocated with the optimal caps,
  7787. // try allocating with the alternate caps.
  7788. if (peSurface->fpHeapOffset == 0)
  7789. {
  7790. peSurface->fpHeapOffset =
  7791. DdHeapAlloc(peDirectDrawGlobal->dwNumHeaps,
  7792. peDirectDrawGlobal->pvmList,
  7793. AGP_HDEV(peDirectDrawGlobal),
  7794. &peDirectDrawGlobal->HalInfo.vmiData,
  7795. dwWidth,
  7796. dwHeight,
  7797. peSurface,
  7798. dwFlags | DDHA_USEALTCAPS,
  7799. &peSurface->lpVidMemHeap,
  7800. &lNewPitch,
  7801. &dwNewCaps,
  7802. &dwSurfaceSize);
  7803. }
  7804. if (peSurface->fpHeapOffset != 0)
  7805. {
  7806. // If this surface was allocated from an AGP heap then
  7807. // we must make sure that the heap has a user-mode mapping
  7808. // for this process and we must commit the necessary user-mode
  7809. // pages.
  7810. if (dwNewCaps & DDSCAPS_NONLOCALVIDMEM)
  7811. {
  7812. hr = hrDdCommitAgpSurface(peSurface, dwSurfaceSize);
  7813. if (hr != DD_OK)
  7814. {
  7815. DxDdHeapVidMemFree(peSurface->lpVidMemHeap->lpHeap,
  7816. peSurface->fpHeapOffset);
  7817. return hr;
  7818. }
  7819. }
  7820. else
  7821. {
  7822. peSurface->fpVidMem = peSurface->fpHeapOffset;
  7823. }
  7824. hr = DD_OK;
  7825. peSurface->fl |= DD_SURFACE_FLAG_VMEM_ALLOCATED;
  7826. // The particular heap that was used for the allocation may
  7827. // modify certain aspects of the surface. Update the surface
  7828. // to reflect any changes.
  7829. //
  7830. // The stride is not relevant for an execute buffer so we don't
  7831. // override it in that case.
  7832. if (lNewPitch != 0 && bAllowNewPitch &&
  7833. !(peSurface->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER))
  7834. {
  7835. peSurface->lPitch = lNewPitch;
  7836. }
  7837. peSurface->ddsCaps.dwCaps |= dwNewCaps;
  7838. ASSERTGDI((peSurface->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) ||
  7839. peSurface->lPitch > 0,
  7840. "Unexpected negative surface pitch");
  7841. ASSERTGDI((peSurface->fl & DD_SURFACE_FLAG_DRIVER_CREATED) ||
  7842. ((peSurface->ddpfSurface.dwFlags &
  7843. (DDPF_RGB | DDPF_ZBUFFER)) &&
  7844. (peSurface->ddsCaps.dwCaps & DDSCAPS_OVERLAY) == 0),
  7845. "Unexpected non-driver surface type");
  7846. DDKHEAP(("DDKHEAP: New vm %08X, o %08X, heap %X, surf %X (%X)\n",
  7847. peSurface->fpVidMem, peSurface->fpHeapOffset,
  7848. peSurface->lpVidMemHeap->lpHeap,
  7849. peSurface->hGet(), peSurface));
  7850. }
  7851. }
  7852. #if DBG
  7853. if (hr == DD_OK &&
  7854. (peSurface->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) == 0)
  7855. {
  7856. ASSERTGDI((peSurface->fpVidMem & 3) == 0 &&
  7857. (peSurface->lPitch & 3) == 0,
  7858. "Unaligned surface pointer or pitch");
  7859. ASSERTGDI(ABS(peSurface->lPitch) <= 4 * DD_MAXIMUM_COORDINATE,
  7860. "Pitch out of range");
  7861. // The width in bytes must not be more than the pitch.
  7862. // There are weird cases when this is actually valid (e.g. planar YUV formats), but in all
  7863. // such cases it would involve FOURCCs and the driver telling us which block size to allocate.
  7864. ASSERTGDI((peSurface->wWidth * peSurface->ddpfSurface.dwRGBBitCount <=
  7865. (ULONG) 8 * ABS(peSurface->lPitch) ||
  7866. (!bAllowNewPitch && (peSurface->ddpfSurface.dwFlags & DDPF_FOURCC))),
  7867. "Pitch less than width");
  7868. }
  7869. #endif
  7870. return hr;
  7871. }
  7872. /******************************Public*Routine******************************\
  7873. * DWORD dwDdCreateSurfaceOrBuffer
  7874. *
  7875. * Handles DxDdCreateSurface and DxDdCreateD3DBuffer.
  7876. *
  7877. * 3-Feb-1998 -by- Drew Bliss [drewb]
  7878. * Merged common code from calling functions.
  7879. \**************************************************************************/
  7880. DWORD dwDdCreateSurfaceOrBuffer(
  7881. HANDLE hDirectDraw,
  7882. HANDLE* phSurfaceHandles,
  7883. DDSURFACEDESC* puSurfaceDescription,
  7884. DD_SURFACE_GLOBAL* puSurfaceGlobalData,
  7885. DD_SURFACE_LOCAL* puSurfaceLocalData,
  7886. DD_SURFACE_MORE* puSurfaceMoreData,
  7887. DD_CREATESURFACEDATA* puCreateSurfaceData,
  7888. HANDLE* puhReturnSurfaceHandles
  7889. )
  7890. {
  7891. DWORD dwRet;
  7892. DD_CREATESURFACEDATA CreateSurfaceData;
  7893. DDSURFACEDESC2 SurfaceDescription;
  7894. ULONG dwNumToCreate;
  7895. HANDLE hSecureSurfaceHandles;
  7896. HANDLE hSecureGlobals;
  7897. HANDLE hSecureLocals;
  7898. HANDLE hSecureMore;
  7899. HANDLE hSecureReturn;
  7900. ULONG cjHandles;
  7901. ULONG cjGlobals;
  7902. ULONG cjLocals;
  7903. ULONG cjMore;
  7904. ULONG i;
  7905. ULONG j;
  7906. ULONG k;
  7907. BOOL bAutomicCreate;
  7908. BOOL bNotifyCreation;
  7909. ULONG dwStart;
  7910. ULONG dwEnd;
  7911. __try
  7912. {
  7913. CreateSurfaceData = ProbeAndReadStructure(puCreateSurfaceData,
  7914. DD_CREATESURFACEDATA);
  7915. SurfaceDescription = ProbeAndReadStructure((DDSURFACEDESC2*)puSurfaceDescription,
  7916. DDSURFACEDESC2);
  7917. }
  7918. __except(EXCEPTION_EXECUTE_HANDLER)
  7919. {
  7920. return(DDHAL_DRIVER_HANDLED);
  7921. }
  7922. // All video memory heaps are handled in the kernel so if
  7923. // this routine cannot create a surface then user-mode can't
  7924. // either. Always returns DRIVER_HANDLED to enforce this.
  7925. dwRet = DDHAL_DRIVER_HANDLED;
  7926. CreateSurfaceData.ddRVal = DDERR_GENERIC;
  7927. dwNumToCreate = CreateSurfaceData.dwSCnt;
  7928. EDD_SURFACE** peSurface;
  7929. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  7930. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  7931. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  7932. DD_SURFACE_LOCAL* pSurfaceLocal;
  7933. BOOL bKeepSurface;
  7934. PDD_CREATESURFACE pfnCreate;
  7935. DD_SURFACE_LOCAL** pSList = NULL;
  7936. EDD_SURFACE* peSurfaceOnStack = NULL;
  7937. BOOL bAnyType = TRUE;
  7938. DWORD dwForceMemType = 0;
  7939. peSurface = NULL;
  7940. bKeepSurface = FALSE;
  7941. bAutomicCreate = FALSE;
  7942. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
  7943. if (peDirectDrawLocal != NULL)
  7944. {
  7945. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  7946. // Hold the devlock throughout this process for
  7947. // the driver call and to protect heap manipulations.
  7948. EDD_SHAREDEVLOCK eDevlock(peDirectDrawGlobal);
  7949. if ((peDirectDrawGlobal->fl & DD_GLOBAL_FLAG_DRIVER_ENABLED) &&
  7950. !(peDirectDrawGlobal->bSuspended))
  7951. {
  7952. // If the display pitch is 0 (which we should have already caught, but we want to
  7953. // be safe), fail the call now or else vDdCompleteSurfaceObject will blue screen.
  7954. if (peDirectDrawGlobal->HalInfo.vmiData.lDisplayPitch == 0)
  7955. {
  7956. CreateSurfaceData.ddRVal = DDERR_GENERIC;
  7957. }
  7958. else
  7959. {
  7960. // Secure all of the arrays that we are working with
  7961. hSecureSurfaceHandles = 0;
  7962. hSecureGlobals = 0;
  7963. hSecureLocals = 0;
  7964. hSecureMore = 0;
  7965. hSecureReturn = 0;
  7966. if (!BALLOC_OVERFLOW1(dwNumToCreate, HANDLE) &&
  7967. !BALLOC_OVERFLOW1(dwNumToCreate, DD_SURFACE_GLOBAL) &&
  7968. !BALLOC_OVERFLOW1(dwNumToCreate, DD_SURFACE_LOCAL) &&
  7969. !BALLOC_OVERFLOW1(dwNumToCreate, DD_SURFACE_MORE))
  7970. {
  7971. cjHandles = dwNumToCreate * sizeof(HANDLE);
  7972. cjGlobals = dwNumToCreate * sizeof(DD_SURFACE_GLOBAL);
  7973. cjLocals = dwNumToCreate * sizeof(DD_SURFACE_LOCAL);
  7974. cjMore = dwNumToCreate * sizeof(DD_SURFACE_MORE);
  7975. if (phSurfaceHandles &&
  7976. puSurfaceGlobalData &&
  7977. puSurfaceLocalData &&
  7978. puSurfaceMoreData &&
  7979. puhReturnSurfaceHandles)
  7980. {
  7981. __try
  7982. {
  7983. ProbeForWrite(phSurfaceHandles, cjHandles, sizeof(UCHAR));
  7984. hSecureSurfaceHandles = MmSecureVirtualMemory(phSurfaceHandles,
  7985. cjHandles,
  7986. PAGE_READWRITE);
  7987. ProbeForWrite(puSurfaceGlobalData, cjGlobals, sizeof(UCHAR));
  7988. hSecureGlobals = MmSecureVirtualMemory(puSurfaceGlobalData,
  7989. cjGlobals,
  7990. PAGE_READWRITE);
  7991. ProbeForWrite(puSurfaceLocalData, cjLocals, sizeof(UCHAR));
  7992. hSecureLocals = MmSecureVirtualMemory(puSurfaceLocalData,
  7993. cjLocals,
  7994. PAGE_READWRITE);
  7995. ProbeForWrite(puSurfaceMoreData, cjMore, sizeof(UCHAR));
  7996. hSecureMore = MmSecureVirtualMemory(puSurfaceMoreData,
  7997. cjMore,
  7998. PAGE_READWRITE);
  7999. ProbeForWrite(puhReturnSurfaceHandles, cjHandles, sizeof(UCHAR));
  8000. hSecureReturn = MmSecureVirtualMemory(puhReturnSurfaceHandles,
  8001. cjHandles,
  8002. PAGE_READWRITE);
  8003. RtlZeroMemory(puhReturnSurfaceHandles, cjHandles);
  8004. }
  8005. __except(EXCEPTION_EXECUTE_HANDLER)
  8006. {
  8007. }
  8008. }
  8009. }
  8010. // Allocate placeholder where we keep pointers to peSurface.
  8011. if (dwNumToCreate > 1)
  8012. {
  8013. peSurface = (EDD_SURFACE**) PALLOCMEM(sizeof(EDD_SURFACE*) * dwNumToCreate, 'pddG');
  8014. }
  8015. else
  8016. {
  8017. peSurface = &peSurfaceOnStack;
  8018. }
  8019. }
  8020. if ((hSecureSurfaceHandles != 0) &&
  8021. (hSecureGlobals != 0) &&
  8022. (hSecureLocals != 0) &&
  8023. (hSecureMore != 0) &&
  8024. (hSecureReturn != 0) &&
  8025. (peSurface != NULL))
  8026. {
  8027. // if driver supports atomic creation and we are creating more than 1 surface,
  8028. // allocate surface list.
  8029. if ((peDirectDrawGlobal->PrivateCaps.dwPrivateCaps & DDHAL_PRIVATECAP_ATOMICSURFACECREATION) &&
  8030. (dwNumToCreate > 1))
  8031. {
  8032. pSList = (DD_SURFACE_LOCAL**) PALLOCMEM(sizeof(DD_SURFACE_LOCAL*) * dwNumToCreate, 'pddG');
  8033. if (pSList != NULL)
  8034. {
  8035. bAutomicCreate = TRUE;
  8036. }
  8037. }
  8038. else
  8039. {
  8040. pSList = NULL;
  8041. }
  8042. // Determine which function to call.
  8043. if (puSurfaceLocalData[0].ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER)
  8044. {
  8045. pfnCreate = peDirectDrawGlobal->D3dBufCallbacks.CreateD3DBuffer;
  8046. }
  8047. else
  8048. {
  8049. pfnCreate =
  8050. (peDirectDrawGlobal->CallBacks.dwFlags &
  8051. DDHAL_CB32_CREATESURFACE) ?
  8052. peDirectDrawGlobal->CallBacks.CreateSurface :
  8053. NULL;
  8054. }
  8055. CreateSurfaceData.ddRVal = DD_OK;
  8056. for (i = 0; (i < dwNumToCreate) && (CreateSurfaceData.ddRVal == DD_OK); i++)
  8057. {
  8058. // Do some basic parameter checking to avoid creating
  8059. // surfaces based on bad information.
  8060. if (!(puSurfaceLocalData[i].ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  8061. bDdValidateSurfaceDescription(&puSurfaceGlobalData[i], &puSurfaceLocalData[i]))
  8062. {
  8063. peSurface[i] = peDdOpenNewSurfaceObject(peDirectDrawLocal,
  8064. phSurfaceHandles[i],
  8065. &puSurfaceGlobalData[i],
  8066. &puSurfaceLocalData[i],
  8067. &puSurfaceMoreData[i]);
  8068. if (peSurface[i] != NULL)
  8069. {
  8070. bKeepSurface = TRUE;
  8071. dwRet = DDHAL_DRIVER_NOTHANDLED;
  8072. pSurfaceLocal = peSurface[i];
  8073. peSurface[i]->fpVidMem = 0;
  8074. peSurface[i]->fpHeapOffset = 0;
  8075. peSurface[i]->hCreatorProcess =
  8076. peDirectDrawLocal->UniqueProcess;
  8077. // Setup some internal flags that are required because some
  8078. // drivers look at them and not setting them for NT5 cause
  8079. // regressions in NT4 drivers and incompatibilites between
  8080. // Win9X driver code.
  8081. if ((SurfaceDescription.ddsCaps.dwCaps & DDSCAPS_OVERLAY) ||
  8082. ((SurfaceDescription.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) &&
  8083. (peDirectDrawGlobal->HalInfo.ddCaps.dwCaps & DDCAPS_OVERLAY)))
  8084. {
  8085. peSurface[i]->dwFlags |= DDRAWISURF_HASOVERLAYDATA;
  8086. puSurfaceLocalData[i].dwFlags |= DDRAWISURF_HASOVERLAYDATA;
  8087. }
  8088. if (SurfaceDescription.dwFlags & DDSD_PIXELFORMAT)
  8089. {
  8090. if (!(SurfaceDescription.ddpfPixelFormat.dwFlags & DDPF_RGB) ||
  8091. (SurfaceDescription.ddpfPixelFormat.dwRGBBitCount !=
  8092. peDirectDrawGlobal->HalInfo.vmiData.ddpfDisplay.dwRGBBitCount) ||
  8093. ((SurfaceDescription.ddpfPixelFormat.dwRGBBitCount != 8) &&
  8094. ((SurfaceDescription.ddpfPixelFormat.dwRBitMask !=
  8095. peDirectDrawGlobal->HalInfo.vmiData.ddpfDisplay.dwRBitMask) ||
  8096. (SurfaceDescription.ddpfPixelFormat.dwGBitMask !=
  8097. peDirectDrawGlobal->HalInfo.vmiData.ddpfDisplay.dwGBitMask) ||
  8098. (SurfaceDescription.ddpfPixelFormat.dwBBitMask !=
  8099. peDirectDrawGlobal->HalInfo.vmiData.ddpfDisplay.dwBBitMask) ||
  8100. ((SurfaceDescription.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) &&
  8101. (!(peDirectDrawGlobal->HalInfo.vmiData.ddpfDisplay.dwFlags & DDPF_ALPHAPIXELS) ||
  8102. (SurfaceDescription.ddpfPixelFormat.dwRGBAlphaBitMask !=
  8103. peDirectDrawGlobal->HalInfo.vmiData.ddpfDisplay.dwRGBAlphaBitMask))))))
  8104. {
  8105. if (!(SurfaceDescription.ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER))
  8106. {
  8107. peSurface[i]->dwFlags |= DDRAWISURF_HASPIXELFORMAT;
  8108. puSurfaceLocalData[i].dwFlags |= DDRAWISURF_HASPIXELFORMAT;
  8109. }
  8110. }
  8111. }
  8112. // If this is an automic create, we need to complete all of the surfaces
  8113. // only after the final create surface is called, otherwise we need to
  8114. // complete each surface as we go through the loop.
  8115. if (bAutomicCreate)
  8116. {
  8117. dwStart = 0;
  8118. if (i == (dwNumToCreate - 1))
  8119. {
  8120. dwEnd = dwNumToCreate;
  8121. }
  8122. else
  8123. {
  8124. dwEnd = 0;
  8125. }
  8126. }
  8127. else
  8128. {
  8129. dwStart = i;
  8130. dwEnd = i + 1;
  8131. }
  8132. // Primary surfaces aren't truly allocated, so
  8133. // intercept requests for primary allocations and
  8134. // trivially succeed them with recorded primary information.
  8135. bNotifyCreation = TRUE;
  8136. if (peSurface[i]->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
  8137. {
  8138. peSurface[i]->fpVidMem =
  8139. peDirectDrawGlobal->HalInfo.vmiData.fpPrimary;
  8140. peSurface[i]->lPitch =
  8141. peDirectDrawGlobal->HalInfo.vmiData.lDisplayPitch;
  8142. peSurface[i]->wWidth =
  8143. peDirectDrawGlobal->HalInfo.vmiData.dwDisplayWidth;
  8144. peSurface[i]->wHeight =
  8145. peDirectDrawGlobal->HalInfo.vmiData.dwDisplayHeight;
  8146. peSurface[i]->ddpfSurface =
  8147. peDirectDrawGlobal->HalInfo.vmiData.ddpfDisplay;
  8148. peSurface[i]->fl |= DD_SURFACE_FLAG_PRIMARY;
  8149. CreateSurfaceData.ddRVal = DD_OK;
  8150. dwRet = DDHAL_DRIVER_HANDLED;
  8151. if (!(peDirectDrawGlobal->PrivateCaps.dwPrivateCaps & DDHAL_PRIVATECAP_NOTIFYPRIMARYCREATION))
  8152. {
  8153. bNotifyCreation = FALSE;
  8154. }
  8155. DDKHEAP(("DDKHEAP: Allocated primary %X, surf %X (%X)\n",
  8156. peSurface[i]->fpVidMem, peSurface[i]->hGet(),
  8157. peSurface[i]));
  8158. }
  8159. if (dwStart != dwEnd)
  8160. {
  8161. // Determines whether the memory type was explicit or not, so we know
  8162. // if we can change it if an allocation fails later.
  8163. if (dwForceMemType == 0)
  8164. {
  8165. bAnyType = !(peSurface[dwStart]->ddsCaps.dwCaps &
  8166. (DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM));
  8167. // if it's not any type, initialize force mem type so that always
  8168. // that type for all surfaces.
  8169. if (!bAnyType)
  8170. {
  8171. dwForceMemType = peSurface[dwStart]->ddsCaps.dwCaps &
  8172. (DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM);
  8173. }
  8174. }
  8175. // if force allocations, set the same memory type as the first one
  8176. if (dwForceMemType)
  8177. {
  8178. for (j = dwStart; j < dwEnd; j++)
  8179. {
  8180. peSurface[j]->ddsCaps.dwCaps &=
  8181. ~(DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM);
  8182. peSurface[j]->ddsCaps.dwCaps |= dwForceMemType;
  8183. }
  8184. }
  8185. if ((pfnCreate != NULL) && bNotifyCreation)
  8186. {
  8187. // Let the driver attempt to allocate the surface first.
  8188. CreateSurfaceData.lpDD = peDirectDrawGlobal;
  8189. CreateSurfaceData.lpDDSurfaceDesc = (DDSURFACEDESC*)&SurfaceDescription;
  8190. if (bAutomicCreate)
  8191. {
  8192. for (j = dwStart; j < dwEnd; j++)
  8193. {
  8194. pSList[j] = peSurface[j];
  8195. }
  8196. CreateSurfaceData.lplpSList = pSList;
  8197. CreateSurfaceData.dwSCnt = dwNumToCreate;
  8198. }
  8199. else
  8200. {
  8201. CreateSurfaceData.lplpSList = &pSurfaceLocal;
  8202. CreateSurfaceData.dwSCnt = 1;
  8203. }
  8204. dwRet = pfnCreate(&CreateSurfaceData);
  8205. if (dwRet == DDHAL_DRIVER_HANDLED)
  8206. {
  8207. if (CreateSurfaceData.ddRVal == DD_OK)
  8208. {
  8209. for (j = dwStart; j < dwEnd; j++)
  8210. {
  8211. // Set the driver created flag because the driver
  8212. // involved itself in the creation.
  8213. peSurface[j]->fl |=
  8214. DD_SURFACE_FLAG_DRIVER_CREATED;
  8215. }
  8216. for (j = dwStart;
  8217. (j < dwEnd) && (CreateSurfaceData.ddRVal == DD_OK);
  8218. j++)
  8219. {
  8220. // If the surfaces were allocated from one of our non-local
  8221. // heaps, commit sufficient virtual memory and fill in the
  8222. // virtual address for fpVidMem so the surface can be locked
  8223. // and accessed by user mode apps:
  8224. if ((peSurface[j]->ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM) &&
  8225. (peSurface[j]->lpVidMemHeap != NULL) &&
  8226. (peSurface[j]->lpVidMemHeap->lpHeap != NULL) &&
  8227. !(peSurface[j]->lpVidMemHeap->dwFlags & VIDMEM_ISHEAP) &&
  8228. (peSurface[j]->lpVidMemHeap->dwFlags & VIDMEM_ISNONLOCAL))
  8229. {
  8230. CreateSurfaceData.ddRVal =
  8231. hrDdCommitAgpSurface(peSurface[j], 0);
  8232. }
  8233. }
  8234. if (CreateSurfaceData.ddRVal == DD_OK)
  8235. {
  8236. if (dwForceMemType == 0)
  8237. {
  8238. // All surfaces must be of the same type as the first
  8239. // so we remember the type of surface type which
  8240. // we have successfully created.
  8241. // This only has meaning non-atomic case, since
  8242. // if driver can do atomic creation and handled it
  8243. // without error, that's driver's responsibility to
  8244. // make sure all surface came from same type of memory.
  8245. dwForceMemType =
  8246. peSurface[dwStart]->ddsCaps.dwCaps &
  8247. (DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM);
  8248. }
  8249. }
  8250. }
  8251. DDKHEAP(("DDHKEAP: Driver alloced %X, "
  8252. "hr %X, surf %X (%X)\n",
  8253. peSurface[i]->fpVidMem,
  8254. CreateSurfaceData.ddRVal,
  8255. peSurface[i]->hGet(),
  8256. peSurface[i]));
  8257. }
  8258. else if (peSurface[dwStart]->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
  8259. {
  8260. // Driver possible to return NOTHANDLED for notification of
  8261. // primary surface cration, but creation itself is done by
  8262. // us in above, but we had "notified" to driver, make
  8263. // the surface as driver created. (so that we call driver
  8264. // when destroy).
  8265. peSurface[dwStart]->fl |=
  8266. DD_SURFACE_FLAG_DRIVER_CREATED;
  8267. }
  8268. }
  8269. if (dwRet == DDHAL_DRIVER_NOTHANDLED)
  8270. {
  8271. // FIX WINBUG: #322363
  8272. // Prevent setup blue-screen playing intro AVI on nv3 display drivers
  8273. if ((SurfaceDescription.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
  8274. (SurfaceDescription.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY))
  8275. {
  8276. // Mask off system memory flag
  8277. WARNING("Driver turn on SYSTEMMEMORY flag, disable it");
  8278. SurfaceDescription.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
  8279. }
  8280. dwRet = DDHAL_DRIVER_HANDLED;
  8281. for (j = dwStart;
  8282. (j < dwEnd) && (CreateSurfaceData.ddRVal == DD_OK);
  8283. j++)
  8284. {
  8285. if (peSurface[j]->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
  8286. {
  8287. // Driver possible to return NOTHANDLED for notification of
  8288. // primary surface cration, but creation itself is done by
  8289. // us in above, so just ignore driver return.
  8290. // Since this is just "notification" to driver, we don't
  8291. // except any work in driver basically.
  8292. CreateSurfaceData.ddRVal = DD_OK;
  8293. }
  8294. else
  8295. {
  8296. // FIX WINBUG: #322363
  8297. // Prevent setup blue-screen playing intro AVI on nv3 display drivers
  8298. if ((peSurface[j]->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
  8299. (peSurface[j]->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY))
  8300. {
  8301. // Mask off system memory flag
  8302. WARNING("Driver turn on SYSTEMMEMORY flag, disable it");
  8303. peSurface[j]->ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
  8304. }
  8305. if (peSurface[j]->fpVidMem != DDHAL_PLEASEALLOC_USERMEM)
  8306. {
  8307. // Force allocations to the same memory type as the first
  8308. if (dwForceMemType)
  8309. {
  8310. peSurface[j]->ddsCaps.dwCaps &=
  8311. ~(DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM);
  8312. peSurface[j]->ddsCaps.dwCaps |= dwForceMemType;
  8313. }
  8314. // The driver didn't allocate a vidmem surface, so try
  8315. // to allocate one from system-managed memory.
  8316. CreateSurfaceData.ddRVal =
  8317. hrDdAllocSurface(peDirectDrawLocal,
  8318. peDirectDrawGlobal,
  8319. peSurface[j]);
  8320. DDKHEAP(("DDHKEAP: Heap alloced %X, "
  8321. "hr %X, surf %X (%X)\n",
  8322. peSurface[j]->fpVidMem,
  8323. CreateSurfaceData.ddRVal,
  8324. peSurface[j]->hGet(),
  8325. peSurface[j]));
  8326. if (CreateSurfaceData.ddRVal == DD_OK)
  8327. {
  8328. if (dwForceMemType == 0)
  8329. {
  8330. // All surfaces must be of the same type as the first
  8331. // so we remember the type of surface type which
  8332. // we have successfully created first time.
  8333. dwForceMemType =
  8334. peSurface[j]->ddsCaps.dwCaps &
  8335. (DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM);
  8336. }
  8337. }
  8338. }
  8339. else
  8340. {
  8341. // No forcemem things for user mode memory allocation.
  8342. //
  8343. // The driver didn't allocate a vidmem surface, so try
  8344. // to allocate one from system-managed memory.
  8345. CreateSurfaceData.ddRVal =
  8346. hrDdAllocSurface(peDirectDrawLocal,
  8347. peDirectDrawGlobal,
  8348. peSurface[j]);
  8349. }
  8350. }
  8351. }
  8352. }
  8353. // An attempt to allocate was made either by the driver
  8354. // or by the system allocator. If the attempt succeeded,
  8355. // complete the surface creation.
  8356. if ((dwRet == DDHAL_DRIVER_HANDLED) &&
  8357. (CreateSurfaceData.ddRVal == DD_OK))
  8358. {
  8359. // The object is complete. We can ignore any
  8360. // following DxDdCreateSurfaceObject calls that may
  8361. // occur on this object.
  8362. for (j = dwStart; j < dwEnd; j++)
  8363. {
  8364. vDdCompleteSurfaceObject(peDirectDrawLocal, peSurface[j]);
  8365. #if 0
  8366. ASSERTGDI((peSurface[j]->fl & DD_SURFACE_FLAG_PRIMARY) ||
  8367. (peSurface[j]->fpVidMem !=
  8368. peDirectDrawGlobal->HalInfo.vmiData.fpPrimary),
  8369. "Expected primary surface to be marked as such");
  8370. #endif
  8371. ASSERTGDI(peSurface[j]->hbmGdi == NULL,
  8372. "DxDdCreateSurface: Invalid cached bitmap");
  8373. if (peSurface[j]->bLost)
  8374. {
  8375. // Surface is ready for use.
  8376. peSurface[j]->bLost = FALSE;
  8377. // Now this surface is ready to go, increment active surface ref. count.
  8378. peSurface[j]->peDirectDrawLocal->cActiveSurface++;
  8379. ASSERTGDI(peSurface[j]->peDirectDrawLocal->cActiveSurface <=
  8380. peSurface[j]->peDirectDrawLocal->cSurface,
  8381. "cActiveSurface is > than cSurface");
  8382. }
  8383. // Copy surface information to local storage
  8384. // for access after the unlock.
  8385. puSurfaceGlobalData[j] = *peSurface[j];
  8386. puSurfaceLocalData[j].ddsCaps = peSurface[j]->ddsCaps;
  8387. puSurfaceMoreData[j].ddsCapsEx = peSurface[j]->ddsCapsEx;
  8388. // We were successful, so unlock the surface:
  8389. puhReturnSurfaceHandles[j] = peSurface[j]->hGet();
  8390. }
  8391. }
  8392. } // if (dwStart != dwEnd)
  8393. }
  8394. else
  8395. {
  8396. WARNING("DxDdCreateSurface: Couldn't allocate surface\n");
  8397. CreateSurfaceData.ddRVal = DDERR_OUTOFMEMORY;
  8398. }
  8399. }
  8400. else
  8401. {
  8402. WARNING("DxDdCreateSurface: Bad surface description\n");
  8403. CreateSurfaceData.ddRVal = DDERR_INVALIDPARAMS;
  8404. }
  8405. } // For loop
  8406. // The surface object is now created, call CreateSurfaceEx, to
  8407. // inform the driver to associate a cookie if the driver can
  8408. if ((peDirectDrawGlobal->Miscellaneous2CallBacks.CreateSurfaceEx)
  8409. && (CreateSurfaceData.ddRVal == DD_OK)
  8410. && (NULL != peSurface[0])
  8411. && (0 != peSurface[0]->dwSurfaceHandle)
  8412. )
  8413. {
  8414. DD_CREATESURFACEEXDATA CreateSurfaceExData;
  8415. CreateSurfaceExData.ddRVal = DDERR_GENERIC;
  8416. CreateSurfaceExData.dwFlags = 0;
  8417. CreateSurfaceExData.lpDDLcl = peDirectDrawLocal;
  8418. CreateSurfaceExData.lpDDSLcl = peSurface[0];
  8419. dwRet = peDirectDrawGlobal->Miscellaneous2CallBacks.CreateSurfaceEx(&CreateSurfaceExData);
  8420. if (dwRet != DDHAL_DRIVER_HANDLED)
  8421. {
  8422. // For now, simply warn that the driver failed to associate the surface with the
  8423. // token and continue
  8424. WARNING("dwDdCreateSurfaceOrBuffer: DDI call to the driver not handled\n");
  8425. dwRet = DDHAL_DRIVER_HANDLED;
  8426. CreateSurfaceData.ddRVal = DDERR_GENERIC;
  8427. }
  8428. else
  8429. {
  8430. // need to prop the return value as if it's in CreateSurfaceData
  8431. CreateSurfaceData.ddRVal = CreateSurfaceExData.ddRVal;
  8432. }
  8433. }
  8434. // Unlock the surfaces and clean up any failures.
  8435. for (j = 0; j < i; j++)
  8436. {
  8437. if (peSurface[j] != NULL)
  8438. {
  8439. if (CreateSurfaceData.ddRVal != DD_OK)
  8440. {
  8441. // Failure, so clean up the surface object.
  8442. bDdDeleteSurfaceObject(peSurface[j]->hGet(), NULL);
  8443. // bKeepSurface is left at TRUE so that any
  8444. // failure codes get written back. Ensure
  8445. // that fpVidMem is zero on return.
  8446. puSurfaceGlobalData[j].fpVidMem = 0;
  8447. puhReturnSurfaceHandles[j] = 0;
  8448. }
  8449. else
  8450. {
  8451. DEC_EXCLUSIVE_REF_CNT(peSurface[j]);
  8452. }
  8453. }
  8454. }
  8455. }
  8456. else
  8457. {
  8458. WARNING("DxDdCreateSurface: Unable to allocate or secure memory\n");
  8459. }
  8460. if (hSecureSurfaceHandles)
  8461. {
  8462. MmUnsecureVirtualMemory(hSecureSurfaceHandles);
  8463. }
  8464. if (hSecureGlobals)
  8465. {
  8466. MmUnsecureVirtualMemory(hSecureGlobals);
  8467. }
  8468. if (hSecureLocals)
  8469. {
  8470. MmUnsecureVirtualMemory(hSecureLocals);
  8471. }
  8472. if (hSecureMore)
  8473. {
  8474. MmUnsecureVirtualMemory(hSecureMore);
  8475. }
  8476. if (hSecureReturn)
  8477. {
  8478. MmUnsecureVirtualMemory(hSecureReturn);
  8479. }
  8480. if (peSurface != &peSurfaceOnStack)
  8481. {
  8482. VFREEMEM(peSurface);
  8483. }
  8484. if (pSList != NULL)
  8485. {
  8486. VFREEMEM(pSList);
  8487. }
  8488. }
  8489. else
  8490. {
  8491. if (!(peDirectDrawGlobal->fl & DD_GLOBAL_FLAG_DRIVER_ENABLED))
  8492. {
  8493. WARNING("DxDdCreateSurface: Driver doesn't support this mode\n");
  8494. }
  8495. else
  8496. {
  8497. CreateSurfaceData.ddRVal = DDERR_SURFACELOST;
  8498. }
  8499. }
  8500. }
  8501. else
  8502. {
  8503. WARNING("DxDdCreateSurface: Invalid object\n");
  8504. }
  8505. DDKHEAP(("DDKHEAP: Create returns %X, rval %X\n",
  8506. dwRet, CreateSurfaceData.ddRVal));
  8507. // We have to wrap this in another try-except because the user-mode
  8508. // memory containing the input may have been deallocated by now:
  8509. __try
  8510. {
  8511. if (dwRet == DDHAL_DRIVER_HANDLED)
  8512. {
  8513. ProbeAndWriteRVal(&puCreateSurfaceData->ddRVal,
  8514. CreateSurfaceData.ddRVal);
  8515. }
  8516. if (bKeepSurface)
  8517. {
  8518. ProbeAndWriteStructure((DDSURFACEDESC2*)puSurfaceDescription,
  8519. SurfaceDescription,
  8520. DDSURFACEDESC2);
  8521. }
  8522. }
  8523. __except(EXCEPTION_EXECUTE_HANDLER)
  8524. {
  8525. }
  8526. return(dwRet);
  8527. }
  8528. /******************************Public*Routine******************************\
  8529. * DWORD DxDdCreateSurface
  8530. *
  8531. * Corresponds to HAL CreateSurface entry point.
  8532. *
  8533. * Calls the driver to create a DirectDraw surface.
  8534. *
  8535. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  8536. * Wrote it.
  8537. \**************************************************************************/
  8538. DWORD
  8539. APIENTRY
  8540. DxDdCreateSurface(
  8541. HANDLE hDirectDraw,
  8542. HANDLE* puhSurfaceHandle,
  8543. DDSURFACEDESC* puSurfaceDescription,
  8544. DD_SURFACE_GLOBAL* puSurfaceGlobalData,
  8545. DD_SURFACE_LOCAL* puSurfaceLocalData,
  8546. DD_SURFACE_MORE* puSurfaceMoreData,
  8547. DD_CREATESURFACEDATA* puCreateSurfaceData,
  8548. HANDLE* puhSurface
  8549. )
  8550. {
  8551. return dwDdCreateSurfaceOrBuffer(hDirectDraw, puhSurfaceHandle,
  8552. puSurfaceDescription, puSurfaceGlobalData,
  8553. puSurfaceLocalData, puSurfaceMoreData,
  8554. puCreateSurfaceData, puhSurface);
  8555. }
  8556. /******************************Public*Routine******************************\
  8557. * DWORD DxDdDestroySurface
  8558. *
  8559. * Calls the driver to delete a surface it created via CreateSurface.
  8560. *
  8561. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  8562. * Wrote it.
  8563. \**************************************************************************/
  8564. DWORD
  8565. APIENTRY
  8566. DxDdDestroySurface(
  8567. HANDLE hSurface,
  8568. BOOL bRealDestroy
  8569. )
  8570. {
  8571. DWORD dwRet;
  8572. EDD_LOCK_SURFACE eLockSurface;
  8573. EDD_SURFACE* peSurface;
  8574. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  8575. BOOL b;
  8576. dwRet = DDHAL_DRIVER_NOTHANDLED;
  8577. peSurface = eLockSurface.peLock(hSurface);
  8578. if (peSurface != NULL)
  8579. {
  8580. peDirectDrawGlobal = peSurface->peDirectDrawGlobal;
  8581. {
  8582. EDD_SHAREDEVLOCK eDevlock(peDirectDrawGlobal);
  8583. if(bRealDestroy)
  8584. {
  8585. vDdDisableSurfaceObject(peDirectDrawGlobal,
  8586. peSurface,
  8587. &dwRet);
  8588. }
  8589. else
  8590. {
  8591. vDdLooseManagedSurfaceObject(peDirectDrawGlobal,
  8592. peSurface,
  8593. &dwRet);
  8594. return(dwRet);
  8595. }
  8596. }
  8597. // vDdDisableSurfaceObject doesn't delete the DC because it may
  8598. // be called from a different process than the one that created
  8599. // the DC. However, at this point we're guaranteed to be in the
  8600. // process that created the DC, so we should delete it now:
  8601. if (peSurface->hdc)
  8602. {
  8603. b = DxEngDeleteDC(peSurface->hdc, TRUE);
  8604. // DC may still be in use, which would cause the delete to fail,
  8605. // so we don't assert on the return value (the DC will still get
  8606. // cleaned up at process termination):
  8607. if (!b)
  8608. {
  8609. WARNING("DxDdDestroySurface: bDeleteDCInternal failed");
  8610. }
  8611. peSurface->hdc = 0;
  8612. }
  8613. }
  8614. else
  8615. {
  8616. WARNING("DxDdDestroySurface: Couldn't lock DirectDraw surface");
  8617. }
  8618. return(dwRet);
  8619. }
  8620. /******************************Public*Routine******************************\
  8621. * DWORD DxDdCreateD3DBuffer
  8622. *
  8623. * Calls the driver to create a D3D buffer.
  8624. *
  8625. * Corresponds to HAL CreateD3DBuffer entry point.
  8626. *
  8627. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  8628. * Wrote it.
  8629. \**************************************************************************/
  8630. DWORD
  8631. APIENTRY
  8632. DxDdCreateD3DBuffer(
  8633. HANDLE hDirectDraw,
  8634. HANDLE* puhSurfaceHandle,
  8635. DDSURFACEDESC* puSurfaceDescription,
  8636. DD_SURFACE_GLOBAL* puSurfaceGlobalData,
  8637. DD_SURFACE_LOCAL* puSurfaceLocalData,
  8638. DD_SURFACE_MORE* puSurfaceMoreData,
  8639. DD_CREATESURFACEDATA* puCreateSurfaceData,
  8640. HANDLE* puhSurface
  8641. )
  8642. {
  8643. return dwDdCreateSurfaceOrBuffer(hDirectDraw, puhSurfaceHandle,
  8644. puSurfaceDescription, puSurfaceGlobalData,
  8645. puSurfaceLocalData, puSurfaceMoreData,
  8646. puCreateSurfaceData, puhSurface);
  8647. }
  8648. /******************************Public*Routine******************************\
  8649. * DWORD DxDdDestroyD3DBuffer
  8650. *
  8651. * Calls the driver to delete a surface it created via CreateD3DBuffer.
  8652. *
  8653. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  8654. * Wrote it.
  8655. \**************************************************************************/
  8656. DWORD
  8657. APIENTRY
  8658. DxDdDestroyD3DBuffer(
  8659. HANDLE hSurface
  8660. )
  8661. {
  8662. DWORD dwRet;
  8663. EDD_LOCK_SURFACE eLockSurface;
  8664. EDD_SURFACE* peSurface;
  8665. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  8666. dwRet = DDHAL_DRIVER_NOTHANDLED;
  8667. peSurface = eLockSurface.peLock(hSurface);
  8668. if (peSurface != NULL)
  8669. {
  8670. peDirectDrawGlobal = peSurface->peDirectDrawGlobal;
  8671. {
  8672. EDD_SHAREDEVLOCK eDevlock(peDirectDrawGlobal);
  8673. vDdDisableSurfaceObject(peDirectDrawGlobal,
  8674. peSurface,
  8675. &dwRet);
  8676. }
  8677. }
  8678. else
  8679. {
  8680. WARNING("DxDdDestroyD3DBuffer: Couldn't lock DirectDraw surface");
  8681. }
  8682. return(dwRet);
  8683. }
  8684. /******************************Public*Routine******************************\
  8685. * DWORD DxDdSetColorKey
  8686. *
  8687. * This entry point is always hooked by NT kernel, regardless of whether
  8688. * the driver hooks it or not.
  8689. *
  8690. * Note that this call does not necessary need to be called on an overlay
  8691. * surface.
  8692. *
  8693. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  8694. * Wrote it.
  8695. \**************************************************************************/
  8696. DWORD
  8697. APIENTRY
  8698. DxDdSetColorKey(
  8699. HANDLE hSurface,
  8700. PDD_SETCOLORKEYDATA puSetColorKeyData
  8701. )
  8702. {
  8703. DWORD dwRet;
  8704. DD_SETCOLORKEYDATA SetColorKeyData;
  8705. __try
  8706. {
  8707. SetColorKeyData = ProbeAndReadStructure(puSetColorKeyData,
  8708. DD_SETCOLORKEYDATA);
  8709. }
  8710. __except(EXCEPTION_EXECUTE_HANDLER)
  8711. {
  8712. return(DDHAL_DRIVER_NOTHANDLED);
  8713. }
  8714. dwRet = DDHAL_DRIVER_NOTHANDLED;
  8715. SetColorKeyData.ddRVal = DDERR_GENERIC;
  8716. EDD_SURFACE* peSurface;
  8717. EDD_LOCK_SURFACE eLockSurface;
  8718. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  8719. peSurface = eLockSurface.peLock(hSurface);
  8720. if ((peSurface != NULL) &&
  8721. !(peSurface->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY))
  8722. {
  8723. peDirectDrawGlobal = peSurface->peDirectDrawGlobal;
  8724. if (SetColorKeyData.dwFlags & DDCKEY_SRCBLT)
  8725. {
  8726. peSurface->dwFlags |= DDRAWISURF_HASCKEYSRCBLT;
  8727. peSurface->ddckCKSrcBlt = SetColorKeyData.ckNew;
  8728. }
  8729. // If the driver doesn't hook SetColorKey, we return
  8730. // DDHAL_DRIVER_NOTHANDLED, which means okay.
  8731. if (peDirectDrawGlobal->SurfaceCallBacks.dwFlags &
  8732. DDHAL_SURFCB32_SETCOLORKEY)
  8733. {
  8734. SetColorKeyData.lpDD = peDirectDrawGlobal;
  8735. SetColorKeyData.lpDDSurface = peSurface;
  8736. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  8737. if (peSurface->bLost)
  8738. {
  8739. dwRet = DDHAL_DRIVER_HANDLED;
  8740. SetColorKeyData.ddRVal = DDERR_SURFACELOST;
  8741. }
  8742. else
  8743. {
  8744. dwRet = peDirectDrawGlobal->
  8745. SurfaceCallBacks.SetColorKey(&SetColorKeyData);
  8746. }
  8747. }
  8748. }
  8749. else
  8750. {
  8751. WARNING("DxDdSetColorKey: Invalid surface or dwFlags\n");
  8752. }
  8753. // We have to wrap this in another try-except because the user-mode
  8754. // memory containing the input may have been deallocated by now:
  8755. __try
  8756. {
  8757. ProbeAndWriteRVal(&puSetColorKeyData->ddRVal, SetColorKeyData.ddRVal);
  8758. }
  8759. __except(EXCEPTION_EXECUTE_HANDLER)
  8760. {
  8761. }
  8762. return(dwRet);
  8763. }
  8764. /******************************Public*Routine******************************\
  8765. * DWORD DxDdAddAttachedSurface
  8766. *
  8767. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  8768. * Wrote it.
  8769. \**************************************************************************/
  8770. DWORD
  8771. APIENTRY
  8772. DxDdAddAttachedSurface(
  8773. HANDLE hSurface,
  8774. HANDLE hSurfaceAttached,
  8775. PDD_ADDATTACHEDSURFACEDATA puAddAttachedSurfaceData
  8776. )
  8777. {
  8778. DWORD dwRet;
  8779. DD_ADDATTACHEDSURFACEDATA AddAttachedSurfaceData;
  8780. __try
  8781. {
  8782. AddAttachedSurfaceData = ProbeAndReadStructure(puAddAttachedSurfaceData,
  8783. DD_ADDATTACHEDSURFACEDATA);
  8784. }
  8785. __except(EXCEPTION_EXECUTE_HANDLER)
  8786. {
  8787. return(DDHAL_DRIVER_NOTHANDLED);
  8788. }
  8789. dwRet = DDHAL_DRIVER_NOTHANDLED;
  8790. AddAttachedSurfaceData.ddRVal = DDERR_GENERIC;
  8791. EDD_SURFACE* peSurface;
  8792. EDD_SURFACE* peSurfaceAttached;
  8793. EDD_LOCK_SURFACE eLockSurface;
  8794. EDD_LOCK_SURFACE eLockSurfaceAttached;
  8795. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  8796. peSurface = eLockSurface.peLock(hSurface);
  8797. peSurfaceAttached = eLockSurfaceAttached.peLock(hSurfaceAttached);
  8798. if ((peSurface != NULL) &&
  8799. (peSurfaceAttached != NULL) &&
  8800. !(peSurface->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  8801. !(peSurfaceAttached->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  8802. (peSurface->peDirectDrawLocal == peSurfaceAttached->peDirectDrawLocal))
  8803. {
  8804. peDirectDrawGlobal = peSurface->peDirectDrawGlobal;
  8805. // If the driver doesn't hook AddAttachedSurface, we return
  8806. // DDHAL_DRIVER_NOTHANDLED, which means okay.
  8807. if (peDirectDrawGlobal->SurfaceCallBacks.dwFlags &
  8808. DDHAL_SURFCB32_ADDATTACHEDSURFACE)
  8809. {
  8810. AddAttachedSurfaceData.lpDD = peDirectDrawGlobal;
  8811. AddAttachedSurfaceData.lpDDSurface = peSurface;
  8812. AddAttachedSurfaceData.lpSurfAttached = peSurfaceAttached;
  8813. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  8814. if ((peSurface->bLost) || (peSurfaceAttached->bLost))
  8815. {
  8816. dwRet = DDHAL_DRIVER_HANDLED;
  8817. AddAttachedSurfaceData.ddRVal = DDERR_SURFACELOST;
  8818. }
  8819. else
  8820. {
  8821. dwRet = peDirectDrawGlobal->
  8822. SurfaceCallBacks.AddAttachedSurface(&AddAttachedSurfaceData);
  8823. }
  8824. }
  8825. }
  8826. else
  8827. {
  8828. WARNING("DxDdAddAttachedSurface: Invalid surface or dwFlags\n");
  8829. }
  8830. // We have to wrap this in another try-except because the user-mode
  8831. // memory containing the input may have been deallocated by now:
  8832. __try
  8833. {
  8834. ProbeAndWriteRVal(&puAddAttachedSurfaceData->ddRVal,
  8835. AddAttachedSurfaceData.ddRVal);
  8836. }
  8837. __except(EXCEPTION_EXECUTE_HANDLER)
  8838. {
  8839. }
  8840. return(dwRet);
  8841. }
  8842. /******************************Public*Routine******************************\
  8843. * DWORD DxDdUpdateOverlay
  8844. *
  8845. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  8846. * Wrote it.
  8847. \**************************************************************************/
  8848. DWORD
  8849. APIENTRY
  8850. DxDdUpdateOverlay(
  8851. HANDLE hSurfaceDestination,
  8852. HANDLE hSurfaceSource,
  8853. PDD_UPDATEOVERLAYDATA puUpdateOverlayData
  8854. )
  8855. {
  8856. DWORD dwRet;
  8857. DD_UPDATEOVERLAYDATA UpdateOverlayData;
  8858. EDD_VIDEOPORT* peVideoPort = NULL;
  8859. EDD_DXSURFACE* peDxSurface;
  8860. DWORD dwOldFlags;
  8861. __try
  8862. {
  8863. UpdateOverlayData = ProbeAndReadStructure(puUpdateOverlayData,
  8864. DD_UPDATEOVERLAYDATA);
  8865. }
  8866. __except(EXCEPTION_EXECUTE_HANDLER)
  8867. {
  8868. return(DDHAL_DRIVER_NOTHANDLED);
  8869. }
  8870. dwRet = DDHAL_DRIVER_NOTHANDLED;
  8871. UpdateOverlayData.ddRVal = DDERR_GENERIC;
  8872. EDD_SURFACE* peSurfaceSource;
  8873. EDD_SURFACE* peSurfaceDestination;
  8874. EDD_SURFACE* peSurface;
  8875. EDD_LOCK_SURFACE eLockSurfaceSource;
  8876. EDD_LOCK_SURFACE eLockSurfaceDestination;
  8877. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  8878. // 'peSurfaceSource' is the overlay surface, 'peSurfaceDestination' is
  8879. // the surface to be overlayed.
  8880. peSurfaceSource = eLockSurfaceSource.peLock(hSurfaceSource);
  8881. if ((peSurfaceSource != NULL) &&
  8882. !(peSurfaceSource->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  8883. (peSurfaceSource->ddsCaps.dwCaps & DDSCAPS_OVERLAY))
  8884. {
  8885. peDirectDrawGlobal = peSurfaceSource->peDirectDrawGlobal;
  8886. // If we're being asked to hide the overlay, then we don't need
  8887. // check any more parameters:
  8888. peSurfaceDestination = NULL;
  8889. if (!(UpdateOverlayData.dwFlags & DDOVER_HIDE))
  8890. {
  8891. // Okay, we have to validate every parameter in this call:
  8892. peSurfaceDestination
  8893. = eLockSurfaceDestination.peLock(hSurfaceDestination);
  8894. if ((peSurfaceDestination == NULL) ||
  8895. (peSurfaceDestination->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) ||
  8896. (peSurfaceDestination->peDirectDrawLocal !=
  8897. peSurfaceSource->peDirectDrawLocal) ||
  8898. (UpdateOverlayData.rDest.left < DD_MINIMUM_COORDINATE) ||
  8899. (UpdateOverlayData.rDest.top < DD_MINIMUM_COORDINATE) ||
  8900. (UpdateOverlayData.rDest.right > DD_MAXIMUM_COORDINATE) ||
  8901. (UpdateOverlayData.rDest.bottom > DD_MAXIMUM_COORDINATE) ||
  8902. (UpdateOverlayData.rDest.left >= UpdateOverlayData.rDest.right) ||
  8903. (UpdateOverlayData.rDest.top >= UpdateOverlayData.rDest.bottom) ||
  8904. (UpdateOverlayData.rSrc.left < DD_MINIMUM_COORDINATE) ||
  8905. (UpdateOverlayData.rSrc.top < DD_MINIMUM_COORDINATE) ||
  8906. (UpdateOverlayData.rSrc.right > DD_MAXIMUM_COORDINATE) ||
  8907. (UpdateOverlayData.rSrc.bottom > DD_MAXIMUM_COORDINATE) ||
  8908. (UpdateOverlayData.rSrc.left >= UpdateOverlayData.rSrc.right) ||
  8909. (UpdateOverlayData.rSrc.top >= UpdateOverlayData.rSrc.bottom))
  8910. {
  8911. WARNING("DxDdUpdateOverlay: Invalid destination or rectangle\n");
  8912. return(dwRet);
  8913. }
  8914. // We don't keep track of pSurfaceLocal->ddckCKSrcOverlay in
  8915. // kernel mode, so we always expect the user-mode call to convert
  8916. // to DDOVER_KEYDESTOVERRIDE or DDOVER_KEYSRCOVERRIDE. It is by
  8917. // no means fatal if this is not the case, so we only do a warning:
  8918. if ((UpdateOverlayData.dwFlags & DDOVER_KEYDEST) ||
  8919. (UpdateOverlayData.dwFlags & DDOVER_KEYSRC))
  8920. {
  8921. WARNING("DxDdUpdateOverlay: Expected user-mode to set OVERRIDE\n");
  8922. }
  8923. // If using a video port, disable autoflipping and hardware
  8924. // bob when neccesary
  8925. if( peSurfaceSource->ddsCaps.dwCaps & DDSCAPS_VIDEOPORT )
  8926. {
  8927. peVideoPort = (EDD_VIDEOPORT*) peSurfaceSource->lpVideoPort;
  8928. if( peVideoPort != NULL )
  8929. {
  8930. if( ( peVideoPort->peDxVideoPort->bSoftwareAutoflip ) ||
  8931. ( peVideoPort->peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_SOFTWAREBOB ) )
  8932. {
  8933. UpdateOverlayData.dwFlags &= ~(DDOVER_AUTOFLIP|DDOVER_BOBHARDWARE);
  8934. }
  8935. }
  8936. }
  8937. // If this surface is being used by DxApi, change to weave if
  8938. // DxApi told it to and visa versa.
  8939. peDxSurface = peSurfaceSource->peDxSurface;
  8940. if( peDxSurface != NULL )
  8941. {
  8942. if( peDxSurface->flFlags & DD_DXSURFACE_FLAG_STATE_SET )
  8943. {
  8944. if( peDxSurface->flFlags & DD_DXSURFACE_FLAG_STATE_BOB )
  8945. {
  8946. UpdateOverlayData.dwFlags |= DDOVER_BOB;
  8947. }
  8948. else if( peDxSurface->flFlags & DD_DXSURFACE_FLAG_STATE_WEAVE )
  8949. {
  8950. UpdateOverlayData.dwFlags &= ~DDOVER_BOB | DDOVER_BOBHARDWARE;
  8951. }
  8952. }
  8953. }
  8954. }
  8955. if (peDirectDrawGlobal->SurfaceCallBacks.dwFlags
  8956. & DDHAL_SURFCB32_UPDATEOVERLAY)
  8957. {
  8958. UpdateOverlayData.lpDD = peDirectDrawGlobal;
  8959. UpdateOverlayData.lpDDDestSurface = peSurfaceDestination;
  8960. UpdateOverlayData.lpDDSrcSurface = peSurfaceSource;
  8961. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  8962. if ((peSurfaceSource->bLost) ||
  8963. ((peSurfaceDestination != NULL) && (peSurfaceDestination->bLost)))
  8964. {
  8965. dwRet = DDHAL_DRIVER_HANDLED;
  8966. UpdateOverlayData.ddRVal = DDERR_SURFACELOST;
  8967. }
  8968. else
  8969. {
  8970. peSurfaceSource->fl |= DD_SURFACE_FLAG_UPDATE_OVERLAY_CALLED;
  8971. dwRet = peDirectDrawGlobal->SurfaceCallBacks.UpdateOverlay(
  8972. &UpdateOverlayData);
  8973. // If it failed due to hardware autoflipping/bobbing
  8974. // and software autoflipping is an option, try again
  8975. // without hardware autolfipping. If it works, we will
  8976. // revert to software autoflipping.
  8977. if( ( dwRet == DDHAL_DRIVER_HANDLED ) &&
  8978. ( UpdateOverlayData.ddRVal != DD_OK ) &&
  8979. ( UpdateOverlayData.dwFlags & (DDOVER_AUTOFLIP|DDOVER_BOBHARDWARE) ) &&
  8980. ( peDirectDrawGlobal->DDKernelCaps.dwCaps & DDKERNELCAPS_AUTOFLIP ) )
  8981. {
  8982. dwOldFlags = UpdateOverlayData.dwFlags;
  8983. UpdateOverlayData.dwFlags &= ~(DDOVER_AUTOFLIP|DDOVER_BOBHARDWARE);
  8984. dwRet = peDirectDrawGlobal->SurfaceCallBacks.UpdateOverlay(
  8985. &UpdateOverlayData);
  8986. if ((dwRet == DDHAL_DRIVER_HANDLED) &&
  8987. (UpdateOverlayData.ddRVal == DD_OK))
  8988. {
  8989. if( dwOldFlags & DDOVER_AUTOFLIP )
  8990. {
  8991. peVideoPort->peDxVideoPort->bSoftwareAutoflip = TRUE;
  8992. if( peVideoPort->cAutoflipVideo > 0 )
  8993. {
  8994. peVideoPort->peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_AUTOFLIP;
  8995. }
  8996. if( peVideoPort->cAutoflipVbi > 0 )
  8997. {
  8998. peVideoPort->peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI;
  8999. }
  9000. }
  9001. if( dwOldFlags & DDOVER_BOBHARDWARE )
  9002. {
  9003. peVideoPort->peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_SOFTWAREBOB;
  9004. }
  9005. }
  9006. }
  9007. if ((dwRet == DDHAL_DRIVER_HANDLED) &&
  9008. (UpdateOverlayData.ddRVal == DD_OK))
  9009. {
  9010. // Update the DXAPI data for all surfaces in the chain:
  9011. if( peVideoPort != NULL )
  9012. {
  9013. if( UpdateOverlayData.dwFlags & DDOVER_BOB )
  9014. {
  9015. peVideoPort->peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_BOB;
  9016. }
  9017. else
  9018. {
  9019. peVideoPort->peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_BOB;
  9020. }
  9021. }
  9022. peSurface = peSurfaceSource;
  9023. while (TRUE)
  9024. {
  9025. peSurface->dwOverlayFlags = UpdateOverlayData.dwFlags;
  9026. peSurface->dwOverlaySrcWidth
  9027. = UpdateOverlayData.rSrc.right -
  9028. UpdateOverlayData.rSrc.left;
  9029. peSurface->dwOverlaySrcHeight
  9030. = UpdateOverlayData.rSrc.bottom -
  9031. UpdateOverlayData.rSrc.top;
  9032. peSurface->dwOverlayDestWidth
  9033. = UpdateOverlayData.rDest.right -
  9034. UpdateOverlayData.rDest.left;
  9035. peSurface->dwOverlayDestHeight
  9036. = UpdateOverlayData.rDest.bottom -
  9037. UpdateOverlayData.rDest.top;
  9038. peSurface->rcOverlaySrc.left =
  9039. UpdateOverlayData.rSrc.left;
  9040. peSurface->rcOverlaySrc.right =
  9041. UpdateOverlayData.rSrc.right;
  9042. peSurface->rcOverlaySrc.top =
  9043. UpdateOverlayData.rSrc.top;
  9044. peSurface->rcOverlaySrc.bottom =
  9045. UpdateOverlayData.rSrc.bottom;
  9046. vDdSynchronizeSurface(peSurface);
  9047. if (peSurface->lpAttachList == NULL)
  9048. break;
  9049. peSurface
  9050. = pedFromLp(peSurface->lpAttachList->lpAttached);
  9051. }
  9052. }
  9053. }
  9054. }
  9055. }
  9056. else
  9057. {
  9058. WARNING("DxDdUpdateOverlay: Invalid source or dwFlags\n");
  9059. }
  9060. // We have to wrap this in another try-except because the user-mode
  9061. // memory containing the input may have been deallocated by now:
  9062. __try
  9063. {
  9064. ProbeAndWriteRVal(&puUpdateOverlayData->ddRVal, UpdateOverlayData.ddRVal);
  9065. }
  9066. __except(EXCEPTION_EXECUTE_HANDLER)
  9067. {
  9068. }
  9069. return(dwRet);
  9070. }
  9071. /******************************Public*Routine******************************\
  9072. * DWORD DxDdSetOverlayPosition
  9073. *
  9074. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  9075. * Wrote it.
  9076. \**************************************************************************/
  9077. DWORD
  9078. APIENTRY
  9079. DxDdSetOverlayPosition(
  9080. HANDLE hSurfaceSource,
  9081. HANDLE hSurfaceDestination,
  9082. PDD_SETOVERLAYPOSITIONDATA puSetOverlayPositionData
  9083. )
  9084. {
  9085. DWORD dwRet;
  9086. DD_SETOVERLAYPOSITIONDATA SetOverlayPositionData;
  9087. __try
  9088. {
  9089. SetOverlayPositionData = ProbeAndReadStructure(puSetOverlayPositionData,
  9090. DD_SETOVERLAYPOSITIONDATA);
  9091. }
  9092. __except(EXCEPTION_EXECUTE_HANDLER)
  9093. {
  9094. return(DDHAL_DRIVER_NOTHANDLED);
  9095. }
  9096. dwRet = DDHAL_DRIVER_NOTHANDLED;
  9097. SetOverlayPositionData.ddRVal = DDERR_GENERIC;
  9098. EDD_SURFACE* peSurfaceSource;
  9099. EDD_SURFACE* peSurfaceDestination;
  9100. EDD_LOCK_SURFACE eLockSurfaceSource;
  9101. EDD_LOCK_SURFACE eLockSurfaceDestination;
  9102. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  9103. peSurfaceSource = eLockSurfaceSource.peLock(hSurfaceSource);
  9104. peSurfaceDestination = eLockSurfaceSource.peLock(hSurfaceDestination);
  9105. if ((peSurfaceSource != NULL) &&
  9106. (peSurfaceDestination != NULL) &&
  9107. (peSurfaceSource->ddsCaps.dwCaps & DDSCAPS_OVERLAY) &&
  9108. !(peSurfaceSource->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  9109. !(peSurfaceDestination->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY))
  9110. {
  9111. peDirectDrawGlobal = peSurfaceSource->peDirectDrawGlobal;
  9112. if (peDirectDrawGlobal->SurfaceCallBacks.dwFlags &
  9113. DDHAL_SURFCB32_SETOVERLAYPOSITION)
  9114. {
  9115. SetOverlayPositionData.lpDD = peDirectDrawGlobal;
  9116. SetOverlayPositionData.lpDDSrcSurface = peSurfaceSource;
  9117. SetOverlayPositionData.lpDDDestSurface = peSurfaceDestination;
  9118. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  9119. if ((peSurfaceSource->bLost) || (peSurfaceDestination->bLost))
  9120. {
  9121. dwRet = DDHAL_DRIVER_HANDLED;
  9122. SetOverlayPositionData.ddRVal = DDERR_SURFACELOST;
  9123. }
  9124. else
  9125. {
  9126. dwRet = peDirectDrawGlobal->
  9127. SurfaceCallBacks.SetOverlayPosition(&SetOverlayPositionData);
  9128. }
  9129. }
  9130. }
  9131. else
  9132. {
  9133. WARNING("DxDdSetOverlayPosition: Invalid surfaces or dwFlags\n");
  9134. }
  9135. // We have to wrap this in another try-except because the user-mode
  9136. // memory containing the input may have been deallocated by now:
  9137. __try
  9138. {
  9139. ProbeAndWriteRVal(&puSetOverlayPositionData->ddRVal,
  9140. SetOverlayPositionData.ddRVal);
  9141. }
  9142. __except(EXCEPTION_EXECUTE_HANDLER)
  9143. {
  9144. }
  9145. return(dwRet);
  9146. }
  9147. /******************************Public*Routine******************************\
  9148. * DWORD DxDdGetScanLine
  9149. *
  9150. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  9151. * Wrote it.
  9152. \**************************************************************************/
  9153. DWORD
  9154. APIENTRY
  9155. DxDdGetScanLine(
  9156. HANDLE hDirectDraw,
  9157. PDD_GETSCANLINEDATA puGetScanLineData
  9158. )
  9159. {
  9160. DWORD dwRet;
  9161. DD_GETSCANLINEDATA GetScanLineData;
  9162. __try
  9163. {
  9164. GetScanLineData = ProbeAndReadStructure(puGetScanLineData,
  9165. DD_GETSCANLINEDATA);
  9166. }
  9167. __except(EXCEPTION_EXECUTE_HANDLER)
  9168. {
  9169. return(DDHAL_DRIVER_NOTHANDLED);
  9170. }
  9171. dwRet = DDHAL_DRIVER_NOTHANDLED;
  9172. GetScanLineData.ddRVal = DDERR_GENERIC;
  9173. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  9174. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  9175. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  9176. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
  9177. if (peDirectDrawLocal != NULL)
  9178. {
  9179. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  9180. if (peDirectDrawGlobal->CallBacks.dwFlags & DDHAL_CB32_GETSCANLINE)
  9181. {
  9182. GetScanLineData.lpDD = peDirectDrawGlobal;
  9183. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  9184. if (peDirectDrawGlobal->bSuspended)
  9185. {
  9186. dwRet = DDHAL_DRIVER_HANDLED;
  9187. GetScanLineData.ddRVal = DDERR_SURFACELOST;
  9188. }
  9189. else
  9190. {
  9191. dwRet = peDirectDrawGlobal->
  9192. CallBacks.GetScanLine(&GetScanLineData);
  9193. }
  9194. }
  9195. }
  9196. else
  9197. {
  9198. WARNING("DxDdGetScanLine: Invalid object or dwFlags\n");
  9199. }
  9200. // We have to wrap this in another try-except because the user-mode
  9201. // memory containing the input may have been deallocated by now:
  9202. __try
  9203. {
  9204. ProbeAndWriteRVal(&puGetScanLineData->ddRVal,
  9205. GetScanLineData.ddRVal);
  9206. ProbeAndWriteUlong(&puGetScanLineData->dwScanLine,
  9207. GetScanLineData.dwScanLine);
  9208. }
  9209. __except(EXCEPTION_EXECUTE_HANDLER)
  9210. {
  9211. }
  9212. return(dwRet);
  9213. }
  9214. /******************************Public*Routine******************************\
  9215. * DWORD DxDdSetExclusiveMode
  9216. *
  9217. * 22-Apr-1998 -by- John Stephens [johnstep]
  9218. * Wrote it.
  9219. \**************************************************************************/
  9220. DWORD
  9221. APIENTRY
  9222. DxDdSetExclusiveMode(
  9223. HANDLE hDirectDraw,
  9224. PDD_SETEXCLUSIVEMODEDATA puSetExclusiveModeData
  9225. )
  9226. {
  9227. DWORD dwRet;
  9228. DD_SETEXCLUSIVEMODEDATA SetExclusiveModeData;
  9229. __try
  9230. {
  9231. SetExclusiveModeData = ProbeAndReadStructure(puSetExclusiveModeData,
  9232. DD_SETEXCLUSIVEMODEDATA);
  9233. }
  9234. __except(EXCEPTION_EXECUTE_HANDLER)
  9235. {
  9236. return(DDHAL_DRIVER_NOTHANDLED);
  9237. }
  9238. dwRet = DDHAL_DRIVER_NOTHANDLED;
  9239. SetExclusiveModeData.ddRVal = DDERR_GENERIC;
  9240. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  9241. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  9242. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  9243. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
  9244. if (peDirectDrawLocal != NULL)
  9245. {
  9246. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  9247. if (peDirectDrawGlobal->NTCallBacks.dwFlags &
  9248. DDHAL_NTCB32_SETEXCLUSIVEMODE)
  9249. {
  9250. SetExclusiveModeData.lpDD = peDirectDrawGlobal;
  9251. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  9252. if (!peDirectDrawGlobal->bSuspended)
  9253. {
  9254. dwRet = peDirectDrawGlobal->NTCallBacks.
  9255. SetExclusiveMode(&SetExclusiveModeData);
  9256. }
  9257. else
  9258. {
  9259. dwRet = DDHAL_DRIVER_HANDLED;
  9260. WARNING("DxDdSetExclusiveMode: "
  9261. "Can't set exclusive mode because disabled\n");
  9262. }
  9263. }
  9264. }
  9265. else
  9266. {
  9267. WARNING("DxDdSetExclusiveMode: Invalid object or dwFlags\n");
  9268. }
  9269. // We have to wrap this in another try-except because the user-mode
  9270. // memory containing the input may have been deallocated by now:
  9271. __try
  9272. {
  9273. ProbeAndWriteRVal(&puSetExclusiveModeData->ddRVal,
  9274. SetExclusiveModeData.ddRVal);
  9275. }
  9276. __except(EXCEPTION_EXECUTE_HANDLER)
  9277. {
  9278. }
  9279. return(dwRet);
  9280. }
  9281. /******************************Public*Routine******************************\
  9282. * DWORD DxDdFlipToGDISurface
  9283. *
  9284. * 22-Apr-1998 -by- John Stephens [johnstep]
  9285. * Wrote it.
  9286. \**************************************************************************/
  9287. DWORD
  9288. APIENTRY
  9289. DxDdFlipToGDISurface(
  9290. HANDLE hDirectDraw,
  9291. PDD_FLIPTOGDISURFACEDATA puFlipToGDISurfaceData
  9292. )
  9293. {
  9294. DWORD dwRet;
  9295. DD_FLIPTOGDISURFACEDATA FlipToGDISurfaceData;
  9296. __try
  9297. {
  9298. FlipToGDISurfaceData = ProbeAndReadStructure(puFlipToGDISurfaceData,
  9299. DD_FLIPTOGDISURFACEDATA);
  9300. }
  9301. __except(EXCEPTION_EXECUTE_HANDLER)
  9302. {
  9303. return(DDHAL_DRIVER_NOTHANDLED);
  9304. }
  9305. dwRet = DDHAL_DRIVER_NOTHANDLED;
  9306. FlipToGDISurfaceData.ddRVal = DDERR_GENERIC;
  9307. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  9308. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  9309. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  9310. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
  9311. if (peDirectDrawLocal != NULL)
  9312. {
  9313. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  9314. if (peDirectDrawGlobal->NTCallBacks.dwFlags &
  9315. DDHAL_NTCB32_FLIPTOGDISURFACE)
  9316. {
  9317. FlipToGDISurfaceData.lpDD = peDirectDrawGlobal;
  9318. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  9319. if (!peDirectDrawGlobal->bSuspended)
  9320. {
  9321. dwRet = peDirectDrawGlobal->NTCallBacks.
  9322. FlipToGDISurface(&FlipToGDISurfaceData);
  9323. }
  9324. else
  9325. {
  9326. dwRet = DDHAL_DRIVER_HANDLED;
  9327. WARNING("DxDdFlipToGDISurface: "
  9328. "Can't flip because disabled\n");
  9329. }
  9330. }
  9331. }
  9332. else
  9333. {
  9334. WARNING("DxDdFlipToGDISurface: Invalid object or dwFlags\n");
  9335. }
  9336. // We have to wrap this in another try-except because the user-mode
  9337. // memory containing the input may have been deallocated by now:
  9338. __try
  9339. {
  9340. ProbeAndWriteRVal(&puFlipToGDISurfaceData->ddRVal,
  9341. FlipToGDISurfaceData.ddRVal);
  9342. }
  9343. __except(EXCEPTION_EXECUTE_HANDLER)
  9344. {
  9345. }
  9346. return(dwRet);
  9347. }
  9348. /*****************************Private*Routine******************************\
  9349. * DWORD DxDdGetVailDriverMemory
  9350. *
  9351. * History:
  9352. * 16-Feb-1997 -by- J. Andrew Goossen [andrewgo]
  9353. * Wrote it.
  9354. \**************************************************************************/
  9355. DWORD
  9356. APIENTRY
  9357. DxDdGetAvailDriverMemory(
  9358. HANDLE hDirectDraw,
  9359. PDD_GETAVAILDRIVERMEMORYDATA puGetAvailDriverMemoryData
  9360. )
  9361. {
  9362. DD_GETAVAILDRIVERMEMORYDATA GetAvailDriverMemoryData;
  9363. DWORD dwHeap;
  9364. VIDEOMEMORY* pHeap;
  9365. DWORD dwAllocated = 0;
  9366. DWORD dwFree = 0;
  9367. __try
  9368. {
  9369. GetAvailDriverMemoryData
  9370. = ProbeAndReadStructure(puGetAvailDriverMemoryData,
  9371. DD_GETAVAILDRIVERMEMORYDATA);
  9372. }
  9373. __except(EXCEPTION_EXECUTE_HANDLER)
  9374. {
  9375. return(DDHAL_DRIVER_NOTHANDLED);
  9376. }
  9377. GetAvailDriverMemoryData.ddRVal = DD_OK;
  9378. GetAvailDriverMemoryData.dwTotal = 0;
  9379. GetAvailDriverMemoryData.dwFree = 0;
  9380. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  9381. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  9382. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  9383. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
  9384. if (peDirectDrawLocal != NULL)
  9385. {
  9386. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  9387. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  9388. // First count up all the memory for the heaps we control in kernel.
  9389. pHeap = peDirectDrawGlobal->pvmList;
  9390. for (dwHeap = 0;
  9391. dwHeap < peDirectDrawGlobal->dwNumHeaps;
  9392. pHeap++, dwHeap++)
  9393. {
  9394. /*
  9395. * We use ddsCapsAlt as we wish to return the total amount
  9396. * of memory of the given type it is possible to allocate
  9397. * regardless of whether it is desirable to allocate that
  9398. * type of memory from a given heap or not.
  9399. */
  9400. if( (pHeap->dwFlags & VIDMEM_HEAPDISABLED) == 0 &&
  9401. (GetAvailDriverMemoryData.DDSCaps.dwCaps &
  9402. pHeap->ddsCapsAlt.dwCaps) == 0 )
  9403. {
  9404. dwFree += VidMemAmountFree( pHeap->lpHeap );
  9405. dwAllocated += VidMemAmountAllocated( pHeap->lpHeap );
  9406. }
  9407. }
  9408. if (peDirectDrawGlobal->MiscellaneousCallBacks.dwFlags &
  9409. DDHAL_MISCCB32_GETAVAILDRIVERMEMORY)
  9410. {
  9411. GetAvailDriverMemoryData.lpDD = peDirectDrawGlobal;
  9412. if (peDirectDrawGlobal->bSuspended)
  9413. {
  9414. GetAvailDriverMemoryData.ddRVal = DDERR_SURFACELOST;
  9415. }
  9416. else
  9417. {
  9418. peDirectDrawGlobal->MiscellaneousCallBacks.
  9419. GetAvailDriverMemory(&GetAvailDriverMemoryData);
  9420. }
  9421. }
  9422. }
  9423. else
  9424. {
  9425. WARNING("DxDdGetAvailDriverMemory: Invalid object or dwFlags\n");
  9426. }
  9427. // We have to wrap this in another try-except because the user-mode
  9428. // memory containing the input may have been deallocated by now:
  9429. __try
  9430. {
  9431. ProbeAndWriteRVal(&puGetAvailDriverMemoryData->ddRVal,
  9432. GetAvailDriverMemoryData.ddRVal);
  9433. ProbeAndWriteUlong(&puGetAvailDriverMemoryData->dwTotal,
  9434. GetAvailDriverMemoryData.dwTotal + dwAllocated + dwFree);
  9435. ProbeAndWriteUlong(&puGetAvailDriverMemoryData->dwFree,
  9436. GetAvailDriverMemoryData.dwFree + dwFree);
  9437. }
  9438. __except(EXCEPTION_EXECUTE_HANDLER)
  9439. {
  9440. }
  9441. return(DDHAL_DRIVER_HANDLED);
  9442. }
  9443. /*****************************Private*Routine******************************\
  9444. * DWORD DxDdColorControl
  9445. *
  9446. * Not to be confused with the VideoPort ColorControl function.
  9447. *
  9448. * History:
  9449. * 16-Feb-1997 -by- J. Andrew Goossen [andrewgo]
  9450. * Wrote it.
  9451. \**************************************************************************/
  9452. DWORD
  9453. APIENTRY
  9454. DxDdColorControl(
  9455. HANDLE hSurface,
  9456. PDD_COLORCONTROLDATA puColorControlData
  9457. )
  9458. {
  9459. DWORD dwRet;
  9460. DD_COLORCONTROLDATA ColorControlData;
  9461. DDCOLORCONTROL ColorInfo;
  9462. __try
  9463. {
  9464. ColorControlData = ProbeAndReadStructure(puColorControlData,
  9465. DD_COLORCONTROLDATA);
  9466. ColorInfo = ProbeAndReadStructure(ColorControlData.lpColorData,
  9467. DDCOLORCONTROL);
  9468. }
  9469. __except(EXCEPTION_EXECUTE_HANDLER)
  9470. {
  9471. return(DDHAL_DRIVER_NOTHANDLED);
  9472. }
  9473. dwRet = DDHAL_DRIVER_NOTHANDLED;
  9474. ColorControlData.ddRVal = DDERR_GENERIC;
  9475. EDD_SURFACE* peSurface;
  9476. EDD_LOCK_SURFACE eLockSurface;
  9477. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  9478. peSurface = eLockSurface.peLock(hSurface);
  9479. if ((peSurface != NULL) &&
  9480. !(peSurface->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY))
  9481. {
  9482. peDirectDrawGlobal = peSurface->peDirectDrawGlobal;
  9483. // NOTE: For security, gotta reset when switching desktops
  9484. if (peDirectDrawGlobal->ColorControlCallBacks.dwFlags &
  9485. DDHAL_COLOR_COLORCONTROL)
  9486. {
  9487. ColorControlData.lpDD = peDirectDrawGlobal;
  9488. ColorControlData.lpDDSurface = peSurface;
  9489. ColorControlData.lpColorData = &ColorInfo;
  9490. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  9491. if (peSurface->bLost)
  9492. {
  9493. dwRet = DDHAL_DRIVER_HANDLED;
  9494. ColorControlData.ddRVal = DDERR_SURFACELOST;
  9495. }
  9496. else
  9497. {
  9498. dwRet = peDirectDrawGlobal->
  9499. ColorControlCallBacks.ColorControl(&ColorControlData);
  9500. }
  9501. }
  9502. }
  9503. else
  9504. {
  9505. WARNING("DxColorControl: Invalid surface or dwFlags\n");
  9506. }
  9507. // We have to wrap this in another try-except because the user-mode
  9508. // memory containing the input may have been deallocated by now:
  9509. __try
  9510. {
  9511. ProbeAndWriteRVal(&puColorControlData->ddRVal, ColorControlData.ddRVal);
  9512. ProbeAndWriteStructure(ColorControlData.lpColorData,
  9513. ColorInfo,
  9514. DDCOLORCONTROL);
  9515. }
  9516. __except(EXCEPTION_EXECUTE_HANDLER)
  9517. {
  9518. }
  9519. return(dwRet);
  9520. }
  9521. /*****************************Private*Routine******************************\
  9522. * DWORD DxDdGetDriverInfo
  9523. *
  9524. * History:
  9525. * 16-Feb-1997 -by- J. Andrew Goossen [andrewgo]
  9526. * Wrote it.
  9527. \**************************************************************************/
  9528. DWORD
  9529. APIENTRY
  9530. DxDdGetDriverInfo(
  9531. HANDLE hDirectDraw,
  9532. PDD_GETDRIVERINFODATA puGetDriverInfoData
  9533. )
  9534. {
  9535. DD_GETDRIVERINFODATA GetDriverInfoData;
  9536. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  9537. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  9538. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  9539. GUID* pGuid;
  9540. VOID* pvData;
  9541. ULONG cjData;
  9542. // Needed for Z-Pixels and others which don't cache information
  9543. // in the global.
  9544. // 1K should be enough for about 30 DDPIXELFORMATS,
  9545. // which should be plenty
  9546. DWORD adwBuffer[256];
  9547. __try
  9548. {
  9549. GetDriverInfoData = ProbeAndReadStructure(puGetDriverInfoData,
  9550. DD_GETDRIVERINFODATA);
  9551. // Assume failure:
  9552. puGetDriverInfoData->ddRVal = DDERR_GENERIC;
  9553. }
  9554. __except(EXCEPTION_EXECUTE_HANDLER)
  9555. {
  9556. return(DDHAL_DRIVER_NOTHANDLED);
  9557. }
  9558. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
  9559. if (peDirectDrawLocal != NULL)
  9560. {
  9561. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  9562. pGuid = &GetDriverInfoData.guidInfo;
  9563. pvData = NULL;
  9564. // Note that the actual addresses of the call-backs won't be of
  9565. // much interest to user-mode DirectDraw, but it will still use the
  9566. // dwFlags field of the CALLBACKS structure.
  9567. if (IsEqualIID(pGuid, &GUID_VideoPortCallbacks) &&
  9568. (peDirectDrawGlobal->flDriverInfo & DD_DRIVERINFO_VIDEOPORT))
  9569. {
  9570. pvData = &peDirectDrawGlobal->VideoPortCallBacks;
  9571. cjData = sizeof(peDirectDrawGlobal->VideoPortCallBacks);
  9572. }
  9573. if (IsEqualIID(pGuid, &GUID_VideoPortCaps) &&
  9574. (peDirectDrawGlobal->flDriverInfo & DD_DRIVERINFO_VIDEOPORT))
  9575. {
  9576. pvData = peDirectDrawGlobal->lpDDVideoPortCaps;
  9577. cjData = peDirectDrawGlobal->HalInfo.ddCaps.dwMaxVideoPorts
  9578. * sizeof(DDVIDEOPORTCAPS);
  9579. }
  9580. if (IsEqualIID(pGuid, &GUID_KernelCaps) )
  9581. {
  9582. pvData = &(peDirectDrawGlobal->DDKernelCaps);
  9583. cjData = sizeof(DDKERNELCAPS);
  9584. }
  9585. if (IsEqualIID(pGuid, &GUID_ColorControlCallbacks) &&
  9586. (peDirectDrawGlobal->flDriverInfo & DD_DRIVERINFO_COLORCONTROL))
  9587. {
  9588. pvData = &peDirectDrawGlobal->ColorControlCallBacks;
  9589. cjData = sizeof(peDirectDrawGlobal->ColorControlCallBacks);
  9590. }
  9591. if (IsEqualIID(pGuid, &GUID_MiscellaneousCallbacks) &&
  9592. (peDirectDrawGlobal->flDriverInfo & DD_DRIVERINFO_MISCELLANEOUS))
  9593. {
  9594. pvData = &peDirectDrawGlobal->MiscellaneousCallBacks;
  9595. cjData = sizeof(peDirectDrawGlobal->MiscellaneousCallBacks);
  9596. }
  9597. if (IsEqualIID(pGuid, &GUID_Miscellaneous2Callbacks) &&
  9598. (peDirectDrawGlobal->flDriverInfo & DD_DRIVERINFO_MISCELLANEOUS2))
  9599. {
  9600. pvData = &peDirectDrawGlobal->Miscellaneous2CallBacks;
  9601. cjData = sizeof(peDirectDrawGlobal->Miscellaneous2CallBacks);
  9602. }
  9603. if (IsEqualIID(pGuid, &GUID_NTCallbacks) &&
  9604. (peDirectDrawGlobal->flDriverInfo & DD_DRIVERINFO_NT))
  9605. {
  9606. pvData = &peDirectDrawGlobal->NTCallBacks;
  9607. cjData = sizeof(peDirectDrawGlobal->NTCallBacks);
  9608. }
  9609. if (IsEqualIID(pGuid, &GUID_D3DCallbacks3) &&
  9610. (peDirectDrawGlobal->flDriverInfo & DD_DRIVERINFO_D3DCALLBACKS3))
  9611. {
  9612. pvData = &peDirectDrawGlobal->D3dCallBacks3;
  9613. cjData = sizeof(peDirectDrawGlobal->D3dCallBacks3);
  9614. }
  9615. if (IsEqualIID(pGuid, &GUID_MotionCompCallbacks) &&
  9616. (peDirectDrawGlobal->flDriverInfo & DD_DRIVERINFO_MOTIONCOMP))
  9617. {
  9618. pvData = &peDirectDrawGlobal->MotionCompCallbacks;
  9619. cjData = sizeof(peDirectDrawGlobal->MotionCompCallbacks);
  9620. }
  9621. if (IsEqualIID(pGuid, &GUID_DDMoreCaps) &&
  9622. (peDirectDrawGlobal->flDriverInfo & DD_DRIVERINFO_MORECAPS))
  9623. {
  9624. pvData = &peDirectDrawGlobal->MoreCaps;
  9625. cjData = sizeof(peDirectDrawGlobal->MoreCaps);
  9626. }
  9627. if (IsEqualIID(pGuid, &GUID_DDMoreSurfaceCaps))
  9628. {
  9629. pvData = &peDirectDrawGlobal->MoreSurfaceCaps;
  9630. cjData = sizeof(DD_MORESURFACECAPS)-2*sizeof(DDSCAPSEX);
  9631. }
  9632. //
  9633. // The information for the following GUIDs does not
  9634. // need to be kept around in the kernel so the call
  9635. // is passed directly to the driver.
  9636. //
  9637. if (pvData == NULL)
  9638. {
  9639. cjData = 0;
  9640. if (IsEqualIID(pGuid, &GUID_D3DExtendedCaps))
  9641. {
  9642. cjData = sizeof(D3DNTHAL_D3DEXTENDEDCAPS);
  9643. }
  9644. if (IsEqualIID(pGuid, &GUID_ZPixelFormats))
  9645. {
  9646. cjData = sizeof(adwBuffer);
  9647. }
  9648. if (IsEqualIID(pGuid, &GUID_NonLocalVidMemCaps))
  9649. {
  9650. cjData = sizeof(DD_NONLOCALVIDMEMCAPS);
  9651. }
  9652. if (IsEqualIID(pGuid, &GUID_DDStereoMode))
  9653. {
  9654. cjData = sizeof(DD_STEREOMODE);
  9655. __try
  9656. {
  9657. ProbeForRead(GetDriverInfoData.lpvData, cjData, sizeof(ULONG));
  9658. RtlCopyMemory(adwBuffer, GetDriverInfoData.lpvData, cjData);
  9659. }
  9660. __except(EXCEPTION_EXECUTE_HANDLER)
  9661. {
  9662. return(DDHAL_DRIVER_NOTHANDLED);
  9663. }
  9664. }
  9665. if (cjData > 0)
  9666. {
  9667. ASSERTGDI(sizeof(adwBuffer) >= cjData,
  9668. "adwBuffer too small");
  9669. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  9670. if (bDdGetDriverInfo(peDirectDrawGlobal, pGuid,
  9671. adwBuffer, cjData, &cjData))
  9672. {
  9673. pvData = adwBuffer;
  9674. }
  9675. }
  9676. }
  9677. if (pvData != NULL)
  9678. {
  9679. __try
  9680. {
  9681. ProbeForWrite(GetDriverInfoData.lpvData, cjData, sizeof(ULONG));
  9682. RtlCopyMemory(GetDriverInfoData.lpvData, pvData, cjData);
  9683. ProbeAndWriteUlong(&puGetDriverInfoData->dwActualSize, cjData);
  9684. ProbeAndWriteRVal(&puGetDriverInfoData->ddRVal, DD_OK);
  9685. }
  9686. __except(EXCEPTION_EXECUTE_HANDLER)
  9687. {
  9688. return(DDHAL_DRIVER_NOTHANDLED);
  9689. }
  9690. }
  9691. }
  9692. else
  9693. {
  9694. WARNING("DxDdGetDriverInfo: Invalid object\n");
  9695. }
  9696. return(DDHAL_DRIVER_HANDLED);
  9697. }
  9698. /******************************Public*Routine******************************\
  9699. * DWORD DxDdGetDxHandle
  9700. *
  9701. * 18-Oct-1997 -by- smac
  9702. * Wrote it.
  9703. \**************************************************************************/
  9704. HANDLE
  9705. APIENTRY
  9706. DxDdGetDxHandle(
  9707. HANDLE hDirectDraw,
  9708. HANDLE hSurface,
  9709. BOOL bRelease
  9710. )
  9711. {
  9712. EDD_LOCK_SURFACE eLockSurface;
  9713. EDD_SURFACE* peSurface;
  9714. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  9715. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  9716. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  9717. HANDLE hRet;
  9718. hRet = NULL;
  9719. if( hDirectDraw != NULL )
  9720. {
  9721. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
  9722. if( peDirectDrawLocal != NULL )
  9723. {
  9724. // Use the devlock to synchronize additions and deletions to
  9725. // the attach list:
  9726. EDD_DEVLOCK eDevLock(peDirectDrawLocal->peDirectDrawGlobal);
  9727. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  9728. if( !bRelease )
  9729. {
  9730. if( bDdLoadDxApi( peDirectDrawLocal ) &&
  9731. ( peDirectDrawGlobal->hDirectDraw != NULL ) )
  9732. {
  9733. hRet = hDirectDraw;
  9734. peDirectDrawGlobal->dwDxApiExplicitLoads++;
  9735. }
  9736. }
  9737. else if( ( peDirectDrawGlobal->hDirectDraw != NULL ) && bRelease &&
  9738. ( peDirectDrawGlobal->dwDxApiExplicitLoads > 0 ) )
  9739. {
  9740. vDdUnloadDxApi( peDirectDrawGlobal );
  9741. hRet = hDirectDraw;
  9742. peDirectDrawGlobal->dwDxApiExplicitLoads--;
  9743. }
  9744. }
  9745. }
  9746. else if( hSurface != NULL )
  9747. {
  9748. peSurface = eLockSurface.peLock(hSurface);
  9749. if( peSurface != NULL )
  9750. {
  9751. // Use the devlock to synchronize additions and deletions to
  9752. // the attach list:
  9753. EDD_DEVLOCK eDevLock(peSurface->peDirectDrawGlobal);
  9754. // They must open the DirectDraw handle before opening the
  9755. // surface handle, otherwise we fail.
  9756. if( peSurface->peDirectDrawGlobal->hDirectDraw != NULL )
  9757. {
  9758. if ((peSurface->bLost) ||
  9759. (peSurface->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY))
  9760. {
  9761. WARNING("DxDdGetDxHandle: Video surface is bad/lost/system");
  9762. }
  9763. else if( ( peSurface->hSurface == NULL ) && !bRelease )
  9764. {
  9765. peSurface->hSurface = hDdOpenDxApiSurface( peSurface );
  9766. if( peSurface->hSurface != NULL )
  9767. {
  9768. hRet = hSurface;
  9769. }
  9770. }
  9771. else if( ( peSurface->hSurface != NULL ) && bRelease )
  9772. {
  9773. vDdCloseDxApiSurface( peSurface );
  9774. hRet = hSurface;
  9775. }
  9776. }
  9777. }
  9778. }
  9779. return( hRet );
  9780. }
  9781. /******************************Public*Routine******************************\
  9782. * DWORD DxDdGetMoCompGuids
  9783. *
  9784. * 18-Nov-1997 -by- Scott MacDonald [smac]
  9785. * Wrote it.
  9786. \**************************************************************************/
  9787. DWORD
  9788. APIENTRY
  9789. DxDdGetMoCompGuids(
  9790. HANDLE hDirectDraw,
  9791. PDD_GETMOCOMPGUIDSDATA puGetMoCompGuidsData
  9792. )
  9793. {
  9794. DWORD dwRet;
  9795. DD_GETMOCOMPGUIDSDATA GetMoCompGuidsData;
  9796. LPGUID puGuids;
  9797. ULONG cjGuids;
  9798. HANDLE hSecure;
  9799. __try
  9800. {
  9801. GetMoCompGuidsData
  9802. = ProbeAndReadStructure(puGetMoCompGuidsData,
  9803. DD_GETMOCOMPGUIDSDATA);
  9804. puGuids = GetMoCompGuidsData.lpGuids;
  9805. }
  9806. __except(EXCEPTION_EXECUTE_HANDLER)
  9807. {
  9808. return(DDHAL_DRIVER_NOTHANDLED);
  9809. }
  9810. dwRet = DDHAL_DRIVER_HANDLED;
  9811. GetMoCompGuidsData.ddRVal = DDERR_GENERIC;
  9812. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  9813. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  9814. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  9815. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
  9816. if( peDirectDrawLocal != NULL )
  9817. {
  9818. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  9819. GetMoCompGuidsData.lpDD = peDirectDrawGlobal;
  9820. GetMoCompGuidsData.dwNumGuids = 0;
  9821. GetMoCompGuidsData.lpGuids = NULL;
  9822. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  9823. if ((!peDirectDrawGlobal->bSuspended) &&
  9824. (peDirectDrawGlobal->MotionCompCallbacks.GetMoCompGuids))
  9825. {
  9826. dwRet = peDirectDrawGlobal->MotionCompCallbacks.
  9827. GetMoCompGuids(&GetMoCompGuidsData);
  9828. cjGuids = GetMoCompGuidsData.dwNumGuids
  9829. * sizeof(GUID);
  9830. if ((dwRet == DDHAL_DRIVER_HANDLED) &&
  9831. (GetMoCompGuidsData.ddRVal == DD_OK) &&
  9832. (cjGuids > 0) &&
  9833. (puGuids != NULL))
  9834. {
  9835. hSecure = 0;
  9836. GetMoCompGuidsData.ddRVal = DDERR_GENERIC;
  9837. __try
  9838. {
  9839. ProbeForWrite(puGuids, cjGuids, sizeof(UCHAR));
  9840. hSecure = MmSecureVirtualMemory(puGuids,
  9841. cjGuids,
  9842. PAGE_READWRITE);
  9843. }
  9844. __except(EXCEPTION_EXECUTE_HANDLER)
  9845. {
  9846. }
  9847. if (hSecure)
  9848. {
  9849. GetMoCompGuidsData.lpGuids = puGuids;
  9850. dwRet = peDirectDrawGlobal->MotionCompCallbacks.
  9851. GetMoCompGuids(&GetMoCompGuidsData);
  9852. MmUnsecureVirtualMemory(hSecure);
  9853. }
  9854. else
  9855. {
  9856. WARNING("DxDdGetMoCompGuids: Bad destination buffer\n");
  9857. }
  9858. }
  9859. }
  9860. }
  9861. else
  9862. {
  9863. WARNING("DxDdGetMoCompGuids: Invalid object\n");
  9864. }
  9865. // We have to wrap this in another try-except because the user-mode
  9866. // memory containing the input may have been deallocated by now:
  9867. __try
  9868. {
  9869. ProbeAndWriteRVal(&puGetMoCompGuidsData->ddRVal,
  9870. GetMoCompGuidsData.ddRVal);
  9871. ProbeAndWriteUlong(&puGetMoCompGuidsData->dwNumGuids,
  9872. GetMoCompGuidsData.dwNumGuids);
  9873. }
  9874. __except(EXCEPTION_EXECUTE_HANDLER)
  9875. {
  9876. }
  9877. return(dwRet);
  9878. }
  9879. /******************************Public*Routine******************************\
  9880. * DWORD DxDdGetMoCompFormats
  9881. *
  9882. * 18-Nov-1997 -by- Scott MacDonald [smac]
  9883. * Wrote it.
  9884. \**************************************************************************/
  9885. DWORD
  9886. APIENTRY
  9887. DxDdGetMoCompFormats(
  9888. HANDLE hDirectDraw,
  9889. PDD_GETMOCOMPFORMATSDATA puGetMoCompFormatsData
  9890. )
  9891. {
  9892. DWORD dwRet;
  9893. DD_GETMOCOMPFORMATSDATA GetMoCompFormatsData;
  9894. GUID guid;
  9895. LPDDPIXELFORMAT puFormats;
  9896. ULONG cjFormats;
  9897. HANDLE hSecure;
  9898. __try
  9899. {
  9900. GetMoCompFormatsData
  9901. = ProbeAndReadStructure(puGetMoCompFormatsData,
  9902. DD_GETMOCOMPFORMATSDATA);
  9903. guid = ProbeAndReadStructure(GetMoCompFormatsData.lpGuid,
  9904. GUID);
  9905. GetMoCompFormatsData.lpGuid = &guid;
  9906. puFormats = GetMoCompFormatsData.lpFormats;
  9907. }
  9908. __except(EXCEPTION_EXECUTE_HANDLER)
  9909. {
  9910. return(DDHAL_DRIVER_NOTHANDLED);
  9911. }
  9912. dwRet = DDHAL_DRIVER_HANDLED;
  9913. GetMoCompFormatsData.ddRVal = DDERR_GENERIC;
  9914. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  9915. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  9916. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  9917. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
  9918. if( peDirectDrawLocal != NULL )
  9919. {
  9920. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  9921. GetMoCompFormatsData.lpDD = peDirectDrawGlobal;
  9922. GetMoCompFormatsData.dwNumFormats = 0;
  9923. GetMoCompFormatsData.lpFormats = NULL;
  9924. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  9925. if ((!peDirectDrawGlobal->bSuspended) &&
  9926. (peDirectDrawGlobal->MotionCompCallbacks.GetMoCompFormats))
  9927. {
  9928. dwRet = peDirectDrawGlobal->MotionCompCallbacks.
  9929. GetMoCompFormats(&GetMoCompFormatsData);
  9930. cjFormats = GetMoCompFormatsData.dwNumFormats
  9931. * sizeof(DDPIXELFORMAT);
  9932. if ((dwRet == DDHAL_DRIVER_HANDLED) &&
  9933. (GetMoCompFormatsData.ddRVal == DD_OK) &&
  9934. (cjFormats > 0) &&
  9935. (puFormats != NULL))
  9936. {
  9937. hSecure = 0;
  9938. GetMoCompFormatsData.ddRVal = DDERR_GENERIC;
  9939. __try
  9940. {
  9941. ProbeForWrite(puFormats, cjFormats, sizeof(UCHAR));
  9942. hSecure = MmSecureVirtualMemory(puFormats,
  9943. cjFormats,
  9944. PAGE_READWRITE);
  9945. }
  9946. __except(EXCEPTION_EXECUTE_HANDLER)
  9947. {
  9948. }
  9949. if (hSecure)
  9950. {
  9951. GetMoCompFormatsData.lpFormats = puFormats;
  9952. dwRet = peDirectDrawGlobal->MotionCompCallbacks.
  9953. GetMoCompFormats(&GetMoCompFormatsData);
  9954. MmUnsecureVirtualMemory(hSecure);
  9955. }
  9956. else
  9957. {
  9958. WARNING("DxDdGetMoCompFormats: Bad destination buffer\n");
  9959. }
  9960. }
  9961. }
  9962. }
  9963. else
  9964. {
  9965. WARNING("DxDdGetMoCompFormats: Invalid object\n");
  9966. }
  9967. // We have to wrap this in another try-except because the user-mode
  9968. // memory containing the input may have been deallocated by now:
  9969. __try
  9970. {
  9971. ProbeAndWriteRVal(&puGetMoCompFormatsData->ddRVal,
  9972. GetMoCompFormatsData.ddRVal);
  9973. ProbeAndWriteUlong(&puGetMoCompFormatsData->dwNumFormats,
  9974. GetMoCompFormatsData.dwNumFormats);
  9975. }
  9976. __except(EXCEPTION_EXECUTE_HANDLER)
  9977. {
  9978. }
  9979. return(dwRet);
  9980. }
  9981. /******************************Public*Routine******************************\
  9982. * BOOL bDdDeleteMotionCompObject
  9983. *
  9984. * Deletes a kernel-mode representation of the motion comp object.
  9985. *
  9986. * 19-Nov-1997 -by- Scott MacDonald [smac]
  9987. * Wrote it.
  9988. \**************************************************************************/
  9989. BOOL
  9990. bDdDeleteMotionCompObject(
  9991. HANDLE hMotionComp,
  9992. DWORD* pdwRet // For returning driver return code, may be NULL
  9993. )
  9994. {
  9995. BOOL bRet;
  9996. DWORD dwRet;
  9997. EDD_MOTIONCOMP* peMotionComp;
  9998. EDD_MOTIONCOMP* peTmp;
  9999. VOID* pvRemove;
  10000. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  10001. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  10002. DD_DESTROYMOCOMPDATA DestroyMoCompData;
  10003. DXOBJ* pDxObj;
  10004. DXOBJ* pDxObjNext;
  10005. bRet = FALSE;
  10006. dwRet = DDHAL_DRIVER_HANDLED;
  10007. peMotionComp = (EDD_MOTIONCOMP*) DdHmgLock((HDD_OBJ) hMotionComp, DD_MOTIONCOMP_TYPE, FALSE);
  10008. if (peMotionComp != NULL)
  10009. {
  10010. peDirectDrawGlobal = peMotionComp->peDirectDrawGlobal;
  10011. pvRemove = DdHmgRemoveObject((HDD_OBJ) hMotionComp,
  10012. DdHmgQueryLock((HDD_OBJ) hMotionComp),
  10013. 0,
  10014. TRUE,
  10015. DD_MOTIONCOMP_TYPE);
  10016. // Hold the devlock while we call the driver and while we muck
  10017. // around in the motion comp list:
  10018. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  10019. if (peMotionComp->fl & DD_MOTIONCOMP_FLAG_DRIVER_CREATED)
  10020. {
  10021. // Call the driver if it created the object:
  10022. if (peDirectDrawGlobal->MotionCompCallbacks.DestroyMoComp)
  10023. {
  10024. DestroyMoCompData.lpDD = peDirectDrawGlobal;
  10025. DestroyMoCompData.lpMoComp = peMotionComp;
  10026. DestroyMoCompData.ddRVal = DDERR_GENERIC;
  10027. dwRet = peDirectDrawGlobal->
  10028. MotionCompCallbacks.DestroyMoComp(&DestroyMoCompData);
  10029. }
  10030. }
  10031. // Remove from the motion comp object from linked-list:
  10032. peDirectDrawLocal = peMotionComp->peDirectDrawLocal;
  10033. if (peDirectDrawLocal->peMotionComp_DdList == peMotionComp)
  10034. {
  10035. peDirectDrawLocal->peMotionComp_DdList
  10036. = peMotionComp->peMotionComp_DdNext;
  10037. }
  10038. else
  10039. {
  10040. for (peTmp = peDirectDrawLocal->peMotionComp_DdList;
  10041. ( peTmp != NULL)&&(peTmp->peMotionComp_DdNext != peMotionComp);
  10042. peTmp = peTmp->peMotionComp_DdNext)
  10043. ;
  10044. if( peTmp != NULL )
  10045. {
  10046. peTmp->peMotionComp_DdNext = peMotionComp->peMotionComp_DdNext;
  10047. }
  10048. }
  10049. // We're all done with this object, so free the memory and
  10050. // leave:
  10051. DdFreeObject(peMotionComp, DD_MOTIONCOMP_TYPE);
  10052. bRet = TRUE;
  10053. }
  10054. else
  10055. {
  10056. WARNING1("bDdDeleteMotionComp: Bad handle or object was busy\n");
  10057. }
  10058. if (pdwRet != NULL)
  10059. {
  10060. *pdwRet = dwRet;
  10061. }
  10062. return(bRet);
  10063. }
  10064. /******************************Public*Routine******************************\
  10065. * DWORD DxDdCreateMoComp
  10066. *
  10067. * 18-Nov-1997 -by- Scott MacDonald [smac]
  10068. * Wrote it.
  10069. \**************************************************************************/
  10070. HANDLE
  10071. APIENTRY
  10072. DxDdCreateMoComp(
  10073. HANDLE hDirectDraw,
  10074. PDD_CREATEMOCOMPDATA puCreateMoCompData
  10075. )
  10076. {
  10077. HANDLE hRet;
  10078. DWORD dwRet;
  10079. DD_CREATEMOCOMPDATA CreateMoCompData;
  10080. GUID guid;
  10081. PBYTE puData;
  10082. ULONG cjData;
  10083. HANDLE hSecure;
  10084. __try
  10085. {
  10086. CreateMoCompData =
  10087. ProbeAndReadStructure(puCreateMoCompData,
  10088. DD_CREATEMOCOMPDATA);
  10089. guid = ProbeAndReadStructure(CreateMoCompData.lpGuid,
  10090. GUID);
  10091. CreateMoCompData.lpGuid = &guid;
  10092. puData = (PBYTE) CreateMoCompData.lpData;
  10093. }
  10094. __except(EXCEPTION_EXECUTE_HANDLER)
  10095. {
  10096. return(DDHAL_DRIVER_NOTHANDLED);
  10097. }
  10098. hRet = NULL;
  10099. dwRet = DDHAL_DRIVER_HANDLED;
  10100. CreateMoCompData.ddRVal = DDERR_GENERIC;
  10101. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  10102. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  10103. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  10104. EDD_MOTIONCOMP* peMotionComp;
  10105. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
  10106. if (peDirectDrawLocal != NULL)
  10107. {
  10108. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  10109. // Here we do the minimal validations checks to ensure that bad
  10110. // parameters won't crash NT. We're not more strict than
  10111. // checking for stuff that will crash us, as the user-mode part
  10112. // of DirectDraw handles that.
  10113. peMotionComp = (EDD_MOTIONCOMP*) DdHmgAlloc(sizeof(EDD_MOTIONCOMP),
  10114. DD_MOTIONCOMP_TYPE,
  10115. HMGR_ALLOC_LOCK);
  10116. if (peMotionComp)
  10117. {
  10118. // Private data:
  10119. peMotionComp->peDirectDrawGlobal = peDirectDrawGlobal;
  10120. peMotionComp->peDirectDrawLocal = peDirectDrawLocal;
  10121. cjData = CreateMoCompData.dwDataSize;
  10122. // Public data:
  10123. peMotionComp->lpDD = peDirectDrawGlobal;
  10124. RtlCopyMemory(&(peMotionComp->guid),
  10125. &guid,
  10126. sizeof(GUID));
  10127. peMotionComp->dwUncompWidth = CreateMoCompData.dwUncompWidth;
  10128. peMotionComp->dwUncompHeight = CreateMoCompData.dwUncompHeight;
  10129. RtlCopyMemory(&(peMotionComp->ddUncompPixelFormat),
  10130. &CreateMoCompData.ddUncompPixelFormat,
  10131. sizeof(DDPIXELFORMAT));
  10132. // Hold devlock for driver call
  10133. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  10134. // Add this videoport to the list hanging off the
  10135. // DirectDrawLocal object allocated for this process:
  10136. peMotionComp->peMotionComp_DdNext
  10137. = peDirectDrawLocal->peMotionComp_DdList;
  10138. peDirectDrawLocal->peMotionComp_DdList
  10139. = peMotionComp;
  10140. // Now call the driver to create its version:
  10141. CreateMoCompData.lpDD = peDirectDrawGlobal;
  10142. CreateMoCompData.lpMoComp = peMotionComp;
  10143. CreateMoCompData.ddRVal = DDERR_GENERIC;
  10144. dwRet = DDHAL_DRIVER_NOTHANDLED; // Call is optional
  10145. if ((!peDirectDrawGlobal->bSuspended) &&
  10146. (peDirectDrawGlobal->MotionCompCallbacks.CreateMoComp))
  10147. {
  10148. hSecure = 0;
  10149. if( puData )
  10150. {
  10151. __try
  10152. {
  10153. ProbeForWrite(puData, cjData, sizeof(UCHAR));
  10154. hSecure = MmSecureVirtualMemory(puData,
  10155. cjData,
  10156. PAGE_READWRITE);
  10157. }
  10158. __except(EXCEPTION_EXECUTE_HANDLER)
  10159. {
  10160. }
  10161. }
  10162. if( ( puData == NULL ) || hSecure )
  10163. {
  10164. CreateMoCompData.lpData = puData;
  10165. dwRet = peDirectDrawGlobal->MotionCompCallbacks.
  10166. CreateMoComp(&CreateMoCompData);
  10167. }
  10168. else
  10169. {
  10170. WARNING("DxDdCreateMoComp: Bad data buffer\n");
  10171. dwRet = DDHAL_DRIVER_HANDLED;
  10172. }
  10173. if( hSecure )
  10174. {
  10175. MmUnsecureVirtualMemory(hSecure);
  10176. }
  10177. if ((CreateMoCompData.ddRVal == DD_OK))
  10178. {
  10179. peMotionComp->fl |= DD_MOTIONCOMP_FLAG_DRIVER_CREATED;
  10180. }
  10181. else
  10182. {
  10183. WARNING("DxDdCreateMoComp: Driver failed call\n");
  10184. }
  10185. }
  10186. if ((dwRet == DDHAL_DRIVER_NOTHANDLED) ||
  10187. (CreateMoCompData.ddRVal == DD_OK))
  10188. {
  10189. CreateMoCompData.ddRVal = DD_OK;
  10190. hRet = peMotionComp->hGet();
  10191. DEC_EXCLUSIVE_REF_CNT( peMotionComp );
  10192. }
  10193. else
  10194. {
  10195. bDdDeleteMotionCompObject(peMotionComp->hGet(), NULL);
  10196. CreateMoCompData.ddRVal = DDERR_GENERIC;
  10197. }
  10198. }
  10199. else
  10200. {
  10201. WARNING("DxDdCreateMoComp: Bad parameters\n");
  10202. }
  10203. }
  10204. else
  10205. {
  10206. WARNING("DxDdCreateMoComp: Invalid object\n");
  10207. }
  10208. // We have to wrap this in another try-except because the user-mode
  10209. // memory containing the input may have been deallocated by now:
  10210. __try
  10211. {
  10212. ProbeAndWriteRVal(&puCreateMoCompData->ddRVal, CreateMoCompData.ddRVal);
  10213. }
  10214. __except(EXCEPTION_EXECUTE_HANDLER)
  10215. {
  10216. }
  10217. // Note that the user-mode stub always returns DDHAL_DRIVER_HANDLED
  10218. // to DirectDraw.
  10219. return(hRet);
  10220. }
  10221. /******************************Public*Routine******************************\
  10222. * DWORD DxDdGetMoCompBuffInfo
  10223. *
  10224. * 17-Jun-1998 -by- Scott MacDonald [smac]
  10225. * Wrote it.
  10226. \**************************************************************************/
  10227. DWORD
  10228. APIENTRY
  10229. DxDdGetMoCompBuffInfo(
  10230. HANDLE hDirectDraw,
  10231. PDD_GETMOCOMPCOMPBUFFDATA puGetBuffData
  10232. )
  10233. {
  10234. DWORD dwRet;
  10235. DD_GETMOCOMPCOMPBUFFDATA GetBuffData;
  10236. LPDDCOMPBUFFERINFO puBuffInfo;
  10237. GUID guid;
  10238. ULONG cjNumTypes;
  10239. HANDLE hSecure;
  10240. __try
  10241. {
  10242. GetBuffData =
  10243. ProbeAndReadStructure(puGetBuffData,
  10244. DD_GETMOCOMPCOMPBUFFDATA);
  10245. guid = ProbeAndReadStructure(GetBuffData.lpGuid,
  10246. GUID);
  10247. GetBuffData.lpGuid = &guid;
  10248. puBuffInfo = GetBuffData.lpCompBuffInfo;
  10249. }
  10250. __except(EXCEPTION_EXECUTE_HANDLER)
  10251. {
  10252. return(DDHAL_DRIVER_NOTHANDLED);
  10253. }
  10254. dwRet = DDHAL_DRIVER_HANDLED;
  10255. GetBuffData.ddRVal = DDERR_GENERIC;
  10256. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  10257. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  10258. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  10259. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
  10260. if( peDirectDrawLocal != NULL )
  10261. {
  10262. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  10263. GetBuffData.lpDD = peDirectDrawGlobal;
  10264. GetBuffData.dwNumTypesCompBuffs = 0;
  10265. GetBuffData.lpCompBuffInfo = NULL;
  10266. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  10267. if ((!peDirectDrawGlobal->bSuspended) &&
  10268. (peDirectDrawGlobal->MotionCompCallbacks.GetMoCompBuffInfo))
  10269. {
  10270. dwRet = peDirectDrawGlobal->MotionCompCallbacks.
  10271. GetMoCompBuffInfo(&GetBuffData);
  10272. cjNumTypes = GetBuffData.dwNumTypesCompBuffs *
  10273. sizeof(DDCOMPBUFFERINFO);
  10274. if ((dwRet == DDHAL_DRIVER_HANDLED) &&
  10275. (GetBuffData.ddRVal == DD_OK) &&
  10276. (cjNumTypes > 0) &&
  10277. (puBuffInfo != NULL))
  10278. {
  10279. hSecure = 0;
  10280. GetBuffData.ddRVal = DDERR_GENERIC;
  10281. __try
  10282. {
  10283. ProbeForWrite(puBuffInfo, cjNumTypes, sizeof(UCHAR));
  10284. hSecure = MmSecureVirtualMemory(puBuffInfo,
  10285. cjNumTypes,
  10286. PAGE_READWRITE);
  10287. }
  10288. __except(EXCEPTION_EXECUTE_HANDLER)
  10289. {
  10290. }
  10291. if (hSecure)
  10292. {
  10293. GetBuffData.lpCompBuffInfo = puBuffInfo;
  10294. dwRet = peDirectDrawGlobal->MotionCompCallbacks.
  10295. GetMoCompBuffInfo(&GetBuffData);
  10296. MmUnsecureVirtualMemory(hSecure);
  10297. }
  10298. else
  10299. {
  10300. WARNING("DxDdGetMoCompBuffInfo: Bad destination buffer\n");
  10301. }
  10302. }
  10303. }
  10304. }
  10305. else
  10306. {
  10307. WARNING("DxDdGetMoCompBuffInfo: Invalid object\n");
  10308. }
  10309. // We have to wrap this in another try-except because the user-mode
  10310. // memory containing the input may have been deallocated by now:
  10311. __try
  10312. {
  10313. ProbeAndWriteRVal(&puGetBuffData->ddRVal,
  10314. GetBuffData.ddRVal);
  10315. ProbeAndWriteUlong(&puGetBuffData->dwNumTypesCompBuffs,
  10316. GetBuffData.dwNumTypesCompBuffs);
  10317. }
  10318. __except(EXCEPTION_EXECUTE_HANDLER)
  10319. {
  10320. }
  10321. return(dwRet);
  10322. }
  10323. /******************************Public*Routine******************************\
  10324. * DWORD DxDdGetInternalMoCompInfo
  10325. *
  10326. * 17-Jun-1998 -by- Scott MacDonald [smac]
  10327. * Wrote it.
  10328. \**************************************************************************/
  10329. DWORD
  10330. APIENTRY
  10331. DxDdGetInternalMoCompInfo(
  10332. HANDLE hDirectDraw,
  10333. PDD_GETINTERNALMOCOMPDATA puGetInternalData
  10334. )
  10335. {
  10336. DWORD dwRet;
  10337. DD_GETINTERNALMOCOMPDATA GetInternalData;
  10338. GUID guid;
  10339. __try
  10340. {
  10341. GetInternalData =
  10342. ProbeAndReadStructure(puGetInternalData,
  10343. DD_GETINTERNALMOCOMPDATA);
  10344. guid = ProbeAndReadStructure(GetInternalData.lpGuid,
  10345. GUID);
  10346. GetInternalData.lpGuid = &guid;
  10347. }
  10348. __except(EXCEPTION_EXECUTE_HANDLER)
  10349. {
  10350. return(DDHAL_DRIVER_NOTHANDLED);
  10351. }
  10352. dwRet = DDHAL_DRIVER_HANDLED;
  10353. GetInternalData.ddRVal = DDERR_GENERIC;
  10354. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  10355. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  10356. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  10357. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
  10358. if( peDirectDrawLocal != NULL )
  10359. {
  10360. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  10361. GetInternalData.lpDD = peDirectDrawGlobal;
  10362. GetInternalData.dwScratchMemAlloc = 0;
  10363. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  10364. if ((!peDirectDrawGlobal->bSuspended) &&
  10365. (peDirectDrawGlobal->MotionCompCallbacks.GetInternalMoCompInfo))
  10366. {
  10367. dwRet = peDirectDrawGlobal->MotionCompCallbacks.
  10368. GetInternalMoCompInfo(&GetInternalData);
  10369. }
  10370. }
  10371. else
  10372. {
  10373. WARNING("DxDdGetInternalMoCompInfo: Invalid object\n");
  10374. }
  10375. // We have to wrap this in another try-except because the user-mode
  10376. // memory containing the input may have been deallocated by now:
  10377. __try
  10378. {
  10379. ProbeAndWriteRVal(&puGetInternalData->ddRVal,
  10380. GetInternalData.ddRVal);
  10381. ProbeAndWriteUlong(&puGetInternalData->dwScratchMemAlloc,
  10382. GetInternalData.dwScratchMemAlloc);
  10383. }
  10384. __except(EXCEPTION_EXECUTE_HANDLER)
  10385. {
  10386. }
  10387. return(dwRet);
  10388. }
  10389. /******************************Public*Routine******************************\
  10390. * DWORD DxDdDestroyMoComp
  10391. *
  10392. * 18-Nov-1997 -by- Scott MacDonald [smac]
  10393. * Wrote it.
  10394. \**************************************************************************/
  10395. DWORD
  10396. APIENTRY
  10397. DxDdDestroyMoComp(
  10398. HANDLE hMoComp,
  10399. PDD_DESTROYMOCOMPDATA puDestroyMoCompData
  10400. )
  10401. {
  10402. DWORD dwRet;
  10403. bDdDeleteMotionCompObject(hMoComp, &dwRet);
  10404. __try
  10405. {
  10406. ProbeAndWriteRVal(&puDestroyMoCompData->ddRVal, DD_OK);
  10407. }
  10408. __except(EXCEPTION_EXECUTE_HANDLER)
  10409. {
  10410. }
  10411. return(dwRet);
  10412. }
  10413. /******************************Public*Routine******************************\
  10414. * DWORD DxDdBeginMoCompFrame
  10415. *
  10416. * 18-Nov-1997 -by- Scott MacDonald [smac]
  10417. * Wrote it.
  10418. \**************************************************************************/
  10419. DWORD
  10420. APIENTRY
  10421. DxDdBeginMoCompFrame(
  10422. HANDLE hMoComp,
  10423. PDD_BEGINMOCOMPFRAMEDATA puBeginFrameData
  10424. )
  10425. {
  10426. DWORD dwRet;
  10427. DD_BEGINMOCOMPFRAMEDATA BeginFrameData;
  10428. LPBYTE puInputData;
  10429. ULONG cjInputData;
  10430. LPBYTE puOutputData;
  10431. ULONG cjOutputData;
  10432. ULONG cjRefData;
  10433. HANDLE hInputSecure;
  10434. HANDLE hOutputSecure;
  10435. DWORD dwNumRefSurfaces;
  10436. DWORD i;
  10437. DWORD j;
  10438. __try
  10439. {
  10440. BeginFrameData
  10441. = ProbeAndReadStructure(puBeginFrameData,
  10442. DD_BEGINMOCOMPFRAMEDATA);
  10443. puInputData = (PBYTE) BeginFrameData.lpInputData;
  10444. puOutputData = (PBYTE) BeginFrameData.lpOutputData;
  10445. }
  10446. __except(EXCEPTION_EXECUTE_HANDLER)
  10447. {
  10448. return(DDHAL_DRIVER_NOTHANDLED);
  10449. }
  10450. dwRet = DDHAL_DRIVER_HANDLED;
  10451. BeginFrameData.ddRVal = DDERR_GENERIC;
  10452. EDD_MOTIONCOMP* peMotionComp;
  10453. EDD_LOCK_MOTIONCOMP eLockMotionComp;
  10454. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  10455. EDD_SURFACE* peSurfaceDest;
  10456. EDD_LOCK_SURFACE eLockSurfaceDest;
  10457. peSurfaceDest = eLockSurfaceDest.peLock(BeginFrameData.lpDestSurface);
  10458. peMotionComp = eLockMotionComp.peLock(hMoComp);
  10459. if ((peMotionComp != NULL) && (peSurfaceDest != NULL))
  10460. {
  10461. peDirectDrawGlobal = peMotionComp->peDirectDrawGlobal;
  10462. cjInputData = BeginFrameData.dwInputDataSize;
  10463. cjOutputData = BeginFrameData.dwOutputDataSize;
  10464. BeginFrameData.lpDD = peDirectDrawGlobal;
  10465. BeginFrameData.lpMoComp = peMotionComp;
  10466. BeginFrameData.lpDestSurface = peSurfaceDest;
  10467. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  10468. if ((!peDirectDrawGlobal->bSuspended) &&
  10469. (peDirectDrawGlobal->MotionCompCallbacks.BeginMoCompFrame))
  10470. {
  10471. // Secure the input buffer
  10472. hInputSecure = 0;
  10473. if( puInputData )
  10474. {
  10475. __try
  10476. {
  10477. ProbeForWrite(puInputData, cjInputData, sizeof(UCHAR));
  10478. hInputSecure = MmSecureVirtualMemory(puInputData,
  10479. cjInputData,
  10480. PAGE_READWRITE);
  10481. }
  10482. __except(EXCEPTION_EXECUTE_HANDLER)
  10483. {
  10484. }
  10485. }
  10486. // Secure the output buffer
  10487. hOutputSecure = 0;
  10488. if( puOutputData )
  10489. {
  10490. __try
  10491. {
  10492. ProbeForWrite(puOutputData, cjOutputData, sizeof(UCHAR));
  10493. hOutputSecure = MmSecureVirtualMemory(puOutputData,
  10494. cjOutputData,
  10495. PAGE_READWRITE);
  10496. }
  10497. __except(EXCEPTION_EXECUTE_HANDLER)
  10498. {
  10499. }
  10500. }
  10501. if( ( ( puInputData == NULL ) || hInputSecure ) &&
  10502. ( ( puOutputData == NULL ) || hOutputSecure ) )
  10503. {
  10504. BeginFrameData.lpInputData = puInputData;
  10505. BeginFrameData.lpOutputData = puOutputData;
  10506. dwRet = peDirectDrawGlobal->MotionCompCallbacks.
  10507. BeginMoCompFrame(&BeginFrameData);
  10508. if ((BeginFrameData.ddRVal != DD_OK) &&
  10509. (dwRet == DDHAL_DRIVER_NOTHANDLED))
  10510. {
  10511. WARNING("DxDdBeginMoCompFrame: Driver failed callad\n");
  10512. }
  10513. }
  10514. else
  10515. {
  10516. WARNING("DxDdBeginMoCompFrame: Bad intput or output buffer\n");
  10517. dwRet = DDHAL_DRIVER_HANDLED;
  10518. }
  10519. if( hInputSecure )
  10520. {
  10521. MmUnsecureVirtualMemory(hInputSecure);
  10522. }
  10523. if( hOutputSecure )
  10524. {
  10525. MmUnsecureVirtualMemory(hOutputSecure);
  10526. }
  10527. }
  10528. }
  10529. else
  10530. {
  10531. WARNING("DxDdBeginMoCompFrame: Invalid object\n");
  10532. }
  10533. // We have to wrap this in another try-except because the user-mode
  10534. // memory containing the input may have been deallocated by now:
  10535. __try
  10536. {
  10537. ProbeAndWriteRVal(&puBeginFrameData->ddRVal,
  10538. BeginFrameData.ddRVal);
  10539. ProbeAndWriteUlong(&puBeginFrameData->dwOutputDataSize,
  10540. BeginFrameData.dwOutputDataSize);
  10541. }
  10542. __except(EXCEPTION_EXECUTE_HANDLER)
  10543. {
  10544. }
  10545. return(dwRet);
  10546. }
  10547. /******************************Public*Routine******************************\
  10548. * DWORD DxDdEndMoCompFrame
  10549. *
  10550. * 18-Nov-1997 -by- Scott MacDonald [smac]
  10551. * Wrote it.
  10552. \**************************************************************************/
  10553. DWORD
  10554. APIENTRY
  10555. DxDdEndMoCompFrame(
  10556. HANDLE hMoComp,
  10557. PDD_ENDMOCOMPFRAMEDATA puEndFrameData
  10558. )
  10559. {
  10560. DWORD dwRet;
  10561. DD_ENDMOCOMPFRAMEDATA EndFrameData;
  10562. LPBYTE puData;
  10563. ULONG cjData;
  10564. HANDLE hSecure;
  10565. __try
  10566. {
  10567. EndFrameData
  10568. = ProbeAndReadStructure(puEndFrameData,
  10569. DD_ENDMOCOMPFRAMEDATA);
  10570. puData = (PBYTE) EndFrameData.lpInputData;
  10571. }
  10572. __except(EXCEPTION_EXECUTE_HANDLER)
  10573. {
  10574. return(DDHAL_DRIVER_NOTHANDLED);
  10575. }
  10576. dwRet = DDHAL_DRIVER_HANDLED;
  10577. EndFrameData.ddRVal = DDERR_GENERIC;
  10578. EDD_MOTIONCOMP* peMotionComp;
  10579. EDD_LOCK_MOTIONCOMP eLockMotionComp;
  10580. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  10581. peMotionComp = eLockMotionComp.peLock(hMoComp);
  10582. if (peMotionComp != NULL)
  10583. {
  10584. peDirectDrawGlobal = peMotionComp->peDirectDrawGlobal;
  10585. cjData = EndFrameData.dwInputDataSize;
  10586. EndFrameData.lpDD = peDirectDrawGlobal;
  10587. EndFrameData.lpMoComp = peMotionComp;
  10588. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  10589. if ((!peDirectDrawGlobal->bSuspended) &&
  10590. (peDirectDrawGlobal->MotionCompCallbacks.EndMoCompFrame))
  10591. {
  10592. hSecure = 0;
  10593. if( puData )
  10594. {
  10595. __try
  10596. {
  10597. ProbeForWrite(puData, cjData, sizeof(UCHAR));
  10598. hSecure = MmSecureVirtualMemory(puData,
  10599. cjData,
  10600. PAGE_READWRITE);
  10601. }
  10602. __except(EXCEPTION_EXECUTE_HANDLER)
  10603. {
  10604. }
  10605. }
  10606. if( ( puData == NULL ) || hSecure )
  10607. {
  10608. EndFrameData.lpInputData = puData;
  10609. dwRet = peDirectDrawGlobal->MotionCompCallbacks.
  10610. EndMoCompFrame(&EndFrameData);
  10611. if ((dwRet == DDHAL_DRIVER_HANDLED) &&
  10612. (EndFrameData.ddRVal != DD_OK))
  10613. {
  10614. WARNING("DxDdEndMoCompFrame: Driver failed call\n");
  10615. }
  10616. }
  10617. else
  10618. {
  10619. WARNING("DxDdEndMoCompFrame: Bad data buffer\n");
  10620. }
  10621. if( hSecure )
  10622. {
  10623. MmUnsecureVirtualMemory(hSecure);
  10624. }
  10625. }
  10626. }
  10627. else
  10628. {
  10629. WARNING("DxDdEndMoCompFrame: Invalid object\n");
  10630. }
  10631. // We have to wrap this in another try-except because the user-mode
  10632. // memory containing the input may have been deallocated by now:
  10633. __try
  10634. {
  10635. ProbeAndWriteRVal(&puEndFrameData->ddRVal,
  10636. EndFrameData.ddRVal);
  10637. }
  10638. __except(EXCEPTION_EXECUTE_HANDLER)
  10639. {
  10640. }
  10641. return(dwRet);
  10642. }
  10643. /******************************Public*Routine******************************\
  10644. * DWORD DxDdRenderMoComp
  10645. *
  10646. * 18-Nov-1997 -by- Scott MacDonald [smac]
  10647. * Wrote it.
  10648. \**************************************************************************/
  10649. DWORD
  10650. APIENTRY
  10651. DxDdRenderMoComp(
  10652. HANDLE hMoComp,
  10653. PDD_RENDERMOCOMPDATA puRenderMoCompData
  10654. )
  10655. {
  10656. DWORD dwRet;
  10657. DD_RENDERMOCOMPDATA RenderMoCompData;
  10658. LPDDMOCOMPBUFFERINFO pMacroBlocks;
  10659. DWORD dwNumMacroBlocks;
  10660. LPBYTE puData;
  10661. ULONG cjData;
  10662. HANDLE hSecure;
  10663. LPBYTE puInputData;
  10664. ULONG cjInputData;
  10665. LPBYTE puOutputData;
  10666. ULONG cjOutputData;
  10667. DWORD i;
  10668. DWORD j;
  10669. __try
  10670. {
  10671. RenderMoCompData
  10672. = ProbeAndReadStructure(puRenderMoCompData,
  10673. DD_RENDERMOCOMPDATA);
  10674. pMacroBlocks = RenderMoCompData.lpBufferInfo;
  10675. dwNumMacroBlocks = RenderMoCompData.dwNumBuffers;
  10676. puInputData = (PBYTE) RenderMoCompData.lpInputData;
  10677. puOutputData = (PBYTE) RenderMoCompData.lpOutputData;
  10678. }
  10679. __except(EXCEPTION_EXECUTE_HANDLER)
  10680. {
  10681. return(DDHAL_DRIVER_NOTHANDLED);
  10682. }
  10683. dwRet = DDHAL_DRIVER_HANDLED;
  10684. RenderMoCompData.ddRVal = DDERR_GENERIC;
  10685. EDD_MOTIONCOMP* peMotionComp;
  10686. EDD_LOCK_MOTIONCOMP eLockMotionComp;
  10687. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  10688. peMotionComp = eLockMotionComp.peLock(hMoComp);
  10689. if (peMotionComp != NULL)
  10690. {
  10691. peDirectDrawGlobal = peMotionComp->peDirectDrawGlobal;
  10692. RenderMoCompData.lpDD = peDirectDrawGlobal;
  10693. RenderMoCompData.lpMoComp = peMotionComp;
  10694. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  10695. if ((!peDirectDrawGlobal->bSuspended) &&
  10696. (peDirectDrawGlobal->MotionCompCallbacks.RenderMoComp))
  10697. {
  10698. if (!BALLOC_OVERFLOW1(dwNumMacroBlocks, DDMOCOMPBUFFERINFO))
  10699. {
  10700. cjData = dwNumMacroBlocks * sizeof(DDMOCOMPBUFFERINFO);
  10701. hSecure = 0;
  10702. if (pMacroBlocks)
  10703. {
  10704. __try
  10705. {
  10706. ProbeForWrite(pMacroBlocks, cjData, sizeof(UCHAR));
  10707. hSecure = MmSecureVirtualMemory(pMacroBlocks,
  10708. cjData,
  10709. PAGE_READWRITE);
  10710. }
  10711. __except(EXCEPTION_EXECUTE_HANDLER)
  10712. {
  10713. }
  10714. for (i = 0; i < dwNumMacroBlocks; i++)
  10715. {
  10716. // HmgLock return EDD_SURFACE, but we need a pointer to
  10717. // a DD_SURFACE_LOCAL, so we need to adjust by the size of
  10718. // an OBJECT. This means when releasing the lock, we need to
  10719. // reverse this adjustment.
  10720. pMacroBlocks[i].lpCompSurface = (PDD_SURFACE_LOCAL)
  10721. ((LPBYTE)(DdHmgLock((HDD_OBJ)(pMacroBlocks[i].lpCompSurface), DD_SURFACE_TYPE, FALSE))
  10722. + sizeof(DD_OBJECT));
  10723. if (pMacroBlocks[i].lpCompSurface == NULL)
  10724. {
  10725. for (j = 0; j < i; j++)
  10726. {
  10727. DEC_EXCLUSIVE_REF_CNT(((LPBYTE)(pMacroBlocks[i].lpCompSurface) - sizeof(DD_OBJECT)));
  10728. }
  10729. MmUnsecureVirtualMemory(hSecure);
  10730. hSecure = 0;
  10731. break;
  10732. }
  10733. }
  10734. }
  10735. if( (( pMacroBlocks == NULL ) && (dwNumMacroBlocks == 0)) ||
  10736. hSecure )
  10737. {
  10738. HANDLE hInputSecure = 0;
  10739. HANDLE hOutputSecure = 0;
  10740. // Secure the input buffer
  10741. cjInputData = RenderMoCompData.dwInputDataSize;
  10742. cjOutputData = RenderMoCompData.dwOutputDataSize;
  10743. if( puInputData )
  10744. {
  10745. __try
  10746. {
  10747. ProbeForWrite(puInputData, cjInputData, sizeof(UCHAR));
  10748. hInputSecure = MmSecureVirtualMemory(puInputData,
  10749. cjInputData,
  10750. PAGE_READWRITE);
  10751. }
  10752. __except(EXCEPTION_EXECUTE_HANDLER)
  10753. {
  10754. }
  10755. }
  10756. // Secure the output buffer
  10757. if( puOutputData )
  10758. {
  10759. __try
  10760. {
  10761. ProbeForWrite(puOutputData, cjOutputData, sizeof(UCHAR));
  10762. hOutputSecure = MmSecureVirtualMemory(puOutputData,
  10763. cjOutputData,
  10764. PAGE_READWRITE);
  10765. }
  10766. __except(EXCEPTION_EXECUTE_HANDLER)
  10767. {
  10768. }
  10769. }
  10770. if( ( ( puInputData == NULL ) || hInputSecure ) &&
  10771. ( ( puOutputData == NULL ) || hOutputSecure ) )
  10772. {
  10773. RenderMoCompData.lpInputData = puInputData;
  10774. RenderMoCompData.lpOutputData = puOutputData;
  10775. RenderMoCompData.lpBufferInfo = pMacroBlocks;
  10776. dwRet = peDirectDrawGlobal->MotionCompCallbacks.
  10777. RenderMoComp(&RenderMoCompData);
  10778. if (RenderMoCompData.ddRVal != DD_OK)
  10779. {
  10780. WARNING("DxDdEnderMoComp: Driver failed call\n");
  10781. }
  10782. }
  10783. if( hInputSecure )
  10784. {
  10785. MmUnsecureVirtualMemory(hInputSecure);
  10786. }
  10787. if( hOutputSecure )
  10788. {
  10789. MmUnsecureVirtualMemory(hOutputSecure);
  10790. }
  10791. }
  10792. if( hSecure )
  10793. {
  10794. for (i = 0; i < dwNumMacroBlocks; i++)
  10795. {
  10796. DEC_EXCLUSIVE_REF_CNT(((LPBYTE)(pMacroBlocks[i].lpCompSurface) - sizeof(DD_OBJECT)));
  10797. }
  10798. MmUnsecureVirtualMemory(hSecure);
  10799. }
  10800. }
  10801. }
  10802. }
  10803. else
  10804. {
  10805. WARNING("DxDdRenderMoComp: Invalid object\n");
  10806. }
  10807. // We have to wrap this in another try-except because the user-mode
  10808. // memory containing the input may have been deallocated by now:
  10809. __try
  10810. {
  10811. ProbeAndWriteRVal(&puRenderMoCompData->ddRVal,
  10812. RenderMoCompData.ddRVal);
  10813. ProbeAndWriteUlong(&puRenderMoCompData->dwOutputDataSize,
  10814. RenderMoCompData.dwOutputDataSize);
  10815. }
  10816. __except(EXCEPTION_EXECUTE_HANDLER)
  10817. {
  10818. }
  10819. return(dwRet);
  10820. }
  10821. /******************************Public*Routine******************************\
  10822. * DWORD DxDdQueryMoCompStatus
  10823. *
  10824. * 18-Nov-1997 -by- Scott MacDonald [smac]
  10825. * Wrote it.
  10826. \**************************************************************************/
  10827. DWORD
  10828. APIENTRY
  10829. DxDdQueryMoCompStatus(
  10830. HANDLE hMoComp,
  10831. PDD_QUERYMOCOMPSTATUSDATA puQueryMoCompStatusData
  10832. )
  10833. {
  10834. DWORD dwRet;
  10835. DD_QUERYMOCOMPSTATUSDATA QueryMoCompData;
  10836. __try
  10837. {
  10838. QueryMoCompData
  10839. = ProbeAndReadStructure(puQueryMoCompStatusData,
  10840. DD_QUERYMOCOMPSTATUSDATA);
  10841. }
  10842. __except(EXCEPTION_EXECUTE_HANDLER)
  10843. {
  10844. return(DDHAL_DRIVER_NOTHANDLED);
  10845. }
  10846. dwRet = DDHAL_DRIVER_HANDLED;
  10847. QueryMoCompData.ddRVal = DDERR_GENERIC;
  10848. EDD_MOTIONCOMP* peMotionComp;
  10849. EDD_LOCK_MOTIONCOMP eLockMotionComp;
  10850. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  10851. EDD_SURFACE* peSurface;
  10852. EDD_LOCK_SURFACE eLockSurface;
  10853. peMotionComp = eLockMotionComp.peLock(hMoComp);
  10854. peSurface = eLockSurface.peLock(QueryMoCompData.lpSurface);
  10855. if ((peMotionComp != NULL) && (peSurface != NULL))
  10856. {
  10857. peDirectDrawGlobal = peMotionComp->peDirectDrawGlobal;
  10858. QueryMoCompData.lpDD = peDirectDrawGlobal;
  10859. QueryMoCompData.lpMoComp = peMotionComp;
  10860. QueryMoCompData.lpSurface = peSurface;
  10861. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  10862. if ((!peDirectDrawGlobal->bSuspended) &&
  10863. (peDirectDrawGlobal->MotionCompCallbacks.QueryMoCompStatus))
  10864. {
  10865. dwRet = peDirectDrawGlobal->MotionCompCallbacks.
  10866. QueryMoCompStatus(&QueryMoCompData);
  10867. if (QueryMoCompData.ddRVal != DD_OK)
  10868. {
  10869. WARNING("DxDdQueryMoCompStatus: Driver failed call\n");
  10870. }
  10871. }
  10872. }
  10873. else
  10874. {
  10875. WARNING("DxDdQueryMoCompStatus: Invalid object\n");
  10876. }
  10877. // We have to wrap this in another try-except because the user-mode
  10878. // memory containing the input may have been deallocated by now:
  10879. __try
  10880. {
  10881. ProbeAndWriteRVal(&puQueryMoCompStatusData->ddRVal,
  10882. QueryMoCompData.ddRVal);
  10883. }
  10884. __except(EXCEPTION_EXECUTE_HANDLER)
  10885. {
  10886. }
  10887. return(dwRet);
  10888. }
  10889. /******************************Public*Routine******************************\
  10890. * DWORD DxDdAlphaBlt
  10891. *
  10892. * 24-Nov-1997 -by- Scott MacDonald [smac]
  10893. * Wrote it.
  10894. \**************************************************************************/
  10895. DWORD
  10896. APIENTRY
  10897. DxDdAlphaBlt(
  10898. HANDLE hSurfaceDest,
  10899. HANDLE hSurfaceSrc,
  10900. PDD_BLTDATA puBltData
  10901. )
  10902. {
  10903. DWORD dwRet;
  10904. DD_BLTDATA BltData;
  10905. __try
  10906. {
  10907. BltData
  10908. = ProbeAndReadStructure(puBltData,
  10909. DD_BLTDATA);
  10910. }
  10911. __except(EXCEPTION_EXECUTE_HANDLER)
  10912. {
  10913. return(DDHAL_DRIVER_NOTHANDLED);
  10914. }
  10915. dwRet = DDHAL_DRIVER_NOTHANDLED;
  10916. BltData.ddRVal = DDERR_GENERIC;
  10917. EDD_SURFACE* peSurfaceDest;
  10918. EDD_SURFACE* peSurfaceSrc;
  10919. EDD_LOCK_SURFACE eLockSurfaceDest;
  10920. EDD_LOCK_SURFACE eLockSurfaceSrc;
  10921. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  10922. peSurfaceDest = eLockSurfaceDest.peLock(hSurfaceDest);
  10923. BltData.lpDDDestSurface = peSurfaceDest;
  10924. if (peSurfaceDest != NULL)
  10925. {
  10926. peDirectDrawGlobal = peSurfaceDest->peDirectDrawGlobal;
  10927. if( peDirectDrawGlobal->flDriverInfo & DD_DRIVERINFO_MORECAPS )
  10928. {
  10929. // We support only a specific set of Blt calls down to the driver
  10930. // that we're willing to support and to test.
  10931. if (hSurfaceSrc == NULL)
  10932. {
  10933. // Do simpler stuff 'cause we don't need to lock a source:
  10934. BltData.lpDDSrcSurface = NULL;
  10935. peSurfaceSrc = NULL;
  10936. if ((peSurfaceDest->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  10937. (peDirectDrawGlobal->MoreCaps.dwVSBAlphaCaps == 0) &&
  10938. (peDirectDrawGlobal->MoreCaps.dwSSBAlphaCaps == 0))
  10939. {
  10940. WARNING("DxDdAlphaBlt: Can't blt to system memory surface");
  10941. return(dwRet);
  10942. }
  10943. }
  10944. else
  10945. {
  10946. // Lock the source surface:
  10947. peSurfaceSrc = eLockSurfaceSrc.peLock(hSurfaceSrc);
  10948. BltData.lpDDSrcSurface = peSurfaceSrc;
  10949. // Ensure that both surfaces belong to the same DirectDraw
  10950. // object, and check source rectangle:
  10951. if ((peSurfaceSrc == NULL) ||
  10952. (peSurfaceSrc->peDirectDrawLocal !=
  10953. peSurfaceDest->peDirectDrawLocal) ||
  10954. (BltData.rSrc.left < 0) ||
  10955. (BltData.rSrc.top < 0) ||
  10956. (BltData.rSrc.right > (LONG) peSurfaceSrc->wWidth) ||
  10957. (BltData.rSrc.bottom > (LONG) peSurfaceSrc->wHeight) ||
  10958. (BltData.rSrc.left >= BltData.rSrc.right) ||
  10959. (BltData.rSrc.top >= BltData.rSrc.bottom))
  10960. {
  10961. WARNING("DxDdAlphaBlt: Invalid source surface or source rectangle\n");
  10962. return(dwRet);
  10963. }
  10964. if (peSurfaceDest->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  10965. {
  10966. if (peSurfaceSrc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  10967. {
  10968. if (peDirectDrawGlobal->MoreCaps.dwSSBAlphaCaps == 0)
  10969. {
  10970. WARNING("DxDdAlphaBlt: System to System Blts not supported\n");
  10971. return(dwRet);
  10972. }
  10973. }
  10974. else if (peDirectDrawGlobal->MoreCaps.dwVSBAlphaCaps == 0)
  10975. {
  10976. WARNING("DxDdAlphaBlt: Video to System Blts not supported\n");
  10977. return(dwRet);
  10978. }
  10979. }
  10980. else
  10981. {
  10982. if (peSurfaceSrc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  10983. {
  10984. if (peDirectDrawGlobal->MoreCaps.dwSVBAlphaCaps == 0)
  10985. {
  10986. WARNING("DxDdAlphaBlt: System to Video Blts not supported\n");
  10987. return(dwRet);
  10988. }
  10989. }
  10990. else if (peDirectDrawGlobal->MoreCaps.dwAlphaCaps == 0)
  10991. {
  10992. WARNING("DxDdAlphaBlt: Video to Video Blts not supported\n");
  10993. return(dwRet);
  10994. }
  10995. }
  10996. }
  10997. // Make sure that we weren't given rectangle coordinates
  10998. // which might cause the driver to crash. Note that we
  10999. // don't allow inverting stretch blts:
  11000. if ((BltData.rDest.left >= 0) &&
  11001. (BltData.rDest.top >= 0) &&
  11002. (BltData.rDest.right <= (LONG) peSurfaceDest->wWidth) &&
  11003. (BltData.rDest.bottom <= (LONG) peSurfaceDest->wHeight) &&
  11004. (BltData.rDest.left < BltData.rDest.right) &&
  11005. (BltData.rDest.top < BltData.rDest.bottom))
  11006. {
  11007. BltData.lpDD = peDirectDrawGlobal;
  11008. // Make sure that the surfaces aren't associated
  11009. // with a PDEV whose mode has gone away.
  11010. //
  11011. // Also ensure that there are no outstanding
  11012. // surface locks if running on a brain-dead video
  11013. // card that crashes if the accelerator runs at
  11014. // the same time the frame buffer is accessed.
  11015. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  11016. // We will return SURFACELOST when ...
  11017. //
  11018. // 1) This device is suspended.
  11019. // 2) The driver managed surface is managed by other device.
  11020. // 3) One of surface is losted.
  11021. // 4) The visible region has been changed when surface is primary.
  11022. if (peDirectDrawGlobal->bSuspended) // 1)
  11023. {
  11024. dwRet = DDHAL_DRIVER_HANDLED;
  11025. BltData.ddRVal = DDERR_SURFACELOST;
  11026. }
  11027. else if ((peSurfaceDest->fl & DD_SURFACE_FLAG_WRONG_DRIVER) ||
  11028. ((peSurfaceSrc != NULL) &&
  11029. (peSurfaceSrc->fl & DD_SURFACE_FLAG_WRONG_DRIVER))) // 2)
  11030. {
  11031. dwRet = DDHAL_DRIVER_HANDLED;
  11032. BltData.ddRVal = DDERR_SURFACELOST;
  11033. }
  11034. else if ((peSurfaceDest->bLost) ||
  11035. ((peSurfaceSrc != NULL) && (peSurfaceSrc->bLost))) // 3)
  11036. {
  11037. dwRet = DDHAL_DRIVER_HANDLED;
  11038. BltData.ddRVal = DDERR_SURFACELOST;
  11039. }
  11040. else if ((peSurfaceDest->fl & DD_SURFACE_FLAG_PRIMARY) &&
  11041. (peSurfaceDest->iVisRgnUniqueness != VISRGN_UNIQUENESS())) // 4)
  11042. {
  11043. // The VisRgn changed since the application last queried it;
  11044. // fail the call with a unique error code so that they know
  11045. // to requery the VisRgn and try again:
  11046. dwRet = DDHAL_DRIVER_HANDLED;
  11047. BltData.ddRVal = DDERR_VISRGNCHANGED;
  11048. }
  11049. else
  11050. {
  11051. if (peDirectDrawGlobal->Miscellaneous2CallBacks.AlphaBlt)
  11052. {
  11053. DEVEXCLUDERECT dxo;
  11054. HANDLE hSecure;
  11055. ULONG cjData;
  11056. DWORD i;
  11057. LPRECT lpRect;
  11058. // Secure the clip list and ensure that all of its
  11059. // rectangles are valid
  11060. hSecure = 0;
  11061. if( BltData.dwRectCnt == 0 )
  11062. {
  11063. BltData.prDestRects = NULL;
  11064. }
  11065. else if ( BltData.prDestRects == NULL )
  11066. {
  11067. BltData.dwRectCnt = 0;
  11068. }
  11069. else
  11070. {
  11071. __try
  11072. {
  11073. cjData = BltData.dwRectCnt * sizeof( RECT );
  11074. if (!BALLOC_OVERFLOW1(BltData.dwRectCnt, RECT))
  11075. {
  11076. ProbeForWrite(BltData.prDestRects, cjData, sizeof(UCHAR));
  11077. hSecure = MmSecureVirtualMemory(BltData.prDestRects,
  11078. cjData,
  11079. PAGE_READWRITE);
  11080. }
  11081. }
  11082. __except(EXCEPTION_EXECUTE_HANDLER)
  11083. {
  11084. }
  11085. if( hSecure == NULL )
  11086. {
  11087. BltData.ddRVal = DDERR_OUTOFMEMORY;
  11088. dwRet = DDHAL_DRIVER_HANDLED;
  11089. }
  11090. else
  11091. {
  11092. // Validate each rectangle
  11093. lpRect = BltData.prDestRects;
  11094. for( i = 0; i < BltData.dwRectCnt; i++ )
  11095. {
  11096. if ((lpRect->left < 0) ||
  11097. (lpRect->top < 0) ||
  11098. (lpRect->left > lpRect->right ) ||
  11099. (lpRect->top > lpRect->bottom ) )
  11100. {
  11101. MmUnsecureVirtualMemory(hSecure);
  11102. WARNING("DxDdAlphaBlt: Couldn't lock destination surface\n");
  11103. dwRet = DDHAL_DRIVER_HANDLED;
  11104. BltData.ddRVal = DDERR_INVALIDPARAMS;
  11105. break;
  11106. }
  11107. lpRect++;
  11108. }
  11109. }
  11110. }
  11111. // Only do the Blt it everything has worked up until now
  11112. if( dwRet == DDHAL_DRIVER_NOTHANDLED )
  11113. {
  11114. // Exclude the mouse pointer if necessary:
  11115. if (peSurfaceDest->fl & DD_SURFACE_FLAG_PRIMARY)
  11116. {
  11117. dxo.vExclude(peDirectDrawGlobal->hdev,
  11118. &BltData.rDest);
  11119. }
  11120. dwRet = peDirectDrawGlobal->Miscellaneous2CallBacks.
  11121. AlphaBlt(&BltData);
  11122. if( hSecure )
  11123. {
  11124. MmUnsecureVirtualMemory(hSecure);
  11125. }
  11126. }
  11127. }
  11128. }
  11129. }
  11130. else
  11131. {
  11132. WARNING("DxDdAlphaBlt: Invalid destination rectangle\n");
  11133. }
  11134. }
  11135. else
  11136. {
  11137. WARNING("DxDdAlphaBlt: Alpha not supported\n");
  11138. }
  11139. }
  11140. else
  11141. {
  11142. WARNING("DxDdAlphaBlt: Couldn't lock destination surface\n");
  11143. }
  11144. // We have to wrap this in another try-except because the user-mode
  11145. // memory containing the input may have been deallocated by now:
  11146. __try
  11147. {
  11148. ProbeAndWriteRVal(&puBltData->ddRVal, BltData.ddRVal);
  11149. }
  11150. __except(EXCEPTION_EXECUTE_HANDLER)
  11151. {
  11152. }
  11153. return(dwRet);
  11154. }
  11155. /******************************Public*Routine******************************\
  11156. * DxDdSetGammaRamp
  11157. *
  11158. * The reason we need this function when GDI already has one is that
  11159. * DirectDraw games need the ability to set bizarre gamma ramps to
  11160. * achieve special effects. The GDI SetDeviceGammaRamp call does a range
  11161. * check that will reject all of these gamma ramps. When this function is
  11162. * used, DirectDraw gaurentees that the original gamma ramp gets restored
  11163. * when the game gets minimized or exits.
  11164. *
  11165. * History:
  11166. *
  11167. * Wrote it:
  11168. * 06-Jun-1998 -by- Scott MacDonald [smac]
  11169. \**************************************************************************/
  11170. #define MAX_COLORTABLE 256
  11171. BOOL
  11172. DxDdSetGammaRamp(
  11173. HANDLE hDirectDraw,
  11174. HDC hdc,
  11175. LPVOID lpGammaRamp
  11176. )
  11177. {
  11178. WORD * pTemp1;
  11179. WORD * pTemp2;
  11180. int i;
  11181. BOOL bRet = FALSE;
  11182. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  11183. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  11184. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  11185. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
  11186. if (peDirectDrawLocal != NULL)
  11187. {
  11188. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  11189. if (lpGammaRamp)
  11190. {
  11191. HANDLE hSecure = NULL;
  11192. BOOL bError = FALSE;
  11193. __try
  11194. {
  11195. ProbeForRead(lpGammaRamp, MAX_COLORTABLE * sizeof(WORD) * 3, sizeof(BYTE));
  11196. hSecure = MmSecureVirtualMemory(lpGammaRamp, MAX_COLORTABLE * sizeof(WORD) * 3, PAGE_READONLY);
  11197. }
  11198. __except(EXCEPTION_EXECUTE_HANDLER)
  11199. {
  11200. WARNING("DxDdSetGammaRamp: Fail to capture usermode buffer\n");
  11201. bError = TRUE;
  11202. }
  11203. {
  11204. EDD_SHAREDEVLOCK eDevlock(peDirectDrawGlobal);
  11205. // If the gamma has not already been set by this app, get the existing gamma
  11206. // ramp and save it so we can clean up after ourselves.
  11207. if ((peDirectDrawLocal->pGammaRamp == NULL) && !bError)
  11208. {
  11209. peDirectDrawLocal->pGammaRamp = (WORD *) PALLOCMEM(MAX_COLORTABLE * 3 * sizeof(WORD), 'pddG');
  11210. if (peDirectDrawLocal->pGammaRamp != NULL)
  11211. {
  11212. bRet = DxEngGetDeviceGammaRamp( peDirectDrawGlobal->hdev, peDirectDrawLocal->pGammaRamp );
  11213. if (!bRet)
  11214. {
  11215. bError = TRUE;
  11216. }
  11217. }
  11218. else
  11219. {
  11220. bError = TRUE;
  11221. }
  11222. }
  11223. // If this new gamma ramp is the same as the original ramp, we know
  11224. // that we are restoring it.
  11225. if ((peDirectDrawLocal->pGammaRamp != NULL) && !bError)
  11226. {
  11227. pTemp1 = (WORD *) lpGammaRamp;
  11228. pTemp2 = peDirectDrawLocal->pGammaRamp;
  11229. for (i = 0; i < MAX_COLORTABLE * 3; i++)
  11230. {
  11231. if (*pTemp1++ != *pTemp2++)
  11232. {
  11233. break;
  11234. }
  11235. }
  11236. if (i == MAX_COLORTABLE * 3)
  11237. {
  11238. VFREEMEM(peDirectDrawLocal->pGammaRamp);
  11239. peDirectDrawLocal->pGammaRamp = NULL;
  11240. }
  11241. }
  11242. if ((bError == FALSE) && hSecure)
  11243. {
  11244. bRet = DxEngSetDeviceGammaRamp(peDirectDrawGlobal->hdev, lpGammaRamp, FALSE);
  11245. }
  11246. }
  11247. if (hSecure)
  11248. {
  11249. MmUnsecureVirtualMemory(hSecure);
  11250. }
  11251. }
  11252. else
  11253. {
  11254. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  11255. }
  11256. }
  11257. else
  11258. {
  11259. WARNING("DxDdSetGammaRamp: Invalid DirectDraw object specified\n");
  11260. }
  11261. return(bRet);
  11262. }
  11263. /******************************Public*Routine******************************\
  11264. * DxDdCreateSurfaceEx
  11265. *
  11266. * Just notify driver of new handle association by calling its
  11267. * CreateSurfaceEx
  11268. *
  11269. * History:
  11270. *
  11271. * Wrote it:
  11272. * 25-Feb-1999 -by- Kan Qiu [kanqiu]
  11273. \**************************************************************************/
  11274. DWORD
  11275. APIENTRY
  11276. DxDdCreateSurfaceEx(
  11277. HANDLE hDirectDraw,
  11278. HANDLE hSurface,
  11279. DWORD dwSurfaceHandle
  11280. )
  11281. {
  11282. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  11283. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  11284. EDD_SURFACE* peSurface;
  11285. EDD_LOCK_SURFACE eLockSurface;
  11286. peSurface = eLockSurface.peLock( hSurface );
  11287. if (peSurface == NULL)
  11288. {
  11289. WARNING("DxDdCreateSurfaceEx: Invalid surfaces specified\n");
  11290. return DDERR_GENERIC;
  11291. }
  11292. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
  11293. if (peDirectDrawLocal != NULL )
  11294. {
  11295. EDD_DIRECTDRAW_GLOBAL *peDirectDrawGlobal =
  11296. peDirectDrawLocal->peDirectDrawGlobal;
  11297. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  11298. // associate user mode surface handle to kernel mode surface
  11299. if ((peSurface->dwSurfaceHandle != 0) &&
  11300. (peSurface->dwSurfaceHandle != dwSurfaceHandle))
  11301. {
  11302. WARNING("DxDdCreateSurfaceEx: called with surface which has been called already\n");
  11303. }
  11304. if (peDirectDrawGlobal->bSuspended)
  11305. {
  11306. return DDERR_SURFACELOST;
  11307. }
  11308. else if ((peDirectDrawGlobal->Miscellaneous2CallBacks.CreateSurfaceEx) &&
  11309. (dwSurfaceHandle != 0))
  11310. {
  11311. peSurface->dwSurfaceHandle = dwSurfaceHandle;
  11312. DD_CREATESURFACEEXDATA CreateSurfaceExData;
  11313. // Use the CreateSurfaceEx DDI to once again inform the
  11314. // driver that something has changed
  11315. CreateSurfaceExData.dwFlags = 0;
  11316. CreateSurfaceExData.ddRVal = DDERR_GENERIC;
  11317. CreateSurfaceExData.lpDDLcl = peDirectDrawLocal;
  11318. CreateSurfaceExData.lpDDSLcl = peSurface;
  11319. peDirectDrawGlobal->Miscellaneous2CallBacks.CreateSurfaceEx(&CreateSurfaceExData);
  11320. if (CreateSurfaceExData.ddRVal != DD_OK)
  11321. {
  11322. WARNING("DxDdCreateSurfaceEx: DDI call to the driver failed\n");
  11323. return (CreateSurfaceExData.ddRVal);
  11324. }
  11325. else
  11326. {
  11327. if (peSurface->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  11328. {
  11329. PDEVOBJ po(peDirectDrawGlobal->hdev);
  11330. // Mark we called CreateSurfaceEx on this surface.
  11331. // this information will be used when we need to call
  11332. // CreateSurfaceEx after video mode change.
  11333. peSurface->fl |= DD_SURFACE_FLAG_SYSMEM_CREATESURFACEEX;
  11334. ASSERTGDI(peSurface->pGraphicsDeviceCreator == po.pGraphicsDevice(),
  11335. "DXG: CreateSurfaceEx: calling non-owner driver");
  11336. }
  11337. }
  11338. }
  11339. else
  11340. {
  11341. return DDERR_GENERIC;
  11342. }
  11343. }
  11344. return DD_OK;
  11345. }
  11346. /******************************Public*Routine******************************\
  11347. * VOID DxDdCloseProcess
  11348. *
  11349. * 2-May-2000 -by- Hideyuki Nagase [hideyukn]
  11350. * Wrote it.
  11351. \**************************************************************************/
  11352. VOID DxDdCloseProcess(W32PID w32Pid)
  11353. {
  11354. DdHmgCloseProcess(w32Pid);
  11355. }
  11356. /******************************Public*Routine******************************\
  11357. * PVOID DxDdAllocPrivateUserMem()
  11358. *
  11359. * History:
  11360. * 28-Oct-1999 -by- Scott MacDonald [smac]
  11361. * Wrote it.
  11362. \**************************************************************************/
  11363. PVOID
  11364. DxDdAllocPrivateUserMem(
  11365. PDD_SURFACE_LOCAL pSurfaceLocal,
  11366. SIZE_T cj, //ZwAllocateVirtualMemory uses SIZE_T, change accordingly
  11367. ULONG tag
  11368. )
  11369. {
  11370. EDD_SURFACE *peSurface = (EDD_SURFACE *) pSurfaceLocal;
  11371. PVOID pv = NULL;
  11372. //
  11373. // DirectDraw can call the driver outside of it's process (e.g. switching
  11374. // desktops, etc.), so this function helps protect against that.
  11375. //
  11376. if (PsGetCurrentProcess() == peSurface->peDirectDrawLocal->Process)
  11377. {
  11378. pv = EngAllocUserMem ( cj, tag );
  11379. }
  11380. return pv;
  11381. }
  11382. /******************************Public*Routine******************************\
  11383. * DxDdFreePrivateUserMem()
  11384. *
  11385. * History:
  11386. * 28-Oct-1999 -by- Scott MacDonald [smac]
  11387. * Wrote it.
  11388. \**************************************************************************/
  11389. VOID
  11390. DxDdFreePrivateUserMem(
  11391. PDD_SURFACE_LOCAL pSurfaceLocal,
  11392. PVOID pv
  11393. )
  11394. {
  11395. EDD_SURFACE *peSurface = (EDD_SURFACE *) pSurfaceLocal;
  11396. // If the surface has an aliased lock on it, then we don't want
  11397. // to delete this memory now or else the app may fault, so we put
  11398. // it in a list of memory to free later.
  11399. if (peSurface->fl & DD_SURFACE_FLAG_ALIAS_LOCK)
  11400. {
  11401. DeferMemoryFree(pv, peSurface);
  11402. }
  11403. else
  11404. {
  11405. SafeFreeUserMem(pv, peSurface->peDirectDrawLocal->Process);
  11406. }
  11407. return;
  11408. }
  11409. /******************************Public*Routine******************************\
  11410. * DxDdIoctl()
  11411. *
  11412. * History:
  11413. * 17-Apr-2001 -by- Scott MacDonald [smac]
  11414. * Wrote it.
  11415. \**************************************************************************/
  11416. HRESULT
  11417. DxDdIoctl(
  11418. ULONG Ioctl,
  11419. PVOID pBuffer,
  11420. ULONG BufferSize
  11421. )
  11422. {
  11423. return DDERR_UNSUPPORTED;
  11424. }
  11425. /******************************Public*Routine******************************\
  11426. *
  11427. * DxDdLock/UnlockDirectDrawSurface
  11428. *
  11429. * Functions to allow drivers to lock and unlock DirectDraw surface handles
  11430. * that may get passed to them.
  11431. *
  11432. * Such handles are currently passed to the driver in the Direct3D texture
  11433. * interface, necessitating these functions.
  11434. *
  11435. * History:
  11436. * Wed Oct 23 15:52:27 1996 -by- Drew Bliss [drewb]
  11437. * Created
  11438. *
  11439. \**************************************************************************/
  11440. PDD_SURFACE_LOCAL
  11441. DxDdLockDirectDrawSurface(HANDLE hSurface)
  11442. {
  11443. EDD_SURFACE *peSurf;
  11444. peSurf = (EDD_SURFACE *)DdHmgLock((HDD_OBJ)hSurface, DD_SURFACE_TYPE, FALSE);
  11445. if (peSurf != NULL)
  11446. {
  11447. return (PDD_SURFACE_LOCAL)peSurf;
  11448. }
  11449. else
  11450. {
  11451. return peSurf;
  11452. }
  11453. }
  11454. BOOL
  11455. DxDdUnlockDirectDrawSurface(PDD_SURFACE_LOCAL pSurface)
  11456. {
  11457. if (pSurface != NULL)
  11458. {
  11459. DEC_EXCLUSIVE_REF_CNT((EDD_SURFACE *)pSurface);
  11460. return TRUE;
  11461. }
  11462. else
  11463. {
  11464. return FALSE;
  11465. }
  11466. }
  11467. /******************************Public*Routine******************************\
  11468. * BOOL DxDdEnableDirectDrawRedirection
  11469. *
  11470. * 11-Apr-2000 -by- Hideyuki Nagase [hideyukn]
  11471. * Wrote it.
  11472. \**************************************************************************/
  11473. BOOL DxDdEnableDirectDrawRedirection(HDEV hdev, BOOL bEnable)
  11474. {
  11475. #ifdef DX_REDIRECTION
  11476. LONG* pl;
  11477. PDEVOBJ po(hdev);
  11478. if (po.bValid())
  11479. {
  11480. // Hold devlock to prevent from mode change.
  11481. EDD_DEVLOCK eDevLock(po.hdev());
  11482. // Bump the mode uniqueness to let user-mode DirectDraw know that
  11483. // someone else has done 'something' need to refresh user-mode
  11484. // data.
  11485. INC_DISPLAY_UNIQUENESS();
  11486. // Save redirection status
  11487. gbDxRedirection = bEnable;
  11488. return (TRUE);
  11489. }
  11490. else
  11491. {
  11492. return (FALSE);
  11493. }
  11494. #else
  11495. return (FALSE);
  11496. #endif // DX_REDIRECTION
  11497. }
  11498. /******************************Public*Routine******************************\
  11499. * VOID DxDdSetAccelLevel
  11500. *
  11501. * 2-Oct-2000 -by- Hideyuki Nagase [hideyukn]
  11502. * Wrote it.
  11503. \**************************************************************************/
  11504. VOID DxDdSetAccelLevel(HDEV hdev, DWORD dwAccelLevel, DWORD dwOverride)
  11505. {
  11506. if ((dwAccelLevel >= 3) ||
  11507. (dwOverride & DRIVER_NOT_CAPABLE_DDRAW))
  11508. {
  11509. PDEVOBJ po(hdev);
  11510. po.peDirectDrawGlobal()->llAssertModeTimeout = 0;
  11511. }
  11512. }
  11513. /******************************Public*Routine******************************\
  11514. * VOID DxDdGetSurfaceLock
  11515. *
  11516. * 2-Oct-2000 -by- Hideyuki Nagase [hideyukn]
  11517. * Wrote it.
  11518. \**************************************************************************/
  11519. DWORD DxDdGetSurfaceLock(HDEV hdev)
  11520. {
  11521. PDEVOBJ po(hdev);
  11522. return (po.peDirectDrawGlobal()->cSurfaceLocks);
  11523. }
  11524. /******************************Public*Routine******************************\
  11525. * VOID DxDdEnumLockedSurfaceRect
  11526. *
  11527. * 2-Oct-2000 -by- Hideyuki Nagase [hideyukn]
  11528. * Wrote it.
  11529. \**************************************************************************/
  11530. PVOID DxDdEnumLockedSurfaceRect(HDEV hdev, PVOID pvSurface, RECTL *pRect)
  11531. {
  11532. PDEVOBJ po(hdev);
  11533. EDD_SURFACE *peSurface;
  11534. if (pvSurface == NULL)
  11535. {
  11536. peSurface = po.peDirectDrawGlobal()->peSurface_PrimaryLockList;
  11537. }
  11538. else
  11539. {
  11540. peSurface = ((EDD_SURFACE *)pvSurface)->peSurface_PrimaryLockNext;
  11541. }
  11542. if (peSurface)
  11543. {
  11544. *pRect = peSurface->rclLock;
  11545. }
  11546. return ((PVOID)peSurface);
  11547. }
  11548. /******************************Public*Routine******************************\
  11549. * DWORD DxDxgGenericThunk
  11550. *
  11551. * 14-Jun-2000 -by- Hideyuki Nagase [hideyukn]
  11552. * Wrote it (stub).
  11553. \**************************************************************************/
  11554. DWORD DxDxgGenericThunk(
  11555. IN ULONG_PTR ulIndex,
  11556. IN ULONG_PTR ulHandle,
  11557. IN OUT SIZE_T *pdwSizeOfPtr1,
  11558. IN OUT PVOID pvPtr1,
  11559. IN OUT SIZE_T *pdwSizeOfPtr2,
  11560. IN OUT PVOID pvPtr2)
  11561. {
  11562. UNREFERENCED_PARAMETER(ulIndex);
  11563. UNREFERENCED_PARAMETER(ulHandle);
  11564. UNREFERENCED_PARAMETER(pdwSizeOfPtr1);
  11565. UNREFERENCED_PARAMETER(pvPtr1);
  11566. UNREFERENCED_PARAMETER(pdwSizeOfPtr2);
  11567. UNREFERENCED_PARAMETER(pvPtr2);
  11568. return (0);
  11569. }