Module: wine Branch: master Commit: a9e241e4fe6c1abc34ccb43d422c44ad129bdcb2 URL: http://source.winehq.org/git/wine.git/?a=commit;h=a9e241e4fe6c1abc34ccb43d42...
Author: Henri Verbeet hverbeet@codeweavers.com Date: Tue Dec 11 22:27:31 2012 +0100
d3d10core: Only create unique sampler state objects.
---
dlls/d3d10core/d3d10core_main.c | 8 ++++- dlls/d3d10core/d3d10core_private.h | 10 ++++- dlls/d3d10core/device.c | 67 ++++++++++++++++++++++++++++++++---- dlls/d3d10core/state.c | 22 ++++++++--- 4 files changed, 91 insertions(+), 16 deletions(-)
diff --git a/dlls/d3d10core/d3d10core_main.c b/dlls/d3d10core/d3d10core_main.c index e977afa..78826f6 100644 --- a/dlls/d3d10core/d3d10core_main.c +++ b/dlls/d3d10core/d3d10core_main.c @@ -69,6 +69,7 @@ static HRESULT WINAPI layer_create(enum dxgi_device_layer_id id, void **layer_ba void *device_object, REFIID riid, void **device_layer) { struct d3d10_device *object; + HRESULT hr;
TRACE("id %#x, layer_base %p, unknown0 %#x, device_object %p, riid %s, device_layer %p\n", id, layer_base, unknown0, device_object, debugstr_guid(riid), device_layer); @@ -81,7 +82,12 @@ static HRESULT WINAPI layer_create(enum dxgi_device_layer_id id, void **layer_ba }
object = *layer_base; - d3d10_device_init(object, device_object); + if (FAILED(hr = d3d10_device_init(object, device_object))) + { + WARN("Failed to initialize device, hr %#x.\n", hr); + *device_layer = NULL; + return hr; + } *device_layer = &object->IUnknown_inner;
TRACE("Created d3d10 device at %p\n", object); diff --git a/dlls/d3d10core/d3d10core_private.h b/dlls/d3d10core/d3d10core_private.h index 4d643a0..b32825e 100644 --- a/dlls/d3d10core/d3d10core_private.h +++ b/dlls/d3d10core/d3d10core_private.h @@ -35,6 +35,7 @@ #endif #include "wine/wined3d.h" #include "wine/winedxgi.h" +#include "wine/rbtree.h"
#define MAKE_TAG(ch0, ch1, ch2, ch3) \ ((DWORD)(ch0) | ((DWORD)(ch1) << 8) | \ @@ -247,11 +248,14 @@ struct d3d10_sampler_state ID3D10SamplerState ID3D10SamplerState_iface; LONG refcount;
+ struct d3d10_device *device; struct wined3d_sampler *wined3d_sampler; D3D10_SAMPLER_DESC desc; + struct wine_rb_entry entry; };
-HRESULT d3d10_sampler_state_init(struct d3d10_sampler_state *state, const D3D10_SAMPLER_DESC *desc) DECLSPEC_HIDDEN; +HRESULT d3d10_sampler_state_init(struct d3d10_sampler_state *state, struct d3d10_device *device, + const D3D10_SAMPLER_DESC *desc) DECLSPEC_HIDDEN; struct d3d10_sampler_state *unsafe_impl_from_ID3D10SamplerState(ID3D10SamplerState *iface) DECLSPEC_HIDDEN;
/* ID3D10Query */ @@ -275,6 +279,8 @@ struct d3d10_device struct wined3d_device_parent device_parent; struct wined3d_device *wined3d_device;
+ struct wine_rb_tree sampler_states; + struct d3d10_blend_state *blend_state; float blend_factor[4]; UINT sample_mask; @@ -283,7 +289,7 @@ struct d3d10_device struct d3d10_rasterizer_state *rasterizer_state; };
-void d3d10_device_init(struct d3d10_device *device, void *outer_unknown) DECLSPEC_HIDDEN; +HRESULT d3d10_device_init(struct d3d10_device *device, void *outer_unknown) DECLSPEC_HIDDEN;
/* Layered device */ enum dxgi_device_layer_id diff --git a/dlls/d3d10core/device.c b/dlls/d3d10core/device.c index 9070d85..29f1648 100644 --- a/dlls/d3d10core/device.c +++ b/dlls/d3d10core/device.c @@ -72,15 +72,16 @@ static ULONG STDMETHODCALLTYPE d3d10_device_inner_AddRef(IUnknown *iface)
static ULONG STDMETHODCALLTYPE d3d10_device_inner_Release(IUnknown *iface) { - struct d3d10_device *This = impl_from_IUnknown(iface); - ULONG refcount = InterlockedDecrement(&This->refcount); + struct d3d10_device *device = impl_from_IUnknown(iface); + ULONG refcount = InterlockedDecrement(&device->refcount);
- TRACE("%p decreasing refcount to %u\n", This, refcount); + TRACE("%p decreasing refcount to %u.\n", device, refcount);
if (!refcount) { - if (This->wined3d_device) - wined3d_device_decref(This->wined3d_device); + if (device->wined3d_device) + wined3d_device_decref(device->wined3d_device); + wine_rb_destroy(&device->sampler_states, NULL, NULL); }
return refcount; @@ -1471,7 +1472,9 @@ static HRESULT STDMETHODCALLTYPE d3d10_device_CreateRasterizerState(ID3D10Device static HRESULT STDMETHODCALLTYPE d3d10_device_CreateSamplerState(ID3D10Device *iface, const D3D10_SAMPLER_DESC *desc, ID3D10SamplerState **sampler_state) { + struct d3d10_device *device = impl_from_ID3D10Device(iface); struct d3d10_sampler_state *object; + struct wine_rb_entry *entry; HRESULT hr;
TRACE("iface %p, desc %p, sampler_state %p.\n", iface, desc, sampler_state); @@ -1479,6 +1482,17 @@ static HRESULT STDMETHODCALLTYPE d3d10_device_CreateSamplerState(ID3D10Device *i if (!desc) return E_INVALIDARG;
+ if ((entry = wine_rb_get(&device->sampler_states, desc))) + { + object = WINE_RB_ENTRY_VALUE(entry, struct d3d10_sampler_state, entry); + + TRACE("Returning existing sampler state %p.\n", object); + *sampler_state = &object->ID3D10SamplerState_iface; + ID3D10SamplerState_AddRef(*sampler_state); + + return S_OK; + } + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); if (!object) { @@ -1486,7 +1500,7 @@ static HRESULT STDMETHODCALLTYPE d3d10_device_CreateSamplerState(ID3D10Device *i return E_OUTOFMEMORY; }
- if (FAILED(hr = d3d10_sampler_state_init(object, desc))) + if (FAILED(hr = d3d10_sampler_state_init(object, device, desc))) { WARN("Failed to initialize sampler state, hr %#x.\n", hr); HeapFree(GetProcessHeap(), 0, object); @@ -1908,7 +1922,38 @@ static const struct wined3d_device_parent_ops d3d10_wined3d_device_parent_ops = device_parent_create_swapchain, };
-void d3d10_device_init(struct d3d10_device *device, void *outer_unknown) +static void *d3d10_rb_alloc(size_t size) +{ + return HeapAlloc(GetProcessHeap(), 0, size); +} + +static void *d3d10_rb_realloc(void *ptr, size_t size) +{ + return HeapReAlloc(GetProcessHeap(), 0, ptr, size); +} + +static void d3d10_rb_free(void *ptr) +{ + HeapFree(GetProcessHeap(), 0, ptr); +} + +static int d3d10_sampler_state_compare(const void *key, const struct wine_rb_entry *entry) +{ + const D3D10_SAMPLER_DESC *ka = key; + const D3D10_SAMPLER_DESC *kb = &WINE_RB_ENTRY_VALUE(entry, const struct d3d10_sampler_state, entry)->desc; + + return memcmp(ka, kb, sizeof(*ka)); +} + +static const struct wine_rb_functions d3d10_sampler_state_rb_ops = +{ + d3d10_rb_alloc, + d3d10_rb_realloc, + d3d10_rb_free, + d3d10_sampler_state_compare, +}; + +HRESULT d3d10_device_init(struct d3d10_device *device, void *outer_unknown) { device->ID3D10Device_iface.lpVtbl = &d3d10_device_vtbl; device->IUnknown_inner.lpVtbl = &d3d10_device_inner_unknown_vtbl; @@ -1917,4 +1962,12 @@ void d3d10_device_init(struct d3d10_device *device, void *outer_unknown) device->refcount = 1; /* COM aggregation always takes place */ device->outer_unk = outer_unknown; + + if (wine_rb_init(&device->sampler_states, &d3d10_sampler_state_rb_ops) == -1) + { + WARN("Failed to initialize sampler state rbtree.\n"); + return E_FAIL; + } + + return S_OK; } diff --git a/dlls/d3d10core/state.c b/dlls/d3d10core/state.c index c086066..387d561 100644 --- a/dlls/d3d10core/state.c +++ b/dlls/d3d10core/state.c @@ -438,15 +438,16 @@ static ULONG STDMETHODCALLTYPE d3d10_sampler_state_AddRef(ID3D10SamplerState *if
static ULONG STDMETHODCALLTYPE d3d10_sampler_state_Release(ID3D10SamplerState *iface) { - struct d3d10_sampler_state *This = impl_from_ID3D10SamplerState(iface); - ULONG refcount = InterlockedDecrement(&This->refcount); + struct d3d10_sampler_state *state = impl_from_ID3D10SamplerState(iface); + ULONG refcount = InterlockedDecrement(&state->refcount);
- TRACE("%p decreasing refcount to %u.\n", This, refcount); + TRACE("%p decreasing refcount to %u.\n", state, refcount);
if (!refcount) { - wined3d_sampler_decref(This->wined3d_sampler); - HeapFree(GetProcessHeap(), 0, This); + wined3d_sampler_decref(state->wined3d_sampler); + wine_rb_remove(&state->device->sampler_states, &state->desc); + HeapFree(GetProcessHeap(), 0, state); }
return refcount; @@ -512,12 +513,14 @@ static const struct ID3D10SamplerStateVtbl d3d10_sampler_state_vtbl = d3d10_sampler_state_GetDesc, };
-HRESULT d3d10_sampler_state_init(struct d3d10_sampler_state *state, const D3D10_SAMPLER_DESC *desc) +HRESULT d3d10_sampler_state_init(struct d3d10_sampler_state *state, struct d3d10_device *device, + const D3D10_SAMPLER_DESC *desc) { HRESULT hr;
state->ID3D10SamplerState_iface.lpVtbl = &d3d10_sampler_state_vtbl; state->refcount = 1; + state->device = device; state->desc = *desc;
if (FAILED(hr = wined3d_sampler_create(state, &state->wined3d_sampler))) @@ -526,6 +529,13 @@ HRESULT d3d10_sampler_state_init(struct d3d10_sampler_state *state, const D3D10_ return hr; }
+ if (wine_rb_put(&device->sampler_states, desc, &state->entry) == -1) + { + ERR("Failed to insert sampler state entry.\n"); + wined3d_sampler_decref(state->wined3d_sampler); + return E_FAIL; + } + return S_OK; }