WINED3D: Texture stages that reference NULL textures should just pass through the result of the previous stage

H. Verbeet hverbeet at gmail.com
Tue Jul 11 17:44:03 CDT 2006


If a texture stage references D3DTA_TEXTURE, but a texture is not set
for that stage, the stage returns the result of the previous stage.

The default operation for stage 0 is D3DTOP_MODULATE with
D3DTA_TEXTURE and D3DTA_CURRENT, without a texture. Previously the bug
this patch fixes was not as visible because the dummy textures that
were used were white, which had as result that the output of the stage
was the same as when D3DTOP_SELECDTARG1 was used with D3DTA_CURRENT.
-------------- next part --------------
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index a729344..dedcd43 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -653,6 +653,15 @@ typedef struct {
     GLenum component_usage[3];
 } tex_op_args;
 
+static BOOL is_invalid_op(IWineD3DDeviceImpl *This, int stage, D3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3) {
+    if (This->stateBlock->textures[stage]) return FALSE;
+
+    return (op != D3DTOP_DISABLE
+            && ((arg1 == D3DTA_TEXTURE && (op != D3DTOP_SELECTARG2 && op != D3DTOP_DISABLE))
+            || (arg2 == D3DTA_TEXTURE && (op != D3DTOP_SELECTARG1 && op != D3DTOP_DISABLE))
+            || (arg3 == D3DTA_TEXTURE && (op == D3DTOP_MULTIPLYADD || op == D3DTOP_LERP))));
+}
+
 void set_tex_op_nvrc(IWineD3DDevice *iface, BOOL is_alpha, int stage, D3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3, INT texture_idx) {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl*)iface;
     tex_op_args tex_op_args = {{0}, {0}, {0}};
@@ -662,6 +671,13 @@ void set_tex_op_nvrc(IWineD3DDevice *ifa
     TRACE("stage %d, is_alpha %d, op %s, arg1 %#lx, arg2 %#lx, arg3 %#lx, texture_idx %d\n",
             stage, is_alpha, debug_d3dtop(op), arg1, arg2, arg3, texture_idx);
 
+    /* If a texture stage references an invalid texture unit the stage just
+     * passes through the result from the previous stage */
+    if (is_invalid_op(This, stage, op, arg1, arg2, arg3)) {
+        arg1 = D3DTA_CURRENT;
+        op = D3DTOP_SELECTARG1;
+    }
+
     get_src_and_opr_nvrc(stage, arg1, is_alpha, &tex_op_args.input[0],
             &tex_op_args.mapping[0], &tex_op_args.component_usage[0], texture_idx);
     get_src_and_opr_nvrc(stage, arg2, is_alpha, &tex_op_args.input[1],
@@ -1053,6 +1069,13 @@ #define GLINFO_LOCATION ((IWineD3DImpl *
                 scal_target = useext(GL_RGB_SCALE);
         }
 
+        /* If a texture stage references an invalid texture unit the stage just
+         * passes through the result from the previous stage */
+        if (is_invalid_op(This, Stage, op, arg1, arg2, arg3)) {
+            arg1 = D3DTA_CURRENT;
+            op = D3DTOP_SELECTARG1;
+        }
+
         /* From MSDN (WINED3DTSS_ALPHAARG1) :
            The default argument is D3DTA_TEXTURE. If no texture is set for this stage,
                    then the default argument is D3DTA_DIFFUSE.










More information about the wine-patches mailing list