Commit 51a31538 authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

ddraw: Use a less offensive handle table implementation for surfaces.

parent 91193b6e
...@@ -322,17 +322,6 @@ extern const IParentVtbl IParent_Vtbl DECLSPEC_HIDDEN; ...@@ -322,17 +322,6 @@ extern const IParentVtbl IParent_Vtbl DECLSPEC_HIDDEN;
/***************************************************************************** /*****************************************************************************
* IDirect3DDevice implementation * IDirect3DDevice implementation
*****************************************************************************/ *****************************************************************************/
typedef enum
{
DDrawHandle_Unknown = 0,
DDrawHandle_Texture = 1,
} DDrawHandleTypes;
struct HandleEntry
{
void *ptr;
DDrawHandleTypes type;
};
#define DDRAW_INVALID_HANDLE ~0U #define DDRAW_INVALID_HANDLE ~0U
...@@ -342,6 +331,7 @@ enum ddraw_handle_type ...@@ -342,6 +331,7 @@ enum ddraw_handle_type
DDRAW_HANDLE_MATERIAL, DDRAW_HANDLE_MATERIAL,
DDRAW_HANDLE_MATRIX, DDRAW_HANDLE_MATRIX,
DDRAW_HANDLE_STATEBLOCK, DDRAW_HANDLE_STATEBLOCK,
DDRAW_HANDLE_SURFACE,
}; };
struct ddraw_handle_entry struct ddraw_handle_entry
...@@ -401,8 +391,6 @@ struct IDirect3DDeviceImpl ...@@ -401,8 +391,6 @@ struct IDirect3DDeviceImpl
DWORD buffer_size; DWORD buffer_size;
/* Handle management */ /* Handle management */
struct HandleEntry *Handles;
DWORD numHandles;
struct ddraw_handle_table handle_table; struct ddraw_handle_table handle_table;
D3DMATRIXHANDLE world, proj, view; D3DMATRIXHANDLE world, proj, view;
}; };
...@@ -419,7 +407,6 @@ extern const GUID IID_D3DDEVICE_WineD3D DECLSPEC_HIDDEN; ...@@ -419,7 +407,6 @@ extern const GUID IID_D3DDEVICE_WineD3D DECLSPEC_HIDDEN;
/* Helper functions */ /* Helper functions */
HRESULT IDirect3DImpl_GetCaps(IWineD3D *WineD3D, D3DDEVICEDESC *Desc123, D3DDEVICEDESC7 *Desc7) DECLSPEC_HIDDEN; HRESULT IDirect3DImpl_GetCaps(IWineD3D *WineD3D, D3DDEVICEDESC *Desc123, D3DDEVICEDESC7 *Desc7) DECLSPEC_HIDDEN;
DWORD IDirect3DDeviceImpl_CreateHandle(IDirect3DDeviceImpl *This) DECLSPEC_HIDDEN;
WINED3DZBUFFERTYPE IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This) DECLSPEC_HIDDEN; WINED3DZBUFFERTYPE IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This) DECLSPEC_HIDDEN;
static inline IDirect3DDeviceImpl *device_from_device1(IDirect3DDevice *iface) static inline IDirect3DDeviceImpl *device_from_device1(IDirect3DDevice *iface)
......
...@@ -366,30 +366,7 @@ IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface) ...@@ -366,30 +366,7 @@ IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
} }
/* The texture handles should be unset by now, but there might be some bits /* The texture handles should be unset by now, but there might be some bits
* missing in our reference counting(needs test). Do a sanity check * missing in our reference counting(needs test). Do a sanity check. */
*/
for(i = 0; i < This->numHandles; i++)
{
if(This->Handles[i].ptr)
{
switch(This->Handles[i].type)
{
case DDrawHandle_Texture:
{
IDirectDrawSurfaceImpl *surf = This->Handles[i].ptr;
FIXME("Texture Handle %d not unset properly\n", i + 1);
surf->Handle = 0;
}
break;
default:
FIXME("Unknown handle %d not unset properly\n", i + 1);
}
}
}
HeapFree(GetProcessHeap(), 0, This->Handles);
for (i = 0; i < This->handle_table.entry_count; ++i) for (i = 0; i < This->handle_table.entry_count; ++i)
{ {
struct ddraw_handle_entry *entry = &This->handle_table.entries[i]; struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
...@@ -423,6 +400,14 @@ IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface) ...@@ -423,6 +400,14 @@ IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
break; break;
} }
case DDRAW_HANDLE_SURFACE:
{
IDirectDrawSurfaceImpl *surf = entry->object;
FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
surf->Handle = 0;
break;
}
default: default:
FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type); FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
break; break;
...@@ -627,18 +612,21 @@ IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface, ...@@ -627,18 +612,21 @@ IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
IDirect3DTexture2 *Tex2) IDirect3DTexture2 *Tex2)
{ {
IDirect3DDeviceImpl *This = device_from_device2(iface); IDirect3DDeviceImpl *This = device_from_device2(iface);
DWORD swap;
IDirectDrawSurfaceImpl *surf1 = surface_from_texture2(Tex1); IDirectDrawSurfaceImpl *surf1 = surface_from_texture2(Tex1);
IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(Tex2); IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(Tex2);
DWORD h1, h2;
TRACE("(%p)->(%p,%p)\n", This, surf1, surf2); TRACE("(%p)->(%p,%p)\n", This, surf1, surf2);
EnterCriticalSection(&ddraw_cs); EnterCriticalSection(&ddraw_cs);
This->Handles[surf1->Handle - 1].ptr = surf2;
This->Handles[surf2->Handle - 1].ptr = surf1;
swap = surf2->Handle; h1 = surf1->Handle - 1;
surf2->Handle = surf1->Handle; h2 = surf2->Handle - 1;
surf1->Handle = swap; This->handle_table.entries[h1].object = surf2;
This->handle_table.entries[h2].object = surf1;
surf2->Handle = h1 + 1;
surf1->Handle = h2 + 1;
LeaveCriticalSection(&ddraw_cs); LeaveCriticalSection(&ddraw_cs);
return D3D_OK; return D3D_OK;
...@@ -2883,6 +2871,8 @@ IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface, ...@@ -2883,6 +2871,8 @@ IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
{ {
case D3DRENDERSTATE_TEXTUREHANDLE: case D3DRENDERSTATE_TEXTUREHANDLE:
{ {
IDirectDrawSurfaceImpl *surf;
if(Value == 0) if(Value == 0)
{ {
hr = IWineD3DDevice_SetTexture(This->wineD3DDevice, hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
...@@ -2891,25 +2881,16 @@ IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface, ...@@ -2891,25 +2881,16 @@ IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
break; break;
} }
if(Value > This->numHandles) surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
if (!surf)
{ {
FIXME("Specified handle %d out of range\n", Value); WARN("Invalid texture handle.\n");
hr = DDERR_INVALIDPARAMS; hr = DDERR_INVALIDPARAMS;
break; break;
} }
if(This->Handles[Value - 1].type != DDrawHandle_Texture)
{ hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
FIXME("Handle %d isn't a texture handle\n", Value); break;
hr = DDERR_INVALIDPARAMS;
break;
}
else
{
IDirectDrawSurfaceImpl *surf = This->Handles[Value - 1].ptr;
IDirect3DTexture2 *tex = surf ? (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl : NULL;
hr = IDirect3DDevice3_SetTexture(iface, 0, tex);
break;
}
} }
case D3DRENDERSTATE_TEXTUREMAPBLEND: case D3DRENDERSTATE_TEXTUREMAPBLEND:
...@@ -6874,71 +6855,6 @@ const IDirect3DDeviceVtbl IDirect3DDevice1_Vtbl = ...@@ -6874,71 +6855,6 @@ const IDirect3DDeviceVtbl IDirect3DDevice1_Vtbl =
}; };
/***************************************************************************** /*****************************************************************************
* IDirect3DDeviceImpl_CreateHandle
*
* Not called from the VTable
*
* Some older interface versions operate with handles, which are basically
* DWORDs which identify an interface, for example
* IDirect3DDevice::SetRenderState with DIRECT3DRENDERSTATE_TEXTUREHANDLE
*
* Those handle could be just casts to the interface pointers or vice versa,
* but that is not 64 bit safe and would mean blindly derefering a DWORD
* passed by the app. Instead there is a dynamic array in the device which
* keeps a DWORD to pointer information and a type for the handle.
*
* Basically this array only grows, when a handle is freed its pointer is
* just set to NULL. There will be much more reads from the array than
* insertion operations, so a dynamic array is fine.
*
* Params:
* This: D3DDevice implementation for which this handle should be created
*
* Returns:
* A free handle on success
* 0 on failure
*
*****************************************************************************/
DWORD
IDirect3DDeviceImpl_CreateHandle(IDirect3DDeviceImpl *This)
{
DWORD i;
struct HandleEntry *oldHandles = This->Handles;
TRACE("(%p)\n", This);
for(i = 0; i < This->numHandles; i++)
{
if(This->Handles[i].ptr == NULL &&
This->Handles[i].type == DDrawHandle_Unknown)
{
TRACE("Reusing freed handle %d\n", i + 1);
return i + 1;
}
}
TRACE("Growing the handle array\n");
This->numHandles++;
This->Handles = HeapAlloc(GetProcessHeap(), 0, sizeof(struct HandleEntry) * This->numHandles);
if(!This->Handles)
{
ERR("Out of memory\n");
This->Handles = oldHandles;
This->numHandles--;
return 0;
}
if(oldHandles)
{
memcpy(This->Handles, oldHandles, (This->numHandles - 1) * sizeof(struct HandleEntry));
HeapFree(GetProcessHeap(), 0, oldHandles);
}
TRACE("Returning %d\n", This->numHandles);
return This->numHandles;
}
/*****************************************************************************
* IDirect3DDeviceImpl_UpdateDepthStencil * IDirect3DDeviceImpl_UpdateDepthStencil
* *
* Checks the current render target for attached depth stencils and sets the * Checks the current render target for attached depth stencils and sets the
......
...@@ -805,9 +805,6 @@ IDirect3DImpl_7_CreateDevice(IDirect3D7 *iface, ...@@ -805,9 +805,6 @@ IDirect3DImpl_7_CreateDevice(IDirect3D7 *iface,
object->material = 0; object->material = 0;
object->target = target; object->target = target;
object->Handles = NULL;
object->numHandles = 0;
if (!ddraw_handle_table_init(&object->handle_table, 64)) if (!ddraw_handle_table_init(&object->handle_table, 64))
{ {
ERR("Failed to initialize handle table.\n"); ERR("Failed to initialize handle table.\n");
......
...@@ -250,8 +250,7 @@ void ddraw_surface_destroy(IDirectDrawSurfaceImpl *This) ...@@ -250,8 +250,7 @@ void ddraw_surface_destroy(IDirectDrawSurfaceImpl *This)
/* Having a texture handle set implies that the device still exists */ /* Having a texture handle set implies that the device still exists */
if(This->Handle) if(This->Handle)
{ {
This->ddraw->d3ddevice->Handles[This->Handle - 1].ptr = NULL; ddraw_free_handle(&This->ddraw->d3ddevice->handle_table, This->Handle - 1, DDRAW_HANDLE_SURFACE);
This->ddraw->d3ddevice->Handles[This->Handle - 1].type = DDrawHandle_Unknown;
} }
/* Reduce the ddraw surface count */ /* Reduce the ddraw surface count */
......
...@@ -211,12 +211,15 @@ IDirect3DTextureImpl_GetHandle(IDirect3DTexture2 *iface, ...@@ -211,12 +211,15 @@ IDirect3DTextureImpl_GetHandle(IDirect3DTexture2 *iface,
EnterCriticalSection(&ddraw_cs); EnterCriticalSection(&ddraw_cs);
if(!This->Handle) if(!This->Handle)
{ {
This->Handle = IDirect3DDeviceImpl_CreateHandle(d3d); DWORD h = ddraw_allocate_handle(&d3d->handle_table, This, DDRAW_HANDLE_SURFACE);
if(This->Handle) if (h == DDRAW_INVALID_HANDLE)
{ {
d3d->Handles[This->Handle - 1].ptr = This; ERR("Failed to allocate a texture handle.\n");
d3d->Handles[This->Handle - 1].type = DDrawHandle_Texture; LeaveCriticalSection(&ddraw_cs);
return DDERR_OUTOFMEMORY;
} }
This->Handle = h + 1;
} }
*lpHandle = This->Handle; *lpHandle = This->Handle;
......
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