[PATCH 2/4] wined3d: Merge strect_rect_fbo() and surface_load_srgb_fbo().
Henri Verbeet
hverbeet at codeweavers.com
Mon Jul 26 05:06:33 CDT 2010
---
dlls/wined3d/device.c | 132 ---------------------------
dlls/wined3d/surface.c | 196 +++++++++++++++++++++++++++++++---------
dlls/wined3d/wined3d_private.h | 4 -
3 files changed, 155 insertions(+), 177 deletions(-)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index cd2ad97..d59a5e7 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -5743,138 +5743,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice
}
}
-static BOOL surface_is_full_rect(IWineD3DSurfaceImpl *surface, const RECT *r)
-{
- if ((r->left && r->right) || abs(r->right - r->left) != surface->currentDesc.Width)
- return FALSE;
- if ((r->top && r->bottom) || abs(r->bottom - r->top) != surface->currentDesc.Height)
- return FALSE;
- return TRUE;
-}
-
-void stretch_rect_fbo(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *src_surface, const RECT *src_rect_in,
- IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect_in, const WINED3DTEXTUREFILTERTYPE filter)
-{
- GLbitfield mask = GL_COLOR_BUFFER_BIT; /* TODO: Support blitting depth/stencil surfaces */
- const struct wined3d_gl_info *gl_info;
- struct wined3d_context *context;
- GLenum gl_filter;
- RECT src_rect, dst_rect;
-
- TRACE("device %p, src_surface %p, src_rect_in %s, dst_surface %p, dst_rect_in %s, filter %s (0x%08x).\n",
- device, src_surface, wine_dbgstr_rect(src_rect_in), dst_surface,
- wine_dbgstr_rect(dst_rect_in), debug_d3dtexturefiltertype(filter), filter);
-
- 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 (0x%08x)\n", debug_d3dtexturefiltertype(filter), filter);
- case WINED3DTEXF_NONE:
- case WINED3DTEXF_POINT:
- gl_filter = GL_NEAREST;
- break;
- }
-
- /* Make sure the drawables 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, SFLAG_INDRAWABLE, NULL);
- if (!surface_is_full_rect(dst_surface, &dst_rect))
- surface_load_location(dst_surface, SFLAG_INDRAWABLE, NULL);
-
- if (!surface_is_offscreen(src_surface)) context = context_acquire(device, src_surface);
- else if (!surface_is_offscreen(dst_surface)) 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 (!surface_is_offscreen(src_surface))
- {
- GLenum buffer = surface_get_gl_buffer(src_surface);
-
- TRACE("Source surface %p is onscreen\n", src_surface);
-
- if (buffer == GL_FRONT)
- surface_translate_frontbuffer_coords(src_surface, context->win_handle, &src_rect);
-
- src_rect.top = src_surface->currentDesc.Height - src_rect.top;
- src_rect.bottom = src_surface->currentDesc.Height - src_rect.bottom;
-
- ENTER_GL();
- context_bind_fbo(context, GL_READ_FRAMEBUFFER, NULL);
- glReadBuffer(buffer);
- checkGLcall("glReadBuffer()");
- } else {
- TRACE("Source surface %p is offscreen\n", src_surface);
- ENTER_GL();
- context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, src_surface, NULL, SFLAG_INTEXTURE);
- glReadBuffer(GL_COLOR_ATTACHMENT0);
- checkGLcall("glReadBuffer()");
- }
- LEAVE_GL();
-
- /* Attach dst surface to dst fbo */
- if (!surface_is_offscreen(dst_surface))
- {
- GLenum buffer = surface_get_gl_buffer(dst_surface);
-
- TRACE("Destination surface %p is onscreen\n", dst_surface);
-
- if (buffer == GL_FRONT)
- surface_translate_frontbuffer_coords(dst_surface, context->win_handle, &dst_rect);
-
- dst_rect.top = dst_surface->currentDesc.Height - dst_rect.top;
- dst_rect.bottom = dst_surface->currentDesc.Height - dst_rect.bottom;
-
- ENTER_GL();
- context_bind_fbo(context, GL_DRAW_FRAMEBUFFER, NULL);
- context_set_draw_buffer(context, buffer);
- }
- else
- {
- TRACE("Destination surface %p is offscreen\n", dst_surface);
-
- ENTER_GL();
- context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, dst_surface, NULL, SFLAG_INTEXTURE);
- context_set_draw_buffer(context, GL_COLOR_ATTACHMENT0);
- }
-
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE));
- IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE1));
- IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE2));
- IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE3));
-
- glDisable(GL_SCISSOR_TEST);
- IWineD3DDeviceImpl_MarkStateDirty(device, 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, mask, gl_filter);
- checkGLcall("glBlitFramebuffer()");
-
- LEAVE_GL();
-
- if (wined3d_settings.strict_draw_ordering) wglFlush(); /* Flush to ensure ordering across contexts. */
-
- context_release(context);
-
- surface_modify_location(dst_surface, SFLAG_INDRAWABLE, TRUE);
-}
-
static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget,
BOOL set_viewport) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 995d00c..662cdb8 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -3218,6 +3218,147 @@ void surface_translate_frontbuffer_coords(IWineD3DSurfaceImpl *surface, HWND win
OffsetRect(rect, offset.x, offset.y);
}
+static BOOL surface_is_full_rect(IWineD3DSurfaceImpl *surface, const RECT *r)
+{
+ if ((r->left && r->right) || abs(r->right - r->left) != surface->currentDesc.Width)
+ return FALSE;
+ if ((r->top && r->bottom) || abs(r->bottom - r->top) != surface->currentDesc.Height)
+ return FALSE;
+ return TRUE;
+}
+
+/* blit between surface locations. onscreen on different swapchains is not supported.
+ * depth / stencil is not supported. */
+static void surface_blt_fbo(IWineD3DDeviceImpl *device, const WINED3DTEXTUREFILTERTYPE filter,
+ IWineD3DSurfaceImpl *src_surface, DWORD src_location, const RECT *src_rect_in,
+ IWineD3DSurfaceImpl *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;
+
+ 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)
+ {
+ GLenum buffer = surface_get_gl_buffer(src_surface);
+
+ TRACE("Source surface %p is onscreen.\n", src_surface);
+
+ if (buffer == GL_FRONT)
+ surface_translate_frontbuffer_coords(src_surface, context->win_handle, &src_rect);
+
+ src_rect.top = src_surface->currentDesc.Height - src_rect.top;
+ src_rect.bottom = src_surface->currentDesc.Height - src_rect.bottom;
+
+ ENTER_GL();
+ context_bind_fbo(context, GL_READ_FRAMEBUFFER, NULL);
+ glReadBuffer(buffer);
+ checkGLcall("glReadBuffer()");
+ }
+ else
+ {
+ TRACE("Source surface %p is offscreen.\n", src_surface);
+ ENTER_GL();
+ context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, src_surface, NULL, src_location);
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+ checkGLcall("glReadBuffer()");
+ }
+ LEAVE_GL();
+
+ if (dst_location == SFLAG_INDRAWABLE)
+ {
+ GLenum buffer = surface_get_gl_buffer(dst_surface);
+
+ TRACE("Destination surface %p is onscreen.\n", dst_surface);
+
+ if (buffer == GL_FRONT)
+ surface_translate_frontbuffer_coords(dst_surface, context->win_handle, &dst_rect);
+
+ dst_rect.top = dst_surface->currentDesc.Height - dst_rect.top;
+ dst_rect.bottom = dst_surface->currentDesc.Height - dst_rect.bottom;
+
+ ENTER_GL();
+ context_bind_fbo(context, GL_DRAW_FRAMEBUFFER, NULL);
+ context_set_draw_buffer(context, buffer);
+ }
+ else
+ {
+ TRACE("Destination surface %p is offscreen.\n", dst_surface);
+
+ ENTER_GL();
+ context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, dst_surface, NULL, dst_location);
+ context_set_draw_buffer(context, GL_COLOR_ATTACHMENT0);
+ }
+
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE));
+ IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE1));
+ IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE2));
+ IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE3));
+
+ glDisable(GL_SCISSOR_TEST);
+ IWineD3DDeviceImpl_MarkStateDirty(device, 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) wglFlush(); /* Flush to ensure ordering across contexts. */
+
+ context_release(context);
+}
+
/* Not called from the VTable */
static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *dst_surface, const RECT *DestRect,
IWineD3DSurfaceImpl *src_surface, const RECT *SrcRect, DWORD Flags, const WINEDDBLTFX *DDBltFx,
@@ -3429,7 +3570,10 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *dst_surface,
&src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format_desc,
&dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format_desc))
{
- stretch_rect_fbo(device, src_surface, &src_rect, dst_surface, &dst_rect, Filter);
+ 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->currentDesc.Width
|| dst_rect.bottom - dst_rect.top > src_surface->currentDesc.Height)
@@ -3470,10 +3614,13 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *dst_surface,
&dst_rect, dst_surface->resource.usage, dst_surface->resource.pool,
dst_surface->resource.format_desc))
{
- TRACE("Using stretch_rect_fbo\n");
+ 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. */
- stretch_rect_fbo(device, src_surface, &src_rect, dst_surface, &dst_rect, Filter);
+ 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;
}
@@ -4206,43 +4353,6 @@ static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT
context_release(context);
}
-static void surface_load_srgb_fbo(IWineD3DSurfaceImpl *surface, DWORD location)
-{
- IWineD3DDeviceImpl *device = surface->resource.device;
- const struct wined3d_gl_info *gl_info;
- struct wined3d_context *context;
-
- context = context_acquire(device, NULL);
- gl_info = context->gl_info;
-
- ENTER_GL();
-
- context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, surface, NULL,
- location == SFLAG_INSRGBTEX ? SFLAG_INTEXTURE : SFLAG_INSRGBTEX);
- glReadBuffer(GL_COLOR_ATTACHMENT0);
- checkGLcall("glReadBuffer()");
-
- context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, surface, NULL, location);
- context_set_draw_buffer(context, GL_COLOR_ATTACHMENT0);
-
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE));
- IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE1));
- IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE2));
- IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE3));
-
- glDisable(GL_SCISSOR_TEST);
- IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
-
- gl_info->fbo_ops.glBlitFramebuffer(0, 0, surface->currentDesc.Width, surface->currentDesc.Height,
- 0, 0, surface->currentDesc.Width, surface->currentDesc.Height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
- checkGLcall("glBlitFramebuffer()");
-
- LEAVE_GL();
-
- context_release(context);
-}
-
HRESULT surface_load_location(IWineD3DSurfaceImpl *surface, DWORD flag, const RECT *rect)
{
IWineD3DDeviceImpl *device = surface->resource.device;
@@ -4409,7 +4519,11 @@ HRESULT surface_load_location(IWineD3DSurfaceImpl *surface, DWORD flag, const RE
NULL, surface->resource.usage, surface->resource.pool, surface->resource.format_desc,
NULL, surface->resource.usage, surface->resource.pool, surface->resource.format_desc))
{
- surface_load_srgb_fbo(surface, flag);
+ DWORD src_location = flag == SFLAG_INSRGBTEX ? SFLAG_INTEXTURE : SFLAG_INSRGBTEX;
+ RECT rect = {0, 0, surface->currentDesc.Width, surface->currentDesc.Height};
+
+ surface_blt_fbo(surface->resource.device, WINED3DTEXF_POINT,
+ surface, src_location, &rect, surface, flag, &rect);
}
else
{
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index fe44eae..77ef661 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2993,10 +2993,6 @@ static inline BOOL use_ps(IWineD3DStateBlockImpl *stateblock)
return (stateblock->pixelShader && stateblock->device->ps_selected_mode != SHADER_NONE);
}
-void stretch_rect_fbo(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *src_surface,
- const RECT *src_rect, IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect,
- const WINED3DTEXTUREFILTERTYPE filter) DECLSPEC_HIDDEN;
-
/* The WNDCLASS-Name for the fake window which we use to retrieve the GL capabilities */
#define WINED3D_OPENGL_WINDOW_CLASS_NAME "WineD3D_OpenGL"
--
1.7.1
More information about the wine-patches
mailing list