{
DDrawHandle_Unknown = 0,
DDrawHandle_Texture = 1,
- DDrawHandle_Material = 2,
DDrawHandle_Matrix = 3,
DDrawHandle_StateBlock = 4
} DDrawHandleTypes;
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 */
/* Handle management */
struct HandleEntry *Handles;
DWORD numHandles;
+ struct ddraw_handle_table handle_table;
D3DMATRIXHANDLE world, proj, view;
};
}
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 */
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)
EnterCriticalSection(&ddraw_cs);
if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
{
- IDirect3DMaterialImpl *mat;
-
- if(Value == 0) mat = NULL;
- else if(Value > This->numHandles)
- {
- ERR("Material handle out of range(%d)\n", Value);
- LeaveCriticalSection(&ddraw_cs);
- return DDERR_INVALIDPARAMS;
- }
- else if(This->Handles[Value - 1].type != DDrawHandle_Material)
+ IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
+ if (!m)
{
- ERR("Invalid handle %d\n", Value);
+ WARN("Invalid material handle.\n");
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 */)
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 */
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;
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;
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];
-
- 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 */) {
+ else if (ci->u1.dlstLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
+ {
+ IDirect3DMaterialImpl *m;
+
+ 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");
/* 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.
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);
}
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);
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;