Stefan Dösinger : wined3d: Emulate the 4 component address register in ARB.

Alexandre Julliard julliard at winehq.org
Wed May 20 08:29:33 CDT 2009


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

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Fri May 15 13:56:40 2009 +0200

wined3d: Emulate the 4 component address register in ARB.

---

 dlls/wined3d/arb_program_shader.c |   58 ++++++++++++++++++++++++++++++-------
 dlls/wined3d/baseshader.c         |    3 +-
 dlls/wined3d/glsl_shader.c        |    4 +-
 dlls/wined3d/wined3d_private.h    |    3 +-
 4 files changed, 53 insertions(+), 15 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 87a1d4c..d871fc9 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -84,6 +84,10 @@ struct shader_arb_priv {
     struct hash_table_t     *fragment_shaders;
 };
 
+struct shader_arb_ctx_priv {
+    char addr_reg[20];
+};
+
 /********************************************************
  * ARB_[vertex/fragment]_program helper functions follow
  ********************************************************/
@@ -503,6 +507,17 @@ static void shader_arb_get_swizzle(const struct wined3d_shader_src_param *param,
     *ptr = '\0';
 }
 
+static void shader_arb_request_a0(const struct wined3d_shader_instruction *ins, const char *src)
+{
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
+
+    if(strcmp(priv->addr_reg, src) == 0) return;
+
+    strcpy(priv->addr_reg, src);
+    shader_addline(buffer, "ARL A0.x, %s;\n", src);
+}
+
 static void shader_arb_get_src_param(const struct wined3d_shader_instruction *ins,
         const struct wined3d_shader_src_param *src, unsigned int tmpreg, char *outregstr);
 
@@ -543,7 +558,9 @@ static void shader_arb_get_register_name(const struct wined3d_shader_instruction
                 if(This->baseShader.reg_maps.shader_version.major < 2) {
                     sprintf(rel_reg, "A0.x");
                 } else {
+                    shader_arb_get_src_param(ins, reg->rel_addr, 0, rel_reg);
                     /* FIXME: GL_NV_vertex_progam2_option */
+                    shader_arb_request_a0(ins, rel_reg);
                     sprintf(rel_reg, "A0.x");
                 }
                 if (reg->idx >= rel_offset)
@@ -574,7 +591,17 @@ static void shader_arb_get_register_name(const struct wined3d_shader_instruction
                     sprintf(register_name, "fragment.texcoord[%u]", reg->idx);
                 }
             }
-            else  sprintf(register_name, "A%u", reg->idx);
+            else
+            {
+                if(This->baseShader.reg_maps.shader_version.major == 1)
+                {
+                    sprintf(register_name, "A%u", reg->idx);
+                }
+                else
+                {
+                    sprintf(register_name, "A%u_SHADOW", reg->idx);
+                }
+            }
             break;
 
         case WINED3DSPR_COLOROUT:
@@ -1016,9 +1043,11 @@ static void shader_hw_mov(const struct wined3d_shader_instruction *ins)
 
     if(ins->handler_idx == WINED3DSIH_MOVA) {
         struct wined3d_shader_src_param tmp_src = ins->src[0];
+        char write_mask[6];
 
         tmp_src.swizzle = (tmp_src.swizzle & 0x3) * 0x55;
         shader_arb_get_src_param(ins, &tmp_src, 0, src0_param);
+        shader_arb_get_write_mask(ins, &ins->dst[0], write_mask);
 
         /* This implements the mova formula used in GLSL. The first two instructions
          * prepare the sign() part. Note that it is fine to have my_sign(0.0) = 1.0
@@ -1027,16 +1056,20 @@ static void shader_hw_mov(const struct wined3d_shader_instruction *ins)
          *
          * A0.x = arl(floor(abs(0.0) + 0.5) * 1.0) = floor(0.5) = 0.0 since arl does a floor
          *
+         * The ARL is performed when A0 is used - the requested component is read from A0_SHADOW into
+         * A0.x. We can use the overwritten component of A0_shadow as temporary storage for the sign.
+         *
          * TODO: ARR from GL_NV_vertex_program2_option
          */
-        shader_addline(buffer, "SGE TA.y, %s, mova_const.y;\n", src0_param);
-        shader_addline(buffer, "MAD TA.y, TA.y, mova_const.z, -mova_const.w;\n");
-
-        shader_addline(buffer, "ABS TA.x, %s;\n", src0_param);
-        shader_addline(buffer, "ADD TA.x, TA.x, mova_const.x;\n");
-        shader_addline(buffer, "FLR TA.x, TA.x;\n");
-        shader_addline(buffer, "MUL TA.x, TA.x, TA.y;\n");
-        shader_addline(buffer, "ARL A0.x, TA.x;\n");
+        shader_addline(buffer, "SGE A0_SHADOW%s, %s, mova_const.y;\n", write_mask, src0_param);
+        shader_addline(buffer, "MAD A0_SHADOW%s, A0_SHADOW, mova_const.z, -mova_const.w;\n", write_mask);
+
+        shader_addline(buffer, "ABS TA%s, %s;\n", write_mask, src0_param);
+        shader_addline(buffer, "ADD TA%s, TA, mova_const.x;\n", write_mask);
+        shader_addline(buffer, "FLR TA%s, TA;\n", write_mask);
+        shader_addline(buffer, "MUL A0_SHADOW%s, TA, A0_SHADOW;\n", write_mask);
+
+        ((struct shader_arb_ctx_priv *)ins->ctx->backend_data)->addr_reg[0] = '\0';
     } else if (ins->ctx->reg_maps->shader_version.major == 1
           && !shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type)
           && ins->dst[0].reg.type == WINED3DSPR_ADDR)
@@ -1982,7 +2015,7 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface,
     shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, lconst_map);
 
     /* Base Shader Body */
-    shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function);
+    shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, NULL);
 
     if(args->srgb_correction) {
         arbfp_add_sRGB_correction(buffer, fragcolor, "TA", "TB", "TC");
@@ -2036,7 +2069,9 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface,
     const local_constant *lconst;
     GLuint ret;
     DWORD *lconst_map = local_const_mapping((IWineD3DBaseShaderImpl *) This);
+    struct shader_arb_ctx_priv priv_ctx;
 
+    memset(&priv_ctx, 0, sizeof(priv_ctx));
     /*  Create the hw ARB shader */
     shader_addline(buffer, "!!ARBvp1.0\n");
 
@@ -2045,6 +2080,7 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface,
     }
     if(need_mova_const((IWineD3DBaseShader *) iface, gl_info)) {
         shader_addline(buffer, "PARAM mova_const = { 0.5, 0.0, 2.0, 1.0 };\n");
+        shader_addline(buffer, "TEMP A0_SHADOW;\n");
     }
 
     /* Mesa supports only 95 constants */
@@ -2086,7 +2122,7 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface,
     }
 
     /* Base Shader Body */
-    shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function);
+    shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, &priv_ctx);
 
     /* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used
      * or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE),
diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c
index cf8171b..2fd79ff 100644
--- a/dlls/wined3d/baseshader.c
+++ b/dlls/wined3d/baseshader.c
@@ -929,7 +929,7 @@ void shader_dump_src_param(const struct wined3d_shader_src_param *param,
 /* 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)
+        const shader_reg_maps *reg_maps, const DWORD *pFunction, void *backend_ctx)
 {
     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device; /* To access shader backend callbacks */
@@ -951,6 +951,7 @@ void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER *buffer,
     ctx.shader = iface;
     ctx.reg_maps = reg_maps;
     ctx.buffer = buffer;
+    ctx.backend_data = backend_ctx;
 
     ins.ctx = &ctx;
     ins.dst = &dst_param;
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 13d82ba..c978e5b 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -4142,7 +4142,7 @@ static GLuint shader_glsl_generate_pshader(IWineD3DPixelShader *iface,
     }
 
     /* Base Shader Body */
-    shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function);
+    shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, NULL);
 
     /* Pixel shaders < 2.0 place the resulting color in R0 implicitly */
     if (reg_maps->shader_version.major < 2)
@@ -4229,7 +4229,7 @@ static GLuint shader_glsl_generate_vshader(IWineD3DVertexShader *iface,
     shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, NULL);
 
     /* Base Shader Body */
-    shader_generate_main((IWineD3DBaseShader*)This, buffer, reg_maps, function);
+    shader_generate_main((IWineD3DBaseShader*)This, buffer, reg_maps, function, NULL);
 
     /* Unpack 3.0 outputs */
     if (reg_maps->shader_version.major >= 3) shader_addline(buffer, "order_ps_input(OUT);\n");
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 526ba24..79ac60b 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -648,6 +648,7 @@ struct wined3d_shader_context
     IWineD3DBaseShader *shader;
     const struct shader_reg_maps *reg_maps;
     SHADER_BUFFER *buffer;
+    void *backend_data;
 };
 
 struct wined3d_shader_register
@@ -2575,7 +2576,7 @@ void shader_dump_src_param(const struct wined3d_shader_src_param *param,
 void shader_dump_dst_param(const struct wined3d_shader_dst_param *param,
         const struct wined3d_shader_version *shader_version);
 void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER *buffer,
-        const shader_reg_maps *reg_maps, const DWORD *pFunction);
+        const shader_reg_maps *reg_maps, const DWORD *pFunction, void *backend_ctx);
 HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, const struct wined3d_shader_frontend *fe,
         struct shader_reg_maps *reg_maps, struct wined3d_shader_semantic *semantics_in,
         struct wined3d_shader_semantic *semantics_out, const DWORD *byte_code, DWORD constf_size);




More information about the wine-cvs mailing list