From: Andrew Boyarshin andrew.boyarshin@gmail.com
--- dlls/wined3d/context_gl.c | 2 +- dlls/wined3d/cs.c | 6 +-- dlls/wined3d/device.c | 8 ++-- dlls/wined3d/surface.c | 2 +- dlls/wined3d/swapchain.c | 81 ++++++++++++++++++++++------------ dlls/wined3d/texture.c | 2 +- dlls/wined3d/wined3d_private.h | 8 +++- 7 files changed, 70 insertions(+), 39 deletions(-)
diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index ac1b9370fc1..6d16bc69b4e 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -4340,7 +4340,7 @@ struct wined3d_context *wined3d_context_gl_acquire(const struct wined3d_device * struct wined3d_swapchain *swapchain = device->swapchains[0];
if (swapchain->back_buffers) - texture = swapchain->back_buffers[0]; + texture = swapchain->back_buffers[0].texture; else texture = swapchain->front_buffer; sub_resource_idx = 0; diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 21ed1264971..de969ba82fd 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -671,7 +671,7 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data)
swapchain = op->swapchain; desc = &swapchain->state.desc; - back_buffer = swapchain->back_buffers[0]; + back_buffer = swapchain->back_buffers[0].texture; wined3d_swapchain_set_window(swapchain, op->dst_window_override);
if ((logo_texture = swapchain->device->logo_texture)) @@ -711,7 +711,7 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) swapchain->swapchain_ops->swapchain_present(swapchain, &op->src_rect, &op->dst_rect, op->swap_interval, op->flags);
/* Discard buffers if the swap effect allows it. */ - back_buffer = swapchain->back_buffers[desc->backbuffer_count - 1]; + back_buffer = swapchain->back_buffers[desc->backbuffer_count - 1].texture; if (desc->swap_effect == WINED3D_SWAP_EFFECT_DISCARD || desc->swap_effect == WINED3D_SWAP_EFFECT_FLIP_DISCARD) wined3d_texture_validate_location(back_buffer, 0, WINED3D_LOCATION_DISCARDED);
@@ -777,7 +777,7 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw wined3d_resource_reference(&swapchain->front_buffer->resource); for (i = 0; i < swapchain->state.desc.backbuffer_count; ++i) { - wined3d_resource_reference(&swapchain->back_buffers[i]->resource); + wined3d_resource_reference(&swapchain->back_buffers[i].texture->resource); }
wined3d_device_context_submit(&cs->c, WINED3D_CS_QUEUE_DEFAULT); diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 443bf10ab76..eb26ffe8d4e 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1487,7 +1487,7 @@ void wined3d_device_gl_create_primary_opengl_context_cs(void *object)
device = &device_gl->d; swapchain = device->swapchains[0]; - target = swapchain->back_buffers ? swapchain->back_buffers[0] : swapchain->front_buffer; + target = swapchain->back_buffers ? swapchain->back_buffers[0].texture : swapchain->front_buffer; if (!(context = context_acquire(device, target, 0))) { WARN("Failed to acquire context.\n"); @@ -1571,7 +1571,7 @@ HRESULT wined3d_device_set_implicit_swapchain(struct wined3d_device *device, str swapchain_desc = &swapchain->state.desc; if (swapchain_desc->backbuffer_count && swapchain_desc->backbuffer_bind_flags & WINED3D_BIND_RENDER_TARGET) { - struct wined3d_resource *back_buffer = &swapchain->back_buffers[0]->resource; + struct wined3d_resource *back_buffer = &swapchain->back_buffers[0].texture->resource; struct wined3d_view_desc view_desc;
view_desc.format_id = back_buffer->format->id; @@ -5154,7 +5154,7 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, update_swapchain_flags(swapchain->front_buffer); for (i = 0; i < current_desc->backbuffer_count; ++i) { - update_swapchain_flags(swapchain->back_buffers[i]); + update_swapchain_flags(swapchain->back_buffers[i].texture); } }
@@ -5212,7 +5212,7 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, } if (current_desc->backbuffer_count && current_desc->backbuffer_bind_flags & WINED3D_BIND_RENDER_TARGET) { - struct wined3d_resource *back_buffer = &swapchain->back_buffers[0]->resource; + struct wined3d_resource *back_buffer = &swapchain->back_buffers[0].texture->resource;
view_desc.format_id = back_buffer->format->id; view_desc.flags = 0; diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 067b3afc30e..7f519cb553e 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -1586,7 +1586,7 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_ } else if (dst_swapchain && dst_swapchain->back_buffers && dst_texture == dst_swapchain->front_buffer - && src_texture == dst_swapchain->back_buffers[0]) + && src_texture == dst_swapchain->back_buffers[0].texture) { /* Use present for back -> front blits. The idea behind this is that * present is potentially faster than a blit, in particular when FBO diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index a1000ec2393..9156d74beef 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -53,9 +53,11 @@ void wined3d_swapchain_cleanup(struct wined3d_swapchain *swapchain)
while (i--) { - wined3d_texture_set_swapchain(swapchain->back_buffers[i], NULL); - if (wined3d_texture_decref(swapchain->back_buffers[i])) - WARN("Something's still holding back buffer %u (%p).\n", i, swapchain->back_buffers[i]); + struct wined3d_backbuffer *backbuffer = &swapchain->back_buffers[i]; + if (backbuffer->dirty_region) DeleteObject(backbuffer->dirty_region); + wined3d_texture_set_swapchain(backbuffer->texture, NULL); + if (wined3d_texture_decref(backbuffer->texture)) + WARN("Something's still holding back buffer %u (%p).\n", i, swapchain->back_buffers[i].texture); } free(swapchain->back_buffers); swapchain->back_buffers = NULL; @@ -272,9 +274,9 @@ struct wined3d_texture * CDECL wined3d_swapchain_get_back_buffer(const struct wi return NULL; }
- TRACE("Returning back buffer %p.\n", swapchain->back_buffers[back_buffer_idx]); + TRACE("Returning back buffer %p.\n", swapchain->back_buffers[back_buffer_idx].texture);
- return swapchain->back_buffers[back_buffer_idx]; + return swapchain->back_buffers[back_buffer_idx].texture; }
struct wined3d_texture * CDECL wined3d_swapchain_get_front_buffer(const struct wined3d_swapchain *swapchain) @@ -399,7 +401,7 @@ HRESULT CDECL wined3d_swapchain_get_gamma_ramp(const struct wined3d_swapchain *s static void swapchain_blit_gdi(struct wined3d_swapchain *swapchain, struct wined3d_context *context, const RECT *src_rect, const RECT *dst_rect) { - struct wined3d_texture *back_buffer = swapchain->back_buffers[0]; + struct wined3d_texture *back_buffer = swapchain->back_buffers[0].texture; D3DKMT_DESTROYDCFROMMEMORY destroy_desc; D3DKMT_CREATEDCFROMMEMORY create_desc; const struct wined3d_format *format; @@ -466,7 +468,7 @@ static void swapchain_blit_gdi(struct wined3d_swapchain *swapchain, static void swapchain_blit(const struct wined3d_swapchain *swapchain, struct wined3d_context *context, const RECT *src_rect, const RECT *dst_rect) { - struct wined3d_texture *texture = swapchain->back_buffers[0]; + struct wined3d_texture *texture = swapchain->back_buffers[0].texture; struct wined3d_device *device = swapchain->device; enum wined3d_texture_filter_type filter; DWORD location; @@ -516,8 +518,10 @@ static void swapchain_gl_set_swap_interval(struct wined3d_swapchain *swapchain, static void wined3d_swapchain_gl_rotate(struct wined3d_swapchain *swapchain, struct wined3d_context *context) { struct wined3d_texture_sub_resource *sub_resource; + struct wined3d_backbuffer *backbuffer, *backbuffer_prev; struct wined3d_texture_gl *texture, *texture_prev; struct gl_texture tex0; + HRGN dirty_region0; GLuint rb0; DWORD locations0; unsigned int i; @@ -526,30 +530,36 @@ static void wined3d_swapchain_gl_rotate(struct wined3d_swapchain *swapchain, str if (swapchain->state.desc.backbuffer_count < 2) return;
- texture_prev = wined3d_texture_gl(swapchain->back_buffers[0]); + backbuffer_prev = &swapchain->back_buffers[0]; + texture_prev = wined3d_texture_gl(backbuffer_prev->texture);
/* Back buffer 0 is already in the draw binding. */ + dirty_region0 = backbuffer_prev->dirty_region; tex0 = texture_prev->texture_rgb; rb0 = texture_prev->rb_multisample; locations0 = texture_prev->t.sub_resources[0].locations;
for (i = 1; i < swapchain->state.desc.backbuffer_count; ++i) { - texture = wined3d_texture_gl(swapchain->back_buffers[i]); + backbuffer = &swapchain->back_buffers[i]; + texture = wined3d_texture_gl(backbuffer->texture); sub_resource = &texture->t.sub_resources[0];
if (!(sub_resource->locations & supported_locations)) wined3d_texture_load_location(&texture->t, 0, context, texture->t.resource.draw_binding);
+ backbuffer_prev->dirty_region = backbuffer->dirty_region; texture_prev->texture_rgb = texture->texture_rgb; texture_prev->rb_multisample = texture->rb_multisample;
wined3d_texture_validate_location(&texture_prev->t, 0, sub_resource->locations & supported_locations); wined3d_texture_invalidate_location(&texture_prev->t, 0, ~(sub_resource->locations & supported_locations));
+ backbuffer_prev = backbuffer; texture_prev = texture; }
+ backbuffer_prev->dirty_region = dirty_region0; texture_prev->texture_rgb = tex0; texture_prev->rb_multisample = rb0;
@@ -583,7 +593,7 @@ static bool swapchain_present_is_partial_copy(struct wined3d_swapchain *swapchai static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT *src_rect, const RECT *dst_rect, unsigned int swap_interval, uint32_t flags) { - struct wined3d_texture *back_buffer = swapchain->back_buffers[0]; + struct wined3d_texture *back_buffer = swapchain->back_buffers[0].texture; const struct wined3d_pixel_format *pixel_format; const struct wined3d_gl_info *gl_info; struct wined3d_context_gl *context_gl; @@ -1040,7 +1050,7 @@ static void wined3d_swapchain_vk_set_swap_interval(struct wined3d_swapchain_vk * static VkResult wined3d_swapchain_vk_blit(struct wined3d_swapchain_vk *swapchain_vk, struct wined3d_context_vk *context_vk, const RECT *src_rect, const RECT *dst_rect, unsigned int swap_interval) { - struct wined3d_texture_vk *back_buffer_vk = wined3d_texture_vk(swapchain_vk->s.back_buffers[0]); + struct wined3d_texture_vk *back_buffer_vk = wined3d_texture_vk(swapchain_vk->s.back_buffers[0].texture); struct wined3d_device_vk *device_vk = wined3d_device_vk(swapchain_vk->s.device); const struct wined3d_swapchain_desc *desc = &swapchain_vk->s.state.desc; const struct wined3d_vk_info *vk_info = context_vk->vk_info; @@ -1168,11 +1178,13 @@ static VkResult wined3d_swapchain_vk_blit(struct wined3d_swapchain_vk *swapchain static void wined3d_swapchain_vk_rotate(struct wined3d_swapchain *swapchain, struct wined3d_context_vk *context_vk) { struct wined3d_texture_sub_resource *sub_resource; + struct wined3d_backbuffer *backbuffer, *backbuffer_prev; struct wined3d_texture_vk *texture, *texture_prev; struct wined3d_image_vk image0; VkDescriptorImageInfo vk_info0; VkImageLayout vk_layout0; uint32_t bind_mask0; + HRGN dirty_region0; DWORD locations0; unsigned int i;
@@ -1181,9 +1193,11 @@ static void wined3d_swapchain_vk_rotate(struct wined3d_swapchain *swapchain, str if (swapchain->state.desc.backbuffer_count < 2) return;
- texture_prev = wined3d_texture_vk(swapchain->back_buffers[0]); + backbuffer_prev = &swapchain->back_buffers[0]; + texture_prev = wined3d_texture_vk(backbuffer_prev->texture);
/* Back buffer 0 is already in the draw binding. */ + dirty_region0 = backbuffer_prev->dirty_region; image0 = texture_prev->image; vk_layout0 = texture_prev->layout; bind_mask0 = texture_prev->bind_mask; @@ -1192,12 +1206,14 @@ static void wined3d_swapchain_vk_rotate(struct wined3d_swapchain *swapchain, str
for (i = 1; i < swapchain->state.desc.backbuffer_count; ++i) { - texture = wined3d_texture_vk(swapchain->back_buffers[i]); + backbuffer = &swapchain->back_buffers[i]; + texture = wined3d_texture_vk(backbuffer->texture); sub_resource = &texture->t.sub_resources[0];
if (!(sub_resource->locations & supported_locations)) wined3d_texture_load_location(&texture->t, 0, &context_vk->c, texture->t.resource.draw_binding);
+ backbuffer_prev->dirty_region = backbuffer->dirty_region; texture_prev->image = texture->image; texture_prev->layout = texture->layout; texture_prev->bind_mask = texture->bind_mask; @@ -1206,9 +1222,11 @@ static void wined3d_swapchain_vk_rotate(struct wined3d_swapchain *swapchain, str wined3d_texture_validate_location(&texture_prev->t, 0, sub_resource->locations & supported_locations); wined3d_texture_invalidate_location(&texture_prev->t, 0, ~(sub_resource->locations & supported_locations));
+ backbuffer_prev = backbuffer; texture_prev = texture; }
+ backbuffer_prev->dirty_region = dirty_region0; texture_prev->image = image0; texture_prev->layout = vk_layout0; texture_prev->bind_mask = bind_mask0; @@ -1224,7 +1242,7 @@ static void swapchain_vk_present(struct wined3d_swapchain *swapchain, const RECT const RECT *dst_rect, unsigned int swap_interval, uint32_t flags) { struct wined3d_swapchain_vk *swapchain_vk = wined3d_swapchain_vk(swapchain); - struct wined3d_texture *back_buffer = swapchain->back_buffers[0]; + struct wined3d_texture *back_buffer = swapchain->back_buffers[0].texture; struct wined3d_context_vk *context_vk; VkResult vr; HRESULT hr; @@ -1324,7 +1342,7 @@ static void swapchain_gdi_present(struct wined3d_swapchain *swapchain, HDC dc;
front = &swapchain->front_buffer->dc_info[0]; - back = &swapchain->back_buffers[0]->dc_info[0]; + back = &swapchain->back_buffers[0].texture->dc_info[0];
/* Flip the surface data. */ dc = front->dc; @@ -1334,13 +1352,13 @@ static void swapchain_gdi_present(struct wined3d_swapchain *swapchain,
front->dc = back->dc; front->bitmap = back->bitmap; - swapchain->front_buffer->resource.heap_pointer = swapchain->back_buffers[0]->resource.heap_pointer; - swapchain->front_buffer->resource.heap_memory = swapchain->back_buffers[0]->resource.heap_memory; + swapchain->front_buffer->resource.heap_pointer = swapchain->back_buffers[0].texture->resource.heap_pointer; + swapchain->front_buffer->resource.heap_memory = swapchain->back_buffers[0].texture->resource.heap_memory;
back->dc = dc; back->bitmap = bitmap; - swapchain->back_buffers[0]->resource.heap_pointer = heap_pointer; - swapchain->back_buffers[0]->resource.heap_memory = heap_memory; + swapchain->back_buffers[0].texture->resource.heap_pointer = heap_pointer; + swapchain->back_buffers[0].texture->resource.heap_memory = heap_memory;
SetRect(&swapchain->front_buffer_update, 0, 0, swapchain->front_buffer->resource.width, @@ -1608,7 +1626,7 @@ static HRESULT wined3d_swapchain_init(struct wined3d_swapchain *swapchain, struc for (i = 0; i < swapchain->state.desc.backbuffer_count; ++i) { TRACE("Creating back buffer %u.\n", i); - if (FAILED(hr = swapchain_create_texture(swapchain, false, false, &swapchain->back_buffers[i]))) + if (FAILED(hr = swapchain_create_texture(swapchain, false, false, &swapchain->back_buffers[i].texture))) { WARN("Failed to create back buffer %u, hr %#lx.\n", i, hr); swapchain->state.desc.backbuffer_count = i; @@ -1666,11 +1684,12 @@ err: { for (i = 0; i < swapchain->state.desc.backbuffer_count; ++i) { - if (swapchain->back_buffers[i]) + if (swapchain->back_buffers[i].texture) { - wined3d_texture_set_swapchain(swapchain->back_buffers[i], NULL); - wined3d_texture_decref(swapchain->back_buffers[i]); + wined3d_texture_set_swapchain(swapchain->back_buffers[i].texture, NULL); + wined3d_texture_decref(swapchain->back_buffers[i].texture); } + // No Present possible, no need to check and free dirty HRGN } free(swapchain->back_buffers); } @@ -1827,7 +1846,7 @@ void swapchain_update_draw_bindings(struct wined3d_swapchain *swapchain)
for (i = 0; i < swapchain->state.desc.backbuffer_count; ++i) { - wined3d_resource_update_draw_binding(&swapchain->back_buffers[i]->resource); + wined3d_resource_update_draw_binding(&swapchain->back_buffers[i].texture->resource); } }
@@ -2019,12 +2038,18 @@ HRESULT CDECL wined3d_swapchain_resize_buffers(struct wined3d_swapchain *swapcha
for (i = 0; i < desc->backbuffer_count; ++i) { + struct wined3d_backbuffer *backbuffer = &swapchain->back_buffers[i]; if (FAILED(hr = swapchain_create_texture(swapchain, false, false, &new_texture))) return hr; - wined3d_texture_set_swapchain(swapchain->back_buffers[i], NULL); - if (wined3d_texture_decref(swapchain->back_buffers[i])) - ERR("Something's still holding back buffer %u (%p).\n", i, swapchain->back_buffers[i]); - swapchain->back_buffers[i] = new_texture; + wined3d_texture_set_swapchain(backbuffer->texture, NULL); + if (wined3d_texture_decref(backbuffer->texture)) + ERR("Something's still holding back buffer %u (%p).\n", i, backbuffer->texture); + backbuffer->texture = new_texture; + if (backbuffer->dirty_region) + { + DeleteObject(backbuffer->dirty_region); + backbuffer->dirty_region = NULL; + } } }
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index deb4304c282..715e883020a 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -128,7 +128,7 @@ GLenum wined3d_texture_get_gl_buffer(const struct wined3d_texture *texture) return GL_FRONT; }
- if (texture == swapchain->back_buffers[0]) + if (texture == swapchain->back_buffers[0].texture) { TRACE("Returning GL_BACK.\n"); return GL_BACK; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 7b2ef0d4b7f..7bcd37651de 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4080,6 +4080,12 @@ struct wined3d_swapchain_ops void (*swapchain_frontbuffer_updated)(struct wined3d_swapchain *swapchain); };
+struct wined3d_backbuffer +{ + struct wined3d_texture *texture; + HRGN dirty_region; +}; + struct wined3d_swapchain { LONG ref; @@ -4088,7 +4094,7 @@ struct wined3d_swapchain const struct wined3d_swapchain_ops *swapchain_ops; struct wined3d_device *device;
- struct wined3d_texture **back_buffers; + struct wined3d_backbuffer *back_buffers; struct wined3d_texture *front_buffer; struct wined3d_gamma_ramp orig_gamma; bool reapply_mode;