[WINED3D 2] Hook software shaders into drawStridedSlow

Ivan Gyurdiev ivg231 at gmail.com
Fri Jul 7 01:21:28 CDT 2006


- split drawStridedSlow into "prepare" and "draw" segments -
  fixed_prepare_draw (vs swshader_prepare_draw), and draw_vertex.

- do not load or unload attribute arrays for software shaders
  make software shaders go through the drawStridedSlow code path

- disable VBOs for software shaders

- delete the old (disabled) swshader hook.
-------------- next part --------------
---
 dlls/wined3d/device.c          |    4 
 dlls/wined3d/drawprim.c        |  786 +++++++++++++---------------------------
 dlls/wined3d/wined3d_private.h |    9 
 3 files changed, 267 insertions(+), 532 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 7176954..a61eaae 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -732,10 +732,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl
      * dx7 apps.
      * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
      * more. In this call we can convert dx7 buffers too.
+     *
+     * Also, disable VBOs for software shaders.
      */
     conv = ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) || (FVF & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR));
     if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && 
-        (dxVersion > 7 || !conv) ) {
+        (dxVersion > 7 || !conv) && wined3d_settings.vs_selected_mode != SHADER_SW) {
         CreateVBO(object);
 
         /* DX7 buffers can be locked directly into the VBO(no conversion, see above */
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 7b9d133..e15f74b 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -791,137 +791,6 @@ #endif
     }
 }
 
-#if 0 /* TODO: Software Shaders */
-/* Draw a single vertex using this information */
-static void draw_vertex(IWineD3DDevice *iface,                         /* interface    */
-                 BOOL isXYZ,    float x, float y, float z, float rhw,  /* xyzn position*/
-                 BOOL isNormal, float nx, float ny, float nz,          /* normal       */
-                 BOOL isDiffuse, float *dRGBA,                         /* 1st   colors */
-                 BOOL isSpecular, float *sRGB,                         /* 2ndry colors */
-                 BOOL isPtSize, float ptSize,                       /* pointSize    */
-                 WINED3DVECTOR_4 *texcoords, int *numcoords)        /* texture info */
-{
-    unsigned int textureNo;
-    float s, t, r, q;
-    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-
-    /* Diffuse -------------------------------- */
-    if (isDiffuse) {
-        glColor4fv(dRGBA);
-        VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
-    }
-
-    /* Specular Colour ------------------------------------------*/
-    if (isSpecular) {
-        if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
-          GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
-          VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
-        } else {
-	  VTRACE(("Specular color extensions not supplied\n"));
-	}
-    }
-
-    /* Normal -------------------------------- */
-    if (isNormal) {
-        VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
-        glNormal3f(nx, ny, nz);
-    }
-
-    /* Point Size ----------------------------------------------*/
-    if (isPtSize) {
-
-        /* no such functionality in the fixed function GL pipeline */
-        FIXME("Cannot change ptSize here in openGl\n");
-    }
-
-    /* Texture coords --------------------------- */
-    for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
-
-        if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
-            FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
-            continue ;
-        }
-
-        /* Query tex coords */
-        if (This->stateBlock->textures[textureNo] != NULL) {
-
-            int    coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
-            if (coordIdx >= MAX_TEXTURES) {
-                VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
-                continue;
-            } else if (numcoords[coordIdx] == 0) {
-                TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
-                continue;
-            } else {
-
-                /* Initialize vars */
-                s = 0.0f;
-                t = 0.0f;
-                r = 0.0f;
-                q = 0.0f;
-
-                switch (numcoords[coordIdx]) {
-                case 4: q = texcoords[coordIdx].w; /* drop through */
-                case 3: r = texcoords[coordIdx].z; /* drop through */
-                case 2: t = texcoords[coordIdx].y; /* drop through */
-                case 1: s = texcoords[coordIdx].x;
-                }
-
-                switch (numcoords[coordIdx]) {   /* Supply the provided texture coords */
-                case D3DTTFF_COUNT1:
-                    VTRACE(("tex:%d, s=%f\n", textureNo, s));
-                    if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-                        GLMULTITEXCOORD1F(textureNo, s);
-                    } else {
-                        glTexCoord1f(s);
-                    }
-                    break;
-                case D3DTTFF_COUNT2:
-                    VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
-                    if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-                        GLMULTITEXCOORD2F(textureNo, s, t);
-                    } else {
-                        glTexCoord2f(s, t);
-                    }
-                    break;
-                case D3DTTFF_COUNT3:
-                    VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
-                    if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-                        GLMULTITEXCOORD3F(textureNo, s, t, r);
-                    } else {
-                        glTexCoord3f(s, t, r);
-                    }
-                    break;
-                case D3DTTFF_COUNT4:
-                    VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
-                    if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-                        GLMULTITEXCOORD4F(textureNo, s, t, r, q);
-                    } else {
-                        glTexCoord4f(s, t, r, q);
-                    }
-                    break;
-                default:
-                    FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
-                }
-            }
-        }
-    } /* End of textures */
-
-    /* Position -------------------------------- */
-    if (isXYZ) {
-        if (1.0f == rhw || rhw < 0.00001f) {
-            VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
-            glVertex3f(x, y, z);
-        } else {
-            /* Cannot optimize by dividing through by rhw as rhw is required
-               later for perspective in the GL pipeline for vertex shaders   */
-            VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
-            glVertex4f(x,y,z,rhw);
-        }
-    }
-}
-#endif /* TODO: Software shaders */
-
 void loadNumberedArrays(
     IWineD3DDevice *iface, 
     WineDirect3DVertexStridedData *sd, 
@@ -1400,350 +1269,275 @@ #endif
     return;
 }
 
-/*
- * Actually draw using the supplied information.
- * Slower GL version which extracts info about each vertex in turn
- */
-	
-static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
-                     UINT NumVertexes, GLenum glPrimType,
-                     const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
-
-    unsigned int               textureNo    = 0;
-    unsigned int               texture_idx  = 0;
-    const short               *pIdxBufS     = NULL;
-    const long                *pIdxBufL     = NULL;
-    LONG                       SkipnStrides = 0;
-    LONG                       vx_index;
-    float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
-    float nx = 0.0f, ny = 0.0, nz = 0.0f;  /* normal x,y,z coordinates   */
-    float rhw = 0.0f;                      /* rhw                        */
-    float ptSize = 0.0f;                   /* Point size                 */
-    DWORD diffuseColor = 0xFFFFFFFF;       /* Diffuse Color              */
-    DWORD specularColor = 0;               /* Specular Color             */
-    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-
-    TRACE("Using slow vertex array code\n");
+static inline void swshader_prepare_draw(
+    IWineD3DDeviceImpl* This,
+    WineDirect3DVertexStridedData *strided,
+    int skip_strides,
+    draw_context* draw) {
+
+    This = NULL;
+    strided = NULL;
+    skip_strides = 0;
+    draw = NULL;
+    FIXME("Stub\n");
+}
 
-    /* Variable Initialization */
-    if (idxData != NULL) {
-        if (idxSize == 2) pIdxBufS = (const short *) idxData;
-        else pIdxBufL = (const long *) idxData;
+static inline void fixed_prepare_draw(
+    IWineD3DDeviceImpl* This,
+    WineDirect3DVertexStridedData *strided,
+    int skip_strides,
+    draw_context* draw) {
+
+    int i, textureNo;
+
+    const WINED3DSHADERVECTOR def_position = { 0.0f, 0.0f, 0.0f, 0.0f };
+    const WINED3DSHADERVECTOR def_diffuse = { 1.0f, 1.0f, 1.0f, 1.0f };
+    const WINED3DSHADERVECTOR def_specular = { 0.0f, 0.0f, 0.0f, 1.0f };
+    const WINED3DSHADERVECTOR def_normal = { 0.0f, 0.0f, 1.0f, 0.0f };
+    const WINED3DSHADERVECTOR def_texcoord = { 0.0f, 0.0f, 0.0f, 1.0f };
+
+    /* Defaults */
+    draw->is_transformed = FALSE;
+    memcpy(&draw->diffuse, &def_diffuse, sizeof(WINED3DSHADERVECTOR));
+    memcpy(&draw->specular, &def_specular, sizeof(WINED3DSHADERVECTOR));
+    memcpy(&draw->position, &def_position, sizeof(WINED3DSHADERVECTOR));
+    memcpy(&draw->normal, &def_normal, sizeof(WINED3DSHADERVECTOR));
+    for (i = 0; i < GL_LIMITS(texture_stages); i++) {
+        if (This->stateBlock->textures[i] != NULL)
+            memcpy(&draw->texcoords[i], &def_texcoord, sizeof(WINED3DSHADERVECTOR));
     }
 
-    /* Start drawing in GL */
-    VTRACE(("glBegin(%x)\n", glPrimType));
-    glBegin(glPrimType);
+    /* Position ---------------------------- */
+    if (strided->u.s.position.lpData) {
+        float *ptrToCoords =
+            (float *)(strided->u.s.position.lpData + (skip_strides * strided->u.s.position.dwStride));
 
-    /* We shouldn't start this function if any VBO is involved. Should I put a safety check here?
-     * Guess it's not necessary(we crash then anyway) and would only eat CPU time
-     */
+        draw->position.x = ptrToCoords[0];
+        draw->position.y = ptrToCoords[1];
+        draw->position.z = ptrToCoords[2];
+        draw->position.w = 1.0;
 
-    /* For each primitive */
-    for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
+        /* Data contains rhw */
+        if (strided->u.s.position.dwType == D3DDECLTYPE_FLOAT4) {
+            float rhw = ptrToCoords[3];
 
-        /* Initialize diffuse color */
-        diffuseColor = 0xFFFFFFFF;
+            draw->is_transformed = TRUE;
 
-        /* For indexed data, we need to go a few more strides in */
-        if (idxData != NULL) {
+            /* FIXUP: divide by rhw */
+            if (rhw > eps && rhw < -eps) {
+               draw->position.w = 1.0 / rhw;
+               draw->position.x /= rhw;
+               draw->position.y /= rhw;
+               draw->position.z /= rhw;
 
-            /* Indexed so work out the number of strides to skip */
-            if (idxSize == 2) {
-                VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
-                SkipnStrides = pIdxBufS[startIdx + vx_index];
-            } else {
-                VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
-                SkipnStrides = pIdxBufL[startIdx + vx_index];
-            }
+            } else draw->position.w = rhw;
         }
+        VTRACE(("position = { %f, %f, %f, %f }\n",
+            draw->position.x, draw->position.y, draw->position.z, draw->position.w));
+    }
 
-        /* Position Information ------------------ */
-        if (sd->u.s.position.lpData != NULL) {
+    /* Normal --------------------------------- */
+    if (strided->u.s.normal.lpData) {
+        float *ptrToCoords =
+            (float *)(strided->u.s.normal.lpData + (skip_strides * strided->u.s.normal.dwStride));
+        draw->normal.x = ptrToCoords[0];
+        draw->normal.y = ptrToCoords[1];
+        draw->normal.z = ptrToCoords[2];
+        VTRACE(("normal = { %f, %f, %f }\n", draw->normal.x, draw->normal.y, draw->normal.z));
+   }
+
+   /* Diffuse -------------------------------- */
+   if (strided->u.s.diffuse.lpData) {
+
+        DWORD *ptrToCoords =
+            (DWORD *)(strided->u.s.diffuse.lpData + (skip_strides * strided->u.s.diffuse.dwStride));
+        draw->diffuse.x = D3DCOLOR_B(ptrToCoords[0]);
+        draw->diffuse.y = D3DCOLOR_G(ptrToCoords[0]);
+        draw->diffuse.z = D3DCOLOR_R(ptrToCoords[0]);
+        draw->diffuse.w = D3DCOLOR_A(ptrToCoords[0]);
+        VTRACE(("diffuse = { %f, %f, %f, %f }\n",
+            draw->diffuse.x, draw->diffuse.y, draw->diffuse.z, draw->diffuse.w));
+    }
+    /* Specular  -------------------------------- */
+    if (strided->u.s.specular.lpData) {
+
+        DWORD *ptrToCoords =
+            (DWORD *)(strided->u.s.specular.lpData + (skip_strides * strided->u.s.specular.dwStride));
+        draw->specular.x = D3DCOLOR_B(ptrToCoords[0]);
+        draw->specular.y = D3DCOLOR_G(ptrToCoords[0]);
+        draw->specular.z = D3DCOLOR_R(ptrToCoords[0]);
+        draw->specular.w = D3DCOLOR_A(ptrToCoords[0]);
+        VTRACE(("specular = { %f, %f, %f, %f }\n",
+            draw->specular.x, draw->specular.y, draw->specular.z, draw->specular.w));
+    }
 
-            float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
-            x = ptrToCoords[0];
-            y = ptrToCoords[1];
-            z = ptrToCoords[2];
-            rhw = 1.0;
-            VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
+    /* Blending ---------------------------------- */
+    if (strided->u.s.blendWeights.lpData != NULL ||
+        strided->u.s.blendMatrixIndices.lpData != NULL) {
 
-            /* RHW follows, only if transformed, ie 4 floats were provided */
-            if (sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4) {
-                rhw = ptrToCoords[3];
-                VTRACE(("rhw=%f\n", rhw));
-            }
-        }
+        FIXME("Blending not supported yet\n");
+    }
 
-        /* Blending data -------------------------- */
-        if (sd->u.s.blendWeights.lpData != NULL) {
-            /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */
-            FIXME("Blending not supported yet\n");
+    /* Point Size -------------------------------- */
+    if (strided->u.s.pSize.lpData != NULL) {
 
-            if (sd->u.s.blendMatrixIndices.lpData != NULL) {
-                /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
-            }
-        }
+        FIXME("Point Size not supported yet\n");
+    }
 
-        /* Vertex Normal Data (untransformed only)- */
-        if (sd->u.s.normal.lpData != NULL) {
+    /* Texture ---------------------------------- */
+    for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
 
-            float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
-            nx = ptrToCoords[0];
-            ny = ptrToCoords[1];
-            nz = ptrToCoords[2];
-            VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
-        }
+        unsigned int idx;
+        if (This->stateBlock->textures[textureNo] == NULL)
+            continue;
 
-        /* Point Size ----------------------------- */
-        if (sd->u.s.pSize.lpData != NULL) {
+        idx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
+        if (strided->u.s.texCoords[idx].lpData) {
+
+            float* ptrToCoords =
+                (float *)(strided->u.s.texCoords[idx].lpData + (skip_strides * strided->u.s.texCoords[idx].dwStride));
+            unsigned int numcoords = strided->u.s.texCoords[idx].dwType + 1;
+            switch (numcoords) {
+                case 4: draw->texcoords[textureNo].w = ptrToCoords[3]; /* drop through */
+                case 3: draw->texcoords[textureNo].z = ptrToCoords[2]; /* drop through */
+                case 2: draw->texcoords[textureNo].y = ptrToCoords[1]; /* drop through */
+                case 1: draw->texcoords[textureNo].x = ptrToCoords[0];
+             }
+
+           /* Projected is more 'fun' - Move the last coord to the 'q'
+            *  parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
+           if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
+               (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
+
+               if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
+                   switch (numcoords) {
+                       case 0:  /* Drop Through */
+                       case 1:
+                           FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
+                           break;
+                       case 2:
+                           draw->texcoords[textureNo].w = draw->texcoords[textureNo].y;
+                           draw->texcoords[textureNo].y = 0.0;
+                           break;
+                       case 3:
+                           draw->texcoords[textureNo].w = draw->texcoords[textureNo].z;
+                           draw->texcoords[textureNo].z = 0.0;
+                           break;
+                       case 4:  /* Nop here */
+                           break;
+                       default:
+                           FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
+                               This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] &
+                               D3DTTFF_PROJECTED);
+                   }
+               }
+           }
 
-            float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
-            ptSize = ptrToCoords[0];
-            VTRACE(("ptSize=%f\n", ptSize));
-            FIXME("No support for ptSize yet\n");
-        }
+           VTRACE(("tex: %d (%u coords) = { %f %f %f %f }\n", idx,
+               numcoords, draw->texcoords[textureNo].x, draw->texcoords[textureNo].y,
+                          draw->texcoords[textureNo].z, draw->texcoords[textureNo].w));
+         }
+    }
+}
 
-        /* Diffuse -------------------------------- */
-        if (sd->u.s.diffuse.lpData != NULL) {
+/* Draw a single vertex using the supplied data */
+static inline void draw_vertex(
+    IWineD3DDeviceImpl* This,
+    draw_context* draw) {
 
-            DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
-            diffuseColor = ptrToCoords[0];
-            VTRACE(("diffuseColor=%lx\n", diffuseColor));
-        }
+    unsigned int textureNo, texture_idx;
 
-        /* Specular  -------------------------------- */
-        if (sd->u.s.specular.lpData != NULL) {
+    /* Draw Vertex: Texture coords --------------------------- */
+    for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
 
-            DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
-            specularColor = ptrToCoords[0];
-            VTRACE(("specularColor=%lx\n", specularColor));
+        if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
+            FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
+            continue ;
         }
 
-        /* Texture coords --------------------------- */
-        for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
-
-            if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
-                FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
-                continue ;
-            }
-
-            /* Query tex coords */
-            if (This->stateBlock->textures[textureNo] != NULL) {
-
-                int    coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
-                float *ptrToCoords = NULL;
-                float  s = 0.0, t = 0.0, r = 0.0, q = 0.0;
-
-                if (coordIdx > 7) {
-                    VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
-                    continue;
-                } else if (coordIdx < 0) {
-                    FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx);
-                    continue;
-                }
-
-                ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
-                if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
-                    TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
-                    continue;
-                } else {
-
-                    int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
-
-                    /* The coords to supply depend completely on the fvf / vertex shader */
-                    switch (coordsToUse) {
-                    case 4: q = ptrToCoords[3]; /* drop through */
-                    case 3: r = ptrToCoords[2]; /* drop through */
-                    case 2: t = ptrToCoords[1]; /* drop through */
-                    case 1: s = ptrToCoords[0];
-                    }
-
-                    /* Projected is more 'fun' - Move the last coord to the 'q'
-                          parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
-                    if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
-                        (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
-
-                        if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
-                            switch (coordsToUse) {
-                            case 0:  /* Drop Through */
-                            case 1:
-                                FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
-                                break;
-                            case 2:
-                                q = t;
-                                t = 0.0;
-                                coordsToUse = 4;
-                                break;
-                            case 3:
-                                q = r;
-                                r = 0.0;
-                                coordsToUse = 4;
-                                break;
-                            case 4:  /* Nop here */
-                                break;
-                            default:
-                                FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
-                                      This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
-                            }
-                        }
-                    }
-
-                    switch (coordsToUse) {   /* Supply the provided texture coords */
-                    case D3DTTFF_COUNT1:
-                        VTRACE(("tex:%d, s=%f\n", textureNo, s));
-                        if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-                            GL_EXTCALL(glMultiTexCoord1fARB(texture_idx, s));
-                        } else {
-                            glTexCoord1f(s);
-                        }
-                        break;
-                    case D3DTTFF_COUNT2:
-                        VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
-                        if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-                            GL_EXTCALL(glMultiTexCoord2fARB(texture_idx, s, t));
-                        } else {
-                            glTexCoord2f(s, t);
-                        }
-                        break;
-                    case D3DTTFF_COUNT3:
-                        VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
-                        if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-                            GL_EXTCALL(glMultiTexCoord3fARB(texture_idx, s, t, r));
-                        } else {
-                            glTexCoord3f(s, t, r);
-                        }
-                        break;
-                    case D3DTTFF_COUNT4:
-                        VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
-                        if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-                            GL_EXTCALL(glMultiTexCoord4fARB(texture_idx, s, t, r, q));
-                        } else {
-                            glTexCoord4f(s, t, r, q);
-                        }
-                        break;
-                    default:
-                        FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
-                    }
-                }
-            }
-            if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx;
-        } /* End of textures */
-
-        /* Diffuse -------------------------------- */
-        if (sd->u.s.diffuse.lpData != NULL) {
-	  glColor4ub(D3DCOLOR_B_R(diffuseColor),
-		     D3DCOLOR_B_G(diffuseColor),
-		     D3DCOLOR_B_B(diffuseColor),
-		     D3DCOLOR_B_A(diffuseColor));
-            VTRACE(("glColor4ub: r,g,b,a=%lu,%lu,%lu,%lu\n", 
-                    D3DCOLOR_B_R(diffuseColor),
-		    D3DCOLOR_B_G(diffuseColor),
-		    D3DCOLOR_B_B(diffuseColor),
-		    D3DCOLOR_B_A(diffuseColor)));
-        } else {
-            if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
-        }
+        if (This->stateBlock->textures[textureNo] != NULL) {
 
-        /* Specular ------------------------------- */
-        if (sd->u.s.specular.lpData != NULL) {
-            /* special case where the fog density is stored in the diffuse alpha channel */
-            if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] &&
-              (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == D3DFOG_NONE || sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4 )&&
-              This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
-                if(GL_SUPPORT(EXT_FOG_COORD)) {
-                    GL_EXTCALL(glFogCoordfEXT(specularColor >> 24));
-                } else {
-                    static BOOL warned = FALSE;
-                    if(!warned) {
-                        /* TODO: Use the fog table code from old ddraw */
-                        FIXME("Implement fog for transformed vertices in software\n");
-                        warned = TRUE;
-                    }
-                }
-            }
+            float s = draw->texcoords[textureNo].x;
+            float t = draw->texcoords[textureNo].y;
+            float r = draw->texcoords[textureNo].z;
+            float q = draw->texcoords[textureNo].w;
 
-            VTRACE(("glSecondaryColor4ub: r,g,b=%lu,%lu,%lu\n", 
-                    D3DCOLOR_B_R(specularColor), 
-                    D3DCOLOR_B_G(specularColor), 
-                    D3DCOLOR_B_B(specularColor)));
-            if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
-                GL_EXTCALL(glSecondaryColor3ubEXT)(
-                           D3DCOLOR_B_R(specularColor),
-                           D3DCOLOR_B_G(specularColor),
-                           D3DCOLOR_B_B(specularColor));
-            } else {
-                /* Do not worry if specular colour missing and disable request */
-                VTRACE(("Specular color extensions not supplied\n"));
-            }
-        } else {
-            if (vx_index == 0) {
-                if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
-                    GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
-                } else {
-                    /* Do not worry if specular colour missing and disable request */
-                    VTRACE(("Specular color extensions not supplied\n"));
-                }
-            }
+            VTRACE(("DRAW tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
+            if (GL_SUPPORT(ARB_MULTITEXTURE))
+                GL_EXTCALL(glMultiTexCoord4fARB(texture_idx, s, t, r, q));
+            else
+                glTexCoord4f(s, t, r, q);
         }
+        if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx;
+    } /* End of textures */
 
-        /* Normal -------------------------------- */
-        if (sd->u.s.normal.lpData != NULL) {
-            VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
-            glNormal3f(nx, ny, nz);
-        } else {
-            if (vx_index == 0) glNormal3f(0, 0, 1);
-        }
+    /* Draw Vertex: Diffuse -------------------------------- */
+    glColor4f(draw->diffuse.z, draw->diffuse.y, draw->diffuse.x, draw->diffuse.w);
+    VTRACE(("DRAW diffuse: r,g,b,a=%f,%f,%f,%f\n",
+        draw->diffuse.z, draw->diffuse.y, draw->diffuse.x, draw->diffuse.w));
+
+    /* Draw Vertex: Fog (non-table, non-vertex)  ------------------------------- */
+    /* special case where the fog density is stored in the diffuse alpha channel */
+    /* FIXME: then why is this looking in the specular alpha channel? */
+    if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] &&
+      (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == D3DFOG_NONE || draw->is_transformed ) &&
+       This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
+
+       if (GL_SUPPORT(EXT_FOG_COORD))
+           GL_EXTCALL(glFogCoordfEXT(draw->specular.w));
+
+       else {
+           static BOOL warned = FALSE;
+           if(!warned) {
+               /* TODO: Use the fog table code from old ddraw */
+               FIXME("Implement fog for transformed vertices in software\n");
+               warned = TRUE;
+           }
+       }
+    }
 
-        /* Position -------------------------------- */
-        if (sd->u.s.position.lpData != NULL) {
-            if (1.0f == rhw || ((rhw < eps) && (rhw > -eps))) {
-                VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
-                glVertex3f(x, y, z);
-            } else {
-                GLfloat w = 1.0 / rhw;
-                VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
-                glVertex4f(x*w, y*w, z*w, w);
-            }
-        }
+    /* Draw Vertex: Specular ------------------------------- */
+    VTRACE(("DRAW specular: r,g,b=%f,%f,%f\n",
+        draw->specular.z, draw->specular.y, draw->specular.x));
+    if (GL_SUPPORT(EXT_SECONDARY_COLOR))
+        GL_EXTCALL(glSecondaryColor3fEXT(draw->specular.z, draw->specular.y, draw->specular.x));
+    else
+        /* Do not worry if specular colour missing and disable request */
+        VTRACE(("Specular color extensions not supplied\n"));
 
-        /* For non indexed mode, step onto next parts */
-        if (idxData == NULL) {
-            ++SkipnStrides;
-        }
-    }
+    /* Draw Vertex: Normal -------------------------------- */
+    VTRACE(("DRAW normal:nx,ny,nz=%f,%f,%f\n", draw->normal.x, draw->normal.y, draw->normal.z));
+    glNormal3f(draw->normal.x, draw->normal.y, draw->normal.z);
 
-    glEnd();
-    checkGLcall("glEnd and previous calls");
+    /* Draw Vertex: Position -------------------------------- */
+    VTRACE(("DRAW position: x,y,z,w=%f,%f,%f,%f\n",
+        draw->position.x, draw->position.y, draw->position.z, draw->position.w));
+    glVertex4f(draw->position.x, draw->position.y, draw->position.z, draw->position.w);
 }
 
-#if 0 /* TODO: Software/Hardware vertex blending support */
 /*
- * Draw with emulated vertex shaders
- * Note: strided data is uninitialized, as we need to pass the vertex
- *     shader directly as ordering irs yet
+ * Actually draw using the supplied information.
+ * Slower GL version which extracts info about each vertex in turn
  */
-void drawStridedSoftwareVS(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
-                     int PrimitiveType, ULONG NumPrimitives,
-                     const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
 
-    unsigned int               textureNo    = 0;
-    GLenum                     glPrimType   = GL_POINTS;
-    int                        NumVertexes  = NumPrimitives;
+static void drawStridedSlow(
+    IWineD3DDevice *iface,
+    WineDirect3DVertexStridedData *strided,
+    UINT NumVertexes,
+    GLenum glPrimType,
+    const void *idxData,
+    short idxSize,
+    ULONG minIndex,
+    ULONG startIdx,
+    BOOL software_shader) {
+
     const short               *pIdxBufS     = NULL;
     const long                *pIdxBufL     = NULL;
     LONG                       SkipnStrides = 0;
     LONG                       vx_index;
-    float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
-    float rhw = 0.0f;                      /* rhw                        */
-    float ptSize = 0.0f;                   /* Point size                 */
-    D3DVECTOR_4 texcoords[8];              /* Texture Coords             */
-    int   numcoords[8];                    /* Number of coords           */
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
 
-    IDirect3DVertexShaderImpl* vertexShader = NULL;
-
-    TRACE("Using slow software vertex shader code\n");
+    TRACE("Using slow vertex array code\n");
 
     /* Variable Initialization */
     if (idxData != NULL) {
@@ -1751,115 +1545,44 @@ void drawStridedSoftwareVS(IWineD3DDevic
         else pIdxBufL = (const long *) idxData;
     }
 
-    /* Ok, Work out which primitive is requested and how many vertexes that will be */
-    NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
-
-    /* Retrieve the VS information */
-    vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader;
-
     /* Start drawing in GL */
     VTRACE(("glBegin(%x)\n", glPrimType));
     glBegin(glPrimType);
 
-    /* For each primitive */
-    for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
+     /* For each primitive */
+     for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
 
-        /* For indexed data, we need to go a few more strides in */
-        if (idxData != NULL) {
+         draw_context draw;
 
-            /* Indexed so work out the number of strides to skip */
-            if (idxSize == 2) {
-                VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
-                SkipnStrides = pIdxBufS[startIdx+vx_index];
-            } else {
-                VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
-                SkipnStrides = pIdxBufL[startIdx+vx_index];
-            }
-        }
+         /* For indexed data, we need to go a few more strides in */
+         if (idxData != NULL) {
 
-        /* Fill the vertex shader input */
-        IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides);
-
-        /* Initialize the output fields to the same defaults as it would normally have */
-        memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8));
-        vertexShader->output.oD[0].x = 1.0;
-        vertexShader->output.oD[0].y = 1.0;
-        vertexShader->output.oD[0].z = 1.0;
-        vertexShader->output.oD[0].w = 1.0;
-
-        /* Now execute the vertex shader */
-        IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output);
-
-        /*
-        TRACE_VECTOR(vertexShader->output.oPos);
-        TRACE_VECTOR(vertexShader->output.oD[0]);
-        TRACE_VECTOR(vertexShader->output.oD[1]);
-        TRACE_VECTOR(vertexShader->output.oT[0]);
-        TRACE_VECTOR(vertexShader->output.oT[1]);
-        TRACE_VECTOR(vertexShader->input.V[0]);
-        TRACE_VECTOR(vertexShader->data->C[0]);
-        TRACE_VECTOR(vertexShader->data->C[1]);
-        TRACE_VECTOR(vertexShader->data->C[2]);
-        TRACE_VECTOR(vertexShader->data->C[3]);
-        TRACE_VECTOR(vertexShader->data->C[4]);
-        TRACE_VECTOR(vertexShader->data->C[5]);
-        TRACE_VECTOR(vertexShader->data->C[6]);
-        TRACE_VECTOR(vertexShader->data->C[7]);
-        */
+             /* Indexed so work out the number of strides to skip */
+             if (idxSize == 2) {
+                 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
+                 SkipnStrides = pIdxBufS[startIdx + vx_index];
+             } else {
+                 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
+                 SkipnStrides = pIdxBufL[startIdx + vx_index];
+             }
+         }
 
-        /* Extract out the output */
-        /* FIXME: Fog coords? */
-        x = vertexShader->output.oPos.x;
-        y = vertexShader->output.oPos.y;
-        z = vertexShader->output.oPos.z;
-        rhw = vertexShader->output.oPos.w;
-        ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */
-
-        /** Update textures coords using vertexShader->output.oT[0->7] */
-        memset(texcoords, 0x00, sizeof(texcoords));
-        memset(numcoords, 0x00, sizeof(numcoords));
-        for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
-            if (This->stateBlock->textures[textureNo] != NULL) {
-               texcoords[textureNo].x = vertexShader->output.oT[textureNo].x;
-               texcoords[textureNo].y = vertexShader->output.oT[textureNo].y;
-               texcoords[textureNo].z = vertexShader->output.oT[textureNo].z;
-               texcoords[textureNo].w = vertexShader->output.oT[textureNo].w;
-               if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
-                   numcoords[textureNo]    = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
-               } else {
-                   switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
-                   case WINED3DRTYPE_TEXTURE:       numcoords[textureNo] = 2; break;
-                   case WINED3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
-                   default:                         numcoords[textureNo] = 4;
-                   }
-               }
-            } else {
-                numcoords[textureNo] = 0;
-            }
-        }
+        if (software_shader)
+            swshader_prepare_draw(This, strided, SkipnStrides, &draw);
+        else
+            fixed_prepare_draw(This, strided, SkipnStrides, &draw);
 
-        /* Draw using this information */
-        draw_vertex(iface,
-                    TRUE, x, y, z, rhw,
-                    TRUE, 0.0f, 0.0f, 1.0f,
-                    TRUE, (float*) &vertexShader->output.oD[0],
-                    TRUE, (float*) &vertexShader->output.oD[1],
-                    FALSE, ptSize,         /* FIXME: Change back when supported */
-                    texcoords, numcoords);
-
-        /* For non indexed mode, step onto next parts */
-        if (idxData == NULL) {
-           ++SkipnStrides;
-        }
+        draw_vertex(This, &draw);
 
-    } /* for each vertex */
+         /* For non indexed mode, step onto next parts */
+        if (idxData == NULL)
+            ++SkipnStrides;
+    }
 
     glEnd();
     checkGLcall("glEnd and previous calls");
 }
 
-#endif
-
 static inline void drawPrimitiveDrawStrided(
     IWineD3DDevice *iface,
     BOOL useVertexShaderFunction,
@@ -1913,8 +1636,8 @@ #undef BUFFER_OR_DATA
         loadVertexData(iface, dataLocations);
         useDrawStridedSlow = FALSE;
 
-    /* Shader pipeline - load attribute arrays */
-    } else if(useVertexShaderFunction) {
+    /* Hardware Shader pipeline - load attribute arrays */
+    } else if(useVertexShaderFunction && wined3d_settings.vs_selected_mode != SHADER_SW) {
 
         loadNumberedArrays(iface, dataLocations, 
             ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->semantics_in);
@@ -1988,12 +1711,13 @@ #undef BUFFER_OR_DATA
         
     /* Draw vertex-by-vertex */
     if (useDrawStridedSlow)
-        drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType, idxData, idxSize, minIndex,  StartIdx);
+        drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType,
+            idxData, idxSize, minIndex, StartIdx, useVertexShaderFunction);
     else
         drawStridedFast(iface, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx);
 
     /* Cleanup vertex program */
-    if (useVertexShaderFunction) {
+    if (useVertexShaderFunction && wined3d_settings.vs_selected_mode != SHADER_SW) {
         /* disable any attribs (this is the same for both GLSL and ARB modes) */
         GLint maxAttribs;
         int i;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index a71539a..e70a9a0 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1284,6 +1284,15 @@ #define MAX_CONST_F 256
 #define MAX_CONST_I 16
 #define MAX_CONST_B 16
 
+typedef struct draw_context {
+    WINED3DSHADERVECTOR position;
+    WINED3DSHADERVECTOR diffuse;
+    WINED3DSHADERVECTOR specular;
+    WINED3DSHADERVECTOR texcoords[D3DDP_MAXTEXCOORD];
+    WINED3DSHADERVECTOR normal;
+    BOOL is_transformed;
+} draw_context;
+
 typedef struct shader_reg_maps {
 
     char texcoord[MAX_REG_TEXCRD];          /* pixel < 3.0 */
-- 
1.4.0



More information about the wine-patches mailing list