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.
This commit is contained in:
Stefan Dösinger 2007-04-22 17:55:30 +02:00 committed by Alexandre Julliard
parent 32cfbd127c
commit 0386eed91f
6 changed files with 126 additions and 8 deletions

View File

@ -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;
}

View File

@ -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 ***/

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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;