From b7e134f80a36151baaff16c5ba546909c06c4c9f Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Sun, 11 Aug 2019 14:05:10 +0430 Subject: [PATCH] wined3d: Make the adapter responsible for render target view creation and destruction. Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/adapter_gl.c | 96 ++++++++++++++++++++++++++++++++++ dlls/wined3d/adapter_vk.c | 48 +++++++++++++++++ dlls/wined3d/directx.c | 47 +++++++++++++++++ dlls/wined3d/view.c | 93 ++++++++++++++++---------------- dlls/wined3d/wined3d_private.h | 28 ++++++++++ 5 files changed, 265 insertions(+), 47 deletions(-) diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 471eb42e862..7f321d4acba 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -4741,6 +4741,100 @@ static void adapter_gl_destroy_buffer(struct wined3d_buffer *buffer) wined3d_device_decref(device); } +static HRESULT adapter_gl_create_rendertarget_view(const struct wined3d_view_desc *desc, + struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops, + struct wined3d_rendertarget_view **view) +{ + struct wined3d_rendertarget_view_gl *view_gl; + HRESULT hr; + + TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n", + wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view); + + if (!(view_gl = heap_alloc_zero(sizeof(*view_gl)))) + return E_OUTOFMEMORY; + + if (FAILED(hr = wined3d_rendertarget_view_gl_init(view_gl, desc, resource, parent, parent_ops))) + { + WARN("Failed to initialise view, hr %#x.\n", hr); + heap_free(view_gl); + return hr; + } + + TRACE("Created render target view %p.\n", view_gl); + *view = &view_gl->v; + + return hr; +} + +struct wined3d_view_gl_destroy_ctx +{ + struct wined3d_device *device; + const struct wined3d_gl_view *gl_view; + void *object; + struct wined3d_view_gl_destroy_ctx *free; +}; + +static void wined3d_view_gl_destroy_object(void *object) +{ + struct wined3d_view_gl_destroy_ctx *ctx = object; + const struct wined3d_gl_info *gl_info; + struct wined3d_context *context; + struct wined3d_device *device; + + device = ctx->device; + + if (ctx->gl_view->name) + { + context = context_acquire(device, NULL, 0); + gl_info = wined3d_context_gl(context)->gl_info; + context_gl_resource_released(device, ctx->gl_view->name, FALSE); + gl_info->gl_ops.gl.p_glDeleteTextures(1, &ctx->gl_view->name); + checkGLcall("delete resources"); + context_release(context); + } + + heap_free(ctx->object); + heap_free(ctx->free); +} + +static void wined3d_view_gl_destroy(struct wined3d_device *device, + const struct wined3d_gl_view *gl_view, void *object) +{ + struct wined3d_view_gl_destroy_ctx *ctx, c; + + if (!(ctx = heap_alloc(sizeof(*ctx)))) + ctx = &c; + ctx->device = device; + ctx->gl_view = gl_view; + ctx->object = object; + ctx->free = ctx != &c ? ctx : NULL; + + wined3d_cs_destroy_object(device->cs, wined3d_view_gl_destroy_object, ctx); + if (!ctx->free) + device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); +} + +static void adapter_gl_destroy_rendertarget_view(struct wined3d_rendertarget_view *view) +{ + struct wined3d_rendertarget_view_gl *view_gl = wined3d_rendertarget_view_gl(view); + struct wined3d_device *device = view_gl->v.resource->device; + unsigned int swapchain_count = device->swapchain_count; + + TRACE("view_gl %p.\n", view_gl); + + /* Take a reference to the device, in case releasing the view's resource + * would cause the device to be destroyed. However, swapchain resources + * don't take a reference to the device, and we wouldn't want to increment + * the refcount on a device that's in the process of being destroyed. */ + if (swapchain_count) + wined3d_device_incref(device); + wined3d_rendertarget_view_cleanup(&view_gl->v); + wined3d_view_gl_destroy(device, &view_gl->gl_view, view_gl); + if (swapchain_count) + wined3d_device_decref(device); +} + static const struct wined3d_adapter_ops wined3d_adapter_gl_ops = { adapter_gl_destroy, @@ -4756,6 +4850,8 @@ static const struct wined3d_adapter_ops wined3d_adapter_gl_ops = adapter_gl_destroy_swapchain, adapter_gl_create_buffer, adapter_gl_destroy_buffer, + adapter_gl_create_rendertarget_view, + adapter_gl_destroy_rendertarget_view, }; static BOOL wined3d_adapter_gl_init(struct wined3d_adapter_gl *adapter_gl, diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 73a16177f41..a58efb8b7d8 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -540,6 +540,52 @@ static void adapter_vk_destroy_buffer(struct wined3d_buffer *buffer) wined3d_device_decref(device); } +static HRESULT adapter_vk_create_rendertarget_view(const struct wined3d_view_desc *desc, + struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops, + struct wined3d_rendertarget_view **view) +{ + struct wined3d_rendertarget_view_vk *view_vk; + HRESULT hr; + + TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n", + wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view); + + if (!(view_vk = heap_alloc_zero(sizeof(*view_vk)))) + return E_OUTOFMEMORY; + + if (FAILED(hr = wined3d_rendertarget_view_vk_init(view_vk, desc, resource, parent, parent_ops))) + { + WARN("Failed to initialise view, hr %#x.\n", hr); + heap_free(view_vk); + return hr; + } + + TRACE("Created render target view %p.\n", view_vk); + *view = &view_vk->v; + + return hr; +} + +static void adapter_vk_destroy_rendertarget_view(struct wined3d_rendertarget_view *view) +{ + struct wined3d_rendertarget_view_vk *view_vk = wined3d_rendertarget_view_vk(view); + struct wined3d_device *device = view_vk->v.resource->device; + unsigned int swapchain_count = device->swapchain_count; + + TRACE("view_vk %p.\n", view_vk); + + /* Take a reference to the device, in case releasing the view's resource + * would cause the device to be destroyed. However, swapchain resources + * don't take a reference to the device, and we wouldn't want to increment + * the refcount on a device that's in the process of being destroyed. */ + if (swapchain_count) + wined3d_device_incref(device); + wined3d_rendertarget_view_cleanup(&view_vk->v); + wined3d_cs_destroy_object(device->cs, heap_free, view_vk); + if (swapchain_count) + wined3d_device_decref(device); +} + static const struct wined3d_adapter_ops wined3d_adapter_vk_ops = { adapter_vk_destroy, @@ -555,6 +601,8 @@ static const struct wined3d_adapter_ops wined3d_adapter_vk_ops = adapter_vk_destroy_swapchain, adapter_vk_create_buffer, adapter_vk_destroy_buffer, + adapter_vk_create_rendertarget_view, + adapter_vk_destroy_rendertarget_view, }; static unsigned int wined3d_get_wine_vk_version(void) diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 7cc2490390a..5a4f7d2471e 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -2430,6 +2430,51 @@ static void adapter_no3d_destroy_buffer(struct wined3d_buffer *buffer) wined3d_device_decref(device); } +static HRESULT adapter_no3d_create_rendertarget_view(const struct wined3d_view_desc *desc, + struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops, + struct wined3d_rendertarget_view **view) +{ + struct wined3d_rendertarget_view *view_no3d; + HRESULT hr; + + TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n", + wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view); + + if (!(view_no3d = heap_alloc_zero(sizeof(*view_no3d)))) + return E_OUTOFMEMORY; + + if (FAILED(hr = wined3d_rendertarget_view_no3d_init(view_no3d, desc, resource, parent, parent_ops))) + { + WARN("Failed to initialise view, hr %#x.\n", hr); + heap_free(view_no3d); + return hr; + } + + TRACE("Created render target view %p.\n", view_no3d); + *view = view_no3d; + + return hr; +} + +static void adapter_no3d_destroy_rendertarget_view(struct wined3d_rendertarget_view *view) +{ + struct wined3d_device *device = view->resource->device; + unsigned int swapchain_count = device->swapchain_count; + + TRACE("view %p.\n", view); + + /* Take a reference to the device, in case releasing the view's resource + * would cause the device to be destroyed. However, swapchain resources + * don't take a reference to the device, and we wouldn't want to increment + * the refcount on a device that's in the process of being destroyed. */ + if (swapchain_count) + wined3d_device_incref(device); + wined3d_rendertarget_view_cleanup(view); + wined3d_cs_destroy_object(device->cs, heap_free, view); + if (swapchain_count) + wined3d_device_decref(device); +} + static const struct wined3d_adapter_ops wined3d_adapter_no3d_ops = { adapter_no3d_destroy, @@ -2445,6 +2490,8 @@ static const struct wined3d_adapter_ops wined3d_adapter_no3d_ops = adapter_no3d_destroy_swapchain, adapter_no3d_create_buffer, adapter_no3d_destroy_buffer, + adapter_no3d_create_rendertarget_view, + adapter_no3d_destroy_rendertarget_view, }; static void wined3d_adapter_no3d_init_d3d_info(struct wined3d_adapter *adapter, unsigned int wined3d_creation_flags) diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c index 5ab7965d0f4..8239059279b 100644 --- a/dlls/wined3d/view.c +++ b/dlls/wined3d/view.c @@ -345,25 +345,12 @@ ULONG CDECL wined3d_rendertarget_view_incref(struct wined3d_rendertarget_view *v return refcount; } -static void wined3d_rendertarget_view_gl_destroy_object(void *object) +void wined3d_rendertarget_view_cleanup(struct wined3d_rendertarget_view *view) { - struct wined3d_rendertarget_view_gl *view_gl = object; - struct wined3d_device *device = view_gl->v.resource->device; - - if (view_gl->gl_view.name) - { - const struct wined3d_gl_info *gl_info; - struct wined3d_context *context; - - context = context_acquire(device, NULL, 0); - gl_info = wined3d_context_gl(context)->gl_info; - context_gl_resource_released(device, view_gl->gl_view.name, FALSE); - gl_info->gl_ops.gl.p_glDeleteTextures(1, &view_gl->gl_view.name); - checkGLcall("glDeleteTextures"); - context_release(context); - } - - heap_free(view_gl); + /* Call wined3d_object_destroyed() before releasing the resource, + * since releasing the resource may end up destroying the parent. */ + view->parent_ops->wined3d_object_destroyed(view->parent); + wined3d_resource_decref(view->resource); } ULONG CDECL wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view *view) @@ -373,17 +360,7 @@ ULONG CDECL wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view *v TRACE("%p decreasing refcount to %u.\n", view, refcount); if (!refcount) - { - struct wined3d_resource *resource = view->resource; - struct wined3d_device *device = resource->device; - - /* Call wined3d_object_destroyed() before releasing the resource, - * since releasing the resource may end up destroying the parent. */ - view->parent_ops->wined3d_object_destroyed(view->parent); - wined3d_cs_destroy_object(device->cs, wined3d_rendertarget_view_gl_destroy_object, - wined3d_rendertarget_view_gl(view)); - wined3d_resource_decref(resource); - } + view->resource->device->adapter->adapter_ops->adapter_destroy_rendertarget_view(view); return refcount; } @@ -619,32 +596,54 @@ static HRESULT wined3d_rendertarget_view_init(struct wined3d_rendertarget_view * return WINED3D_OK; } +HRESULT wined3d_rendertarget_view_no3d_init(struct wined3d_rendertarget_view *view_no3d, + const struct wined3d_view_desc *desc, struct wined3d_resource *resource, + void *parent, const struct wined3d_parent_ops *parent_ops) +{ + TRACE("view_no3d %p, desc %s, resource %p, parent %p, parent_ops %p.\n", + view_no3d, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops); + + return wined3d_rendertarget_view_init(view_no3d, desc, resource, parent, parent_ops); +} + +HRESULT wined3d_rendertarget_view_gl_init(struct wined3d_rendertarget_view_gl *view_gl, + const struct wined3d_view_desc *desc, struct wined3d_resource *resource, + void *parent, const struct wined3d_parent_ops *parent_ops) +{ + HRESULT hr; + + TRACE("view_gl %p, desc %s, resource %p, parent %p, parent_ops %p.\n", + view_gl, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops); + + if (FAILED(hr = wined3d_rendertarget_view_init(&view_gl->v, desc, resource, parent, parent_ops))) + return hr; + + wined3d_cs_init_object(resource->device->cs, wined3d_render_target_view_gl_cs_init, view_gl); + + return hr; +} + +HRESULT wined3d_rendertarget_view_vk_init(struct wined3d_rendertarget_view_vk *view_vk, + const struct wined3d_view_desc *desc, struct wined3d_resource *resource, + void *parent, const struct wined3d_parent_ops *parent_ops) +{ + TRACE("view_vk %p, desc %s, resource %p, parent %p, parent_ops %p.\n", + view_vk, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops); + + return wined3d_rendertarget_view_init(&view_vk->v, desc, resource, parent, parent_ops); +} + HRESULT CDECL wined3d_rendertarget_view_create(const struct wined3d_view_desc *desc, struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_rendertarget_view **view) { - struct wined3d_rendertarget_view_gl *object; - HRESULT hr; + const struct wined3d_adapter_ops *adapter_ops; TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n", wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view); - if (!(object = heap_alloc_zero(sizeof(*object)))) - return E_OUTOFMEMORY; - - if (FAILED(hr = wined3d_rendertarget_view_init(&object->v, desc, resource, parent, parent_ops))) - { - heap_free(object); - WARN("Failed to initialise view, hr %#x.\n", hr); - return hr; - } - - wined3d_cs_init_object(resource->device->cs, wined3d_render_target_view_gl_cs_init, object); - - TRACE("Created render target view %p.\n", object); - *view = &object->v; - - return hr; + adapter_ops = resource->device->adapter->adapter_ops; + return adapter_ops->adapter_create_rendertarget_view(desc, resource, parent, parent_ops, view); } HRESULT CDECL wined3d_rendertarget_view_create_from_sub_resource(struct wined3d_texture *texture, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 18fed2eda19..e9bb28536c9 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2788,6 +2788,10 @@ struct wined3d_adapter_ops const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_buffer **buffer); void (*adapter_destroy_buffer)(struct wined3d_buffer *buffer); + HRESULT (*adapter_create_rendertarget_view)(const struct wined3d_view_desc *desc, + struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops, + struct wined3d_rendertarget_view **view); + void (*adapter_destroy_rendertarget_view)(struct wined3d_rendertarget_view *view); }; /* The adapter structure */ @@ -4153,6 +4157,7 @@ struct wined3d_rendertarget_view struct wined3d_view_desc desc; }; +void wined3d_rendertarget_view_cleanup(struct wined3d_rendertarget_view *view) DECLSPEC_HIDDEN; void wined3d_rendertarget_view_get_drawable_size(const struct wined3d_rendertarget_view *view, const struct wined3d_context *context, unsigned int *width, unsigned int *height) DECLSPEC_HIDDEN; void wined3d_rendertarget_view_invalidate_location(struct wined3d_rendertarget_view *view, @@ -4164,6 +4169,10 @@ void wined3d_rendertarget_view_prepare_location(struct wined3d_rendertarget_view void wined3d_rendertarget_view_validate_location(struct wined3d_rendertarget_view *view, DWORD location) DECLSPEC_HIDDEN; +HRESULT wined3d_rendertarget_view_no3d_init(struct wined3d_rendertarget_view *view_no3d, + const struct wined3d_view_desc *desc, struct wined3d_resource *resource, + void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN; + struct wined3d_rendertarget_view_gl { struct wined3d_rendertarget_view v; @@ -4176,6 +4185,25 @@ static inline struct wined3d_rendertarget_view_gl *wined3d_rendertarget_view_gl( return CONTAINING_RECORD(view, struct wined3d_rendertarget_view_gl, v); } +HRESULT wined3d_rendertarget_view_gl_init(struct wined3d_rendertarget_view_gl *view_gl, + const struct wined3d_view_desc *desc, struct wined3d_resource *resource, + void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN; + +struct wined3d_rendertarget_view_vk +{ + struct wined3d_rendertarget_view v; +}; + +static inline struct wined3d_rendertarget_view_vk *wined3d_rendertarget_view_vk( + struct wined3d_rendertarget_view *view) +{ + return CONTAINING_RECORD(view, struct wined3d_rendertarget_view_vk, v); +} + +HRESULT wined3d_rendertarget_view_vk_init(struct wined3d_rendertarget_view_vk *view_vk, + const struct wined3d_view_desc *desc, struct wined3d_resource *resource, + void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN; + struct wined3d_shader_resource_view { LONG refcount;