Stefan Dösinger : wined3d: Non-primary stateblocks also hold an internal reference to buffers.

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


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

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Sun Aug 19 20:40:44 2007 +0200

wined3d: Non-primary stateblocks also hold an internal reference to buffers.

---

 dlls/wined3d/device.c     |   21 +++++++++++++++++++++
 dlls/wined3d/stateblock.c |   32 ++++++++++++++++++++++++--------
 2 files changed, 45 insertions(+), 8 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 2b2dac5..6b53729 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -514,6 +514,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface,
             }
         }
 
+        for(i = 0; i < MAX_STREAMS; i++) {
+            if(object->streamSource[i]) {
+                IWineD3DVertexBuffer_AddRef(object->streamSource[i]);
+            }
+        }
+
     } else if (Type == WINED3DSBT_PIXELSTATE) {
 
         TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
@@ -560,6 +566,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface,
             }
         }
 
+        /* Pixel state blocks do not contain vertex buffers. Set them to NULL to avoid wrong refcounting
+         * on them. This makes releasing the buffer easier
+         */
+        for(i = 0; i < MAX_STREAMS; i++) {
+            object->streamSource[i] = NULL;
+        }
+
     } else if (Type == WINED3DSBT_VERTEXSTATE) {
 
         TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
@@ -613,6 +626,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface,
                 light->enabledChanged = TRUE;
             }
         }
+
+        for(i = 0; i < MAX_STREAMS; i++) {
+            if(object->streamSource[i]) {
+                IWineD3DVertexBuffer_AddRef(object->streamSource[i]);
+            }
+        }
     } else {
         FIXME("Unrecognized state block type %d\n", Type);
     }
@@ -2237,6 +2256,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface,
     /* Handle recording of state blocks */
     if (This->isRecordingState) {
         TRACE("Recording... not performing anything\n");
+        if(pStreamData) IWineD3DVertexBuffer_AddRef(pStreamData);
+        if(oldSrc) IWineD3DVertexBuffer_Release(oldSrc);
         return WINED3D_OK;
     }
 
diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c
index dfe62c9..0362053 100644
--- a/dlls/wined3d/stateblock.c
+++ b/dlls/wined3d/stateblock.c
@@ -262,15 +262,15 @@ static ULONG  WINAPI IWineD3DStateBlockImpl_Release(IWineD3DStateBlock *iface) {
                     }
                 }
             }
-            for (counter = 0; counter < MAX_STREAMS; counter++) {
-                if(This->streamSource[counter]) {
-                    if(0 != IWineD3DVertexBuffer_Release(This->streamSource[counter])) {
-                        TRACE("Vertex buffer still referenced by stateblock, applications has leaked Stream %u, buffer %p\n", counter, This->streamSource[counter]);
-                    }
-                }
-            }
             if(This->pIndexData) IWineD3DIndexBuffer_Release(This->pIndexData);
+        }
 
+        for (counter = 0; counter < MAX_STREAMS; counter++) {
+            if(This->streamSource[counter]) {
+                if(0 != IWineD3DVertexBuffer_Release(This->streamSource[counter])) {
+                    TRACE("Vertex buffer still referenced by stateblock, applications has leaked Stream %u, buffer %p\n", counter, This->streamSource[counter]);
+                }
+            }
         }
 
         for(counter = 0; counter < LIGHTMAP_SIZE; counter++) {
@@ -532,6 +532,8 @@ static HRESULT  WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
                 TRACE("Updating stream source %d to %p, stride to %d\n", i, targetStateBlock->streamSource[i],
                                                                             targetStateBlock->streamStride[i]);
                 This->streamStride[i] = targetStateBlock->streamStride[i];
+                if(targetStateBlock->streamSource[i]) IWineD3DVertexBuffer_AddRef(targetStateBlock->streamSource[i]);
+                if(This->streamSource[i]) IWineD3DVertexBuffer_Release(This->streamSource[i]);
                 This->streamSource[i] = targetStateBlock->streamSource[i];
             }
 
@@ -600,7 +602,6 @@ static HRESULT  WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
         memcpy(This->vertexShaderConstantF, targetStateBlock->vertexShaderConstantF, sizeof(float) * GL_LIMITS(vshader_constantsF) * 4);
         memcpy(This->streamStride, targetStateBlock->streamStride, sizeof(This->streamStride));
         memcpy(This->streamOffset, targetStateBlock->streamOffset, sizeof(This->streamOffset));
-        memcpy(This->streamSource, targetStateBlock->streamSource, sizeof(This->streamSource));
         memcpy(This->streamFreq, targetStateBlock->streamFreq, sizeof(This->streamFreq));
         memcpy(This->streamFlags, targetStateBlock->streamFlags, sizeof(This->streamFlags));
         This->pIndexData = targetStateBlock->pIndexData;
@@ -621,6 +622,14 @@ static HRESULT  WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
         memcpy(This->textureState, targetStateBlock->textureState, sizeof(This->textureState));
         memcpy(This->samplerState, targetStateBlock->samplerState, sizeof(This->samplerState));
         This->scissorRect = targetStateBlock->scissorRect;
+
+        for(i = 0; i < MAX_STREAMS; i++) {
+            if(targetStateBlock->streamSource[i] != This->streamSource[i]) {
+                if(targetStateBlock->streamSource[i]) IWineD3DVertexBuffer_AddRef(targetStateBlock->streamSource[i]);
+                if(This->streamSource[i]) IWineD3DVertexBuffer_Release(This->streamSource[i]);
+                This->streamSource[i] = targetStateBlock->streamSource[i];
+            }
+        }
     } else if(This->blockType == WINED3DSBT_VERTEXSTATE) {
         This->vertexShader = targetStateBlock->vertexShader;
         memcpy(This->vertexShaderConstantB, targetStateBlock->vertexShaderConstantB, sizeof(This->vertexShaderConstantI));
@@ -640,6 +649,13 @@ static HRESULT  WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
                 This->textureState[j][SavedVertexStates_R[i]] = targetStateBlock->textureState[j][SavedVertexStates_R[i]];
             }
         }
+        for(i = 0; i < MAX_STREAMS; i++) {
+            if(targetStateBlock->streamSource[i] != This->streamSource[i]) {
+                if(targetStateBlock->streamSource[i]) IWineD3DVertexBuffer_AddRef(targetStateBlock->streamSource[i]);
+                if(This->streamSource[i]) IWineD3DVertexBuffer_Release(This->streamSource[i]);
+                This->streamSource[i] = targetStateBlock->streamSource[i];
+            }
+        }
     } else if(This->blockType == WINED3DSBT_PIXELSTATE) {
         This->pixelShader = targetStateBlock->pixelShader;
         memcpy(This->pixelShaderConstantB, targetStateBlock->pixelShaderConstantB, sizeof(This->pixelShaderConstantI));




More information about the wine-cvs mailing list