wined3d: Implented signed texture formats via NV_TEXTURE_SHADER

Fabian Bieler der.fabe at gmx.net
Sat Mar 10 08:02:31 CST 2007


This patch implements D3DFMT_V8U8 and D3DFMT_Q8W8V8U8 via NV_TEXTURE_SHADER. 
This fixes some renderissues in Half-Life 2 with the DirectX9 path and the 
DirectX8 path via GLSL.

Pavel Troller described these issues as:
"there is too much
shine all over the game. Not only barrels and weapons, but also faces, 
dresses,
walls.. It looks like covered by the oil film. There are also some strange
shadow effects - like that the top of the hand is dark and the bottom is 
bright,
like if the light would come from the ground."

There are still some issues in the closing cutscene. I'm not sure if this is 
due to different handling of RGBA and QWVU textures by the driver or some 
other bug.

Somebody should probably do the same with ATI_envmap_bumpmap for ATI cards.
-------------- next part --------------
From 214eccb0d5ecf58a0eefcdd64d8f6e0a6ee76907 Mon Sep 17 00:00:00 2001
From: Fabian Bieler <der.fabe at gmx.net>
Date: Sat, 10 Mar 2007 14:37:06 +0100
Subject: [PATCH] wined3d: Implented signed texture formats via NV_TEXTURE_SHADER

---
 dlls/wined3d/arb_program_shader.c |    8 +++++---
 dlls/wined3d/device.c             |    6 +++---
 dlls/wined3d/state.c              |    4 ++--
 dlls/wined3d/surface.c            |   11 ++++++-----
 dlls/wined3d/surface_gdi.c        |   15 ++++++++-------
 dlls/wined3d/utils.c              |   32 +++++++++++++++++++++++++++-----
 dlls/wined3d/volume.c             |    2 +-
 dlls/wined3d/wined3d_private.h    |    2 +-
 8 files changed, 53 insertions(+), 27 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 79148e5..2e636ad 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -694,6 +694,7 @@ 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;
@@ -714,11 +715,12 @@ void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) {
          * So the surface loading code converts the -128 ... 127 signed integers to
          * 0 ... 255 unsigned ones. The following line undoes that.
          *
-         * TODO: Both GL_NV_texture_shader and GL_ATI_envmap_bumpmap provide pixel formats
-         * suitable for loading the Direct3D perturbation data. If one of them is used, do
+         * TODO: GL_ATI_envmap_bumpmap provides pixel formats
+         * suitable for loading the Direct3D perturbation data. If it is used, do
          * not correct the signedness
          */
-        shader_addline(buffer, "MAD T%u, T%u, coefmul.x, -one;\n", src, src);
+        if(!GL_SUPPORT(NV_TEXTURE_SHADER3))
+            shader_addline(buffer, "MAD T%u, T%u, coefmul.x, -one;\n", src, src);
 
         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/device.c b/dlls/wined3d/device.c
index cff0f19..1f745d8 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -587,7 +587,7 @@ static HRESULT  WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U
     IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
     unsigned int pow2Width, pow2Height;
     unsigned int Size       = 1;
-    const PixelFormatDesc *tableEntry = getFormatDescEntry(Format);
+    const PixelFormatDesc *tableEntry = getFormatDescEntry(&GLINFO_LOCATION, Format);
     TRACE("(%p) Create surface\n",This);
     
     /** FIXME: Check ranges on the inputs are valid 
@@ -951,7 +951,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
 
     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
     IWineD3DVolumeImpl        *object; /** NOTE: impl ref allowed since this is a create function **/
-    const PixelFormatDesc *formatDesc  = getFormatDescEntry(Format);
+    const PixelFormatDesc *formatDesc  = getFormatDescEntry(&GLINFO_LOCATION, Format);
 
     D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
 
@@ -1835,7 +1835,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, U
     DEVMODEW devmode;
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     LONG ret;
-    const PixelFormatDesc *formatDesc  = getFormatDescEntry(pMode->Format);
+    const PixelFormatDesc *formatDesc  = getFormatDescEntry(&GLINFO_LOCATION, pMode->Format);
     RECT clip_rc;
 
     TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index cf1b7f4..059e6f6 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -349,7 +349,7 @@ static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
         surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0];
 
         if(surf->CKeyFlags & DDSD_CKSRCBLT) {
-            const PixelFormatDesc *fmt = getFormatDescEntry(surf->resource.format);
+            const PixelFormatDesc *fmt = getFormatDescEntry(&GLINFO_LOCATION, surf->resource.format);
             /* The surface conversion does not do color keying conversion for surfaces that have an alpha
              * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the
              * surface has alpha bits
@@ -1595,7 +1595,7 @@ static void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
         IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
 
         if(surf->CKeyFlags & DDSD_CKSRCBLT &&
-           getFormatDescEntry(surf->resource.format)->alphaMask == 0x00000000) {
+           getFormatDescEntry(&GLINFO_LOCATION, surf->resource.format)->alphaMask == 0x00000000) {
 
             /* Color keying needs to pass alpha values from the texture through to have the alpha test work properly.
              * On the other hand applications can still use texture combiners apparently. This code takes care that apps
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index c8d39f6..d1142ca 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -1168,7 +1168,7 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
     DWORD *masks;
     HRESULT hr;
     RGBQUAD col[256];
-    const PixelFormatDesc *formatEntry = getFormatDescEntry(This->resource.format);
+    const PixelFormatDesc *formatEntry = getFormatDescEntry(&GLINFO_LOCATION, This->resource.format);
 
     TRACE("(%p)->(%p)\n",This,pHDC);
 
@@ -1383,7 +1383,7 @@ HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC) {
 
 HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_texturing, GLenum *format, GLenum *internal, GLenum *type, CONVERT_TYPES *convert, int *target_bpp) {
     BOOL colorkey_active = need_alpha_ck && (This->CKeyFlags & DDSD_CKSRCBLT);
-    const PixelFormatDesc *formatEntry = getFormatDescEntry(This->resource.format);
+    const PixelFormatDesc *formatEntry = getFormatDescEntry(&GLINFO_LOCATION, This->resource.format);
 
     /* Default values: From the surface */
     *format = formatEntry->glFormat;
@@ -1455,10 +1455,11 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_
             break;
 
         case WINED3DFMT_V8U8:
-            /* TODO: GL_NV_texture_shader and GL_ATI_envmap_bumpmap provide suitable formats.
-             * use one of them instead of converting
+            /* TODO: GL_ATI_envmap_bumpmap provides suitable formats.
+             * use it instead of converting
              * Remember to adjust the texbem instruction in the shader
              */
+            if(GL_SUPPORT(NV_TEXTURE_SHADER3)) break;
             *convert = CONVERT_V8U8;
             *format = GL_BGR;
             *internal = GL_RGB8;
@@ -2035,7 +2036,7 @@ HRESULT WINAPI IWineD3DSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWineD3D
 
 HRESULT WINAPI IWineD3DSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3DFORMAT format) {
     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
-    const PixelFormatDesc *formatEntry = getFormatDescEntry(format);
+    const PixelFormatDesc *formatEntry = getFormatDescEntry(&GLINFO_LOCATION, format);
 
     if (This->resource.format != WINED3DFMT_UNKNOWN) {
         FIXME("(%p) : The foramt of the surface must be WINED3DFORMAT_UNKNOWN\n", This);
diff --git a/dlls/wined3d/surface_gdi.c b/dlls/wined3d/surface_gdi.c
index 4565f72..638e305 100644
--- a/dlls/wined3d/surface_gdi.c
+++ b/dlls/wined3d/surface_gdi.c
@@ -35,6 +35,7 @@
 /* Use the d3d_surface debug channel to have one channel for all surfaces */
 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
 WINE_DECLARE_DEBUG_CHANNEL(fps);
+#define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->resource.wineD3DDevice)->wineD3D))->gl_info
 
 /*****************************************************************************
  * x11_copy_to_screen
@@ -534,7 +535,7 @@ IWineGDISurfaceImpl_Blt(IWineD3DSurface *iface,
         dfmt = This->resource.format;
         slock = dlock;
         sfmt = dfmt;
-        sEntry = getFormatDescEntry(sfmt);
+        sEntry = getFormatDescEntry(&GLINFO_LOCATION, sfmt);
         dEntry = sEntry;
     }
     else
@@ -544,9 +545,9 @@ IWineGDISurfaceImpl_Blt(IWineD3DSurface *iface,
             IWineD3DSurface_LockRect(SrcSurface, &slock, NULL, WINED3DLOCK_READONLY);
             sfmt = Src->resource.format;
         }
-        sEntry = getFormatDescEntry(sfmt);
+        sEntry = getFormatDescEntry(&GLINFO_LOCATION, sfmt);
         dfmt = This->resource.format;
-        dEntry = getFormatDescEntry(dfmt);
+        dEntry = getFormatDescEntry(&GLINFO_LOCATION, dfmt);
         IWineD3DSurface_LockRect(iface, &dlock,NULL,0);
     }
 
@@ -1224,7 +1225,7 @@ IWineGDISurfaceImpl_BltFast(IWineD3DSurface *iface,
         assert(This->resource.allocatedMemory != NULL);
         sbuf = (BYTE *)This->resource.allocatedMemory + lock_src.top * pitch + lock_src.left * bpp;
         dbuf = (BYTE *)This->resource.allocatedMemory + lock_dst.top * pitch + lock_dst.left * bpp;
-        sEntry = getFormatDescEntry(Src->resource.format);
+        sEntry = getFormatDescEntry(&GLINFO_LOCATION, Src->resource.format);
         dEntry = sEntry;
     }
     else
@@ -1238,8 +1239,8 @@ IWineGDISurfaceImpl_BltFast(IWineD3DSurface *iface,
         dbuf = dlock.pBits;
         TRACE("Dst is at %p, Src is at %p\n", dbuf, sbuf);
 
-        sEntry = getFormatDescEntry(Src->resource.format);
-        dEntry = getFormatDescEntry(This->resource.format);
+        sEntry = getFormatDescEntry(&GLINFO_LOCATION, Src->resource.format);
+        dEntry = getFormatDescEntry(&GLINFO_LOCATION, This->resource.format);
     }
 
     /* Handle first the FOURCC surfaces... */
@@ -1417,7 +1418,7 @@ const char* filename)
     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
     static char *output = NULL;
     static int size = 0;
-    const PixelFormatDesc *formatEntry = getFormatDescEntry(This->resource.format);
+    const PixelFormatDesc *formatEntry = getFormatDescEntry(&GLINFO_LOCATION, This->resource.format);
 
     if (This->pow2Width > size) {
         output = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->pow2Width * 3);
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 9c82ef0..2e6247f 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -27,8 +27,6 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
 
-#define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
-
 /*****************************************************************************
  * Pixel format array
  */
@@ -107,14 +105,31 @@ static const PixelFormatDesc formats[] = {
     {WINED3DFMT_Q16W16V16U16,0x0        ,0x0        ,0x0        ,0x0        ,8      ,FALSE      ,GL_COLOR_INDEX         ,GL_COLOR_INDEX     ,GL_UNSIGNED_SHORT              }
 };
 
-const PixelFormatDesc *getFormatDescEntry(WINED3DFORMAT fmt)
+static const PixelFormatDesc NV_texture_shader_formats[] = {
+    {WINED3DFMT_V8U8        ,0x0        ,0x0        ,0x0        ,0x0        ,2      ,FALSE      ,GL_SIGNED_HILO8_NV     ,GL_HILO_NV         ,GL_BYTE                        },
+    {WINED3DFMT_X8L8V8U8    ,0x0        ,0x0        ,0x0        ,0x0        ,4      ,FALSE      ,GL_DSDT8_MAG8_INTENSITY8_NV,GL_DSDT_MAG_INTENSITY_NV,GL_BYTE},
+    {WINED3DFMT_Q8W8V8U8    ,0x0        ,0x0        ,0x0        ,0x0        ,4      ,FALSE      ,GL_SIGNED_RGBA8_NV     ,GL_RGBA            ,GL_BYTE                        },
+    {WINED3DFMT_V16U16      ,0x0        ,0x0        ,0x0        ,0x0        ,4      ,FALSE      ,GL_SIGNED_HILO16_NV    ,GL_HILO_NV         ,GL_SHORT                       }
+};
+
+#define GLINFO_LOCATION      (*gl_info)
+
+const PixelFormatDesc *getFormatDescEntry(WineD3D_GL_Info *gl_info, WINED3DFORMAT fmt)
 {
     /* First check if the format is at the position of its value.
      * This will catch the argb formats before the loop is entered
      */
     if(fmt < (sizeof(formats) / sizeof(formats[0])) && formats[fmt].format == fmt) {
         return &formats[fmt];
-    } else {
+    }
+    if(GL_SUPPORT(NV_TEXTURE_SHADER3)) {
+        unsigned int i;
+        for(i = 0; i < (sizeof(NV_texture_shader_formats) / sizeof(NV_texture_shader_formats[0])); i++) {
+            if(NV_texture_shader_formats[i].format == fmt) {
+                return &NV_texture_shader_formats[i];
+            }
+        }
+    } {
         unsigned int i;
         for(i = 0; i < (sizeof(formats) / sizeof(formats[0])); i++) {
             if(formats[i].format == fmt) {
@@ -122,15 +137,18 @@ const PixelFormatDesc *getFormatDescEntry(WINED3DFORMAT fmt)
             }
         }
     }
+
     FIXME("Can't find format %s(%d) in the format lookup table\n", debug_d3dformat(fmt), fmt);
     if(fmt == WINED3DFMT_UNKNOWN) {
         ERR("Format table corrupt - Can't find WINED3DFMT_UNKNOWN\n");
         return NULL;
     }
     /* Get the caller a valid pointer */
-    return getFormatDescEntry(WINED3DFMT_UNKNOWN);
+    return getFormatDescEntry(gl_info, WINED3DFMT_UNKNOWN);
 }
 
+#undef GLINFO_LOCATION
+
 /*****************************************************************************
  * Trace formatting of useful values
  */
@@ -787,6 +805,8 @@ static BOOL is_invalid_op(IWineD3DDeviceImpl *This, int stage, WINED3DTEXTUREOP
     return FALSE;
 }
 
+#define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
+
 void set_tex_op_nvrc(IWineD3DDevice *iface, BOOL is_alpha, int stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3, INT texture_idx) {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl*)iface;
     tex_op_args tex_op_args = {{0}, {0}, {0}};
@@ -1085,6 +1105,8 @@ void set_tex_op_nvrc(IWineD3DDevice *iface, BOOL is_alpha, int stage, WINED3DTEX
     LEAVE_GL();
 }
 
+#undef GLINFO_LOCATION
+
 static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) {
     /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the
      * input should be used for all input components. The WINED3DTA_COMPLEMENT
diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c
index 3fb3036..3ad9c00 100644
--- a/dlls/wined3d/volume.c
+++ b/dlls/wined3d/volume.c
@@ -264,7 +264,7 @@ static HRESULT WINAPI IWineD3DVolumeImpl_SetContainer(IWineD3DVolume *iface, IWi
 
 static HRESULT WINAPI IWineD3DVolumeImpl_LoadTexture(IWineD3DVolume *iface, GLenum gl_level) {
     IWineD3DVolumeImpl *This     = (IWineD3DVolumeImpl *)iface;
-    const PixelFormatDesc *formatEntry = getFormatDescEntry(This->resource.format);
+    const PixelFormatDesc *formatEntry = getFormatDescEntry(&GLINFO_LOCATION, This->resource.format);
 
     if(GL_SUPPORT(EXT_TEXTURE3D)) {
         TRACE("Calling glTexImage3D %x level=%d, intfmt=%x, w=%d, h=%d,d=%d, 0=%d, glFmt=%x, glType=%x, Mem=%p\n",
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index df0ff6a..5670c83 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1936,5 +1936,5 @@ typedef struct {
     GLint                   glInternal, glFormat, glType;
 } PixelFormatDesc;
 
-const PixelFormatDesc *getFormatDescEntry(WINED3DFORMAT fmt);
+const PixelFormatDesc *getFormatDescEntry(WineD3D_GL_Info *gl_info, WINED3DFORMAT fmt);
 #endif
-- 
1.4.4.1



More information about the wine-patches mailing list