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.

1531 lines
41 KiB

  1. /*==========================================================================
  2. * Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
  3. *
  4. * File: ddkernel.c
  5. * Content: APIs for getting the kernel mode handles for
  6. * DirectDraw and the surfaces
  7. * History:
  8. * Date By Reason
  9. * ==== == ======
  10. * 09-jan-97 smac created
  11. *
  12. ***************************************************************************/
  13. #include "ddrawpr.h"
  14. #ifdef WINNT
  15. #include "ddrawgdi.h"
  16. #include "ddkmmini.h"
  17. #include "ddkmapi.h"
  18. #else
  19. #include "minivdd.h"
  20. #include "ddkmmini.h"
  21. #include "ddkmapip.h"
  22. #endif
  23. #define DPF_MODNAME "DirectDrawVideoPort"
  24. #define DISPLAY_STR "display"
  25. extern char g_szPrimaryDisplay[]; // usually \\.\Display1 on Win98
  26. #if WIN95
  27. /*
  28. * IsWindows98
  29. */
  30. BOOL IsWindows98( VOID )
  31. {
  32. OSVERSIONINFO osVer;
  33. osVer.dwOSVersionInfoSize = sizeof( osVer );
  34. osVer.dwMinorVersion = 0;
  35. GetVersionEx( &osVer );
  36. return( ( osVer.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) &&
  37. ( osVer.dwMinorVersion > 0 ) );
  38. }
  39. /*
  40. * SyncKernelSurface
  41. *
  42. * Initializes the buffer with the kernel surface info and then gives
  43. * it to the HAL so they can make whatever modifications are neccesary
  44. * and to fill in the dwDriverReserved fields with their internal state
  45. * data.
  46. */
  47. HRESULT SyncKernelSurface( LPDDRAWI_DDRAWSURFACE_LCL lpSurface,
  48. LPDDKMSURFACEINFO lpddkmSurfaceInfo )
  49. {
  50. LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
  51. DDHAL_SYNCSURFACEDATA HALSurfaceData;
  52. LPDDHALKERNELCB_SYNCSURFACE pfn;
  53. LPDDPIXELFORMAT lpddpfFormat;
  54. DWORD rc;
  55. /*
  56. * Determine the default data the best that we can
  57. */
  58. memset( &HALSurfaceData, 0, sizeof( HALSurfaceData ) );
  59. HALSurfaceData.dwSize = sizeof( HALSurfaceData );
  60. HALSurfaceData.lpDD = lpSurface->lpSurfMore->lpDD_lcl;
  61. HALSurfaceData.lpDDSurface = lpSurface;
  62. HALSurfaceData.dwSurfaceOffset = 0;
  63. HALSurfaceData.fpLockPtr = lpSurface->lpGbl->fpVidMem;
  64. HALSurfaceData.lPitch = (DWORD) lpSurface->lpGbl->lPitch;
  65. HALSurfaceData.dwOverlayOffset = 0;
  66. if( lpSurface->ddsCaps.dwCaps & DDSCAPS_OVERLAY )
  67. {
  68. HALSurfaceData.dwOverlaySrcWidth =
  69. lpSurface->rcOverlaySrc.right -
  70. lpSurface->rcOverlaySrc.left;
  71. HALSurfaceData.dwOverlaySrcHeight =
  72. lpSurface->rcOverlaySrc.bottom -
  73. lpSurface->rcOverlaySrc.top;
  74. HALSurfaceData.dwOverlayDestWidth =
  75. lpSurface->rcOverlayDest.right -
  76. lpSurface->rcOverlayDest.left;
  77. HALSurfaceData.dwOverlayDestHeight =
  78. lpSurface->rcOverlayDest.bottom -
  79. lpSurface->rcOverlayDest.top;
  80. }
  81. else
  82. {
  83. HALSurfaceData.dwOverlaySrcWidth = 0;
  84. HALSurfaceData.dwOverlaySrcHeight = 0;
  85. HALSurfaceData.dwOverlayDestWidth = 0;
  86. HALSurfaceData.dwOverlayDestHeight = 0;
  87. }
  88. /*
  89. * Now call the HAL and have it fill in the rest of the values
  90. */
  91. pfn = lpSurface->lpSurfMore->lpDD_lcl->lpDDCB->HALDDKernel.SyncSurfaceData;
  92. if( pfn != NULL )
  93. {
  94. DOHALCALL( SyncSurfaceData, pfn, HALSurfaceData, rc, 0 );
  95. if( DDHAL_DRIVER_HANDLED != rc )
  96. {
  97. return DDERR_UNSUPPORTED;
  98. }
  99. else if( DD_OK != HALSurfaceData.ddRVal )
  100. {
  101. return (HRESULT)rc;
  102. }
  103. }
  104. else
  105. {
  106. return DDERR_UNSUPPORTED;
  107. }
  108. /*
  109. * Now put all of the data into a structure that the VDD can understand
  110. */
  111. lpddkmSurfaceInfo->ddsCaps = lpSurface->ddsCaps.dwCaps;
  112. lpddkmSurfaceInfo->dwSurfaceOffset = HALSurfaceData.dwSurfaceOffset;
  113. lpddkmSurfaceInfo->fpLockPtr = HALSurfaceData.fpLockPtr;
  114. lpddkmSurfaceInfo->dwWidth = (DWORD) lpSurface->lpGbl->wWidth;
  115. lpddkmSurfaceInfo->dwHeight = (DWORD) lpSurface->lpGbl->wHeight;
  116. lpddkmSurfaceInfo->lPitch = HALSurfaceData.lPitch;
  117. lpddkmSurfaceInfo->dwOverlayFlags = lpSurface->lpSurfMore->dwOverlayFlags;
  118. lpddkmSurfaceInfo->dwOverlayOffset = HALSurfaceData.dwOverlayOffset;
  119. lpddkmSurfaceInfo->dwOverlaySrcWidth = HALSurfaceData.dwOverlaySrcWidth;
  120. lpddkmSurfaceInfo->dwOverlaySrcHeight = HALSurfaceData.dwOverlaySrcHeight;
  121. lpddkmSurfaceInfo->dwOverlayDestWidth = HALSurfaceData.dwOverlayDestWidth;
  122. lpddkmSurfaceInfo->dwOverlayDestHeight = HALSurfaceData.dwOverlayDestHeight;
  123. lpddkmSurfaceInfo->dwDriverReserved1 = HALSurfaceData.dwDriverReserved1;
  124. lpddkmSurfaceInfo->dwDriverReserved2 = HALSurfaceData.dwDriverReserved2;
  125. lpddkmSurfaceInfo->dwDriverReserved3 = HALSurfaceData.dwDriverReserved3;
  126. if( lpSurface->lpSurfMore->lpVideoPort == NULL )
  127. {
  128. lpddkmSurfaceInfo->dwVideoPortId = (DWORD)-1;
  129. }
  130. else
  131. {
  132. lpddkmSurfaceInfo->dwVideoPortId =
  133. lpSurface->lpSurfMore->lpVideoPort->ddvpDesc.dwVideoPortID;
  134. }
  135. lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( lpSurface->lpGbl );
  136. lpddkmSurfaceInfo->dwPhysicalPageTable = lpSurfGblMore->dwPhysicalPageTable;
  137. lpddkmSurfaceInfo->pPageTable = (DWORD)lpSurfGblMore->pPageTable;
  138. lpddkmSurfaceInfo->cPages = lpSurfGblMore->cPages;
  139. GET_PIXEL_FORMAT( lpSurface, lpSurface->lpGbl, lpddpfFormat );
  140. if( lpddpfFormat != NULL )
  141. {
  142. lpddkmSurfaceInfo->dwFormatFlags = lpddpfFormat->dwFlags;
  143. lpddkmSurfaceInfo->dwFormatFourCC = lpddpfFormat->dwFourCC;
  144. lpddkmSurfaceInfo->dwFormatBitCount = lpddpfFormat->dwRGBBitCount;
  145. lpddkmSurfaceInfo->dwRBitMask = lpddpfFormat->dwRBitMask;
  146. lpddkmSurfaceInfo->dwGBitMask = lpddpfFormat->dwGBitMask;
  147. lpddkmSurfaceInfo->dwBBitMask = lpddpfFormat->dwBBitMask;
  148. }
  149. return DD_OK;
  150. }
  151. /*
  152. * SyncKernelVideoPort
  153. *
  154. * Initializes the buffer with the kernel video port info and then gives
  155. * it to the HAL so they can make whatever modifications are neccesary
  156. * and to fill in the dwDriverReserved fields with their internal state
  157. * data.
  158. */
  159. HRESULT SyncKernelVideoPort( LPDDRAWI_DDVIDEOPORT_LCL lpVideoPort,
  160. LPDDKMVIDEOPORTINFO lpddkmVideoPortInfo )
  161. {
  162. LPDDHALKERNELCB_SYNCVIDEOPORT pfn;
  163. DDHAL_SYNCVIDEOPORTDATA HALVideoPortData;
  164. DWORD rc;
  165. /*
  166. * Determine the default data the best that we can
  167. */
  168. memset( &HALVideoPortData, 0, sizeof( HALVideoPortData ) );
  169. HALVideoPortData.dwSize = sizeof( HALVideoPortData );
  170. HALVideoPortData.lpDD = lpVideoPort->lpDD;
  171. HALVideoPortData.lpVideoPort = lpVideoPort;
  172. HALVideoPortData.dwOriginOffset = 0;
  173. if( lpVideoPort->ddvpInfo.dwVPFlags & DDVP_PRESCALE )
  174. {
  175. HALVideoPortData.dwHeight = lpVideoPort->ddvpInfo.dwPrescaleHeight;
  176. }
  177. else if( lpVideoPort->ddvpInfo.dwVPFlags & DDVP_CROP )
  178. {
  179. HALVideoPortData.dwHeight = lpVideoPort->ddvpInfo.rCrop.bottom -
  180. lpVideoPort->ddvpInfo.rCrop.top;
  181. }
  182. else
  183. {
  184. HALVideoPortData.dwHeight = lpVideoPort->ddvpDesc.dwFieldHeight;
  185. }
  186. if( lpVideoPort->ddvpInfo.dwVPFlags & DDVP_INTERLEAVE )
  187. {
  188. HALVideoPortData.dwHeight *= 2;
  189. }
  190. HALVideoPortData.dwVBIHeight = lpVideoPort->ddvpInfo.dwVBIHeight;
  191. /*
  192. * Now call the HAL and have it fill in the rest of the values
  193. */
  194. pfn = lpVideoPort->lpDD->lpDDCB->HALDDKernel.SyncVideoPortData;
  195. if( pfn != NULL )
  196. {
  197. DOHALCALL( SyncVideoPortData, pfn, HALVideoPortData, rc, 0 );
  198. if( DDHAL_DRIVER_HANDLED != rc )
  199. {
  200. return DDERR_UNSUPPORTED;
  201. }
  202. else if( DD_OK != HALVideoPortData.ddRVal )
  203. {
  204. return (HRESULT)rc;
  205. }
  206. }
  207. else
  208. {
  209. return DDERR_UNSUPPORTED;
  210. }
  211. /*
  212. * Now put all of the data into a structure that the VDD can understand
  213. */
  214. lpddkmVideoPortInfo->dwOriginOffset = HALVideoPortData.dwOriginOffset;
  215. lpddkmVideoPortInfo->dwHeight = HALVideoPortData.dwHeight;
  216. lpddkmVideoPortInfo->dwVBIHeight = HALVideoPortData.dwVBIHeight;
  217. lpddkmVideoPortInfo->dwDriverReserved1 = HALVideoPortData.dwDriverReserved1;
  218. lpddkmVideoPortInfo->dwDriverReserved2 = HALVideoPortData.dwDriverReserved2;
  219. lpddkmVideoPortInfo->dwDriverReserved3 = HALVideoPortData.dwDriverReserved3;
  220. return DD_OK;
  221. }
  222. /*
  223. * UpdateKernelSurface
  224. */
  225. HRESULT UpdateKernelSurface( LPDDRAWI_DDRAWSURFACE_LCL lpSurface )
  226. {
  227. LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
  228. HANDLE hDeviceHandle;
  229. DWORD ddRVal;
  230. if( !IsKernelInterfaceSupported( lpSurface->lpSurfMore->lpDD_lcl ) )
  231. {
  232. return DDERR_UNSUPPORTED;
  233. }
  234. lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( lpSurface->lpGbl );
  235. if( lpSurfGblMore->hKernelSurface == 0 )
  236. {
  237. return DDERR_GENERIC;
  238. }
  239. else
  240. {
  241. DDKMSURFACEUPDATE ddkmSurfaceInfo;
  242. DWORD dwReturned;
  243. hDeviceHandle = GETDDVXDHANDLE( lpSurface->lpSurfMore->lpDD_lcl );
  244. if( INVALID_HANDLE_VALUE == hDeviceHandle )
  245. {
  246. return DDERR_UNSUPPORTED;
  247. }
  248. /*
  249. * Get/sync the surface info
  250. */
  251. ddRVal = SyncKernelSurface( lpSurface, &(ddkmSurfaceInfo.si) );
  252. if( ddRVal != DD_OK )
  253. {
  254. DPF( 0, "Unable to sync surface data with HAL" );
  255. return ddRVal;
  256. }
  257. /*
  258. * Get the handle from the VDD
  259. */
  260. ddkmSurfaceInfo.dwDirectDrawHandle =
  261. lpSurface->lpSurfMore->lpDD_lcl->lpGbl->hKernelHandle;
  262. ddkmSurfaceInfo.dwSurfaceHandle =
  263. lpSurfGblMore->hKernelSurface;
  264. ddRVal = (DWORD) DDERR_GENERIC;
  265. DeviceIoControl( hDeviceHandle,
  266. DD_DXAPI_UPDATE_SURFACE_INFO,
  267. &ddkmSurfaceInfo,
  268. sizeof( ddkmSurfaceInfo ),
  269. &ddRVal,
  270. sizeof( ddRVal ),
  271. &dwReturned,
  272. NULL);
  273. if( ddRVal != DD_OK )
  274. {
  275. DPF( 0, "Unable to update the surface info" );
  276. return DDERR_UNSUPPORTED;
  277. }
  278. }
  279. return DD_OK;
  280. }
  281. /*
  282. * GetKernelSurfaceState
  283. */
  284. HRESULT GetKernelSurfaceState( LPDDRAWI_DDRAWSURFACE_LCL lpSurf, LPDWORD lpdwStateFlags )
  285. {
  286. DDGETSURFACESTATEIN ddStateInput;
  287. DDGETSURFACESTATEOUT ddStateOutput;
  288. LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
  289. HANDLE hDeviceHandle;
  290. DWORD dwReturned;
  291. *lpdwStateFlags = 0;
  292. if( !IsKernelInterfaceSupported( lpSurf->lpSurfMore->lpDD_lcl ) )
  293. {
  294. return DDERR_UNSUPPORTED;
  295. }
  296. hDeviceHandle = GETDDVXDHANDLE( lpSurf->lpSurfMore->lpDD_lcl );
  297. if( INVALID_HANDLE_VALUE == hDeviceHandle )
  298. {
  299. return DDERR_UNSUPPORTED;
  300. }
  301. /*
  302. * Send the new info down to the VDD
  303. */
  304. lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( lpSurf->lpGbl );
  305. ddStateInput.hDirectDraw = (HANDLE)
  306. (lpSurf->lpSurfMore->lpDD_lcl->lpGbl->hKernelHandle);
  307. ddStateInput.hSurface = (HANDLE)
  308. (lpSurfGblMore->hKernelSurface);
  309. ddStateOutput.ddRVal = (DWORD) DDERR_GENERIC;
  310. DeviceIoControl( hDeviceHandle,
  311. DD_DXAPI_PRIVATE_GET_SURFACE_STATE,
  312. &ddStateInput,
  313. sizeof( ddStateInput ),
  314. &ddStateOutput,
  315. sizeof( ddStateOutput ),
  316. &dwReturned,
  317. NULL);
  318. if( ddStateOutput.ddRVal != DD_OK )
  319. {
  320. DPF( 0, "Unable to get the surface state" );
  321. return DDERR_UNSUPPORTED;
  322. }
  323. *lpdwStateFlags = ddStateOutput.dwStateStatus;
  324. return DD_OK;
  325. }
  326. /*
  327. * SetKernelDOSBoxEvent
  328. */
  329. HRESULT SetKernelDOSBoxEvent( LPDDRAWI_DIRECTDRAW_LCL lpDD )
  330. {
  331. DDSETDOSBOXEVENT ddDOSBox;
  332. DWORD dwReturned;
  333. DWORD ddRVal;
  334. ddDOSBox.dwDirectDrawHandle = lpDD->lpGbl->hKernelHandle;
  335. ddDOSBox.dwDOSBoxEvent = lpDD->lpGbl->dwDOSBoxEvent;
  336. ddRVal = (DWORD) DDERR_GENERIC;
  337. DeviceIoControl( (HANDLE)lpDD->hDDVxd,
  338. DD_DXAPI_SET_DOS_BOX_EVENT,
  339. &ddDOSBox,
  340. sizeof( ddDOSBox ),
  341. &ddRVal,
  342. sizeof( ddRVal ),
  343. &dwReturned,
  344. NULL);
  345. return DD_OK;
  346. }
  347. /*
  348. * UpdateKernelVideoPort
  349. *
  350. * On NT, this same stuff is done in kernel mode as part of the
  351. * UpdateVideo call, so it doesn't have to do it again here.
  352. */
  353. HRESULT UpdateKernelVideoPort( LPDDRAWI_DDVIDEOPORT_LCL lpVideoPort, DWORD dwFlags )
  354. {
  355. LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
  356. LPDDRAWI_DDRAWSURFACE_LCL lpSurf;
  357. DDKMVIDEOPORTINFO ddkmVideoPortInfo;
  358. HANDLE hDeviceHandle;
  359. DWORD dwReturned;
  360. DWORD ddRVal;
  361. DWORD dwIRQ;
  362. DWORD i;
  363. if( ( lpVideoPort->lpDD->lpGbl->lpDDKernelCaps == NULL ) ||
  364. ( lpVideoPort->lpDD->lpGbl->hKernelHandle == (DWORD)NULL ) )
  365. {
  366. return DDERR_UNSUPPORTED;
  367. }
  368. hDeviceHandle = GETDDVXDHANDLE( lpVideoPort->lpDD );
  369. if( INVALID_HANDLE_VALUE == hDeviceHandle )
  370. {
  371. return DDERR_UNSUPPORTED;
  372. }
  373. /*
  374. * Start filling in the info
  375. */
  376. memset( &ddkmVideoPortInfo, 0, sizeof( DDKMVIDEOPORTINFO ) );
  377. ddkmVideoPortInfo.dwDirectDrawHandle =
  378. lpVideoPort->lpDD->lpGbl->hKernelHandle;
  379. ddkmVideoPortInfo.dwVideoPortId = lpVideoPort->ddvpDesc.dwVideoPortID;
  380. ddkmVideoPortInfo.dwVPFlags = lpVideoPort->ddvpInfo.dwVPFlags;
  381. ddkmVideoPortInfo.dwFlags = dwFlags;
  382. if( lpVideoPort->dwFlags & DDRAWIVPORT_ON )
  383. {
  384. ddkmVideoPortInfo.dwFlags |= DDKMVP_ON;
  385. }
  386. if( dwFlags != DDKMVP_RELEASE )
  387. {
  388. if( ( lpVideoPort->dwFlags & DDRAWIVPORT_SOFTWARE_AUTOFLIP ) &&
  389. ( lpVideoPort->ddvpInfo.dwVPFlags & DDVP_AUTOFLIP ) )
  390. {
  391. if( lpVideoPort->dwNumAutoflip > 0 )
  392. {
  393. ddkmVideoPortInfo.dwFlags |= DDKMVP_AUTOFLIP;
  394. }
  395. if( lpVideoPort->dwNumVBIAutoflip > 0 )
  396. {
  397. ddkmVideoPortInfo.dwFlags |= DDKMVP_AUTOFLIP_VBI;
  398. }
  399. }
  400. ddkmVideoPortInfo.dwNumAutoflipping = lpVideoPort->dwNumAutoflip;
  401. ddkmVideoPortInfo.dwNumVBIAutoflipping = lpVideoPort->dwNumVBIAutoflip;
  402. /*
  403. * Fill in surface handles for the regular video
  404. */
  405. if( lpVideoPort->lpSurface != NULL )
  406. {
  407. if( lpVideoPort->dwNumAutoflip > 0 )
  408. {
  409. for( i = 0; i < lpVideoPort->dwNumAutoflip; i++ )
  410. {
  411. lpSurf = lpVideoPort->lpFlipInts[i]->lpLcl;
  412. DDASSERT( lpSurf != NULL );
  413. lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( lpSurf->lpGbl );
  414. ddkmVideoPortInfo.dwSurfaceHandle[i] =
  415. lpSurfGblMore->hKernelSurface;
  416. }
  417. }
  418. else
  419. {
  420. lpSurf = lpVideoPort->lpSurface->lpLcl;
  421. lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( lpSurf->lpGbl );
  422. ddkmVideoPortInfo.dwSurfaceHandle[0] =
  423. lpSurfGblMore->hKernelSurface;
  424. }
  425. }
  426. /*
  427. * Fill in surface handles for the VBI data
  428. */
  429. if( lpVideoPort->lpVBISurface != NULL )
  430. {
  431. if( lpVideoPort->dwNumVBIAutoflip > 0 )
  432. {
  433. DWORD dwCnt = 0;
  434. for( i = lpVideoPort->dwNumAutoflip;
  435. i < (lpVideoPort->dwNumVBIAutoflip + lpVideoPort->dwNumAutoflip);
  436. i++ )
  437. {
  438. lpSurf = lpVideoPort->lpFlipInts[i]->lpLcl;
  439. DDASSERT( lpSurf != NULL );
  440. lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( lpSurf->lpGbl );
  441. ddkmVideoPortInfo.dwVBISurfaceHandle[dwCnt++] =
  442. lpSurfGblMore->hKernelSurface;
  443. }
  444. }
  445. else
  446. {
  447. lpSurf = lpVideoPort->lpVBISurface->lpLcl;
  448. lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( lpSurf->lpGbl );
  449. ddkmVideoPortInfo.dwVBISurfaceHandle[0] =
  450. lpSurfGblMore->hKernelSurface;
  451. }
  452. }
  453. /*
  454. * Sync with the HAL
  455. */
  456. if( dwFlags == DDKMVP_UPDATE )
  457. {
  458. /*
  459. * Get/sync the surface info
  460. */
  461. ddRVal = SyncKernelVideoPort( lpVideoPort, &ddkmVideoPortInfo );
  462. if( ddRVal != DD_OK )
  463. {
  464. DPF( 0, "Unable to sync video port data with HAL" );
  465. return ddRVal;
  466. }
  467. }
  468. /*
  469. * Does this support an IRQ?
  470. */
  471. dwIRQ = DDIRQ_VPORT0_VSYNC;
  472. dwIRQ <<= ( lpVideoPort->ddvpDesc.dwVideoPortID * 2 );
  473. if( !( lpVideoPort->lpDD->lpGbl->lpDDKernelCaps->dwIRQCaps &
  474. dwIRQ ) )
  475. {
  476. ddkmVideoPortInfo.dwFlags |= DDKMVP_NOIRQ;
  477. }
  478. if( !( lpVideoPort->lpDD->lpGbl->lpDDKernelCaps->dwCaps &
  479. DDKERNELCAPS_SKIPFIELDS ) )
  480. {
  481. ddkmVideoPortInfo.dwFlags |= DDKMVP_NOSKIP;
  482. }
  483. }
  484. /*
  485. * Notify DDVXD if the even field is shifted down by one line
  486. * due to half lines. This is really only an issue when capturing.
  487. */
  488. if( lpVideoPort->ddvpDesc.VideoPortType.dwFlags & DDVPCONNECT_HALFLINE )
  489. {
  490. ddkmVideoPortInfo.dwFlags |= DDKMVP_HALFLINES;
  491. }
  492. /*
  493. * Send the new info down to the VDD
  494. */
  495. ddRVal = (DWORD) DDERR_GENERIC;
  496. DeviceIoControl( hDeviceHandle,
  497. DD_DXAPI_UPDATE_VP_INFO,
  498. &ddkmVideoPortInfo,
  499. sizeof( ddkmVideoPortInfo ),
  500. &ddRVal,
  501. sizeof( ddRVal ),
  502. &dwReturned,
  503. NULL);
  504. if( ddRVal != DD_OK )
  505. {
  506. DPF( 0, "Unable to update the video port info" );
  507. return DDERR_UNSUPPORTED;
  508. }
  509. return DD_OK;
  510. }
  511. /*
  512. * EnableAutoflip
  513. */
  514. VOID EnableAutoflip( LPDDRAWI_DDVIDEOPORT_LCL lpVideoPort, BOOL bEnable )
  515. {
  516. DDENABLEAUTOFLIP ddkmEnableAutoflip;
  517. HANDLE hDeviceHandle;
  518. DWORD dwReturned;
  519. DWORD ddRVal;
  520. if( lpVideoPort == NULL )
  521. {
  522. return;
  523. }
  524. #ifdef WIN95
  525. if( !IsWindows98() )
  526. {
  527. return;
  528. }
  529. #endif
  530. hDeviceHandle = GETDDVXDHANDLE( lpVideoPort->lpDD );
  531. if( INVALID_HANDLE_VALUE == hDeviceHandle )
  532. {
  533. return;
  534. }
  535. /*
  536. * Start filling in the info
  537. */
  538. memset( &ddkmEnableAutoflip, 0, sizeof( DDENABLEAUTOFLIP ) );
  539. ddkmEnableAutoflip.dwDirectDrawHandle =
  540. lpVideoPort->lpDD->lpGbl->hKernelHandle;
  541. ddkmEnableAutoflip.dwVideoPortId = lpVideoPort->ddvpDesc.dwVideoPortID;
  542. ddkmEnableAutoflip.bEnableAutoflip = bEnable;
  543. ddRVal = (DWORD) DDERR_GENERIC;
  544. DeviceIoControl( hDeviceHandle,
  545. DD_DXAPI_ENABLE_AUTOFLIP,
  546. &ddkmEnableAutoflip,
  547. sizeof( ddkmEnableAutoflip ),
  548. &ddRVal,
  549. sizeof( ddRVal ),
  550. &dwReturned,
  551. NULL);
  552. }
  553. /*
  554. * MungeAutoflipCaps
  555. */
  556. void MungeAutoflipCaps( LPDDRAWI_DIRECTDRAW_GBL pdrv )
  557. {
  558. LPDDVIDEOPORTCAPS lpVideoPortCaps;
  559. DWORD i;
  560. if( ( pdrv->hKernelHandle != (DWORD) NULL ) &&
  561. ( pdrv->lpDDVideoPortCaps != NULL ) &&
  562. ( pdrv->lpDDKernelCaps != NULL ) &&
  563. ( pdrv->lpDDKernelCaps->dwCaps & DDKERNELCAPS_AUTOFLIP ) )
  564. {
  565. /*
  566. * Software autoflipping is supported, so set the autoflip
  567. * capabilities to the max.
  568. */
  569. for( i = 0; i < pdrv->ddCaps.dwMaxVideoPorts; i++ )
  570. {
  571. lpVideoPortCaps = &(pdrv->lpDDVideoPortCaps[i]);
  572. if( ( lpVideoPortCaps != NULL ) &&
  573. VALID_DDVIDEOPORTCAPS_PTR( lpVideoPortCaps ) )
  574. {
  575. lpVideoPortCaps->dwCaps |= DDVPCAPS_AUTOFLIP;
  576. lpVideoPortCaps->dwNumAutoFlipSurfaces = MAX_AUTOFLIP;
  577. if( lpVideoPortCaps->dwCaps & DDVPCAPS_VBISURFACE )
  578. {
  579. lpVideoPortCaps->dwNumVBIAutoFlipSurfaces = MAX_AUTOFLIP;
  580. }
  581. }
  582. }
  583. }
  584. }
  585. #endif
  586. /*
  587. * InternalReleaseKernelHandle
  588. */
  589. HRESULT InternalReleaseKernelSurfaceHandle( LPDDRAWI_DDRAWSURFACE_LCL lpSurface, BOOL bLosingSurface )
  590. {
  591. LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
  592. HANDLE hDeviceHandle;
  593. DWORD dwReturned;
  594. DWORD ddRVal;
  595. #ifdef WIN95
  596. DDRELEASEHANDLE ddRelease;
  597. #endif
  598. #ifdef WIN95
  599. if( lpSurface->lpSurfMore->lpDD_lcl->lpGbl->hKernelHandle == (DWORD) NULL )
  600. {
  601. return DD_OK;
  602. }
  603. hDeviceHandle = GETDDVXDHANDLE( lpSurface->lpSurfMore->lpDD_lcl );
  604. if( INVALID_HANDLE_VALUE == hDeviceHandle )
  605. {
  606. return DDERR_UNSUPPORTED;
  607. }
  608. #endif
  609. lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( lpSurface->lpGbl );
  610. if( lpSurfGblMore->hKernelSurface == 0 )
  611. {
  612. return DD_OK;
  613. }
  614. /*
  615. * Check the ref count to make sure it's time to release this surface
  616. */
  617. if( bLosingSurface )
  618. {
  619. lpSurfGblMore->dwKernelRefCnt = 0;
  620. }
  621. else if( lpSurfGblMore->dwKernelRefCnt > 0 )
  622. {
  623. if( --(lpSurfGblMore->dwKernelRefCnt) > 0 )
  624. {
  625. return DD_OK;
  626. }
  627. }
  628. #if WIN95
  629. /*
  630. * Tell the VDD to release the surface
  631. */
  632. ddRelease.dwDirectDrawHandle =
  633. lpSurface->lpSurfMore->lpDD_lcl->lpGbl->hKernelHandle;
  634. ddRelease.hSurface = lpSurfGblMore->hKernelSurface;
  635. ddRVal = (DWORD) DDERR_GENERIC;
  636. DeviceIoControl( hDeviceHandle,
  637. DD_DXAPI_RELEASE_SURFACE_HANDLE,
  638. &ddRelease,
  639. sizeof( ddRelease ),
  640. &ddRVal,
  641. sizeof( ddRVal ),
  642. &dwReturned,
  643. NULL);
  644. if( ddRVal != DD_OK )
  645. {
  646. DPF_ERR( "Unable to release the surface handle in the VDD" );
  647. return (HRESULT)ddRVal;
  648. }
  649. #else
  650. {
  651. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl = lpSurface->lpSurfMore->lpDD_lcl;
  652. LPDDRAWI_DIRECTDRAW_GBL pdrv = pdrv_lcl->lpGbl;
  653. // Update DDraw handle in driver GBL object before calling DdGetDxHandle.
  654. pdrv->hDD = pdrv_lcl->hDD;
  655. DdGetDxHandle( NULL, lpSurface, TRUE );
  656. }
  657. #endif
  658. lpSurfGblMore->hKernelSurface = 0;
  659. return DD_OK;
  660. }
  661. /*
  662. * InternalCreateKernelSurfaceHandle
  663. */
  664. HRESULT InternalCreateKernelSurfaceHandle( LPDDRAWI_DDRAWSURFACE_LCL lpSurface,
  665. PULONG_PTR lpHandle )
  666. {
  667. LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
  668. HANDLE hDeviceHandle;
  669. DWORD ddRVal;
  670. *lpHandle = 0;
  671. if( !IsKernelInterfaceSupported( lpSurface->lpSurfMore->lpDD_lcl ) )
  672. {
  673. return DDERR_UNSUPPORTED;
  674. }
  675. lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( lpSurface->lpGbl );
  676. if( lpSurfGblMore->hKernelSurface != 0 )
  677. {
  678. *lpHandle = lpSurfGblMore->hKernelSurface;
  679. lpSurfGblMore->dwKernelRefCnt++;
  680. }
  681. else
  682. {
  683. #if WIN95
  684. DDKMSURFACEINFO ddkmSurfaceInfo;
  685. DDGETSURFACEHANDLE ddkmGetSurfaceHandle;
  686. DWORD dwReturned;
  687. hDeviceHandle = GETDDVXDHANDLE( lpSurface->lpSurfMore->lpDD_lcl );
  688. if( INVALID_HANDLE_VALUE == hDeviceHandle )
  689. {
  690. return DDERR_UNSUPPORTED;
  691. }
  692. /*
  693. * Get/sync the surface info
  694. */
  695. ddRVal = SyncKernelSurface( lpSurface, &ddkmSurfaceInfo );
  696. if( ddRVal != DD_OK )
  697. {
  698. DPF( 0, "Unable to sync surface data with HAL" );
  699. return ddRVal;
  700. }
  701. /*
  702. * Get the handle from DDRAW.VXD
  703. */
  704. ddkmSurfaceInfo.dwDirectDrawHandle =
  705. lpSurface->lpSurfMore->lpDD_lcl->lpGbl->hKernelHandle;
  706. ddkmGetSurfaceHandle.ddRVal = (DWORD) DDERR_GENERIC;
  707. ddkmGetSurfaceHandle.hSurface = 0;
  708. DeviceIoControl( hDeviceHandle,
  709. DD_DXAPI_GET_SURFACE_HANDLE,
  710. &ddkmSurfaceInfo,
  711. sizeof( ddkmSurfaceInfo ),
  712. &ddkmGetSurfaceHandle,
  713. sizeof( ddkmGetSurfaceHandle ),
  714. &dwReturned,
  715. NULL);
  716. if( ( ddkmGetSurfaceHandle.ddRVal != DD_OK ) ||
  717. ( ddkmGetSurfaceHandle.hSurface == 0 ) )
  718. {
  719. DPF( 0, "Unable to get surface handle from the VDD" );
  720. return DDERR_UNSUPPORTED;
  721. }
  722. *lpHandle = lpSurfGblMore->hKernelSurface =
  723. ddkmGetSurfaceHandle.hSurface;
  724. #else
  725. *lpHandle = (ULONG_PTR) DdGetDxHandle( NULL, lpSurface, 0 );
  726. if( *lpHandle == 0 )
  727. {
  728. return DDERR_GENERIC;
  729. }
  730. lpSurfGblMore->hKernelSurface = *lpHandle;
  731. #endif
  732. lpSurfGblMore->dwKernelRefCnt = 1;
  733. }
  734. return DD_OK;
  735. }
  736. /*
  737. * InitKernelInterface
  738. */
  739. #ifdef WINNT
  740. #ifndef MAX_AUTOFLIP
  741. #define MAX_AUTOFLIP 10
  742. #endif
  743. #endif
  744. HRESULT InitKernelInterface( LPDDRAWI_DIRECTDRAW_LCL lpDD )
  745. {
  746. #ifdef WIN95
  747. VDD_IOCTL_SET_NOTIFY_INPUT vddNotify;
  748. DDINITDEVICEIN ddInput;
  749. DDINITDEVICEOUT ddOutput;
  750. DDSETKERNELCAPS ddSetCaps;
  751. #endif
  752. LPDDKERNELCAPS lpKernelCaps;
  753. HANDLE hDeviceHandle;
  754. DWORD dwReturned;
  755. DWORD ddRVal;
  756. DWORD dwTemp;
  757. BYTE szDisplayName[MAX_DRIVER_NAME];
  758. #ifdef WIN95
  759. /*
  760. * Don't do anything unles we're Windows98 or later
  761. */
  762. if( !IsWindows98() )
  763. {
  764. return DDERR_UNSUPPORTED;
  765. }
  766. /*
  767. * Get the name of the VDD device to open
  768. * This is a hack to do some temporary work on Win95
  769. */
  770. lstrcpy( szDisplayName, lpDD->lpGbl->cDriverName );
  771. if( _stricmp( szDisplayName, DISPLAY_STR ) == 0 )
  772. {
  773. lstrcpy( szDisplayName, g_szPrimaryDisplay );
  774. }
  775. /*
  776. * Open the VDD for communication
  777. */
  778. lpDD->lpGbl->hKernelHandle = 0;
  779. hDeviceHandle = CreateFile( szDisplayName,
  780. GENERIC_WRITE,
  781. FILE_SHARE_WRITE,
  782. NULL,
  783. OPEN_EXISTING,
  784. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_GLOBAL_HANDLE,
  785. NULL);
  786. if( INVALID_HANDLE_VALUE == hDeviceHandle )
  787. {
  788. DPF( 0, "Unable to open the VDD" );
  789. return DDERR_UNSUPPORTED;
  790. }
  791. /*
  792. * Get the function table from the mini VDD
  793. */
  794. memset( &ddInput, 0, sizeof( ddInput ) );
  795. DeviceIoControl( hDeviceHandle,
  796. VDD_IOCTL_GET_DDHAL,
  797. &dwTemp,
  798. sizeof( DWORD ),
  799. &(ddInput.MiniVDDTable),
  800. sizeof( DDMINIVDDTABLE ),
  801. &dwReturned,
  802. NULL);
  803. /*
  804. * Send the new info down to DDRAW.VXD
  805. */
  806. lpKernelCaps = lpDD->lpGbl->lpDDKernelCaps;
  807. if( lpKernelCaps != NULL )
  808. {
  809. ddInput.dwMaxVideoPorts = lpDD->lpGbl->ddCaps.dwMaxVideoPorts;
  810. if( lpDD->lpGbl->ddCaps.dwCaps2 & DDCAPS2_CANBOBINTERLEAVED )
  811. {
  812. ddInput.dwDeviceFlags |= DDKMDF_CAN_BOB_INTERLEAVED;
  813. }
  814. if( lpDD->lpGbl->ddCaps.dwCaps2 & DDCAPS2_CANBOBNONINTERLEAVED )
  815. {
  816. ddInput.dwDeviceFlags |= DDKMDF_CAN_BOB_NONINTERLEAVED;
  817. }
  818. if( !( lpKernelCaps->dwCaps & DDKERNELCAPS_SETSTATE ) )
  819. {
  820. ddInput.dwDeviceFlags |= DDKMDF_NOSTATE;
  821. }
  822. }
  823. ddOutput.ddRVal = (DWORD) DDERR_GENERIC;
  824. DeviceIoControl( (HANDLE)lpDD->hDDVxd,
  825. DD_DXAPI_INIT_DEVICE,
  826. &ddInput,
  827. sizeof( ddInput ),
  828. &ddOutput,
  829. sizeof( ddOutput ),
  830. &dwReturned,
  831. NULL);
  832. if( ddOutput.ddRVal != DD_OK )
  833. {
  834. DPF( 0, "Unable to initialize the kernel data" );
  835. CloseHandle( hDeviceHandle );
  836. return DDERR_UNSUPPORTED;
  837. }
  838. /*
  839. * If unable to allocate the IRQ, disable functionality that depends
  840. * on it.
  841. */
  842. if( lpKernelCaps != NULL )
  843. {
  844. if( !ddOutput.bHaveIRQ )
  845. {
  846. DPF( 1, "Unable to allocate IRQ - disabling some kernel mode functionality" );
  847. lpKernelCaps->dwIRQCaps = 0;
  848. }
  849. /*
  850. * Disable kernel mode caps for which functions are not available
  851. */
  852. if( ( ddInput.MiniVDDTable.vddGetIRQInfo == NULL ) ||
  853. ( ddInput.MiniVDDTable.vddEnableIRQ == NULL ) )
  854. {
  855. // Can't to any IRQ stuff w/o these functions
  856. DPF( 1, "vddGet/EnableIRQ not supported - overriding dwIRQCaps" );
  857. lpKernelCaps->dwIRQCaps = 0;
  858. }
  859. if( ddInput.MiniVDDTable.vddSetState == NULL )
  860. {
  861. DPF( 1, "vddSetState not supported - overriding DDKERNELCAPS_SETSTATE" );
  862. lpKernelCaps->dwCaps &= ~DDKERNELCAPS_SETSTATE;
  863. }
  864. if( ddInput.MiniVDDTable.vddLock == NULL )
  865. {
  866. DPF( 1, "vddLock not supported - overriding DDKERNELCAPS_LOCK" );
  867. lpKernelCaps->dwCaps &= ~DDKERNELCAPS_LOCK;
  868. }
  869. if( ddInput.MiniVDDTable.vddSkipNextField == NULL )
  870. {
  871. DPF( 1, "vddSkipNextField not supported - overriding DDKERNELCAPS_SKIPFIELDS" );
  872. lpKernelCaps->dwCaps &= ~DDKERNELCAPS_SKIPFIELDS;
  873. }
  874. if( ddInput.MiniVDDTable.vddFlipOverlay == NULL )
  875. {
  876. DPF( 1, "vddFlipOverlay not supported - overriding DDKERNELCAPS_FLIPOVERLAY" );
  877. lpKernelCaps->dwCaps &= ~DDKERNELCAPS_FLIPOVERLAY;
  878. }
  879. if( ddInput.MiniVDDTable.vddFlipVideoPort == NULL )
  880. {
  881. DPF( 1, "vddFlipVideoPort not supported - overriding DDKERNELCAPS_FLIPVIDEOPORT" );
  882. lpKernelCaps->dwCaps &= ~DDKERNELCAPS_FLIPVIDEOPORT;
  883. }
  884. if( ddInput.MiniVDDTable.vddGetPolarity == NULL )
  885. {
  886. DPF( 1, "vddGetFieldPolarity not supported - overriding DDKERNELCAPS_FIELDPOLARITY" );
  887. lpKernelCaps->dwCaps &= ~DDKERNELCAPS_FIELDPOLARITY;
  888. }
  889. if( ( ddInput.MiniVDDTable.vddTransfer == NULL ) ||
  890. ( ddInput.MiniVDDTable.vddGetTransferStatus == NULL ) )
  891. {
  892. DPF( 1, "vddTransfer/GetTransferStatus not supported - overriding DDKERNELCAPS_CAPTURE_NONLOCALVIDMEM/SYSMEM" );
  893. lpKernelCaps->dwCaps &= ~DDKERNELCAPS_CAPTURE_NONLOCALVIDMEM;
  894. lpKernelCaps->dwCaps &= ~DDKERNELCAPS_CAPTURE_SYSMEM;
  895. lpKernelCaps->dwCaps &= ~DDKERNELCAPS_CAPTURE_INVERTED;
  896. }
  897. if( ( ddInput.MiniVDDTable.vddBobNextField == NULL ) &&
  898. ( lpDD->lpGbl->ddCaps.dwCaps2 & DDCAPS2_CANBOBINTERLEAVED ) )
  899. {
  900. DPF( 1, "vddBobNextField not supported - overriding DDKERNELCAPS_AUTOFLIP" );
  901. lpKernelCaps->dwCaps &= ~DDKERNELCAPS_AUTOFLIP;
  902. }
  903. if( ( ddInput.MiniVDDTable.vddFlipOverlay == NULL ) ||
  904. ( ddInput.MiniVDDTable.vddFlipVideoPort == NULL ) )
  905. {
  906. DPF( 1, "vddFlipOverlay/VideoPort not supported - overriding DDKERNELCAPS_AUTOFLIP" );
  907. lpKernelCaps->dwCaps &= ~DDKERNELCAPS_AUTOFLIP;
  908. }
  909. if( !( lpKernelCaps->dwIRQCaps & DDIRQ_VPORT0_VSYNC ) )
  910. {
  911. DPF( 1, "DDIRQ_VPORT0_VSYNC not set - overriding DDKERNELCAPS_AUTOFLIP" );
  912. lpKernelCaps->dwCaps &= ~( DDKERNELCAPS_AUTOFLIP | DDKERNELCAPS_SETSTATE );
  913. }
  914. if( !( lpKernelCaps->dwCaps & DDKERNELCAPS_AUTOFLIP ) )
  915. {
  916. DPF( 1, "DDKERNELCAPS_AUTOFLIP not set - overriding DDKERNELCAPS_SKIPFIELDS" );
  917. lpKernelCaps->dwCaps &= ~DDKERNELCAPS_SKIPFIELDS;
  918. }
  919. /*
  920. * Notify DDVXD of the updated caps
  921. */
  922. ddSetCaps.dwDirectDrawHandle = ddOutput.dwDirectDrawHandle;
  923. ddSetCaps.dwCaps = lpKernelCaps->dwCaps;
  924. ddSetCaps.dwIRQCaps = lpKernelCaps->dwIRQCaps;
  925. ddRVal = (DWORD) DDERR_GENERIC;
  926. DeviceIoControl( (HANDLE)lpDD->hDDVxd,
  927. DD_DXAPI_SET_KERNEL_CAPS,
  928. &ddSetCaps,
  929. sizeof( ddSetCaps ),
  930. &ddRVal,
  931. sizeof( ddRVal ),
  932. &dwReturned,
  933. NULL);
  934. if( ddRVal != DD_OK )
  935. {
  936. DPF( 0, "Unable to initialize the kernel data" );
  937. CloseHandle( hDeviceHandle );
  938. return DDERR_UNSUPPORTED;
  939. }
  940. }
  941. /*
  942. * Tell the VDD to notify us of dos box and res change events.
  943. */
  944. vddNotify.NotifyMask = VDD_NOTIFY_START_MODE_CHANGE |
  945. VDD_NOTIFY_END_MODE_CHANGE | VDD_NOTIFY_ENABLE | VDD_NOTIFY_DISABLE;
  946. vddNotify.NotifyType = VDD_NOTIFY_TYPE_CALLBACK;
  947. vddNotify.NotifyProc = ddOutput.pfnNotifyProc;
  948. vddNotify.NotifyData = ddOutput.dwDirectDrawHandle;
  949. DeviceIoControl( hDeviceHandle,
  950. VDD_IOCTL_SET_NOTIFY,
  951. &vddNotify,
  952. sizeof( vddNotify ),
  953. &dwTemp,
  954. sizeof( dwTemp ),
  955. &dwReturned,
  956. NULL);
  957. CloseHandle( hDeviceHandle );
  958. lpDD->lpGbl->hKernelHandle = ddOutput.dwDirectDrawHandle;
  959. lpDD->lpGbl->pfnNotifyProc = ddOutput.pfnNotifyProc;
  960. /*
  961. * Everything worked. If they can support software autoflipping,
  962. * we'll update the video port caps structure accordingly.
  963. */
  964. MungeAutoflipCaps( lpDD->lpGbl );
  965. #else
  966. /*
  967. * Can we software autoflip? If so, we'll update the video
  968. * port caps structure accordingly.
  969. */
  970. lpKernelCaps = lpDD->lpGbl->lpDDKernelCaps;
  971. if( ( lpKernelCaps != NULL ) &&
  972. ( lpKernelCaps->dwCaps & DDKERNELCAPS_AUTOFLIP ) &&
  973. ( lpDD->lpGbl->lpDDVideoPortCaps != NULL ) )
  974. {
  975. LPDDVIDEOPORTCAPS lpVideoPortCaps;
  976. DWORD i;
  977. for( i = 0; i < lpDD->lpGbl->ddCaps.dwMaxVideoPorts; i++ )
  978. {
  979. lpVideoPortCaps = &(lpDD->lpGbl->lpDDVideoPortCaps[i]);
  980. if( ( lpVideoPortCaps != NULL ) &&
  981. VALID_DDVIDEOPORTCAPS_PTR( lpVideoPortCaps ) )
  982. {
  983. lpVideoPortCaps->dwCaps |= DDVPCAPS_AUTOFLIP;
  984. lpVideoPortCaps->dwNumAutoFlipSurfaces = MAX_AUTOFLIP;
  985. if( lpVideoPortCaps->dwCaps & DDVPCAPS_VBISURFACE )
  986. {
  987. lpVideoPortCaps->dwNumVBIAutoFlipSurfaces = MAX_AUTOFLIP;
  988. }
  989. }
  990. }
  991. }
  992. #endif
  993. return DD_OK;
  994. }
  995. /*
  996. * ReleaseKernelInterface
  997. */
  998. HRESULT ReleaseKernelInterface( LPDDRAWI_DIRECTDRAW_LCL lpDD )
  999. {
  1000. HANDLE hDDVxd;
  1001. HANDLE hVDD;
  1002. DWORD dwTemp;
  1003. DWORD dwReturned;
  1004. BYTE szDisplayName[MAX_DRIVER_NAME];
  1005. /*
  1006. * Do nothing if no interface has been created.
  1007. */
  1008. if( lpDD->lpGbl->hKernelHandle == 0 )
  1009. {
  1010. return DD_OK;
  1011. }
  1012. #if WIN95
  1013. /*
  1014. * Tell the VDD to stop notifying us of DOS box and res change events.
  1015. */
  1016. if( lpDD->lpGbl->pfnNotifyProc != 0 )
  1017. {
  1018. /*
  1019. * Get the name of the VDD device to open
  1020. */
  1021. lstrcpy( szDisplayName, lpDD->lpGbl->cDriverName );
  1022. if( _stricmp( szDisplayName, DISPLAY_STR ) == 0 )
  1023. {
  1024. lstrcpy( szDisplayName, g_szPrimaryDisplay );
  1025. }
  1026. hVDD = CreateFile( szDisplayName,
  1027. GENERIC_WRITE,
  1028. FILE_SHARE_WRITE,
  1029. NULL,
  1030. OPEN_EXISTING,
  1031. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_GLOBAL_HANDLE,
  1032. NULL);
  1033. if( hVDD != INVALID_HANDLE_VALUE )
  1034. {
  1035. VDD_IOCTL_SET_NOTIFY_INPUT vddNotify;
  1036. vddNotify.NotifyMask = 0;
  1037. vddNotify.NotifyType = VDD_NOTIFY_TYPE_CALLBACK;
  1038. vddNotify.NotifyProc = lpDD->lpGbl->pfnNotifyProc;
  1039. vddNotify.NotifyData = lpDD->lpGbl->hKernelHandle;
  1040. DeviceIoControl( hVDD,
  1041. VDD_IOCTL_SET_NOTIFY,
  1042. &vddNotify,
  1043. sizeof( vddNotify ),
  1044. &dwTemp,
  1045. sizeof( dwTemp ),
  1046. &dwReturned,
  1047. NULL);
  1048. CloseHandle( hVDD );
  1049. }
  1050. }
  1051. /*
  1052. * Need to decide which VXD handle to use. If we are executing
  1053. * on a DDHELP thread use the helper's VXD handle.
  1054. */
  1055. hDDVxd = ( ( GetCurrentProcessId() != GETCURRPID() ) ? hHelperDDVxd : (HANDLE)lpDD->hDDVxd );
  1056. dwTemp = lpDD->lpGbl->hKernelHandle;
  1057. if( ( hDDVxd != NULL ) && ( dwTemp != 0 ) )
  1058. {
  1059. DeviceIoControl( hDDVxd,
  1060. DD_DXAPI_RELEASE_DEVICE,
  1061. &dwTemp,
  1062. sizeof( DWORD ),
  1063. &dwTemp,
  1064. sizeof( DWORD ),
  1065. &dwReturned,
  1066. NULL);
  1067. }
  1068. #else
  1069. DdGetDxHandle( lpDD, NULL, TRUE );
  1070. #endif
  1071. return DD_OK;
  1072. }
  1073. /*
  1074. * Determines if software autoflipping is an option.
  1075. */
  1076. BOOL CanSoftwareAutoflip( LPDDRAWI_DDVIDEOPORT_LCL lpVideoPort )
  1077. {
  1078. DWORD dwIRQ;
  1079. #if WIN95
  1080. /*
  1081. * Fail if the ring 0 interface is not present
  1082. */
  1083. if( ( lpVideoPort == NULL ) ||
  1084. ( !IsKernelInterfaceSupported( lpVideoPort->lpDD ) ) ||
  1085. ( lpVideoPort->lpDD->lpGbl->hKernelHandle == (DWORD) 0 ) ||
  1086. ( lpVideoPort->dwFlags & DDRAWIVPORT_NOKERNELHANDLES ) )
  1087. {
  1088. return FALSE;
  1089. }
  1090. /*
  1091. * Check the ring 0 caps to see if autoflipping is available
  1092. */
  1093. if( ( lpVideoPort->lpDD->lpGbl->lpDDKernelCaps == NULL ) ||
  1094. !( lpVideoPort->lpDD->lpGbl->lpDDKernelCaps->dwCaps &
  1095. DDKERNELCAPS_AUTOFLIP ) )
  1096. {
  1097. return FALSE;
  1098. }
  1099. /*
  1100. * Check to make sure an IRQ is available for this video port
  1101. */
  1102. dwIRQ = DDIRQ_VPORT0_VSYNC;
  1103. dwIRQ <<= ( lpVideoPort->ddvpDesc.dwVideoPortID * 2 );
  1104. if( !( lpVideoPort->lpDD->lpGbl->lpDDKernelCaps->dwIRQCaps & dwIRQ ) )
  1105. {
  1106. return FALSE;
  1107. }
  1108. #else
  1109. /*
  1110. * Check the ring 0 caps to see if autoflipping is available
  1111. */
  1112. if( (lpVideoPort == NULL ) ||
  1113. ( lpVideoPort->lpDD->lpGbl->lpDDKernelCaps == NULL ) ||
  1114. !( lpVideoPort->lpDD->lpGbl->lpDDKernelCaps->dwCaps &
  1115. DDKERNELCAPS_AUTOFLIP ) )
  1116. {
  1117. return FALSE;
  1118. }
  1119. /*
  1120. * Check to make sure an IRQ is available for this video port
  1121. */
  1122. dwIRQ = DDIRQ_VPORT0_VSYNC;
  1123. dwIRQ <<= ( lpVideoPort->ddvpDesc.dwVideoPortID * 2 );
  1124. if( !( lpVideoPort->lpDD->lpGbl->lpDDKernelCaps->dwIRQCaps & dwIRQ ) )
  1125. {
  1126. return FALSE;
  1127. }
  1128. #endif
  1129. return TRUE;
  1130. }
  1131. /*
  1132. * DD_Kernel_GetCaps
  1133. */
  1134. HRESULT DDAPI DD_Kernel_GetCaps(LPDIRECTDRAWKERNEL lpDDK, LPDDKERNELCAPS lpCaps )
  1135. {
  1136. LPDDRAWI_DIRECTDRAW_INT this_int;
  1137. LPDDRAWI_DIRECTDRAW_GBL this;
  1138. ENTER_DDRAW();
  1139. DPF(2,A,"ENTERAPI: DD_Kernel_GetCaps");
  1140. TRY
  1141. {
  1142. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDDK;
  1143. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  1144. {
  1145. LEAVE_DDRAW();
  1146. return DDERR_INVALIDOBJECT;
  1147. }
  1148. this = this_int->lpLcl->lpGbl;
  1149. if( !VALID_DDKERNELCAPS_PTR( lpCaps ) )
  1150. {
  1151. DPF( 0, "Invalid DDKERNELCAPS ptr" );
  1152. LEAVE_DDRAW();
  1153. return DDERR_INVALIDPARAMS;
  1154. }
  1155. if( !IsKernelInterfaceSupported( this_int->lpLcl ) )
  1156. {
  1157. DPF( 0, "Device does not support kernel interface" );
  1158. LEAVE_DDRAW();
  1159. return DDERR_UNSUPPORTED;
  1160. }
  1161. }
  1162. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1163. {
  1164. DPF_ERR( "Exception encountered validating parameters" );
  1165. LEAVE_DDRAW();
  1166. return DDERR_EXCEPTION;
  1167. }
  1168. memcpy( lpCaps, this->lpDDKernelCaps, sizeof( DDKERNELCAPS ));
  1169. lpCaps->dwSize = sizeof( DDKERNELCAPS );
  1170. LEAVE_DDRAW();
  1171. return DD_OK;
  1172. }
  1173. /*
  1174. * DD_Kernel_GetKernelHandle
  1175. */
  1176. HRESULT DDAPI DD_Kernel_GetKernelHandle(LPDIRECTDRAWKERNEL lpDDK, PULONG_PTR lpHandle )
  1177. {
  1178. LPDDRAWI_DIRECTDRAW_INT this_int;
  1179. LPDDRAWI_DIRECTDRAW_GBL this;
  1180. ENTER_DDRAW();
  1181. DPF(2,A,"ENTERAPI: DD_Kernel_GetKernelHandle");
  1182. TRY
  1183. {
  1184. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDDK;
  1185. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  1186. {
  1187. LEAVE_DDRAW();
  1188. return DDERR_INVALIDOBJECT;
  1189. }
  1190. this = this_int->lpLcl->lpGbl;
  1191. if( !VALID_DWORD_PTR( lpHandle ) )
  1192. {
  1193. DPF( 0, "Invalid handle ptr" );
  1194. LEAVE_DDRAW();
  1195. return DDERR_INVALIDPARAMS;
  1196. }
  1197. if( !IsKernelInterfaceSupported( this_int->lpLcl ) )
  1198. {
  1199. DPF( 0, "Device does not support kernel interface" );
  1200. LEAVE_DDRAW();
  1201. return DDERR_UNSUPPORTED;
  1202. }
  1203. }
  1204. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1205. {
  1206. DPF_ERR( "Exception encountered validating parameters" );
  1207. LEAVE_DDRAW();
  1208. return DDERR_EXCEPTION;
  1209. }
  1210. #ifdef WINNT
  1211. this->hKernelHandle = (ULONG_PTR) DdGetDxHandle( this_int->lpLcl, NULL, FALSE );
  1212. if( this->hKernelHandle == 0 )
  1213. {
  1214. DPF( 0, "Kernel failed GetDxHandle" );
  1215. LEAVE_DDRAW();
  1216. return DDERR_GENERIC;
  1217. }
  1218. #endif
  1219. *lpHandle = this->hKernelHandle;
  1220. LEAVE_DDRAW();
  1221. return DD_OK;
  1222. }
  1223. /*
  1224. * DD_Kernel_ReleaseKernelHandle
  1225. *
  1226. * Does nothing - should it?
  1227. */
  1228. HRESULT DDAPI DD_Kernel_ReleaseKernelHandle(LPDIRECTDRAWKERNEL lpDDK )
  1229. {
  1230. LPDDRAWI_DIRECTDRAW_INT this_int;
  1231. LPDDRAWI_DIRECTDRAW_GBL this;
  1232. ENTER_DDRAW();
  1233. DPF(2,A,"ENTERAPI: DD_Kernel_ReleaseKernelHandle");
  1234. TRY
  1235. {
  1236. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDDK;
  1237. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  1238. {
  1239. LEAVE_DDRAW();
  1240. return DDERR_INVALIDOBJECT;
  1241. }
  1242. this = this_int->lpLcl->lpGbl;
  1243. if( !IsKernelInterfaceSupported( this_int->lpLcl ) )
  1244. {
  1245. DPF( 0, "Device does not support kernel interface" );
  1246. LEAVE_DDRAW();
  1247. return DDERR_UNSUPPORTED;
  1248. }
  1249. }
  1250. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1251. {
  1252. DPF_ERR( "Exception encountered validating parameters" );
  1253. LEAVE_DDRAW();
  1254. return DDERR_EXCEPTION;
  1255. }
  1256. #ifdef WINNT
  1257. ReleaseKernelInterface( this_int->lpLcl );
  1258. #endif
  1259. LEAVE_DDRAW();
  1260. return DD_OK;
  1261. }
  1262. /*
  1263. * DD_SurfaceKernel_GetKernelHandle
  1264. */
  1265. HRESULT DDAPI DD_SurfaceKernel_GetKernelHandle(LPDIRECTDRAWSURFACEKERNEL lpDDK,
  1266. PULONG_PTR lpHandle )
  1267. {
  1268. LPDDRAWI_DDRAWSURFACE_INT this_int;
  1269. DWORD ddRVal;
  1270. ENTER_DDRAW();
  1271. DPF(2,A,"ENTERAPI: DD_SurfaceKernel_GetKernelHandle");
  1272. TRY
  1273. {
  1274. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDK;
  1275. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  1276. {
  1277. LEAVE_DDRAW();
  1278. return DDERR_INVALIDOBJECT;
  1279. }
  1280. if( !VALID_DWORD_PTR( lpHandle ) )
  1281. {
  1282. DPF( 0, "Invalid handle ptr" );
  1283. LEAVE_DDRAW();
  1284. return DDERR_INVALIDPARAMS;
  1285. }
  1286. if( !IsKernelInterfaceSupported( this_int->lpLcl->lpSurfMore->lpDD_lcl ) )
  1287. {
  1288. DPF( 0, "Device does not support kernel interface" );
  1289. LEAVE_DDRAW();
  1290. return DDERR_UNSUPPORTED;
  1291. }
  1292. }
  1293. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1294. {
  1295. DPF_ERR( "Exception encountered validating parameters" );
  1296. LEAVE_DDRAW();
  1297. return DDERR_EXCEPTION;
  1298. }
  1299. ddRVal = InternalCreateKernelSurfaceHandle( this_int->lpLcl, lpHandle );
  1300. LEAVE_DDRAW();
  1301. return ddRVal;
  1302. }
  1303. /*
  1304. * DD_SurfaceKernel_ReleaseKernelHandle
  1305. */
  1306. HRESULT DDAPI DD_SurfaceKernel_ReleaseKernelHandle(LPDIRECTDRAWSURFACEKERNEL lpDDK )
  1307. {
  1308. LPDDRAWI_DDRAWSURFACE_INT this_int;
  1309. LPDDRAWI_DDRAWSURFACE_GBL this;
  1310. LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
  1311. DWORD ddRVal;
  1312. ENTER_DDRAW();
  1313. DPF(2,A,"ENTERAPI: DD_SurfaceKernel_ReleaseKernelHandle");
  1314. TRY
  1315. {
  1316. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDK;
  1317. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  1318. {
  1319. LEAVE_DDRAW();
  1320. return DDERR_INVALIDOBJECT;
  1321. }
  1322. this = this_int->lpLcl->lpGbl;
  1323. lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( this );
  1324. if( lpSurfGblMore->hKernelSurface == 0 )
  1325. {
  1326. DPF_ERR( "Kernel handle has already been released" );
  1327. LEAVE_DDRAW();
  1328. return DD_OK;
  1329. }
  1330. if( this_int->lpLcl->lpSurfMore->lpDD_lcl->lpGbl->hKernelHandle == (DWORD) 0 )
  1331. {
  1332. DPF( 0, "Device does not support kernel interface" );
  1333. LEAVE_DDRAW();
  1334. return DDERR_UNSUPPORTED;
  1335. }
  1336. }
  1337. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1338. {
  1339. DPF_ERR( "Exception encountered validating parameters" );
  1340. LEAVE_DDRAW();
  1341. return DDERR_EXCEPTION;
  1342. }
  1343. ddRVal = InternalReleaseKernelSurfaceHandle( this_int->lpLcl, FALSE );
  1344. LEAVE_DDRAW();
  1345. return ddRVal;
  1346. }
  1347. /*
  1348. * IsKernelInterfaceSupported
  1349. */
  1350. BOOL IsKernelInterfaceSupported( LPDDRAWI_DIRECTDRAW_LCL lpDD )
  1351. {
  1352. #ifdef WIN95
  1353. if( ( lpDD->lpGbl->hKernelHandle == (DWORD) NULL ) ||
  1354. ( lpDD->lpGbl->lpDDKernelCaps == NULL ) ||
  1355. ( lpDD->lpDDCB->HALDDKernel.SyncSurfaceData == NULL ) )
  1356. {
  1357. return FALSE;
  1358. }
  1359. #else
  1360. if( ( lpDD->lpGbl->lpDDKernelCaps == NULL ) ||
  1361. ( lpDD->lpGbl->lpDDKernelCaps->dwCaps == 0 ) )
  1362. {
  1363. return FALSE;
  1364. }
  1365. #endif
  1366. return TRUE;
  1367. }