[PATCH 2/5] wined3d: Pass a context to read_from_framebuffer.

Stefan Dösinger stefan at codeweavers.com
Mon Oct 12 15:34:39 CDT 2015


Sometimes the context won't be reusable because we need a specific
context to access the WGL drawable. Afterwards we need to switch back to
the caller's context. Bug 34574 is related to this. This is only
relevant for backbuffer offscreen rendering, and in practise it is rare.
It'll only matter if the application is blitting from an onscreen
surface to a currently active offscreen one. For everything else the
offscreen surface is copied into the texture when it is deactivated.

Note that in most cases the wined3d_context * structure is the same for
both surfaces involved in the blit, but context->render_offscreen
differs for source and destination. That's why context_restore needs a
surface and not the old context.

I'm open to placing the extra context_acquire / context_release calls
into the callers. We need them in 4 places: read_from_framebuffer,
surface_blt_to_drawable, surface_blt_fbo and surface_load_fb_texture.

Signed-off-by: Stefan Dösinger <stefan at codeweavers.com>
---
 dlls/wined3d/context.c         | 14 ++++++++++++++
 dlls/wined3d/surface.c         | 18 +++++++++++++-----
 dlls/wined3d/wined3d_private.h |  1 +
 3 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 3e2a804..dc4199a 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -1194,6 +1194,20 @@ void context_release(struct wined3d_context *context)
     }
 }
 
+/* This is used when a context for render target A is active, but a separate context is
+ * needed to access the WGL framebuffer for render target B. Re-acquire a context for rt
+ * A to avoid breaking caller code. */
+void context_restore(struct wined3d_context *context, struct wined3d_surface *restore)
+{
+    if (context->current_rt != restore)
+    {
+        context_release(context);
+        context = context_acquire(restore->resource.device, restore);
+    }
+
+    context_release(context);
+}
+
 static void context_enter(struct wined3d_context *context)
 {
     TRACE("Entering context %p, level %u.\n", context, context->level + 1);
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index c911d35..7101bc4 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -2681,11 +2681,13 @@ HRESULT CDECL wined3d_surface_releasedc(struct wined3d_surface *surface, HDC dc)
     return WINED3D_OK;
 }
 
-static void read_from_framebuffer(struct wined3d_surface *surface, DWORD dst_location)
+static void read_from_framebuffer(struct wined3d_surface *surface,
+        struct wined3d_context *old_ctx, DWORD dst_location)
 {
     struct wined3d_device *device = surface->resource.device;
     const struct wined3d_gl_info *gl_info;
-    struct wined3d_context *context;
+    struct wined3d_context *context = old_ctx;
+    struct wined3d_surface *restore_rt = NULL;
     BYTE *mem;
     BYTE *row, *top, *bottom;
     int i;
@@ -2694,7 +2696,12 @@ static void read_from_framebuffer(struct wined3d_surface *surface, DWORD dst_loc
 
     surface_get_memory(surface, &data, dst_location);
 
-    context = context_acquire(device, surface);
+    if (surface != old_ctx->current_rt)
+    {
+        restore_rt = old_ctx->current_rt;
+        context = context_acquire(device, surface);
+    }
+
     context_apply_blit_state(context, device);
     gl_info = context->gl_info;
 
@@ -2781,7 +2788,8 @@ error:
         checkGLcall("glBindBuffer");
     }
 
-    context_release(context);
+    if (restore_rt)
+        context_restore(context, restore_rt);
 }
 
 /* Read the framebuffer contents into a texture. Note that this function
@@ -3824,7 +3832,7 @@ static void surface_load_sysmem(struct wined3d_surface *surface,
 
     if (surface->locations & WINED3D_LOCATION_DRAWABLE)
     {
-        read_from_framebuffer(surface, dst_location);
+        read_from_framebuffer(surface, context, dst_location);
         return;
     }
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index d75761e..8ce372a 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1419,6 +1419,7 @@ void context_resource_released(const struct wined3d_device *device,
         struct wined3d_resource *resource, enum wined3d_resource_type type) DECLSPEC_HIDDEN;
 void context_resource_unloaded(const struct wined3d_device *device,
         struct wined3d_resource *resource, enum wined3d_resource_type type) DECLSPEC_HIDDEN;
+void context_restore(struct wined3d_context *context, struct wined3d_surface *restore) DECLSPEC_HIDDEN;
 BOOL context_set_current(struct wined3d_context *ctx) DECLSPEC_HIDDEN;
 void context_set_draw_buffer(struct wined3d_context *context, GLenum buffer) DECLSPEC_HIDDEN;
 void context_set_tls_idx(DWORD idx) DECLSPEC_HIDDEN;
-- 
2.4.9




More information about the wine-patches mailing list