ddraw: Use a less offensive handle table implementation for materials.
This commit is contained in:
parent
7b3d200ab3
commit
0cb4de4542
|
@ -326,7 +326,6 @@ typedef enum
|
|||
{
|
||||
DDrawHandle_Unknown = 0,
|
||||
DDrawHandle_Texture = 1,
|
||||
DDrawHandle_Material = 2,
|
||||
DDrawHandle_Matrix = 3,
|
||||
DDrawHandle_StateBlock = 4
|
||||
} DDrawHandleTypes;
|
||||
|
@ -337,6 +336,34 @@ struct HandleEntry
|
|||
DDrawHandleTypes type;
|
||||
};
|
||||
|
||||
#define DDRAW_INVALID_HANDLE ~0U
|
||||
|
||||
enum ddraw_handle_type
|
||||
{
|
||||
DDRAW_HANDLE_FREE,
|
||||
DDRAW_HANDLE_MATERIAL,
|
||||
};
|
||||
|
||||
struct ddraw_handle_entry
|
||||
{
|
||||
void *object;
|
||||
enum ddraw_handle_type type;
|
||||
};
|
||||
|
||||
struct ddraw_handle_table
|
||||
{
|
||||
struct ddraw_handle_entry *entries;
|
||||
struct ddraw_handle_entry *free_entries;
|
||||
UINT table_size;
|
||||
UINT entry_count;
|
||||
};
|
||||
|
||||
BOOL ddraw_handle_table_init(struct ddraw_handle_table *t, UINT initial_size) DECLSPEC_HIDDEN;
|
||||
void ddraw_handle_table_destroy(struct ddraw_handle_table *t) DECLSPEC_HIDDEN;
|
||||
DWORD ddraw_allocate_handle(struct ddraw_handle_table *t, void *object, enum ddraw_handle_type type) DECLSPEC_HIDDEN;
|
||||
void *ddraw_free_handle(struct ddraw_handle_table *t, DWORD handle, enum ddraw_handle_type type) DECLSPEC_HIDDEN;
|
||||
void *ddraw_get_object(struct ddraw_handle_table *t, DWORD handle, enum ddraw_handle_type type) DECLSPEC_HIDDEN;
|
||||
|
||||
struct IDirect3DDeviceImpl
|
||||
{
|
||||
/* IUnknown */
|
||||
|
@ -376,6 +403,7 @@ struct IDirect3DDeviceImpl
|
|||
/* Handle management */
|
||||
struct HandleEntry *Handles;
|
||||
DWORD numHandles;
|
||||
struct ddraw_handle_table handle_table;
|
||||
D3DMATRIXHANDLE world, proj, view;
|
||||
};
|
||||
|
||||
|
|
|
@ -382,14 +382,6 @@ IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
|
|||
}
|
||||
break;
|
||||
|
||||
case DDrawHandle_Material:
|
||||
{
|
||||
IDirect3DMaterialImpl *mat = This->Handles[i].ptr;
|
||||
FIXME("Material handle %d not unset properly\n", i + 1);
|
||||
mat->Handle = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case DDrawHandle_Matrix:
|
||||
{
|
||||
/* No fixme here because this might happen because of sloppy apps */
|
||||
|
@ -414,6 +406,31 @@ IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
|
|||
|
||||
HeapFree(GetProcessHeap(), 0, This->Handles);
|
||||
|
||||
for (i = 0; i < This->handle_table.entry_count; ++i)
|
||||
{
|
||||
struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
|
||||
|
||||
switch (entry->type)
|
||||
{
|
||||
case DDRAW_HANDLE_FREE:
|
||||
break;
|
||||
|
||||
case DDRAW_HANDLE_MATERIAL:
|
||||
{
|
||||
IDirect3DMaterialImpl *m = entry->object;
|
||||
FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
|
||||
m->Handle = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ddraw_handle_table_destroy(&This->handle_table);
|
||||
|
||||
TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
|
||||
/* Release the render target and the WineD3D render target
|
||||
* (See IDirect3D7::CreateDevice for more comments on this)
|
||||
|
@ -3048,35 +3065,17 @@ IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
|
|||
EnterCriticalSection(&ddraw_cs);
|
||||
if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
|
||||
{
|
||||
IDirect3DMaterialImpl *mat;
|
||||
|
||||
if(Value == 0) mat = NULL;
|
||||
else if(Value > This->numHandles)
|
||||
IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
|
||||
if (!m)
|
||||
{
|
||||
ERR("Material handle out of range(%d)\n", Value);
|
||||
WARN("Invalid material handle.\n");
|
||||
LeaveCriticalSection(&ddraw_cs);
|
||||
return DDERR_INVALIDPARAMS;
|
||||
}
|
||||
else if(This->Handles[Value - 1].type != DDrawHandle_Material)
|
||||
{
|
||||
ERR("Invalid handle %d\n", Value);
|
||||
LeaveCriticalSection(&ddraw_cs);
|
||||
return DDERR_INVALIDPARAMS;
|
||||
}
|
||||
else
|
||||
{
|
||||
mat = This->Handles[Value - 1].ptr;
|
||||
}
|
||||
|
||||
if (mat != NULL)
|
||||
{
|
||||
TRACE(" activating material %p.\n", mat);
|
||||
mat->activate(mat);
|
||||
}
|
||||
else
|
||||
{
|
||||
FIXME(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
|
||||
}
|
||||
TRACE(" activating material %p.\n", m);
|
||||
m->activate(m);
|
||||
|
||||
This->material = Value;
|
||||
}
|
||||
else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
|
||||
|
|
|
@ -808,6 +808,14 @@ IDirect3DImpl_7_CreateDevice(IDirect3D7 *iface,
|
|||
object->Handles = NULL;
|
||||
object->numHandles = 0;
|
||||
|
||||
if (!ddraw_handle_table_init(&object->handle_table, 64))
|
||||
{
|
||||
ERR("Failed to initialize handle table.\n");
|
||||
HeapFree(GetProcessHeap(), 0, object);
|
||||
LeaveCriticalSection(&ddraw_cs);
|
||||
return DDERR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
object->legacyTextureBlending = FALSE;
|
||||
|
||||
/* This is for convenience */
|
||||
|
@ -818,6 +826,7 @@ IDirect3DImpl_7_CreateDevice(IDirect3D7 *iface,
|
|||
if(!IndexBufferParent)
|
||||
{
|
||||
ERR("Allocating memory for an index buffer parent failed\n");
|
||||
ddraw_handle_table_destroy(&object->handle_table);
|
||||
HeapFree(GetProcessHeap(), 0, object);
|
||||
LeaveCriticalSection(&ddraw_cs);
|
||||
return DDERR_OUTOFMEMORY;
|
||||
|
@ -837,6 +846,7 @@ IDirect3DImpl_7_CreateDevice(IDirect3D7 *iface,
|
|||
if(FAILED(hr))
|
||||
{
|
||||
ERR("Failed to create an index buffer\n");
|
||||
ddraw_handle_table_destroy(&object->handle_table);
|
||||
HeapFree(GetProcessHeap(), 0, object);
|
||||
LeaveCriticalSection(&ddraw_cs);
|
||||
return hr;
|
||||
|
|
|
@ -251,22 +251,18 @@ IDirect3DExecuteBufferImpl_Execute(IDirect3DExecuteBufferImpl *This,
|
|||
|
||||
if (!ci->u1.dlstLightStateType || (ci->u1.dlstLightStateType > D3DLIGHTSTATE_COLORVERTEX))
|
||||
ERR("Unexpected Light State Type %d\n", ci->u1.dlstLightStateType);
|
||||
else if (ci->u1.dlstLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
|
||||
DWORD matHandle = ci->u2.dwArg[0];
|
||||
else if (ci->u1.dlstLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
|
||||
{
|
||||
IDirect3DMaterialImpl *m;
|
||||
|
||||
if (!matHandle) {
|
||||
FIXME(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
|
||||
} else if (matHandle >= lpDevice->numHandles) {
|
||||
WARN("Material handle %d is invalid\n", matHandle);
|
||||
} else if (lpDevice->Handles[matHandle - 1].type != DDrawHandle_Material) {
|
||||
WARN("Handle %d is not a material handle\n", matHandle);
|
||||
} else {
|
||||
IDirect3DMaterialImpl *mat =
|
||||
lpDevice->Handles[matHandle - 1].ptr;
|
||||
|
||||
mat->activate(mat);
|
||||
}
|
||||
} else if (ci->u1.dlstLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
|
||||
m = ddraw_get_object(&lpDevice->handle_table, ci->u2.dwArg[0] - 1, DDRAW_HANDLE_MATERIAL);
|
||||
if (!m)
|
||||
ERR("Invalid material handle %#x.\n", ci->u2.dwArg[0]);
|
||||
else
|
||||
m->activate(m);
|
||||
}
|
||||
else if (ci->u1.dlstLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
|
||||
{
|
||||
switch (ci->u2.dwArg[0]) {
|
||||
case D3DCOLOR_MONO:
|
||||
ERR("DDCOLOR_MONO should not happen!\n");
|
||||
|
|
|
@ -70,6 +70,117 @@ CRITICAL_SECTION ddraw_cs = { &ddraw_cs_debug, -1, 0, 0, 0, 0 };
|
|||
/* value of ForceRefreshRate */
|
||||
DWORD force_refresh_rate = 0;
|
||||
|
||||
/* Handle table functions */
|
||||
BOOL ddraw_handle_table_init(struct ddraw_handle_table *t, UINT initial_size)
|
||||
{
|
||||
t->entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, initial_size * sizeof(*t->entries));
|
||||
if (!t->entries)
|
||||
{
|
||||
ERR("Failed to allocate handle table memory.\n");
|
||||
return FALSE;
|
||||
}
|
||||
t->free_entries = NULL;
|
||||
t->table_size = initial_size;
|
||||
t->entry_count = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void ddraw_handle_table_destroy(struct ddraw_handle_table *t)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, t->entries);
|
||||
memset(t, 0, sizeof(*t));
|
||||
}
|
||||
|
||||
DWORD ddraw_allocate_handle(struct ddraw_handle_table *t, void *object, enum ddraw_handle_type type)
|
||||
{
|
||||
struct ddraw_handle_entry *entry;
|
||||
|
||||
if (t->free_entries)
|
||||
{
|
||||
DWORD idx = t->free_entries - t->entries;
|
||||
/* Use a free handle */
|
||||
entry = t->free_entries;
|
||||
if (entry->type != DDRAW_HANDLE_FREE)
|
||||
{
|
||||
ERR("Handle %#x (%p) is in the free list, but has type %#x.\n", idx, entry->object, entry->type);
|
||||
return DDRAW_INVALID_HANDLE;
|
||||
}
|
||||
t->free_entries = entry->object;
|
||||
entry->object = object;
|
||||
entry->type = type;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
if (!(t->entry_count < t->table_size))
|
||||
{
|
||||
/* Grow the table */
|
||||
UINT new_size = t->table_size + (t->table_size >> 1);
|
||||
struct ddraw_handle_entry *new_entries = HeapReAlloc(GetProcessHeap(),
|
||||
0, t->entries, new_size * sizeof(*t->entries));
|
||||
if (!new_entries)
|
||||
{
|
||||
ERR("Failed to grow the handle table.\n");
|
||||
return DDRAW_INVALID_HANDLE;
|
||||
}
|
||||
t->entries = new_entries;
|
||||
t->table_size = new_size;
|
||||
}
|
||||
|
||||
entry = &t->entries[t->entry_count];
|
||||
entry->object = object;
|
||||
entry->type = type;
|
||||
|
||||
return t->entry_count++;
|
||||
}
|
||||
|
||||
void *ddraw_free_handle(struct ddraw_handle_table *t, DWORD handle, enum ddraw_handle_type type)
|
||||
{
|
||||
struct ddraw_handle_entry *entry;
|
||||
void *object;
|
||||
|
||||
if (handle == DDRAW_INVALID_HANDLE || handle >= t->entry_count)
|
||||
{
|
||||
WARN("Invalid handle %#x passed.\n", handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
entry = &t->entries[handle];
|
||||
if (entry->type != type)
|
||||
{
|
||||
WARN("Handle %#x (%p) is not of type %#x.\n", handle, entry->object, type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
object = entry->object;
|
||||
entry->object = t->free_entries;
|
||||
entry->type = DDRAW_HANDLE_FREE;
|
||||
t->free_entries = entry;
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
void *ddraw_get_object(struct ddraw_handle_table *t, DWORD handle, enum ddraw_handle_type type)
|
||||
{
|
||||
struct ddraw_handle_entry *entry;
|
||||
|
||||
if (handle == DDRAW_INVALID_HANDLE || handle >= t->entry_count)
|
||||
{
|
||||
WARN("Invalid handle %#x passed.\n", handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
entry = &t->entries[handle];
|
||||
if (entry->type != type)
|
||||
{
|
||||
WARN("Handle %#x (%p) is not of type %#x.\n", handle, entry->object, type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return entry->object;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper Function for DDRAW_Create and DirectDrawCreateClipper for
|
||||
* lazy loading of the Wine D3D driver.
|
||||
|
|
|
@ -160,8 +160,7 @@ IDirect3DMaterialImpl_Release(IDirect3DMaterial3 *iface)
|
|||
if(This->Handle)
|
||||
{
|
||||
EnterCriticalSection(&ddraw_cs);
|
||||
This->ddraw->d3ddevice->Handles[This->Handle - 1].ptr = NULL;
|
||||
This->ddraw->d3ddevice->Handles[This->Handle - 1].type = DDrawHandle_Unknown;
|
||||
ddraw_free_handle(&This->ddraw->d3ddevice->handle_table, This->Handle - 1, DDRAW_HANDLE_MATERIAL);
|
||||
LeaveCriticalSection(&ddraw_cs);
|
||||
}
|
||||
|
||||
|
@ -328,15 +327,15 @@ IDirect3DMaterialImpl_GetHandle(IDirect3DMaterial3 *iface,
|
|||
This->active_device = device;
|
||||
if(!This->Handle)
|
||||
{
|
||||
This->Handle = IDirect3DDeviceImpl_CreateHandle(device);
|
||||
if(!This->Handle)
|
||||
DWORD h = ddraw_allocate_handle(&device->handle_table, This, DDRAW_HANDLE_MATERIAL);
|
||||
if (h == DDRAW_INVALID_HANDLE)
|
||||
{
|
||||
ERR("Error creating a handle\n");
|
||||
ERR("Failed to allocate a material handle.\n");
|
||||
LeaveCriticalSection(&ddraw_cs);
|
||||
return DDERR_INVALIDPARAMS; /* Unchecked */
|
||||
}
|
||||
device->Handles[This->Handle - 1].ptr = This;
|
||||
device->Handles[This->Handle - 1].type = DDrawHandle_Material;
|
||||
|
||||
This->Handle = h + 1;
|
||||
}
|
||||
*lpHandle = This->Handle;
|
||||
TRACE(" returning handle %08x.\n", *lpHandle);
|
||||
|
|
|
@ -529,36 +529,32 @@ IDirect3DViewportImpl_SetBackground(IDirect3DViewport3 *iface,
|
|||
D3DMATERIALHANDLE hMat)
|
||||
{
|
||||
IDirect3DViewportImpl *This = (IDirect3DViewportImpl *)iface;
|
||||
IDirect3DMaterialImpl *m;
|
||||
|
||||
TRACE("(%p)->(%d)\n", This, hMat);
|
||||
|
||||
EnterCriticalSection(&ddraw_cs);
|
||||
if(hMat && hMat > This->ddraw->d3ddevice->numHandles)
|
||||
|
||||
if (!hMat)
|
||||
{
|
||||
WARN("Specified Handle %d out of range\n", hMat);
|
||||
This->background = NULL;
|
||||
TRACE("Setting background to NULL\n");
|
||||
LeaveCriticalSection(&ddraw_cs);
|
||||
return DDERR_INVALIDPARAMS;
|
||||
return D3D_OK;
|
||||
}
|
||||
else if(hMat && This->ddraw->d3ddevice->Handles[hMat - 1].type != DDrawHandle_Material)
|
||||
|
||||
m = ddraw_get_object(&This->ddraw->d3ddevice->handle_table, hMat - 1, DDRAW_HANDLE_MATERIAL);
|
||||
if (!m)
|
||||
{
|
||||
WARN("Handle %d is not a material handle\n", hMat);
|
||||
WARN("Invalid material handle.\n");
|
||||
LeaveCriticalSection(&ddraw_cs);
|
||||
return DDERR_INVALIDPARAMS;
|
||||
}
|
||||
|
||||
if(hMat)
|
||||
{
|
||||
This->background = This->ddraw->d3ddevice->Handles[hMat - 1].ptr;
|
||||
TRACE(" setting background color : %f %f %f %f\n",
|
||||
This->background->mat.u.diffuse.u1.r,
|
||||
This->background->mat.u.diffuse.u2.g,
|
||||
This->background->mat.u.diffuse.u3.b,
|
||||
This->background->mat.u.diffuse.u4.a);
|
||||
}
|
||||
else
|
||||
{
|
||||
This->background = NULL;
|
||||
TRACE("Setting background to NULL\n");
|
||||
}
|
||||
TRACE("Setting background color : %.8e %.8e %.8e %.8e.\n",
|
||||
m->mat.u.diffuse.u1.r, m->mat.u.diffuse.u2.g,
|
||||
m->mat.u.diffuse.u3.b, m->mat.u.diffuse.u4.a);
|
||||
This->background = m;
|
||||
|
||||
LeaveCriticalSection(&ddraw_cs);
|
||||
return D3D_OK;
|
||||
|
|
Loading…
Reference in New Issue