From cea41b0a0ff4a68c9c0507cdec604c142c493e53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Tue, 27 Jun 2006 13:11:13 +0200 Subject: [PATCH] wined3d: Vertex buffer can be locked multiple times. --- dlls/d3d8/tests/device.c | 14 ++++++++++++++ dlls/ddraw/vertexbuffer.c | 20 +++++++++++--------- dlls/wined3d/vertexbuffer.c | 25 ++++++++++++++++++++++--- dlls/wined3d/wined3d_private.h | 1 + 4 files changed, 48 insertions(+), 12 deletions(-) diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c index f754fe127c2..d821340b256 100644 --- a/dlls/d3d8/tests/device.c +++ b/dlls/d3d8/tests/device.c @@ -267,6 +267,20 @@ static void test_refcount(void) hr = IDirect3DDevice8_CreateAdditionalSwapChain( pDevice, &d3dpp, &pSwapChain ); CHECK_CALL( hr, "CreateAdditionalSwapChain", pDevice, refcount+1 ); + if(pVertexBuffer) + { + BYTE *data; + /* Vertex buffers can be locked multiple times */ + hr = IDirect3DVertexBuffer8_Lock(pVertexBuffer, 0, 0, &data, 0); + ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Lock failed with %08lx\n", hr); + hr = IDirect3DVertexBuffer8_Lock(pVertexBuffer, 0, 0, &data, 0); + ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Lock failed with %08lx\n", hr); + hr = IDirect3DVertexBuffer8_Unlock(pVertexBuffer); + ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Unlock failed with %08lx\n", hr); + hr = IDirect3DVertexBuffer8_Unlock(pVertexBuffer); + ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Unlock failed with %08lx\n", hr); + } + cleanup: if (pDevice) IUnknown_Release( pDevice ); diff --git a/dlls/ddraw/vertexbuffer.c b/dlls/ddraw/vertexbuffer.c index a24bfc40f56..01db5d5385b 100644 --- a/dlls/ddraw/vertexbuffer.c +++ b/dlls/ddraw/vertexbuffer.c @@ -214,20 +214,22 @@ IDirect3DVertexBufferImpl_Lock(IDirect3DVertexBuffer7 *iface, HRESULT hr; TRACE("(%p)->(%08lx,%p,%p)\n", This, Flags, Data, Size); - /* Get the size, for returning it, and for locking */ - hr = IWineD3DVertexBuffer_GetDesc(This->wineD3DVertexBuffer, - &Desc); - if(hr != D3D_OK) + if(*Size) { - ERR("(%p) IWineD3DVertexBuffer::GetDesc failed with hr=%08lx\n", This, hr); - return hr; + /* Get the size, for returning it, and for locking */ + hr = IWineD3DVertexBuffer_GetDesc(This->wineD3DVertexBuffer, + &Desc); + if(hr != D3D_OK) + { + ERR("(%p) IWineD3DVertexBuffer::GetDesc failed with hr=%08lx\n", This, hr); + return hr; + } + *Size = Desc.Size; } - if(Size) *Size = Desc.Size; - return IWineD3DVertexBuffer_Lock(This->wineD3DVertexBuffer, 0 /* OffsetToLock */, - Desc.Size, + 0 /* SizeToLock, 0 == Full lock */, (BYTE **) Data, Flags); } diff --git a/dlls/wined3d/vertexbuffer.c b/dlls/wined3d/vertexbuffer.c index c669a6bea89..b58591c98d7 100644 --- a/dlls/wined3d/vertexbuffer.c +++ b/dlls/wined3d/vertexbuffer.c @@ -145,8 +145,9 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, This->vbo)); checkGLcall("glBindBufferARB"); GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, This->resource.size, This->resource.allocatedMemory)); - checkGLcall("glUnmapBuffer glBufferSubDataARB"); + checkGLcall("glBufferSubDataARB"); LEAVE_GL(); + /* Lock directly into the VBO in the future */ HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory); This->resource.allocatedMemory = NULL; This->Flags &= ~VBFLAG_DIRTY; @@ -334,12 +335,21 @@ static HRESULT WINAPI IWineD3DVertexBufferImpl_Lock(IWineD3DVertexBuffer *iface BYTE *data; TRACE("(%p)->%d, %d, %p, %08lx\n", This, OffsetToLock, SizeToLock, ppbData, Flags); + InterlockedIncrement(&This->lockcount); + if(This->Flags & VBFLAG_DIRTY) { if(This->dirtystart > OffsetToLock) This->dirtystart = OffsetToLock; - if(This->dirtyend < OffsetToLock + SizeToLock) This->dirtyend = OffsetToLock + SizeToLock; + if(SizeToLock) { + if(This->dirtyend < OffsetToLock + SizeToLock) This->dirtyend = OffsetToLock + SizeToLock; + } else { + This->dirtyend = This->resource.size; + } } else { This->dirtystart = OffsetToLock; - This->dirtyend = OffsetToLock + SizeToLock; + if(SizeToLock) + This->dirtyend = OffsetToLock + SizeToLock; + else + This->dirtyend = OffsetToLock + This->resource.size; } if(This->resource.allocatedMemory) { @@ -375,7 +385,16 @@ static HRESULT WINAPI IWineD3DVertexBufferImpl_Lock(IWineD3DVertexBuffer *iface } HRESULT WINAPI IWineD3DVertexBufferImpl_Unlock(IWineD3DVertexBuffer *iface) { IWineD3DVertexBufferImpl *This = (IWineD3DVertexBufferImpl *) iface; + LONG lockcount; TRACE("(%p)\n", This); + + lockcount = InterlockedDecrement(&This->lockcount); + if(lockcount > 0) { + /* Delay loading the buffer until everything is unlocked */ + TRACE("Ignoring the unlock\n"); + return D3D_OK; + } + if(!This->resource.allocatedMemory) { ENTER_GL(); GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, This->vbo)); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index cbb92f54ada..d55b810c03c 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -633,6 +633,7 @@ typedef struct IWineD3DVertexBufferImpl UINT stream; UINT dirtystart, dirtyend; + LONG lockcount; /* Last description of the buffer */ WineDirect3DVertexStridedData strided;