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.

3888 lines
132 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: dxapi.cxx
  3. *
  4. * Contains the public kernel-mode APIs for DirectX.
  5. *
  6. * All of the stuff that has to happen at raised IRQL happens here, because
  7. * win32k is entirely pageable.
  8. *
  9. * Created: 11-Apr-1997
  10. * Author: J. Andrew Goossen [andrewgo]
  11. *
  12. * Copyright (c) 1997 Microsoft Corporation
  13. *
  14. \**************************************************************************/
  15. #include "precomp.hxx"
  16. #if DBG
  17. #define RIPDX(x) { KdPrint((x)); DbgBreakPoint();}
  18. #define ASSERTDX(x, y) if (!(x)) RIPDX(y)
  19. #else
  20. #define RIPDX(x)
  21. #define ASSERTDX(x, y)
  22. #endif
  23. extern "C" {
  24. VOID
  25. APIENTRY
  26. DxIrqCallBack(
  27. DX_IRQDATA* pIrqData
  28. );
  29. NTSTATUS
  30. DriverEntry(
  31. PDRIVER_OBJECT DriverObject,
  32. PUNICODE_STRING RegistryPath
  33. );
  34. VOID
  35. APIENTRY
  36. DxGetVersionNumber(
  37. DWORD dwNotUsed,
  38. DDGETVERSIONNUMBER* pGetVersionNumber
  39. );
  40. BOOL
  41. bDxModifyPassiveEventList(
  42. EDD_DXDIRECTDRAW* peDxDirectDraw,
  43. BOOL bAdd,
  44. DWORD dwEvent,
  45. LPDD_NOTIFYCALLBACK pfnCallBack,
  46. PVOID pContext
  47. );
  48. DWORD
  49. dwDxRegisterEvent(
  50. DDREGISTERCALLBACK* pRegisterEvent,
  51. BOOL bRegister
  52. );
  53. VOID
  54. APIENTRY
  55. DxRegisterEvent(
  56. DDREGISTERCALLBACK* pRegisterEvent,
  57. DWORD* pdwRet
  58. );
  59. VOID
  60. APIENTRY
  61. DxUnregisterEvent(
  62. DDREGISTERCALLBACK* pRegisterEvent,
  63. DWORD* pdwRet
  64. );
  65. VOID
  66. APIENTRY
  67. DxOpenDirectDraw(
  68. DDOPENDIRECTDRAWIN* pOpenDirectDrawIn,
  69. DDOPENDIRECTDRAWOUT* pOpenDirectDrawOut
  70. );
  71. VOID
  72. APIENTRY
  73. DxApiInitialize(
  74. PFNDXAPIOPENDIRECTDRAW pfnOpenDirectDraw,
  75. PFNDXAPIOPENVIDEOPORT pfnOpenVideoPort,
  76. PFNDXAPIOPENSURFACE pfnOpenSurface,
  77. PFNDXAPICLOSEHANDLE pfnCloseHandle,
  78. PFNDXAPIGETKERNELCAPS pfnGetKernelCaps,
  79. PFNDXAPIOPENCAPTUREDEVICE pfnOpenCaptureDevice,
  80. PFNDXAPILOCKDEVICE pfnLockDevice,
  81. PFNDXAPIUNLOCKDEVICE pfnUnlockDevice
  82. );
  83. DWORD
  84. APIENTRY
  85. DxApi(
  86. DWORD iFunction,
  87. VOID* pInBuffer,
  88. DWORD cInBuffer,
  89. VOID* pOutBuffer,
  90. DWORD cOutBuffer
  91. );
  92. VOID
  93. APIENTRY
  94. DxAutoflipDpc(
  95. DWORD dwEvent,
  96. PVOID pContext,
  97. DWORD dwParam1,
  98. DWORD dwParam2
  99. );
  100. VOID
  101. APIENTRY
  102. DxAutoflipUpdate(
  103. EDD_DXVIDEOPORT* peDxVideoPort,
  104. EDD_DXSURFACE** apeDxSurfaceVideo,
  105. ULONG cSurfacesVideo,
  106. EDD_DXSURFACE** apeDxSurfaceVbi,
  107. ULONG cSurfacesVbi
  108. );
  109. VOID
  110. APIENTRY
  111. DxLoseObject(
  112. VOID* pvObject,
  113. LOTYPE loType
  114. );
  115. VOID
  116. APIENTRY
  117. DxEnableIRQ(
  118. EDD_DXVIDEOPORT* peDxVideoPort,
  119. BOOL bEnable
  120. );
  121. VOID
  122. APIENTRY
  123. DxUpdateCapture(
  124. EDD_DXVIDEOPORT* peDxVideoPort,
  125. EDD_DXCAPTURE* peDxCapture,
  126. BOOL bRemove
  127. );
  128. DWORD
  129. APIENTRY
  130. DxApiGetVersion(
  131. VOID
  132. );
  133. }; // end "extern "C"
  134. // Marke whatever we can as pageable:
  135. #if defined(ALLOC_PRAGMA)
  136. #pragma alloc_text(PAGE,DriverEntry)
  137. #pragma alloc_text(PAGE,DxGetVersionNumber)
  138. #pragma alloc_text(PAGE,bDxModifyPassiveEventList)
  139. #pragma alloc_text(PAGE,dwDxRegisterEvent)
  140. #pragma alloc_text(PAGE,DxRegisterEvent)
  141. #pragma alloc_text(PAGE,DxUnregisterEvent)
  142. #pragma alloc_text(PAGE,DxOpenDirectDraw)
  143. #pragma alloc_text(PAGE,DxApiInitialize)
  144. #pragma alloc_text(PAGE,DxApiGetVersion)
  145. #endif
  146. PFNDXAPIOPENDIRECTDRAW gpfnOpenDirectDraw;
  147. PFNDXAPILOCKDEVICE gpfnLockDevice;
  148. PFNDXAPIUNLOCKDEVICE gpfnUnlockDevice;
  149. /***************************************************************************\
  150. * NTSTATUS DriverEntry
  151. *
  152. * This routine is never actually called, but we need it to link.
  153. *
  154. \***************************************************************************/
  155. extern "C"
  156. NTSTATUS
  157. DriverEntry(
  158. PDRIVER_OBJECT DriverObject,
  159. PUNICODE_STRING RegistryPath
  160. )
  161. {
  162. return(STATUS_SUCCESS);
  163. }
  164. /******************************Public*Routine******************************\
  165. * DWORD DxGetVersionNumber
  166. *
  167. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  168. * Wrote it.
  169. \**************************************************************************/
  170. VOID
  171. APIENTRY
  172. DxGetVersionNumber(
  173. DWORD dwNotUsed,
  174. DDGETVERSIONNUMBER* pGetVersionNumber
  175. )
  176. {
  177. ASSERTDX(KeGetCurrentIrql() == PASSIVE_LEVEL,
  178. "DxGetVersionNumber: Call only at passive level (it's not pageable)");
  179. pGetVersionNumber->dwMajorVersion = DXAPI_MAJORVERSION;
  180. pGetVersionNumber->dwMinorVersion = DXAPI_MINORVERSION;
  181. pGetVersionNumber->ddRVal = DD_OK;
  182. }
  183. /******************************Public*Routine******************************\
  184. * VOID DxGetFieldNumber
  185. *
  186. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  187. * Wrote it.
  188. \**************************************************************************/
  189. VOID
  190. APIENTRY
  191. DxGetFieldNumber(
  192. DDGETFIELDNUMIN* pGetFieldNumIn,
  193. DDGETFIELDNUMOUT* pGetFieldNumOut
  194. )
  195. {
  196. DXOBJ* pDxObjDirectDraw;
  197. DXOBJ* pDxObjVideoPort;
  198. EDD_DXDIRECTDRAW* peDxDirectDraw;
  199. EDD_DXVIDEOPORT* peDxVideoPort;
  200. pGetFieldNumOut->ddRVal = DDERR_INVALIDPARAMS;
  201. if (pGetFieldNumIn == NULL)
  202. {
  203. return;
  204. }
  205. pDxObjDirectDraw = (DXOBJ*) pGetFieldNumIn->hDirectDraw;
  206. if (pDxObjDirectDraw != NULL)
  207. {
  208. peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
  209. pDxObjVideoPort = (DXOBJ*) pGetFieldNumIn->hVideoPort;
  210. if (pDxObjVideoPort != NULL)
  211. {
  212. peDxVideoPort = pDxObjVideoPort->peDxVideoPort;
  213. ASSERTDX(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW,
  214. "Invalid DirectDraw object");
  215. ASSERTDX(pDxObjVideoPort->iDxType == DXT_VIDEOPORT,
  216. "Invalid VideoPort object");
  217. ASSERTDX(peDxDirectDraw == peDxVideoPort->peDxDirectDraw,
  218. "VideoPort and DirectDraw objects don't match");
  219. if (peDxVideoPort->peDxDirectDraw->dwIRQCaps & DDIRQ_VPORT0_VSYNC )
  220. {
  221. pGetFieldNumOut->dwFieldNum = peDxVideoPort->dwCurrentField;
  222. pGetFieldNumOut->ddRVal = DD_OK;
  223. }
  224. else
  225. {
  226. KdPrint(("DxGetFieldNumber: Device doesn't support an interrupt\n"));
  227. pGetFieldNumOut->ddRVal = DDERR_UNSUPPORTED;
  228. }
  229. }
  230. }
  231. }
  232. /******************************Public*Routine******************************\
  233. * VOID DxSetFieldNumber
  234. *
  235. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  236. * Wrote it.
  237. \**************************************************************************/
  238. VOID
  239. APIENTRY
  240. DxSetFieldNumber(
  241. DDSETFIELDNUM* pSetFieldNum,
  242. DWORD* pdwRet
  243. )
  244. {
  245. DXOBJ* pDxObjDirectDraw;
  246. DXOBJ* pDxObjVideoPort;
  247. EDD_DXDIRECTDRAW* peDxDirectDraw;
  248. EDD_DXVIDEOPORT* peDxVideoPort;
  249. *pdwRet = DDERR_INVALIDPARAMS;
  250. if (pSetFieldNum == NULL)
  251. {
  252. return;
  253. }
  254. pDxObjDirectDraw = (DXOBJ*) pSetFieldNum->hDirectDraw;
  255. if (pDxObjDirectDraw != NULL)
  256. {
  257. peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
  258. pDxObjVideoPort = (DXOBJ*) pSetFieldNum->hVideoPort;
  259. if (pDxObjVideoPort != NULL)
  260. {
  261. peDxVideoPort = pDxObjVideoPort->peDxVideoPort;
  262. ASSERTDX(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW,
  263. "Invalid DirectDraw object");
  264. ASSERTDX(pDxObjVideoPort->iDxType == DXT_VIDEOPORT,
  265. "Invalid VideoPort object");
  266. ASSERTDX(peDxDirectDraw == peDxVideoPort->peDxDirectDraw,
  267. "VideoPort and DirectDraw objects don't match");
  268. if (peDxVideoPort->peDxDirectDraw->dwIRQCaps & DDIRQ_VPORT0_VSYNC )
  269. {
  270. peDxVideoPort->dwCurrentField = pSetFieldNum->dwFieldNum;
  271. *pdwRet = DD_OK;
  272. }
  273. else
  274. {
  275. KdPrint(("DxSetFieldNumber: Device doesn't support an interrupt\n"));
  276. *pdwRet = DDERR_UNSUPPORTED;
  277. }
  278. }
  279. }
  280. }
  281. /******************************Public*Routine******************************\
  282. * VOID DxSetSkipPattern
  283. *
  284. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  285. * Wrote it.
  286. \**************************************************************************/
  287. VOID
  288. APIENTRY
  289. DxSetSkipPattern(
  290. DDSETSKIPFIELD* pSetSkipPattern,
  291. DWORD* pdwRet
  292. )
  293. {
  294. DXOBJ* pDxObjDirectDraw;
  295. DXOBJ* pDxObjVideoPort;
  296. EDD_DXDIRECTDRAW* peDxDirectDraw;
  297. EDD_DXVIDEOPORT* peDxVideoPort;
  298. KIRQL OldIrql;
  299. DWORD dwStartField;
  300. *pdwRet = DDERR_INVALIDPARAMS;
  301. if (pSetSkipPattern == NULL)
  302. {
  303. return;
  304. }
  305. pDxObjDirectDraw = (DXOBJ*) pSetSkipPattern->hDirectDraw;
  306. if (pDxObjDirectDraw != NULL)
  307. {
  308. peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
  309. pDxObjVideoPort = (DXOBJ*) pSetSkipPattern->hVideoPort;
  310. if (pDxObjVideoPort != NULL)
  311. {
  312. peDxVideoPort = pDxObjVideoPort->peDxVideoPort;
  313. ASSERTDX(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW,
  314. "Invalid DirectDraw object");
  315. ASSERTDX(pDxObjVideoPort->iDxType == DXT_VIDEOPORT,
  316. "Invalid VideoPort object");
  317. ASSERTDX(peDxDirectDraw == peDxVideoPort->peDxDirectDraw,
  318. "VideoPort and DirectDraw objects don't match");
  319. // Acquire the spinlock while we muck around
  320. KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
  321. // We assume that we are called during the VSYNC callback notification
  322. // so all that we do is store the value and do the actual skipping
  323. // during the AutoflipDpc call.
  324. dwStartField = pSetSkipPattern->dwStartField;
  325. if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_SKIP_SET )
  326. {
  327. if( peDxVideoPort->dwFieldToSkip > dwStartField )
  328. {
  329. peDxVideoPort->dwNextFieldToSkip = peDxVideoPort->dwFieldToSkip;
  330. peDxVideoPort->dwFieldToSkip = dwStartField;
  331. peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_NEXT_SKIP_SET;
  332. }
  333. else if ( dwStartField != peDxVideoPort->dwFieldToSkip )
  334. {
  335. peDxVideoPort->dwFieldToSkip = dwStartField;
  336. peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_NEXT_SKIP_SET;
  337. }
  338. }
  339. else
  340. {
  341. peDxVideoPort->dwFieldToSkip = dwStartField;
  342. peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_SKIP_SET;
  343. }
  344. KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
  345. *pdwRet = DX_OK;
  346. }
  347. }
  348. }
  349. /******************************Public*Routine******************************\
  350. * VOID EffectStateChange
  351. *
  352. * 09-Jan-1998 -by- Scott MacDonald [smac]
  353. * Wrote it.
  354. \**************************************************************************/
  355. VOID EffectStateChange( EDD_DXVIDEOPORT* peDxVideoPort,
  356. EDD_DXSURFACE* peDxSurface, DWORD dwNewState )
  357. {
  358. EDD_DXDIRECTDRAW* peDxDirectDraw;
  359. DDSETSTATEININFO ddStateInInfo;
  360. DDSETSTATEOUTINFO ddStateOutInfo;
  361. DWORD dwOldFlags;
  362. DWORD dwOldVPFlags;
  363. DWORD ddRVal;
  364. DWORD i;
  365. DWORD dwRet;
  366. dwOldVPFlags = 0;
  367. if( peDxVideoPort != NULL )
  368. {
  369. peDxVideoPort->dwSetStateState = 0;
  370. peDxSurface = peDxVideoPort->apeDxSurfaceVideo[0];
  371. dwOldVPFlags = peDxVideoPort->dwVPFlags;
  372. if( dwNewState & DDSTATE_SKIPEVENFIELDS )
  373. {
  374. peDxVideoPort->dwVPFlags |= DDVP_SKIPEVENFIELDS;
  375. }
  376. else
  377. {
  378. peDxVideoPort->dwVPFlags &= ~DDVP_SKIPEVENFIELDS;
  379. }
  380. }
  381. if( peDxSurface != NULL )
  382. {
  383. dwOldFlags = peDxSurface->dwOverlayFlags;
  384. if( dwNewState & DDSTATE_BOB )
  385. {
  386. peDxSurface->dwOverlayFlags |= DDOVER_BOB;
  387. }
  388. else if( dwNewState & ( DDSTATE_WEAVE | DDSTATE_SKIPEVENFIELDS ) )
  389. {
  390. peDxSurface->dwOverlayFlags &= ~DDOVER_BOB;
  391. }
  392. peDxDirectDraw = peDxSurface->peDxDirectDraw;
  393. ddStateInInfo.lpSurfaceData = peDxSurface;
  394. ddStateInInfo.lpVideoPortData = peDxVideoPort;
  395. ddStateOutInfo.bSoftwareAutoflip = 0;
  396. dwRet = DDERR_UNSUPPORTED;
  397. if (peDxDirectDraw->DxApiInterface.DxSetState != NULL)
  398. {
  399. dwRet = peDxDirectDraw->DxApiInterface.DxSetState(
  400. peDxDirectDraw->HwDeviceExtension,
  401. &ddStateInInfo,
  402. &ddStateOutInfo);
  403. }
  404. if( dwRet != DD_OK )
  405. {
  406. peDxSurface->dwOverlayFlags = dwOldFlags;
  407. if( peDxVideoPort != NULL )
  408. {
  409. peDxVideoPort->dwVPFlags = dwOldVPFlags;
  410. }
  411. }
  412. peDxSurface->flFlags |= DD_DXSURFACE_FLAG_STATE_SET;
  413. if( peDxVideoPort != NULL )
  414. {
  415. if( peDxSurface->dwOverlayFlags & DDOVER_BOB )
  416. {
  417. peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_BOB;
  418. }
  419. else
  420. {
  421. peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_BOB;
  422. }
  423. // Do they want to switch from hardware autoflipping to
  424. // software autoflipping?
  425. if( ( ddStateOutInfo.bSoftwareAutoflip ) &&
  426. ( peDxVideoPort->dwVPFlags & DDVP_AUTOFLIP ) &&
  427. !( peDxVideoPort->flFlags & (DD_DXVIDEOPORT_FLAG_AUTOFLIP|DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI)))
  428. {
  429. if( peDxVideoPort->cAutoflipVideo > 0 )
  430. {
  431. peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_AUTOFLIP;
  432. }
  433. if( peDxVideoPort->cAutoflipVbi > 0 )
  434. {
  435. peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI;
  436. }
  437. if( ddStateOutInfo.dwSurfaceIndex >= peDxVideoPort->cAutoflipVideo )
  438. {
  439. peDxVideoPort->iCurrentVideo = 0;
  440. }
  441. else
  442. {
  443. peDxVideoPort->iCurrentVideo = ddStateOutInfo.dwSurfaceIndex;
  444. }
  445. if( ddStateOutInfo.dwVBISurfaceIndex >= peDxVideoPort->cAutoflipVbi )
  446. {
  447. peDxVideoPort->iCurrentVbi = 0;
  448. }
  449. else
  450. {
  451. peDxVideoPort->iCurrentVbi = ddStateOutInfo.dwVBISurfaceIndex;
  452. }
  453. }
  454. for( i = 0; i < peDxVideoPort->iCurrentVideo; i++ )
  455. {
  456. peDxSurface = peDxVideoPort->apeDxSurfaceVideo[i];
  457. peDxSurface->flFlags &= ~(DD_DXSURFACE_FLAG_STATE_BOB|DD_DXSURFACE_FLAG_STATE_WEAVE);
  458. if( dwNewState & DDSTATE_BOB )
  459. {
  460. peDxSurface->dwOverlayFlags |= DDOVER_BOB;
  461. peDxSurface->flFlags |= DD_DXSURFACE_FLAG_STATE_BOB;
  462. }
  463. else if( dwNewState & ( DDSTATE_WEAVE | DDSTATE_SKIPEVENFIELDS ) )
  464. {
  465. peDxSurface->dwOverlayFlags &= ~DDOVER_BOB;
  466. if( dwNewState == DDSTATE_WEAVE )
  467. {
  468. peDxSurface->flFlags |= DD_DXSURFACE_FLAG_STATE_WEAVE;
  469. }
  470. }
  471. peDxSurface->flFlags |= DD_DXSURFACE_FLAG_STATE_SET;
  472. }
  473. }
  474. }
  475. }
  476. /******************************Public*Routine******************************\
  477. * VOID DxGetSurfaceState
  478. *
  479. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  480. * Wrote it.
  481. \**************************************************************************/
  482. VOID
  483. APIENTRY
  484. DxGetSurfaceState(
  485. DDGETSURFACESTATEIN* pGetSurfaceStateIn,
  486. DDGETSURFACESTATEOUT* pGetSurfaceStateOut
  487. )
  488. {
  489. DXOBJ* pDxObjDirectDraw;
  490. DXOBJ* pDxObjSurface;
  491. EDD_DXDIRECTDRAW* peDxDirectDraw;
  492. EDD_DXVIDEOPORT* peDxVideoPort;
  493. EDD_DXSURFACE* peDxSurface;
  494. pGetSurfaceStateOut->ddRVal = DDERR_INVALIDPARAMS;
  495. if (pGetSurfaceStateIn == NULL)
  496. {
  497. return;
  498. }
  499. pDxObjDirectDraw = (DXOBJ*) pGetSurfaceStateIn->hDirectDraw;
  500. pDxObjSurface = (DXOBJ*) pGetSurfaceStateIn->hSurface;
  501. if ((pDxObjDirectDraw != NULL) &&
  502. (pDxObjSurface != NULL))
  503. {
  504. peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
  505. peDxSurface = pDxObjSurface->peDxSurface;
  506. ASSERTDX(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW,
  507. "Invalid DirectDraw object");
  508. ASSERTDX(pDxObjSurface->iDxType == DXT_SURFACE,
  509. "Invalid Surface object");
  510. ASSERTDX(peDxDirectDraw == peDxSurface->peDxDirectDraw,
  511. "Surface and DirectDraw objects don't match");
  512. ASSERTDX(peDxSurface->ddsCaps & DDSCAPS_OVERLAY,
  513. "Surface is not an overlay surface");
  514. // Fill in the available caps
  515. pGetSurfaceStateOut->dwStateCaps = 0;
  516. pGetSurfaceStateOut->dwStateStatus = 0;
  517. peDxVideoPort = peDxSurface->peDxVideoPort;
  518. // If the DDOVER_OVERRIDEBOBWEAVE flag was set, the status is equal
  519. // to the caps.
  520. if( peDxSurface->dwOverlayFlags & DDOVER_OVERRIDEBOBWEAVE )
  521. {
  522. if( peDxSurface->dwOverlayFlags & DDOVER_BOB )
  523. {
  524. pGetSurfaceStateOut->dwStateStatus |= DDSTATE_BOB;
  525. pGetSurfaceStateOut->dwStateCaps |= DDSTATE_BOB;
  526. }
  527. else if( ( peDxVideoPort != NULL ) &&
  528. ( peDxVideoPort->dwVPFlags & (DDVP_SKIPEVENFIELDS|DDVP_SKIPODDFIELDS) ) )
  529. {
  530. pGetSurfaceStateOut->dwStateStatus |= DDSTATE_SKIPEVENFIELDS;
  531. pGetSurfaceStateOut->dwStateCaps |= DDSTATE_SKIPEVENFIELDS;
  532. }
  533. else if( ( peDxVideoPort != NULL ) &&
  534. ( peDxVideoPort->dwVPFlags & DDVP_INTERLEAVE ) )
  535. {
  536. pGetSurfaceStateOut->dwStateStatus |= DDSTATE_WEAVE;
  537. pGetSurfaceStateOut->dwStateCaps |= DDSTATE_WEAVE;
  538. }
  539. else if( ( peDxVideoPort == NULL ) &&
  540. ( peDxSurface->dwOverlayFlags & DDOVER_INTERLEAVED ) )
  541. {
  542. pGetSurfaceStateOut->dwStateStatus |= DDSTATE_WEAVE;
  543. pGetSurfaceStateOut->dwStateCaps |= DDSTATE_WEAVE;
  544. }
  545. }
  546. else
  547. {
  548. // The status is different from the caps
  549. if( ( peDxVideoPort != NULL ) &&
  550. ( peDxVideoPort->dwVPFlags & (DDVP_SKIPEVENFIELDS|DDVP_SKIPODDFIELDS) ) )
  551. {
  552. pGetSurfaceStateOut->dwStateStatus |= DDSTATE_SKIPEVENFIELDS;
  553. }
  554. else if( peDxSurface->dwOverlayFlags & DDOVER_BOB )
  555. {
  556. pGetSurfaceStateOut->dwStateStatus |= DDSTATE_BOB;
  557. }
  558. if( ( ( peDxVideoPort != NULL ) &&
  559. ( peDxVideoPort->dwVPFlags & DDVP_INTERLEAVE ) ) ||
  560. ( ( peDxVideoPort == NULL ) &&
  561. ( peDxSurface->dwOverlayFlags & DDOVER_INTERLEAVED ) ) )
  562. {
  563. pGetSurfaceStateOut->dwStateCaps |= DDSTATE_WEAVE;
  564. if( peDxSurface->flFlags & DD_DXSURFACE_FLAG_CAN_BOB_INTERLEAVED )
  565. {
  566. pGetSurfaceStateOut->dwStateCaps |= DDSTATE_BOB;
  567. }
  568. if( pGetSurfaceStateOut->dwStateStatus == 0 )
  569. {
  570. pGetSurfaceStateOut->dwStateStatus |= DDSTATE_WEAVE;
  571. }
  572. }
  573. else if( peDxSurface->flFlags & DD_DXSURFACE_FLAG_CAN_BOB_NONINTERLEAVED )
  574. {
  575. pGetSurfaceStateOut->dwStateCaps |= DDSTATE_BOB;
  576. }
  577. if( peDxVideoPort != NULL )
  578. {
  579. pGetSurfaceStateOut->dwStateCaps |= DDSTATE_SKIPEVENFIELDS;
  580. }
  581. }
  582. // Notify the client that the state was explicity set by a
  583. // kernel mode client.
  584. if( peDxSurface->flFlags & DD_DXSURFACE_FLAG_STATE_SET )
  585. {
  586. pGetSurfaceStateOut->dwStateStatus |= DDSTATE_EXPLICITLY_SET;
  587. }
  588. // Tell if software autoflipping vs. hardware autofliping. This
  589. // is mostly for DDraw's benefit.
  590. if( ( peDxVideoPort != NULL ) && ( peDxVideoPort->bSoftwareAutoflip ) )
  591. {
  592. pGetSurfaceStateOut->dwStateStatus |= DDSTATE_SOFTWARE_AUTOFLIP;
  593. }
  594. pGetSurfaceStateOut->ddRVal = DD_OK;
  595. }
  596. }
  597. /******************************Public*Routine******************************\
  598. * VOID DxSetSurfaceState
  599. *
  600. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  601. * Wrote it.
  602. \**************************************************************************/
  603. VOID
  604. APIENTRY
  605. DxSetSurfaceState(
  606. DDSETSURFACESTATE* pSetSurfaceState,
  607. DWORD* pdwRet
  608. )
  609. {
  610. DWORD dwState;
  611. DXOBJ* pDxObjDirectDraw;
  612. DXOBJ* pDxObjSurface;
  613. EDD_DXDIRECTDRAW* peDxDirectDraw;
  614. EDD_DXVIDEOPORT* peDxVideoPort;
  615. EDD_DXSURFACE* peDxSurface;
  616. DDGETSURFACESTATEIN GetSurfaceStateIn;
  617. DDGETSURFACESTATEOUT GetSurfaceStateOut;
  618. DDSETSTATEININFO SetStateInInfo;
  619. DDSETSTATEOUTINFO SetStateOutInfo;
  620. DWORD iCurrentVideo;
  621. KIRQL OldIrql;
  622. DWORD dwRet;
  623. DWORD dwVPFlags;
  624. *pdwRet = dwRet = DDERR_INVALIDPARAMS;
  625. if (pSetSurfaceState == NULL)
  626. {
  627. return;
  628. }
  629. pDxObjDirectDraw = (DXOBJ*) pSetSurfaceState->hDirectDraw;
  630. pDxObjSurface = (DXOBJ*) pSetSurfaceState->hSurface;
  631. if ((pDxObjDirectDraw != NULL) &&
  632. (pDxObjSurface != NULL))
  633. {
  634. peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
  635. peDxSurface = pDxObjSurface->peDxSurface;
  636. GetSurfaceStateIn.hDirectDraw = pSetSurfaceState->hDirectDraw;
  637. GetSurfaceStateIn.hSurface = pSetSurfaceState->hSurface;
  638. DxGetSurfaceState(&GetSurfaceStateIn, &GetSurfaceStateOut);
  639. ASSERTDX(GetSurfaceStateOut.ddRVal == DD_OK,
  640. "DxSetSurfaceState: Didn't expect failure from DxGetSurfaceState");
  641. dwState = pSetSurfaceState->dwState;
  642. // Get the video port if one is associated with the surface
  643. if( peDxSurface->peDxVideoPort == NULL )
  644. {
  645. peDxVideoPort = NULL;
  646. dwVPFlags = 0;
  647. }
  648. else
  649. {
  650. peDxVideoPort = peDxSurface->peDxVideoPort;
  651. dwVPFlags = peDxVideoPort->dwVPFlags;
  652. }
  653. if ((dwState != DDSTATE_BOB) &&
  654. (dwState != DDSTATE_WEAVE) &&
  655. (dwState != DDSTATE_SKIPEVENFIELDS))
  656. {
  657. RIPDX("DxSetSurfaceState: Invalid dwState flags");
  658. }
  659. else if ((dwState & GetSurfaceStateOut.dwStateCaps) != dwState)
  660. {
  661. RIPDX("DxSetSurfaceState: State not supported");
  662. }
  663. else if ((dwState == DDSTATE_SKIPEVENFIELDS) && (peDxVideoPort == NULL ))
  664. {
  665. RIPDX("DxSetSurfaceState: Surface not attached to video port");
  666. }
  667. else if (((dwState & DDSTATE_BOB) &&
  668. (peDxSurface->dwOverlayFlags & DDOVER_BOB)) ||
  669. ((dwState & DDSTATE_WEAVE) &&
  670. !(peDxSurface->dwOverlayFlags & DDOVER_BOB) &&
  671. !(dwVPFlags & (DDVP_SKIPEVENFIELDS|DDVP_SKIPODDFIELDS))) ||
  672. ((dwState & DDSTATE_SKIPEVENFIELDS ) &&
  673. (dwVPFlags & (DDVP_SKIPEVENFIELDS|DDVP_SKIPODDFIELDS))))
  674. {
  675. // Don't do nothin, it's already in the requested state.
  676. dwRet = DD_OK;
  677. }
  678. else if (peDxDirectDraw->DxApiInterface.DxSetState != NULL)
  679. {
  680. // Acquire the spinlock while we muck around in the 'dwSetStateState'
  681. // and 'dwSetStateField' members, which are accessed by the videoport
  682. // DPC.
  683. KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
  684. if ((peDxDirectDraw->bLost) ||
  685. ((peDxVideoPort != NULL) && (peDxVideoPort->bLost)) ||
  686. (peDxSurface->bLost))
  687. {
  688. KdPrint(("DxSetSurfaceState: Objects are lost\n"));
  689. dwRet = DDERR_SURFACELOST;
  690. }
  691. // If they want it to happen for the next field or we are not
  692. // using a video port, call the mini port now; otherwise, we'll let
  693. // the IRQ logoic handle this later.
  694. else if ((pSetSurfaceState->dwStartField == 0) ||
  695. (peDxVideoPort == NULL) ||
  696. !(peDxVideoPort->bSoftwareAutoflip))
  697. {
  698. EffectStateChange( peDxVideoPort, peDxSurface, dwState );
  699. }
  700. else
  701. {
  702. peDxVideoPort->dwSetStateState = dwState;
  703. peDxVideoPort->dwSetStateField = pSetSurfaceState->dwStartField;
  704. peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_NEW_STATE;
  705. }
  706. KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
  707. dwRet = DD_OK;
  708. }
  709. if (peDxDirectDraw->DxApiInterface.DxSetState == NULL)
  710. {
  711. dwRet = DDERR_UNSUPPORTED;
  712. }
  713. *pdwRet = dwRet;
  714. }
  715. }
  716. /******************************Public*Routine******************************\
  717. * VOID DxLock
  718. *
  719. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  720. * Wrote it.
  721. \**************************************************************************/
  722. VOID
  723. APIENTRY
  724. DxLock(
  725. DDLOCKIN* pLockIn,
  726. DDLOCKOUT* pLockOut
  727. )
  728. {
  729. DWORD dwRet;
  730. DXOBJ* pDxObjDirectDraw;
  731. DXOBJ* pDxObjSurface;
  732. EDD_DXDIRECTDRAW* peDxDirectDraw;
  733. EDD_DXSURFACE* peDxSurface;
  734. DDLOCKININFO LockInInfo;
  735. DDLOCKOUTINFO LockOutInfo;
  736. KIRQL OldIrql;
  737. pLockOut->ddRVal = DDERR_INVALIDPARAMS;
  738. if (pLockIn == NULL)
  739. {
  740. return;
  741. }
  742. dwRet = DD_OK;
  743. pDxObjDirectDraw = (DXOBJ*) pLockIn->hDirectDraw;
  744. pDxObjSurface = (DXOBJ*) pLockIn->hSurface;
  745. if ((pDxObjDirectDraw != NULL) &&
  746. (pDxObjSurface != NULL))
  747. {
  748. peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
  749. peDxSurface = pDxObjSurface->peDxSurface;
  750. ASSERTDX(peDxDirectDraw == peDxSurface->peDxDirectDraw,
  751. "Surface and DirectDraw objects don't match");
  752. ASSERTDX(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW,
  753. "Invalid DirectDraw object");
  754. ASSERTDX(pDxObjSurface->iDxType == DXT_SURFACE,
  755. "Invalid surface object");
  756. LockInInfo.lpSurfaceData = peDxSurface;
  757. LockOutInfo.dwSurfacePtr = peDxSurface->fpLockPtr;
  758. // The display driver can set 'fpLockPtr' to NULL in its SyncSurfaceData
  759. // routine if it doesn't want to support a DXAPI lock.
  760. if (peDxSurface->fpLockPtr == NULL)
  761. {
  762. KdPrint(("DxLock: Video miniport doesn't support lock on this surface\n"));
  763. dwRet = DDERR_UNSUPPORTED;
  764. }
  765. else
  766. {
  767. // NOTE: The miniport should not wait for accelerator complete!
  768. if (peDxDirectDraw->DxApiInterface.DxLock)
  769. {
  770. KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
  771. if ((peDxDirectDraw->bLost) || (peDxSurface->bLost))
  772. {
  773. KdPrint(("DxLock: Objects are lost\n"));
  774. dwRet = DDERR_SURFACELOST;
  775. }
  776. else
  777. {
  778. dwRet = peDxDirectDraw->DxApiInterface.DxLock(
  779. peDxDirectDraw->HwDeviceExtension,
  780. &LockInInfo,
  781. &LockOutInfo);
  782. }
  783. KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
  784. if (dwRet != DD_OK)
  785. {
  786. KdPrint(("DxLock: Driver failed call\n"));
  787. // Pass the return code on down...
  788. }
  789. }
  790. pLockOut->lpSurface = (LPVOID) LockOutInfo.dwSurfacePtr;
  791. pLockOut->dwSurfHeight = peDxSurface->dwHeight;
  792. pLockOut->dwSurfWidth = peDxSurface->dwWidth;
  793. pLockOut->lSurfPitch = peDxSurface->lPitch;
  794. pLockOut->SurfaceCaps = peDxSurface->ddsCaps;
  795. pLockOut->dwFormatFlags = peDxSurface->dwFormatFlags;
  796. pLockOut->dwFormatFourCC = peDxSurface->dwFormatFourCC;
  797. pLockOut->dwFormatBitCount = peDxSurface->dwFormatBitCount;
  798. pLockOut->dwRBitMask = peDxSurface->dwRBitMask;
  799. pLockOut->dwGBitMask = peDxSurface->dwGBitMask;
  800. pLockOut->dwBBitMask = peDxSurface->dwBBitMask;
  801. }
  802. pLockOut->ddRVal = dwRet;
  803. }
  804. }
  805. /******************************Public*Routine******************************\
  806. * VOID DxFlipOverlay
  807. *
  808. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  809. * Wrote it.
  810. \**************************************************************************/
  811. VOID
  812. APIENTRY
  813. DxFlipOverlay(
  814. DDFLIPOVERLAY* pFlipOverlay,
  815. DWORD* pdwRet
  816. )
  817. {
  818. DWORD dwRet;
  819. DXOBJ* pDxObjDirectDraw;
  820. DXOBJ* pDxObjTarget;
  821. DXOBJ* pDxObjCurrent;
  822. EDD_DXDIRECTDRAW* peDxDirectDraw;
  823. EDD_DXSURFACE* peDxTarget;
  824. EDD_DXSURFACE* peDxCurrent;
  825. DDFLIPOVERLAYINFO FlipOverlayInfo;
  826. KIRQL OldIrql;
  827. *pdwRet = DDERR_INVALIDPARAMS;
  828. if (pFlipOverlay == NULL)
  829. {
  830. return;
  831. }
  832. dwRet = DDERR_UNSUPPORTED; // Assume failure
  833. pDxObjDirectDraw = (DXOBJ*) pFlipOverlay->hDirectDraw;
  834. pDxObjTarget = (DXOBJ*) pFlipOverlay->hTargetSurface;
  835. pDxObjCurrent = (DXOBJ*) pFlipOverlay->hCurrentSurface;
  836. if ((pDxObjDirectDraw != NULL) &&
  837. (pDxObjTarget != NULL) &&
  838. (pDxObjCurrent != NULL))
  839. {
  840. peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
  841. peDxTarget = pDxObjTarget->peDxSurface;
  842. peDxCurrent = pDxObjCurrent->peDxSurface;
  843. ASSERTDX(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW,
  844. "Invalid DirectDraw object");
  845. ASSERTDX(pDxObjTarget->iDxType == DXT_SURFACE,
  846. "Invalid target object");
  847. ASSERTDX(pDxObjCurrent->iDxType == DXT_SURFACE,
  848. "Invalid current object");
  849. ASSERTDX((peDxDirectDraw == peDxTarget->peDxDirectDraw) &&
  850. (peDxDirectDraw == peDxCurrent->peDxDirectDraw),
  851. "Surface and DirectDraw objects don't match");
  852. ASSERTDX((peDxCurrent->dwWidth == peDxTarget->dwWidth) &&
  853. (peDxCurrent->dwHeight == peDxTarget->dwHeight),
  854. "Surfaces are different sizes");
  855. if (!(peDxCurrent->ddsCaps & DDSCAPS_OVERLAY) ||
  856. (peDxCurrent->dwOverlayFlags & DDOVER_AUTOFLIP))
  857. {
  858. RIPDX("Invalid current overlay status");
  859. }
  860. else if (!(peDxTarget->ddsCaps & DDSCAPS_OVERLAY) ||
  861. (peDxTarget->dwOverlayFlags & DDOVER_AUTOFLIP))
  862. {
  863. RIPDX("Invalid target overlay status");
  864. }
  865. else
  866. {
  867. FlipOverlayInfo.lpCurrentSurface = peDxCurrent;
  868. FlipOverlayInfo.lpTargetSurface = peDxTarget;
  869. FlipOverlayInfo.dwFlags = pFlipOverlay->dwFlags;
  870. if (peDxDirectDraw->DxApiInterface.DxFlipOverlay)
  871. {
  872. KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
  873. if ((peDxDirectDraw->bLost) ||
  874. (peDxTarget->bLost) ||
  875. (peDxCurrent->bLost))
  876. {
  877. KdPrint(("DxFlipOverlay: Objects are lost\n"));
  878. dwRet = DDERR_SURFACELOST;
  879. }
  880. else
  881. {
  882. dwRet = peDxDirectDraw->DxApiInterface.DxFlipOverlay(
  883. peDxDirectDraw->HwDeviceExtension,
  884. &FlipOverlayInfo,
  885. NULL);
  886. }
  887. KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
  888. }
  889. if (dwRet != DD_OK)
  890. {
  891. KdPrint(("DxFlipOverlay: Driver failed call\n"));
  892. }
  893. }
  894. *pdwRet = dwRet;
  895. }
  896. }
  897. /******************************Public*Routine******************************\
  898. * VOID DxFlipVideoPort
  899. *
  900. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  901. * Wrote it.
  902. \**************************************************************************/
  903. VOID
  904. APIENTRY
  905. DxFlipVideoPort(
  906. DDFLIPVIDEOPORT* pFlipVideoPort,
  907. DWORD* pdwRet
  908. )
  909. {
  910. DWORD dwRet;
  911. DXOBJ* pDxObjDirectDraw;
  912. DXOBJ* pDxObjVideoPort;
  913. DXOBJ* pDxObjTarget;
  914. DXOBJ* pDxObjCurrent;
  915. EDD_DXDIRECTDRAW* peDxDirectDraw;
  916. EDD_DXVIDEOPORT* peDxVideoPort;
  917. EDD_DXSURFACE* peDxTarget;
  918. EDD_DXSURFACE* peDxCurrent;
  919. DDFLIPVIDEOPORTINFO FlipVideoPortInfo;
  920. KIRQL OldIrql;
  921. *pdwRet = DDERR_INVALIDPARAMS;
  922. if (pFlipVideoPort == NULL)
  923. {
  924. return;
  925. }
  926. dwRet = DDERR_UNSUPPORTED; // Assume failure
  927. pDxObjDirectDraw = (DXOBJ*) pFlipVideoPort->hDirectDraw;
  928. pDxObjVideoPort = (DXOBJ*) pFlipVideoPort->hVideoPort;
  929. pDxObjTarget = (DXOBJ*) pFlipVideoPort->hTargetSurface;
  930. pDxObjCurrent = (DXOBJ*) pFlipVideoPort->hCurrentSurface;
  931. if ((pDxObjDirectDraw != NULL) &&
  932. (pDxObjVideoPort != NULL) &&
  933. (pDxObjTarget != NULL) &&
  934. (pDxObjCurrent != NULL))
  935. {
  936. peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
  937. peDxVideoPort = pDxObjVideoPort->peDxVideoPort;
  938. peDxTarget = pDxObjTarget->peDxSurface;
  939. peDxCurrent = pDxObjCurrent->peDxSurface;
  940. ASSERTDX(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW,
  941. "Invalid DirectDraw object");
  942. ASSERTDX(pDxObjVideoPort->iDxType == DXT_VIDEOPORT,
  943. "Invalid VideoPort object");
  944. ASSERTDX(pDxObjTarget->iDxType == DXT_SURFACE,
  945. "Invalid target object");
  946. ASSERTDX(pDxObjCurrent->iDxType == DXT_SURFACE,
  947. "Invalid current object");
  948. ASSERTDX((peDxDirectDraw == peDxTarget->peDxDirectDraw) &&
  949. (peDxDirectDraw == peDxCurrent->peDxDirectDraw) &&
  950. (peDxDirectDraw == peDxVideoPort->peDxDirectDraw),
  951. "Surface, VideoPort, and DirectDraw objects don't match");
  952. ASSERTDX((peDxCurrent->dwWidth == peDxTarget->dwWidth) &&
  953. (peDxCurrent->dwHeight == peDxTarget->dwHeight),
  954. "Surfaces are different sizes");
  955. ASSERTDX((pFlipVideoPort->dwFlags == DDVPFLIP_VIDEO) ||
  956. (pFlipVideoPort->dwFlags == DDVPFLIP_VBI),
  957. "Invalid flags");
  958. ASSERTDX(!(peDxVideoPort->dwVPFlags & DDVP_AUTOFLIP),
  959. "Flip not available while autoflipping");
  960. FlipVideoPortInfo.lpVideoPortData = peDxVideoPort;
  961. FlipVideoPortInfo.lpCurrentSurface = peDxCurrent;
  962. FlipVideoPortInfo.lpTargetSurface = peDxTarget;
  963. FlipVideoPortInfo.dwFlipVPFlags = pFlipVideoPort->dwFlags;
  964. if (peDxDirectDraw->DxApiInterface.DxFlipVideoPort)
  965. {
  966. KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
  967. if ((peDxDirectDraw->bLost) ||
  968. (peDxVideoPort->bLost) ||
  969. (peDxTarget->bLost) ||
  970. (peDxCurrent->bLost))
  971. {
  972. KdPrint(("DxFlipVideoPort: Objects are lost\n"));
  973. dwRet = DDERR_SURFACELOST;
  974. }
  975. else
  976. {
  977. dwRet = peDxDirectDraw->DxApiInterface.DxFlipVideoPort(
  978. peDxDirectDraw->HwDeviceExtension,
  979. &FlipVideoPortInfo,
  980. NULL);
  981. }
  982. peDxCurrent->peDxVideoPort = NULL;
  983. peDxTarget->peDxVideoPort = peDxVideoPort;
  984. KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
  985. }
  986. if (dwRet != DD_OK)
  987. {
  988. KdPrint(("DxFlipVideoPort: Driver failed call\n"));
  989. }
  990. *pdwRet = dwRet;
  991. }
  992. }
  993. /******************************Public*Routine******************************\
  994. * VOID DxGetCurrentAutoflip
  995. *
  996. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  997. * Wrote it.
  998. \**************************************************************************/
  999. VOID
  1000. APIENTRY
  1001. DxGetCurrentAutoflip(
  1002. DDGETAUTOFLIPIN* pGetCurrentAutoflipIn,
  1003. DDGETAUTOFLIPOUT* pGetCurrentAutoflipOut
  1004. )
  1005. {
  1006. DWORD dwRet;
  1007. DXOBJ* pDxObjDirectDraw;
  1008. DXOBJ* pDxObjVideoPort;
  1009. DXOBJ* pDxObjTarget;
  1010. DXOBJ* pDxObjCurrent;
  1011. EDD_DXDIRECTDRAW* peDxDirectDraw;
  1012. EDD_DXVIDEOPORT* peDxVideoPort;
  1013. EDD_DXSURFACE* peDxTarget;
  1014. EDD_DXSURFACE* peDxCurrent;
  1015. DDGETPOLARITYININFO GetPolarityInInfo;
  1016. DDGETPOLARITYOUTINFO GetPolarityOutInfo;
  1017. DDGETCURRENTAUTOFLIPININFO GetCurrentAutoflipInInfo;
  1018. DDGETCURRENTAUTOFLIPOUTINFO GetCurrentAutoflipOutInfo;
  1019. KIRQL OldIrql;
  1020. DWORD dwVideo;
  1021. DWORD dwVBI;
  1022. BOOL bFlipping;
  1023. pGetCurrentAutoflipOut->ddRVal = DDERR_INVALIDPARAMS;
  1024. if (pGetCurrentAutoflipIn == NULL)
  1025. {
  1026. return;
  1027. }
  1028. dwRet = DDERR_UNSUPPORTED; // Assume failure
  1029. pDxObjDirectDraw = (DXOBJ*) pGetCurrentAutoflipIn->hDirectDraw;
  1030. pDxObjVideoPort = (DXOBJ*) pGetCurrentAutoflipIn->hVideoPort;
  1031. if ((pDxObjDirectDraw != NULL) &&
  1032. (pDxObjVideoPort != NULL))
  1033. {
  1034. peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
  1035. peDxVideoPort = pDxObjVideoPort->peDxVideoPort;
  1036. ASSERTDX(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW,
  1037. "Invalid DirectDraw object");
  1038. ASSERTDX(pDxObjVideoPort->iDxType == DXT_VIDEOPORT,
  1039. "Invalid VideoPort object");
  1040. ASSERTDX(peDxDirectDraw == peDxVideoPort->peDxDirectDraw,
  1041. "Surface, VideoPort, and DirectDraw objects don't match");
  1042. ASSERTDX(peDxVideoPort->dwVPFlags & DDVP_AUTOFLIP,
  1043. "Not currently autoflipping");
  1044. GetPolarityInInfo.lpVideoPortData = peDxVideoPort;
  1045. KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
  1046. if ((peDxDirectDraw->bLost) ||
  1047. (peDxVideoPort->bLost))
  1048. {
  1049. KdPrint(("DxGetCurrentAutoflip: Objects are lost\n"));
  1050. dwRet = DDERR_SURFACELOST;
  1051. }
  1052. else
  1053. {
  1054. dwRet = DDERR_UNSUPPORTED;
  1055. if (peDxDirectDraw->DxApiInterface.DxGetPolarity)
  1056. {
  1057. dwRet = peDxDirectDraw->DxApiInterface.DxGetPolarity(
  1058. peDxDirectDraw->HwDeviceExtension,
  1059. &GetPolarityInInfo,
  1060. &GetPolarityOutInfo);
  1061. }
  1062. if (dwRet != DD_OK)
  1063. {
  1064. KdPrint(("DxGetCurrentAutoflip: Driver failed GetPolarity\n"));
  1065. }
  1066. else
  1067. {
  1068. // Determine which field is currently receiving the data. If they
  1069. // are software autoflipping, I can do that myself; otherwise, I
  1070. // have to call the HAL
  1071. //
  1072. // When software autoflipping, there is an issue that if this
  1073. // function is called between the time that the IRQ occured
  1074. // and the time that the DPC ran, this function would return
  1075. // the wrong surface. Since fixing this requires that we do all
  1076. // of the work at IRQ time (bad), we can probably assume that
  1077. // this will always be the case since anybody using this
  1078. // function would be calling it during the IRQ callback. We
  1079. // will therefore work around it.
  1080. dwVideo = (DWORD) -1;
  1081. dwVBI = (DWORD) -1;
  1082. if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP )
  1083. {
  1084. dwVideo = peDxVideoPort->iCurrentVideo;
  1085. bFlipping = TRUE;
  1086. if( ( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_SKIP_SET ) &&
  1087. ( peDxVideoPort->dwFieldToSkip == 1 ) )
  1088. {
  1089. bFlipping = FALSE;
  1090. }
  1091. else if( !( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_SKIPPED_LAST ) &&
  1092. ( peDxVideoPort->dwVPFlags & DDVP_INTERLEAVE ) &&
  1093. !( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_FLIP_NEXT ) )
  1094. {
  1095. bFlipping = FALSE;
  1096. }
  1097. if( bFlipping )
  1098. {
  1099. if( ++dwVideo >= peDxVideoPort->cAutoflipVideo )
  1100. {
  1101. dwVideo = 0;
  1102. }
  1103. }
  1104. }
  1105. if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI )
  1106. {
  1107. dwVBI = peDxVideoPort->iCurrentVbi;
  1108. if( ( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_VBI_INTERLEAVED ) &&
  1109. !( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_FLIP_NEXT_VBI ) )
  1110. {
  1111. if( ++dwVBI >= peDxVideoPort->cAutoflipVbi )
  1112. {
  1113. dwVBI = 0;
  1114. }
  1115. }
  1116. }
  1117. if( ( dwVideo == (DWORD) -1 ) && ( dwVBI == (DWORD) -1 ) )
  1118. {
  1119. GetCurrentAutoflipInInfo.lpVideoPortData = peDxVideoPort;
  1120. GetCurrentAutoflipOutInfo.dwSurfaceIndex = 0;
  1121. GetCurrentAutoflipOutInfo.dwVBISurfaceIndex = 0;
  1122. if (peDxDirectDraw->DxApiInterface.DxGetCurrentAutoflip)
  1123. {
  1124. dwRet = peDxDirectDraw->DxApiInterface.DxGetCurrentAutoflip(
  1125. peDxDirectDraw->HwDeviceExtension,
  1126. &GetCurrentAutoflipInInfo,
  1127. &GetCurrentAutoflipOutInfo);
  1128. }
  1129. dwVideo = GetCurrentAutoflipOutInfo.dwSurfaceIndex;
  1130. dwVBI = GetCurrentAutoflipOutInfo.dwVBISurfaceIndex;
  1131. }
  1132. pGetCurrentAutoflipOut->hVideoSurface = NULL;
  1133. pGetCurrentAutoflipOut->hVBISurface = NULL;
  1134. if( ( peDxVideoPort->cAutoflipVideo > 0 ) && ( dwVideo != (DWORD) -1 ) )
  1135. {
  1136. pGetCurrentAutoflipOut->hVideoSurface =
  1137. peDxVideoPort->apeDxSurfaceVideo[dwVideo];
  1138. }
  1139. if( ( peDxVideoPort->cAutoflipVbi > 0 ) && ( dwVBI != (DWORD) -1 ) )
  1140. {
  1141. pGetCurrentAutoflipOut->hVBISurface =
  1142. peDxVideoPort->apeDxSurfaceVbi[dwVBI];
  1143. }
  1144. pGetCurrentAutoflipOut->bPolarity = GetPolarityOutInfo.bPolarity;
  1145. }
  1146. }
  1147. KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
  1148. pGetCurrentAutoflipOut->ddRVal = dwRet;
  1149. }
  1150. }
  1151. /******************************Public*Routine******************************\
  1152. * VOID DxGetPreviousAutoflip
  1153. *
  1154. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  1155. * Wrote it.
  1156. \**************************************************************************/
  1157. VOID
  1158. APIENTRY
  1159. DxGetPreviousAutoflip(
  1160. DDGETAUTOFLIPIN* pGetPreviousAutoflipIn,
  1161. DDGETAUTOFLIPOUT* pGetPreviousAutoflipOut
  1162. )
  1163. {
  1164. DWORD dwRet;
  1165. DXOBJ* pDxObjDirectDraw;
  1166. DXOBJ* pDxObjVideoPort;
  1167. DXOBJ* pDxObjTarget;
  1168. DXOBJ* pDxObjCurrent;
  1169. EDD_DXDIRECTDRAW* peDxDirectDraw;
  1170. EDD_DXVIDEOPORT* peDxVideoPort;
  1171. EDD_DXSURFACE* peDxTarget;
  1172. EDD_DXSURFACE* peDxPrevious;
  1173. DDGETPOLARITYININFO GetPolarityInInfo;
  1174. DDGETPOLARITYOUTINFO GetPolarityOutInfo;
  1175. DDGETPREVIOUSAUTOFLIPININFO GetPreviousAutoflipInInfo;
  1176. DDGETPREVIOUSAUTOFLIPOUTINFO GetPreviousAutoflipOutInfo;
  1177. KIRQL OldIrql;
  1178. DWORD dwVideo;
  1179. DWORD dwVBI;
  1180. pGetPreviousAutoflipOut->ddRVal = DDERR_INVALIDPARAMS;
  1181. if (pGetPreviousAutoflipIn == NULL)
  1182. {
  1183. return;
  1184. }
  1185. dwRet = DDERR_UNSUPPORTED; // Assume failure
  1186. pDxObjDirectDraw = (DXOBJ*) pGetPreviousAutoflipIn->hDirectDraw;
  1187. pDxObjVideoPort = (DXOBJ*) pGetPreviousAutoflipIn->hVideoPort;
  1188. if ((pDxObjDirectDraw != NULL) &&
  1189. (pDxObjVideoPort != NULL))
  1190. {
  1191. peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
  1192. peDxVideoPort = pDxObjVideoPort->peDxVideoPort;
  1193. ASSERTDX(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW,
  1194. "Invalid DirectDraw object");
  1195. ASSERTDX(pDxObjVideoPort->iDxType == DXT_VIDEOPORT,
  1196. "Invalid VideoPort object");
  1197. ASSERTDX(peDxDirectDraw == peDxVideoPort->peDxDirectDraw,
  1198. "Surface, VideoPort, and DirectDraw objects don't match");
  1199. ASSERTDX(peDxVideoPort->dwVPFlags & DDVP_AUTOFLIP,
  1200. "Not currently autoflipping");
  1201. GetPolarityInInfo.lpVideoPortData = peDxVideoPort;
  1202. KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
  1203. if ((peDxDirectDraw->bLost) ||
  1204. (peDxVideoPort->bLost))
  1205. {
  1206. KdPrint(("DxGetPreviousAutoflip: Objects are lost\n"));
  1207. dwRet = DDERR_SURFACELOST;
  1208. }
  1209. else
  1210. {
  1211. dwRet = DDERR_UNSUPPORTED;
  1212. if (peDxDirectDraw->DxApiInterface.DxGetPolarity)
  1213. {
  1214. dwRet = peDxDirectDraw->DxApiInterface.DxGetPolarity(
  1215. peDxDirectDraw->HwDeviceExtension,
  1216. &GetPolarityInInfo,
  1217. &GetPolarityOutInfo);
  1218. }
  1219. if (dwRet != DD_OK)
  1220. {
  1221. KdPrint(("DxGetPreviousAutoflip: Driver failed GetPolarity\n"));
  1222. }
  1223. else
  1224. {
  1225. // Determine which field is currently receiving the data. If they
  1226. // are software autoflipping, I can do that myself; otherwise, I
  1227. // have to call the HAL
  1228. //
  1229. // This is complicated by the facts that:
  1230. // 1) Skipping may be enabled.
  1231. // 3) When interleaving, they flip every other field, but its not
  1232. // guarenteed that the flip always occurs between the even and the
  1233. // odd fields.
  1234. //
  1235. // When software autoflipping, there is an issue that if this
  1236. // function is called between the time that the IRQ occured
  1237. // and the time that the DPC ran, this function would return
  1238. // the wrong surface. Since fixing this requires that we do all
  1239. // of the work at IRQ time (bad), we can probably assume that
  1240. // this will always be the case since anybody using this
  1241. // function would be calling it during the IRQ callback. We
  1242. // will therefore work around it.
  1243. dwVideo = (DWORD) -1;
  1244. dwVBI = (DWORD) -1;
  1245. if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP )
  1246. {
  1247. dwVideo = peDxVideoPort->iCurrentVideo;
  1248. }
  1249. if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI )
  1250. {
  1251. dwVBI = peDxVideoPort->iCurrentVbi;
  1252. }
  1253. if( ( dwVideo == (DWORD) -1 ) && ( dwVBI == (DWORD) -1 ) )
  1254. {
  1255. GetPreviousAutoflipInInfo.lpVideoPortData = peDxVideoPort;
  1256. GetPreviousAutoflipOutInfo.dwSurfaceIndex = 0;
  1257. GetPreviousAutoflipOutInfo.dwVBISurfaceIndex = 0;
  1258. if (peDxDirectDraw->DxApiInterface.DxGetPreviousAutoflip)
  1259. {
  1260. dwRet = peDxDirectDraw->DxApiInterface.DxGetPreviousAutoflip(
  1261. peDxDirectDraw->HwDeviceExtension,
  1262. &GetPreviousAutoflipInInfo,
  1263. &GetPreviousAutoflipOutInfo);
  1264. }
  1265. dwVideo = GetPreviousAutoflipOutInfo.dwSurfaceIndex;
  1266. dwVBI = GetPreviousAutoflipOutInfo.dwVBISurfaceIndex;
  1267. }
  1268. pGetPreviousAutoflipOut->hVideoSurface = NULL;
  1269. pGetPreviousAutoflipOut->hVBISurface = NULL;
  1270. if( ( peDxVideoPort->cAutoflipVideo > 0 ) && ( dwVideo != (DWORD) -1 ) )
  1271. {
  1272. pGetPreviousAutoflipOut->hVideoSurface =
  1273. peDxVideoPort->apeDxSurfaceVideo[dwVideo];
  1274. }
  1275. if( ( peDxVideoPort->cAutoflipVbi > 0 ) && ( dwVBI != (DWORD) -1 ) )
  1276. {
  1277. pGetPreviousAutoflipOut->hVBISurface =
  1278. peDxVideoPort->apeDxSurfaceVbi[dwVBI];
  1279. }
  1280. pGetPreviousAutoflipOut->bPolarity =
  1281. ( GetPolarityOutInfo.bPolarity == FALSE ); // invert
  1282. }
  1283. }
  1284. KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
  1285. pGetPreviousAutoflipOut->ddRVal = dwRet;
  1286. }
  1287. }
  1288. /******************************Public*Routine******************************\
  1289. * BOOL bDxModifyPassiveEventList
  1290. *
  1291. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  1292. * Wrote it.
  1293. \**************************************************************************/
  1294. BOOL
  1295. bDxModifyPassiveEventList(
  1296. EDD_DXDIRECTDRAW* peDxDirectDraw,
  1297. BOOL bAdd, // TRUE to add, FALSE to delete
  1298. DWORD dwEvent,
  1299. LPDD_NOTIFYCALLBACK pfnCallBack,
  1300. PVOID pContext
  1301. )
  1302. {
  1303. BOOL bRet;
  1304. DXAPI_EVENT* pDxEvent;
  1305. DXAPI_EVENT* pDxEvent_New;
  1306. DXAPI_EVENT* pDxEvent_Previous;
  1307. KIRQL OldIrql;
  1308. bRet = FALSE; // Assume failure
  1309. ASSERTDX(KeGetCurrentIrql() == PASSIVE_LEVEL, "Expected passive level");
  1310. ASSERTDX((bAdd == FALSE) || (bAdd == TRUE), "Bad boolean");
  1311. if (bAdd)
  1312. {
  1313. pDxEvent_New = (DXAPI_EVENT*) ExAllocatePoolWithTag(PagedPool,
  1314. sizeof(*pDxEvent),
  1315. 'eddG');
  1316. if (pDxEvent_New == NULL)
  1317. return(FALSE);
  1318. RtlZeroMemory(pDxEvent_New, sizeof(*pDxEvent_New));
  1319. }
  1320. // We must synchronize additions or deletions to the passive-level
  1321. // event list via our devlock.
  1322. ASSERTDX(gpfnLockDevice, "bDxModifyPassiveEventList: gpfnLockDevice is NULL");
  1323. gpfnLockDevice(peDxDirectDraw->hdev);
  1324. if (peDxDirectDraw->bLost)
  1325. {
  1326. KdPrint(("bDxModifyPassiveEventList: Object is lost\n"));
  1327. }
  1328. else
  1329. {
  1330. // First, try to find this event in the list:
  1331. pDxEvent_Previous = NULL;
  1332. for (pDxEvent = peDxDirectDraw->pDxEvent_PassiveList;
  1333. pDxEvent != NULL;
  1334. pDxEvent = pDxEvent->pDxEvent_Next)
  1335. {
  1336. if ((pDxEvent->dwEvent == dwEvent) &&
  1337. (pDxEvent->pfnCallBack == pfnCallBack) &&
  1338. (pDxEvent->pContext == pContext))
  1339. {
  1340. break;
  1341. }
  1342. pDxEvent_Previous = pDxEvent;
  1343. }
  1344. // It's a failure when:
  1345. //
  1346. // 1) If adding, the same event is already in the list;
  1347. // 2) If deleting, the event is not in the list.
  1348. if ((bAdd) == (pDxEvent == NULL))
  1349. {
  1350. if (bAdd)
  1351. {
  1352. // Add the event.
  1353. pDxEvent_New->peDxDirectDraw = peDxDirectDraw;
  1354. pDxEvent_New->dwEvent = dwEvent;
  1355. pDxEvent_New->dwIrqFlag = 0;
  1356. pDxEvent_New->pfnCallBack = pfnCallBack;
  1357. pDxEvent_New->pContext = pContext;
  1358. pDxEvent_New->pDxEvent_Next = peDxDirectDraw->pDxEvent_PassiveList;
  1359. peDxDirectDraw->pDxEvent_PassiveList = pDxEvent_New;
  1360. bRet = TRUE;
  1361. }
  1362. else
  1363. {
  1364. // Delete the event.
  1365. if (pDxEvent_Previous == NULL)
  1366. {
  1367. ASSERTDX(peDxDirectDraw->pDxEvent_PassiveList == pDxEvent,
  1368. "Deletion code is confused");
  1369. peDxDirectDraw->pDxEvent_PassiveList = pDxEvent->pDxEvent_Next;
  1370. }
  1371. else
  1372. {
  1373. pDxEvent_Previous->pDxEvent_Next = pDxEvent->pDxEvent_Next;
  1374. }
  1375. bRet = TRUE;
  1376. }
  1377. }
  1378. }
  1379. ASSERTDX(gpfnUnlockDevice, "bDxModifyPassiveEventList: gpfnUnlockDevice is NULL");
  1380. gpfnUnlockDevice(peDxDirectDraw->hdev);
  1381. if (bAdd) // Add case
  1382. {
  1383. if (!bRet)
  1384. {
  1385. // Add failed, so free the new node we allocated up front:
  1386. ExFreePool(pDxEvent_New);
  1387. RIPDX("DD_DXAPI_REGISTER_EVENT: Event was already registered");
  1388. }
  1389. }
  1390. else // Remove case
  1391. {
  1392. if (bRet)
  1393. {
  1394. // Delete succeeded, so free the old node:
  1395. ExFreePool(pDxEvent);
  1396. }
  1397. else
  1398. {
  1399. KdPrint(("DD_DXAPI_UNREGISTEREVENT: Couldn't find an event registered with those\n"));
  1400. KdPrint(("same parameters, so the unregister failed.\n"));
  1401. RIPDX("This will probably cause a leak of non-paged memory!");
  1402. }
  1403. }
  1404. return(bRet);
  1405. }
  1406. /******************************Public*Routine******************************\
  1407. * BOOL bDxModifyDispatchEventList
  1408. *
  1409. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  1410. * Wrote it.
  1411. \**************************************************************************/
  1412. BOOL
  1413. bDxModifyDispatchEventList(
  1414. EDD_DXDIRECTDRAW* peDxDirectDraw,
  1415. EDD_DXVIDEOPORT* peDxVideoPort,
  1416. BOOL bAdd, // TRUE to add, FALSE to delete
  1417. DWORD dwEvent,
  1418. DWORD dwIrqFlag,
  1419. LPDD_NOTIFYCALLBACK pfnCallBack,
  1420. PVOID pContext,
  1421. DWORD dwListEntry
  1422. )
  1423. {
  1424. BOOL bRet;
  1425. DXAPI_EVENT* pDxEvent;
  1426. DXAPI_EVENT* pDxEvent_New;
  1427. DXAPI_EVENT* pDxEvent_Previous;
  1428. KIRQL OldIrql;
  1429. bRet = FALSE; // Assume failure
  1430. ASSERTDX(KeGetCurrentIrql() == PASSIVE_LEVEL, "Expected passive level");
  1431. ASSERTDX((bAdd == FALSE) || (bAdd == TRUE), "Bad boolean");
  1432. // The event list is traversed at dispatch-level, so needs
  1433. // to be allocated non-paged.
  1434. if (bAdd)
  1435. {
  1436. pDxEvent_New = (DXAPI_EVENT*) ExAllocatePoolWithTag(NonPagedPool,
  1437. sizeof(*pDxEvent),
  1438. 'eddG');
  1439. if (pDxEvent_New == NULL)
  1440. return(FALSE);
  1441. RtlZeroMemory(pDxEvent_New, sizeof(*pDxEvent_New));
  1442. }
  1443. // We must synchronize additions or deletions to the dispatch-level
  1444. // event list via our spin lock. Note that this spinlock (of course)
  1445. // raises our IRQL level, which means we can't touch any pageable code!
  1446. KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
  1447. if ((peDxDirectDraw->bLost) ||
  1448. ((peDxVideoPort != NULL) && (peDxVideoPort->bLost)))
  1449. {
  1450. KdPrint(("bDxModifyDispatchEventList: Objects are lost\n"));
  1451. }
  1452. else
  1453. {
  1454. // First, try to find this event in the list:
  1455. pDxEvent_Previous = NULL;
  1456. for (pDxEvent = peDxDirectDraw->pDxEvent_DispatchList[dwListEntry];
  1457. pDxEvent != NULL;
  1458. pDxEvent = pDxEvent->pDxEvent_Next)
  1459. {
  1460. if ((pDxEvent->dwEvent == dwEvent) &&
  1461. (pDxEvent->dwIrqFlag == dwIrqFlag) &&
  1462. (pDxEvent->pfnCallBack == pfnCallBack) &&
  1463. (pDxEvent->pContext == pContext))
  1464. {
  1465. break;
  1466. }
  1467. pDxEvent_Previous = pDxEvent;
  1468. }
  1469. // It's a failure when:
  1470. //
  1471. // 1) If adding, the same event is already in the list;
  1472. // 2) If deleting, the event is not in the list.
  1473. if ((bAdd) == (pDxEvent == NULL))
  1474. {
  1475. if (bAdd)
  1476. {
  1477. // Add the event.
  1478. pDxEvent_New->peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
  1479. pDxEvent_New->peDxVideoPort = peDxVideoPort;
  1480. pDxEvent_New->dwEvent = dwEvent;
  1481. pDxEvent_New->dwIrqFlag = dwIrqFlag;
  1482. pDxEvent_New->pfnCallBack = pfnCallBack;
  1483. pDxEvent_New->pContext = pContext;
  1484. pDxEvent_New->pDxEvent_Next = peDxDirectDraw->pDxEvent_DispatchList[dwListEntry];
  1485. peDxDirectDraw->pDxEvent_DispatchList[dwListEntry] = pDxEvent_New;
  1486. bRet = TRUE;
  1487. }
  1488. else
  1489. {
  1490. // Delete the event.
  1491. if (pDxEvent_Previous == NULL)
  1492. {
  1493. ASSERTDX(peDxDirectDraw->pDxEvent_DispatchList[dwListEntry] == pDxEvent,
  1494. "Deletion code is confused");
  1495. peDxDirectDraw->pDxEvent_DispatchList[dwListEntry]
  1496. = pDxEvent->pDxEvent_Next;
  1497. }
  1498. else
  1499. {
  1500. pDxEvent_Previous->pDxEvent_Next = pDxEvent->pDxEvent_Next;
  1501. }
  1502. bRet = TRUE;
  1503. }
  1504. }
  1505. }
  1506. KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
  1507. if (bAdd) // Add case
  1508. {
  1509. if (!bRet)
  1510. {
  1511. // Add failed, so free the new node we allocated up front:
  1512. ExFreePool(pDxEvent_New);
  1513. }
  1514. }
  1515. else // Remove case
  1516. {
  1517. if (bRet)
  1518. {
  1519. // Delete succeeded, so free the old node:
  1520. ExFreePool(pDxEvent);
  1521. }
  1522. else
  1523. {
  1524. KdPrint(("DD_DXAPI_UNREGISTEREVENT: Couldn't find an event registered with those\n"));
  1525. KdPrint(("same parameters, so the unregister failed.\n"));
  1526. RIPDX("This will probably cause a leak of non-paged memory!");
  1527. }
  1528. }
  1529. return(bRet);
  1530. }
  1531. /******************************Public*Routine******************************\
  1532. * VOID vDxEnableInterrupts
  1533. *
  1534. * NOTE: Drivers may not fail DxEnableIrq.
  1535. *
  1536. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  1537. * Wrote it.
  1538. \**************************************************************************/
  1539. VOID
  1540. vDxEnableInterrupts(
  1541. EDD_DXDIRECTDRAW* peDxDirectDraw,
  1542. DWORD dwLine
  1543. )
  1544. {
  1545. DWORD dwIRQSources = 0;
  1546. KIRQL OldIrql;
  1547. DXAPI_EVENT* pDxEvent;
  1548. DDENABLEIRQINFO EnableIrqInfo;
  1549. DWORD dwRet;
  1550. DWORD i;
  1551. ASSERTDX(KeGetCurrentIrql() == PASSIVE_LEVEL, "Expected passive level");
  1552. ASSERTDX(peDxDirectDraw->DxApiInterface.DxEnableIrq != NULL,
  1553. "DxEnableIrq must be hooked if supporting interrupts.");
  1554. // We acquire both the devlock and the spinlock to ensure that no other
  1555. // activity in the driver is occurring while interrupts are enabled.
  1556. //
  1557. // The motivation for acquiring both (the spinlock could have been
  1558. // sufficient) is that we want to allow drivers to touch the CRTC
  1559. // registers in their interrupt enable routine (typically, both the
  1560. // display driver and the enable interrupt routine use CRTC registers,
  1561. // the usage of which must be synchronized).
  1562. ASSERTDX(gpfnLockDevice, "vDxEnableInterrupts: gpfnLockDevice is NULL");
  1563. gpfnLockDevice(peDxDirectDraw->hdev);
  1564. KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
  1565. // Compute the interrupts that are to be enabled by traversing the
  1566. // active event list:
  1567. for( i = 0; i < NUM_DISPATCH_LISTS; i++ )
  1568. {
  1569. for (pDxEvent = peDxDirectDraw->pDxEvent_DispatchList[i];
  1570. pDxEvent != NULL;
  1571. pDxEvent = pDxEvent->pDxEvent_Next)
  1572. {
  1573. dwIRQSources |= pDxEvent->dwIrqFlag;
  1574. }
  1575. }
  1576. EnableIrqInfo.dwIRQSources = dwIRQSources;
  1577. EnableIrqInfo.dwLine = dwLine;
  1578. EnableIrqInfo.IRQCallback = DxIrqCallBack;
  1579. EnableIrqInfo.lpIRQData = &peDxDirectDraw->IrqData;
  1580. dwRet = peDxDirectDraw->DxApiInterface.DxEnableIrq(
  1581. peDxDirectDraw->HwDeviceExtension,
  1582. &EnableIrqInfo,
  1583. NULL);
  1584. KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
  1585. ASSERTDX(gpfnUnlockDevice, "vDxEnableInterrupts: gpfnUnlockDevice is NULL");
  1586. gpfnUnlockDevice(peDxDirectDraw->hdev);
  1587. ASSERTDX(dwRet == DD_OK, "vDxEnableInterrupts: Driver failed DxEnableIrq");
  1588. }
  1589. /******************************Public*Routine******************************\
  1590. * DWORD dwDxRegisterEvent
  1591. *
  1592. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  1593. * Wrote it.
  1594. \**************************************************************************/
  1595. DWORD
  1596. dwDxRegisterEvent(
  1597. DDREGISTERCALLBACK* pRegisterEvent,
  1598. BOOL bRegister // TRUE if register, FALSE if unregister
  1599. )
  1600. {
  1601. DWORD dwRet;
  1602. DXOBJ* pDxObjDirectDraw;
  1603. DXOBJ* pDxObjVideoPort;
  1604. EDD_DXDIRECTDRAW* peDxDirectDraw;
  1605. EDD_DXVIDEOPORT* peDxVideoPort;
  1606. DWORD dwEvent;
  1607. DWORD dwIrqFlag;
  1608. BOOL bPassiveEvent;
  1609. BOOL bDispatchEvent;
  1610. DWORD dwLine;
  1611. dwRet = DDERR_GENERIC; // Assume failure
  1612. // Passive level is required because we have to acquire the devlock
  1613. // for the RESCHANGE and DOSBOX notifications.
  1614. ASSERTDX(KeGetCurrentIrql() == PASSIVE_LEVEL, "Expected passive level");
  1615. ASSERTDX(pRegisterEvent->pfnCallback != NULL, "Null callback specified");
  1616. ASSERTDX(pRegisterEvent->hDirectDraw != NULL, "Null hDirectDraw specified");
  1617. pDxObjDirectDraw = (DXOBJ*) pRegisterEvent->hDirectDraw;
  1618. if (pDxObjDirectDraw != NULL)
  1619. {
  1620. peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
  1621. // Note that we don't support the hooking of DDEVENT_CLOSEDIRECTDRAW,
  1622. // DDEVENT_CLOSESURFACE, or DDEVENT_CLOSEVIDEOPORT because those are
  1623. // always explictly registered with the object open call. If multiple
  1624. // clients want object close notification, they should each open their
  1625. // own object instances.
  1626. dwEvent = pRegisterEvent->dwEvents;
  1627. // Memphis doesn't bother checking to verify that 'dwParam1' and
  1628. // 'dwParam2' are zero when unused, so we won't either.
  1629. bPassiveEvent = FALSE;
  1630. bDispatchEvent = FALSE;
  1631. peDxVideoPort = NULL;
  1632. dwLine = 0;
  1633. dwIrqFlag = 0;
  1634. switch (dwEvent)
  1635. {
  1636. case DDEVENT_VP_VSYNC:
  1637. case DDEVENT_VP_LINE:
  1638. ASSERTDX(pRegisterEvent->dwParam1 != NULL,
  1639. "dwParam1 should be videoport handle");
  1640. pDxObjVideoPort = (DXOBJ*) pRegisterEvent->dwParam1;
  1641. if (pDxObjVideoPort != NULL)
  1642. {
  1643. peDxVideoPort = pDxObjVideoPort->peDxVideoPort;
  1644. ASSERTDX(pDxObjVideoPort->iDxType == DXT_VIDEOPORT,
  1645. "dwParam1 should be videoport handle");
  1646. if (dwEvent == DDEVENT_VP_LINE)
  1647. {
  1648. dwIrqFlag = DDIRQ_VPORT0_LINE; // We're going to shift this...
  1649. // We make it so that the 'dwLine' parameter is non-zero only
  1650. // when the event is registered, not unregistered,
  1651. dwLine = (bRegister) ? (DWORD) pRegisterEvent->dwParam2 : 0;
  1652. }
  1653. else
  1654. {
  1655. dwIrqFlag = DDIRQ_VPORT0_VSYNC; // We're going to shift this...
  1656. }
  1657. dwIrqFlag <<= (2 * peDxVideoPort->dwVideoPortID);
  1658. bDispatchEvent = TRUE;
  1659. }
  1660. break;
  1661. case DDEVENT_DISPLAY_VSYNC:
  1662. dwIrqFlag = DDIRQ_DISPLAY_VSYNC;
  1663. bDispatchEvent = TRUE;
  1664. break;
  1665. case DDEVENT_PRERESCHANGE:
  1666. case DDEVENT_POSTRESCHANGE:
  1667. case DDEVENT_PREDOSBOX:
  1668. case DDEVENT_POSTDOSBOX:
  1669. bPassiveEvent = TRUE;
  1670. break;
  1671. default:
  1672. KdPrint(("dwDxRegisterEvent: Invalid dwEvents specified\n"));
  1673. dwRet = DDERR_UNSUPPORTED;
  1674. break;
  1675. }
  1676. if (bPassiveEvent)
  1677. {
  1678. if (bDxModifyPassiveEventList(peDxDirectDraw,
  1679. bRegister,
  1680. dwEvent,
  1681. pRegisterEvent->pfnCallback,
  1682. pRegisterEvent->pContext))
  1683. {
  1684. dwRet = DD_OK;
  1685. }
  1686. }
  1687. else if (bDispatchEvent)
  1688. {
  1689. // First, verify that the requested interrupt is supported:
  1690. if (!(peDxDirectDraw->dwIRQCaps & dwIrqFlag))
  1691. {
  1692. KdPrint(("dwDxRegisterEvent: Interrupt not supported by driver.\n"));
  1693. dwRet = DDERR_UNSUPPORTED;
  1694. }
  1695. else
  1696. {
  1697. if (bDxModifyDispatchEventList(peDxDirectDraw,
  1698. peDxVideoPort,
  1699. bRegister,
  1700. dwEvent,
  1701. dwIrqFlag,
  1702. pRegisterEvent->pfnCallback,
  1703. pRegisterEvent->pContext,
  1704. CLIENT_DISPATCH_LIST))
  1705. {
  1706. vDxEnableInterrupts(peDxDirectDraw, dwLine);
  1707. dwRet = DD_OK;
  1708. }
  1709. }
  1710. }
  1711. }
  1712. return(dwRet);
  1713. }
  1714. /******************************Public*Routine******************************\
  1715. * VOID DxRegisterEvent
  1716. *
  1717. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  1718. * Wrote it.
  1719. \**************************************************************************/
  1720. VOID
  1721. APIENTRY
  1722. DxRegisterEvent(
  1723. DDREGISTERCALLBACK* pRegisterEvent,
  1724. DWORD* pdwRet
  1725. )
  1726. {
  1727. if (pRegisterEvent == NULL)
  1728. {
  1729. *pdwRet = DDERR_INVALIDPARAMS;
  1730. }
  1731. else
  1732. {
  1733. *pdwRet = dwDxRegisterEvent(pRegisterEvent, TRUE);
  1734. }
  1735. }
  1736. /******************************Public*Routine******************************\
  1737. * VOID DxUnregisterEvent
  1738. *
  1739. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  1740. * Wrote it.
  1741. \**************************************************************************/
  1742. VOID
  1743. APIENTRY
  1744. DxUnregisterEvent(
  1745. DDREGISTERCALLBACK* pRegisterEvent,
  1746. DWORD* pdwRet
  1747. )
  1748. {
  1749. if (pRegisterEvent == NULL)
  1750. {
  1751. *pdwRet = DDERR_INVALIDPARAMS;
  1752. }
  1753. else
  1754. {
  1755. *pdwRet = dwDxRegisterEvent(pRegisterEvent, FALSE);
  1756. }
  1757. }
  1758. /******************************Public*Routine******************************\
  1759. * VOID DxGetPolarity
  1760. *
  1761. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  1762. * Wrote it.
  1763. \**************************************************************************/
  1764. VOID
  1765. APIENTRY
  1766. DxGetPolarity(
  1767. DDGETPOLARITYIN* pGetPolarityIn,
  1768. DDGETPOLARITYOUT* pGetPolarityOut
  1769. )
  1770. {
  1771. DWORD dwRet;
  1772. DXOBJ* pDxObjDirectDraw;
  1773. DXOBJ* pDxObjVideoPort;
  1774. DXOBJ* pDxObjTarget;
  1775. DXOBJ* pDxObjCurrent;
  1776. EDD_DXDIRECTDRAW* peDxDirectDraw;
  1777. EDD_DXVIDEOPORT* peDxVideoPort;
  1778. DDGETPOLARITYININFO GetPolarityInInfo;
  1779. DDGETPOLARITYOUTINFO GetPolarityOutInfo;
  1780. KIRQL OldIrql;
  1781. pGetPolarityOut->ddRVal = DDERR_INVALIDPARAMS;
  1782. if (pGetPolarityIn == NULL)
  1783. {
  1784. return;
  1785. }
  1786. dwRet = DDERR_UNSUPPORTED; // Assume failure
  1787. pDxObjDirectDraw = (DXOBJ*) pGetPolarityIn->hDirectDraw;
  1788. pDxObjVideoPort = (DXOBJ*) pGetPolarityIn->hVideoPort;
  1789. if ((pDxObjDirectDraw != NULL) &&
  1790. (pDxObjVideoPort != NULL))
  1791. {
  1792. peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
  1793. peDxVideoPort = pDxObjVideoPort->peDxVideoPort;
  1794. ASSERTDX(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW,
  1795. "Invalid DirectDraw object");
  1796. ASSERTDX(pDxObjVideoPort->iDxType == DXT_VIDEOPORT,
  1797. "Invalid VideoPort object");
  1798. ASSERTDX(peDxDirectDraw == peDxVideoPort->peDxDirectDraw,
  1799. "Surface, VideoPort, and DirectDraw objects don't match");
  1800. GetPolarityInInfo.lpVideoPortData = peDxVideoPort;
  1801. GetPolarityOutInfo.bPolarity = 0;
  1802. KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
  1803. if ((peDxDirectDraw->bLost) ||
  1804. (peDxVideoPort->bLost))
  1805. {
  1806. KdPrint(("DxGetPolarity: Objects are lost\n"));
  1807. dwRet = DDERR_SURFACELOST;
  1808. }
  1809. else
  1810. {
  1811. if (peDxDirectDraw->DxApiInterface.DxGetPolarity)
  1812. {
  1813. dwRet = peDxDirectDraw->DxApiInterface.DxGetPolarity(
  1814. peDxDirectDraw->HwDeviceExtension,
  1815. &GetPolarityInInfo,
  1816. &GetPolarityOutInfo);
  1817. }
  1818. }
  1819. KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
  1820. pGetPolarityOut->ddRVal = dwRet;
  1821. pGetPolarityOut->bPolarity = GetPolarityOutInfo.bPolarity;
  1822. }
  1823. }
  1824. /******************************Public*Routine******************************\
  1825. * VOID DxAddVpCaptureBuffer
  1826. *
  1827. * 01-Nov-1997 -by- smac
  1828. * Wrote it.
  1829. \**************************************************************************/
  1830. VOID
  1831. APIENTRY
  1832. DxAddVpCaptureBuffer(
  1833. DDADDVPCAPTUREBUFF* pAddCaptureBuff,
  1834. DWORD* pdwRet
  1835. )
  1836. {
  1837. DXOBJ* pDxObjCapture;
  1838. EDD_DXCAPTURE* peDxCapture;
  1839. EDD_DXVIDEOPORT* peDxVideoPort;
  1840. EDD_DXDIRECTDRAW* peDxDirectDraw;
  1841. DWORD dwTop;
  1842. KIRQL OldIrql;
  1843. *pdwRet = DDERR_INVALIDPARAMS;
  1844. if (pAddCaptureBuff == NULL)
  1845. {
  1846. return;
  1847. }
  1848. pDxObjCapture = (DXOBJ*) pAddCaptureBuff->hCapture;
  1849. if (pDxObjCapture != NULL)
  1850. {
  1851. peDxCapture = pDxObjCapture->peDxCapture;
  1852. ASSERTDX(pDxObjCapture->iDxType == DXT_CAPTURE,
  1853. "Invalid Capture object");
  1854. ASSERTDX(pAddCaptureBuff->pKEvent != NULL,
  1855. "No KEvent specified");
  1856. ASSERTDX(pAddCaptureBuff->pMDL != NULL,
  1857. "No MDL specified");
  1858. ASSERTDX((pAddCaptureBuff->dwFlags != 0 ) &&
  1859. !(pAddCaptureBuff->dwFlags & ~(DDADDBUFF_SYSTEMMEMORY|DDADDBUFF_NONLOCALVIDMEM|DDADDBUFF_INVERT)),
  1860. "Invalid flags specified");
  1861. ASSERTDX(pAddCaptureBuff->lpBuffInfo != NULL,
  1862. "lpBuffInfo not specified");
  1863. *pdwRet = DDERR_INVALIDOBJECT;
  1864. peDxVideoPort = peDxCapture->peDxVideoPort;
  1865. if( peDxVideoPort != NULL )
  1866. {
  1867. peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
  1868. KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
  1869. if( !( peDxVideoPort->bLost ) &&
  1870. !( peDxCapture->bLost ) )
  1871. {
  1872. // Is the queue full?
  1873. dwTop = peDxCapture->dwTop;
  1874. if( ( peDxCapture->CaptureQueue[dwTop].flFlags & DD_DXCAPTUREBUFF_FLAG_IN_USE ) ||
  1875. !( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_ON ) )
  1876. {
  1877. *pdwRet = DDERR_CURRENTLYNOTAVAIL;
  1878. }
  1879. else
  1880. {
  1881. // Save the new buffer in the queque
  1882. peDxCapture->CaptureQueue[dwTop].dwClientFlags =
  1883. pAddCaptureBuff->dwFlags;
  1884. peDxCapture->CaptureQueue[dwTop].pBuffMDL =
  1885. pAddCaptureBuff->pMDL;
  1886. peDxCapture->CaptureQueue[dwTop].pBuffKEvent =
  1887. pAddCaptureBuff->pKEvent;
  1888. peDxCapture->CaptureQueue[dwTop].lpBuffInfo =
  1889. (PVOID) pAddCaptureBuff->lpBuffInfo;
  1890. peDxCapture->CaptureQueue[dwTop].flFlags = DD_DXCAPTUREBUFF_FLAG_IN_USE;
  1891. peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_CAPTURING;
  1892. if( ++(peDxCapture->dwTop) >= DXCAPTURE_MAX_CAPTURE_BUFFS )
  1893. {
  1894. peDxCapture->dwTop = 0;
  1895. }
  1896. *pdwRet = DD_OK;
  1897. }
  1898. }
  1899. KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
  1900. }
  1901. }
  1902. }
  1903. /******************************Public*Routine******************************\
  1904. * VOID DxInternalFlushVpCaptureBuffs
  1905. *
  1906. * 12-Apr-1999 -by- smac
  1907. * Wrote it.
  1908. \**************************************************************************/
  1909. VOID
  1910. APIENTRY
  1911. DxInternalFlushVpCaptureBuffs(
  1912. EDD_DXDIRECTDRAW* peDxDirectDraw,
  1913. EDD_DXVIDEOPORT* peDxVideoPort,
  1914. EDD_DXCAPTURE* peDxCapture
  1915. )
  1916. {
  1917. DDTRANSFERININFO ddTransferIn;
  1918. DDTRANSFEROUTINFO ddTransferOut;
  1919. LPDDCAPBUFFINFO lpBuffInfo;
  1920. DWORD i;
  1921. // Turn off all video port capture if nobody else is capturing
  1922. if( peDxVideoPort->peDxCapture && ( peDxCapture->peDxCaptureNext == NULL ) )
  1923. {
  1924. peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_CAPTURING;
  1925. }
  1926. // If a buffer is in the queue and the busmaster has not yet been
  1927. // initiated, clear it now so we don't do it. If the busmaster has
  1928. // already been initiated, we will tell the miniport to stop it now.
  1929. peDxCapture->dwTop = peDxCapture->dwBottom = 0;
  1930. for( i = 0; i < DXCAPTURE_MAX_CAPTURE_BUFFS; i++ )
  1931. {
  1932. if( peDxCapture->CaptureQueue[i].flFlags & DD_DXCAPTUREBUFF_FLAG_IN_USE )
  1933. {
  1934. if( peDxCapture->CaptureQueue[i].flFlags & DD_DXCAPTUREBUFF_FLAG_WAITING )
  1935. {
  1936. ddTransferIn.dwStartLine = 0;
  1937. ddTransferIn.dwEndLine = 0;
  1938. ddTransferIn.dwTransferFlags = DDTRANSFER_CANCEL;
  1939. ddTransferIn.lpDestMDL = NULL;
  1940. ddTransferIn.lpSurfaceData = NULL;
  1941. ddTransferIn.dwTransferID = ((ULONG_PTR)peDxCapture & ~0xf) + i;
  1942. if (peDxDirectDraw->DxApiInterface.DxTransfer)
  1943. {
  1944. peDxDirectDraw->DxApiInterface.DxTransfer(
  1945. peDxDirectDraw->HwDeviceExtension,
  1946. &ddTransferIn,
  1947. &ddTransferOut);
  1948. }
  1949. peDxCapture->CaptureQueue[i].peDxSurface->flFlags
  1950. &= ~DD_DXSURFACE_FLAG_TRANSFER;
  1951. }
  1952. lpBuffInfo = (LPDDCAPBUFFINFO) peDxCapture->CaptureQueue[i].lpBuffInfo;
  1953. lpBuffInfo->bPolarity = 0;
  1954. lpBuffInfo->dwFieldNumber = 0;
  1955. lpBuffInfo->ddRVal = (DWORD) DDERR_GENERIC;
  1956. peDxCapture->CaptureQueue[i].flFlags = 0;
  1957. KeSetEvent( peDxCapture->CaptureQueue[i].pBuffKEvent, 0, 0 );
  1958. }
  1959. }
  1960. }
  1961. /******************************Public*Routine******************************\
  1962. * VOID DxFlushVpCaptureBuffs
  1963. *
  1964. * 01-Nov-1997 -by- smac
  1965. * Wrote it.
  1966. \**************************************************************************/
  1967. VOID
  1968. APIENTRY
  1969. DxFlushVpCaptureBuffs(
  1970. DWORD** hCapture,
  1971. DWORD* pdwRet
  1972. )
  1973. {
  1974. DXOBJ* pDxObjCapture;
  1975. EDD_DXCAPTURE* peDxCapture;
  1976. EDD_DXVIDEOPORT* peDxVideoPort;
  1977. EDD_DXDIRECTDRAW* peDxDirectDraw;
  1978. KIRQL OldIrql;
  1979. *pdwRet = DDERR_INVALIDPARAMS;
  1980. if (hCapture == NULL)
  1981. {
  1982. return;
  1983. }
  1984. ASSERTDX(KeGetCurrentIrql() <= DISPATCH_LEVEL,
  1985. "DxFlushCaptureBuffs: Call less than or equl to DISPATCH_LEVEL (it accesses the dispatch table)");
  1986. pDxObjCapture = (DXOBJ*) (*hCapture);
  1987. if (pDxObjCapture != NULL)
  1988. {
  1989. peDxCapture = pDxObjCapture->peDxCapture;
  1990. peDxVideoPort = peDxCapture->peDxVideoPort;
  1991. peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
  1992. KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
  1993. DxInternalFlushVpCaptureBuffs( peDxDirectDraw, peDxVideoPort, peDxCapture );
  1994. KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
  1995. *pdwRet = DD_OK;
  1996. }
  1997. }
  1998. /******************************Public*Routine******************************\
  1999. * VOID DxIrqCallBack
  2000. *
  2001. * This routine is called by the miniport at interrupt time to notify us
  2002. * of interrupt-based events. We simply queue a DPC to handle the request
  2003. * at the more appropriate dispatch level, instead of interrupt level that
  2004. * we're currently at.
  2005. *
  2006. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  2007. * Wrote it.
  2008. \**************************************************************************/
  2009. VOID
  2010. APIENTRY
  2011. DxIrqCallBack(
  2012. DX_IRQDATA* pIrqData
  2013. )
  2014. {
  2015. EDD_DXDIRECTDRAW* peDxDirectDraw;
  2016. // We always tell the miniport to call us back with the pointer to
  2017. // &peDxDirectDraw->IrqData, so we can get back to the original
  2018. // peDxDirectDraw by subtracting the offset. If we ever need to
  2019. // change this in the future, we can simply add a field to DX_IRQDATA
  2020. // to point to the context:
  2021. peDxDirectDraw = (EDD_DXDIRECTDRAW*)
  2022. ((BYTE*) pIrqData - offsetof(EDD_DXDIRECTDRAW, IrqData));
  2023. // It's okay if KeInsertQueueDpc fails because the same DPC for a
  2024. // previous interrupt is still queued -- the miniport always ORs
  2025. // its interrupt flags into pIrqData->dwIrqflags.
  2026. KeInsertQueueDpc(&peDxDirectDraw->EventDpc, pIrqData, NULL);
  2027. }
  2028. /******************************Public*Routine******************************\
  2029. * VOID DxGetIrqFlags
  2030. *
  2031. * Out interrupt processing code runs at DPC level, and can be interrupt
  2032. * by an ISR. Consequently, when we look at the interrupt status, we
  2033. * must synchronize with the ISR. This is accomplished by having
  2034. * VideoPortSynchronizeExecution (which does a KeSynchronizeExecution)
  2035. * call-back to this routine.
  2036. *
  2037. * All we do here is copy the flags to the device extension (actually,
  2038. * we use the EDD_DXDIRECTDRAW which is allocated one-to-one with the
  2039. * device extension).
  2040. *
  2041. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  2042. * Wrote it.
  2043. \**************************************************************************/
  2044. BOOLEAN
  2045. DxGetIrqFlags(
  2046. PVOID pvContext
  2047. )
  2048. {
  2049. EDD_DXDIRECTDRAW* peDxDirectDraw;
  2050. peDxDirectDraw = (EDD_DXDIRECTDRAW*) pvContext;
  2051. // Copy the flags to a safe place:
  2052. peDxDirectDraw->dwSynchedIrqFlags = peDxDirectDraw->IrqData.dwIrqFlags;
  2053. // We have to zero the current flags because the miniport always ORs
  2054. // its flags in:
  2055. peDxDirectDraw->IrqData.dwIrqFlags = 0;
  2056. return(TRUE);
  2057. }
  2058. /******************************Public*Routine******************************\
  2059. * VOID DxEventDpc
  2060. *
  2061. * This routine does all the work of handling interrupt notification
  2062. * from the miniport. It makes the synchronous call-backs to anyone
  2063. * who has hooked the particular event.
  2064. *
  2065. * Note that to be synchronous we're making the call-backs at dispatch
  2066. * level. So if a callee doesn't require a truly synchronous notification,
  2067. * they should do nothing but kick off an event.
  2068. *
  2069. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  2070. * Wrote it.
  2071. \**************************************************************************/
  2072. // We can't call KeSynchronizeExecution directly, because we don't
  2073. // have the device's interrupt object. Videoport.sys does, however.
  2074. // Unfortunately, 'video.h', which is used to access the videoport.sys
  2075. // routines, was never intended to be mixed with GDI and USER header
  2076. // files (among other problems, there are conflicts in the PEVENT and
  2077. // PVIDEO_POWER_MANAGEMENT structures). So we define what prototypes
  2078. // we need here:
  2079. extern "C" {
  2080. typedef enum VIDEO_SYNCHRONIZE_PRIORITY {
  2081. VpLowPriority,
  2082. VpMediumPriority,
  2083. VpHighPriority
  2084. } VIDEO_SYNCHRONIZE_PRIORITY, *PVIDEO_SYNCHRONIZE_PRIORITY;
  2085. typedef
  2086. BOOLEAN
  2087. (*PMINIPORT_SYNCHRONIZE_ROUTINE)(
  2088. PVOID Context
  2089. );
  2090. VOID
  2091. VideoPortSynchronizeExecution(
  2092. PVOID HwDeviceExtension,
  2093. VIDEO_SYNCHRONIZE_PRIORITY Priority,
  2094. PMINIPORT_SYNCHRONIZE_ROUTINE synchronizeRoutine,
  2095. PVOID Context
  2096. );
  2097. };
  2098. VOID
  2099. DxEventDpc(
  2100. PKDPC pDpc,
  2101. PVOID pvContext,
  2102. PVOID pvArgument1,
  2103. PVOID pvArgument2
  2104. )
  2105. {
  2106. EDD_DXDIRECTDRAW* peDxDirectDraw;
  2107. DX_IRQDATA* pIrqData;
  2108. DXAPI_EVENT* pDxEvent;
  2109. DWORD dwIrqFlags;
  2110. DWORD i;
  2111. pIrqData = (DX_IRQDATA*) pvArgument1;
  2112. peDxDirectDraw = (EDD_DXDIRECTDRAW*) pvContext;
  2113. // The ISR can be triggered even while we're processing the DPC for
  2114. // its previous interrupt. Consequently, we have to access the
  2115. // interrupt flags in a routine that is synchronized to the ISR
  2116. // routine.
  2117. //
  2118. // Note that we don't call KeSynchronizeExecution directly, because
  2119. // we don't have the device's interrupt object.
  2120. VideoPortSynchronizeExecution(peDxDirectDraw->HwDeviceExtension,
  2121. VpMediumPriority,
  2122. DxGetIrqFlags,
  2123. peDxDirectDraw);
  2124. dwIrqFlags = peDxDirectDraw->dwSynchedIrqFlags;
  2125. // We must acquire a spinlock while traversing the event list to
  2126. // protect against simultaneous modifications to the list.
  2127. KeAcquireSpinLockAtDpcLevel(&peDxDirectDraw->SpinLock);
  2128. // We call the callbacks registered by the client before we
  2129. // call the ones that we registered so we give the client a chance
  2130. // to skip fields before we execute our skip logic. This is why
  2131. // we keep two dispatch lists.
  2132. for (i = 0; i < NUM_DISPATCH_LISTS; i++)
  2133. {
  2134. for (pDxEvent = peDxDirectDraw->pDxEvent_DispatchList[i];
  2135. pDxEvent != NULL;
  2136. pDxEvent = pDxEvent->pDxEvent_Next)
  2137. {
  2138. if (pDxEvent->dwIrqFlag & dwIrqFlags)
  2139. {
  2140. pDxEvent->pfnCallBack(pDxEvent->dwEvent, pDxEvent->pContext, 0, 0);
  2141. }
  2142. }
  2143. }
  2144. // If it was a busmaster IRQ, take care of them as well
  2145. if (dwIrqFlags & DDIRQ_BUSMASTER)
  2146. {
  2147. for (pDxEvent = peDxDirectDraw->pDxEvent_CaptureList;
  2148. pDxEvent != NULL;
  2149. pDxEvent = pDxEvent->pDxEvent_Next)
  2150. {
  2151. pDxEvent->pfnCallBack(pDxEvent->dwEvent, pDxEvent->pContext, 0, 0);
  2152. }
  2153. }
  2154. KeReleaseSpinLockFromDpcLevel(&peDxDirectDraw->SpinLock);
  2155. }
  2156. /******************************Public*Routine******************************\
  2157. * VOID vDxFlip
  2158. *
  2159. * Assumes the spinlock is held.
  2160. *
  2161. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  2162. * Wrote it.
  2163. \**************************************************************************/
  2164. VOID
  2165. vDxFlip(
  2166. EDD_DXVIDEOPORT* peDxVideoPort,
  2167. DWORD dwFlags
  2168. )
  2169. {
  2170. EDD_DXDIRECTDRAW* peDxDirectDraw;
  2171. DWORD iOldVideo;
  2172. DWORD iOldVbi;
  2173. DWORD iOldOverlay;
  2174. DWORD iNewVideo;
  2175. DWORD iNewVbi;
  2176. DWORD iNewOverlay;
  2177. DDFLIPVIDEOPORTINFO FlipVideoPortInfo;
  2178. DDFLIPOVERLAYINFO FlipOverlayInfo;
  2179. DWORD dwRet;
  2180. DWORD dwTemp;
  2181. ASSERTDX(KeGetCurrentIrql() == DISPATCH_LEVEL, "Expected held spinlock");
  2182. peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
  2183. if( dwFlags == DDVPFLIP_VBI )
  2184. {
  2185. if (peDxVideoPort->cAutoflipVbi != 0)
  2186. {
  2187. // Flip videoport VBI surface:
  2188. iOldVbi = peDxVideoPort->iCurrentVbi;
  2189. iNewVbi = iOldVbi + 1;
  2190. if (iNewVbi >= peDxVideoPort->cAutoflipVbi)
  2191. iNewVbi = 0;
  2192. peDxVideoPort->iCurrentVbi = iNewVbi;
  2193. FlipVideoPortInfo.lpVideoPortData
  2194. = peDxVideoPort;
  2195. FlipVideoPortInfo.lpCurrentSurface
  2196. = peDxVideoPort->apeDxSurfaceVbi[iOldVbi];
  2197. FlipVideoPortInfo.lpTargetSurface
  2198. = peDxVideoPort->apeDxSurfaceVbi[iNewVbi];
  2199. FlipVideoPortInfo.dwFlipVPFlags = DDVPFLIP_VBI;
  2200. if (peDxDirectDraw->DxApiInterface.DxFlipVideoPort)
  2201. {
  2202. dwRet = peDxDirectDraw->DxApiInterface.DxFlipVideoPort(
  2203. peDxDirectDraw->HwDeviceExtension,
  2204. &FlipVideoPortInfo,
  2205. NULL);
  2206. }
  2207. }
  2208. }
  2209. else if( dwFlags == DDVPFLIP_VIDEO )
  2210. {
  2211. if (peDxVideoPort->cAutoflipVideo != 0)
  2212. {
  2213. // Flip videoport video surface:
  2214. iOldVideo = peDxVideoPort->iCurrentVideo;
  2215. iNewVideo = iOldVideo + 1;
  2216. if (iNewVideo >= peDxVideoPort->cAutoflipVideo)
  2217. iNewVideo = 0;
  2218. peDxVideoPort->iCurrentVideo = iNewVideo;
  2219. FlipVideoPortInfo.lpVideoPortData
  2220. = peDxVideoPort;
  2221. FlipVideoPortInfo.lpCurrentSurface
  2222. = peDxVideoPort->apeDxSurfaceVideo[iOldVideo];
  2223. FlipVideoPortInfo.lpTargetSurface
  2224. = peDxVideoPort->apeDxSurfaceVideo[iNewVideo];
  2225. FlipVideoPortInfo.dwFlipVPFlags
  2226. = DDVPFLIP_VIDEO;
  2227. if (peDxDirectDraw->DxApiInterface.DxFlipVideoPort)
  2228. {
  2229. dwRet = peDxDirectDraw->DxApiInterface.DxFlipVideoPort(
  2230. peDxDirectDraw->HwDeviceExtension,
  2231. &FlipVideoPortInfo,
  2232. NULL);
  2233. }
  2234. // Flip overlay surface:
  2235. if( ( peDxVideoPort->apeDxSurfaceVideo[0] != NULL ) &&
  2236. ( peDxVideoPort->apeDxSurfaceVideo[0]->ddsCaps & DDSCAPS_OVERLAY ) &&
  2237. ( ( peDxVideoPort->apeDxSurfaceVideo[0]->dwOverlayFlags & DDOVER_AUTOFLIP ) ||
  2238. ( peDxVideoPort->bSoftwareAutoflip ) ) )
  2239. {
  2240. // If there are two surfaces, flip to the opposite surface. If
  2241. // there are more than two surfaces, flip to dwNumAutoflip - 2.
  2242. dwTemp = 1;
  2243. if( peDxVideoPort->cAutoflipVideo != 2 )
  2244. {
  2245. dwTemp++;
  2246. }
  2247. dwTemp = peDxVideoPort->iCurrentVideo +
  2248. peDxVideoPort->cAutoflipVideo - dwTemp;
  2249. if( dwTemp >= peDxVideoPort->cAutoflipVideo )
  2250. {
  2251. dwTemp -= peDxVideoPort->cAutoflipVideo;
  2252. }
  2253. FlipOverlayInfo.lpTargetSurface
  2254. = peDxVideoPort->apeDxSurfaceVideo[dwTemp];
  2255. if( dwTemp == 0 )
  2256. {
  2257. dwTemp = peDxVideoPort->cAutoflipVideo;
  2258. }
  2259. FlipOverlayInfo.lpCurrentSurface
  2260. = peDxVideoPort->apeDxSurfaceVideo[--dwTemp];
  2261. FlipOverlayInfo.dwFlags = 0;
  2262. if (peDxDirectDraw->DxApiInterface.DxFlipOverlay)
  2263. {
  2264. dwRet = peDxDirectDraw->DxApiInterface.DxFlipOverlay(
  2265. peDxDirectDraw->HwDeviceExtension,
  2266. &FlipOverlayInfo,
  2267. NULL);
  2268. }
  2269. }
  2270. }
  2271. }
  2272. }
  2273. /******************************Public*Routine******************************\
  2274. * VOID vDxBob
  2275. *
  2276. * Assumes the spinlock is held.
  2277. *
  2278. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  2279. * Wrote it.
  2280. \**************************************************************************/
  2281. VOID
  2282. vDxBob(
  2283. EDD_DXVIDEOPORT* peDxVideoPort
  2284. )
  2285. {
  2286. EDD_DXDIRECTDRAW* peDxDirectDraw;
  2287. DDBOBNEXTFIELDINFO BobNextFieldInfo;
  2288. DWORD dwRet;
  2289. DWORD dwTemp;
  2290. ASSERTDX(KeGetCurrentIrql() == DISPATCH_LEVEL, "Expected held spinlock");
  2291. peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
  2292. // Get the current surface handle. This is tricky because
  2293. // dwCurrentBuffer tells us which surface the video port is
  2294. // writting to - not which surface has the overlay. Therefore,
  2295. // we re-create the algorithm used in DoFlip to get the surface.
  2296. if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP )
  2297. {
  2298. dwTemp = 1;
  2299. if( peDxVideoPort->cAutoflipVideo != 2 )
  2300. {
  2301. dwTemp++;
  2302. }
  2303. dwTemp = peDxVideoPort->iCurrentVideo +
  2304. peDxVideoPort->cAutoflipVideo - dwTemp;
  2305. if( dwTemp >= peDxVideoPort->cAutoflipVideo )
  2306. {
  2307. dwTemp -= peDxVideoPort->cAutoflipVideo;
  2308. }
  2309. }
  2310. else
  2311. {
  2312. dwTemp = 0;
  2313. }
  2314. BobNextFieldInfo.lpSurface = peDxVideoPort->apeDxSurfaceVideo[dwTemp];
  2315. if (peDxDirectDraw->DxApiInterface.DxBobNextField)
  2316. {
  2317. dwRet = peDxDirectDraw->DxApiInterface.DxBobNextField(
  2318. peDxDirectDraw->HwDeviceExtension,
  2319. &BobNextFieldInfo,
  2320. NULL);
  2321. }
  2322. }
  2323. /******************************Public*Routine******************************\
  2324. * VOID vDxSkip
  2325. *
  2326. * Assumes the spinlock is held.
  2327. *
  2328. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  2329. * Wrote it.
  2330. \**************************************************************************/
  2331. VOID
  2332. vDxSkip(
  2333. EDD_DXVIDEOPORT* peDxVideoPort,
  2334. DWORD dwFlags
  2335. )
  2336. {
  2337. EDD_DXDIRECTDRAW* peDxDirectDraw;
  2338. DDSKIPNEXTFIELDINFO SkipNextFieldInfo;
  2339. DWORD dwRet;
  2340. ASSERTDX(KeGetCurrentIrql() == DISPATCH_LEVEL, "Expected held spinlock");
  2341. peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
  2342. if (peDxDirectDraw->DxApiInterface.DxSkipNextField)
  2343. {
  2344. SkipNextFieldInfo.lpVideoPortData = peDxVideoPort;
  2345. SkipNextFieldInfo.dwSkipFlags = dwFlags;
  2346. dwRet = peDxDirectDraw->DxApiInterface.DxSkipNextField(
  2347. peDxDirectDraw->HwDeviceExtension,
  2348. &SkipNextFieldInfo,
  2349. NULL);
  2350. }
  2351. }
  2352. /******************************Public*Routine******************************\
  2353. * VOID IRQCapture
  2354. *
  2355. * This routine initiates video/VBI capture based on a video port VSYNC.
  2356. *
  2357. * NOTE: The spinlock is already held.
  2358. *
  2359. * 10-Jan-1998 -by- Scott MacDonald [smac]
  2360. * Wrote it.
  2361. \**************************************************************************/
  2362. VOID IRQCapture(
  2363. EDD_DXVIDEOPORT* peDxVideoPort,
  2364. EDD_DXDIRECTDRAW* peDxDirectDraw
  2365. )
  2366. {
  2367. DDGETCURRENTAUTOFLIPININFO ddAutoflipInInfo;
  2368. DDGETCURRENTAUTOFLIPOUTINFO ddAutoflipOutInfo;
  2369. EDD_DXCAPTURE* peDxCapture;
  2370. LPDDCAPBUFFINFO lpBuffInfo;
  2371. DXCAPTUREBUFF* lpBuff;
  2372. DDTRANSFERININFO ddTransferIn;
  2373. DDTRANSFEROUTINFO ddTransferOut;
  2374. ULONGLONG ullTimeStamp;
  2375. PULONGLONG pullTemp;
  2376. ULONGLONG rate;
  2377. DWORD dwVBIIndex;
  2378. DWORD dwVideoIndex;
  2379. BOOL bStarved = TRUE;
  2380. DWORD ddRVal;
  2381. // Get the current time stamp
  2382. ullTimeStamp = (ULONGLONG)KeQueryPerformanceCounter((PLARGE_INTEGER)&rate).QuadPart;
  2383. ullTimeStamp = (ullTimeStamp & 0xFFFFFFFF00000000) / rate * 10000000 +
  2384. (ullTimeStamp & 0xFFFFFFFF) * 10000000 / rate;
  2385. // If either the VBI or video is being hardware autoflipped, figure out
  2386. // the correct buffers.
  2387. dwVBIIndex = 0;
  2388. dwVideoIndex = 0;
  2389. if( ( ( peDxVideoPort->cAutoflipVbi > 1 ) &&
  2390. !( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI ) ) ||
  2391. ( ( peDxVideoPort->cAutoflipVideo > 1 ) &&
  2392. !( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP ) ) )
  2393. {
  2394. ddAutoflipInInfo.lpVideoPortData = peDxVideoPort;
  2395. ddAutoflipOutInfo.dwSurfaceIndex = 0;
  2396. if (peDxDirectDraw->DxApiInterface.DxGetCurrentAutoflip)
  2397. {
  2398. ddRVal = peDxDirectDraw->DxApiInterface.DxGetCurrentAutoflip(
  2399. peDxDirectDraw->HwDeviceExtension,
  2400. &ddAutoflipInInfo,
  2401. &ddAutoflipOutInfo);
  2402. }
  2403. if( peDxVideoPort->cAutoflipVideo > 0 )
  2404. {
  2405. dwVideoIndex = ddAutoflipOutInfo.dwSurfaceIndex;
  2406. if( dwVideoIndex-- == 0 )
  2407. {
  2408. dwVideoIndex = peDxVideoPort->cAutoflipVideo - 1;
  2409. }
  2410. }
  2411. if( peDxVideoPort->cAutoflipVbi > 0 )
  2412. {
  2413. dwVBIIndex = ddAutoflipOutInfo.dwVBISurfaceIndex;
  2414. if( dwVBIIndex-- == 0 )
  2415. {
  2416. dwVBIIndex = peDxVideoPort->cAutoflipVbi - 1;
  2417. }
  2418. }
  2419. }
  2420. // Which is the surface containing the most recent VBI data?
  2421. if( ( peDxVideoPort->cAutoflipVbi > 0 ) &&
  2422. ( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI ) )
  2423. {
  2424. dwVBIIndex = peDxVideoPort->iCurrentVbi;
  2425. if( dwVBIIndex-- == 0 )
  2426. {
  2427. dwVBIIndex = peDxVideoPort->cAutoflipVbi - 1;
  2428. }
  2429. }
  2430. // Which is the surface containing the most recent video data?
  2431. if( ( peDxVideoPort->cAutoflipVideo > 0 ) &&
  2432. ( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP ) )
  2433. {
  2434. dwVideoIndex = peDxVideoPort->iCurrentVideo;
  2435. if( dwVideoIndex-- == 0 )
  2436. {
  2437. dwVideoIndex = peDxVideoPort->cAutoflipVideo - 1;
  2438. }
  2439. }
  2440. // Look at each capture device to determine if it has to do a busmaster
  2441. // or not
  2442. peDxCapture = peDxVideoPort->peDxCapture;
  2443. while( peDxCapture != NULL )
  2444. {
  2445. if( ( peDxCapture->CaptureQueue[peDxCapture->dwBottom].flFlags & DD_DXCAPTUREBUFF_FLAG_IN_USE ) &&
  2446. !( peDxCapture->CaptureQueue[peDxCapture->dwBottom].flFlags & DD_DXCAPTUREBUFF_FLAG_WAITING ) )
  2447. {
  2448. bStarved = FALSE;
  2449. if( peDxCapture->dwCaptureCountDown-- == 1 )
  2450. {
  2451. peDxCapture->dwCaptureCountDown = peDxCapture->dwCaptureEveryNFields;
  2452. lpBuff = &(peDxCapture->CaptureQueue[peDxCapture->dwBottom]);
  2453. // Fill in the buffer info
  2454. lpBuffInfo = (LPDDCAPBUFFINFO) lpBuff->lpBuffInfo;
  2455. lpBuffInfo->dwFieldNumber = peDxVideoPort->dwCurrentField;
  2456. pullTemp = (PULONGLONG) &(lpBuffInfo->liTimeStamp);
  2457. *pullTemp = ullTimeStamp;
  2458. // Tell mini port to do the transfer
  2459. ddTransferIn.dwStartLine = peDxCapture->dwStartLine;
  2460. ddTransferIn.dwEndLine = peDxCapture->dwEndLine;
  2461. ddTransferIn.dwTransferFlags = lpBuff->dwClientFlags;
  2462. if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_HALFLINES )
  2463. {
  2464. ddTransferIn.dwTransferFlags |= DDTRANSFER_HALFLINES;
  2465. }
  2466. ddTransferIn.lpDestMDL = lpBuff->pBuffMDL;
  2467. if( peDxCapture->flFlags & DD_DXCAPTURE_FLAG_VIDEO )
  2468. {
  2469. ddTransferIn.lpSurfaceData = peDxVideoPort->apeDxSurfaceVideo[dwVideoIndex];
  2470. }
  2471. else
  2472. {
  2473. ddTransferIn.lpSurfaceData = peDxVideoPort->apeDxSurfaceVbi[dwVBIIndex];
  2474. }
  2475. if (ddTransferIn.lpSurfaceData)
  2476. {
  2477. ddTransferIn.dwTransferID = (ULONG_PTR) peDxCapture;
  2478. ddTransferIn.dwTransferID &= ~0xf;
  2479. ddTransferIn.dwTransferID |= peDxCapture->dwBottom;
  2480. ddRVal = DDERR_UNSUPPORTED;
  2481. if (peDxDirectDraw->DxApiInterface.DxTransfer)
  2482. {
  2483. ddRVal = peDxDirectDraw->DxApiInterface.DxTransfer(
  2484. peDxDirectDraw->HwDeviceExtension,
  2485. &ddTransferIn,
  2486. &ddTransferOut);
  2487. }
  2488. }
  2489. else
  2490. {
  2491. ddRVal = DDERR_INVALIDPARAMS;
  2492. }
  2493. lpBuffInfo->ddRVal = ddRVal;
  2494. if( ddRVal != DD_OK )
  2495. {
  2496. // Set the KEvent now
  2497. KeSetEvent( lpBuff->pBuffKEvent, 0, 0 );
  2498. lpBuff->flFlags = 0;
  2499. lpBuff->pBuffKEvent = 0;
  2500. }
  2501. else
  2502. {
  2503. // Mark the lucky surface as doing a transfer
  2504. lpBuffInfo->bPolarity = ddTransferOut.dwBufferPolarity;
  2505. lpBuff->peDxSurface = (EDD_DXSURFACE*) ddTransferIn.lpSurfaceData;
  2506. lpBuff->peDxSurface->flFlags |= DD_DXSURFACE_FLAG_TRANSFER;
  2507. lpBuff->flFlags |= DD_DXCAPTUREBUFF_FLAG_WAITING;
  2508. }
  2509. // Next time use the next buffer
  2510. if( ++( peDxCapture->dwBottom ) >= DXCAPTURE_MAX_CAPTURE_BUFFS )
  2511. {
  2512. peDxCapture->dwBottom = 0;
  2513. }
  2514. }
  2515. }
  2516. peDxCapture = peDxCapture->peDxCaptureNext;
  2517. }
  2518. if( bStarved )
  2519. {
  2520. peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_CAPTURING;
  2521. }
  2522. }
  2523. /******************************Public*Routine******************************\
  2524. * VOID DxAutoflipDpc
  2525. *
  2526. * This routine handles 'software autoflipping' and is called at dispatch
  2527. * level when the miniport's videoport interrupt is triggered. This routine
  2528. * can't be kept in 'win32k.sys' because it needs to be non-pageable.
  2529. *
  2530. * NOTE: The spinlock is already held.
  2531. *
  2532. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  2533. * Wrote it.
  2534. \**************************************************************************/
  2535. VOID
  2536. APIENTRY
  2537. DxAutoflipDpc(
  2538. DWORD dwEvent,
  2539. PVOID pContext,
  2540. DWORD dwParam1,
  2541. DWORD dwParam2
  2542. )
  2543. {
  2544. EDD_DXDIRECTDRAW* peDxDirectDraw;
  2545. EDD_DXVIDEOPORT* peDxVideoPort;
  2546. DWORD dwCurrentField;
  2547. BOOL bAdjustFirstWeave;
  2548. BOOL bSkipped;
  2549. BOOL bFlipped;
  2550. ASSERTDX(KeGetCurrentIrql() == DISPATCH_LEVEL, "Expected dispath level");
  2551. ASSERTDX(dwEvent == DDEVENT_VP_VSYNC, "Expected VP_VSYNC event");
  2552. peDxVideoPort = (EDD_DXVIDEOPORT*) pContext;
  2553. peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
  2554. // If capturing, do it now
  2555. if( ( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_CAPTURING ) &&
  2556. ( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_ON ) )
  2557. {
  2558. IRQCapture(peDxVideoPort, peDxDirectDraw);
  2559. }
  2560. // Do we need to notify user mode that a vsync occurred?
  2561. if ((peDxVideoPort->pNotifyEvent != NULL) &&
  2562. (peDxVideoPort->pNotifyBuffer != NULL) &&
  2563. (1 == InterlockedExchange( &peDxVideoPort->pNotifyBuffer->lDone, 0 ) ) )
  2564. {
  2565. DDGETCURRENTAUTOFLIPININFO ddAutoflipInInfo;
  2566. DDGETCURRENTAUTOFLIPOUTINFO ddAutoflipOutInfo;
  2567. ULONGLONG ullTimeStamp;
  2568. ULONGLONG rate;
  2569. UINT dwVideoIndex;
  2570. // Fill in the buffer
  2571. peDxVideoPort->pNotifyBuffer->lField = -1;
  2572. if ( peDxDirectDraw->DxApiInterface.DxGetPolarity )
  2573. {
  2574. DDGETPOLARITYININFO ddPolarityInInfo;
  2575. DDGETPOLARITYOUTINFO ddPolarityOutInfo;
  2576. ddPolarityInInfo.lpVideoPortData = peDxVideoPort;
  2577. peDxDirectDraw->DxApiInterface.DxGetPolarity( peDxDirectDraw->HwDeviceExtension,
  2578. &ddPolarityInInfo, &ddPolarityOutInfo );
  2579. peDxVideoPort->pNotifyBuffer->lField = ddPolarityOutInfo.bPolarity ? 1 : 0;
  2580. }
  2581. dwVideoIndex = 0;
  2582. if (peDxVideoPort->cAutoflipVideo > 1 )
  2583. {
  2584. if (peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP)
  2585. {
  2586. dwVideoIndex = peDxVideoPort->iCurrentVideo;
  2587. }
  2588. else
  2589. {
  2590. ddAutoflipInInfo.lpVideoPortData = peDxVideoPort;
  2591. ddAutoflipOutInfo.dwSurfaceIndex = 0;
  2592. if (peDxDirectDraw->DxApiInterface.DxGetCurrentAutoflip)
  2593. {
  2594. peDxDirectDraw->DxApiInterface.DxGetCurrentAutoflip(
  2595. peDxDirectDraw->HwDeviceExtension,
  2596. &ddAutoflipInInfo,
  2597. &ddAutoflipOutInfo);
  2598. }
  2599. dwVideoIndex = ddAutoflipOutInfo.dwSurfaceIndex;
  2600. }
  2601. if( dwVideoIndex-- == 0 )
  2602. {
  2603. dwVideoIndex = peDxVideoPort->cAutoflipVideo - 1;
  2604. }
  2605. }
  2606. peDxVideoPort->pNotifyBuffer->dwSurfaceIndex = dwVideoIndex;
  2607. ullTimeStamp = (ULONGLONG)KeQueryPerformanceCounter((PLARGE_INTEGER)&rate).QuadPart;
  2608. ullTimeStamp = (ullTimeStamp & 0xFFFFFFFF00000000) / rate * 10000000 +
  2609. (ullTimeStamp & 0xFFFFFFFF) * 10000000 / rate;
  2610. *((ULONGLONG*)&(peDxVideoPort->pNotifyBuffer->ApproximateTimeStamp)) = ullTimeStamp;
  2611. KeSetEvent (peDxVideoPort->pNotifyEvent, IO_NO_INCREMENT, FALSE);
  2612. }
  2613. // Note that it is okay to modify 'dwCurrentField' outside of a spinlock,
  2614. // as the only other routine that modifies it is 'DxSetFieldNumber' and
  2615. // it always does an atomic write.
  2616. dwCurrentField = InterlockedIncrement((LONG*) &peDxVideoPort->dwCurrentField);
  2617. // Check for posted state changes
  2618. bAdjustFirstWeave = FALSE;
  2619. if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_NEW_STATE )
  2620. {
  2621. if( peDxVideoPort->dwSetStateField-- == 0 )
  2622. {
  2623. peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_NEW_STATE;
  2624. // If we'll be weaving, we need to make sure that
  2625. // we only flip at the beginning of a frame and not
  2626. // during the middle. We assume that we're told to
  2627. // star weaving at the beginning of the frame.
  2628. if( ( peDxVideoPort->dwSetStateState & DDSTATE_WEAVE ) &&
  2629. !( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_FLIP_NEXT ) )
  2630. {
  2631. bAdjustFirstWeave = TRUE;
  2632. peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_FLIP_NEXT;
  2633. }
  2634. EffectStateChange( peDxVideoPort, NULL, peDxVideoPort->dwSetStateState );
  2635. }
  2636. }
  2637. // Check the skip logic
  2638. bSkipped = FALSE;
  2639. if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_SKIP_SET )
  2640. {
  2641. if( peDxVideoPort->dwFieldToSkip-- == 0 )
  2642. {
  2643. // Tell the MiniPort to skip the next field
  2644. vDxSkip( peDxVideoPort, DDSKIP_SKIPNEXT );
  2645. peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_SKIPPED_LAST;
  2646. bSkipped = TRUE;
  2647. if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_NEXT_SKIP_SET )
  2648. {
  2649. peDxVideoPort->dwFieldToSkip = peDxVideoPort->dwNextFieldToSkip;
  2650. peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_NEXT_SKIP_SET;
  2651. }
  2652. else
  2653. {
  2654. peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_SKIP_SET;
  2655. }
  2656. }
  2657. else if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_NEXT_SKIP_SET )
  2658. {
  2659. peDxVideoPort->dwNextFieldToSkip--;
  2660. }
  2661. }
  2662. if( ( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_SKIPPED_LAST ) && !bSkipped )
  2663. {
  2664. // Tell the MiniPort to un-skip the next field
  2665. vDxSkip( peDxVideoPort, DDSKIP_ENABLENEXT );
  2666. peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_SKIPPED_LAST;
  2667. // This next part is a hack.We keep track of which fields
  2668. // to flip on in weave mode during the ISR, but what if we
  2669. // happen to miss an IRQ (due to DOS box, etc.)? We can't
  2670. // use to polarity to re-sync because field skipping screws
  2671. // that up, so this code assume that the repeat field will
  2672. // always be the last field of a frame and so the following
  2673. // field will be the first field. This will make it re-sync
  2674. // if we ever miss an IRQ.
  2675. peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_FLIP_NEXT;
  2676. }
  2677. // Now do all of the autoflipping
  2678. if( peDxVideoPort->flFlags & (DD_DXVIDEOPORT_FLAG_AUTOFLIP|
  2679. DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI|DD_DXVIDEOPORT_FLAG_BOB ) )
  2680. {
  2681. // Check for autoflipping the VBI surface in which case we
  2682. // don't care about the skip logic
  2683. if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI )
  2684. {
  2685. if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_VBI_INTERLEAVED )
  2686. {
  2687. if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_FLIP_NEXT_VBI )
  2688. {
  2689. peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_FLIP_NEXT_VBI;
  2690. vDxFlip( peDxVideoPort, DDVPFLIP_VBI );
  2691. }
  2692. else
  2693. {
  2694. peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_FLIP_NEXT_VBI;
  2695. }
  2696. }
  2697. else
  2698. {
  2699. peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_FLIP_NEXT_VBI;
  2700. vDxFlip( peDxVideoPort, DDVPFLIP_VBI );
  2701. }
  2702. }
  2703. // Autoflip the vhe video if we are not skipping this field
  2704. if( !bSkipped )
  2705. {
  2706. bFlipped = FALSE;
  2707. if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP )
  2708. {
  2709. if( peDxVideoPort->dwVPFlags & DDVP_INTERLEAVE )
  2710. {
  2711. if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_FLIP_NEXT )
  2712. {
  2713. peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_FLIP_NEXT;
  2714. if( !bAdjustFirstWeave )
  2715. {
  2716. vDxFlip( peDxVideoPort, DDVPFLIP_VIDEO );
  2717. bFlipped = TRUE;
  2718. }
  2719. }
  2720. else
  2721. {
  2722. peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_FLIP_NEXT;
  2723. }
  2724. }
  2725. else
  2726. {
  2727. vDxFlip( peDxVideoPort, DDVPFLIP_VIDEO );
  2728. bFlipped = TRUE;
  2729. peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_FLIP_NEXT;
  2730. }
  2731. }
  2732. // They may be bobbing even when not autoflipping
  2733. // (they may have one interleaved buffer that they
  2734. // use for bob - technically this is not a flip since
  2735. // only one surface is involved).
  2736. if( ( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_BOB ) &&
  2737. !bFlipped )
  2738. {
  2739. vDxBob( peDxVideoPort );
  2740. }
  2741. }
  2742. }
  2743. }
  2744. /******************************Public*Routine******************************\
  2745. * VOID DxBusmasterDpc
  2746. *
  2747. * This routine handles the video capture and is called when one of
  2748. * the buffers is filled. It figures out which one and then sets the
  2749. * compeletion event for that buffer.
  2750. *
  2751. * NOTE: The spinlock is already held.
  2752. *
  2753. * 10-Jan-1998 -by- Scott MacDonald [smac]
  2754. * Wrote it.
  2755. \**************************************************************************/
  2756. VOID
  2757. APIENTRY
  2758. DxBusmasterDpc(
  2759. DWORD dwEvent,
  2760. PVOID pContext,
  2761. DWORD dwParam1,
  2762. DWORD dwParam2
  2763. )
  2764. {
  2765. DDGETTRANSFERSTATUSOUTINFO ddGetTransferStatus;
  2766. EDD_DXVIDEOPORT* peDxVideoPort;
  2767. EDD_DXDIRECTDRAW* peDxDirectDraw;
  2768. EDD_DXCAPTURE* peDxCapture;
  2769. DWORD ddRVal;
  2770. ULONG_PTR dwTempId;
  2771. DWORD dwTempIndex;
  2772. // Call the miniport to get the transfer ID of the completed busmaster
  2773. ddRVal = DDERR_UNSUPPORTED;
  2774. peDxVideoPort = (EDD_DXVIDEOPORT*) pContext;
  2775. peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
  2776. if (peDxDirectDraw->DxApiInterface.DxGetTransferStatus)
  2777. {
  2778. ddRVal = peDxDirectDraw->DxApiInterface.DxGetTransferStatus(
  2779. peDxDirectDraw->HwDeviceExtension,
  2780. NULL,
  2781. &ddGetTransferStatus);
  2782. }
  2783. if( ddRVal == DD_OK )
  2784. {
  2785. // Find the capture object. It may not even be associated with this
  2786. // video port if multiple vidoe ports exist in the system.
  2787. dwTempId = ddGetTransferStatus.dwTransferID & ~0xf;
  2788. peDxCapture = peDxVideoPort->peDxCapture;
  2789. while (peDxCapture && (((ULONG_PTR)peDxCapture & ~0xf) != dwTempId))
  2790. {
  2791. peDxCapture = peDxCapture->peDxCaptureNext;
  2792. }
  2793. if (peDxCapture != NULL)
  2794. {
  2795. // We've found the capture object
  2796. dwTempIndex = (DWORD)(ddGetTransferStatus.dwTransferID & 0xf);
  2797. if (peDxCapture->CaptureQueue[dwTempIndex].flFlags & DD_DXCAPTUREBUFF_FLAG_WAITING )
  2798. {
  2799. peDxCapture->CaptureQueue[dwTempIndex].flFlags = 0;
  2800. KeSetEvent(peDxCapture->CaptureQueue[dwTempIndex].pBuffKEvent, 0, 0);
  2801. }
  2802. // Mark the lucky surface as being done w/ the transfer
  2803. peDxCapture->CaptureQueue[dwTempIndex].peDxSurface->flFlags
  2804. &= ~DD_DXSURFACE_FLAG_TRANSFER;
  2805. peDxCapture->CaptureQueue[dwTempIndex].peDxSurface = NULL;
  2806. }
  2807. }
  2808. }
  2809. /******************************Public*Routine******************************\
  2810. * VOID DxAutoflipUpdate
  2811. *
  2812. * This routine handles 'software autoflipping' and is called at dispatch
  2813. * level when the miniport's videoport interrupt is triggered. This routine
  2814. * can't be kept in 'win32k.sys' because it needs to be non-pageable.
  2815. *
  2816. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  2817. * Wrote it.
  2818. \**************************************************************************/
  2819. VOID
  2820. APIENTRY
  2821. DxAutoflipUpdate(
  2822. EDD_DXVIDEOPORT* peDxVideoPort,
  2823. EDD_DXSURFACE** apeDxSurfaceVideo,
  2824. ULONG cSurfacesVideo,
  2825. EDD_DXSURFACE** apeDxSurfaceVbi,
  2826. ULONG cSurfacesVbi
  2827. )
  2828. {
  2829. KIRQL OldIrql;
  2830. ULONG i;
  2831. KeAcquireSpinLock(&peDxVideoPort->peDxDirectDraw->SpinLock, &OldIrql);
  2832. peDxVideoPort->cAutoflipVideo = cSurfacesVideo;
  2833. for (i = 0; i < cSurfacesVideo; i++)
  2834. {
  2835. peDxVideoPort->apeDxSurfaceVideo[i] = apeDxSurfaceVideo[i];
  2836. peDxVideoPort->apeDxSurfaceVideo[i]->peDxVideoPort = peDxVideoPort;
  2837. }
  2838. peDxVideoPort->cAutoflipVbi = cSurfacesVbi;
  2839. for (i = 0; i < cSurfacesVbi; i++)
  2840. {
  2841. peDxVideoPort->apeDxSurfaceVbi[i] = apeDxSurfaceVbi[i];
  2842. peDxVideoPort->apeDxSurfaceVbi[i]->peDxVideoPort = peDxVideoPort;
  2843. }
  2844. KeReleaseSpinLock(&peDxVideoPort->peDxDirectDraw->SpinLock, OldIrql);
  2845. }
  2846. /******************************Public*Routine******************************\
  2847. * VOID DxLoseObject
  2848. *
  2849. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  2850. * Wrote it.
  2851. \**************************************************************************/
  2852. VOID
  2853. APIENTRY
  2854. DxLoseObject(
  2855. VOID* pvObject,
  2856. LOTYPE loType
  2857. )
  2858. {
  2859. KIRQL OldIrql;
  2860. EDD_DXDIRECTDRAW* peDxDirectDraw;
  2861. EDD_DXVIDEOPORT* peDxVideoPort;
  2862. EDD_DXSURFACE* peDxSurface;
  2863. EDD_DXCAPTURE* peDxCapture;
  2864. DXAPI_EVENT* pDxEvent;
  2865. DDENABLEIRQINFO EnableIrqInfo;
  2866. DWORD dwRet;
  2867. switch (loType)
  2868. {
  2869. case LO_DIRECTDRAW:
  2870. peDxDirectDraw = (EDD_DXDIRECTDRAW*) pvObject;
  2871. peDxDirectDraw->peDirectDrawGlobal->peDxDirectDraw = NULL; // Passive
  2872. KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
  2873. peDxDirectDraw->bLost = TRUE;
  2874. peDxDirectDraw->peDirectDrawGlobal = NULL;
  2875. if (peDxDirectDraw->DxApiInterface.DxEnableIrq)
  2876. {
  2877. // Make sure all IRQs are disabled
  2878. EnableIrqInfo.dwIRQSources = 0;
  2879. EnableIrqInfo.dwLine = 0;
  2880. EnableIrqInfo.IRQCallback = NULL;
  2881. EnableIrqInfo.lpIRQData = NULL;
  2882. peDxDirectDraw->DxApiInterface.DxEnableIrq(
  2883. peDxDirectDraw->HwDeviceExtension,
  2884. &EnableIrqInfo,
  2885. NULL);
  2886. }
  2887. KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
  2888. break;
  2889. case LO_VIDEOPORT:
  2890. peDxVideoPort = (EDD_DXVIDEOPORT*) pvObject;
  2891. peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
  2892. peDxVideoPort->peVideoPort->peDxVideoPort = NULL; // Passive
  2893. KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
  2894. peDxVideoPort->bLost = TRUE;
  2895. peDxVideoPort->peVideoPort = NULL;
  2896. peDxVideoPort->peDxCapture = NULL;
  2897. KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
  2898. break;
  2899. case LO_SURFACE:
  2900. peDxSurface = (EDD_DXSURFACE*) pvObject;
  2901. peDxDirectDraw = peDxSurface->peDxDirectDraw;
  2902. peDxSurface->peSurface->peDxSurface = NULL; // Passive
  2903. KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
  2904. peDxSurface->bLost = TRUE;
  2905. peDxSurface->peSurface = NULL;
  2906. peDxSurface->peDxVideoPort = NULL;
  2907. KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
  2908. break;
  2909. case LO_CAPTURE:
  2910. peDxCapture = (EDD_DXCAPTURE*) pvObject;
  2911. peDxVideoPort = peDxCapture->peDxVideoPort;
  2912. if( peDxVideoPort != NULL )
  2913. {
  2914. peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
  2915. KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
  2916. // First flush the capture buffers
  2917. DxInternalFlushVpCaptureBuffs( peDxDirectDraw, peDxVideoPort, peDxCapture );
  2918. // Disassociate the capture object from the video port
  2919. peDxCapture->peDxVideoPort = NULL;
  2920. peDxCapture->bLost = TRUE;
  2921. if( peDxVideoPort->peDxCapture == peDxCapture )
  2922. {
  2923. peDxVideoPort->peDxCapture = peDxCapture->peDxCaptureNext;
  2924. }
  2925. else
  2926. {
  2927. EDD_DXCAPTURE* peDxTemp;
  2928. for( peDxTemp = peDxVideoPort->peDxCapture;
  2929. ( peDxTemp != NULL ) &&
  2930. ( peDxTemp->peDxCaptureNext != peDxCapture );
  2931. peDxTemp = peDxTemp->peDxCaptureNext );
  2932. if( peDxTemp != NULL )
  2933. {
  2934. peDxTemp->peDxCaptureNext = peDxCapture->peDxCaptureNext;
  2935. }
  2936. else
  2937. {
  2938. RIPDX("Capture object not in video port list");
  2939. }
  2940. }
  2941. // If there are no more capture objects associated with the
  2942. // video port, remove the video port from the capture list.
  2943. pDxEvent = NULL;
  2944. if( peDxVideoPort->peDxCapture == NULL )
  2945. {
  2946. if( peDxDirectDraw->pDxEvent_CaptureList->peDxVideoPort == peDxVideoPort )
  2947. {
  2948. pDxEvent = peDxDirectDraw->pDxEvent_CaptureList;
  2949. peDxDirectDraw->pDxEvent_CaptureList = pDxEvent->pDxEvent_Next;
  2950. }
  2951. else
  2952. {
  2953. for( pDxEvent = peDxDirectDraw->pDxEvent_CaptureList;
  2954. (pDxEvent != NULL) &&
  2955. (pDxEvent->pDxEvent_Next->peDxVideoPort != peDxVideoPort);
  2956. pDxEvent = pDxEvent->pDxEvent_Next );
  2957. if( pDxEvent != NULL )
  2958. {
  2959. pDxEvent->pDxEvent_Next =
  2960. pDxEvent->pDxEvent_Next->pDxEvent_Next;
  2961. pDxEvent = pDxEvent->pDxEvent_Next;
  2962. }
  2963. }
  2964. }
  2965. KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
  2966. if( pDxEvent != NULL )
  2967. {
  2968. ExFreePool(pDxEvent);
  2969. }
  2970. }
  2971. break;
  2972. default:
  2973. RIPDX("Unexpected type");
  2974. }
  2975. }
  2976. /******************************Public*Routine******************************\
  2977. * VOID DxUpdateCapture
  2978. *
  2979. * This routine inserts capture devices intot he list handling off of the
  2980. * video port. Since this list is walked at DPC level, we need to
  2981. * synchronize this with the DPC.
  2982. *
  2983. * 10-Jan-1997 -by- Scott MacDonald [smac]
  2984. * Wrote it.
  2985. \**************************************************************************/
  2986. VOID
  2987. APIENTRY
  2988. DxUpdateCapture(
  2989. EDD_DXVIDEOPORT* peDxVideoPort,
  2990. EDD_DXCAPTURE* peDxCapture,
  2991. BOOL bRemove
  2992. )
  2993. {
  2994. KIRQL OldIrql;
  2995. EDD_DXCAPTURE* peDxTemp;
  2996. EDD_DXDIRECTDRAW* peDxDirectDraw;
  2997. DXAPI_EVENT* pDxEvent_New;
  2998. DXAPI_EVENT* pDxEvent_Temp = NULL;
  2999. DWORD dwRet;
  3000. // If adding to the list, also an event to the capture list so we
  3001. // can get the busmaster complete notification. Allocate the
  3002. // memory for this now.
  3003. peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
  3004. if( !bRemove )
  3005. {
  3006. pDxEvent_New = (DXAPI_EVENT*) ExAllocatePoolWithTag(NonPagedPool,
  3007. sizeof(*pDxEvent_New),
  3008. 'eddG');
  3009. if (pDxEvent_New == NULL)
  3010. return;
  3011. RtlZeroMemory(pDxEvent_New, sizeof(*pDxEvent_New));
  3012. pDxEvent_New->peDxDirectDraw = peDxDirectDraw;
  3013. pDxEvent_New->peDxVideoPort = peDxVideoPort;
  3014. pDxEvent_New->pfnCallBack = (LPDD_NOTIFYCALLBACK) DxBusmasterDpc;
  3015. pDxEvent_New->pContext = peDxVideoPort;
  3016. }
  3017. KeAcquireSpinLock(&peDxVideoPort->peDxDirectDraw->SpinLock, &OldIrql);
  3018. if( bRemove )
  3019. {
  3020. // First flush the capture buffers
  3021. DxInternalFlushVpCaptureBuffs( peDxDirectDraw, peDxVideoPort, peDxCapture );
  3022. // Disassociate the capture object with the video port
  3023. if( peDxVideoPort->peDxCapture == peDxCapture )
  3024. {
  3025. peDxVideoPort->peDxCapture = peDxCapture->peDxCaptureNext;
  3026. }
  3027. else
  3028. {
  3029. for( peDxTemp = peDxVideoPort->peDxCapture;
  3030. ( peDxTemp != NULL ) &&
  3031. ( peDxTemp->peDxCaptureNext != peDxCapture );
  3032. peDxTemp = peDxTemp->peDxCaptureNext );
  3033. if( peDxTemp != NULL )
  3034. {
  3035. peDxTemp->peDxCaptureNext = peDxCapture->peDxCaptureNext;
  3036. }
  3037. }
  3038. peDxCapture->peDxVideoPort = NULL;
  3039. // If there are no more capture objects associated with the
  3040. // video port, remove the video port from the capture list.
  3041. if( peDxVideoPort->peDxCapture == NULL )
  3042. {
  3043. pDxEvent_Temp = NULL;
  3044. if( peDxDirectDraw->pDxEvent_CaptureList->peDxVideoPort == peDxVideoPort )
  3045. {
  3046. pDxEvent_Temp = peDxDirectDraw->pDxEvent_CaptureList;
  3047. peDxDirectDraw->pDxEvent_CaptureList = pDxEvent_Temp->pDxEvent_Next;
  3048. }
  3049. else
  3050. {
  3051. for( pDxEvent_Temp = peDxDirectDraw->pDxEvent_CaptureList;
  3052. (pDxEvent_Temp != NULL) &&
  3053. (pDxEvent_Temp->pDxEvent_Next->peDxVideoPort != NULL);
  3054. pDxEvent_Temp = pDxEvent_Temp->pDxEvent_Next );
  3055. if( pDxEvent_Temp != NULL )
  3056. {
  3057. pDxEvent_Temp->pDxEvent_Next =
  3058. pDxEvent_Temp->pDxEvent_Next->pDxEvent_Next;
  3059. pDxEvent_Temp = pDxEvent_Temp->pDxEvent_Next;
  3060. }
  3061. }
  3062. }
  3063. }
  3064. else
  3065. {
  3066. // Associate the capture object with the video port
  3067. peDxCapture->peDxCaptureNext = peDxVideoPort->peDxCapture;
  3068. peDxVideoPort->peDxCapture = peDxCapture;
  3069. // Add an event to the capture list so we can get the busmaster
  3070. // complete notification. First check to see if it's already in
  3071. // in the list.
  3072. for (pDxEvent_Temp = peDxDirectDraw->pDxEvent_CaptureList;
  3073. pDxEvent_Temp != NULL;
  3074. pDxEvent_Temp = pDxEvent_Temp->pDxEvent_Next)
  3075. {
  3076. if (pDxEvent_Temp->peDxVideoPort == peDxVideoPort)
  3077. {
  3078. break;
  3079. }
  3080. }
  3081. if( pDxEvent_Temp == NULL )
  3082. {
  3083. // Not already in list - add it
  3084. pDxEvent_New->pDxEvent_Next = peDxDirectDraw->pDxEvent_CaptureList;
  3085. peDxDirectDraw->pDxEvent_CaptureList = pDxEvent_New;
  3086. }
  3087. }
  3088. KeReleaseSpinLock(&peDxVideoPort->peDxDirectDraw->SpinLock, OldIrql);
  3089. if( bRemove && ( pDxEvent_Temp != NULL ) )
  3090. {
  3091. ExFreePool(pDxEvent_Temp);
  3092. }
  3093. else if( pDxEvent_Temp != NULL )
  3094. {
  3095. ExFreePool(pDxEvent_New);
  3096. }
  3097. }
  3098. /******************************Public*Routine******************************\
  3099. * DWORD DxOpenDirectDraw
  3100. *
  3101. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  3102. * Wrote it.
  3103. \**************************************************************************/
  3104. VOID
  3105. APIENTRY
  3106. DxOpenDirectDraw(
  3107. DDOPENDIRECTDRAWIN* pOpenDirectDrawIn,
  3108. DDOPENDIRECTDRAWOUT* pOpenDirectDrawOut
  3109. )
  3110. {
  3111. pOpenDirectDrawOut->ddRVal = DDERR_UNSUPPORTED;
  3112. if (pOpenDirectDrawIn != NULL)
  3113. {
  3114. if (gpfnOpenDirectDraw != NULL)
  3115. {
  3116. gpfnOpenDirectDraw(pOpenDirectDrawIn,
  3117. pOpenDirectDrawOut,
  3118. DxEventDpc,
  3119. DXAPI_PRIVATE_VERSION_NUMBER);
  3120. }
  3121. }
  3122. }
  3123. /******************************Public*Routine******************************\
  3124. * VOID DxEnableIRQ
  3125. *
  3126. * This routine enables/disables the video port VSYNC IRQ and is
  3127. * is called at dispatch level.
  3128. *
  3129. * 17-Oct-1997 -by- smac
  3130. * Wrote it.
  3131. \**************************************************************************/
  3132. VOID
  3133. APIENTRY
  3134. DxEnableIRQ(
  3135. EDD_DXVIDEOPORT* peDxVideoPort,
  3136. BOOL bEnable
  3137. )
  3138. {
  3139. EDD_DXDIRECTDRAW* peDxDirectDraw;
  3140. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  3141. DWORD dwBit;
  3142. peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
  3143. peDirectDrawGlobal = peDxDirectDraw->peDirectDrawGlobal;
  3144. dwBit = DDIRQ_VPORT0_VSYNC << ( peDxVideoPort->dwVideoPortID * 2);
  3145. /*
  3146. * Don't enable or disable of the IRQ isn't supported
  3147. */
  3148. if( ( peDirectDrawGlobal != NULL ) &&
  3149. ( peDirectDrawGlobal->DDKernelCaps.dwIRQCaps & dwBit ) )
  3150. {
  3151. if( bEnable )
  3152. {
  3153. if( !( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_REGISTERED_IRQ ) )
  3154. {
  3155. bDxModifyDispatchEventList(peDxDirectDraw,
  3156. peDxVideoPort,
  3157. bEnable,
  3158. DDEVENT_VP_VSYNC,
  3159. dwBit,
  3160. (LPDD_NOTIFYCALLBACK) DxAutoflipDpc,
  3161. (PVOID)peDxVideoPort,
  3162. INTERNAL_DISPATCH_LIST);
  3163. peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_REGISTERED_IRQ;
  3164. }
  3165. }
  3166. else
  3167. {
  3168. if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_REGISTERED_IRQ )
  3169. {
  3170. bDxModifyDispatchEventList(peDxDirectDraw,
  3171. peDxVideoPort,
  3172. bEnable,
  3173. DDEVENT_VP_VSYNC,
  3174. dwBit,
  3175. (LPDD_NOTIFYCALLBACK) DxAutoflipDpc,
  3176. (PVOID)peDxVideoPort,
  3177. INTERNAL_DISPATCH_LIST);
  3178. peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_REGISTERED_IRQ;
  3179. }
  3180. }
  3181. vDxEnableInterrupts( peDxDirectDraw, 0 );
  3182. }
  3183. }
  3184. /******************************Public*Routine******************************\
  3185. * DxApi
  3186. *
  3187. * Single entry point for all DXAPI.SYS public functionality.
  3188. *
  3189. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  3190. * Wrote it.
  3191. \**************************************************************************/
  3192. typedef VOID (APIENTRY* PDX_FUNCTION)(VOID*, VOID*);
  3193. typedef struct _DXAPI_ENTRY_POINT {
  3194. PDX_FUNCTION pfn;
  3195. DWORD cInBuffer;
  3196. DWORD cOutBuffer;
  3197. BOOLEAN bMapProcess;
  3198. } DXAPI_ENTRY_POINT;
  3199. #define DX(fn, structin, structout, boolean) \
  3200. (PDX_FUNCTION) fn, structin, sizeof(structout), boolean
  3201. DXAPI_ENTRY_POINT gDxApiEntryPoint[] = {
  3202. DX(DxGetVersionNumber, 0, DDGETVERSIONNUMBER, FALSE ), // 0
  3203. DX(NULL, sizeof(DDCLOSEHANDLE), DWORD, TRUE ), // 1
  3204. DX(DxOpenDirectDraw, sizeof(DDOPENDIRECTDRAWIN), DDOPENDIRECTDRAWOUT, FALSE ), // 2
  3205. DX(NULL, sizeof(DDOPENSURFACEIN), DDOPENSURFACEOUT, TRUE ), // 3
  3206. DX(NULL, sizeof(DDOPENVIDEOPORTIN), DDOPENVIDEOPORTOUT, TRUE ), // 4
  3207. DX(NULL, sizeof(DWORD), DDGETKERNELCAPSOUT, TRUE ), // 5
  3208. DX(DxGetFieldNumber, sizeof(DDGETFIELDNUMIN), DDGETFIELDNUMOUT, FALSE ), // 6
  3209. DX(DxSetFieldNumber, sizeof(DDSETFIELDNUM), DWORD, FALSE ), // 7
  3210. DX(DxSetSkipPattern, sizeof(DDSETSKIPFIELD), DWORD, FALSE ), // 8
  3211. DX(DxGetSurfaceState, sizeof(DDGETSURFACESTATEIN), DDGETSURFACESTATEOUT, FALSE ), // 9
  3212. DX(DxSetSurfaceState, sizeof(DDSETSURFACESTATE), DWORD, FALSE ), // 10
  3213. DX(DxLock, sizeof(DDLOCKIN), DDLOCKOUT, FALSE ), // 11
  3214. DX(DxFlipOverlay, sizeof(DDFLIPOVERLAY), DWORD, FALSE ), // 12
  3215. DX(DxFlipVideoPort, sizeof(DDFLIPVIDEOPORT), DWORD, FALSE ), // 13
  3216. DX(DxGetCurrentAutoflip, sizeof(DDGETAUTOFLIPIN), DDGETAUTOFLIPOUT, FALSE ), // 14
  3217. DX(DxGetPreviousAutoflip, sizeof(DDGETAUTOFLIPIN), DDGETAUTOFLIPOUT, FALSE ), // 15
  3218. DX(DxRegisterEvent, sizeof(DDREGISTERCALLBACK), DWORD, FALSE ), // 16
  3219. DX(DxUnregisterEvent, sizeof(DDREGISTERCALLBACK), DWORD, FALSE ), // 17
  3220. DX(DxGetPolarity, sizeof(DDGETPOLARITYIN), DDGETPOLARITYOUT, FALSE ), // 18
  3221. DX(NULL, sizeof(DDOPENVPCAPTUREDEVICEIN),DDOPENVPCAPTUREDEVICEOUT, TRUE ), // 19
  3222. DX(DxAddVpCaptureBuffer, sizeof(DDADDVPCAPTUREBUFF), DWORD, FALSE ), // 20
  3223. DX(DxFlushVpCaptureBuffs, sizeof(DWORD), DWORD, FALSE ), // 21
  3224. };
  3225. DWORD
  3226. APIENTRY
  3227. DxApi(
  3228. DWORD iFunction,
  3229. VOID* pInBuffer,
  3230. DWORD cInBuffer,
  3231. VOID* pOutBuffer,
  3232. DWORD cOutBuffer
  3233. )
  3234. {
  3235. DWORD dwRet;
  3236. BOOL bProcessAttached = FALSE;
  3237. dwRet = 0;
  3238. iFunction -= DD_FIRST_DXAPI;
  3239. if ((iFunction >= sizeof(gDxApiEntryPoint) / sizeof(DXAPI_ENTRY_POINT)) ||
  3240. (gDxApiEntryPoint[iFunction].pfn == NULL))
  3241. {
  3242. KdPrint(("DxApi: Invalid function\n"));
  3243. }
  3244. else if ((cInBuffer < gDxApiEntryPoint[iFunction].cInBuffer) ||
  3245. (cOutBuffer < gDxApiEntryPoint[iFunction].cOutBuffer))
  3246. {
  3247. KdPrint(("DxApi: Input or output buffer too small\n"));
  3248. }
  3249. else if (pOutBuffer == NULL)
  3250. {
  3251. KdPrint(("DxApi: Invalid output buffer specified\n"));
  3252. }
  3253. else
  3254. {
  3255. if (gDxApiEntryPoint[iFunction].bMapProcess)
  3256. {
  3257. PEPROCESS pepSession;
  3258. switch (iFunction)
  3259. {
  3260. case (DD_DXAPI_CLOSEHANDLE - DD_FIRST_DXAPI):
  3261. case (DD_DXAPI_OPENSURFACE - DD_FIRST_DXAPI):
  3262. case (DD_DXAPI_OPENVIDEOPORT - DD_FIRST_DXAPI):
  3263. case (DD_DXAPI_OPENVPCAPTUREDEVICE - DD_FIRST_DXAPI):
  3264. // pInBuffer is a pointer to a structure that has
  3265. // a pointer to DXOBJ as its first element.
  3266. pepSession = ((DXOBJ *)(*(HANDLE *)pInBuffer))->pepSession;
  3267. break;
  3268. case (DD_DXAPI_GETKERNELCAPS - DD_FIRST_DXAPI):
  3269. // pInBuffer is a pointer to DXOBJ.
  3270. pepSession = ((DXOBJ *)pInBuffer)->pepSession;
  3271. break;
  3272. default:
  3273. return (dwRet);
  3274. }
  3275. if (!KeIsAttachedProcess())
  3276. {
  3277. KeAttachProcess(PsGetProcessPcb(pepSession));
  3278. bProcessAttached = TRUE;
  3279. }
  3280. }
  3281. // The return value is the size of the output buffer:
  3282. dwRet = gDxApiEntryPoint[iFunction].cOutBuffer;
  3283. // Call the actual routine:
  3284. gDxApiEntryPoint[iFunction].pfn(pInBuffer, pOutBuffer);
  3285. if (bProcessAttached)
  3286. {
  3287. KeDetachProcess();
  3288. }
  3289. }
  3290. return(dwRet);
  3291. }
  3292. /******************************Public*Routine******************************\
  3293. * VOID DxApiInitialize
  3294. *
  3295. * Called by win32k.sys to initialize dxapi.sys state.
  3296. *
  3297. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  3298. * Wrote it.
  3299. \**************************************************************************/
  3300. VOID
  3301. APIENTRY
  3302. DxApiInitialize(
  3303. PFNDXAPIOPENDIRECTDRAW pfnOpenDirectDraw,
  3304. PFNDXAPIOPENVIDEOPORT pfnOpenVideoPort,
  3305. PFNDXAPIOPENSURFACE pfnOpenSurface,
  3306. PFNDXAPICLOSEHANDLE pfnCloseHandle,
  3307. PFNDXAPIGETKERNELCAPS pfnGetKernelCaps,
  3308. PFNDXAPIOPENCAPTUREDEVICE pfnOpenCaptureDevice,
  3309. PFNDXAPILOCKDEVICE pfnLockDevice,
  3310. PFNDXAPIUNLOCKDEVICE pfnUnlockDevice
  3311. )
  3312. {
  3313. gpfnOpenDirectDraw = pfnOpenDirectDraw;
  3314. gpfnLockDevice = pfnLockDevice;
  3315. gpfnUnlockDevice = pfnUnlockDevice;
  3316. gDxApiEntryPoint[DD_DXAPI_OPENVIDEOPORT - DD_FIRST_DXAPI].pfn
  3317. = (PDX_FUNCTION) pfnOpenVideoPort;
  3318. gDxApiEntryPoint[DD_DXAPI_OPENSURFACE - DD_FIRST_DXAPI].pfn
  3319. = (PDX_FUNCTION) pfnOpenSurface;
  3320. gDxApiEntryPoint[DD_DXAPI_CLOSEHANDLE - DD_FIRST_DXAPI].pfn
  3321. = (PDX_FUNCTION) pfnCloseHandle;
  3322. gDxApiEntryPoint[DD_DXAPI_GETKERNELCAPS - DD_FIRST_DXAPI].pfn
  3323. = (PDX_FUNCTION) pfnGetKernelCaps;
  3324. gDxApiEntryPoint[DD_DXAPI_OPENVPCAPTUREDEVICE - DD_FIRST_DXAPI].pfn
  3325. = (PDX_FUNCTION) pfnOpenCaptureDevice;
  3326. }
  3327. /******************************Public*Routine******************************\
  3328. * ULONG DxApiGetVersion
  3329. *
  3330. * The original Memphis DXAPI had this entry point and although it doesn't
  3331. * do anything usefull, some drivers called it so we have to support it
  3332. * for those drivers to load. It does not return a real version number
  3333. * because the original incorrectly returned the DSOUND version 4.02,
  3334. * which has no correlation to the DxApi version number. If we return the
  3335. * real version, however, we risk breaking drivers.
  3336. *
  3337. * 16-Apr-1998 -by- Scott MacDonald [smac]
  3338. * Wrote it.
  3339. \**************************************************************************/
  3340. ULONG
  3341. APIENTRY
  3342. DxApiGetVersion(
  3343. VOID
  3344. )
  3345. {
  3346. return( 0x402 );
  3347. }