[7/20] WineD3D: Avoid negative draw start indices
Stefan Dösinger
stefan at codeweavers.com
Sat Jan 6 11:19:55 CST 2007
A negative draw start index seems to cause troubles with at least the nvidia
driver, so avoid it. A secound base vertex index member is added to the
stateblock to reflect the base vertex index that is loaded. If the base
vertex index is changed the stream sources have to be dirtified. For
non-indexed drawing this is 0, otherwise the base vertex index set by
SetIndices.
-------------- next part --------------
From 3cf5450a1d4e934eead579a104295757931c6f19 Mon Sep 17 00:00:00 2001
From: Stefan Doesinger <stefan at codeweavers.com>
Date: Fri, 5 Jan 2007 00:56:16 +0100
Subject: [PATCH] WineD3D: Avoid negative draw start indices
---
dlls/wined3d/device.c | 23 ++++++++++++++++++-----
dlls/wined3d/drawprim.c | 6 +++---
dlls/wined3d/state.c | 28 ++++++++++++++--------------
dlls/wined3d/wined3d_private.h | 3 ++-
4 files changed, 37 insertions(+), 23 deletions(-)
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 @@ static HRESULT WINAPI IWineD3DDeviceImpl
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 @@ static HRESULT WINAPI IWineD3DDeviceIm
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 @@ static HRESULT WINAPI IWineD3DDeviceImpl
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 @@ static HRESULT WINAPI IWineD3DDeviceImpl
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 @@ static HRESULT WINAPI IWineD3DDeviceImpl
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 c5703a8..8800c1e 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -650,7 +650,7 @@ static void drawStridedSlow(IWineD3DDevi
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 @@ static void drawStridedSlow(IWineD3DDevi
/* 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 @@ static inline void loadNumberedArrays(IW
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 @@ #if 1
#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 @@ #endif
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 @@ #endif
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 @@ #if 0
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 @@ #if 0 /* FOG --------------------------
(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 @@ #if 0 /* tangents ---------------------
(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 @@ #if 0 /* tangents ---------------------
(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 @@ #endif
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 @@ #endif
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 @@ #endif
}
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 @@ #endif
}
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 @@ #endif
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 @@ struct IWineD3DStateBlockImpl
/* 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];
--
1.4.2.4
More information about the wine-patches
mailing list