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.

5818 lines
151 KiB

  1. /*==========================================================================
  2. * Copyright (C) 1996 Microsoft Corporation. All Rights Reserved.
  3. *
  4. * File: ddvp.c
  5. * Content: DirectDrawVideoPort
  6. * History:
  7. * Date By Reason
  8. * ==== == ======
  9. * 11-jun-96 scottm created
  10. * 29-jan-97 smac Various API changes and bug fixes
  11. * 31-jan-97 colinmc Bug 5457: Fixed problem with new aliased (no-Win16
  12. * lock) and multiple AMovie clips playing on old cards.
  13. * 03-mar-97 smac Added kernel mode interface and fixed some bugs
  14. *
  15. ***************************************************************************/
  16. #include "ddrawpr.h"
  17. #ifdef WINNT
  18. #include "ddrawgdi.h"
  19. #include "ddkmmini.h"
  20. #include "ddkmapi.h"
  21. #else
  22. #include "ddkmmini.h"
  23. #include "ddkmapip.h"
  24. #endif
  25. #define DPF_MODNAME "DirectDrawVideoPort"
  26. #define MAX_VP_FORMATS 25
  27. #define MAX_VIDEO_PORTS 10
  28. DDPIXELFORMAT ddpfVPFormats[MAX_VP_FORMATS];
  29. BOOL bInEnumCallback = FALSE;
  30. HRESULT InternalUpdateVideo( LPDDRAWI_DDVIDEOPORT_INT, LPDDVIDEOPORTINFO );
  31. HRESULT InternalStartVideo( LPDDRAWI_DDVIDEOPORT_INT, LPDDVIDEOPORTINFO );
  32. LPDDPIXELFORMAT GetSurfaceFormat( LPDDRAWI_DDRAWSURFACE_LCL );
  33. HRESULT CreateVideoPortNotify( LPDDRAWI_DDVIDEOPORT_INT, LPDIRECTDRAWVIDEOPORTNOTIFY *lplpVPNotify );
  34. /*
  35. * This function 1) updates the surfaces in the chain so they know they
  36. * are no longer receiving video port data and 2) releases any implicitly
  37. * created kernel handles.
  38. */
  39. VOID ReleaseVPESurfaces( LPDDRAWI_DDRAWSURFACE_INT surf_int, BOOL bRelease )
  40. {
  41. LPDDRAWI_DDRAWSURFACE_INT surf_first;
  42. DDASSERT( surf_int != NULL );
  43. surf_first = surf_int;
  44. do
  45. {
  46. if( bRelease &&
  47. ( surf_int->lpLcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_IMPLICITHANDLE ) )
  48. {
  49. InternalReleaseKernelSurfaceHandle( surf_int->lpLcl, FALSE );
  50. surf_int->lpLcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_IMPLICITHANDLE;
  51. }
  52. surf_int->lpLcl->lpSurfMore->lpVideoPort = NULL;
  53. surf_int = FindAttachedFlip( surf_int );
  54. } while( ( surf_int != NULL ) && ( surf_int->lpLcl != surf_first->lpLcl ) );
  55. }
  56. /*
  57. * This function 1) updates the surfaces in the chain so they know they
  58. * are receiving video port data and 2) implicitly creates kernel handles
  59. * for each surface if one does not already exist so ring 0 can perform
  60. * software autoflipping or software bobbing.
  61. */
  62. DWORD PrepareVPESurfaces( LPDDRAWI_DDRAWSURFACE_INT surf_int,
  63. LPDDRAWI_DDVIDEOPORT_LCL lpVideoPort, BOOL bAutoflipping )
  64. {
  65. LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
  66. LPDDRAWI_DDRAWSURFACE_INT surf_first;
  67. ULONG_PTR dwHandle;
  68. DWORD ddRVal;
  69. DDASSERT( surf_int != NULL );
  70. surf_first = surf_int;
  71. do
  72. {
  73. /*
  74. * Create a kernel handle if one doesn't already exist
  75. */
  76. if( bAutoflipping )
  77. {
  78. surf_int->lpLcl->lpSurfMore->lpVideoPort = lpVideoPort;
  79. }
  80. lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( surf_int->lpLcl->lpGbl );
  81. if( ( lpSurfGblMore->hKernelSurface == 0 ) &&
  82. !( lpVideoPort->dwFlags & DDRAWIVPORT_NOKERNELHANDLES ) )
  83. {
  84. ddRVal = InternalCreateKernelSurfaceHandle( surf_int->lpLcl, &dwHandle );
  85. if( ddRVal == DD_OK )
  86. {
  87. surf_int->lpLcl->lpGbl->dwGlobalFlags |= DDRAWISURFGBL_IMPLICITHANDLE;
  88. }
  89. else
  90. {
  91. /*
  92. * This is not a catastrophic failure, but it will stop us
  93. * from software autoflipping.
  94. */
  95. lpVideoPort->dwFlags |= DDRAWIVPORT_NOKERNELHANDLES;
  96. }
  97. }
  98. surf_int = FindAttachedFlip( surf_int );
  99. } while( ( surf_int != NULL ) && ( surf_int->lpLcl != surf_first->lpLcl ) );
  100. if( !bAutoflipping )
  101. {
  102. surf_first->lpLcl->lpSurfMore->lpVideoPort = lpVideoPort;
  103. }
  104. return DD_OK;
  105. }
  106. /*
  107. * GetVideoPortFromSurface
  108. *
  109. * Returns the video port associated with the surface. The video
  110. * port can be anywhere in the surface list.
  111. */
  112. LPDDRAWI_DDVIDEOPORT_LCL GetVideoPortFromSurface( LPDDRAWI_DDRAWSURFACE_INT surf_int )
  113. {
  114. LPDDRAWI_DDRAWSURFACE_INT surf_first;
  115. LPDDRAWI_DDVIDEOPORT_LCL lpVp;
  116. /*
  117. * Is it associated with video port? If not explicitly, is another
  118. * surface in the chain explicitly associated?
  119. */
  120. lpVp = surf_int->lpLcl->lpSurfMore->lpVideoPort;
  121. if( lpVp == NULL )
  122. {
  123. surf_first = surf_int;
  124. do
  125. {
  126. surf_int = FindAttachedFlip( surf_int );
  127. if( surf_int != NULL )
  128. {
  129. lpVp = surf_int->lpLcl->lpSurfMore->lpVideoPort;
  130. }
  131. }
  132. while( ( surf_int != NULL ) && ( lpVp == NULL ) && ( surf_int->lpLcl != surf_first->lpLcl ) );
  133. }
  134. return lpVp;
  135. }
  136. /*
  137. * Determines if the specified overlay surface can support autoflipping
  138. * Return: 0 = Not valid, 1 = software only, 2 = hardware autoflipping
  139. */
  140. DWORD IsValidAutoFlipSurface( LPDDRAWI_DDRAWSURFACE_INT lpSurface_int )
  141. {
  142. LPDDRAWI_DDRAWSURFACE_INT lpFirstSurf;
  143. LPDDRAWI_DDRAWSURFACE_INT lpSurf;
  144. LPDDRAWI_DDVIDEOPORT_LCL lpVp;
  145. BOOL bFound;
  146. /*
  147. * Is it associated with video port?
  148. */
  149. lpVp = GetVideoPortFromSurface( lpSurface_int );
  150. if( lpVp == NULL )
  151. {
  152. return IVAS_NOAUTOFLIPPING;
  153. }
  154. /*
  155. * Is the video port autoflipping? If not, then neither can the overlay.
  156. */
  157. if( !( lpVp->ddvpInfo.dwVPFlags & DDVP_AUTOFLIP ) )
  158. {
  159. return IVAS_NOAUTOFLIPPING;
  160. }
  161. /*
  162. * It's still possible that VBI is autoflipping, but not the regular
  163. * video (which applies to the overlay).
  164. */
  165. if( lpVp->dwNumAutoflip == 0 )
  166. {
  167. return IVAS_NOAUTOFLIPPING;
  168. }
  169. lpSurf = lpFirstSurf = lpVp->lpSurface;
  170. bFound = FALSE;
  171. if( lpFirstSurf != NULL )
  172. {
  173. do
  174. {
  175. if( lpSurf->lpLcl == lpSurface_int->lpLcl )
  176. {
  177. bFound = TRUE;
  178. }
  179. lpSurf = FindAttachedFlip( lpSurf );
  180. } while( !bFound && ( lpSurf != NULL) && ( lpSurf->lpLcl != lpFirstSurf->lpLcl ) );
  181. }
  182. if( !bFound )
  183. {
  184. return IVAS_NOAUTOFLIPPING;
  185. }
  186. /*
  187. * If the video port is software autoflipping, then the overlay must
  188. * as well.
  189. */
  190. if( lpVp->dwFlags & DDRAWIVPORT_SOFTWARE_AUTOFLIP )
  191. {
  192. return IVAS_SOFTWAREAUTOFLIPPING;
  193. }
  194. return IVAS_HARDWAREAUTOFLIPPING;
  195. }
  196. /*
  197. * Notifies the video port that the overlay will only allow software
  198. * autoflipping
  199. */
  200. VOID RequireSoftwareAutoflip( LPDDRAWI_DDRAWSURFACE_INT lpSurface_int )
  201. {
  202. LPDDRAWI_DDVIDEOPORT_LCL lpVideoPort;
  203. lpVideoPort = GetVideoPortFromSurface( lpSurface_int );
  204. if( lpVideoPort != NULL )
  205. {
  206. lpVideoPort->dwFlags |= DDRAWIVPORT_SOFTWARE_AUTOFLIP;
  207. /*
  208. * If they are already hardware autoflipping, make them switch
  209. * to software.
  210. */
  211. if( lpVideoPort->dwFlags & DDRAWIVPORT_ON )
  212. {
  213. LPDDRAWI_DDVIDEOPORT_INT lpVp_int;
  214. /*
  215. * The next function requires a DDVIDEOPORT_INT and all we
  216. * have is a DDVIDEOPORT_LCL, so we need to search for it.
  217. */
  218. lpVp_int = lpSurface_int->lpLcl->lpSurfMore->lpDD_lcl->lpGbl->dvpList;
  219. while( lpVp_int != NULL )
  220. {
  221. if( ( lpVp_int->lpLcl == lpVideoPort ) &&
  222. !( lpVp_int->dwFlags & DDVPCREATE_NOTIFY ) )
  223. {
  224. InternalUpdateVideo( lpVp_int,
  225. &( lpVp_int->lpLcl->ddvpInfo) );
  226. }
  227. lpVp_int = lpVp_int->lpLink;
  228. }
  229. }
  230. }
  231. }
  232. /*
  233. * Determines if the overlay must be bobbed using software or whether
  234. * it should try software.
  235. */
  236. BOOL MustSoftwareBob( LPDDRAWI_DDRAWSURFACE_INT lpSurface_int )
  237. {
  238. LPDDRAWI_DDVIDEOPORT_LCL lpVp;
  239. /*
  240. * Is it associated with video port?
  241. */
  242. lpVp = GetVideoPortFromSurface( lpSurface_int );
  243. if( lpVp == NULL )
  244. {
  245. return TRUE;
  246. }
  247. /*
  248. * If the video port is software autoflipping or software bobbing,
  249. * then the overlay must as well.
  250. */
  251. if( ( lpVp->dwFlags & DDRAWIVPORT_SOFTWARE_AUTOFLIP ) ||
  252. ( lpVp->dwFlags & DDRAWIVPORT_SOFTWARE_BOB ) )
  253. {
  254. return TRUE;
  255. }
  256. return FALSE;
  257. }
  258. /*
  259. * Notifies the video port that the overlay will only allow software
  260. * bobbing
  261. */
  262. VOID RequireSoftwareBob( LPDDRAWI_DDRAWSURFACE_INT lpSurface_int )
  263. {
  264. LPDDRAWI_DDVIDEOPORT_LCL lpVideoPort;
  265. lpVideoPort = GetVideoPortFromSurface( lpSurface_int );
  266. if( lpVideoPort != NULL )
  267. {
  268. lpVideoPort->dwFlags |= DDRAWIVPORT_SOFTWARE_BOB;
  269. /*
  270. * If they are already hardware autoflipping, make them switch
  271. * to software.
  272. */
  273. if( ( lpVideoPort->dwFlags & DDRAWIVPORT_ON ) &&
  274. ( lpVideoPort->dwNumAutoflip > 0 ) &&
  275. !( lpVideoPort->dwFlags & DDRAWIVPORT_SOFTWARE_AUTOFLIP ) )
  276. {
  277. LPDDRAWI_DDVIDEOPORT_INT lpVp_int;
  278. /*
  279. * The next function requires a DDVIDEOPORT_INT and all we
  280. * have is a DDVIDEOPORT_LCL, so we need to search for it.
  281. */
  282. lpVp_int = lpSurface_int->lpLcl->lpSurfMore->lpDD_lcl->lpGbl->dvpList;
  283. while( lpVp_int != NULL )
  284. {
  285. if( ( lpVp_int->lpLcl == lpVideoPort ) &&
  286. !( lpVp_int->dwFlags & DDVPCREATE_NOTIFY ) )
  287. {
  288. InternalUpdateVideo( lpVp_int,
  289. &( lpVp_int->lpLcl->ddvpInfo) );
  290. }
  291. lpVp_int = lpVp_int->lpLink;
  292. }
  293. }
  294. }
  295. }
  296. #ifdef WIN95
  297. /*
  298. * OverrideOverlay
  299. *
  300. * Checks to see if there is a chance that the kernel mode interface
  301. * has changed the state from bob to weave or visa versa, or if it's
  302. * cahnged from hardware autoflipping to software autoflipping. If the
  303. * chance exists, it calls down to ring 0 to get the state and if
  304. * it's changed, changes the overlay parameters accordingly.
  305. */
  306. VOID OverrideOverlay( LPDDRAWI_DDRAWSURFACE_INT surf_int,
  307. LPDWORD lpdwFlags )
  308. {
  309. LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
  310. LPDDRAWI_DDRAWSURFACE_MORE lpSurfMore;
  311. LPDDRAWI_DDVIDEOPORT_LCL lpVp;
  312. DWORD dwStateFlags;
  313. /*
  314. * Ring 0 can change the state, so we need to call down to it.
  315. */
  316. lpSurfMore = surf_int->lpLcl->lpSurfMore;
  317. lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( surf_int->lpLcl->lpGbl );
  318. if( lpSurfGblMore->hKernelSurface != 0 )
  319. {
  320. dwStateFlags = 0;
  321. GetKernelSurfaceState( surf_int->lpLcl, &dwStateFlags );
  322. if( dwStateFlags & DDSTATE_EXPLICITLY_SET )
  323. {
  324. if( ( dwStateFlags & DDSTATE_BOB ) &&
  325. !( *lpdwFlags & DDOVER_BOB ) )
  326. {
  327. // Switch from weave to bob
  328. *lpdwFlags |= DDOVER_BOB;
  329. }
  330. else if( ( dwStateFlags & DDSTATE_WEAVE ) &&
  331. ( *lpdwFlags & DDOVER_BOB ) )
  332. {
  333. // Switch from bob to weave
  334. *lpdwFlags &= ~DDOVER_BOB;
  335. }
  336. else if( ( dwStateFlags & DDSTATE_SKIPEVENFIELDS ) &&
  337. ( *lpdwFlags & DDOVER_BOB ) )
  338. {
  339. // Switch from bob to weave
  340. *lpdwFlags &= ~DDOVER_BOB;
  341. }
  342. }
  343. lpVp = GetVideoPortFromSurface( surf_int );
  344. if( ( dwStateFlags & DDSTATE_SOFTWARE_AUTOFLIP ) &&
  345. ( lpVp != NULL ) &&
  346. ( lpVp->ddvpInfo.dwVPFlags & DDVP_AUTOFLIP ) &&
  347. !( lpVp->dwFlags & DDRAWIVPORT_SOFTWARE_AUTOFLIP ) )
  348. {
  349. RequireSoftwareAutoflip( surf_int );
  350. }
  351. }
  352. }
  353. /*
  354. * OverrideVideoPort
  355. *
  356. * Checks to see if there is a chance that the kernel mode interface
  357. * has changed the state from bob/weave to field skipping or visa versa.
  358. * If the chance exists, it calls down to ring 0 to get the state and if
  359. * it's changed, changes the overlay parameters accordingly.
  360. */
  361. VOID OverrideVideoPort( LPDDRAWI_DDRAWSURFACE_INT surf_int,
  362. LPDWORD lpdwFlags )
  363. {
  364. LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
  365. LPDDRAWI_DDRAWSURFACE_MORE lpSurfMore;
  366. DWORD dwStateFlags;
  367. /*
  368. * Ring 0 can change the state, so we need to call down to it.
  369. */
  370. lpSurfMore = surf_int->lpLcl->lpSurfMore;
  371. lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( surf_int->lpLcl->lpGbl );
  372. if( lpSurfGblMore->hKernelSurface != 0 )
  373. {
  374. dwStateFlags = 0;
  375. GetKernelSurfaceState( surf_int->lpLcl, &dwStateFlags );
  376. if( dwStateFlags & DDSTATE_EXPLICITLY_SET )
  377. {
  378. if( ( dwStateFlags & DDSTATE_SKIPEVENFIELDS ) &&
  379. !( *lpdwFlags & DDVP_SKIPODDFIELDS ) )
  380. {
  381. // Switch from bob to weave
  382. *lpdwFlags &= ~DDVP_INTERLEAVE;
  383. *lpdwFlags |= DDVP_SKIPEVENFIELDS;
  384. }
  385. }
  386. }
  387. }
  388. #endif
  389. /*
  390. * UpdateInterleavedFlags
  391. *
  392. * We want to track whether the surface data came from a vidoe port or not
  393. * and if it did, was it interleaved. This is important so we can
  394. * automatically set the DDOVER_INTERLEAVED flag while using the video port.
  395. */
  396. VOID UpdateInterleavedFlags( LPDDRAWI_DDVIDEOPORT_LCL this_lcl, DWORD dwVPFlags )
  397. {
  398. LPDDRAWI_DDRAWSURFACE_INT surf_first;
  399. LPDDRAWI_DDRAWSURFACE_INT surf_temp;
  400. /*
  401. * Since the interleaved flag is only used for calling UpdateOverlay,
  402. * we only need to handle this for the regular video.
  403. */
  404. surf_temp = this_lcl->lpSurface;
  405. if( surf_temp == NULL )
  406. {
  407. return;
  408. }
  409. /*
  410. * If autoflipping, update every surface in the chain.
  411. */
  412. if( ( dwVPFlags & DDVP_AUTOFLIP ) && ( this_lcl->dwNumAutoflip > 0 ) )
  413. {
  414. surf_first = surf_temp;
  415. do
  416. {
  417. surf_temp->lpLcl->lpGbl->dwGlobalFlags |= DDRAWISURFGBL_VPORTDATA;
  418. if( dwVPFlags & DDVP_INTERLEAVE )
  419. {
  420. surf_temp->lpLcl->lpGbl->dwGlobalFlags |= DDRAWISURFGBL_VPORTINTERLEAVED;
  421. }
  422. else
  423. {
  424. surf_temp->lpLcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_VPORTINTERLEAVED;
  425. }
  426. surf_temp = FindAttachedFlip( surf_temp );
  427. } while( ( surf_temp != NULL ) && ( surf_temp->lpLcl != surf_first->lpLcl ) );
  428. }
  429. else
  430. {
  431. surf_temp->lpLcl->lpGbl->dwGlobalFlags |= DDRAWISURFGBL_VPORTDATA;
  432. if( dwVPFlags & DDVP_INTERLEAVE )
  433. {
  434. surf_temp->lpLcl->lpGbl->dwGlobalFlags |= DDRAWISURFGBL_VPORTINTERLEAVED;
  435. }
  436. else
  437. {
  438. surf_temp->lpLcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_VPORTINTERLEAVED;
  439. }
  440. }
  441. }
  442. /*
  443. * InternalVideoPortFlip
  444. *
  445. * This fucntion acts differntly based on whether the flip is occurring
  446. * based on an overlay flip or whether an explicit flip was specified.
  447. */
  448. HRESULT InternalVideoPortFlip( LPDDRAWI_DDVIDEOPORT_LCL this_lcl,
  449. LPDDRAWI_DDRAWSURFACE_INT next_int,
  450. BOOL bExplicit )
  451. {
  452. LPDDRAWI_DDRAWSURFACE_LCL next_lcl;
  453. LPDDHALVPORTCB_FLIP pfn;
  454. DDHAL_FLIPVPORTDATA FlipData;
  455. DWORD rc;
  456. /*
  457. * surfaces must be in video memory
  458. */
  459. next_lcl = next_int->lpLcl;
  460. if( next_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  461. {
  462. if ( !( this_lcl->lpDD->lpGbl->lpDDVideoPortCaps[this_lcl->ddvpDesc.dwVideoPortID].dwCaps &
  463. DDVPCAPS_SYSTEMMEMORY ) )
  464. {
  465. DPF_ERR( "Surface must be in video memory" );
  466. return DDERR_INVALIDPARAMS;
  467. }
  468. if( next_lcl->lpSurfMore->dwPageLockCount == 0 )
  469. {
  470. DPF_ERR( "Surface must be page locked" );
  471. return DDERR_INVALIDPARAMS;
  472. }
  473. }
  474. /*
  475. * surfaces must have the VIDEOPORT attribute
  476. */
  477. if( !( next_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOPORT ) )
  478. {
  479. DPF_ERR( "Surface must have the DDSCAPS_VIDEOPORT attribute" );
  480. return DDERR_INVALIDPARAMS;
  481. }
  482. /*
  483. * Tell the HAL to perform the flip
  484. */
  485. pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.FlipVideoPort;
  486. if( pfn != NULL )
  487. {
  488. FlipData.lpDD = this_lcl->lpDD;
  489. FlipData.lpVideoPort = this_lcl;
  490. FlipData.lpSurfCurr = this_lcl->lpSurface->lpLcl;
  491. FlipData.lpSurfTarg = next_lcl;
  492. DOHALCALL( FlipVideoPort, pfn, FlipData, rc, 0 );
  493. if( DDHAL_DRIVER_HANDLED != rc )
  494. {
  495. return DDERR_UNSUPPORTED;
  496. }
  497. else if( DD_OK != FlipData.ddRVal )
  498. {
  499. return FlipData.ddRVal;
  500. }
  501. }
  502. else
  503. {
  504. return DDERR_UNSUPPORTED;
  505. }
  506. /*
  507. * Update the surfaces so they know which one is connected to the
  508. * video port.
  509. */
  510. if( bExplicit )
  511. {
  512. if( this_lcl->lpSurface != NULL )
  513. {
  514. this_lcl->lpSurface->lpLcl->lpSurfMore->lpVideoPort = NULL;
  515. }
  516. next_int->lpLcl->lpSurfMore->lpVideoPort = this_lcl;
  517. this_lcl->lpSurface = next_int;
  518. }
  519. UpdateInterleavedFlags( this_lcl, this_lcl->ddvpInfo.dwVPFlags );
  520. this_lcl->fpLastFlip = next_int->lpLcl->lpGbl->fpVidMem;
  521. return DD_OK;
  522. }
  523. /*
  524. * FlipVideoPortToN
  525. *
  526. * This flips the video port to the next N surface. If N is 1, it flips it
  527. * to the next surface, etc.
  528. */
  529. HRESULT FlipVideoPortToN( LPDDRAWI_DDVIDEOPORT_LCL this_lcl, DWORD dwSkipNum )
  530. {
  531. LPDDRAWI_DDRAWSURFACE_INT surf_int;
  532. DWORD i;
  533. /*
  534. * Get the target surface. We can eliminate a lot of error checking
  535. * since this function is called from DD_Surface_Flip which already
  536. * performs the same error checking.
  537. */
  538. surf_int = this_lcl->lpSurface;
  539. for( i = 0; i < dwSkipNum; i++ )
  540. {
  541. surf_int = FindAttachedFlip( surf_int );
  542. }
  543. if (surf_int == NULL)
  544. {
  545. // Better to do this instead of faulting.
  546. DPF_ERR("Couldn't find Nth flipping surface.");
  547. return DDERR_INVALIDPARAMS;
  548. }
  549. return InternalVideoPortFlip( this_lcl, surf_int, 0 );
  550. }
  551. /*
  552. * FlipVideoPortSurface
  553. *
  554. * Called when flipping a surface that is fed by a video port. This searches
  555. * for each videoport associated with the surface and flips the video port.
  556. */
  557. DWORD FlipVideoPortSurface( LPDDRAWI_DDRAWSURFACE_INT surf_int, DWORD dwNumSkipped )
  558. {
  559. LPDDRAWI_DDRAWSURFACE_INT surf_first;
  560. LPDDRAWI_DIRECTDRAW_GBL lpDD_Gbl;
  561. LPDDRAWI_DDVIDEOPORT_INT lpVp;
  562. LPDDRAWI_DDRAWSURFACE_INT lpSurface;
  563. BOOL bFound;
  564. DWORD rc;
  565. lpDD_Gbl = surf_int->lpLcl->lpSurfMore->lpDD_lcl->lpGbl;
  566. lpVp = lpDD_Gbl->dvpList;
  567. while( lpVp != NULL )
  568. {
  569. bFound = FALSE;
  570. if( ( lpVp->lpLcl->lpSurface != NULL ) &&
  571. !( lpVp->lpLcl->ddvpInfo.dwVPFlags & DDVP_AUTOFLIP ) &&
  572. !( lpVp->dwFlags & DDVPCREATE_NOTIFY ) )
  573. {
  574. surf_first = lpSurface = lpVp->lpLcl->lpSurface;
  575. do
  576. {
  577. if( lpSurface == surf_int )
  578. {
  579. rc = FlipVideoPortToN( lpVp->lpLcl, dwNumSkipped );
  580. bFound = TRUE;
  581. }
  582. lpSurface = FindAttachedFlip( lpSurface );
  583. } while( ( lpSurface != NULL ) && ( lpSurface->lpLcl != surf_first->lpLcl ) );
  584. }
  585. lpVp = lpVp->lpLink;
  586. }
  587. return DD_OK;
  588. }
  589. /*
  590. * IndepenantVBIPossible
  591. *
  592. * Returns TRUE if the specified caps determine it is possible to manage the
  593. * VBI stream completely independant of the video stream.
  594. */
  595. BOOL IndependantVBIPossible( LPDDVIDEOPORTCAPS lpCaps )
  596. {
  597. if( ( lpCaps->dwCaps & ( DDVPCAPS_VBISURFACE|DDVPCAPS_OVERSAMPLEDVBI ) ) !=
  598. ( DDVPCAPS_VBISURFACE | DDVPCAPS_OVERSAMPLEDVBI ) )
  599. {
  600. return FALSE;
  601. }
  602. if( ( lpCaps->dwFX & ( DDVPFX_VBINOSCALE | DDVPFX_IGNOREVBIXCROP |
  603. DDVPFX_VBINOINTERLEAVE ) ) != ( DDVPFX_VBINOSCALE |
  604. DDVPFX_IGNOREVBIXCROP | DDVPFX_VBINOINTERLEAVE ) )
  605. {
  606. return FALSE;
  607. }
  608. return TRUE;
  609. }
  610. /*
  611. * DDVPC_EnumVideoPorts
  612. */
  613. HRESULT DDAPI DDVPC_EnumVideoPorts(
  614. LPDDVIDEOPORTCONTAINER lpDVP,
  615. DWORD dwReserved,
  616. LPDDVIDEOPORTCAPS lpCaps,
  617. LPVOID lpContext,
  618. LPDDENUMVIDEOCALLBACK lpEnumCallback )
  619. {
  620. LPDDRAWI_DIRECTDRAW_INT this_int;
  621. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  622. LPDDVIDEOPORTCAPS lpHALCaps;
  623. DWORD rc;
  624. DWORD dwMaxVideoPorts;
  625. DWORD flags;
  626. DWORD i;
  627. BOOL bEnumThisOne;
  628. ENTER_DDRAW();
  629. DPF(2,A,"ENTERAPI: DDVPC_EnumVideoPorts");
  630. /*
  631. * Don't allow access to this function if called from within the
  632. * the EnumVideoPort callback.
  633. */
  634. if( bInEnumCallback )
  635. {
  636. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  637. LEAVE_DDRAW();
  638. return DDERR_CURRENTLYNOTAVAIL;
  639. }
  640. /*
  641. * validate parameters
  642. */
  643. TRY
  644. {
  645. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDVP;
  646. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  647. {
  648. DPF_ERR( "Invalid video port container specified" );
  649. LEAVE_DDRAW();
  650. return DDERR_INVALIDOBJECT;
  651. }
  652. this_lcl = this_int->lpLcl;
  653. if( !VALIDEX_CODE_PTR( lpEnumCallback ) )
  654. {
  655. DPF_ERR( "Invalid callback routine" );
  656. LEAVE_DDRAW();
  657. return DDERR_INVALIDPARAMS;
  658. }
  659. if( NULL == lpCaps )
  660. {
  661. /*
  662. * If a NULL description is defined, we will assume that they
  663. * want to enum everything.
  664. */
  665. flags = 0;
  666. }
  667. else
  668. {
  669. if( !VALID_DDVIDEOPORTCAPS_PTR( lpCaps ) )
  670. {
  671. DPF_ERR( "Invalid DDVIDEOPORTCAPS specified" );
  672. LEAVE_DDRAW();
  673. return DDERR_INVALIDPARAMS;
  674. }
  675. flags = lpCaps->dwFlags;
  676. /*
  677. * check height/width
  678. */
  679. if( ((flags & DDVPD_HEIGHT) && !(flags & DDVPD_WIDTH)) ||
  680. (!(flags & DDVPD_HEIGHT) && (flags & DDVPD_WIDTH)) )
  681. {
  682. DPF_ERR( "Specify both height & width in video port desc" );
  683. LEAVE_DDRAW();
  684. return DDERR_INVALIDPARAMS;
  685. }
  686. if( lpCaps->dwVideoPortID >= this_lcl->lpGbl->ddCaps.dwMaxVideoPorts )
  687. {
  688. DPF_ERR( "Invalid video port ID specified" );
  689. LEAVE_DDRAW();
  690. return DDERR_INVALIDPARAMS;
  691. }
  692. }
  693. if( NULL == this_lcl->lpGbl->lpDDVideoPortCaps )
  694. {
  695. DPF_ERR( "Driver failed query for video port caps" );
  696. LEAVE_DDRAW();
  697. return DDERR_UNSUPPORTED;
  698. }
  699. for( i = 0; i < this_lcl->lpGbl->ddCaps.dwMaxVideoPorts; i++ )
  700. {
  701. lpHALCaps = &(this_lcl->lpGbl->lpDDVideoPortCaps[i]);
  702. if( !VALID_DDVIDEOPORTCAPS_PTR( lpHALCaps ) )
  703. {
  704. DPF_ERR( "Driver returned invalid DDVIDEOPORTCAPS" );
  705. LEAVE_DDRAW();
  706. return DDERR_UNSUPPORTED;
  707. }
  708. }
  709. }
  710. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  711. {
  712. DPF_ERR( "Exception encountered validating parameters" );
  713. LEAVE_DDRAW();
  714. return DDERR_INVALIDPARAMS;
  715. }
  716. /*
  717. * Look at each video port and match it with the input description.
  718. */
  719. dwMaxVideoPorts = this_lcl->lpGbl->ddCaps.dwMaxVideoPorts;
  720. lpHALCaps = this_lcl->lpGbl->lpDDVideoPortCaps;
  721. for (i = 0; i < dwMaxVideoPorts; i++)
  722. {
  723. bEnumThisOne = TRUE;
  724. if( flags & DDVPD_WIDTH )
  725. {
  726. if( lpCaps->dwMaxWidth > lpHALCaps->dwMaxWidth )
  727. bEnumThisOne = FALSE;
  728. }
  729. if( flags & DDVPD_HEIGHT )
  730. {
  731. if( lpCaps->dwMaxHeight > lpHALCaps->dwMaxHeight )
  732. bEnumThisOne = FALSE;
  733. }
  734. if( flags & DDVPD_ID )
  735. {
  736. if( lpCaps->dwVideoPortID != lpHALCaps->dwVideoPortID )
  737. bEnumThisOne = FALSE;
  738. }
  739. if( flags & DDVPD_CAPS )
  740. {
  741. /*
  742. * Simple check to make sure no caps were specified that are
  743. * not returned by the HAL.
  744. */
  745. if ( (lpCaps->dwCaps & lpHALCaps->dwCaps) != lpCaps->dwCaps )
  746. bEnumThisOne = FALSE;
  747. }
  748. if( flags & DDVPD_FX )
  749. {
  750. /*
  751. * Simple check to make sure no FX were specified that are
  752. * not returned by the HAL.
  753. */
  754. if ( (lpCaps->dwFX & lpHALCaps->dwFX) != lpCaps->dwFX )
  755. bEnumThisOne = FALSE;
  756. }
  757. if ( TRUE == bEnumThisOne )
  758. {
  759. /*
  760. * Don't trust the drivers to set this bit correctly (especially
  761. * since we are adding it so late)
  762. */
  763. if( IndependantVBIPossible( lpHALCaps ) )
  764. {
  765. lpHALCaps->dwCaps |= DDVPCAPS_VBIANDVIDEOINDEPENDENT;
  766. }
  767. else
  768. {
  769. lpHALCaps->dwCaps &= ~DDVPCAPS_VBIANDVIDEOINDEPENDENT;
  770. }
  771. /*
  772. * We added the dwNumPrefferedAutoflip for Memphis, so some
  773. * old drivers might not report this correctly. For that reason,
  774. * we will attempt to fill in a valid value.
  775. */
  776. if( !( lpHALCaps->dwFlags & DDVPD_PREFERREDAUTOFLIP ) )
  777. {
  778. /*
  779. * The driver did not set this, so we should force the
  780. * value to 3.
  781. */
  782. lpHALCaps->dwNumPreferredAutoflip = 3;
  783. lpHALCaps->dwFlags |= DDVPD_PREFERREDAUTOFLIP;
  784. }
  785. if( lpHALCaps->dwNumPreferredAutoflip > lpHALCaps->dwNumAutoFlipSurfaces )
  786. {
  787. lpHALCaps->dwNumPreferredAutoflip = lpHALCaps->dwNumAutoFlipSurfaces;
  788. }
  789. bInEnumCallback = TRUE;
  790. rc = lpEnumCallback( lpHALCaps, lpContext );
  791. bInEnumCallback = FALSE;
  792. if( rc == 0 )
  793. {
  794. break;
  795. }
  796. }
  797. lpHALCaps++;
  798. }
  799. LEAVE_DDRAW();
  800. return DD_OK;
  801. } /* DDVPC_EnumVideoPorts */
  802. /*
  803. * DDVPC_GetVideoPortConnectInfo
  804. */
  805. HRESULT DDAPI DDVPC_GetVideoPortConnectInfo(
  806. LPDDVIDEOPORTCONTAINER lpDVP,
  807. DWORD dwVideoPortID,
  808. LPDWORD lpdwNumEntries,
  809. LPDDVIDEOPORTCONNECT lpConnect )
  810. {
  811. LPDDHALVPORTCB_GETVPORTCONNECT pfn;
  812. LPDDRAWI_DIRECTDRAW_INT this_int;
  813. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  814. LPDDVIDEOPORTCONNECT lpTemp;
  815. DDHAL_GETVPORTCONNECTDATA GetGuidData;
  816. DWORD rc;
  817. DWORD i;
  818. ENTER_DDRAW();
  819. DPF(2,A,"ENTERAPI: DDVPC_GetVideoPortConnectInfo");
  820. /*
  821. * Don't allow access to this function if called from within the
  822. * the EnumVideoPort callback.
  823. */
  824. if( bInEnumCallback )
  825. {
  826. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  827. LEAVE_DDRAW();
  828. return DDERR_CURRENTLYNOTAVAIL;
  829. }
  830. /*
  831. * Validate parameters
  832. */
  833. TRY
  834. {
  835. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDVP;
  836. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  837. {
  838. DPF_ERR ( "DDVPC_GetVideoPortConnectInfo: Invalid DirectDraw ptr");
  839. LEAVE_DDRAW();
  840. return DDERR_INVALIDOBJECT;
  841. }
  842. this_lcl = this_int->lpLcl;
  843. #ifdef WINNT
  844. // Update DDraw handle in driver GBL object.
  845. this_lcl->lpGbl->hDD = this_lcl->hDD;
  846. #endif
  847. if( dwVideoPortID >= this_lcl->lpGbl->ddCaps.dwMaxVideoPorts )
  848. {
  849. DPF_ERR ( "DDVPC_GetVideoPortConnectInfo: invalid port ID");
  850. LEAVE_DDRAW();
  851. return DDERR_INVALIDPARAMS;
  852. }
  853. if( (lpdwNumEntries == NULL) || !VALID_BYTE_ARRAY( lpdwNumEntries, sizeof( LPVOID ) ) )
  854. {
  855. DPF_ERR ( "DDVPC_GetVideoPortConnectInfo: numentries not valid");
  856. LEAVE_DDRAW();
  857. return DDERR_INVALIDPARAMS;
  858. }
  859. if( NULL != lpConnect )
  860. {
  861. if( 0 == *lpdwNumEntries )
  862. {
  863. DPF_ERR ( "DDVPC_GetVideoPortConnectInfo: numentries not valid");
  864. LEAVE_DDRAW();
  865. return DDERR_INVALIDPARAMS;
  866. }
  867. if( !VALID_BYTE_ARRAY( lpConnect, *lpdwNumEntries * sizeof( DDVIDEOPORTCONNECT ) ) )
  868. {
  869. DPF_ERR ( "DDVPC_GetVideoPortConnectInfo: invalid array passed in");
  870. LEAVE_DDRAW();
  871. return DDERR_INVALIDPARAMS;
  872. }
  873. }
  874. }
  875. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  876. {
  877. DPF_ERR( "Exception encountered validating parameters" );
  878. LEAVE_DDRAW();
  879. return DDERR_EXCEPTION;
  880. }
  881. pfn = this_int->lpLcl->lpDDCB->HALDDVideoPort.GetVideoPortConnectInfo;
  882. if( pfn != NULL )
  883. {
  884. /*
  885. * Get the number of GUIDs
  886. */
  887. GetGuidData.lpDD = this_int->lpLcl;
  888. GetGuidData.dwPortId = dwVideoPortID;
  889. GetGuidData.lpConnect = NULL;
  890. DOHALCALL( GetVideoPortConnectInfo, pfn, GetGuidData, rc, 0 );
  891. if( DDHAL_DRIVER_HANDLED != rc )
  892. {
  893. LEAVE_DDRAW();
  894. return GetGuidData.ddRVal;
  895. }
  896. else if( DD_OK != GetGuidData.ddRVal )
  897. {
  898. LEAVE_DDRAW();
  899. return GetGuidData.ddRVal;
  900. }
  901. if( NULL == lpConnect )
  902. {
  903. *lpdwNumEntries = GetGuidData.dwNumEntries;
  904. }
  905. else
  906. {
  907. /*
  908. * Make sure we have enough room for GUIDs
  909. */
  910. if( GetGuidData.dwNumEntries > *lpdwNumEntries )
  911. {
  912. lpTemp = (LPDDVIDEOPORTCONNECT) MemAlloc(
  913. sizeof( DDVIDEOPORTCONNECT ) * GetGuidData.dwNumEntries );
  914. GetGuidData.lpConnect = lpTemp;
  915. }
  916. else
  917. {
  918. GetGuidData.lpConnect = lpConnect;
  919. }
  920. DOHALCALL( GetVideoPortConnectInfo, pfn, GetGuidData, rc, 0 );
  921. if( DDHAL_DRIVER_HANDLED != rc )
  922. {
  923. LEAVE_DDRAW();
  924. return DDERR_UNSUPPORTED;
  925. }
  926. else if( DD_OK != GetGuidData.ddRVal )
  927. {
  928. LEAVE_DDRAW();
  929. return GetGuidData.ddRVal;
  930. }
  931. /*
  932. * Make sure the reserved fields are set to 0
  933. */
  934. for( i = 0; i < *lpdwNumEntries; i++ )
  935. {
  936. GetGuidData.lpConnect[i].dwReserved1 = 0;
  937. }
  938. if( GetGuidData.lpConnect != lpConnect )
  939. {
  940. memcpy( lpConnect, lpTemp,
  941. sizeof( DDVIDEOPORTCONNECT ) * *lpdwNumEntries );
  942. MemFree( lpTemp );
  943. LEAVE_DDRAW();
  944. return DDERR_MOREDATA;
  945. }
  946. else
  947. {
  948. *lpdwNumEntries = GetGuidData.dwNumEntries;
  949. }
  950. }
  951. }
  952. else
  953. {
  954. LEAVE_DDRAW();
  955. return DDERR_UNSUPPORTED;
  956. }
  957. LEAVE_DDRAW();
  958. return DD_OK;
  959. } /* DDVPC_GetVideoPortConnectInfo */
  960. /*
  961. * DDVPC_QueryVideoPortStatus
  962. */
  963. HRESULT DDAPI DDVPC_QueryVideoPortStatus(
  964. LPDDVIDEOPORTCONTAINER lpDVP,
  965. DWORD dwVideoPortID,
  966. LPDDVIDEOPORTSTATUS lpStatus )
  967. {
  968. LPDDRAWI_DIRECTDRAW_INT this_int;
  969. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  970. LPDDRAWI_DIRECTDRAW_GBL this;
  971. LPDDRAWI_DDVIDEOPORT_INT lpVP_int;
  972. ENTER_DDRAW();
  973. DPF(2,A,"ENTERAPI: DDVPC_QueryVideoPortStatus");
  974. /*
  975. * Don't allow access to this function if called from within the
  976. * the EnumVideoPort callback.
  977. */
  978. if( bInEnumCallback )
  979. {
  980. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  981. LEAVE_DDRAW();
  982. return DDERR_CURRENTLYNOTAVAIL;
  983. }
  984. /*
  985. * Validate parameters
  986. */
  987. TRY
  988. {
  989. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDVP;
  990. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  991. {
  992. LEAVE_DDRAW();
  993. return DDERR_INVALIDOBJECT;
  994. }
  995. this_lcl = this_int->lpLcl;
  996. this = this_lcl->lpGbl;
  997. if( ( lpStatus == NULL ) || !VALID_DDVIDEOPORTSTATUS_PTR( lpStatus ) )
  998. {
  999. DPF_ERR ( "DDVPC_QueryVideoPortStatus: Invalid DDVIDEOPORTSTATUS ptr");
  1000. LEAVE_DDRAW();
  1001. return DDERR_INVALIDOBJECT;
  1002. }
  1003. memset( lpStatus, 0, sizeof( DDVIDEOPORTSTATUS ) );
  1004. lpStatus->dwSize = sizeof( DDVIDEOPORTSTATUS );
  1005. if( dwVideoPortID >= this->ddCaps.dwMaxVideoPorts )
  1006. {
  1007. DPF_ERR ( "DDVPC_QueryVideoPortStatus: Invalid Video Port ID specified");
  1008. LEAVE_DDRAW();
  1009. return DDERR_INVALIDPARAMS;
  1010. }
  1011. }
  1012. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1013. {
  1014. DPF_ERR( "Exception encountered validating parameters" );
  1015. LEAVE_DDRAW();
  1016. return DDERR_EXCEPTION;
  1017. }
  1018. /*
  1019. * Search the list of video ports to see if anybody's using this one
  1020. */
  1021. lpVP_int = this->dvpList;
  1022. while( lpVP_int != NULL )
  1023. {
  1024. if( ( lpVP_int->lpLcl->ddvpDesc.dwVideoPortID == dwVideoPortID ) &&
  1025. !( lpVP_int->dwFlags & DDVPCREATE_NOTIFY ) )
  1026. {
  1027. /*
  1028. * One does exist - return info about it
  1029. */
  1030. lpStatus->bInUse = TRUE;
  1031. memcpy( &(lpStatus->VideoPortType),
  1032. &(lpVP_int->lpLcl->ddvpDesc.VideoPortType),
  1033. sizeof( DDVIDEOPORTCONNECT ) );
  1034. lpStatus->dwFlags |= lpVP_int->dwFlags;
  1035. }
  1036. lpVP_int = lpVP_int->lpLink;
  1037. }
  1038. if( ( lpStatus->dwFlags & DDVPCREATE_VBIONLY ) &&
  1039. ( lpStatus->dwFlags & DDVPCREATE_VIDEOONLY ) )
  1040. {
  1041. lpStatus->dwFlags = 0;
  1042. }
  1043. LEAVE_DDRAW();
  1044. return DD_OK;
  1045. } /* DDVPC_QueryVideoPortStatus */
  1046. /*
  1047. * InsertVideoPortInList
  1048. */
  1049. VOID InsertVideoPortInList( LPDDRAWI_DIRECTDRAW_GBL lpGbl, LPDDRAWI_DDVIDEOPORT_INT lpNew )
  1050. {
  1051. if( NULL == lpGbl->dvpList )
  1052. {
  1053. lpGbl->dvpList = lpNew;
  1054. }
  1055. else
  1056. {
  1057. LPDDRAWI_DDVIDEOPORT_INT lpTemp;
  1058. lpTemp = lpGbl->dvpList;
  1059. while( NULL != lpTemp->lpLink )
  1060. {
  1061. lpTemp = lpTemp->lpLink;
  1062. }
  1063. lpTemp->lpLink = lpNew;
  1064. }
  1065. }
  1066. /*
  1067. * IncrementRefCounts
  1068. *
  1069. * Used to increment the reference count of all surfaces that could
  1070. * receive data from the video port, insuring that a surface isn't released
  1071. * while we are using it.
  1072. */
  1073. VOID IncrementRefCounts( LPDDRAWI_DDRAWSURFACE_INT surf_int )
  1074. {
  1075. LPDDRAWI_DDRAWSURFACE_INT surf_first;
  1076. surf_first = surf_int;
  1077. do
  1078. {
  1079. DD_Surface_AddRef( (LPDIRECTDRAWSURFACE) surf_int );
  1080. surf_int = FindAttachedFlip( surf_int );
  1081. } while( ( surf_int != NULL ) && ( surf_int->lpLcl != surf_first->lpLcl ) );
  1082. }
  1083. /*
  1084. * DecrementRefCounts
  1085. *
  1086. * Used to decrement the reference count of all surfaces that were previously
  1087. * AddRefed because they were using the video port.
  1088. */
  1089. VOID DecrementRefCounts( LPDDRAWI_DDRAWSURFACE_INT surf_int )
  1090. {
  1091. LPDDRAWI_DDRAWSURFACE_INT *lpSurfList;
  1092. LPDDRAWI_DDRAWSURFACE_INT surf_first;
  1093. DWORD dwCnt;
  1094. DWORD i;
  1095. /*
  1096. * We cannot simply walk the chain, releasing each surface as we go
  1097. * because if the ref cnt goes to zero, the chain goes away and we
  1098. * cannot get to the next surface becasue the current interface is
  1099. * unusable. For this reason, we cnt how many explicit surfaces are
  1100. * in the chain, allocate a buffer to store all of them, and then
  1101. * release them without walking the chain.
  1102. *
  1103. * We do not release the implicitly created surfaces since 1) DirectDraw
  1104. * ignores this anyway and 2) they are immediately released when
  1105. * releasing their explicit surface, so touching them can be dangerous.
  1106. */
  1107. dwCnt = 0;
  1108. surf_first = surf_int;
  1109. do
  1110. {
  1111. if( !( surf_int->lpLcl->dwFlags & DDRAWISURF_IMPLICITCREATE ) )
  1112. {
  1113. dwCnt++;
  1114. }
  1115. surf_int = FindAttachedFlip( surf_int );
  1116. } while( ( surf_int != NULL ) && ( surf_int->lpLcl != surf_first->lpLcl ) );
  1117. lpSurfList = (LPDDRAWI_DDRAWSURFACE_INT *) MemAlloc( dwCnt *
  1118. sizeof( surf_first ) );
  1119. if( lpSurfList == NULL )
  1120. {
  1121. return;
  1122. }
  1123. /*
  1124. * Now put the surfaces in the list
  1125. */
  1126. i = 0;
  1127. surf_int = surf_first;
  1128. do
  1129. {
  1130. if( !( surf_int->lpLcl->dwFlags & DDRAWISURF_IMPLICITCREATE ) )
  1131. {
  1132. lpSurfList[i++] = surf_int;
  1133. }
  1134. surf_int = FindAttachedFlip( surf_int );
  1135. } while( ( surf_int != NULL ) && ( surf_int->lpLcl != surf_first->lpLcl ) );
  1136. /*
  1137. * Now release them
  1138. */
  1139. for( i = 0; i < dwCnt; i++ )
  1140. {
  1141. DD_Surface_Release( (LPDIRECTDRAWSURFACE) lpSurfList[i] );
  1142. }
  1143. MemFree( lpSurfList );
  1144. }
  1145. /*
  1146. * MergeVPDescriptions
  1147. *
  1148. * This function takes two DDVIDEOPORTDESC structures (one for VBI and one
  1149. * for video) and merges them into a single structure. If only one is
  1150. * passed, it does a memcpy.
  1151. */
  1152. VOID MergeVPDescriptions( LPDDVIDEOPORTDESC lpOutDesc,
  1153. LPDDVIDEOPORTDESC lpInDesc, LPDDRAWI_DDVIDEOPORT_INT lpOtherInt )
  1154. {
  1155. memcpy( lpOutDesc, lpInDesc, sizeof( DDVIDEOPORTDESC ) );
  1156. if( lpOtherInt != NULL )
  1157. {
  1158. if( lpOtherInt->dwFlags & DDVPCREATE_VIDEOONLY )
  1159. {
  1160. lpOutDesc->dwFieldWidth = lpOtherInt->lpLcl->ddvpDesc.dwFieldWidth;
  1161. }
  1162. else
  1163. {
  1164. lpOutDesc->dwVBIWidth = lpOtherInt->lpLcl->ddvpDesc.dwVBIWidth;
  1165. }
  1166. if( lpOtherInt->lpLcl->ddvpDesc.dwFieldHeight > lpOutDesc->dwFieldHeight )
  1167. {
  1168. lpOutDesc->dwFieldHeight = lpOtherInt->lpLcl->ddvpDesc.dwFieldHeight;
  1169. }
  1170. if( lpOtherInt->lpLcl->ddvpDesc.dwMicrosecondsPerField >
  1171. lpOutDesc->dwMicrosecondsPerField )
  1172. {
  1173. lpOutDesc->dwMicrosecondsPerField =
  1174. lpOtherInt->lpLcl->ddvpDesc.dwMicrosecondsPerField;
  1175. }
  1176. if( lpOtherInt->lpLcl->ddvpDesc.dwMaxPixelsPerSecond >
  1177. lpOutDesc->dwMaxPixelsPerSecond )
  1178. {
  1179. lpOutDesc->dwMaxPixelsPerSecond =
  1180. lpOtherInt->lpLcl->ddvpDesc.dwMaxPixelsPerSecond;
  1181. }
  1182. }
  1183. }
  1184. /*
  1185. * MergeVPInfo
  1186. *
  1187. * This function takes two DDVIDEOPORTINFO structures (one for VBI and one
  1188. * for video) and merges them into a single structure.
  1189. */
  1190. HRESULT MergeVPInfo( LPDDRAWI_DDVIDEOPORT_LCL lpVP, LPDDVIDEOPORTINFO lpVBIInfo,
  1191. LPDDVIDEOPORTINFO lpVideoInfo, LPDDVIDEOPORTINFO lpOutInfo )
  1192. {
  1193. /*
  1194. * First, handle the case where only one interface is on. Also, we
  1195. * require that the following be true for VBI/Video-only video ports:
  1196. * 1) They both must set the dwVBIHeight.
  1197. * 2) Neither one can crop the area immediately adjacent to the other.
  1198. */
  1199. if( lpVBIInfo == NULL )
  1200. {
  1201. if( lpVideoInfo->dwVBIHeight == 0 )
  1202. {
  1203. DPF_ERR( "Video-only video port failed to set dwVBIHeight" );
  1204. return DDERR_INVALIDPARAMS;
  1205. }
  1206. memcpy( lpOutInfo, lpVideoInfo, sizeof( DDVIDEOPORTINFO ) );
  1207. if( lpVideoInfo->dwVPFlags & DDVP_CROP )
  1208. {
  1209. if( lpVideoInfo->rCrop.top > (int) lpVideoInfo->dwVBIHeight )
  1210. {
  1211. DPF_ERR( "rCrop.top > dwVBIHeight on video-only video port" );
  1212. return DDERR_INVALIDPARAMS;
  1213. }
  1214. lpOutInfo->rCrop.top = lpVideoInfo->dwVBIHeight;
  1215. }
  1216. else
  1217. {
  1218. lpOutInfo->dwVPFlags |= DDVP_CROP;
  1219. lpOutInfo->rCrop.top = lpVideoInfo->dwVBIHeight;
  1220. lpOutInfo->rCrop.left = 0;
  1221. lpOutInfo->rCrop.right = lpVP->lpVideoDesc->dwFieldWidth;
  1222. lpOutInfo->rCrop.bottom = lpVP->lpVideoDesc->dwFieldHeight;
  1223. }
  1224. }
  1225. else if( lpVideoInfo == NULL )
  1226. {
  1227. if( lpVBIInfo->dwVBIHeight == 0 )
  1228. {
  1229. DPF_ERR( "VBI-only video port failed to set dwVBIHeight" );
  1230. return DDERR_INVALIDPARAMS;
  1231. }
  1232. memcpy( lpOutInfo, lpVBIInfo, sizeof( DDVIDEOPORTINFO ) );
  1233. if( lpVBIInfo->dwVPFlags & DDVP_CROP )
  1234. {
  1235. if( lpVBIInfo->rCrop.bottom < (int) lpVBIInfo->dwVBIHeight )
  1236. {
  1237. DPF_ERR( "rCrop.bottom < dwVBIHeight on VBI-only video port" );
  1238. return DDERR_INVALIDPARAMS;
  1239. }
  1240. lpOutInfo->rCrop.bottom = lpVBIInfo->dwVBIHeight;
  1241. }
  1242. else
  1243. {
  1244. lpOutInfo->dwVPFlags |= DDVP_CROP;
  1245. lpOutInfo->rCrop.top = 0;
  1246. lpOutInfo->rCrop.bottom = lpVBIInfo->dwVBIHeight;
  1247. lpOutInfo->rCrop.left = 0;
  1248. lpOutInfo->rCrop.right = lpVP->lpVBIDesc->dwVBIWidth;
  1249. }
  1250. }
  1251. /*
  1252. * Now handle the case where both are on and we have to truly merge them.
  1253. */
  1254. else
  1255. {
  1256. memset( lpOutInfo, 0, sizeof( DDVIDEOPORTINFO ) );
  1257. lpOutInfo->dwSize = sizeof( DDVIDEOPORTINFO );
  1258. lpOutInfo->dwOriginX = lpVideoInfo->dwOriginX;
  1259. lpOutInfo->dwOriginY = lpVideoInfo->dwOriginY;
  1260. lpOutInfo->dwVPFlags = lpVideoInfo->dwVPFlags | lpVBIInfo->dwVPFlags;
  1261. lpOutInfo->dwVBIHeight = lpVBIInfo->dwVBIHeight;
  1262. /*
  1263. * Fix up the cropping.
  1264. */
  1265. if( lpOutInfo->dwVPFlags & DDVP_CROP )
  1266. {
  1267. if( ( lpVBIInfo->dwVPFlags & DDVP_CROP ) &&
  1268. ( lpVBIInfo->rCrop.bottom < (int) lpVBIInfo->dwVBIHeight ) )
  1269. {
  1270. DPF_ERR( "rCrop.bottom < dwVBIHeight on VBI-only video port" );
  1271. return DDERR_INVALIDPARAMS;
  1272. }
  1273. if( ( lpVideoInfo->dwVPFlags & DDVP_CROP ) &&
  1274. ( lpVideoInfo->rCrop.top > (int) lpVideoInfo->dwVBIHeight ) )
  1275. {
  1276. DPF_ERR( "rCrop.top > dwVBIHeight on video-only video port" );
  1277. return DDERR_INVALIDPARAMS;
  1278. }
  1279. lpOutInfo->dwVPFlags |= DDVP_IGNOREVBIXCROP;
  1280. if( lpVBIInfo->dwVPFlags & DDVP_CROP )
  1281. {
  1282. lpOutInfo->rCrop.top = lpVBIInfo->rCrop.top;
  1283. }
  1284. else
  1285. {
  1286. lpOutInfo->rCrop.top = 0;
  1287. }
  1288. if( lpVideoInfo->dwVPFlags & DDVP_CROP )
  1289. {
  1290. lpOutInfo->rCrop.bottom = lpVideoInfo->rCrop.bottom;
  1291. lpOutInfo->rCrop.left = lpVideoInfo->rCrop.left;
  1292. lpOutInfo->rCrop.right = lpVideoInfo->rCrop.right;
  1293. }
  1294. else
  1295. {
  1296. lpOutInfo->rCrop.bottom = lpVP->lpVideoDesc->dwFieldHeight;
  1297. lpOutInfo->rCrop.left = 0;
  1298. lpOutInfo->rCrop.right = lpVP->lpVideoDesc->dwFieldWidth;
  1299. }
  1300. }
  1301. else if( lpVP->ddvpDesc.dwFieldHeight > lpVP->lpVideoDesc->dwFieldHeight )
  1302. {
  1303. lpOutInfo->dwVPFlags |= DDVP_CROP;
  1304. lpOutInfo->rCrop.top = 0;
  1305. lpOutInfo->rCrop.bottom = lpVP->lpVideoDesc->dwFieldHeight;
  1306. lpOutInfo->rCrop.left = 0;
  1307. lpOutInfo->rCrop.right = lpVP->lpVideoDesc->dwFieldWidth;
  1308. }
  1309. /*
  1310. * Handle pre-scaling. Assume that VBI video ports are not allowed
  1311. * to prescale.
  1312. */
  1313. if( lpVBIInfo->dwVPFlags & DDVP_PRESCALE )
  1314. {
  1315. DPF_ERR( "VBI-only video port set DDVP_PRESCALE" );
  1316. return DDERR_INVALIDPARAMS;
  1317. }
  1318. else if( lpVideoInfo->dwVPFlags & DDVP_PRESCALE )
  1319. {
  1320. lpOutInfo->dwPrescaleWidth = lpVideoInfo->dwPrescaleWidth;
  1321. lpOutInfo->dwPrescaleHeight = lpVideoInfo->dwPrescaleHeight;
  1322. }
  1323. lpOutInfo->lpddpfInputFormat = lpVideoInfo->lpddpfInputFormat;
  1324. lpOutInfo->lpddpfVBIInputFormat = lpVBIInfo->lpddpfVBIInputFormat;
  1325. lpOutInfo->lpddpfVBIOutputFormat = lpVBIInfo->lpddpfVBIOutputFormat;
  1326. }
  1327. return DD_OK;
  1328. }
  1329. /*
  1330. * DDVPC_CreateVideoPort
  1331. */
  1332. HRESULT DDAPI DDVPC_CreateVideoPort(
  1333. LPDDVIDEOPORTCONTAINER lpDVP,
  1334. DWORD dwClientFlags,
  1335. LPDDVIDEOPORTDESC lpDesc,
  1336. LPDIRECTDRAWVIDEOPORT FAR *lplpDDVideoPort,
  1337. IUnknown FAR *pUnkOuter )
  1338. {
  1339. DDVIDEOPORTDESC ddTempDesc;
  1340. LPDDRAWI_DIRECTDRAW_INT this_int;
  1341. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  1342. LPDDRAWI_DIRECTDRAW_GBL this;
  1343. LPDDRAWI_DDVIDEOPORT_INT lpVPInt;
  1344. LPDDRAWI_DDVIDEOPORT_INT lpEven;
  1345. LPDDRAWI_DDVIDEOPORT_INT lpOdd;
  1346. LPDDRAWI_DDVIDEOPORT_INT lpOtherInt = NULL;
  1347. LPDDVIDEOPORTCAPS lpAvailCaps;
  1348. LPDDHALVPORTCB_CANCREATEVIDEOPORT ccvppfn;
  1349. LPDDHALVPORTCB_CREATEVIDEOPORT cvppfn;
  1350. LPDDRAWI_DDVIDEOPORT_INT new_int;
  1351. LPDDRAWI_DDVIDEOPORT_LCL new_lcl;
  1352. DWORD dwAvailCaps;
  1353. DWORD dwConnectFlags;
  1354. DWORD rc;
  1355. if( pUnkOuter != NULL )
  1356. {
  1357. return CLASS_E_NOAGGREGATION;
  1358. }
  1359. ENTER_DDRAW();
  1360. DPF(2,A,"ENTERAPI: DDVPC_CreateVideoPort");
  1361. /*
  1362. * Don't allow access to this function if called from within the
  1363. * the EnumVideoPort callback.
  1364. */
  1365. if( bInEnumCallback )
  1366. {
  1367. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  1368. LEAVE_DDRAW();
  1369. return DDERR_CURRENTLYNOTAVAIL;
  1370. }
  1371. /*
  1372. * Validate parameters
  1373. */
  1374. TRY
  1375. {
  1376. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDVP;
  1377. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  1378. {
  1379. LEAVE_DDRAW();
  1380. return DDERR_INVALIDOBJECT;
  1381. }
  1382. this_lcl = this_int->lpLcl;
  1383. this = this_lcl->lpGbl;
  1384. #ifdef WINNT
  1385. // Update DDraw handle in driver GBL object.
  1386. this->hDD = this_lcl->hDD;
  1387. #endif
  1388. if( dwClientFlags & ~( DDVPCREATE_VBIONLY|DDVPCREATE_VIDEOONLY) )
  1389. {
  1390. DPF_ERR( "Invalid flags specified" );
  1391. LEAVE_DDRAW();
  1392. return DDERR_INVALIDPARAMS;
  1393. }
  1394. if( dwClientFlags == ( DDVPCREATE_VBIONLY | DDVPCREATE_VIDEOONLY ) )
  1395. {
  1396. /*
  1397. * SPecifying boht flags is the same as specifying neither
  1398. */
  1399. dwClientFlags = 0;
  1400. }
  1401. if( ( NULL == lpDesc ) || !VALID_DDVIDEOPORTDESC_PTR( lpDesc ) )
  1402. {
  1403. LEAVE_DDRAW();
  1404. return DDERR_INVALIDPARAMS;
  1405. }
  1406. if( ( NULL == lplpDDVideoPort ) || !VALID_PTR_PTR( lplpDDVideoPort ) )
  1407. {
  1408. LEAVE_DDRAW();
  1409. return DDERR_INVALIDPARAMS;
  1410. }
  1411. if( NULL == this->lpDDVideoPortCaps )
  1412. {
  1413. LEAVE_DDRAW();
  1414. return DDERR_UNSUPPORTED;
  1415. }
  1416. if( lpDesc->dwVideoPortID >= this->ddCaps.dwMaxVideoPorts )
  1417. {
  1418. LEAVE_DDRAW();
  1419. return DDERR_INVALIDPARAMS;
  1420. }
  1421. if( ( lpDesc->VideoPortType.dwReserved1 != 0 ) ||
  1422. ( lpDesc->dwReserved1 != 0 ) ||
  1423. ( lpDesc->dwReserved2 != 0 ) ||
  1424. ( lpDesc->dwReserved3 != 0 ) )
  1425. {
  1426. DPF_ERR( "Reserved field not set to zero" );
  1427. LEAVE_DDRAW();
  1428. return DDERR_INVALIDPARAMS;
  1429. }
  1430. lpAvailCaps = &(this->lpDDVideoPortCaps[lpDesc->dwVideoPortID]);
  1431. if( !VALID_DDVIDEOPORTCAPS_PTR( lpAvailCaps ) )
  1432. {
  1433. LEAVE_DDRAW();
  1434. return DDERR_UNSUPPORTED;
  1435. }
  1436. if( ( dwClientFlags & DDVPCREATE_VBIONLY ) &&
  1437. !IndependantVBIPossible( lpAvailCaps ) )
  1438. {
  1439. DPF_ERR( "DDVPCREATE_VBIONLY is not supported" );
  1440. LEAVE_DDRAW();
  1441. return DDERR_UNSUPPORTED;
  1442. }
  1443. }
  1444. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1445. {
  1446. DPF_ERR( "Exception encountered validating parameters" );
  1447. LEAVE_DDRAW();
  1448. return DDERR_EXCEPTION;
  1449. }
  1450. if( this_lcl->dwProcessId != GetCurrentProcessId() )
  1451. {
  1452. DPF_ERR( "Process does not have access to object" );
  1453. LEAVE_DDRAW();
  1454. return DDERR_INVALIDPARAMS;
  1455. }
  1456. /*
  1457. * Is the requested video port available?
  1458. */
  1459. lpVPInt = this->dvpList;
  1460. lpEven = lpOdd = NULL;
  1461. while( NULL != lpVPInt )
  1462. {
  1463. if( ( lpVPInt->lpLcl->ddvpDesc.dwVideoPortID == lpDesc->dwVideoPortID ) &&
  1464. !( lpVPInt->dwFlags & DDVPCREATE_NOTIFY ) )
  1465. {
  1466. if( lpVPInt->lpLcl->ddvpDesc.VideoPortType.dwFlags &
  1467. DDVPCONNECT_SHAREEVEN )
  1468. {
  1469. lpEven = lpVPInt;
  1470. }
  1471. else if( lpVPInt->lpLcl->ddvpDesc.VideoPortType.dwFlags &
  1472. DDVPCONNECT_SHAREODD )
  1473. {
  1474. lpOdd = lpVPInt;
  1475. }
  1476. else if( !dwClientFlags || !(lpVPInt->dwFlags) ||
  1477. ( dwClientFlags & lpVPInt->dwFlags ) )
  1478. {
  1479. lpEven = lpOdd = lpVPInt;
  1480. }
  1481. else
  1482. {
  1483. /*
  1484. * Video has been opened for VBI/Video only use. Remember
  1485. * the other interface because we will need it shortly.
  1486. */
  1487. lpOtherInt = lpVPInt;
  1488. }
  1489. }
  1490. lpVPInt = lpVPInt->lpLink;
  1491. }
  1492. if( ( NULL != lpEven ) && ( NULL != lpOdd ) )
  1493. {
  1494. DPF_ERR( "video port already in use" );
  1495. LEAVE_DDRAW();
  1496. return DDERR_OUTOFCAPS;
  1497. }
  1498. /*
  1499. * Get the caps of the specified video port
  1500. */
  1501. dwAvailCaps = lpAvailCaps->dwCaps;
  1502. dwConnectFlags = lpDesc->VideoPortType.dwFlags;
  1503. if( NULL != lpEven )
  1504. {
  1505. dwAvailCaps &= ~( DDVPCAPS_NONINTERLACED |
  1506. DDVPCAPS_SKIPEVENFIELDS | DDVPCAPS_SKIPODDFIELDS );
  1507. if( dwConnectFlags & DDVPCONNECT_SHAREEVEN )
  1508. {
  1509. DPF_ERR( "Even field already used" );
  1510. LEAVE_DDRAW();
  1511. return DDERR_INVALIDCAPS;
  1512. }
  1513. }
  1514. else if( NULL != lpOdd )
  1515. {
  1516. dwAvailCaps &= ~( DDVPCAPS_NONINTERLACED |
  1517. DDVPCAPS_SKIPEVENFIELDS | DDVPCAPS_SKIPODDFIELDS );
  1518. if( dwConnectFlags & DDVPCONNECT_SHAREODD )
  1519. {
  1520. DPF_ERR( "Odd field already used" );
  1521. LEAVE_DDRAW();
  1522. return DDERR_INVALIDCAPS;
  1523. }
  1524. }
  1525. else if( dwClientFlags )
  1526. {
  1527. dwAvailCaps &= ~( DDVPCAPS_SKIPEVENFIELDS | DDVPCAPS_SKIPODDFIELDS );
  1528. }
  1529. /*
  1530. * Check for incompatible flags/caps
  1531. */
  1532. if( ( dwConnectFlags & DDVPCONNECT_INTERLACED ) &&
  1533. !( dwAvailCaps & DDVPCAPS_INTERLACED ) )
  1534. {
  1535. DPF_ERR( "DDVPCONNECT_INTERLACED not supported" );
  1536. LEAVE_DDRAW();
  1537. return DDERR_INVALIDCAPS;
  1538. }
  1539. if( !( dwConnectFlags & DDVPCONNECT_INTERLACED ) &&
  1540. !( dwAvailCaps & DDVPCAPS_NONINTERLACED ) )
  1541. {
  1542. DPF_ERR( "Non interlaced is not supported" );
  1543. LEAVE_DDRAW();
  1544. return DDERR_INVALIDCAPS;
  1545. }
  1546. if( ( dwConnectFlags &
  1547. (DDVPCONNECT_SHAREEVEN|DDVPCONNECT_SHAREODD) ) &&
  1548. !( dwAvailCaps & DDVPCAPS_SHAREABLE ) )
  1549. {
  1550. DPF_ERR( "DDVPCONNECT_SHAREEVEN/SHAREODD not supported" );
  1551. LEAVE_DDRAW();
  1552. return DDERR_INVALIDCAPS;
  1553. }
  1554. if( !( dwConnectFlags & DDVPCONNECT_INTERLACED ) )
  1555. {
  1556. if( dwConnectFlags & ( DDVPCONNECT_SHAREEVEN |
  1557. DDVPCONNECT_SHAREODD ) )
  1558. {
  1559. DPF_ERR( "cap invalid with non-interlaced video" );
  1560. LEAVE_DDRAW();
  1561. return DDERR_INVALIDCAPS;
  1562. }
  1563. }
  1564. if( ( dwConnectFlags & DDVPCONNECT_SHAREEVEN ) &&
  1565. ( dwConnectFlags & DDVPCONNECT_SHAREODD ) )
  1566. {
  1567. DPF_ERR( "shareeven and share odd are mutually exclusive" );
  1568. LEAVE_DDRAW();
  1569. return DDERR_INVALIDCAPS;
  1570. }
  1571. if( ( ( NULL != lpEven ) && !( dwConnectFlags & DDVPCONNECT_SHAREODD ) ) ||
  1572. ( ( NULL != lpOdd ) && !( dwConnectFlags & DDVPCONNECT_SHAREEVEN ) ) )
  1573. {
  1574. DPF_ERR( "specifed video port must be shared" );
  1575. LEAVE_DDRAW();
  1576. return DDERR_INVALIDCAPS;
  1577. }
  1578. if( lpAvailCaps->dwMaxWidth < lpDesc->dwFieldWidth )
  1579. {
  1580. DPF_ERR( "specified width is too large" );
  1581. LEAVE_DDRAW();
  1582. return DDERR_INVALIDPARAMS;
  1583. }
  1584. if( lpAvailCaps->dwMaxHeight < lpDesc->dwFieldHeight )
  1585. {
  1586. DPF_ERR( "specified height is too large" );
  1587. LEAVE_DDRAW();
  1588. return DDERR_INVALIDPARAMS;
  1589. }
  1590. if( lpDesc->dwMicrosecondsPerField == 0 )
  1591. {
  1592. DPF_ERR( "Microseconds/field not specified" );
  1593. LEAVE_DDRAW();
  1594. return DDERR_INVALIDPARAMS;
  1595. }
  1596. if( lpDesc->dwMaxPixelsPerSecond == 0 )
  1597. {
  1598. DPF_ERR( "Max pixels per second not specified" );
  1599. LEAVE_DDRAW();
  1600. return DDERR_INVALIDPARAMS;
  1601. }
  1602. if( NULL != lpEven )
  1603. {
  1604. if( !( ( IsEqualIID( &(lpDesc->VideoPortType.guidTypeID),
  1605. &(lpOdd->lpLcl->ddvpDesc.VideoPortType.guidTypeID) ) ) &&
  1606. ( lpDesc->VideoPortType.dwPortWidth ==
  1607. lpOdd->lpLcl->ddvpDesc.VideoPortType.dwPortWidth ) &&
  1608. ( ( lpDesc->VideoPortType.dwFlags & lpOdd->lpLcl->ddvpDesc.VideoPortType.dwFlags )
  1609. == lpDesc->VideoPortType.dwFlags ) ) )
  1610. {
  1611. DPF_ERR( "invalid GUID specified" );
  1612. LEAVE_DDRAW();
  1613. return DDERR_INVALIDPARAMS;
  1614. }
  1615. }
  1616. else if( NULL != lpOdd )
  1617. {
  1618. if( !( ( IsEqualIID( &(lpDesc->VideoPortType.guidTypeID),
  1619. &(lpEven->lpLcl->ddvpDesc.VideoPortType.guidTypeID) ) ) &&
  1620. ( lpDesc->VideoPortType.dwPortWidth ==
  1621. lpEven->lpLcl->ddvpDesc.VideoPortType.dwPortWidth ) &&
  1622. ( ( lpDesc->VideoPortType.dwFlags & lpEven->lpLcl->ddvpDesc.VideoPortType.dwFlags )
  1623. == lpDesc->VideoPortType.dwFlags ) ) )
  1624. {
  1625. DPF_ERR( "invalid GUID specified" );
  1626. LEAVE_DDRAW();
  1627. return DDERR_INVALIDPARAMS;
  1628. }
  1629. }
  1630. else if( NULL != lpOtherInt )
  1631. {
  1632. /*
  1633. * Since they are both sharing the exact same connection, fail
  1634. * unless the connections are identical.
  1635. */
  1636. if( lpDesc->VideoPortType.dwPortWidth !=
  1637. lpOtherInt->lpLcl->ddvpDesc.VideoPortType.dwPortWidth )
  1638. {
  1639. DPF_ERR( "connection info must match other interface" );
  1640. LEAVE_DDRAW();
  1641. return DDERR_INVALIDPARAMS;
  1642. }
  1643. if( lpDesc->VideoPortType.dwFlags !=
  1644. lpOtherInt->lpLcl->ddvpDesc.VideoPortType.dwFlags )
  1645. {
  1646. DPF_ERR( "connection info must match other interface" );
  1647. LEAVE_DDRAW();
  1648. return DDERR_INVALIDPARAMS;
  1649. }
  1650. if( !IsEqualIID( &(lpDesc->VideoPortType.guidTypeID),
  1651. &(lpOtherInt->lpLcl->ddvpDesc.VideoPortType.guidTypeID) ) )
  1652. {
  1653. DPF_ERR( "connection info must match other interface" );
  1654. LEAVE_DDRAW();
  1655. return DDERR_INVALIDPARAMS;
  1656. }
  1657. }
  1658. else
  1659. {
  1660. LPDDVIDEOPORTCONNECT lpConnect;
  1661. DWORD dwNumEntries;
  1662. DWORD i;
  1663. DWORD rc;
  1664. /*
  1665. * Verify that the connection can be supported.
  1666. */
  1667. rc = DDVPC_GetVideoPortConnectInfo( lpDVP,
  1668. lpDesc->dwVideoPortID, &dwNumEntries, NULL );
  1669. if( rc != DD_OK )
  1670. {
  1671. LEAVE_DDRAW();
  1672. return DDERR_INVALIDPARAMS;
  1673. }
  1674. lpConnect = (LPDDVIDEOPORTCONNECT) MemAlloc(
  1675. sizeof( DDVIDEOPORTCONNECT ) * dwNumEntries );
  1676. if( NULL == lpConnect )
  1677. {
  1678. LEAVE_DDRAW();
  1679. return DDERR_OUTOFMEMORY;
  1680. }
  1681. rc = DDVPC_GetVideoPortConnectInfo( lpDVP,
  1682. lpDesc->dwVideoPortID, &dwNumEntries, lpConnect );
  1683. if( rc != DD_OK )
  1684. {
  1685. LEAVE_DDRAW();
  1686. return DDERR_INVALIDPARAMS;
  1687. }
  1688. for (i = 0; i < dwNumEntries; i++)
  1689. {
  1690. if( ( IsEqualIID( &(lpDesc->VideoPortType.guidTypeID),
  1691. &(lpConnect[i].guidTypeID) ) ) &&
  1692. ( lpDesc->VideoPortType.dwPortWidth ==
  1693. lpConnect[i].dwPortWidth ) )
  1694. {
  1695. break;
  1696. }
  1697. }
  1698. MemFree( lpConnect );
  1699. if ( i == dwNumEntries )
  1700. {
  1701. DPF_ERR( "invalid GUID specified" );
  1702. LEAVE_DDRAW();
  1703. return DDERR_INVALIDPARAMS;
  1704. }
  1705. }
  1706. /*
  1707. * Turn merge the description of the multiple interfaces into one.
  1708. */
  1709. MergeVPDescriptions( &ddTempDesc, lpDesc, lpOtherInt );
  1710. /*
  1711. * Things look good so far. Lets call the HAL and see if they
  1712. * can handle it.
  1713. */
  1714. ccvppfn = this_lcl->lpDDCB->HALDDVideoPort.CanCreateVideoPort;
  1715. if( NULL != ccvppfn )
  1716. {
  1717. DDHAL_CANCREATEVPORTDATA CanCreateData;
  1718. CanCreateData.lpDD = this_lcl;
  1719. CanCreateData.lpDDVideoPortDesc = &ddTempDesc;
  1720. DOHALCALL( CanCreateVideoPort, ccvppfn, CanCreateData, rc, 0 );
  1721. if( ( DDHAL_DRIVER_HANDLED == rc ) && (DD_OK != CanCreateData.ddRVal ) )
  1722. {
  1723. LEAVE_DDRAW();
  1724. return CanCreateData.ddRVal;
  1725. }
  1726. }
  1727. /*
  1728. * Allocate the sucker(s)
  1729. */
  1730. new_int = MemAlloc( sizeof( DDRAWI_DDVIDEOPORT_INT ) );
  1731. if( NULL == new_int )
  1732. {
  1733. LEAVE_DDRAW();
  1734. return DDERR_OUTOFMEMORY;
  1735. }
  1736. new_int->lpVtbl = (LPVOID)&ddVideoPortCallbacks;
  1737. new_int->dwFlags = dwClientFlags;
  1738. if( lpOtherInt != NULL )
  1739. {
  1740. new_lcl = lpOtherInt->lpLcl;
  1741. }
  1742. else
  1743. {
  1744. new_lcl = MemAlloc( sizeof( DDRAWI_DDVIDEOPORT_LCL ) +
  1745. ( 2 * sizeof( DDPIXELFORMAT ) ) );
  1746. if( NULL == new_lcl )
  1747. {
  1748. LEAVE_DDRAW();
  1749. return DDERR_OUTOFMEMORY;
  1750. }
  1751. new_lcl->lpDD = this_lcl;
  1752. new_lcl->lpSurface = NULL;
  1753. new_lcl->lpVBISurface = NULL;
  1754. }
  1755. if( dwClientFlags & DDVPCREATE_VBIONLY )
  1756. {
  1757. new_lcl->dwVBIProcessID = GetCurrentProcessId();
  1758. }
  1759. else
  1760. {
  1761. new_lcl->dwProcessID = GetCurrentProcessId();
  1762. }
  1763. new_int->lpLcl = new_lcl;
  1764. memcpy( &(new_lcl->ddvpDesc), &ddTempDesc, sizeof( DDVIDEOPORTDESC ));
  1765. /*
  1766. * If this is a VBI/VIDEOONLY interface, save the original description
  1767. * for future use.
  1768. */
  1769. if( dwClientFlags & DDVPCREATE_VBIONLY )
  1770. {
  1771. new_lcl->lpVBIDesc = MemAlloc( sizeof( DDVIDEOPORTDESC ) );
  1772. if( NULL == new_lcl->lpVBIDesc )
  1773. {
  1774. LEAVE_DDRAW();
  1775. return DDERR_OUTOFMEMORY;
  1776. }
  1777. memcpy( new_lcl->lpVBIDesc, lpDesc, sizeof( DDVIDEOPORTDESC ));
  1778. }
  1779. else if( dwClientFlags & DDVPCREATE_VIDEOONLY )
  1780. {
  1781. new_lcl->lpVideoDesc = MemAlloc( sizeof( DDVIDEOPORTDESC ) );
  1782. if( NULL == new_lcl->lpVideoDesc )
  1783. {
  1784. LEAVE_DDRAW();
  1785. return DDERR_OUTOFMEMORY;
  1786. }
  1787. memcpy( new_lcl->lpVideoDesc, lpDesc, sizeof( DDVIDEOPORTDESC ));
  1788. }
  1789. /*
  1790. * Notify the HAL that we created it
  1791. */
  1792. cvppfn = this_lcl->lpDDCB->HALDDVideoPort.CreateVideoPort;
  1793. if( NULL != cvppfn )
  1794. {
  1795. DDHAL_CREATEVPORTDATA CreateData;
  1796. CreateData.lpDD = this_lcl;
  1797. CreateData.lpDDVideoPortDesc = &ddTempDesc;
  1798. CreateData.lpVideoPort = new_lcl;
  1799. DOHALCALL( CreateVideoPort, cvppfn, CreateData, rc, 0 );
  1800. if( ( DDHAL_DRIVER_HANDLED == rc ) && (DD_OK != CreateData.ddRVal ) )
  1801. {
  1802. LEAVE_DDRAW();
  1803. return CreateData.ddRVal;
  1804. }
  1805. }
  1806. InsertVideoPortInList( this, new_int );
  1807. DD_VP_AddRef( (LPDIRECTDRAWVIDEOPORT )new_int );
  1808. *lplpDDVideoPort = (LPDIRECTDRAWVIDEOPORT) new_int;
  1809. /*
  1810. * Notify kernel mode of we created the video port
  1811. */
  1812. #ifdef WIN95
  1813. if( lpOtherInt == NULL )
  1814. {
  1815. UpdateKernelVideoPort( new_lcl, DDKMVP_CREATE );
  1816. }
  1817. #endif
  1818. LEAVE_DDRAW();
  1819. return DD_OK;
  1820. } /* DDVPC_CreateVideoPort */
  1821. /*
  1822. * DD_VP_AddRef
  1823. */
  1824. DWORD DDAPI DD_VP_AddRef( LPDIRECTDRAWVIDEOPORT lpDVP )
  1825. {
  1826. LPDDRAWI_DDVIDEOPORT_INT this_int;
  1827. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  1828. ENTER_DDRAW();
  1829. DPF(2,A,"ENTERAPI: DD_VP_AddRef");
  1830. /*
  1831. * Don't allow access to this function if called from within the
  1832. * the EnumVideoPort callback.
  1833. */
  1834. if( bInEnumCallback )
  1835. {
  1836. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  1837. LEAVE_DDRAW();
  1838. return 0;
  1839. }
  1840. DPF( 5, "DD_VP_AddRef, pid=%08lx, obj=%08lx", GETCURRPID(), lpDVP );
  1841. TRY
  1842. {
  1843. this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
  1844. if( !VALID_DDVIDEOPORT_PTR( this_int ) )
  1845. {
  1846. LEAVE_DDRAW();
  1847. return 0;
  1848. }
  1849. this_lcl = this_int->lpLcl;
  1850. }
  1851. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1852. {
  1853. DPF_ERR( "Exception encountered validating parameters" );
  1854. LEAVE_DDRAW();
  1855. return 0;
  1856. }
  1857. /*
  1858. * bump refcnt
  1859. */
  1860. this_lcl->dwRefCnt++;
  1861. this_int->dwIntRefCnt++;
  1862. LEAVE_DDRAW();
  1863. return this_int->dwIntRefCnt;
  1864. } /* DD_VP_AddRef */
  1865. /*
  1866. * DD_VP_QueryInterface
  1867. */
  1868. HRESULT DDAPI DD_VP_QueryInterface(LPDIRECTDRAWVIDEOPORT lpDVP, REFIID riid, LPVOID FAR * ppvObj )
  1869. {
  1870. LPDDRAWI_DDVIDEOPORT_INT this_int;
  1871. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  1872. ENTER_DDRAW();
  1873. DPF(2,A,"ENTERAPI: DD_VP_QueryInterface");
  1874. /*
  1875. * Don't allow access to this function if called from within the
  1876. * the EnumVideoPort callback.
  1877. */
  1878. if( bInEnumCallback )
  1879. {
  1880. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  1881. LEAVE_DDRAW();
  1882. return DDERR_CURRENTLYNOTAVAIL;
  1883. }
  1884. /*
  1885. * validate parms
  1886. */
  1887. TRY
  1888. {
  1889. this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
  1890. if( !VALID_DDVIDEOPORT_PTR( this_int ) )
  1891. {
  1892. DPF_ERR( "Invalid videoport pointer" );
  1893. LEAVE_DDRAW();
  1894. return DDERR_INVALIDOBJECT;
  1895. }
  1896. this_lcl = this_int->lpLcl;
  1897. if( !VALID_PTR_PTR( ppvObj ) )
  1898. {
  1899. DPF_ERR( "Invalid videoport interface pointer" );
  1900. LEAVE_DDRAW();
  1901. return DDERR_INVALIDPARAMS;
  1902. }
  1903. *ppvObj = NULL;
  1904. if( !VALIDEX_IID_PTR( riid ) )
  1905. {
  1906. DPF_ERR( "Invalid IID pointer" );
  1907. LEAVE_DDRAW();
  1908. return DDERR_INVALIDPARAMS;
  1909. }
  1910. }
  1911. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1912. {
  1913. DPF_ERR( "Exception encountered validating parameters" );
  1914. LEAVE_DDRAW();
  1915. return DDERR_INVALIDPARAMS;
  1916. }
  1917. /*
  1918. * asking for IUnknown?
  1919. */
  1920. if( IsEqualIID(riid, &IID_IUnknown) ||
  1921. IsEqualIID(riid, &IID_IDirectDrawVideoPort) )
  1922. {
  1923. /*
  1924. * Our IUnknown interface is the same as our V1
  1925. * interface. We must always return the V1 interface
  1926. * if IUnknown is requested.
  1927. */
  1928. *ppvObj = (LPVOID) this_int;
  1929. DD_VP_AddRef( *ppvObj );
  1930. LEAVE_DDRAW();
  1931. return DD_OK;
  1932. }
  1933. else if( IsEqualIID(riid, &IID_IDirectDrawVideoPortNotify) )
  1934. {
  1935. HRESULT ret;
  1936. ret = CreateVideoPortNotify (this_int, (LPDIRECTDRAWVIDEOPORTNOTIFY*)ppvObj);
  1937. LEAVE_DDRAW();
  1938. return ret;
  1939. }
  1940. DPF_ERR( "IID not understood by DirectDraw" );
  1941. LEAVE_DDRAW();
  1942. return E_NOINTERFACE;
  1943. } /* DD_VP_QueryInterface */
  1944. /*
  1945. * DD_VP_Release
  1946. */
  1947. DWORD DDAPI DD_VP_Release(LPDIRECTDRAWVIDEOPORT lpDVP )
  1948. {
  1949. LPDDRAWI_DDVIDEOPORT_INT this_int;
  1950. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  1951. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  1952. LPDDHALVPORTCB_DESTROYVPORT pfn;
  1953. DWORD dwIntRefCnt;
  1954. DWORD rc;
  1955. ENTER_DDRAW();
  1956. DPF(2,A,"ENTERAPI: DD_VP_Release");
  1957. /*
  1958. * Don't allow access to this function if called from within the
  1959. * the EnumVideoPort callback.
  1960. */
  1961. if( bInEnumCallback )
  1962. {
  1963. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  1964. LEAVE_DDRAW();
  1965. return 0;
  1966. }
  1967. TRY
  1968. {
  1969. this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
  1970. if( !VALID_DDVIDEOPORT_PTR( this_int ) )
  1971. {
  1972. DPF_ERR( "Invalid videoport pointer" );
  1973. LEAVE_DDRAW();
  1974. return 0;
  1975. }
  1976. this_lcl = this_int->lpLcl;
  1977. pdrv = this_lcl->lpDD->lpGbl;
  1978. }
  1979. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1980. {
  1981. DPF_ERR( "Exception encountered validating parameters" );
  1982. LEAVE_DDRAW();
  1983. return 0;
  1984. }
  1985. /*
  1986. * decrement the reference count. if it hits zero, free the surface
  1987. */
  1988. this_lcl->dwRefCnt--;
  1989. this_int->dwIntRefCnt--;
  1990. DPF( 5, "DD_VP_Release, Reference Count: Local = %ld Int = %ld",
  1991. this_lcl->dwRefCnt, this_int->dwIntRefCnt );
  1992. /*
  1993. * interface at zero?
  1994. */
  1995. dwIntRefCnt = this_int->dwIntRefCnt;
  1996. if( dwIntRefCnt == 0 )
  1997. {
  1998. LPDDRAWI_DDVIDEOPORT_INT curr_int;
  1999. LPDDRAWI_DDVIDEOPORT_INT last_int;
  2000. /*
  2001. * remove videoport from list
  2002. */
  2003. curr_int = pdrv->dvpList;
  2004. last_int = NULL;
  2005. while( curr_int != this_int )
  2006. {
  2007. last_int = curr_int;
  2008. curr_int = curr_int->lpLink;
  2009. if( curr_int == NULL )
  2010. {
  2011. DPF_ERR( "VideoPort not in list!" );
  2012. LEAVE_DDRAW();
  2013. return 0;
  2014. }
  2015. }
  2016. if( last_int == NULL )
  2017. {
  2018. pdrv->dvpList = pdrv->dvpList->lpLink;
  2019. }
  2020. else
  2021. {
  2022. last_int->lpLink = curr_int->lpLink;
  2023. }
  2024. /*
  2025. * Decrement the surface reference counts and clean things up
  2026. */
  2027. if( !( this_int->dwFlags & DDVPCREATE_NOTIFY ) )
  2028. {
  2029. DD_VP_StopVideo( (LPDIRECTDRAWVIDEOPORT) this_int );
  2030. this_lcl->dwFlags &= ~DDRAWIVPORT_ON;
  2031. if( this_int->dwFlags & DDVPCREATE_VBIONLY )
  2032. {
  2033. if( this_lcl->lpVBISurface != NULL )
  2034. {
  2035. DecrementRefCounts( this_lcl->lpVBISurface );
  2036. this_lcl->lpVBISurface = NULL;
  2037. }
  2038. if( this_lcl->lpVBIDesc != NULL )
  2039. {
  2040. MemFree( this_lcl->lpVBIDesc );
  2041. this_lcl->lpVBIDesc = NULL;
  2042. }
  2043. if( this_lcl->lpVBIInfo != NULL )
  2044. {
  2045. MemFree( this_lcl->lpVBIInfo );
  2046. this_lcl->lpVBIInfo = NULL;
  2047. }
  2048. this_lcl->dwVBIProcessID = 0;
  2049. }
  2050. else if( this_int->dwFlags & DDVPCREATE_VIDEOONLY )
  2051. {
  2052. if( this_lcl->lpSurface != NULL )
  2053. {
  2054. DecrementRefCounts( this_lcl->lpSurface );
  2055. this_lcl->lpSurface = NULL;
  2056. }
  2057. if( this_lcl->lpVideoDesc != NULL )
  2058. {
  2059. MemFree( this_lcl->lpVideoDesc );
  2060. this_lcl->lpVideoDesc = NULL;
  2061. }
  2062. if( this_lcl->lpVideoInfo != NULL )
  2063. {
  2064. MemFree( this_lcl->lpVideoInfo );
  2065. this_lcl->lpVideoInfo = NULL;
  2066. }
  2067. this_lcl->dwProcessID = 0;
  2068. }
  2069. else
  2070. {
  2071. if( this_lcl->lpSurface != NULL )
  2072. {
  2073. DecrementRefCounts( this_lcl->lpSurface );
  2074. }
  2075. if( this_lcl->lpVBISurface != NULL )
  2076. {
  2077. DecrementRefCounts( this_lcl->lpVBISurface );
  2078. }
  2079. this_lcl->dwProcessID = 0;
  2080. }
  2081. }
  2082. else
  2083. {
  2084. this_lcl->lpVPNotify = NULL;
  2085. }
  2086. /*
  2087. * just in case someone comes back in with this pointer, set
  2088. * an invalid vtbl & data ptr.
  2089. */
  2090. this_int->lpVtbl = NULL;
  2091. this_int->lpLcl = NULL;
  2092. MemFree( this_int );
  2093. }
  2094. /*
  2095. * local object at zero?
  2096. */
  2097. if( this_lcl->dwRefCnt == 0 )
  2098. {
  2099. /*
  2100. * turn off the videoport hardware
  2101. */
  2102. if( this_lcl->dwFlags & DDRAWIVPORT_ON )
  2103. {
  2104. DD_VP_StopVideo( lpDVP );
  2105. }
  2106. #ifdef WIN95
  2107. UpdateKernelVideoPort( this_lcl, DDKMVP_RELEASE );
  2108. #endif
  2109. /*
  2110. * Notify the HAL
  2111. */
  2112. pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.DestroyVideoPort;
  2113. if( NULL != pfn )
  2114. {
  2115. DDHAL_DESTROYVPORTDATA DestroyVportData;
  2116. DestroyVportData.lpDD = this_lcl->lpDD;
  2117. DestroyVportData.lpVideoPort = this_lcl;
  2118. DOHALCALL( DestroyVideoPort, pfn, DestroyVportData, rc, 0 );
  2119. if( ( DDHAL_DRIVER_HANDLED == rc ) && ( DD_OK != DestroyVportData.ddRVal ) )
  2120. {
  2121. LEAVE_DDRAW();
  2122. return DestroyVportData.ddRVal;
  2123. }
  2124. }
  2125. MemFree( this_lcl->lpFlipInts );
  2126. MemFree( this_lcl );
  2127. }
  2128. LEAVE_DDRAW();
  2129. return dwIntRefCnt;
  2130. }
  2131. /*
  2132. * DD_VP_SetTargetSurface
  2133. */
  2134. HRESULT DDAPI DD_VP_SetTargetSurface(LPDIRECTDRAWVIDEOPORT lpDVP, LPDIRECTDRAWSURFACE lpSurface, DWORD dwFlags )
  2135. {
  2136. LPDDRAWI_DDRAWSURFACE_INT surf_first;
  2137. LPDDRAWI_DDVIDEOPORT_INT this_int;
  2138. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  2139. LPDDRAWI_DDRAWSURFACE_INT surf_int;
  2140. LPDDRAWI_DDRAWSURFACE_LCL surf_lcl;
  2141. LPDDRAWI_DDRAWSURFACE_INT lpTemp;
  2142. LPDDRAWI_DDRAWSURFACE_INT lpPrevious;
  2143. BOOL bWasOn;
  2144. DWORD ddRVal;
  2145. ENTER_DDRAW();
  2146. DPF(2,A,"ENTERAPI: DD_VP_SetTargetSurface");
  2147. /*
  2148. * Don't allow access to this function if called from within the
  2149. * the EnumVideoPort callback.
  2150. */
  2151. if( bInEnumCallback )
  2152. {
  2153. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  2154. LEAVE_DDRAW();
  2155. return DDERR_CURRENTLYNOTAVAIL;
  2156. }
  2157. /*
  2158. * Validate parameters
  2159. */
  2160. TRY
  2161. {
  2162. this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
  2163. if( !VALID_DDVIDEOPORT_PTR( this_int ) )
  2164. {
  2165. LEAVE_DDRAW();
  2166. return DDERR_INVALIDOBJECT;
  2167. }
  2168. this_lcl = this_int->lpLcl;
  2169. surf_int = (LPDDRAWI_DDRAWSURFACE_INT) lpSurface;
  2170. if( ( NULL == lpSurface ) || !VALID_DIRECTDRAWSURFACE_PTR( surf_int ) )
  2171. {
  2172. LEAVE_DDRAW();
  2173. return DDERR_INVALIDOBJECT;
  2174. }
  2175. surf_lcl = surf_int->lpLcl;
  2176. /*
  2177. * Make sure the surface and video port belong to the same device.
  2178. */
  2179. if (surf_lcl->lpSurfMore->lpDD_lcl->lpGbl != this_lcl->lpDD->lpGbl)
  2180. {
  2181. DPF_ERR("Video port and Surface must belong to the same device");
  2182. LEAVE_DDRAW();
  2183. return DDERR_DEVICEDOESNTOWNSURFACE;
  2184. }
  2185. if( this_int->dwFlags & DDVPCREATE_VBIONLY )
  2186. {
  2187. if( dwFlags & DDVPTARGET_VIDEO )
  2188. {
  2189. DPF_ERR( "DDVPTARGET_VIDEO specified on a VBI-only video port" );
  2190. LEAVE_DDRAW();
  2191. return DDERR_INVALIDPARAMS;
  2192. }
  2193. dwFlags |= DDVPTARGET_VBI;
  2194. }
  2195. else if( this_int->dwFlags & DDVPCREATE_VIDEOONLY )
  2196. {
  2197. if( dwFlags & DDVPTARGET_VBI )
  2198. {
  2199. DPF_ERR( "DDVPTARGET_VBI specified on a video-only video port" );
  2200. LEAVE_DDRAW();
  2201. return DDERR_INVALIDPARAMS;
  2202. }
  2203. dwFlags |= DDVPTARGET_VIDEO;
  2204. }
  2205. }
  2206. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2207. {
  2208. DPF_ERR( "Exception encountered validating parameters" );
  2209. LEAVE_DDRAW();
  2210. return DDERR_EXCEPTION;
  2211. }
  2212. /*
  2213. * Surface must have the video port flag set
  2214. */
  2215. if( !( surf_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOPORT ) )
  2216. {
  2217. DPF_ERR( "Specified surface doesnt have DDSCAPS_VIDEOPORT set" );
  2218. LEAVE_DDRAW();
  2219. return DDERR_INVALIDPARAMS;
  2220. }
  2221. /*
  2222. * Can surface live in system memory?
  2223. */
  2224. if( surf_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
  2225. {
  2226. if( !( this_lcl->lpDD->lpGbl->lpDDVideoPortCaps[this_lcl->ddvpDesc.dwVideoPortID].dwCaps &
  2227. DDVPCAPS_SYSTEMMEMORY ) )
  2228. {
  2229. DPF_ERR( "Video port surface must live in video memory" );
  2230. LEAVE_DDRAW();
  2231. return DDERR_INVALIDPARAMS;
  2232. }
  2233. if( surf_lcl->lpSurfMore->dwPageLockCount == 0 )
  2234. {
  2235. DPF_ERR( "Surface must be page locked" );
  2236. LEAVE_DDRAW();
  2237. return DDERR_INVALIDPARAMS;
  2238. }
  2239. }
  2240. /*
  2241. * If another surface in the chain is attached to a different video
  2242. * port, fail now.
  2243. */
  2244. surf_first = surf_int;
  2245. do
  2246. {
  2247. if( ( surf_int->lpLcl->lpSurfMore->lpVideoPort != NULL ) &&
  2248. ( surf_int->lpLcl->lpSurfMore->lpVideoPort != this_lcl ) )
  2249. {
  2250. LEAVE_DDRAW();
  2251. return DDERR_INVALIDPARAMS;
  2252. }
  2253. surf_int = FindAttachedFlip( surf_int );
  2254. } while( ( surf_int != NULL ) && ( surf_int->lpLcl != surf_first->lpLcl ) );
  2255. surf_int = surf_first;
  2256. /*
  2257. * If the video was on, we need to temporarily turn it off. Otherwise,
  2258. * we could lose our kernel surfaces while they are still in use.
  2259. */
  2260. bWasOn = FALSE;
  2261. if( this_int->dwFlags & DDVPCREATE_VBIONLY )
  2262. {
  2263. if( this_lcl->lpVBIInfo != NULL )
  2264. {
  2265. bWasOn = TRUE;
  2266. }
  2267. }
  2268. else if( this_int->dwFlags & DDVPCREATE_VIDEOONLY )
  2269. {
  2270. if( this_lcl->lpVideoInfo != NULL )
  2271. {
  2272. bWasOn = TRUE;
  2273. }
  2274. }
  2275. else if( this_lcl->dwFlags & DDRAWIVPORT_ON )
  2276. {
  2277. bWasOn = TRUE;
  2278. }
  2279. if( bWasOn )
  2280. {
  2281. DD_VP_StopVideo( lpDVP );
  2282. }
  2283. if( dwFlags & DDVPTARGET_VIDEO )
  2284. {
  2285. /*
  2286. * Set the new surface
  2287. */
  2288. lpPrevious = this_lcl->lpSurface;
  2289. lpTemp = (LPDDRAWI_DDRAWSURFACE_INT) this_lcl->lpSurface;
  2290. this_lcl->lpSurface = surf_int;
  2291. IncrementRefCounts( surf_int );
  2292. }
  2293. else if( dwFlags & DDVPTARGET_VBI )
  2294. {
  2295. if( this_lcl->lpDD->lpGbl->lpDDVideoPortCaps[this_lcl->ddvpDesc.dwVideoPortID].dwCaps & DDVPCAPS_VBISURFACE )
  2296. {
  2297. /*
  2298. * Set the new surface
  2299. */
  2300. lpPrevious = this_lcl->lpVBISurface;
  2301. lpTemp = (LPDDRAWI_DDRAWSURFACE_INT) this_lcl->lpVBISurface;
  2302. this_lcl->lpVBISurface = surf_int;
  2303. IncrementRefCounts( surf_int );
  2304. }
  2305. else
  2306. {
  2307. DPF_ERR( "device does not support attaching VBI surfaces" );
  2308. LEAVE_DDRAW();
  2309. return DDERR_INVALIDCAPS;
  2310. }
  2311. }
  2312. else
  2313. {
  2314. LEAVE_DDRAW();
  2315. return DDERR_INVALIDPARAMS;
  2316. }
  2317. /*
  2318. * If the video port is already on, we should tell the hardware
  2319. * to make this change.
  2320. */
  2321. if( bWasOn )
  2322. {
  2323. if( this_int->dwFlags & DDVPCREATE_VBIONLY )
  2324. {
  2325. ddRVal = DD_VP_StartVideo( lpDVP, this_lcl->lpVBIInfo );
  2326. }
  2327. else if( this_int->dwFlags & DDVPCREATE_VIDEOONLY )
  2328. {
  2329. ddRVal = DD_VP_StartVideo( lpDVP, this_lcl->lpVideoInfo );
  2330. }
  2331. else
  2332. {
  2333. ddRVal = DD_VP_StartVideo( lpDVP, &(this_lcl->ddvpInfo) );
  2334. }
  2335. if( ddRVal != DD_OK )
  2336. {
  2337. // Restore the old surface
  2338. DD_VP_SetTargetSurface( lpDVP,
  2339. (LPDIRECTDRAWSURFACE) lpTemp, dwFlags );
  2340. if( lpTemp != NULL )
  2341. {
  2342. DecrementRefCounts( lpTemp );
  2343. }
  2344. LEAVE_DDRAW();
  2345. return ddRVal;
  2346. }
  2347. }
  2348. /*
  2349. * Decrement the ref counts of the previously attached surfaces. We
  2350. * wait until now so we don't inadvertantly blast data to a surface that
  2351. * has just been released.
  2352. */
  2353. if( lpPrevious != NULL )
  2354. {
  2355. DecrementRefCounts( lpPrevious );
  2356. }
  2357. LEAVE_DDRAW();
  2358. return DD_OK;
  2359. }
  2360. /*
  2361. * DD_VP_Flip
  2362. */
  2363. HRESULT DDAPI DD_VP_Flip(LPDIRECTDRAWVIDEOPORT lpDVP, LPDIRECTDRAWSURFACE lpSurface, DWORD dwFlags )
  2364. {
  2365. LPDDRAWI_DDRAWSURFACE_LCL surf_lcl;
  2366. LPDDRAWI_DDRAWSURFACE_INT surf_int;
  2367. LPDDRAWI_DDRAWSURFACE_GBL surf;
  2368. LPDDRAWI_DDRAWSURFACE_INT surf_dest_int;
  2369. LPDDRAWI_DDRAWSURFACE_LCL surf_dest_lcl;
  2370. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  2371. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  2372. LPDDRAWI_DDVIDEOPORT_INT this_int;
  2373. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  2374. LPDDRAWI_DDRAWSURFACE_INT next_save_int;
  2375. LPDDRAWI_DDRAWSURFACE_INT next_int;
  2376. BOOL found_dest;
  2377. DWORD rc;
  2378. ENTER_DDRAW();
  2379. DPF(2,A,"ENTERAPI: DD_VP_Flip");
  2380. /*
  2381. * Don't allow access to this function if called from within the
  2382. * the EnumVideoPort callback.
  2383. */
  2384. if( bInEnumCallback )
  2385. {
  2386. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  2387. LEAVE_DDRAW();
  2388. return DDERR_CURRENTLYNOTAVAIL;
  2389. }
  2390. TRY
  2391. {
  2392. this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
  2393. if( !VALID_DDVIDEOPORT_PTR( this_int ) )
  2394. {
  2395. LEAVE_DDRAW();
  2396. return DDERR_INVALIDOBJECT;
  2397. }
  2398. this_lcl = this_int->lpLcl;
  2399. if( this_lcl->ddvpInfo.dwVPFlags & DDVP_AUTOFLIP )
  2400. {
  2401. DPF_ERR( "cannot manually flip while autoflipping is enabled" );
  2402. LEAVE_DDRAW();
  2403. return DDERR_NOTFLIPPABLE;
  2404. }
  2405. surf_dest_int = (LPDDRAWI_DDRAWSURFACE_INT) lpSurface;
  2406. if( NULL != surf_dest_int )
  2407. {
  2408. if( !VALID_DIRECTDRAWSURFACE_PTR( surf_dest_int ) )
  2409. {
  2410. LEAVE_DDRAW();
  2411. return DDERR_INVALIDOBJECT;
  2412. }
  2413. surf_dest_lcl = surf_dest_int->lpLcl;
  2414. if( SURFACE_LOST( surf_dest_lcl ) )
  2415. {
  2416. LEAVE_DDRAW();
  2417. return DDERR_SURFACELOST;
  2418. }
  2419. }
  2420. else
  2421. {
  2422. surf_dest_lcl = NULL;
  2423. }
  2424. if( dwFlags & DDVPFLIP_VBI )
  2425. {
  2426. surf_int = this_lcl->lpVBISurface;
  2427. }
  2428. else
  2429. {
  2430. surf_int = this_lcl->lpSurface;
  2431. }
  2432. if( surf_int == NULL )
  2433. {
  2434. DPF_ERR( "SetTargetSurface not yet called" );
  2435. LEAVE_DDRAW();
  2436. return DDERR_INVALIDPARAMS;
  2437. }
  2438. surf_lcl = surf_int->lpLcl;
  2439. if( NULL == surf_lcl )
  2440. {
  2441. LEAVE_DDRAW();
  2442. return DDERR_SURFACENOTATTACHED;
  2443. }
  2444. else if( SURFACE_LOST( surf_lcl ) )
  2445. {
  2446. LEAVE_DDRAW();
  2447. return DDERR_SURFACELOST;
  2448. }
  2449. surf = surf_lcl->lpGbl;
  2450. /*
  2451. * device busy?
  2452. */
  2453. pdrv_lcl = surf_lcl->lpSurfMore->lpDD_lcl;
  2454. pdrv = pdrv_lcl->lpGbl;
  2455. #ifdef USE_ALIAS
  2456. if( pdrv->dwBusyDueToAliasedLock > 0 )
  2457. {
  2458. /*
  2459. * Aliased locks (the ones that don't take the Win16 lock) don't
  2460. * set the busy bit either (it can't or USER get's very confused).
  2461. * However, we must prevent blits happening via DirectDraw as
  2462. * otherwise we get into the old host talking to VRAM while
  2463. * blitter does at the same time. Bad. So fail if there is an
  2464. * outstanding aliased lock just as if the BUST bit had been
  2465. * set.
  2466. */
  2467. DPF_ERR( "Graphics adapter is busy (due to a DirectDraw lock)" );
  2468. LEAVE_DDRAW();
  2469. return DDERR_SURFACEBUSY;
  2470. }
  2471. #endif /* USE_ALIAS */
  2472. if( *(pdrv->lpwPDeviceFlags) & BUSY )
  2473. {
  2474. DPF( 0, "BUSY - Flip" );
  2475. LEAVE_DDRAW()
  2476. return DDERR_SURFACEBUSY;
  2477. }
  2478. /*
  2479. * make sure that it's OK to flip this surface
  2480. */
  2481. if( !(surf_lcl->ddsCaps.dwCaps & DDSCAPS_FLIP) )
  2482. {
  2483. LEAVE_DDRAW();
  2484. return DDERR_NOTFLIPPABLE;
  2485. }
  2486. if( surf->dwUsageCount > 0 )
  2487. {
  2488. DPF_ERR( "Can't flip because surface is locked" );
  2489. LEAVE_DDRAW();
  2490. return DDERR_SURFACEBUSY;
  2491. }
  2492. }
  2493. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2494. {
  2495. DPF_ERR( "Exception encountered validating parameters" );
  2496. LEAVE_DDRAW();
  2497. return DDERR_INVALIDPARAMS;
  2498. }
  2499. /*
  2500. * make sure no surfaces are in use
  2501. */
  2502. found_dest = FALSE;
  2503. next_save_int = next_int = FindAttachedFlip( surf_int );
  2504. if( next_int == NULL )
  2505. {
  2506. LEAVE_DDRAW();
  2507. return DDERR_NOTFLIPPABLE; // ACKACK: real error?
  2508. }
  2509. do
  2510. {
  2511. if( SURFACE_LOST( next_int->lpLcl ) )
  2512. {
  2513. DPF_ERR( "Can't flip - back buffer is lost" );
  2514. LEAVE_DDRAW();
  2515. return DDERR_SURFACELOST;
  2516. }
  2517. if( next_int->lpLcl->lpGbl->dwUsageCount != 0 )
  2518. {
  2519. LEAVE_DDRAW();
  2520. return DDERR_SURFACEBUSY;
  2521. }
  2522. if( surf_dest_int->lpLcl == next_int->lpLcl )
  2523. {
  2524. found_dest = TRUE;
  2525. }
  2526. next_int = FindAttachedFlip( next_int );
  2527. } while( next_int->lpLcl != surf_lcl );
  2528. /*
  2529. * see if we can use the specified destination
  2530. */
  2531. if( surf_dest_int != NULL )
  2532. {
  2533. if( !found_dest )
  2534. {
  2535. DPF_ERR( "Destination not part of flipping chain!" );
  2536. LEAVE_DDRAW();
  2537. return DDERR_NOTFLIPPABLE; // ACKACK: real error?
  2538. }
  2539. next_save_int = surf_dest_int;
  2540. }
  2541. /*
  2542. * found the linked surface we want to flip to
  2543. */
  2544. next_int = next_save_int;
  2545. rc = InternalVideoPortFlip( this_lcl, next_int, 1 );
  2546. LEAVE_DDRAW();
  2547. return (HRESULT)rc;
  2548. }
  2549. /*
  2550. * InternalGetBandwidth
  2551. */
  2552. HRESULT InternalGetBandwidth( LPDDRAWI_DDVIDEOPORT_LCL this_lcl,
  2553. LPDDPIXELFORMAT lpf, DWORD dwWidth, DWORD dwHeight, DWORD dwFlags,
  2554. LPDDVIDEOPORTBANDWIDTH lpBandwidth )
  2555. {
  2556. LPDDHALVPORTCB_GETBANDWIDTH pfn;
  2557. DDHAL_GETVPORTBANDWIDTHDATA GetBandwidthData;
  2558. DWORD rc;
  2559. lpBandwidth->dwCaps = 0;
  2560. lpBandwidth->dwOverlay = (DWORD) -1;
  2561. lpBandwidth->dwColorkey = (DWORD) -1;
  2562. lpBandwidth->dwYInterpolate = (DWORD) -1;
  2563. lpBandwidth->dwYInterpAndColorkey = (DWORD) -1;
  2564. pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.GetVideoPortBandwidth;
  2565. if( pfn != NULL )
  2566. {
  2567. /*
  2568. * Call the HAL
  2569. */
  2570. GetBandwidthData.lpDD = this_lcl->lpDD;
  2571. GetBandwidthData.lpVideoPort = this_lcl;
  2572. GetBandwidthData.lpddpfFormat = lpf;
  2573. GetBandwidthData.dwWidth = dwWidth;
  2574. GetBandwidthData.dwHeight = dwHeight;
  2575. GetBandwidthData.lpBandwidth = lpBandwidth;
  2576. GetBandwidthData.dwFlags = dwFlags;
  2577. DOHALCALL( GetVideoPortBandwidthInfo, pfn, GetBandwidthData, rc, 0 );
  2578. if( DDHAL_DRIVER_HANDLED != rc )
  2579. {
  2580. return DDERR_UNSUPPORTED;
  2581. }
  2582. else if( DD_OK != GetBandwidthData.ddRVal )
  2583. {
  2584. return GetBandwidthData.ddRVal;
  2585. }
  2586. lpBandwidth->dwReserved1 = 0;
  2587. lpBandwidth->dwReserved2 = 0;
  2588. }
  2589. else
  2590. {
  2591. return DDERR_UNSUPPORTED;
  2592. }
  2593. return DD_OK;
  2594. }
  2595. /*
  2596. * DD_VP_GetBandwidth
  2597. */
  2598. HRESULT DDAPI DD_VP_GetBandwidth(LPDIRECTDRAWVIDEOPORT lpDVP,
  2599. LPDDPIXELFORMAT lpf, DWORD dwWidth, DWORD dwHeight, DWORD dwFlags,
  2600. LPDDVIDEOPORTBANDWIDTH lpBandwidth )
  2601. {
  2602. LPDDRAWI_DDVIDEOPORT_INT this_int;
  2603. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  2604. DWORD rc;
  2605. ENTER_DDRAW();
  2606. DPF(2,A,"ENTERAPI: DD_VP_Getbandwidth");
  2607. /*
  2608. * Don't allow access to this function if called from within the
  2609. * the EnumVideoPort callback.
  2610. */
  2611. if( bInEnumCallback )
  2612. {
  2613. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  2614. LEAVE_DDRAW();
  2615. return DDERR_CURRENTLYNOTAVAIL;
  2616. }
  2617. /*
  2618. * Validate parameters
  2619. */
  2620. TRY
  2621. {
  2622. this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
  2623. if( !VALID_DDVIDEOPORT_PTR( this_int ) )
  2624. {
  2625. LEAVE_DDRAW();
  2626. return DDERR_INVALIDOBJECT;
  2627. }
  2628. this_lcl = this_int->lpLcl;
  2629. if( (lpf == NULL) || !VALID_DDPIXELFORMAT_PTR( lpf ) )
  2630. {
  2631. DPF_ERR( "Invalid LPDDPIXELFORMAT specified" );
  2632. LEAVE_DDRAW();
  2633. return DDERR_INVALIDPARAMS;
  2634. }
  2635. if( (lpBandwidth == NULL) || !VALID_DDVIDEOPORTBANDWIDTH_PTR( lpBandwidth ) )
  2636. {
  2637. DPF_ERR( "Invalid LPDDVIDEOPORTBANDWIDTH specified" );
  2638. LEAVE_DDRAW();
  2639. return DDERR_INVALIDPARAMS;
  2640. }
  2641. if( ( ( dwHeight == 0 ) || ( dwWidth == 0 ) ) &&
  2642. !( dwFlags & DDVPB_TYPE ) )
  2643. {
  2644. DPF_ERR( "Width and Height must be specified" );
  2645. LEAVE_DDRAW();
  2646. return DDERR_INVALIDPARAMS;
  2647. }
  2648. if( ( dwFlags & DDVPB_VIDEOPORT ) && ( dwFlags & DDVPB_OVERLAY ) )
  2649. {
  2650. DPF_ERR( "Mutually exclusive flags specified" );
  2651. LEAVE_DDRAW();
  2652. return DDERR_INVALIDPARAMS;
  2653. }
  2654. if( dwFlags & DDVPB_VIDEOPORT )
  2655. {
  2656. if( !( this_lcl->lpDD->lpGbl->lpDDVideoPortCaps[this_lcl->ddvpDesc.dwVideoPortID].dwFX &
  2657. ( DDVPFX_PRESTRETCHX | DDVPFX_PRESTRETCHY |
  2658. DDVPFX_PRESTRETCHXN | DDVPFX_PRESTRETCHYN ) ) )
  2659. {
  2660. if( ( dwWidth > this_lcl->ddvpDesc.dwFieldWidth ) ||
  2661. ( dwHeight > this_lcl->ddvpDesc.dwFieldHeight ) )
  2662. {
  2663. DPF_ERR( "Invalid Width/Height specified" );
  2664. LEAVE_DDRAW();
  2665. return DDERR_INVALIDPARAMS;
  2666. }
  2667. }
  2668. }
  2669. }
  2670. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2671. {
  2672. DPF_ERR( "Exception encountered validating parameters" );
  2673. LEAVE_DDRAW();
  2674. return DDERR_EXCEPTION;
  2675. }
  2676. rc = InternalGetBandwidth( this_lcl, lpf, dwWidth, dwHeight,
  2677. dwFlags, lpBandwidth );
  2678. LEAVE_DDRAW();
  2679. return rc;
  2680. }
  2681. /*
  2682. * DD_VP_GetInputFormats
  2683. */
  2684. HRESULT DDAPI DD_VP_GetInputFormats(LPDIRECTDRAWVIDEOPORT lpDVP, LPDWORD lpdwNum, LPDDPIXELFORMAT lpf, DWORD dwFlags )
  2685. {
  2686. LPDDHALVPORTCB_GETINPUTFORMATS pfn;
  2687. LPDDRAWI_DDVIDEOPORT_INT this_int;
  2688. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  2689. LPDDPIXELFORMAT lpTemp = NULL;
  2690. DDHAL_GETVPORTINPUTFORMATDATA GetFormatData;
  2691. DWORD rc;
  2692. ENTER_DDRAW();
  2693. DPF(2,A,"ENTERAPI: DD_VP_GetInputFormats");
  2694. /*
  2695. * Don't allow access to this function if called from within the
  2696. * the EnumVideoPort callback.
  2697. */
  2698. if( bInEnumCallback )
  2699. {
  2700. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  2701. LEAVE_DDRAW();
  2702. return DDERR_CURRENTLYNOTAVAIL;
  2703. }
  2704. /*
  2705. * Validate parameters
  2706. */
  2707. TRY
  2708. {
  2709. this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
  2710. if( !VALID_DDVIDEOPORT_PTR( this_int ) )
  2711. {
  2712. LEAVE_DDRAW();
  2713. return DDERR_INVALIDOBJECT;
  2714. }
  2715. this_lcl = this_int->lpLcl;
  2716. if( (lpdwNum == NULL) || !VALID_BYTE_ARRAY( lpdwNum, sizeof( LPVOID ) ) )
  2717. {
  2718. LEAVE_DDRAW();
  2719. return DDERR_INVALIDPARAMS;
  2720. }
  2721. if( NULL != lpf )
  2722. {
  2723. if( 0 == *lpdwNum )
  2724. {
  2725. LEAVE_DDRAW();
  2726. return DDERR_INVALIDPARAMS;
  2727. }
  2728. if( !VALID_BYTE_ARRAY( lpf, *lpdwNum * sizeof( DDPIXELFORMAT ) ) )
  2729. {
  2730. LEAVE_DDRAW();
  2731. return DDERR_INVALIDPARAMS;
  2732. }
  2733. }
  2734. if( ( dwFlags == 0 ) ||
  2735. ( dwFlags & ~(DDVPFORMAT_VIDEO|DDVPFORMAT_VBI|DDVPFORMAT_NOFAIL) ) )
  2736. {
  2737. LEAVE_DDRAW();
  2738. return DDERR_INVALIDPARAMS;
  2739. }
  2740. if( ( this_int->dwFlags & DDVPCREATE_VBIONLY ) &&
  2741. !( dwFlags & DDVPFORMAT_NOFAIL ) )
  2742. {
  2743. if( dwFlags & DDVPFORMAT_VIDEO )
  2744. {
  2745. DPF_ERR( "DDVPFORMAT_VIDEO specified on a VBI-only video port" );
  2746. LEAVE_DDRAW();
  2747. return DDERR_INVALIDPARAMS;
  2748. }
  2749. dwFlags |= DDVPFORMAT_VBI;
  2750. }
  2751. else if( ( this_int->dwFlags & DDVPCREATE_VIDEOONLY ) &&
  2752. !( dwFlags & DDVPFORMAT_NOFAIL ) )
  2753. {
  2754. if( dwFlags & DDVPFORMAT_VBI )
  2755. {
  2756. DPF_ERR( "DDVPFORMAT_VBI specified on a video-only video port" );
  2757. LEAVE_DDRAW();
  2758. return DDERR_INVALIDPARAMS;
  2759. }
  2760. dwFlags |= DDVPFORMAT_VIDEO;
  2761. }
  2762. }
  2763. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2764. {
  2765. DPF_ERR( "Exception encountered validating parameters" );
  2766. LEAVE_DDRAW();
  2767. return DDERR_EXCEPTION;
  2768. }
  2769. pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.GetVideoPortInputFormats;
  2770. if( pfn != NULL )
  2771. {
  2772. /*
  2773. * Get the number of formats
  2774. */
  2775. GetFormatData.lpDD = this_lcl->lpDD;
  2776. GetFormatData.dwFlags = dwFlags;
  2777. GetFormatData.lpVideoPort = this_lcl;
  2778. GetFormatData.lpddpfFormat = NULL;
  2779. DOHALCALL( GetVideoPortInputFormats, pfn, GetFormatData, rc, 0 );
  2780. if( DDHAL_DRIVER_HANDLED != rc )
  2781. {
  2782. LEAVE_DDRAW();
  2783. return GetFormatData.ddRVal;
  2784. }
  2785. else if( DD_OK != GetFormatData.ddRVal )
  2786. {
  2787. LEAVE_DDRAW();
  2788. return GetFormatData.ddRVal;
  2789. }
  2790. if( NULL == lpf )
  2791. {
  2792. *lpdwNum = GetFormatData.dwNumFormats;
  2793. }
  2794. else
  2795. {
  2796. /*
  2797. * Make sure we have enough room for formats
  2798. */
  2799. if( GetFormatData.dwNumFormats > *lpdwNum )
  2800. {
  2801. lpTemp = (LPDDPIXELFORMAT) MemAlloc( sizeof( DDPIXELFORMAT ) *
  2802. GetFormatData.dwNumFormats );
  2803. GetFormatData.lpddpfFormat = lpTemp;
  2804. }
  2805. else
  2806. {
  2807. GetFormatData.lpddpfFormat = lpf;
  2808. }
  2809. DOHALCALL( GetVideoPortInputFormats, pfn, GetFormatData, rc, 0 );
  2810. if( DDHAL_DRIVER_HANDLED != rc )
  2811. {
  2812. MemFree( lpTemp );
  2813. LEAVE_DDRAW();
  2814. return DDERR_UNSUPPORTED;
  2815. }
  2816. else if( DD_OK != GetFormatData.ddRVal )
  2817. {
  2818. MemFree( lpTemp );
  2819. LEAVE_DDRAW();
  2820. return GetFormatData.ddRVal;
  2821. }
  2822. if( GetFormatData.lpddpfFormat != lpf )
  2823. {
  2824. memcpy( lpf, lpTemp, sizeof( DDPIXELFORMAT ) * *lpdwNum );
  2825. MemFree( lpTemp );
  2826. LEAVE_DDRAW();
  2827. return DDERR_MOREDATA;
  2828. }
  2829. else
  2830. {
  2831. *lpdwNum = GetFormatData.dwNumFormats;
  2832. }
  2833. }
  2834. }
  2835. else
  2836. {
  2837. LEAVE_DDRAW();
  2838. return DDERR_UNSUPPORTED;
  2839. }
  2840. LEAVE_DDRAW();
  2841. return DD_OK;
  2842. }
  2843. /*
  2844. * DD_VP_GetOutputFormats
  2845. */
  2846. HRESULT DDAPI DD_VP_GetOutputFormats(LPDIRECTDRAWVIDEOPORT lpDVP, LPDDPIXELFORMAT lpddpfInput, LPDWORD lpdwNum, LPDDPIXELFORMAT lpddpfOutput, DWORD dwFlags )
  2847. {
  2848. LPDDHALVPORTCB_GETOUTPUTFORMATS pfn;
  2849. LPDDRAWI_DDVIDEOPORT_INT this_int;
  2850. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  2851. LPDDPIXELFORMAT lpTemp = NULL;
  2852. DDHAL_GETVPORTOUTPUTFORMATDATA GetFormatData;
  2853. DWORD rc;
  2854. ENTER_DDRAW();
  2855. DPF(2,A,"ENTERAPI: DD_VP_GetOutputFormats");
  2856. /*
  2857. * Don't allow access to this function if called from within the
  2858. * the EnumVideoPort callback.
  2859. */
  2860. if( bInEnumCallback )
  2861. {
  2862. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  2863. LEAVE_DDRAW();
  2864. return DDERR_CURRENTLYNOTAVAIL;
  2865. }
  2866. /*
  2867. * Validate parameters
  2868. */
  2869. TRY
  2870. {
  2871. this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
  2872. if( !VALID_DDVIDEOPORT_PTR( this_int ) )
  2873. {
  2874. LEAVE_DDRAW();
  2875. return DDERR_INVALIDOBJECT;
  2876. }
  2877. this_lcl = this_int->lpLcl;
  2878. if( !VALID_DDPIXELFORMAT_PTR( lpddpfInput ) )
  2879. {
  2880. LEAVE_DDRAW();
  2881. return DDERR_INVALIDPARAMS;
  2882. }
  2883. if( (lpdwNum == NULL) || !VALID_BYTE_ARRAY( lpdwNum, sizeof( LPVOID ) ) )
  2884. {
  2885. LEAVE_DDRAW();
  2886. return DDERR_INVALIDPARAMS;
  2887. }
  2888. if( NULL != lpddpfOutput )
  2889. {
  2890. if( 0 == *lpdwNum )
  2891. {
  2892. LEAVE_DDRAW();
  2893. return DDERR_INVALIDPARAMS;
  2894. }
  2895. if( !VALID_BYTE_ARRAY( lpddpfOutput, *lpdwNum * sizeof( DDPIXELFORMAT ) ) )
  2896. {
  2897. LEAVE_DDRAW();
  2898. return DDERR_INVALIDPARAMS;
  2899. }
  2900. }
  2901. if( ( dwFlags == 0 ) ||
  2902. ( dwFlags & ~(DDVPFORMAT_VIDEO|DDVPFORMAT_VBI|DDVPFORMAT_NOFAIL) ) )
  2903. {
  2904. LEAVE_DDRAW();
  2905. return DDERR_INVALIDPARAMS;
  2906. }
  2907. if( ( this_int->dwFlags & DDVPCREATE_VBIONLY ) &&
  2908. !( dwFlags & DDVPFORMAT_NOFAIL ) )
  2909. {
  2910. if( dwFlags & DDVPFORMAT_VIDEO )
  2911. {
  2912. DPF_ERR( "DDVPFORMAT_VIDEO specified on a VBI-only video port" );
  2913. LEAVE_DDRAW();
  2914. return DDERR_INVALIDPARAMS;
  2915. }
  2916. dwFlags |= DDVPFORMAT_VBI;
  2917. }
  2918. else if( ( this_int->dwFlags & DDVPCREATE_VIDEOONLY ) &&
  2919. !( dwFlags & DDVPFORMAT_NOFAIL ) )
  2920. {
  2921. if( dwFlags & DDVPFORMAT_VBI )
  2922. {
  2923. DPF_ERR( "DDVPFORMAT_VBI specified on a video-only video port" );
  2924. LEAVE_DDRAW();
  2925. return DDERR_INVALIDPARAMS;
  2926. }
  2927. dwFlags |= DDVPFORMAT_VIDEO;
  2928. }
  2929. }
  2930. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2931. {
  2932. DPF_ERR( "Exception encountered validating parameters" );
  2933. LEAVE_DDRAW();
  2934. return DDERR_EXCEPTION;
  2935. }
  2936. pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.GetVideoPortOutputFormats;
  2937. if( pfn != NULL )
  2938. {
  2939. /*
  2940. * Get the number of formats
  2941. */
  2942. GetFormatData.lpDD = this_lcl->lpDD;
  2943. GetFormatData.dwFlags = dwFlags;
  2944. GetFormatData.lpVideoPort = this_lcl;
  2945. GetFormatData.lpddpfInputFormat = lpddpfInput;
  2946. GetFormatData.lpddpfOutputFormats = NULL;
  2947. DOHALCALL( GetVideoPortOutputFormats, pfn, GetFormatData, rc, 0 );
  2948. if( DDHAL_DRIVER_HANDLED != rc )
  2949. {
  2950. LEAVE_DDRAW();
  2951. return DDERR_UNSUPPORTED;
  2952. }
  2953. else if( DD_OK != GetFormatData.ddRVal )
  2954. {
  2955. LEAVE_DDRAW();
  2956. return GetFormatData.ddRVal;
  2957. }
  2958. if( NULL == lpddpfOutput )
  2959. {
  2960. *lpdwNum = GetFormatData.dwNumFormats;
  2961. }
  2962. else
  2963. {
  2964. /*
  2965. * Make sure we have enough room for formats
  2966. */
  2967. if( GetFormatData.dwNumFormats > *lpdwNum )
  2968. {
  2969. lpTemp = (LPDDPIXELFORMAT) MemAlloc( sizeof( DDPIXELFORMAT ) *
  2970. GetFormatData.dwNumFormats );
  2971. GetFormatData.lpddpfOutputFormats = lpTemp;
  2972. }
  2973. else
  2974. {
  2975. GetFormatData.lpddpfOutputFormats = lpddpfOutput;
  2976. }
  2977. DOHALCALL( GetVideoPortOutputFormats, pfn, GetFormatData, rc, 0 );
  2978. if( DDHAL_DRIVER_HANDLED != rc )
  2979. {
  2980. MemFree( lpTemp );
  2981. LEAVE_DDRAW();
  2982. return DDERR_UNSUPPORTED;
  2983. }
  2984. else if( DD_OK != GetFormatData.ddRVal )
  2985. {
  2986. MemFree( lpTemp );
  2987. LEAVE_DDRAW();
  2988. return GetFormatData.ddRVal;
  2989. }
  2990. if( GetFormatData.lpddpfOutputFormats != lpddpfOutput )
  2991. {
  2992. memcpy( lpddpfOutput, lpTemp, sizeof( DDPIXELFORMAT ) * *lpdwNum );
  2993. MemFree( lpTemp );
  2994. LEAVE_DDRAW();
  2995. return DDERR_MOREDATA;
  2996. }
  2997. else
  2998. {
  2999. *lpdwNum = GetFormatData.dwNumFormats;
  3000. }
  3001. }
  3002. }
  3003. else
  3004. {
  3005. LEAVE_DDRAW();
  3006. return DDERR_UNSUPPORTED;
  3007. }
  3008. LEAVE_DDRAW();
  3009. return DD_OK;
  3010. }
  3011. /*
  3012. * DD_VP_GetField
  3013. */
  3014. HRESULT DDAPI DD_VP_GetField(LPDIRECTDRAWVIDEOPORT lpDVP, LPBOOL lpField )
  3015. {
  3016. LPDDHALVPORTCB_GETFIELD pfn;
  3017. LPDDRAWI_DDVIDEOPORT_INT this_int;
  3018. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  3019. DWORD rc;
  3020. DDHAL_GETVPORTFIELDDATA GetFieldData;
  3021. ENTER_DDRAW();
  3022. DPF(2,A,"ENTERAPI: DD_VP_GetField");
  3023. /*
  3024. * Don't allow access to this function if called from within the
  3025. * the EnumVideoPort callback.
  3026. */
  3027. if( bInEnumCallback )
  3028. {
  3029. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  3030. LEAVE_DDRAW();
  3031. return DDERR_CURRENTLYNOTAVAIL;
  3032. }
  3033. /*
  3034. * Validate parameters
  3035. */
  3036. TRY
  3037. {
  3038. this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
  3039. if( !VALID_DDVIDEOPORT_PTR( this_int ) )
  3040. {
  3041. LEAVE_DDRAW();
  3042. return DDERR_INVALIDOBJECT;
  3043. }
  3044. this_lcl = this_int->lpLcl;
  3045. if( (NULL == lpField ) || !VALID_BOOL_PTR( lpField ) )
  3046. {
  3047. LEAVE_DDRAW();
  3048. return DDERR_INVALIDPARAMS;
  3049. }
  3050. }
  3051. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  3052. {
  3053. DPF_ERR( "Exception encountered validating parameters" );
  3054. LEAVE_DDRAW();
  3055. return DDERR_EXCEPTION;
  3056. }
  3057. pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.GetVideoPortField;
  3058. if( pfn != NULL )
  3059. {
  3060. GetFieldData.lpDD = this_lcl->lpDD;
  3061. GetFieldData.lpVideoPort = this_lcl;
  3062. GetFieldData.bField = 0;
  3063. DOHALCALL( GetVideoPortField, pfn, GetFieldData, rc, 0 );
  3064. if( DDHAL_DRIVER_HANDLED != rc )
  3065. {
  3066. LEAVE_DDRAW();
  3067. return DDERR_UNSUPPORTED;
  3068. }
  3069. else if( DD_OK != GetFieldData.ddRVal )
  3070. {
  3071. LEAVE_DDRAW();
  3072. return GetFieldData.ddRVal;
  3073. }
  3074. *lpField = GetFieldData.bField;
  3075. }
  3076. else
  3077. {
  3078. LEAVE_DDRAW();
  3079. return DDERR_UNSUPPORTED;
  3080. }
  3081. LEAVE_DDRAW();
  3082. return DD_OK;
  3083. }
  3084. /*
  3085. * DD_VP_GetLine
  3086. */
  3087. HRESULT DDAPI DD_VP_GetLine(LPDIRECTDRAWVIDEOPORT lpDVP, LPDWORD lpdwLine )
  3088. {
  3089. LPDDHALVPORTCB_GETLINE pfn;
  3090. LPDDRAWI_DDVIDEOPORT_INT this_int;
  3091. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  3092. DWORD rc;
  3093. DDHAL_GETVPORTLINEDATA GetLineData;
  3094. ENTER_DDRAW();
  3095. DPF(2,A,"ENTERAPI: DD_VP_GetLine");
  3096. /*
  3097. * Don't allow access to this function if called from within the
  3098. * the EnumVideoPort callback.
  3099. */
  3100. if( bInEnumCallback )
  3101. {
  3102. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  3103. LEAVE_DDRAW();
  3104. return DDERR_CURRENTLYNOTAVAIL;
  3105. }
  3106. /*
  3107. * Validate parameters
  3108. */
  3109. TRY
  3110. {
  3111. this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
  3112. if( !VALID_DDVIDEOPORT_PTR( this_int ) )
  3113. {
  3114. LEAVE_DDRAW();
  3115. return DDERR_INVALIDOBJECT;
  3116. }
  3117. this_lcl = this_int->lpLcl;
  3118. if( (NULL == lpdwLine ) || !VALID_DWORD_PTR( lpdwLine ) )
  3119. {
  3120. LEAVE_DDRAW();
  3121. return DDERR_INVALIDPARAMS;
  3122. }
  3123. }
  3124. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  3125. {
  3126. DPF_ERR( "Exception encountered validating parameters" );
  3127. LEAVE_DDRAW();
  3128. return DDERR_EXCEPTION;
  3129. }
  3130. pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.GetVideoPortLine;
  3131. if( pfn != NULL )
  3132. {
  3133. GetLineData.lpDD = this_lcl->lpDD;
  3134. GetLineData.lpVideoPort = this_lcl;
  3135. GetLineData.dwLine = 0;
  3136. DOHALCALL( GetVideoPortLine, pfn, GetLineData, rc, 0 );
  3137. if( DDHAL_DRIVER_HANDLED != rc )
  3138. {
  3139. LEAVE_DDRAW();
  3140. return DDERR_UNSUPPORTED;
  3141. }
  3142. else if( DD_OK != GetLineData.ddRVal )
  3143. {
  3144. LEAVE_DDRAW();
  3145. return GetLineData.ddRVal;
  3146. }
  3147. *lpdwLine = GetLineData.dwLine;
  3148. }
  3149. else
  3150. {
  3151. LEAVE_DDRAW();
  3152. return DDERR_UNSUPPORTED;
  3153. }
  3154. LEAVE_DDRAW();
  3155. return DD_OK;
  3156. }
  3157. /*
  3158. * ValidateVideoInfo
  3159. */
  3160. HRESULT ValidateVideoInfo(LPDDRAWI_DDVIDEOPORT_INT this_int,
  3161. LPDDVIDEOPORTINFO lpInfo, LPDWORD lpNumAutoFlip, LPDWORD lpNumVBIAutoFlip )
  3162. {
  3163. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  3164. LPDDPIXELFORMAT lpOutputFormat;
  3165. LPDDRAWI_DDRAWSURFACE_LCL surf_lcl = NULL;
  3166. DWORD rc;
  3167. DWORD dwAvailCaps;
  3168. DWORD dwAvailFX;
  3169. DWORD dwConnectFlags;
  3170. DWORD dwVPFlags;
  3171. DWORD dwNum;
  3172. DWORD i;
  3173. this_lcl = this_int->lpLcl;
  3174. *lpNumAutoFlip = 0;
  3175. *lpNumVBIAutoFlip = 0;
  3176. /*
  3177. * Check for invalid caps
  3178. */
  3179. dwAvailCaps = this_lcl->lpDD->lpGbl->lpDDVideoPortCaps[this_lcl->ddvpDesc.dwVideoPortID].dwCaps;
  3180. dwAvailFX = this_lcl->lpDD->lpGbl->lpDDVideoPortCaps[this_lcl->ddvpDesc.dwVideoPortID].dwFX;
  3181. dwConnectFlags = this_lcl->ddvpDesc.VideoPortType.dwFlags;
  3182. dwVPFlags = lpInfo->dwVPFlags;
  3183. if( ( dwVPFlags & DDVP_AUTOFLIP ) && !( dwAvailCaps & DDVPCAPS_AUTOFLIP ) )
  3184. {
  3185. DPF_ERR( "Invalid autoflip capability specified" );
  3186. return DDERR_INVALIDCAPS;
  3187. }
  3188. if( ( dwVPFlags & DDVP_INTERLEAVE ) && (
  3189. !( dwConnectFlags & DDVPCONNECT_INTERLACED ) ||
  3190. ( dwConnectFlags & DDVPCONNECT_SHAREEVEN ) ||
  3191. ( dwConnectFlags & DDVPCONNECT_SHAREODD ) ||
  3192. !( dwAvailFX & DDVPFX_INTERLEAVE ) ||
  3193. ( dwVPFlags & DDVP_SKIPODDFIELDS ) ||
  3194. ( dwVPFlags & DDVP_SKIPEVENFIELDS ) ) )
  3195. {
  3196. DPF_ERR( "Invalid interleave capability specified" );
  3197. return DDERR_INVALIDCAPS;
  3198. }
  3199. if( ( dwVPFlags & DDVP_MIRRORLEFTRIGHT ) && !( dwAvailFX & DDVPFX_MIRRORLEFTRIGHT ) )
  3200. {
  3201. DPF_ERR( "Invalid mirror left/right capability specified" );
  3202. return DDERR_INVALIDCAPS;
  3203. }
  3204. if( ( dwVPFlags & DDVP_MIRRORUPDOWN ) && !( dwAvailFX & DDVPFX_MIRRORUPDOWN ) )
  3205. {
  3206. DPF_ERR( "Invalid mirror up/down capability specified" );
  3207. return DDERR_INVALIDCAPS;
  3208. }
  3209. if( ( dwVPFlags & DDVP_SKIPEVENFIELDS ) && (
  3210. !( dwConnectFlags & DDVPCONNECT_INTERLACED ) ||
  3211. ( dwConnectFlags & DDVPCONNECT_SHAREEVEN ) ||
  3212. ( dwConnectFlags & DDVPCONNECT_SHAREODD ) ||
  3213. !( dwAvailCaps & DDVPCAPS_SKIPEVENFIELDS ) ||
  3214. ( dwVPFlags & DDVP_SKIPODDFIELDS ) ) )
  3215. {
  3216. DPF_ERR( "Invalid skipevenfields capability specified" );
  3217. return DDERR_INVALIDCAPS;
  3218. }
  3219. if( ( dwVPFlags & DDVP_SKIPODDFIELDS ) && (
  3220. !( dwConnectFlags & DDVPCONNECT_INTERLACED ) ||
  3221. ( dwConnectFlags & DDVPCONNECT_SHAREEVEN ) ||
  3222. ( dwConnectFlags & DDVPCONNECT_SHAREODD ) ||
  3223. !( dwAvailCaps & DDVPCAPS_SKIPODDFIELDS ) ) )
  3224. {
  3225. DPF_ERR( "Invalid skipoddfields capability specified" );
  3226. return DDERR_INVALIDCAPS;
  3227. }
  3228. if( ( dwVPFlags & DDVP_VBINOSCALE ) && !( dwAvailFX & DDVPFX_VBINOSCALE ) )
  3229. {
  3230. DPF_ERR( "Invalid VBI no-scale capability specified" );
  3231. return DDERR_INVALIDCAPS;
  3232. }
  3233. if( ( dwVPFlags & ( DDVP_VBICONVERT | DDVP_VBINOSCALE ) ) ||
  3234. ( NULL != this_lcl->lpVBISurface ) )
  3235. {
  3236. if( ( lpInfo->dwVBIHeight == 0 ) ||
  3237. ( lpInfo->dwVBIHeight >= this_lcl->ddvpDesc.dwFieldHeight ) )
  3238. {
  3239. DPF_ERR( "Invalid dwVBIHeight specified" );
  3240. return DDERR_INVALIDPARAMS;
  3241. }
  3242. if( ( dwVPFlags & DDVP_CROP ) &&
  3243. ( lpInfo->rCrop.top > (int) lpInfo->dwVBIHeight ) )
  3244. {
  3245. DPF_ERR( "Invalid dwVBIHeight specified" );
  3246. return DDERR_INVALIDPARAMS;
  3247. }
  3248. }
  3249. if( dwVPFlags & DDVP_CROP )
  3250. {
  3251. if( lpInfo->rCrop.bottom > (int) this_lcl->ddvpDesc.dwFieldHeight )
  3252. {
  3253. DPF_ERR( "Invalid cropping rectangle specified" );
  3254. return DDERR_SURFACENOTATTACHED;
  3255. }
  3256. if( !( dwAvailFX & ( DDVPFX_CROPY | DDVPFX_CROPTOPDATA ) ) && (
  3257. (lpInfo->rCrop.bottom - lpInfo->rCrop.top ) !=
  3258. (int) this_lcl->ddvpDesc.dwFieldHeight ) )
  3259. {
  3260. DPF_ERR( "Invalid cropping rectangle specified" );
  3261. return DDERR_SURFACENOTATTACHED;
  3262. }
  3263. if( lpInfo->rCrop.top >= (int) lpInfo->dwVBIHeight )
  3264. {
  3265. lpInfo->dwVBIHeight = 0;
  3266. }
  3267. /*
  3268. * Only do the extensive field width/height checking if the video
  3269. * region is involved
  3270. */
  3271. if( lpInfo->rCrop.bottom > (int) lpInfo->dwVBIHeight )
  3272. {
  3273. if( lpInfo->rCrop.right > (int) this_lcl->ddvpDesc.dwFieldWidth )
  3274. {
  3275. DPF_ERR( "Invalid cropping rectangle specified" );
  3276. return DDERR_SURFACENOTATTACHED;
  3277. }
  3278. if( !( dwAvailFX & DDVPFX_CROPX ) && (
  3279. (lpInfo->rCrop.right - lpInfo->rCrop.left ) !=
  3280. (int) this_lcl->ddvpDesc.dwFieldWidth ) )
  3281. {
  3282. DPF_ERR( "Invalid cropping rectangle specified" );
  3283. return DDERR_SURFACENOTATTACHED;
  3284. }
  3285. if( ( ( lpInfo->rCrop.right - lpInfo->rCrop.left ) ==
  3286. (int) this_lcl->ddvpDesc.dwFieldWidth ) &&
  3287. ( ( lpInfo->rCrop.bottom - lpInfo->rCrop.top ) ==
  3288. (int) this_lcl->ddvpDesc.dwFieldHeight ) )
  3289. {
  3290. dwVPFlags &= ~DDVP_CROP;
  3291. lpInfo->dwVPFlags &= ~DDVP_CROP;
  3292. }
  3293. }
  3294. }
  3295. if( dwVPFlags & DDVP_PRESCALE )
  3296. {
  3297. DWORD dwPreWidth;
  3298. DWORD dwPreHeight;
  3299. if( dwVPFlags & DDVP_CROP )
  3300. {
  3301. dwPreWidth = lpInfo->rCrop.right - lpInfo->rCrop.left;
  3302. dwPreHeight = lpInfo->rCrop.bottom - lpInfo->rCrop.top;
  3303. }
  3304. else
  3305. {
  3306. dwPreWidth = this_lcl->ddvpDesc.dwFieldWidth;
  3307. dwPreHeight = this_lcl->ddvpDesc.dwFieldHeight;
  3308. }
  3309. if( lpInfo->dwPrescaleWidth > dwPreWidth )
  3310. {
  3311. if( !( dwAvailFX & DDVPFX_PRESTRETCHX ) &&
  3312. !( ( dwAvailFX & DDVPFX_PRESTRETCHXN ) &&
  3313. ( lpInfo->dwPrescaleWidth % dwPreWidth ) ) )
  3314. {
  3315. DPF_ERR( "Invalid stretch specified" );
  3316. return DDERR_INVALIDPARAMS;
  3317. }
  3318. }
  3319. if( lpInfo->dwPrescaleHeight > dwPreHeight )
  3320. {
  3321. if( !( dwAvailFX & DDVPFX_PRESTRETCHY ) &&
  3322. !( ( dwAvailFX & DDVPFX_PRESTRETCHYN ) &&
  3323. ( lpInfo->dwPrescaleHeight % dwPreHeight ) ) )
  3324. {
  3325. DPF_ERR( "Invalid stretch specified" );
  3326. return DDERR_INVALIDPARAMS;
  3327. }
  3328. }
  3329. if( lpInfo->dwPrescaleWidth < dwPreWidth )
  3330. {
  3331. if( !( dwAvailFX & DDVPFX_PRESHRINKX ) &&
  3332. !( dwAvailFX & DDVPFX_PRESHRINKXS ) &&
  3333. !( dwAvailFX & DDVPFX_PRESHRINKXB ) )
  3334. {
  3335. DPF_ERR( "Invalid shrink specified" );
  3336. return DDERR_INVALIDPARAMS;
  3337. }
  3338. }
  3339. if( lpInfo->dwPrescaleHeight < dwPreHeight )
  3340. {
  3341. if( !( dwAvailFX & DDVPFX_PRESHRINKY ) &&
  3342. !( dwAvailFX & DDVPFX_PRESHRINKYS ) &&
  3343. !( dwAvailFX & DDVPFX_PRESHRINKYB ) )
  3344. {
  3345. DPF_ERR( "Invalid shrink specified" );
  3346. return DDERR_INVALIDPARAMS;
  3347. }
  3348. }
  3349. if( ( lpInfo->dwPrescaleWidth == dwPreWidth ) &&
  3350. ( lpInfo->dwPrescaleHeight == dwPreHeight ) )
  3351. {
  3352. dwVPFlags &= ~DDVP_PRESCALE;
  3353. lpInfo->dwVPFlags &= ~DDVP_PRESCALE;
  3354. }
  3355. }
  3356. if( dwVPFlags & DDVP_VBINOINTERLEAVE )
  3357. {
  3358. if( !( dwAvailFX & DDVPFX_VBINOINTERLEAVE ) )
  3359. {
  3360. DPF_ERR( "Device does not support DDVP_VBINOINTERLEAVE" );
  3361. return DDERR_INVALIDPARAMS;
  3362. }
  3363. if( this_lcl->lpVBISurface == NULL )
  3364. {
  3365. DPF_ERR( "DDVP_VBINOINTERLEAVE only valid when using a separate VBI surface" );
  3366. return DDERR_INVALIDPARAMS;
  3367. }
  3368. }
  3369. if( dwVPFlags & DDVP_HARDWAREDEINTERLACE )
  3370. {
  3371. if( !( dwAvailCaps & DDVPCAPS_HARDWAREDEINTERLACE ) )
  3372. {
  3373. DPF_ERR( "DDVP_HARDWAREDEINTERLACE not supported by this device" );
  3374. return DDERR_INVALIDPARAMS;
  3375. }
  3376. if( ( this_lcl->lpSurface != NULL ) &&
  3377. !( this_lcl->lpSurface->lpLcl->lpSurfMore->ddsCapsEx.dwCaps2 &
  3378. DDSCAPS2_RESERVED4 ) )
  3379. {
  3380. DPF_ERR( "DDSCAPS2_RESERVED4 not set on target surface" );
  3381. return DDERR_INVALIDPARAMS;
  3382. }
  3383. if( ( this_lcl->lpVBISurface != NULL ) &&
  3384. !( this_lcl->lpVBISurface->lpLcl->lpSurfMore->ddsCapsEx.dwCaps2 &
  3385. DDSCAPS2_RESERVED4 ) )
  3386. {
  3387. DPF_ERR( "DDSCAPS2_RESERVED4 not set on target surface" );
  3388. return DDERR_INVALIDPARAMS;
  3389. }
  3390. if( dwVPFlags & DDVP_AUTOFLIP )
  3391. {
  3392. DPF_ERR( "DDVP_HARDWAREDEINTERLACE not valid with DDVP_AUTOFLIP" );
  3393. return DDERR_INVALIDPARAMS;
  3394. }
  3395. }
  3396. /*
  3397. * Fail if neither a VBI or regular surface is attached
  3398. */
  3399. if( ( NULL == this_lcl->lpSurface ) && ( NULL == this_lcl->lpVBISurface ) )
  3400. {
  3401. DPF_ERR( "No surfaces are attached to the video port" );
  3402. return DDERR_INVALIDPARAMS;
  3403. }
  3404. /*
  3405. * Validate the regular video data
  3406. */
  3407. if( ( NULL != this_lcl->lpSurface ) &&
  3408. ( this_int->lpLcl->dwFlags & DDRAWIVPORT_VIDEOON ) )
  3409. {
  3410. DWORD dwVidWidth;
  3411. DWORD dwVidHeight;
  3412. /*
  3413. * Validate the input format
  3414. */
  3415. dwNum = MAX_VP_FORMATS;
  3416. rc = DD_VP_GetInputFormats( (LPDIRECTDRAWVIDEOPORT) this_int,
  3417. &dwNum, ddpfVPFormats, DDVPFORMAT_VIDEO | DDVPFORMAT_NOFAIL );
  3418. if( ( rc != DD_OK ) && ( rc != DDERR_MOREDATA ) )
  3419. {
  3420. DPF_ERR( "Invalid input format specified" );
  3421. return DDERR_INVALIDPIXELFORMAT;
  3422. }
  3423. i = 0;
  3424. while( ( i < dwNum ) && IsDifferentPixelFormat( &(ddpfVPFormats[i]),
  3425. lpInfo->lpddpfInputFormat ) )
  3426. {
  3427. i++;
  3428. }
  3429. if( i == dwNum )
  3430. {
  3431. DPF_ERR( "Invalid input format specified" );
  3432. return DDERR_INVALIDPIXELFORMAT;
  3433. }
  3434. /*
  3435. * Validate the output format
  3436. */
  3437. dwNum = MAX_VP_FORMATS;
  3438. rc = DD_VP_GetOutputFormats( (LPDIRECTDRAWVIDEOPORT) this_int,
  3439. lpInfo->lpddpfInputFormat, &dwNum, ddpfVPFormats,
  3440. DDVPFORMAT_VIDEO | DDVPFORMAT_NOFAIL );
  3441. if( ( rc != DD_OK ) && ( rc != DDERR_MOREDATA ) )
  3442. {
  3443. DPF_ERR( "Invalid output format specified" );
  3444. return DDERR_INVALIDPIXELFORMAT;
  3445. }
  3446. i = 0;
  3447. surf_lcl = this_lcl->lpSurface->lpLcl;
  3448. lpOutputFormat = GetSurfaceFormat( surf_lcl );
  3449. if( ( IsDifferentPixelFormat( lpInfo->lpddpfInputFormat,
  3450. lpOutputFormat ) ) && !( dwVPFlags |= DDVP_CONVERT ) )
  3451. {
  3452. DPF_ERR( "Invalid output format specified" );
  3453. return DDERR_INVALIDPIXELFORMAT;
  3454. }
  3455. while( ( i < dwNum ) && IsDifferentPixelFormat( &(ddpfVPFormats[i]),
  3456. lpOutputFormat ) )
  3457. {
  3458. i++;
  3459. }
  3460. if( i == dwNum )
  3461. {
  3462. DPF_ERR( "Invalid output format specified" );
  3463. return DDERR_INVALIDPIXELFORMAT;
  3464. }
  3465. /*
  3466. * Make sure the video fits within the attached surface
  3467. */
  3468. if( SURFACE_LOST( surf_lcl ) )
  3469. {
  3470. DPF_ERR( "Target surface is lost" );
  3471. return DDERR_SURFACELOST;
  3472. }
  3473. if( dwVPFlags & DDVP_PRESCALE )
  3474. {
  3475. dwVidWidth = lpInfo->dwPrescaleWidth;
  3476. dwVidHeight = lpInfo->dwPrescaleHeight;
  3477. }
  3478. else if( dwVPFlags & DDVP_CROP )
  3479. {
  3480. dwVidWidth = lpInfo->rCrop.right - lpInfo->rCrop.left;
  3481. dwVidHeight = lpInfo->rCrop.bottom - lpInfo->rCrop.top;
  3482. }
  3483. else
  3484. {
  3485. dwVidWidth = this_lcl->ddvpDesc.dwFieldWidth;
  3486. dwVidHeight = this_lcl->ddvpDesc.dwFieldHeight;
  3487. }
  3488. if( ( lpInfo->dwVBIHeight > 0 ) &&
  3489. ( this_lcl->dwFlags & DDRAWIVPORT_VBION ) &&
  3490. ( NULL != this_lcl->lpVBISurface ) )
  3491. {
  3492. dwVidHeight -= lpInfo->dwVBIHeight;
  3493. }
  3494. if( dwVPFlags & DDVP_INTERLEAVE )
  3495. {
  3496. dwVidHeight *= 2;
  3497. }
  3498. if( lpInfo->dwOriginX + dwVidWidth > (DWORD) surf_lcl->lpGbl->wWidth )
  3499. {
  3500. DPF_ERR( "surface is not wide enough to hold the videoport data" );
  3501. return DDERR_TOOBIGWIDTH;
  3502. }
  3503. if( lpInfo->dwOriginY + dwVidHeight > (DWORD) surf_lcl->lpGbl->wHeight )
  3504. {
  3505. DPF_ERR( "surface is not tall enough to hold the videoport data" );
  3506. return DDERR_TOOBIGHEIGHT;
  3507. }
  3508. }
  3509. else if( this_lcl->dwFlags & DDRAWIVPORT_VIDEOON )
  3510. {
  3511. DPF_ERR( "Video surface not specified" );
  3512. return DDERR_INVALIDPARAMS;
  3513. }
  3514. /*
  3515. * Validate the VBI formats.
  3516. */
  3517. if( ( lpInfo->dwVBIHeight > 0 ) &&
  3518. ( this_int->lpLcl->dwFlags & DDRAWIVPORT_VBION ) )
  3519. {
  3520. if( lpInfo->lpddpfVBIInputFormat == NULL )
  3521. {
  3522. DPF_ERR( "VBI input format not specified" );
  3523. return DDERR_INVALIDPIXELFORMAT;
  3524. }
  3525. }
  3526. /*
  3527. * Unless they want to convert the format, we don't do very much
  3528. * error checking.
  3529. */
  3530. if( dwVPFlags & DDVP_VBICONVERT )
  3531. {
  3532. if( !( dwAvailFX & DDVPFX_VBICONVERT ) )
  3533. {
  3534. DPF_ERR( "device cannot convert the VBI data" );
  3535. return DDERR_INVALIDCAPS;
  3536. }
  3537. /*
  3538. * Validate the VBI input format
  3539. */
  3540. dwNum = MAX_VP_FORMATS;
  3541. rc = DD_VP_GetInputFormats( (LPDIRECTDRAWVIDEOPORT) this_int,
  3542. &dwNum, ddpfVPFormats, DDVPFORMAT_VBI | DDVPFORMAT_NOFAIL );
  3543. if( ( rc != DD_OK ) && ( rc != DDERR_MOREDATA ) )
  3544. {
  3545. DPF_ERR( "Invalid input VBI format specified" );
  3546. return DDERR_INVALIDPIXELFORMAT;
  3547. }
  3548. i = 0;
  3549. while( ( i < dwNum ) && IsDifferentPixelFormat( &(ddpfVPFormats[i]),
  3550. lpInfo->lpddpfVBIInputFormat ) )
  3551. {
  3552. i++;
  3553. }
  3554. if( i == dwNum )
  3555. {
  3556. DPF_ERR( "Invalid VBI input format specified" );
  3557. return DDERR_INVALIDPIXELFORMAT;
  3558. }
  3559. /*
  3560. * Validate the VBI output format
  3561. */
  3562. if( lpInfo->lpddpfVBIOutputFormat == NULL )
  3563. {
  3564. DPF_ERR( "VBI output format not specified" );
  3565. return DDERR_INVALIDPIXELFORMAT;
  3566. }
  3567. dwNum = MAX_VP_FORMATS;
  3568. rc = DD_VP_GetOutputFormats( (LPDIRECTDRAWVIDEOPORT) this_int,
  3569. lpInfo->lpddpfVBIInputFormat, &dwNum, ddpfVPFormats,
  3570. DDVPFORMAT_VBI | DDVPFORMAT_NOFAIL );
  3571. if( ( rc != DD_OK ) && ( rc != DDERR_MOREDATA ) )
  3572. {
  3573. DPF_ERR( "Invalid output format specified" );
  3574. return DDERR_INVALIDPIXELFORMAT;
  3575. }
  3576. i = 0;
  3577. while( ( i < dwNum ) && IsDifferentPixelFormat( &(ddpfVPFormats[i]),
  3578. lpInfo->lpddpfVBIOutputFormat ) )
  3579. {
  3580. i++;
  3581. }
  3582. if( i == dwNum )
  3583. {
  3584. DPF_ERR( "Invalid VBI output format specified" );
  3585. return DDERR_INVALIDPIXELFORMAT;
  3586. }
  3587. }
  3588. /*
  3589. * Validate the VBI surface
  3590. */
  3591. if( ( lpInfo->dwVBIHeight > 0 ) &&
  3592. ( this_int->lpLcl->dwFlags & DDRAWIVPORT_VBION ) )
  3593. {
  3594. DWORD dwVBIBytes;
  3595. DWORD dwSurfaceBytes = 0;
  3596. DWORD dwVBIHeight;
  3597. /*
  3598. * Determine the height of the VBI data
  3599. */
  3600. dwVBIHeight = lpInfo->dwVBIHeight;
  3601. if( dwVPFlags & DDVP_CROP )
  3602. {
  3603. if( lpInfo->rCrop.top < (int) lpInfo->dwVBIHeight )
  3604. {
  3605. dwVBIHeight -= lpInfo->rCrop.top;
  3606. if( lpInfo->rCrop.bottom < (int) lpInfo->dwVBIHeight )
  3607. {
  3608. dwVBIHeight -= (lpInfo->dwVBIHeight - (DWORD)lpInfo->rCrop.bottom);
  3609. }
  3610. }
  3611. else
  3612. {
  3613. dwVBIHeight = 0;
  3614. }
  3615. }
  3616. if( ( dwVPFlags & DDVP_INTERLEAVE ) &&
  3617. !( dwVPFlags & DDVP_VBINOINTERLEAVE ) )
  3618. {
  3619. dwVBIHeight *= 2;
  3620. }
  3621. /*
  3622. * Make sure that the data will fit in the surface
  3623. */
  3624. if( ( dwVPFlags & DDVP_VBINOSCALE ) ||
  3625. !( dwVPFlags & DDVP_PRESCALE ) )
  3626. {
  3627. dwVBIBytes = this_lcl->ddvpDesc.dwVBIWidth;
  3628. }
  3629. else
  3630. {
  3631. dwVBIBytes = lpInfo->dwPrescaleWidth;
  3632. }
  3633. if( dwVPFlags & DDVP_VBICONVERT )
  3634. {
  3635. lpOutputFormat = lpInfo->lpddpfVBIOutputFormat;
  3636. }
  3637. else
  3638. {
  3639. lpOutputFormat = lpInfo->lpddpfVBIInputFormat;
  3640. }
  3641. if( lpOutputFormat->dwRGBBitCount )
  3642. {
  3643. dwVBIBytes *= lpOutputFormat->dwRGBBitCount;
  3644. dwVBIBytes /= 8;
  3645. }
  3646. else
  3647. {
  3648. dwVBIBytes *= 2;
  3649. }
  3650. if( NULL != this_lcl->lpVBISurface )
  3651. {
  3652. if( SURFACE_LOST( this_lcl->lpVBISurface->lpLcl ) )
  3653. {
  3654. DPF_ERR( "Target VBI surface is lost" );
  3655. return DDERR_SURFACELOST;
  3656. }
  3657. dwSurfaceBytes = (DWORD) this_lcl->lpVBISurface->lpLcl->lpGbl->wWidth;
  3658. if( this_lcl->lpVBISurface->lpLcl->dwFlags & DDRAWISURF_HASPIXELFORMAT )
  3659. {
  3660. dwSurfaceBytes *= this_lcl->lpVBISurface->lpLcl->lpGbl->ddpfSurface.dwRGBBitCount;
  3661. }
  3662. else
  3663. {
  3664. dwSurfaceBytes *= this_lcl->lpDD->lpGbl->vmiData.ddpfDisplay.dwRGBBitCount;
  3665. }
  3666. if( dwVBIHeight > (DWORD) this_lcl->lpVBISurface->lpLcl->lpGbl->wHeight )
  3667. {
  3668. DPF_ERR( "VBI surface is not tall enough to hold the VBI data" );
  3669. return DDERR_TOOBIGHEIGHT;
  3670. }
  3671. }
  3672. else if( NULL != surf_lcl )
  3673. {
  3674. dwSurfaceBytes = (DWORD) surf_lcl->lpGbl->wWidth;
  3675. if( surf_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT )
  3676. {
  3677. dwSurfaceBytes *= surf_lcl->lpGbl->ddpfSurface.dwRGBBitCount;
  3678. }
  3679. else
  3680. {
  3681. dwSurfaceBytes *= this_lcl->lpDD->lpGbl->vmiData.ddpfDisplay.dwRGBBitCount;
  3682. }
  3683. if( dwVBIHeight > (DWORD) this_lcl->lpSurface->lpLcl->lpGbl->wHeight )
  3684. {
  3685. DPF_ERR( "Surface is not tall enough to hold the VBI data" );
  3686. return DDERR_TOOBIGHEIGHT;
  3687. }
  3688. }
  3689. dwSurfaceBytes /= 8;
  3690. if( dwSurfaceBytes == 0 )
  3691. {
  3692. DPF_ERR( "No VBI/Video surface is attached to hold VBI data" );
  3693. return DDERR_INVALIDPARAMS;
  3694. }
  3695. if( dwVBIBytes > dwSurfaceBytes )
  3696. {
  3697. DPF_ERR( "VBI surface is not wide enough to hold the VBI data" );
  3698. return DDERR_TOOBIGWIDTH;
  3699. }
  3700. }
  3701. /*
  3702. * Validate the autoflip parameters
  3703. */
  3704. if( dwVPFlags & DDVP_AUTOFLIP )
  3705. {
  3706. LPDDRAWI_DDRAWSURFACE_INT surf_first;
  3707. LPDDRAWI_DDRAWSURFACE_INT surf_int;
  3708. /*
  3709. * Count how many regular surfaces there are
  3710. */
  3711. if( ( NULL != this_lcl->lpSurface ) &&
  3712. ( this_int->lpLcl->dwFlags & DDRAWIVPORT_VIDEOON ) )
  3713. {
  3714. surf_first = surf_int = this_lcl->lpSurface;
  3715. do
  3716. {
  3717. (*lpNumAutoFlip)++;
  3718. surf_int = FindAttachedFlip( surf_int );
  3719. } while( ( surf_int != NULL ) && ( surf_int->lpLcl != surf_first->lpLcl ) );
  3720. if( *lpNumAutoFlip == 1 )
  3721. {
  3722. *lpNumAutoFlip = 0;
  3723. }
  3724. }
  3725. /*
  3726. * Count how many VBI surfaces there are
  3727. */
  3728. if( ( NULL != this_lcl->lpVBISurface ) &&
  3729. ( this_int->lpLcl->dwFlags & DDRAWIVPORT_VBION ) )
  3730. {
  3731. surf_first = surf_int = this_lcl->lpVBISurface;
  3732. do
  3733. {
  3734. (*lpNumVBIAutoFlip)++;
  3735. surf_int = FindAttachedFlip( surf_int );
  3736. } while( ( surf_int != NULL ) && ( surf_int->lpLcl != surf_first->lpLcl ) );
  3737. if( *lpNumVBIAutoFlip == 1 )
  3738. {
  3739. *lpNumVBIAutoFlip = 0;
  3740. }
  3741. }
  3742. /*
  3743. * It's an error if neither one has sufficient surfaces to autoflip
  3744. */
  3745. if( ( *lpNumAutoFlip == 0 ) && ( *lpNumVBIAutoFlip == 0 ) )
  3746. {
  3747. DPF_ERR( "no autoflip surfaces are attached" );
  3748. return DDERR_INVALIDPARAMS;
  3749. }
  3750. }
  3751. return DD_OK;
  3752. }
  3753. /*
  3754. * FillFlipArray
  3755. */
  3756. DWORD FillFlipArray( LPDDRAWI_DDRAWSURFACE_INT *lpArray,
  3757. LPDDRAWI_DDRAWSURFACE_INT lpStart, LPDWORD lpdwCnt )
  3758. {
  3759. LPDDRAWI_DDRAWSURFACE_INT surf_first;
  3760. *lpdwCnt = 0;
  3761. surf_first = lpStart;
  3762. do
  3763. {
  3764. if( SURFACE_LOST( lpStart->lpLcl ) )
  3765. {
  3766. DPF_ERR( "Autoflip surface is lost" );
  3767. return (DWORD) DDERR_SURFACELOST;
  3768. }
  3769. (*lpdwCnt)++;
  3770. *lpArray++ = lpStart;
  3771. lpStart = FindAttachedFlip( lpStart );
  3772. } while( ( lpStart != NULL ) && ( lpStart->lpLcl != surf_first->lpLcl ) );
  3773. return DD_OK;
  3774. }
  3775. /*
  3776. * InternalStartVideo
  3777. */
  3778. HRESULT InternalStartVideo(LPDDRAWI_DDVIDEOPORT_INT this_int,
  3779. LPDDVIDEOPORTINFO lpInfo )
  3780. {
  3781. LPDDHALVPORTCB_UPDATE pfn;
  3782. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  3783. DDHAL_UPDATEVPORTDATA UpdateData;
  3784. DDVIDEOPORTBANDWIDTH Bandwidth;
  3785. LPDDRAWI_DDRAWSURFACE_INT *lpTempFlipInts;
  3786. LPDDVIDEOPORTCAPS lpAvailCaps;
  3787. DWORD dwTempNumAutoFlip;
  3788. DWORD dwTempNumVBIAutoFlip;
  3789. DWORD rc;
  3790. DWORD dwNumAutoFlip;
  3791. DWORD dwNumVBIAutoFlip;
  3792. DWORD dwTemp;
  3793. /*
  3794. * Validate the input parameters
  3795. */
  3796. rc = ValidateVideoInfo( this_int, lpInfo, &dwNumAutoFlip, &dwNumVBIAutoFlip );
  3797. if( DD_OK != rc )
  3798. {
  3799. return rc;
  3800. }
  3801. this_lcl = this_int->lpLcl;
  3802. lpAvailCaps = &(this_lcl->lpDD->lpGbl->lpDDVideoPortCaps[this_lcl->ddvpDesc.dwVideoPortID]);
  3803. /*
  3804. * Setup the autoflip surfaces
  3805. */
  3806. lpTempFlipInts = NULL;
  3807. if( lpInfo->dwVPFlags & DDVP_AUTOFLIP )
  3808. {
  3809. DWORD dwCnt;
  3810. lpTempFlipInts = this_lcl->lpFlipInts;
  3811. this_lcl->lpFlipInts = MemAlloc( sizeof( LPDDRAWI_DDRAWSURFACE_INT ) *
  3812. ( dwNumAutoFlip + dwNumVBIAutoFlip ) );
  3813. if( NULL == this_lcl->lpFlipInts )
  3814. {
  3815. DPF_ERR( "insufficient memory" );
  3816. this_lcl->lpFlipInts = lpTempFlipInts;
  3817. return DDERR_OUTOFMEMORY;
  3818. }
  3819. /*
  3820. * Now put the surface INTs into the array.
  3821. */
  3822. if( dwNumAutoFlip )
  3823. {
  3824. rc = FillFlipArray( this_lcl->lpFlipInts, this_lcl->lpSurface, &dwCnt );
  3825. if( rc != DD_OK )
  3826. {
  3827. MemFree( this_lcl->lpFlipInts );
  3828. this_lcl->lpFlipInts = lpTempFlipInts;
  3829. return rc;
  3830. }
  3831. DDASSERT( dwCnt == dwNumAutoFlip );
  3832. if( dwNumAutoFlip > lpAvailCaps->dwNumAutoFlipSurfaces )
  3833. {
  3834. DPF_ERR( "Too many autoflip surfaces" );
  3835. MemFree( this_lcl->lpFlipInts );
  3836. this_lcl->lpFlipInts = lpTempFlipInts;
  3837. return DDERR_INVALIDPARAMS;
  3838. }
  3839. }
  3840. /*
  3841. * Now put the VBI surface INTs into the array.
  3842. */
  3843. if( dwNumVBIAutoFlip )
  3844. {
  3845. rc = FillFlipArray( &(this_lcl->lpFlipInts[dwNumAutoFlip]),
  3846. this_lcl->lpVBISurface, &dwCnt );
  3847. if( rc != DD_OK )
  3848. {
  3849. MemFree( this_lcl->lpFlipInts );
  3850. this_lcl->lpFlipInts = lpTempFlipInts;
  3851. return rc;
  3852. }
  3853. DDASSERT( dwCnt == dwNumVBIAutoFlip );
  3854. if( dwNumVBIAutoFlip > lpAvailCaps->dwNumVBIAutoFlipSurfaces )
  3855. {
  3856. DPF_ERR( "Too many VBI autoflip surfaces" );
  3857. MemFree( this_lcl->lpFlipInts );
  3858. return DDERR_INVALIDPARAMS;
  3859. }
  3860. }
  3861. }
  3862. dwTempNumAutoFlip = this_lcl->dwNumAutoflip;
  3863. dwTempNumVBIAutoFlip = this_lcl->dwNumVBIAutoflip;
  3864. this_lcl->dwNumAutoflip = dwNumAutoFlip;
  3865. this_lcl->dwNumVBIAutoflip = dwNumVBIAutoFlip;
  3866. /*
  3867. * The kernel interface may have switched from hardware autoflipping
  3868. * to software autoflipping w/o us knowing. We need to check for
  3869. * this.
  3870. */
  3871. #ifdef WIN95
  3872. if( ( lpInfo->dwVPFlags & DDVP_AUTOFLIP ) &&
  3873. ( this_lcl->dwFlags & DDRAWIVPORT_SOFTWARE_AUTOFLIP ) &&
  3874. ( ( this_lcl->lpSurface != NULL ) || ( this_lcl->lpVBISurface != NULL ) ) )
  3875. {
  3876. DWORD dwState;
  3877. dwState = 0;
  3878. if( this_lcl->dwFlags & DDRAWIVPORT_VIDEOON )
  3879. {
  3880. GetKernelSurfaceState( this_lcl->lpSurface->lpLcl, &dwState );
  3881. }
  3882. else
  3883. {
  3884. GetKernelSurfaceState( this_lcl->lpVBISurface->lpLcl, &dwState );
  3885. }
  3886. if( dwState & DDSTATE_SOFTWARE_AUTOFLIP )
  3887. {
  3888. this_lcl->dwFlags |= DDRAWIVPORT_SOFTWARE_AUTOFLIP;
  3889. }
  3890. }
  3891. #endif
  3892. pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.UpdateVideoPort;
  3893. if( pfn != NULL )
  3894. {
  3895. /*
  3896. * Call the HAL
  3897. */
  3898. memset( &UpdateData, 0, sizeof( UpdateData ) );
  3899. UpdateData.lpDD = this_lcl->lpDD;
  3900. UpdateData.lpVideoPort = this_lcl;
  3901. UpdateData.lpVideoInfo = lpInfo;
  3902. UpdateData.dwFlags = DDRAWI_VPORTSTART;
  3903. if( dwNumAutoFlip && ( this_lcl->dwFlags & DDRAWIVPORT_VIDEOON ) )
  3904. {
  3905. UpdateData.lplpDDSurface = this_lcl->lpFlipInts;
  3906. UpdateData.dwNumAutoflip = dwNumAutoFlip;
  3907. }
  3908. else if( this_lcl->lpSurface && ( this_lcl->dwFlags & DDRAWIVPORT_VIDEOON ) )
  3909. {
  3910. UpdateData.lplpDDSurface = &(this_lcl->lpSurface);
  3911. }
  3912. else
  3913. {
  3914. UpdateData.lplpDDSurface = NULL;
  3915. }
  3916. if( dwNumVBIAutoFlip && ( this_lcl->dwFlags & DDRAWIVPORT_VBION ) )
  3917. {
  3918. UpdateData.lplpDDVBISurface =
  3919. &(this_lcl->lpFlipInts[this_lcl->dwNumAutoflip]);
  3920. UpdateData.dwNumVBIAutoflip = dwNumVBIAutoFlip;
  3921. }
  3922. else if( this_lcl->lpVBISurface && ( this_lcl->dwFlags & DDRAWIVPORT_VBION ) )
  3923. {
  3924. UpdateData.lplpDDVBISurface = &(this_lcl->lpVBISurface);
  3925. }
  3926. else
  3927. {
  3928. UpdateData.lplpDDVBISurface = NULL;
  3929. }
  3930. dwTemp = lpInfo->dwVPFlags;
  3931. if( this_lcl->dwFlags & DDRAWIVPORT_SOFTWARE_AUTOFLIP )
  3932. {
  3933. lpInfo->dwVPFlags &= ~DDVP_AUTOFLIP;
  3934. }
  3935. /*
  3936. * Before we call the HAL, create the implicit kernel surfaces if
  3937. * needed and update the list. A failure here will tell us whether
  3938. * software autoflip, etc. is an option.
  3939. */
  3940. if( ( this_lcl->lpSurface != NULL ) &&
  3941. ( this_lcl->dwFlags & DDRAWIVPORT_VIDEOON ) )
  3942. {
  3943. ReleaseVPESurfaces( this_lcl->lpSurface, FALSE );
  3944. PrepareVPESurfaces( this_lcl->lpSurface, this_lcl,
  3945. dwNumAutoFlip > 0 );
  3946. }
  3947. if( ( this_lcl->lpVBISurface != NULL ) &&
  3948. ( this_lcl->dwFlags & DDRAWIVPORT_VBION ) )
  3949. {
  3950. ReleaseVPESurfaces( this_lcl->lpVBISurface, FALSE );
  3951. PrepareVPESurfaces( this_lcl->lpVBISurface, this_lcl,
  3952. dwNumVBIAutoFlip > 0 );
  3953. }
  3954. #ifdef WIN95
  3955. if( this_lcl->lpSurface != NULL )
  3956. {
  3957. OverrideVideoPort( this_lcl->lpSurface, &(lpInfo->dwVPFlags) );
  3958. }
  3959. #endif
  3960. DOHALCALL( UpdateVideoPort, pfn, UpdateData, rc, 0 );
  3961. if( DDHAL_DRIVER_HANDLED != rc )
  3962. {
  3963. lpInfo->dwVPFlags = dwTemp;
  3964. if( lpInfo->dwVPFlags & DDVP_AUTOFLIP )
  3965. {
  3966. MemFree( this_lcl->lpFlipInts );
  3967. this_lcl->lpFlipInts = lpTempFlipInts;
  3968. this_lcl->dwNumAutoflip = dwTempNumAutoFlip;
  3969. this_lcl->dwNumVBIAutoflip = dwTempNumVBIAutoFlip;
  3970. }
  3971. return DDERR_UNSUPPORTED;
  3972. }
  3973. else if( DD_OK != UpdateData.ddRVal )
  3974. {
  3975. /*
  3976. * If we failed due to hardware autoflipping, try again w/o
  3977. */
  3978. #ifdef WIN95
  3979. if( ( lpInfo->dwVPFlags & DDVP_AUTOFLIP ) &&
  3980. CanSoftwareAutoflip( this_lcl ) )
  3981. {
  3982. lpInfo->dwVPFlags &= ~DDVP_AUTOFLIP;
  3983. DOHALCALL( UpdateVideoPort, pfn, UpdateData, rc, 0 );
  3984. if( ( DDHAL_DRIVER_HANDLED != rc ) ||
  3985. ( DD_OK != UpdateData.ddRVal ) )
  3986. {
  3987. lpInfo->dwVPFlags = dwTemp;
  3988. MemFree( this_lcl->lpFlipInts );
  3989. this_lcl->lpFlipInts = lpTempFlipInts;
  3990. this_lcl->dwNumAutoflip = dwTempNumAutoFlip;
  3991. this_lcl->dwNumVBIAutoflip = dwTempNumVBIAutoFlip;
  3992. return UpdateData.ddRVal;
  3993. }
  3994. this_lcl->dwFlags |= DDRAWIVPORT_SOFTWARE_AUTOFLIP;
  3995. }
  3996. else
  3997. {
  3998. #endif
  3999. lpInfo->dwVPFlags = dwTemp;
  4000. if( lpInfo->dwVPFlags & DDVP_AUTOFLIP )
  4001. {
  4002. MemFree( this_lcl->lpFlipInts );
  4003. this_lcl->lpFlipInts = lpTempFlipInts;
  4004. this_lcl->dwNumAutoflip = dwTempNumAutoFlip;
  4005. this_lcl->dwNumVBIAutoflip = dwTempNumVBIAutoFlip;
  4006. }
  4007. return UpdateData.ddRVal;
  4008. #ifdef WIN95
  4009. }
  4010. #endif
  4011. }
  4012. MemFree( lpTempFlipInts );
  4013. lpTempFlipInts = NULL;
  4014. lpInfo->dwVPFlags = dwTemp;
  4015. UpdateInterleavedFlags( this_lcl, lpInfo->dwVPFlags );
  4016. this_lcl->dwFlags |= DDRAWIVPORT_ON;
  4017. memcpy( &(this_lcl->ddvpInfo), lpInfo, sizeof( DDVIDEOPORTINFO ) );
  4018. if( NULL != lpInfo->lpddpfInputFormat )
  4019. {
  4020. this_lcl->ddvpInfo.lpddpfInputFormat = (LPDDPIXELFORMAT)
  4021. ((LPBYTE)this_lcl +
  4022. sizeof( DDRAWI_DDVIDEOPORT_LCL ) );
  4023. memcpy( this_lcl->ddvpInfo.lpddpfInputFormat,
  4024. lpInfo->lpddpfInputFormat, sizeof( DDPIXELFORMAT ) );
  4025. }
  4026. /*
  4027. * Determine if this can be colorkeyed and interpolated at
  4028. * the same time.
  4029. */
  4030. if( NULL != lpInfo->lpddpfInputFormat )
  4031. {
  4032. memset( &Bandwidth, 0, sizeof( Bandwidth ) );
  4033. Bandwidth.dwSize = sizeof( Bandwidth );
  4034. InternalGetBandwidth( this_lcl, lpInfo->lpddpfInputFormat,
  4035. 0, 0, DDVPB_TYPE, &Bandwidth );
  4036. if( Bandwidth.dwCaps & DDVPBCAPS_SOURCE )
  4037. {
  4038. if( InternalGetBandwidth( this_lcl, lpInfo->lpddpfInputFormat,
  4039. this_lcl->ddvpDesc.dwFieldWidth,
  4040. this_lcl->ddvpDesc.dwFieldHeight,
  4041. DDVPB_OVERLAY,
  4042. &Bandwidth ) == DD_OK )
  4043. {
  4044. if( Bandwidth.dwYInterpAndColorkey ==
  4045. Bandwidth.dwYInterpolate )
  4046. {
  4047. this_lcl->dwFlags |= DDRAWIVPORT_COLORKEYANDINTERP;
  4048. }
  4049. }
  4050. }
  4051. else
  4052. {
  4053. if( InternalGetBandwidth( this_lcl, lpInfo->lpddpfInputFormat,
  4054. this_lcl->ddvpDesc.dwFieldWidth,
  4055. this_lcl->ddvpDesc.dwFieldHeight,
  4056. DDVPB_VIDEOPORT,
  4057. &Bandwidth ) == DD_OK )
  4058. {
  4059. if( Bandwidth.dwYInterpAndColorkey <= 2000 )
  4060. {
  4061. this_lcl->dwFlags |= DDRAWIVPORT_COLORKEYANDINTERP;
  4062. }
  4063. }
  4064. }
  4065. }
  4066. }
  4067. else
  4068. {
  4069. this_lcl->dwNumAutoflip = dwTempNumAutoFlip;
  4070. this_lcl->dwNumVBIAutoflip = dwTempNumVBIAutoFlip;
  4071. if( lpInfo->dwVPFlags & DDVP_AUTOFLIP )
  4072. {
  4073. MemFree( this_lcl->lpFlipInts );
  4074. this_lcl->lpFlipInts = lpTempFlipInts;
  4075. }
  4076. return DDERR_UNSUPPORTED;
  4077. }
  4078. /*
  4079. * Notify kernel mode of the change
  4080. */
  4081. #ifdef WIN95
  4082. UpdateKernelVideoPort( this_lcl, DDKMVP_UPDATE );
  4083. #endif
  4084. return DD_OK;
  4085. }
  4086. /*
  4087. * InternalStopVideo
  4088. */
  4089. HRESULT InternalStopVideo( LPDDRAWI_DDVIDEOPORT_INT this_int )
  4090. {
  4091. LPDDHALVPORTCB_UPDATE pfn;
  4092. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  4093. DDHAL_UPDATEVPORTDATA UpdateData;
  4094. DWORD dwTemp2;
  4095. DWORD dwTemp;
  4096. DWORD rc;
  4097. this_lcl = this_int->lpLcl;
  4098. if( !( this_lcl->dwFlags & DDRAWIVPORT_ON ) )
  4099. {
  4100. // VPORT is not on
  4101. return DD_OK;
  4102. }
  4103. /*
  4104. * Notify kernel mode of the change
  4105. */
  4106. dwTemp2 = this_lcl->dwFlags;
  4107. this_lcl->dwFlags &= ~DDRAWIVPORT_ON;
  4108. dwTemp = this_lcl->ddvpInfo.dwVPFlags;
  4109. this_lcl->ddvpInfo.dwVPFlags &= ~DDVP_AUTOFLIP;
  4110. this_lcl->dwNumAutoflip = 0;
  4111. this_lcl->dwNumVBIAutoflip = 0;
  4112. #ifdef WIN95
  4113. UpdateKernelVideoPort( this_lcl, DDKMVP_UPDATE );
  4114. #endif
  4115. this_lcl->ddvpInfo.dwVPFlags = dwTemp;
  4116. this_lcl->dwFlags = dwTemp2;
  4117. pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.UpdateVideoPort;
  4118. if( pfn != NULL )
  4119. {
  4120. /*
  4121. * Call the HAL
  4122. */
  4123. memset( &UpdateData, 0, sizeof( UpdateData ) );
  4124. UpdateData.lpDD = this_lcl->lpDD;
  4125. UpdateData.lpVideoPort = this_lcl;
  4126. UpdateData.lpVideoInfo = &(this_lcl->ddvpInfo);
  4127. UpdateData.dwFlags = DDRAWI_VPORTSTOP;
  4128. UpdateData.dwNumAutoflip = 0;
  4129. UpdateData.dwNumVBIAutoflip = 0;
  4130. UpdateData.lplpDDSurface = NULL;
  4131. dwTemp = this_lcl->ddvpInfo.dwVPFlags;
  4132. this_lcl->ddvpInfo.dwVPFlags &= ~DDVP_AUTOFLIP;
  4133. DOHALCALL( UpdateVideoPort, pfn, UpdateData, rc, 0 );
  4134. if( DDHAL_DRIVER_HANDLED != rc )
  4135. {
  4136. this_lcl->ddvpInfo.dwVPFlags = dwTemp;
  4137. return DDERR_UNSUPPORTED;
  4138. }
  4139. else if( DD_OK != UpdateData.ddRVal )
  4140. {
  4141. this_lcl->ddvpInfo.dwVPFlags = dwTemp;
  4142. return UpdateData.ddRVal;
  4143. }
  4144. this_lcl->dwFlags &= ~DDRAWIVPORT_ON;
  4145. this_lcl->ddvpInfo.dwVPFlags = dwTemp;
  4146. }
  4147. else
  4148. {
  4149. return DDERR_UNSUPPORTED;
  4150. }
  4151. /*
  4152. * Update the surfaces and release implicit kernel handles.
  4153. */
  4154. if( this_lcl->lpSurface != NULL )
  4155. {
  4156. ReleaseVPESurfaces( this_lcl->lpSurface, TRUE );
  4157. }
  4158. if( this_lcl->lpVBISurface != NULL )
  4159. {
  4160. ReleaseVPESurfaces( this_lcl->lpVBISurface, TRUE );
  4161. }
  4162. return DD_OK;
  4163. }
  4164. /*
  4165. * InternalUpdateVideo
  4166. */
  4167. HRESULT InternalUpdateVideo(LPDDRAWI_DDVIDEOPORT_INT this_int,
  4168. LPDDVIDEOPORTINFO lpInfo )
  4169. {
  4170. LPDDHALVPORTCB_UPDATE pfn;
  4171. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  4172. DDHAL_UPDATEVPORTDATA UpdateData;
  4173. LPDDRAWI_DDRAWSURFACE_INT *lpTempFlipInts;
  4174. LPDDVIDEOPORTCAPS lpAvailCaps;
  4175. DWORD dwTempNumAutoFlip;
  4176. DWORD dwTempNumVBIAutoFlip;
  4177. DWORD rc;
  4178. DWORD dwNumAutoFlip;
  4179. DWORD dwNumVBIAutoFlip;
  4180. DWORD dwTemp;
  4181. /*
  4182. * Validate the input parameters
  4183. */
  4184. rc = ValidateVideoInfo( this_int, lpInfo, &dwNumAutoFlip, &dwNumVBIAutoFlip );
  4185. if( DD_OK != rc )
  4186. {
  4187. return rc;
  4188. }
  4189. this_lcl = this_int->lpLcl;
  4190. lpAvailCaps = &(this_lcl->lpDD->lpGbl->lpDDVideoPortCaps[this_lcl->ddvpDesc.dwVideoPortID]);
  4191. if( !( this_lcl->dwFlags & DDRAWIVPORT_ON ) )
  4192. {
  4193. // VPORT is not on - nothing to update
  4194. return DD_OK;
  4195. }
  4196. /*
  4197. * Setup the autoflip surfaces
  4198. */
  4199. lpTempFlipInts = NULL;
  4200. if( lpInfo->dwVPFlags & DDVP_AUTOFLIP )
  4201. {
  4202. DWORD dwCnt;
  4203. lpTempFlipInts = this_lcl->lpFlipInts;
  4204. this_lcl->lpFlipInts = MemAlloc( sizeof( LPDDRAWI_DDRAWSURFACE_INT ) *
  4205. ( dwNumAutoFlip + dwNumVBIAutoFlip ) );
  4206. if( NULL == this_lcl->lpFlipInts )
  4207. {
  4208. DPF_ERR( "insufficient memory" );
  4209. this_lcl->lpFlipInts = lpTempFlipInts;
  4210. return DDERR_OUTOFMEMORY;
  4211. }
  4212. /*
  4213. * Now put the surface INTs into the array.
  4214. */
  4215. if( dwNumAutoFlip )
  4216. {
  4217. rc = FillFlipArray( this_lcl->lpFlipInts, this_lcl->lpSurface, &dwCnt );
  4218. if( rc != DD_OK )
  4219. {
  4220. MemFree( this_lcl->lpFlipInts );
  4221. this_lcl->lpFlipInts = lpTempFlipInts;
  4222. return rc;
  4223. }
  4224. DDASSERT( dwCnt == dwNumAutoFlip );
  4225. if( dwNumAutoFlip > lpAvailCaps->dwNumAutoFlipSurfaces )
  4226. {
  4227. DPF_ERR( "Too many autoflip surfaces" );
  4228. MemFree( this_lcl->lpFlipInts );
  4229. this_lcl->lpFlipInts = lpTempFlipInts;
  4230. return DDERR_INVALIDPARAMS;
  4231. }
  4232. }
  4233. /*
  4234. * Now put the VBI surface INTs into the array.
  4235. */
  4236. if( dwNumVBIAutoFlip )
  4237. {
  4238. rc = FillFlipArray( &(this_lcl->lpFlipInts[dwNumAutoFlip]),
  4239. this_lcl->lpVBISurface, &dwCnt );
  4240. if( rc != DD_OK )
  4241. {
  4242. MemFree( this_lcl->lpFlipInts );
  4243. this_lcl->lpFlipInts = lpTempFlipInts;
  4244. return rc;
  4245. }
  4246. DDASSERT( dwCnt == dwNumVBIAutoFlip );
  4247. if( dwNumVBIAutoFlip > lpAvailCaps->dwNumVBIAutoFlipSurfaces )
  4248. {
  4249. DPF_ERR( "Too many VBI autoflip surfaces" );
  4250. MemFree( this_lcl->lpFlipInts );
  4251. return DDERR_INVALIDPARAMS;
  4252. }
  4253. }
  4254. }
  4255. dwTempNumAutoFlip = this_lcl->dwNumAutoflip;
  4256. dwTempNumVBIAutoFlip = this_lcl->dwNumVBIAutoflip;
  4257. this_lcl->dwNumAutoflip = dwNumAutoFlip;
  4258. this_lcl->dwNumVBIAutoflip = dwNumVBIAutoFlip;
  4259. /*
  4260. * The kernel interface may have switched from hardware autoflipping
  4261. * to software autoflipping w/o us knowing. We need to check for
  4262. * this.
  4263. */
  4264. #ifdef WIN95
  4265. if( ( lpInfo->dwVPFlags & DDVP_AUTOFLIP ) &&
  4266. ( this_lcl->dwFlags & DDRAWIVPORT_SOFTWARE_AUTOFLIP ) &&
  4267. ( ( this_lcl->lpSurface != NULL ) || ( this_lcl->lpVBISurface != NULL ) ) )
  4268. {
  4269. DWORD dwState;
  4270. dwState = 0;
  4271. if( this_lcl->dwFlags & DDRAWIVPORT_VIDEOON )
  4272. {
  4273. GetKernelSurfaceState( this_lcl->lpSurface->lpLcl, &dwState );
  4274. }
  4275. else
  4276. {
  4277. GetKernelSurfaceState( this_lcl->lpVBISurface->lpLcl, &dwState );
  4278. }
  4279. if( dwState & DDSTATE_SOFTWARE_AUTOFLIP )
  4280. {
  4281. this_lcl->dwFlags |= DDRAWIVPORT_SOFTWARE_AUTOFLIP;
  4282. }
  4283. }
  4284. #endif
  4285. pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.UpdateVideoPort;
  4286. if( pfn != NULL )
  4287. {
  4288. /*
  4289. * Call the HAL
  4290. */
  4291. memset( &UpdateData, 0, sizeof( UpdateData ) );
  4292. UpdateData.lpDD = this_lcl->lpDD;
  4293. UpdateData.lpVideoPort = this_lcl;
  4294. UpdateData.lpVideoInfo = lpInfo;
  4295. UpdateData.dwFlags = DDRAWI_VPORTSTART;
  4296. if( dwNumAutoFlip && ( this_lcl->dwFlags & DDRAWIVPORT_VIDEOON ) )
  4297. {
  4298. UpdateData.lplpDDSurface = this_lcl->lpFlipInts;
  4299. UpdateData.dwNumAutoflip = dwNumAutoFlip;
  4300. }
  4301. else if( this_lcl->lpSurface && ( this_lcl->dwFlags & DDRAWIVPORT_VIDEOON ) )
  4302. {
  4303. UpdateData.lplpDDSurface = &(this_lcl->lpSurface);
  4304. }
  4305. else
  4306. {
  4307. UpdateData.lplpDDSurface = NULL;
  4308. }
  4309. if( dwNumVBIAutoFlip && ( this_lcl->dwFlags & DDRAWIVPORT_VBION ) )
  4310. {
  4311. UpdateData.lplpDDVBISurface =
  4312. &(this_lcl->lpFlipInts[this_lcl->dwNumAutoflip]);
  4313. UpdateData.dwNumVBIAutoflip = dwNumVBIAutoFlip;
  4314. }
  4315. else if( this_lcl->lpVBISurface && ( this_lcl->dwFlags & DDRAWIVPORT_VBION ) )
  4316. {
  4317. UpdateData.lplpDDVBISurface = &(this_lcl->lpVBISurface);
  4318. }
  4319. else
  4320. {
  4321. UpdateData.lplpDDVBISurface = NULL;
  4322. }
  4323. dwTemp = lpInfo->dwVPFlags;
  4324. if( this_lcl->dwFlags & DDRAWIVPORT_SOFTWARE_AUTOFLIP )
  4325. {
  4326. lpInfo->dwVPFlags &= ~DDVP_AUTOFLIP;
  4327. }
  4328. #ifdef WIN95
  4329. if( this_lcl->lpSurface != NULL )
  4330. {
  4331. OverrideVideoPort( this_lcl->lpSurface, &(lpInfo->dwVPFlags) );
  4332. }
  4333. #endif
  4334. DOHALCALL( UpdateVideoPort, pfn, UpdateData, rc, 0 );
  4335. if( DDHAL_DRIVER_HANDLED != rc )
  4336. {
  4337. lpInfo->dwVPFlags = dwTemp;
  4338. if( lpInfo->dwVPFlags & DDVP_AUTOFLIP )
  4339. {
  4340. MemFree( this_lcl->lpFlipInts );
  4341. this_lcl->lpFlipInts = lpTempFlipInts;
  4342. this_lcl->dwNumAutoflip = dwTempNumAutoFlip;
  4343. this_lcl->dwNumVBIAutoflip = dwTempNumVBIAutoFlip;
  4344. }
  4345. return DDERR_UNSUPPORTED;
  4346. }
  4347. else if( DD_OK != UpdateData.ddRVal )
  4348. {
  4349. /*
  4350. * If we failed due to hardware autoflipping, try again w/o
  4351. */
  4352. if( ( lpInfo->dwVPFlags & DDVP_AUTOFLIP ) ||
  4353. CanSoftwareAutoflip( this_lcl ) )
  4354. {
  4355. lpInfo->dwVPFlags &= ~DDVP_AUTOFLIP;
  4356. DOHALCALL( UpdateVideoPort, pfn, UpdateData, rc, 0 );
  4357. if( ( DDHAL_DRIVER_HANDLED != rc ) &&
  4358. ( DD_OK != UpdateData.ddRVal ) )
  4359. {
  4360. lpInfo->dwVPFlags = dwTemp;
  4361. MemFree( this_lcl->lpFlipInts );
  4362. this_lcl->lpFlipInts = lpTempFlipInts;
  4363. this_lcl->dwNumAutoflip = dwTempNumAutoFlip;
  4364. this_lcl->dwNumVBIAutoflip = dwTempNumVBIAutoFlip;
  4365. return UpdateData.ddRVal;
  4366. }
  4367. this_lcl->dwFlags |= DDRAWIVPORT_SOFTWARE_AUTOFLIP;
  4368. }
  4369. else
  4370. {
  4371. lpInfo->dwVPFlags = dwTemp;
  4372. if( lpInfo->dwVPFlags & DDVP_AUTOFLIP )
  4373. {
  4374. MemFree( this_lcl->lpFlipInts );
  4375. this_lcl->lpFlipInts = lpTempFlipInts;
  4376. this_lcl->dwNumAutoflip = dwTempNumAutoFlip;
  4377. this_lcl->dwNumVBIAutoflip = dwTempNumVBIAutoFlip;
  4378. }
  4379. return UpdateData.ddRVal;
  4380. }
  4381. }
  4382. MemFree( lpTempFlipInts );
  4383. lpTempFlipInts = NULL;
  4384. lpInfo->dwVPFlags = dwTemp;
  4385. /*
  4386. * If they are changing to or from autoflipping, we need to update
  4387. * the surfaces.
  4388. */
  4389. if( ( dwNumAutoFlip > dwTempNumAutoFlip ) &&
  4390. ( this_lcl->dwFlags & DDRAWIVPORT_VIDEOON ) )
  4391. {
  4392. DDASSERT( this_lcl->lpSurface != NULL );
  4393. PrepareVPESurfaces( this_lcl->lpSurface, this_lcl, TRUE );
  4394. }
  4395. if( ( dwNumVBIAutoFlip > dwTempNumVBIAutoFlip ) &&
  4396. ( this_lcl->dwFlags & DDRAWIVPORT_VBION ) )
  4397. {
  4398. DDASSERT( this_lcl->lpVBISurface != NULL );
  4399. PrepareVPESurfaces( this_lcl->lpVBISurface, this_lcl, TRUE );
  4400. }
  4401. if( ( dwNumAutoFlip < dwTempNumAutoFlip ) &&
  4402. ( this_lcl->dwFlags & DDRAWIVPORT_VIDEOON ) )
  4403. {
  4404. DDASSERT( this_lcl->lpSurface != NULL );
  4405. ReleaseVPESurfaces( this_lcl->lpSurface, FALSE );
  4406. PrepareVPESurfaces( this_lcl->lpSurface, this_lcl, FALSE );
  4407. }
  4408. if( ( dwNumVBIAutoFlip < dwTempNumVBIAutoFlip ) &&
  4409. ( this_lcl->dwFlags & DDRAWIVPORT_VBION ) )
  4410. {
  4411. DDASSERT( this_lcl->lpVBISurface != NULL );
  4412. ReleaseVPESurfaces( this_lcl->lpVBISurface, FALSE );
  4413. PrepareVPESurfaces( this_lcl->lpVBISurface, this_lcl, FALSE );
  4414. }
  4415. UpdateInterleavedFlags( this_lcl, lpInfo->dwVPFlags );
  4416. memcpy( &(this_lcl->ddvpInfo), lpInfo, sizeof( DDVIDEOPORTINFO ) );
  4417. if( NULL != lpInfo->lpddpfInputFormat )
  4418. {
  4419. this_lcl->ddvpInfo.lpddpfInputFormat = (LPDDPIXELFORMAT)
  4420. ((LPBYTE)this_lcl +
  4421. sizeof( DDRAWI_DDVIDEOPORT_LCL ) );
  4422. memcpy( this_lcl->ddvpInfo.lpddpfInputFormat,
  4423. lpInfo->lpddpfInputFormat, sizeof( DDPIXELFORMAT ) );
  4424. }
  4425. }
  4426. else
  4427. {
  4428. this_lcl->dwNumAutoflip = dwTempNumAutoFlip;
  4429. this_lcl->dwNumVBIAutoflip = dwTempNumVBIAutoFlip;
  4430. if( lpInfo->dwVPFlags & DDVP_AUTOFLIP )
  4431. {
  4432. MemFree( this_lcl->lpFlipInts );
  4433. this_lcl->lpFlipInts = lpTempFlipInts;
  4434. }
  4435. return DDERR_UNSUPPORTED;
  4436. }
  4437. /*
  4438. * Notify kernel mode of the change
  4439. */
  4440. #ifdef WIN95
  4441. UpdateKernelVideoPort( this_lcl, DDKMVP_UPDATE );
  4442. #endif
  4443. return DD_OK;
  4444. }
  4445. /*
  4446. * DD_VP_StartVideo
  4447. */
  4448. HRESULT DDAPI DD_VP_StartVideo(LPDIRECTDRAWVIDEOPORT lpDVP, LPDDVIDEOPORTINFO lpInfo )
  4449. {
  4450. LPDDRAWI_DDVIDEOPORT_INT this_int;
  4451. DDVIDEOPORTINFO TempInfo;
  4452. DWORD dwTempFlags;
  4453. DWORD rc;
  4454. ENTER_DDRAW();
  4455. DPF(2,A,"ENTERAPI: DD_VP_StartVideo");
  4456. /*
  4457. * Don't allow access to this function if called from within the
  4458. * the EnumVideoPort callback.
  4459. */
  4460. if( bInEnumCallback )
  4461. {
  4462. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  4463. LEAVE_DDRAW();
  4464. return DDERR_CURRENTLYNOTAVAIL;
  4465. }
  4466. /*
  4467. * Validate parameters
  4468. */
  4469. TRY
  4470. {
  4471. this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
  4472. if( !VALID_DDVIDEOPORT_PTR( this_int ) )
  4473. {
  4474. LEAVE_DDRAW();
  4475. return DDERR_INVALIDOBJECT;
  4476. }
  4477. if( (NULL == lpInfo) || !VALID_DDVIDEOPORTINFO_PTR( lpInfo ) )
  4478. {
  4479. LEAVE_DDRAW();
  4480. return DDERR_INVALIDPARAMS;
  4481. }
  4482. if( ( lpInfo->dwReserved1 != 0 ) ||
  4483. ( lpInfo->dwReserved2 != 0 ) )
  4484. {
  4485. DPF_ERR( "Reserved field not set to zero" );
  4486. LEAVE_DDRAW();
  4487. return DDERR_INVALIDPARAMS;
  4488. }
  4489. if( this_int->dwFlags & DDVPCREATE_VBIONLY )
  4490. {
  4491. if( (NULL == lpInfo->lpddpfVBIInputFormat) ||
  4492. !VALID_DDPIXELFORMAT_PTR( lpInfo->lpddpfVBIInputFormat ) )
  4493. {
  4494. LEAVE_DDRAW();
  4495. return DDERR_INVALIDPARAMS;
  4496. }
  4497. }
  4498. else if( (NULL == lpInfo->lpddpfInputFormat) ||
  4499. !VALID_DDPIXELFORMAT_PTR( lpInfo->lpddpfInputFormat ) )
  4500. {
  4501. LEAVE_DDRAW();
  4502. return DDERR_INVALIDPARAMS;
  4503. }
  4504. }
  4505. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  4506. {
  4507. DPF_ERR( "Exception encountered validating parameters" );
  4508. LEAVE_DDRAW();
  4509. return DDERR_EXCEPTION;
  4510. }
  4511. dwTempFlags = this_int->lpLcl->dwFlags;
  4512. if( this_int->dwFlags )
  4513. {
  4514. rc = MergeVPInfo( this_int->lpLcl,
  4515. this_int->dwFlags & DDVPCREATE_VBIONLY ? lpInfo : this_int->lpLcl->lpVBIInfo,
  4516. this_int->dwFlags & DDVPCREATE_VIDEOONLY ? lpInfo : this_int->lpLcl->lpVideoInfo,
  4517. &TempInfo );
  4518. if( rc == DD_OK )
  4519. {
  4520. if( this_int->dwFlags & DDVPCREATE_VBIONLY )
  4521. {
  4522. this_int->lpLcl->dwFlags |= DDRAWIVPORT_VBION;
  4523. }
  4524. else
  4525. {
  4526. this_int->lpLcl->dwFlags |= DDRAWIVPORT_VIDEOON;
  4527. }
  4528. rc = InternalStartVideo( this_int, &TempInfo );
  4529. }
  4530. }
  4531. else
  4532. {
  4533. this_int->lpLcl->dwFlags |= DDRAWIVPORT_VIDEOON | DDRAWIVPORT_VBION;
  4534. rc = InternalStartVideo( this_int, lpInfo );
  4535. }
  4536. if( ( rc == DD_OK ) && this_int->dwFlags )
  4537. {
  4538. /*
  4539. * Save the original info
  4540. */
  4541. if( this_int->dwFlags & DDVPCREATE_VBIONLY )
  4542. {
  4543. if( this_int->lpLcl->lpVBIInfo == NULL )
  4544. {
  4545. this_int->lpLcl->lpVBIInfo = MemAlloc( sizeof( TempInfo ) +
  4546. ( 2 * sizeof( DDPIXELFORMAT)) );
  4547. }
  4548. if( this_int->lpLcl->lpVBIInfo != NULL )
  4549. {
  4550. memcpy( this_int->lpLcl->lpVBIInfo, lpInfo, sizeof( TempInfo ) );
  4551. this_int->lpLcl->lpVBIInfo->lpddpfVBIInputFormat = (LPDDPIXELFORMAT)
  4552. ((LPBYTE)this_int->lpLcl->lpVBIInfo + sizeof( DDVIDEOPORTINFO ));
  4553. this_int->lpLcl->lpVBIInfo->lpddpfVBIOutputFormat = (LPDDPIXELFORMAT)
  4554. ((LPBYTE)this_int->lpLcl->lpVBIInfo + sizeof( DDVIDEOPORTINFO ) +
  4555. sizeof( DDPIXELFORMAT ) );
  4556. memcpy( this_int->lpLcl->lpVBIInfo->lpddpfVBIInputFormat,
  4557. lpInfo->lpddpfVBIInputFormat, sizeof( DDPIXELFORMAT ) );
  4558. if( lpInfo->lpddpfVBIOutputFormat != NULL )
  4559. {
  4560. memcpy( this_int->lpLcl->lpVBIInfo->lpddpfVBIOutputFormat,
  4561. lpInfo->lpddpfVBIOutputFormat, sizeof( DDPIXELFORMAT ) );
  4562. }
  4563. }
  4564. }
  4565. else if( this_int->dwFlags & DDVPCREATE_VIDEOONLY )
  4566. {
  4567. if( this_int->lpLcl->lpVideoInfo == NULL )
  4568. {
  4569. this_int->lpLcl->lpVideoInfo = MemAlloc( sizeof( TempInfo ) );
  4570. }
  4571. if( this_int->lpLcl->lpVideoInfo != NULL )
  4572. {
  4573. memcpy( this_int->lpLcl->lpVideoInfo, lpInfo, sizeof( TempInfo ) );
  4574. this_int->lpLcl->lpVideoInfo->lpddpfInputFormat =
  4575. this_int->lpLcl->ddvpInfo.lpddpfInputFormat;
  4576. }
  4577. }
  4578. }
  4579. else if( rc != DD_OK )
  4580. {
  4581. this_int->lpLcl->dwFlags = dwTempFlags;
  4582. }
  4583. LEAVE_DDRAW();
  4584. return rc;
  4585. }
  4586. /*
  4587. * DD_VP_StopVideo
  4588. */
  4589. HRESULT DDAPI DD_VP_StopVideo(LPDIRECTDRAWVIDEOPORT lpDVP )
  4590. {
  4591. LPDDRAWI_DDVIDEOPORT_INT this_int;
  4592. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  4593. DDVIDEOPORTINFO TempInfo;
  4594. BOOL bChanged;
  4595. DWORD rc = DD_OK;
  4596. ENTER_DDRAW();
  4597. DPF(2,A,"ENTERAPI: DD_VP_StopVideo");
  4598. /*
  4599. * Don't allow access to this function if called from within the
  4600. * the EnumVideoPort callback.
  4601. */
  4602. if( bInEnumCallback )
  4603. {
  4604. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  4605. LEAVE_DDRAW();
  4606. return DDERR_CURRENTLYNOTAVAIL;
  4607. }
  4608. /*
  4609. * Validate parameters
  4610. */
  4611. TRY
  4612. {
  4613. this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
  4614. if( !VALID_DDVIDEOPORT_PTR( this_int ) )
  4615. {
  4616. LEAVE_DDRAW();
  4617. return DDERR_INVALIDOBJECT;
  4618. }
  4619. this_lcl = this_int->lpLcl;
  4620. }
  4621. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  4622. {
  4623. DPF_ERR( "Exception encountered validating parameters" );
  4624. LEAVE_DDRAW();
  4625. return DDERR_EXCEPTION;
  4626. }
  4627. /*
  4628. * Three special things are done for VBI/Video-only video ports:
  4629. * 1. Remove the lpVBI/VideoInfo reference so we know we are no
  4630. * longer on.
  4631. * 2. If the other interface is running, instead of stoping the
  4632. * video stream, we simply crop it out so the other stream can
  4633. * continue un-interrupted.
  4634. * 3. Release the kernel handles.
  4635. */
  4636. if( this_int->dwFlags )
  4637. {
  4638. bChanged = FALSE;
  4639. if( this_int->dwFlags & DDVPCREATE_VBIONLY )
  4640. {
  4641. if( this_lcl->lpVBIInfo != NULL )
  4642. {
  4643. MemFree( this_lcl->lpVBIInfo );
  4644. this_lcl->lpVBIInfo = NULL;
  4645. bChanged = TRUE;
  4646. }
  4647. if( this_lcl->lpVBISurface != NULL )
  4648. {
  4649. ReleaseVPESurfaces( this_lcl->lpVBISurface, TRUE );
  4650. }
  4651. this_lcl->dwFlags &= ~DDRAWIVPORT_VBION;
  4652. }
  4653. else if( this_int->dwFlags & DDVPCREATE_VIDEOONLY )
  4654. {
  4655. if( this_lcl->lpVideoInfo != NULL )
  4656. {
  4657. MemFree( this_lcl->lpVideoInfo );
  4658. this_lcl->lpVideoInfo = NULL;
  4659. bChanged = TRUE;
  4660. }
  4661. if( this_lcl->lpSurface != NULL )
  4662. {
  4663. ReleaseVPESurfaces( this_lcl->lpSurface, TRUE );
  4664. }
  4665. this_lcl->dwFlags &= ~DDRAWIVPORT_VIDEOON;
  4666. }
  4667. if( bChanged && ( ( this_lcl->lpVideoInfo != NULL ) ||
  4668. ( this_lcl->lpVBIInfo != NULL ) ) )
  4669. {
  4670. rc = MergeVPInfo( this_lcl,
  4671. this_lcl->lpVBIInfo,
  4672. this_lcl->lpVideoInfo,
  4673. &TempInfo );
  4674. if( rc == DD_OK )
  4675. {
  4676. rc = InternalUpdateVideo( this_int, &TempInfo );
  4677. }
  4678. }
  4679. else if( bChanged )
  4680. {
  4681. rc = InternalStopVideo( this_int );
  4682. }
  4683. }
  4684. else
  4685. {
  4686. this_lcl->dwFlags &= ~( DDRAWIVPORT_VIDEOON | DDRAWIVPORT_VBION );
  4687. rc = InternalStopVideo( this_int );
  4688. }
  4689. LEAVE_DDRAW();
  4690. return rc;
  4691. }
  4692. /*
  4693. * DD_VP_UpdateVideo
  4694. */
  4695. HRESULT DDAPI DD_VP_UpdateVideo(LPDIRECTDRAWVIDEOPORT lpDVP, LPDDVIDEOPORTINFO lpInfo )
  4696. {
  4697. LPDDRAWI_DDVIDEOPORT_INT this_int;
  4698. DDVIDEOPORTINFO TempInfo;
  4699. DWORD rc;
  4700. ENTER_DDRAW();
  4701. DPF(2,A,"ENTERAPI: DD_VP_UpdateVideo");
  4702. /*
  4703. * Don't allow access to this function if called from within the
  4704. * the EnumVideoPort callback.
  4705. */
  4706. if( bInEnumCallback )
  4707. {
  4708. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  4709. LEAVE_DDRAW();
  4710. return DDERR_CURRENTLYNOTAVAIL;
  4711. }
  4712. /*
  4713. * Validate parameters
  4714. */
  4715. TRY
  4716. {
  4717. this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
  4718. if( !VALID_DDVIDEOPORT_PTR( this_int ) )
  4719. {
  4720. LEAVE_DDRAW();
  4721. return DDERR_INVALIDOBJECT;
  4722. }
  4723. if( (NULL == lpInfo) || !VALID_DDVIDEOPORTINFO_PTR( lpInfo ) )
  4724. {
  4725. LEAVE_DDRAW();
  4726. return DDERR_INVALIDPARAMS;
  4727. }
  4728. if( ( lpInfo->dwReserved1 != 0 ) ||
  4729. ( lpInfo->dwReserved2 != 0 ) )
  4730. {
  4731. DPF_ERR( "Reserved field not set to zero" );
  4732. LEAVE_DDRAW();
  4733. return DDERR_INVALIDPARAMS;
  4734. }
  4735. if( this_int->dwFlags & DDVPCREATE_VBIONLY )
  4736. {
  4737. if( (NULL == lpInfo->lpddpfVBIInputFormat) ||
  4738. !VALID_DDPIXELFORMAT_PTR( lpInfo->lpddpfVBIInputFormat ) )
  4739. {
  4740. LEAVE_DDRAW();
  4741. return DDERR_INVALIDPARAMS;
  4742. }
  4743. }
  4744. else if( (NULL == lpInfo->lpddpfInputFormat) ||
  4745. !VALID_DDPIXELFORMAT_PTR( lpInfo->lpddpfInputFormat ) )
  4746. {
  4747. LEAVE_DDRAW();
  4748. return DDERR_INVALIDPARAMS;
  4749. }
  4750. }
  4751. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  4752. {
  4753. DPF_ERR( "Exception encountered validating parameters" );
  4754. LEAVE_DDRAW();
  4755. return DDERR_EXCEPTION;
  4756. }
  4757. if( this_int->dwFlags )
  4758. {
  4759. rc = MergeVPInfo( this_int->lpLcl,
  4760. this_int->dwFlags & DDVPCREATE_VBIONLY ? lpInfo : this_int->lpLcl->lpVBIInfo,
  4761. this_int->dwFlags & DDVPCREATE_VIDEOONLY ? lpInfo : this_int->lpLcl->lpVideoInfo,
  4762. &TempInfo );
  4763. if( rc == DD_OK )
  4764. {
  4765. rc = InternalUpdateVideo( this_int, &TempInfo );
  4766. }
  4767. }
  4768. else
  4769. {
  4770. rc = InternalUpdateVideo( this_int, lpInfo );
  4771. }
  4772. if( ( rc == DD_OK ) && this_int->dwFlags )
  4773. {
  4774. /*
  4775. * Save the original info
  4776. */
  4777. if( this_int->dwFlags & DDVPCREATE_VBIONLY )
  4778. {
  4779. if( this_int->lpLcl->lpVBIInfo != NULL )
  4780. {
  4781. memcpy( this_int->lpLcl->lpVBIInfo, lpInfo, sizeof( TempInfo ) );
  4782. this_int->lpLcl->lpVBIInfo->lpddpfVBIInputFormat = (LPDDPIXELFORMAT)
  4783. ((LPBYTE)this_int->lpLcl->lpVBIInfo + sizeof( DDVIDEOPORTINFO ));
  4784. this_int->lpLcl->lpVBIInfo->lpddpfVBIOutputFormat = (LPDDPIXELFORMAT)
  4785. ((LPBYTE)this_int->lpLcl->lpVBIInfo + sizeof( DDVIDEOPORTINFO ) +
  4786. sizeof( DDPIXELFORMAT ) );
  4787. memcpy( this_int->lpLcl->lpVBIInfo->lpddpfVBIInputFormat,
  4788. lpInfo->lpddpfVBIInputFormat, sizeof( DDPIXELFORMAT ) );
  4789. if( lpInfo->lpddpfVBIOutputFormat != NULL )
  4790. {
  4791. memcpy( this_int->lpLcl->lpVBIInfo->lpddpfVBIOutputFormat,
  4792. lpInfo->lpddpfVBIOutputFormat, sizeof( DDPIXELFORMAT ) );
  4793. }
  4794. }
  4795. }
  4796. else if( this_int->dwFlags & DDVPCREATE_VIDEOONLY )
  4797. {
  4798. if( this_int->lpLcl->lpVideoInfo != NULL )
  4799. {
  4800. memcpy( this_int->lpLcl->lpVideoInfo, lpInfo, sizeof( TempInfo ) );
  4801. this_int->lpLcl->lpVideoInfo->lpddpfInputFormat =
  4802. this_int->lpLcl->ddvpInfo.lpddpfInputFormat;
  4803. }
  4804. }
  4805. }
  4806. LEAVE_DDRAW();
  4807. return rc;
  4808. }
  4809. /*
  4810. * DD_VP_WaitForSync
  4811. */
  4812. HRESULT DDAPI DD_VP_WaitForSync(LPDIRECTDRAWVIDEOPORT lpDVP, DWORD dwFlags, DWORD dwLine, DWORD dwTimeOut )
  4813. {
  4814. LPDDHALVPORTCB_WAITFORSYNC pfn;
  4815. LPDDRAWI_DDVIDEOPORT_INT this_int;
  4816. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  4817. DWORD rc;
  4818. DDHAL_WAITFORVPORTSYNCDATA WaitSyncData;
  4819. ENTER_DDRAW();
  4820. DPF(2,A,"ENTERAPI: DD_VP_WaitForSync");
  4821. /*
  4822. * Don't allow access to this function if called from within the
  4823. * the EnumVideoPort callback.
  4824. */
  4825. if( bInEnumCallback )
  4826. {
  4827. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  4828. LEAVE_DDRAW();
  4829. return DDERR_CURRENTLYNOTAVAIL;
  4830. }
  4831. /*
  4832. * Validate parameters
  4833. */
  4834. TRY
  4835. {
  4836. this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
  4837. if( !VALID_DDVIDEOPORT_PTR( this_int ) )
  4838. {
  4839. LEAVE_DDRAW();
  4840. return DDERR_INVALIDOBJECT;
  4841. }
  4842. this_lcl = this_int->lpLcl;
  4843. }
  4844. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  4845. {
  4846. DPF_ERR( "Exception encountered validating parameters" );
  4847. LEAVE_DDRAW();
  4848. return DDERR_EXCEPTION;
  4849. }
  4850. if( !dwFlags || ( dwFlags > 3 ) )
  4851. {
  4852. LEAVE_DDRAW();
  4853. return DDERR_INVALIDPARAMS;
  4854. }
  4855. pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.WaitForVideoPortSync;
  4856. if( pfn != NULL )
  4857. {
  4858. WaitSyncData.lpDD = this_lcl->lpDD;
  4859. WaitSyncData.lpVideoPort = this_lcl;
  4860. WaitSyncData.dwFlags = dwFlags;
  4861. WaitSyncData.dwLine = dwLine;
  4862. if( dwTimeOut != 0 )
  4863. {
  4864. WaitSyncData.dwTimeOut = dwTimeOut;
  4865. }
  4866. else
  4867. {
  4868. WaitSyncData.dwTimeOut = this_lcl->ddvpDesc.dwMicrosecondsPerField * 3;
  4869. }
  4870. DOHALCALL( WaitForVideoPortSync, pfn, WaitSyncData, rc, 0 );
  4871. if( DDHAL_DRIVER_HANDLED != rc )
  4872. {
  4873. LEAVE_DDRAW();
  4874. return DDERR_UNSUPPORTED;
  4875. }
  4876. }
  4877. else
  4878. {
  4879. LEAVE_DDRAW();
  4880. return DDERR_UNSUPPORTED;
  4881. }
  4882. LEAVE_DDRAW();
  4883. return WaitSyncData.ddRVal;
  4884. }
  4885. /*
  4886. * DD_VP_GetSignalStatus
  4887. */
  4888. HRESULT DDAPI DD_VP_GetSignalStatus(LPDIRECTDRAWVIDEOPORT lpDVP, LPDWORD lpdwStatus )
  4889. {
  4890. LPDDHALVPORTCB_GETSIGNALSTATUS pfn;
  4891. LPDDRAWI_DDVIDEOPORT_INT this_int;
  4892. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  4893. DDHAL_GETVPORTSIGNALDATA GetSignalData;
  4894. DWORD rc;
  4895. ENTER_DDRAW();
  4896. DPF(2,A,"ENTERAPI: DD_VP_GetSignalStatus");
  4897. /*
  4898. * Don't allow access to this function if called from within the
  4899. * the EnumVideoPort callback.
  4900. */
  4901. if( bInEnumCallback )
  4902. {
  4903. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  4904. LEAVE_DDRAW();
  4905. return DDERR_CURRENTLYNOTAVAIL;
  4906. }
  4907. /*
  4908. * Validate parameters
  4909. */
  4910. TRY
  4911. {
  4912. this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
  4913. if( !VALID_DDVIDEOPORT_PTR( this_int ) )
  4914. {
  4915. LEAVE_DDRAW();
  4916. return DDERR_INVALIDOBJECT;
  4917. }
  4918. this_lcl = this_int->lpLcl;
  4919. if( (NULL == lpdwStatus ) || !VALID_DWORD_PTR( lpdwStatus ) )
  4920. {
  4921. LEAVE_DDRAW();
  4922. return DDERR_INVALIDPARAMS;
  4923. }
  4924. }
  4925. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  4926. {
  4927. DPF_ERR( "Exception encountered validating parameters" );
  4928. LEAVE_DDRAW();
  4929. return DDERR_EXCEPTION;
  4930. }
  4931. pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.GetVideoSignalStatus;
  4932. if( pfn != NULL )
  4933. {
  4934. /*
  4935. * Call the HAL
  4936. */
  4937. GetSignalData.lpDD = this_lcl->lpDD;
  4938. GetSignalData.lpVideoPort = this_lcl;
  4939. GetSignalData.dwStatus = DDVPSQ_NOSIGNAL; // Let the HAL tell us otherwise
  4940. DOHALCALL( GetVideoSignalStatus, pfn, GetSignalData, rc, 0 );
  4941. if( DDHAL_DRIVER_HANDLED != rc )
  4942. {
  4943. LEAVE_DDRAW();
  4944. return DDERR_UNSUPPORTED;
  4945. }
  4946. else if( DD_OK != GetSignalData.ddRVal )
  4947. {
  4948. LEAVE_DDRAW();
  4949. return GetSignalData.ddRVal;
  4950. }
  4951. }
  4952. else
  4953. {
  4954. LEAVE_DDRAW();
  4955. return DDERR_UNSUPPORTED;
  4956. }
  4957. *lpdwStatus = GetSignalData.dwStatus;
  4958. LEAVE_DDRAW();
  4959. return DD_OK;
  4960. }
  4961. /*
  4962. * DD_VP_GetColorControls
  4963. */
  4964. HRESULT DDAPI DD_VP_GetColorControls(LPDIRECTDRAWVIDEOPORT lpDVP, LPDDCOLORCONTROL lpColor )
  4965. {
  4966. LPDDHALVPORTCB_COLORCONTROL pfn;
  4967. LPDDRAWI_DDVIDEOPORT_INT this_int;
  4968. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  4969. DDHAL_VPORTCOLORDATA ColorData;
  4970. DWORD rc;
  4971. ENTER_DDRAW();
  4972. DPF(2,A,"ENTERAPI: DD_VP_GetColorControls");
  4973. /*
  4974. * Don't allow access to this function if called from within the
  4975. * the EnumVideoPort callback.
  4976. */
  4977. if( bInEnumCallback )
  4978. {
  4979. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  4980. LEAVE_DDRAW();
  4981. return DDERR_CURRENTLYNOTAVAIL;
  4982. }
  4983. /*
  4984. * Validate parameters
  4985. */
  4986. TRY
  4987. {
  4988. this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
  4989. if( !VALID_DDVIDEOPORT_PTR( this_int ) )
  4990. {
  4991. LEAVE_DDRAW();
  4992. return DDERR_INVALIDOBJECT;
  4993. }
  4994. this_lcl = this_int->lpLcl;
  4995. if( (NULL == lpColor ) || !VALID_DDCOLORCONTROL_PTR( lpColor ) )
  4996. {
  4997. LEAVE_DDRAW();
  4998. return DDERR_INVALIDPARAMS;
  4999. }
  5000. if( this_int->dwFlags & DDVPCREATE_VBIONLY )
  5001. {
  5002. DPF_ERR( "Unable to set color controls on a VBI-only video port" );
  5003. LEAVE_DDRAW();
  5004. return DDERR_UNSUPPORTED;
  5005. }
  5006. }
  5007. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  5008. {
  5009. DPF_ERR( "Exception encountered validating parameters" );
  5010. LEAVE_DDRAW();
  5011. return DDERR_EXCEPTION;
  5012. }
  5013. pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.ColorControl;
  5014. if( pfn != NULL )
  5015. {
  5016. /*
  5017. * Call the HAL
  5018. */
  5019. ColorData.lpDD = this_lcl->lpDD;
  5020. ColorData.lpVideoPort = this_lcl;
  5021. ColorData.dwFlags = DDRAWI_VPORTGETCOLOR;
  5022. ColorData.lpColorData = lpColor;
  5023. DOHALCALL( VideoColorControl, pfn, ColorData, rc, 0 );
  5024. if( DDHAL_DRIVER_HANDLED != rc )
  5025. {
  5026. LEAVE_DDRAW();
  5027. return DDERR_UNSUPPORTED;
  5028. }
  5029. else if( DD_OK != ColorData.ddRVal )
  5030. {
  5031. LEAVE_DDRAW();
  5032. return ColorData.ddRVal;
  5033. }
  5034. }
  5035. else
  5036. {
  5037. LEAVE_DDRAW();
  5038. return DDERR_UNSUPPORTED;
  5039. }
  5040. LEAVE_DDRAW();
  5041. return DD_OK;
  5042. }
  5043. /*
  5044. * DD_VP_SetColorControls
  5045. */
  5046. HRESULT DDAPI DD_VP_SetColorControls(LPDIRECTDRAWVIDEOPORT lpDVP, LPDDCOLORCONTROL lpColor )
  5047. {
  5048. LPDDHALVPORTCB_COLORCONTROL pfn;
  5049. LPDDRAWI_DDVIDEOPORT_INT this_int;
  5050. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  5051. DDHAL_VPORTCOLORDATA ColorData;
  5052. DWORD rc;
  5053. ENTER_DDRAW();
  5054. DPF(2,A,"ENTERAPI: DD_VP_SetColorControls");
  5055. /*
  5056. * Don't allow access to this function if called from within the
  5057. * the EnumVideoPort callback.
  5058. */
  5059. if( bInEnumCallback )
  5060. {
  5061. DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
  5062. LEAVE_DDRAW();
  5063. return DDERR_CURRENTLYNOTAVAIL;
  5064. }
  5065. /*
  5066. * Validate parameters
  5067. */
  5068. TRY
  5069. {
  5070. this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
  5071. if( !VALID_DDVIDEOPORT_PTR( this_int ) )
  5072. {
  5073. LEAVE_DDRAW();
  5074. return DDERR_INVALIDOBJECT;
  5075. }
  5076. this_lcl = this_int->lpLcl;
  5077. if( (NULL == lpColor ) || !VALID_DDCOLORCONTROL_PTR( lpColor ) )
  5078. {
  5079. LEAVE_DDRAW();
  5080. return DDERR_INVALIDPARAMS;
  5081. }
  5082. if( this_int->dwFlags & DDVPCREATE_VBIONLY )
  5083. {
  5084. DPF_ERR( "Unable to set color controls on a VBI-only video port" );
  5085. LEAVE_DDRAW();
  5086. return DDERR_UNSUPPORTED;
  5087. }
  5088. }
  5089. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  5090. {
  5091. DPF_ERR( "Exception encountered validating parameters" );
  5092. LEAVE_DDRAW();
  5093. return DDERR_EXCEPTION;
  5094. }
  5095. pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.ColorControl;
  5096. if( pfn != NULL )
  5097. {
  5098. /*
  5099. * Call the HAL
  5100. */
  5101. ColorData.lpDD = this_lcl->lpDD;
  5102. ColorData.lpVideoPort = this_lcl;
  5103. ColorData.dwFlags = DDRAWI_VPORTSETCOLOR;
  5104. ColorData.lpColorData = lpColor;
  5105. DOHALCALL( VideoColorControl, pfn, ColorData, rc, 0 );
  5106. if( DDHAL_DRIVER_HANDLED != rc )
  5107. {
  5108. LEAVE_DDRAW();
  5109. return DDERR_UNSUPPORTED;
  5110. }
  5111. else if( DD_OK != ColorData.ddRVal )
  5112. {
  5113. LEAVE_DDRAW();
  5114. return ColorData.ddRVal;
  5115. }
  5116. }
  5117. else
  5118. {
  5119. LEAVE_DDRAW();
  5120. return DDERR_UNSUPPORTED;
  5121. }
  5122. LEAVE_DDRAW();
  5123. return DD_OK;
  5124. }
  5125. /*
  5126. * GetSurfaceFormat
  5127. *
  5128. * Fills in the DDPIXELFORMAT structure with the surface's format
  5129. */
  5130. LPDDPIXELFORMAT GetSurfaceFormat( LPDDRAWI_DDRAWSURFACE_LCL surf_lcl )
  5131. {
  5132. if( surf_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT )
  5133. {
  5134. return &(surf_lcl->lpGbl->ddpfSurface);
  5135. }
  5136. else
  5137. {
  5138. return &(surf_lcl->lpSurfMore->lpDD_lcl->lpGbl->vmiData.ddpfDisplay);
  5139. }
  5140. return NULL;
  5141. }
  5142. /*
  5143. * CreateVideoPortNotify
  5144. */
  5145. HRESULT CreateVideoPortNotify( LPDDRAWI_DDVIDEOPORT_INT lpDDVPInt, LPDIRECTDRAWVIDEOPORTNOTIFY *lplpVPNotify )
  5146. {
  5147. #ifdef WINNT
  5148. OSVERSIONINFOEX osvi;
  5149. DWORDLONG dwlConditionMask = 0;
  5150. LPDDRAWI_DDVIDEOPORT_INT lpInt;
  5151. #endif
  5152. *lplpVPNotify = NULL;
  5153. #ifdef WIN95
  5154. // This is available on Win9X
  5155. return DDERR_UNSUPPORTED;
  5156. #else
  5157. // This is only available on whistler
  5158. ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
  5159. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  5160. osvi.dwMajorVersion = 5;
  5161. osvi.dwMinorVersion = 1;
  5162. VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION,
  5163. VER_GREATER_EQUAL );
  5164. VER_SET_CONDITION( dwlConditionMask, VER_MINORVERSION,
  5165. VER_GREATER_EQUAL );
  5166. if (!VerifyVersionInfo(&osvi, VER_MAJORVERSION|VER_MINORVERSION, dwlConditionMask))
  5167. {
  5168. return DDERR_UNSUPPORTED;
  5169. }
  5170. // Only one notification interface can be active at any time for a single
  5171. // video port
  5172. if (lpDDVPInt->lpLcl->lpVPNotify != NULL)
  5173. {
  5174. DPF_ERR("A IDirectDrawVideoPortNotify interface already exists for this video port");
  5175. return DDERR_CURRENTLYNOTAVAIL;
  5176. }
  5177. lpInt = MemAlloc(sizeof(DDRAWI_DDVIDEOPORT_INT));
  5178. if (lpInt == NULL)
  5179. {
  5180. return DDERR_OUTOFMEMORY;
  5181. }
  5182. lpInt->lpVtbl = (LPVOID)&ddVideoPortNotifyCallbacks;
  5183. lpInt->lpLcl = lpDDVPInt->lpLcl;
  5184. lpInt->dwFlags = DDVPCREATE_NOTIFY | lpDDVPInt->dwFlags;
  5185. DD_VP_AddRef( (LPDIRECTDRAWVIDEOPORT )lpInt );
  5186. *lplpVPNotify = (LPDIRECTDRAWVIDEOPORTNOTIFY) lpInt;
  5187. lpInt->lpLink = lpDDVPInt->lpLcl->lpDD->lpGbl->dvpList;
  5188. lpDDVPInt->lpLcl->lpDD->lpGbl->dvpList = lpInt;
  5189. #endif
  5190. return DD_OK;
  5191. }
  5192. /*
  5193. * DDAPI DD_VP_Notify_AcquireNotification
  5194. */
  5195. HRESULT DDAPI DD_VP_Notify_AcquireNotification( LPDIRECTDRAWVIDEOPORTNOTIFY lpNotify, HANDLE* pEvent, LPDDVIDEOPORTNOTIFY pBuffer )
  5196. {
  5197. LPDDRAWI_DDVIDEOPORT_INT this_int;
  5198. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  5199. HRESULT rc;
  5200. ENTER_DDRAW();
  5201. DPF(2,A,"ENTERAPI: DD_VP_Notify_AcquireNotification");
  5202. /*
  5203. * Validate parameters
  5204. */
  5205. TRY
  5206. {
  5207. this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpNotify;
  5208. if( !VALID_DDVIDEOPORT_PTR( this_int ) )
  5209. {
  5210. LEAVE_DDRAW();
  5211. return DDERR_INVALIDOBJECT;
  5212. }
  5213. this_lcl = this_int->lpLcl;
  5214. if( (pBuffer == NULL) || !VALID_DDVIDEOPORTNOTIFY_PTR( pBuffer ) )
  5215. {
  5216. DPF_ERR( "Invalid LPDDVIDEOPORTNOTIFY specified" );
  5217. LEAVE_DDRAW();
  5218. return DDERR_INVALIDPARAMS;
  5219. }
  5220. if( (pEvent == NULL) || !VALID_HANDLE_PTR( pEvent ) )
  5221. {
  5222. DPF_ERR( "Invalid event handle ptr specified" );
  5223. LEAVE_DDRAW();
  5224. return DDERR_INVALIDPARAMS;
  5225. }
  5226. }
  5227. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  5228. {
  5229. DPF_ERR( "Exception encountered validating parameters" );
  5230. LEAVE_DDRAW();
  5231. return DDERR_EXCEPTION;
  5232. }
  5233. *pEvent = NULL;
  5234. rc = DDERR_UNSUPPORTED;
  5235. #ifdef WINNT
  5236. this_lcl->lpDD->lpGbl->lpDDCBtmp->HALDDVPE2.AcquireNotification(this_lcl, pEvent, pBuffer);
  5237. if (*pEvent != NULL)
  5238. {
  5239. rc = DD_OK;
  5240. }
  5241. #endif
  5242. LEAVE_DDRAW();
  5243. return rc;
  5244. }
  5245. /*
  5246. * DDAPI DD_VP_Notify_AcquireNotification
  5247. */
  5248. HRESULT DDAPI DD_VP_Notify_ReleaseNotification( LPDIRECTDRAWVIDEOPORTNOTIFY lpNotify, HANDLE pEvent )
  5249. {
  5250. LPDDRAWI_DDVIDEOPORT_INT this_int;
  5251. LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
  5252. ENTER_DDRAW();
  5253. DPF(2,A,"ENTERAPI: DD_VP_Notify_ReleaseNotification");
  5254. /*
  5255. * Validate parameters
  5256. */
  5257. TRY
  5258. {
  5259. this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpNotify;
  5260. if( !VALID_DDVIDEOPORT_PTR( this_int ) )
  5261. {
  5262. LEAVE_DDRAW();
  5263. return DDERR_INVALIDOBJECT;
  5264. }
  5265. this_lcl = this_int->lpLcl;
  5266. }
  5267. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  5268. {
  5269. DPF_ERR( "Exception encountered validating parameters" );
  5270. LEAVE_DDRAW();
  5271. return DDERR_EXCEPTION;
  5272. }
  5273. #ifdef WINNT
  5274. this_lcl->lpDD->lpGbl->lpDDCBtmp->HALDDVPE2.ReleaseNotification(this_lcl, pEvent);
  5275. #endif
  5276. LEAVE_DDRAW();
  5277. return DD_OK;
  5278. }
  5279. /*
  5280. * ProcessVideoPortCleanup
  5281. *
  5282. * A process is done, clean up any videoports that it may have locked.
  5283. *
  5284. * NOTE: we enter with a lock taken on the DIRECTDRAW object.
  5285. */
  5286. void ProcessVideoPortCleanup( LPDDRAWI_DIRECTDRAW_GBL pdrv, DWORD pid, LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
  5287. {
  5288. LPDDRAWI_DDVIDEOPORT_INT pvport_int;
  5289. LPDDRAWI_DDVIDEOPORT_LCL pvport_lcl;
  5290. LPDDRAWI_DDVIDEOPORT_INT pvpnext_int;
  5291. DWORD rcnt;
  5292. ULONG rc;
  5293. DWORD vp_id;
  5294. /*
  5295. * run through all videoports owned by the driver object, and find ones
  5296. * that have been accessed by this process. If the pdrv_lcl parameter
  5297. * is non-null, only delete videoports created by that local driver object.
  5298. */
  5299. pvport_int = pdrv->dvpList;
  5300. DPF( 4, "ProcessVideoPortCleanup" );
  5301. while( pvport_int != NULL )
  5302. {
  5303. pvport_lcl = pvport_int->lpLcl;
  5304. pvpnext_int = pvport_int->lpLink;
  5305. rc = 1;
  5306. if( pvport_int->dwFlags & DDVPCREATE_VBIONLY )
  5307. {
  5308. vp_id = pvport_lcl->dwVBIProcessID;
  5309. }
  5310. else
  5311. {
  5312. vp_id = pvport_lcl->dwProcessID;
  5313. }
  5314. if( ( vp_id == pid ) &&
  5315. ( (NULL == pdrv_lcl) || (pvport_lcl->lpDD == pdrv_lcl) ) )
  5316. {
  5317. /*
  5318. * release the references by this process
  5319. */
  5320. rcnt = pvport_int->dwIntRefCnt;
  5321. DPF( 5, "Process %08lx had %ld accesses to videoport %08lx", pid, rcnt, pvport_int );
  5322. while( rcnt > 0 )
  5323. {
  5324. DD_VP_Release( (LPDIRECTDRAWVIDEOPORT) pvport_int );
  5325. pvpnext_int = pdrv->dvpList;
  5326. if( rc == 0 )
  5327. {
  5328. break;
  5329. }
  5330. rcnt--;
  5331. }
  5332. }
  5333. else
  5334. {
  5335. DPF( 5, "Process %08lx had no accesses to videoport %08lx", pid, pvport_int );
  5336. }
  5337. pvport_int = pvpnext_int;
  5338. }
  5339. DPF( 4, "Leaving ProcessVideoPortCleanup");
  5340. } /* ProcessVideoPortCleanup */