Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/wined3d/cs.c | 43 +++++++++++++++++++++------------- dlls/wined3d/device.c | 27 ++++++++++++++++++++- dlls/wined3d/wined3d.spec | 2 ++ dlls/wined3d/wined3d_private.h | 4 +++- include/wine/wined3d.h | 2 ++ 5 files changed, 60 insertions(+), 18 deletions(-)
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 5176c635cf5..13a034660d3 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -2732,12 +2732,23 @@ static void wined3d_cs_st_finish(struct wined3d_device_context *context, enum wi { }
+static void wined3d_cs_st_destroy(struct wined3d_device_context *context) +{ + struct wined3d_cs *cs = wined3d_cs_from_context(context); + + wined3d_state_destroy(cs->c.state); + state_cleanup(&cs->state); + heap_free(cs->data); + heap_free(cs); +} + static const struct wined3d_device_context_ops wined3d_cs_st_ops = { wined3d_cs_st_require_space, wined3d_cs_st_submit, wined3d_cs_st_finish, wined3d_cs_st_push_constants, + wined3d_cs_st_destroy, };
static BOOL wined3d_cs_queue_is_empty(const struct wined3d_cs *cs, const struct wined3d_cs_queue *queue) @@ -2853,12 +2864,27 @@ static void wined3d_cs_mt_finish(struct wined3d_device_context *context, enum wi YieldProcessor(); }
+static void wined3d_cs_mt_destroy(struct wined3d_device_context *context) +{ + struct wined3d_cs *cs = wined3d_cs_from_context(context); + + wined3d_cs_emit_stop(cs); + CloseHandle(cs->thread); + CloseHandle(cs->event); + + wined3d_state_destroy(cs->c.state); + state_cleanup(&cs->state); + heap_free(cs->data); + heap_free(cs); +} + static const struct wined3d_device_context_ops wined3d_cs_mt_ops = { wined3d_cs_mt_require_space, wined3d_cs_mt_submit, wined3d_cs_mt_finish, wined3d_cs_mt_push_constants, + wined3d_cs_mt_destroy, };
static void poll_queries(struct wined3d_cs *cs) @@ -2994,6 +3020,7 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) return NULL; }
+ cs->c.refcount = 1; cs->c.ops = &wined3d_cs_st_ops; cs->c.device = device; cs->serialize_commands = TRACE_ON(d3d_sync) || wined3d_settings.cs_multithreaded & WINED3D_CSMT_SERIALIZE; @@ -3043,19 +3070,3 @@ fail: heap_free(cs); return NULL; } - -void wined3d_cs_destroy(struct wined3d_cs *cs) -{ - if (cs->thread) - { - wined3d_cs_emit_stop(cs); - CloseHandle(cs->thread); - if (!CloseHandle(cs->event)) - ERR("Closing event failed.\n"); - } - - wined3d_state_destroy(cs->c.state); - state_cleanup(&cs->state); - heap_free(cs->data); - heap_free(cs); -} diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 181f491546a..629f8c2c740 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -90,6 +90,30 @@ const struct wined3d_light WINED3D_default_light = 0.0f /* Phi */ };
+ULONG CDECL wined3d_device_context_incref(struct wined3d_device_context *context) +{ + ULONG refcount = InterlockedIncrement(&context->refcount); + + TRACE("%p increasing refcount to %u.\n", context, refcount); + + return refcount; +} + +ULONG CDECL wined3d_device_context_decref(struct wined3d_device_context *context) +{ + ULONG refcount = InterlockedDecrement(&context->refcount); + + TRACE("%p decreasing refcount to %u.\n", context, refcount); + + if (!refcount) + { + context->ops->destroy(context); + TRACE("Destroyed device context %p.\n", context); + } + + return refcount; +} + BOOL device_context_add(struct wined3d_device *device, struct wined3d_context *context) { struct wined3d_context **new_array; @@ -218,7 +242,7 @@ void wined3d_device_cleanup(struct wined3d_device *device) if (device->swapchain_count) wined3d_device_uninit_3d(device);
- wined3d_cs_destroy(device->cs); + wined3d_device_context_decref(&device->cs->c);
for (i = 0; i < ARRAY_SIZE(device->multistate_funcs); ++i) { @@ -2058,6 +2082,7 @@ struct wined3d_device_context * CDECL wined3d_device_get_immediate_context(struc { TRACE("device %p.\n", device);
+ wined3d_device_context_incref(&device->cs->c); return &device->cs->c; }
diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index f5fa1d3d7e5..72f12243add 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -167,6 +167,8 @@ @ cdecl wined3d_device_update_texture(ptr ptr ptr) @ cdecl wined3d_device_validate_device(ptr ptr)
+@ cdecl wined3d_device_context_decref(ptr) +@ cdecl wined3d_device_context_incref(ptr) @ cdecl wined3d_device_context_set_shader(ptr long ptr)
@ cdecl wined3d_output_find_closest_matching_mode(ptr ptr) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index ee00530981c..2c39898d03c 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4676,10 +4676,13 @@ struct wined3d_device_context_ops void (*finish)(struct wined3d_device_context *context, enum wined3d_cs_queue_id queue_id); void (*push_constants)(struct wined3d_device_context *context, enum wined3d_push_constants p, unsigned int start_idx, unsigned int count, const void *constants); + void (*destroy)(struct wined3d_device_context *context); };
struct wined3d_device_context { + LONG refcount; + const struct wined3d_device_context_ops *ops; struct wined3d_device *device; struct wined3d_state *state; @@ -4707,7 +4710,6 @@ struct wined3d_cs };
struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) DECLSPEC_HIDDEN; -void wined3d_cs_destroy(struct wined3d_cs *cs) DECLSPEC_HIDDEN; void wined3d_cs_destroy_object(struct wined3d_cs *cs, void (*callback)(void *object), void *object) DECLSPEC_HIDDEN; void wined3d_cs_emit_add_dirty_texture_region(struct wined3d_cs *cs, diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index ba9e8642ea2..424ee8e75a5 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2549,6 +2549,8 @@ HRESULT __cdecl wined3d_device_update_texture(struct wined3d_device *device, struct wined3d_texture *src_texture, struct wined3d_texture *dst_texture); HRESULT __cdecl wined3d_device_validate_device(const struct wined3d_device *device, DWORD *num_passes);
+ULONG __cdecl wined3d_device_context_decref(struct wined3d_device_context *context); +ULONG __cdecl wined3d_device_context_incref(struct wined3d_device_context *context); void __cdecl wined3d_device_context_set_shader(struct wined3d_device_context *context, enum wined3d_shader_type type, struct wined3d_shader *shader);