=?UTF-8?Q?Andr=C3=A9=20Hentschel=20?=: gdi32: Copy gamma ramp validation from winex11 to make it driver independent.

Alexandre Julliard julliard at winehq.org
Wed Apr 17 15:14:46 CDT 2013


Module: wine
Branch: master
Commit: 741f7b6f0c1ed8c35e1c30ca226641c0611299f1
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=741f7b6f0c1ed8c35e1c30ca226641c0611299f1

Author: André Hentschel <nerv at dawncrow.de>
Date:   Wed Apr 17 00:38:37 2013 +0200

gdi32: Copy gamma ramp validation from winex11 to make it driver independent.

---

 dlls/gdi32/dc.c |   82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 81 insertions(+), 1 deletions(-)

diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c
index c6ba488..231f197 100644
--- a/dlls/gdi32/dc.c
+++ b/dlls/gdi32/dc.c
@@ -1311,6 +1311,84 @@ BOOL WINAPI GetDeviceGammaRamp(HDC hDC, LPVOID ptr)
     return ret;
 }
 
+static BOOL check_gamma_ramps(void *ptr)
+{
+    WORD *ramp = ptr;
+
+    while (ramp < (WORD*)ptr + 3 * 256)
+    {
+        float r_x, r_y, r_lx, r_ly, r_d, r_v, r_e, g_avg, g_min, g_max;
+        unsigned i, f, l, g_n, c;
+
+        f = ramp[0];
+        l = ramp[255];
+        if (f >= l)
+        {
+            TRACE("inverted or flat gamma ramp (%d->%d), rejected\n", f, l);
+            return FALSE;
+        }
+        r_d = l - f;
+        g_min = g_max = g_avg = 0.0;
+
+        /* check gamma ramp entries to estimate the gamma */
+        TRACE("analyzing gamma ramp (%d->%d)\n", f, l);
+        for (i=1, g_n=0; i<255; i++)
+        {
+            if (ramp[i] < f || ramp[i] > l)
+            {
+                TRACE("strange gamma ramp ([%d]=%d for %d->%d), rejected\n", i, ramp[i], f, l);
+                return FALSE;
+            }
+            c = ramp[i] - f;
+            if (!c) continue; /* avoid log(0) */
+
+            /* normalize entry values into 0..1 range */
+            r_x = i/255.0; r_y = c / r_d;
+            /* compute logarithms of values */
+            r_lx = log(r_x); r_ly = log(r_y);
+            /* compute gamma for this entry */
+            r_v = r_ly / r_lx;
+            /* compute differential (error estimate) for this entry */
+            /* some games use table-based logarithms that magnifies the error by 128 */
+            r_e = -r_lx * 128 / (c * r_lx * r_lx);
+
+            /* compute min & max while compensating for estimated error */
+            if (!g_n || g_min > (r_v + r_e)) g_min = r_v + r_e;
+            if (!g_n || g_max < (r_v - r_e)) g_max = r_v - r_e;
+
+            /* add to average */
+            g_avg += r_v;
+            g_n++;
+        }
+
+        if (!g_n)
+        {
+            TRACE("no gamma data, shouldn't happen\n");
+            return FALSE;
+        }
+        g_avg /= g_n;
+        TRACE("low bias is %d, high is %d, gamma is %5.3f\n", f, 65535-l, g_avg);
+
+        /* check that the gamma is reasonably uniform across the ramp */
+        if (g_max - g_min > 12.8)
+        {
+            TRACE("ramp not uniform (max=%f, min=%f, avg=%f), rejected\n", g_max, g_min, g_avg);
+            return FALSE;
+        }
+
+        /* check that the gamma is not too bright */
+        if (g_avg < 0.2)
+        {
+            TRACE("too bright gamma ( %5.3f), rejected\n", g_avg);
+            return FALSE;
+        }
+
+        ramp += 256;
+    }
+
+    return TRUE;
+}
+
 /***********************************************************************
  *           SetDeviceGammaRamp    (GDI32.@)
  */
@@ -1325,7 +1403,9 @@ BOOL WINAPI SetDeviceGammaRamp(HDC hDC, LPVOID ptr)
         if (GetObjectType( hDC ) != OBJ_MEMDC)
         {
             PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDeviceGammaRamp );
-            ret = physdev->funcs->pSetDeviceGammaRamp( physdev, ptr );
+
+            if (check_gamma_ramps(ptr))
+                ret = physdev->funcs->pSetDeviceGammaRamp( physdev, ptr );
         }
         else SetLastError( ERROR_INVALID_PARAMETER );
 	release_dc_ptr( dc );




More information about the wine-cvs mailing list