Module: wine Branch: master Commit: 3bfecd58d282ac50463f659e427a2d3d86d12334 URL: http://source.winehq.org/git/wine.git/?a=commit;h=3bfecd58d282ac50463f659e42...
Author: Henri Verbeet hverbeet@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;