[Bug 25298] Divinity2 crashes

wine-bugs at winehq.org wine-bugs at winehq.org
Sat Feb 5 13:30:40 CST 2011


http://bugs.winehq.org/show_bug.cgi?id=25298

--- Comment #26 from Vadim <vadim.home at gmail.com> 2011-02-05 13:30:39 CST ---
(From update of attachment 33150)
diff -Naur a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
--- a/dlls/wined3d/directx.c    2011-02-03 14:37:38.000000000 +0300
+++ b/dlls/wined3d/directx.c    2011-02-05 22:04:50.000000000 +0300
@@ -4489,8 +4489,13 @@
     caps->MaxUserClipPlanes = gl_info->limits.clipplanes;
     caps->MaxActiveLights = gl_info->limits.lights;

-    caps->MaxVertexBlendMatrices = gl_info->limits.blends;
-    caps->MaxVertexBlendMatrixIndex   = 0;
+    if (gl_info->supported[ARB_VERTEX_BLEND]) {
+        caps->MaxVertexBlendMatrices    = gl_info->limits.blends;
+        caps->MaxVertexBlendMatrixIndex = 0;
+    } else {
+        caps->MaxVertexBlendMatrices    = 4;
+        caps->MaxVertexBlendMatrixIndex = 255;
+    }

     caps->MaxAnisotropy = gl_info->limits.anisotropy;
     caps->MaxPointSize = gl_info->limits.pointsize_max;
diff -Naur a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
--- a/dlls/wined3d/drawprim.c   2011-01-29 03:46:55.000000000 +0300
+++ b/dlls/wined3d/drawprim.c   2011-02-05 22:04:50.000000000 +0300
@@ -50,6 +50,75 @@
 }

 /*
+ * Emit a vertex using swoftware vertex blending
+ */
+static void emitBlendedVertex(struct wined3d_stateblock *stateBlock,
+                              const float *weights, int nweights, const BYTE
*indices,
+                              const float *pos, const float *norm)
+{
+    const float *m;
+    float        vec[4];
+    float        mat[4*4];
+    float        last = 1.f;
+    int          i, j;
+
+    /* compute the weighted sum of the matrices */
+    m = &stateBlock->state.transforms[WINED3DTS_WORLDMATRIX((indices ?
indices[0] : 0))].u.m[0][0];
+    for (j = 0; j < 16; j++)
+        mat[j] = m[j] * weights[0];
+    last -= weights[0];
+
+    for (i = 1; i < nweights; i++) {
+        if (weights[i]) {
+            m = &stateBlock->state.transforms[WINED3DTS_WORLDMATRIX((indices ?
indices[i] : i))].u.m[0][0];
+            for (j = 0; j < 16; j++)
+                mat[j] += m[j] * weights[i];
+            last -= weights[i];
+        }
+    }
+
+    /* do the last */
+    if (last) {
+        m = &stateBlock->state.transforms[WINED3DTS_WORLDMATRIX((indices ?
indices[i] : i))].u.m[0][0];
+        for (j = 0; j < 16; j++)
+            mat[j] += m[j] * last;
+    }
+
+    if (norm) {
+        /* compute the resulting normal */
+        vec[0] = norm[0] * mat[0] + norm[1] * mat[4] + norm[2] * mat[8];
+        vec[1] = norm[0] * mat[1] + norm[1] * mat[5] + norm[2] * mat[9];
+        vec[2] = norm[0] * mat[2] + norm[1] * mat[6] + norm[2] * mat[10];
+        /* normalize */
+        vec[3] = vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2];
+        if (vec[3]) {
+            vec[3] = 1.f / sqrtf(vec[3]);
+            vec[0] *= vec[3];
+            vec[1] *= vec[3];
+            vec[2] *= vec[3];
+        }
+
+        glNormal3fv(vec);
+    }
+
+    if (pos) {
+        /* compute the resulting position */
+        vec[0] = pos[0] * mat[0] + pos[1] * mat[4] + pos[2] * mat[8] +
mat[12];
+        vec[1] = pos[0] * mat[1] + pos[1] * mat[5] + pos[2] * mat[9] +
mat[13];
+        vec[2] = pos[0] * mat[2] + pos[1] * mat[6] + pos[2] * mat[10] +
mat[14];
+        vec[3] = pos[0] * mat[3] + pos[1] * mat[7] + pos[2] * mat[11] +
mat[15];
+        /* normalize */
+        if (vec[3]) {
+            vec[0] /= vec[3];
+            vec[1] /= vec[3];
+            vec[2] /= vec[3];
+        }
+
+        glVertex3fv(vec);
+    }
+}
+
+/*
  * Actually draw using the supplied information.
  * Slower GL version which extracts info about each vertex in turn
  */
@@ -69,7 +138,8 @@
     BOOL pixelShader = use_ps(state);
     BOOL specular_fog = FALSE;
     const BYTE *texCoords[WINED3DDP_MAXTEXCOORD];
-    const BYTE *diffuse = NULL, *specular = NULL, *normal = NULL, *position =
NULL;
+    const BYTE *diffuse = NULL, *specular = NULL, *normal = NULL, *position =
NULL, *weights = NULL, *indices = NULL;
+    int nweights = 0;
     const struct wined3d_gl_info *gl_info = context->gl_info;
     UINT texture_stages = gl_info->limits.texture_stages;
     const struct wined3d_stream_info_element *element;
@@ -161,6 +231,31 @@
     {
         GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
     }
+    
+    if (device->vertexBlendSW) {
+        if (!si->elements[WINED3D_FFP_BLENDWEIGHT].data) {
+            WARN("vertex blending enabled but blendWeights.data=NULL\n");
+        } else if (si->elements[WINED3D_FFP_BLENDWEIGHT].format->gl_vtx_type
!= GL_FLOAT) {
+            FIXME("unsupported blend weights datatype (%d)\n",
si->elements[WINED3D_FFP_BLENDWEIGHT].format->id);
+        } else if (position &&
si->elements[WINED3D_FFP_POSITION].format->emit_idx != WINED3D_FFP_EMIT_FLOAT3)
{
+            FIXME("unsupported postion datatype (%d)\n",
si->elements[WINED3D_FFP_POSITION].format->id);
+        } else if (normal && si->elements[WINED3D_FFP_NORMAL].format->emit_idx
!= WINED3D_FFP_EMIT_FLOAT3) {
+            FIXME("unsupported normal datatype (%d)\n",
si->elements[WINED3D_FFP_NORMAL].format->id);
+        } else {
+            element = &si->elements[WINED3D_FFP_BLENDWEIGHT];
+            weights = element->data + streams[element->stream_idx].offset;
+            nweights = element->format->gl_vtx_format;
+        }
+        
+        if (si->elements[WINED3D_FFP_BLENDINDICES].data) {
+            if (si->elements[WINED3D_FFP_BLENDINDICES].format->emit_idx !=
WINED3D_FFP_EMIT_UBYTE4) {
+                FIXME("unsupported blend indices datatype (%d)\n",
si->elements[WINED3D_FFP_BLENDINDICES].format->id);
+            } else {
+                element = &si->elements[WINED3D_FFP_BLENDINDICES];
+                indices = element->data + streams[element->stream_idx].offset;
+            }
+        }
+    }

     for (textureNo = 0; textureNo < texture_stages; ++textureNo)
     {
@@ -278,17 +373,24 @@
             }
         }

-        /* Normal -------------------------------- */
-        if (normal)
-        {
-            const void *ptrToCoords = normal + SkipnStrides *
si->elements[WINED3D_FFP_NORMAL].stride;
-           
normal_funcs[si->elements[WINED3D_FFP_NORMAL].format->emit_idx](ptrToCoords);
-        }
-
-        /* Position -------------------------------- */
-        if (position) {
-            const void *ptrToCoords = position + SkipnStrides *
si->elements[WINED3D_FFP_POSITION].stride;
-           
position_funcs[si->elements[WINED3D_FFP_POSITION].format->emit_idx](ptrToCoords);
+        if (weights) { 
+            emitBlendedVertex(device->stateBlock,
+                              (const float*)(weights + SkipnStrides *
si->elements[WINED3D_FFP_BLENDWEIGHT].stride), nweights,
+                              indices ? (indices + SkipnStrides *
si->elements[WINED3D_FFP_BLENDINDICES].stride) : NULL,
+                              (const float*)(position ? (position +
SkipnStrides * si->elements[WINED3D_FFP_POSITION].stride) : NULL),
+                              (const float*)(normal ? (normal + SkipnStrides *
si->elements[WINED3D_FFP_NORMAL].stride) : NULL));
+        } else {
+            /* Normal -------------------------------- */
+            if (normal != NULL) {
+                const void *ptrToCoords = normal + SkipnStrides *
si->elements[WINED3D_FFP_NORMAL].stride;
+               
normal_funcs[si->elements[WINED3D_FFP_NORMAL].format->emit_idx](ptrToCoords);
+            }
+
+            /* Position -------------------------------- */
+            if (position) {
+                const void *ptrToCoords = position + SkipnStrides *
si->elements[WINED3D_FFP_POSITION].stride;
+               
position_funcs[si->elements[WINED3D_FFP_POSITION].format->emit_idx](ptrToCoords);
+            }
         }

         /* For non indexed mode, step onto next parts */
@@ -678,6 +780,17 @@
                 }
                 emulation = TRUE;
             }
+            else if (device->vertexBlendSW)
+            {
+                static BOOL warned;
+                if (!warned) {
+                    FIXME("Using software emulation because vertex blending is
enabled\n");
+                    warned = TRUE;
+                } else {
+                    TRACE("Using software emulation because vertex blending is
enabled\n");
+                }
+                emulation = TRUE;
+            }

             if(emulation) {
                 stream_info = &stridedlcl;
diff -Naur a/dlls/wined3d/state.c b/dlls/wined3d/state.c
--- a/dlls/wined3d/state.c      2011-02-01 16:17:23.000000000 +0300
+++ b/dlls/wined3d/state.c      2011-02-05 22:18:26.000000000 +0300
@@ -3771,7 +3771,7 @@
     if(context->last_was_rhw) {
         glLoadIdentity();
         checkGLcall("glLoadIdentity()");
-    } else {
+    } else if (!stateblock->device->vertexBlendSW) {
         /* In the general case, the view matrix is the identity matrix */
         if (stateblock->device->view_ident)
         {
@@ -3785,6 +3785,9 @@
            
glMultMatrixf(&stateblock->state.transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
             checkGLcall("glMultMatrixf");
         }
+    } else {
+       
glLoadMatrixf(&stateblock->state.transforms[WINED3DTS_VIEW].u.m[0][0]);
+        checkGLcall("glLoadMatrixf");
     }
 }

@@ -3874,13 +3877,33 @@

 static void state_vertexblend_w(DWORD state, struct wined3d_stateblock
*stateblock, struct wined3d_context *context)
 {
-    WINED3DVERTEXBLENDFLAGS f =
stateblock->state.render_states[WINED3DRS_VERTEXBLEND];
+    WINED3DVERTEXBLENDFLAGS val =
stateblock->state.render_states[WINED3DRS_VERTEXBLEND];
     static unsigned int once;

-    if (f == WINED3DVBF_DISABLE) return;
-
-    if (!once++) FIXME("Vertex blend flags %#x not supported.\n", f);
-    else WARN("Vertex blend flags %#x not supported.\n", f);
+    switch (val) {
+        case WINED3DVBF_0WEIGHTS:
+        case WINED3DVBF_1WEIGHTS:
+        case WINED3DVBF_2WEIGHTS:
+        case WINED3DVBF_3WEIGHTS:
+            if(!once) {
+                once = TRUE;
+                FIXME("Vertex blending enabled, but not supported by hardware.
Using software emulation.\n");
+            }
+            if (!stateblock->device->vertexBlendSW) {
+                stateblock->device->vertexBlendSW = TRUE;
+                transform_world(state, stateblock, context);
+            }
+            break;
+        case WINED3DVBF_TWEENING:
+            WARN("Vertex blend flags %#x not supported.\n", val);
+            /* fall through */
+        default:
+            if (stateblock->device->vertexBlendSW) {
+                stateblock->device->vertexBlendSW = FALSE;
+                transform_world(state, stateblock, context);
+            }
+            break;
+    }
 }

 static void state_vertexblend(DWORD state, struct wined3d_stateblock
*stateblock, struct wined3d_context *context)
diff -Naur a/dlls/wined3d/vertexdeclaration.c
b/dlls/wined3d/vertexdeclaration.c
--- a/dlls/wined3d/vertexdeclaration.c  2011-02-05 15:14:05.000000000 +0300
+++ b/dlls/wined3d/vertexdeclaration.c  2011-02-05 22:04:50.000000000 +0300
@@ -106,6 +106,15 @@
                 default:
                     return FALSE;
             }
+            
+        case WINED3DDECLUSAGE_BLENDINDICES:
+            switch(element->format)
+            {
+                case WINED3DFMT_R8G8B8A8_UINT:
+                    return TRUE;
+                default:
+                    return FALSE;
+            }

         case WINED3DDECLUSAGE_NORMAL:
             switch(element->format)
diff -Naur a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
--- a/dlls/wined3d/wined3d_private.h    2011-02-05 15:14:05.000000000 +0300
+++ b/dlls/wined3d/wined3d_private.h    2011-02-05 22:04:50.000000000 +0300
@@ -1670,6 +1670,7 @@
     WORD view_ident : 1;                /* true iff view matrix is identity */
     WORD untransformed : 1;
     WORD vertexBlendUsed : 1;           /* To avoid needless setting of the
blend matrices */
+    WORD vertexBlendSW : 1;             /* vertexBlend software fallback used
*/
     WORD isRecordingState : 1;
     WORD isInDraw : 1;
     WORD bCursorVisible : 1;

-- 
Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email
Do not reply to this email, post in Bugzilla using the
above URL to reply.
------- You are receiving this mail because: -------
You are watching all bug changes.



More information about the wine-bugs mailing list