2 * PROJECT: ReactOS Win32k Subsystem
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: win32k/objects/icm.c
5 * PURPOSE: Icm functions
14 HCOLORSPACE hStockColorSpace
= NULL
;
19 IntGdiCreateColorSpace(
20 PLOGCOLORSPACEEXW pLogColorSpace
)
25 pCS
= COLORSPACEOBJ_AllocCSWithHandle();
26 hCS
= pCS
->BaseObject
.hHmgr
;
28 pCS
->lcsColorSpace
= pLogColorSpace
->lcsColorSpace
;
29 pCS
->dwFlags
= pLogColorSpace
->dwFlags
;
31 COLORSPACEOBJ_UnlockCS(pCS
);
37 IntGdiDeleteColorSpace(
38 HCOLORSPACE hColorSpace
)
42 if ( hColorSpace
!= hStockColorSpace
&&
43 GDI_HANDLE_GET_TYPE(hColorSpace
) == GDILoObjType_LO_ICMLCS_TYPE
)
45 Ret
= GreDeleteObject(hColorSpace
);
46 if ( !Ret
) EngSetLastError(ERROR_INVALID_PARAMETER
);
53 NtGdiCreateColorSpace(
54 IN PLOGCOLORSPACEEXW pLogColorSpace
)
56 LOGCOLORSPACEEXW Safelcs
;
57 NTSTATUS Status
= STATUS_SUCCESS
;
61 ProbeForRead( pLogColorSpace
,
62 sizeof(LOGCOLORSPACEEXW
),
64 RtlCopyMemory(&Safelcs
, pLogColorSpace
, sizeof(LOGCOLORSPACEEXW
));
66 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
68 Status
= _SEH2_GetExceptionCode();
72 if (!NT_SUCCESS(Status
))
74 SetLastNtError(Status
);
77 return IntGdiCreateColorSpace(&Safelcs
);
82 NtGdiDeleteColorSpace(
83 IN HANDLE hColorSpace
)
85 return IntGdiDeleteColorSpace(hColorSpace
);
90 IntGetDeviceGammaRamp(HDEV hPDev
, PGAMMARAMP Ramp
)
92 PPDEVOBJ pGDev
= (PPDEVOBJ
) hPDev
;
95 if (!(pGDev
->flFlags
& PDEV_DISPLAY
)) return FALSE
;
97 if ((pGDev
->devinfo
.iDitherFormat
== BMF_8BPP
) ||
98 (pGDev
->devinfo
.iDitherFormat
== BMF_16BPP
) ||
99 (pGDev
->devinfo
.iDitherFormat
== BMF_24BPP
) ||
100 (pGDev
->devinfo
.iDitherFormat
== BMF_32BPP
))
102 if (pGDev
->flFlags
& PDEV_GAMMARAMP_TABLE
)
107 // Generate the 256-colors array
108 for(i
=0; i
<256; i
++ )
110 int NewValue
= i
* 256;
112 Ramp
->Red
[i
] = Ramp
->Green
[i
] = Ramp
->Blue
[i
] = ((WORD
)NewValue
);
122 NtGdiGetDeviceGammaRamp(HDC hDC
,
127 NTSTATUS Status
= STATUS_SUCCESS
;
130 if (!Ramp
) return FALSE
;
135 EngSetLastError(ERROR_INVALID_HANDLE
);
139 SafeRamp
= ExAllocatePoolWithTag(PagedPool
, sizeof(GAMMARAMP
), GDITAG_ICM
);
143 EngSetLastError(STATUS_NO_MEMORY
);
147 Ret
= IntGetDeviceGammaRamp((HDEV
)dc
->ppdev
, SafeRamp
);
149 if (!Ret
) return Ret
;
153 ProbeForWrite(Ramp
, sizeof(GAMMARAMP
), 1);
154 RtlCopyMemory(Ramp
, SafeRamp
, sizeof(GAMMARAMP
));
156 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
158 Status
= _SEH2_GetExceptionCode();
163 ExFreePoolWithTag(SafeRamp
, GDITAG_ICM
);
165 if (!NT_SUCCESS(Status
))
167 SetLastNtError(Status
);
175 NtGdiSetColorSpace(IN HDC hdc
,
176 IN HCOLORSPACE hColorSpace
)
182 pDC
= DC_LockDc(hdc
);
185 EngSetLastError(ERROR_INVALID_HANDLE
);
188 pdcattr
= pDC
->pdcattr
;
190 if (pdcattr
->hColorSpace
== hColorSpace
)
196 pCS
= COLORSPACEOBJ_LockCS(hColorSpace
);
199 EngSetLastError(ERROR_INVALID_HANDLE
);
203 if (pDC
->dclevel
.pColorSpace
)
205 GDIOBJ_vDereferenceObject((POBJ
) pDC
->dclevel
.pColorSpace
);
208 pDC
->dclevel
.pColorSpace
= pCS
;
209 pdcattr
->hColorSpace
= hColorSpace
;
211 COLORSPACEOBJ_UnlockCS(pCS
);
218 UpdateDeviceGammaRamp( HDEV hPDev
)
223 PPDEVOBJ pGDev
= (PPDEVOBJ
) hPDev
;
225 if ((pGDev
->devinfo
.iDitherFormat
== BMF_8BPP
) ||
226 (pGDev
->devinfo
.iDitherFormat
== BMF_16BPP
) ||
227 (pGDev
->devinfo
.iDitherFormat
== BMF_24BPP
) ||
228 (pGDev
->devinfo
.iDitherFormat
== BMF_32BPP
))
230 if (pGDev
->DriverFunctions
.IcmSetDeviceGammaRamp
)
231 return pGDev
->DriverFunctions
.IcmSetDeviceGammaRamp( pGDev
->dhpdev
,
235 if ( (pGDev
->devinfo
.iDitherFormat
!= BMF_8BPP
) ||
236 !(pGDev
->gdiinfo
.flRaster
& RC_PALETTE
)) return FALSE
;
238 if (!(pGDev
->flFlags
& PDEV_GAMMARAMP_TABLE
)) return FALSE
;
240 palGDI
= PALETTE_ShareLockPalette(pGDev
->devinfo
.hpalDefault
);
241 if(!palGDI
) return FALSE
;
242 palPtr
= (PALOBJ
*) palGDI
;
244 if (pGDev
->flFlags
& PDEV_GAMMARAMP_TABLE
)
245 palGDI
->flFlags
|= PAL_GAMMACORRECTION
;
247 palGDI
->flFlags
&= ~PAL_GAMMACORRECTION
;
249 if (!(pGDev
->flFlags
& PDEV_DRIVER_PUNTED_CALL
)) // No punting, we hook
252 // PALOBJ_cGetColors check mode flags and update Gamma Correction.
253 // Set the HDEV to pal and go.
254 palGDI
->hPDev
= hPDev
;
255 Ret
= pGDev
->DriverFunctions
.SetPalette(pGDev
->dhpdev
,
261 PALETTE_ShareUnlockPalette(palGDI
);
269 // ICM registry subkey sets internal brightness range, gamma range is 128 or
270 // 256 when icm is init.
271 INT IcmGammaRangeSet
= 128; // <- Make it global
275 IntSetDeviceGammaRamp(HDEV hPDev
, PGAMMARAMP Ramp
, BOOL Test
)
277 WORD IcmGR
, i
, R
, G
, B
;
278 BOOL Ret
= FALSE
, TstPeak
;
279 PPDEVOBJ pGDev
= (PPDEVOBJ
) hPDev
;
281 if (!hPDev
) return FALSE
;
283 if (!(pGDev
->flFlags
& PDEV_DISPLAY
)) return FALSE
;
285 if ((pGDev
->devinfo
.iDitherFormat
== BMF_8BPP
) ||
286 (pGDev
->devinfo
.iDitherFormat
== BMF_16BPP
) ||
287 (pGDev
->devinfo
.iDitherFormat
== BMF_24BPP
) ||
288 (pGDev
->devinfo
.iDitherFormat
== BMF_32BPP
))
290 if (!pGDev
->DriverFunctions
.IcmSetDeviceGammaRamp
)
291 { // No driver support
292 if (!(pGDev
->devinfo
.flGraphicsCaps2
& GCAPS2_CHANGEGAMMARAMP
))
293 { // Driver does not support Gamma Ramp, so test to see we
294 // have BMF_8BPP only and palette operation support.
295 if ((pGDev
->devinfo
.iDitherFormat
!= BMF_8BPP
) ||
296 !(pGDev
->gdiinfo
.flRaster
& RC_PALETTE
)) return FALSE
;
300 if (pGDev
->flFlags
& PDEV_GAMMARAMP_TABLE
)
301 if (RtlCompareMemory( pGDev
->pvGammaRamp
, Ramp
, sizeof(GAMMARAMP
)) ==
302 sizeof(GAMMARAMP
)) return TRUE
;
303 // Verify Ramp is inside range.
304 IcmGR
= -IcmGammaRangeSet
;
305 TstPeak
= (Test
== FALSE
);
306 for (i
= 0; i
< 256; i
++)
308 R
= Ramp
->Red
[i
] / 256;
309 G
= Ramp
->Green
[i
] / 256;
310 B
= Ramp
->Blue
[i
] / 256;
313 if ( R
<= IcmGammaRangeSet
+ i
)
316 (G
<= IcmGammaRangeSet
+ i
) &&
318 (B
<= IcmGammaRangeSet
+ i
) ) continue;
321 if (Test
) return Ret
; // Don't set and return.
322 // No test override, check max range
325 if ( R
!= (IcmGR
* 256) ||
326 G
!= (IcmGR
* 256) ||
327 B
!= (IcmGR
* 256) ) TstPeak
= FALSE
; // W/i range.
330 // ReactOS allocates a ramp even if it is 8BPP and Palette only.
331 // This way we have a record of the change in memory.
332 if (!pGDev
->pvGammaRamp
&& !(pGDev
->flFlags
& PDEV_GAMMARAMP_TABLE
))
333 { // If the above is true and we have nothing allocated, create it.
334 pGDev
->pvGammaRamp
= ExAllocatePoolWithTag(PagedPool
, sizeof(GAMMARAMP
), GDITAG_ICM
);
335 pGDev
->flFlags
|= PDEV_GAMMARAMP_TABLE
;
337 if (pGDev
->pvGammaRamp
)
338 RtlCopyMemory( pGDev
->pvGammaRamp
, Ramp
, sizeof(GAMMARAMP
));
340 Ret
= UpdateDeviceGammaRamp(hPDev
);
350 NtGdiSetDeviceGammaRamp(HDC hDC
,
355 NTSTATUS Status
= STATUS_SUCCESS
;
357 if (!Ramp
) return FALSE
;
362 EngSetLastError(ERROR_INVALID_HANDLE
);
366 SafeRamp
= ExAllocatePoolWithTag(PagedPool
, sizeof(GAMMARAMP
), GDITAG_ICM
);
370 EngSetLastError(STATUS_NO_MEMORY
);
375 ProbeForRead(Ramp
, sizeof(GAMMARAMP
), 1);
376 RtlCopyMemory(SafeRamp
, Ramp
, sizeof(GAMMARAMP
));
378 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
380 Status
= _SEH2_GetExceptionCode();
384 if (!NT_SUCCESS(Status
))
387 ExFreePoolWithTag(SafeRamp
, GDITAG_ICM
);
388 SetLastNtError(Status
);
392 Ret
= IntSetDeviceGammaRamp((HDEV
)dc
->ppdev
, SafeRamp
, TRUE
);
394 ExFreePoolWithTag(SafeRamp
, GDITAG_ICM
);
400 NtGdiSetIcmMode(HDC hDC
,
402 ULONG EnableICM
) // ulMode
404 /* FIXME: This should be coded someday */
405 if (EnableICM
== ICM_OFF
)
409 if (EnableICM
== ICM_ON
)
413 if (EnableICM
== ICM_QUERY
)