[PATCH 1/7] wined3d: Avoid a drawable -> texture transfer through sysmem in arbfp_blit_surface() with backbuffer ORM.

Henri Verbeet hverbeet at codeweavers.com
Thu Nov 3 13:37:24 CDT 2011


---
 dlls/wined3d/arb_program_shader.c |   21 ++++++++++++++++++---
 dlls/wined3d/surface.c            |   26 +++++++++-----------------
 dlls/wined3d/wined3d_private.h    |    1 +
 3 files changed, 28 insertions(+), 20 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 8fd0714..1573c17 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -7270,14 +7270,29 @@ static BOOL arbfp_blit_supported(const struct wined3d_gl_info *gl_info, enum win
 }
 
 HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter,
-        struct wined3d_surface *src_surface, const RECT *src_rect,
+        struct wined3d_surface *src_surface, const RECT *src_rect_in,
         struct wined3d_surface *dst_surface, const RECT *dst_rect_in)
 {
     struct wined3d_context *context;
+    RECT src_rect = *src_rect_in;
     RECT dst_rect = *dst_rect_in;
 
     /* Now load the surface */
-    surface_internal_preload(src_surface, SRGB_RGB);
+    if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
+            && (src_surface->flags & (SFLAG_INTEXTURE | SFLAG_INDRAWABLE)) == SFLAG_INDRAWABLE)
+    {
+        /* Without FBO blits transfering from the drawable to the texture is
+         * expensive, because we have to flip the data in sysmem. Since we can
+         * flip in the blitter, we don't actually need that flip anyway. So we
+         * use the surface's texture as scratch texture, and flip the source
+         * rectangle instead. */
+        surface_load_fb_texture(src_surface, FALSE);
+
+        src_rect.top = src_surface->resource.height - src_rect.top;
+        src_rect.bottom = src_surface->resource.height - src_rect.bottom;
+    }
+    else
+        surface_internal_preload(src_surface, SRGB_RGB);
 
     /* Activate the destination context, set it up for blitting */
     context = context_acquire(device, dst_surface);
@@ -7291,7 +7306,7 @@ HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter,
     ENTER_GL();
 
     /* Draw a textured quad */
-    draw_textured_quad(src_surface, context, src_rect, &dst_rect, filter);
+    draw_textured_quad(src_surface, context, &src_rect, &dst_rect, filter);
 
     LEAVE_GL();
 
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index f75593d..6713f98 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -4310,25 +4310,14 @@ static void read_from_framebuffer(struct wined3d_surface *surface, const RECT *r
     }
 }
 
-/* Read the framebuffer contents into a texture */
-static void read_from_framebuffer_texture(struct wined3d_surface *surface, BOOL srgb)
+/* Read the framebuffer contents into a texture. Note that this function
+ * doesn't do any kind of flipping. Using this on an onscreen surface will
+ * result in a flipped D3D texture. */
+void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb)
 {
     struct wined3d_device *device = surface->resource.device;
     struct wined3d_context *context;
 
-    if (!surface_is_offscreen(surface))
-    {
-        /* We would need to flip onscreen surfaces, but there's no efficient
-         * way to do that here. It makes more sense for the caller to
-         * explicitly go through sysmem. */
-        ERR("Not supported for onscreen targets.\n");
-        return;
-    }
-
-    /* Activate the surface to read from. In some situations it isn't the currently active target(e.g. backbuffer
-     * locking during offscreen rendering). RESOURCELOAD is ok because glCopyTexSubImage2D isn't affected by any
-     * states in the stateblock, and no driver was found yet that had bugs in that regard.
-     */
     context = context_acquire(device, surface);
     device_invalidate_state(device, STATE_FRAMEBUFFER);
 
@@ -4339,7 +4328,10 @@ static void read_from_framebuffer_texture(struct wined3d_surface *surface, BOOL
 
     ENTER_GL();
 
-    glReadBuffer(device->offscreenBuffer);
+    if (surface_is_offscreen(surface))
+        glReadBuffer(device->offscreenBuffer);
+    else
+        glReadBuffer(surface_get_gl_buffer(surface));
     checkGLcall("glReadBuffer");
 
     glCopyTexSubImage2D(surface->texture_target, surface->texture_level,
@@ -6037,7 +6029,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
             && surface_is_offscreen(surface)
             && (surface->flags & SFLAG_INDRAWABLE))
     {
-        read_from_framebuffer_texture(surface, srgb);
+        surface_load_fb_texture(surface, srgb);
 
         return WINED3D_OK;
     }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 90a70b4..4adfa83 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2088,6 +2088,7 @@ BOOL surface_is_offscreen(const struct wined3d_surface *surface) DECLSPEC_HIDDEN
 HRESULT surface_load(struct wined3d_surface *surface, BOOL srgb) DECLSPEC_HIDDEN;
 void surface_load_ds_location(struct wined3d_surface *surface,
         struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN;
+void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb) DECLSPEC_HIDDEN;
 HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location, const RECT *rect) DECLSPEC_HIDDEN;
 void surface_modify_ds_location(struct wined3d_surface *surface, DWORD location, UINT w, UINT h) DECLSPEC_HIDDEN;
 void surface_modify_location(struct wined3d_surface *surface, DWORD location, BOOL persistent) DECLSPEC_HIDDEN;
-- 
1.7.3.4




More information about the wine-patches mailing list