[2/10] WineD3D: Move lights to the state table

Stefan Dösinger stefan at codeweavers.com
Wed Feb 14 10:48:52 CST 2007


The state table keeps track of active lights, not set lights, because there 
can be only a max of 8 active lights at any time, but any number of defined 
lights.

This patch fixes the lighting of the 2nd teapot in the codesampler swapchain 
sample. It even shows the same 'bug' as windows does.
-------------- next part --------------
From aaf9ca4a45b694d1f293f33acc48a67cc8009fd5 Mon Sep 17 00:00:00 2001
From: Stefan Doesinger <stefan at codeweavers.com>
Date: Wed, 31 Jan 2007 14:03:51 +0100
Subject: [PATCH] WineD3D: Move lights to the state table

---
 dlls/wined3d/device.c          |  110 +-------------------------------------
 dlls/wined3d/state.c           |  113 ++++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/wined3d_private.h |    5 ++-
 3 files changed, 120 insertions(+), 108 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 9a0b1b5..04ff58c 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -149,103 +149,6 @@ static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_
 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};  /* When needed for comparisons */
 
 /**********************************************************
- * Utility functions follow
- **********************************************************/
-/* Convert the WINED3DLIGHT properties into equivalent gl lights */
-static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
-
-    float quad_att;
-    float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
-    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-
-    /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
-    glMatrixMode(GL_MODELVIEW);
-    glPushMatrix();
-    glLoadMatrixf((float *)&This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
-
-    /* Diffuse: */
-    colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
-    colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
-    colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
-    colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
-    glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
-    checkGLcall("glLightfv");
-
-    /* Specular */
-    colRGBA[0] = lightInfo->OriginalParms.Specular.r;
-    colRGBA[1] = lightInfo->OriginalParms.Specular.g;
-    colRGBA[2] = lightInfo->OriginalParms.Specular.b;
-    colRGBA[3] = lightInfo->OriginalParms.Specular.a;
-    glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
-    checkGLcall("glLightfv");
-
-    /* Ambient */
-    colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
-    colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
-    colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
-    colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
-    glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
-    checkGLcall("glLightfv");
-
-    /* Attenuation - Are these right? guessing... */
-    glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION,  lightInfo->OriginalParms.Attenuation0);
-    checkGLcall("glLightf");
-    glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION,    lightInfo->OriginalParms.Attenuation1);
-    checkGLcall("glLightf");
-
-    if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
-        quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
-    } else {
-        quad_att = 0; /*  0 or  MAX?  (0 seems to be ok) */
-    }
-
-    if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
-    glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
-    checkGLcall("glLightf");
-
-    switch (lightInfo->OriginalParms.Type) {
-    case WINED3DLIGHT_POINT:
-        /* Position */
-        glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
-        checkGLcall("glLightfv");
-        glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
-        checkGLcall("glLightf");
-        /* FIXME: Range */
-        break;
-
-    case WINED3DLIGHT_SPOT:
-        /* Position */
-        glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
-        checkGLcall("glLightfv");
-        /* Direction */
-        glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
-        checkGLcall("glLightfv");
-        glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
-        checkGLcall("glLightf");
-        glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
-        checkGLcall("glLightf");
-        /* FIXME: Range */
-        break;
-
-    case WINED3DLIGHT_DIRECTIONAL:
-        /* Direction */
-        glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
-        checkGLcall("glLightfv");
-        glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
-        checkGLcall("glLightf");
-        glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
-        checkGLcall("glLightf");
-        break;
-
-    default:
-        FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
-    }
-
-    /* Restore the modelview matrix */
-    glPopMatrix();
-}
-
-/**********************************************************
  * GLSL helper functions follow
  **********************************************************/
 
@@ -2423,7 +2326,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD I
 
     /* Update the live definitions if the light is currently assigned a glIndex */
     if (object->glIndex != -1 && !This->isRecordingState) {
-        setup_light(iface, object->glIndex, object);
+        IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(object->glIndex));
     }
     return WINED3D_OK;
 }
@@ -2493,10 +2396,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, D
     if(!Enable) {
         if(lightInfo->glIndex != -1) {
             if(!This->isRecordingState) {
-                ENTER_GL();
-                glDisable(GL_LIGHT0 + lightInfo->glIndex);
-                checkGLcall("glDisable GL_LIGHT0+Index");
-                LEAVE_GL();
+                IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(lightInfo->glIndex));
             }
 
             This->stateBlock->activeLights[lightInfo->glIndex] = NULL;
@@ -2525,11 +2425,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, D
 
             /* i == lightInfo->glIndex */
             if(!This->isRecordingState) {
-                setup_light(iface, i, lightInfo);
-                ENTER_GL();
-                glEnable(GL_LIGHT0 + i);
-                checkGLcall("glEnable(GL_LIGHT0 + i)");
-                LEAVE_GL();
+                IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(i));
             }
         }
     }
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index ee898c2..3dac07f 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -2783,6 +2783,110 @@ static void viewport(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCon
 
 }
 
+static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
+    UINT Index = state - STATE_ACTIVELIGHT(0);
+    PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
+
+    if(!lightInfo) {
+        glDisable(GL_LIGHT0 + Index);
+        checkGLcall("glDisable(GL_LIGHT0 + Index)");
+    } else {
+        float quad_att;
+        float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
+
+        /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
+        glMatrixMode(GL_MODELVIEW);
+        glPushMatrix();
+        glLoadMatrixf((float *)&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
+
+        /* Diffuse: */
+        colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
+        colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
+        colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
+        colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
+        glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
+        checkGLcall("glLightfv");
+
+        /* Specular */
+        colRGBA[0] = lightInfo->OriginalParms.Specular.r;
+        colRGBA[1] = lightInfo->OriginalParms.Specular.g;
+        colRGBA[2] = lightInfo->OriginalParms.Specular.b;
+        colRGBA[3] = lightInfo->OriginalParms.Specular.a;
+        glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
+        checkGLcall("glLightfv");
+
+        /* Ambient */
+        colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
+        colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
+        colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
+        colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
+        glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
+        checkGLcall("glLightfv");
+
+        /* Attenuation - Are these right? guessing... */
+        glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION,  lightInfo->OriginalParms.Attenuation0);
+        checkGLcall("glLightf");
+        glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION,    lightInfo->OriginalParms.Attenuation1);
+        checkGLcall("glLightf");
+
+        if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
+            quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
+        } else {
+            quad_att = 0; /*  0 or  MAX?  (0 seems to be ok) */
+        }
+
+        if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
+        glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
+        checkGLcall("glLightf");
+
+        switch (lightInfo->OriginalParms.Type) {
+            case WINED3DLIGHT_POINT:
+                /* Position */
+                glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
+                checkGLcall("glLightfv");
+                glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
+                checkGLcall("glLightf");
+                /* FIXME: Range */
+                break;
+
+            case WINED3DLIGHT_SPOT:
+                /* Position */
+                glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
+                checkGLcall("glLightfv");
+                /* Direction */
+                glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
+                checkGLcall("glLightfv");
+                glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
+                checkGLcall("glLightf");
+                glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
+                checkGLcall("glLightf");
+                /* FIXME: Range */
+                break;
+
+            case WINED3DLIGHT_DIRECTIONAL:
+                /* Direction */
+                glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
+                checkGLcall("glLightfv");
+                glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
+                checkGLcall("glLightf");
+                glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
+                checkGLcall("glLightf");
+                break;
+
+            default:
+                FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
+        }
+
+        /* Restore the modelview matrix */
+        glPopMatrix();
+
+        glEnable(GL_LIGHT0 + Index);
+        checkGLcall("glEnable(GL_LIGHT0 + Index)");
+    }
+
+    return;
+}
+
 const struct StateEntry StateTable[] =
 {
       /* State name                                         representative,                                     apply function */
@@ -3803,4 +3907,13 @@ const struct StateEntry StateTable[] =
     { /*   , STATE_VIEWPORT                         */      STATE_VIEWPORT,                                     viewport            },
     { /*   , STATE_VERTEXSHADERCONSTANT             */      STATE_VERTEXSHADERCONSTANT,                         shaderconstant      },
     { /*   , STATE_PIXELSHADERCONSTANT              */      STATE_VERTEXSHADERCONSTANT,                         shaderconstant      },
+      /* Lights */
+    { /*   , STATE_ACTIVELIGHT(0)                   */      STATE_ACTIVELIGHT(0),                               light               },
+    { /*   , STATE_ACTIVELIGHT(1)                   */      STATE_ACTIVELIGHT(1),                               light               },
+    { /*   , STATE_ACTIVELIGHT(2)                   */      STATE_ACTIVELIGHT(2),                               light               },
+    { /*   , STATE_ACTIVELIGHT(3)                   */      STATE_ACTIVELIGHT(3),                               light               },
+    { /*   , STATE_ACTIVELIGHT(4)                   */      STATE_ACTIVELIGHT(4),                               light               },
+    { /*   , STATE_ACTIVELIGHT(5)                   */      STATE_ACTIVELIGHT(5),                               light               },
+    { /*   , STATE_ACTIVELIGHT(6)                   */      STATE_ACTIVELIGHT(6),                               light               },
+    { /*   , STATE_ACTIVELIGHT(7)                   */      STATE_ACTIVELIGHT(7),                               light               },
 };
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 3b30a3a..4dc914b 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -441,7 +441,10 @@ typedef void (*APPLYSTATEFUNC)(DWORD state, IWineD3DStateBlockImpl *stateblock,
 #define STATE_IS_VERTEXSHADERCONSTANT(a) ((a) == STATE_VERTEXSHADERCONSTANT)
 #define STATE_IS_PIXELSHADERCONSTANT(a) ((a) == STATE_PIXELSHADERCONSTANT)
 
-#define STATE_HIGHEST (STATE_PIXELSHADERCONSTANT)
+#define STATE_ACTIVELIGHT(a) (STATE_PIXELSHADERCONSTANT + (a) + 1)
+#define STATE_IS_ACTIVELIGHT(a) ((a) >= STATE_ACTIVELIGHT(0) && (a) < STATE_PIXELSHADERCONSTANT(MAX_ACTIVE_LIGHTS))
+
+#define STATE_HIGHEST (STATE_ACTIVELIGHT(MAX_ACTIVE_LIGHTS - 1))
 
 struct StateEntry
 {
-- 
1.4.4.3



More information about the wine-patches mailing list