Stefan Dösinger : wined3d: Implement texbem in arb, improve it in glsl.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Feb 15 05:27:58 CST 2007


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

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Thu Feb 15 03:00:57 2007 +0100

wined3d: Implement texbem in arb, improve it in glsl.

---

 dlls/wined3d/arb_program_shader.c |   53 ++++++++++++++++++++++++++++++++++++-
 dlls/wined3d/glsl_shader.c        |   47 ++++++++++++++++++++++++++++----
 2 files changed, 93 insertions(+), 7 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 86e8430..4742447 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -119,6 +119,15 @@ void shader_arb_load_constants(
                                    GL_LIMITS(pshader_constantsF),
                                    stateBlock->pixelShaderConstantF,
                                    &stateBlock->set_pconstantsF);
+        if(((IWineD3DPixelShaderImpl *) pshader)->bumpenvmatconst) {
+            /* needsbumpmat stores the stage number from where to load the matrix. bumpenvmatconst stores the
+             * number of the constant to load the matrix into.
+             * The state manager takes care that this function is always called if the bump env matrix changes
+             */
+            IWineD3DPixelShaderImpl *psi = (IWineD3DPixelShaderImpl *) pshader;
+            float *data = (float *) &stateBlock->textureState[(int) psi->needsbumpmat][WINED3DTSS_BUMPENVMAT00];
+            GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->bumpenvmatconst, data));
+        }
     }
 }
 
@@ -159,6 +168,19 @@ void shader_generate_arb_declarations(
             shader_addline(buffer, "MOV T%u, fragment.texcoord[%u];\n", i, i);
     }
 
+    if(reg_maps->bumpmat /* Only  a pshader can use texbem */) {
+        /* If the shader does not use all available constants, use the next free constant to load the bump mapping environment matrix from
+         * the stateblock into the shader. If no constant is available don't load, texbem will then just sample the texture without applying
+         * bump mapping.
+         */
+        if(max_constantsF < GL_LIMITS(pshader_constantsF)) {
+            ((IWineD3DPixelShaderImpl *)This)->bumpenvmatconst = max_constantsF;
+            shader_addline(buffer, "PARAM bumpenvmat = program.env[%d];\n", ((IWineD3DPixelShaderImpl *)This)->bumpenvmatconst);
+        } else {
+            FIXME("No free constant found to load environemnt bump mapping matrix into the shader. texbem instruction will not apply bump mapping\n");
+        }
+    }
+
     /* Need to PARAM the environment parameters (constants) so we can use relative addressing */
     shader_addline(buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
                    max_constantsF, max_constantsF - 1);
@@ -662,7 +684,7 @@ void pshader_hw_texreg2gb(SHADER_OPCODE_ARG* arg) {
 }
 
 void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) {
-
+#if 0
      SHADER_BUFFER* buffer = arg->buffer;
      DWORD reg1 = arg->dst  & WINED3DSP_REGNUM_MASK;
      DWORD reg2 = arg->src[0] & WINED3DSP_REGNUM_MASK;
@@ -672,6 +694,35 @@ void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) {
      sprintf(dst_str, "T%u", reg1);
      shader_addline(buffer, "ADD TMP.rg, fragment.texcoord[%u], T%u;\n", reg1, reg2);
      shader_hw_sample(arg, reg1, dst_str, "TMP");
+#endif
+    IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
+
+    DWORD dst = arg->dst;
+    DWORD src = arg->src[0] & WINED3DSP_REGNUM_MASK;
+    SHADER_BUFFER* buffer = arg->buffer;
+
+    char reg_coord[40];
+    DWORD reg_dest_code;
+
+    /* All versions have a destination register */
+    reg_dest_code = dst & WINED3DSP_REGNUM_MASK;
+    /* Can directly use the name because texbem is only valid for <= 1.3 shaders */
+    pshader_get_register_name(dst, reg_coord);
+
+    if(This->bumpenvmatconst) {
+        /*shader_addline(buffer, "MOV T%u, fragment.texcoord[%u];\n", 1, 1); Not needed - done already */
+        shader_addline(buffer, "SWZ TMP2, bumpenvmat, x, z, 0, 0;\n");
+        shader_addline(buffer, "DP3 TMP.r, TMP2, T%u;\n", src);
+        shader_addline(buffer, "SWZ TMP2, bumpenvmat, y, w, 0, 0;\n");
+        shader_addline(buffer, "DP3 TMP.g, TMP2, T%u;\n", src);
+        shader_addline(buffer, "ADD TMP.rg, TMP, %s;\n", reg_coord);
+        /* Not sure about this, but hl2 needs it. It uses a projected texture with texbem and depends on the 4th coordinate */
+        shader_addline(buffer, "MOV TMP.a, %s;\n", reg_coord);
+        shader_hw_sample(arg, reg_dest_code, reg_coord, "TMP");
+    } else {
+        /* Without a bump matrix loaded, just sample with the unmodified coordinates */
+        shader_hw_sample(arg, reg_dest_code, reg_coord, reg_coord);
+    }
 }
 
 void pshader_hw_texm3x2pad(SHADER_OPCODE_ARG* arg) {
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 566442b..f270af7 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -1767,15 +1767,50 @@ void pshader_glsl_texm3x3vspec(SHADER_OPCODE_ARG* arg) {
 
 /** Process the WINED3DSIO_TEXBEM instruction in GLSL.
  * Apply a fake bump map transform.
- * FIXME: Should apply the BUMPMAPENV matrix.  For now, just sample the texture */
+ * texbem is pshader <= 1.3 only, this saves a few version checks
+ */
 void pshader_glsl_texbem(SHADER_OPCODE_ARG* arg) {
+    IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
+    IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
+    char dst_swizzle[6];
+    glsl_sample_function_t sample_function;
+    DWORD sampler_type;
+    DWORD sampler_idx;
+    BOOL projected;
+    DWORD mask = 0;
+    DWORD flags;
+    char coord_mask[6];
+
+    /* All versions have a destination register */
+    shader_glsl_append_dst(arg->buffer, arg);
+
+    sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
+    flags = deviceImpl->stateBlock->textureState[sampler_idx][WINED3DTSS_TEXTURETRANSFORMFLAGS];
+
+    /* TODO: Does texbem even support projected textures? half-life 2 uses it */
+    if (flags & WINED3DTTFF_PROJECTED) {
+        projected = TRUE;
+        switch (flags & ~WINED3DTTFF_PROJECTED) {
+            case WINED3DTTFF_COUNT1: FIXME("WINED3DTTFF_PROJECTED with WINED3DTTFF_COUNT1?\n"); break;
+            case WINED3DTTFF_COUNT2: mask = WINED3DSP_WRITEMASK_1; break;
+            case WINED3DTTFF_COUNT3: mask = WINED3DSP_WRITEMASK_2; break;
+            case WINED3DTTFF_COUNT4:
+            case WINED3DTTFF_DISABLE: mask = WINED3DSP_WRITEMASK_3; break;
+        }
+    } else {
+        projected = FALSE;
+    }
+
+    sampler_type = arg->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK;
+    shader_glsl_get_sample_function(sampler_type, projected, &sample_function);
+    mask |= sample_function.coord_mask;
 
-    DWORD reg1 = arg->dst & WINED3DSP_REGNUM_MASK;
-    DWORD reg2 = arg->src[0] & WINED3DSP_REGNUM_MASK;
+    shader_glsl_get_write_mask(arg->dst, dst_swizzle);
 
-    FIXME("Not applying the BUMPMAPENV matrix for pixel shader instruction texbem.\n");
-    shader_addline(arg->buffer, "T%u = texture2D(Psampler%u, gl_TexCoord[%u].xy + T%u.xy);\n",
-            reg1, reg1, reg1, reg2);
+    shader_glsl_get_write_mask(mask, coord_mask);
+    FIXME("Bump map transform not handled yet\n");
+    shader_addline(arg->buffer, "%s(Psampler%u, T%u%s)%s);\n",
+                   sample_function.name, sampler_idx, sampler_idx, coord_mask, dst_swizzle);
 }
 
 /** Process the WINED3DSIO_TEXREG2AR instruction in GLSL




More information about the wine-cvs mailing list