[PATCH 1/5] wined3d: Decouple private data from the resource structure.
Stefan Dösinger
stefan at codeweavers.com
Mon Feb 24 08:37:29 CST 2014
I have kept the somewhat questionable behavior where set_private_data
clears the old data in case of an IUnknown * size mismatch for now.
Native ddraw behaves the same way, but native d3d8/9 do not. I'll deal
with this in a separate patch.
---
dlls/wined3d/resource.c | 281 ++++++++++++++++++++++++-----------------
dlls/wined3d/wined3d_private.h | 17 ++-
2 files changed, 182 insertions(+), 116 deletions(-)
diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c
index 177d23e..7bde580 100644
--- a/dlls/wined3d/resource.c
+++ b/dlls/wined3d/resource.c
@@ -4,7 +4,7 @@
* Copyright 2004 Christian Costa
* Copyright 2005 Oliver Stieber
* Copyright 2009-2010 Henri Verbeet for CodeWeavers
- * Copyright 2006-2008, 2013 Stefan Dösinger for CodeWeavers
+ * Copyright 2006-2008, 2013-2014 Stefan Dösinger for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -116,7 +116,6 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *
resource->parent = parent;
resource->parent_ops = parent_ops;
resource->resource_ops = resource_ops;
- list_init(&resource->privateData);
if (size)
{
@@ -151,9 +150,6 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *
void resource_cleanup(struct wined3d_resource *resource)
{
const struct wined3d *d3d = resource->device->wined3d;
- struct private_data *data;
- struct list *e1, *e2;
- HRESULT hr;
TRACE("Cleaning up resource %p.\n", resource);
@@ -163,13 +159,7 @@ void resource_cleanup(struct wined3d_resource *resource)
adapter_adjust_memory(resource->device->adapter, 0 - resource->size);
}
- LIST_FOR_EACH_SAFE(e1, e2, &resource->privateData)
- {
- data = LIST_ENTRY(e1, struct private_data, entry);
- hr = wined3d_resource_free_private_data(resource, &data->tag);
- if (FAILED(hr))
- ERR("Failed to free private data when destroying resource %p, hr = %#x.\n", resource, hr);
- }
+ wined3d_privstore_destroy(resource->privstore);
wined3d_resource_free_sysmem(resource);
@@ -185,126 +175,36 @@ void resource_unload(struct wined3d_resource *resource)
resource, resource->type);
}
-static struct private_data *resource_find_private_data(const struct wined3d_resource *resource, REFGUID tag)
-{
- struct private_data *data;
- struct list *entry;
-
- TRACE("Searching for private data %s\n", debugstr_guid(tag));
- LIST_FOR_EACH(entry, &resource->privateData)
- {
- data = LIST_ENTRY(entry, struct private_data, entry);
- if (IsEqualGUID(&data->tag, tag)) {
- TRACE("Found %p\n", data);
- return data;
- }
- }
- TRACE("Not found\n");
- return NULL;
-}
-
HRESULT CDECL wined3d_resource_set_private_data(struct wined3d_resource *resource, REFGUID guid,
const void *data, DWORD data_size, DWORD flags)
{
- struct private_data *d;
-
- TRACE("resource %p, riid %s, data %p, data_size %u, flags %#x.\n",
- resource, debugstr_guid(guid), data, data_size, flags);
-
- wined3d_resource_free_private_data(resource, guid);
-
- d = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d));
- if (!d) return E_OUTOFMEMORY;
-
- d->tag = *guid;
- d->flags = flags;
-
- if (flags & WINED3DSPD_IUNKNOWN)
+ if (!resource->privstore)
{
- if (data_size != sizeof(IUnknown *))
- {
- WARN("IUnknown data with size %u, returning WINED3DERR_INVALIDCALL.\n", data_size);
- HeapFree(GetProcessHeap(), 0, d);
- return WINED3DERR_INVALIDCALL;
- }
- d->ptr.object = (IUnknown *)data;
- d->size = sizeof(IUnknown *);
- IUnknown_AddRef(d->ptr.object);
- }
- else
- {
- d->ptr.data = HeapAlloc(GetProcessHeap(), 0, data_size);
- if (!d->ptr.data)
- {
- HeapFree(GetProcessHeap(), 0, d);
+ resource->privstore = wined3d_privstore_create();
+ if (!resource->privstore)
return E_OUTOFMEMORY;
- }
- d->size = data_size;
- memcpy(d->ptr.data, data, data_size);
}
- list_add_tail(&resource->privateData, &d->entry);
- return WINED3D_OK;
+ return wined3d_privstore_set_private_data(resource->privstore, guid, data, data_size, flags);
}
HRESULT CDECL wined3d_resource_get_private_data(const struct wined3d_resource *resource, REFGUID guid,
void *data, DWORD *data_size)
{
- const struct private_data *d;
+ BOOL addref = resource->device->wined3d->dxVersion != 7;
- TRACE("resource %p, guid %s, data %p, data_size %p.\n",
- resource, debugstr_guid(guid), data, data_size);
+ if (!resource->privstore)
+ return WINED3DERR_NOTFOUND;
- d = resource_find_private_data(resource, guid);
- if (!d) return WINED3DERR_NOTFOUND;
-
- if (*data_size < d->size)
- {
- *data_size = d->size;
- return WINED3DERR_MOREDATA;
- }
-
- if (d->flags & WINED3DSPD_IUNKNOWN)
- {
- *(IUnknown **)data = d->ptr.object;
- if (resource->device->wined3d->dxVersion != 7)
- {
- /* D3D8 and D3D9 addref the private data, DDraw does not. This
- * can't be handled in ddraw because it doesn't know if the
- * pointer returned is an IUnknown * or just a blob. */
- IUnknown_AddRef(d->ptr.object);
- }
- }
- else
- {
- memcpy(data, d->ptr.data, d->size);
- }
-
- return WINED3D_OK;
+ return wined3d_privstore_get_private_data(resource->privstore, guid, data, data_size, addref);
}
+
HRESULT CDECL wined3d_resource_free_private_data(struct wined3d_resource *resource, REFGUID guid)
{
- struct private_data *data;
-
- TRACE("resource %p, guid %s.\n", resource, debugstr_guid(guid));
-
- data = resource_find_private_data(resource, guid);
- if (!data) return WINED3DERR_NOTFOUND;
-
- if (data->flags & WINED3DSPD_IUNKNOWN)
- {
- if (data->ptr.object)
- IUnknown_Release(data->ptr.object);
- }
- else
- {
- HeapFree(GetProcessHeap(), 0, data->ptr.data);
- }
- list_remove(&data->entry);
+ if (!resource->privstore)
+ return WINED3DERR_NOTFOUND;
- HeapFree(GetProcessHeap(), 0, data);
-
- return WINED3D_OK;
+ return wined3d_privstore_free_private_data(resource->privstore, guid);
}
DWORD resource_set_priority(struct wined3d_resource *resource, DWORD priority)
@@ -431,3 +331,156 @@ GLenum wined3d_resource_gl_legacy_map_flags(DWORD d3d_flags)
return GL_WRITE_ONLY_ARB;
return GL_READ_WRITE_ARB;
}
+
+struct wined3d_privstore *wined3d_privstore_create(void)
+{
+ struct wined3d_privstore *ret;
+
+ ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ list_init(&ret->content);
+ return ret;
+}
+
+void wined3d_privstore_destroy(struct wined3d_privstore *store)
+{
+ struct private_data *data;
+ struct list *e1, *e2;
+ HRESULT hr;
+
+ if (!store)
+ return;
+
+ LIST_FOR_EACH_SAFE(e1, e2, &store->content)
+ {
+ data = LIST_ENTRY(e1, struct private_data, entry);
+ hr = wined3d_privstore_free_private_data(store, &data->tag);
+ if (FAILED(hr))
+ ERR("Failed to free private data when destroying store %p, hr = %#x.\n", store, hr);
+ }
+
+ HeapFree(GetProcessHeap(), 0, store);
+}
+
+static struct private_data *wined3d_privstore_find_private_data(const struct wined3d_privstore *store,
+ const GUID *tag)
+{
+ struct private_data *data;
+ struct list *entry;
+
+ TRACE("Searching for private data %s\n", debugstr_guid(tag));
+ LIST_FOR_EACH(entry, &store->content)
+ {
+ data = LIST_ENTRY(entry, struct private_data, entry);
+ if (IsEqualGUID(&data->tag, tag))
+ {
+ TRACE("Found %p\n", data);
+ return data;
+ }
+ }
+ TRACE("Not found\n");
+ return NULL;
+}
+
+HRESULT wined3d_privstore_free_private_data(struct wined3d_privstore *store, const GUID *guid)
+{
+ struct private_data *entry;
+
+ TRACE("store %p, guid %s.\n", store, debugstr_guid(guid));
+
+ entry = wined3d_privstore_find_private_data(store, guid);
+ if (!entry)
+ return WINED3DERR_NOTFOUND;
+
+ if (entry->flags & WINED3DSPD_IUNKNOWN)
+ IUnknown_Release(entry->ptr.object);
+ else
+ HeapFree(GetProcessHeap(), 0, entry->ptr.data);
+
+ list_remove(&entry->entry);
+ HeapFree(GetProcessHeap(), 0, entry);
+
+ return WINED3D_OK;
+}
+
+HRESULT wined3d_privstore_get_private_data(const struct wined3d_privstore *store,
+ const GUID *guid, void *data, DWORD *data_size, BOOL addref)
+{
+ const struct private_data *entry;
+
+ TRACE("store %p, guid %s, data %p, data_size %p.\n",
+ store, debugstr_guid(guid), data, data_size);
+
+ entry = wined3d_privstore_find_private_data(store, guid);
+ if (!entry)
+ return WINED3DERR_NOTFOUND;
+
+ if (*data_size < entry->size)
+ {
+ *data_size = entry->size;
+ return WINED3DERR_MOREDATA;
+ }
+
+ if (entry->flags & WINED3DSPD_IUNKNOWN)
+ {
+ *(IUnknown **)data = entry->ptr.object;
+ /* D3D8 and D3D9 addref the private data, DDraw does not. This
+ * can't be handled in ddraw because it doesn't know if the
+ * pointer returned is an IUnknown * or just a blob. */
+ if (addref)
+ IUnknown_AddRef(*(IUnknown **)data);
+ }
+ else
+ {
+ memcpy(data, entry->ptr.data, entry->size);
+ }
+
+ return WINED3D_OK;
+}
+
+HRESULT wined3d_privstore_set_private_data(struct wined3d_privstore *store, const GUID *guid,
+ const void *data, DWORD data_size, DWORD flags)
+{
+ struct private_data *entry;
+
+ TRACE("store %p, riid %s, data %p, data_size %u, flags %#x.\n",
+ store, debugstr_guid(guid), data, data_size, flags);
+
+ wined3d_privstore_free_private_data(store, guid);
+
+ entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*entry));
+ if (!entry)
+ return E_OUTOFMEMORY;
+
+ entry->tag = *guid;
+ entry->flags = flags;
+
+ if (flags & WINED3DSPD_IUNKNOWN)
+ {
+ if (data_size != sizeof(IUnknown *))
+ {
+ WARN("IUnknown data with size %u, returning WINED3DERR_INVALIDCALL.\n", data_size);
+ HeapFree(GetProcessHeap(), 0, entry);
+ return WINED3DERR_INVALIDCALL;
+ }
+ entry->ptr.object = (IUnknown *)data;
+ entry->size = sizeof(IUnknown *);
+ IUnknown_AddRef(entry->ptr.object);
+ }
+ else
+ {
+ entry->ptr.data = HeapAlloc(GetProcessHeap(), 0, data_size);
+ if (!entry->ptr.data)
+ {
+ HeapFree(GetProcessHeap(), 0, entry);
+ return E_OUTOFMEMORY;
+ }
+ entry->size = data_size;
+ memcpy(entry->ptr.data, data, data_size);
+ }
+ list_add_tail(&store->content, &entry->entry);
+
+ return WINED3D_OK;
+}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 0ceb6f1..08159cc 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -5,7 +5,7 @@
* Copyright 2002-2003 Raphael Junqueira
* Copyright 2002-2003, 2004 Jason Edmeades
* Copyright 2005 Oliver Stieber
- * Copyright 2006-2011, 2013 Stefan Dösinger for CodeWeavers
+ * Copyright 2006-2011, 2013-2014 Stefan Dösinger for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -1976,6 +1976,19 @@ static inline void context_invalidate_active_texture(struct wined3d_context *con
context_invalidate_state(context, STATE_SAMPLER(sampler));
}
+struct wined3d_privstore
+{
+ struct list content;
+};
+
+struct wined3d_privstore *wined3d_privstore_create(void) DECLSPEC_HIDDEN;
+void wined3d_privstore_destroy(struct wined3d_privstore *store) DECLSPEC_HIDDEN;
+HRESULT wined3d_privstore_free_private_data(struct wined3d_privstore *store, const GUID *guid);
+HRESULT wined3d_privstore_get_private_data(const struct wined3d_privstore *store,
+ const GUID *guid, void *data, DWORD *data_size, BOOL addref) DECLSPEC_HIDDEN;
+HRESULT wined3d_privstore_set_private_data(struct wined3d_privstore *store,
+ const GUID *guid, const void *data, DWORD data_size, DWORD flags) DECLSPEC_HIDDEN;
+
#define WINED3D_RESOURCE_ACCESS_GPU 0x1
#define WINED3D_RESOURCE_ACCESS_CPU 0x2
@@ -2003,8 +2016,8 @@ struct wined3d_resource
UINT size;
DWORD priority;
void *heap_memory;
- struct list privateData;
struct list resource_list_entry;
+ struct wined3d_privstore *privstore;
void *parent;
const struct wined3d_parent_ops *parent_ops;
--
1.8.3.2
More information about the wine-patches
mailing list