[WIN32K] Use TAG_GDIICM tag for ICM allocations
[reactos.git] / reactos / subsystems / win32 / win32k / objects / icm.c
index 03e1489..f0d7ef7 100644 (file)
  *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  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.
  */
-/* $Id$ */
 
-#include <w32k.h>
+#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
-STDCALL
-NtGdiColorMatchToTarget(HDC  hDC,
-                             HDC  hDCTarget,
-                             DWORD  Action)
+FASTCALL
+IntGdiDeleteColorSpace(
+    HCOLORSPACE hColorSpace)
 {
-  UNIMPLEMENTED;
-  return FALSE;
+  BOOL Ret = FALSE;
+
+  if ( hColorSpace != hStockColorSpace )
+  {
+     Ret = COLORSPACEOBJ_FreeCSByHandle(hColorSpace);
+     if ( !Ret ) SetLastWin32Error(ERROR_INVALID_PARAMETER);
+  }
+  return Ret;
 }
 
 HANDLE
@@ -38,8 +63,28 @@ APIENTRY
 NtGdiCreateColorSpace(
     IN PLOGCOLORSPACEEXW pLogColorSpace)
 {
-  UNIMPLEMENTED;
-  return 0;
+  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
@@ -47,82 +92,329 @@ APIENTRY
 NtGdiDeleteColorSpace(
     IN HANDLE hColorSpace)
 {
-  UNIMPLEMENTED;
-  return FALSE;
+  return IntGdiDeleteColorSpace(hColorSpace);
 }
 
-INT
-STDCALL
-NtGdiEnumICMProfiles(HDC    hDC,
-                    LPWSTR lpstrBuffer,
-                    UINT   cch )
+BOOL
+FASTCALL
+IntGetDeviceGammaRamp(HDEV hPDev, PGAMMARAMP Ramp)
 {
-  /*
-   * FIXME - build list of file names into lpstrBuffer.
-   * (MULTI-SZ would probably be best format)
-   * return (needed) length of buffer in bytes
-   */
-  UNIMPLEMENTED;
-  return 0;
-}
+  PPDEVOBJ pGDev = (PPDEVOBJ) hPDev;
+  int i;
 
-HCOLORSPACE
-STDCALL
-NtGdiGetColorSpace(HDC  hDC)
-{
-  /* FIXME: Need to to whatever GetColorSpace actually does */
-  return  0;
+  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
-STDCALL
+APIENTRY
 NtGdiGetDeviceGammaRamp(HDC  hDC,
                              LPVOID  Ramp)
 {
-  UNIMPLEMENTED;
-  return FALSE;
+  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
-STDCALL
-NtGdiGetICMProfile(HDC  hDC,
-                        LPDWORD  NameSize,
-                        LPWSTR  Filename)
+APIENTRY
+NtGdiSetColorSpace(IN HDC hdc,
+                   IN HCOLORSPACE hColorSpace)
 {
-  UNIMPLEMENTED;
-  return FALSE;
+  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
-STDCALL
-NtGdiGetLogColorSpace(HCOLORSPACE  hColorSpace,
-                           LPLOGCOLORSPACEW  Buffer,
-                           DWORD  Size)
+FASTCALL
+UpdateDeviceGammaRamp( HDEV hPDev )
 {
-  UNIMPLEMENTED;
-  return FALSE;
+  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
-STDCALL
-NtGdiSetColorSpace(IN HDC hdc,
-                   IN HCOLORSPACE hColorSpace)
+FASTCALL
+IntSetDeviceGammaRamp(HDEV hPDev, PGAMMARAMP Ramp, BOOL Test)
 {
-  UNIMPLEMENTED;
-  return 0;
+  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
-STDCALL
+APIENTRY
 NtGdiSetDeviceGammaRamp(HDC  hDC,
                              LPVOID  Ramp)
 {
-  UNIMPLEMENTED;
-  return FALSE;
+  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
-STDCALL
+APIENTRY
 NtGdiSetIcmMode(HDC  hDC,
                 ULONG nCommand,
                 ULONG EnableICM) // ulMode
@@ -144,24 +436,4 @@ NtGdiSetIcmMode(HDC  hDC,
   return  0;
 }
 
-BOOL
-STDCALL
-NtGdiSetICMProfile(HDC  hDC,
-                        LPWSTR  Filename)
-{
-  UNIMPLEMENTED;
-  return FALSE;
-}
-
-BOOL
-STDCALL
-NtGdiUpdateICMRegKey(DWORD  Reserved,
-                          LPWSTR  CMID,
-                          LPWSTR  Filename,
-                          UINT  Command)
-{
-  UNIMPLEMENTED;
-  return FALSE;
-}
-
 /* EOF */