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.

499 lines
15 KiB

  1. /*==========================================================================
  2. * Copyright (C) 1998 Microsoft Corporation. All Rights Reserved.
  3. *
  4. * File: ddgamma.c
  5. * Content: Implements the DirectDrawGammaControl interface, which
  6. * allows controlling the gamma for the primary surface.
  7. * History:
  8. * Date By Reason
  9. * ==== == ======
  10. * 05-mar-98 smac created
  11. *
  12. ***************************************************************************/
  13. #include "ddrawpr.h"
  14. #ifdef WINNT
  15. #include "ddrawgdi.h"
  16. #endif
  17. #define DPF_MODNAME "DirectDrawGammaControl"
  18. #define DISPLAY_STR "display"
  19. /*
  20. * InitGamma
  21. *
  22. * Called while initializing the DDraw object. It determines whether the
  23. * driver can support loadable gamma ramps and if so, it sets the
  24. * DDCAPS2_PRIMARYGAMMA cap bit.
  25. */
  26. VOID InitGamma( LPDDRAWI_DIRECTDRAW_GBL pdrv, LPSTR szDrvName )
  27. {
  28. /*
  29. * In NT, we set the DDCAPS2_PRIMARYGAMMA cap in kernel mode, but on Win9X
  30. * we just call GetDeviceGammaRamp and if it works, we assume that the device
  31. * supports gamma. However, GetDeviceGammaRamp was obviously not well tested
  32. * in Win9X because GDI calls a NULL pointer in some instances where the driver
  33. * doesn't support downloadable gamma ramps. The only way to work around
  34. * this is to look at the HDC and detect the situations that crash
  35. * and then know not to attemp gamma in those situations. We have to do
  36. * this in DDRAW16.
  37. */
  38. #ifdef WIN95
  39. LPWORD lpGammaRamp;
  40. HDC hdc;
  41. pdrv->ddCaps.dwCaps2 &= ~DDCAPS2_PRIMARYGAMMA;
  42. lpGammaRamp = (LPWORD) LocalAlloc( LMEM_FIXED, sizeof( DDGAMMARAMP ) );
  43. if( NULL != lpGammaRamp )
  44. {
  45. hdc = DD_CreateDC( szDrvName );
  46. if( DD16_AttemptGamma(hdc) &&
  47. GetDeviceGammaRamp( hdc, lpGammaRamp ) )
  48. {
  49. pdrv->ddCaps.dwCaps2 |= DDCAPS2_PRIMARYGAMMA;
  50. }
  51. DD_DoneDC( hdc );
  52. LocalFree( (HLOCAL) lpGammaRamp );
  53. }
  54. #endif
  55. if( bGammaCalibratorExists &&
  56. ( pdrv->ddCaps.dwCaps2 & DDCAPS2_PRIMARYGAMMA ) )
  57. {
  58. pdrv->ddCaps.dwCaps2 |= DDCAPS2_CANCALIBRATEGAMMA;
  59. }
  60. else
  61. {
  62. pdrv->ddCaps.dwCaps2 &= ~DDCAPS2_CANCALIBRATEGAMMA;
  63. }
  64. }
  65. /*
  66. * SetGamma
  67. *
  68. * Sets the new GammaRamp. If it is being set for the first time, we will
  69. * save the old gamma ramp so we can restore it later.
  70. */
  71. BOOL SetGamma( LPDDRAWI_DDRAWSURFACE_LCL this_lcl, LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
  72. {
  73. BOOL bRet = TRUE;
  74. if( !( this_lcl->dwFlags & DDRAWISURF_SETGAMMA ) )
  75. {
  76. bRet = GetDeviceGammaRamp( (HDC) pdrv_lcl->hDC,
  77. this_lcl->lpSurfMore->lpOriginalGammaRamp );
  78. }
  79. if( bRet )
  80. {
  81. #ifdef WINNT
  82. bRet = DdSetGammaRamp( pdrv_lcl, (HDC) pdrv_lcl->hDC,
  83. this_lcl->lpSurfMore->lpGammaRamp);
  84. #else
  85. bRet = SetDeviceGammaRamp( (HDC) pdrv_lcl->hDC,
  86. this_lcl->lpSurfMore->lpGammaRamp );
  87. #endif
  88. this_lcl->dwFlags |= DDRAWISURF_SETGAMMA;
  89. }
  90. if( !bRet )
  91. {
  92. return DDERR_UNSUPPORTED;
  93. }
  94. return DD_OK;
  95. }
  96. /*
  97. * RestoreGamma
  98. *
  99. * Restores the old GammaRamp.
  100. */
  101. VOID RestoreGamma( LPDDRAWI_DDRAWSURFACE_LCL this_lcl, LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
  102. {
  103. BOOL bRet;
  104. HDC hdcTemp = NULL;
  105. /*
  106. * If we are on DDHELP's thread cleaning up, then pdrv_lcl->hDC
  107. * will be invalid. In this case, we need to temporarily create
  108. * a new DC to use.
  109. */
  110. if( ( pdrv_lcl->dwProcessId != GetCurrentProcessId() ) &&
  111. ( this_lcl->dwFlags & DDRAWISURF_SETGAMMA ) )
  112. {
  113. hdcTemp = (HDC) pdrv_lcl->hDC;
  114. if( _stricmp( pdrv_lcl->lpGbl->cDriverName, DISPLAY_STR ) == 0 )
  115. {
  116. (HDC) pdrv_lcl->hDC = DD_CreateDC( g_szPrimaryDisplay );
  117. }
  118. else
  119. {
  120. (HDC) pdrv_lcl->hDC = DD_CreateDC( pdrv_lcl->lpGbl->cDriverName );
  121. }
  122. }
  123. if( ( this_lcl->dwFlags & DDRAWISURF_SETGAMMA ) &&
  124. ( this_lcl->lpSurfMore->lpOriginalGammaRamp != NULL ))
  125. {
  126. #ifdef WINNT
  127. bRet = DdSetGammaRamp( pdrv_lcl, (HDC) pdrv_lcl->hDC,
  128. this_lcl->lpSurfMore->lpOriginalGammaRamp);
  129. #else
  130. bRet = SetDeviceGammaRamp( (HDC) pdrv_lcl->hDC,
  131. this_lcl->lpSurfMore->lpOriginalGammaRamp );
  132. #endif
  133. }
  134. this_lcl->dwFlags &= ~DDRAWISURF_SETGAMMA;
  135. if( hdcTemp != NULL )
  136. {
  137. DD_DoneDC( (HDC) pdrv_lcl->hDC );
  138. (HDC) pdrv_lcl->hDC = hdcTemp;
  139. }
  140. }
  141. /*
  142. * ReleaseGammaControl
  143. */
  144. VOID ReleaseGammaControl( LPDDRAWI_DDRAWSURFACE_LCL lpSurface )
  145. {
  146. RestoreGamma( lpSurface, lpSurface->lpSurfMore->lpDD_lcl );
  147. if( lpSurface->lpSurfMore->lpGammaRamp != NULL )
  148. {
  149. MemFree( lpSurface->lpSurfMore->lpGammaRamp );
  150. lpSurface->lpSurfMore->lpGammaRamp = NULL;
  151. }
  152. if( lpSurface->lpSurfMore->lpOriginalGammaRamp != NULL )
  153. {
  154. MemFree( lpSurface->lpSurfMore->lpOriginalGammaRamp );
  155. lpSurface->lpSurfMore->lpOriginalGammaRamp = NULL;
  156. }
  157. }
  158. /*
  159. * DD_Gamma_GetGammaControls
  160. */
  161. HRESULT DDAPI DD_Gamma_GetGammaRamp(LPDIRECTDRAWGAMMACONTROL lpDDGC,
  162. DWORD dwFlags, LPDDGAMMARAMP lpGammaRamp)
  163. {
  164. LPDDRAWI_DDRAWSURFACE_INT this_int;
  165. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  166. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  167. LPDDRAWI_DDRAWSURFACE_MORE lpSurfMore;
  168. BOOL bRet;
  169. ENTER_DDRAW();
  170. DPF(2,A,"ENTERAPI: DD_Gamma_GetGammaRamp");
  171. /*
  172. * Validate parameters
  173. */
  174. TRY
  175. {
  176. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDGC;
  177. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  178. {
  179. LEAVE_DDRAW();
  180. return DDERR_INVALIDOBJECT;
  181. }
  182. this_lcl = this_int->lpLcl;
  183. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  184. lpSurfMore = this_lcl->lpSurfMore;
  185. if( (lpGammaRamp == NULL) || !VALID_BYTE_ARRAY( lpGammaRamp,
  186. sizeof( DDGAMMARAMP ) ) )
  187. {
  188. DPF_ERR("DD_Gamma_GetGammaRamp: Invalid gamma table specified");
  189. LEAVE_DDRAW();
  190. return DDERR_INVALIDPARAMS;
  191. }
  192. if( dwFlags )
  193. {
  194. DPF_ERR("DD_Gamma_GetGammaRamp: Invalid flags specified");
  195. LEAVE_DDRAW();
  196. return DDERR_INVALIDPARAMS;
  197. }
  198. /*
  199. * For now, only support setting the gamma for the primary surface
  200. */
  201. if( !( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) )
  202. {
  203. DPF_ERR("DD_Gamma_GetGammaRamp: Must specify primary surface");
  204. LEAVE_DDRAW();
  205. return DDERR_INVALIDPARAMS;
  206. }
  207. if( !( pdrv_lcl->lpGbl->ddCaps.dwCaps2 & DDCAPS2_PRIMARYGAMMA ) )
  208. {
  209. DPF_ERR("DD_Gamma_GetGammaRamp: Device deos not support gamma ramps");
  210. LEAVE_DDRAW();
  211. return DDERR_INVALIDPARAMS;
  212. }
  213. if( SURFACE_LOST( this_lcl ) )
  214. {
  215. DPF_ERR("DD_Gamma_GetGammaRamp: Secified surface has been lost");
  216. LEAVE_DDRAW();
  217. return DDERR_SURFACELOST;
  218. }
  219. }
  220. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  221. {
  222. DPF_ERR( "Exception encountered validating parameters" );
  223. LEAVE_DDRAW();
  224. return DDERR_EXCEPTION;
  225. }
  226. /*
  227. * If a gamma table has been set, return it; otherwise, get it from
  228. * the driver.
  229. */
  230. if( lpSurfMore->lpGammaRamp != NULL )
  231. {
  232. memcpy( lpGammaRamp, lpSurfMore->lpGammaRamp, sizeof( DDGAMMARAMP ) );
  233. }
  234. else
  235. {
  236. bRet = GetDeviceGammaRamp( (HDC) pdrv_lcl->hDC, (LPVOID) lpGammaRamp );
  237. if( bRet == FALSE )
  238. {
  239. DPF_ERR("DD_Gamma_GetGammaRamp: GetDeviceGammaRamp failed");
  240. LEAVE_DDRAW();
  241. return DDERR_UNSUPPORTED;
  242. }
  243. }
  244. LEAVE_DDRAW();
  245. return DD_OK;
  246. }
  247. /*
  248. * LoadGammaCalibrator
  249. */
  250. VOID LoadGammaCalibrator( LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
  251. {
  252. DDASSERT( pdrv_lcl->hGammaCalibrator == (ULONG_PTR) INVALID_HANDLE_VALUE );
  253. pdrv_lcl->hGammaCalibrator = (ULONG_PTR) LoadLibrary( szGammaCalibrator );
  254. if( pdrv_lcl->hGammaCalibrator != (ULONG_PTR) NULL )
  255. {
  256. pdrv_lcl->lpGammaCalibrator = (LPDDGAMMACALIBRATORPROC)
  257. GetProcAddress( (HANDLE)(pdrv_lcl->hGammaCalibrator), "CalibrateGammaRamp" );
  258. if( pdrv_lcl->lpGammaCalibrator == (ULONG_PTR) NULL )
  259. {
  260. FreeLibrary( (HMODULE) pdrv_lcl->hGammaCalibrator );
  261. pdrv_lcl->hGammaCalibrator = (ULONG_PTR) INVALID_HANDLE_VALUE;
  262. }
  263. }
  264. else
  265. {
  266. pdrv_lcl->hGammaCalibrator = (ULONG_PTR) INVALID_HANDLE_VALUE;
  267. }
  268. }
  269. /*
  270. * DD_Gamma_SetGammaRamp
  271. */
  272. HRESULT DDAPI DD_Gamma_SetGammaRamp(LPDIRECTDRAWGAMMACONTROL lpDDGC,
  273. DWORD dwFlags, LPDDGAMMARAMP lpGammaRamp)
  274. {
  275. LPDDRAWI_DDRAWSURFACE_INT this_int;
  276. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  277. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  278. LPDDRAWI_DDRAWSURFACE_MORE lpSurfMore;
  279. LPDDGAMMARAMP lpTempRamp=NULL;
  280. HRESULT ddRVal;
  281. DWORD rc;
  282. ENTER_DDRAW();
  283. DPF(2,A,"ENTERAPI: DD_Gamma_SetGammaRamp");
  284. /*
  285. * Validate parameters
  286. */
  287. TRY
  288. {
  289. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDGC;
  290. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  291. {
  292. LEAVE_DDRAW();
  293. return DDERR_INVALIDOBJECT;
  294. }
  295. this_lcl = this_int->lpLcl;
  296. pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
  297. lpSurfMore = this_lcl->lpSurfMore;
  298. if( (lpGammaRamp != NULL) && !VALID_BYTE_ARRAY( lpGammaRamp,
  299. sizeof( DDGAMMARAMP ) ) )
  300. {
  301. DPF_ERR("DD_Gamma_SetGammaRamp: Invalid gamma table specified");
  302. LEAVE_DDRAW();
  303. return DDERR_INVALIDPARAMS;
  304. }
  305. if( dwFlags & ~DDSGR_VALID )
  306. {
  307. DPF_ERR("DD_Gamma_SetGammaRamp: Invalid flag specified");
  308. LEAVE_DDRAW();
  309. return DDERR_INVALIDPARAMS;
  310. }
  311. if( ( dwFlags & DDSGR_CALIBRATE ) && !bGammaCalibratorExists )
  312. {
  313. DPF_ERR("DD_Gamma_SetGammaRamp: DDSGR_CALIBRATE unsupported - Gamma calibrator not installed");
  314. LEAVE_DDRAW();
  315. return DDERR_UNSUPPORTED;
  316. }
  317. /*
  318. * For now, only support setting the gamma for the primary surface
  319. */
  320. if( !( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) )
  321. {
  322. DPF_ERR("DD_Gamma_SetGammaRamp: Must specify primary surface");
  323. LEAVE_DDRAW();
  324. return DDERR_INVALIDPARAMS;
  325. }
  326. if( !( pdrv_lcl->lpGbl->ddCaps.dwCaps2 & DDCAPS2_PRIMARYGAMMA ) )
  327. {
  328. DPF_ERR("DD_Gamma_SetGammaRamp: Device deos not support gamma ramps");
  329. LEAVE_DDRAW();
  330. return DDERR_INVALIDPARAMS;
  331. }
  332. if( SURFACE_LOST( this_lcl ) )
  333. {
  334. DPF_ERR("DD_Gamma_SetGammaRamp: Secified surface has been lost");
  335. LEAVE_DDRAW();
  336. return DDERR_SURFACELOST;
  337. }
  338. }
  339. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  340. {
  341. DPF_ERR( "Exception encountered validating parameters" );
  342. LEAVE_DDRAW();
  343. return DDERR_EXCEPTION;
  344. }
  345. /*
  346. * lpGammaRamp is NULL, they are trying to restore the gamma.
  347. */
  348. if( lpGammaRamp == NULL )
  349. {
  350. ReleaseGammaControl( this_lcl );
  351. }
  352. else
  353. {
  354. /*
  355. * If they want to calibrate the gamma, we will do that now. We will
  356. * copy this to a different buffer so that we don't mess up the one
  357. * passed in to us.
  358. */
  359. if( dwFlags & DDSGR_CALIBRATE )
  360. {
  361. /*
  362. * If the calibrator isn't loaded, do so now.
  363. */
  364. if( pdrv_lcl->hGammaCalibrator == (ULONG_PTR) INVALID_HANDLE_VALUE )
  365. {
  366. LoadGammaCalibrator( pdrv_lcl );
  367. }
  368. if( ( pdrv_lcl->hGammaCalibrator == (ULONG_PTR) INVALID_HANDLE_VALUE ) ||
  369. ( pdrv_lcl->lpGammaCalibrator == (ULONG_PTR) NULL ) )
  370. {
  371. /*
  372. * If we were unable to load the library correctly,
  373. * we shouldn't try again later.
  374. */
  375. bGammaCalibratorExists = FALSE;
  376. DPF_ERR("DD_Gamma_SetGammaRamp: Unable to load gamma calibrator");
  377. LEAVE_DDRAW();
  378. return DDERR_UNSUPPORTED;
  379. }
  380. else
  381. {
  382. /*
  383. * Call the calibrator to let it do it's thing. First
  384. * need to copy the buffer over so we don't mess with
  385. * the one passed in.
  386. */
  387. lpTempRamp = (LPDDGAMMARAMP) LocalAlloc( LMEM_FIXED,
  388. sizeof( DDGAMMARAMP ) );
  389. if( lpTempRamp == NULL )
  390. {
  391. DPF_ERR("DD_Gamma_SetGammaRamp: Insuficient memory for gamma ramps");
  392. LEAVE_DDRAW();
  393. return DDERR_OUTOFMEMORY;
  394. }
  395. memcpy( lpTempRamp, lpGammaRamp, sizeof( DDGAMMARAMP ) );
  396. lpGammaRamp = lpTempRamp;
  397. ddRVal = pdrv_lcl->lpGammaCalibrator( lpGammaRamp, pdrv_lcl->lpGbl->cDriverName );
  398. if( ddRVal != DD_OK )
  399. {
  400. DPF_ERR("DD_Gamma_SetGammaRamp: Calibrator failed the call");
  401. LocalFree( (HLOCAL) lpTempRamp );
  402. LEAVE_DDRAW();
  403. return ddRVal;
  404. }
  405. }
  406. }
  407. /*
  408. * If we are setting this for the first time, allocate memory to hold
  409. * the gamma ramps
  410. */
  411. if( lpSurfMore->lpOriginalGammaRamp == NULL )
  412. {
  413. lpSurfMore->lpOriginalGammaRamp = MemAlloc( sizeof( DDGAMMARAMP ) );
  414. }
  415. if( lpSurfMore->lpGammaRamp == NULL )
  416. {
  417. lpSurfMore->lpGammaRamp = MemAlloc( sizeof( DDGAMMARAMP ) );
  418. }
  419. /*
  420. * If we are in exlusive mode now, set the gamma ramp now; otherwise,
  421. * we'll let it get set when we enter excluisve mode.
  422. */
  423. if( lpSurfMore->lpGammaRamp && lpSurfMore->lpOriginalGammaRamp )
  424. {
  425. memcpy( lpSurfMore->lpGammaRamp, lpGammaRamp, sizeof( DDGAMMARAMP ) );
  426. if( pdrv_lcl->dwLocalFlags & DDRAWILCL_HASEXCLUSIVEMODE )
  427. {
  428. SetGamma( this_lcl, pdrv_lcl );
  429. }
  430. if( lpTempRamp != NULL )
  431. {
  432. LocalFree( (HLOCAL) lpTempRamp );
  433. }
  434. }
  435. else
  436. {
  437. /*
  438. * Out of memory condition. Release the two ramps
  439. */
  440. if( lpTempRamp != NULL )
  441. {
  442. LocalFree( (HLOCAL) lpTempRamp );
  443. }
  444. if( lpSurfMore->lpGammaRamp != NULL )
  445. {
  446. MemFree( lpSurfMore->lpGammaRamp );
  447. lpSurfMore->lpGammaRamp = NULL;
  448. }
  449. if( lpSurfMore->lpOriginalGammaRamp != NULL )
  450. {
  451. MemFree( lpSurfMore->lpOriginalGammaRamp );
  452. lpSurfMore->lpOriginalGammaRamp = NULL;
  453. }
  454. DPF_ERR("DD_Gamma_SetGammaRamp: Insuficient memory for gamma ramps");
  455. LEAVE_DDRAW();
  456. return DDERR_OUTOFMEMORY;
  457. }
  458. }
  459. LEAVE_DDRAW();
  460. return DD_OK;
  461. }