[WINED3D 6/8] Stateblock support for dmap and vtf samplers

Ivan Gyurdiev ivg231 at gmail.com
Mon Oct 2 19:18:15 CDT 2006


Add displacement map and vertex texture (vtf) samplers to the stateblock.
Nothing is done with them yet... todo.

-------------- next part --------------
>From 30cf4451d4aaa69ef66c9d5969ec93b1953a2ba5 Mon Sep 17 00:00:00 2001
From: Ivan Gyurdiev <ivg2 at cornell.edu>
Date: Mon, 2 Oct 2006 19:48:06 -0400
Subject: [PATCH] Stateblock support for dmap and vtf samplers.

Add displacement map and vertex texture (vtf) samplers to the stateblock.
Nothing is done with them yet... todo.
---
 dlls/wined3d/device.c          |   91 +++++++++++++++++++++++++++++-----------
 dlls/wined3d/directx.c         |    5 ++
 dlls/wined3d/stateblock.c      |   64 +++++++++++++++++++++++++++-
 dlls/wined3d/wined3d_private.h |    7 +++
 include/wine/wined3d_gl.h      |    1 
 5 files changed, 139 insertions(+), 29 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 6f79444..a99798f 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -8,6 +8,7 @@
  * Copyright 2005 Oliver Stieber
  * Copyright 2006 Stefan Dösinger for CodeWeavers
  * Copyright 2006 Henri Verbeet
+ * Copyright 2006 Ivan Gyurdiev
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -2156,9 +2157,14 @@ static HRESULT WINAPI IWineD3DDeviceImpl
         This->cursorTexture = 0;
     }
 
-    for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
+    /* Set all textures to NULL */
+    IWineD3DDevice_SetTexture(iface, D3DDMAPSAMPLER, NULL);
+
+    for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler)
         IWineD3DDevice_SetTexture(iface, sampler, NULL);
-    }
+
+    for(sampler = 0; sampler < GL_LIMITS(vertex_samplers); ++sampler) 
+        IWineD3DDevice_SetTexture(iface, D3DVERTEXTEXTURESAMPLER0 + sampler, NULL);
 
     /* Release the buffers (with sanity checks)*/
     TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
@@ -5738,20 +5744,23 @@ static HRESULT WINAPI IWineD3DDeviceImpl
 
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     IWineD3DBaseTexture   *oldTexture;
-
-    oldTexture = This->updateStateBlock->textures[Stage];
+    BOOL vertexTexture = FALSE;
+    BOOL dmapTexture = FALSE;
+  
     TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
-
-#if 0 /* TODO: check so vertex textures */
-    if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
-        This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
-        return WINED3D_OK;
-    }
-#endif
-
+ 
+    /* Check for displacement map sampler */
+    if (Stage == D3DDMAPSAMPLER) 
+        dmapTexture = TRUE;
+ 
+    /* Check for vertex shader textures */
+    else if (Stage >= D3DVERTEXTEXTURESAMPLER0 && Stage <= D3DVERTEXTEXTURESAMPLER3) 
+        vertexTexture = TRUE;
+         
     /* Reject invalid texture units */
-    if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
-        WARN("Attempt to access invalid texture rejected\n");
+    else if (Stage >= GL_LIMITS(sampler_stages)) {
+         WARN("Attempt to access invalid texture rejected, stage=%u, limit=%u\n",
+             Stage, GL_LIMITS(sampler_stages));
         return WINED3DERR_INVALIDCALL;
     }
 
@@ -5764,14 +5773,34 @@ #endif
         }
     }
 
-    oldTexture = This->updateStateBlock->textures[Stage];
-    TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
-    TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
+    if (dmapTexture) {
+        oldTexture = This->updateStateBlock->dmapTexture;
+        TRACE("(%p) : Old Texture: (Stage=%u, %p)\n", This, Stage, oldTexture);
+        TRACE("(%p) : New Texture: (Stage=%u, %p)\n", This, Stage, pTexture);
+        This->updateStateBlock->set.dmapTexture = TRUE;
+        This->updateStateBlock->changed.dmapTexture = TRUE;
+        This->updateStateBlock->dmapTexture = pTexture;
 
-    This->updateStateBlock->set.textures[Stage]     = TRUE;
-    This->updateStateBlock->changed.textures[Stage] = TRUE;
-    TRACE("(%p) : setting new texture to %p\n", This, pTexture);
-    This->updateStateBlock->textures[Stage]         = pTexture;
+    } else if (vertexTexture) {
+        const int idx = Stage - D3DVERTEXTEXTURESAMPLER0;
+        oldTexture = This->updateStateBlock->vertexTextures[idx];
+        TRACE("(%p) : Old Texture: (Stage=%u, %p)\n", This, Stage, oldTexture);
+        TRACE("(%p) : New Texture: (Stage=%u, %p)\n", This, Stage, pTexture);
+
+        This->updateStateBlock->set.vertexTextures[idx] = TRUE;
+        This->updateStateBlock->changed.vertexTextures[idx] = TRUE;        
+        This->updateStateBlock->vertexTextures[idx] = pTexture;
+ 
+    } else  {
+        const int idx = Stage;
+        oldTexture = This->updateStateBlock->textures[idx];
+        TRACE("(%p) : Old Texture: (Stage=%u, %p)\n", This, Stage, oldTexture);
+        TRACE("(%p) : New Texture: (Stage=%u, %p)\n", This, Stage, pTexture);
+
+        This->updateStateBlock->set.textures[idx] = TRUE;
+        This->updateStateBlock->changed.textures[idx] = TRUE;
+        This->updateStateBlock->textures[idx] = pTexture;
+    }
 
     /* Handle recording of state blocks */
     if (This->isRecordingState) {
@@ -5783,8 +5812,8 @@ #endif
     * and the the application nust set the texture back to null (or have a leaky application),
     * This means we should pass the refcount up to the parent
      *******************************/
-    if (NULL != This->updateStateBlock->textures[Stage]) {
-        IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
+    if (NULL != pTexture) {
+        IWineD3DBaseTexture_AddRef(pTexture);
     }
 
     if (NULL != oldTexture) {
@@ -5813,12 +5842,22 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
 
-    /* Reject invalid texture units */
-    if (Stage >= GL_LIMITS(sampler_stages)) {
+    /* Check for vertex shader textures */
+
+    if (Stage == D3DDMAPSAMPLER)
+        *ppTexture = This->updateStateBlock->dmapTexture;
+
+    else if (Stage >= D3DVERTEXTEXTURESAMPLER0 && Stage <= D3DVERTEXTEXTURESAMPLER3)
+        *ppTexture = This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER0];
+
+    else if (Stage < GL_LIMITS(sampler_stages))
+        *ppTexture = This->updateStateBlock->textures[Stage];
+
+    else {
         TRACE("Attempt to access invalid texture rejected\n");
         return WINED3DERR_INVALIDCALL;
     }
-    *ppTexture=This->updateStateBlock->textures[Stage];
+
     if (*ppTexture)
         IWineD3DBaseTexture_AddRef(*ppTexture);
     else
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 0563918..2627d30 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -5,6 +5,7 @@
  * Copyright 2003-2004 Raphael Junqueira
  * Copyright 2004 Christian Costa
  * Copyright 2005 Oliver Stieber
+ * Copyright 2006 Ivan Gyurdiev
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -464,6 +465,7 @@ BOOL IWineD3DImpl_FillGLCaps(IWineD3D *i
     gl_info->max_textures       = 1;
     gl_info->max_texture_stages = 1;
     gl_info->max_samplers       = 1;
+    gl_info->max_vertex_samplers = 0;
     gl_info->max_sampler_stages = 1;
     gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
     gl_info->ps_arb_max_temps = 0;
@@ -622,6 +624,9 @@ #undef USE_GL_FUNC
                 gl_max /= 4;
                 TRACE_(d3d_caps)(" FOUND: ARB_vertex_shader (GLSL) support - max float vs constants=%u\n", gl_max);
                 gl_info->vs_glsl_constantsF = gl_max;
+                glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &gl_max);
+                TRACE_(d3d_caps)(" FOUND: ARB_vertex_shader (GLSL) support - max vs samplers=%u\n", gl_max);
+                gl_info->max_vertex_samplers = min(MAX_VERTEX_SAMPLERS, gl_max);
             } else if (strcmp(ThisExtn, "GL_ARB_vertex_blend") == 0) {
                 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
                 TRACE_(d3d_caps)(" FOUND: ARB Vertex Blend support GL_MAX_VERTEX_UNITS_ARB %d\n", gl_max);
diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c
index 98de692..d066f46 100644
--- a/dlls/wined3d/stateblock.c
+++ b/dlls/wined3d/stateblock.c
@@ -78,11 +78,13 @@ void stateblock_savedstates_copy(
     dest->vertexDecl = source->vertexDecl;
     dest->pixelShader = source->pixelShader;
     dest->vertexShader = source->vertexShader;
+    dest->dmapTexture = source->dmapTexture;
 
     /* Fixed size arrays */
     memcpy(dest->streamSource, source->streamSource, bsize * MAX_STREAMS);
     memcpy(dest->streamFreq, source->streamFreq, bsize * MAX_STREAMS);
     memcpy(dest->textures, source->textures, bsize * MAX_SAMPLERS);
+    memcpy(dest->vertexTextures, source->vertexTextures, bsize * MAX_VERTEX_SAMPLERS);
     memcpy(dest->transform, source->transform, bsize * (HIGHEST_TRANSFORMSTATE + 1));
     memcpy(dest->renderState, source->renderState, bsize * (WINEHIGHEST_RENDER_STATE + 1));
     memcpy(dest->textureState, source->textureState, bsize * MAX_TEXTURES * (WINED3D_HIGHEST_TEXTURE_STATE + 1));
@@ -115,11 +117,13 @@ void stateblock_savedstates_set(
     states->vertexDecl = value;
     states->pixelShader = value;
     states->vertexShader = value;
+    states->dmapTexture = FALSE;
 
     /* Fixed size arrays */
     memset(states->streamSource, value, bsize * MAX_STREAMS);
     memset(states->streamFreq, value, bsize * MAX_STREAMS);
     memset(states->textures, value, bsize * MAX_SAMPLERS);
+    memset(states->vertexTextures, value, bsize * MAX_VERTEX_SAMPLERS);
     memset(states->transform, value, bsize * (HIGHEST_TRANSFORMSTATE + 1));
     memset(states->renderState, value, bsize * (WINEHIGHEST_RENDER_STATE + 1));
     memset(states->textureState, value, bsize * MAX_TEXTURES * (WINED3D_HIGHEST_TEXTURE_STATE + 1));
@@ -170,6 +174,8 @@ void stateblock_copy(
     Dest->vertex_blend = This->vertex_blend;
     Dest->tween_factor = This->tween_factor;
     Dest->glsl_program = This->glsl_program;
+    Dest->dmapTexture = This->dmapTexture;
+    Dest->dmapTextureDimensions = This->dmapTextureDimensions;
 
     /* Fixed size arrays */
     memcpy(Dest->vertexShaderConstantB, This->vertexShaderConstantB, sizeof(BOOL) * MAX_CONST_B);
@@ -187,6 +193,9 @@ void stateblock_copy(
     memcpy(Dest->renderState,  This->renderState,  sizeof(DWORD) * (WINEHIGHEST_RENDER_STATE + 1));
     memcpy(Dest->textures,     This->textures,     sizeof(IWineD3DBaseTexture*) * MAX_SAMPLERS);
     memcpy(Dest->textureDimensions, This->textureDimensions, sizeof(int) * MAX_SAMPLERS);
+    memcpy(Dest->vertexTextures,    This->vertexTextures,    sizeof(IWineD3DBaseTexture*) * MAX_VERTEX_SAMPLERS);
+    memcpy(Dest->vertexTextureDimensions, This->vertexTextureDimensions, sizeof(int) * MAX_VERTEX_SAMPLERS);
+
     memcpy(Dest->textureState, This->textureState, sizeof(DWORD) * MAX_TEXTURES * (WINED3D_HIGHEST_TEXTURE_STATE + 1));
     memcpy(Dest->samplerState, This->samplerState, sizeof(DWORD) * MAX_SAMPLERS * (WINED3D_HIGHEST_SAMPLER_STATE + 1));
 
@@ -261,15 +270,31 @@ static ULONG  WINAPI IWineD3DStateBlockI
             }
 
             /* NOTE: according to MSDN: The application is responsible for making sure the texture references are cleared down */
+
+            if (This->dmapTexture) {
+                /* release our 'internal' hold on the texture */
+                if (0 != IWineD3DBaseTexture_Release(This->dmapTexture))
+                    TRACE("Texture still referenced by stateblock, application has leaked "
+                        "(Stage = %u, Texture = %p)\n", D3DDMAPSAMPLER, This->dmapTexture);
+            }
+
             for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
                 if (This->textures[counter]) {
                     /* release our 'internal' hold on the texture */
-                    if(0 != IWineD3DBaseTexture_Release(This->textures[counter])) {
-                        TRACE("Texture still referenced by stateblock, applications has leaked Stage = %u Texture = %p\n", counter, This->textures[counter]);
-                    }
+                    if(0 != IWineD3DBaseTexture_Release(This->textures[counter]))
+                        TRACE("Texture still referenced by stateblock, application has leaked "
+                            "(Stage = %u, Texture = %p)\n", counter, This->textures[counter]);
                 }
             }
 
+            for (counter = 0; counter < GL_LIMITS(vertex_samplers); counter++) {
+                if (This->vertexTextures[counter]) {
+                    /* release our 'internal' hold on the texture */
+                    if (0 != IWineD3DBaseTexture_Release(This->vertexTextures[counter]))
+                        TRACE("Texture still referenced by stateblock, application has leaked "
+                            "(Stage = %u, Texture = %p)\n", D3DVERTEXTEXTURESAMPLER0 + counter, This->vertexTextures[counter]);
+                }
+            }
         }
 
         HeapFree(GetProcessHeap(), 0, This->vertexShaderConstantF);
@@ -586,6 +611,14 @@ static HRESULT  WINAPI IWineD3DStateBloc
 
         /* Samplers */
         /* TODO: move over to using memcpy */
+
+        if (This->set.dmapTexture) {
+            TRACE("Updating texture %d to %p (was %p)\n",
+                D3DDMAPSAMPLER, targetStateBlock->dmapTexture,  This->dmapTexture);
+            This->dmapTexture = targetStateBlock->dmapTexture;
+        }
+        /* FIXME: is sampler state allowed here? */
+
         for (j = 0; j < GL_LIMITS(sampler_stages); j++) {
             if (This->set.textures[j]) {
                 TRACE("Updating texture %d to %p (was %p)\n", j, targetStateBlock->textures[j],  This->textures[j]);
@@ -600,6 +633,16 @@ static HRESULT  WINAPI IWineD3DStateBloc
                 }
             }
         }
+
+        for (j = 0; j < GL_LIMITS(vertex_samplers); j++) {
+            if (This->set.vertexTextures[j]) {
+                TRACE("Updating texture %d to %p (was %p)\n",
+                    D3DVERTEXTEXTURESAMPLER0 + j, targetStateBlock->vertexTextures[j],  This->vertexTextures[j]);
+                This->vertexTextures[j] = targetStateBlock->vertexTextures[j];
+            }
+            /* FIXME: are sampler states allowed here? */
+        }
+
     }
 
     TRACE("(%p) : Updated state block %p ------------------^\n", targetStateBlock, This);
@@ -745,6 +788,12 @@ should really perform a delta so that on
 
         /* Samplers */
         /* TODO: move over to memcpy */
+
+        if (This->set.dmapTexture && This->changed.dmapTexture) {
+            IWineD3DDevice_SetTexture(pDevice, D3DDMAPSAMPLER, This->dmapTexture);
+        } 
+        /* FIXME: are sampler states allowed here? */
+
         for (j = 0 ; j < GL_LIMITS(sampler_stages); j++){
             if (This->set.textures[j] && This->changed.textures[j]) {
                 IWineD3DDevice_SetTexture(pDevice, j, This->textures[j]);
@@ -756,9 +805,16 @@ should really perform a delta so that on
                     ((IWineD3DDeviceImpl *)pDevice)->stateBlock->changed.samplerState[j][i] = TRUE;
                 }
             }
+        }
 
+        for (j = 0 ; j < GL_LIMITS(vertex_samplers); j++){
+            if (This->set.vertexTextures[j] && This->changed.vertexTextures[j]) {
+                IWineD3DDevice_SetTexture(pDevice, D3DVERTEXTEXTURESAMPLER0 + j, This->vertexTextures[j]);
+            }
+            /* FIXME: are sampler states allowed here? */
         }
 
+
     } else if (This->blockType == WINED3DSBT_PIXELSTATE) {
 
         for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
@@ -1023,6 +1079,8 @@ static HRESULT  WINAPI IWineD3DStateBloc
         This->samplerState[i][WINED3DSAMP_DMAPOFFSET       ] = 256; /* TODO: Vertex offset in the presampled displacement map */
     }
 
+    /* FIXME: does not account for vertex textures */
+
     /* Under DirectX you can have texture stage operations even if no texture is
        bound, whereas opengl will only do texture operations when a valid texture is
        bound. We emulate this by creating dummy textures and binding them to each
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index b859ade..6f1d984 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -48,6 +48,7 @@ #include "wine/list.h"
 #define MAX_PALETTES      256
 #define MAX_STREAMS       16
 #define MAX_TEXTURES      8
+#define MAX_VERTEX_SAMPLERS 4
 #define MAX_SAMPLERS      16
 #define MAX_ACTIVE_LIGHTS 8
 #define MAX_CLIPPLANES    D3DMAXUSERCLIPPLANES
@@ -1036,7 +1037,9 @@ typedef struct SAVEDSTATES {
         BOOL                      fvf;
         BOOL                      streamSource[MAX_STREAMS];
         BOOL                      streamFreq[MAX_STREAMS];
+        BOOL                      dmapTexture;
         BOOL                      textures[MAX_SAMPLERS];
+        BOOL                      vertexTextures[MAX_VERTEX_SAMPLERS];
         BOOL                      transform[HIGHEST_TRANSFORMSTATE + 1];
         BOOL                      viewport;
         BOOL                      renderState[WINEHIGHEST_RENDER_STATE + 1];
@@ -1132,8 +1135,12 @@ struct IWineD3DStateBlockImpl
     DWORD                     renderState[WINEHIGHEST_RENDER_STATE + 1];
 
     /* Texture */
+    IWineD3DBaseTexture      *dmapTexture;
     IWineD3DBaseTexture      *textures[MAX_SAMPLERS];
+    IWineD3DBaseTexture      *vertexTextures[MAX_VERTEX_SAMPLERS];
+    int                       dmapTextureDimensions;
     int                       textureDimensions[MAX_SAMPLERS];
+    int                       vertexTextureDimensions[MAX_VERTEX_SAMPLERS];
 
     /* Texture State Stage */
     DWORD                     textureState[MAX_TEXTURES][WINED3D_HIGHEST_TEXTURE_STATE + 1];
diff --git a/include/wine/wined3d_gl.h b/include/wine/wined3d_gl.h
index 1cc6409..4b73984 100644
--- a/include/wine/wined3d_gl.h
+++ b/include/wine/wined3d_gl.h
@@ -1756,6 +1756,7 @@ typedef struct _WineD3D_GL_Info {
   UINT   max_textures;
   UINT   max_texture_stages;
   UINT   max_samplers;
+  UINT   max_vertex_samplers;
   UINT   max_sampler_stages;
   UINT   max_clipplanes;
   UINT   max_texture_size;
-- 
1.4.2.1



More information about the wine-patches mailing list