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.

1213 lines
39 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: d3d.cxx
  3. *
  4. * Contains all of GDI's private Direct3D APIs.
  5. *
  6. * Created: 04-Jun-1996
  7. * Author: Drew Bliss [drewb]
  8. *
  9. * Copyright (c) 1995-1999 Microsoft Corporation
  10. *
  11. \**************************************************************************/
  12. #include "precomp.hxx"
  13. // Minimum size of DrawPrimitive buffer associated with a context.
  14. #define MIN_PRIM_BUFFER_SIZE (1 << 14)
  15. // Maximum
  16. #define MAX_PRIM_BUFFER_SIZE (1 << 20)
  17. // Default
  18. #define DEF_PRIM_BUFFER_SIZE (1 << 16)
  19. // Alignment requirement for the DrawPrim buffer. Must be a power of two.
  20. #define DP_BUFFER_ALIGN 32
  21. // Maximum number of vertices considered legal.
  22. #define MAX_VERTEX_COUNT 0x10000
  23. // Maximum number of indices considered legal.
  24. #define MAX_INDEX_COUNT 0x80000
  25. // Maximum number of clear rectangles considered legal.
  26. #define MAX_CLEAR_RECTS 0x1000
  27. // Maximum number of state changes per RenderState call
  28. #define MAX_STATE_CHANGE (D3DRENDERSTATE_STIPPLEPATTERN31+1)
  29. #ifdef D3D_ENTRIES
  30. #define D3D_ENTRY(s) WARNING(s)
  31. #else
  32. #define D3D_ENTRY(s)
  33. #endif
  34. // Simple structure for managing DD surfaces
  35. struct D3D_SURFACE
  36. {
  37. HANDLE h;
  38. BOOL bOptional;
  39. EDD_SURFACE* peSurf;
  40. PDD_SURFACE_LOCAL pLcl;
  41. };
  42. #define INIT_D3DSURFACE(SurfaceArray, Count) \
  43. for (int i = 0 ; i < (Count) ; i++) { \
  44. (SurfaceArray)[i].peSurf = NULL; \
  45. }
  46. #define CLEANUP_D3DSURFACE(SurfaceArray, Count) \
  47. for (int i = 0 ; i < (Count) ; i++) { \
  48. if ((SurfaceArray)[i].peSurf) { \
  49. DEC_EXCLUSIVE_REF_CNT((SurfaceArray)[i].peSurf); \
  50. } \
  51. }
  52. // Convenience macro for parameter validation. ProbeForWrite does
  53. // all the checks that ProbeForRead does in addition to write testing
  54. // so it serves as a read/write check.
  55. // Assumes DWORD alignment.
  56. #define CAPTURE_RW_STRUCT(ptr, type) \
  57. (ProbeForWrite(ptr, sizeof(type), sizeof(DWORD)), *(ptr))
  58. #define CAPTURE_RD_STRUCT(ptr, type) \
  59. (ProbeForRead(ptr, sizeof(type), sizeof(DWORD)), *(ptr))
  60. /******************************Public*Routine******************************\
  61. *
  62. * D3dLockSurfaces
  63. *
  64. * Walks the array of surfaces, locking any with non-zero handles
  65. *
  66. * 1. This routine must be called with the HmgrSemaphore acquired.
  67. * 2. INIT_D3DSURFACE must be called for pSurf parameter.
  68. *
  69. * History:
  70. * Fri Jun 14 14:26:06 1996 -by- Drew Bliss [drewb]
  71. * Created
  72. *
  73. \**************************************************************************/
  74. BOOL D3dLockSurfaces(int n, D3D_SURFACE *pSurf)
  75. {
  76. while (n-- > 0)
  77. {
  78. if (pSurf->h != NULL)
  79. {
  80. pSurf->peSurf = (EDD_SURFACE *)DdHmgLock((HDD_OBJ)pSurf->h, DD_SURFACE_TYPE, TRUE);
  81. if (pSurf->peSurf == NULL)
  82. {
  83. WARNING("D3dLockSurfaces unable to lock buffer");
  84. return FALSE;
  85. }
  86. if (pSurf->peSurf->bLost)
  87. {
  88. WARNING("D3dLockSurfaces unable to lock buffer Surface is Lost");
  89. return FALSE;
  90. }
  91. pSurf->pLcl = pSurf->peSurf;
  92. }
  93. else if (!pSurf->bOptional)
  94. {
  95. WARNING("D3dLockSurfaces: NULL for mandatory surface");
  96. return FALSE;
  97. }
  98. else
  99. {
  100. pSurf->pLcl = NULL;
  101. }
  102. pSurf++;
  103. }
  104. return TRUE;
  105. }
  106. /******************************Public*Routine******************************\
  107. *
  108. * D3dSetup
  109. *
  110. * Prepares the system for a call to a D3D driver
  111. *
  112. * History:
  113. * Tue Jun 04 17:09:23 1996 -by- Drew Bliss [drewb]
  114. * Created
  115. *
  116. \**************************************************************************/
  117. BOOL D3dSetup(EDD_DIRECTDRAW_GLOBAL* peDdGlobal,
  118. KFLOATING_SAVE* pfsState)
  119. {
  120. ASSERTGDI(peDdGlobal != NULL,
  121. "D3dSetup on NULL global\n");
  122. if (!NT_SUCCESS(KeSaveFloatingPointState(pfsState)))
  123. {
  124. WARNING("D3dSetup: Unable to save FP state\n");
  125. return FALSE;
  126. }
  127. DxEngLockHdev(peDdGlobal->hdev);
  128. return TRUE;
  129. }
  130. /******************************Public*Routine******************************\
  131. *
  132. * D3dCleanup
  133. *
  134. * Cleans up after a D3D driver calls
  135. *
  136. * History:
  137. * Tue Jun 04 17:10:21 1996 -by- Drew Bliss [drewb]
  138. * Created
  139. *
  140. \**************************************************************************/
  141. void D3dCleanup(EDD_DIRECTDRAW_GLOBAL* peDdGlobal,
  142. KFLOATING_SAVE* pfsState)
  143. {
  144. DxEngUnlockHdev(peDdGlobal->hdev);
  145. KeRestoreFloatingPointState(pfsState);
  146. }
  147. /******************************Public*Routine******************************\
  148. *
  149. * D3dLockContext
  150. *
  151. * Prepares the system for a call to a D3D driver with a driver context
  152. *
  153. * This routine must be called with the HmgrSemaphore acquired
  154. *
  155. * History:
  156. * Tue Jun 04 17:09:23 1996 -by- Drew Bliss [drewb]
  157. * Created
  158. *
  159. \**************************************************************************/
  160. D3DNTHAL_CONTEXT *D3dLockContext(KFLOATING_SAVE *pfsState,
  161. ULONG_PTR *pdwhContext)
  162. {
  163. D3DNTHAL_CONTEXT *pdhctx;
  164. pdhctx = (D3DNTHAL_CONTEXT *)DdHmgLock((HDD_OBJ)*pdwhContext, D3D_HANDLE_TYPE, TRUE);
  165. // release handle manager lock.
  166. DdHmgReleaseHmgrSemaphore();
  167. if (pdhctx == NULL)
  168. {
  169. WARNING("D3dLockContext unable to lock context");
  170. return NULL;
  171. }
  172. // Before we access inside D3DCONTEXT.peDdGlobal, hold shared devlock,
  173. // since peDdGlobal can be changed during video mode change.
  174. DxEngLockShareSem();
  175. if (pdhctx->dwType != DNHO_CONTEXT)
  176. {
  177. WARNING("D3dLockContext: Valid handle not a context");
  178. goto Error_LockContext;
  179. }
  180. if (pdhctx->peDdGlobal == NULL)
  181. {
  182. WARNING("D3dLockContext: Call on disabled object");
  183. goto Error_LockContext;
  184. }
  185. ASSERTGDI(pdhctx->peDdGlobal->Miscellaneous2CallBacks.CreateSurfaceEx,
  186. "D3dLockContext: No CreateSurfaceEx callback");
  187. if (D3dSetup(pdhctx->peDdGlobal, pfsState))
  188. {
  189. *pdwhContext = pdhctx->dwDriver;
  190. // keep holding share lock, will be released at D3dUnlockContext.
  191. return pdhctx;
  192. }
  193. Error_LockContext:
  194. DEC_EXCLUSIVE_REF_CNT(pdhctx);
  195. DxEngUnlockShareSem();
  196. return NULL;
  197. }
  198. /******************************Public*Routine******************************\
  199. *
  200. * D3dUnlockContext
  201. *
  202. * Cleans up after a D3D driver calls with D3D context
  203. *
  204. * History:
  205. * Tue Apr 10 16:15:00 2001 -by- Hideyuki Nagase [hideyukn]
  206. * Created
  207. *
  208. \**************************************************************************/
  209. VOID D3dUnlockContext(D3DNTHAL_CONTEXT *pdhctx, KFLOATING_SAVE *pfsState)
  210. {
  211. //
  212. // Release devlock, and restore floating point state.
  213. //
  214. D3dCleanup(pdhctx->peDdGlobal, pfsState);
  215. //
  216. // Release share devlock.
  217. //
  218. DxEngUnlockShareSem();
  219. //
  220. // Unlock context
  221. //
  222. DEC_EXCLUSIVE_REF_CNT(pdhctx);
  223. }
  224. /******************************Public*Routine******************************\
  225. *
  226. * D3dDeleteHandle
  227. *
  228. * Cleans up D3D driver context wrapper objects
  229. *
  230. * History:
  231. * Tue Jun 11 17:42:25 1996 -by- Drew Bliss [drewb]
  232. * Created
  233. *
  234. \**************************************************************************/
  235. DWORD D3dDeleteHandle(HANDLE hD3dHandle, ULONG_PTR dwContext,
  236. BOOL *pbRemoved, HRESULT *phr)
  237. {
  238. D3DNTHAL_OBJECT *pdhobj;
  239. D3DNTHAL_CONTEXT *pdhctx;
  240. D3DNTHAL_CONTEXTDESTROYDATA dcdd;
  241. D3DNTHAL_TEXTUREDESTROYDATA dtdd;
  242. KFLOATING_SAVE fsState;
  243. DWORD dwRet = DDHAL_DRIVER_HANDLED;
  244. // Lock handle first.
  245. pdhobj = (D3DNTHAL_OBJECT *) DdHmgLock((HDD_OBJ)hD3dHandle, D3D_HANDLE_TYPE, FALSE);
  246. if (pdhobj == NULL)
  247. {
  248. if (pbRemoved != NULL)
  249. {
  250. *pbRemoved = FALSE;
  251. }
  252. *phr = DDERR_INVALIDOBJECT;
  253. return (dwRet);
  254. }
  255. // Before we access inside D3DCONTEXT.peDdGlobal, hold shared devlock,
  256. // since peDdGlobal can be changed during video mode change.
  257. DxEngLockShareSem();
  258. // Sundowndx: Needs to pass in cjBuffer as SIZE_T inorder to compiler in 64bit
  259. SIZE_T cjBuffer = 0;
  260. if (!D3dSetup(pdhobj->peDdGlobal, &fsState))
  261. {
  262. DxEngUnlockShareSem();
  263. DEC_EXCLUSIVE_REF_CNT(pdhobj);
  264. *phr = DDERR_OUTOFMEMORY;
  265. return (dwRet);
  266. }
  267. switch(pdhobj->dwType)
  268. {
  269. case DNHO_CONTEXT:
  270. // Clean up DrawPrimitive buffer.
  271. pdhctx = (D3DNTHAL_CONTEXT *)pdhobj;
  272. MmUnsecureVirtualMemory(pdhctx->hBufSecure);
  273. ZwFreeVirtualMemory(NtCurrentProcess(), &pdhctx->pvBufferAlloc,
  274. &cjBuffer, MEM_RELEASE);
  275. // Sundowndx: need to look at the d3d structure, truncate it for now
  276. pdhctx->cjBuffer = (ULONG)cjBuffer;
  277. // Call driver.
  278. dcdd.dwhContext = pdhobj->dwDriver;
  279. dwRet = pdhobj->peDdGlobal->D3dCallBacks.ContextDestroy(&dcdd);
  280. *phr = dcdd.ddrval;
  281. break;
  282. case DNHO_TEXTURE:
  283. dtdd.dwhContext = dwContext;
  284. dtdd.dwHandle = pdhobj->dwDriver;
  285. dwRet = pdhobj->peDdGlobal->D3dCallBacks.TextureDestroy(&dtdd);
  286. *phr = dtdd.ddrval;
  287. break;
  288. }
  289. // Now Remove handle from handle manager.
  290. PVOID pv = DdHmgRemoveObject((HDD_OBJ)hD3dHandle, 1, 0, TRUE, D3D_HANDLE_TYPE);
  291. // This shouldn't fail, because above DdHmgLock is succeeded.
  292. ASSERTGDI(pv,"DdHmgRemoveObject failed D3dDeleteHandle");
  293. // Release devlock and restore floating point state.
  294. D3dCleanup(pdhobj->peDdGlobal, &fsState);
  295. // Release share lock
  296. DxEngUnlockShareSem();
  297. // If this is last reference to DdGlobal (= GDI's PDEV), this
  298. // will release it, so we can't call it while devlock is hold (which
  299. // means between D3dSetup ~ D3dCleanup).
  300. vDdDecrementReferenceCount(pdhobj->peDdGlobal);
  301. // Delete the object.
  302. DdFreeObject(pdhobj, D3D_HANDLE_TYPE);
  303. if (pbRemoved != NULL)
  304. {
  305. *pbRemoved = TRUE;
  306. }
  307. return dwRet;
  308. }
  309. /******************************Public*Routine******************************\
  310. *
  311. * D3D_SIMPLE_COPY_WITH_CONTEXT
  312. *
  313. * Macro which creates a thunk function for D3D entry points which
  314. * have only simple copy arguments in, a context to dereference and
  315. * only a simple copy out.
  316. *
  317. * D3D_SIMPLE_DECL can be defined to add declarations.
  318. * By default it's empty.
  319. * D3D_SIMPLE_SETUP can be defined to add more setup code.
  320. * By default it's empty.
  321. * D3D_SIMPLE_WRITEBACK can be defined to add more writeback code.
  322. * By default it's empty.
  323. * D3D_SIMPLE_CALLBACKS is defined to the callbacks structure to look in.
  324. * By default it's D3dCallBacks.
  325. *
  326. * History:
  327. * Fri Jun 14 14:12:54 1996 -by- Drew Bliss [drewb]
  328. * Created
  329. *
  330. \**************************************************************************/
  331. #define D3D_SIMPLE_DECL
  332. #define D3D_SIMPLE_SETUP
  333. #define D3D_SIMPLE_WRITEBACK
  334. #define D3D_SIMPLE_CALLBACKS D3dCallBacks
  335. #define D3D_SIMPLE_COPY_WITH_CONTEXT(Name, Type) \
  336. DWORD APIENTRY \
  337. DxD3d##Name(LPD3DNTHAL_##Type##DATA pdata) \
  338. { \
  339. D3DNTHAL_##Type##DATA data; \
  340. KFLOATING_SAVE fsState; \
  341. DWORD dwRet; \
  342. D3DNTHAL_CONTEXT* pdhctx; \
  343. D3D_SIMPLE_DECL \
  344. \
  345. D3D_ENTRY("DxD3d" #Name); \
  346. \
  347. dwRet = DDHAL_DRIVER_NOTHANDLED; \
  348. \
  349. __try \
  350. { \
  351. data = CAPTURE_RW_STRUCT(pdata, D3DNTHAL_##Type##DATA); \
  352. } \
  353. __except(EXCEPTION_EXECUTE_HANDLER) \
  354. { \
  355. WARNING("DxD3d" #Name " unable to access argument"); \
  356. return dwRet; \
  357. } \
  358. \
  359. DdHmgAcquireHmgrSemaphore(); /* will be released inside D3dLockContext */ \
  360. \
  361. pdhctx = D3dLockContext(&fsState, &data.dwhContext); \
  362. if (pdhctx == NULL) \
  363. { \
  364. return dwRet; \
  365. } \
  366. \
  367. D3D_SIMPLE_SETUP \
  368. \
  369. if (pdhctx->peDdGlobal->bSuspended) \
  370. { \
  371. data.ddrval = DDERR_SURFACELOST; \
  372. } \
  373. else \
  374. { \
  375. if (pdhctx->peDdGlobal->D3D_SIMPLE_CALLBACKS.##Name) \
  376. { \
  377. dwRet = pdhctx->peDdGlobal->D3D_SIMPLE_CALLBACKS.##Name(&data);\
  378. } \
  379. else \
  380. { \
  381. WARNING("DxD3d" #Name " call not present!"); \
  382. } \
  383. } \
  384. \
  385. D3dUnlockContext(pdhctx, &fsState); \
  386. \
  387. __try \
  388. { \
  389. pdata->ddrval = data.ddrval; \
  390. D3D_SIMPLE_WRITEBACK \
  391. } \
  392. __except(EXCEPTION_EXECUTE_HANDLER) \
  393. { \
  394. WARNING("DxD3d" #Name " unable to write back arguments"); \
  395. } \
  396. \
  397. return dwRet; \
  398. }
  399. /******************************Public*Routine******************************\
  400. *
  401. * D3D_DELETE_HANDLE
  402. *
  403. * Macro for routines which destroy a handle-managed object.
  404. *
  405. * History:
  406. * Wed Oct 23 19:32:11 1996 -by- Drew Bliss [drewb]
  407. * Created
  408. *
  409. \**************************************************************************/
  410. #define D3D_DELETE_HANDLE(Name, Type, Field) \
  411. DWORD APIENTRY \
  412. DxD3d##Name##Destroy(LPD3DNTHAL_##Type##DESTROYDATA pdata) \
  413. { \
  414. DWORD dwRet; \
  415. HANDLE hD3dHandle; \
  416. HRESULT hr; \
  417. \
  418. D3D_ENTRY("DxD3d" #Name "Destroy"); \
  419. \
  420. __try \
  421. { \
  422. ProbeForWrite(pdata, sizeof(D3DNTHAL_##Type##DESTROYDATA), \
  423. sizeof(DWORD)); \
  424. hD3dHandle = (HANDLE)pdata->Field; \
  425. } \
  426. __except(EXCEPTION_EXECUTE_HANDLER) \
  427. { \
  428. WARNING("DxD3d" #Name "Destroy unable to access argument"); \
  429. return DDHAL_DRIVER_NOTHANDLED; \
  430. } \
  431. \
  432. dwRet = D3dDeleteHandle(hD3dHandle, 0, (BOOL *)NULL, &hr); \
  433. \
  434. __try \
  435. { \
  436. pdata->ddrval = hr; \
  437. } \
  438. __except(EXCEPTION_EXECUTE_HANDLER) \
  439. { \
  440. WARNING("DxD3d" #Name "Destroy unable to write back arguments"); \
  441. } \
  442. \
  443. return dwRet; \
  444. }
  445. /******************************Public*Routine******************************\
  446. *
  447. * DxD3dContextCreate
  448. *
  449. * History:
  450. * Tue Jun 04 13:05:18 1996 -by- Drew Bliss [drewb]
  451. * Created
  452. *
  453. \**************************************************************************/
  454. DWORD APIENTRY
  455. DxD3dContextCreate(HANDLE hDirectDrawLocal,
  456. HANDLE hSurfColor,
  457. HANDLE hSurfZ,
  458. D3DNTHAL_CONTEXTCREATEI *pdcci)
  459. {
  460. LPD3DNTHAL_CONTEXTCREATEDATA pdccd;
  461. D3DNTHAL_CONTEXTCREATEDATA dccd;
  462. KFLOATING_SAVE fsState;
  463. DWORD dwRet;
  464. HANDLE hCleanup = 0;
  465. EDD_DIRECTDRAW_LOCAL* peDdLocal;
  466. EDD_LOCK_DIRECTDRAW eLockDd;
  467. EDD_DIRECTDRAW_GLOBAL* peDdGlobal;
  468. D3D_SURFACE dsurf[2];
  469. NTSTATUS nts;
  470. SIZE_T cjBuffer;
  471. D3DNTHAL_CONTEXT* pdhctx = NULL;
  472. PVOID pvBuffer = NULL;
  473. PVOID pvBufRet = NULL;
  474. HANDLE hBufSecure = NULL;
  475. ULONG_PTR Interface;
  476. D3D_ENTRY("DxD3dContextCreate");
  477. ASSERTGDI(FIELD_OFFSET(D3DNTHAL_CONTEXTCREATEI, pvBuffer) ==
  478. sizeof(D3DNTHAL_CONTEXTCREATEDATA),
  479. "D3DNTHAL_CONTEXTCREATEI out of sync\n");
  480. pdccd = (LPD3DNTHAL_CONTEXTCREATEDATA)pdcci;
  481. dwRet = DDHAL_DRIVER_NOTHANDLED;
  482. __try
  483. {
  484. ProbeForWrite(pdcci, sizeof(D3DNTHAL_CONTEXTCREATEI), sizeof(DWORD));
  485. dccd.dwPID = pdccd->dwPID;
  486. dccd.dwhContext = pdccd->dwhContext;
  487. dccd.ddrval = pdccd->ddrval;
  488. cjBuffer = pdcci->cjBuffer;
  489. Interface = pdccd->dwhContext;
  490. }
  491. __except(EXCEPTION_EXECUTE_HANDLER)
  492. {
  493. WARNING("DxD3dContextCreate unable to access argument");
  494. return dwRet;
  495. }
  496. if (cjBuffer == 0)
  497. {
  498. cjBuffer = DEF_PRIM_BUFFER_SIZE;
  499. }
  500. else if (cjBuffer < MIN_PRIM_BUFFER_SIZE ||
  501. cjBuffer > MAX_PRIM_BUFFER_SIZE)
  502. {
  503. WARNING("DxD3dContextCreate: illegal prim buffer size");
  504. return dwRet;
  505. }
  506. peDdLocal = eLockDd.peLock(hDirectDrawLocal);
  507. if (peDdLocal == NULL)
  508. {
  509. WARNING("DxD3dContextCreate unable to lock hDdLocal");
  510. return dwRet;
  511. }
  512. peDdGlobal = peDdLocal->peDirectDrawGlobal;
  513. INIT_D3DSURFACE(dsurf, 2);
  514. dsurf[0].h = hSurfColor;
  515. dsurf[0].bOptional = FALSE;
  516. dsurf[1].h = hSurfZ;
  517. dsurf[1].bOptional = TRUE;
  518. DdHmgAcquireHmgrSemaphore();
  519. if (!D3dLockSurfaces(2, dsurf))
  520. {
  521. DdHmgReleaseHmgrSemaphore();
  522. goto Exit_CreateContext;
  523. }
  524. DdHmgReleaseHmgrSemaphore();
  525. pdhctx = (D3DNTHAL_CONTEXT *)DdHmgAlloc(sizeof(D3DNTHAL_CONTEXT),
  526. D3D_HANDLE_TYPE, HMGR_ALLOC_LOCK);
  527. if (pdhctx == NULL)
  528. {
  529. WARNING("DxD3dContextCreate unable to alloc handle");
  530. goto Exit_CreateContext;
  531. }
  532. hCleanup = pdhctx->hHmgr;
  533. // Allocate and lock DrawPrimitive buffer space. We want the
  534. // buffer to be aligned on a large boundary so we alter the
  535. // pointer to return to be aligned. Note that we do not overallocate
  536. // since we don't want the extra alignment space to push the allocation
  537. // into another page. We're returning a size anyway so we can
  538. // get away with this transparently.
  539. nts = ZwAllocateVirtualMemory(NtCurrentProcess(), &pvBuffer,
  540. 0, &cjBuffer, MEM_COMMIT | MEM_RESERVE,
  541. PAGE_READWRITE);
  542. if (!NT_SUCCESS(nts))
  543. {
  544. goto Exit_CreateContext;
  545. }
  546. hBufSecure = MmSecureVirtualMemory(pvBuffer, cjBuffer, PAGE_READWRITE);
  547. if (hBufSecure == NULL)
  548. {
  549. goto Exit_CreateContext;
  550. }
  551. if (!D3dSetup(peDdGlobal, &fsState))
  552. {
  553. goto Exit_CreateContext;
  554. }
  555. // CreateSurfaceEx callback must exist for DX7 or greater drivers
  556. if (!peDdGlobal->Miscellaneous2CallBacks.CreateSurfaceEx)
  557. {
  558. D3dCleanup(peDdGlobal, &fsState);
  559. goto Exit_CreateContext;
  560. }
  561. dccd.lpDDLcl = peDdLocal;
  562. dccd.lpDDS = dsurf[0].pLcl;
  563. dccd.lpDDSZ = dsurf[1].pLcl;
  564. if (peDdGlobal->D3dCallBacks.ContextCreate)
  565. {
  566. dwRet = peDdGlobal->D3dCallBacks.ContextCreate(&dccd);
  567. }
  568. else
  569. {
  570. WARNING("DxD3dContextCreate: ContextCreate callback not found");
  571. }
  572. if (dwRet == DDHAL_DRIVER_HANDLED &&
  573. dccd.ddrval == DD_OK)
  574. {
  575. // Create a wrapper for the handle and stash the DD global in it
  576. pdhctx->dwType = DNHO_CONTEXT;
  577. pdhctx->dwDriver = dccd.dwhContext;
  578. pdhctx->peDdGlobal = peDdGlobal;
  579. pdhctx->peDdLocal = peDdLocal;
  580. pdhctx->hSurfColor = hSurfColor;
  581. pdhctx->hSurfZ = hSurfZ;
  582. pdhctx->hBufSecure = hBufSecure;
  583. // Save the real pointer for freeing and return an aligned pointer
  584. // rather than the raw pointer.
  585. pdhctx->pvBufferAlloc = pvBuffer;
  586. pvBufRet = (PVOID)(((ULONG_PTR)pvBuffer+DP_BUFFER_ALIGN-1) &
  587. ~(DP_BUFFER_ALIGN-1));
  588. pdhctx->pvBufferAligned = pvBufRet;
  589. pdhctx->cjBuffer = (ULONG)cjBuffer;
  590. // Subtract off any space used for alignment.
  591. cjBuffer -= (DWORD)((ULONG_PTR)pvBufRet-(ULONG_PTR)pvBuffer);
  592. // Save interface number
  593. pdhctx->Interface = Interface;
  594. // Null these values to deactivate cleanup code.
  595. hBufSecure = NULL;
  596. pvBuffer = NULL;
  597. hCleanup = NULL;
  598. dccd.dwhContext = (ULONG_PTR)pdhctx->hHmgr;
  599. /* Add reference to DirectDraw driver instance so that it won't
  600. go away during dynamic mode changes, until the object is
  601. deleted. */
  602. vDdIncrementReferenceCount(pdhctx->peDdGlobal);
  603. }
  604. // We're done with pdhctx so unlock it
  605. DEC_EXCLUSIVE_REF_CNT(pdhctx);
  606. D3dCleanup(peDdGlobal, &fsState);
  607. __try
  608. {
  609. pdccd->dwhContext = dccd.dwhContext;
  610. pdccd->ddrval = dccd.ddrval;
  611. pdcci->pvBuffer = pvBufRet;
  612. pdcci->cjBuffer = (ULONG)cjBuffer;
  613. }
  614. __except(EXCEPTION_EXECUTE_HANDLER)
  615. {
  616. WARNING("DxD3dContextCreate unable to write back arguments");
  617. /* This is an unlikely thing to occur so we don't bother cleaning
  618. up the handle here. It will be cleaned up by the process
  619. termination handle cleanup. */
  620. dwRet = DDHAL_DRIVER_NOTHANDLED;
  621. }
  622. Exit_CreateContext:
  623. CLEANUP_D3DSURFACE(dsurf, 2);
  624. if (hBufSecure != NULL)
  625. {
  626. MmUnsecureVirtualMemory(hBufSecure);
  627. }
  628. if (pvBuffer != NULL)
  629. {
  630. // cjBuffer has to be zero to free memory.
  631. cjBuffer = 0;
  632. ZwFreeVirtualMemory(NtCurrentProcess(), &pvBuffer, &cjBuffer,
  633. MEM_RELEASE);
  634. }
  635. if (hCleanup != NULL)
  636. {
  637. DdHmgFree((HDD_OBJ)hCleanup);
  638. }
  639. return dwRet;
  640. }
  641. /******************************Public*Routine******************************\
  642. *
  643. * DxD3dContextDestroy
  644. *
  645. * History:
  646. * Tue Jun 04 13:08:43 1996 -by- Drew Bliss [drewb]
  647. * Created
  648. *
  649. \**************************************************************************/
  650. D3D_DELETE_HANDLE(Context, CONTEXT, dwhContext)
  651. /******************************Public*Routine******************************\
  652. *
  653. * DxD3dContextDestroyAll
  654. *
  655. * History:
  656. * Tue Jun 04 13:09:04 1996 -by- Drew Bliss [drewb]
  657. * Created
  658. *
  659. \**************************************************************************/
  660. DWORD APIENTRY
  661. DxD3dContextDestroyAll(LPD3DNTHAL_CONTEXTDESTROYALLDATA pdcdad)
  662. {
  663. DWORD dwRet;
  664. D3D_ENTRY("DxD3dContextDestroyAll");
  665. __try
  666. {
  667. ProbeForWrite(pdcdad, sizeof(D3DNTHAL_CONTEXTDESTROYALLDATA),
  668. sizeof(DWORD));
  669. }
  670. __except(EXCEPTION_EXECUTE_HANDLER)
  671. {
  672. WARNING("DxD3dContextDestroyAll unable to access argument");
  673. return DDHAL_DRIVER_NOTHANDLED;
  674. }
  675. // Having the context wrappers be handle-based should
  676. // provide automatic process cleanup of driver contexts
  677. // If this function does need to be passed to the driver then
  678. // some way to get the proper DD global will need to be found
  679. // I don't think it's necessary, though
  680. dwRet = DDHAL_DRIVER_NOTHANDLED;
  681. __try
  682. {
  683. pdcdad->ddrval = DDERR_GENERIC;
  684. }
  685. __except(EXCEPTION_EXECUTE_HANDLER)
  686. {
  687. WARNING("DxD3dContextDestroyAll unable to write back arguments");
  688. }
  689. return dwRet;
  690. }
  691. /******************************Public*Routine******************************\
  692. *
  693. * DxD3dDrawPrimitives2
  694. *
  695. * History:
  696. * Fri Jun 14 11:56:53 1996 -by- Drew Bliss [drewb]
  697. * Created
  698. *
  699. \**************************************************************************/
  700. DWORD APIENTRY
  701. DxD3dDrawPrimitives2(HANDLE hCmdBuf, HANDLE hVBuf,
  702. LPD3DNTHAL_DRAWPRIMITIVES2DATA pded,
  703. FLATPTR* pfpVidMemCmd,
  704. DWORD* pdwSizeCmd,
  705. FLATPTR* pfpVidMemVtx,
  706. DWORD* pdwSizeVtx)
  707. {
  708. D3DNTHAL_DRAWPRIMITIVES2DATA ded;
  709. KFLOATING_SAVE fsState;
  710. DWORD dwRet;
  711. D3D_SURFACE dsurf[4];
  712. HANDLE hSecure = NULL;
  713. D3DNTHAL_CONTEXT* pdhctx = NULL;
  714. D3D_ENTRY("DxD3dDrawPrimitives2");
  715. dwRet = DDHAL_DRIVER_NOTHANDLED;
  716. __try
  717. {
  718. //
  719. // ProbeForRead and ProbeForWrite are fairly expensive. Moved the write probe
  720. // to the bottom but we could also do a ProbeForWriteStructure here if the
  721. // error checking needs to be the exact same semantics.
  722. //
  723. ded = ProbeAndReadStructure(pded, D3DNTHAL_DRAWPRIMITIVES2DATA);
  724. }
  725. __except(EXCEPTION_EXECUTE_HANDLER)
  726. {
  727. WARNING("DxD3dDrawPrimitives2 unable to access argument");
  728. return dwRet;
  729. }
  730. // Initialize surface array.
  731. INIT_D3DSURFACE(dsurf, 4);
  732. DWORD Length = ded.dwVertexLength*ded.dwVertexSize;
  733. // Validate and secure user-mode memory if it is a user
  734. // allocated buffer instead of a ddraw surface
  735. if (ded.dwFlags & D3DNTHALDP2_USERMEMVERTICES)
  736. {
  737. // !!Assert here that hVBuf is NULL
  738. ASSERTGDI(hVBuf == NULL,
  739. "User allocated memory, hVBuf should be NULL\n");
  740. if ((Length > 0) && (ded.lpVertices != NULL))
  741. {
  742. LPVOID Address = (LPVOID) ((LPBYTE)ded.lpVertices +
  743. ded.dwVertexOffset);
  744. // Secure user-mode data.
  745. __try
  746. {
  747. ProbeForRead(Address, Length, sizeof(BYTE));
  748. }
  749. __except(EXCEPTION_EXECUTE_HANDLER)
  750. {
  751. WARNING("DxD3dDrawPrimives2 fail to secure the vertex buffer");
  752. goto Exit_DP2;
  753. }
  754. hSecure = MmSecureVirtualMemory(Address, Length, PAGE_READONLY);
  755. if (hSecure == NULL)
  756. {
  757. goto Exit_DP2;
  758. }
  759. dsurf[0].h = hCmdBuf;
  760. dsurf[0].bOptional = FALSE;
  761. DdHmgAcquireHmgrSemaphore(); // will be released at D3dLockContext();
  762. if (!D3dLockSurfaces(1, dsurf))
  763. {
  764. DdHmgReleaseHmgrSemaphore();
  765. goto Exit_DP2;
  766. }
  767. ded.lpDDCommands = dsurf[0].pLcl;
  768. }
  769. else
  770. {
  771. goto Exit_DP2;
  772. }
  773. }
  774. else
  775. {
  776. dsurf[0].h = hCmdBuf;
  777. dsurf[0].bOptional = FALSE;
  778. dsurf[1].h = hVBuf;
  779. dsurf[1].bOptional = FALSE;
  780. DdHmgAcquireHmgrSemaphore(); // will be released at D3dLockContext();
  781. if (!D3dLockSurfaces(2, dsurf))
  782. {
  783. DdHmgReleaseHmgrSemaphore();
  784. goto Exit_DP2;
  785. }
  786. ded.lpDDCommands = dsurf[0].pLcl;
  787. ded.lpDDVertex = dsurf[1].pLcl;
  788. // Make sure given buffer size is smaller than the actual surface size.
  789. if (dsurf[1].peSurf && ded.dwVertexSize)
  790. {
  791. DWORD dwSurfaceSize = dsurf[1].peSurf->lPitch;
  792. if (Length > dwSurfaceSize)
  793. {
  794. WARNING("DxD3dDrawPrimitive2 d3d.dwVertexLength is bigger than surface, trim it!!");
  795. ded.dwVertexLength = dwSurfaceSize / ded.dwVertexSize;
  796. }
  797. }
  798. }
  799. pdhctx = D3dLockContext(&fsState, &ded.dwhContext);
  800. if (pdhctx == NULL)
  801. {
  802. goto Exit_DP2;
  803. }
  804. // Validate that the lpdwRStates pointer is the same as the one allocated
  805. // by the kernel during context create. The D3d runtime uses this pointer
  806. // to receive state information from the driver.
  807. if (ded.lpdwRStates != pdhctx->pvBufferAligned)
  808. {
  809. goto Exit_DP2;
  810. }
  811. if ((pdhctx->peDdGlobal->bSuspended) ||
  812. ((pdhctx->peDdLocal->cSurface != pdhctx->peDdLocal->cActiveSurface) &&
  813. // We wish we could do this for all interfaces, but due to legacy app compat reasons, we can't.
  814. // We have noticed that apps such as Dungeon Keeper II and Final Fantasy lose surfaces and
  815. // never bother to restore them.
  816. pdhctx->Interface >= 4))
  817. {
  818. #if DBG
  819. if (pdhctx->peDdGlobal->bSuspended)
  820. {
  821. // WARNING("D3dDrawPrimitives2" Caller uses disabled device");
  822. }
  823. else if ((pdhctx->peDdLocal->cSurface != pdhctx->peDdLocal->cActiveSurface))
  824. {
  825. WARNING("D3dDrawPrimitives2: Cannot call driver when lost surfaces exist in the context");
  826. }
  827. #endif
  828. dwRet = DDHAL_DRIVER_HANDLED;
  829. ded.ddrval = DDERR_SURFACELOST;
  830. }
  831. else
  832. {
  833. if (pdhctx->peDdGlobal->D3dCallBacks3.DrawPrimitives2)
  834. {
  835. dwRet = pdhctx->peDdGlobal->D3dCallBacks3.DrawPrimitives2(&ded);
  836. }
  837. else
  838. {
  839. WARNING("DxD3dDrawPrimitives2: DrawPrimitives2 callback absent!");
  840. }
  841. }
  842. __try
  843. {
  844. if ((dwRet == DDHAL_DRIVER_HANDLED) && (ded.ddrval == DD_OK))
  845. {
  846. if (ded.dwFlags & D3DNTHALDP2_SWAPCOMMANDBUFFER)
  847. {
  848. ProbeAndWriteStructure( pfpVidMemCmd, ded.lpDDCommands->lpGbl->fpVidMem, FLATPTR);
  849. ProbeAndWriteStructure( pdwSizeCmd, ded.lpDDCommands->lpGbl->dwLinearSize, DWORD);
  850. }
  851. if ((ded.dwFlags & D3DNTHALDP2_SWAPVERTEXBUFFER) &&
  852. !(ded.dwFlags & D3DNTHALDP2_USERMEMVERTICES))
  853. {
  854. ProbeAndWriteStructure( pfpVidMemVtx, ded.lpDDVertex->lpGbl->fpVidMem, FLATPTR);
  855. ProbeAndWriteStructure( pdwSizeVtx, ded.lpDDVertex->lpGbl->dwLinearSize, DWORD);
  856. }
  857. }
  858. ProbeAndWriteUlong(&pded->dwErrorOffset, ded.dwErrorOffset);
  859. //
  860. // Should be cleaned up as HRESULT might not allways be a ULONG
  861. //
  862. ProbeAndWriteLong(&pded->ddrval, ded.ddrval);
  863. }
  864. __except(EXCEPTION_EXECUTE_HANDLER)
  865. {
  866. WARNING("DxD3dDrawPrimitives2 unable to write back arguments");
  867. dwRet = DDHAL_DRIVER_NOTHANDLED;
  868. }
  869. Exit_DP2:
  870. if (pdhctx)
  871. {
  872. D3dUnlockContext(pdhctx, &fsState);
  873. }
  874. CLEANUP_D3DSURFACE(dsurf, 4);
  875. if (hSecure)
  876. {
  877. MmUnsecureVirtualMemory(hSecure);
  878. }
  879. return dwRet;
  880. }
  881. /******************************Public*Routine******************************\
  882. *
  883. * DxD3dValidateTextureStageState
  884. *
  885. \**************************************************************************/
  886. #undef D3D_SIMPLE_WRITEBACK
  887. #define D3D_SIMPLE_WRITEBACK pdata->dwNumPasses = data.dwNumPasses;
  888. #undef D3D_SIMPLE_CALLBACKS
  889. #define D3D_SIMPLE_CALLBACKS D3dCallBacks3
  890. D3D_SIMPLE_COPY_WITH_CONTEXT(ValidateTextureStageState, VALIDATETEXTURESTAGESTATE)
  891. #undef D3D_SIMPLE_WRITEBACK
  892. #define D3D_SIMPLE_WRITEBACK
  893. #undef D3D_SIMPLE_CALLBACKS
  894. #define D3D_SIMPLE_CALLBACKS D3dCallBacks
  895. /******************************Public*Routine******************************\
  896. *
  897. * D3DParseUnknownCommand
  898. *
  899. \**************************************************************************/
  900. HRESULT CALLBACK D3DParseUnknownCommand (LPVOID lpvCommands,
  901. LPVOID *lplpvReturnedCommand)
  902. {
  903. LPD3DINSTRUCTION lpInstr = (LPD3DINSTRUCTION) lpvCommands;
  904. LPD3DPROCESSVERTICES data;
  905. int i;
  906. // Initialize the return address to the command's address
  907. *lplpvReturnedCommand = lpvCommands;
  908. switch (lpInstr->bOpcode)
  909. {
  910. case D3DOP_SPAN:
  911. *lplpvReturnedCommand = (LPVOID) ((LPBYTE)lpInstr +
  912. sizeof (D3DINSTRUCTION) +
  913. lpInstr->wCount *
  914. lpInstr->bSize);
  915. return DD_OK;
  916. case D3DNTDP2OP_VIEWPORTINFO:
  917. *lplpvReturnedCommand = (LPVOID) ((LPBYTE)lpInstr +
  918. sizeof(D3DINSTRUCTION) +
  919. lpInstr->wCount *
  920. sizeof(D3DNTHAL_DP2VIEWPORTINFO));
  921. return DD_OK;
  922. case D3DNTDP2OP_WINFO:
  923. *lplpvReturnedCommand = (LPVOID) ((LPBYTE)lpInstr +
  924. sizeof(D3DINSTRUCTION) +
  925. lpInstr->wCount *
  926. sizeof(D3DNTHAL_DP2WINFO));
  927. return DD_OK;
  928. case D3DOP_PROCESSVERTICES:
  929. case D3DOP_MATRIXLOAD:
  930. case D3DOP_MATRIXMULTIPLY:
  931. case D3DOP_STATETRANSFORM:
  932. case D3DOP_STATELIGHT:
  933. case D3DOP_TEXTURELOAD:
  934. case D3DOP_BRANCHFORWARD:
  935. case D3DOP_SETSTATUS:
  936. case D3DOP_EXIT:
  937. return D3DNTERR_COMMAND_UNPARSED;
  938. default:
  939. return DDERR_GENERIC;
  940. }
  941. }
  942. /******************************Public*Routine******************************\
  943. *
  944. * DxDdGetDriverState
  945. *
  946. \**************************************************************************/
  947. DWORD APIENTRY
  948. DxDdGetDriverState(PDD_GETDRIVERSTATEDATA pdata)
  949. {
  950. DD_GETDRIVERSTATEDATA data;
  951. KFLOATING_SAVE fsState;
  952. DWORD dwRet;
  953. D3DNTHAL_CONTEXT* pdhctx;
  954. HANDLE hSecure;
  955. D3D_ENTRY("DxDdGetDriverState");
  956. dwRet = DDHAL_DRIVER_NOTHANDLED;
  957. __try
  958. {
  959. data = CAPTURE_RW_STRUCT(pdata, DD_GETDRIVERSTATEDATA);
  960. }
  961. __except(EXCEPTION_EXECUTE_HANDLER)
  962. {
  963. WARNING("DxDdGetDriverState unable to access argument");
  964. return dwRet;
  965. }
  966. if (data.lpdwStates == NULL)
  967. {
  968. WARNING("DxDdGetDriverState passed null lpdwStates");
  969. return dwRet;
  970. }
  971. // Secure the usermode memory passed down to collect state data
  972. hSecure = MmSecureVirtualMemory((LPVOID)data.lpdwStates, data.dwLength,
  973. PAGE_READONLY);
  974. if (hSecure == 0)
  975. {
  976. return dwRet;
  977. }
  978. DdHmgAcquireHmgrSemaphore(); // will be released inside D3dLockContext()
  979. pdhctx = D3dLockContext(&fsState, &data.dwhContext);
  980. if (pdhctx == NULL)
  981. {
  982. goto Exit_GDS;
  983. }
  984. // No additional validation is needed
  985. // Assuming that GetDriverState exists in all DX7+ drivers
  986. ASSERTGDI(pdhctx->peDdGlobal->Miscellaneous2CallBacks.GetDriverState != NULL,
  987. "DxDdGetDriverState is not present. It is not an optional callback\n");
  988. if (pdhctx->peDdGlobal->bSuspended)
  989. {
  990. data.ddRVal = DDERR_GENERIC;
  991. }
  992. else
  993. {
  994. if (pdhctx->peDdGlobal->Miscellaneous2CallBacks.GetDriverState)
  995. {
  996. dwRet = pdhctx->peDdGlobal->Miscellaneous2CallBacks.GetDriverState(&data);
  997. }
  998. else
  999. {
  1000. WARNING("DxD3dDrawPrimitives2: GetDriverState callback absent!");
  1001. }
  1002. }
  1003. D3dUnlockContext(pdhctx, &fsState);
  1004. __try
  1005. {
  1006. pdata->ddRVal = data.ddRVal;
  1007. }
  1008. __except(EXCEPTION_EXECUTE_HANDLER)
  1009. {
  1010. WARNING("DxDdGetDriverState unable to write back arguments");
  1011. }
  1012. Exit_GDS:
  1013. MmUnsecureVirtualMemory(hSecure);
  1014. return dwRet;
  1015. }