wined3d: Improve float constant loading a bit.

- Use a list to keep track of what constants are set.
- Move TRACEs and checkGLcall calls out of the main constant loading loop.
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 7aa6691..7a3fb70 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -8,6 +8,7 @@
  * Copyright 2005 Oliver Stieber
  * Copyright 2006 Ivan Gyurdiev
  * Copyright 2006 Jason Green
+ * Copyright 2006 Henri Verbeet
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -41,48 +42,57 @@
 
 /** 
  * Loads floating point constants into the currently set ARB_vertex/fragment_program.
- * When @constants_set == NULL, it will load all the constants.
+ * When constant_list == NULL, it will load all the constants.
  *  
  * @target_type should be either GL_VERTEX_PROGRAM_ARB (for vertex shaders)
  *  or GL_FRAGMENT_PROGRAM_ARB (for pixel shaders)
  */
-void shader_arb_load_constantsF(
-    IWineD3DBaseShaderImpl* This,
-    WineD3D_GL_Info *gl_info,
-    GLuint target_type,
-    unsigned max_constants,
-    float* constants,
-    BOOL* constants_set) {
-
+static void shader_arb_load_constantsF(IWineD3DBaseShaderImpl* This, WineD3D_GL_Info *gl_info, GLuint target_type,
+        unsigned int max_constants, float* constants, struct list *constant_list) {
+    constant_entry *constant;
+    local_constant* lconst;
     int i;
-    struct list* ptr;
-    
-    for (i=0; i<max_constants; ++i) {
-        if (NULL == constants_set || constants_set[i]) {
-            TRACE("Loading constants %i: %f, %f, %f, %f\n", i,
-                  constants[i * 4 + 0], constants[i * 4 + 1],
-                  constants[i * 4 + 2], constants[i * 4 + 3]);
 
-            GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, &constants[i * 4]));
-            checkGLcall("glProgramEnvParameter4fvARB");
+    if (!constant_list) {
+        if (TRACE_ON(d3d_shader)) {
+            for (i = 0; i < max_constants; ++i) {
+                TRACE("Loading constants %i: %f, %f, %f, %f\n", i,
+                        constants[i * 4 + 0], constants[i * 4 + 1],
+                        constants[i * 4 + 2], constants[i * 4 + 3]);
+            }
         }
+        for (i = 0; i < max_constants; ++i) {
+            GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, constants + (i * 4)));
+        }
+        checkGLcall("glProgramEnvParameter4fvARB()");
+    } else {
+        if (TRACE_ON(d3d_shader)) {
+            LIST_FOR_EACH_ENTRY(constant, constant_list, constant_entry, entry) {
+                i = constant->idx;
+                TRACE("Loading constants %i: %f, %f, %f, %f\n", i,
+                        constants[i * 4 + 0], constants[i * 4 + 1],
+                        constants[i * 4 + 2], constants[i * 4 + 3]);
+            }
+        }
+        LIST_FOR_EACH_ENTRY(constant, constant_list, constant_entry, entry) {
+            i = constant->idx;
+            GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, constants + (i * 4)));
+        }
+        checkGLcall("glProgramEnvParameter4fvARB()");
     }
 
     /* Load immediate constants */
-    ptr = list_head(&This->baseShader.constantsF);
-    while (ptr) {
-
-        local_constant* lconst = LIST_ENTRY(ptr, struct local_constant, entry);
-        unsigned int idx = lconst->idx;
-        GLfloat* values = (GLfloat*) lconst->value;
-
-        TRACE("Loading local constants %i: %f, %f, %f, %f\n", idx,
-            values[0], values[1], values[2], values[3]);
-
-        GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, idx, values));
-        checkGLcall("glProgramEnvParameter4fvARB");
-        ptr = list_next(&This->baseShader.constantsF, ptr);
+    if (TRACE_ON(d3d_shader)) {
+        LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
+            GLfloat* values = (GLfloat*)lconst->value;
+            TRACE("Loading local constants %i: %f, %f, %f, %f\n", lconst->idx,
+                    values[0], values[1], values[2], values[3]);
+        }
     }
+    LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
+        GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, lconst->idx, (GLfloat*)lconst->value));
+    }
+    checkGLcall("glProgramEnvParameter4fvARB()");
 }
 
 /**
@@ -116,7 +126,7 @@
         shader_arb_load_constantsF(vshader, gl_info, GL_VERTEX_PROGRAM_ARB,
                                    GL_LIMITS(vshader_constantsF),
                                    stateBlock->vertexShaderConstantF,
-                                   stateBlock->set.vertexShaderConstantsF);
+                                   &stateBlock->set_vconstantsF);
     }
 
     if (usePixelShader) {
@@ -127,7 +137,7 @@
         shader_arb_load_constantsF(pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB, 
                                    GL_LIMITS(pshader_constantsF),
                                    stateBlock->pixelShaderConstantF,
-                                   stateBlock->set.pixelShaderConstantsF);
+                                   &stateBlock->set_pconstantsF);
     }
 }
 
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 75c8a6d..5e303a2 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -4882,8 +4882,13 @@
            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
 
     for (i = start; i < cnt + start; ++i) {
+        if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
+            constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
+            ptr->idx = i;
+            list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
+            This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
+        }
         This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
-        This->updateStateBlock->set.vertexShaderConstantsF[i]     = TRUE;
     }
 
     return WINED3D_OK;
@@ -5064,8 +5069,13 @@
            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
 
     for (i = start; i < cnt + start; ++i) {
+        if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
+            constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
+            ptr->idx = i;
+            list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
+            This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
+        }
         This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
-        This->updateStateBlock->set.pixelShaderConstantsF[i]     = TRUE;
     }
 
     return WINED3D_OK;
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 3c1d9ad..2ff147c 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -76,49 +76,77 @@
 
 /** 
  * Loads floating point constants (aka uniforms) into the currently set GLSL program.
- * When @constants_set == NULL, it will load all the constants.
+ * When constant_list == NULL, it will load all the constants.
  */
-void shader_glsl_load_constantsF(IWineD3DBaseShaderImpl* This, WineD3D_GL_Info *gl_info,
+static void shader_glsl_load_constantsF(IWineD3DBaseShaderImpl* This, WineD3D_GL_Info *gl_info,
         unsigned int max_constants, float* constants, GLhandleARB *constant_locations,
-        BOOL* constants_set) {
+        struct list *constant_list) {
+    local_constant* lconst;
     GLhandleARB tmp_loc;
     int i;
-    struct list* ptr;
 
-    for (i=0; i<max_constants; ++i) {
-        if (NULL == constants_set || constants_set[i]) {
-
-            TRACE("Loading constants %i: %f, %f, %f, %f\n", i,
-                  constants[i * 4 + 0], constants[i * 4 + 1],
-                  constants[i * 4 + 2], constants[i * 4 + 3]);
-
+    if (!constant_list) {
+        if (TRACE_ON(d3d_shader)) {
+            for (i = 0; i < max_constants; ++i) {
+                tmp_loc = constant_locations[i];
+                if (tmp_loc != -1) {
+                    TRACE("Loading constants %i: %f, %f, %f, %f\n", i,
+                            constants[i * 4 + 0], constants[i * 4 + 1],
+                            constants[i * 4 + 2], constants[i * 4 + 3]);
+                }
+            }
+        }
+        for (i = 0; i < max_constants; ++i) {
             tmp_loc = constant_locations[i];
             if (tmp_loc != -1) {
                 /* We found this uniform name in the program - go ahead and send the data */
-                GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, &constants[i * 4]));
-                checkGLcall("glUniform4fvARB");
+                GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, constants + (i * 4)));
             }
         }
+        checkGLcall("glUniform4fvARB()");
+    } else {
+        constant_entry *constant;
+        if (TRACE_ON(d3d_shader)) {
+            LIST_FOR_EACH_ENTRY(constant, constant_list, constant_entry, entry) {
+                i = constant->idx;
+                tmp_loc = constant_locations[i];
+                if (tmp_loc != -1) {
+                    TRACE("Loading constants %i: %f, %f, %f, %f\n", i,
+                            constants[i * 4 + 0], constants[i * 4 + 1],
+                            constants[i * 4 + 2], constants[i * 4 + 3]);
+                }
+            }
+        }
+        LIST_FOR_EACH_ENTRY(constant, constant_list, constant_entry, entry) {
+            i = constant->idx;
+            tmp_loc = constant_locations[i];
+            if (tmp_loc != -1) {
+                /* We found this uniform name in the program - go ahead and send the data */
+                GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, constants + (i * 4)));
+            }
+        }
+        checkGLcall("glUniform4fvARB()");
     }
 
     /* Load immediate constants */
-    ptr = list_head(&This->baseShader.constantsF);
-    while (ptr) {
-        local_constant* lconst = LIST_ENTRY(ptr, struct local_constant, entry);
-        unsigned int idx = lconst->idx;
-        GLfloat* values = (GLfloat*) lconst->value;
-
-        TRACE("Loading local constants %i: %f, %f, %f, %f\n", idx,
-            values[0], values[1], values[2], values[3]);
-
-        tmp_loc = constant_locations[idx];
+    if (TRACE_ON(d3d_shader)) {
+        LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
+            tmp_loc = constant_locations[lconst->idx];
+            if (tmp_loc != -1) {
+                GLfloat* values = (GLfloat*)lconst->value;
+                TRACE("Loading local constants %i: %f, %f, %f, %f\n", lconst->idx,
+                        values[0], values[1], values[2], values[3]);
+            }
+        }
+    }
+    LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
+        tmp_loc = constant_locations[lconst->idx];
         if (tmp_loc != -1) {
             /* We found this uniform name in the program - go ahead and send the data */
-            GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, values));
-            checkGLcall("glUniform4fvARB");
+            GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, (GLfloat*)lconst->value));
         }
-        ptr = list_next(&This->baseShader.constantsF, ptr);
     }
+    checkGLcall("glUniform4fvARB()");
 }
 
 /** 
@@ -248,6 +276,7 @@
     IWineD3DStateBlockImpl* stateBlock = (IWineD3DStateBlockImpl*) iface;
     WineD3D_GL_Info *gl_info = &((IWineD3DImpl*)stateBlock->wineD3DDevice->wineD3D)->gl_info;
     GLhandleARB *constant_locations;
+    struct list *constant_list;
     GLhandleARB programId;
     
     if (!stateBlock->glsl_program) {
@@ -264,6 +293,7 @@
             (IWineD3DVertexDeclarationImpl*) vshader_impl->vertexDeclaration;
 
         constant_locations = stateBlock->glsl_program->vuniformF_locations;
+        constant_list = &stateBlock->set_vconstantsF;
 
         if (NULL != vertexDeclaration && NULL != vertexDeclaration->constants) {
             /* Load DirectX 8 float constants/uniforms for vertex shader */
@@ -273,7 +303,7 @@
 
         /* Load DirectX 9 float constants/uniforms for vertex shader */
         shader_glsl_load_constantsF(vshader, gl_info, GL_LIMITS(vshader_constantsF),
-                stateBlock->vertexShaderConstantF, constant_locations, stateBlock->set.vertexShaderConstantsF);
+                stateBlock->vertexShaderConstantF, constant_locations, constant_list);
 
         /* Load DirectX 9 integer constants/uniforms for vertex shader */
         shader_glsl_load_constantsI(vshader, gl_info, programId, MAX_CONST_I,
@@ -291,13 +321,14 @@
         IWineD3DBaseShaderImpl* pshader = (IWineD3DBaseShaderImpl*) stateBlock->pixelShader;
 
         constant_locations = stateBlock->glsl_program->puniformF_locations;
+        constant_list = &stateBlock->set_pconstantsF;
 
         /* Load pixel shader samplers */
         shader_glsl_load_psamplers(gl_info, iface);
 
         /* Load DirectX 9 float constants/uniforms for pixel shader */
         shader_glsl_load_constantsF(pshader, gl_info, GL_LIMITS(pshader_constantsF),
-                stateBlock->pixelShaderConstantF, constant_locations, stateBlock->set.pixelShaderConstantsF);
+                stateBlock->pixelShaderConstantF, constant_locations, constant_list);
 
         /* Load DirectX 9 integer constants/uniforms for pixel shader */
         shader_glsl_load_constantsI(pshader, gl_info, programId, MAX_CONST_I,
diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c
index 6dde429..823bc7a 100644
--- a/dlls/wined3d/stateblock.c
+++ b/dlls/wined3d/stateblock.c
@@ -53,6 +53,9 @@
     object->changed.vertexShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BOOL) * GL_LIMITS(vshader_constantsF));
     WINED3D_MEMCHECK(object->changed.vertexShaderConstantsF);
 
+    list_init(&object->set_vconstantsF);
+    list_init(&object->set_pconstantsF);
+
 #undef WINED3D_MEMCHECK
 
     return WINED3D_OK;
@@ -225,6 +228,8 @@
     TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
 
     if (!refCount) {
+        constant_entry *constant, *constant2;
+
         /* type 0 represents the primary stateblock, so free all the resources */
         if (This->blockType == WINED3DSBT_INIT) {
             int counter;
@@ -274,6 +279,14 @@
         HeapFree(GetProcessHeap(), 0, This->set.pixelShaderConstantsF);
         HeapFree(GetProcessHeap(), 0, This->changed.pixelShaderConstantsF);
 
+        LIST_FOR_EACH_ENTRY_SAFE(constant, constant2, &This->set_vconstantsF, constant_entry, entry) {
+            HeapFree(GetProcessHeap(), 0, constant);
+        }
+
+        LIST_FOR_EACH_ENTRY_SAFE(constant, constant2, &This->set_pconstantsF, constant_entry, entry) {
+            HeapFree(GetProcessHeap(), 0, constant);
+        }
+
         HeapFree(GetProcessHeap(), 0, This);
     }
     return refCount;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index bfa7510..5d7af02 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1040,6 +1040,11 @@
         BOOL                     *vertexShaderConstantsF;
 } SAVEDSTATES;
 
+typedef struct {
+    struct list entry;
+    int idx;
+} constant_entry;
+
 struct IWineD3DStateBlockImpl
 {
     /* IUnknown fields */
@@ -1054,6 +1059,8 @@
     /* Array indicating whether things have been set or changed */
     SAVEDSTATES               changed;
     SAVEDSTATES               set;
+    struct list               set_vconstantsF;
+    struct list               set_pconstantsF;
 
     /* Drawing - Vertex Shader or FVF related */
     DWORD                     fvf;