From 460f71dcf839ea406831d246b367260e6057a4ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Sun, 22 Apr 2007 18:06:07 +0200 Subject: [PATCH] d3d: Fix ProcessVertices. IDirect3DDevice9::ProcessVertices takes a vertex declaration, not a vertex buffer. The source for ProcessVertices is taken from the stateblock, not the vertex declaration. --- dlls/d3d9/device.c | 3 +- dlls/ddraw/vertexbuffer.c | 13 ++++- dlls/wined3d/device.c | 89 ++++++++++++++------------------ include/wine/wined3d_interface.h | 2 +- 4 files changed, 54 insertions(+), 53 deletions(-) diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index 5adec6b5bf7..682cb902016 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -774,8 +774,9 @@ static HRESULT WINAPI IDirect3DDevice9Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDE static HRESULT WINAPI IDirect3DDevice9Impl_ProcessVertices(LPDIRECT3DDEVICE9 iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer9* pDestBuffer, IDirect3DVertexDeclaration9* pVertexDecl, DWORD Flags) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + IDirect3DVertexDeclaration9Impl *Decl = (IDirect3DVertexDeclaration9Impl *) pVertexDecl; TRACE("(%p) Relay\n" , This); - return IWineD3DDevice_ProcessVertices(This->WineD3DDevice,SrcStartIndex, DestIndex, VertexCount, ((IDirect3DVertexBuffer9Impl *)pDestBuffer)->wineD3DVertexBuffer, ((IDirect3DVertexBuffer9Impl *)pVertexDecl)->wineD3DVertexBuffer, Flags); + return IWineD3DDevice_ProcessVertices(This->WineD3DDevice,SrcStartIndex, DestIndex, VertexCount, ((IDirect3DVertexBuffer9Impl *)pDestBuffer)->wineD3DVertexBuffer, Decl ? Decl->wineD3DVertexDeclaration : NULL, Flags); } IDirect3DVertexDeclaration9 *getConvertedDecl(IDirect3DDevice9Impl *This, DWORD fvf) { diff --git a/dlls/ddraw/vertexbuffer.c b/dlls/ddraw/vertexbuffer.c index 9fa2da9ed53..d0592e2a0fd 100644 --- a/dlls/ddraw/vertexbuffer.c +++ b/dlls/ddraw/vertexbuffer.c @@ -341,6 +341,7 @@ IDirect3DVertexBufferImpl_ProcessVertices(IDirect3DVertexBuffer7 *iface, IDirect3DDeviceImpl *D3D = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice7, D3DDevice); BOOL oldClip, doClip; HRESULT hr; + WINED3DVERTEXBUFFER_DESC Desc; TRACE("(%p)->(%08x,%d,%d,%p,%d,%p,%08x)\n", This, VertexOp, DestIndex, Count, Src, SrcIndex, D3D, Flags); @@ -371,13 +372,21 @@ IDirect3DVertexBufferImpl_ProcessVertices(IDirect3DVertexBuffer7 *iface, doClip); } - + IWineD3DVertexBuffer_GetDesc(Src->wineD3DVertexBuffer, + &Desc); + IWineD3DDevice_SetStreamSource(D3D->wineD3DDevice, + 0, /* Stream No */ + Src->wineD3DVertexBuffer, + 0, /* Offset */ + get_flexible_vertex_size(Desc.FVF)); + IWineD3DDevice_SetVertexDeclaration(D3D->wineD3DDevice, + Src->wineD3DVertexDeclaration); hr = IWineD3DDevice_ProcessVertices(D3D->wineD3DDevice, SrcIndex, DestIndex, Count, This->wineD3DVertexBuffer, - Src->wineD3DVertexBuffer, + NULL /* Output vdecl */, Flags); /* Restore the states if needed */ diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 226b3a676ff..aeb99638705 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -3489,7 +3489,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF( #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size) static HRESULT -process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) { +process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) { char *dest_ptr, *dest_conv = NULL, *dest_conv_addr = NULL; unsigned int i; DWORD DestFVF = dest->fvf; @@ -3498,11 +3498,11 @@ process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCo BOOL doClip; int numTextures; - if (SrcFVF & WINED3DFVF_NORMAL) { + if (lpStrideData->u.s.normal.lpData) { WARN(" lighting state not saved yet... Some strange stuff may happen !\n"); } - if ( (SrcFVF & WINED3DFVF_POSITION_MASK) != WINED3DFVF_XYZ) { + if (lpStrideData->u.s.position.lpData == NULL) { ERR("Source has no position mask\n"); return WINED3DERR_INVALIDCALL; } @@ -3837,15 +3837,14 @@ process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCo } #undef copy_and_next -static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) { +static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexDeclaration* pVertexDecl, DWORD Flags) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl; WineDirect3DVertexStridedData strided; + BOOL vbo = FALSE; TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags); - if (!SrcImpl) { - WARN("NULL source vertex buffer\n"); - return WINED3DERR_INVALIDCALL; + if(pVertexDecl) { + ERR("Output vertex declaration not implemented yet\n"); } /* Need any context to write to the vbo. In a non-multithreaded environment a context is there anyway, @@ -3857,50 +3856,42 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, LEAVE_GL(); } - /* We don't need the source vbo because this buffer is only used as - * a source for ProcessVertices. Avoid wasting resources by converting the - * buffer and loading the VBO - */ - if(SrcImpl->vbo) { - TRACE("Releasing the source vbo, it won't be needed\n"); - - if(!SrcImpl->resource.allocatedMemory) { - /* Rescue the data from the buffer */ - void *src; - SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size); - if(!SrcImpl->resource.allocatedMemory) { - ERR("Out of memory\n"); - return E_OUTOFMEMORY; - } - - ENTER_GL(); - GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo)); - checkGLcall("glBindBufferARB"); - - src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB)); - if(src) { - memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size); - } - - GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)); - checkGLcall("glUnmapBufferARB"); - } else { - ENTER_GL(); - } - - GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); - checkGLcall("glBindBufferARB"); - GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo)); - checkGLcall("glDeleteBuffersARB"); - LEAVE_GL(); - - SrcImpl->vbo = 0; + memset(&strided, 0, sizeof(strided)); + if(This->stateBlock->vertexDecl) { + primitiveDeclarationConvertToStridedData(iface, FALSE, &strided, &vbo); + } else { + primitiveConvertToStridedData(iface, &strided, &vbo); } - memset(&strided, 0, sizeof(strided)); - primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0, 0); + if(vbo || SrcStartIndex) { + unsigned int i; + /* ProcessVertices can't convert FROM a vbo, and vertex buffers used to source into ProcesVerticse are + * unlikely to ever be used for drawing. Release vbos in those buffers and fix up the strided structure + * + * Also get the start index in, but only loop over all elements if there's something to add at all. + */ + for(i=0; i < 16; i++) { + if(strided.u.input[i].VBO) { + IWineD3DVertexBufferImpl *vb = (IWineD3DVertexBufferImpl *) This->stateBlock->streamSource[strided.u.input[i].streamNo]; - return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags); + /* The vertex buffer is supposed to have a system memory copy */ + strided.u.input[i].VBO = 0; + strided.u.input[i].lpData = (BYTE *) ((unsigned long) strided.u.input[i].lpData + (unsigned long) vb->resource.allocatedMemory); + ENTER_GL(); + GL_EXTCALL(glDeleteBuffersARB(1, &vb->vbo)); + vb->vbo = 0; + LEAVE_GL(); + + /* To be safe. An app could technically draw, then call ProcessVertices, then draw again without ever changing the stream sources */ + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC); + } + if(strided.u.input[i].lpData) { + strided.u.input[i].lpData += strided.u.input[i].dwStride * SrcStartIndex; + } + } + } + + return process_vertices_strided(This, DestIndex, VertexCount, &strided, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags); } /***** diff --git a/include/wine/wined3d_interface.h b/include/wine/wined3d_interface.h index 3181bc7c331..d9f33d05d22 100644 --- a/include/wine/wined3d_interface.h +++ b/include/wine/wined3d_interface.h @@ -452,7 +452,7 @@ DECLARE_INTERFACE_(IWineD3DDevice,IWineD3DBase) STDMETHOD(GetViewport)(THIS_ WINED3DVIEWPORT * pViewport) PURE; STDMETHOD(MultiplyTransform)(THIS_ WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX * pMatrix) PURE; STDMETHOD(ValidateDevice)(THIS_ DWORD* pNumPasses) PURE; - STDMETHOD(ProcessVertices)(THIS_ UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, struct IWineD3DVertexBuffer* pDestBuffer, struct IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) PURE; + STDMETHOD(ProcessVertices)(THIS_ UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, struct IWineD3DVertexBuffer* pDestBuffer, struct IWineD3DVertexDeclaration* pVertexDecl, DWORD Flags) PURE; STDMETHOD(BeginStateBlock)(THIS) PURE; STDMETHOD(EndStateBlock)(THIS_ struct IWineD3DStateBlock** ppStateBlock) PURE; STDMETHOD(BeginScene)(THIS) PURE;