Stefan Dösinger : wined3d: BaseVertexIndex can be negative.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Aug 27 06:07:40 CDT 2007


Module: wine
Branch: master
Commit: 6ec6c941fabbbb7cbfedce17017bee40ded16709
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=6ec6c941fabbbb7cbfedce17017bee40ded16709

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Sat Aug 25 00:09:33 2007 +0200

wined3d: BaseVertexIndex can be negative.

---

 dlls/d3d8/device.c               |    9 ++++++++-
 dlls/wined3d/device.c            |    4 ++--
 dlls/wined3d/drawprim.c          |   20 ++++++++++++++++++--
 dlls/wined3d/wined3d_private.h   |    4 ++--
 include/wine/wined3d_interface.h |    4 ++--
 5 files changed, 32 insertions(+), 9 deletions(-)

diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c
index 74a0d13..205120e 100644
--- a/dlls/d3d8/device.c
+++ b/dlls/d3d8/device.c
@@ -1803,6 +1803,12 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, I
     TRACE("(%p) Relay\n", This);
 
     EnterCriticalSection(&d3d8_cs);
+    /* WineD3D takes an INT(due to d3d9), but d3d8 uses UINTs. Do I have to add a check here that
+     * the UINT doesn't cause an overflow in the INT? It seems rather unlikely because such large
+     * vertex buffers can't be created to address them with an index that requires the 32nd bit
+     * (4 Byte minimum vertex size * 2^31-1 -> 8 gb buffer. The index sign would be the least
+     * problem)
+     */
     IWineD3DDevice_SetBaseVertexIndex(This->WineD3DDevice, baseVertexIndex);
     hr = IWineD3DDevice_SetIndices(This->WineD3DDevice,
             pIndexData ? ((IDirect3DIndexBuffer8Impl *)pIndexData)->wineD3DIndexBuffer : NULL);
@@ -1822,7 +1828,8 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, I
     }
 
     EnterCriticalSection(&d3d8_cs);
-    IWineD3DDevice_GetBaseVertexIndex(This->WineD3DDevice, pBaseVertexIndex);
+    /* The case from UINT to INT is safe because d3d8 will never set negative values */
+    IWineD3DDevice_GetBaseVertexIndex(This->WineD3DDevice, (INT *) pBaseVertexIndex);
     rc = IWineD3DDevice_GetIndices(This->WineD3DDevice, &retIndexData);
     if (SUCCEEDED(rc) && retIndexData) {
         IWineD3DIndexBuffer_GetParent(retIndexData, (IUnknown **)ppIndexData);
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 425ffe2..2b2dac5 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -2829,7 +2829,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWine
 }
 
 /* Method to offer d3d9 a simple way to set the base vertex index without messing with the index buffer */
-static HRESULT WINAPI IWineD3DDeviceImpl_SetBaseVertexIndex(IWineD3DDevice *iface, UINT BaseIndex) {
+static HRESULT WINAPI IWineD3DDeviceImpl_SetBaseVertexIndex(IWineD3DDevice *iface, INT BaseIndex) {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     TRACE("(%p)->(%d)\n", This, BaseIndex);
 
@@ -2849,7 +2849,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetBaseVertexIndex(IWineD3DDevice *ifac
     return WINED3D_OK;
 }
 
-static HRESULT WINAPI IWineD3DDeviceImpl_GetBaseVertexIndex(IWineD3DDevice *iface, UINT* base_index) {
+static HRESULT WINAPI IWineD3DDeviceImpl_GetBaseVertexIndex(IWineD3DDevice *iface, INT* base_index) {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     TRACE("(%p) : base_index %p\n", This, base_index);
 
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 3a47912..2dcaa5d 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -178,6 +178,7 @@ void primitiveDeclarationConvertToStridedData(
         if (This->stateBlock->streamSource[element->Stream] == NULL)
             continue;
 
+        stride  = This->stateBlock->streamStride[element->Stream];
         if (This->stateBlock->streamIsUP) {
             TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
             streamVBO = 0;
@@ -185,6 +186,22 @@ void primitiveDeclarationConvertToStridedData(
         } else {
             TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
             data    = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0, &streamVBO);
+
+            /* Can't use vbo's if the base vertex index is negative. OpenGL doesn't accept negative offsets
+             * (or rather offsets bigger than the vbo, because the pointer is unsigned), so use system memory
+             * sources. In most sane cases the pointer - offset will still be > 0, otherwise it will wrap
+             * around to some big value. Hope that with the indices, the driver wraps it back internally. If
+             * not, drawStridedSlow is needed, including a vertex buffer path.
+             */
+            if(This->stateBlock->loadBaseVertexIndex < 0) {
+                WARN("loadBaseVertexIndex is < 0 (%d), not using vbos\n", This->stateBlock->loadBaseVertexIndex);
+                streamVBO = 0;
+                data = ((IWineD3DVertexBufferImpl *) This->stateBlock->streamSource[element->Stream])->resource.allocatedMemory;
+                if(data + This->stateBlock->loadBaseVertexIndex * stride < 0) {
+                    FIXME("System memory vertex data load offset is negative!\n");
+                }
+            }
+
             if(fixup) {
                 if( streamVBO != 0) *fixup = TRUE;
                 else if(*fixup && !useVertexShaderFunction &&
@@ -195,7 +212,6 @@ void primitiveDeclarationConvertToStridedData(
                 }
             }
         }
-        stride  = This->stateBlock->streamStride[element->Stream];
         data += element->Offset;
         reg = element->Reg;
 
@@ -284,7 +300,7 @@ static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData
     DWORD specularColor = 0;               /* Specular Color             */
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     UINT *streamOffset = This->stateBlock->streamOffset;
-    DWORD                      SkipnStrides = startVertex + This->stateBlock->loadBaseVertexIndex;
+    long                      SkipnStrides = startVertex + This->stateBlock->loadBaseVertexIndex;
 
     BYTE *texCoords[WINED3DDP_MAXTEXCOORD];
     BYTE *diffuse = NULL, *specular = NULL, *normal = NULL, *position = NULL;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 0328780..61a6385 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1343,8 +1343,8 @@ struct IWineD3DStateBlockImpl
 
     /* Indices */
     IWineD3DIndexBuffer*      pIndexData;
-    UINT                      baseVertexIndex;
-    UINT                      loadBaseVertexIndex; /* non-indexed drawing needs 0 here, indexed baseVertexIndex */
+    INT                       baseVertexIndex;
+    INT                       loadBaseVertexIndex; /* non-indexed drawing needs 0 here, indexed baseVertexIndex */
 
     /* Transform */
     WINED3DMATRIX             transforms[HIGHEST_TRANSFORMSTATE + 1];
diff --git a/include/wine/wined3d_interface.h b/include/wine/wined3d_interface.h
index 35430b9..603eeb5 100644
--- a/include/wine/wined3d_interface.h
+++ b/include/wine/wined3d_interface.h
@@ -405,8 +405,8 @@ DECLARE_INTERFACE_(IWineD3DDevice,IWineD3DBase)
     STDMETHOD_(void, GetGammaRamp)(THIS_ UINT iSwapChain, WINED3DGAMMARAMP* pRamp) PURE;
     STDMETHOD(SetIndices)(THIS_ struct IWineD3DIndexBuffer * pIndexData) PURE;
     STDMETHOD(GetIndices)(THIS_ struct IWineD3DIndexBuffer ** ppIndexData) PURE;
-    STDMETHOD(SetBaseVertexIndex)(THIS_ UINT baseIndex);
-    STDMETHOD(GetBaseVertexIndex)(THIS_ UINT *baseIndex);
+    STDMETHOD(SetBaseVertexIndex)(THIS_ INT baseIndex);
+    STDMETHOD(GetBaseVertexIndex)(THIS_ INT *baseIndex);
     STDMETHOD(SetLight)(THIS_ DWORD  Index,CONST WINED3DLIGHT * pLight) PURE;
     STDMETHOD(GetLight)(THIS_ DWORD  Index,WINED3DLIGHT * pLight) PURE;
     STDMETHOD(SetLightEnable)(THIS_ DWORD  Index,BOOL  Enable) PURE;




More information about the wine-cvs mailing list