Module: wine
Branch: master
Commit: 3bfecd58d282ac50463f659e427a2d3d86d12334
URL: http://source.winehq.org/git/wine.git/?a=commit;h=3bfecd58d282ac50463f659e4…
Author: Henri Verbeet <hverbeet(a)codeweavers.com>
Date: Thu Nov 3 19:37:24 2011 +0100
wined3d: Avoid a drawable -> texture transfer through sysmem in arbfp_blit_surface() with backbuffer ORM.
---
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;