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

/*==========================================================================
* Copyright (C) 1998 Microsoft Corporation. All Rights Reserved.
*
* File: ddgamma.c
* Content: Implements the DirectDrawGammaControl interface, which
* allows controlling the gamma for the primary surface.
* History:
* Date By Reason
* ==== == ======
* 05-mar-98 smac created
*
***************************************************************************/
#include "ddrawpr.h"
#ifdef WINNT
#include "ddrawgdi.h"
#endif
#define DPF_MODNAME "DirectDrawGammaControl"
#define DISPLAY_STR "display"
/*
* InitGamma
*
* Called while initializing the DDraw object. It determines whether the
* driver can support loadable gamma ramps and if so, it sets the
* DDCAPS2_PRIMARYGAMMA cap bit.
*/
VOID InitGamma( LPDDRAWI_DIRECTDRAW_GBL pdrv, LPSTR szDrvName )
{
/*
* In NT, we set the DDCAPS2_PRIMARYGAMMA cap in kernel mode, but on Win9X
* we just call GetDeviceGammaRamp and if it works, we assume that the device
* supports gamma. However, GetDeviceGammaRamp was obviously not well tested
* in Win9X because GDI calls a NULL pointer in some instances where the driver
* doesn't support downloadable gamma ramps. The only way to work around
* this is to look at the HDC and detect the situations that crash
* and then know not to attemp gamma in those situations. We have to do
* this in DDRAW16.
*/
#ifdef WIN95
LPWORD lpGammaRamp;
HDC hdc;
pdrv->ddCaps.dwCaps2 &= ~DDCAPS2_PRIMARYGAMMA;
lpGammaRamp = (LPWORD) LocalAlloc( LMEM_FIXED, sizeof( DDGAMMARAMP ) );
if( NULL != lpGammaRamp )
{
hdc = DD_CreateDC( szDrvName );
if( DD16_AttemptGamma(hdc) &&
GetDeviceGammaRamp( hdc, lpGammaRamp ) )
{
pdrv->ddCaps.dwCaps2 |= DDCAPS2_PRIMARYGAMMA;
}
DD_DoneDC( hdc );
LocalFree( (HLOCAL) lpGammaRamp );
}
#endif
if( bGammaCalibratorExists &&
( pdrv->ddCaps.dwCaps2 & DDCAPS2_PRIMARYGAMMA ) )
{
pdrv->ddCaps.dwCaps2 |= DDCAPS2_CANCALIBRATEGAMMA;
}
else
{
pdrv->ddCaps.dwCaps2 &= ~DDCAPS2_CANCALIBRATEGAMMA;
}
}
/*
* SetGamma
*
* Sets the new GammaRamp. If it is being set for the first time, we will
* save the old gamma ramp so we can restore it later.
*/
BOOL SetGamma( LPDDRAWI_DDRAWSURFACE_LCL this_lcl, LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
{
BOOL bRet = TRUE;
if( !( this_lcl->dwFlags & DDRAWISURF_SETGAMMA ) )
{
bRet = GetDeviceGammaRamp( (HDC) pdrv_lcl->hDC,
this_lcl->lpSurfMore->lpOriginalGammaRamp );
}
if( bRet )
{
#ifdef WINNT
bRet = DdSetGammaRamp( pdrv_lcl, (HDC) pdrv_lcl->hDC,
this_lcl->lpSurfMore->lpGammaRamp);
#else
bRet = SetDeviceGammaRamp( (HDC) pdrv_lcl->hDC,
this_lcl->lpSurfMore->lpGammaRamp );
#endif
this_lcl->dwFlags |= DDRAWISURF_SETGAMMA;
}
if( !bRet )
{
return DDERR_UNSUPPORTED;
}
return DD_OK;
}
/*
* RestoreGamma
*
* Restores the old GammaRamp.
*/
VOID RestoreGamma( LPDDRAWI_DDRAWSURFACE_LCL this_lcl, LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
{
BOOL bRet;
HDC hdcTemp = NULL;
/*
* If we are on DDHELP's thread cleaning up, then pdrv_lcl->hDC
* will be invalid. In this case, we need to temporarily create
* a new DC to use.
*/
if( ( pdrv_lcl->dwProcessId != GetCurrentProcessId() ) &&
( this_lcl->dwFlags & DDRAWISURF_SETGAMMA ) )
{
hdcTemp = (HDC) pdrv_lcl->hDC;
if( _stricmp( pdrv_lcl->lpGbl->cDriverName, DISPLAY_STR ) == 0 )
{
(HDC) pdrv_lcl->hDC = DD_CreateDC( g_szPrimaryDisplay );
}
else
{
(HDC) pdrv_lcl->hDC = DD_CreateDC( pdrv_lcl->lpGbl->cDriverName );
}
}
if( ( this_lcl->dwFlags & DDRAWISURF_SETGAMMA ) &&
( this_lcl->lpSurfMore->lpOriginalGammaRamp != NULL ))
{
#ifdef WINNT
bRet = DdSetGammaRamp( pdrv_lcl, (HDC) pdrv_lcl->hDC,
this_lcl->lpSurfMore->lpOriginalGammaRamp);
#else
bRet = SetDeviceGammaRamp( (HDC) pdrv_lcl->hDC,
this_lcl->lpSurfMore->lpOriginalGammaRamp );
#endif
}
this_lcl->dwFlags &= ~DDRAWISURF_SETGAMMA;
if( hdcTemp != NULL )
{
DD_DoneDC( (HDC) pdrv_lcl->hDC );
(HDC) pdrv_lcl->hDC = hdcTemp;
}
}
/*
* ReleaseGammaControl
*/
VOID ReleaseGammaControl( LPDDRAWI_DDRAWSURFACE_LCL lpSurface )
{
RestoreGamma( lpSurface, lpSurface->lpSurfMore->lpDD_lcl );
if( lpSurface->lpSurfMore->lpGammaRamp != NULL )
{
MemFree( lpSurface->lpSurfMore->lpGammaRamp );
lpSurface->lpSurfMore->lpGammaRamp = NULL;
}
if( lpSurface->lpSurfMore->lpOriginalGammaRamp != NULL )
{
MemFree( lpSurface->lpSurfMore->lpOriginalGammaRamp );
lpSurface->lpSurfMore->lpOriginalGammaRamp = NULL;
}
}
/*
* DD_Gamma_GetGammaControls
*/
HRESULT DDAPI DD_Gamma_GetGammaRamp(LPDIRECTDRAWGAMMACONTROL lpDDGC,
DWORD dwFlags, LPDDGAMMARAMP lpGammaRamp)
{
LPDDRAWI_DDRAWSURFACE_INT this_int;
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
LPDDRAWI_DDRAWSURFACE_MORE lpSurfMore;
BOOL bRet;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Gamma_GetGammaRamp");
/*
* Validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDGC;
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
lpSurfMore = this_lcl->lpSurfMore;
if( (lpGammaRamp == NULL) || !VALID_BYTE_ARRAY( lpGammaRamp,
sizeof( DDGAMMARAMP ) ) )
{
DPF_ERR("DD_Gamma_GetGammaRamp: Invalid gamma table specified");
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( dwFlags )
{
DPF_ERR("DD_Gamma_GetGammaRamp: Invalid flags specified");
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* For now, only support setting the gamma for the primary surface
*/
if( !( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) )
{
DPF_ERR("DD_Gamma_GetGammaRamp: Must specify primary surface");
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( !( pdrv_lcl->lpGbl->ddCaps.dwCaps2 & DDCAPS2_PRIMARYGAMMA ) )
{
DPF_ERR("DD_Gamma_GetGammaRamp: Device deos not support gamma ramps");
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( SURFACE_LOST( this_lcl ) )
{
DPF_ERR("DD_Gamma_GetGammaRamp: Secified surface has been lost");
LEAVE_DDRAW();
return DDERR_SURFACELOST;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_EXCEPTION;
}
/*
* If a gamma table has been set, return it; otherwise, get it from
* the driver.
*/
if( lpSurfMore->lpGammaRamp != NULL )
{
memcpy( lpGammaRamp, lpSurfMore->lpGammaRamp, sizeof( DDGAMMARAMP ) );
}
else
{
bRet = GetDeviceGammaRamp( (HDC) pdrv_lcl->hDC, (LPVOID) lpGammaRamp );
if( bRet == FALSE )
{
DPF_ERR("DD_Gamma_GetGammaRamp: GetDeviceGammaRamp failed");
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
}
LEAVE_DDRAW();
return DD_OK;
}
/*
* LoadGammaCalibrator
*/
VOID LoadGammaCalibrator( LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
{
DDASSERT( pdrv_lcl->hGammaCalibrator == (ULONG_PTR) INVALID_HANDLE_VALUE );
pdrv_lcl->hGammaCalibrator = (ULONG_PTR) LoadLibrary( szGammaCalibrator );
if( pdrv_lcl->hGammaCalibrator != (ULONG_PTR) NULL )
{
pdrv_lcl->lpGammaCalibrator = (LPDDGAMMACALIBRATORPROC)
GetProcAddress( (HANDLE)(pdrv_lcl->hGammaCalibrator), "CalibrateGammaRamp" );
if( pdrv_lcl->lpGammaCalibrator == (ULONG_PTR) NULL )
{
FreeLibrary( (HMODULE) pdrv_lcl->hGammaCalibrator );
pdrv_lcl->hGammaCalibrator = (ULONG_PTR) INVALID_HANDLE_VALUE;
}
}
else
{
pdrv_lcl->hGammaCalibrator = (ULONG_PTR) INVALID_HANDLE_VALUE;
}
}
/*
* DD_Gamma_SetGammaRamp
*/
HRESULT DDAPI DD_Gamma_SetGammaRamp(LPDIRECTDRAWGAMMACONTROL lpDDGC,
DWORD dwFlags, LPDDGAMMARAMP lpGammaRamp)
{
LPDDRAWI_DDRAWSURFACE_INT this_int;
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
LPDDRAWI_DDRAWSURFACE_MORE lpSurfMore;
LPDDGAMMARAMP lpTempRamp=NULL;
HRESULT ddRVal;
DWORD rc;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Gamma_SetGammaRamp");
/*
* Validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDGC;
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
lpSurfMore = this_lcl->lpSurfMore;
if( (lpGammaRamp != NULL) && !VALID_BYTE_ARRAY( lpGammaRamp,
sizeof( DDGAMMARAMP ) ) )
{
DPF_ERR("DD_Gamma_SetGammaRamp: Invalid gamma table specified");
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( dwFlags & ~DDSGR_VALID )
{
DPF_ERR("DD_Gamma_SetGammaRamp: Invalid flag specified");
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( ( dwFlags & DDSGR_CALIBRATE ) && !bGammaCalibratorExists )
{
DPF_ERR("DD_Gamma_SetGammaRamp: DDSGR_CALIBRATE unsupported - Gamma calibrator not installed");
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
/*
* For now, only support setting the gamma for the primary surface
*/
if( !( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) )
{
DPF_ERR("DD_Gamma_SetGammaRamp: Must specify primary surface");
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( !( pdrv_lcl->lpGbl->ddCaps.dwCaps2 & DDCAPS2_PRIMARYGAMMA ) )
{
DPF_ERR("DD_Gamma_SetGammaRamp: Device deos not support gamma ramps");
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( SURFACE_LOST( this_lcl ) )
{
DPF_ERR("DD_Gamma_SetGammaRamp: Secified surface has been lost");
LEAVE_DDRAW();
return DDERR_SURFACELOST;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_EXCEPTION;
}
/*
* lpGammaRamp is NULL, they are trying to restore the gamma.
*/
if( lpGammaRamp == NULL )
{
ReleaseGammaControl( this_lcl );
}
else
{
/*
* If they want to calibrate the gamma, we will do that now. We will
* copy this to a different buffer so that we don't mess up the one
* passed in to us.
*/
if( dwFlags & DDSGR_CALIBRATE )
{
/*
* If the calibrator isn't loaded, do so now.
*/
if( pdrv_lcl->hGammaCalibrator == (ULONG_PTR) INVALID_HANDLE_VALUE )
{
LoadGammaCalibrator( pdrv_lcl );
}
if( ( pdrv_lcl->hGammaCalibrator == (ULONG_PTR) INVALID_HANDLE_VALUE ) ||
( pdrv_lcl->lpGammaCalibrator == (ULONG_PTR) NULL ) )
{
/*
* If we were unable to load the library correctly,
* we shouldn't try again later.
*/
bGammaCalibratorExists = FALSE;
DPF_ERR("DD_Gamma_SetGammaRamp: Unable to load gamma calibrator");
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
else
{
/*
* Call the calibrator to let it do it's thing. First
* need to copy the buffer over so we don't mess with
* the one passed in.
*/
lpTempRamp = (LPDDGAMMARAMP) LocalAlloc( LMEM_FIXED,
sizeof( DDGAMMARAMP ) );
if( lpTempRamp == NULL )
{
DPF_ERR("DD_Gamma_SetGammaRamp: Insuficient memory for gamma ramps");
LEAVE_DDRAW();
return DDERR_OUTOFMEMORY;
}
memcpy( lpTempRamp, lpGammaRamp, sizeof( DDGAMMARAMP ) );
lpGammaRamp = lpTempRamp;
ddRVal = pdrv_lcl->lpGammaCalibrator( lpGammaRamp, pdrv_lcl->lpGbl->cDriverName );
if( ddRVal != DD_OK )
{
DPF_ERR("DD_Gamma_SetGammaRamp: Calibrator failed the call");
LocalFree( (HLOCAL) lpTempRamp );
LEAVE_DDRAW();
return ddRVal;
}
}
}
/*
* If we are setting this for the first time, allocate memory to hold
* the gamma ramps
*/
if( lpSurfMore->lpOriginalGammaRamp == NULL )
{
lpSurfMore->lpOriginalGammaRamp = MemAlloc( sizeof( DDGAMMARAMP ) );
}
if( lpSurfMore->lpGammaRamp == NULL )
{
lpSurfMore->lpGammaRamp = MemAlloc( sizeof( DDGAMMARAMP ) );
}
/*
* If we are in exlusive mode now, set the gamma ramp now; otherwise,
* we'll let it get set when we enter excluisve mode.
*/
if( lpSurfMore->lpGammaRamp && lpSurfMore->lpOriginalGammaRamp )
{
memcpy( lpSurfMore->lpGammaRamp, lpGammaRamp, sizeof( DDGAMMARAMP ) );
if( pdrv_lcl->dwLocalFlags & DDRAWILCL_HASEXCLUSIVEMODE )
{
SetGamma( this_lcl, pdrv_lcl );
}
if( lpTempRamp != NULL )
{
LocalFree( (HLOCAL) lpTempRamp );
}
}
else
{
/*
* Out of memory condition. Release the two ramps
*/
if( lpTempRamp != NULL )
{
LocalFree( (HLOCAL) lpTempRamp );
}
if( lpSurfMore->lpGammaRamp != NULL )
{
MemFree( lpSurfMore->lpGammaRamp );
lpSurfMore->lpGammaRamp = NULL;
}
if( lpSurfMore->lpOriginalGammaRamp != NULL )
{
MemFree( lpSurfMore->lpOriginalGammaRamp );
lpSurfMore->lpOriginalGammaRamp = NULL;
}
DPF_ERR("DD_Gamma_SetGammaRamp: Insuficient memory for gamma ramps");
LEAVE_DDRAW();
return DDERR_OUTOFMEMORY;
}
}
LEAVE_DDRAW();
return DD_OK;
}