From ec87407e7c31451aab636f1b586edaf3ce38a6a1 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Wed, 20 Aug 2014 13:20:02 +0200 Subject: [PATCH] wined3d: Keep a reference to the frontbuffer texture instead of the surface in the swapchain. --- dlls/wined3d/arb_program_shader.c | 2 +- dlls/wined3d/context.c | 4 +-- dlls/wined3d/device.c | 11 ++++--- dlls/wined3d/resource.c | 2 +- dlls/wined3d/surface.c | 23 ++++++++------- dlls/wined3d/swapchain.c | 49 ++++++++++++++++++------------- dlls/wined3d/wined3d_private.h | 2 +- 7 files changed, 53 insertions(+), 40 deletions(-) diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index e694b727159..5d6214a5487 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -7675,7 +7675,7 @@ HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter, if (wined3d_settings.strict_draw_ordering || (dst_surface->container->swapchain - && (dst_surface->container->swapchain->front_buffer == dst_surface))) + && (dst_surface->container->swapchain->front_buffer == dst_surface->container))) context->gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ context_release(context); diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 1044f99a6ce..bd8de7b6f44 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -1826,7 +1826,7 @@ static void context_get_rt_size(const struct wined3d_context *context, SIZE *siz { const struct wined3d_surface *rt = context->current_rt; - if (rt->container->swapchain && rt->container->swapchain->front_buffer == rt) + if (rt->container->swapchain && rt->container->swapchain->front_buffer == rt->container) { RECT window_size; @@ -3104,7 +3104,7 @@ struct wined3d_context *context_acquire(const struct wined3d_device *device, str if (swapchain->back_buffers) target = swapchain->back_buffers[0]; else - target = swapchain->front_buffer; + target = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)); } } diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index c650066142f..fc754b3a305 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -462,7 +462,7 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c } if (wined3d_settings.strict_draw_ordering || (flags & WINED3DCLEAR_TARGET - && target->container->swapchain && target->container->swapchain->front_buffer == target)) + && target->container->swapchain && target->container->swapchain->front_buffer == target->container)) gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ context_release(context); @@ -913,7 +913,8 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device, device->swapchains[0] = swapchain; device_init_swapchain_state(device, swapchain); - context = context_acquire(device, swapchain->front_buffer); + context = context_acquire(device, + surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0))); create_dummy_textures(device, context); @@ -4169,7 +4170,8 @@ static HRESULT create_primary_opengl_context(struct wined3d_device *device, stru return E_OUTOFMEMORY; } - target = swapchain->back_buffers ? swapchain->back_buffers[0] : swapchain->front_buffer; + target = swapchain->back_buffers ? swapchain->back_buffers[0] + : surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)); if (!(context = context_create(swapchain, target, swapchain->ds_format))) { WARN("Failed to create context.\n"); @@ -4401,7 +4403,8 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, { UINT i; - if (FAILED(hr = wined3d_surface_update_desc(swapchain->front_buffer, swapchain->desc.backbuffer_width, + if (FAILED(hr = wined3d_surface_update_desc(surface_from_resource( + wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)), swapchain->desc.backbuffer_width, swapchain->desc.backbuffer_height, swapchain->desc.backbuffer_format, swapchain->desc.multisample_type, swapchain->desc.multisample_quality, NULL, 0))) return hr; diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c index c7a5adaf613..4247cd7ff11 100644 --- a/dlls/wined3d/resource.c +++ b/dlls/wined3d/resource.c @@ -316,7 +316,7 @@ BOOL wined3d_resource_is_offscreen(struct wined3d_resource *resource) return TRUE; /* The front buffer is always onscreen */ - if (resource == &swapchain->front_buffer->container->resource) + if (resource == &swapchain->front_buffer->resource) return FALSE; /* If the swapchain is rendered to an FBO, the backbuffer is diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 23c9fd30f38..9be4ac2f558 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -749,7 +749,7 @@ static void surface_unmap(struct wined3d_surface *surface) return; } - if (surface->container->swapchain && surface->container->swapchain->front_buffer == surface) + if (surface->container->swapchain && surface->container->swapchain->front_buffer == surface->container) surface_load_location(surface, surface->container->resource.draw_binding); else if (surface->resource.format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) FIXME("Depth / stencil buffer locking is not implemented.\n"); @@ -968,7 +968,7 @@ static void surface_blt_fbo(const struct wined3d_device *device, enum wined3d_te if (wined3d_settings.strict_draw_ordering || (dst_location == WINED3D_LOCATION_DRAWABLE - && dst_surface->container->swapchain->front_buffer == dst_surface)) + && dst_surface->container->swapchain->front_buffer == dst_surface->container)) gl_info->gl_ops.gl.p_glFlush(); context_release(context); @@ -1291,7 +1291,7 @@ static void gdi_surface_unmap(struct wined3d_surface *surface) TRACE("surface %p.\n", surface); /* Tell the swapchain to update the screen. */ - if (surface->container->swapchain && surface == surface->container->swapchain->front_buffer) + if (surface->container->swapchain && surface->container == surface->container->swapchain->front_buffer) x11_copy_to_screen(surface->container->swapchain, &surface->lockedRect); memset(&surface->lockedRect, 0, sizeof(RECT)); @@ -1607,7 +1607,7 @@ static HRESULT d3dfmt_get_conv(const struct wined3d_surface *surface, BOOL need_ * conflicts with this. */ if (!((blit_supported && surface->container->swapchain - && surface == surface->container->swapchain->front_buffer)) + && surface->container == surface->container->swapchain->front_buffer)) || colorkey_active || !use_texturing) { format->glFormat = GL_RGBA; @@ -1995,7 +1995,7 @@ GLenum surface_get_gl_buffer(const struct wined3d_surface *surface) TRACE("Returning GL_BACK\n"); return GL_BACK; } - else if (surface == swapchain->front_buffer) + else if (surface->container == swapchain->front_buffer) { TRACE("Returning GL_FRONT\n"); return GL_FRONT; @@ -3855,7 +3855,7 @@ void surface_translate_drawable_coords(const struct wined3d_surface *surface, HW { UINT drawable_height; - if (surface->container->swapchain && surface == surface->container->swapchain->front_buffer) + if (surface->container->swapchain && surface->container == surface->container->swapchain->front_buffer) { POINT offset = {0, 0}; RECT windowsize; @@ -3936,7 +3936,8 @@ static void surface_blt_to_drawable(const struct wined3d_device *device, device->blitter->unset_shader(context->gl_info); if (wined3d_settings.strict_draw_ordering - || (dst_surface->container->swapchain && dst_surface->container->swapchain->front_buffer == dst_surface)) + || (dst_surface->container->swapchain + && dst_surface->container->swapchain->front_buffer == dst_surface->container)) gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ context_release(context); @@ -4309,7 +4310,8 @@ void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_co /* Note that we use depth_blt here as well, rather than glCopyTexImage2D * directly on the FBO texture. That's because we need to flip. */ context_apply_fbo_state_blit(context, GL_FRAMEBUFFER, - context->swapchain->front_buffer, NULL, WINED3D_LOCATION_DRAWABLE); + surface_from_resource(wined3d_texture_get_sub_resource(context->swapchain->front_buffer, 0)), + NULL, WINED3D_LOCATION_DRAWABLE); if (surface->texture_target == GL_TEXTURE_RECTANGLE_ARB) { gl_info->gl_ops.gl.p_glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_binding); @@ -4355,7 +4357,8 @@ void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_co TRACE("Copying depth texture to onscreen depth buffer.\n"); context_apply_fbo_state_blit(context, GL_FRAMEBUFFER, - context->swapchain->front_buffer, NULL, WINED3D_LOCATION_DRAWABLE); + surface_from_resource(wined3d_texture_get_sub_resource(context->swapchain->front_buffer, 0)), + NULL, WINED3D_LOCATION_DRAWABLE); surface_depth_blt(surface, context, surface->container->texture_rgb.name, 0, surface->pow2Height - h, w, h, surface->texture_target); checkGLcall("depth_blt"); @@ -5828,7 +5831,7 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC * to the frontbuffer instead of doing a Flip(). D3D8 and D3D9 * applications can't blit directly to the frontbuffer. */ if (dst_swapchain && dst_swapchain->back_buffers - && dst_surface == dst_swapchain->front_buffer + && dst_surface->container == dst_swapchain->front_buffer && src_surface == dst_swapchain->back_buffers[0]) { enum wined3d_swap_effect swap_effect = dst_swapchain->desc.swap_effect; diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index 2d1a93bf9c5..fb9bfa89bca 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -40,8 +40,8 @@ static void swapchain_cleanup(struct wined3d_swapchain *swapchain) * is the last buffer to be destroyed, FindContext() depends on that. */ if (swapchain->front_buffer) { - wined3d_texture_set_swapchain(swapchain->front_buffer->container, NULL); - if (wined3d_surface_decref(swapchain->front_buffer)) + wined3d_texture_set_swapchain(swapchain->front_buffer, NULL); + if (wined3d_texture_decref(swapchain->front_buffer)) WARN("Something's still holding the front buffer (%p).\n", swapchain->front_buffer); swapchain->front_buffer = NULL; } @@ -163,7 +163,7 @@ HRESULT CDECL wined3d_swapchain_get_front_buffer_data(const struct wined3d_swapc TRACE("swapchain %p, dst_surface %p.\n", swapchain, dst_surface); - src_surface = swapchain->front_buffer; + src_surface = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)); SetRect(&src_rect, 0, 0, src_surface->resource.width, src_surface->resource.height); dst_rect = src_rect; @@ -315,7 +315,8 @@ static void swapchain_blit(const struct wined3d_swapchain *swapchain, gl_info->gl_ops.gl.p_glReadBuffer(GL_COLOR_ATTACHMENT0); context_check_fbo_status(context, GL_READ_FRAMEBUFFER); - context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, swapchain->front_buffer, + context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, + surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)), NULL, WINED3D_LOCATION_DRAWABLE); context_set_draw_buffer(context, GL_BACK); context_invalidate_state(context, STATE_FRAMEBUFFER); @@ -358,7 +359,8 @@ static void swapchain_blit(const struct wined3d_swapchain *swapchain, if (is_complex_fixup(backbuffer->resource.format->color_fixup)) gl_filter = GL_NEAREST; - context_apply_fbo_state_blit(context2, GL_FRAMEBUFFER, swapchain->front_buffer, + context_apply_fbo_state_blit(context2, GL_FRAMEBUFFER, + surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)), NULL, WINED3D_LOCATION_DRAWABLE); context_bind_texture(context2, backbuffer->texture_target, backbuffer->container->texture_rgb.name); @@ -420,6 +422,7 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT const struct wined3d_fb_state *fb = &swapchain->device->fb; const struct wined3d_gl_info *gl_info; struct wined3d_context *context; + struct wined3d_surface *front; RECT src_rect, dst_rect; BOOL render_to_fbo; @@ -549,13 +552,13 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT } } - if (!swapchain->render_to_fbo && ((swapchain->front_buffer->locations & WINED3D_LOCATION_SYSMEM) + front = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)); + if (!swapchain->render_to_fbo && ((front->locations & WINED3D_LOCATION_SYSMEM) || (back_buffer->locations & WINED3D_LOCATION_SYSMEM))) { /* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying * Doesn't work with render_to_fbo because we're not flipping */ - struct wined3d_surface *front = swapchain->front_buffer; if (front->resource.size == back_buffer->resource.size) { @@ -576,8 +579,8 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT } else { - surface_validate_location(swapchain->front_buffer, WINED3D_LOCATION_DRAWABLE); - surface_invalidate_location(swapchain->front_buffer, ~WINED3D_LOCATION_DRAWABLE); + surface_validate_location(front, WINED3D_LOCATION_DRAWABLE); + surface_invalidate_location(front, ~WINED3D_LOCATION_DRAWABLE); /* If the swapeffect is DISCARD, the back buffer is undefined. That means the SYSMEM * and INTEXTURE copies can keep their old content if they have any defined content. * If the swapeffect is COPY, the content remains the same. If it is FLIP however, @@ -625,10 +628,10 @@ void x11_copy_to_screen(const struct wined3d_swapchain *swapchain, const RECT *r TRACE("swapchain %p, rect %s.\n", swapchain, wine_dbgstr_rect(rect)); + front = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)); if (swapchain->palette) - wined3d_palette_apply_to_dc(swapchain->palette, swapchain->front_buffer->hDC); + wined3d_palette_apply_to_dc(swapchain->palette, front->hDC); - front = swapchain->front_buffer; if (front->resource.map_count) ERR("Trying to blit a mapped surface.\n"); @@ -666,7 +669,7 @@ static void swapchain_gdi_present(struct wined3d_swapchain *swapchain, const REC { struct wined3d_surface *front, *back; - front = swapchain->front_buffer; + front = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)); back = swapchain->back_buffers[0]; /* Flip the DC. */ @@ -767,6 +770,7 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3 { const struct wined3d_adapter *adapter = device->adapter; struct wined3d_resource_desc surface_desc; + struct wined3d_surface *front_buffer; BOOL displaymode_set = FALSE; RECT client_rect; HWND window; @@ -848,17 +852,18 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3 surface_desc.size = 0; if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent, - parent, &surface_desc, &swapchain->front_buffer))) + parent, &surface_desc, &front_buffer))) { WARN("Failed to create front buffer, hr %#x.\n", hr); goto err; } - wined3d_texture_set_swapchain(swapchain->front_buffer->container, swapchain); + swapchain->front_buffer = front_buffer->container; + wined3d_texture_set_swapchain(swapchain->front_buffer, swapchain); if (!(device->wined3d->flags & WINED3D_NO3D)) { - surface_validate_location(swapchain->front_buffer, WINED3D_LOCATION_DRAWABLE); - surface_invalidate_location(swapchain->front_buffer, ~WINED3D_LOCATION_DRAWABLE); + surface_validate_location(front_buffer, WINED3D_LOCATION_DRAWABLE); + surface_invalidate_location(front_buffer, ~WINED3D_LOCATION_DRAWABLE); } /* MSDN says we're only allowed a single fullscreen swapchain per device, @@ -920,7 +925,7 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3 for (i = 0; i < (sizeof(formats) / sizeof(*formats)); i++) { swapchain->ds_format = wined3d_get_format(gl_info, formats[i]); - swapchain->context[0] = context_create(swapchain, swapchain->front_buffer, swapchain->ds_format); + swapchain->context[0] = context_create(swapchain, front_buffer, swapchain->ds_format); if (swapchain->context[0]) break; TRACE("Depth stencil format %s is not supported, trying next format\n", debug_d3dformat(formats[i])); @@ -1025,8 +1030,8 @@ err: if (swapchain->front_buffer) { - wined3d_texture_set_swapchain(swapchain->front_buffer->container, NULL); - wined3d_surface_decref(swapchain->front_buffer); + wined3d_texture_set_swapchain(swapchain->front_buffer, NULL); + wined3d_texture_decref(swapchain->front_buffer); } return hr; @@ -1066,7 +1071,9 @@ static struct wined3d_context *swapchain_create_context(struct wined3d_swapchain TRACE("Creating a new context for swapchain %p, thread %u.\n", swapchain, GetCurrentThreadId()); - if (!(ctx = context_create(swapchain, swapchain->front_buffer, swapchain->ds_format))) + if (!(ctx = context_create(swapchain, + surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)), + swapchain->ds_format))) { ERR("Failed to create a new context for the swapchain\n"); return NULL; @@ -1144,7 +1151,7 @@ void swapchain_update_draw_bindings(struct wined3d_swapchain *swapchain) { UINT i; - wined3d_resource_update_draw_binding(&swapchain->front_buffer->container->resource); + wined3d_resource_update_draw_binding(&swapchain->front_buffer->resource); for (i = 0; i < swapchain->desc.backbuffer_count; ++i) { diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 38328150229..b517d4eb793 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2622,7 +2622,7 @@ struct wined3d_swapchain struct wined3d_device *device; struct wined3d_surface **back_buffers; - struct wined3d_surface *front_buffer; + struct wined3d_texture *front_buffer; struct wined3d_swapchain_desc desc; struct wined3d_display_mode original_mode; struct wined3d_gamma_ramp orig_gamma;