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.
This commit is contained in:
Stefan Dösinger 2007-04-22 18:06:07 +02:00 committed by Alexandre Julliard
parent 0386eed91f
commit 460f71dcf8
4 changed files with 54 additions and 53 deletions

View File

@ -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) { static HRESULT WINAPI IDirect3DDevice9Impl_ProcessVertices(LPDIRECT3DDEVICE9 iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer9* pDestBuffer, IDirect3DVertexDeclaration9* pVertexDecl, DWORD Flags) {
IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
IDirect3DVertexDeclaration9Impl *Decl = (IDirect3DVertexDeclaration9Impl *) pVertexDecl;
TRACE("(%p) Relay\n" , This); 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) { IDirect3DVertexDeclaration9 *getConvertedDecl(IDirect3DDevice9Impl *This, DWORD fvf) {

View File

@ -341,6 +341,7 @@ IDirect3DVertexBufferImpl_ProcessVertices(IDirect3DVertexBuffer7 *iface,
IDirect3DDeviceImpl *D3D = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice7, D3DDevice); IDirect3DDeviceImpl *D3D = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice7, D3DDevice);
BOOL oldClip, doClip; BOOL oldClip, doClip;
HRESULT hr; HRESULT hr;
WINED3DVERTEXBUFFER_DESC Desc;
TRACE("(%p)->(%08x,%d,%d,%p,%d,%p,%08x)\n", This, VertexOp, DestIndex, Count, Src, SrcIndex, D3D, Flags); 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); 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, hr = IWineD3DDevice_ProcessVertices(D3D->wineD3DDevice,
SrcIndex, SrcIndex,
DestIndex, DestIndex,
Count, Count,
This->wineD3DVertexBuffer, This->wineD3DVertexBuffer,
Src->wineD3DVertexBuffer, NULL /* Output vdecl */,
Flags); Flags);
/* Restore the states if needed */ /* Restore the states if needed */

View File

@ -3489,7 +3489,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
#define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size) #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
static HRESULT 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; char *dest_ptr, *dest_conv = NULL, *dest_conv_addr = NULL;
unsigned int i; unsigned int i;
DWORD DestFVF = dest->fvf; DWORD DestFVF = dest->fvf;
@ -3498,11 +3498,11 @@ process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCo
BOOL doClip; BOOL doClip;
int numTextures; int numTextures;
if (SrcFVF & WINED3DFVF_NORMAL) { if (lpStrideData->u.s.normal.lpData) {
WARN(" lighting state not saved yet... Some strange stuff may happen !\n"); 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"); ERR("Source has no position mask\n");
return WINED3DERR_INVALIDCALL; return WINED3DERR_INVALIDCALL;
} }
@ -3837,15 +3837,14 @@ process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCo
} }
#undef copy_and_next #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; IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
WineDirect3DVertexStridedData strided; WineDirect3DVertexStridedData strided;
BOOL vbo = FALSE;
TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags); TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
if (!SrcImpl) { if(pVertexDecl) {
WARN("NULL source vertex buffer\n"); ERR("Output vertex declaration not implemented yet\n");
return WINED3DERR_INVALIDCALL;
} }
/* Need any context to write to the vbo. In a non-multithreaded environment a context is there anyway, /* 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(); LEAVE_GL();
} }
/* We don't need the source vbo because this buffer is only used as memset(&strided, 0, sizeof(strided));
* a source for ProcessVertices. Avoid wasting resources by converting the if(This->stateBlock->vertexDecl) {
* buffer and loading the VBO primitiveDeclarationConvertToStridedData(iface, FALSE, &strided, &vbo);
*/ } else {
if(SrcImpl->vbo) { primitiveConvertToStridedData(iface, &strided, &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(vbo || SrcStartIndex) {
primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0, 0); 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);
} }
/***** /*****

View File

@ -452,7 +452,7 @@ DECLARE_INTERFACE_(IWineD3DDevice,IWineD3DBase)
STDMETHOD(GetViewport)(THIS_ WINED3DVIEWPORT * pViewport) PURE; STDMETHOD(GetViewport)(THIS_ WINED3DVIEWPORT * pViewport) PURE;
STDMETHOD(MultiplyTransform)(THIS_ WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX * pMatrix) PURE; STDMETHOD(MultiplyTransform)(THIS_ WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX * pMatrix) PURE;
STDMETHOD(ValidateDevice)(THIS_ DWORD* pNumPasses) 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(BeginStateBlock)(THIS) PURE;
STDMETHOD(EndStateBlock)(THIS_ struct IWineD3DStateBlock** ppStateBlock) PURE; STDMETHOD(EndStateBlock)(THIS_ struct IWineD3DStateBlock** ppStateBlock) PURE;
STDMETHOD(BeginScene)(THIS) PURE; STDMETHOD(BeginScene)(THIS) PURE;