Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/wined3d/surface.c | 71 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 26 deletions(-)
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 6e80f85773cc..72bf9d32ff8f 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -1402,21 +1402,21 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_texture *sr }
static void read_from_framebuffer(struct wined3d_surface *surface, - struct wined3d_context *old_ctx, DWORD dst_location) + struct wined3d_context *old_ctx, DWORD src_location, DWORD dst_location) { unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface); struct wined3d_texture *texture = surface->container; struct wined3d_device *device = texture->resource.device; - const struct wined3d_gl_info *gl_info; struct wined3d_context *context = old_ctx; struct wined3d_surface *restore_rt = NULL; + const struct wined3d_gl_info *gl_info; unsigned int row_pitch, slice_pitch; + struct wined3d_bo_address data; unsigned int width, height; - BYTE *mem; BYTE *row, *top, *bottom; - int i; - BOOL srcIsUpsideDown; - struct wined3d_bo_address data; + BOOL src_is_upside_down; + unsigned int i; + BYTE *mem;
wined3d_texture_get_memory(texture, sub_resource_idx, &data, dst_location);
@@ -1425,21 +1425,30 @@ static void read_from_framebuffer(struct wined3d_surface *surface, context = context_acquire(device, texture, sub_resource_idx); else restore_rt = NULL; - - context_apply_blit_state(context, device); gl_info = context->gl_info;
+ if (src_location != texture->resource.draw_binding) + { + context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, surface, NULL, src_location); + context_check_fbo_status(context, GL_READ_FRAMEBUFFER); + context_invalidate_state(context, STATE_FRAMEBUFFER); + } + else + { + context_apply_blit_state(context, device); + } + /* Select the correct read buffer, and give some debug output. - * There is no need to keep track of the current read buffer or reset it, every part of the code - * that reads sets the read buffer as desired. + * There is no need to keep track of the current read buffer or reset it, + * every part of the code that reads sets the read buffer as desired. */ - if (wined3d_resource_is_offscreen(&texture->resource)) + if (src_location != WINED3D_LOCATION_DRAWABLE || wined3d_resource_is_offscreen(&texture->resource)) { /* Mapping the primary render target which is not on a swapchain. * Read from the back buffer. */ TRACE("Mapping offscreen render target.\n"); gl_info->gl_ops.gl.p_glReadBuffer(context_get_offscreen_gl_buffer(context)); - srcIsUpsideDown = TRUE; + src_is_upside_down = TRUE; } else { @@ -1447,9 +1456,9 @@ static void read_from_framebuffer(struct wined3d_surface *surface, GLenum buffer = wined3d_texture_get_gl_buffer(texture); TRACE("Mapping %#x buffer.\n", buffer); gl_info->gl_ops.gl.p_glReadBuffer(buffer); - checkGLcall("glReadBuffer"); - srcIsUpsideDown = FALSE; + src_is_upside_down = FALSE; } + checkGLcall("glReadBuffer");
if (data.buffer_object) { @@ -1474,7 +1483,7 @@ static void read_from_framebuffer(struct wined3d_surface *surface, gl_info->gl_ops.gl.p_glPixelStorei(GL_PACK_ROW_LENGTH, 0); checkGLcall("glPixelStorei");
- if (!srcIsUpsideDown) + if (!src_is_upside_down) { /* glReadPixels returns the image upside down, and there is no way to * prevent this. Flip the lines in software. */ @@ -2134,24 +2143,34 @@ static BOOL surface_load_sysmem(struct wined3d_surface *surface, sub_resource = &texture->sub_resources[sub_resource_idx]; wined3d_texture_prepare_location(texture, sub_resource_idx, context, dst_location);
- if (sub_resource->locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED)) - wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB); - - /* Download the surface to system memory. */ - if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) + /* We cannot download data from multisample textures directly. */ + if (is_multisample_location(texture, WINED3D_LOCATION_TEXTURE_RGB)) { - wined3d_texture_bind_and_dirtify(texture, context, - !(sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB)); - surface_download_data(surface, gl_info, dst_location); - ++texture->download_count; - + wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_RB_RESOLVED); + read_from_framebuffer(surface, context, WINED3D_LOCATION_RB_RESOLVED, dst_location); return TRUE; } + else + { + if (sub_resource->locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED)) + wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB); + + /* Download the surface to system memory. */ + if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) + { + wined3d_texture_bind_and_dirtify(texture, context, + !(sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB)); + surface_download_data(surface, gl_info, dst_location); + ++texture->download_count; + + return TRUE; + } + }
if (!(texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL) && (sub_resource->locations & WINED3D_LOCATION_DRAWABLE)) { - read_from_framebuffer(surface, context, dst_location); + read_from_framebuffer(surface, context, texture->resource.draw_binding, dst_location); return TRUE; }