reactos/subsystems/win32/win32k/objects/icm.c
Amine Khaldi c424146e2c Create a branch for cmake bringup.
svn path=/branches/cmake-bringup/; revision=48236
2010-07-24 18:52:44 +00:00

439 lines
10 KiB
C

/*
* ReactOS W32 Subsystem
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <win32k.h>
#define NDEBUG
#include <debug.h>
HCOLORSPACE hStockColorSpace = NULL;
HCOLORSPACE
FASTCALL
IntGdiCreateColorSpace(
PLOGCOLORSPACEEXW pLogColorSpace)
{
PCOLORSPACE pCS;
HCOLORSPACE hCS;
pCS = COLORSPACEOBJ_AllocCSWithHandle();
hCS = pCS->BaseObject.hHmgr;
pCS->lcsColorSpace = pLogColorSpace->lcsColorSpace;
pCS->dwFlags = pLogColorSpace->dwFlags;
COLORSPACEOBJ_UnlockCS(pCS);
return hCS;
}
BOOL
FASTCALL
IntGdiDeleteColorSpace(
HCOLORSPACE hColorSpace)
{
BOOL Ret = FALSE;
if ( hColorSpace != hStockColorSpace )
{
Ret = COLORSPACEOBJ_FreeCSByHandle(hColorSpace);
if ( !Ret ) SetLastWin32Error(ERROR_INVALID_PARAMETER);
}
return Ret;
}
HANDLE
APIENTRY
NtGdiCreateColorSpace(
IN PLOGCOLORSPACEEXW pLogColorSpace)
{
LOGCOLORSPACEEXW Safelcs;
NTSTATUS Status = STATUS_SUCCESS;
_SEH2_TRY
{
ProbeForRead( pLogColorSpace,
sizeof(LOGCOLORSPACEEXW),
1);
RtlCopyMemory(&Safelcs, pLogColorSpace, sizeof(LOGCOLORSPACEEXW));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
return NULL;
}
return IntGdiCreateColorSpace(&Safelcs);
}
BOOL
APIENTRY
NtGdiDeleteColorSpace(
IN HANDLE hColorSpace)
{
return IntGdiDeleteColorSpace(hColorSpace);
}
BOOL
FASTCALL
IntGetDeviceGammaRamp(HDEV hPDev, PGAMMARAMP Ramp)
{
PPDEVOBJ pGDev = (PPDEVOBJ) hPDev;
int i;
if (!(pGDev->flFlags & PDEV_DISPLAY )) return FALSE;
if ((pGDev->devinfo.iDitherFormat == BMF_8BPP) ||
(pGDev->devinfo.iDitherFormat == BMF_16BPP) ||
(pGDev->devinfo.iDitherFormat == BMF_24BPP) ||
(pGDev->devinfo.iDitherFormat == BMF_32BPP))
{
if (pGDev->flFlags & PDEV_GAMMARAMP_TABLE)
RtlCopyMemory( Ramp,
pGDev->pvGammaRamp,
sizeof(GAMMARAMP));
else
// Generate the 256-colors array
for(i=0; i<256; i++ )
{
int NewValue = i * 256;
Ramp->Red[i] = Ramp->Green[i] = Ramp->Blue[i] = ((WORD)NewValue);
}
return TRUE;
}
else
return FALSE;
}
BOOL
APIENTRY
NtGdiGetDeviceGammaRamp(HDC hDC,
LPVOID Ramp)
{
BOOL Ret;
PDC dc;
NTSTATUS Status = STATUS_SUCCESS;
PGAMMARAMP SafeRamp;
if (!Ramp) return FALSE;
dc = DC_LockDc(hDC);
if (!dc)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
SafeRamp = ExAllocatePoolWithTag(PagedPool, sizeof(GAMMARAMP), TAG_GDIICM);
if (!SafeRamp)
{
DC_UnlockDc(dc);
SetLastWin32Error(STATUS_NO_MEMORY);
return FALSE;
}
Ret = IntGetDeviceGammaRamp((HDEV)dc->ppdev, SafeRamp);
if (!Ret) return Ret;
_SEH2_TRY
{
ProbeForWrite( Ramp,
sizeof(PVOID),
1);
RtlCopyMemory( Ramp,
SafeRamp,
sizeof(GAMMARAMP));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
DC_UnlockDc(dc);
ExFreePoolWithTag(SafeRamp, TAG_GDIICM);
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
return FALSE;
}
return Ret;
}
BOOL
APIENTRY
NtGdiSetColorSpace(IN HDC hdc,
IN HCOLORSPACE hColorSpace)
{
PDC pDC;
PDC_ATTR pdcattr;
PCOLORSPACE pCS;
pDC = DC_LockDc(hdc);
if (!pDC)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
pdcattr = pDC->pdcattr;
if (pdcattr->hColorSpace == hColorSpace)
{
DC_UnlockDc(pDC);
return TRUE;
}
pCS = COLORSPACEOBJ_LockCS(hColorSpace);
if (!pCS)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
if (pDC->dclevel.pColorSpace)
{
GDIOBJ_ShareUnlockObjByPtr((POBJ) pDC->dclevel.pColorSpace);
}
pDC->dclevel.pColorSpace = pCS;
pdcattr->hColorSpace = hColorSpace;
COLORSPACEOBJ_UnlockCS(pCS);
DC_UnlockDc(pDC);
return TRUE;
}
BOOL
FASTCALL
UpdateDeviceGammaRamp( HDEV hPDev )
{
BOOL Ret = FALSE;
PPALETTE palGDI;
PALOBJ *palPtr;
PPDEVOBJ pGDev = (PPDEVOBJ) hPDev;
if ((pGDev->devinfo.iDitherFormat == BMF_8BPP) ||
(pGDev->devinfo.iDitherFormat == BMF_16BPP) ||
(pGDev->devinfo.iDitherFormat == BMF_24BPP) ||
(pGDev->devinfo.iDitherFormat == BMF_32BPP))
{
if (pGDev->DriverFunctions.IcmSetDeviceGammaRamp)
return pGDev->DriverFunctions.IcmSetDeviceGammaRamp( pGDev->dhpdev,
IGRF_RGB_256WORDS,
pGDev->pvGammaRamp);
if ( (pGDev->devinfo.iDitherFormat != BMF_8BPP) ||
!(pGDev->gdiinfo.flRaster & RC_PALETTE)) return FALSE;
if (!(pGDev->flFlags & PDEV_GAMMARAMP_TABLE)) return FALSE;
palGDI = PALETTE_LockPalette(pGDev->devinfo.hpalDefault);
if(!palGDI) return FALSE;
palPtr = (PALOBJ*) palGDI;
if (pGDev->flFlags & PDEV_GAMMARAMP_TABLE)
palGDI->Mode |= PAL_GAMMACORRECTION;
else
palGDI->Mode &= ~PAL_GAMMACORRECTION;
if (!(pGDev->flFlags & PDEV_DRIVER_PUNTED_CALL)) // No punting, we hook
{
// BMF_8BPP only!
// PALOBJ_cGetColors check mode flags and update Gamma Correction.
// Set the HDEV to pal and go.
palGDI->hPDev = hPDev;
Ret = pGDev->DriverFunctions.SetPalette(pGDev->dhpdev,
palPtr,
0,
0,
palGDI->NumColors);
}
PALETTE_UnlockPalette(palGDI);
return Ret;
}
else
return FALSE;
}
//
// ICM registry subkey sets internal brightness range, gamma range is 128 or
// 256 when icm is init.
INT IcmGammaRangeSet = 128; // <- make it global
BOOL
FASTCALL
IntSetDeviceGammaRamp(HDEV hPDev, PGAMMARAMP Ramp, BOOL Test)
{
WORD IcmGR, i, R, G, B;
BOOL Ret = FALSE, TstPeak;
PPDEVOBJ pGDev = (PPDEVOBJ) hPDev;
if (!hPDev) return FALSE;
if (!(pGDev->flFlags & PDEV_DISPLAY )) return FALSE;
if ((pGDev->devinfo.iDitherFormat == BMF_8BPP) ||
(pGDev->devinfo.iDitherFormat == BMF_16BPP) ||
(pGDev->devinfo.iDitherFormat == BMF_24BPP) ||
(pGDev->devinfo.iDitherFormat == BMF_32BPP))
{
if (!pGDev->DriverFunctions.IcmSetDeviceGammaRamp)
{ // No driver support
if (!(pGDev->devinfo.flGraphicsCaps2 & GCAPS2_CHANGEGAMMARAMP))
{ // Driver does not support Gamma Ramp, so test to see we
// have BMF_8BPP only and palette operation support.
if ((pGDev->devinfo.iDitherFormat != BMF_8BPP) ||
!(pGDev->gdiinfo.flRaster & RC_PALETTE)) return FALSE;
}
}
if (pGDev->flFlags & PDEV_GAMMARAMP_TABLE)
if (RtlCompareMemory( pGDev->pvGammaRamp, Ramp, sizeof(GAMMARAMP)) ==
sizeof(GAMMARAMP)) return TRUE;
// Verify Ramp is inside range.
IcmGR = -IcmGammaRangeSet;
TstPeak = (Test == FALSE);
for (i = 0; i < 256; i++)
{
R = Ramp->Red[i] / 256;
G = Ramp->Green[i] / 256;
B = Ramp->Blue[i] / 256;
if ( R >= IcmGR)
{
if ( R <= IcmGammaRangeSet + i)
{
if ( G >= IcmGR &&
(G <= IcmGammaRangeSet + i) &&
B >= IcmGR &&
(B <= IcmGammaRangeSet + i) ) continue;
}
}
if (Test) return Ret; // Don't set and return.
// No test override, check max range
if (TstPeak)
{
if ( R != (IcmGR * 256) ||
G != (IcmGR * 256) ||
B != (IcmGR * 256) ) TstPeak = FALSE; // W/i range.
}
}
// ReactOS allocates a ramp even if it is 8BPP and Palette only.
// This way we have a record of the change in memory.
if (!pGDev->pvGammaRamp && !(pGDev->flFlags & PDEV_GAMMARAMP_TABLE))
{ // If the above is true and we have nothing allocated, create it.
pGDev->pvGammaRamp = ExAllocatePoolWithTag(PagedPool, sizeof(GAMMARAMP), TAG_GDIICM);
pGDev->flFlags |= PDEV_GAMMARAMP_TABLE;
}
if (pGDev->pvGammaRamp)
RtlCopyMemory( pGDev->pvGammaRamp, Ramp, sizeof(GAMMARAMP));
Ret = UpdateDeviceGammaRamp(hPDev);
return Ret;
}
else
return Ret;
}
BOOL
APIENTRY
NtGdiSetDeviceGammaRamp(HDC hDC,
LPVOID Ramp)
{
BOOL Ret;
PDC dc;
NTSTATUS Status = STATUS_SUCCESS;
PGAMMARAMP SafeRamp;
if (!Ramp) return FALSE;
dc = DC_LockDc(hDC);
if (!dc)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
SafeRamp = ExAllocatePoolWithTag(PagedPool, sizeof(GAMMARAMP), TAG_GDIICM);
if (!SafeRamp)
{
DC_UnlockDc(dc);
SetLastWin32Error(STATUS_NO_MEMORY);
return FALSE;
}
_SEH2_TRY
{
ProbeForRead( Ramp,
sizeof(PVOID),
1);
RtlCopyMemory( SafeRamp,
Ramp,
sizeof(GAMMARAMP));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
if (!NT_SUCCESS(Status))
{
DC_UnlockDc(dc);
ExFreePoolWithTag(SafeRamp, TAG_GDIICM);
SetLastNtError(Status);
return FALSE;
}
Ret = IntSetDeviceGammaRamp((HDEV)dc->ppdev, SafeRamp, TRUE);
DC_UnlockDc(dc);
ExFreePoolWithTag(SafeRamp, TAG_GDIICM);
return Ret;
}
INT
APIENTRY
NtGdiSetIcmMode(HDC hDC,
ULONG nCommand,
ULONG EnableICM) // ulMode
{
/* FIXME: this should be coded someday */
if (EnableICM == ICM_OFF)
{
return ICM_OFF;
}
if (EnableICM == ICM_ON)
{
return 0;
}
if (EnableICM == ICM_QUERY)
{
return ICM_OFF;
}
return 0;
}
/* EOF */