Commit d47ec212 authored by Stefan Dösinger's avatar Stefan Dösinger Committed by Alexandre Julliard

wined3d: Vertex buffers can use the declaration from the device.

parent 6fb1869b
...@@ -219,6 +219,10 @@ void primitiveDeclarationConvertToStridedData( ...@@ -219,6 +219,10 @@ void primitiveDeclarationConvertToStridedData(
WINED3DVERTEXELEMENT *element; WINED3DVERTEXELEMENT *element;
DWORD stride; DWORD stride;
int reg; int reg;
char isPreLoaded[MAX_STREAMS];
DWORD preLoadStreams[MAX_STREAMS], numPreloadStreams = 0;
memset(isPreLoaded, 0, sizeof(isPreLoaded));
/* Locate the vertex declaration */ /* Locate the vertex declaration */
if (This->stateBlock->vertexShader && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration) { if (This->stateBlock->vertexShader && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration) {
...@@ -249,7 +253,11 @@ void primitiveDeclarationConvertToStridedData( ...@@ -249,7 +253,11 @@ void primitiveDeclarationConvertToStridedData(
if(fixup && *fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n"); if(fixup && *fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
} else { } else {
TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]); TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[element->Stream]); if(!isPreLoaded[element->Stream]) {
preLoadStreams[numPreloadStreams] = element->Stream;
numPreloadStreams++;
isPreLoaded[element->Stream] = 1;
}
data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0, &streamVBO); data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0, &streamVBO);
if(fixup) { if(fixup) {
if( streamVBO != 0) *fixup = TRUE; if( streamVBO != 0) *fixup = TRUE;
...@@ -287,6 +295,17 @@ void primitiveDeclarationConvertToStridedData( ...@@ -287,6 +295,17 @@ void primitiveDeclarationConvertToStridedData(
} }
} }
}; };
/* Now call PreLoad on all the vertex buffers. In the very rare case
* that the buffers stopps converting PreLoad will dirtify the VDECL again.
* The vertex buffer can now use the strided structure in the device instead of finding its
* own again.
*
* NULL streams won't be recorded in the array, UP streams won't be either. A stream is only
* once in there.
*/
for(i=0; i < numPreloadStreams; i++) {
IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[preLoadStreams[i]]);
}
} }
void primitiveConvertFVFtoOffset(DWORD thisFVF, DWORD stride, BYTE *data, WineDirect3DVertexStridedData *strided, GLint streamVBO) { void primitiveConvertFVFtoOffset(DWORD thisFVF, DWORD stride, BYTE *data, WineDirect3DVertexStridedData *strided, GLint streamVBO) {
...@@ -413,6 +432,7 @@ void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStri ...@@ -413,6 +432,7 @@ void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStri
short LoopThroughTo = 0; short LoopThroughTo = 0;
short nStream; short nStream;
GLint streamVBO = 0; GLint streamVBO = 0;
DWORD preLoadStreams[MAX_STREAMS], numPreloadStreams = 0;
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
...@@ -443,7 +463,11 @@ void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStri ...@@ -443,7 +463,11 @@ void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStri
streamVBO = 0; streamVBO = 0;
data = (BYTE *)This->stateBlock->streamSource[nStream]; data = (BYTE *)This->stateBlock->streamSource[nStream];
} else { } else {
IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[nStream]); /* The for loop should iterate through here only once per stream, so we don't need magic to prevent double loading
* buffers
*/
preLoadStreams[numPreloadStreams] = nStream;
numPreloadStreams++;
/* GetMemory binds the VBO */ /* GetMemory binds the VBO */
data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0, &streamVBO); data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0, &streamVBO);
if(fixup) { if(fixup) {
...@@ -462,6 +486,17 @@ void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStri ...@@ -462,6 +486,17 @@ void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStri
/* Now convert the stream into pointers */ /* Now convert the stream into pointers */
primitiveConvertFVFtoOffset(thisFVF, stride, data, strided, streamVBO); primitiveConvertFVFtoOffset(thisFVF, stride, data, strided, streamVBO);
} }
/* Now call PreLoad on all the vertex buffers. In the very rare case
* that the buffers stopps converting PreLoad will dirtify the VDECL again.
* The vertex buffer can now use the strided structure in the device instead of finding its
* own again.
*
* NULL streams won't be recorded in the array, UP streams won't be either. A stream is only
* once in there.
*/
for(nStream=0; nStream < numPreloadStreams; nStream++) {
IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[preLoadStreams[nStream]]);
}
} }
#if 0 /* TODO: Software Shaders */ #if 0 /* TODO: Software Shaders */
......
...@@ -164,7 +164,6 @@ inline BOOL WINAPI IWineD3DVertexBufferImpl_FindDecl(IWineD3DVertexBufferImpl *T ...@@ -164,7 +164,6 @@ inline BOOL WINAPI IWineD3DVertexBufferImpl_FindDecl(IWineD3DVertexBufferImpl *T
{ {
WineDirect3DVertexStridedData strided; WineDirect3DVertexStridedData strided;
IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
BOOL ret;
memset(&strided, 0, sizeof(strided)); memset(&strided, 0, sizeof(strided));
/* There are certain vertex data types that need to be fixed up. The Vertex Buffers FVF doesn't /* There are certain vertex data types that need to be fixed up. The Vertex Buffers FVF doesn't
...@@ -191,38 +190,18 @@ inline BOOL WINAPI IWineD3DVertexBufferImpl_FindDecl(IWineD3DVertexBufferImpl *T ...@@ -191,38 +190,18 @@ inline BOOL WINAPI IWineD3DVertexBufferImpl_FindDecl(IWineD3DVertexBufferImpl *T
* FALSE: otherwise * FALSE: otherwise
*/ */
if(device->stateBlock->vertexShader != NULL && wined3d_settings.vs_mode != VS_NONE if(device->stateBlock->vertexShader && ((IWineD3DVertexShaderImpl *) device->stateBlock->vertexShader)->baseShader.function) {
&&((IWineD3DVertexShaderImpl *)device->stateBlock->vertexShader)->baseShader.function != NULL /* Assume no conversion */
&& GL_SUPPORT(ARB_VERTEX_PROGRAM)) { memset(&strided, 0, sizeof(strided));
/* Case 1: Vertex Shader: No conversion */
TRACE("Vertex Shader, no conversion needed\n");
} else if(device->stateBlock->vertexDecl || device->stateBlock->vertexShader) {
/* Case 2: Vertex Declaration */
TRACE("Using vertex declaration\n");
This->Flags |= VBFLAG_LOAD;
primitiveDeclarationConvertToStridedData((IWineD3DDevice *) device,
FALSE,
&strided,
&ret /* buffer contains fixed data, ignored here */);
This->Flags &= ~VBFLAG_LOAD;
} else {
/* Case 3: FVF */
if(!(This->Flags & VBFLAG_STREAM) ) {
TRACE("No vertex decl used and buffer is not bound to a stream\n");
/* No reload needed */
return FALSE;
} else { } else {
This->Flags |= VBFLAG_LOAD; /* we need a copy because we modify some params */
primitiveConvertFVFtoOffset(device->stateBlock->fvf, memcpy(&strided, &device->strided_streams, sizeof(strided));
device->stateBlock->streamStride[This->stream],
NULL, /* Filter out data that does not come from this VBO */
&strided, if(strided.u.s.position.VBO != This->vbo) memset(&strided.u.s.position, 0, sizeof(strided.u.s.position));
This->vbo); if(strided.u.s.diffuse.VBO != This->vbo) memset(&strided.u.s.diffuse, 0, sizeof(strided.u.s.diffuse));
This->Flags &= ~VBFLAG_LOAD; if(strided.u.s.specular.VBO != This->vbo) memset(&strided.u.s.specular, 0, sizeof(strided.u.s.specular));
/* Data can only come from this buffer */ if(strided.u.s.position2.VBO != This->vbo) memset(&strided.u.s.position2, 0, sizeof(strided.u.s.position2));
}
} }
/* Filter out data that does not come from this VBO */ /* Filter out data that does not come from this VBO */
...@@ -297,6 +276,14 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if ...@@ -297,6 +276,14 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if
checkGLcall("glDeleteBuffersARB"); checkGLcall("glDeleteBuffersARB");
LEAVE_GL(); LEAVE_GL();
This->vbo = 0; This->vbo = 0;
/* The stream source state handler might have read the memory of the vertex buffer already
* and got the memory in the vbo which is not valid any longer. Dirtify the stream source
* to force a reload. This happens only once per changed vertexbuffer and should occur rather
* rarely
*/
IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_STREAMSRC);
return; return;
} }
/* Otherwise do not bother to release the VBO. If we're doing direct locking now, /* Otherwise do not bother to release the VBO. If we're doing direct locking now,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment