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

ddraw: Get rid of FVFs.

Remove all IWineD3DDevice::SetFVF calls and instead create converted vertex declarations and use them. The idea is to remove the FVF paths from wined3d to simplify the code, and optimize the vertex declaration codepath.
parent 32cfbd12
......@@ -246,6 +246,14 @@ IDirectDrawImpl_AddRef(IDirectDraw7 *iface)
void
IDirectDrawImpl_Destroy(IDirectDrawImpl *This)
{
int i;
for(i = 0; i < This->numConvertedDecls; i++)
{
IWineD3DVertexDeclaration_Release(This->decls[i].decl);
}
HeapFree(GetProcessHeap(), 0, This->decls);
/* Clear the cooplevel to restore window and display mode */
IDirectDraw7_SetCooperativeLevel(ICOM_INTERFACE(This, IDirectDraw7),
NULL,
......@@ -3014,3 +3022,78 @@ const IDirectDraw7Vtbl IDirectDraw7_Vtbl =
IDirectDrawImpl_StartModeTest,
IDirectDrawImpl_EvaluateMode
};
/*****************************************************************************
* IDirectDrawImpl_FindDecl
*
* Finds the WineD3D vertex declaration for a specific fvf, and creates one
* if none was found.
*
* This function is in ddraw.c and the DDraw object space because D3D7
* vertex buffers are created using the IDirect3D interface to the ddraw
* object, so they can be valid accross D3D devices(theoretically. The ddraw
* object also owns the wined3d device
*
* Parameters:
* This: Device
* fvf: Fvf to find the decl for
*
* Returns:
* NULL in case of an error, the IWineD3DVertexDeclaration interface for the
* fvf otherwise.
*
*****************************************************************************/
IWineD3DVertexDeclaration *
IDirectDrawImpl_FindDecl(IDirectDrawImpl *This,
DWORD fvf)
{
HRESULT hr;
IWineD3DVertexDeclaration* pDecl = NULL;
int p, low, high; /* deliberately signed */
struct FvfToDecl *convertedDecls = This->decls;
TRACE("Searching for declaration for fvf %08x... ", fvf);
low = 0;
high = This->numConvertedDecls - 1;
while(low <= high) {
p = (low + high) >> 1;
TRACE("%d ", p);
if(convertedDecls[p].fvf == fvf) {
TRACE("found %p\n", convertedDecls[p].decl);
return convertedDecls[p].decl;
} else if(convertedDecls[p].fvf < fvf) {
low = p + 1;
} else {
high = p - 1;
}
}
TRACE("not found. Creating and inserting at position %d.\n", low);
hr = IWineD3DDevice_CreateVertexDeclarationFromFVF(This->wineD3DDevice,
&pDecl,
(IUnknown *) ICOM_INTERFACE(This, IDirectDraw7),
fvf);
if (hr != S_OK) return NULL;
if(This->declArraySize == This->numConvertedDecls) {
int grow = max(This->declArraySize / 2, 8);
convertedDecls = HeapReAlloc(GetProcessHeap(), 0, convertedDecls,
sizeof(convertedDecls[0]) * (This->numConvertedDecls + grow));
if(!convertedDecls) {
/* This will destroy it */
IWineD3DVertexDeclaration_Release(pDecl);
return NULL;
}
This->decls = convertedDecls;
This->declArraySize += grow;
}
memmove(convertedDecls + low + 1, convertedDecls + low, sizeof(convertedDecls[0]) * (This->numConvertedDecls - low));
convertedDecls[low].decl = pDecl;
convertedDecls[low].fvf = fvf;
This->numConvertedDecls++;
TRACE("Returning %p. %d decls in array\n", pDecl, This->numConvertedDecls);
return pDecl;
}
......@@ -83,6 +83,11 @@ extern ULONG WINAPI D3D7CB_DestroyDepthStencilSurface(IWineD3DSurface *pSurface)
/*****************************************************************************
* IDirectDraw implementation structure
*****************************************************************************/
struct FvfToDecl
{
DWORD fvf;
IWineD3DVertexDeclaration *decl;
};
struct IDirectDrawImpl
{
......@@ -149,6 +154,10 @@ struct IDirectDrawImpl
*/
struct list surface_list;
LONG surfaces;
/* FVF management */
struct FvfToDecl *decls;
UINT numConvertedDecls, declArraySize;
};
/* Declare the VTables. They can be found ddraw.c */
......@@ -187,6 +196,10 @@ HRESULT WINAPI
IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf,
DDSURFACEDESC2 *desc,
void *Context);
IWineD3DVertexDeclaration *
IDirectDrawImpl_FindDecl(IDirectDrawImpl *This,
DWORD fvf);
void
remove_ddraw_object(IDirectDrawImpl *ddraw);
......@@ -577,6 +590,7 @@ struct IDirect3DVertexBufferImpl
/*** WineD3D and ddraw links ***/
IWineD3DVertexBuffer *wineD3DVertexBuffer;
IWineD3DVertexDeclaration *wineD3DVertexDeclaration;
IDirectDrawImpl *ddraw;
/*** Storage for D3D7 specific things ***/
......
......@@ -2963,7 +2963,8 @@ IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
stride = get_flexible_vertex_size(VertexType);
/* Set the FVF */
hr = IWineD3DDevice_SetFVF(This->wineD3DDevice, VertexType);
hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
IDirectDrawImpl_FindDecl(This->ddraw, VertexType));
if(hr != D3D_OK) return hr;
/* This method translates to the user pointer draw of WineD3D */
......@@ -3091,7 +3092,8 @@ IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
}
/* Set the D3DDevice's FVF */
hr = IWineD3DDevice_SetFVF(This->wineD3DDevice, VertexType);
hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
IDirectDrawImpl_FindDecl(This->ddraw, VertexType));
if(FAILED(hr))
{
ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
......@@ -3381,9 +3383,7 @@ IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
default: return DDERR_INVALIDPARAMS;
}
IWineD3DDevice_SetFVF(This->wineD3DDevice,
VertexType);
/* WineD3D doesn't need the FVF here */
return IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice,
PrimitiveType,
PrimitiveCount,
......@@ -3549,7 +3549,8 @@ IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
}
stride = get_flexible_vertex_size(Desc.FVF);
hr = IWineD3DDevice_SetFVF(This->wineD3DDevice, Desc.FVF);
hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
vb->wineD3DVertexDeclaration);
if(FAILED(hr))
{
ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
......@@ -3681,7 +3682,8 @@ IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
stride = get_flexible_vertex_size(Desc.FVF);
TRACE("Vertex buffer FVF = %08x, stride=%d\n", Desc.FVF, stride);
hr = IWineD3DDevice_SetFVF(This->wineD3DDevice, Desc.FVF);
hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
vb->wineD3DVertexDeclaration);
if(FAILED(hr))
{
ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
......
......@@ -1021,6 +1021,17 @@ IDirect3DImpl_7_CreateVertexBuffer(IDirect3D7 *iface,
return hr;
}
object->wineD3DVertexDeclaration = IDirectDrawImpl_FindDecl(This,
Desc->dwFVF);
if(!object->wineD3DVertexDeclaration)
{
ERR("Cannot find the vertex declaration for fvf %08x\n", Desc->dwFVF);
IWineD3DVertexBuffer_Release(object->wineD3DVertexBuffer);
HeapFree(GetProcessHeap(), 0, object);
return DDERR_INVALIDPARAMS;
}
IWineD3DVertexDeclaration_AddRef(object->wineD3DVertexDeclaration);
/* Return the interface */
*VertexBuffer = ICOM_INTERFACE(object, IDirect3DVertexBuffer7);
......
......@@ -322,6 +322,13 @@ DDRAW_Create(const GUID *guid,
list_add_head(&global_ddraw_list, &This->ddraw_list_entry);
LeaveCriticalSection(&ddraw_list_cs);
This->decls = HeapAlloc(GetProcessHeap(), 0, 0);
if(!This->decls)
{
ERR("Error allocating an empty array for the converted vertex decls\n");
goto err_out;
}
/* Call QueryInterface to get the pointer to the requested interface. This also initializes
* The required refcount
*/
......@@ -332,6 +339,7 @@ err_out:
/* Let's hope we never need this ;) */
if(wineD3DDevice) IWineD3DDevice_Release(wineD3DDevice);
if(wineD3D) IWineD3D_Release(wineD3D);
if(This) HeapFree(GetProcessHeap(), 0, This->decls);
HeapFree(GetProcessHeap(), 0, This);
return hr;
}
......
......@@ -189,7 +189,7 @@ IDirect3DVertexBufferImpl_Release(IDirect3DVertexBuffer7 *iface)
IWineD3DVertexBuffer_Release(curVB); /* For the GetStreamSource */
}
IWineD3DVertexDeclaration_Release(This->wineD3DVertexDeclaration);
IWineD3DVertexBuffer_Release(This->wineD3DVertexBuffer);
HeapFree(GetProcessHeap(), 0, This);
return 0;
......
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