- sync wined3d with wine HEAD
authorKamil Hornicek <kamil.hornicek@reactos.org>
Sun, 18 Jan 2009 21:09:22 +0000 (21:09 +0000)
committerKamil Hornicek <kamil.hornicek@reactos.org>
Sun, 18 Jan 2009 21:09:22 +0000 (21:09 +0000)
svn path=/trunk/; revision=38914

34 files changed:
reactos/dll/directx/wine/wined3d/arb_program_shader.c
reactos/dll/directx/wine/wined3d/ati_fragment_shader.c
reactos/dll/directx/wine/wined3d/baseshader.c
reactos/dll/directx/wine/wined3d/basetexture.c
reactos/dll/directx/wine/wined3d/context.c
reactos/dll/directx/wine/wined3d/cubetexture.c
reactos/dll/directx/wine/wined3d/device.c
reactos/dll/directx/wine/wined3d/directx.c
reactos/dll/directx/wine/wined3d/drawprim.c
reactos/dll/directx/wine/wined3d/gl_compat.c [new file with mode: 0644]
reactos/dll/directx/wine/wined3d/glsl_shader.c
reactos/dll/directx/wine/wined3d/indexbuffer.c
reactos/dll/directx/wine/wined3d/nvidia_texture_shader.c
reactos/dll/directx/wine/wined3d/palette.c
reactos/dll/directx/wine/wined3d/pixelshader.c
reactos/dll/directx/wine/wined3d/query.c
reactos/dll/directx/wine/wined3d/resource.c
reactos/dll/directx/wine/wined3d/state.c
reactos/dll/directx/wine/wined3d/stateblock.c
reactos/dll/directx/wine/wined3d/surface.c
reactos/dll/directx/wine/wined3d/surface_base.c
reactos/dll/directx/wine/wined3d/surface_gdi.c
reactos/dll/directx/wine/wined3d/texture.c
reactos/dll/directx/wine/wined3d/utils.c
reactos/dll/directx/wine/wined3d/vertexbuffer.c
reactos/dll/directx/wine/wined3d/vertexdeclaration.c
reactos/dll/directx/wine/wined3d/vertexshader.c
reactos/dll/directx/wine/wined3d/volume.c
reactos/dll/directx/wine/wined3d/volumetexture.c
reactos/dll/directx/wine/wined3d/wined3d.rbuild
reactos/dll/directx/wine/wined3d/wined3d_gl.h
reactos/dll/directx/wine/wined3d/wined3d_main.c
reactos/dll/directx/wine/wined3d/wined3d_private.h
reactos/include/reactos/wine/wined3d.idl

index 9d51250..7ff3cd4 100644 (file)
@@ -70,6 +70,7 @@ struct shader_arb_priv {
 static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl* This, const WineD3D_GL_Info *gl_info,
         GLuint target_type, unsigned int max_constants, const float *constants, char *dirty_consts)
 {
+    DWORD shader_version = This->baseShader.reg_maps.shader_version;
     local_constant* lconst;
     DWORD i, j;
     unsigned int ret;
@@ -83,8 +84,8 @@ static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl* This, con
         }
     }
     /* In 1.X pixel shaders constants are implicitly clamped in the range [-1;1] */
-    if(target_type == GL_FRAGMENT_PROGRAM_ARB &&
-       WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1) {
+    if (target_type == GL_FRAGMENT_PROGRAM_ARB && WINED3DSHADER_VERSION_MAJOR(shader_version) == 1)
+    {
         float lcl_const[4];
         for(i = 0; i < max_constants; i++) {
             if(!dirty_consts[i]) continue;
@@ -225,6 +226,28 @@ static void shader_arb_load_constants(
     }
 }
 
+static void shader_arb_update_float_vertex_constants(IWineD3DDevice *iface, UINT start, UINT count)
+{
+    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+
+    /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
+     * context. On a context switch the old context will be fully dirtified */
+    memset(This->activeContext->vshader_const_dirty + start, 1,
+            sizeof(*This->activeContext->vshader_const_dirty) * count);
+    This->highest_dirty_vs_const = max(This->highest_dirty_vs_const, start + count + 1);
+}
+
+static void shader_arb_update_float_pixel_constants(IWineD3DDevice *iface, UINT start, UINT count)
+{
+    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+
+    /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
+     * context. On a context switch the old context will be fully dirtified */
+    memset(This->activeContext->pshader_const_dirty + start, 1,
+            sizeof(*This->activeContext->pshader_const_dirty) * count);
+    This->highest_dirty_ps_const = max(This->highest_dirty_ps_const, start + count + 1);
+}
+
 /* Generate the variable & register declarations for the ARB_vertex_program output target */
 static void shader_generate_arb_declarations(IWineD3DBaseShader *iface, const shader_reg_maps *reg_maps,
         SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_info)
@@ -232,7 +255,7 @@ static void shader_generate_arb_declarations(IWineD3DBaseShader *iface, const sh
     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device;
     DWORD i, cur;
-    char pshader = shader_is_pshader_version(This->baseShader.hex_version);
+    char pshader = shader_is_pshader_version(reg_maps->shader_version);
     unsigned max_constantsF = min(This->baseShader.limits.constant_float, 
             (pshader ? GL_LIMITS(pshader_constantsF) : GL_LIMITS(vshader_constantsF)));
     UINT extra_constants_needed = 0;
@@ -291,7 +314,7 @@ static void shader_generate_arb_declarations(IWineD3DBaseShader *iface, const sh
                 FIXME("No free constant to load the luminance parameters\n");
             }
         } else {
-            FIXME("No free constant found to load environemnt bump mapping matrix into the shader. texbem instruction will not apply bump mapping\n");
+            FIXME("No free constant found to load environment bump mapping matrix into the shader. texbem instruction will not apply bump mapping\n");
         }
 
         ps->numbumpenvmatconsts = cur + 1;
@@ -360,9 +383,8 @@ static const char * const shift_tab[] = {
 
 static void shader_arb_get_write_mask(const SHADER_OPCODE_ARG *arg, const DWORD param, char *write_mask)
 {
-    IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *) arg->shader;
     char *ptr = write_mask;
-    char vshader = shader_is_vshader_version(This->baseShader.hex_version);
+    char vshader = shader_is_vshader_version(arg->reg_maps->shader_version);
 
     if(vshader && shader_get_regtype(param) == WINED3DSPR_ADDR) {
         *ptr++ = '.';
@@ -488,8 +510,7 @@ static void vshader_program_add_param(const SHADER_OPCODE_ARG *arg, const DWORD
     break;
   case WINED3DSPR_INPUT:
 
-    if (vshader_input_is_color((IWineD3DVertexShader*) This, reg))
-        is_color = TRUE;
+    if (This->swizzle_map & (1 << reg)) is_color = TRUE;
 
     sprintf(tmpReg, "vertex.attrib[%u]", reg);
     strcat(hwLine, tmpReg);
@@ -787,7 +808,6 @@ static void pshader_hw_bem(const SHADER_OPCODE_ARG *arg)
 
 static void pshader_hw_cnd(const SHADER_OPCODE_ARG *arg)
 {
-    IWineD3DBaseShaderImpl* shader = (IWineD3DBaseShaderImpl*) arg->shader;
     SHADER_BUFFER* buffer = arg->buffer;
     char dst_wmask[20];
     char dst_name[50];
@@ -807,8 +827,8 @@ static void pshader_hw_cnd(const SHADER_OPCODE_ARG *arg)
     pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[2], 2, src_name[2]);
 
     /* The coissue flag changes the semantic of the cnd instruction in <= 1.3 shaders */
-    if (shader->baseShader.hex_version <= WINED3DPS_VERSION(1, 3) &&
-        arg->opcode_token & WINED3DSI_COISSUE) {
+    if (arg->reg_maps->shader_version <= WINED3DPS_VERSION(1, 3) && arg->opcode_token & WINED3DSI_COISSUE)
+    {
         shader_addline(buffer, "MOV%s %s%s, %s;\n", sat ? "_SAT" : "", dst_name, dst_wmask, src_name[1]);
     } else {
         shader_addline(buffer, "ADD TMP, -%s, coefdiv.x;\n", src_name[0]);
@@ -877,15 +897,45 @@ static void pshader_hw_dp2add(const SHADER_OPCODE_ARG *arg)
 /* Map the opcode 1-to-1 to the GL code */
 static void shader_hw_map2gl(const SHADER_OPCODE_ARG *arg)
 {
-    IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl*)arg->shader;
     CONST SHADER_OPCODE* curOpcode = arg->opcode;
     SHADER_BUFFER* buffer = arg->buffer;
     DWORD dst = arg->dst;
     const DWORD *src = arg->src;
+    const char *instruction;
     char arguments[256];
     unsigned int i;
 
-    if (shader_is_pshader_version(shader->baseShader.hex_version))
+    switch (curOpcode->opcode)
+    {
+        case WINED3DSIO_ABS: instruction = "ABS"; break;
+        case WINED3DSIO_ADD: instruction = "ADD"; break;
+        case WINED3DSIO_CRS: instruction = "XPD"; break;
+        case WINED3DSIO_DP3: instruction = "DP3"; break;
+        case WINED3DSIO_DP4: instruction = "DP4"; break;
+        case WINED3DSIO_DST: instruction = "DST"; break;
+        case WINED3DSIO_EXP: instruction = "EX2"; break;
+        case WINED3DSIO_EXPP: instruction = "EXP"; break;
+        case WINED3DSIO_FRC: instruction = "FRC"; break;
+        case WINED3DSIO_LIT: instruction = "LIT"; break;
+        case WINED3DSIO_LOG: instruction = "LG2"; break;
+        case WINED3DSIO_LOGP: instruction = "LOG"; break;
+        case WINED3DSIO_LRP: instruction = "LRP"; break;
+        case WINED3DSIO_MAD: instruction = "MAD"; break;
+        case WINED3DSIO_MAX: instruction = "MAX"; break;
+        case WINED3DSIO_MIN: instruction = "MIN"; break;
+        case WINED3DSIO_MOV: instruction = "MOV"; break;
+        case WINED3DSIO_MUL: instruction = "MUL"; break;
+        case WINED3DSIO_NOP: instruction = "NOP"; break;
+        case WINED3DSIO_POW: instruction = "POW"; break;
+        case WINED3DSIO_SGE: instruction = "SGE"; break;
+        case WINED3DSIO_SLT: instruction = "SLT"; break;
+        case WINED3DSIO_SUB: instruction = "SUB"; break;
+        default: instruction = "";
+            FIXME("Unhandled opcode %s\n", curOpcode->name);
+            break;
+    }
+
+    if (shader_is_pshader_version(arg->reg_maps->shader_version))
     {
         /* Output token related */
         char output_rname[256];
@@ -938,7 +988,7 @@ static void shader_hw_map2gl(const SHADER_OPCODE_ARG *arg)
             strcat(arguments, ", ");
             strcat(arguments, operands[i]);
         }
-        shader_addline(buffer, "%s%s %s;\n", curOpcode->glname, modifier, arguments);
+        shader_addline(buffer, "%s%s %s;\n", instruction, modifier, arguments);
 
         /* A shift requires another line. */
         if (shift) pshader_gen_output_modifier_line(buffer, saturate, output_wmask, shift, output_rname);
@@ -955,7 +1005,7 @@ static void shader_hw_map2gl(const SHADER_OPCODE_ARG *arg)
                 vshader_program_add_param(arg, src[i-1], TRUE, arguments);
             }
         }
-        shader_addline(buffer, "%s%s;\n", curOpcode->glname, arguments);
+        shader_addline(buffer, "%s%s;\n", instruction, arguments);
     }
 }
 
@@ -963,8 +1013,8 @@ static void shader_hw_mov(const SHADER_OPCODE_ARG *arg)
 {
     IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl*)arg->shader;
 
-    if ((WINED3DSHADER_VERSION_MAJOR(shader->baseShader.hex_version) == 1
-            && !shader_is_pshader_version(shader->baseShader.hex_version)
+    if ((WINED3DSHADER_VERSION_MAJOR(arg->reg_maps->shader_version) == 1
+            && !shader_is_pshader_version(arg->reg_maps->shader_version)
             && shader_get_regtype(arg->dst) == WINED3DSPR_ADDR)
             || arg->opcode->opcode == WINED3DSIO_MOVA)
     {
@@ -1008,8 +1058,7 @@ static void shader_hw_mov(const SHADER_OPCODE_ARG *arg)
 
 static void pshader_hw_texkill(const SHADER_OPCODE_ARG *arg)
 {
-    IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
-    DWORD hex_version = This->baseShader.hex_version;
+    DWORD shader_version = arg->reg_maps->shader_version;
     SHADER_BUFFER* buffer = arg->buffer;
     char reg_dest[40];
 
@@ -1018,7 +1067,8 @@ static void pshader_hw_texkill(const SHADER_OPCODE_ARG *arg)
      */
     pshader_get_register_name(arg->shader, arg->dst, reg_dest);
 
-    if(hex_version >= WINED3DPS_VERSION(2,0)) {
+    if (shader_version >= WINED3DPS_VERSION(2,0))
+    {
         /* The arb backend doesn't claim ps 2.0 support, but try to eat what the app feeds to us */
         shader_addline(buffer, "KIL %s;\n", reg_dest);
     } else {
@@ -1039,7 +1089,7 @@ static void pshader_hw_tex(const SHADER_OPCODE_ARG *arg)
     DWORD dst = arg->dst;
     const DWORD *src = arg->src;
     SHADER_BUFFER* buffer = arg->buffer;
-    DWORD hex_version = This->baseShader.hex_version;
+    DWORD shader_version = arg->reg_maps->shader_version;
     BOOL projected = FALSE, bias = FALSE;
 
     char reg_dest[40];
@@ -1053,14 +1103,14 @@ static void pshader_hw_tex(const SHADER_OPCODE_ARG *arg)
 
     /* 1.0-1.3: Use destination register as coordinate source.
        1.4+: Use provided coordinate source register. */
-   if (hex_version < WINED3DPS_VERSION(1,4))
+   if (shader_version < WINED3DPS_VERSION(1,4))
       strcpy(reg_coord, reg_dest);
    else
       pshader_gen_input_modifier_line(arg->shader, buffer, src[0], 0, reg_coord);
 
   /* 1.0-1.4: Use destination register number as texture code.
      2.0+: Use provided sampler number as texure code. */
-  if (hex_version < WINED3DPS_VERSION(2,0))
+  if (shader_version < WINED3DPS_VERSION(2,0))
      reg_sampler_code = reg_dest_code;
   else
      reg_sampler_code = src[1] & WINED3DSP_REGNUM_MASK;
@@ -1070,7 +1120,8 @@ static void pshader_hw_tex(const SHADER_OPCODE_ARG *arg)
    * 1.4: Use WINED3DSPSM_DZ or WINED3DSPSM_DW on src[0]
    * 2.0+: Use WINED3DSI_TEXLD_PROJECT on the opcode
    */
-  if(hex_version < WINED3DPS_VERSION(1,4)) {
+  if (shader_version < WINED3DPS_VERSION(1,4))
+  {
       DWORD flags = 0;
       if(reg_sampler_code < MAX_TEXTURES) {
         flags = deviceImpl->stateBlock->textureState[reg_sampler_code][WINED3DTSS_TEXTURETRANSFORMFLAGS];
@@ -1078,7 +1129,9 @@ static void pshader_hw_tex(const SHADER_OPCODE_ARG *arg)
       if (flags & WINED3DTTFF_PROJECTED) {
           projected = TRUE;
       }
-  } else if(hex_version < WINED3DPS_VERSION(2,0)) {
+  }
+  else if (shader_version < WINED3DPS_VERSION(2,0))
+  {
       DWORD src_mod = arg->src[0] & WINED3DSP_SRCMOD_MASK;
       if (src_mod == WINED3DSPSM_DZ) {
           projected = TRUE;
@@ -1098,14 +1151,13 @@ static void pshader_hw_tex(const SHADER_OPCODE_ARG *arg)
 
 static void pshader_hw_texcoord(const SHADER_OPCODE_ARG *arg)
 {
-    IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
     DWORD dst = arg->dst;
     SHADER_BUFFER* buffer = arg->buffer;
-    DWORD hex_version = This->baseShader.hex_version;
 
     char tmp[20];
     shader_arb_get_write_mask(arg, dst, tmp);
-    if (hex_version != WINED3DPS_VERSION(1,4)) {
+    if (arg->reg_maps->shader_version != WINED3DPS_VERSION(1,4))
+    {
         DWORD reg = dst & WINED3DSP_REGNUM_MASK;
         shader_addline(buffer, "MOV_SAT T%u%s, fragment.texcoord[%u];\n", reg, tmp, reg);
     } else {
@@ -1130,8 +1182,8 @@ static void pshader_hw_texreg2ar(const SHADER_OPCODE_ARG *arg)
 
      sprintf(dst_str, "T%u", reg1);
      pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src_str);
-     shader_addline(buffer, "MOV TMP.r, %s.a;\n", src_str);
-     shader_addline(buffer, "MOV TMP.g, %s.r;\n", src_str);
+     shader_addline(buffer, "MOV TMP.x, %s.w;\n", src_str);
+     shader_addline(buffer, "MOV TMP.y, %s.x;\n", src_str);
      flags = reg1 < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg1][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0;
      shader_hw_sample(arg, reg1, dst_str, "TMP", flags & WINED3DTTFF_PROJECTED, FALSE);
 }
@@ -1146,8 +1198,8 @@ static void pshader_hw_texreg2gb(const SHADER_OPCODE_ARG *arg)
 
      sprintf(dst_str, "T%u", reg1);
      pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src_str);
-     shader_addline(buffer, "MOV TMP.r, %s.g;\n", src_str);
-     shader_addline(buffer, "MOV TMP.g, %s.b;\n", src_str);
+     shader_addline(buffer, "MOV TMP.x, %s.y;\n", src_str);
+     shader_addline(buffer, "MOV TMP.y, %s.z;\n", src_str);
      shader_hw_sample(arg, reg1, dst_str, "TMP", FALSE, FALSE);
 }
 
@@ -1199,20 +1251,20 @@ static void pshader_hw_texbem(const SHADER_OPCODE_ARG *arg)
         /* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed */
 
         shader_addline(buffer, "SWZ TMP2, bumpenvmat%d, x, z, 0, 0;\n", reg_dest_code);
-        shader_addline(buffer, "DP3 TMP.r, TMP2, T%u;\n", src);
+        shader_addline(buffer, "DP3 TMP.x, TMP2, T%u;\n", src);
         shader_addline(buffer, "SWZ TMP2, bumpenvmat%d, y, w, 0, 0;\n", reg_dest_code);
-        shader_addline(buffer, "DP3 TMP.g, TMP2, T%u;\n", src);
+        shader_addline(buffer, "DP3 TMP.y, TMP2, T%u;\n", src);
 
         /* with projective textures, texbem only divides the static texture coord, not the displacement,
          * so we can't let the GL handle this.
          */
         if (((IWineD3DDeviceImpl*) This->baseShader.device)->stateBlock->textureState[reg_dest_code][WINED3DTSS_TEXTURETRANSFORMFLAGS]
               & WINED3DTTFF_PROJECTED) {
-            shader_addline(buffer, "RCP TMP2.a, %s.a;\n", reg_coord);
-            shader_addline(buffer, "MUL TMP2.rg, %s, TMP2.a;\n", reg_coord);
-            shader_addline(buffer, "ADD TMP.rg, TMP, TMP2;\n");
+            shader_addline(buffer, "RCP TMP2.w, %s.w;\n", reg_coord);
+            shader_addline(buffer, "MUL TMP2.xy, %s, TMP2.w;\n", reg_coord);
+            shader_addline(buffer, "ADD TMP.xy, TMP, TMP2;\n");
         } else {
-            shader_addline(buffer, "ADD TMP.rg, TMP, %s;\n", reg_coord);
+            shader_addline(buffer, "ADD TMP.xy, TMP, %s;\n", reg_coord);
         }
 
         shader_hw_sample(arg, reg_dest_code, reg_coord, "TMP", FALSE, FALSE);
@@ -1384,15 +1436,15 @@ static void pshader_hw_texdepth(const SHADER_OPCODE_ARG *arg)
     /* According to the msdn, the source register(must be r5) is unusable after
      * the texdepth instruction, so we're free to modify it
      */
-    shader_addline(buffer, "MIN %s.g, %s.g, one.g;\n", dst_name, dst_name);
+    shader_addline(buffer, "MIN %s.y, %s.y, one.y;\n", dst_name, dst_name);
 
     /* How to deal with the special case dst_name.g == 0? if r != 0, then
      * the r * (1 / 0) will give infinity, which is clamped to 1.0, the correct
      * result. But if r = 0.0, then 0 * inf = 0, which is incorrect.
      */
-    shader_addline(buffer, "RCP %s.g, %s.g;\n", dst_name, dst_name);
-    shader_addline(buffer, "MUL TMP.x, %s.r, %s.g;\n", dst_name, dst_name);
-    shader_addline(buffer, "MIN TMP.x, TMP.x, one.r;\n");
+    shader_addline(buffer, "RCP %s.y, %s.y;\n", dst_name, dst_name);
+    shader_addline(buffer, "MUL TMP.x, %s.x, %s.y;\n", dst_name, dst_name);
+    shader_addline(buffer, "MIN TMP.x, TMP.x, one.x;\n");
     shader_addline(buffer, "MAX result.depth, TMP.x, 0.0;\n");
 }
 
@@ -1474,7 +1526,7 @@ static void pshader_hw_texm3x2depth(const SHADER_OPCODE_ARG *arg)
      */
     shader_addline(buffer, "RCP TMP.y, TMP.y;\n");
     shader_addline(buffer, "MUL TMP.x, TMP.x, TMP.y;\n");
-    shader_addline(buffer, "MIN TMP.x, TMP.x, one.r;\n");
+    shader_addline(buffer, "MIN TMP.x, TMP.x, one.x;\n");
     shader_addline(buffer, "MAX result.depth, TMP.x, 0.0;\n");
 }
 
@@ -1487,7 +1539,7 @@ static void shader_hw_mnxn(const SHADER_OPCODE_ARG *arg)
     SHADER_OPCODE_ARG tmpArg;
     IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)arg->shader;
     const SHADER_OPCODE *opcode_table = shader->baseShader.shader_ins;
-    DWORD shader_version = shader->baseShader.hex_version;
+    DWORD shader_version = arg->reg_maps->shader_version;
 
     memset(&tmpArg, 0, sizeof(SHADER_OPCODE_ARG));
 
@@ -1538,10 +1590,20 @@ static void vshader_hw_rsq_rcp(const SHADER_OPCODE_ARG *arg)
     DWORD dst = arg->dst;
     DWORD src = arg->src[0];
     DWORD swizzle = (src & WINED3DSP_SWIZZLE_MASK) >> WINED3DSP_SWIZZLE_SHIFT;
+    const char *instruction;
 
     char tmpLine[256];
 
-    strcpy(tmpLine, curOpcode->glname); /* Opcode */
+    switch(curOpcode->opcode)
+    {
+        case WINED3DSIO_RSQ: instruction = "RSQ"; break;
+        case WINED3DSIO_RCP: instruction = "RCP"; break;
+        default: instruction = "";
+            FIXME("Unhandled opcode %s\n", curOpcode->name);
+            break;
+    }
+
+    strcpy(tmpLine, instruction);
     vshader_program_add_param(arg, dst, FALSE, tmpLine); /* Destination */
     strcat(tmpLine, ",");
     vshader_program_add_param(arg, src, TRUE, tmpLine);
@@ -1631,7 +1693,7 @@ static GLuint create_arb_blt_vertex_program(const WineD3D_GL_Info *gl_info)
 static GLuint create_arb_blt_fragment_program(const WineD3D_GL_Info *gl_info, enum tex_types tex_type)
 {
     GLuint program_id = 0;
-    const char *blt_fprograms[tex_type_count] =
+    static const char * const blt_fprograms[tex_type_count] =
     {
         /* tex_1d */
         NULL,
@@ -1777,19 +1839,12 @@ static void shader_arb_deselect_depth_blt(IWineD3DDevice *iface) {
     }
 }
 
-static void shader_arb_cleanup(IWineD3DDevice *iface) {
-    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-    const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
-    if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) glDisable(GL_VERTEX_PROGRAM_ARB);
-    if (GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) glDisable(GL_FRAGMENT_PROGRAM_ARB);
-}
-
 static void shader_arb_destroy(IWineD3DBaseShader *iface) {
     IWineD3DBaseShaderImpl *baseShader = (IWineD3DBaseShaderImpl *) iface;
     const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)baseShader->baseShader.device)->adapter->gl_info;
-    char pshader = shader_is_pshader_version(baseShader->baseShader.hex_version);
 
-    if(pshader) {
+    if (shader_is_pshader_version(baseShader->baseShader.reg_maps.shader_version))
+    {
         IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *) iface;
         UINT i;
 
@@ -1864,18 +1919,35 @@ static void arbfp_add_sRGB_correction(SHADER_BUFFER *buffer, const char *fragcol
     /* [0.0;1.0] clamping. Not needed, this is done implicitly */
 }
 
-static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer) {
+static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer, const struct ps_compile_args *args) {
     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
     const shader_reg_maps* reg_maps = &This->baseShader.reg_maps;
     CONST DWORD *function = This->baseShader.function;
-    const char *fragcolor;
+    DWORD shader_version = reg_maps->shader_version;
     const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info;
     const local_constant *lconst;
     GLuint retval;
+    const char *fragcolor;
 
     /*  Create the hw ARB shader */
     shader_addline(buffer, "!!ARBfp1.0\n");
 
+    if (shader_version < WINED3DPS_VERSION(3,0)) {
+        switch(args->fog) {
+            case FOG_OFF:
+                break;
+            case FOG_LINEAR:
+                shader_addline(buffer, "OPTION ARB_fog_linear;\n");
+                break;
+            case FOG_EXP:
+                shader_addline(buffer, "OPTION ARB_fog_exp;\n");
+                break;
+            case FOG_EXP2:
+                shader_addline(buffer, "OPTION ARB_fog_exp2;\n");
+                break;
+        }
+    }
+
     shader_addline(buffer, "TEMP TMP;\n");     /* Used in matrix ops */
     shader_addline(buffer, "TEMP TMP2;\n");    /* Used in matrix ops */
     shader_addline(buffer, "TEMP TA;\n");      /* Used for modifiers */
@@ -1885,37 +1957,23 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUF
     shader_addline(buffer, "PARAM coefmul = { 2, 4, 8, 16 };\n");
     shader_addline(buffer, "PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n");
 
-    /* Base Declarations */
-    shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION);
-
-    /* We need two variables for fog blending */
-    shader_addline(buffer, "TEMP TMP_FOG;\n");
-    if (This->baseShader.hex_version >= WINED3DPS_VERSION(2,0)) {
+    if (shader_version < WINED3DPS_VERSION(2,0)) {
+        fragcolor = "R0";
+    } else {
         shader_addline(buffer, "TEMP TMP_COLOR;\n");
+        fragcolor = "TMP_COLOR";
     }
 
+    /* Base Declarations */
+    shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION);
+
     /* Base Shader Body */
     shader_generate_main( (IWineD3DBaseShader*) This, buffer, reg_maps, function);
 
-    /* calculate fog and blend it
-     * NOTE: state.fog.params.y and state.fog.params.z don't hold fog start s and end e but
-     * -1/(e-s) and e/(e-s) respectively.
-     */
-    shader_addline(buffer, "MAD_SAT TMP_FOG, fragment.fogcoord, state.fog.params.y, state.fog.params.z;\n");
-
-    if (This->baseShader.hex_version < WINED3DPS_VERSION(2,0)) {
-        fragcolor = "R0";
-    } else {
-        fragcolor = "TMP_COLOR";
-    }
-    if(((IWineD3DDeviceImpl *)This->baseShader.device)->stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE]) {
+    if(args->srgb_correction) {
         arbfp_add_sRGB_correction(buffer, fragcolor, "TMP", "TMP2", "TA", "TB");
     }
-    if (This->baseShader.hex_version < WINED3DPS_VERSION(3,0)) {
-        shader_addline(buffer, "LRP result.color.rgb, TMP_FOG.x, %s, state.fog.color;\n", fragcolor);
-        shader_addline(buffer, "MOV result.color.a, %s.a;\n", fragcolor);
-    }
-
+    shader_addline(buffer, "MOV result.color, %s;\n", fragcolor);
     shader_addline(buffer, "END\n");
 
     /* TODO: change to resource.glObjectHandle or something like that */
@@ -2185,8 +2243,9 @@ const shader_backend_t arb_program_shader_backend = {
     shader_arb_select,
     shader_arb_select_depth_blt,
     shader_arb_deselect_depth_blt,
+    shader_arb_update_float_vertex_constants,
+    shader_arb_update_float_pixel_constants,
     shader_arb_load_constants,
-    shader_arb_cleanup,
     shader_arb_color_correction,
     shader_arb_destroy,
     shader_arb_alloc,
@@ -2310,7 +2369,7 @@ static void state_texfactor_arbfp(DWORD state, IWineD3DStateBlockImpl *statebloc
      * application provided constants
      */
     if(device->shader_backend == &arb_program_shader_backend) {
-        if(use_ps(device)) return;
+        if (use_ps(stateblock)) return;
 
         device = stateblock->wineD3DDevice;
         device->activeContext->pshader_const_dirty[ARB_FFP_CONST_TFACTOR] = 1;
@@ -2331,7 +2390,7 @@ static void state_arb_specularenable(DWORD state, IWineD3DStateBlockImpl *stateb
      * application provided constants
      */
     if(device->shader_backend == &arb_program_shader_backend) {
-        if(use_ps(device)) return;
+        if (use_ps(stateblock)) return;
 
         device = stateblock->wineD3DDevice;
         device->activeContext->pshader_const_dirty[ARB_FFP_CONST_SPECULAR_ENABLE] = 1;
@@ -2351,11 +2410,12 @@ static void state_arb_specularenable(DWORD state, IWineD3DStateBlockImpl *stateb
 }
 
 static void set_bumpmat_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
-    DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
+    DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
     IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
     float mat[2][2];
 
-    if(use_ps(device)) {
+    if (use_ps(stateblock))
+    {
         if(stage != 0 &&
            ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.bumpmat[stage]) {
             /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
@@ -2385,11 +2445,12 @@ static void set_bumpmat_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, W
 }
 
 static void tex_bumpenvlum_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
-    DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
+    DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
     IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
     float param[4];
 
-    if(use_ps(device)) {
+    if (use_ps(stateblock))
+    {
         if(stage != 0 &&
            ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
             /* The pixel shader has to know the luminance offset. Do a constants update if it
@@ -2481,7 +2542,7 @@ static const char *get_argreg(SHADER_BUFFER *buffer, DWORD argnum, unsigned int
         if(argnum == 2) ret = "arg2";
     }
     if(arg & WINED3DTA_ALPHAREPLICATE) {
-        shader_addline(buffer, "MOV arg%u, %s.a;\n", argnum, ret);
+        shader_addline(buffer, "MOV arg%u, %s.w;\n", argnum, ret);
         if(argnum == 0) ret = "arg0";
         if(argnum == 1) ret = "arg1";
         if(argnum == 2) ret = "arg2";
@@ -2496,8 +2557,8 @@ static void gen_ffp_instr(SHADER_BUFFER *buffer, unsigned int stage, BOOL color,
     BOOL mul_final_dest = FALSE;
 
     if(color && alpha) dstmask = "";
-    else if(color) dstmask = ".rgb";
-    else dstmask = ".a";
+    else if(color) dstmask = ".xyz";
+    else dstmask = ".w";
 
     if(dst == tempreg) dstreg = "tempreg";
     else dstreg = "ret";
@@ -2508,7 +2569,7 @@ static void gen_ffp_instr(SHADER_BUFFER *buffer, unsigned int stage, BOOL color,
 
     switch(op) {
         case WINED3DTOP_DISABLE:
-            if(stage == 1) shader_addline(buffer, "MOV %s%s, fragment.color.primary;\n", dstreg, dstmask);
+            if(stage == 0) shader_addline(buffer, "MOV %s%s, fragment.color.primary;\n", dstreg, dstmask);
             break;
 
         case WINED3DTOP_SELECTARG2:
@@ -2553,42 +2614,42 @@ static void gen_ffp_instr(SHADER_BUFFER *buffer, unsigned int stage, BOOL color,
 
         case WINED3DTOP_BLENDCURRENTALPHA:
             arg0 = get_argreg(buffer, 0, stage, WINED3DTA_CURRENT);
-            shader_addline(buffer, "LRP %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
+            shader_addline(buffer, "LRP %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
             break;
         case WINED3DTOP_BLENDFACTORALPHA:
             arg0 = get_argreg(buffer, 0, stage, WINED3DTA_TFACTOR);
-            shader_addline(buffer, "LRP %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
+            shader_addline(buffer, "LRP %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
             break;
         case WINED3DTOP_BLENDTEXTUREALPHA:
             arg0 = get_argreg(buffer, 0, stage, WINED3DTA_TEXTURE);
-            shader_addline(buffer, "LRP %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
+            shader_addline(buffer, "LRP %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
             break;
         case WINED3DTOP_BLENDDIFFUSEALPHA:
             arg0 = get_argreg(buffer, 0, stage, WINED3DTA_DIFFUSE);
-            shader_addline(buffer, "LRP %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
+            shader_addline(buffer, "LRP %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
             break;
 
         case WINED3DTOP_BLENDTEXTUREALPHAPM:
             arg0 = get_argreg(buffer, 0, stage, WINED3DTA_TEXTURE);
-            shader_addline(buffer, "SUB arg0.a, const.x, %s.a;\n", arg0);
-            shader_addline(buffer, "MAD_SAT %s%s, %s, arg0.a, %s;\n", dstreg, dstmask, arg2, arg1);
+            shader_addline(buffer, "SUB arg0.w, const.x, %s.w;\n", arg0);
+            shader_addline(buffer, "MAD_SAT %s%s, %s, arg0.w, %s;\n", dstreg, dstmask, arg2, arg1);
             break;
 
         /* D3DTOP_PREMODULATE ???? */
 
         case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
-            shader_addline(buffer, "SUB arg0.a, const.x, %s;\n", arg1);
-            shader_addline(buffer, "MAD_SAT %s%s, arg0.a, %s, %s;\n", dstreg, dstmask, arg2, arg1);
+            shader_addline(buffer, "SUB arg0.w, const.x, %s;\n", arg1);
+            shader_addline(buffer, "MAD_SAT %s%s, arg0.w, %s, %s;\n", dstreg, dstmask, arg2, arg1);
             break;
         case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
-            shader_addline(buffer, "MAD_SAT %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg1, arg2, arg1);
+            shader_addline(buffer, "MAD_SAT %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg1, arg2, arg1);
             break;
         case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
             shader_addline(buffer, "SUB arg0, const.x, %s;\n", arg1);
-            shader_addline(buffer, "MAD_SAT %s%s, arg0, %s, %s.a;\n", dstreg, dstmask, arg2, arg1);
+            shader_addline(buffer, "MAD_SAT %s%s, arg0, %s, %s.w;\n", dstreg, dstmask, arg2, arg1);
             break;
         case WINED3DTOP_MODULATECOLOR_ADDALPHA:
-            shader_addline(buffer, "MAD_SAT %s%s, %s, %s, %s.a;\n", dstreg, dstmask, arg1, arg2, arg1);
+            shader_addline(buffer, "MAD_SAT %s%s, %s, %s, %s.w;\n", dstreg, dstmask, arg1, arg2, arg1);
             break;
 
         case WINED3DTOP_DOTPRODUCT3:
@@ -2694,10 +2755,7 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi
     }
 
     /* Shader header */
-    buffer.bsize = 0;
-    buffer.lineNo = 0;
-    buffer.newline = TRUE;
-    buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
+    shader_buffer_init(&buffer);
 
     shader_addline(&buffer, "!!ARBfp1.0\n");
 
@@ -2776,20 +2834,20 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi
            (settings->op[stage - 1].cop == WINED3DTOP_BUMPENVMAP ||
             settings->op[stage - 1].cop == WINED3DTOP_BUMPENVMAPLUMINANCE)) {
             shader_addline(&buffer, "SWZ arg1, bumpmat%u, x, z, 0, 0;\n", stage - 1);
-            shader_addline(&buffer, "DP3 ret.r, arg1, tex%u;\n", stage - 1);
+            shader_addline(&buffer, "DP3 ret.x, arg1, tex%u;\n", stage - 1);
             shader_addline(&buffer, "SWZ arg1, bumpmat%u, y, w, 0, 0;\n", stage - 1);
-            shader_addline(&buffer, "DP3 ret.g, arg1, tex%u;\n", stage - 1);
+            shader_addline(&buffer, "DP3 ret.y, arg1, tex%u;\n", stage - 1);
 
             /* with projective textures, texbem only divides the static texture coord, not the displacement,
              * so multiply the displacement with the dividing parameter before passing it to TXP
              */
             if (settings->op[stage].projected != proj_none) {
                 if(settings->op[stage].projected == proj_count4) {
-                    shader_addline(&buffer, "MOV ret.a, fragment.texcoord[%u].a;\n", stage);
-                    shader_addline(&buffer, "MUL ret.rgb, ret, fragment.texcoord[%u].a, fragment.texcoord[%u];\n", stage, stage);
+                    shader_addline(&buffer, "MOV ret.w, fragment.texcoord[%u].w;\n", stage);
+                    shader_addline(&buffer, "MUL ret.xyz, ret, fragment.texcoord[%u].w, fragment.texcoord[%u];\n", stage, stage);
                 } else {
-                    shader_addline(&buffer, "MOV ret.a, fragment.texcoord[%u].b;\n", stage);
-                    shader_addline(&buffer, "MAD ret.rgb, ret, fragment.texcoord[%u].b, fragment.texcoord[%u];\n", stage, stage);
+                    shader_addline(&buffer, "MOV ret.w, fragment.texcoord[%u].z;\n", stage);
+                    shader_addline(&buffer, "MAD ret.xyz, ret, fragment.texcoord[%u].z, fragment.texcoord[%u];\n", stage, stage);
                 }
             } else {
                 shader_addline(&buffer, "ADD ret, ret, fragment.texcoord[%u];\n", stage);
@@ -2798,13 +2856,13 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi
             shader_addline(&buffer, "%s%s tex%u, ret, texture[%u], %s;\n",
                            instr, sat, stage, stage, textype);
             if(settings->op[stage - 1].cop == WINED3DTOP_BUMPENVMAPLUMINANCE) {
-                shader_addline(&buffer, "MAD_SAT ret.r, tex%u.b, luminance%u.r, luminance%u.g;\n",
+                shader_addline(&buffer, "MAD_SAT ret.x, tex%u.z, luminance%u.x, luminance%u.y;\n",
                                stage - 1, stage - 1, stage - 1);
-                shader_addline(&buffer, "MUL tex%u, tex%u, ret.r;\n", stage, stage);
+                shader_addline(&buffer, "MUL tex%u, tex%u, ret.x;\n", stage, stage);
             }
         } else if(settings->op[stage].projected == proj_count3) {
             shader_addline(&buffer, "MOV ret, fragment.texcoord[%u];\n", stage);
-            shader_addline(&buffer, "MOV ret.a, ret.b;\n");
+            shader_addline(&buffer, "MOV ret.w, ret.z;\n");
             shader_addline(&buffer, "%s%s tex%u, ret, texture[%u], %s;\n",
                             instr, sat, stage, stage, textype);
         } else {
@@ -2814,7 +2872,7 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi
 
         sprintf(colorcor_dst, "tex%u", stage);
         gen_color_correction(&buffer, colorcor_dst, WINED3DSP_WRITEMASK_ALL, "const.x", "const.y",
-                settings->op[stage].color_correction);
+                settings->op[stage].color_fixup);
     }
 
     /* Generate the main shader */
@@ -2850,7 +2908,7 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi
                           settings->op[stage].cop, settings->op[stage].carg0,
                           settings->op[stage].carg1, settings->op[stage].carg2);
             if(stage == 0) {
-                shader_addline(&buffer, "MOV ret.a, fragment.color.primary.a;\n");
+                shader_addline(&buffer, "MOV ret.w, fragment.color.primary.w;\n");
             }
         } else if(op_equal) {
             gen_ffp_instr(&buffer, stage, TRUE, TRUE, settings->op[stage].dst,
@@ -2869,7 +2927,7 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi
     if(settings->sRGB_write) {
         shader_addline(&buffer, "MAD ret, fragment.color.secondary, specular_enable, %s;\n", final_combiner_src);
         arbfp_add_sRGB_correction(&buffer, "ret", "arg0", "arg1", "arg2", "tempreg");
-        shader_addline(&buffer, "MOV result.color.a, ret.a;\n");
+        shader_addline(&buffer, "MOV result.color.w, ret.w;\n");
     } else {
         shader_addline(&buffer, "MAD result.color, fragment.color.secondary, specular_enable, %s;\n", final_combiner_src);
     }
@@ -2888,15 +2946,15 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi
         FIXME("Fragment program error at position %d: %s\n", pos,
               debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
     }
-    HeapFree(GetProcessHeap(), 0, buffer.buffer);
+    shader_buffer_free(&buffer);
     return ret;
 }
 
 static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
     IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
     struct shader_arb_priv *priv = (struct shader_arb_priv *) device->fragment_priv;
-    BOOL use_pshader = use_ps(device);
-    BOOL use_vshader = use_vs(device);
+    BOOL use_pshader = use_ps(stateblock);
+    BOOL use_vshader = use_vs(stateblock);
     struct ffp_frag_settings settings;
     const struct arbfp_ffp_desc *desc;
     unsigned int i;
@@ -2909,6 +2967,8 @@ static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock,
             }
             state_texfactor_arbfp(STATE_RENDER(WINED3DRS_TEXTUREFACTOR), stateblock, context);
             state_arb_specularenable(STATE_RENDER(WINED3DRS_SPECULARENABLE), stateblock, context);
+        } else if(use_pshader && !isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
+            device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
         }
         return;
     }
@@ -2983,9 +3043,36 @@ static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock,
  * fragment_prog_arbfp function being called because FOGENABLE is dirty, which calls this function here
  */
 static void state_arbfp_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
+    enum fogsource new_source;
+
     if(!isStateDirty(context, STATE_PIXELSHADER)) {
         fragment_prog_arbfp(state, stateblock, context);
     }
+
+    if(!stateblock->renderState[WINED3DRS_FOGENABLE]) return;
+
+    if(use_vs(stateblock)
+       && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog) {
+        if( stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE ) {
+            FIXME("vertex shader with table fog used\n");
+        }
+        context->last_was_foggy_shader = TRUE;
+        new_source = FOGSOURCE_VS;
+    } else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
+        context->last_was_foggy_shader = FALSE;
+        if(stateblock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || context->last_was_rhw) {
+            new_source = FOGSOURCE_COORD;
+        } else {
+            new_source = FOGSOURCE_FFP;
+        }
+    } else {
+        context->last_was_foggy_shader = FALSE;
+        new_source = FOGSOURCE_FFP;
+    }
+    if(new_source != context->fog_source) {
+        context->fog_source = new_source;
+        state_fogstartend(STATE_RENDER(WINED3DRS_FOGSTART), stateblock, context);
+    }
 }
 
 static void textransform(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
@@ -3130,7 +3217,11 @@ static const struct StateEntryTemplate arbfp_fragmentstate_template[] = {
     { STATE_RENDER(WINED3DRS_FOGENABLE),                  { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_arbfp_fog         }, 0                               },
     { STATE_RENDER(WINED3DRS_FOGTABLEMODE),               { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_arbfp_fog         }, 0                               },
     { STATE_RENDER(WINED3DRS_FOGVERTEXMODE),              { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_arbfp_fog         }, 0                               },
+    { STATE_RENDER(WINED3DRS_FOGSTART),                   { STATE_RENDER(WINED3DRS_FOGSTART),                   state_fogstartend       }, 0                               },
+    { STATE_RENDER(WINED3DRS_FOGEND),                     { STATE_RENDER(WINED3DRS_FOGSTART),                   state_fogstartend       }, 0                               },
     { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE),            { STATE_PIXELSHADER,                                  fragment_prog_arbfp     }, 0                               },
+    { STATE_RENDER(WINED3DRS_FOGCOLOR),                   { STATE_RENDER(WINED3DRS_FOGCOLOR),                   state_fogcolor      }, 0                               },
+    { STATE_RENDER(WINED3DRS_FOGDENSITY),                 { STATE_RENDER(WINED3DRS_FOGDENSITY),                 state_fogdensity    }, 0                               },
     {STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform      }, 0                               },
     {STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform      }, 0                               },
     {STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform      }, 0                               },
@@ -3191,11 +3282,11 @@ static BOOL gen_planar_yuv_read(SHADER_BUFFER *buffer, enum yuv_fixup yuv_fixup,
     const char *tex, *texinstr;
 
     if (yuv_fixup == YUV_FIXUP_UYVY) {
-        chroma = 'r';
-        *luminance = 'a';
+        chroma = 'x';
+        *luminance = 'w';
     } else {
-        chroma = 'a';
-        *luminance = 'r';
+        chroma = 'w';
+        *luminance = 'x';
     }
     switch(textype) {
         case GL_TEXTURE_2D:             tex = "2D";     texinstr = "TXP"; break;
@@ -3221,8 +3312,8 @@ static BOOL gen_planar_yuv_read(SHADER_BUFFER *buffer, enum yuv_fixup yuv_fixup,
      * So we have to get the sampling x position in non-normalized coordinates in integers
      */
     if(textype != GL_TEXTURE_RECTANGLE_ARB) {
-        shader_addline(buffer, "MUL texcrd.rg, fragment.texcoord[0], size.x;\n");
-        shader_addline(buffer, "MOV texcrd.a, size.x;\n");
+        shader_addline(buffer, "MUL texcrd.xy, fragment.texcoord[0], size.x;\n");
+        shader_addline(buffer, "MOV texcrd.w, size.x;\n");
     } else {
         shader_addline(buffer, "MOV texcrd, fragment.texcoord[0];\n");
     }
@@ -3244,9 +3335,9 @@ static BOOL gen_planar_yuv_read(SHADER_BUFFER *buffer, enum yuv_fixup yuv_fixup,
 
     /* Put the value into either of the chroma values */
     shader_addline(buffer, "SGE temp.x, texcrd2.x, coef.y;\n");
-    shader_addline(buffer, "MUL chroma.r, luminance.%c, temp.x;\n", chroma);
+    shader_addline(buffer, "MUL chroma.x, luminance.%c, temp.x;\n", chroma);
     shader_addline(buffer, "SLT temp.x, texcrd2.x, coef.y;\n");
-    shader_addline(buffer, "MUL chroma.g, luminance.%c, temp.x;\n", chroma);
+    shader_addline(buffer, "MUL chroma.y, luminance.%c, temp.x;\n", chroma);
 
     /* Sample pixel 2. If we read an even pixel(SLT above returned 1), sample
      * the pixel right to the current one. Otherwise, sample the left pixel.
@@ -3258,9 +3349,9 @@ static BOOL gen_planar_yuv_read(SHADER_BUFFER *buffer, enum yuv_fixup yuv_fixup,
 
     /* Put the value into the other chroma */
     shader_addline(buffer, "SGE temp.x, texcrd2.x, coef.y;\n");
-    shader_addline(buffer, "MAD chroma.g, luminance.%c, temp.x, chroma.g;\n", chroma);
+    shader_addline(buffer, "MAD chroma.y, luminance.%c, temp.x, chroma.y;\n", chroma);
     shader_addline(buffer, "SLT temp.x, texcrd2.x, coef.y;\n");
-    shader_addline(buffer, "MAD chroma.r, luminance.%c, temp.x, chroma.r;\n", chroma);
+    shader_addline(buffer, "MAD chroma.x, luminance.%c, temp.x, chroma.x;\n", chroma);
 
     /* TODO: If filtering is enabled, sample a 2nd pair of pixels left or right of
      * the current one and lerp the two U and V values
@@ -3380,7 +3471,7 @@ static BOOL gen_yv12_read(SHADER_BUFFER *buffer, GLenum textype, char *luminance
     }
     /* Read the texture, put the result into the output register */
     shader_addline(buffer, "TEX temp, texcrd, texture[0], %s;\n", tex);
-    shader_addline(buffer, "MOV chroma.r, temp.a;\n");
+    shader_addline(buffer, "MOV chroma.x, temp.w;\n");
 
     /* The other chroma value is 1/6th of the texture lower, from 5/6th to 6/6th
      * No need to clamp because we're just reusing the already clamped value from above
@@ -3391,7 +3482,7 @@ static BOOL gen_yv12_read(SHADER_BUFFER *buffer, GLenum textype, char *luminance
         shader_addline(buffer, "MAD texcrd.y, size.y, coef.w, texcrd.y;\n");
     }
     shader_addline(buffer, "TEX temp, texcrd, texture[0], %s;\n", tex);
-    shader_addline(buffer, "MOV chroma.g, temp.a;\n");
+    shader_addline(buffer, "MOV chroma.y, temp.w;\n");
 
     /* Sample the luminance value. It is in the top 2/3rd of the texture, so scale the y coordinate.
      * Clamp the y coordinate to prevent the chroma values from bleeding into the sampled luminance
@@ -3405,7 +3496,7 @@ static BOOL gen_yv12_read(SHADER_BUFFER *buffer, GLenum textype, char *luminance
         shader_addline(buffer, "MIN texcrd.y, temp.y, texcrd.y;\n");
         shader_addline(buffer, "TEX luminance, texcrd, texture[0], %s;\n", tex);
     } else {
-        /* Reading from texture_rectangles is pretty streightforward, just use the unmodified
+        /* Reading from texture_rectangles is pretty straightforward, just use the unmodified
          * texture coordinate. It is still a good idea to clamp it though, since the opengl texture
          * is bigger
          */
@@ -3426,10 +3517,7 @@ static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum yuv_fixup yuv_fixu
     struct arbfp_blit_priv *priv = (struct arbfp_blit_priv *) device->blit_priv;
 
     /* Shader header */
-    buffer.bsize = 0;
-    buffer.lineNo = 0;
-    buffer.newline = TRUE;
-    buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
+    shader_buffer_init(&buffer);
 
     ENTER_GL();
     GL_EXTCALL(glGenProgramsARB(1, &shader));
@@ -3438,7 +3526,7 @@ static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum yuv_fixup yuv_fixu
     checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader)");
     LEAVE_GL();
     if(!shader) {
-        HeapFree(GetProcessHeap(), 0, buffer.buffer);
+        shader_buffer_free(&buffer);
         return 0;
     }
 
@@ -3452,7 +3540,7 @@ static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum yuv_fixup yuv_fixu
      * contains the luminance and alpha the chroma. With UYVY it is vice versa. Thus
      * take the format into account when generating the read swizzles
      *
-     * Reading the Y value is streightforward - just sample the texture. The hardware
+     * Reading the Y value is straightforward - just sample the texture. The hardware
      * takes care of filtering in the horizontal and vertical direction.
      *
      * Reading the U and V values is harder. We have to avoid filtering horizontally,
@@ -3493,7 +3581,7 @@ static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum yuv_fixup yuv_fixu
         case YUV_FIXUP_YUY2:
             if (!gen_planar_yuv_read(&buffer, yuv_fixup, textype, &luminance_component))
             {
-                HeapFree(GetProcessHeap(), 0, buffer.buffer);
+                shader_buffer_free(&buffer);
                 return 0;
             }
             break;
@@ -3501,14 +3589,14 @@ static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum yuv_fixup yuv_fixu
         case YUV_FIXUP_YV12:
             if (!gen_yv12_read(&buffer, textype, &luminance_component))
             {
-                HeapFree(GetProcessHeap(), 0, buffer.buffer);
+                shader_buffer_free(&buffer);
                 return 0;
             }
             break;
 
         default:
             FIXME("Unsupported YUV fixup %#x\n", yuv_fixup);
-            HeapFree(GetProcessHeap(), 0, buffer.buffer);
+            shader_buffer_free(&buffer);
             return 0;
     }
 
@@ -3516,12 +3604,12 @@ static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum yuv_fixup yuv_fixu
      * http://www.fourcc.org/fccyvrgb.php. Note that the chroma
      * ranges from -0.5 to 0.5
      */
-    shader_addline(&buffer, "SUB chroma.rg, chroma, coef.y;\n");
+    shader_addline(&buffer, "SUB chroma.xy, chroma, coef.y;\n");
 
-    shader_addline(&buffer, "MAD result.color.r, chroma.r, yuv_coef.x, luminance.%c;\n", luminance_component);
-    shader_addline(&buffer, "MAD temp.r, -chroma.g, yuv_coef.y, luminance.%c;\n", luminance_component);
-    shader_addline(&buffer, "MAD result.color.g, -chroma.r, yuv_coef.z, temp.r;\n");
-    shader_addline(&buffer, "MAD result.color.b, chroma.g, yuv_coef.w, luminance.%c;\n", luminance_component);
+    shader_addline(&buffer, "MAD result.color.x, chroma.x, yuv_coef.x, luminance.%c;\n", luminance_component);
+    shader_addline(&buffer, "MAD temp.x, -chroma.y, yuv_coef.y, luminance.%c;\n", luminance_component);
+    shader_addline(&buffer, "MAD result.color.y, -chroma.x, yuv_coef.z, temp.x;\n");
+    shader_addline(&buffer, "MAD result.color.z, chroma.y, yuv_coef.w, luminance.%c;\n", luminance_component);
     shader_addline(&buffer, "END\n");
 
     ENTER_GL();
@@ -3533,7 +3621,7 @@ static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum yuv_fixup yuv_fixu
         FIXME("Fragment program error at position %d: %s\n", pos,
               debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
     }
-    HeapFree(GetProcessHeap(), 0, buffer.buffer);
+    shader_buffer_free(&buffer);
     LEAVE_GL();
 
     switch (yuv_fixup)
index 90ca192..c01ec1a 100644 (file)
@@ -159,7 +159,96 @@ static const char *debug_rep(GLuint rep) {
     }
 }
 
+static const char *debug_op(GLuint op) {
+    switch(op) {
+        case GL_MOV_ATI:                return "GL_MOV_ATI";
+        case GL_ADD_ATI:                return "GL_ADD_ATI";
+        case GL_MUL_ATI:                return "GL_MUL_ATI";
+        case GL_SUB_ATI:                return "GL_SUB_ATI";
+        case GL_DOT3_ATI:               return "GL_DOT3_ATI";
+        case GL_DOT4_ATI:               return "GL_DOT4_ATI";
+        case GL_MAD_ATI:                return "GL_MAD_ATI";
+        case GL_LERP_ATI:               return "GL_LERP_ATI";
+        case GL_CND_ATI:                return "GL_CND_ATI";
+        case GL_CND0_ATI:               return "GL_CND0_ATI";
+        case GL_DOT2_ADD_ATI:           return "GL_DOT2_ADD_ATI";
+        default:                        return "unexpected op";
+    }
+}
+
+static const char *debug_mask(GLuint mask) {
+    switch(mask) {
+        case GL_NONE:                           return "GL_NONE";
+        case GL_RED_BIT_ATI:                    return "GL_RED_BIT_ATI";
+        case GL_GREEN_BIT_ATI:                  return "GL_GREEN_BIT_ATI";
+        case GL_BLUE_BIT_ATI:                   return "GL_BLUE_BIT_ATI";
+        case GL_RED_BIT_ATI | GL_GREEN_BIT_ATI: return "GL_RED_BIT_ATI | GL_GREEN_BIT_ATI";
+        case GL_RED_BIT_ATI | GL_BLUE_BIT_ATI:  return "GL_RED_BIT_ATI | GL_BLUE_BIT_ATI";
+        case GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI:return "GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI";
+        case GL_RED_BIT_ATI | GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI:return "GL_RED_BIT_ATI | GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI";
+        default:                                return "Unexpected writemask";
+    }
+}
 #define GLINFO_LOCATION (*gl_info)
+
+static void wrap_op1(const WineD3D_GL_Info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod,
+                     GLuint arg1, GLuint arg1Rep, GLuint arg1Mod) {
+    if(dstMask == GL_ALPHA) {
+        TRACE("glAlphaFragmentOp1ATI(%s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod),
+              debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod));
+        GL_EXTCALL(glAlphaFragmentOp1ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod));
+    } else {
+        TRACE("glColorFragmentOp1ATI(%s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst),
+              debug_mask(dstMask), debug_dstmod(dstMod),
+              debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod));
+        GL_EXTCALL(glColorFragmentOp1ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod));
+    }
+}
+
+static void wrap_op2(const WineD3D_GL_Info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod,
+                     GLuint arg1, GLuint arg1Rep, GLuint arg1Mod,
+                     GLuint arg2, GLuint arg2Rep, GLuint arg2Mod) {
+    if(dstMask == GL_ALPHA) {
+        TRACE("glAlphaFragmentOp2ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod),
+              debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod),
+              debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod));
+        GL_EXTCALL(glAlphaFragmentOp2ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod));
+    } else {
+        TRACE("glColorFragmentOp2ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst),
+              debug_mask(dstMask), debug_dstmod(dstMod),
+              debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod),
+              debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod));
+        GL_EXTCALL(glColorFragmentOp2ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod));
+    }
+}
+
+static void wrap_op3(const WineD3D_GL_Info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod,
+                     GLuint arg1, GLuint arg1Rep, GLuint arg1Mod,
+                     GLuint arg2, GLuint arg2Rep, GLuint arg2Mod,
+                     GLuint arg3, GLuint arg3Rep, GLuint arg3Mod) {
+    if(dstMask == GL_ALPHA) {
+        /* Leave some free space to fit "GL_NONE, " in to align most alpha and color op lines */
+        TRACE("glAlphaFragmentOp3ATI(%s, %s,          %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod),
+              debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod),
+              debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod),
+              debug_register(arg3), debug_rep(arg3Rep), debug_argmod(arg3Mod));
+        GL_EXTCALL(glAlphaFragmentOp3ATI(op, dst, dstMod,
+                                         arg1, arg1Rep, arg1Mod,
+                                         arg2, arg2Rep, arg2Mod,
+                                         arg3, arg3Rep, arg3Mod));
+    } else {
+        TRACE("glColorFragmentOp3ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst),
+              debug_mask(dstMask), debug_dstmod(dstMod),
+              debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod),
+              debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod),
+              debug_register(arg3), debug_rep(arg3Rep), debug_argmod(arg3Mod));
+        GL_EXTCALL(glColorFragmentOp3ATI(op, dst, dstMask, dstMod,
+                                         arg1, arg1Rep, arg1Mod,
+                                         arg2, arg2Rep, arg2Mod,
+                                         arg3, arg3Rep, arg3Mod));
+    }
+}
+
 static GLuint register_for_arg(DWORD arg, const WineD3D_GL_Info *gl_info,
         unsigned int stage, GLuint *mod, GLuint *rep, GLuint tmparg)
 {
@@ -351,6 +440,7 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
         if(op[stage].cop != WINED3DTOP_BUMPENVMAP &&
            op[stage].cop != WINED3DTOP_BUMPENVMAPLUMINANCE) continue;
 
+        fixup = op[stage].color_fixup;
         if (fixup.x_source != CHANNEL_SOURCE_X || fixup.y_source != CHANNEL_SOURCE_Y)
         {
             FIXME("Swizzles not implemented\n");
@@ -364,12 +454,10 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
             argmodextra_y = fixup.y_sign_fixup ? GL_2X_BIT_ATI | GL_BIAS_BIT_ATI : GL_NONE;
         }
 
-        TRACE("glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, GL_REG_%d_ATI, GL_RED_BIT_ATI, GL_NONE, GL_REG_%d_ATI, GL_NONE, %s, ATI_FFP_CONST_BUMPMAT(%d), GL_NONE, GL_NONE, GL_REG_%d_ATI, GL_RED, GL_NONE)\n",
-              stage + 1, stage, debug_argmod(argmodextra_x), stage, stage + 1);
-        GL_EXTCALL(glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, GL_REG_0_ATI + stage + 1, GL_RED_BIT_ATI, GL_NONE,
-                                         GL_REG_0_ATI + stage, GL_NONE, argmodextra_x,
-                                         ATI_FFP_CONST_BUMPMAT(stage), GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
-                                         GL_REG_0_ATI + stage + 1, GL_RED, GL_NONE));
+        wrap_op3(gl_info, GL_DOT2_ADD_ATI, GL_REG_0_ATI + stage + 1, GL_RED_BIT_ATI, GL_NONE,
+                 GL_REG_0_ATI + stage, GL_NONE, argmodextra_x,
+                 ATI_FFP_CONST_BUMPMAT(stage), GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
+                 GL_REG_0_ATI + stage + 1, GL_RED, GL_NONE);
 
         /* FIXME: How can I make GL_DOT2_ADD_ATI read the factors from blue and alpha? It defaults to red and green,
          * and it is fairly easy to make it read GL_BLUE or BL_ALPHA, but I can't get an R * B + G * A. So we're wasting
@@ -379,18 +467,14 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
          * NOTE: GL_BLUE | GL_ALPHA is not possible. It doesn't throw a compilation error, but an OR operation on the
          * constants doesn't make sense, considering their values.
          */
-        TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_5_ATI, GL_RED_BIT_ATI, GL_NONE, ATI_FFP_CONST_BUMPMAT(%d), GL_BLUE, GL_NONE)\n", stage);
-        GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_5_ATI, GL_RED_BIT_ATI, GL_NONE,
-                                         ATI_FFP_CONST_BUMPMAT(stage), GL_BLUE, GL_NONE));
-        TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_5_ATI, GL_GREEN_BIT_ATI, GL_NONE, ATI_FFP_CONST_BUMPMAT(%d), GL_ALPHA, GL_NONE)\n", stage);
-        GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_5_ATI, GL_GREEN_BIT_ATI, GL_NONE,
-                                        ATI_FFP_CONST_BUMPMAT(stage), GL_ALPHA, GL_NONE));
-        TRACE("glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, GL_REG_%d_ATI, GL_GREEN_BIT_ATI, GL_NONE, GL_REG_%d_ATI, GL_NONE, %s, GL_REG_5_ATI, GL_NONE, GL_NONE, GL_REG_%d_ATI, GL_GREEN, GL_NONE)\n",
-              stage + 1, stage, debug_argmod(argmodextra_y), stage + 1);
-        GL_EXTCALL(glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, GL_REG_0_ATI + stage + 1, GL_GREEN_BIT_ATI, GL_NONE,
-                                         GL_REG_0_ATI + stage, GL_NONE, argmodextra_y,
-                                         GL_REG_5_ATI, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
-                                         GL_REG_0_ATI + stage + 1, GL_GREEN, GL_NONE));
+        wrap_op1(gl_info, GL_MOV_ATI, GL_REG_5_ATI, GL_RED_BIT_ATI, GL_NONE,
+                 ATI_FFP_CONST_BUMPMAT(stage), GL_BLUE, GL_NONE);
+        wrap_op1(gl_info, GL_MOV_ATI, GL_REG_5_ATI, GL_GREEN_BIT_ATI, GL_NONE,
+                 ATI_FFP_CONST_BUMPMAT(stage), GL_ALPHA, GL_NONE);
+        wrap_op3(gl_info, GL_DOT2_ADD_ATI, GL_REG_0_ATI + stage + 1, GL_GREEN_BIT_ATI, GL_NONE,
+                 GL_REG_0_ATI + stage, GL_NONE, argmodextra_y,
+                 GL_REG_5_ATI, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
+                 GL_REG_0_ATI + stage + 1, GL_GREEN, GL_NONE);
     }
 
     /* Pass 3: Generate sampling instructions for regular textures */
@@ -438,12 +522,10 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
         if(op[stage].cop == WINED3DTOP_DISABLE) {
             if(stage == 0) {
                 /* Handle complete texture disabling gracefully */
-                TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, GL_PRIMARY_COLOR, GL_NONE, GL_NONE)\n");
-                GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
-                                                 GL_PRIMARY_COLOR, GL_NONE, GL_NONE));
-                TRACE("glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_PRIMARY_COLOR, GL_NONE, GL_NONE)\n");
-                GL_EXTCALL(glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE,
-                                                 GL_PRIMARY_COLOR, GL_NONE, GL_NONE));
+                wrap_op1(gl_info, GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
+                         GL_PRIMARY_COLOR, GL_NONE, GL_NONE);
+                wrap_op1(gl_info, GL_MOV_ATI, GL_REG_0_ATI, GL_ALPHA, GL_NONE,
+                         GL_PRIMARY_COLOR, GL_NONE, GL_NONE);
             }
             break;
         }
@@ -472,10 +554,8 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
                 argmod1 = argmod2;
                 rep1 = rep2;
             case WINED3DTOP_SELECTARG1:
-                TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, %s, GL_NONE, GL_NONE, %s, %s, %s)\n",
-                      debug_register(dstreg), debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1));
-                GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, dstreg, GL_NONE, GL_NONE,
-                                                 arg1, rep1, argmod1));
+                wrap_op1(gl_info, GL_MOV_ATI, dstreg, GL_NONE, GL_NONE,
+                         arg1, rep1, argmod1);
                 break;
 
             case WINED3DTOP_MODULATE4X:
@@ -484,13 +564,9 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
                 if(dstmod == GL_NONE) dstmod = GL_2X_BIT_ATI;
                 dstmod |= GL_SATURATE_BIT_ATI;
             case WINED3DTOP_MODULATE:
-                TRACE("glColorFragmentOp2ATI(GL_MUL_ATI, %s, GL_NONE, %s, %s, %s, %s, %s, %s, %s)\n",
-                      debug_register(dstreg), debug_dstmod(dstmod),
-                      debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1),
-                      debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2));
-                GL_EXTCALL(glColorFragmentOp2ATI(GL_MUL_ATI, dstreg, GL_NONE, dstmod,
-                                                 arg1, rep1, argmod1,
-                                                 arg2, rep2, argmod2));
+                wrap_op2(gl_info, GL_MUL_ATI, dstreg, GL_NONE, dstmod,
+                         arg1, rep1, argmod1,
+                         arg2, rep2, argmod2);
                 break;
 
             case WINED3DTOP_ADDSIGNED2X:
@@ -499,40 +575,27 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
                 argmodextra = GL_BIAS_BIT_ATI;
             case WINED3DTOP_ADD:
                 dstmod |= GL_SATURATE_BIT_ATI;
-                TRACE("glColorFragmentOp2ATI(GL_ADD_ATI, %s, GL_NONE, %s, %s, %s, %s, %s, %s, %s)\n",
-                      debug_register(dstreg), debug_dstmod(dstmod),
-                      debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1),
-                      debug_register(arg2), debug_rep(rep2), debug_argmod(argmodextra | argmod2));
-                GL_EXTCALL(glColorFragmentOp2ATI(GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, dstmod,
-                                                 arg1, rep1, argmod1,
-                                                 arg2, rep2, argmodextra | argmod2));
+                wrap_op2(gl_info, GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, dstmod,
+                         arg1, rep1, argmod1,
+                         arg2, rep2, argmodextra | argmod2);
                 break;
 
             case WINED3DTOP_SUBTRACT:
                 dstmod |= GL_SATURATE_BIT_ATI;
-                TRACE("glColorFragmentOp2ATI(GL_SUB_ATI, %s, GL_NONE, %s, %s, %s, %s, %s, %s, %s)\n",
-                      debug_register(dstreg), debug_dstmod(dstmod),
-                      debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1),
-                      debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2));
-                GL_EXTCALL(glColorFragmentOp2ATI(GL_SUB_ATI, dstreg, GL_NONE, dstmod,
-                                                 arg1, rep1, argmod1,
-                                                 arg2, rep2, argmod2));
+                wrap_op2(gl_info, GL_SUB_ATI, dstreg, GL_NONE, dstmod,
+                         arg1, rep1, argmod1,
+                         arg2, rep2, argmod2);
                 break;
 
             case WINED3DTOP_ADDSMOOTH:
                 argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
-                TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, GL_SATURATE_BIT_ATI, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n",
-                      debug_register(dstreg),
-                      debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2),
-                      debug_register(arg1), debug_rep(rep1), debug_argmod(argmodextra),
-                      debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1));
                 /* Dst = arg1 + * arg2(1 -arg 1)
                  *     = arg2 * (1 - arg1) + arg1
                  */
-                GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
-                                                 arg2, rep2, argmod2,
-                                                 arg1, rep1, argmodextra,
-                                                 arg1, rep1, argmod1));
+                wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
+                         arg2, rep2, argmod2,
+                         arg1, rep1, argmodextra,
+                         arg1, rep1, argmod1);
                 break;
 
             case WINED3DTOP_BLENDCURRENTALPHA:
@@ -543,28 +606,18 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
                 if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
             case WINED3DTOP_BLENDDIFFUSEALPHA:
                 if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL, NULL, -1);
-                TRACE("glColorFragmentOp3ATI(GL_LERP_ATI, %s, GL_NONE, GL_NONE, %s, GL_ALPHA, GL_NONE, %s, %s, %s, %s, %s, %s)\n",
-                      debug_register(dstreg),
-                      debug_register(extrarg),
-                      debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1),
-                      debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2));
-                GL_EXTCALL(glColorFragmentOp3ATI(GL_LERP_ATI, dstreg, GL_NONE, GL_NONE,
-                                                 extrarg, GL_ALPHA, GL_NONE,
-                                                 arg1, rep1, argmod1,
-                                                 arg2, rep2, argmod2));
+                wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_NONE, GL_NONE,
+                         extrarg, GL_ALPHA, GL_NONE,
+                         arg1, rep1, argmod1,
+                         arg2, rep2, argmod2);
                 break;
 
             case WINED3DTOP_BLENDTEXTUREALPHAPM:
                 arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
-                TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, GL_NONE, %s, %s, %s, %s, GL_ALPHA, GL_COMP_BIT_ATI, %s, %s, %s)\n",
-                      debug_register(dstreg),
-                      debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2),
-                      debug_register(arg0),
-                      debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1));
-                GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, GL_NONE,
-                                                 arg2, rep2,  argmod2,
-                                                 arg0, GL_ALPHA, GL_COMP_BIT_ATI,
-                                                 arg1, rep1,  argmod1));
+                wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_NONE,
+                         arg2, rep2,  argmod2,
+                         arg0, GL_ALPHA, GL_COMP_BIT_ATI,
+                         arg1, rep1,  argmod1);
                 break;
 
             /* D3DTOP_PREMODULATE ???? */
@@ -573,63 +626,40 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
                 argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
             case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
                 if(!argmodextra) argmodextra = argmod1;
-                TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, GL_SATURATE_BIT_ATI, %s, %s, %s, %s, GL_ALPHA, %s, %s, %s, %s)\n",
-                      debug_register(dstreg),
-                      debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2),
-                      debug_register(arg1), debug_argmod(argmodextra), debug_register(arg1), debug_rep(rep1), debug_argmod(arg1));
-                GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
-                                                 arg2, rep2,  argmod2,
-                                                 arg1, GL_ALPHA, argmodextra,
-                                                 arg1, rep1,  argmod1));
+                wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
+                         arg2, rep2,  argmod2,
+                         arg1, GL_ALPHA, argmodextra,
+                         arg1, rep1,  argmod1);
                 break;
 
             case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
                 argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
             case WINED3DTOP_MODULATECOLOR_ADDALPHA:
                 if(!argmodextra) argmodextra = argmod1;
-                TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, GL_SATURATE_BIT_ATI, %s, %s, %s, %s, %s, %s, %s, GL_ALPHA, %s)\n",
-                      debug_register(dstreg),
-                      debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2),
-                      debug_register(arg1), debug_rep(rep1), debug_argmod(argmodextra),
-                      debug_register(arg1), debug_argmod(argmod1));
-                GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
-                                                 arg2, rep2,  argmod2,
-                                                 arg1, rep1,  argmodextra,
-                                                 arg1, GL_ALPHA, argmod1));
+                wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
+                         arg2, rep2,  argmod2,
+                         arg1, rep1,  argmodextra,
+                         arg1, GL_ALPHA, argmod1);
                 break;
 
             case WINED3DTOP_DOTPRODUCT3:
-                TRACE("glColorFragmentOp2ATI(GL_DOT3_ATI, %s, GL_NONE, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI, %s, %s, %s, %s, %s, %s)\n",
-                      debug_register(dstreg),
-                      debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1 | GL_BIAS_BIT_ATI),
-                      debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2 | GL_BIAS_BIT_ATI));
-                GL_EXTCALL(glColorFragmentOp2ATI(GL_DOT3_ATI, dstreg, GL_NONE, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI,
-                                                 arg1, rep1, argmod1 | GL_BIAS_BIT_ATI,
-                                                 arg2, rep2, argmod2 | GL_BIAS_BIT_ATI));
+                wrap_op2(gl_info, GL_DOT3_ATI, dstreg, GL_NONE, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI,
+                         arg1, rep1, argmod1 | GL_BIAS_BIT_ATI,
+                         arg2, rep2, argmod2 | GL_BIAS_BIT_ATI);
                 break;
 
             case WINED3DTOP_MULTIPLYADD:
-                TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, GL_SATURATE_BIT_ATI, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n",
-                      debug_register(dstreg),
-                      debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1),
-                      debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2),
-                      debug_register(arg0), debug_rep(rep0), debug_argmod(argmod0));
-                GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
-                                                 arg1, rep1, argmod1,
-                                                 arg2, rep2, argmod2,
-                                                 arg0, rep0, argmod0));
+                wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
+                         arg1, rep1, argmod1,
+                         arg2, rep2, argmod2,
+                         arg0, rep0, argmod0);
                 break;
 
             case WINED3DTOP_LERP:
-                TRACE("glColorFragmentOp3ATI(GL_LERP_ATI, %s, GL_NONE, GL_NONE, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n",
-                      debug_register(dstreg),
-                      debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1),
-                      debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2),
-                      debug_register(arg0), debug_rep(rep0), debug_argmod(argmod0));
-                GL_EXTCALL(glColorFragmentOp3ATI(GL_LERP_ATI, dstreg, GL_NONE, GL_NONE,
-                                                 arg0, rep0, argmod0,
-                                                 arg1, rep1, argmod1,
-                                                 arg2, rep2, argmod2));
+                wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_NONE, GL_NONE,
+                         arg0, rep0, argmod0,
+                         arg1, rep1, argmod1,
+                         arg2, rep2, argmod2);
                 break;
 
             case WINED3DTOP_BUMPENVMAP:
@@ -651,9 +681,8 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
             case WINED3DTOP_DISABLE:
                 /* Get the primary color to the output if on stage 0, otherwise leave register 0 untouched */
                 if(stage == 0) {
-                    TRACE("glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_PRIMARY_COLOR, GL_NONE, GL_NONE)\n");
-                    GL_EXTCALL(glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE,
-                               GL_PRIMARY_COLOR, GL_NONE, GL_NONE));
+                    wrap_op1(gl_info, GL_MOV_ATI, GL_REG_0_ATI, GL_ALPHA, GL_NONE,
+                             GL_PRIMARY_COLOR, GL_NONE, GL_NONE);
                 }
                 break;
 
@@ -661,11 +690,8 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
                 arg1 = arg2;
                 argmod1 = argmod2;
             case WINED3DTOP_SELECTARG1:
-                TRACE("glAlphaFragmentOp1ATI(GL_MOV_ATI, %s,          GL_NONE, %s, GL_NONE, %s)\n",
-                      debug_register(dstreg),
-                      debug_register(arg1), debug_argmod(argmod1));
-                GL_EXTCALL(glAlphaFragmentOp1ATI(GL_MOV_ATI, dstreg, GL_NONE,
-                                                 arg1, GL_NONE, argmod1));
+                wrap_op1(gl_info, GL_MOV_ATI, dstreg, GL_ALPHA, GL_NONE,
+                         arg1, GL_NONE, argmod1);
                 break;
 
             case WINED3DTOP_MODULATE4X:
@@ -674,13 +700,9 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
                 if(dstmod == GL_NONE) dstmod = GL_2X_BIT_ATI;
                 dstmod |= GL_SATURATE_BIT_ATI;
             case WINED3DTOP_MODULATE:
-                TRACE("glAlphaFragmentOp2ATI(GL_MUL_ATI, %s,          %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
-                      debug_register(dstreg), debug_dstmod(dstmod),
-                      debug_register(arg1), debug_argmod(argmod1),
-                      debug_register(arg2), debug_argmod(argmod2));
-                GL_EXTCALL(glAlphaFragmentOp2ATI(GL_MUL_ATI, dstreg, dstmod,
-                                                 arg1, GL_NONE, argmod1,
-                                                 arg2, GL_NONE, argmod2));
+                wrap_op2(gl_info, GL_MUL_ATI, dstreg, GL_ALPHA, dstmod,
+                         arg1, GL_NONE, argmod1,
+                         arg2, GL_NONE, argmod2);
                 break;
 
             case WINED3DTOP_ADDSIGNED2X:
@@ -689,40 +711,27 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
                 argmodextra = GL_BIAS_BIT_ATI;
             case WINED3DTOP_ADD:
                 dstmod |= GL_SATURATE_BIT_ATI;
-                TRACE("glAlphaFragmentOp2ATI(GL_ADD_ATI, %s,          %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
-                      debug_register(dstreg), debug_dstmod(dstmod),
-                      debug_register(arg1), debug_argmod(argmod1),
-                      debug_register(arg2), debug_argmod(argmodextra | argmod2));
-                GL_EXTCALL(glAlphaFragmentOp2ATI(GL_ADD_ATI, dstreg, dstmod,
-                                                 arg1, GL_NONE, argmod1,
-                                                 arg2, GL_NONE, argmodextra | argmod2));
+                wrap_op2(gl_info, GL_ADD_ATI, dstreg, GL_ALPHA, dstmod,
+                         arg1, GL_NONE, argmod1,
+                         arg2, GL_NONE, argmodextra | argmod2);
                 break;
 
             case WINED3DTOP_SUBTRACT:
                 dstmod |= GL_SATURATE_BIT_ATI;
-                TRACE("glAlphaFragmentOp2ATI(GL_SUB_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
-                      debug_register(dstreg), debug_dstmod(dstmod),
-                      debug_register(arg1), debug_argmod(argmod1),
-                      debug_register(arg2), debug_argmod(argmod2));
-                GL_EXTCALL(glAlphaFragmentOp2ATI(GL_SUB_ATI, dstreg, dstmod,
-                                                 arg1, GL_NONE, argmod1,
-                                                 arg2, GL_NONE, argmod2));
+                wrap_op2(gl_info, GL_SUB_ATI, dstreg, GL_ALPHA, dstmod,
+                         arg1, GL_NONE, argmod1,
+                         arg2, GL_NONE, argmod2);
                 break;
 
             case WINED3DTOP_ADDSMOOTH:
                 argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
-                TRACE("glAlphaFragmentOp3ATI(GL_MAD_ATI, %s,          GL_SATURATE_BIT_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
-                      debug_register(dstreg),
-                      debug_register(arg2), debug_argmod(argmod2),
-                      debug_register(arg1), debug_argmod(argmodextra),
-                      debug_register(arg1), debug_argmod(argmod1));
                 /* Dst = arg1 + * arg2(1 -arg 1)
                  *     = arg2 * (1 - arg1) + arg1
                  */
-                GL_EXTCALL(glAlphaFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_SATURATE_BIT_ATI,
-                                                 arg2, GL_NONE, argmod2,
-                                                 arg1, GL_NONE, argmodextra,
-                                                 arg1, GL_NONE, argmod1));
+                wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI,
+                         arg2, GL_NONE, argmod2,
+                         arg1, GL_NONE, argmodextra,
+                         arg1, GL_NONE, argmod1);
                 break;
 
             case WINED3DTOP_BLENDCURRENTALPHA:
@@ -733,64 +742,40 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
                 if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
             case WINED3DTOP_BLENDDIFFUSEALPHA:
                 if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL, NULL, -1);
-                TRACE("glAlphaFragmentOp3ATI(GL_LERP_ATI, %s,          GL_NONE, %s, GL_ALPHA, GL_NONE, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
-                      debug_register(dstreg),
-                      debug_register(extrarg),
-                      debug_register(arg1), debug_argmod(argmod1),
-                      debug_register(arg2), debug_argmod(argmod2));
-                GL_EXTCALL(glAlphaFragmentOp3ATI(GL_LERP_ATI, dstreg, GL_NONE,
-                                                 extrarg, GL_ALPHA, GL_NONE,
-                                                 arg1, GL_NONE, argmod1,
-                                                 arg2, GL_NONE, argmod2));
+                wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_ALPHA, GL_NONE,
+                         extrarg, GL_ALPHA, GL_NONE,
+                         arg1, GL_NONE, argmod1,
+                         arg2, GL_NONE, argmod2);
                 break;
 
             case WINED3DTOP_BLENDTEXTUREALPHAPM:
                 arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
-                TRACE("glAlphaFragmentOp3ATI(GL_MAD_ATI, %s,          GL_NONE, %s, GL_NONE, %s, %s, GL_ALPHA, GL_COMP_BIT_ATI, %s, GL_NONE, %s)\n",
-                      debug_register(dstreg),
-                      debug_register(arg2), debug_argmod(argmod2),
-                      debug_register(arg0),
-                      debug_register(arg1), debug_argmod(argmod1));
-                GL_EXTCALL(glAlphaFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE,
-                                                 arg2, GL_NONE,  argmod2,
-                                                 arg0, GL_ALPHA, GL_COMP_BIT_ATI,
-                                                 arg1, GL_NONE,  argmod1));
+                wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_NONE,
+                         arg2, GL_NONE,  argmod2,
+                         arg0, GL_ALPHA, GL_COMP_BIT_ATI,
+                         arg1, GL_NONE,  argmod1);
                 break;
 
             /* D3DTOP_PREMODULATE ???? */
 
             case WINED3DTOP_DOTPRODUCT3:
-                TRACE("glAlphaFragmentOp2ATI(GL_DOT3_ATI, %s,          GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
-                      debug_register(dstreg),
-                      debug_register(arg1), debug_argmod(argmod1 | GL_BIAS_BIT_ATI),
-                      debug_register(arg2), debug_argmod(argmod2 | GL_BIAS_BIT_ATI));
-                GL_EXTCALL(glAlphaFragmentOp2ATI(GL_DOT3_ATI, dstreg, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI,
-                                                 arg1, GL_NONE, argmod1 | GL_BIAS_BIT_ATI,
-                                                 arg2, GL_NONE, argmod2 | GL_BIAS_BIT_ATI));
+                wrap_op2(gl_info, GL_DOT3_ATI, dstreg, GL_ALPHA, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI,
+                         arg1, GL_NONE, argmod1 | GL_BIAS_BIT_ATI,
+                         arg2, GL_NONE, argmod2 | GL_BIAS_BIT_ATI);
                 break;
 
             case WINED3DTOP_MULTIPLYADD:
-                TRACE("glAlphaFragmentOp3ATI(GL_MAD_ATI, %s,          GL_SATURATE_BIT_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
-                      debug_register(dstreg),
-                      debug_register(arg1), debug_argmod(argmod1),
-                      debug_register(arg2), debug_argmod(argmod2),
-                      debug_register(arg0), debug_argmod(argmod0));
-                GL_EXTCALL(glAlphaFragmentOp3ATI(GL_MAD_ATI, dstreg,          GL_SATURATE_BIT_ATI,
-                           arg1, GL_NONE, argmod1,
-                           arg2, GL_NONE, argmod2,
-                           arg0, GL_NONE, argmod0));
+                wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI,
+                         arg1, GL_NONE, argmod1,
+                         arg2, GL_NONE, argmod2,
+                         arg0, GL_NONE, argmod0);
                 break;
 
             case WINED3DTOP_LERP:
-                TRACE("glAlphaFragmentOp3ATI(GL_LERP_ATI, %s,          GL_SATURATE_BIT_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
-                      debug_register(dstreg),
-                      debug_register(arg1), debug_argmod(argmod1),
-                      debug_register(arg2), debug_argmod(argmod2),
-                      debug_register(arg0), debug_argmod(argmod0));
-                GL_EXTCALL(glAlphaFragmentOp3ATI(GL_LERP_ATI, dstreg, GL_SATURATE_BIT_ATI,
-                                                 arg1, GL_NONE, argmod1,
-                                                 arg2, GL_NONE, argmod2,
-                                                 arg0, GL_NONE, argmod0));
+                wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI,
+                         arg1, GL_NONE, argmod1,
+                         arg2, GL_NONE, argmod2,
+                         arg0, GL_NONE, argmod0);
                 break;
 
             case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
@@ -868,7 +853,7 @@ static void state_texfactor_atifs(DWORD state, IWineD3DStateBlockImpl *statebloc
 }
 
 static void set_bumpmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
-    DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
+    DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
     float mat[2][2];
 
     mat[0][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]);
@@ -896,10 +881,41 @@ static void textransform(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3
     }
 }
 
+static void atifs_apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
+    IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
+    BOOL use_vshader = use_vs(stateblock);
+
+    /* The ATIFS code does not support pixel shaders currently, but we have to provide a state handler
+     * to call shader_select to select a vertex shader if one is applied because the vertex shader state
+     * may defer calling the shader backend if the pshader state is dirty.
+     *
+     * In theory the application should not be able to mark the pixel shader dirty because it cannot
+     * create a shader, and thus has no way to set the state to something != NULL. However, a different
+     * pipeline part may link a different state to its pixelshader handler, thus a pshader state exists
+     * and can be dirtified. Also the pshader is always dirtified at startup, and blitting disables all
+     * shaders and dirtifies all shader states. If atifs can deal with this it keeps the rest of the code
+     * simpler.
+     */
+    if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
+        device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, use_vshader);
+
+        if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && use_vshader) {
+            device->StateTable[STATE_VERTEXSHADERCONSTANT].apply(STATE_VERTEXSHADERCONSTANT, stateblock, context);
+        }
+    }
+}
+
 #undef GLINFO_LOCATION
 
 static const struct StateEntryTemplate atifs_fragmentstate_template[] = {
     {STATE_RENDER(WINED3DRS_TEXTUREFACTOR),               { STATE_RENDER(WINED3DRS_TEXTUREFACTOR),              state_texfactor_atifs   }, 0                               },
+    {STATE_RENDER(WINED3DRS_FOGCOLOR),                    { STATE_RENDER(WINED3DRS_FOGCOLOR),                   state_fogcolor          }, 0                               },
+    {STATE_RENDER(WINED3DRS_FOGDENSITY),                  { STATE_RENDER(WINED3DRS_FOGDENSITY),                 state_fogdensity        }, 0                               },
+    {STATE_RENDER(WINED3DRS_FOGENABLE),                   { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog_fragpart      }, 0                               },
+    {STATE_RENDER(WINED3DRS_FOGTABLEMODE),                { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog_fragpart      }, 0                               },
+    {STATE_RENDER(WINED3DRS_FOGVERTEXMODE),               { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog_fragpart      }, 0                               },
+    {STATE_RENDER(WINED3DRS_FOGSTART),                    { STATE_RENDER(WINED3DRS_FOGSTART),                   state_fogstartend       }, 0                               },
+    {STATE_RENDER(WINED3DRS_FOGEND),                      { STATE_RENDER(WINED3DRS_FOGSTART),                   state_fogstartend       }, 0                               },
     {STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),           { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          set_tex_op_atifs        }, 0                               },
     {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1),         { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          set_tex_op_atifs        }, 0                               },
     {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2),         { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          set_tex_op_atifs        }, 0                               },
@@ -1020,6 +1036,7 @@ static const struct StateEntryTemplate atifs_fragmentstate_template[] = {
     {STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform      }, 0                               },
     {STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform      }, 0                               },
     {STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform      }, 0                               },
+    {STATE_PIXELSHADER,                                   { STATE_PIXELSHADER,                                  atifs_apply_pixelshader }, 0                               },
     {0 /* Terminate */,                                   { 0,                                                  0                       }, 0                               },
 };
 
index c0b149f..a270b0c 100644 (file)
@@ -40,6 +40,20 @@ static inline BOOL shader_is_version_token(DWORD token) {
            shader_is_vshader_version(token);
 }
 
+void shader_buffer_init(struct SHADER_BUFFER *buffer)
+{
+    buffer->buffer = HeapAlloc(GetProcessHeap(), 0, SHADER_PGMSIZE);
+    buffer->buffer[0] = '\0';
+    buffer->bsize = 0;
+    buffer->lineNo = 0;
+    buffer->newline = TRUE;
+}
+
+void shader_buffer_free(struct SHADER_BUFFER *buffer)
+{
+    HeapFree(GetProcessHeap(), 0, buffer->buffer);
+}
+
 int shader_addline(
     SHADER_BUFFER* buffer,  
     const char *format, ...) {
@@ -76,6 +90,15 @@ int shader_addline(
     return 0;
 }
 
+void shader_init(struct IWineD3DBaseShaderClass *shader,
+        IWineD3DDevice *device, const SHADER_OPCODE *instruction_table)
+{
+    shader->ref = 1;
+    shader->device = device;
+    shader->shader_ins = instruction_table;
+    list_init(&shader->linked_programs);
+}
+
 const SHADER_OPCODE *shader_get_opcode(const SHADER_OPCODE *opcode_table, DWORD shader_version, DWORD code)
 {
     DWORD i = 0;
@@ -117,17 +140,12 @@ static int shader_get_param(const DWORD *pToken, DWORD shader_version, DWORD *pa
 }
 
 /* Return the number of parameters to skip for an opcode */
-static inline int shader_skip_opcode(
-    IWineD3DBaseShaderImpl* This,
-    const SHADER_OPCODE* curOpcode,
-    DWORD opcode_token) {
-
+static inline int shader_skip_opcode(const SHADER_OPCODE *curOpcode, DWORD opcode_token, DWORD shader_version)
+{
    /* Shaders >= 2.0 may contain address tokens, but fortunately they
     * have a useful length mask - use it here. Shaders 1.0 contain no such tokens */
-
-    return (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 2)?
-        ((opcode_token & WINED3DSI_INSTLENGTH_MASK) >> WINED3DSI_INSTLENGTH_SHIFT):
-        curOpcode->num_params;
+    return (WINED3DSHADER_VERSION_MAJOR(shader_version) >= 2)
+            ? ((opcode_token & WINED3DSI_INSTLENGTH_MASK) >> WINED3DSI_INSTLENGTH_SHIFT) : curOpcode->num_params;
 }
 
 /* Read the parameters of an unrecognized opcode from the input stream
@@ -192,28 +210,21 @@ static void shader_delete_constant_list(struct list* clist) {
 /* Note that this does not count the loop register
  * as an address register. */
 
-HRESULT shader_get_registers_used(
-    IWineD3DBaseShader *iface,
-    shader_reg_maps* reg_maps,
-    semantic* semantics_in,
-    semantic* semantics_out,
-    CONST DWORD* pToken,
-    IWineD3DStateBlockImpl *stateBlock) {
-
+HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, struct shader_reg_maps *reg_maps,
+        struct semantic *semantics_in, struct semantic *semantics_out, const DWORD *byte_code)
+{
     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
     const SHADER_OPCODE *shader_ins = This->baseShader.shader_ins;
-    DWORD shader_version = This->baseShader.hex_version;
+    DWORD shader_version;
     unsigned int cur_loop_depth = 0, max_loop_depth = 0;
+    const DWORD* pToken = byte_code;
+    char pshader;
 
     /* There are some minor differences between pixel and vertex shaders */
-    char pshader = shader_is_pshader_version(This->baseShader.hex_version);
 
     memset(reg_maps->bumpmat, 0, sizeof(reg_maps->bumpmat));
     memset(reg_maps->luminanceparams, 0, sizeof(reg_maps->luminanceparams));
 
-    if (pToken == NULL)
-        return WINED3D_OK;
-
     /* get_registers_used is called on every compile on some 1.x shaders, which can result
      * in stacking up a collection of local constants. Delete the old constants if existing
      */
@@ -221,17 +232,22 @@ HRESULT shader_get_registers_used(
     shader_delete_constant_list(&This->baseShader.constantsB);
     shader_delete_constant_list(&This->baseShader.constantsI);
 
+    /* The version token is supposed to be the first token */
+    if (!shader_is_version_token(*pToken))
+    {
+        FIXME("First token is not a version token, invalid shader.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+    reg_maps->shader_version = shader_version = *pToken++;
+    pshader = shader_is_pshader_version(shader_version);
+
     while (WINED3DVS_END() != *pToken) {
         CONST SHADER_OPCODE* curOpcode;
         DWORD opcode_token;
 
-        /* Skip version */
-        if (shader_is_version_token(*pToken)) {
-             ++pToken;
-             continue;
-
         /* Skip comments */
-        } else if (shader_is_comment(*pToken)) {
+        if (shader_is_comment(*pToken))
+        {
              DWORD comment_len = (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT;
              ++pToken;
              pToken += comment_len;
@@ -287,7 +303,8 @@ HRESULT shader_get_registers_used(
             memcpy(lconst->value, pToken + 1, 4 * sizeof(DWORD));
 
             /* In pixel shader 1.X shaders, the constants are clamped between [-1;1] */
-            if(WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1 && pshader) {
+            if (WINED3DSHADER_VERSION_MAJOR(shader_version) == 1 && pshader)
+            {
                 float *value = (float *) lconst->value;
                 if(value[0] < -1.0) value[0] = -1.0;
                 else if(value[0] >  1.0) value[0] =  1.0;
@@ -328,6 +345,8 @@ HRESULT shader_get_registers_used(
                 max_loop_depth = cur_loop_depth;
             pToken += curOpcode->num_params;
 
+            /* Rep and Loop always use an integer constant for the control parameters */
+            This->baseShader.uses_int_consts = TRUE;
         } else if (WINED3DSIO_ENDLOOP == curOpcode->opcode ||
                    WINED3DSIO_ENDREP == curOpcode->opcode) {
             cur_loop_depth--;
@@ -344,50 +363,25 @@ HRESULT shader_get_registers_used(
             int i, limit;
 
             /* Declare 1.X samplers implicitly, based on the destination reg. number */
-            if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1 &&
-                pshader /* Filter different instructions with the same enum values in VS */ &&
-                (WINED3DSIO_TEX == curOpcode->opcode ||
-                 WINED3DSIO_TEXBEM == curOpcode->opcode ||
-                 WINED3DSIO_TEXBEML == curOpcode->opcode ||
-                 WINED3DSIO_TEXDP3TEX == curOpcode->opcode ||
-                 WINED3DSIO_TEXM3x2TEX == curOpcode->opcode ||
-                 WINED3DSIO_TEXM3x3SPEC == curOpcode->opcode ||
-                 WINED3DSIO_TEXM3x3TEX == curOpcode->opcode ||
-                 WINED3DSIO_TEXM3x3VSPEC == curOpcode->opcode ||
-                 WINED3DSIO_TEXREG2AR == curOpcode->opcode ||
-                 WINED3DSIO_TEXREG2GB == curOpcode->opcode ||
-                 WINED3DSIO_TEXREG2RGB == curOpcode->opcode)) {
-
+            if (WINED3DSHADER_VERSION_MAJOR(shader_version) == 1
+                    && pshader /* Filter different instructions with the same enum values in VS */
+                    && (WINED3DSIO_TEX == curOpcode->opcode
+                        || WINED3DSIO_TEXBEM == curOpcode->opcode
+                        || WINED3DSIO_TEXBEML == curOpcode->opcode
+                        || WINED3DSIO_TEXDP3TEX == curOpcode->opcode
+                        || WINED3DSIO_TEXM3x2TEX == curOpcode->opcode
+                        || WINED3DSIO_TEXM3x3SPEC == curOpcode->opcode
+                        || WINED3DSIO_TEXM3x3TEX == curOpcode->opcode
+                        || WINED3DSIO_TEXM3x3VSPEC == curOpcode->opcode
+                        || WINED3DSIO_TEXREG2AR == curOpcode->opcode
+                        || WINED3DSIO_TEXREG2GB == curOpcode->opcode
+                        || WINED3DSIO_TEXREG2RGB == curOpcode->opcode))
+            {
                 /* Fake sampler usage, only set reserved bit and ttype */
                 DWORD sampler_code = *pToken & WINED3DSP_REGNUM_MASK;
 
-                if(!stateBlock->textures[sampler_code]) {
-                    ERR("No texture bound to sampler %d\n", sampler_code);
-                    reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_2D;
-                } else {
-                    int texType = IWineD3DBaseTexture_GetTextureDimensions(stateBlock->textures[sampler_code]);
-                    switch(texType) {
-                        /* We have to select between texture rectangles and 2D textures later because 2.0 and
-                         * 3.0 shaders only have WINED3DSTT_2D as well
-                         */
-                        case GL_TEXTURE_RECTANGLE_ARB:
-                        case GL_TEXTURE_2D:
-                            reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_2D;
-                            break;
-
-                        case GL_TEXTURE_3D:
-                            reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_VOLUME;
-                            break;
-
-                        case GL_TEXTURE_CUBE_MAP_ARB:
-                            reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_CUBE;
-                            break;
-
-                        default:
-                            ERR("Unexpected gl texture type found: %d\n", texType);
-                            reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_2D;
-                    }
-                }
+                TRACE("Setting fake 2D sampler for 1.x pixelshader\n");
+                reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_2D;
 
                 /* texbem is only valid with < 1.4 pixel shaders */
                 if(WINED3DSIO_TEXBEM  == curOpcode->opcode ||
@@ -473,20 +467,30 @@ HRESULT shader_get_registers_used(
                         reg_maps->usesrelconstF = TRUE;
                     }
                 }
+                else if(WINED3DSPR_CONSTINT == regtype) {
+                    This->baseShader.uses_int_consts = TRUE;
+                }
+                else if(WINED3DSPR_CONSTBOOL == regtype) {
+                    This->baseShader.uses_bool_consts = TRUE;
+                }
 
                 /* WINED3DSPR_TEXCRDOUT is the same as WINED3DSPR_OUTPUT. _OUTPUT can be > MAX_REG_TEXCRD and is used
                  * in >= 3.0 shaders. Filter 3.0 shaders to prevent overflows, and also filter pixel shaders because TECRDOUT
                  * isn't used in them, but future register types might cause issues
                  */
-                else if(WINED3DSPR_TEXCRDOUT == regtype && i == 0 /* Only look at writes */ &&
-                        !pshader && WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) < 3) {
+                else if (WINED3DSPR_TEXCRDOUT == regtype && i == 0 /* Only look at writes */
+                        && !pshader && WINED3DSHADER_VERSION_MAJOR(shader_version) < 3)
+                {
                     reg_maps->texcoord_mask[reg] |= shader_get_writemask(param);
                 }
             }
         }
     }
+    ++pToken;
     reg_maps->loop_depth = max_loop_depth;
 
+    This->baseShader.functionLength = ((char *)pToken - (char *)byte_code);
+
     return WINED3D_OK;
 }
 
@@ -593,7 +597,7 @@ static void shader_dump_param(const DWORD param, const DWORD addr_token, int inp
 {
     static const char * const rastout_reg_names[] = { "oPos", "oFog", "oPts" };
     static const char * const misctype_reg_names[] = { "vPos", "vFace"};
-    char swizzle_reg_chars[4];
+    const char *swizzle_reg_chars = "xyzw";
 
     DWORD reg = param & WINED3DSP_REGNUM_MASK;
     DWORD regtype = shader_get_regtype(param);
@@ -602,14 +606,6 @@ static void shader_dump_param(const DWORD param, const DWORD addr_token, int inp
     /* There are some minor differences between pixel and vertex shaders */
     char pshader = shader_is_pshader_version(shader_version);
 
-    /* For one, we'd prefer color components to be shown for pshaders.
-     * FIXME: use the swizzle function for this */
-
-    swizzle_reg_chars[0] = pshader? 'r': 'x';
-    swizzle_reg_chars[1] = pshader? 'g': 'y';
-    swizzle_reg_chars[2] = pshader? 'b': 'z';
-    swizzle_reg_chars[3] = pshader? 'a': 'w';
-
     if (input) {
         if ( (modifier == WINED3DSPSM_NEG) ||
              (modifier == WINED3DSPSM_BIASNEG) ||
@@ -714,10 +710,10 @@ static void shader_dump_param(const DWORD param, const DWORD addr_token, int inp
    } else {
         /** operand input */
         DWORD swizzle = (param & WINED3DSP_SWIZZLE_MASK) >> WINED3DSP_SWIZZLE_SHIFT;
-        DWORD swizzle_r = swizzle & 0x03;
-        DWORD swizzle_g = (swizzle >> 2) & 0x03;
-        DWORD swizzle_b = (swizzle >> 4) & 0x03;
-        DWORD swizzle_a = (swizzle >> 6) & 0x03;
+        DWORD swizzle_x = swizzle & 0x03;
+        DWORD swizzle_y = (swizzle >> 2) & 0x03;
+        DWORD swizzle_z = (swizzle >> 4) & 0x03;
+        DWORD swizzle_w = (swizzle >> 6) & 0x03;
 
         if (0 != modifier) {
             switch (modifier) {
@@ -745,25 +741,24 @@ static void shader_dump_param(const DWORD param, const DWORD addr_token, int inp
         *  RRGGBBAA
         */
         if ((WINED3DVS_NOSWIZZLE >> WINED3DVS_SWIZZLE_SHIFT) != swizzle) {
-            if (swizzle_r == swizzle_g &&
-                swizzle_r == swizzle_b &&
-                swizzle_r == swizzle_a) {
-                    TRACE(".%c", swizzle_reg_chars[swizzle_r]);
+            if (swizzle_x == swizzle_y &&
+                swizzle_x == swizzle_z &&
+                swizzle_x == swizzle_w) {
+                    TRACE(".%c", swizzle_reg_chars[swizzle_x]);
             } else {
                 TRACE(".%c%c%c%c",
-                swizzle_reg_chars[swizzle_r],
-                swizzle_reg_chars[swizzle_g],
-                swizzle_reg_chars[swizzle_b],
-                swizzle_reg_chars[swizzle_a]);
+                swizzle_reg_chars[swizzle_x],
+                swizzle_reg_chars[swizzle_y],
+                swizzle_reg_chars[swizzle_z],
+                swizzle_reg_chars[swizzle_w]);
             }
         }
     }
 }
 
 static void shader_color_correction(IWineD3DBaseShaderImpl *shader,
-        IWineD3DDeviceImpl *device, const struct SHADER_OPCODE_ARG *arg)
+        IWineD3DDeviceImpl *device, const struct SHADER_OPCODE_ARG *arg, DWORD shader_version)
 {
-    DWORD hex_version = shader->baseShader.hex_version;
     IWineD3DBaseTextureImpl *texture;
     struct color_fixup_desc fixup;
     BOOL recorded = FALSE;
@@ -773,7 +768,7 @@ static void shader_color_correction(IWineD3DBaseShaderImpl *shader,
     switch(arg->opcode->opcode)
     {
         case WINED3DSIO_TEX:
-            if (hex_version < WINED3DPS_VERSION(2,0)) sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
+            if (WINED3DSHADER_VERSION_MAJOR(shader_version) < 2) sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
             else sampler_idx = arg->src[1] & WINED3DSP_REGNUM_MASK;
             break;
 
@@ -821,10 +816,8 @@ static void shader_color_correction(IWineD3DBaseShaderImpl *shader,
     device->shader_backend->shader_color_correction(arg, fixup);
 }
 
-/** Shared code in order to generate the bulk of the shader string.
-    Use the shader_header_fct & shader_footer_fct to add strings
-    that are specific to pixel or vertex functions
-    NOTE: A description of how to parse tokens can be found on msdn */
+/* Shared code in order to generate the bulk of the shader string.
+ * NOTE: A description of how to parse tokens can be found on msdn */
 void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER* buffer,
         const shader_reg_maps* reg_maps, CONST DWORD* pFunction)
 {
@@ -832,10 +825,10 @@ void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER* buffer,
     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device; /* To access shader backend callbacks */
     const SHADER_OPCODE *opcode_table = This->baseShader.shader_ins;
     const SHADER_HANDLER *handler_table = device->shader_backend->shader_instruction_handler_table;
-    DWORD shader_version = This->baseShader.hex_version;
+    DWORD shader_version = reg_maps->shader_version;
     const DWORD *pToken = pFunction;
-    const SHADER_OPCODE *curOpcode = NULL;
-    SHADER_HANDLER hw_fct = NULL;
+    const SHADER_OPCODE *curOpcode;
+    SHADER_HANDLER hw_fct;
     DWORD i;
     SHADER_OPCODE_ARG hw_arg;
 
@@ -845,99 +838,92 @@ void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER* buffer,
     hw_arg.reg_maps = reg_maps;
     This->baseShader.parse_state.current_row = 0;
 
-    /* Second pass, process opcodes */
-    if (NULL != pToken) {
-        while (WINED3DPS_END() != *pToken) {
-
-            /* Skip version token */
-            if (shader_is_version_token(*pToken)) {
-                ++pToken;
-                continue;
-            }
-
-            /* Skip comment tokens */
-            if (shader_is_comment(*pToken)) {
-                DWORD comment_len = (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT;
-                ++pToken;
-                TRACE("#%s\n", (const char*)pToken);
-                pToken += comment_len;
-                continue;
-            }
-
-            /* Read opcode */
-            hw_arg.opcode_token = *pToken++;
-            curOpcode = shader_get_opcode(opcode_table, shader_version, hw_arg.opcode_token);
-
-            /* Select handler */
-            if (curOpcode == NULL)
-                hw_fct = NULL;
-            else
-                hw_fct = handler_table[curOpcode->handler_idx];
-
-            /* Unknown opcode and its parameters */
-            if (NULL == curOpcode) {
-                FIXME("Unrecognized opcode: token=0x%08x\n", hw_arg.opcode_token);
-                pToken += shader_skip_unrecognized(pToken, shader_version);
-
-            /* Nothing to do */
-            } else if (WINED3DSIO_DCL == curOpcode->opcode ||
-                       WINED3DSIO_NOP == curOpcode->opcode ||
-                       WINED3DSIO_DEF == curOpcode->opcode ||
-                       WINED3DSIO_DEFI == curOpcode->opcode ||
-                       WINED3DSIO_DEFB == curOpcode->opcode ||
-                       WINED3DSIO_PHASE == curOpcode->opcode ||
-                       WINED3DSIO_RET == curOpcode->opcode) {
-
-                pToken += shader_skip_opcode(This, curOpcode, hw_arg.opcode_token);
+    while (WINED3DPS_END() != *pToken)
+    {
+        /* Skip version token */
+        if (shader_is_version_token(*pToken))
+        {
+            ++pToken;
+            continue;
+        }
 
-            /* If a generator function is set for current shader target, use it */
-            } else if (hw_fct != NULL) {
+        /* Skip comment tokens */
+        if (shader_is_comment(*pToken))
+        {
+            pToken += (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT;
+            ++pToken;
+            continue;
+        }
 
-                hw_arg.opcode = curOpcode;
+        /* Read opcode */
+        hw_arg.opcode_token = *pToken++;
+        curOpcode = shader_get_opcode(opcode_table, shader_version, hw_arg.opcode_token);
 
-                /* Destination token */
-                if (curOpcode->dst_token) {
+        /* Unknown opcode and its parameters */
+        if (!curOpcode)
+        {
+            FIXME("Unrecognized opcode: token=0x%08x\n", hw_arg.opcode_token);
+            pToken += shader_skip_unrecognized(pToken, shader_version);
+            continue;
+        }
 
-                    DWORD param, addr_token = 0;
-                    pToken += shader_get_param(pToken, shader_version, &param, &addr_token);
-                    hw_arg.dst = param;
-                    hw_arg.dst_addr = addr_token;
-                }
+        /* Nothing to do */
+        if (WINED3DSIO_DCL == curOpcode->opcode
+                || WINED3DSIO_NOP == curOpcode->opcode
+                || WINED3DSIO_DEF == curOpcode->opcode
+                || WINED3DSIO_DEFI == curOpcode->opcode
+                || WINED3DSIO_DEFB == curOpcode->opcode
+                || WINED3DSIO_PHASE == curOpcode->opcode
+                || WINED3DSIO_RET == curOpcode->opcode)
+        {
+            pToken += shader_skip_opcode(curOpcode, hw_arg.opcode_token, shader_version);
+            continue;
+        }
 
-                /* Predication token */
-                if (hw_arg.opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED) 
-                    hw_arg.predicate = *pToken++;
+        /* Select handler */
+        hw_fct = handler_table[curOpcode->handler_idx];
 
-                /* Other source tokens */
-                for (i = 0; i < (curOpcode->num_params - curOpcode->dst_token); i++) {
+        /* Unhandled opcode */
+        if (!hw_fct)
+        {
+            FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
+            pToken += shader_skip_opcode(curOpcode, hw_arg.opcode_token, shader_version);
+            continue;
+        }
 
-                    DWORD param, addr_token = 0; 
-                    pToken += shader_get_param(pToken, shader_version, &param, &addr_token);
-                    hw_arg.src[i] = param;
-                    hw_arg.src_addr[i] = addr_token;
-                }
+        hw_arg.opcode = curOpcode;
 
-                /* Call appropriate function for output target */
-                hw_fct(&hw_arg);
+        /* Destination token */
+        if (curOpcode->dst_token)
+        {
+            DWORD param, addr_token = 0;
+            pToken += shader_get_param(pToken, shader_version, &param, &addr_token);
+            hw_arg.dst = param;
+            hw_arg.dst_addr = addr_token;
+        }
 
-                /* Add color correction if needed */
-                shader_color_correction(This, device, &hw_arg);
+        /* Predication token */
+        if (hw_arg.opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED) hw_arg.predicate = *pToken++;
 
-                /* Process instruction modifiers for GLSL apps ( _sat, etc. ) */
-                /* FIXME: This should be internal to the shader backend.
-                 * Also, right now this is the only reason "shader_mode" exists. */
-                if (This->baseShader.shader_mode == SHADER_GLSL)
-                    shader_glsl_add_instruction_modifiers(&hw_arg);
+        /* Other source tokens */
+        for (i = 0; i < (curOpcode->num_params - curOpcode->dst_token); ++i)
+        {
+            DWORD param, addr_token = 0;
+            pToken += shader_get_param(pToken, shader_version, &param, &addr_token);
+            hw_arg.src[i] = param;
+            hw_arg.src_addr[i] = addr_token;
+        }
 
-            /* Unhandled opcode */
-            } else {
+        /* Call appropriate function for output target */
+        hw_fct(&hw_arg);
 
-                FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
-                pToken += shader_skip_opcode(This, curOpcode, hw_arg.opcode_token);
-            }
-        }
-        /* TODO: What about result.depth? */
+        /* Add color correction if needed */
+        shader_color_correction(This, device, &hw_arg, shader_version);
 
+        /* Process instruction modifiers for GLSL apps ( _sat, etc. ) */
+        /* FIXME: This should be internal to the shader backend.
+         * Also, right now this is the only reason "shader_mode" exists. */
+        if (This->baseShader.shader_mode == SHADER_GLSL) shader_glsl_add_instruction_modifiers(&hw_arg);
     }
 }
 
@@ -966,60 +952,45 @@ static void shader_dump_ins_modifiers(const DWORD output)
         FIXME("_unrecognized_modifier(%#x)", mmask >> WINED3DSP_DSTMOD_SHIFT);
 }
 
-/* First pass: trace shader, initialize length and version */
-void shader_trace_init(
-    IWineD3DBaseShader *iface,
-    const DWORD* pFunction) {
-
-    IWineD3DBaseShaderImpl *This =(IWineD3DBaseShaderImpl *)iface;
-
+void shader_trace_init(const DWORD *pFunction, const SHADER_OPCODE *opcode_table)
+{
     const DWORD* pToken = pFunction;
     const SHADER_OPCODE* curOpcode = NULL;
+    DWORD shader_version;
     DWORD opcode_token;
-    unsigned int len = 0;
     DWORD i;
 
-    TRACE("(%p) : Parsing program\n", This);
+    TRACE("Parsing %p\n", pFunction);
 
-    if (!pFunction)
+    /* The version token is supposed to be the first token */
+    if (!shader_is_version_token(*pToken))
     {
-        WARN("Got a NULL pFunction, returning.\n");
-        This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
+        FIXME("First token is not a version token, invalid shader.\n");
         return;
     }
+    shader_version = *pToken++;
+    TRACE("%s_%u_%u\n", shader_is_pshader_version(shader_version) ? "ps": "vs",
+            WINED3DSHADER_VERSION_MAJOR(shader_version), WINED3DSHADER_VERSION_MINOR(shader_version));
 
     while (WINED3DVS_END() != *pToken)
     {
-        if (shader_is_version_token(*pToken)) /* version */
-        {
-            This->baseShader.hex_version = *pToken;
-            TRACE("%s_%u_%u\n", shader_is_pshader_version(This->baseShader.hex_version)? "ps": "vs",
-                WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version),
-                WINED3DSHADER_VERSION_MINOR(This->baseShader.hex_version));
-            ++pToken;
-            ++len;
-            continue;
-        }
         if (shader_is_comment(*pToken)) /* comment */
         {
             DWORD comment_len = (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT;
             ++pToken;
             TRACE("//%s\n", (const char*)pToken);
             pToken += comment_len;
-            len += comment_len + 1;
             continue;
         }
         opcode_token = *pToken++;
-        curOpcode = shader_get_opcode(This->baseShader.shader_ins, This->baseShader.hex_version, opcode_token);
-        len++;
+        curOpcode = shader_get_opcode(opcode_table, shader_version, opcode_token);
 
         if (!curOpcode)
         {
             int tokens_read;
             FIXME("Unrecognized opcode: token=0x%08x\n", opcode_token);
-            tokens_read = shader_skip_unrecognized(pToken, This->baseShader.hex_version);
+            tokens_read = shader_skip_unrecognized(pToken, shader_version);
             pToken += tokens_read;
-            len += tokens_read;
         }
         else
         {
@@ -1028,12 +999,11 @@ void shader_trace_init(
                 DWORD usage = *pToken;
                 DWORD param = *(pToken + 1);
 
-                shader_dump_decl_usage(usage, param, This->baseShader.hex_version);
+                shader_dump_decl_usage(usage, param, shader_version);
                 shader_dump_ins_modifiers(param);
                 TRACE(" ");
-                shader_dump_param(param, 0, 0, This->baseShader.hex_version);
+                shader_dump_param(param, 0, 0, shader_version);
                 pToken += 2;
-                len += 2;
             }
             else if (curOpcode->opcode == WINED3DSIO_DEF)
             {
@@ -1045,7 +1015,6 @@ void shader_trace_init(
                         *(const float *)(pToken + 3),
                         *(const float *)(pToken + 4));
                 pToken += 5;
-                len += 5;
             }
             else if (curOpcode->opcode == WINED3DSIO_DEFI)
             {
@@ -1055,14 +1024,12 @@ void shader_trace_init(
                         *(pToken + 3),
                         *(pToken + 4));
                 pToken += 5;
-                len += 5;
             }
             else if (curOpcode->opcode == WINED3DSIO_DEFB)
             {
                 TRACE("defb b%u = %s", *pToken & WINED3DSP_REGNUM_MASK,
                         *(pToken + 1)? "true": "false");
                 pToken += 2;
-                len += 2;
             }
             else
             {
@@ -1074,7 +1041,7 @@ void shader_trace_init(
                 if (opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED)
                 {
                     TRACE("(");
-                    shader_dump_param(*(pToken + 2), 0, 1, This->baseShader.hex_version);
+                    shader_dump_param(*(pToken + 2), 0, 1, shader_version);
                     TRACE(") ");
                 }
                 if (opcode_token & WINED3DSI_COISSUE)
@@ -1102,7 +1069,7 @@ void shader_trace_init(
                     }
                 }
                 else if (curOpcode->opcode == WINED3DSIO_TEX
-                        && This->baseShader.hex_version >= WINED3DPS_VERSION(2,0)
+                        && shader_version >= WINED3DPS_VERSION(2,0)
                         && (opcode_token & WINED3DSI_TEXLD_PROJECT))
                 {
                     TRACE("p");
@@ -1111,51 +1078,60 @@ void shader_trace_init(
                 /* Destination token */
                 if (curOpcode->dst_token)
                 {
-                    tokens_read = shader_get_param(pToken, This->baseShader.hex_version, &param, &addr_token);
+                    tokens_read = shader_get_param(pToken, shader_version, &param, &addr_token);
                     pToken += tokens_read;
-                    len += tokens_read;
 
                     shader_dump_ins_modifiers(param);
                     TRACE(" ");
-                    shader_dump_param(param, addr_token, 0, This->baseShader.hex_version);
+                    shader_dump_param(param, addr_token, 0, shader_version);
                 }
 
                 /* Predication token - already printed out, just skip it */
                 if (opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED)
                 {
                     pToken++;
-                    len++;
                 }
 
                 /* Other source tokens */
                 for (i = curOpcode->dst_token; i < curOpcode->num_params; ++i)
                 {
-                    tokens_read = shader_get_param(pToken, This->baseShader.hex_version, &param, &addr_token);
+                    tokens_read = shader_get_param(pToken, shader_version, &param, &addr_token);
                     pToken += tokens_read;
-                    len += tokens_read;
 
                     TRACE((i == 0)? " " : ", ");
-                    shader_dump_param(param, addr_token, 1, This->baseShader.hex_version);
+                    shader_dump_param(param, addr_token, 1, shader_version);
                 }
             }
             TRACE("\n");
         }
     }
-    This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
+}
+
+void shader_cleanup(IWineD3DBaseShader *iface)
+{
+    IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)iface;
+
+    ((IWineD3DDeviceImpl *)This->baseShader.device)->shader_backend->shader_destroy(iface);
+    HeapFree(GetProcessHeap(), 0, This->baseShader.function);
+    shader_delete_constant_list(&This->baseShader.constantsF);
+    shader_delete_constant_list(&This->baseShader.constantsB);
+    shader_delete_constant_list(&This->baseShader.constantsI);
+    list_remove(&This->baseShader.shader_list_entry);
 }
 
 static const SHADER_HANDLER shader_none_instruction_handler_table[WINED3DSIH_TABLE_SIZE] = {0};
 static void shader_none_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {}
 static void shader_none_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) {}
 static void shader_none_deselect_depth_blt(IWineD3DDevice *iface) {}
+static void shader_none_update_float_vertex_constants(IWineD3DDevice *iface, UINT start, UINT count) {}
+static void shader_none_update_float_pixel_constants(IWineD3DDevice *iface, UINT start, UINT count) {}
 static void shader_none_load_constants(IWineD3DDevice *iface, char usePS, char useVS) {}
-static void shader_none_cleanup(IWineD3DDevice *iface) {}
 static void shader_none_color_correction(const struct SHADER_OPCODE_ARG *arg, struct color_fixup_desc fixup) {}
 static void shader_none_destroy(IWineD3DBaseShader *iface) {}
 static HRESULT shader_none_alloc(IWineD3DDevice *iface) {return WINED3D_OK;}
 static void shader_none_free(IWineD3DDevice *iface) {}
 static BOOL shader_none_dirty_const(IWineD3DDevice *iface) {return FALSE;}
-static GLuint shader_none_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer) {
+static GLuint shader_none_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer, const struct ps_compile_args *args) {
     FIXME("NONE shader backend asked to generate a pixel shader\n");
     return 0;
 }
@@ -1196,8 +1172,9 @@ const shader_backend_t none_shader_backend = {
     shader_none_select,
     shader_none_select_depth_blt,
     shader_none_deselect_depth_blt,
+    shader_none_update_float_vertex_constants,
+    shader_none_update_float_pixel_constants,
     shader_none_load_constants,
-    shader_none_cleanup,
     shader_none_color_correction,
     shader_none_destroy,
     shader_none_alloc,
@@ -1208,46 +1185,3 @@ const shader_backend_t none_shader_backend = {
     shader_none_get_caps,
     shader_none_color_fixup_supported,
 };
-
-/* *******************************************
-   IWineD3DPixelShader IUnknown parts follow
-   ******************************************* */
-HRESULT  WINAPI IWineD3DBaseShaderImpl_QueryInterface(IWineD3DBaseShader *iface, REFIID riid, LPVOID *ppobj)
-{
-    IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)iface;
-    TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
-    if (IsEqualGUID(riid, &IID_IUnknown)
-        || IsEqualGUID(riid, &IID_IWineD3DBase)
-        || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
-        || IsEqualGUID(riid, &IID_IWineD3DPixelShader)) {
-        IUnknown_AddRef(iface);
-        *ppobj = This;
-        return S_OK;
-    }
-    *ppobj = NULL;
-    return E_NOINTERFACE;
-}
-
-ULONG  WINAPI IWineD3DBaseShaderImpl_AddRef(IWineD3DBaseShader *iface) {
-    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
-    TRACE("(%p) : AddRef increasing from %d\n", This, This->baseShader.ref);
-    return InterlockedIncrement(&This->baseShader.ref);
-}
-
-ULONG  WINAPI IWineD3DBaseShaderImpl_Release(IWineD3DBaseShader *iface) {
-    IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)iface;
-    IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *) This->baseShader.device;
-    ULONG ref;
-    TRACE("(%p) : Releasing from %d\n", This, This->baseShader.ref);
-    ref = InterlockedDecrement(&This->baseShader.ref);
-    if (ref == 0) {
-        deviceImpl->shader_backend->shader_destroy(iface);
-        HeapFree(GetProcessHeap(), 0, This->baseShader.function);
-        shader_delete_constant_list(&This->baseShader.constantsF);
-        shader_delete_constant_list(&This->baseShader.constantsB);
-        shader_delete_constant_list(&This->baseShader.constantsI);
-        list_remove(&This->baseShader.shader_list_entry);
-        HeapFree(GetProcessHeap(), 0, This);
-    }
-    return ref;
-}
index 158650e..f6189b6 100644 (file)
 WINE_DEFAULT_DEBUG_CHANNEL(d3d_texture);
 #define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info
 
+void basetexture_init(struct IWineD3DBaseTextureClass *texture, UINT levels, DWORD usage)
+{
+    texture->levels = levels;
+    texture->filterType = (usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE;
+    texture->LOD = 0;
+    texture->dirty = TRUE;
+    texture->is_srgb = FALSE;
+    texture->srgb_mode_change_count = 0;
+}
+
 void basetexture_cleanup(IWineD3DBaseTexture *iface)
 {
     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
@@ -249,7 +259,6 @@ HRESULT basetexture_bind(IWineD3DBaseTexture *iface)
                 glTexParameteri(textureDimensions, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
             }
         }
-               
     } else { /* this only happened if we've run out of openGL textures */
         WARN("This texture doesn't have an openGL texture assigned to it\n");
         hr =  WINED3DERR_INVALIDCALL;
index 05afe5d..da3053a 100644 (file)
@@ -839,12 +839,6 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
 
     checkGLcall("glClear");
 
-    glColor3f(1.0, 1.0, 1.0);
-    checkGLcall("glColor3f");
-
-    glEnable(GL_LIGHTING);
-    checkGLcall("glEnable");
-
     glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
     checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
 
@@ -1053,7 +1047,7 @@ static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *contex
     /* TODO: Use a display list */
 
     /* Disable shaders */
-    This->shader_backend->shader_cleanup((IWineD3DDevice *) This);
+    This->shader_backend->shader_select((IWineD3DDevice *)This, FALSE, FALSE);
     Context_MarkStateDirty(context, STATE_VSHADER, StateTable);
     Context_MarkStateDirty(context, STATE_PIXELSHADER, StateTable);
 
@@ -1066,42 +1060,40 @@ static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *contex
 
     /* Disable all textures. The caller can then bind a texture it wants to blit
      * from
+     *
+     * The blitting code uses (for now) the fixed function pipeline, so make sure to reset all fixed
+     * function texture unit. No need to care for higher samplers
      */
-    if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-        /* The blitting code uses (for now) the fixed function pipeline, so make sure to reset all fixed
-         * function texture unit. No need to care for higher samplers
-         */
-        for(i = GL_LIMITS(textures) - 1; i > 0 ; i--) {
-            sampler = This->rev_tex_unit_map[i];
-            GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
-            checkGLcall("glActiveTextureARB");
-
-            if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
-                glDisable(GL_TEXTURE_CUBE_MAP_ARB);
-                checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB");
-            }
-            glDisable(GL_TEXTURE_3D);
-            checkGLcall("glDisable GL_TEXTURE_3D");
-            if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
-                glDisable(GL_TEXTURE_RECTANGLE_ARB);
-                checkGLcall("glDisable GL_TEXTURE_RECTANGLE_ARB");
-            }
-            glDisable(GL_TEXTURE_2D);
-            checkGLcall("glDisable GL_TEXTURE_2D");
+    for(i = GL_LIMITS(textures) - 1; i > 0 ; i--) {
+        sampler = This->rev_tex_unit_map[i];
+        GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
+        checkGLcall("glActiveTextureARB");
 
-            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-            checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);");
+        if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
+            glDisable(GL_TEXTURE_CUBE_MAP_ARB);
+            checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB");
+        }
+        glDisable(GL_TEXTURE_3D);
+        checkGLcall("glDisable GL_TEXTURE_3D");
+        if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
+            glDisable(GL_TEXTURE_RECTANGLE_ARB);
+            checkGLcall("glDisable GL_TEXTURE_RECTANGLE_ARB");
+        }
+        glDisable(GL_TEXTURE_2D);
+        checkGLcall("glDisable GL_TEXTURE_2D");
 
-            if (sampler != -1) {
-                if (sampler < MAX_TEXTURES) {
-                    Context_MarkStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP), StateTable);
-                }
-                Context_MarkStateDirty(context, STATE_SAMPLER(sampler), StateTable);
+        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+        checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);");
+
+        if (sampler != -1) {
+            if (sampler < MAX_TEXTURES) {
+                Context_MarkStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP), StateTable);
             }
+            Context_MarkStateDirty(context, STATE_SAMPLER(sampler), StateTable);
         }
-        GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
-        checkGLcall("glActiveTextureARB");
     }
+    GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
+    checkGLcall("glActiveTextureARB");
 
     sampler = This->rev_tex_unit_map[0];
 
@@ -1150,7 +1142,7 @@ static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *contex
     glDisable(GL_DEPTH_TEST);
     checkGLcall("glDisable GL_DEPTH_TEST");
     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ZENABLE), StateTable);
-    glDisable(GL_FOG);
+    glDisableWINE(GL_FOG);
     checkGLcall("glDisable GL_FOG");
     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_FOGENABLE), StateTable);
     glDisable(GL_BLEND);
@@ -1623,3 +1615,7 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
             FIXME("Unexpected context usage requested\n");
     }
 }
+
+WineD3DContext *getActiveContext(void) {
+    return last_device->activeContext;
+}
index 90b1221..c7de212 100644 (file)
@@ -136,9 +136,8 @@ static void WINAPI IWineD3DCubeTextureImpl_PreLoad(IWineD3DCubeTexture *iface) {
             }
         }
     } else if (srgb_was_toggled) {
-        /* Loop is repeated in the else block with the extra AddDirtyRect line to avoid the alternative of
-         * checking srgb_was_toggled in every iteration, even when the texture is just dirty
-         */
+        /* Loop is repeated in the else block with the extra surface_add_dirty_rect() line to avoid the
+         * alternative of checking srgb_was_toggled in every iteration, even when the texture is just dirty */
         if (This->baseTexture.srgb_mode_change_count < 20)
             ++This->baseTexture.srgb_mode_change_count;
         else
@@ -146,7 +145,7 @@ static void WINAPI IWineD3DCubeTextureImpl_PreLoad(IWineD3DCubeTexture *iface) {
 
         for (i = 0; i < This->baseTexture.levels; i++) {
             for (j = WINED3DCUBEMAP_FACE_POSITIVE_X; j <= WINED3DCUBEMAP_FACE_NEGATIVE_Z ; j++) {
-                IWineD3DSurface_AddDirtyRect(This->surfaces[j][i], NULL);
+                surface_add_dirty_rect(This->surfaces[j][i], NULL);
                 surface_force_reload(This->surfaces[j][i]);
                 IWineD3DSurface_LoadTexture(This->surfaces[j][i], srgb_mode);
             }
@@ -298,7 +297,7 @@ static HRESULT WINAPI IWineD3DCubeTextureImpl_GetLevelDesc(IWineD3DCubeTexture *
         TRACE("(%p) level (%d)\n", This, Level);
         return IWineD3DSurface_GetDesc(This->surfaces[0][Level], pDesc);
     }
-    FIXME("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels);
+    WARN("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels);
     return WINED3DERR_INVALIDCALL;
 }
 
@@ -360,7 +359,8 @@ static HRESULT  WINAPI IWineD3DCubeTextureImpl_AddDirtyRect(IWineD3DCubeTexture
     This->baseTexture.dirty = TRUE;
     TRACE("(%p) : dirtyfication of faceType(%d) Level (0)\n", This, FaceType);
     if (FaceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z) {
-        hr = IWineD3DSurface_AddDirtyRect(This->surfaces[FaceType][0], pDirtyRect);
+        surface_add_dirty_rect(This->surfaces[FaceType][0], pDirtyRect);
+        hr = WINED3D_OK;
     } else {
         WARN("(%p) overflow FaceType(%d)\n", This, FaceType);
     }
index 836ad3b..d4a57c9 100644 (file)
@@ -54,76 +54,6 @@ const WINED3DLIGHT WINED3D_default_light = {
 /* static function declarations */
 static void IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
 
-/* helper macros */
-#define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
-
-#define D3DCREATEOBJECTINSTANCE(object, type) { \
-    object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
-    D3DMEMCHECK(object, pp##type); \
-    object->lpVtbl = &IWineD3D##type##_Vtbl;  \
-    object->wineD3DDevice = This; \
-    object->parent       = parent; \
-    object->ref          = 1; \
-    *pp##type = (IWineD3D##type *) object; \
-}
-
-#define D3DCREATESHADEROBJECTINSTANCE(object, type) { \
-    object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
-    D3DMEMCHECK(object, pp##type); \
-    object->lpVtbl = &IWineD3D##type##_Vtbl;  \
-    object->parent          = parent; \
-    object->baseShader.ref  = 1; \
-    object->baseShader.device = (IWineD3DDevice*) This; \
-    list_init(&object->baseShader.linked_programs); \
-    *pp##type = (IWineD3D##type *) object; \
-}
-
-#define  D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
-    object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
-    D3DMEMCHECK(object, pp##type); \
-    object->lpVtbl = &IWineD3D##type##_Vtbl;  \
-    object->resource.wineD3DDevice   = This; \
-    object->resource.parent          = parent; \
-    object->resource.resourceType    = d3dtype; \
-    object->resource.ref             = 1; \
-    object->resource.pool            = Pool; \
-    object->resource.format          = Format; \
-    object->resource.usage           = Usage; \
-    object->resource.size            = _size; \
-    object->resource.priority        = 0; \
-    list_init(&object->resource.privateData); \
-    /* Check that we have enough video ram left */ \
-    if (Pool == WINED3DPOOL_DEFAULT) { \
-        if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
-            WARN("Out of 'bogus' video memory\n"); \
-            HeapFree(GetProcessHeap(), 0, object); \
-            *pp##type = NULL; \
-            return WINED3DERR_OUTOFVIDEOMEMORY; \
-        } \
-        WineD3DAdapterChangeGLRam(This, _size); \
-    } \
-    object->resource.heapMemory = (0 == _size ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size + RESOURCE_ALIGNMENT)); \
-    if (object->resource.heapMemory == NULL && _size != 0) { \
-        FIXME("Out of memory!\n"); \
-        HeapFree(GetProcessHeap(), 0, object); \
-        *pp##type = NULL; \
-        return WINED3DERR_OUTOFVIDEOMEMORY; \
-    } \
-    object->resource.allocatedMemory = (BYTE *)(((ULONG_PTR) object->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1)); \
-    *pp##type = (IWineD3D##type *) object; \
-    IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
-    TRACE("(%p) : Created resource %p\n", This, object); \
-}
-
-#define D3DINITIALIZEBASETEXTURE(_basetexture) { \
-    _basetexture.levels     = Levels; \
-    _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
-    _basetexture.LOD        = 0; \
-    _basetexture.dirty      = TRUE; \
-    _basetexture.is_srgb = FALSE; \
-    _basetexture.srgb_mode_change_count = 0; \
-}
-
 /**********************************************************
  * Global variable / Constants follow
  **********************************************************/
@@ -164,6 +94,13 @@ static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
     TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
 
     if (!refCount) {
+        UINT i;
+
+        for (i = 0; i < sizeof(This->multistate_funcs)/sizeof(This->multistate_funcs[0]); ++i) {
+            HeapFree(GetProcessHeap(), 0, This->multistate_funcs[i]);
+            This->multistate_funcs[i] = NULL;
+        }
+
         /* TODO: Clean up all the surfaces and textures! */
         /* NOTE: You must release the parent if the object was created via a callback
         ** ***************************/
@@ -203,6 +140,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *ifac
     IWineD3DVertexBufferImpl *object;
     WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
     int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion;
+    HRESULT hr;
     BOOL conv;
 
     if(Size == 0) {
@@ -218,7 +156,27 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *ifac
         return WINED3DERR_INVALIDCALL;
     }
 
-    D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        ERR("Out of memory\n");
+        *ppVertexBuffer = NULL;
+        return WINED3DERR_OUTOFVIDEOMEMORY;
+    }
+
+    object->lpVtbl = &IWineD3DVertexBuffer_Vtbl;
+    hr = resource_init(&object->resource, WINED3DRTYPE_VERTEXBUFFER, This, Size, Usage, Format, Pool, parent);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize resource, returning %#x\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        *ppVertexBuffer = NULL;
+        return hr;
+    }
+
+    TRACE("(%p) : Created resource %p\n", This, object);
+
+    IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object);
 
     TRACE("(%p) : Size=%d, Usage=0x%08x, FVF=%x, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
     *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
@@ -310,10 +268,32 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface
                                                     HANDLE *sharedHandle, IUnknown *parent) {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     IWineD3DIndexBufferImpl *object;
+    HRESULT hr;
+
     TRACE("(%p) Creating index buffer\n", This);
 
     /* Allocate the storage for the device */
-    D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        ERR("Out of memory\n");
+        *ppIndexBuffer = NULL;
+        return WINED3DERR_OUTOFVIDEOMEMORY;
+    }
+
+    object->lpVtbl = &IWineD3DIndexBuffer_Vtbl;
+    hr = resource_init(&object->resource, WINED3DRTYPE_INDEXBUFFER, This, Length, Usage, Format, Pool, parent);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize resource, returning %#x\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        *ppIndexBuffer = NULL;
+        return hr;
+    }
+
+    TRACE("(%p) : Created resource %p\n", This, object);
+
+    IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object);
 
     if(Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
         CreateIndexBufferVBO(This, object);
@@ -333,24 +313,41 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface,
     int i, j;
     HRESULT temp_result;
 
-    D3DCREATEOBJECTINSTANCE(object, StateBlock)
-    object->blockType     = Type;
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if(!object)
+    {
+        ERR("Out of memory\n");
+        *ppStateBlock = NULL;
+        return WINED3DERR_OUTOFVIDEOMEMORY;
+    }
+
+    object->lpVtbl = &IWineD3DStateBlock_Vtbl;
+    object->wineD3DDevice = This;
+    object->parent = parent;
+    object->ref = 1;
+    object->blockType = Type;
+
+    *ppStateBlock = (IWineD3DStateBlock *)object;
 
     for(i = 0; i < LIGHTMAP_SIZE; i++) {
         list_init(&object->lightMap[i]);
     }
 
+    temp_result = allocate_shader_constants(object);
+    if (FAILED(temp_result))
+    {
+        HeapFree(GetProcessHeap(), 0, object);
+        return temp_result;
+    }
+
     /* Special case - Used during initialization to produce a placeholder stateblock
           so other functions called can update a state block                         */
-    if (Type == WINED3DSBT_INIT) {
+    if (Type == WINED3DSBT_INIT || Type == WINED3DSBT_RECORDED)
+    {
         /* Don't bother increasing the reference count otherwise a device will never
            be freed due to circular dependencies                                   */
         return WINED3D_OK;
     }
-    
-    temp_result = allocate_shader_constants(object);
-    if (WINED3D_OK != temp_result)
-        return temp_result;
 
     /* Otherwise, might as well set the whole state block to the appropriate values  */
     if (This->stateBlock != NULL)
@@ -413,7 +410,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface,
         }
         object->num_contained_ps_consts_b = MAX_CONST_B;
         for(i = 0; i < MAX_TEXTURES; i++) {
-            for(j = 1; j <= WINED3D_HIGHEST_TEXTURE_STATE; j++) {
+            for (j = 0; j <= WINED3D_HIGHEST_TEXTURE_STATE; ++j)
+            {
                 object->contained_tss_states[object->num_contained_tss_states].stage = i;
                 object->contained_tss_states[object->num_contained_tss_states].state = j;
                 object->num_contained_tss_states++;
@@ -467,23 +465,26 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface,
         object->num_contained_ps_consts_i = MAX_CONST_I;
 
         for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
-            object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
-            object->contained_render_states[i] = SavedPixelStates_R[i];
+            DWORD rs = SavedPixelStates_R[i];
+            object->changed.renderState[rs >> 5] |= 1 << (rs & 0x1f);
+            object->contained_render_states[i] = rs;
         }
         object->num_contained_render_states = NUM_SAVEDPIXELSTATES_R;
         for (j = 0; j < MAX_TEXTURES; j++) {
             for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
-                object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
+                DWORD state = SavedPixelStates_T[i];
+                object->changed.textureState[j] |= 1 << state;
                 object->contained_tss_states[object->num_contained_tss_states].stage = j;
-                object->contained_tss_states[object->num_contained_tss_states].state = SavedPixelStates_T[i];
+                object->contained_tss_states[object->num_contained_tss_states].state = state;
                 object->num_contained_tss_states++;
             }
         }
         for (j = 0 ; j < MAX_COMBINED_SAMPLERS; j++) {
             for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
-                object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
+                DWORD state = SavedPixelStates_S[i];
+                object->changed.samplerState[j] |= 1 << state;
                 object->contained_sampler_states[object->num_contained_sampler_states].stage = j;
-                object->contained_sampler_states[object->num_contained_sampler_states].state = SavedPixelStates_S[i];
+                object->contained_sampler_states[object->num_contained_sampler_states].state = state;
                 object->num_contained_sampler_states++;
             }
         }
@@ -524,23 +525,26 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface,
         }
         object->num_contained_vs_consts_i = MAX_CONST_I;
         for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
-            object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
-            object->contained_render_states[i] = SavedVertexStates_R[i];
+            DWORD rs = SavedVertexStates_R[i];
+            object->changed.renderState[rs >> 5] |= 1 << (rs & 0x1f);
+            object->contained_render_states[i] = rs;
         }
         object->num_contained_render_states = NUM_SAVEDVERTEXSTATES_R;
         for (j = 0; j < MAX_TEXTURES; j++) {
             for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
-                object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
+                DWORD state = SavedVertexStates_T[i];
+                object->changed.textureState[j] |= 1 << state;
                 object->contained_tss_states[object->num_contained_tss_states].stage = j;
-                object->contained_tss_states[object->num_contained_tss_states].state = SavedVertexStates_T[i];
+                object->contained_tss_states[object->num_contained_tss_states].state = state;
                 object->num_contained_tss_states++;
             }
         }
         for (j = 0 ; j < MAX_COMBINED_SAMPLERS; j++){
             for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
-                object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
+                DWORD state = SavedVertexStates_S[i];
+                object->changed.samplerState[j] |= 1 << state;
                 object->contained_sampler_states[object->num_contained_sampler_states].stage = j;
-                object->contained_sampler_states[object->num_contained_sampler_states].state = SavedVertexStates_S[i];
+                object->contained_sampler_states[object->num_contained_sampler_states].state = state;
                 object->num_contained_sampler_states++;
             }
         }
@@ -572,17 +576,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface,
     return WINED3D_OK;
 }
 
-/* ************************************
-MSDN:
-[in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
-
-Discard
- [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise. 
-
-If this flag is set, the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface.
-
-******************************** */
 static HRESULT  WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,WINED3DRESOURCETYPE Type, DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, WINED3DSURFTYPE Impl, IUnknown *parent) {
     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;    
     IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
@@ -590,29 +583,9 @@ static HRESULT  WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U
     const struct GlPixelFormatDesc *glDesc;
     const StaticPixelFormatDesc *tableEntry = getFormatDescEntry(Format, &GLINFO_LOCATION, &glDesc);
     UINT mul_4w, mul_4h;
-    TRACE("(%p) Create surface\n",This);
-    
-    /** FIXME: Check ranges on the inputs are valid 
-     * MSDN
-     *   MultisampleQuality
-     *    [in] Quality level. The valid range is between zero and one less than the level
-     *    returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType. 
-     *    Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
-     *    values of paired render targets, depth stencil surfaces, and the MultiSample type
-     *    must all match.
-      *******************************/
-
+    HRESULT hr;
 
-    /**
-    * TODO: Discard MSDN
-    * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
-    *
-    * If this flag is set, the contents of the depth stencil buffer will be
-    * invalid after calling either IDirect3DDevice9::Present or  * IDirect3DDevice9::SetDepthStencilSurface
-    * with a different depth surface.
-    *
-    *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
-    ***************************/
+    TRACE("(%p) Create surface\n",This);
 
     if(MultisampleQuality > 0) {
         FIXME("MultisampleQuality set to %d, substituting 0\n", MultisampleQuality);
@@ -648,7 +621,54 @@ static HRESULT  WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U
     if(glDesc->heightscale != 0.0) Size *= glDesc->heightscale;
 
     /** Create and initialise the surface resource **/
-    D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        ERR("Out of memory\n");
+        *ppSurface = NULL;
+        return WINED3DERR_OUTOFVIDEOMEMORY;
+    }
+
+    /* Look at the implementation and set the correct Vtable */
+    switch(Impl)
+    {
+        case SURFACE_OPENGL:
+            /* Check if a 3D adapter is available when creating gl surfaces */
+            if (!This->adapter)
+            {
+                ERR("OpenGL surfaces are not available without opengl\n");
+                HeapFree(GetProcessHeap(), 0, object);
+                return WINED3DERR_NOTAVAILABLE;
+            }
+            object->lpVtbl = &IWineD3DSurface_Vtbl;
+            break;
+
+        case SURFACE_GDI:
+            object->lpVtbl = &IWineGDISurface_Vtbl;
+            break;
+
+        default:
+            /* To be sure to catch this */
+            ERR("Unknown requested surface implementation %d!\n", Impl);
+            HeapFree(GetProcessHeap(), 0, object);
+            return WINED3DERR_INVALIDCALL;
+    }
+
+    hr = resource_init(&object->resource, WINED3DRTYPE_SURFACE, This, Size, Usage, Format, Pool, parent);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize resource, returning %#x\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        *ppSurface = NULL;
+        return hr;
+    }
+
+    TRACE("(%p) : Created resource %p\n", This, object);
+
+    IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object);
+
+    *ppSurface = (IWineD3DSurface *)object;
+
     /* "Standalone" surface */
     IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
 
@@ -711,46 +731,30 @@ static HRESULT  WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U
     }
 
     /* mark the texture as dirty so that it gets loaded first time around*/
-    IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
+    surface_add_dirty_rect(*ppSurface, NULL);
     TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
            This, Width, Height, Format, debug_d3dformat(Format),
            (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
 
-    /* Look at the implementation and set the correct Vtable */
-    switch(Impl) {
-        case SURFACE_OPENGL:
-            /* Check if a 3D adapter is available when creating gl surfaces */
-            if(!This->adapter) {
-                ERR("OpenGL surfaces are not available without opengl\n");
-                HeapFree(GetProcessHeap(), 0, object->resource.allocatedMemory);
-                HeapFree(GetProcessHeap(), 0, object);
-                return WINED3DERR_NOTAVAILABLE;
-            }
-            break;
-
-        case SURFACE_GDI:
-            object->lpVtbl = &IWineGDISurface_Vtbl;
-            break;
-
-        default:
-            /* To be sure to catch this */
-            ERR("Unknown requested surface implementation %d!\n", Impl);
-            IWineD3DSurface_Release((IWineD3DSurface *) object);
-            return WINED3DERR_INVALIDCALL;
-    }
-
     list_init(&object->renderbuffers);
 
     /* Call the private setup routine */
-    return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
+    hr = IWineD3DSurface_PrivateSetup((IWineD3DSurface *)object);
+    if (FAILED(hr))
+    {
+        ERR("Private setup failed, returning %#x\n", hr);
+        IWineD3DSurface_Release(*ppSurface);
+        *ppSurface = NULL;
+        return hr;
+    }
 
+    return hr;
 }
 
-static HRESULT  WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
-                                                 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
-                                                 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
-                                                 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
-
+static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface,
+        UINT Width, UINT Height, UINT Levels, DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
+        IWineD3DTexture **ppTexture, HANDLE *pSharedHandle, IUnknown *parent)
+{
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     IWineD3DTextureImpl *object;
     unsigned int i;
@@ -773,41 +777,89 @@ static HRESULT  WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, U
         return WINED3DERR_INVALIDCALL;
     }
 
-    D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
-    D3DINITIALIZEBASETEXTURE(object->baseTexture);    
-    object->width  = Width;
-    object->height = Height;
-
-    if(glDesc->Flags & WINED3DFMT_FLAG_FILTERING) {
-        object->baseTexture.minMipLookup = minMipLookup;
-        object->baseTexture.magLookup    = magLookup;
-    } else {
-        object->baseTexture.minMipLookup = minMipLookup_noFilter;
-        object->baseTexture.magLookup    = magLookup_noFilter;
-    }
-
-    /** Non-power2 support **/
-    if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
+    /* Non-power2 support */
+    if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO))
+    {
         pow2Width = Width;
         pow2Height = Height;
-    } else {
+    }
+    else
+    {
         /* Find the nearest pow2 match */
         pow2Width = pow2Height = 1;
         while (pow2Width < Width) pow2Width <<= 1;
         while (pow2Height < Height) pow2Height <<= 1;
 
-        if(pow2Width != Width || pow2Height != Height) {
-            if(Levels > 1) {
+        if (pow2Width != Width || pow2Height != Height)
+        {
+            if (Levels > 1)
+            {
                 WARN("Attempted to create a mipmapped np2 texture without unconditional np2 support\n");
-                HeapFree(GetProcessHeap(), 0, object);
-                *ppTexture = NULL;
                 return WINED3DERR_INVALIDCALL;
-            } else {
-                Levels = 1;
             }
+            Levels = 1;
         }
     }
 
+    /* Calculate levels for mip mapping */
+    if (Usage & WINED3DUSAGE_AUTOGENMIPMAP)
+    {
+        if (!GL_SUPPORT(SGIS_GENERATE_MIPMAP))
+        {
+            WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        if (Levels > 1)
+        {
+            WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        Levels = 1;
+    }
+    else if (!Levels)
+    {
+        Levels = wined3d_log2i(max(Width, Height)) + 1;
+        TRACE("Calculated levels = %d\n", Levels);
+    }
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        ERR("Out of memory\n");
+        *ppTexture = NULL;
+        return WINED3DERR_OUTOFVIDEOMEMORY;
+    }
+
+    object->lpVtbl = &IWineD3DTexture_Vtbl;
+    hr = resource_init(&object->resource, WINED3DRTYPE_TEXTURE, This, 0, Usage, Format, Pool, parent);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize resource, returning %#x\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        *ppTexture = NULL;
+        return hr;
+    }
+
+    TRACE("(%p) : Created resource %p\n", This, object);
+
+    IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object);
+
+    *ppTexture = (IWineD3DTexture *)object;
+
+    basetexture_init(&object->baseTexture, Levels, Usage);
+    object->width  = Width;
+    object->height = Height;
+
+    if(glDesc->Flags & WINED3DFMT_FLAG_FILTERING) {
+        object->baseTexture.minMipLookup = minMipLookup;
+        object->baseTexture.magLookup    = magLookup;
+    } else {
+        object->baseTexture.minMipLookup = minMipLookup_noFilter;
+        object->baseTexture.magLookup    = magLookup_noFilter;
+    }
+
     /** FIXME: add support for real non-power-two if it's provided by the video card **/
     /* Precalculated scaling for 'faked' non power of two texture coords.
        Second also don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8 and EXT_PALETTED_TEXTURE
@@ -843,37 +895,14 @@ static HRESULT  WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, U
     }
     TRACE(" xf(%f) yf(%f)\n", object->baseTexture.pow2Matrix[0], object->baseTexture.pow2Matrix[5]);
 
-    /* Calculate levels for mip mapping */
-    if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
-        if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
-            WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
-            return WINED3DERR_INVALIDCALL;
-        }
-        if(Levels > 1) {
-            WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
-            return WINED3DERR_INVALIDCALL;
-        }
-        object->baseTexture.levels = 1;
-    } else if (Levels == 0) {
-        TRACE("calculating levels %d\n", object->baseTexture.levels);
-        object->baseTexture.levels++;
-        tmpW = Width;
-        tmpH = Height;
-        while (tmpW > 1 || tmpH > 1) {
-            tmpW = max(1, tmpW >> 1);
-            tmpH = max(1, tmpH >> 1);
-            object->baseTexture.levels++;
-        }
-        TRACE("Calculated levels = %d\n", object->baseTexture.levels);
-    }
-
     /* Generate all the surfaces */
     tmpW = Width;
     tmpH = Height;
     for (i = 0; i < object->baseTexture.levels; i++)
     {
         /* use the callback to create the texture surface */
-        hr = D3DCB_CreateSurface(This->parent, parent, tmpW, tmpH, Format, Usage, Pool, i, WINED3DCUBEMAP_FACE_POSITIVE_X, &object->surfaces[i],NULL);
+        hr = IWineD3DDeviceParent_CreateSurface(This->device_parent, parent, tmpW, tmpH, Format,
+                Usage, Pool, i, WINED3DCUBEMAP_FACE_POSITIVE_X, &object->surfaces[i]);
         if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
             FIXME("Failed to create surface  %p\n", object);
             /* clean up */
@@ -898,13 +927,9 @@ static HRESULT  WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, U
 }
 
 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
-                                                      UINT Width, UINT Height, UINT Depth,
-                                                      UINT Levels, DWORD Usage,
-                                                      WINED3DFORMAT Format, WINED3DPOOL Pool,
-                                                      IWineD3DVolumeTexture **ppVolumeTexture,
-                                                      HANDLE *pSharedHandle, IUnknown *parent,
-                                                      D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
-
+        UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
+        IWineD3DVolumeTexture **ppVolumeTexture, HANDLE *pSharedHandle, IUnknown *parent)
+{
     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
     IWineD3DVolumeTextureImpl *object;
     unsigned int               i;
@@ -912,6 +937,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa
     UINT                       tmpH;
     UINT                       tmpD;
     const struct GlPixelFormatDesc *glDesc;
+    HRESULT hr;
 
     getFormatDescEntry(Format, &GLINFO_LOCATION, &glDesc);
 
@@ -926,8 +952,52 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa
         return WINED3DERR_INVALIDCALL;
     }
 
-    D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
-    D3DINITIALIZEBASETEXTURE(object->baseTexture);
+    /* Calculate levels for mip mapping */
+    if (Usage & WINED3DUSAGE_AUTOGENMIPMAP)
+    {
+        if (!GL_SUPPORT(SGIS_GENERATE_MIPMAP))
+        {
+            WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        if (Levels > 1)
+        {
+            WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        Levels = 1;
+    }
+    else if (!Levels)
+    {
+        Levels = wined3d_log2i(max(max(Width, Height), Depth)) + 1;
+        TRACE("Calculated levels = %d\n", Levels);
+    }
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        ERR("Out of memory\n");
+        *ppVolumeTexture = NULL;
+        return WINED3DERR_OUTOFVIDEOMEMORY;
+    }
+
+    object->lpVtbl = &IWineD3DVolumeTexture_Vtbl;
+    hr = resource_init(&object->resource, WINED3DRTYPE_VOLUMETEXTURE, This, 0, Usage, Format, Pool, parent);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize resource, returning %#x\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        *ppVolumeTexture = NULL;
+        return hr;
+    }
+
+    TRACE("(%p) : Created resource %p\n", This, object);
+
+    IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object);
+
+    basetexture_init(&object->baseTexture, Levels, Usage);
 
     TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
           Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
@@ -946,31 +1016,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa
         object->baseTexture.magLookup    = magLookup_noFilter;
     }
 
-    /* Calculate levels for mip mapping */
-    if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
-        if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
-            WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
-            return WINED3DERR_INVALIDCALL;
-        }
-        if(Levels > 1) {
-            WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
-            return WINED3DERR_INVALIDCALL;
-        }
-        object->baseTexture.levels = 1;
-    } else if (Levels == 0) {
-        object->baseTexture.levels++;
-        tmpW = Width;
-        tmpH = Height;
-        tmpD = Depth;
-        while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
-            tmpW = max(1, tmpW >> 1);
-            tmpH = max(1, tmpH >> 1);
-            tmpD = max(1, tmpD >> 1);
-            object->baseTexture.levels++;
-        }
-        TRACE("Calculated levels = %d\n", object->baseTexture.levels);
-    }
-
     /* Generate all the surfaces */
     tmpW = Width;
     tmpH = Height;
@@ -980,9 +1025,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa
     {
         HRESULT hr;
         /* Create the volume */
-        hr = D3DCB_CreateVolume(This->parent, parent, tmpW, tmpH, tmpD, Format, Pool, Usage,
-                                &object->volumes[i], pSharedHandle);
-
+        hr = IWineD3DDeviceParent_CreateVolume(This->device_parent, parent,
+                tmpW, tmpH, tmpD, Format, Pool, Usage, &object->volumes[i]);
         if(FAILED(hr)) {
             ERR("Creating a volume for the volume texture failed(%08x)\n", hr);
             IWineD3DVolumeTexture_Release((IWineD3DVolumeTexture *) object);
@@ -1015,13 +1059,37 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
     IWineD3DVolumeImpl        *object; /** NOTE: impl ref allowed since this is a create function **/
     const StaticPixelFormatDesc *formatDesc  = getFormatDescEntry(Format, NULL, NULL);
+    HRESULT hr;
 
     if(!GL_SUPPORT(EXT_TEXTURE3D)) {
         WARN("(%p) : Volume cannot be created - no volume texture support\n", This);
         return WINED3DERR_INVALIDCALL;
     }
 
-    D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        ERR("Out of memory\n");
+        *ppVolume = NULL;
+        return WINED3DERR_OUTOFVIDEOMEMORY;
+    }
+
+    object->lpVtbl = &IWineD3DVolume_Vtbl;
+    hr = resource_init(&object->resource, WINED3DRTYPE_VOLUME, This,
+            Width * Height * Depth * formatDesc->bpp, Usage, Format, Pool, parent);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize resource, returning %#x\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        *ppVolume = NULL;
+        return hr;
+    }
+
+    TRACE("(%p) : Created resource %p\n", This, object);
+
+    IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object);
+
+    *ppVolume = (IWineD3DVolume *)object;
 
     TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
           Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
@@ -1037,16 +1105,15 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
     memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
     object->dirty               = TRUE;
 
-    return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
-}
+    volume_add_dirty_box((IWineD3DVolume *)object, NULL);
 
-static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
-                                                    UINT Levels, DWORD Usage,
-                                                    WINED3DFORMAT Format, WINED3DPOOL Pool,
-                                                    IWineD3DCubeTexture **ppCubeTexture,
-                                                    HANDLE *pSharedHandle, IUnknown *parent,
-                                                    D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
+    return WINED3D_OK;
+}
 
+static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface,
+        UINT EdgeLength, UINT Levels, DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
+        IWineD3DCubeTexture **ppCubeTexture, HANDLE *pSharedHandle, IUnknown *parent)
+{
     IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
     IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
     unsigned int             i, j;
@@ -1068,8 +1135,52 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface
         return WINED3DERR_INVALIDCALL;
     }
 
-    D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
-    D3DINITIALIZEBASETEXTURE(object->baseTexture);
+    /* Calculate levels for mip mapping */
+    if (Usage & WINED3DUSAGE_AUTOGENMIPMAP)
+    {
+        if (!GL_SUPPORT(SGIS_GENERATE_MIPMAP))
+        {
+            WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        if (Levels > 1)
+        {
+            WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        Levels = 1;
+    }
+    else if (!Levels)
+    {
+        Levels = wined3d_log2i(EdgeLength) + 1;
+        TRACE("Calculated levels = %d\n", Levels);
+    }
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        ERR("Out of memory\n");
+        *ppCubeTexture = NULL;
+        return WINED3DERR_OUTOFVIDEOMEMORY;
+    }
+
+    object->lpVtbl = &IWineD3DCubeTexture_Vtbl;
+    hr = resource_init(&object->resource, WINED3DRTYPE_CUBETEXTURE, This, 0, Usage, Format, Pool, parent);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize resource, returning %#x\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        *ppCubeTexture = NULL;
+        return hr;
+    }
+
+    TRACE("(%p) : Created resource %p\n", This, object);
+
+    IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object);
+
+    basetexture_init(&object->baseTexture, Levels, Usage);
 
     TRACE("(%p) Create Cube Texture\n", This);
 
@@ -1099,33 +1210,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface
         object->baseTexture.magLookup    = magLookup_noFilter;
     }
 
-    /* Calculate levels for mip mapping */
-    if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
-        if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
-            WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
-            HeapFree(GetProcessHeap(), 0, object);
-            *ppCubeTexture = NULL;
-
-            return WINED3DERR_INVALIDCALL;
-        }
-        if(Levels > 1) {
-            WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
-            HeapFree(GetProcessHeap(), 0, object);
-            *ppCubeTexture = NULL;
-
-            return WINED3DERR_INVALIDCALL;
-        }
-        object->baseTexture.levels = 1;
-    } else if (Levels == 0) {
-        object->baseTexture.levels++;
-        tmpW = EdgeLength;
-        while (tmpW > 1) {
-            tmpW = max(1, tmpW >> 1);
-            object->baseTexture.levels++;
-        }
-        TRACE("Calculated levels = %d\n", object->baseTexture.levels);
-    }
-
     /* Generate all the surfaces */
     tmpW = EdgeLength;
     for (i = 0; i < object->baseTexture.levels; i++) {
@@ -1141,24 +1225,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface
                 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
             };
 
-            hr=D3DCB_CreateSurface(This->parent, parent, tmpW, tmpW, Format, Usage, Pool,
-                                   i /* Level */, j, &object->surfaces[j][i],pSharedHandle);
-
-            if(hr!= WINED3D_OK) {
-                /* clean up */
-                unsigned int k;
-                unsigned int l;
-                for (l = 0; l < j; l++) {
-                    IWineD3DSurface_Release(object->surfaces[l][i]);
-                }
-                for (k = 0; k < i; k++) {
-                    for (l = 0; l < 6; l++) {
-                        IWineD3DSurface_Release(object->surfaces[l][k]);
-                    }
-                }
-
+            hr = IWineD3DDeviceParent_CreateSurface(This->device_parent, parent, tmpW, tmpW,
+                    Format, Usage, Pool, i /* Level */, j, &object->surfaces[j][i]);
+            if (FAILED(hr))
+            {
                 FIXME("(%p) Failed to create surface\n",object);
-                HeapFree(GetProcessHeap(),0,object);
+                IWineD3DCubeTexture_Release((IWineD3DCubeTexture *)object);
                 *ppCubeTexture = NULL;
                 return hr;
             }
@@ -1225,10 +1297,23 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINE
         return hr;
     }
 
-    D3DCREATEOBJECTINSTANCE(object, Query)
-    object->lpVtbl       = vtable;
-    object->type         = Type;
-    object->state        = QUERY_CREATED;
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if(!object)
+    {
+        ERR("Out of memory\n");
+        *ppQuery = NULL;
+        return WINED3DERR_OUTOFVIDEOMEMORY;
+    }
+
+    object->lpVtbl = vtable;
+    object->type = Type;
+    object->state = QUERY_CREATED;
+    object->wineD3DDevice = This;
+    object->parent = parent;
+    object->ref = 1;
+
+    *ppQuery = (IWineD3DQuery *)object;
+
     /* allocated the 'extended' data based on the type of query requested */
     switch(Type){
     case WINED3DQUERYTYPE_OCCLUSION:
@@ -1392,10 +1477,9 @@ static void IWineD3DDeviceImpl_RestoreWindow(IWineD3DDevice *iface, HWND window)
 }
 
 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
-static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice* iface,
-        WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
-        IUnknown* parent, D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
-        D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil, WINED3DSURFTYPE surface_type)
+static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice *iface,
+        WINED3DPRESENT_PARAMETERS *pPresentationParameters, IWineD3DSwapChain **ppSwapChain,
+        IUnknown *parent, WINED3DSURFTYPE surface_type)
 {
     IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
 
@@ -1422,7 +1506,14 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice* iface,
         FIXME("The app requests more than one back buffer, this can't be supported properly. Please configure the application to use double buffering(=1 back buffer) if possible\n");
     }
 
-    D3DCREATEOBJECTINSTANCE(object, SwapChain)
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if(!object)
+    {
+        ERR("Out of memory\n");
+        *ppSwapChain = NULL;
+        return WINED3DERR_OUTOFVIDEOMEMORY;
+    }
+
     switch(surface_type) {
         case SURFACE_GDI:
             object->lpVtbl = &IWineGDISwapChain_Vtbl;
@@ -1432,8 +1523,14 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice* iface,
             break;
         case SURFACE_UNKNOWN:
             FIXME("Caller tried to create a SURFACE_UNKNOWN swapchain\n");
+            HeapFree(GetProcessHeap(), 0, object);
             return WINED3DERR_INVALIDCALL;
     }
+    object->wineD3DDevice = This;
+    object->parent = parent;
+    object->ref = 1;
+
+    *ppSwapChain = (IWineD3DSwapChain *)object;
 
     /*********************
     * Lookup the window Handle and the relating X window handle
@@ -1465,11 +1562,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice* iface,
     object->orig_fmt = Mode.Format;
     formatDesc  = getFormatDescEntry(Mode.Format, NULL, NULL);
 
-    /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
-     *  then the corresponding dimension of the client area of the hDeviceWindow
-     *  (or the focus window, if hDeviceWindow is NULL) is taken.
-      **********************/
-
     if (pPresentationParameters->Windowed &&
         ((pPresentationParameters->BackBufferWidth == 0) ||
          (pPresentationParameters->BackBufferHeight == 0) ||
@@ -1497,16 +1589,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice* iface,
     object->presentParms = *pPresentationParameters;
 
     TRACE("calling rendertarget CB\n");
-    hr = D3DCB_CreateRenderTarget(This->parent,
-                             parent,
-                             object->presentParms.BackBufferWidth,
-                             object->presentParms.BackBufferHeight,
-                             object->presentParms.BackBufferFormat,
-                             object->presentParms.MultiSampleType,
-                             object->presentParms.MultiSampleQuality,
-                             TRUE /* Lockable */,
-                             &object->frontBuffer,
-                             NULL /* pShared (always null)*/);
+    hr = IWineD3DDeviceParent_CreateRenderTarget(This->device_parent, parent,
+            object->presentParms.BackBufferWidth, object->presentParms.BackBufferHeight,
+            object->presentParms.BackBufferFormat, object->presentParms.MultiSampleType,
+            object->presentParms.MultiSampleQuality, TRUE /* Lockable */, &object->frontBuffer);
     if (SUCCEEDED(hr)) {
         IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
         if(surface_type == SURFACE_OPENGL) {
@@ -1585,16 +1671,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice* iface,
 
         for(i = 0; i < object->presentParms.BackBufferCount; i++) {
             TRACE("calling rendertarget CB\n");
-            hr = D3DCB_CreateRenderTarget(This->parent,
-                                    parent,
-                                    object->presentParms.BackBufferWidth,
-                                    object->presentParms.BackBufferHeight,
-                                    object->presentParms.BackBufferFormat,
-                                    object->presentParms.MultiSampleType,
-                                    object->presentParms.MultiSampleQuality,
-                                    TRUE /* Lockable */,
-                                    &object->backBuffer[i],
-                                    NULL /* pShared (always null)*/);
+            hr = IWineD3DDeviceParent_CreateRenderTarget(This->device_parent, parent,
+                    object->presentParms.BackBufferWidth, object->presentParms.BackBufferHeight,
+                    object->presentParms.BackBufferFormat, object->presentParms.MultiSampleType,
+                    object->presentParms.MultiSampleQuality, TRUE /* Lockable */, &object->backBuffer[i]);
             if(SUCCEEDED(hr)) {
                 IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
             } else {
@@ -1624,16 +1704,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice* iface,
     if (pPresentationParameters->EnableAutoDepthStencil && surface_type == SURFACE_OPENGL) {
         TRACE("Creating depth stencil buffer\n");
         if (This->auto_depth_stencil_buffer == NULL ) {
-            hr = D3DCB_CreateDepthStencil(This->parent,
-                                    parent,
-                                    object->presentParms.BackBufferWidth,
-                                    object->presentParms.BackBufferHeight,
-                                    object->presentParms.AutoDepthStencilFormat,
-                                    object->presentParms.MultiSampleType,
-                                    object->presentParms.MultiSampleQuality,
-                                    FALSE /* FIXME: Discard */,
-                                    &This->auto_depth_stencil_buffer,
-                                    NULL /* pShared (always null)*/  );
+            hr = IWineD3DDeviceParent_CreateDepthStencilSurface(This->device_parent, parent,
+                    object->presentParms.BackBufferWidth, object->presentParms.BackBufferHeight,
+                    object->presentParms.AutoDepthStencilFormat, object->presentParms.MultiSampleType,
+                    object->presentParms.MultiSampleQuality, FALSE /* FIXME: Discard */,
+                    &This->auto_depth_stencil_buffer);
             if (SUCCEEDED(hr)) {
                 IWineD3DSurface_SetContainer(This->auto_depth_stencil_buffer, 0);
             } else {
@@ -1730,7 +1805,20 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice*
     TRACE("(%p) : directXVersion %u, elements %p, element_count %d, ppDecl=%p\n",
             This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, elements, element_count, ppVertexDeclaration);
 
-    D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if(!object)
+    {
+        ERR("Out of memory\n");
+        *ppVertexDeclaration = NULL;
+        return WINED3DERR_OUTOFVIDEOMEMORY;
+    }
+
+    object->lpVtbl = &IWineD3DVertexDeclaration_Vtbl;
+    object->wineD3DDevice = This;
+    object->parent = parent;
+    object->ref = 1;
+
+    *ppVertexDeclaration = (IWineD3DVertexDeclaration *)object;
 
     hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, elements, element_count);
     if(FAILED(hr)) {
@@ -1783,6 +1871,10 @@ static unsigned int ConvertFvfToDeclaration(IWineD3DDeviceImpl *This, /* For the
             elements[idx].Type = WINED3DDECLTYPE_FLOAT4;
             elements[idx].Usage = WINED3DDECLUSAGE_POSITIONT;
         }
+        else if ((fvf & WINED3DFVF_XYZW) == WINED3DFVF_XYZW) {
+            elements[idx].Type = WINED3DDECLTYPE_FLOAT4;
+            elements[idx].Usage = WINED3DDECLUSAGE_POSITION;
+        }
         else {
             elements[idx].Type = WINED3DDECLTYPE_FLOAT3;
             elements[idx].Usage = WINED3DDECLUSAGE_POSITION;
@@ -1896,25 +1988,39 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *ifac
     IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
     IWineD3DVertexShaderImpl *object;  /* NOTE: impl usage is ok, this is a create */
     HRESULT hr = WINED3D_OK;
-    D3DCREATESHADEROBJECTINSTANCE(object, VertexShader)
-    object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
 
-    TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
+    if (!pFunction) return WINED3DERR_INVALIDCALL;
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        ERR("Out of memory\n");
+        *ppVertexShader = NULL;
+        return WINED3DERR_OUTOFVIDEOMEMORY;
+    }
+
+    object->lpVtbl = &IWineD3DVertexShader_Vtbl;
+    object->parent = parent;
+    shader_init(&object->baseShader, iface, IWineD3DVertexShaderImpl_shader_ins);
+    list_add_head(&This->shaders, &object->baseShader.shader_list_entry);
+    *ppVertexShader = (IWineD3DVertexShader *)object;
+
+    TRACE("(%p) : Created vertex shader %p\n", This, *ppVertexShader);
 
     if (vertex_declaration) {
         IWineD3DVertexShader_FakeSemantics(*ppVertexShader, vertex_declaration);
     }
 
     hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
-
-    if (WINED3D_OK != hr) {
-        FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
+    if (FAILED(hr))
+    {
+        WARN("(%p) : Failed to set function, returning %#x\n", iface, hr);
         IWineD3DVertexShader_Release(*ppVertexShader);
-        return WINED3DERR_INVALIDCALL;
+        *ppVertexShader = NULL;
+        return hr;
     }
-    list_add_head(&This->shaders, &object->baseShader.shader_list_entry);
 
-    return WINED3D_OK;
+    return hr;
 }
 
 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
@@ -1922,14 +2028,31 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface
     IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
     HRESULT hr = WINED3D_OK;
 
-    D3DCREATESHADEROBJECTINSTANCE(object, PixelShader)
-    object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
+    if (!pFunction) return WINED3DERR_INVALIDCALL;
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        ERR("Out of memory\n");
+        *ppPixelShader = NULL;
+        return WINED3DERR_OUTOFVIDEOMEMORY;
+    }
+
+    object->lpVtbl = &IWineD3DPixelShader_Vtbl;
+    object->parent = parent;
+    shader_init(&object->baseShader, iface, IWineD3DPixelShaderImpl_shader_ins);
+    list_add_head(&This->shaders, &object->baseShader.shader_list_entry);
+    *ppPixelShader = (IWineD3DPixelShader *)object;
+
+    TRACE("(%p) : Created pixel shader %p\n", This, *ppPixelShader);
+
     hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
-    if (WINED3D_OK == hr) {
-        TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
-        list_add_head(&This->shaders, &object->baseShader.shader_list_entry);
-    } else {
-        WARN("(%p) : Failed to create pixel shader\n", This);
+    if (FAILED(hr))
+    {
+        WARN("(%p) : Failed to set function, returning %#x\n", iface, hr);
+        IWineD3DPixelShader_Release(*ppPixelShader);
+        *ppPixelShader = NULL;
+        return hr;
     }
 
     return hr;
@@ -1956,7 +2079,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DW
     object->parent = Parent;
     object->wineD3DDevice = This;
     object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
-       
     object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
 
     if(!object->hpal) {
@@ -2050,12 +2172,8 @@ static void create_dummy_textures(IWineD3DDeviceImpl *This) {
         GLubyte white = 255;
 
         /* Make appropriate texture active */
-        if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-            GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
-            checkGLcall("glActiveTextureARB");
-        } else if (i > 0) {
-            FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
-        }
+        GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
+        checkGLcall("glActiveTextureARB");
 
         /* Generate an opengl texture name */
         glGenTextures(1, &This->dummyTextureName[i]);
@@ -2064,7 +2182,6 @@ static void create_dummy_textures(IWineD3DDeviceImpl *This) {
 
         /* Generate a dummy 2d texture (not using 1d because they cause many
         * DRI drivers fall back to sw) */
-        This->stateBlock->textureDimensions[i] = GL_TEXTURE_2D;
         glBindTexture(GL_TEXTURE_2D, This->dummyTextureName[i]);
         checkGLcall("glBindTexture");
 
@@ -2080,14 +2197,17 @@ static void create_dummy_textures(IWineD3DDeviceImpl *This) {
     LEAVE_GL();
 }
 
-static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATESWAPCHAIN D3DCB_CreateSwapChain) {
+static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface,
+        WINED3DPRESENT_PARAMETERS *pPresentationParameters)
+{
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
     IWineD3DSwapChainImpl *swapchain = NULL;
     HRESULT hr;
     DWORD state;
     unsigned int i;
 
-    TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateSwapChain);
+    TRACE("(%p)->(%p)\n", This, pPresentationParameters);
+
     if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
     if(!This->adapter->opengl) return WINED3DERR_INVALIDCALL;
 
@@ -2107,11 +2227,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR
     This->updateStateBlock = This->stateBlock;
     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
 
-    hr = allocate_shader_constants(This->updateStateBlock);
-    if (WINED3D_OK != hr) {
-        goto err_out;
-    }
-
     This->render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers));
     This->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLenum) * GL_LIMITS(buffers));
 
@@ -2147,8 +2262,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR
 
     /* Setup the implicit swapchain */
     TRACE("Creating implicit swapchain\n");
-    hr=D3DCB_CreateSwapChain(This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain);
-    if (FAILED(hr) || !swapchain) {
+    hr = IWineD3DDeviceParent_CreateSwapChain(This->device_parent,
+            pPresentationParameters, (IWineD3DSwapChain **)&swapchain);
+    if (FAILED(hr))
+    {
         WARN("Failed to create implicit swapchain\n");
         goto err_out;
     }
@@ -2205,17 +2322,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR
 
     ENTER_GL();
 
-    { /* Set a default viewport */
-        WINED3DVIEWPORT vp;
-        vp.X      = 0;
-        vp.Y      = 0;
-        vp.Width  = pPresentationParameters->BackBufferWidth;
-        vp.Height = pPresentationParameters->BackBufferHeight;
-        vp.MinZ   = 0.0f;
-        vp.MaxZ   = 1.0f;
-        IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
-    }
-
     /* Initialize the current view state */
     This->view_ident = 1;
     This->contexts[0]->last_was_rhw = 0;
@@ -2286,15 +2392,19 @@ err_out:
     return hr;
 }
 
-static HRESULT WINAPI IWineD3DDeviceImpl_InitGDI(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATESWAPCHAIN D3DCB_CreateSwapChain) {
+static HRESULT WINAPI IWineD3DDeviceImpl_InitGDI(IWineD3DDevice *iface,
+        WINED3DPRESENT_PARAMETERS *pPresentationParameters)
+{
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
     IWineD3DSwapChainImpl *swapchain = NULL;
     HRESULT hr;
 
     /* Setup the implicit swapchain */
     TRACE("Creating implicit swapchain\n");
-    hr=D3DCB_CreateSwapChain(This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain);
-    if (FAILED(hr) || !swapchain) {
+    hr = IWineD3DDeviceParent_CreateSwapChain(This->device_parent,
+            pPresentationParameters, (IWineD3DSwapChain **)&swapchain);
+    if (FAILED(hr))
+    {
         WARN("Failed to create implicit swapchain\n");
         goto err_out;
     }
@@ -2560,36 +2670,6 @@ static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *ifa
     return (This->adapter->TextureRam - This->adapter->UsedTextureRam);
 }
 
-
-
-/*****
- * Get / Set FVF
- *****/
-static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
-    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-
-    /* Update the current state block */
-    This->updateStateBlock->changed.fvf      = TRUE;
-
-    if(This->updateStateBlock->fvf == fvf) {
-        TRACE("Application is setting the old fvf over, nothing to do\n");
-        return WINED3D_OK;
-    }
-
-    This->updateStateBlock->fvf              = fvf;
-    TRACE("(%p) : FVF Shader FVF set to %x\n", This, fvf);
-    IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
-    return WINED3D_OK;
-}
-
-
-static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
-    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-    TRACE("(%p) : GetFVF returning %x\n", This, This->stateBlock->fvf);
-    *pfvf = This->stateBlock->fvf;
-    return WINED3D_OK;
-}
-
 /*****
  * Get / Set Stream Source
  *****/
@@ -2608,7 +2688,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface,
     oldSrc = This->updateStateBlock->streamSource[StreamNumber];
     TRACE("(%p) : StreamNo: %u, OldStream (%p), NewStream (%p), OffsetInBytes %u, NewStride %u\n", This, StreamNumber, oldSrc, pStreamData, OffsetInBytes, Stride);
 
-    This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
+    This->updateStateBlock->changed.streamSource |= 1 << StreamNumber;
 
     if(oldSrc == pStreamData &&
        This->updateStateBlock->streamStride[StreamNumber] == Stride &&
@@ -2631,10 +2711,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface,
         return WINED3D_OK;
     }
 
-    /* Need to do a getParent and pass the references up */
-    /* MSDN says ..... When an application no longer holds a reference to this interface, the interface will automatically be freed.
-    which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
-    so for now, just count internally   */
     if (pStreamData != NULL) {
         IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
         InterlockedIncrement(&vbImpl->bindCount);
@@ -2696,7 +2772,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *ifa
     TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
     This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA  | WINED3DSTREAMSOURCE_INDEXEDDATA );
 
-    This->updateStateBlock->changed.streamFreq[StreamNumber]  = TRUE;
+    This->updateStateBlock->changed.streamFreq |= 1 << StreamNumber;
     This->updateStateBlock->streamFreq[StreamNumber]          = Divider & 0x7FFFFF;
 
     if(This->updateStateBlock->streamFreq[StreamNumber] != oldFreq ||
@@ -2730,7 +2806,7 @@ static HRESULT  WINAPI  IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, W
     /* Handle recording of state blocks */
     if (This->isRecordingState) {
         TRACE("Recording... not performing anything\n");
-        This->updateStateBlock->changed.transform[d3dts] = TRUE;
+        This->updateStateBlock->changed.transform[d3dts >> 5] |= 1 << (d3dts & 0x1f);
         This->updateStateBlock->transforms[d3dts] = *lpmatrix;
         return WINED3D_OK;
     }
@@ -2787,7 +2863,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
 
-    if (State < HIGHEST_TRANSFORMSTATE)
+    if (State <= HIGHEST_TRANSFORMSTATE)
     {
         mat = &This->updateStateBlock->transforms[State];
     } else {
@@ -2933,9 +3009,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD I
             if (rho < 0.0001) rho = 0.0001f;
             object->exponent = -0.3/log(cos(rho/2));
         }
-       if (object->exponent > 128.0) {
-               object->exponent = 128.0;
-       }
+        if (object->exponent > 128.0) {
+            object->exponent = 128.0;
+        }
         object->cutoff = pLight->Phi*90/M_PI;
 
         /* FIXME: Range */
@@ -3049,7 +3125,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, D
                  *
                  * TODO: Test how this affects rendering
                  */
-                FIXME("Too many concurrently active lights\n");
+                WARN("Too many concurrently active lights\n");
                 return WINED3D_OK;
             }
 
@@ -3099,7 +3175,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWO
         return WINED3DERR_INVALIDCALL;
     }
 
-    This->updateStateBlock->changed.clipplane[Index] = TRUE;
+    This->updateStateBlock->changed.clipplane |= 1 << Index;
 
     if(This->updateStateBlock->clipplane[Index][0] == pPlane[0] &&
        This->updateStateBlock->clipplane[Index][1] == pPlane[1] &&
@@ -3323,7 +3399,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, W
 
     TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
 
-    This->updateStateBlock->changed.renderState[State] = TRUE;
+    This->updateStateBlock->changed.renderState[State >> 5] |= 1 << (State & 0x1f);
     This->updateStateBlock->renderState[State] = Value;
 
     /* Handle recording of state blocks */
@@ -3386,7 +3462,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface,
 
     oldValue = This->stateBlock->samplerState[Sampler][Type];
     This->updateStateBlock->samplerState[Sampler][Type]         = Value;
-    This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
+    This->updateStateBlock->changed.samplerState[Sampler] |= 1 << Type;
 
     /* Handle recording of state blocks */
     if (This->isRecordingState) {
@@ -3548,7 +3624,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
         This->updateStateBlock->changed.vertexShaderConstantsB |= (1 << i);
     }
 
-    IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
+    if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
 
     return WINED3D_OK;
 }
@@ -3596,7 +3672,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
         This->updateStateBlock->changed.vertexShaderConstantsI |= (1 << i);
     }
 
-    IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
+    if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
 
     return WINED3D_OK;
 }
@@ -3607,64 +3683,24 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
     int *dstData,
     UINT count) {
 
-    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-    int cnt = min(count, MAX_CONST_I - start);
-
-    TRACE("(iface %p, dstData %p, start %d, count %d)\n",
-            iface, dstData, start, count);
-
-    if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
-        return WINED3DERR_INVALIDCALL;
-
-    memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
-    return WINED3D_OK;
-}
-
-static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
-    IWineD3DDevice *iface,
-    UINT start,
-    CONST float *srcData,
-    UINT count) {
-
-    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-    UINT i;
-
-    TRACE("(iface %p, srcData %p, start %d, count %d)\n",
-            iface, srcData, start, count);
-
-    /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
-    if (srcData == NULL || start + count > GL_LIMITS(vshader_constantsF) || start > GL_LIMITS(vshader_constantsF))
-        return WINED3DERR_INVALIDCALL;
-
-    memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
-    if(TRACE_ON(d3d)) {
-        for (i = 0; i < count; i++)
-            TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
-                srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
-    }
+    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+    int cnt = min(count, MAX_CONST_I - start);
 
-    for (i = start; i < count + start; ++i) {
-        if (!This->updateStateBlock->changed.vertexShaderConstantsF[i]) {
-            constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_vconstantsF), constants_entry, entry);
-            if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx)) {
-                ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry));
-                list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
-            }
-            ptr->idx[ptr->count++] = i;
-            This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
-        }
-    }
+    TRACE("(iface %p, dstData %p, start %d, count %d)\n",
+            iface, dstData, start, count);
 
-    IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
+    if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
+        return WINED3DERR_INVALIDCALL;
 
+    memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
     return WINED3D_OK;
 }
 
-static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF_DirtyConst(
-IWineD3DDevice *iface,
-UINT start,
-CONST float *srcData,
-UINT count) {
+static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
+    IWineD3DDevice *iface,
+    UINT start,
+    CONST float *srcData,
+    UINT count) {
 
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     UINT i;
@@ -3680,17 +3716,17 @@ UINT count) {
     if(TRACE_ON(d3d)) {
         for (i = 0; i < count; i++)
             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
-                    srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
+                srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
     }
 
-    /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
-     * context. On a context switch the old context will be fully dirtified
-     */
-    memset(This->activeContext->vshader_const_dirty + start, 1,
-           sizeof(*This->activeContext->vshader_const_dirty) * count);
-    This->highest_dirty_vs_const = max(This->highest_dirty_vs_const, start+count+1);
+    if (!This->isRecordingState)
+    {
+        This->shader_backend->shader_update_float_vertex_constants(iface, start, count);
+        IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
+    }
 
-    IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
+    memset(This->updateStateBlock->changed.vertexShaderConstantsF + start, 1,
+            sizeof(*This->updateStateBlock->changed.vertexShaderConstantsF) * count);
 
     return WINED3D_OK;
 }
@@ -3716,7 +3752,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
 
 static inline void markTextureStagesDirty(IWineD3DDeviceImpl *This, DWORD stage) {
     DWORD i;
-    for(i = 0; i < WINED3D_HIGHEST_TEXTURE_STATE; i++) {
+    for(i = 0; i <= WINED3D_HIGHEST_TEXTURE_STATE; ++i)
+    {
         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, i));
     }
 }
@@ -3739,6 +3776,7 @@ static void device_map_stage(IWineD3DDeviceImpl *This, int stage, int unit) {
 static void device_update_fixed_function_usage_map(IWineD3DDeviceImpl *This) {
     int i;
 
+    This->fixed_function_usage_map = 0;
     for (i = 0; i < MAX_TEXTURES; ++i) {
         WINED3DTEXTUREOP color_op = This->stateBlock->textureState[i][WINED3DTSS_COLOROP];
         WINED3DTEXTUREOP alpha_op = This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP];
@@ -3751,10 +3789,6 @@ static void device_update_fixed_function_usage_map(IWineD3DDeviceImpl *This) {
 
         if (color_op == WINED3DTOP_DISABLE) {
             /* Not used, and disable higher stages */
-            while (i < MAX_TEXTURES) {
-                This->fixed_function_usage_map[i] = FALSE;
-                ++i;
-            }
             break;
         }
 
@@ -3764,26 +3798,27 @@ static void device_update_fixed_function_usage_map(IWineD3DDeviceImpl *This) {
                 || ((alpha_arg1 == WINED3DTA_TEXTURE) && alpha_op != WINED3DTOP_SELECTARG2)
                 || ((alpha_arg2 == WINED3DTA_TEXTURE) && alpha_op != WINED3DTOP_SELECTARG1)
                 || ((alpha_arg3 == WINED3DTA_TEXTURE) && (alpha_op == WINED3DTOP_MULTIPLYADD || alpha_op == WINED3DTOP_LERP))) {
-            This->fixed_function_usage_map[i] = TRUE;
-        } else {
-            This->fixed_function_usage_map[i] = FALSE;
+            This->fixed_function_usage_map |= (1 << i);
         }
 
         if ((color_op == WINED3DTOP_BUMPENVMAP || color_op == WINED3DTOP_BUMPENVMAPLUMINANCE) && i < MAX_TEXTURES - 1) {
-            This->fixed_function_usage_map[i+1] = TRUE;
+            This->fixed_function_usage_map |= (1 << (i + 1));
         }
     }
 }
 
 static void device_map_fixed_function_samplers(IWineD3DDeviceImpl *This) {
     int i, tex;
+    WORD ffu_map;
 
     device_update_fixed_function_usage_map(This);
+    ffu_map = This->fixed_function_usage_map;
 
     if (This->max_ffp_textures == This->max_ffp_texture_stages ||
-        This->stateBlock->lowest_disabled_stage <= This->max_ffp_textures) {
-        for (i = 0; i < This->stateBlock->lowest_disabled_stage; ++i) {
-            if (!This->fixed_function_usage_map[i]) continue;
+            This->stateBlock->lowest_disabled_stage <= This->max_ffp_textures) {
+        for (i = 0; ffu_map; ffu_map >>= 1, ++i)
+        {
+            if (!(ffu_map & 1)) continue;
 
             if (This->texUnitMap[i] != i) {
                 device_map_stage(This, i, i);
@@ -3796,8 +3831,9 @@ static void device_map_fixed_function_samplers(IWineD3DDeviceImpl *This) {
 
     /* Now work out the mapping */
     tex = 0;
-    for (i = 0; i < This->stateBlock->lowest_disabled_stage; ++i) {
-        if (!This->fixed_function_usage_map[i]) continue;
+    for (i = 0; ffu_map; ffu_map >>= 1, ++i)
+    {
+        if (!(ffu_map & 1)) continue;
 
         if (This->texUnitMap[i] != tex) {
             device_map_stage(This, i, tex);
@@ -3840,7 +3876,7 @@ static BOOL device_unit_free_for_vs(IWineD3DDeviceImpl *This, const DWORD *pshad
 
         if (!pshader_sampler_tokens) {
             /* No pixel shader, check fixed function */
-            return current_mapping >= MAX_TEXTURES || !This->fixed_function_usage_map[current_mapping];
+            return current_mapping >= MAX_TEXTURES || !(This->fixed_function_usage_map & (1 << current_mapping));
         }
 
         /* Pixel shader, check the shader's sampler map */
@@ -3861,8 +3897,8 @@ static void device_map_vsamplers(IWineD3DDeviceImpl *This, BOOL ps) {
     if (ps) {
         IWineD3DPixelShaderImpl *pshader = (IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader;
 
-        /* Make sure the shader's reg_maps are up to date. This is only relevant for 1.x pixelshaders. */
-        IWineD3DPixelShader_UpdateSamplers((IWineD3DPixelShader *)pshader);
+        /* Note that we only care if a sampler is sampled or not, not the sampler's specific type.
+         * Otherwise we'd need to call shader_update_samplers() here for 1.x pixelshaders. */
         pshader_sampler_tokens = pshader->baseShader.reg_maps.samplers;
     }
 
@@ -3890,8 +3926,8 @@ static void device_map_vsamplers(IWineD3DDeviceImpl *This, BOOL ps) {
 }
 
 void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This) {
-    BOOL vs = use_vs(This);
-    BOOL ps = use_ps(This);
+    BOOL vs = use_vs(This->stateBlock);
+    BOOL ps = use_ps(This->stateBlock);
     /*
      * Rules are:
      * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
@@ -3981,7 +4017,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
         This->updateStateBlock->changed.pixelShaderConstantsB |= (1 << i);
     }
 
-    IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
+    if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
 
     return WINED3D_OK;
 }
@@ -4029,7 +4065,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
         This->updateStateBlock->changed.pixelShaderConstantsI |= (1 << i);
     }
 
-    IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
+    if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
 
     return WINED3D_OK;
 }
@@ -4076,54 +4112,14 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
                 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
     }
 
-    for (i = start; i < count + start; ++i) {
-        if (!This->updateStateBlock->changed.pixelShaderConstantsF[i]) {
-            constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_pconstantsF), constants_entry, entry);
-            if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx)) {
-                ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry));
-                list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
-            }
-            ptr->idx[ptr->count++] = i;
-            This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
-        }
-    }
-
-    IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
-
-    return WINED3D_OK;
-}
-
-static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF_DirtyConst(
-    IWineD3DDevice *iface,
-    UINT start,
-    CONST float *srcData,
-    UINT count) {
-
-    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-    UINT i;
-
-    TRACE("(iface %p, srcData %p, start %d, count %d)\n",
-            iface, srcData, start, count);
-
-    /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
-    if (srcData == NULL || start + count > GL_LIMITS(pshader_constantsF) || start > GL_LIMITS(pshader_constantsF))
-        return WINED3DERR_INVALIDCALL;
-
-    memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
-    if(TRACE_ON(d3d)) {
-        for (i = 0; i < count; i++)
-            TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
-                    srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
+    if (!This->isRecordingState)
+    {
+        This->shader_backend->shader_update_float_pixel_constants(iface, start, count);
+        IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
     }
 
-    /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
-     * context. On a context switch the old context will be fully dirtified
-     */
-    memset(This->activeContext->pshader_const_dirty + start, 1,
-           sizeof(*This->activeContext->pshader_const_dirty) * count);
-    This->highest_dirty_ps_const = max(This->highest_dirty_ps_const, start+count+1);
-
-    IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
+    memset(This->updateStateBlock->changed.pixelShaderConstantsF + start, 1,
+            sizeof(*This->updateStateBlock->changed.pixelShaderConstantsF) * count);
 
     return WINED3D_OK;
 }
@@ -4584,7 +4580,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *if
         return WINED3D_OK;
     }
 
-    This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
+    This->updateStateBlock->changed.textureState[Stage] |= 1 << Type;
     This->updateStateBlock->textureState[Stage][Type]         = Value;
 
     if (This->isRecordingState) {
@@ -4673,20 +4669,17 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD
 
     oldTexture = This->updateStateBlock->textures[Stage];
 
-    if(pTexture != NULL) {
-        /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; 
-         */
-        if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
-            WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
-            return WINED3DERR_INVALIDCALL;
-        }
-        This->stateBlock->textureDimensions[Stage] = IWineD3DBaseTexture_GetTextureDimensions(pTexture);
+    /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH */
+    if (pTexture && ((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH)
+    {
+        WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
+        return WINED3DERR_INVALIDCALL;
     }
 
     TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
     TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
 
-    This->updateStateBlock->changed.textures[Stage] = TRUE;
+    This->updateStateBlock->changed.textures |= 1 << Stage;
     TRACE("(%p) : setting new texture to %p\n", This, pTexture);
     This->updateStateBlock->textures[Stage]         = pTexture;
 
@@ -4708,8 +4701,15 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD
     if (NULL != This->updateStateBlock->textures[Stage]) {
         IWineD3DBaseTextureImpl *new = (IWineD3DBaseTextureImpl *) This->updateStateBlock->textures[Stage];
         ULONG bindCount = InterlockedIncrement(&new->baseTexture.bindCount);
+        UINT dimensions = IWineD3DBaseTexture_GetTextureDimensions(pTexture);
 
         IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
+
+        if (!oldTexture || dimensions != IWineD3DBaseTexture_GetTextureDimensions(oldTexture))
+        {
+            IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
+        }
+
         if(oldTexture == NULL && Stage < MAX_TEXTURES) {
             /* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
              * so the COLOROP and ALPHAOP have to be dirtified.
@@ -4841,42 +4841,22 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, U
 
 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-    IWineD3DStateBlockImpl *object;
-    HRESULT temp_result;
-    int i;
+    IWineD3DStateBlock *stateblock;
+    HRESULT hr;
 
     TRACE("(%p)\n", This);
-    
-    if (This->isRecordingState) {
-        return WINED3DERR_INVALIDCALL;
-    }
-    
-    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
-    if (NULL == object ) {
-        FIXME("(%p)Error allocating memory for stateblock\n", This);
-        return E_OUTOFMEMORY;
-    }
-    TRACE("(%p) created object %p\n", This, object);
-    object->wineD3DDevice= This;
-    /** FIXME: object->parent       = parent; **/
-    object->parent       = NULL;
-    object->blockType    = WINED3DSBT_RECORDED;
-    object->ref          = 1;
-    object->lpVtbl       = &IWineD3DStateBlock_Vtbl;
 
-    for(i = 0; i < LIGHTMAP_SIZE; i++) {
-        list_init(&object->lightMap[i]);
-    }
+    if (This->isRecordingState) return WINED3DERR_INVALIDCALL;
 
-    temp_result = allocate_shader_constants(object);
-    if (WINED3D_OK != temp_result)
-        return temp_result;
+    hr = IWineD3DDeviceImpl_CreateStateBlock(iface, WINED3DSBT_RECORDED, &stateblock, NULL);
+    if (FAILED(hr)) return hr;
 
     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
-    This->updateStateBlock = object;
+    This->updateStateBlock = (IWineD3DStateBlockImpl *)stateblock;
     This->isRecordingState = TRUE;
 
-    TRACE("(%p) recording stateblock %p\n",This , object);
+    TRACE("(%p) recording stateblock %p\n", This, stateblock);
+
     return WINED3D_OK;
 }
 
@@ -4886,21 +4866,30 @@ static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IW
     IWineD3DStateBlockImpl *object = This->updateStateBlock;
 
     if (!This->isRecordingState) {
-        FIXME("(%p) not recording! returning error\n", This);
+        WARN("(%p) not recording! returning error\n", This);
         *ppStateBlock = NULL;
         return WINED3DERR_INVALIDCALL;
     }
 
-    for(i = 1; i <= WINEHIGHEST_RENDER_STATE; i++) {
-        if(object->changed.renderState[i]) {
-            object->contained_render_states[object->num_contained_render_states] = i;
-            object->num_contained_render_states++;
+    for (i = 0; i <= WINEHIGHEST_RENDER_STATE >> 5; ++i)
+    {
+        DWORD map = object->changed.renderState[i];
+        for (j = 0; map; map >>= 1, ++j)
+        {
+            if (!(map & 1)) continue;
+
+            object->contained_render_states[object->num_contained_render_states++] = (i << 5) | j;
         }
     }
-    for(i = 1; i <= HIGHEST_TRANSFORMSTATE; i++) {
-        if(object->changed.transform[i]) {
-            object->contained_transform_states[object->num_contained_transform_states] = i;
-            object->num_contained_transform_states++;
+
+    for (i = 0; i <= HIGHEST_TRANSFORMSTATE >> 5; ++i)
+    {
+        DWORD map = object->changed.transform[i];
+        for (j = 0; map; map >>= 1, ++j)
+        {
+            if (!(map & 1)) continue;
+
+            object->contained_transform_states[object->num_contained_transform_states++] = (i << 5) | j;
         }
     }
     for(i = 0; i < GL_LIMITS(vshader_constantsF); i++) {
@@ -4923,6 +4912,14 @@ static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IW
             object->num_contained_vs_consts_b++;
         }
     }
+    for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i)
+    {
+        if (object->changed.pixelShaderConstantsF[i])
+        {
+            object->contained_ps_consts_f[object->num_contained_ps_consts_f] = i;
+            ++object->num_contained_ps_consts_f;
+        }
+    }
     for(i = 0; i < MAX_CONST_I; i++) {
         if (object->changed.pixelShaderConstantsI & (1 << i))
         {
@@ -4938,21 +4935,27 @@ static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IW
         }
     }
     for(i = 0; i < MAX_TEXTURES; i++) {
-        for(j = 1; j <= WINED3D_HIGHEST_TEXTURE_STATE; j++) {
-            if(object->changed.textureState[i][j]) {
-                object->contained_tss_states[object->num_contained_tss_states].stage = i;
-                object->contained_tss_states[object->num_contained_tss_states].state = j;
-                object->num_contained_tss_states++;
-            }
+        DWORD map = object->changed.textureState[i];
+
+        for(j = 0; map; map >>= 1, ++j)
+        {
+            if (!(map & 1)) continue;
+
+            object->contained_tss_states[object->num_contained_tss_states].stage = i;
+            object->contained_tss_states[object->num_contained_tss_states].state = j;
+            ++object->num_contained_tss_states;
         }
     }
     for(i = 0; i < MAX_COMBINED_SAMPLERS; i++){
-        for (j = 1; j < WINED3D_HIGHEST_SAMPLER_STATE; j++) {
-            if(object->changed.samplerState[i][j]) {
-                object->contained_sampler_states[object->num_contained_sampler_states].stage = i;
-                object->contained_sampler_states[object->num_contained_sampler_states].state = j;
-                object->num_contained_sampler_states++;
-            }
+        DWORD map = object->changed.samplerState[i];
+
+        for (j = 0; map; map >>= 1, ++j)
+        {
+            if (!(map & 1)) continue;
+
+            object->contained_sampler_states[object->num_contained_sampler_states].stage = i;
+            object->contained_sampler_states[object->num_contained_sampler_states].state = j;
+            ++object->num_contained_sampler_states;
         }
     }
 
@@ -5255,7 +5258,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WI
         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
     }
     /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
-    drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
+    drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0/* NumVertices */, StartVertex /* start_idx */,
                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
     return WINED3D_OK;
 }
@@ -5277,7 +5280,7 @@ static HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *
          * without an index buffer set. (The first time at least...)
          * D3D8 simply dies, but I doubt it can do much harm to return
          * D3DERR_INVALIDCALL there as well. */
-        ERR("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This);
+        WARN("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This);
         return WINED3DERR_INVALIDCALL;
     }
 
@@ -5308,7 +5311,7 @@ static HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *
         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
     }
 
-    drawPrimitive(iface, PrimitiveType, primCount, 0, NumVertices, startIndex,
+    drawPrimitive(iface, PrimitiveType, primCount, NumVertices, startIndex,
                    idxStride, vbo ? NULL : ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
 
     return WINED3D_OK;
@@ -5341,8 +5344,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface,
     /* TODO: Only mark dirty if drawing from a different UP address */
     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
 
-    drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
-                  0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
+    drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* NumVertices */,
+                  0 /* start_idx */, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
 
     /* MSDN specifies stream zero settings must be set to NULL */
     This->stateBlock->streamStride[0] = 0;
@@ -5395,7 +5398,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *
     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
 
-    drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
+    drawPrimitive(iface, PrimitiveType, PrimitiveCount, NumVertices, 0 /* start_idx */, idxStride, pIndexData, MinVertexIndex);
 
     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
     This->stateBlock->streamSource[0] = NULL;
@@ -5426,7 +5429,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided(IWineD3DDevice *if
     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
     This->stateBlock->baseVertexIndex = 0;
     This->up_strided = DrawPrimStrideData;
-    drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0);
+    drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
     This->up_strided = NULL;
     return WINED3D_OK;
 }
@@ -5448,7 +5451,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided(IWineD3DDev
     This->stateBlock->streamIsUP = TRUE;
     This->stateBlock->baseVertexIndex = 0;
     This->up_strided = DrawPrimStrideData;
-    drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* startvertexidx */, 0 /* numindices */, 0 /* startidx */, idxSize, pIndexData, 0 /* minindex */);
+    drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* numindices */, 0 /* start_idx */, idxSize, pIndexData, 0 /* minindex */);
     This->up_strided = NULL;
     return WINED3D_OK;
 }
@@ -5912,12 +5915,10 @@ static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface,
 
     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
 
-    if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-        ENTER_GL();
-        GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
-        checkGLcall("glActiveTextureARB");
-        LEAVE_GL();
-    }
+    ENTER_GL();
+    GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
+    checkGLcall("glActiveTextureARB");
+    LEAVE_GL();
 
     /* Make sure the surface is loaded and up to date */
     IWineD3DSurface_PreLoad(pDestinationSurface);
@@ -6787,10 +6788,8 @@ static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i
                 }
 
                 /* Make sure that a proper texture unit is selected */
-                if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-                    GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
-                    checkGLcall("glActiveTextureARB");
-                }
+                GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
+                checkGLcall("glActiveTextureARB");
                 sampler = This->rev_tex_unit_map[0];
                 if (sampler != -1) {
                     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler));
@@ -7214,16 +7213,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE
        (pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
         pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
     {
-        WINED3DVIEWPORT vp;
         UINT i;
 
-        vp.X = 0;
-        vp.Y = 0;
-        vp.Width = pPresentationParameters->BackBufferWidth;
-        vp.Height = pPresentationParameters->BackBufferHeight;
-        vp.MinZ = 0;
-        vp.MaxZ = 1;
-
         if(!pPresentationParameters->Windowed) {
             DisplayModeChanged = TRUE;
         }
@@ -7237,10 +7228,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE
         if(This->auto_depth_stencil_buffer) {
             updateSurfaceDesc((IWineD3DSurfaceImpl *)This->auto_depth_stencil_buffer, pPresentationParameters);
         }
-
-
-        /* Now set the new viewport */
-        IWineD3DDevice_SetViewport(iface, &vp);
     }
 
     if((pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
@@ -7281,6 +7268,17 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE
         This->exStyle = exStyle;
     }
 
+    TRACE("Resetting stateblock\n");
+    IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock);
+    IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
+
+    /* Note: No parent needed for initial internal stateblock */
+    hr = IWineD3DDevice_CreateStateBlock(iface, WINED3DSBT_INIT, (IWineD3DStateBlock **)&This->stateBlock, NULL);
+    if (FAILED(hr)) ERR("Resetting the stateblock failed with error 0x%08x\n", hr);
+    else TRACE("Created stateblock %p\n", This->stateBlock);
+    This->updateStateBlock = This->stateBlock;
+    IWineD3DStateBlock_AddRef((IWineD3DStateBlock *)This->updateStateBlock);
+
     hr = IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *) This->stateBlock);
     if(FAILED(hr)) {
         ERR("Resetting the stateblock failed with error 0x%08x\n", hr);
@@ -7441,7 +7439,6 @@ static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IW
         /* TODO: nothing really? */
         break;
         case WINED3DRTYPE_VERTEXBUFFER:
-        /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
         {
             int streamNumber;
             TRACE("Cleaning up stream pointers\n");
@@ -7467,7 +7464,6 @@ static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IW
         }
         break;
         case WINED3DRTYPE_INDEXBUFFER:
-        /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
                 This->updateStateBlock->pIndexData =  NULL;
@@ -7571,8 +7567,6 @@ const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
     IWineD3DDeviceImpl_GetCurrentTexturePalette,
     IWineD3DDeviceImpl_SetDepthStencilSurface,
     IWineD3DDeviceImpl_GetDepthStencilSurface,
-    IWineD3DDeviceImpl_SetFVF,
-    IWineD3DDeviceImpl_GetFVF,
     IWineD3DDeviceImpl_SetGammaRamp,
     IWineD3DDeviceImpl_GetGammaRamp,
     IWineD3DDeviceImpl_SetIndices,
@@ -7660,151 +7654,6 @@ const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
     IWineD3DDeviceImpl_EnumResources
 };
 
-const IWineD3DDeviceVtbl IWineD3DDevice_DirtyConst_Vtbl =
-{
-    /*** IUnknown methods ***/
-    IWineD3DDeviceImpl_QueryInterface,
-    IWineD3DDeviceImpl_AddRef,
-    IWineD3DDeviceImpl_Release,
-    /*** IWineD3DDevice methods ***/
-    IWineD3DDeviceImpl_GetParent,
-    /*** Creation methods**/
-    IWineD3DDeviceImpl_CreateVertexBuffer,
-    IWineD3DDeviceImpl_CreateIndexBuffer,
-    IWineD3DDeviceImpl_CreateStateBlock,
-    IWineD3DDeviceImpl_CreateSurface,
-    IWineD3DDeviceImpl_CreateTexture,
-    IWineD3DDeviceImpl_CreateVolumeTexture,
-    IWineD3DDeviceImpl_CreateVolume,
-    IWineD3DDeviceImpl_CreateCubeTexture,
-    IWineD3DDeviceImpl_CreateQuery,
-    IWineD3DDeviceImpl_CreateSwapChain,
-    IWineD3DDeviceImpl_CreateVertexDeclaration,
-    IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF,
-    IWineD3DDeviceImpl_CreateVertexShader,
-    IWineD3DDeviceImpl_CreatePixelShader,
-    IWineD3DDeviceImpl_CreatePalette,
-    /*** Odd functions **/
-    IWineD3DDeviceImpl_Init3D,
-    IWineD3DDeviceImpl_InitGDI,
-    IWineD3DDeviceImpl_Uninit3D,
-    IWineD3DDeviceImpl_UninitGDI,
-    IWineD3DDeviceImpl_SetMultithreaded,
-    IWineD3DDeviceImpl_EvictManagedResources,
-    IWineD3DDeviceImpl_GetAvailableTextureMem,
-    IWineD3DDeviceImpl_GetBackBuffer,
-    IWineD3DDeviceImpl_GetCreationParameters,
-    IWineD3DDeviceImpl_GetDeviceCaps,
-    IWineD3DDeviceImpl_GetDirect3D,
-    IWineD3DDeviceImpl_GetDisplayMode,
-    IWineD3DDeviceImpl_SetDisplayMode,
-    IWineD3DDeviceImpl_GetNumberOfSwapChains,
-    IWineD3DDeviceImpl_GetRasterStatus,
-    IWineD3DDeviceImpl_GetSwapChain,
-    IWineD3DDeviceImpl_Reset,
-    IWineD3DDeviceImpl_SetDialogBoxMode,
-    IWineD3DDeviceImpl_SetCursorProperties,
-    IWineD3DDeviceImpl_SetCursorPosition,
-    IWineD3DDeviceImpl_ShowCursor,
-    IWineD3DDeviceImpl_TestCooperativeLevel,
-    /*** Getters and setters **/
-    IWineD3DDeviceImpl_SetClipPlane,
-    IWineD3DDeviceImpl_GetClipPlane,
-    IWineD3DDeviceImpl_SetClipStatus,
-    IWineD3DDeviceImpl_GetClipStatus,
-    IWineD3DDeviceImpl_SetCurrentTexturePalette,
-    IWineD3DDeviceImpl_GetCurrentTexturePalette,
-    IWineD3DDeviceImpl_SetDepthStencilSurface,
-    IWineD3DDeviceImpl_GetDepthStencilSurface,
-    IWineD3DDeviceImpl_SetFVF,
-    IWineD3DDeviceImpl_GetFVF,
-    IWineD3DDeviceImpl_SetGammaRamp,
-    IWineD3DDeviceImpl_GetGammaRamp,
-    IWineD3DDeviceImpl_SetIndices,
-    IWineD3DDeviceImpl_GetIndices,
-    IWineD3DDeviceImpl_SetBaseVertexIndex,
-    IWineD3DDeviceImpl_GetBaseVertexIndex,
-    IWineD3DDeviceImpl_SetLight,
-    IWineD3DDeviceImpl_GetLight,
-    IWineD3DDeviceImpl_SetLightEnable,
-    IWineD3DDeviceImpl_GetLightEnable,
-    IWineD3DDeviceImpl_SetMaterial,
-    IWineD3DDeviceImpl_GetMaterial,
-    IWineD3DDeviceImpl_SetNPatchMode,
-    IWineD3DDeviceImpl_GetNPatchMode,
-    IWineD3DDeviceImpl_SetPaletteEntries,
-    IWineD3DDeviceImpl_GetPaletteEntries,
-    IWineD3DDeviceImpl_SetPixelShader,
-    IWineD3DDeviceImpl_GetPixelShader,
-    IWineD3DDeviceImpl_SetPixelShaderConstantB,
-    IWineD3DDeviceImpl_GetPixelShaderConstantB,
-    IWineD3DDeviceImpl_SetPixelShaderConstantI,
-    IWineD3DDeviceImpl_GetPixelShaderConstantI,
-    IWineD3DDeviceImpl_SetPixelShaderConstantF_DirtyConst,
-    IWineD3DDeviceImpl_GetPixelShaderConstantF,
-    IWineD3DDeviceImpl_SetRenderState,
-    IWineD3DDeviceImpl_GetRenderState,
-    IWineD3DDeviceImpl_SetRenderTarget,
-    IWineD3DDeviceImpl_GetRenderTarget,
-    IWineD3DDeviceImpl_SetFrontBackBuffers,
-    IWineD3DDeviceImpl_SetSamplerState,
-    IWineD3DDeviceImpl_GetSamplerState,
-    IWineD3DDeviceImpl_SetScissorRect,
-    IWineD3DDeviceImpl_GetScissorRect,
-    IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
-    IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
-    IWineD3DDeviceImpl_SetStreamSource,
-    IWineD3DDeviceImpl_GetStreamSource,
-    IWineD3DDeviceImpl_SetStreamSourceFreq,
-    IWineD3DDeviceImpl_GetStreamSourceFreq,
-    IWineD3DDeviceImpl_SetTexture,
-    IWineD3DDeviceImpl_GetTexture,
-    IWineD3DDeviceImpl_SetTextureStageState,
-    IWineD3DDeviceImpl_GetTextureStageState,
-    IWineD3DDeviceImpl_SetTransform,
-    IWineD3DDeviceImpl_GetTransform,
-    IWineD3DDeviceImpl_SetVertexDeclaration,
-    IWineD3DDeviceImpl_GetVertexDeclaration,
-    IWineD3DDeviceImpl_SetVertexShader,
-    IWineD3DDeviceImpl_GetVertexShader,
-    IWineD3DDeviceImpl_SetVertexShaderConstantB,
-    IWineD3DDeviceImpl_GetVertexShaderConstantB,
-    IWineD3DDeviceImpl_SetVertexShaderConstantI,
-    IWineD3DDeviceImpl_GetVertexShaderConstantI,
-    IWineD3DDeviceImpl_SetVertexShaderConstantF_DirtyConst,
-    IWineD3DDeviceImpl_GetVertexShaderConstantF,
-    IWineD3DDeviceImpl_SetViewport,
-    IWineD3DDeviceImpl_GetViewport,
-    IWineD3DDeviceImpl_MultiplyTransform,
-    IWineD3DDeviceImpl_ValidateDevice,
-    IWineD3DDeviceImpl_ProcessVertices,
-    /*** State block ***/
-    IWineD3DDeviceImpl_BeginStateBlock,
-    IWineD3DDeviceImpl_EndStateBlock,
-    /*** Scene management ***/
-    IWineD3DDeviceImpl_BeginScene,
-    IWineD3DDeviceImpl_EndScene,
-    IWineD3DDeviceImpl_Present,
-    IWineD3DDeviceImpl_Clear,
-    /*** Drawing ***/
-    IWineD3DDeviceImpl_DrawPrimitive,
-    IWineD3DDeviceImpl_DrawIndexedPrimitive,
-    IWineD3DDeviceImpl_DrawPrimitiveUP,
-    IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
-    IWineD3DDeviceImpl_DrawPrimitiveStrided,
-    IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided,
-    IWineD3DDeviceImpl_DrawRectPatch,
-    IWineD3DDeviceImpl_DrawTriPatch,
-    IWineD3DDeviceImpl_DeletePatch,
-    IWineD3DDeviceImpl_ColorFill,
-    IWineD3DDeviceImpl_UpdateTexture,
-    IWineD3DDeviceImpl_UpdateSurface,
-    IWineD3DDeviceImpl_GetFrontBufferData,
-    /*** object tracking ***/
-    IWineD3DDeviceImpl_ResourceReleased,
-    IWineD3DDeviceImpl_EnumResources
-};
-
 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
     WINED3DRS_ALPHABLENDENABLE   ,
     WINED3DRS_ALPHAFUNC          ,
@@ -7844,7 +7693,6 @@ const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
 };
 
 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
-    WINED3DTSS_ADDRESSW              ,
     WINED3DTSS_ALPHAARG0             ,
     WINED3DTSS_ALPHAARG1             ,
     WINED3DTSS_ALPHAARG2             ,
index 253860f..a78f4e5 100644 (file)
@@ -82,6 +82,7 @@ static const struct {
     {"GL_ARB_texture_mirrored_repeat",      ARB_TEXTURE_MIRRORED_REPEAT,    0                           },
     {"GL_ARB_texture_non_power_of_two",     ARB_TEXTURE_NON_POWER_OF_TWO,   MAKEDWORD_VERSION(2, 0)     },
     {"GL_ARB_texture_rectangle",            ARB_TEXTURE_RECTANGLE,          0                           },
+    {"GL_ARB_texture_rg",                   ARB_TEXTURE_RG,                 0                           },
     {"GL_ARB_vertex_blend",                 ARB_VERTEX_BLEND,               0                           },
     {"GL_ARB_vertex_buffer_object",         ARB_VERTEX_BUFFER_OBJECT,       0                           },
     {"GL_ARB_vertex_program",               ARB_VERTEX_PROGRAM,             0                           },
@@ -109,9 +110,11 @@ static const struct {
     {"GL_EXT_texture_env_combine",          EXT_TEXTURE_ENV_COMBINE,        0                           },
     {"GL_EXT_texture_env_dot3",             EXT_TEXTURE_ENV_DOT3,           0                           },
     {"GL_EXT_texture_sRGB",                 EXT_TEXTURE_SRGB,               0                           },
+    {"GL_EXT_texture_swizzle",              EXT_TEXTURE_SWIZZLE,            0                           },
     {"GL_EXT_texture_filter_anisotropic",   EXT_TEXTURE_FILTER_ANISOTROPIC, 0                           },
     {"GL_EXT_texture_lod",                  EXT_TEXTURE_LOD,                0                           },
     {"GL_EXT_texture_lod_bias",             EXT_TEXTURE_LOD_BIAS,           0                           },
+    {"GL_EXT_vertex_array_bgra",            EXT_VERTEX_ARRAY_BGRA,          0                           },
     {"GL_EXT_vertex_shader",                EXT_VERTEX_SHADER,              0                           },
     {"GL_EXT_gpu_program_parameters",       EXT_GPU_PROGRAM_PARAMETERS,     0                           },
 
@@ -187,7 +190,6 @@ glAttribFunc diffuse_funcs[WINED3DDECLTYPE_UNUSED];
 glAttribFunc specular_funcs[WINED3DDECLTYPE_UNUSED];
 glAttribFunc normal_funcs[WINED3DDECLTYPE_UNUSED];
 glMultiTexCoordFunc multi_texcoord_funcs[WINED3DDECLTYPE_UNUSED];
-glAttribFunc texcoord_funcs[WINED3DDECLTYPE_UNUSED];
 
 /**
  * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
@@ -519,8 +521,7 @@ static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
     ENTER_GL();
 
     gl_string = (const char *) glGetString(GL_RENDERER);
-    if (NULL == gl_string)
-       gl_string = "None";
+    if (!gl_string) gl_string = "None";
     strcpy(gl_info->gl_renderer, gl_string);
 
     gl_string = (const char *) glGetString(GL_VENDOR);
@@ -715,7 +716,7 @@ static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
     gl_info->max_texture_stages = 1;
     gl_info->max_fragment_samplers = 1;
     gl_info->max_vertex_samplers = 0;
-    gl_info->max_combined_samplers = 0;
+    gl_info->max_combined_samplers = gl_info->max_fragment_samplers + gl_info->max_vertex_samplers;
     gl_info->max_sampler_stages = 1;
     gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
     gl_info->ps_arb_max_temps = 0;
@@ -743,7 +744,7 @@ static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
     gl_info->max_texture_size = gl_max;
     TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
 
-    glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
+    glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv);
     gl_info->max_pointsizemin = gl_floatv[0];
     gl_info->max_pointsize = gl_floatv[1];
     TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
@@ -1303,7 +1304,8 @@ static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
             }
             break;
         case VENDOR_INTEL:
-            if (strstr(gl_info->gl_renderer, "GMA 950")) {
+            if (strstr(gl_info->gl_renderer, "GMA 950") ||
+                strstr(gl_info->gl_renderer, "945GM")) {
                 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
                 gl_info->gl_card = CARD_INTEL_I945GM;
                 vidmem = 64;
@@ -2361,6 +2363,10 @@ static BOOL CheckTextureCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINE
 
         case WINED3DFMT_G16R16F:
         case WINED3DFMT_G32R32F:
+            if(GL_SUPPORT(ARB_TEXTURE_RG)) {
+                TRACE_(d3d_caps)("[OK]\n");
+                return TRUE;
+            }
             TRACE_(d3d_caps)("[FAILED]\n");
             return FALSE;
 
@@ -3146,11 +3152,11 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter,
         pCaps->RasterCaps         |= WINED3DPRASTERCAPS_FOGRANGE;
     }
                         /* FIXME Add:
-                          WINED3DPRASTERCAPS_COLORPERSPECTIVE
-                          WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
-                          WINED3DPRASTERCAPS_ANTIALIASEDGES
-                          WINED3DPRASTERCAPS_ZBUFFERLESSHSR
-                          WINED3DPRASTERCAPS_WBUFFER */
+                           WINED3DPRASTERCAPS_COLORPERSPECTIVE
+                           WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
+                           WINED3DPRASTERCAPS_ANTIALIASEDGES
+                           WINED3DPRASTERCAPS_ZBUFFERLESSHSR
+                           WINED3DPRASTERCAPS_WBUFFER */
 
     pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS       |
                       WINED3DPCMPCAPS_EQUAL        |
@@ -3616,16 +3622,17 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter,
 
 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
    and fields being inserted in the middle, a new structure is used in place    */
-static HRESULT  WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
-                                           DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
-                                           IUnknown *parent) {
-
+static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
+        WINED3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviourFlags, IUnknown *parent,
+        IWineD3DDeviceParent *device_parent, IWineD3DDevice **ppReturnedDeviceInterface)
+{
     IWineD3DDeviceImpl *object  = NULL;
     IWineD3DImpl       *This    = (IWineD3DImpl *)iface;
     WINED3DDISPLAYMODE  mode;
     const struct fragment_pipeline *frag_pipeline = NULL;
     int i;
     struct fragment_caps ffp_caps;
+    HRESULT hr;
 
     /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
      * number and create a device without a 3D adapter for 2D only operation.
@@ -3649,6 +3656,7 @@ static HRESULT  WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
     object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
     IWineD3D_AddRef(object->wineD3D);
     object->parent  = parent;
+    object->device_parent = device_parent;
     list_init(&object->resources);
     list_init(&object->shaders);
 
@@ -3684,19 +3692,18 @@ static HRESULT  WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
     frag_pipeline->get_caps(DeviceType, &GLINFO_LOCATION, &ffp_caps);
     object->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
     object->max_ffp_texture_stages = ffp_caps.MaxTextureBlendStages;
-    compile_state_table(object->StateTable, object->multistate_funcs, &GLINFO_LOCATION,
+    hr = compile_state_table(object->StateTable, object->multistate_funcs, &GLINFO_LOCATION,
                         ffp_vertexstate_template, frag_pipeline, misc_state_template);
 
-    object->blitter = select_blit_implementation(Adapter, DeviceType);
+    if (FAILED(hr)) {
+        IWineD3D_Release(object->wineD3D);
+        HeapFree(GetProcessHeap(), 0, object);
 
-    /* Prefer the vtable with functions optimized for single dirtifyable objects if the shader
-     * model can deal with that. It is essentially the same, just with adjusted
-     * Set*ShaderConstantF implementations
-     */
-    if(object->shader_backend->shader_dirtifyable_constants((IWineD3DDevice *) object)) {
-        object->lpVtbl  = &IWineD3DDevice_DirtyConst_Vtbl;
+        return hr;
     }
 
+    object->blitter = select_blit_implementation(Adapter, DeviceType);
+
     /* set the state of the device to valid */
     object->state = WINED3D_OK;
 
@@ -4155,35 +4162,11 @@ static void fillGLAttribFuncs(const WineD3D_GL_Info *gl_info)
         multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_texcoord_func;
         multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_texcoord_func;
     }
-
-    texcoord_funcs[WINED3DDECLTYPE_FLOAT1]      = (glAttribFunc)glTexCoord1fv;
-    texcoord_funcs[WINED3DDECLTYPE_FLOAT2]      = (glAttribFunc)glTexCoord2fv;
-    texcoord_funcs[WINED3DDECLTYPE_FLOAT3]      = (glAttribFunc)glTexCoord3fv;
-    texcoord_funcs[WINED3DDECLTYPE_FLOAT4]      = (glAttribFunc)glTexCoord4fv;
-    texcoord_funcs[WINED3DDECLTYPE_D3DCOLOR]    = invalid_func;
-    texcoord_funcs[WINED3DDECLTYPE_UBYTE4]      = invalid_func;
-    texcoord_funcs[WINED3DDECLTYPE_SHORT2]      = (glAttribFunc)glTexCoord2sv;
-    texcoord_funcs[WINED3DDECLTYPE_SHORT4]      = (glAttribFunc)glTexCoord4sv;
-    texcoord_funcs[WINED3DDECLTYPE_UBYTE4N]     = invalid_func;
-    texcoord_funcs[WINED3DDECLTYPE_SHORT2N]     = invalid_func;
-    texcoord_funcs[WINED3DDECLTYPE_SHORT4N]     = invalid_func;
-    texcoord_funcs[WINED3DDECLTYPE_USHORT2N]    = invalid_func;
-    texcoord_funcs[WINED3DDECLTYPE_USHORT4N]    = invalid_func;
-    texcoord_funcs[WINED3DDECLTYPE_UDEC3]       = invalid_func;
-    texcoord_funcs[WINED3DDECLTYPE_DEC3N]       = invalid_func;
-    if (GL_SUPPORT(NV_HALF_FLOAT))
-    {
-        texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2]   = (glAttribFunc)GL_EXTCALL(glTexCoord2hvNV);
-        texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4]   = (glAttribFunc)GL_EXTCALL(glTexCoord4hvNV);
-    } else {
-        texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2]   = invalid_func;
-        texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4]   = invalid_func;
-    }
 }
 
 #define PUSH1(att)        attribs[nAttribs++] = (att);
 BOOL InitAdapters(void) {
-    static HMODULE mod_gl, mod_win32gl;
+    static HMODULE mod_gl;
     BOOL ret;
     int ps_selected_mode, vs_selected_mode;
 
@@ -4202,16 +4185,10 @@ BOOL InitAdapters(void) {
             ERR("Can't load opengl32.dll!\n");
             goto nogl_adapter;
         }
-        mod_win32gl = mod_gl;
 #else
 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
         /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
         mod_gl = GetModuleHandleA("gdi32.dll");
-        mod_win32gl = LoadLibraryA("opengl32.dll");
-        if(!mod_win32gl) {
-            ERR("Can't load opengl32.dll!\n");
-            goto nogl_adapter;
-        }
 #endif
     }
 
@@ -4232,8 +4209,16 @@ BOOL InitAdapters(void) {
     /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
      * otherwise because we have to use winex11.drv's override
      */
-    glFinish = (void*)GetProcAddress(mod_win32gl, "glFinish");
-    glFlush = (void*)GetProcAddress(mod_win32gl, "glFlush");
+#ifdef USE_WIN32_OPENGL
+    glFinish = (void*)GetProcAddress(mod_gl, "glFinish");
+    glFlush = (void*)GetProcAddress(mod_gl, "glFlush");
+#else
+    glFinish = (void*)pwglGetProcAddress("wglFinish");
+    glFlush = (void*)pwglGetProcAddress("wglFlush");
+#endif
+
+    glEnableWINE = glEnable;
+    glDisableWINE = glDisable;
 
     /* For now only one default adapter */
     {
@@ -4376,6 +4361,7 @@ BOOL InitAdapters(void) {
         }
 
         fixup_extensions(&Adapters[0].gl_info);
+        add_gl_compat_wrappers(&Adapters[0].gl_info);
 
         WineD3D_ReleaseFakeGLContext();
 
index 7603103..b78078f 100644 (file)
@@ -152,12 +152,13 @@ void primitiveDeclarationConvertToStridedData(
     const DWORD *streams = vertexDeclaration->streams;
 
     /* Check for transformed vertices, disable vertex shader if present */
-    strided->u.s.position_transformed = vertexDeclaration->position_transformed;
+    strided->position_transformed = vertexDeclaration->position_transformed;
     if(vertexDeclaration->position_transformed) {
         useVertexShaderFunction = FALSE;
     }
 
     /* Translate the declaration into strided data */
+    strided->swizzle_map = 0;
     for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
         GLint streamVBO = 0;
         BOOL stride_used;
@@ -201,8 +202,8 @@ void primitiveDeclarationConvertToStridedData(
                         element->Usage == WINED3DDECLUSAGE_POSITIONT)) {
                     static BOOL warned = FALSE;
                     if(!warned) {
-                       /* This may be bad with the fixed function pipeline */
-                       FIXME("Missing vbo streams with unfixed colors or transformed position, expect problems\n");
+                        /* This may be bad with the fixed function pipeline */
+                        FIXME("Missing vbo streams with unfixed colors or transformed position, expect problems\n");
                         warned = TRUE;
                     }
                 }
@@ -234,6 +235,11 @@ void primitiveDeclarationConvertToStridedData(
                 strided->u.input[idx].dwStride = stride;
                 strided->u.input[idx].VBO = streamVBO;
                 strided->u.input[idx].streamNo = element->Stream;
+                if (!GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA) && element->Type == WINED3DDECLTYPE_D3DCOLOR)
+                {
+                    strided->swizzle_map |= 1 << idx;
+                }
+                strided->use_map |= 1 << idx;
             }
         }
     }
@@ -253,32 +259,35 @@ void primitiveDeclarationConvertToStridedData(
     }
 }
 
-static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
-                     const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx, ULONG startVertex) {
+static void drawStridedFast(IWineD3DDevice *iface, GLenum primitive_type,
+        UINT min_vertex_idx, UINT max_vertex_idx, UINT count, short idx_size,
+        const void *idx_data, UINT start_idx)
+{
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
 
-    if (idxSize != 0 /* This crashes sometimes!*/) {
-        TRACE("(%p) : glElements(%x, %d, %d, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
-        idxData = idxData == (void *)-1 ? NULL : idxData;
+    if (idx_size)
+    {
+        TRACE("(%p) : glElements(%x, %d, %d, ...)\n", This, primitive_type, count, min_vertex_idx);
+
 #if 1
-        glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
-                     (const char *)idxData+(idxSize * startIdx));
+        glDrawElements(primitive_type, count,
+                idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
+                (const char *)idx_data + (idx_size * start_idx));
         checkGLcall("glDrawElements");
-#else /* using drawRangeElements may be faster */
-
-        glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
-                      idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
-                      (const char *)idxData+(idxSize * startIdx));
+#else
+        glDrawRangeElements(primitive_type, min_vertex_idx, max_vertex_idx, count,
+                idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
+                (const char *)idx_data + (idx_size * start_idx));
         checkGLcall("glDrawRangeElements");
 #endif
+    }
+    else
+    {
+        TRACE("(%p) : glDrawArrays(%#x, %d, %d)\n", This, primitive_type, start_idx, count);
 
-    } else {
-        TRACE("(%p) : glDrawArrays(%#x, %d, %d)\n", This, glPrimitiveType, startVertex, numberOfVertices);
-        glDrawArrays(glPrimitiveType, startVertex, numberOfVertices);
+        glDrawArrays(primitive_type, start_idx, count);
         checkGLcall("glDrawArrays");
     }
-
-    return;
 }
 
 /*
@@ -287,7 +296,7 @@ static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum
  */
 
 static void drawStridedSlow(IWineD3DDevice *iface, const WineDirect3DVertexStridedData *sd, UINT NumVertexes,
-        GLenum glPrimType, const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx, ULONG startVertex)
+        GLenum glPrimType, const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx)
 {
     unsigned int               textureNo    = 0;
     const WORD                *pIdxBufS     = NULL;
@@ -295,8 +304,8 @@ static void drawStridedSlow(IWineD3DDevice *iface, const WineDirect3DVertexStrid
     ULONG                      vx_index;
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     const UINT *streamOffset = This->stateBlock->streamOffset;
-    long                      SkipnStrides = startVertex + This->stateBlock->loadBaseVertexIndex;
-    BOOL                      pixelShader = use_ps(This);
+    long                      SkipnStrides = startIdx + This->stateBlock->loadBaseVertexIndex;
+    BOOL                      pixelShader = use_ps(This->stateBlock);
     BOOL specular_fog = FALSE;
     UINT texture_stages = GL_LIMITS(texture_stages);
     const BYTE *texCoords[WINED3DDP_MAXTEXCOORD];
@@ -440,21 +449,15 @@ static void drawStridedSlow(IWineD3DDevice *iface, const WineDirect3DVertexStrid
         {
             int coord_idx;
             const void *ptr;
+            int texture_idx;
 
             if (!(tmp_tex_mask & 1)) continue;
 
             coord_idx = This->stateBlock->textureState[texture][WINED3DTSS_TEXCOORDINDEX];
             ptr = texCoords[coord_idx] + (SkipnStrides * sd->u.s.texCoords[coord_idx].dwStride);
 
-            if (GL_SUPPORT(ARB_MULTITEXTURE))
-            {
-                int texture_idx = This->texUnitMap[texture];
-                multi_texcoord_funcs[sd->u.s.texCoords[coord_idx].dwType](GL_TEXTURE0_ARB + texture_idx, ptr);
-            }
-            else
-            {
-                texcoord_funcs[sd->u.s.texCoords[coord_idx].dwType](ptr);
-            }
+            texture_idx = This->texUnitMap[texture];
+            multi_texcoord_funcs[sd->u.s.texCoords[coord_idx].dwType](GL_TEXTURE0_ARB + texture_idx, ptr);
         }
 
         /* Diffuse -------------------------------- */
@@ -603,10 +606,10 @@ static inline void send_attribute(IWineD3DDeviceImpl *This, const DWORD type, co
 }
 
 static void drawStridedSlowVs(IWineD3DDevice *iface, const WineDirect3DVertexStridedData *sd, UINT numberOfVertices,
-        GLenum glPrimitiveType, const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx, ULONG startVertex)
+        GLenum glPrimitiveType, const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx)
 {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
-    long                      SkipnStrides = startVertex + This->stateBlock->loadBaseVertexIndex;
+    long                      SkipnStrides = startIdx + This->stateBlock->loadBaseVertexIndex;
     const WORD                *pIdxBufS     = NULL;
     const DWORD               *pIdxBufL     = NULL;
     ULONG                      vx_index;
@@ -664,7 +667,7 @@ static void drawStridedSlowVs(IWineD3DDevice *iface, const WineDirect3DVertexStr
 
 static inline void drawStridedInstanced(IWineD3DDevice *iface, const WineDirect3DVertexStridedData *sd,
         UINT numberOfVertices, GLenum glPrimitiveType, const void *idxData, short idxSize, ULONG minIndex,
-        ULONG startIdx, ULONG startVertex)
+        ULONG startIdx)
 {
     UINT numInstances = 0, i;
     int numInstancedAttribs = 0, j;
@@ -684,7 +687,6 @@ static inline void drawStridedInstanced(IWineD3DDevice *iface, const WineDirect3
     }
 
     TRACE("(%p) : glElements(%x, %d, %d, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
-    idxData = idxData == (void *)-1 ? NULL : idxData;
 
     /* First, figure out how many instances we have to draw */
     for(i = 0; i < MAX_STREAMS; i++) {
@@ -817,16 +819,9 @@ static inline void remove_vbos(IWineD3DDeviceImpl *This, WineDirect3DVertexStrid
 }
 
 /* Routine common to the draw primitive and draw indexed primitive routines */
-void drawPrimitive(IWineD3DDevice *iface,
-                   int PrimitiveType,
-                   long NumPrimitives,
-                   /* for Indexed: */
-                   long  StartVertexIndex,
-                   UINT  numberOfVertices,
-                   long  StartIdx,
-                   short idxSize,
-                   const void *idxData,
-                   int   minIndex) {
+void drawPrimitive(IWineD3DDevice *iface, int PrimitiveType, long NumPrimitives,
+        UINT numberOfVertices, long StartIdx, short idxSize, const void *idxData, int minIndex)
+{
 
     IWineD3DDeviceImpl           *This = (IWineD3DDeviceImpl *)iface;
     IWineD3DSurfaceImpl          *target;
@@ -869,9 +864,11 @@ void drawPrimitive(IWineD3DDevice *iface,
         if (numberOfVertices == 0 )
             numberOfVertices = calculatedNumberOfindices;
 
-        if(!use_vs(This)) {
-            if(!This->strided_streams.u.s.position_transformed && This->activeContext->num_untracked_materials &&
-                This->stateBlock->renderState[WINED3DRS_LIGHTING]) {
+        if (!use_vs(This->stateBlock))
+        {
+            if (!This->strided_streams.position_transformed && This->activeContext->num_untracked_materials
+                    && This->stateBlock->renderState[WINED3DRS_LIGHTING])
+            {
                 static BOOL warned;
                 if (!warned) {
                     FIXME("Using software emulation because not all material properties could be tracked\n");
@@ -904,7 +901,8 @@ void drawPrimitive(IWineD3DDevice *iface,
 
         if (This->useDrawStridedSlow || emulation) {
             /* Immediate mode drawing */
-            if(use_vs(This)) {
+            if (use_vs(This->stateBlock))
+            {
                 static BOOL warned;
                 if (!warned) {
                     FIXME("Using immediate mode with vertex shaders for half float emulation\n");
@@ -912,19 +910,19 @@ void drawPrimitive(IWineD3DDevice *iface,
                 } else {
                     TRACE("Using immediate mode with vertex shaders for half float emulation\n");
                 }
-                drawStridedSlowVs(iface, strided, calculatedNumberOfindices, glPrimType,
-                                  idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
+                drawStridedSlowVs(iface, strided, calculatedNumberOfindices,
+                        glPrimType, idxData, idxSize, minIndex, StartIdx);
             } else {
                 drawStridedSlow(iface, strided, calculatedNumberOfindices,
-                                glPrimType, idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
+                        glPrimType, idxData, idxSize, minIndex, StartIdx);
             }
         } else if(This->instancedDraw) {
             /* Instancing emulation with mixing immediate mode and arrays */
             drawStridedInstanced(iface, &This->strided_streams, calculatedNumberOfindices, glPrimType,
-                            idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
+                            idxData, idxSize, minIndex, StartIdx);
         } else {
-            drawStridedFast(iface, calculatedNumberOfindices, glPrimType,
-                            idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
+            drawStridedFast(iface, glPrimType, minIndex, minIndex + numberOfVertices - 1,
+                    calculatedNumberOfindices, idxSize, idxData, StartIdx);
         }
     }
 
@@ -1035,9 +1033,8 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This,
            vtxStride * info->StartVertexOffsetWidth;
 
     /* Not entirely sure about what happens with transformed vertices */
-    if(strided.u.s.position_transformed) {
-        FIXME("Transformed position in rectpatch generation\n");
-    }
+    if (strided.position_transformed) FIXME("Transformed position in rectpatch generation\n");
+
     if(vtxStride % sizeof(GLfloat)) {
         /* glMap2f reads vertex sizes in GLfloats, the d3d stride is in bytes.
          * I don't see how the stride could not be a multiple of 4, but make sure
@@ -1092,11 +1089,11 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This,
     checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)");
     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_FILLMODE));
     if(patch->has_normals) {
-        const GLfloat black[4] = {0, 0, 0, 0};
-        const GLfloat red[4]   = {1, 0, 0, 0};
-        const GLfloat green[4] = {0, 1, 0, 0};
-        const GLfloat blue[4]  = {0, 0, 1, 0};
-        const GLfloat white[4] = {1, 1, 1, 1};
+        static const GLfloat black[] = {0, 0, 0, 0};
+        static const GLfloat red[]   = {1, 0, 0, 0};
+        static const GLfloat green[] = {0, 1, 0, 0};
+        static const GLfloat blue[]  = {0, 0, 1, 0};
+        static const GLfloat white[] = {1, 1, 1, 1};
         glEnable(GL_LIGHTING);
         checkGLcall("glEnable(GL_LIGHTING)");
         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, black);
@@ -1263,9 +1260,9 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This,
 
     if(patch->has_normals) {
         /* Now do the same with reverse light directions */
-        const GLfloat x[4] = {-1,  0,  0, 0};
-        const GLfloat y[4] = { 0, -1,  0, 0};
-        const GLfloat z[4] = { 0,  0, -1, 0};
+        static const GLfloat x[] = {-1,  0,  0, 0};
+        static const GLfloat y[] = { 0, -1,  0, 0};
+        static const GLfloat z[] = { 0,  0, -1, 0};
         glLightfv(GL_LIGHT0, GL_POSITION, x);
         glLightfv(GL_LIGHT1, GL_POSITION, y);
         glLightfv(GL_LIGHT2, GL_POSITION, z);
diff --git a/reactos/dll/directx/wine/wined3d/gl_compat.c b/reactos/dll/directx/wine/wined3d/gl_compat.c
new file mode 100644 (file)
index 0000000..1fc48cc
--- /dev/null
@@ -0,0 +1,535 @@
+/*
+ * Compatibility functions for older GL implementations
+ *
+ * Copyright 2008 Stefan Dösinger for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include <stdio.h>
+#ifdef HAVE_FLOAT_H
+# include <float.h>
+#endif
+#include "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(gl_compat);
+
+/* Start GL_ARB_multitexture emulation */
+static void WINE_GLAPI wine_glMultiTexCoord1fARB(GLenum target, GLfloat s) {
+    if(target != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+    glTexCoord1f(s);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord1fvARB(GLenum target, const GLfloat *v) {
+    if(target != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+    glTexCoord1fv(v);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t) {
+    if(target != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+    glTexCoord2f(s, t);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord2fvARB(GLenum target, const GLfloat *v) {
+    if(target != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+    glTexCoord2fv(v);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord3fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r) {
+    if(target != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+    glTexCoord3f(s, t, r);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord3fvARB(GLenum target, const GLfloat *v) {
+    if(target != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+    glTexCoord3fv(v);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord4fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) {
+    if(target != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+    glTexCoord4f(s, t, r, q);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord4fvARB(GLenum target, const GLfloat *v) {
+    if(target != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+    glTexCoord4fv(v);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord2svARB(GLenum target, const GLshort *v) {
+    if(target != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+    glTexCoord2sv(v);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord4svARB(GLenum target, const GLshort *v) {
+    if(target != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+    glTexCoord4sv(v);
+}
+
+static void WINE_GLAPI wine_glActiveTextureARB(GLenum texture) {
+    if(texture != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+}
+
+static void WINE_GLAPI wine_glClientActiveTextureARB(GLenum texture) {
+    if(texture != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+}
+
+static void (WINE_GLAPI *old_multitex_glGetIntegerv) (GLenum pname, GLint* params) = NULL;
+static void WINE_GLAPI wine_glGetIntegerv(GLenum pname, GLint* params) {
+    switch(pname) {
+        case GL_ACTIVE_TEXTURE:         *params = 0;    break;
+        case GL_MAX_TEXTURE_UNITS_ARB:  *params = 1;    break;
+        default: old_multitex_glGetIntegerv(pname, params);
+    }
+}
+
+static void (WINE_GLAPI *old_multitex_glGetFloatv) (GLenum pname, GLfloat* params) = NULL;
+static void WINE_GLAPI wine_glGetFloatv(GLenum pname, GLfloat* params) {
+    if(pname == GL_ACTIVE_TEXTURE) *params = 0.0;
+    else old_multitex_glGetFloatv(pname, params);
+}
+
+static void (WINE_GLAPI *old_multitex_glGetDoublev) (GLenum pname, GLdouble* params) = NULL;
+static void WINE_GLAPI wine_glGetDoublev(GLenum pname, GLdouble* params) {
+    if(pname == GL_ACTIVE_TEXTURE) *params = 0.0;
+    else old_multitex_glGetDoublev(pname, params);
+}
+
+/* Start GL_EXT_fogcoord emulation */
+static void (WINE_GLAPI *old_fogcoord_glEnable) (GLenum cap) = NULL;
+static void WINE_GLAPI wine_glEnable(GLenum cap) {
+    if(cap == GL_FOG) {
+        WineD3DContext *ctx = getActiveContext();
+        ctx->fog_enabled = 1;
+        if(ctx->gl_fog_source != GL_FRAGMENT_DEPTH_EXT) return;
+    }
+    old_fogcoord_glEnable(cap);
+}
+
+static void (WINE_GLAPI *old_fogcoord_glDisable) (GLenum cap) = NULL;
+static void WINE_GLAPI wine_glDisable(GLenum cap) {
+    if(cap == GL_FOG) {
+        WineD3DContext *ctx = getActiveContext();
+        ctx->fog_enabled = 0;
+        if(ctx->gl_fog_source != GL_FRAGMENT_DEPTH_EXT) return;
+    }
+    old_fogcoord_glDisable(cap);
+}
+
+static void (WINE_GLAPI *old_fogcoord_glFogi) (GLenum pname, GLint param) = NULL;
+static void WINE_GLAPI wine_glFogi(GLenum pname, GLint param) {
+    if(pname == GL_FOG_COORDINATE_SOURCE_EXT) {
+        WineD3DContext *ctx = getActiveContext();
+        ctx->gl_fog_source = param;
+        if(param == GL_FRAGMENT_DEPTH_EXT) {
+            if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG);
+        } else {
+            WARN("Fog coords activated, but not supported. Using slow emulation\n");
+            old_fogcoord_glDisable(GL_FOG);
+        }
+    } else {
+        if(pname == GL_FOG_START) {
+            getActiveContext()->fogstart = param;
+        } else if(pname == GL_FOG_END) {
+            getActiveContext()->fogend = param;
+        }
+        old_fogcoord_glFogi(pname, param);
+    }
+}
+
+static void (WINE_GLAPI *old_fogcoord_glFogiv) (GLenum pname, const GLint *param) = NULL;
+static void WINE_GLAPI wine_glFogiv(GLenum pname, const GLint *param) {
+    if(pname == GL_FOG_COORDINATE_SOURCE_EXT) {
+        WineD3DContext *ctx = getActiveContext();
+        ctx->gl_fog_source = *param;
+        if(*param == GL_FRAGMENT_DEPTH_EXT) {
+            if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG);
+        } else {
+            WARN("Fog coords activated, but not supported. Using slow emulation\n");
+            old_fogcoord_glDisable(GL_FOG);
+        }
+    } else {
+        if(pname == GL_FOG_START) {
+            getActiveContext()->fogstart = *param;
+        } else if(pname == GL_FOG_END) {
+            getActiveContext()->fogend = *param;
+        }
+        old_fogcoord_glFogiv(pname, param);
+    }
+}
+
+static void (WINE_GLAPI *old_fogcoord_glFogf) (GLenum pname, GLfloat param) = NULL;
+static void WINE_GLAPI wine_glFogf(GLenum pname, GLfloat param) {
+    if(pname == GL_FOG_COORDINATE_SOURCE_EXT) {
+        WineD3DContext *ctx = getActiveContext();
+        ctx->gl_fog_source = (GLint) param;
+        if(param == GL_FRAGMENT_DEPTH_EXT) {
+            if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG);
+        } else {
+            WARN("Fog coords activated, but not supported. Using slow emulation\n");
+            old_fogcoord_glDisable(GL_FOG);
+        }
+    } else {
+        if(pname == GL_FOG_START) {
+            getActiveContext()->fogstart = param;
+        } else if(pname == GL_FOG_END) {
+            getActiveContext()->fogend = param;
+        }
+        old_fogcoord_glFogf(pname, param);
+    }
+}
+
+static void (WINE_GLAPI *old_fogcoord_glFogfv) (GLenum pname, const GLfloat *param) = NULL;
+static void WINE_GLAPI wine_glFogfv(GLenum pname, const GLfloat *param) {
+    if(pname == GL_FOG_COORDINATE_SOURCE_EXT) {
+        WineD3DContext *ctx = getActiveContext();
+        ctx->gl_fog_source = (GLint) *param;
+        if(*param == GL_FRAGMENT_DEPTH_EXT) {
+            if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG);
+        } else {
+            WARN("Fog coords activated, but not supported. Using slow emulation\n");
+            old_fogcoord_glDisable(GL_FOG);
+        }
+    } else {
+        if(pname == GL_FOG_COLOR) {
+            WineD3DContext *ctx = getActiveContext();
+            ctx->fogcolor[0] = param[0];
+            ctx->fogcolor[1] = param[1];
+            ctx->fogcolor[2] = param[2];
+            ctx->fogcolor[3] = param[3];
+        } else if(pname == GL_FOG_START) {
+            getActiveContext()->fogstart = *param;
+        } else if(pname == GL_FOG_END) {
+            getActiveContext()->fogend = *param;
+        }
+        old_fogcoord_glFogfv(pname, param);
+    }
+}
+
+static void (WINE_GLAPI *old_fogcoord_glVertex4f) (GLfloat x, GLfloat y, GLfloat z, GLfloat w) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glVertex4fv) (const GLfloat *pos) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glVertex3f) (GLfloat x, GLfloat y, GLfloat z) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glVertex3fv) (const GLfloat *pos) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glColor4f) (GLfloat r, GLfloat g, GLfloat b, GLfloat a) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glColor4fv) (const GLfloat *color) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glColor3f) (GLfloat r, GLfloat g, GLfloat b) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glColor3fv) (const GLfloat *color) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glColor4ub) (GLubyte r, GLubyte g, GLubyte b, GLubyte a) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glFogCoordfEXT) (GLfloat f) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glFogCoorddEXT) (GLdouble f) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glFogCoordfvEXT) (const GLfloat *f) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glFogCoorddvEXT) (const GLdouble *f) = NULL;
+
+static void WINE_GLAPI wine_glVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+    WineD3DContext *ctx = getActiveContext();
+    if(ctx->gl_fog_source == GL_FOG_COORDINATE_EXT && ctx->fog_enabled) {
+        GLfloat c[4] = {ctx->color[0], ctx->color[1], ctx->color[2], ctx->color[3]};
+        GLfloat i;
+
+        i = (ctx->fogend - ctx->fog_coord_value) / (ctx->fogend - ctx->fogstart);
+        c[0] = i * c[0] + (1.0 - i) * ctx->fogcolor[0];
+        c[1] = i * c[1] + (1.0 - i) * ctx->fogcolor[1];
+        c[2] = i * c[2] + (1.0 - i) * ctx->fogcolor[2];
+
+        old_fogcoord_glColor4f(c[0], c[1], c[2], c[3]);
+        old_fogcoord_glVertex4f(x, y, z, w);
+    } else {
+        old_fogcoord_glVertex4f(x, y, z, w);
+    }
+}
+
+static void WINE_GLAPI wine_glVertex4fv(const GLfloat *pos) {
+    wine_glVertex4f(pos[0], pos[1], pos[2], pos[3]);
+}
+
+static void WINE_GLAPI wine_glVertex3f(GLfloat x, GLfloat y, GLfloat z) {
+    wine_glVertex4f(x, y, z, 1.0);
+}
+
+static void WINE_GLAPI wine_glVertex3fv(const GLfloat *pos) {
+    wine_glVertex4f(pos[0], pos[1], pos[2], 1.0);
+}
+
+static void wine_glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
+    WineD3DContext *ctx = getActiveContext();
+    ctx->color[0] = r;
+    ctx->color[1] = g;
+    ctx->color[2] = b;
+    ctx->color[3] = a;
+    old_fogcoord_glColor4f(r, g, b, a);
+}
+
+static void wine_glColor4fv(const GLfloat *c) {
+    wine_glColor4f(c[0], c[1], c[2], c[3]);
+}
+
+static void wine_glColor3f(GLfloat r, GLfloat g, GLfloat b) {
+    wine_glColor4f(r, g, b, 1.0);
+}
+
+static void wine_glColor3fv(const GLfloat *c) {
+    wine_glColor4f(c[0], c[1], c[2], 1.0);
+}
+
+static void wine_glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a) {
+    wine_glColor4f(r / 255.0, g / 255.0, b / 255.0, a / 255.0);
+}
+
+/* In D3D the fog coord is a UBYTE, so there's no problem with using the single
+ * precision function
+ */
+static void wine_glFogCoordfEXT(GLfloat f) {
+    WineD3DContext *ctx = getActiveContext();
+    ctx->fog_coord_value = f;
+}
+static void wine_glFogCoorddEXT(GLdouble f) {
+    wine_glFogCoordfEXT(f);
+}
+static void wine_glFogCoordfvEXT(const GLfloat *f) {
+    wine_glFogCoordfEXT(*f);
+}
+static void wine_glFogCoorddvEXT(const GLdouble *f) {
+    wine_glFogCoordfEXT(*f);
+}
+
+/* End GL_EXT_fog_coord emulation */
+
+#define GLINFO_LOCATION (*gl_info)
+void add_gl_compat_wrappers(WineD3D_GL_Info *gl_info) {
+    if(!GL_SUPPORT(ARB_MULTITEXTURE)) {
+        TRACE("Applying GL_ARB_multitexture emulation hooks\n");
+        gl_info->glActiveTextureARB         = wine_glActiveTextureARB;
+        gl_info->glClientActiveTextureARB   = wine_glClientActiveTextureARB;
+        gl_info->glMultiTexCoord1fARB       = wine_glMultiTexCoord1fARB;
+        gl_info->glMultiTexCoord1fvARB      = wine_glMultiTexCoord1fvARB;
+        gl_info->glMultiTexCoord2fARB       = wine_glMultiTexCoord2fARB;
+        gl_info->glMultiTexCoord2fvARB      = wine_glMultiTexCoord2fvARB;
+        gl_info->glMultiTexCoord3fARB       = wine_glMultiTexCoord3fARB;
+        gl_info->glMultiTexCoord3fvARB      = wine_glMultiTexCoord3fvARB;
+        gl_info->glMultiTexCoord4fARB       = wine_glMultiTexCoord4fARB;
+        gl_info->glMultiTexCoord4fvARB      = wine_glMultiTexCoord4fvARB;
+        gl_info->glMultiTexCoord2svARB      = wine_glMultiTexCoord2svARB;
+        gl_info->glMultiTexCoord4svARB      = wine_glMultiTexCoord4svARB;
+        if(old_multitex_glGetIntegerv) {
+            FIXME("GL_ARB_multitexture glGetIntegerv hook already applied\n");
+        } else {
+            old_multitex_glGetIntegerv = glGetIntegerv;
+            glGetIntegerv = wine_glGetIntegerv;
+        }
+        if(old_multitex_glGetFloatv) {
+            FIXME("GL_ARB_multitexture glGetGloatv hook already applied\n");
+        } else {
+            old_multitex_glGetFloatv = glGetFloatv;
+            glGetFloatv = wine_glGetFloatv;
+        }
+        if(old_multitex_glGetDoublev) {
+            FIXME("GL_ARB_multitexture glGetDoublev hook already applied\n");
+        } else {
+            old_multitex_glGetDoublev = glGetDoublev;
+            glGetDoublev = wine_glGetDoublev;
+        }
+        gl_info->supported[ARB_MULTITEXTURE] = TRUE;
+    }
+
+    if(!GL_SUPPORT(EXT_FOG_COORD)) {
+        /* This emulation isn't perfect. There are a number of potential problems, but they should
+         * not matter in practise:
+         *
+         * Fog vs fragment shader: If we are using GL_ARB_fragment_program with the fog option, the
+         * glDisable(GL_FOG) here won't matter. However, if we have GL_ARB_fragment_program, it is pretty
+         * unlikely that we don't have GL_EXT_fog_coord. Besides, we probably have GL_ARB_vertex_program
+         * too, which would allow fog coord emulation in a fixed function vertex pipeline replacement.
+         *
+         * Fog vs texture: We apply the fog in the vertex color. An app could set up texturing settings which
+         * ignore the vertex color, thus effectively disabing our fog. However, in D3D this type of fog is
+         * a per-vertex fog too, so the apps shouldn't do that.
+         *
+         * Fog vs lighting: The app could in theory use D3DFOG_NONE table and D3DFOG_NONE vertex fog with
+         * untransformed vertices. That enables lighting and fog coords at the same time, and the lighting
+         * calculations could affect the already blended in fog color. There's nothing we can do against that,
+         * but most apps using fog color do their own lighting too and often even use RHW vertices. So live
+         * with it.
+         */
+        TRACE("Applying GL_ARB_fog_coord emulation hooks\n");
+
+        /* This probably means that the implementation doesn't advertise the extension, but implicitly supports
+         * it via the GL core version, or someone messed around in the extension table in directx.c. Add version-
+         * dependent loading for this extension if we ever hit this situation
+         */
+        if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
+            FIXME("GL implementation supports GL_ARB_fragment_program but not GL_EXT_fog_coord\n");
+            FIXME("The fog coord emulation will most likely fail\n");
+        } else if(GL_SUPPORT(ARB_FRAGMENT_SHADER)) {
+            FIXME("GL implementation supports GL_ARB_fragment_shader but not GL_EXT_fog_coord\n");
+            FIXME("The fog coord emulation will most likely fail\n");
+        }
+
+        if(old_fogcoord_glFogi) {
+            FIXME("GL_EXT_fogcoord glFogi hook already applied\n");
+        } else {
+            old_fogcoord_glFogi = glFogi;
+            glFogi = wine_glFogi;
+        }
+        if(old_fogcoord_glFogiv) {
+            FIXME("GL_EXT_fogcoord glFogiv hook already applied\n");
+        } else {
+            old_fogcoord_glFogiv = glFogiv;
+            glFogiv = wine_glFogiv;
+        }
+        if(old_fogcoord_glFogf) {
+            FIXME("GL_EXT_fogcoord glFogf hook already applied\n");
+        } else {
+            old_fogcoord_glFogf = glFogf;
+            glFogf = wine_glFogf;
+        }
+        if(old_fogcoord_glFogfv) {
+            FIXME("GL_EXT_fogcoord glFogfv hook already applied\n");
+        } else {
+            old_fogcoord_glFogfv = glFogfv;
+            glFogfv = wine_glFogfv;
+        }
+        if(old_fogcoord_glEnable) {
+            FIXME("GL_EXT_fogcoord glEnable hook already applied\n");
+        } else {
+            old_fogcoord_glEnable = glEnableWINE;
+            glEnableWINE = wine_glEnable;
+        }
+        if(old_fogcoord_glDisable) {
+            FIXME("GL_EXT_fogcoord glDisable hook already applied\n");
+        } else {
+            old_fogcoord_glDisable = glDisableWINE;
+            glDisableWINE = wine_glDisable;
+        }
+
+        if(old_fogcoord_glVertex4f) {
+            FIXME("GL_EXT_fogcoord glVertex4f hook already applied\n");
+        } else {
+            old_fogcoord_glVertex4f = glVertex4f;
+            glVertex4f = wine_glVertex4f;
+        }
+        if(old_fogcoord_glVertex4fv) {
+            FIXME("GL_EXT_fogcoord glVertex4fv hook already applied\n");
+        } else {
+            old_fogcoord_glVertex4fv = glVertex4fv;
+            glVertex4fv = wine_glVertex4fv;
+        }
+        if(old_fogcoord_glVertex3f) {
+            FIXME("GL_EXT_fogcoord glVertex3f hook already applied\n");
+        } else {
+            old_fogcoord_glVertex3f = glVertex3f;
+            glVertex3f = wine_glVertex3f;
+        }
+        if(old_fogcoord_glVertex3fv) {
+            FIXME("GL_EXT_fogcoord glVertex3fv hook already applied\n");
+        } else {
+            old_fogcoord_glVertex3fv = glVertex3fv;
+            glVertex3fv = wine_glVertex3fv;
+        }
+
+        if(old_fogcoord_glColor4f) {
+            FIXME("GL_EXT_fogcoord glColor4f hook already applied\n");
+        } else {
+            old_fogcoord_glColor4f = glColor4f;
+            glColor4f = wine_glColor4f;
+        }
+        if(old_fogcoord_glColor4fv) {
+            FIXME("GL_EXT_fogcoord glColor4fv hook already applied\n");
+        } else {
+            old_fogcoord_glColor4fv = glColor4fv;
+            glColor4fv = wine_glColor4fv;
+        }
+        if(old_fogcoord_glColor3f) {
+            FIXME("GL_EXT_fogcoord glColor3f hook already applied\n");
+        } else {
+            old_fogcoord_glColor3f = glColor3f;
+            glColor3f = wine_glColor3f;
+        }
+        if(old_fogcoord_glColor3fv) {
+            FIXME("GL_EXT_fogcoord glColor3fv hook already applied\n");
+        } else {
+            old_fogcoord_glColor3fv = glColor3fv;
+            glColor3fv = wine_glColor3fv;
+        }
+        if(old_fogcoord_glColor4ub) {
+            FIXME("GL_EXT_fogcoord glColor4ub hook already applied\n");
+        } else {
+            old_fogcoord_glColor4ub = glColor4ub;
+            glColor4ub = wine_glColor4ub;
+        }
+
+        if(old_fogcoord_glFogCoordfEXT) {
+            FIXME("GL_EXT_fogcoord glFogCoordfEXT hook already applied\n");
+        } else {
+            old_fogcoord_glFogCoordfEXT = gl_info->glFogCoordfEXT;
+            gl_info->glFogCoordfEXT = wine_glFogCoordfEXT;
+        }
+        if(old_fogcoord_glFogCoordfvEXT) {
+            FIXME("GL_EXT_fogcoord glFogCoordfvEXT hook already applied\n");
+        } else {
+            old_fogcoord_glFogCoordfvEXT = gl_info->glFogCoordfvEXT;
+            gl_info->glFogCoordfvEXT = wine_glFogCoordfvEXT;
+        }
+        if(old_fogcoord_glFogCoorddEXT) {
+            FIXME("GL_EXT_fogcoord glFogCoorddEXT hook already applied\n");
+        } else {
+            old_fogcoord_glFogCoorddEXT = gl_info->glFogCoorddEXT;
+            gl_info->glFogCoorddEXT = wine_glFogCoorddEXT;
+        }
+        if(old_fogcoord_glFogCoorddvEXT) {
+            FIXME("GL_EXT_fogcoord glFogCoorddvEXT hook already applied\n");
+        } else {
+            old_fogcoord_glFogCoorddvEXT = gl_info->glFogCoorddvEXT;
+            gl_info->glFogCoorddvEXT = wine_glFogCoorddvEXT;
+        }
+        gl_info->supported[EXT_FOG_COORD] = TRUE;
+    }
+}
+#undef GLINFO_LOCATION
index 4c1d223..8dfb416 100644 (file)
@@ -29,6 +29,7 @@
  */
 
 #include "config.h"
+#include <limits.h>
 #include <stdio.h>
 #include "wined3d_private.h"
 
@@ -54,11 +55,35 @@ typedef struct {
     DWORD coord_mask;
 } glsl_sample_function_t;
 
+enum heap_node_op
+{
+    HEAP_NODE_TRAVERSE_LEFT,
+    HEAP_NODE_TRAVERSE_RIGHT,
+    HEAP_NODE_POP,
+};
+
+struct constant_entry
+{
+    unsigned int idx;
+    unsigned int version;
+};
+
+struct constant_heap
+{
+    struct constant_entry *entries;
+    unsigned int *positions;
+    unsigned int size;
+};
+
 /* GLSL shader private data */
 struct shader_glsl_priv {
     struct hash_table_t *glsl_program_lookup;
-    const struct glsl_shader_prog_link *glsl_program;
+    struct glsl_shader_prog_link *glsl_program;
+    struct constant_heap vconst_heap;
+    struct constant_heap pconst_heap;
+    unsigned char *stack;
     GLhandleARB depth_blt_program[tex_type_count];
+    UINT next_constant_version;
 };
 
 /* Struct to maintain data about a linked GLSL program */
@@ -79,6 +104,7 @@ struct glsl_shader_prog_link {
     GLhandleARB                 vshader;
     IWineD3DPixelShader         *pshader;
     struct ps_compile_args      ps_args;
+    UINT                        constant_version;
 };
 
 typedef struct {
@@ -96,19 +122,23 @@ static void print_glsl_info_log(const WineD3D_GL_Info *gl_info, GLhandleARB obj)
     unsigned int i;
     BOOL is_spam;
 
-    const char *spam[] = {
+    static const char * const spam[] =
+    {
         "Vertex shader was successfully compiled to run on hardware.\n",    /* fglrx          */
         "Fragment shader was successfully compiled to run on hardware.\n",  /* fglrx          */
         "Fragment shader(s) linked, vertex shader(s) linked. \n ",          /* fglrx, with \n */
         "Fragment shader(s) linked, vertex shader(s) linked.",              /* fglrx, no \n   */
         "Vertex shader(s) linked, no fragment shader(s) defined. \n ",      /* fglrx, with \n */
         "Vertex shader(s) linked, no fragment shader(s) defined.",          /* fglrx, no \n   */
-        "Fragment shader was successfully compiled to run on hardware.\nWARNING: 0:1: extension 'GL_ARB_draw_buffers' is not supported",
+        "Fragment shader was successfully compiled to run on hardware.\n"
+        "WARNING: 0:2: extension 'GL_ARB_draw_buffers' is not supported",
         "Fragment shader(s) linked, no vertex shader(s) defined.",          /* fglrx, no \n   */
         "Fragment shader(s) linked, no vertex shader(s) defined. \n ",      /* fglrx, with \n */
         "WARNING: 0:2: extension 'GL_ARB_draw_buffers' is not supported\n"  /* MacOS ati      */
     };
 
+    if (!TRACE_ON(d3d_shader) && !FIXME_ON(d3d_shader)) return;
+
     GL_EXTCALL(glGetObjectParameterivARB(obj,
                GL_OBJECT_INFO_LOG_LENGTH_ARB,
                &infologLength));
@@ -188,106 +218,166 @@ static void shader_glsl_load_vsamplers(const WineD3D_GL_Info *gl_info, IWineD3DS
     }
 }
 
-/** 
- * Loads floating point constants (aka uniforms) into the currently set GLSL program.
- * When constant_list == NULL, it will load all the constants.
- */
-static void shader_glsl_load_constantsF(IWineD3DBaseShaderImpl *This, const WineD3D_GL_Info *gl_info,
-        unsigned int max_constants, const float *constants, const GLhandleARB *constant_locations,
-        const struct list *constant_list)
+static inline void walk_constant_heap(const WineD3D_GL_Info *gl_info, const float *constants,
+        const GLhandleARB *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version)
 {
-    const constants_entry *constant;
-    const local_constant *lconst;
-    GLhandleARB tmp_loc;
-    DWORD i, j, k;
-    const DWORD *idx;
-
-    if (TRACE_ON(d3d_shader)) {
-        LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) {
-            idx = constant->idx;
-            j = constant->count;
-            while (j--) {
-                i = *idx++;
-                tmp_loc = constant_locations[i];
-                if (tmp_loc != -1) {
-                    TRACE_(d3d_constants)("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]);
+    int stack_idx = 0;
+    unsigned int heap_idx = 1;
+    unsigned int idx;
+
+    if (heap->entries[heap_idx].version <= version) return;
+
+    idx = heap->entries[heap_idx].idx;
+    if (constant_locations[idx] != -1) GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4]));
+    stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+
+    while (stack_idx >= 0)
+    {
+        /* Note that we fall through to the next case statement. */
+        switch(stack[stack_idx])
+        {
+            case HEAP_NODE_TRAVERSE_LEFT:
+            {
+                unsigned int left_idx = heap_idx << 1;
+                if (left_idx < heap->size && heap->entries[left_idx].version > version)
+                {
+                    heap_idx = left_idx;
+                    idx = heap->entries[heap_idx].idx;
+                    if (constant_locations[idx] != -1)
+                        GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4]));
+
+                    stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT;
+                    stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+                    break;
                 }
             }
+
+            case HEAP_NODE_TRAVERSE_RIGHT:
+            {
+                unsigned int right_idx = (heap_idx << 1) + 1;
+                if (right_idx < heap->size && heap->entries[right_idx].version > version)
+                {
+                    heap_idx = right_idx;
+                    idx = heap->entries[heap_idx].idx;
+                    if (constant_locations[idx] != -1)
+                        GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4]));
+
+                    stack[stack_idx++] = HEAP_NODE_POP;
+                    stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+                    break;
+                }
+            }
+
+            case HEAP_NODE_POP:
+            {
+                heap_idx >>= 1;
+                --stack_idx;
+                break;
+            }
         }
     }
+    checkGLcall("walk_constant_heap()");
+}
 
-    /* 1.X pshaders have the constants clamped to [-1;1] implicitly. */
-    if(WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1 &&
-       shader_is_pshader_version(This->baseShader.hex_version)) {
-        float lcl_const[4];
-
-        LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) {
-            idx = constant->idx;
-            j = constant->count;
-            while (j--) {
-                i = *idx++;
-                tmp_loc = constant_locations[i];
-                if (tmp_loc != -1) {
-                    /* We found this uniform name in the program - go ahead and send the data */
-                    k = i * 4;
-                    if(constants[k + 0] < -1.0) lcl_const[0] = -1.0;
-                    else if(constants[k + 0] > 1.0) lcl_const[0] = 1.0;
-                    else lcl_const[0] = constants[k + 0];
-                    if(constants[k + 1] < -1.0) lcl_const[1] = -1.0;
-                    else if(constants[k + 1] > 1.0) lcl_const[1] = 1.0;
-                    else lcl_const[1] = constants[k + 1];
-                    if(constants[k + 2] < -1.0) lcl_const[2] = -1.0;
-                    else if(constants[k + 2] > 1.0) lcl_const[2] = 1.0;
-                    else lcl_const[2] = constants[k + 2];
-                    if(constants[k + 3] < -1.0) lcl_const[3] = -1.0;
-                    else if(constants[k + 3] > 1.0) lcl_const[3] = 1.0;
-                    else lcl_const[3] = constants[k + 3];
-
-                    GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, lcl_const));
+static inline void apply_clamped_constant(const WineD3D_GL_Info *gl_info, GLint location, const GLfloat *data)
+{
+    GLfloat clamped_constant[4];
+
+    if (location == -1) return;
+
+    clamped_constant[0] = data[0] < -1.0f ? -1.0f : data[0] > 1.0 ? 1.0 : data[0];
+    clamped_constant[1] = data[1] < -1.0f ? -1.0f : data[1] > 1.0 ? 1.0 : data[1];
+    clamped_constant[2] = data[2] < -1.0f ? -1.0f : data[2] > 1.0 ? 1.0 : data[2];
+    clamped_constant[3] = data[3] < -1.0f ? -1.0f : data[3] > 1.0 ? 1.0 : data[3];
+
+    GL_EXTCALL(glUniform4fvARB(location, 1, clamped_constant));
+}
+
+static inline void walk_constant_heap_clamped(const WineD3D_GL_Info *gl_info, const float *constants,
+        const GLhandleARB *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version)
+{
+    int stack_idx = 0;
+    unsigned int heap_idx = 1;
+    unsigned int idx;
+
+    if (heap->entries[heap_idx].version <= version) return;
+
+    idx = heap->entries[heap_idx].idx;
+    apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx * 4]);
+    stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+
+    while (stack_idx >= 0)
+    {
+        /* Note that we fall through to the next case statement. */
+        switch(stack[stack_idx])
+        {
+            case HEAP_NODE_TRAVERSE_LEFT:
+            {
+                unsigned int left_idx = heap_idx << 1;
+                if (left_idx < heap->size && heap->entries[left_idx].version > version)
+                {
+                    heap_idx = left_idx;
+                    idx = heap->entries[heap_idx].idx;
+                    apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx * 4]);
+
+                    stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT;
+                    stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+                    break;
                 }
             }
-        }
-    } else {
-        LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) {
-            idx = constant->idx;
-            j = constant->count;
-            while (j--) {
-                i = *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)));
+
+            case HEAP_NODE_TRAVERSE_RIGHT:
+            {
+                unsigned int right_idx = (heap_idx << 1) + 1;
+                if (right_idx < heap->size && heap->entries[right_idx].version > version)
+                {
+                    heap_idx = right_idx;
+                    idx = heap->entries[heap_idx].idx;
+                    apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx * 4]);
+
+                    stack[stack_idx++] = HEAP_NODE_POP;
+                    stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+                    break;
                 }
             }
+
+            case HEAP_NODE_POP:
+            {
+                heap_idx >>= 1;
+                --stack_idx;
+                break;
+            }
         }
     }
-    checkGLcall("glUniform4fvARB()");
+    checkGLcall("walk_constant_heap_clamped()");
+}
 
-    if(!This->baseShader.load_local_constsF) {
+/* Loads floating point constants (aka uniforms) into the currently set GLSL program. */
+static void shader_glsl_load_constantsF(IWineD3DBaseShaderImpl *This, const WineD3D_GL_Info *gl_info,
+        const float *constants, const GLhandleARB *constant_locations, const struct constant_heap *heap,
+        unsigned char *stack, UINT version)
+{
+    const local_constant *lconst;
+
+    /* 1.X pshaders have the constants clamped to [-1;1] implicitly. */
+    if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.reg_maps.shader_version) == 1
+            && shader_is_pshader_version(This->baseShader.reg_maps.shader_version))
+        walk_constant_heap_clamped(gl_info, constants, constant_locations, heap, stack, version);
+    else
+        walk_constant_heap(gl_info, constants, constant_locations, heap, stack, version);
+
+    if (!This->baseShader.load_local_constsF)
+    {
         TRACE("No need to load local float constants for this shader\n");
         return;
     }
 
-    /* Load immediate constants */
-    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) {
-                const GLfloat *values = (const GLfloat *)lconst->value;
-                TRACE_(d3d_constants)("Loading local constants %i: %f, %f, %f, %f\n", lconst->idx,
-                        values[0], values[1], values[2], values[3]);
-            }
-        }
-    }
     /* Immediate constants are clamped to [-1;1] at shader creation time if needed */
-    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, (const GLfloat *)lconst->value));
-        }
+    LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry)
+    {
+        GLhandleARB location = constant_locations[lconst->idx];
+        /* We found this uniform name in the program - go ahead and send the data */
+        if (location != -1) GL_EXTCALL(glUniform4fvARB(location, 1, (const GLfloat *)lconst->value));
     }
     checkGLcall("glUniform4fvARB()");
 }
@@ -335,7 +425,7 @@ static void shader_glsl_load_constantsB(IWineD3DBaseShaderImpl *This, const Wine
     GLhandleARB tmp_loc;
     unsigned int i;
     char tmp_name[8];
-    char is_pshader = shader_is_pshader_version(This->baseShader.hex_version);
+    char is_pshader = shader_is_pshader_version(This->baseShader.reg_maps.shader_version);
     const char* prefix = is_pshader? "PB":"VB";
     struct list* ptr;
 
@@ -379,7 +469,11 @@ static void shader_glsl_load_constantsB(IWineD3DBaseShaderImpl *This, const Wine
     }
 }
 
-
+static void reset_program_constant_version(void *value, void *context)
+{
+    struct glsl_shader_prog_link *entry = (struct glsl_shader_prog_link *)value;
+    entry->constant_version = 0;
+}
 
 /**
  * Loads the app-supplied constants into the currently set GLSL program.
@@ -390,14 +484,13 @@ static void shader_glsl_load_constants(
     char useVertexShader) {
    
     IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) device;
-    const struct shader_glsl_priv *priv = (struct shader_glsl_priv *)deviceImpl->shader_priv;
+    struct shader_glsl_priv *priv = (struct shader_glsl_priv *)deviceImpl->shader_priv;
     IWineD3DStateBlockImpl* stateBlock = deviceImpl->stateBlock;
     const WineD3D_GL_Info *gl_info = &deviceImpl->adapter->gl_info;
 
-    const GLhandleARB *constant_locations;
-    const struct list *constant_list;
     GLhandleARB programId;
-    const struct glsl_shader_prog_link *prog = priv->glsl_program;
+    struct glsl_shader_prog_link *prog = priv->glsl_program;
+    UINT constant_version;
     int i;
 
     if (!prog) {
@@ -405,24 +498,26 @@ static void shader_glsl_load_constants(
         return;
     }
     programId = prog->programId;
+    constant_version = prog->constant_version;
 
     if (useVertexShader) {
         IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader;
 
-        constant_locations = prog->vuniformF_locations;
-        constant_list = &stateBlock->set_vconstantsF;
-
         /* Load DirectX 9 float constants/uniforms for vertex shader */
-        shader_glsl_load_constantsF(vshader, gl_info, GL_LIMITS(vshader_constantsF),
-                stateBlock->vertexShaderConstantF, constant_locations, constant_list);
+        shader_glsl_load_constantsF(vshader, gl_info, stateBlock->vertexShaderConstantF,
+                prog->vuniformF_locations, &priv->vconst_heap, priv->stack, constant_version);
 
         /* Load DirectX 9 integer constants/uniforms for vertex shader */
-        shader_glsl_load_constantsI(vshader, gl_info, prog->vuniformI_locations,
-                stateBlock->vertexShaderConstantI, stateBlock->changed.vertexShaderConstantsI);
+        if(vshader->baseShader.uses_int_consts) {
+            shader_glsl_load_constantsI(vshader, gl_info, prog->vuniformI_locations,
+                    stateBlock->vertexShaderConstantI, stateBlock->changed.vertexShaderConstantsI);
+        }
 
         /* Load DirectX 9 boolean constants/uniforms for vertex shader */
-        shader_glsl_load_constantsB(vshader, gl_info, programId,
-                stateBlock->vertexShaderConstantB, stateBlock->changed.vertexShaderConstantsB);
+        if(vshader->baseShader.uses_bool_consts) {
+            shader_glsl_load_constantsB(vshader, gl_info, programId,
+                    stateBlock->vertexShaderConstantB, stateBlock->changed.vertexShaderConstantsB);
+        }
 
         /* Upload the position fixup params */
         GL_EXTCALL(glUniform4fvARB(prog->posFixup_location, 1, &deviceImpl->posFixup[0]));
@@ -433,20 +528,21 @@ static void shader_glsl_load_constants(
 
         IWineD3DBaseShaderImpl* pshader = (IWineD3DBaseShaderImpl*) stateBlock->pixelShader;
 
-        constant_locations = prog->puniformF_locations;
-        constant_list = &stateBlock->set_pconstantsF;
-
         /* Load DirectX 9 float constants/uniforms for pixel shader */
-        shader_glsl_load_constantsF(pshader, gl_info, GL_LIMITS(pshader_constantsF),
-                stateBlock->pixelShaderConstantF, constant_locations, constant_list);
+        shader_glsl_load_constantsF(pshader, gl_info, stateBlock->pixelShaderConstantF,
+                prog->puniformF_locations, &priv->pconst_heap, priv->stack, constant_version);
 
         /* Load DirectX 9 integer constants/uniforms for pixel shader */
-        shader_glsl_load_constantsI(pshader, gl_info, prog->puniformI_locations,
-                stateBlock->pixelShaderConstantI, stateBlock->changed.pixelShaderConstantsI);
+        if(pshader->baseShader.uses_int_consts) {
+            shader_glsl_load_constantsI(pshader, gl_info, prog->puniformI_locations,
+                    stateBlock->pixelShaderConstantI, stateBlock->changed.pixelShaderConstantsI);
+        }
 
         /* Load DirectX 9 boolean constants/uniforms for pixel shader */
-        shader_glsl_load_constantsB(pshader, gl_info, programId,
-                stateBlock->pixelShaderConstantB, stateBlock->changed.pixelShaderConstantsB);
+        if(pshader->baseShader.uses_bool_consts) {
+            shader_glsl_load_constantsB(pshader, gl_info, programId,
+                    stateBlock->pixelShaderConstantB, stateBlock->changed.pixelShaderConstantsB);
+        }
 
         /* Upload the environment bump map matrix if needed. The needsbumpmat member specifies the texture stage to load the matrix from.
          * It can't be 0 for a valid texbem instruction.
@@ -486,19 +582,87 @@ static void shader_glsl_load_constants(
             GL_EXTCALL(glUniform4fvARB(prog->ycorrection_location, 1, correction_params));
         }
     }
+
+    if (priv->next_constant_version == UINT_MAX)
+    {
+        TRACE("Max constant version reached, resetting to 0.\n");
+        hash_table_for_each_entry(priv->glsl_program_lookup, reset_program_constant_version, NULL);
+        priv->next_constant_version = 1;
+    }
+    else
+    {
+        prog->constant_version = priv->next_constant_version++;
+    }
+}
+
+static inline void update_heap_entry(struct constant_heap *heap, unsigned int idx,
+        unsigned int heap_idx, DWORD new_version)
+{
+    struct constant_entry *entries = heap->entries;
+    unsigned int *positions = heap->positions;
+    unsigned int parent_idx;
+
+    while (heap_idx > 1)
+    {
+        parent_idx = heap_idx >> 1;
+
+        if (new_version <= entries[parent_idx].version) break;
+
+        entries[heap_idx] = entries[parent_idx];
+        positions[entries[parent_idx].idx] = heap_idx;
+        heap_idx = parent_idx;
+    }
+
+    entries[heap_idx].version = new_version;
+    entries[heap_idx].idx = idx;
+    positions[idx] = heap_idx;
+}
+
+static void shader_glsl_update_float_vertex_constants(IWineD3DDevice *iface, UINT start, UINT count)
+{
+    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+    struct shader_glsl_priv *priv = (struct shader_glsl_priv *)This->shader_priv;
+    struct constant_heap *heap = &priv->vconst_heap;
+    UINT i;
+
+    for (i = start; i < count + start; ++i)
+    {
+        if (!This->stateBlock->changed.vertexShaderConstantsF[i])
+            update_heap_entry(heap, i, heap->size++, priv->next_constant_version);
+        else
+            update_heap_entry(heap, i, heap->positions[i], priv->next_constant_version);
+    }
+}
+
+static void shader_glsl_update_float_pixel_constants(IWineD3DDevice *iface, UINT start, UINT count)
+{
+    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+    struct shader_glsl_priv *priv = (struct shader_glsl_priv *)This->shader_priv;
+    struct constant_heap *heap = &priv->pconst_heap;
+    UINT i;
+
+    for (i = start; i < count + start; ++i)
+    {
+        if (!This->stateBlock->changed.pixelShaderConstantsF[i])
+            update_heap_entry(heap, i, heap->size++, priv->next_constant_version);
+        else
+            update_heap_entry(heap, i, heap->positions[i], priv->next_constant_version);
+    }
 }
 
 /** Generate the variable & register declarations for the GLSL output target */
 static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const shader_reg_maps *reg_maps,
-        SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_info)
+        SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_info,
+        const struct ps_compile_args *ps_args)
 {
     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device;
+    DWORD shader_version = reg_maps->shader_version;
     unsigned int i, extra_constants_needed = 0;
     const local_constant *lconst;
 
     /* There are some minor differences between pixel and vertex shaders */
-    char pshader = shader_is_pshader_version(This->baseShader.hex_version);
+    char pshader = shader_is_pshader_version(shader_version);
     char prefix = pshader ? 'P' : 'V';
 
     /* Prototype the subroutines */
@@ -532,7 +696,8 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s
          * out. The nvidia driver only does that if the parameter is inout instead of out, hence the
          * inout.
          */
-        if(This->baseShader.hex_version >= WINED3DVS_VERSION(3, 0)) {
+        if (shader_version >= WINED3DVS_VERSION(3, 0))
+        {
             shader_addline(buffer, "void order_ps_input(in vec4[%u]);\n", MAX_REG_OUTPUT);
         } else {
             shader_addline(buffer, "void order_ps_input();\n");
@@ -562,7 +727,7 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s
             ps_impl->numbumpenvmatconsts++;
         }
 
-        if(device->stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE]) {
+        if(ps_args->srgb_correction) {
             shader_addline(buffer, "const vec4 srgb_mul_low = vec4(%f, %f, %f, %f);\n",
                             srgb_mul_low, srgb_mul_low, srgb_mul_low, srgb_mul_low);
             shader_addline(buffer, "const vec4 srgb_comparison = vec4(%f, %f, %f, %f);\n",
@@ -633,8 +798,10 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s
     /* Declare input register varyings. Only pixel shader, vertex shaders have that declared in the
      * helper function shader that is linked in at link time
      */
-    if(pshader && This->baseShader.hex_version >= WINED3DPS_VERSION(3, 0)) {
-        if(use_vs(device)) {
+    if (pshader && shader_version >= WINED3DPS_VERSION(3, 0))
+    {
+        if (use_vs(device->stateBlock))
+        {
             shader_addline(buffer, "varying vec4 IN[%u];\n", GL_LIMITS(glsl_varyings) / 4);
         } else {
             /* TODO: Write a replacement shader for the fixed function vertex pipeline, so this isn't needed.
@@ -803,8 +970,8 @@ static void shader_glsl_get_register_name(const DWORD param, const DWORD addr_to
     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) arg->shader;
     IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
     const WineD3D_GL_Info* gl_info = &deviceImpl->adapter->gl_info;
-
-    char pshader = shader_is_pshader_version(This->baseShader.hex_version);
+    DWORD shader_version = This->baseShader.reg_maps.shader_version;
+    char pshader = shader_is_pshader_version(shader_version);
     char tmpStr[150];
 
     *is_color = FALSE;   
@@ -816,7 +983,8 @@ static void shader_glsl_get_register_name(const DWORD param, const DWORD addr_to
     case WINED3DSPR_INPUT:
         if (pshader) {
             /* Pixel shaders >= 3.0 */
-            if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 3) {
+            if (WINED3DSHADER_VERSION_MAJOR(shader_version) >= 3)
+            {
                 DWORD in_count = GL_LIMITS(glsl_varyings) / 4;
 
                 if (param & WINED3DSHADER_ADDRMODE_RELATIVE) {
@@ -862,8 +1030,7 @@ static void shader_glsl_get_register_name(const DWORD param, const DWORD addr_to
                     strcpy(tmpStr, "gl_SecondaryColor");
             }
         } else {
-            if (vshader_input_is_color((IWineD3DVertexShader*) This, reg))
-               *is_color = TRUE;
+            if (((IWineD3DVertexShaderImpl *)This)->swizzle_map & (1 << reg)) *is_color = TRUE;
             sprintf(tmpStr, "attrib%u", reg);
         } 
         break;
@@ -876,7 +1043,8 @@ static void shader_glsl_get_register_name(const DWORD param, const DWORD addr_to
 
            /* Relative addressing on shaders 2.0+ have a relative address token, 
             * prior to that, it was hard-coded as "A0.x" because there's only 1 register */
-           if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 2)  {
+           if (WINED3DSHADER_VERSION_MAJOR(shader_version) >= 2)
+           {
                glsl_src_param_t rel_param;
                shader_glsl_add_src_param(arg, addr_token, 0, WINED3DSP_WRITEMASK_0, &rel_param);
                if(reg) {
@@ -955,10 +1123,8 @@ static void shader_glsl_get_register_name(const DWORD param, const DWORD addr_to
     break;
     case WINED3DSPR_TEXCRDOUT:
         /* Vertex shaders >= 3.0: WINED3DSPR_OUTPUT */
-        if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 3)
-            sprintf(tmpStr, "OUT[%u]", reg);
-        else
-            sprintf(tmpStr, "gl_TexCoord[%u]", reg);
+        if (WINED3DSHADER_VERSION_MAJOR(shader_version) >= 3) sprintf(tmpStr, "OUT[%u]", reg);
+        else sprintf(tmpStr, "gl_TexCoord[%u]", reg);
     break;
     case WINED3DSPR_MISCTYPE:
         if (reg == 0) {
@@ -1307,7 +1473,6 @@ static void shader_glsl_arith(const SHADER_OPCODE_ARG *arg)
 /* Process the WINED3DSIO_MOV opcode using GLSL (dst = src) */
 static void shader_glsl_mov(const SHADER_OPCODE_ARG *arg)
 {
-    IWineD3DBaseShaderImpl* shader = (IWineD3DBaseShaderImpl*) arg->shader;
     SHADER_BUFFER* buffer = arg->buffer;
     glsl_src_param_t src0_param;
     DWORD write_mask;
@@ -1317,9 +1482,10 @@ static void shader_glsl_mov(const SHADER_OPCODE_ARG *arg)
 
     /* In vs_1_1 WINED3DSIO_MOV can write to the address register. In later
      * shader versions WINED3DSIO_MOVA is used for this. */
-    if ((WINED3DSHADER_VERSION_MAJOR(shader->baseShader.hex_version) == 1 &&
-            !shader_is_pshader_version(shader->baseShader.hex_version) &&
-            shader_get_regtype(arg->dst) == WINED3DSPR_ADDR)) {
+    if ((WINED3DSHADER_VERSION_MAJOR(arg->reg_maps->shader_version) == 1
+            && !shader_is_pshader_version(arg->reg_maps->shader_version)
+            && shader_get_regtype(arg->dst) == WINED3DSPR_ADDR))
+    {
         /* This is a simple floor() */
         unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask);
         if (mask_size > 1) {
@@ -1487,12 +1653,12 @@ static void shader_glsl_map2gl(const SHADER_OPCODE_ARG *arg)
  */
 static void shader_glsl_expp(const SHADER_OPCODE_ARG *arg)
 {
-    IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)arg->shader;
     glsl_src_param_t src_param;
 
     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src_param);
 
-    if (shader->baseShader.hex_version < WINED3DPS_VERSION(2,0)) {
+    if (arg->reg_maps->shader_version < WINED3DPS_VERSION(2,0))
+    {
         char dst_mask[6];
 
         shader_addline(arg->buffer, "tmp0.x = exp2(floor(%s));\n", src_param.param_str);
@@ -1683,14 +1849,14 @@ static void shader_glsl_cmp(const SHADER_OPCODE_ARG *arg)
  * the compare is done per component of src0. */
 static void shader_glsl_cnd(const SHADER_OPCODE_ARG *arg)
 {
-    IWineD3DBaseShaderImpl* shader = (IWineD3DBaseShaderImpl*) arg->shader;
     glsl_src_param_t src0_param;
     glsl_src_param_t src1_param;
     glsl_src_param_t src2_param;
     DWORD write_mask, cmp_channel = 0;
     unsigned int i, j;
 
-    if (shader->baseShader.hex_version < WINED3DPS_VERSION(1, 4)) {
+    if (arg->reg_maps->shader_version < WINED3DPS_VERSION(1, 4))
+    {
         write_mask = shader_glsl_append_dst(arg->buffer, arg);
         shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
         shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], write_mask, &src1_param);
@@ -1749,7 +1915,7 @@ static void shader_glsl_mnxn(const SHADER_OPCODE_ARG *arg)
 {
     IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)arg->shader;
     const SHADER_OPCODE *opcode_table = shader->baseShader.shader_ins;
-    DWORD shader_version = shader->baseShader.hex_version;
+    DWORD shader_version = arg->reg_maps->shader_version;
     int i;
     int nComponents = 0;
     SHADER_OPCODE_ARG tmpArg;
@@ -2085,7 +2251,7 @@ static void pshader_glsl_tex(const SHADER_OPCODE_ARG *arg)
 {
     IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
     IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
-    DWORD hex_version = This->baseShader.hex_version;
+    DWORD shader_version = arg->reg_maps->shader_version;
     char dst_swizzle[6];
     glsl_sample_function_t sample_function;
     DWORD sampler_type;
@@ -2098,14 +2264,12 @@ static void pshader_glsl_tex(const SHADER_OPCODE_ARG *arg)
 
     /* 1.0-1.4: Use destination register as sampler source.
      * 2.0+: Use provided sampler source. */
-    if (hex_version < WINED3DPS_VERSION(2,0)) {
-        sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
-    } else {
-        sampler_idx = arg->src[1] & WINED3DSP_REGNUM_MASK;
-    }
+    if (shader_version < WINED3DPS_VERSION(2,0)) sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
+    else sampler_idx = arg->src[1] & WINED3DSP_REGNUM_MASK;
     sampler_type = arg->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK;
 
-    if (hex_version < WINED3DPS_VERSION(1,4)) {
+    if (shader_version < WINED3DPS_VERSION(1,4))
+    {
         DWORD flags = deviceImpl->stateBlock->textureState[sampler_idx][WINED3DTSS_TEXTURETRANSFORMFLAGS];
 
         /* Projected cube textures don't make a lot of sense, the resulting coordinates stay the same. */
@@ -2121,7 +2285,9 @@ static void pshader_glsl_tex(const SHADER_OPCODE_ARG *arg)
         } else {
             projected = FALSE;
         }
-    } else if (hex_version < WINED3DPS_VERSION(2,0)) {
+    }
+    else if (shader_version < WINED3DPS_VERSION(2,0))
+    {
         DWORD src_mod = arg->src[0] & WINED3DSP_SRCMOD_MASK;
 
         if (src_mod == WINED3DSPSM_DZ) {
@@ -2151,15 +2317,13 @@ static void pshader_glsl_tex(const SHADER_OPCODE_ARG *arg)
     shader_glsl_get_sample_function(sampler_type, projected, texrect, &sample_function);
     mask |= sample_function.coord_mask;