[PATCH 10/10] wined3d: Move FBO based color blits from IWineD3DSurfaceImpl_BltOverride() to wined3d_surface_blt().
Henri Verbeet
hverbeet at codeweavers.com
Sun Aug 21 14:35:00 CDT 2011
---
dlls/wined3d/surface.c | 293 +++++++++++++++++++++++-------------------------
1 files changed, 140 insertions(+), 153 deletions(-)
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 62828e5..2fc08d8 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -1171,6 +1171,127 @@ static void wined3d_surface_depth_blt_fbo(struct wined3d_device *device, struct
context_release(context);
}
+/* Blit between surface locations. Onscreen on different swapchains is not supported.
+ * Depth / stencil is not supported. */
+static void surface_blt_fbo(struct wined3d_device *device, const WINED3DTEXTUREFILTERTYPE filter,
+ struct wined3d_surface *src_surface, DWORD src_location, const RECT *src_rect_in,
+ struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect_in)
+{
+ const struct wined3d_gl_info *gl_info;
+ struct wined3d_context *context;
+ RECT src_rect, dst_rect;
+ GLenum gl_filter;
+ GLenum buffer;
+
+ TRACE("device %p, filter %s,\n", device, debug_d3dtexturefiltertype(filter));
+ TRACE("src_surface %p, src_location %s, src_rect %s,\n",
+ src_surface, debug_surflocation(src_location), wine_dbgstr_rect(src_rect_in));
+ TRACE("dst_surface %p, dst_location %s, dst_rect %s.\n",
+ dst_surface, debug_surflocation(dst_location), wine_dbgstr_rect(dst_rect_in));
+
+ src_rect = *src_rect_in;
+ dst_rect = *dst_rect_in;
+
+ switch (filter)
+ {
+ case WINED3DTEXF_LINEAR:
+ gl_filter = GL_LINEAR;
+ break;
+
+ default:
+ FIXME("Unsupported filter mode %s (%#x).\n", debug_d3dtexturefiltertype(filter), filter);
+ case WINED3DTEXF_NONE:
+ case WINED3DTEXF_POINT:
+ gl_filter = GL_NEAREST;
+ break;
+ }
+
+ if (src_location == SFLAG_INDRAWABLE && surface_is_offscreen(src_surface))
+ src_location = SFLAG_INTEXTURE;
+ if (dst_location == SFLAG_INDRAWABLE && surface_is_offscreen(dst_surface))
+ dst_location = SFLAG_INTEXTURE;
+
+ /* Make sure the locations are up-to-date. Loading the destination
+ * surface isn't required if the entire surface is overwritten. (And is
+ * in fact harmful if we're being called by surface_load_location() with
+ * the purpose of loading the destination surface.) */
+ surface_load_location(src_surface, src_location, NULL);
+ if (!surface_is_full_rect(dst_surface, &dst_rect))
+ surface_load_location(dst_surface, dst_location, NULL);
+
+ if (src_location == SFLAG_INDRAWABLE) context = context_acquire(device, src_surface);
+ else if (dst_location == SFLAG_INDRAWABLE) context = context_acquire(device, dst_surface);
+ else context = context_acquire(device, NULL);
+
+ if (!context->valid)
+ {
+ context_release(context);
+ WARN("Invalid context, skipping blit.\n");
+ return;
+ }
+
+ gl_info = context->gl_info;
+
+ if (src_location == SFLAG_INDRAWABLE)
+ {
+ TRACE("Source surface %p is onscreen.\n", src_surface);
+ buffer = surface_get_gl_buffer(src_surface);
+ surface_translate_drawable_coords(src_surface, context->win_handle, &src_rect);
+ }
+ else
+ {
+ TRACE("Source surface %p is offscreen.\n", src_surface);
+ buffer = GL_COLOR_ATTACHMENT0;
+ }
+
+ ENTER_GL();
+ context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, src_surface, NULL, src_location);
+ glReadBuffer(buffer);
+ checkGLcall("glReadBuffer()");
+ context_check_fbo_status(context, GL_READ_FRAMEBUFFER);
+ LEAVE_GL();
+
+ if (dst_location == SFLAG_INDRAWABLE)
+ {
+ TRACE("Destination surface %p is onscreen.\n", dst_surface);
+ buffer = surface_get_gl_buffer(dst_surface);
+ surface_translate_drawable_coords(dst_surface, context->win_handle, &dst_rect);
+ }
+ else
+ {
+ TRACE("Destination surface %p is offscreen.\n", dst_surface);
+ buffer = GL_COLOR_ATTACHMENT0;
+ }
+
+ ENTER_GL();
+ context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, dst_surface, NULL, dst_location);
+ context_set_draw_buffer(context, buffer);
+ context_check_fbo_status(context, GL_DRAW_FRAMEBUFFER);
+ context_invalidate_state(context, STATE_FRAMEBUFFER);
+
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ context_invalidate_state(context, STATE_RENDER(WINED3DRS_COLORWRITEENABLE));
+ context_invalidate_state(context, STATE_RENDER(WINED3DRS_COLORWRITEENABLE1));
+ context_invalidate_state(context, STATE_RENDER(WINED3DRS_COLORWRITEENABLE2));
+ context_invalidate_state(context, STATE_RENDER(WINED3DRS_COLORWRITEENABLE3));
+
+ glDisable(GL_SCISSOR_TEST);
+ context_invalidate_state(context, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
+
+ gl_info->fbo_ops.glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom,
+ dst_rect.left, dst_rect.top, dst_rect.right, dst_rect.bottom, GL_COLOR_BUFFER_BIT, gl_filter);
+ checkGLcall("glBlitFramebuffer()");
+
+ LEAVE_GL();
+
+ if (wined3d_settings.strict_draw_ordering
+ || (dst_location == SFLAG_INDRAWABLE
+ && dst_surface->container.u.swapchain->front_buffer == dst_surface))
+ wglFlush();
+
+ context_release(context);
+}
+
static BOOL fbo_blit_supported(const struct wined3d_gl_info *gl_info, enum wined3d_blit_op blit_op,
const RECT *src_rect, DWORD src_usage, WINED3DPOOL src_pool, const struct wined3d_format *src_format,
const RECT *dst_rect, DWORD dst_usage, WINED3DPOOL dst_pool, const struct wined3d_format *dst_format)
@@ -1545,6 +1666,23 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC
if (SUCCEEDED(surface_color_fill(dst_surface, &dst_rect, &color)))
return WINED3D_OK;
}
+ else
+ {
+ TRACE("Color blit.\n");
+
+ if (fbo_blit_supported(&device->adapter->gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
+ &src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format,
+ &dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format))
+ {
+ TRACE("Using FBO blit.\n");
+
+ surface_blt_fbo(device, filter,
+ src_surface, SFLAG_INDRAWABLE, &src_rect,
+ dst_surface, SFLAG_INDRAWABLE, &dst_rect);
+ surface_modify_location(dst_surface, SFLAG_INDRAWABLE, TRUE);
+ return WINED3D_OK;
+ }
+ }
}
fallback:
@@ -5045,127 +5183,6 @@ void surface_translate_drawable_coords(const struct wined3d_surface *surface, HW
rect->bottom = drawable_height - rect->bottom;
}
-/* blit between surface locations. onscreen on different swapchains is not supported.
- * depth / stencil is not supported. */
-static void surface_blt_fbo(struct wined3d_device *device, const WINED3DTEXTUREFILTERTYPE filter,
- struct wined3d_surface *src_surface, DWORD src_location, const RECT *src_rect_in,
- struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect_in)
-{
- const struct wined3d_gl_info *gl_info;
- struct wined3d_context *context;
- RECT src_rect, dst_rect;
- GLenum gl_filter;
- GLenum buffer;
-
- TRACE("device %p, filter %s,\n", device, debug_d3dtexturefiltertype(filter));
- TRACE("src_surface %p, src_location %s, src_rect %s,\n",
- src_surface, debug_surflocation(src_location), wine_dbgstr_rect(src_rect_in));
- TRACE("dst_surface %p, dst_location %s, dst_rect %s.\n",
- dst_surface, debug_surflocation(dst_location), wine_dbgstr_rect(dst_rect_in));
-
- src_rect = *src_rect_in;
- dst_rect = *dst_rect_in;
-
- switch (filter)
- {
- case WINED3DTEXF_LINEAR:
- gl_filter = GL_LINEAR;
- break;
-
- default:
- FIXME("Unsupported filter mode %s (%#x).\n", debug_d3dtexturefiltertype(filter), filter);
- case WINED3DTEXF_NONE:
- case WINED3DTEXF_POINT:
- gl_filter = GL_NEAREST;
- break;
- }
-
- if (src_location == SFLAG_INDRAWABLE && surface_is_offscreen(src_surface))
- src_location = SFLAG_INTEXTURE;
- if (dst_location == SFLAG_INDRAWABLE && surface_is_offscreen(dst_surface))
- dst_location = SFLAG_INTEXTURE;
-
- /* Make sure the locations are up-to-date. Loading the destination
- * surface isn't required if the entire surface is overwritten. (And is
- * in fact harmful if we're being called by surface_load_location() with
- * the purpose of loading the destination surface.) */
- surface_load_location(src_surface, src_location, NULL);
- if (!surface_is_full_rect(dst_surface, &dst_rect))
- surface_load_location(dst_surface, dst_location, NULL);
-
- if (src_location == SFLAG_INDRAWABLE) context = context_acquire(device, src_surface);
- else if (dst_location == SFLAG_INDRAWABLE) context = context_acquire(device, dst_surface);
- else context = context_acquire(device, NULL);
-
- if (!context->valid)
- {
- context_release(context);
- WARN("Invalid context, skipping blit.\n");
- return;
- }
-
- gl_info = context->gl_info;
-
- if (src_location == SFLAG_INDRAWABLE)
- {
- TRACE("Source surface %p is onscreen.\n", src_surface);
- buffer = surface_get_gl_buffer(src_surface);
- surface_translate_drawable_coords(src_surface, context->win_handle, &src_rect);
- }
- else
- {
- TRACE("Source surface %p is offscreen.\n", src_surface);
- buffer = GL_COLOR_ATTACHMENT0;
- }
-
- ENTER_GL();
- context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, src_surface, NULL, src_location);
- glReadBuffer(buffer);
- checkGLcall("glReadBuffer()");
- context_check_fbo_status(context, GL_READ_FRAMEBUFFER);
- LEAVE_GL();
-
- if (dst_location == SFLAG_INDRAWABLE)
- {
- TRACE("Destination surface %p is onscreen.\n", dst_surface);
- buffer = surface_get_gl_buffer(dst_surface);
- surface_translate_drawable_coords(dst_surface, context->win_handle, &dst_rect);
- }
- else
- {
- TRACE("Destination surface %p is offscreen.\n", dst_surface);
- buffer = GL_COLOR_ATTACHMENT0;
- }
-
- ENTER_GL();
- context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, dst_surface, NULL, dst_location);
- context_set_draw_buffer(context, buffer);
- context_check_fbo_status(context, GL_DRAW_FRAMEBUFFER);
- context_invalidate_state(context, STATE_FRAMEBUFFER);
-
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- context_invalidate_state(context, STATE_RENDER(WINED3DRS_COLORWRITEENABLE));
- context_invalidate_state(context, STATE_RENDER(WINED3DRS_COLORWRITEENABLE1));
- context_invalidate_state(context, STATE_RENDER(WINED3DRS_COLORWRITEENABLE2));
- context_invalidate_state(context, STATE_RENDER(WINED3DRS_COLORWRITEENABLE3));
-
- glDisable(GL_SCISSOR_TEST);
- context_invalidate_state(context, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
-
- gl_info->fbo_ops.glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom,
- dst_rect.left, dst_rect.top, dst_rect.right, dst_rect.bottom, GL_COLOR_BUFFER_BIT, gl_filter);
- checkGLcall("glBlitFramebuffer()");
-
- LEAVE_GL();
-
- if (wined3d_settings.strict_draw_ordering
- || (dst_location == SFLAG_INDRAWABLE
- && dst_surface->container.u.swapchain->front_buffer == dst_surface))
- wglFlush();
-
- context_release(context);
-}
-
static void surface_blt_to_drawable(struct wined3d_device *device,
WINED3DTEXTUREFILTERTYPE filter, BOOL color_key,
struct wined3d_surface *src_surface, const RECT *src_rect_in,
@@ -5455,21 +5472,8 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(struct wined3d_surface *dst_surfa
* than the frame buffer, draw an upside down scaled image onto the fb, read it back and restore the
* back buffer. This is slower than reading line per line, thus not used for flipping
* -> If the app wants a scaled image with a dest rect that is bigger than the fb, it has to be copied
- * pixel by pixel
- *
- * If EXT_framebuffer_blit is supported that can be used instead. Note that EXT_framebuffer_blit implies
- * FBO support, so it doesn't really make sense to try and make it work with different offscreen rendering
- * backends. */
- if (fbo_blit_supported(gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
- src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format,
- dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format))
- {
- surface_blt_fbo(device, Filter,
- src_surface, SFLAG_INDRAWABLE, src_rect,
- dst_surface, SFLAG_INDRAWABLE, dst_rect);
- surface_modify_location(dst_surface, SFLAG_INDRAWABLE, TRUE);
- }
- else if (!stretchx || dst_rect->right - dst_rect->left > src_surface->resource.width
+ * pixel by pixel. */
+ if (!stretchx || dst_rect->right - dst_rect->left > src_surface->resource.width
|| dst_rect->bottom - dst_rect->top > src_surface->resource.height)
{
TRACE("No stretching in x direction, using direct framebuffer -> texture copy\n");
@@ -5501,23 +5505,6 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(struct wined3d_surface *dst_surfa
TRACE("Blt from surface %p to rendertarget %p\n", src_surface, dst_surface);
if (!(flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE))
- && fbo_blit_supported(gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
- src_rect, src_surface->resource.usage, src_surface->resource.pool,
- src_surface->resource.format,
- dst_rect, dst_surface->resource.usage, dst_surface->resource.pool,
- dst_surface->resource.format))
- {
- TRACE("Using surface_blt_fbo.\n");
- /* The source is always a texture, but never the currently active render target, and the texture
- * contents are never upside down. */
- surface_blt_fbo(device, Filter,
- src_surface, SFLAG_INDRAWABLE, src_rect,
- dst_surface, SFLAG_INDRAWABLE, dst_rect);
- surface_modify_location(dst_surface, SFLAG_INDRAWABLE, TRUE);
- return WINED3D_OK;
- }
-
- if (!(flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE))
&& arbfp_blit.blit_supported(gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
src_rect, src_surface->resource.usage, src_surface->resource.pool,
src_surface->resource.format,
--
1.7.3.4
More information about the wine-patches
mailing list