wined3d: Avoid negative draw start indices.
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index e955a8b..b13854b 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c
@@ -4697,9 +4697,12 @@ debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount); - if(StartVertex - This->stateBlock->baseVertexIndex < 0) ERR("Drawing negative\n"); + if(This->stateBlock->loadBaseVertexIndex != 0) { + This->stateBlock->loadBaseVertexIndex = 0; + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC); + } /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */ - drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex - This->stateBlock->baseVertexIndex, 0/* NumVertices */, -1 /* indxStart */, + drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */, 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */); return WINED3D_OK; } @@ -4728,6 +4731,11 @@ idxStride = 4; } + if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) { + This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex; + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC); + } + drawPrimitive(iface, PrimitiveType, primCount, 0, NumVertices, startIndex, idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex); @@ -4752,11 +4760,12 @@ This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData; This->stateBlock->streamStride[0] = VertexStreamZeroStride; This->stateBlock->streamIsUP = TRUE; + This->stateBlock->loadBaseVertexIndex = 0; /* TODO: Only mark dirty if drawing from a different UP address */ IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC); - drawPrimitive(iface, PrimitiveType, PrimitiveCount, -This->stateBlock->baseVertexIndex /* start vertex */, 0 /* NumVertices */, + drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */, 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */); /* MSDN specifies stream zero settings must be set to NULL */ @@ -4801,10 +4810,11 @@ This->stateBlock->streamIsUP = TRUE; This->stateBlock->streamStride[0] = VertexStreamZeroStride; - /* Mark the state dirty until we have nicer tracking */ - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL); /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */ This->stateBlock->baseVertexIndex = 0; + This->stateBlock->loadBaseVertexIndex = 0; + /* Mark the state dirty until we have nicer tracking of the stream source pointers */ + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL); drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex); @@ -4812,6 +4822,9 @@ This->stateBlock->streamSource[0] = NULL; This->stateBlock->streamStride[0] = 0; This->stateBlock->pIndexData = NULL; + /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call + * SetStreamSource to specify a vertex buffer + */ return WINED3D_OK; }
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index 54db1e7..b913448 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c
@@ -650,7 +650,7 @@ DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */ DWORD specularColor = 0; /* Specular Color */ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - LONG SkipnStrides = startVertex + This->stateBlock->baseVertexIndex; + LONG SkipnStrides = startVertex + This->stateBlock->loadBaseVertexIndex; TRACE("Using slow vertex array code\n"); @@ -680,10 +680,10 @@ /* Indexed so work out the number of strides to skip */ if (idxSize == 2) { VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufS[startIdx+vx_index])); - SkipnStrides = pIdxBufS[startIdx + vx_index] + This->stateBlock->baseVertexIndex; + SkipnStrides = pIdxBufS[startIdx + vx_index] + This->stateBlock->loadBaseVertexIndex; } else { VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufL[startIdx+vx_index])); - SkipnStrides = pIdxBufL[startIdx + vx_index] + This->stateBlock->baseVertexIndex; + SkipnStrides = pIdxBufL[startIdx + vx_index] + This->stateBlock->loadBaseVertexIndex; } }
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 768bd12..cdb250e 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c
@@ -2096,7 +2096,7 @@ WINED3D_ATR_GLTYPE(strided->u.input[i].dwType), WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType), strided->u.input[i].dwStride, - strided->u.input[i].lpData + stateblock->baseVertexIndex * strided->u.input[i].dwStride)); + strided->u.input[i].lpData + stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride)); GL_EXTCALL(glEnableVertexAttribArrayARB(i)); } } @@ -2121,7 +2121,7 @@ #endif TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType), - sd->u.s.blendWeights.lpData + stateblock->baseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride); + sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride); /* FIXME("TODO\n");*/ /* Note dwType == float3 or float4 == 2 or 3 */ @@ -2136,7 +2136,7 @@ VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) , sd->u.s.blendWeights.dwStride, - sd->u.s.blendWeights.lpData + stateblock->baseVertexIndex * sd->u.s.blendWeights.dwStride)); + sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride)); if(curVBO != sd->u.s.blendWeights.VBO) { GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO)); @@ -2148,7 +2148,7 @@ WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType), WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType), sd->u.s.blendWeights.dwStride, - sd->u.s.blendWeights.lpData + stateblock->baseVertexIndex * sd->u.s.blendWeights.dwStride); + sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride); checkGLcall("glWeightPointerARB"); @@ -2168,7 +2168,7 @@ WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType), WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType), sd->u.s.blendWeights.dwStride, - sd->u.s.blendWeights.lpData + stateblock->baseVertexIndex * sd->u.s.blendWeights.dwStride); + sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride); checkGLcall("glVertexWeightPointerEXT(numBlends, ...)"); glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT); checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)"); @@ -2200,7 +2200,7 @@ (GL_EXTCALL)(FogCoordPointerEXT)( WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType), sd->u.s.fog.dwStride, - sd->u.s.fog.lpData + stateblock->baseVertexIndex * sd->u.s.fog.dwStride); + sd->u.s.fog.lpData + stateblock->loadBaseVertexIndex * sd->u.s.fog.dwStride); } else { /* don't bother falling back to 'slow' as we don't support software FOG yet. */ /* FIXME: fixme once */ @@ -2224,7 +2224,7 @@ (GL_EXTCALL)(TangentPointerEXT)( WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType), sd->u.s.tangent.dwStride, - sd->u.s.tangent.lpData + stateblock->baseVertexIndex * sd->u.s.tangent.dwStride); + sd->u.s.tangent.lpData + stateblock->loadBaseVertexIndex * sd->u.s.tangent.dwStride); } else { glDisable(GL_TANGENT_ARRAY_EXT); } @@ -2233,7 +2233,7 @@ (GL_EXTCALL)(BinormalPointerEXT)( WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType), sd->u.s.binormal.dwStride, - sd->u.s.binormal.lpData + stateblock->baseVertexIndex * sd->u.s.binormal.dwStride); + sd->u.s.binormal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.binormal.dwStride); } else{ glDisable(GL_BINORMAL_ARRAY_EXT); } @@ -2286,12 +2286,12 @@ if(sd->u.s.position.VBO == 0) { glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */, WINED3D_ATR_GLTYPE(sd->u.s.position.dwType), - sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->baseVertexIndex * sd->u.s.position.dwStride); + sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride); } else { glVertexPointer( WINED3D_ATR_SIZE(sd->u.s.position.dwType), WINED3D_ATR_GLTYPE(sd->u.s.position.dwType), - sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->baseVertexIndex * sd->u.s.position.dwStride); + sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride); } checkGLcall("glVertexPointer(...)"); glEnableClientState(GL_VERTEX_ARRAY); @@ -2316,7 +2316,7 @@ glNormalPointer( WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType), sd->u.s.normal.dwStride, - sd->u.s.normal.lpData + stateblock->baseVertexIndex * sd->u.s.normal.dwStride); + sd->u.s.normal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.normal.dwStride); checkGLcall("glNormalPointer(...)"); glEnableClientState(GL_NORMAL_ARRAY); checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)"); @@ -2350,7 +2350,7 @@ } glColorPointer(4, GL_UNSIGNED_BYTE, sd->u.s.diffuse.dwStride, - sd->u.s.diffuse.lpData + stateblock->baseVertexIndex * sd->u.s.diffuse.dwStride); + sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride); checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)"); glEnableClientState(GL_COLOR_ARRAY); checkGLcall("glEnableClientState(GL_COLOR_ARRAY)"); @@ -2377,7 +2377,7 @@ } GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE, sd->u.s.specular.dwStride, - sd->u.s.specular.lpData + stateblock->baseVertexIndex * sd->u.s.specular.dwStride); + sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride); vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)"); glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT); vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)"); @@ -2442,7 +2442,7 @@ WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType), WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType), sd->u.s.texCoords[coordIdx].dwStride, - sd->u.s.texCoords[coordIdx].lpData + stateblock->baseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride); + sd->u.s.texCoords[coordIdx].lpData + stateblock->loadBaseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride); glEnableClientState(GL_TEXTURE_COORD_ARRAY); } } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 8b7170f..27f95c8 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h
@@ -1201,7 +1201,8 @@ /* Indices */ IWineD3DIndexBuffer* pIndexData; - UINT baseVertexIndex; /* Note: only used for d3d8 */ + UINT baseVertexIndex; + UINT loadBaseVertexIndex; /* non-indexed drawing needs 0 here, indexed baseVertexIndex */ /* Transform */ WINED3DMATRIX transforms[HIGHEST_TRANSFORMSTATE + 1];