2 * PROJECT: ReactOS Win32k Subsystem
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: win32ss/gdi/ntgdi/icm.c
5 * PURPOSE: Icm functions
14 HCOLORSPACE hStockColorSpace
= NULL
;
19 IntGdiCreateColorSpace(
20 PLOGCOLORSPACEEXW pLogColorSpace
)
25 pCS
= COLORSPACEOBJ_AllocCSWithHandle();
26 if (pCS
== NULL
) return NULL
;
28 hCS
= pCS
->BaseObject
.hHmgr
;
30 pCS
->lcsColorSpace
= pLogColorSpace
->lcsColorSpace
;
31 pCS
->dwFlags
= pLogColorSpace
->dwFlags
;
33 COLORSPACEOBJ_UnlockCS(pCS
);
39 IntGdiDeleteColorSpace(
40 HCOLORSPACE hColorSpace
)
44 if ((hColorSpace
!= hStockColorSpace
) &&
45 (GDI_HANDLE_GET_TYPE(hColorSpace
) == GDILoObjType_LO_ICMLCS_TYPE
))
47 Ret
= GreDeleteObject(hColorSpace
);
48 if (!Ret
) EngSetLastError(ERROR_INVALID_PARAMETER
);
56 NtGdiCreateColorSpace(
57 IN PLOGCOLORSPACEEXW pLogColorSpace
)
59 LOGCOLORSPACEEXW Safelcs
;
60 NTSTATUS Status
= STATUS_SUCCESS
;
64 ProbeForRead( pLogColorSpace
, sizeof(LOGCOLORSPACEEXW
), 1);
65 RtlCopyMemory(&Safelcs
, pLogColorSpace
, sizeof(LOGCOLORSPACEEXW
));
67 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
69 Status
= _SEH2_GetExceptionCode();
73 if (!NT_SUCCESS(Status
))
75 SetLastNtError(Status
);
79 return IntGdiCreateColorSpace(&Safelcs
);
84 NtGdiDeleteColorSpace(
85 IN HANDLE hColorSpace
)
87 return IntGdiDeleteColorSpace(hColorSpace
);
92 IntGetDeviceGammaRamp(HDEV hPDev
, PGAMMARAMP Ramp
)
94 PPDEVOBJ pGDev
= (PPDEVOBJ
) hPDev
;
97 if (!(pGDev
->flFlags
& PDEV_DISPLAY
)) return FALSE
;
99 if ((pGDev
->devinfo
.iDitherFormat
== BMF_8BPP
) ||
100 (pGDev
->devinfo
.iDitherFormat
== BMF_16BPP
) ||
101 (pGDev
->devinfo
.iDitherFormat
== BMF_24BPP
) ||
102 (pGDev
->devinfo
.iDitherFormat
== BMF_32BPP
))
104 if (pGDev
->flFlags
& PDEV_GAMMARAMP_TABLE
)
106 RtlCopyMemory(Ramp
, pGDev
->pvGammaRamp
, sizeof(GAMMARAMP
));
110 // Generate the 256-colors array
111 for (i
= 0; i
< 256; i
++ )
113 int NewValue
= i
* 256;
115 Ramp
->Red
[i
] = Ramp
->Green
[i
] = Ramp
->Blue
[i
] = ((WORD
)NewValue
);
126 NtGdiGetDeviceGammaRamp(
132 NTSTATUS Status
= STATUS_SUCCESS
;
135 if (!Ramp
) return FALSE
;
140 EngSetLastError(ERROR_INVALID_HANDLE
);
144 SafeRamp
= ExAllocatePoolWithTag(PagedPool
, sizeof(GAMMARAMP
), GDITAG_ICM
);
148 EngSetLastError(STATUS_NO_MEMORY
);
152 Ret
= IntGetDeviceGammaRamp((HDEV
)dc
->ppdev
, SafeRamp
);
156 ExFreePoolWithTag(SafeRamp
, GDITAG_ICM
);
162 ProbeForWrite(Ramp
, sizeof(GAMMARAMP
), 1);
163 RtlCopyMemory(Ramp
, SafeRamp
, sizeof(GAMMARAMP
));
165 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
167 Status
= _SEH2_GetExceptionCode();
172 ExFreePoolWithTag(SafeRamp
, GDITAG_ICM
);
174 if (!NT_SUCCESS(Status
))
176 SetLastNtError(Status
);
184 NtGdiSetColorSpace(IN HDC hdc
,
185 IN HCOLORSPACE hColorSpace
)
191 pDC
= DC_LockDc(hdc
);
194 EngSetLastError(ERROR_INVALID_HANDLE
);
197 pdcattr
= pDC
->pdcattr
;
199 if (pdcattr
->hColorSpace
== hColorSpace
)
205 pCS
= COLORSPACEOBJ_LockCS(hColorSpace
);
208 EngSetLastError(ERROR_INVALID_HANDLE
);
212 if (pDC
->dclevel
.pColorSpace
)
214 GDIOBJ_vDereferenceObject((POBJ
) pDC
->dclevel
.pColorSpace
);
217 pDC
->dclevel
.pColorSpace
= pCS
;
218 pdcattr
->hColorSpace
= hColorSpace
;
220 COLORSPACEOBJ_UnlockCS(pCS
);
227 UpdateDeviceGammaRamp(HDEV hPDev
)
232 PPDEVOBJ pGDev
= (PPDEVOBJ
)hPDev
;
234 if ((pGDev
->devinfo
.iDitherFormat
== BMF_8BPP
) ||
235 (pGDev
->devinfo
.iDitherFormat
== BMF_16BPP
) ||
236 (pGDev
->devinfo
.iDitherFormat
== BMF_24BPP
) ||
237 (pGDev
->devinfo
.iDitherFormat
== BMF_32BPP
))
239 if (pGDev
->DriverFunctions
.IcmSetDeviceGammaRamp
)
240 return pGDev
->DriverFunctions
.IcmSetDeviceGammaRamp( pGDev
->dhpdev
,
244 if ((pGDev
->devinfo
.iDitherFormat
!= BMF_8BPP
) ||
245 !(pGDev
->gdiinfo
.flRaster
& RC_PALETTE
)) return FALSE
;
247 if (!(pGDev
->flFlags
& PDEV_GAMMARAMP_TABLE
)) return FALSE
;
249 palGDI
= PALETTE_ShareLockPalette(pGDev
->devinfo
.hpalDefault
);
250 if(!palGDI
) return FALSE
;
251 palPtr
= (PALOBJ
*) palGDI
;
253 if (pGDev
->flFlags
& PDEV_GAMMARAMP_TABLE
)
254 palGDI
->flFlags
|= PAL_GAMMACORRECTION
;
256 palGDI
->flFlags
&= ~PAL_GAMMACORRECTION
;
258 if (!(pGDev
->flFlags
& PDEV_DRIVER_PUNTED_CALL
)) // No punting, we hook
261 // PALOBJ_cGetColors check mode flags and update Gamma Correction.
262 // Set the HDEV to pal and go.
263 palGDI
->hPDev
= hPDev
;
264 Ret
= pGDev
->DriverFunctions
.SetPalette(pGDev
->dhpdev
,
270 PALETTE_ShareUnlockPalette(palGDI
);
278 // ICM registry subkey sets internal brightness range, gamma range is 128 or
279 // 256 when icm is init.
280 INT IcmGammaRangeSet
= 128; // <- Make it global
284 IntSetDeviceGammaRamp(HDEV hPDev
, PGAMMARAMP Ramp
, BOOL Test
)
286 WORD IcmGR
, i
, R
, G
, B
;
287 BOOL Ret
= FALSE
, TstPeak
;
288 PPDEVOBJ pGDev
= (PPDEVOBJ
) hPDev
;
290 if (!hPDev
) return FALSE
;
292 if (!(pGDev
->flFlags
& PDEV_DISPLAY
)) return FALSE
;
294 if ((pGDev
->devinfo
.iDitherFormat
== BMF_8BPP
) ||
295 (pGDev
->devinfo
.iDitherFormat
== BMF_16BPP
) ||
296 (pGDev
->devinfo
.iDitherFormat
== BMF_24BPP
) ||
297 (pGDev
->devinfo
.iDitherFormat
== BMF_32BPP
))
299 if (!pGDev
->DriverFunctions
.IcmSetDeviceGammaRamp
)
302 if (!(pGDev
->devinfo
.flGraphicsCaps2
& GCAPS2_CHANGEGAMMARAMP
))
304 // Driver does not support Gamma Ramp, so test to see we
305 // have BMF_8BPP only and palette operation support.
306 if ((pGDev
->devinfo
.iDitherFormat
!= BMF_8BPP
) ||
307 !(pGDev
->gdiinfo
.flRaster
& RC_PALETTE
)) return FALSE
;
311 if (pGDev
->flFlags
& PDEV_GAMMARAMP_TABLE
)
313 if (RtlCompareMemory(pGDev
->pvGammaRamp
, Ramp
, sizeof(GAMMARAMP
)) ==
314 sizeof(GAMMARAMP
)) return TRUE
;
317 // Verify Ramp is inside range.
318 IcmGR
= -IcmGammaRangeSet
;
319 TstPeak
= (Test
== FALSE
);
320 for (i
= 0; i
< 256; i
++)
322 R
= Ramp
->Red
[i
] / 256;
323 G
= Ramp
->Green
[i
] / 256;
324 B
= Ramp
->Blue
[i
] / 256;
328 if (R
<= IcmGammaRangeSet
+ i
)
331 (G
<= IcmGammaRangeSet
+ i
) &&
333 (B
<= IcmGammaRangeSet
+ i
) ) continue;
337 if (Test
) return Ret
; // Don't set and return.
339 // No test override, check max range
342 if ((R
!= (IcmGR
* 256)) ||
343 (G
!= (IcmGR
* 256)) ||
344 (B
!= (IcmGR
* 256)) ) TstPeak
= FALSE
; // W/i range.
347 // ReactOS allocates a ramp even if it is 8BPP and Palette only.
348 // This way we have a record of the change in memory.
349 if (!pGDev
->pvGammaRamp
&& !(pGDev
->flFlags
& PDEV_GAMMARAMP_TABLE
))
351 // If the above is true and we have nothing allocated, create it.
352 pGDev
->pvGammaRamp
= ExAllocatePoolWithTag(PagedPool
, sizeof(GAMMARAMP
), GDITAG_ICM
);
353 pGDev
->flFlags
|= PDEV_GAMMARAMP_TABLE
;
356 if (pGDev
->pvGammaRamp
)
357 RtlCopyMemory(pGDev
->pvGammaRamp
, Ramp
, sizeof(GAMMARAMP
));
359 Ret
= UpdateDeviceGammaRamp(hPDev
);
367 NtGdiSetDeviceGammaRamp(
373 NTSTATUS Status
= STATUS_SUCCESS
;
375 if (!Ramp
) return FALSE
;
380 EngSetLastError(ERROR_INVALID_HANDLE
);
384 SafeRamp
= ExAllocatePoolWithTag(PagedPool
, sizeof(GAMMARAMP
), GDITAG_ICM
);
388 EngSetLastError(STATUS_NO_MEMORY
);
393 ProbeForRead(Ramp
, sizeof(GAMMARAMP
), 1);
394 RtlCopyMemory(SafeRamp
, Ramp
, sizeof(GAMMARAMP
));
396 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
398 Status
= _SEH2_GetExceptionCode();
402 if (!NT_SUCCESS(Status
))
405 ExFreePoolWithTag(SafeRamp
, GDITAG_ICM
);
406 SetLastNtError(Status
);
410 Ret
= IntSetDeviceGammaRamp((HDEV
)dc
->ppdev
, SafeRamp
, TRUE
);
412 ExFreePoolWithTag(SafeRamp
, GDITAG_ICM
);
418 NtGdiSetIcmMode(HDC hDC
,
420 ULONG EnableICM
) // ulMode
422 /* FIXME: This should be coded someday */
423 if (EnableICM
== ICM_OFF
)
427 if (EnableICM
== ICM_ON
)
431 if (EnableICM
== ICM_QUERY
)