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.

1041 lines
25 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: ddsckey.c
  6. * Content: DirectDraw Surface color key support
  7. * SetColorKey, GetColorKey
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 02-feb-95 craige split out of ddsurf.c
  12. * 21-feb-95 craige created CheckColorKey
  13. * 27-feb-95 craige new sync. macros
  14. * 15-mar-95 craige HEL work
  15. * 19-mar-95 craige use HRESULTs
  16. * 26-mar-95 craige support for driver wide colorkey
  17. * 01-apr-95 craige happy fun joy updated header file
  18. * 06-may-95 craige use driver-level csects only
  19. * 23-may-95 craige call HAL for SetColorKey
  20. * 16-jun-95 craige new surface structure
  21. * 25-jun-95 craige pay attention to DDCKEY_COLORSPACE; allow NULL ckey;
  22. * one ddraw mutex
  23. * 26-jun-95 craige reorganized surface structure
  24. * 28-jun-95 craige ENTER_DDRAW at very start of fns
  25. * 01-jul-95 craige don't allow ckeys for overlays unless supported
  26. * 03-jul-95 craige YEEHAW: new driver struct; SEH
  27. * 09-jul-95 craige handle the display driver failing setcolorkey
  28. * 31-jul-95 craige validate flags
  29. * 12-aug-95 craige call HEL SetColorKey when surface is in system memory
  30. * 09-dec-95 colinmc added execute buffer support
  31. * 02-jan-96 kylej handle new interface structs
  32. * 12-feb-96 colinmc Surface lost flag moved from global to local object
  33. * 21-apr-96 colinmc Bug 18057: SetColorKey fails set on system surfaces
  34. * if no emulation present
  35. * 12-mar-97 smac Bug 1746: Removed redundant checks in SetColorKey
  36. * 12-mar-97 smac Bug 1971: Return failure if HAL fails or sometimes
  37. * if the HAL doesn't handle the call.
  38. *
  39. ***************************************************************************/
  40. #include "ddrawpr.h"
  41. #define DPF_MODNAME "CheckColorKey"
  42. /*
  43. * CheckColorKey
  44. *
  45. * validate that a requested color key is OK
  46. */
  47. HRESULT CheckColorKey(
  48. DWORD dwFlags,
  49. LPDDRAWI_DIRECTDRAW_GBL pdrv,
  50. LPDDCOLORKEY lpDDColorKey,
  51. DWORD *psflags,
  52. BOOL halonly,
  53. BOOL helonly )
  54. {
  55. DWORD ckcaps;
  56. BOOL fail;
  57. BOOL color_space;
  58. ckcaps = pdrv->ddBothCaps.dwCKeyCaps;
  59. fail = FALSE;
  60. *psflags = 0;
  61. /*
  62. * check if is a color space or not
  63. */
  64. if( lpDDColorKey->dwColorSpaceLowValue != lpDDColorKey->dwColorSpaceHighValue )
  65. {
  66. color_space = TRUE;
  67. }
  68. else
  69. {
  70. color_space = FALSE;
  71. }
  72. /*
  73. * Overlay dest. key
  74. */
  75. if( dwFlags & DDCKEY_DESTOVERLAY )
  76. {
  77. if( dwFlags & (DDCKEY_DESTBLT|
  78. DDCKEY_SRCOVERLAY|
  79. DDCKEY_SRCBLT) )
  80. {
  81. DPF_ERR( "Invalid Flags with DESTOVERLAY" );
  82. return DDERR_INVALIDPARAMS;
  83. }
  84. #if 0
  85. /*
  86. * see if we can do this on a per surface/per driver basis
  87. */
  88. if( !isdriver )
  89. {
  90. if( !(ckcaps & DDCKEYCAPS_SRCOVERLAYPERSURFACE) )
  91. {
  92. if( ckcaps & DDCKEYCAPS_SRCOVERLAYDRIVERWIDE)
  93. {
  94. return DDERR_COLORKEYDRIVERWIDE;
  95. }
  96. return DDERR_UNSUPPORTED;
  97. }
  98. }
  99. else
  100. {
  101. if( !(ckcaps & DDCKEYCAPS_SRCOVERLAYDRIVERWIDE) )
  102. {
  103. return DDERR_UNSUPPORTED;
  104. }
  105. }
  106. #endif
  107. /*
  108. * can we do this kind of color key?
  109. */
  110. if( !color_space )
  111. {
  112. if( !(ckcaps & DDCKEYCAPS_DESTOVERLAY ) )
  113. {
  114. GETFAILCODE( pdrv->ddCaps.dwCKeyCaps,
  115. pdrv->ddHELCaps.dwCKeyCaps,
  116. DDCKEYCAPS_DESTOVERLAY );
  117. if( fail )
  118. {
  119. DPF_ERR( "DESTOVERLAY not supported" );
  120. return DDERR_NOCOLORKEYHW;
  121. }
  122. }
  123. }
  124. else
  125. {
  126. if( !(ckcaps & DDCKEYCAPS_DESTOVERLAYCLRSPACE ) )
  127. {
  128. GETFAILCODE( pdrv->ddCaps.dwCKeyCaps,
  129. pdrv->ddHELCaps.dwCKeyCaps,
  130. DDCKEYCAPS_DESTOVERLAYCLRSPACE );
  131. if( fail )
  132. {
  133. DPF_ERR( "DESTOVERLAYCOLORSPACE not supported" );
  134. return DDERR_NOCOLORKEYHW;
  135. }
  136. }
  137. }
  138. /*
  139. * is this hardware or software supported?
  140. */
  141. if( halonly )
  142. {
  143. *psflags |= DDRAWISURF_HW_CKEYDESTOVERLAY;
  144. }
  145. else if( helonly )
  146. {
  147. *psflags |= DDRAWISURF_SW_CKEYDESTOVERLAY;
  148. }
  149. /*
  150. * Blt dest. key
  151. */
  152. }
  153. else if( dwFlags & DDCKEY_DESTBLT )
  154. {
  155. if( dwFlags & (DDCKEY_SRCOVERLAY|
  156. DDCKEY_SRCBLT) )
  157. {
  158. DPF_ERR( "Invalid Flags with DESTBLT" );
  159. return DDERR_INVALIDPARAMS;
  160. }
  161. /*
  162. * can we do the requested color key?
  163. */
  164. if( !color_space )
  165. {
  166. if( !(ckcaps & DDCKEYCAPS_DESTBLT ) )
  167. {
  168. GETFAILCODE( pdrv->ddCaps.dwCKeyCaps,
  169. pdrv->ddHELCaps.dwCKeyCaps,
  170. DDCKEYCAPS_DESTBLT );
  171. if( fail )
  172. {
  173. DPF_ERR( "DESTBLT not supported" );
  174. return DDERR_NOCOLORKEYHW;
  175. }
  176. }
  177. }
  178. else
  179. {
  180. if( !(ckcaps & DDCKEYCAPS_DESTBLTCLRSPACE ) )
  181. {
  182. GETFAILCODE( pdrv->ddCaps.dwCKeyCaps,
  183. pdrv->ddHELCaps.dwCKeyCaps,
  184. DDCKEYCAPS_DESTBLTCLRSPACE );
  185. if( fail )
  186. {
  187. DPF_ERR( "DESTBLTCOLORSPACE not supported" );
  188. return DDERR_NOCOLORKEYHW;
  189. }
  190. }
  191. }
  192. /*
  193. * is this hardware or software supported?
  194. */
  195. if( halonly )
  196. {
  197. *psflags |= DDRAWISURF_HW_CKEYDESTBLT;
  198. }
  199. else if( helonly )
  200. {
  201. *psflags |= DDRAWISURF_SW_CKEYDESTBLT;
  202. }
  203. /*
  204. * Overlay src. key
  205. */
  206. }
  207. else if( dwFlags & DDCKEY_SRCOVERLAY )
  208. {
  209. if( dwFlags & DDCKEY_SRCBLT )
  210. {
  211. DPF_ERR( "Invalid Flags with SRCOVERLAY" );
  212. return DDERR_INVALIDPARAMS;
  213. }
  214. /*
  215. * see if we can do this on a per surface/per driver basis
  216. */
  217. #if 0
  218. if( !(ckcaps & DDCKEYCAPS_SRCOVERLAYPERSURFACE) )
  219. {
  220. if( ckcaps & DDCKEYCAPS_SRCOVERLAYDRIVERWIDE)
  221. {
  222. return DDERR_COLORKEYDRIVERWIDE;
  223. }
  224. return DDERR_UNSUPPORTED;
  225. }
  226. #endif
  227. /*
  228. * make sure we can do this kind of color key
  229. */
  230. if( !color_space )
  231. {
  232. if( !(ckcaps & DDCKEYCAPS_SRCOVERLAY ) )
  233. {
  234. GETFAILCODE( pdrv->ddCaps.dwCKeyCaps,
  235. pdrv->ddHELCaps.dwCKeyCaps,
  236. DDCKEYCAPS_SRCOVERLAY );
  237. if( fail )
  238. {
  239. DPF_ERR( "SRCOVERLAY not supported" );
  240. return DDERR_NOCOLORKEYHW;
  241. }
  242. }
  243. }
  244. else
  245. {
  246. if( !(ckcaps & DDCKEYCAPS_SRCOVERLAYCLRSPACE ) )
  247. {
  248. GETFAILCODE( pdrv->ddCaps.dwCKeyCaps,
  249. pdrv->ddHELCaps.dwCKeyCaps,
  250. DDCKEYCAPS_SRCOVERLAYCLRSPACE );
  251. if( fail )
  252. {
  253. DPF_ERR( "SRCOVERLAYCOLORSPACE not supported" );
  254. return DDERR_NOCOLORKEYHW;
  255. }
  256. }
  257. }
  258. /*
  259. * is this hardware or software supported?
  260. */
  261. if( halonly )
  262. {
  263. *psflags |= DDRAWISURF_HW_CKEYSRCOVERLAY;
  264. }
  265. else if( helonly )
  266. {
  267. *psflags |= DDRAWISURF_SW_CKEYSRCOVERLAY;
  268. }
  269. /*
  270. * Blt src. key
  271. */
  272. }
  273. else if( dwFlags & DDCKEY_SRCBLT )
  274. {
  275. /*
  276. * can we do the requested color key?
  277. */
  278. if( !color_space )
  279. {
  280. if( !(ckcaps & DDCKEYCAPS_SRCBLT ) )
  281. {
  282. GETFAILCODE( pdrv->ddCaps.dwCKeyCaps,
  283. pdrv->ddHELCaps.dwCKeyCaps,
  284. DDCKEYCAPS_SRCBLT );
  285. if( fail )
  286. {
  287. DPF_ERR( "SRCBLT not supported" );
  288. return DDERR_NOCOLORKEYHW;
  289. }
  290. }
  291. }
  292. else
  293. {
  294. if( !(ckcaps & DDCKEYCAPS_SRCBLTCLRSPACE ) )
  295. {
  296. GETFAILCODE( pdrv->ddCaps.dwCKeyCaps,
  297. pdrv->ddHELCaps.dwCKeyCaps,
  298. DDCKEYCAPS_SRCBLTCLRSPACE );
  299. if( fail )
  300. {
  301. DPF_ERR( "SRCBLTCOLORSPACE not supported" );
  302. return DDERR_NOCOLORKEYHW;
  303. }
  304. }
  305. }
  306. /*
  307. * is this hardware or software supported?
  308. */
  309. if( halonly )
  310. {
  311. *psflags |= DDRAWISURF_HW_CKEYSRCBLT;
  312. }
  313. else if( helonly )
  314. {
  315. *psflags |= DDRAWISURF_SW_CKEYSRCBLT;
  316. }
  317. /*
  318. * bad flags
  319. */
  320. }
  321. else
  322. {
  323. DPF_ERR( "Invalid Flags" );
  324. return DDERR_INVALIDPARAMS;
  325. }
  326. return DD_OK;
  327. } /* CheckColorKey */
  328. #undef DPF_MODNAME
  329. #define DPF_MODNAME "GetColorKey"
  330. /*
  331. * DD_Surface_GetColorKey
  332. *
  333. * get the color key associated with this surface
  334. */
  335. HRESULT DDAPI DD_Surface_GetColorKey(
  336. LPDIRECTDRAWSURFACE lpDDSurface,
  337. DWORD dwFlags,
  338. LPDDCOLORKEY lpDDColorKey )
  339. {
  340. LPDDRAWI_DDRAWSURFACE_INT this_int;
  341. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  342. LPDDRAWI_DDRAWSURFACE_GBL this;
  343. DWORD ckcaps;
  344. ENTER_DDRAW();
  345. DPF(2,A,"ENTERAPI: DD_Surface_GetColorKey");
  346. TRY
  347. {
  348. /*
  349. * validate parms
  350. */
  351. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  352. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  353. {
  354. LEAVE_DDRAW();
  355. return DDERR_INVALIDOBJECT;
  356. }
  357. this_lcl = this_int->lpLcl;
  358. this = this_lcl->lpGbl;
  359. if( SURFACE_LOST( this_lcl ) )
  360. {
  361. LEAVE_DDRAW();
  362. return DDERR_SURFACELOST;
  363. }
  364. /*
  365. * We know z-buffers and execute buffers aren't going to have
  366. * color keys.
  367. */
  368. if( this_lcl->ddsCaps.dwCaps & ( DDSCAPS_ZBUFFER | DDSCAPS_EXECUTEBUFFER ) )
  369. {
  370. DPF_ERR( "Surface does not have color key" );
  371. LEAVE_DDRAW();
  372. return DDERR_NOCOLORKEY;
  373. }
  374. if( dwFlags & ~DDCKEY_VALID )
  375. {
  376. DPF_ERR( "Invalid flags" );
  377. LEAVE_DDRAW();
  378. return DDERR_INVALIDPARAMS;
  379. }
  380. if( !VALID_DDCOLORKEY_PTR( lpDDColorKey ) )
  381. {
  382. DPF_ERR( "Invalid colorkey ptr" );
  383. LEAVE_DDRAW();
  384. return DDERR_INVALIDPARAMS;
  385. }
  386. //
  387. // For now, if the current surface is optimized, quit
  388. //
  389. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  390. {
  391. DPF_ERR( "It is an optimized surface" );
  392. LEAVE_DDRAW();
  393. return DDERR_ISOPTIMIZEDSURFACE;
  394. }
  395. /*
  396. * do we even support a color key
  397. */
  398. if( !(this->lpDD->ddCaps.dwCaps & DDCAPS_COLORKEY) &&
  399. !(this->lpDD->ddHELCaps.dwCaps & DDCAPS_COLORKEY) )
  400. {
  401. LEAVE_DDRAW();
  402. return DDERR_NOCOLORKEYHW;
  403. }
  404. ckcaps = this->lpDD->ddCaps.dwCKeyCaps;
  405. /*
  406. * get key for DESTOVERLAY
  407. */
  408. if( dwFlags & DDCKEY_DESTOVERLAY )
  409. {
  410. if( dwFlags & (DDCKEY_DESTBLT|
  411. DDCKEY_SRCOVERLAY|
  412. DDCKEY_SRCBLT) )
  413. {
  414. DPF_ERR( "Invalid Flags with DESTOVERLAY" );
  415. LEAVE_DDRAW();
  416. return DDERR_INVALIDPARAMS;
  417. }
  418. //ACKACK: destoverlay can be set on non-overlay surfaces!
  419. /* GEE: I ramble about this below as well...
  420. * seems to me we have an inconsitency here...
  421. * I am too tired to see if it is a real bug or just
  422. * a weirdness.
  423. */
  424. #if 0
  425. if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY ) )
  426. {
  427. DPF_ERR( "DESTOVERLAY specified for a non-overlay surface" );
  428. LEAVE_DDRAW();
  429. return DDERR_INVALIDOBJECT;
  430. }
  431. #endif
  432. #if 0
  433. if( !(ckcaps & DDCKEYCAPS_DESTOVERLAYPERSURFACE) )
  434. {
  435. if( ckcaps & DDCKEYCAPS_DESTOVERLAYDRIVERWIDE)
  436. {
  437. LEAVE_DDRAW();
  438. return DDERR_COLORKEYDRIVERWIDE;
  439. }
  440. LEAVE_DDRAW();
  441. return DDERR_UNSUPPORTED;
  442. }
  443. #endif
  444. if( !(this_lcl->dwFlags & DDRAWISURF_HASCKEYDESTOVERLAY) )
  445. {
  446. LEAVE_DDRAW();
  447. return DDERR_NOCOLORKEY;
  448. }
  449. *lpDDColorKey = this_lcl->ddckCKDestOverlay;
  450. /*
  451. * get key for DESTBLT
  452. */
  453. }
  454. else if( dwFlags & DDCKEY_DESTBLT )
  455. {
  456. if( dwFlags & (DDCKEY_SRCOVERLAY|
  457. DDCKEY_SRCBLT) )
  458. {
  459. DPF_ERR( "Invalid Flags with DESTBLT" );
  460. LEAVE_DDRAW();
  461. return DDERR_INVALIDPARAMS;
  462. }
  463. if( !(this_lcl->dwFlags & DDRAWISURF_HASCKEYDESTBLT) )
  464. {
  465. LEAVE_DDRAW();
  466. return DDERR_NOCOLORKEY;
  467. }
  468. *lpDDColorKey = this_lcl->ddckCKDestBlt;
  469. /*
  470. * get key for SRCOVERLAY
  471. */
  472. }
  473. else if( dwFlags & DDCKEY_SRCOVERLAY )
  474. {
  475. if( dwFlags & DDCKEY_SRCBLT )
  476. {
  477. DPF_ERR( "Invalid Flags with SRCOVERLAY" );
  478. LEAVE_DDRAW();
  479. return DDERR_INVALIDPARAMS;
  480. }
  481. if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY ) )
  482. {
  483. DPF_ERR( "SRCOVERLAY specified for a non-overlay surface" );
  484. LEAVE_DDRAW();
  485. return DDERR_INVALIDPARAMS;
  486. }
  487. #if 0
  488. if( !(ckcaps & DDCKEYCAPS_SRCOVERLAYPERSURFACE) )
  489. {
  490. if( ckcaps & DDCKEYCAPS_SRCOVERLAYDRIVERWIDE)
  491. {
  492. LEAVE_DDRAW();
  493. return DDERR_COLORKEYDRIVERWIDE;
  494. }
  495. LEAVE_DDRAW();
  496. return DDERR_UNSUPPORTED;
  497. }
  498. #endif
  499. if( !(this_lcl->dwFlags & DDRAWISURF_HASCKEYSRCOVERLAY) )
  500. {
  501. LEAVE_DDRAW();
  502. return DDERR_NOCOLORKEY;
  503. }
  504. *lpDDColorKey = this_lcl->ddckCKSrcOverlay;
  505. /*
  506. * get key for SRCBLT
  507. */
  508. }
  509. else if( dwFlags & DDCKEY_SRCBLT )
  510. {
  511. if( !(this_lcl->dwFlags & DDRAWISURF_HASCKEYSRCBLT) )
  512. {
  513. LEAVE_DDRAW();
  514. return DDERR_NOCOLORKEY;
  515. }
  516. *lpDDColorKey = this_lcl->ddckCKSrcBlt;
  517. }
  518. else
  519. {
  520. DPF_ERR( "Invalid Flags" );
  521. LEAVE_DDRAW();
  522. return DDERR_INVALIDPARAMS;
  523. }
  524. }
  525. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  526. {
  527. DPF_ERR( "Exception encountered validating parameters" );
  528. LEAVE_DDRAW();
  529. return DDERR_INVALIDPARAMS;
  530. }
  531. LEAVE_DDRAW();
  532. return DD_OK;
  533. } /* DD_Surface_GetColorKey */
  534. /*
  535. * ChangeToSoftwareColorKey
  536. */
  537. HRESULT ChangeToSoftwareColorKey(
  538. LPDDRAWI_DDRAWSURFACE_INT this_int,
  539. BOOL use_full_lock )
  540. {
  541. HRESULT ddrval;
  542. ddrval = MoveToSystemMemory( this_int, TRUE, use_full_lock );
  543. if( ddrval != DD_OK )
  544. {
  545. return ddrval;
  546. }
  547. this_int->lpLcl->dwFlags &= ~DDRAWISURF_HW_CKEYSRCOVERLAY;
  548. this_int->lpLcl->dwFlags |= DDRAWISURF_SW_CKEYSRCOVERLAY;
  549. return DD_OK;
  550. } /* ChangeToSoftwareColorKey */
  551. #undef DPF_MODNAME
  552. #define DPF_MODNAME "SetColorKey"
  553. /*
  554. * DD_Surface_SetColorKey
  555. *
  556. * set the color key associated with this surface
  557. */
  558. HRESULT DDAPI DD_Surface_SetColorKey(
  559. LPDIRECTDRAWSURFACE lpDDSurface,
  560. DWORD dwFlags,
  561. LPDDCOLORKEY lpDDColorKey )
  562. {
  563. LPDDRAWI_DDRAWSURFACE_INT this_int;
  564. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  565. LPDDRAWI_DDRAWSURFACE_GBL this;
  566. HRESULT ddrval;
  567. DWORD sflags = 0;
  568. BOOL halonly;
  569. BOOL helonly;
  570. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  571. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  572. LPDDHALSURFCB_SETCOLORKEY sckhalfn;
  573. LPDDHALSURFCB_SETCOLORKEY sckfn;
  574. DDHAL_SETCOLORKEYDATA sckd;
  575. DWORD rc;
  576. DDCOLORKEY ddck;
  577. DDCOLORKEY ddckOldSrcBlt;
  578. DDCOLORKEY ddckOldDestBlt;
  579. DDCOLORKEY ddckOldSrcOverlay;
  580. DDCOLORKEY ddckOldDestOverlay;
  581. DWORD oldflags;
  582. ENTER_DDRAW();
  583. DPF(2,A,"ENTERAPI: DD_Surface_SetColorKey");
  584. /*
  585. * validate parms
  586. */
  587. TRY
  588. {
  589. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  590. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  591. {
  592. LEAVE_DDRAW();
  593. return DDERR_INVALIDOBJECT;
  594. }
  595. this_lcl = this_int->lpLcl;
  596. this = this_lcl->lpGbl;
  597. if( SURFACE_LOST( this_lcl ) )
  598. {
  599. LEAVE_DDRAW();
  600. return DDERR_SURFACELOST;
  601. }
  602. //
  603. // For now, if the current surface is optimized, quit
  604. //
  605. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  606. {
  607. DPF_ERR( "It is an optimized surface" );
  608. LEAVE_DDRAW();
  609. return DDERR_ISOPTIMIZEDSURFACE;
  610. }
  611. /*
  612. * No color keys on z-buffers or execute buffers.
  613. */
  614. if( this_lcl->ddsCaps.dwCaps & ( DDSCAPS_ZBUFFER | DDSCAPS_EXECUTEBUFFER ) )
  615. {
  616. DPF_ERR( "Invalid surface type: can't set color key" );
  617. LEAVE_DDRAW();
  618. return DDERR_INVALIDSURFACETYPE;
  619. }
  620. //
  621. // New interfaces don't let mipmap sublevels have colorkeys
  622. //
  623. if ((!LOWERTHANSURFACE7(this_int)) &&
  624. (this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL))
  625. {
  626. DPF_ERR( "Cannot set colorkey for mipmap sublevels" );
  627. LEAVE_DDRAW();
  628. return DDERR_NOTONMIPMAPSUBLEVEL;
  629. }
  630. if( dwFlags & ~DDCKEY_VALID )
  631. {
  632. DPF_ERR( "Invalid flags" );
  633. LEAVE_DDRAW();
  634. return DDERR_INVALIDPARAMS;
  635. }
  636. if( lpDDColorKey != NULL )
  637. {
  638. if( !VALID_DDCOLORKEY_PTR( lpDDColorKey ) )
  639. {
  640. DPF_ERR( "Invalid colorkey ptr" );
  641. LEAVE_DDRAW();
  642. return DDERR_INVALIDPARAMS;
  643. }
  644. }
  645. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  646. pdrv = pdrv_lcl->lpGbl;
  647. helonly = FALSE;
  648. halonly = FALSE;
  649. /*
  650. * is surface in system memory?
  651. */
  652. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
  653. {
  654. halonly = FALSE;
  655. helonly = TRUE;
  656. }
  657. /*
  658. * do we even support a color key?
  659. */
  660. if( !(pdrv->ddBothCaps.dwCaps & DDCAPS_COLORKEY) )
  661. {
  662. if( pdrv->ddCaps.dwCaps & DDCAPS_COLORKEY )
  663. {
  664. halonly = TRUE;
  665. }
  666. else if( pdrv->ddHELCaps.dwCaps & DDCAPS_COLORKEY )
  667. {
  668. helonly = TRUE;
  669. }
  670. else
  671. {
  672. LEAVE_DDRAW();
  673. return DDERR_UNSUPPORTED;
  674. }
  675. }
  676. if( helonly && halonly )
  677. {
  678. #pragma message( REMIND( "Need to overhaul SetColorKey for DX3!" ) )
  679. /*
  680. * NOTE: This is a temporary fix to keep certain ISVs happy
  681. * until we can overhaul SetColorKey completely. The problem
  682. * is that we don't look at the drivers S->S, S->V and V->S
  683. * caps when deciding whether to call the HEL or the HAL for
  684. * color key sets. This is not terminal for most cards as it
  685. * will simply mean falling back on the HEL when we shouldn't.
  686. * However, for a certain class for cards (those which are
  687. * not display drivers) which have no emulation this will
  688. * result in SetColorKey failing. To keep them happy we
  689. * will just spot this situation and force a HAL call.
  690. *
  691. * 1) This is a temporary fix.
  692. * 2) The H/W must support the same colorkey operations for
  693. * its system memory blits as it does for its video
  694. * memory ones or things will go wrong.
  695. */
  696. if( ( !( pdrv->ddHELCaps.dwCaps & DDCAPS_COLORKEY ) ) &&
  697. ( pdrv->ddCaps.dwCaps & DDCAPS_CANBLTSYSMEM ) )
  698. {
  699. helonly = FALSE;
  700. }
  701. else
  702. {
  703. DPF_ERR( "Not supported in hardware or software!" );
  704. LEAVE_DDRAW();
  705. return DDERR_UNSUPPORTED;
  706. }
  707. }
  708. /*
  709. * Restore these if a failure occurs
  710. */
  711. oldflags = this_lcl->dwFlags;
  712. ddckOldSrcBlt = this_lcl->ddckCKSrcBlt;
  713. ddckOldDestBlt = this_lcl->ddckCKDestBlt;
  714. ddckOldSrcOverlay = this_lcl->ddckCKSrcOverlay;
  715. ddckOldDestOverlay = this_lcl->ddckCKDestOverlay;
  716. /*
  717. * color key specified?
  718. */
  719. if( lpDDColorKey != NULL )
  720. {
  721. /*
  722. * check for color space
  723. */
  724. ddck = *lpDDColorKey;
  725. if( !(dwFlags & DDCKEY_COLORSPACE) )
  726. {
  727. ddck.dwColorSpaceHighValue = ddck.dwColorSpaceLowValue;
  728. }
  729. lpDDColorKey = &ddck;
  730. /*
  731. * check the color key
  732. */
  733. ddrval = CheckColorKey( dwFlags, pdrv, lpDDColorKey, &sflags,
  734. halonly, helonly );
  735. if( ddrval != DD_OK )
  736. {
  737. DPF_ERR( "Failed CheckColorKey" );
  738. LEAVE_DDRAW();
  739. return ddrval;
  740. }
  741. }
  742. /*
  743. * Overlay dest. key
  744. */
  745. if( dwFlags & DDCKEY_DESTOVERLAY )
  746. {
  747. if( !(pdrv->ddCaps.dwCaps & DDCAPS_OVERLAY) )
  748. {
  749. DPF_ERR( "Can't do overlays" );
  750. LEAVE_DDRAW();
  751. return DDERR_NOOVERLAYHW;
  752. }
  753. /* GEE: in GetColorKey we say that DestColorKey can
  754. * be set for non overlay surfaces. Here we require
  755. * overlay data in order to SetColorKey (DestColorKey)
  756. * I understand why this is the case... are their any
  757. * implications to HASOVERLAYDATA other than bigger
  758. * structure... if not then we are okay?
  759. * would it not be more consistent to move DestColorKey
  760. * into local surface structure and not have it be part
  761. * of the optional data.
  762. */
  763. if( !(this_lcl->dwFlags & DDRAWISURF_HASOVERLAYDATA) )
  764. {
  765. DPF_ERR( "Invalid surface for overlay color key" );
  766. LEAVE_DDRAW();
  767. return DDERR_NOTAOVERLAYSURFACE;
  768. }
  769. if( lpDDColorKey == NULL )
  770. {
  771. this_lcl->dwFlags &= ~DDRAWISURF_HASCKEYDESTOVERLAY;
  772. }
  773. else
  774. {
  775. this_lcl->ddckCKDestOverlay = *lpDDColorKey;
  776. this_lcl->dwFlags |= DDRAWISURF_HASCKEYDESTOVERLAY;
  777. }
  778. /*
  779. * Blt dest. key
  780. */
  781. }
  782. else if( dwFlags & DDCKEY_DESTBLT )
  783. {
  784. if( lpDDColorKey == NULL )
  785. {
  786. this_lcl->dwFlags &= ~DDRAWISURF_HASCKEYDESTBLT;
  787. }
  788. else
  789. {
  790. this_lcl->ddckCKDestBlt = *lpDDColorKey;
  791. this_lcl->dwFlags |= DDRAWISURF_HASCKEYDESTBLT;
  792. }
  793. /*
  794. * Overlay src. key
  795. */
  796. }
  797. else if( dwFlags & DDCKEY_SRCOVERLAY )
  798. {
  799. #if 0 // Talisman overlay sprite might not use overlay surface!
  800. if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY ) )
  801. {
  802. DPF_ERR( "SRCOVERLAY specified for a non-overlay surface" );
  803. LEAVE_DDRAW();
  804. return DDERR_NOTAOVERLAYSURFACE;
  805. }
  806. #endif
  807. if( lpDDColorKey == NULL )
  808. {
  809. this_lcl->dwFlags &= ~DDRAWISURF_HASCKEYSRCOVERLAY;
  810. }
  811. else
  812. {
  813. this_lcl->ddckCKSrcOverlay = *lpDDColorKey;
  814. this_lcl->dwFlags |= DDRAWISURF_HASCKEYSRCOVERLAY;
  815. }
  816. /*
  817. * Blt src. key
  818. */
  819. }
  820. else if( dwFlags & DDCKEY_SRCBLT )
  821. {
  822. if( lpDDColorKey == NULL )
  823. {
  824. this_lcl->dwFlags &= ~DDRAWISURF_HASCKEYSRCBLT;
  825. }
  826. else
  827. {
  828. this_lcl->ddckCKSrcBlt = *lpDDColorKey;
  829. this_lcl->dwFlags |= DDRAWISURF_HASCKEYSRCBLT;
  830. }
  831. }
  832. }
  833. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  834. {
  835. DPF_ERR( "Exception encountered validating parameters" );
  836. LEAVE_DDRAW();
  837. return DDERR_INVALIDPARAMS;
  838. }
  839. /*
  840. * add in extra flags
  841. */
  842. this_lcl->dwFlags |= sflags;
  843. /*
  844. * notify the HAL/HEL
  845. */
  846. if( helonly ) // Color key valid only in emulation?
  847. {
  848. sckfn = pdrv_lcl->lpDDCB->HELDDSurface.SetColorKey;
  849. sckhalfn = sckfn;
  850. }
  851. else
  852. {
  853. sckfn = pdrv_lcl->lpDDCB->HALDDSurface.SetColorKey;
  854. sckhalfn = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.SetColorKey;
  855. }
  856. /*
  857. * This next part is a hack, but it should be safe. It is legal for
  858. * them to pass a NULL lpDDColorKey, meaning that they want to stop
  859. * colorkeying. The only problem is that there's no way to pass this
  860. * into the HAL since we always pass them a colorkey structure.
  861. * Therefore, we will not call the HAL/HEL when this is the case. The
  862. * only problem w/ this is an overlay surface will need to know this now,
  863. * so we will call UpdateOverlay in that case.
  864. */
  865. if( lpDDColorKey == NULL )
  866. {
  867. if( dwFlags & ( DDCKEY_DESTOVERLAY | DDCKEY_SRCOVERLAY ) )
  868. {
  869. if( dwFlags & DDCKEY_DESTOVERLAY )
  870. {
  871. this_lcl->lpSurfMore->dwOverlayFlags &= ~(DDOVER_KEYDEST|DDOVER_KEYDESTOVERRIDE);
  872. }
  873. else
  874. {
  875. this_lcl->lpSurfMore->dwOverlayFlags &= ~(DDOVER_KEYSRC|DDOVER_KEYSRCOVERRIDE);
  876. }
  877. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_VISIBLE )
  878. {
  879. if( ( this_lcl->lpSurfMore->dwOverlayFlags & DDOVER_DDFX ) &&
  880. ( this_lcl->lpSurfMore->lpddOverlayFX != NULL ) )
  881. {
  882. DD_Surface_UpdateOverlay(
  883. (LPDIRECTDRAWSURFACE) this_int,
  884. &(this_lcl->rcOverlaySrc),
  885. (LPDIRECTDRAWSURFACE) this_lcl->lpSurfaceOverlaying,
  886. &(this_lcl->rcOverlayDest),
  887. this_lcl->lpSurfMore->dwOverlayFlags,
  888. this_lcl->lpSurfMore->lpddOverlayFX );
  889. }
  890. else
  891. {
  892. DD_Surface_UpdateOverlay(
  893. (LPDIRECTDRAWSURFACE) this_int,
  894. &(this_lcl->rcOverlaySrc),
  895. (LPDIRECTDRAWSURFACE) this_lcl->lpSurfaceOverlaying,
  896. &(this_lcl->rcOverlayDest),
  897. this_lcl->lpSurfMore->dwOverlayFlags,
  898. NULL );
  899. }
  900. }
  901. }
  902. LEAVE_DDRAW();
  903. return DD_OK;
  904. }
  905. ddrval = DD_OK;
  906. if( sckhalfn != NULL )
  907. {
  908. sckd.SetColorKey = sckhalfn;
  909. sckd.lpDD = pdrv;
  910. sckd.lpDDSurface = this_lcl;
  911. sckd.ckNew = *lpDDColorKey;
  912. sckd.dwFlags = dwFlags;
  913. DOHALCALL( SetColorKey, sckfn, sckd, rc, helonly );
  914. if( rc == DDHAL_DRIVER_HANDLED )
  915. {
  916. if( sckd.ddRVal != DD_OK )
  917. {
  918. DPF_ERR( "HAL/HEL call failed" );
  919. ddrval = sckd.ddRVal;
  920. }
  921. }
  922. else if( rc == DDHAL_DRIVER_NOCKEYHW )
  923. {
  924. if( dwFlags & DDCKEY_SRCBLT )
  925. {
  926. ddrval = ChangeToSoftwareColorKey( this_int, TRUE );
  927. if( ddrval != DD_OK )
  928. {
  929. DPF_ERR( "hardware resources are out & can't move to system memory" );
  930. ddrval = DDERR_NOCOLORKEYHW;
  931. }
  932. }
  933. else
  934. {
  935. ddrval = DDERR_UNSUPPORTED;
  936. }
  937. }
  938. }
  939. else
  940. {
  941. /*
  942. * This is really only a problem when setting an overlay colorkey
  943. * and the overlay is already coloerkeying; otherwise, the
  944. * colorkey is set in the LCL and will be used the next time
  945. * the overlay or blt is called.
  946. */
  947. if( dwFlags & DDCKEY_SRCOVERLAY )
  948. {
  949. if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_VISIBLE ) &&
  950. ( this_lcl->lpSurfMore->dwOverlayFlags &
  951. ( DDOVER_KEYSRC | DDOVER_KEYSRCOVERRIDE ) ) )
  952. {
  953. ddrval = DDERR_UNSUPPORTED;
  954. }
  955. }
  956. /*
  957. * NOTE: We'd like to do the same for dest overlay, but:
  958. * 1) We don't see much usefulness in it since apps probably
  959. * will not be changing the dest colorkey on the fly.
  960. * 2) Since dest colorkeying is used a lot, changing the behavior
  961. * might break someone.
  962. * smac and jeffno 3/11/97
  963. */
  964. }
  965. /*
  966. * Restore old values if a failure occurs
  967. */
  968. if( ddrval != DD_OK )
  969. {
  970. this_lcl->dwFlags = oldflags;
  971. this_lcl->ddckCKSrcBlt = ddckOldSrcBlt;
  972. this_lcl->ddckCKDestBlt = ddckOldDestBlt;
  973. this_lcl->ddckCKSrcOverlay = ddckOldSrcOverlay;
  974. this_lcl->ddckCKDestOverlay = ddckOldDestOverlay;
  975. }
  976. LEAVE_DDRAW();
  977. return ddrval;
  978. } /* DD_Surface_SetColorKey */