[4/4] WineD3D: General signed format correction without native signed formats

Stefan Dösinger stefan at codeweavers.com
Wed Mar 21 11:37:40 CDT 2007


It has to be noted that this patch hardcodes another stateblock parameter into 
the shader, the pixel format of the texture(or rather which channels need the 
fixup). It also adds an upward reference into device->stateblock, but I 
personally do not see that as an issue as long as we don't have to compile 
shaders with a foreign stateblock.

So if needed one day we should add a system for storing the stateblock values 
hardcoded in the gl shader and check them against new stateblock values and 
recompile if needed.
-------------- next part --------------
From acd1768fa466d488ab3fa821ab9a034308c8f673 Mon Sep 17 00:00:00 2001
From: Stefan Doesinger <stefan at codeweavers.com>
Date: Wed, 21 Mar 2007 00:06:04 +0100
Subject: [PATCH] WineD3D: General signed format correction without native signed formats

This patch implements signed d3d formats for D3DFMT_V8U8 and D3DFMT_Q8W8V8U8 if no suitable opengl signed format is
supported. This is done by adding 128 before uploading the texture and correcting that after sampling from the texture in
the shader. For the other formats a FIXME is printed in the conversion function

This gets hl2 and 3dmark2001 to the same state on non-nvidia cards as they are on nvidia cards. (ARB shaders for now, GLSL
will follow)
---
 dlls/wined3d/arb_program_shader.c |   30 +++++++++++++------------
 dlls/wined3d/surface.c            |   43 ++++++++++++++++++++++++++++--------
 2 files changed, 49 insertions(+), 24 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 56ef5fb..f2c58ff 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -382,6 +382,8 @@ static void vshader_program_add_param(SHADER_OPCODE_ARG *arg, const DWORD param,
 static void shader_hw_sample(SHADER_OPCODE_ARG* arg, DWORD sampler_idx, const char *dst_str, const char *coord_reg) {
     IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
     IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
+    IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *) deviceImpl->stateBlock->textures[sampler_idx];
+    WineD3D_GL_Info *gl_info = &((IWineD3DImpl *)(((IWineD3DDeviceImpl *)(This->baseShader.device))->wineD3D))->gl_info;
 
     SHADER_BUFFER* buffer = arg->buffer;
     DWORD sampler_type = arg->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK;
@@ -414,6 +416,19 @@ static void shader_hw_sample(SHADER_OPCODE_ARG* arg, DWORD sampler_idx, const ch
     } else {
         shader_addline(buffer, "TEX %s, %s, texture[%u], %s;\n", dst_str, coord_reg, sampler_idx, tex_type);
     }
+
+    /* Signedness correction */
+    if(!GL_SUPPORT(NV_TEXTURE_SHADER3) /* Provides signed formats */ && texture) {
+        WINED3DFORMAT format = texture->baseTexture.format;
+
+        if((format == WINED3DFMT_V8U8 && !GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) ||
+            format == WINED3DFMT_Q8W8V8U8 ||
+            format == WINED3DFMT_V16U16) {
+            shader_addline(buffer, "MAD %s, %s, coefmul.x, -one;\n", dst_str, dst_str);
+        } else if(format == WINED3DFMT_X8L8V8U8) {
+            shader_addline(buffer, "MAD %s.rg, %s, coefmul.x, -one;\n", dst_str, dst_str);
+        }
+    }
 }
 
 
@@ -694,7 +709,6 @@ void pshader_hw_texreg2gb(SHADER_OPCODE_ARG* arg) {
 
 void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) {
     IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
-    WineD3D_GL_Info *gl_info = &((IWineD3DImpl *)(((IWineD3DDeviceImpl *)(This->baseShader.device))->wineD3D))->gl_info;
 
     DWORD dst = arg->dst;
     DWORD src = arg->src[0] & WINED3DSP_REGNUM_MASK;
@@ -709,19 +723,7 @@ void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) {
     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 */
-
-        /* Plain GL does not have any signed formats suitable for that instruction.
-         * So the surface loading code converts the -128 ... 127 signed integers to
-         * 0 ... 255 unsigned ones. The following line undoes that.
-         *
-         * TODO: GL_ATI_envmap_bumpmap supports D3DFMT_DU8DV8 only. If conversion for other formats
-         * is implemented check the texture format.
-         *
-         * TODO: Move that to the common sampling function
-         */
-        if(!GL_SUPPORT(NV_TEXTURE_SHADER3) && !GL_SUPPORT(ATI_ENVMAP_BUMPMAP))
-            shader_addline(buffer, "MAD T%u, T%u, coefmul.x, -one;\n", src, src);
+        /* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed */
 
         shader_addline(buffer, "SWZ TMP2, bumpenvmat, x, z, 0, 0;\n");
         shader_addline(buffer, "DP3 TMP.r, TMP2, T%u;\n", src);
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index e1c754e..8ac924b 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -45,7 +45,10 @@ typedef enum {
     CONVERT_CK_8888,
     CONVERT_CK_8888_ARGB,
     CONVERT_RGB32_888,
-    CONVERT_V8U8
+    CONVERT_V8U8,
+    CONVERT_X8L8V8U8,
+    CONVERT_Q8W8V8U8,
+    CONVERT_V16U16
 } CONVERT_TYPES;
 
 HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *surf);
@@ -1475,37 +1478,37 @@ static HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BO
             *convert = CONVERT_V8U8;
             *format = GL_BGR;
             *internal = GL_RGB8;
-            *type = GL_BYTE;
+            *type = GL_UNSIGNED_BYTE;
             *target_bpp = 3;
             break;
 
         case WINED3DFMT_X8L8V8U8:
             if(GL_SUPPORT(NV_TEXTURE_SHADER3)) break;
-            FIXME("Conversion for D3D_X8L8V8U8 not implemented\n");
+            *convert = CONVERT_X8L8V8U8;
             *format = GL_BGRA;
             *internal = GL_RGBA8;
-            *type = GL_BYTE;
+            *type = GL_UNSIGNED_BYTE;
             *target_bpp = 4;
             /* Not supported by GL_ATI_envmap_bumpmap */
             break;
 
         case WINED3DFMT_Q8W8V8U8:
             if(GL_SUPPORT(NV_TEXTURE_SHADER3)) break;
-            FIXME("Conversion for D3D_Q8W8V8U8 not implemented\n");
+            *convert = CONVERT_Q8W8V8U8;
             *format = GL_BGRA;
             *internal = GL_RGBA8;
-            *type = GL_BYTE;
+            *type = GL_UNSIGNED_BYTE;
             *target_bpp = 4;
             /* Not supported by GL_ATI_envmap_bumpmap */
             break;
 
         case WINED3DFMT_V16U16:
             if(GL_SUPPORT(NV_TEXTURE_SHADER3)) break;
-            FIXME("Conversion for D3D_V16U16 not implemented\n");
-            *format = GL_COLOR_INDEX;
-            *internal = GL_COLOR_INDEX;
+            *convert = CONVERT_V16U16;
+            *format = GL_BGR;
+            *internal = GL_RGB16;
             *type = GL_SHORT;
-            *target_bpp = 4;
+            *target_bpp = 6;
             /* What should I do here about GL_ATI_envmap_bumpmap?
              * Convert it or allow data loss by loading it into a 8 bit / channel texture?
              */
@@ -1649,6 +1652,26 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN
             break;
         }
 
+        case CONVERT_Q8W8V8U8:
+        {
+            unsigned int x, y;
+            DWORD *Source;
+            unsigned char *Dest;
+            for(y = 0; y < height; y++) {
+                Source = (DWORD *) (src + y * pitch);
+                Dest = (unsigned char *) (dst + y * outpitch);
+                for (x = 0; x < width; x++ ) {
+                    long color = (*Source++);
+                    /* B */ Dest[0] = ((color >> 16) & 0xff) + 128; /* W */
+                    /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */
+                    /* R */ Dest[2] = (color         & 0xff) + 128; /* U */
+                    /* A */ Dest[3] = ((color >> 24) & 0xff) + 128; /* Q */
+                    Dest += 4;
+                }
+            }
+            break;
+        }
+
         default:
             ERR("Unsupported conversation type %d\n", convert);
     }
-- 
1.4.4.3



More information about the wine-patches mailing list