From: Stian Low <wineryyyyy@gmail.com> --- dlls/wined3d/adapter_gl.c | 39 +++++++++++---- dlls/wined3d/swapchain.c | 33 +++++++++++++ dlls/wined3d/view.c | 100 +++++++++++++++++++++++++++++--------- dlls/wined3d/wined3d_gl.h | 7 +++ 4 files changed, 145 insertions(+), 34 deletions(-) diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 35f73b64497..dd1b1a65deb 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -4586,7 +4586,7 @@ static HRESULT adapter_gl_create_rendertarget_view(const struct wined3d_view_des struct wined3d_view_gl_destroy_ctx { struct wined3d_device *device; - const struct wined3d_gl_view *gl_view; + GLuint name; struct wined3d_bo_user *bo_user; struct wined3d_bo_gl *counter_bo; void *object; @@ -4606,14 +4606,14 @@ static void wined3d_view_gl_destroy_object(void *object) device = ctx->device; counter_id = ctx->counter_bo ? ctx->counter_bo->id : 0; - if (ctx->gl_view->name || counter_id) + if (ctx->name || counter_id) { context = context_acquire(device, NULL, 0); gl_info = wined3d_context_gl(context)->gl_info; - if (ctx->gl_view->name) + if (ctx->name) { - context_gl_resource_released(device, ctx->gl_view->name, FALSE); - gl_info->gl_ops.gl.p_glDeleteTextures(1, &ctx->gl_view->name); + context_gl_resource_released(device, ctx->name, FALSE); + gl_info->gl_ops.gl.p_glDeleteTextures(1, &ctx->name); } if (counter_id) wined3d_context_gl_destroy_bo(wined3d_context_gl(context), ctx->counter_bo); @@ -4627,7 +4627,7 @@ static void wined3d_view_gl_destroy_object(void *object) free(ctx->free); } -static void wined3d_view_gl_destroy(struct wined3d_device *device, const struct wined3d_gl_view *gl_view, +static void wined3d_view_gl_destroy(struct wined3d_device *device, GLuint name, struct wined3d_bo_user *bo_user, struct wined3d_bo_gl *counter_bo, void *object) { struct wined3d_view_gl_destroy_ctx *ctx, c; @@ -4635,7 +4635,7 @@ static void wined3d_view_gl_destroy(struct wined3d_device *device, const struct if (!(ctx = malloc(sizeof(*ctx)))) ctx = &c; ctx->device = device; - ctx->gl_view = gl_view; + ctx->name = name; ctx->bo_user = bo_user; ctx->counter_bo = counter_bo; ctx->object = object; @@ -4646,6 +4646,24 @@ static void wined3d_view_gl_destroy(struct wined3d_device *device, const struct wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); } +static void adapter_gl_destroy_swapchain_rendertarget_views(struct wined3d_rendertarget_view_gl *view_gl) +{ + struct wined3d_swapchain_rendertarget_view_gl *swap_view_gl, *swap_view_gl_next; + struct wined3d_resource *resource = view_gl->v.resource; + struct wined3d_swapchain *swapchain; + + if (!(swapchain = wined3d_swapchain_from_resource(resource))) + return; + + LIST_FOR_EACH_ENTRY_SAFE(swap_view_gl, swap_view_gl_next, &view_gl->swapchain_views, struct wined3d_swapchain_rendertarget_view_gl, entry) + { + wined3d_view_gl_destroy(resource->device, swap_view_gl->name, NULL, NULL, NULL); + list_remove(&swap_view_gl->entry); + free(swap_view_gl); + swap_view_gl = swap_view_gl_next; + } +} + static void adapter_gl_destroy_rendertarget_view(struct wined3d_rendertarget_view *view) { struct wined3d_rendertarget_view_gl *view_gl = wined3d_rendertarget_view_gl(view); @@ -4653,8 +4671,9 @@ static void adapter_gl_destroy_rendertarget_view(struct wined3d_rendertarget_vie TRACE("view_gl %p.\n", view_gl); + adapter_gl_destroy_swapchain_rendertarget_views(view_gl); wined3d_rendertarget_view_cleanup(&view_gl->v); - wined3d_view_gl_destroy(resource->device, &view_gl->gl_view, NULL, NULL, view_gl); + wined3d_view_gl_destroy(resource->device, view_gl->gl_view.name, NULL, NULL, view_gl); } static HRESULT adapter_gl_create_shader_resource_view(const struct wined3d_view_desc *desc, @@ -4691,7 +4710,7 @@ static void adapter_gl_destroy_shader_resource_view(struct wined3d_shader_resour TRACE("view_gl %p.\n", view_gl); wined3d_shader_resource_view_cleanup(&view_gl->v); - wined3d_view_gl_destroy(resource->device, &view_gl->gl_view, &view_gl->bo_user, NULL, view_gl); + wined3d_view_gl_destroy(resource->device, view_gl->gl_view.name, &view_gl->bo_user, NULL, view_gl); } static HRESULT adapter_gl_create_unordered_access_view(const struct wined3d_view_desc *desc, @@ -4728,7 +4747,7 @@ static void adapter_gl_destroy_unordered_access_view(struct wined3d_unordered_ac TRACE("view_gl %p.\n", view_gl); wined3d_unordered_access_view_cleanup(&view_gl->v); - wined3d_view_gl_destroy(resource->device, &view_gl->gl_view, &view_gl->bo_user, &view_gl->counter_bo, view_gl); + wined3d_view_gl_destroy(resource->device, view_gl->gl_view.name, &view_gl->bo_user, &view_gl->counter_bo, view_gl); } static HRESULT adapter_gl_create_video_decoder_output_view(const struct wined3d_view_desc *desc, diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index 59fa4e9146e..f9556c01c1d 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -538,6 +538,39 @@ static void swapchain_gl_set_swap_interval(struct wined3d_swapchain *swapchain, } } +static void wined3d_swapchain_rendertarget_view_gl_rotate(struct wined3d_swapchain *swapchain) +{ + struct wined3d_swapchain_rendertarget_view_gl *swap_view_gl; + struct wined3d_swapchain_rendertarget_view *swap_view; + struct wined3d_rendertarget_view_gl *view_gl; + GLuint name, name_prev; + + if (!swapchain || swapchain->state.desc.backbuffer_count < 2) + return; + + LIST_FOR_EACH_ENTRY(swap_view, &swapchain->back_buffer_rendertarget_views, struct wined3d_swapchain_rendertarget_view, entry) + { + if (!swap_view->view) + continue; + + view_gl = wined3d_rendertarget_view_gl(swap_view->view); + if (!view_gl->gl_view.name) + { + FIXME("Skipping rotate for view_gl %p with name 0 which should not occur.\n", view_gl); + continue; + } + + name_prev = view_gl->gl_view.name; + LIST_FOR_EACH_ENTRY(swap_view_gl, &view_gl->swapchain_views, struct wined3d_swapchain_rendertarget_view_gl, entry) + { + name = swap_view_gl->name; + swap_view_gl->name = name_prev; + name_prev = name; + } + view_gl->gl_view.name = name_prev; + } +} + /* Context activation is done by the caller. */ static void wined3d_swapchain_gl_rotate(struct wined3d_swapchain *swapchain, struct wined3d_context *context) { diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c index a8892a88b92..6f2e11ebdd1 100644 --- a/dlls/wined3d/view.c +++ b/dlls/wined3d/view.c @@ -603,48 +603,99 @@ void wined3d_rendertarget_view_get_box(struct wined3d_rendertarget_view *view, static void wined3d_render_target_view_gl_cs_init(void *object) { + struct wined3d_swapchain_rendertarget_view_gl *swap_view_gl; struct wined3d_rendertarget_view_gl *view_gl = object; struct wined3d_resource *resource = view_gl->v.resource; const struct wined3d_view_desc *desc = &view_gl->v.desc; + struct wined3d_swapchain_rendertarget_view *lview; + struct wined3d_texture_gl *texture_gl; + struct wined3d_swapchain *swapchain; + unsigned int depth_or_layer_count; + GLenum resource_class, view_class; + struct wined3d_context *context; + unsigned int i, count; + GLuint name; TRACE("view_gl %p.\n", view_gl); if (resource->type == WINED3D_RTYPE_BUFFER) { FIXME("Not implemented for resources %s.\n", debug_d3dresourcetype(resource->type)); + return; } + + texture_gl = wined3d_texture_gl(texture_from_resource(resource)); + if (resource->type == WINED3D_RTYPE_TEXTURE_3D) + depth_or_layer_count = wined3d_texture_get_level_depth(&texture_gl->t, desc->u.texture.level_idx); else + depth_or_layer_count = texture_gl->t.layer_count; + + if (resource->format->id == view_gl->v.format->id + && (view_gl->v.layer_count == 1 && view_gl->v.layer_count == depth_or_layer_count)) { - struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(texture_from_resource(resource)); - unsigned int depth_or_layer_count; + TRACE("Skipping view init because format and layer_count matches underlying texture\n"); + return; + } - if (resource->type == WINED3D_RTYPE_TEXTURE_3D) - depth_or_layer_count = wined3d_texture_get_level_depth(&texture_gl->t, desc->u.texture.level_idx); - else - depth_or_layer_count = texture_gl->t.layer_count; + resource_class = wined3d_format_gl(resource->format)->view_class; + view_class = wined3d_format_gl(view_gl->v.format)->view_class; + if (resource_class != view_class) + { + FIXME("Render target view not supported, resource format %s, view format %s.\n", + debug_d3dformat(resource->format->id), debug_d3dformat(view_gl->v.format->id)); + return; + } - if (resource->format->id != view_gl->v.format->id - || (view_gl->v.layer_count != 1 && view_gl->v.layer_count != depth_or_layer_count)) - { - GLenum resource_class, view_class; + context = context_acquire(resource->device, NULL, 0); + create_texture_view(&view_gl->gl_view, texture_gl->target, desc, texture_gl, view_gl->v.format); + context_release(context); + if (!view_gl->gl_view.name) + { + ERR("Failed to create render target view for resource %p\n", resource); + /* TODO: flag for cleanup? */ + return; + } - resource_class = wined3d_format_gl(resource->format)->view_class; - view_class = wined3d_format_gl(view_gl->v.format)->view_class; - if (resource_class != view_class) - { - FIXME("Render target view not supported, resource format %s, view format %s.\n", - debug_d3dformat(resource->format->id), debug_d3dformat(view_gl->v.format->id)); - return; - } - if (texture_gl->t.swapchain && texture_gl->t.swapchain->state.desc.backbuffer_count > 1) - { - FIXME("Swapchain views not supported.\n"); - return; - } + if (!(swapchain = swapchain_from_resource(resource))) + return; + + context = context_acquire(resource->device, NULL, 0); + count = swapchain->state.desc.backbuffer_count - 1; + name = view_gl->gl_view.name; + for (i = 0; i < count; i++) + { + if (!(swap_view_gl = calloc(1, sizeof(*swap_view_gl)))) + { + ERR("Out of memory.\n"); + return; + } - create_texture_view(&view_gl->gl_view, texture_gl->target, desc, texture_gl, view_gl->v.format); + list_add_head(&view_gl->swapchain_views, &swap_view_gl->entry); + texture_gl = wined3d_texture_gl(swapchain->back_buffers[i + 1]); + create_texture_view(&view_gl->gl_view, texture_gl->target, desc, texture_gl, view_gl->v.format); + if (view_gl->gl_view.name) + { + swap_view_gl->name = view_gl->gl_view.name; + continue; } + + ERR("Failed to create render target view for swapchain %p backbuffer[%u]\n", swapchain, i); + /* TODO: flag for cleanup? */ + break; } + + view_gl->gl_view.name = name; + context_release(context); + + if (!(lview = calloc(1, sizeof(*lview)))) + { + ERR("Out of memory.\n"); + /* TODO: flag for cleanup? */ + return; + } + + list_add_head(&swapchain->back_buffer_rendertarget_views, &lview->entry); + lview->view = &view_gl->v; } static HRESULT wined3d_rendertarget_view_init(struct wined3d_rendertarget_view *view, @@ -716,6 +767,7 @@ HRESULT wined3d_rendertarget_view_gl_init(struct wined3d_rendertarget_view_gl *v if (FAILED(hr = wined3d_rendertarget_view_init(&view_gl->v, desc, resource, parent, parent_ops))) return hr; + list_init(&view_gl->swapchain_views); wined3d_cs_init_object(resource->device->cs, wined3d_render_target_view_gl_cs_init, view_gl); return hr; diff --git a/dlls/wined3d/wined3d_gl.h b/dlls/wined3d/wined3d_gl.h index c9c7118c59e..fdd3e4a0e9b 100644 --- a/dlls/wined3d/wined3d_gl.h +++ b/dlls/wined3d/wined3d_gl.h @@ -1078,10 +1078,17 @@ HRESULT wined3d_buffer_gl_init(struct wined3d_buffer_gl *buffer_gl, struct wined const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops); +struct wined3d_swapchain_rendertarget_view_gl +{ + struct list entry; + GLuint name; +}; + struct wined3d_rendertarget_view_gl { struct wined3d_rendertarget_view v; struct wined3d_gl_view gl_view; + struct list swapchain_views; }; static inline struct wined3d_rendertarget_view_gl *wined3d_rendertarget_view_gl( -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10567