From a90132c381702bd5ab4feea5df55c9aae5b70f38 Mon Sep 17 00:00:00 2001
From: Andrew Wesie <awesie@gmail.com>
Date: Sun, 30 Sep 2018 12:02:00 -0500
Subject: [PATCH] wined3d: Use glReadPixels for RT texture download.

Signed-off-by: Andrew Wesie <awesie@gmail.com>
---
 dlls/wined3d/texture.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index fcab1d5d773..7e2dccd280a 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -2456,6 +2456,7 @@ static void wined3d_texture_gl_download_data(struct wined3d_context *context,
     struct wined3d_bo_gl *dst_bo;
     BOOL srgb = FALSE;
     GLenum target;
+    struct wined3d_texture_sub_resource *sub_resource;
 
     TRACE("context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_box %s, dst_bo_addr %s, "
             "dst_format %s, dst_x %u, dst_y %u, dst_z %u, dst_row_pitch %u, dst_slice_pitch %u.\n",
@@ -2510,6 +2511,7 @@ static void wined3d_texture_gl_download_data(struct wined3d_context *context,
 
     format_gl = wined3d_format_gl(src_texture->resource.format);
     target = wined3d_texture_gl_get_sub_resource_target(src_texture_gl, src_sub_resource_idx);
+    sub_resource = &src_texture->sub_resources[src_sub_resource_idx];
 
     if ((src_texture->resource.type == WINED3D_RTYPE_TEXTURE_2D
             && (target == GL_TEXTURE_2D_ARRAY || format_gl->f.conv_byte_count
@@ -2542,6 +2544,23 @@ static void wined3d_texture_gl_download_data(struct wined3d_context *context,
         GL_EXTCALL(glGetCompressedTexImage(target, src_level, dst_bo_addr->addr));
         checkGLcall("glGetCompressedTexImage");
     }
+    else if (dst_bo_addr->buffer_object && src_texture->resource.bind_flags & WINED3D_BIND_RENDER_TARGET)
+    {
+        /* PBO texture download is not accelerated on Mesa. Use glReadPixels if possible. */
+        TRACE("Downloading (glReadPixels) texture %p, %u, level %u, format %#x, type %#x, data %p.\n",
+                src_texture, src_sub_resource_idx, src_level, format_gl->format, format_gl->type, dst_bo_addr->addr);
+
+        wined3d_context_gl_apply_fbo_state_blit(context_gl, GL_READ_FRAMEBUFFER, &src_texture->resource, src_sub_resource_idx, NULL,
+                0, sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB));
+        wined3d_context_gl_check_fbo_status(context_gl, GL_READ_FRAMEBUFFER);
+        context_invalidate_state(context, STATE_FRAMEBUFFER);
+        gl_info->gl_ops.gl.p_glReadBuffer(GL_COLOR_ATTACHMENT0);
+        checkGLcall("glReadBuffer()");
+
+        gl_info->gl_ops.gl.p_glReadPixels(0, 0, wined3d_texture_get_level_width(src_texture, src_level),
+                wined3d_texture_get_level_height(src_texture, src_level), format_gl->format, format_gl->type, dst_bo_addr->addr);
+        checkGLcall("glReadPixels");
+    }
     else
     {
         TRACE("Downloading texture %p, %u, level %u, format %#x, type %#x, data %p.\n",
-- 
2.26.1

