Stefan Dösinger : wined3d: Split out offscreen rendering concerns from FindContext.

Alexandre Julliard julliard at winehq.org
Wed Mar 31 10:04:53 CDT 2010


Module: wine
Branch: master
Commit: a4b0bedc30f31d19d969364c80f979b77cce9011
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a4b0bedc30f31d19d969364c80f979b77cce9011

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Sat Mar 27 17:40:28 2010 +0100

wined3d: Split out offscreen rendering concerns from FindContext.

---

 dlls/wined3d/context.c |  163 ++++++++++++++++++++++++-----------------------
 1 files changed, 83 insertions(+), 80 deletions(-)

diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 15a8f77..f3729ae 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -1834,10 +1834,8 @@ static struct wined3d_context *FindContext(IWineD3DDeviceImpl *This, IWineD3DSur
 {
     IWineD3DSwapChain *swapchain = NULL;
     struct wined3d_context *current_context = context_get_current();
-    const struct StateEntry *StateTable = This->StateTable;
     DWORD tid = GetCurrentThreadId();
     struct wined3d_context *context;
-    BOOL old_render_offscreen;
 
     if (current_context && current_context->destroyed) current_context = NULL;
 
@@ -1867,9 +1865,6 @@ static struct wined3d_context *FindContext(IWineD3DDeviceImpl *This, IWineD3DSur
         TRACE("Rendering onscreen\n");
 
         context = findThreadContextForSwapChain(swapchain, tid);
-
-        old_render_offscreen = context->render_offscreen;
-        context->render_offscreen = surface_is_offscreen(target);
         IWineD3DSwapChain_Release(swapchain);
     }
     else
@@ -1891,85 +1886,10 @@ static struct wined3d_context *FindContext(IWineD3DDeviceImpl *This, IWineD3DSur
              * is perfect to call. */
             context = findThreadContextForSwapChain(This->swapchains[0], tid);
         }
-
-        old_render_offscreen = context->render_offscreen;
-        context->render_offscreen = TRUE;
     }
 
     context_validate(context);
 
-    if (context->render_offscreen != old_render_offscreen)
-    {
-        Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION), StateTable);
-        Context_MarkStateDirty(context, STATE_VDECL, StateTable);
-        Context_MarkStateDirty(context, STATE_VIEWPORT, StateTable);
-        Context_MarkStateDirty(context, STATE_SCISSORRECT, StateTable);
-        Context_MarkStateDirty(context, STATE_FRONTFACE, StateTable);
-    }
-
-    /* To compensate the lack of format switching with some offscreen rendering methods and on onscreen buffers
-     * the alpha blend state changes with different render target formats. */
-    if (!context->current_rt)
-    {
-        Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable);
-    }
-    else
-    {
-        const struct wined3d_format_desc *old = ((IWineD3DSurfaceImpl *)context->current_rt)->resource.format_desc;
-        const struct wined3d_format_desc *new = ((IWineD3DSurfaceImpl *)target)->resource.format_desc;
-
-        if (old->format != new->format)
-        {
-            /* Disable blending when the alpha mask has changed and when a format doesn't support blending. */
-            if ((old->alpha_mask && !new->alpha_mask) || (!old->alpha_mask && new->alpha_mask)
-                    || !(new->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
-            {
-                Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable);
-            }
-        }
-
-        /* When switching away from an offscreen render target, and we're not
-         * using FBOs, we have to read the drawable into the texture. This is
-         * done via PreLoad (and SFLAG_INDRAWABLE set on the surface). There
-         * are some things that need care though. PreLoad needs a GL context,
-         * and FindContext is called before the context is activated. It also
-         * has to be called with the old rendertarget active, otherwise a
-         * wrong drawable is read. */
-        if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
-                && old_render_offscreen && context->current_rt != target)
-        {
-            BOOL oldInDraw = This->isInDraw;
-
-            /* surface_internal_preload() requires a context to load the
-             * texture, so it will call context_acquire(). Set isInDraw to true
-             * to signal surface_internal_preload() that it has a context. */
-
-            /* FIXME: This is just broken. There's no guarantee whatsoever
-             * that the currently active context, if any, is appropriate for
-             * reading back the render target. We should probably call
-             * context_set_current(context) here and then rely on
-             * context_acquire() doing the right thing. */
-            This->isInDraw = TRUE;
-
-            /* Read the back buffer of the old drawable into the destination texture. */
-            if (((IWineD3DSurfaceImpl *)context->current_rt)->texture_name_srgb)
-            {
-                surface_internal_preload(context->current_rt, SRGB_BOTH);
-            }
-            else
-            {
-                surface_internal_preload(context->current_rt, SRGB_RGB);
-            }
-
-            IWineD3DSurface_ModifyLocation(context->current_rt, SFLAG_INDRAWABLE, FALSE);
-
-            This->isInDraw = oldInDraw;
-        }
-    }
-
-    context->draw_buffer_dirty = TRUE;
-    context->current_rt = target;
-
     return context;
 }
 
@@ -2139,6 +2059,88 @@ static void context_apply_state(struct wined3d_context *context, IWineD3DDeviceI
     }
 }
 
+static void context_setup_target(IWineD3DDeviceImpl *device, struct wined3d_context *context, IWineD3DSurface *target)
+{
+    BOOL old_render_offscreen = context->render_offscreen;
+    const struct StateEntry *StateTable = device->StateTable;
+
+    if (!target) return;
+    else if (context->current_rt == target) return;
+    context->render_offscreen = surface_is_offscreen(target);
+
+    if (context->render_offscreen != old_render_offscreen)
+    {
+        Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION), StateTable);
+        Context_MarkStateDirty(context, STATE_VDECL, StateTable);
+        Context_MarkStateDirty(context, STATE_VIEWPORT, StateTable);
+        Context_MarkStateDirty(context, STATE_SCISSORRECT, StateTable);
+        Context_MarkStateDirty(context, STATE_FRONTFACE, StateTable);
+    }
+
+    /* To compensate the lack of format switching with some offscreen rendering methods and on onscreen buffers
+     * the alpha blend state changes with different render target formats. */
+    if (!context->current_rt)
+    {
+        Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable);
+    }
+    else
+    {
+        const struct wined3d_format_desc *old = ((IWineD3DSurfaceImpl *)context->current_rt)->resource.format_desc;
+        const struct wined3d_format_desc *new = ((IWineD3DSurfaceImpl *)target)->resource.format_desc;
+
+        if (old->format != new->format)
+        {
+            /* Disable blending when the alpha mask has changed and when a format doesn't support blending. */
+            if ((old->alpha_mask && !new->alpha_mask) || (!old->alpha_mask && new->alpha_mask)
+                    || !(new->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
+            {
+                Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable);
+            }
+        }
+
+        /* When switching away from an offscreen render target, and we're not
+         * using FBOs, we have to read the drawable into the texture. This is
+         * done via PreLoad (and SFLAG_INDRAWABLE set on the surface). There
+         * are some things that need care though. PreLoad needs a GL context,
+         * and FindContext is called before the context is activated. It also
+         * has to be called with the old rendertarget active, otherwise a
+         * wrong drawable is read. */
+        if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
+                && old_render_offscreen && context->current_rt != target)
+        {
+            BOOL oldInDraw = device->isInDraw;
+
+            /* surface_internal_preload() requires a context to load the
+             * texture, so it will call context_acquire(). Set isInDraw to true
+             * to signal surface_internal_preload() that it has a context. */
+
+            /* FIXME: This is just broken. There's no guarantee whatsoever
+             * that the currently active context, if any, is appropriate for
+             * reading back the render target. We should probably call
+             * context_set_current(context) here and then rely on
+             * context_acquire() doing the right thing. */
+            device->isInDraw = TRUE;
+
+            /* Read the back buffer of the old drawable into the destination texture. */
+            if (((IWineD3DSurfaceImpl *)context->current_rt)->texture_name_srgb)
+            {
+                surface_internal_preload(context->current_rt, SRGB_BOTH);
+            }
+            else
+            {
+                surface_internal_preload(context->current_rt, SRGB_RGB);
+            }
+
+            IWineD3DSurface_ModifyLocation(context->current_rt, SFLAG_INDRAWABLE, FALSE);
+
+            device->isInDraw = oldInDraw;
+        }
+    }
+
+    context->draw_buffer_dirty = TRUE;
+    context->current_rt = target;
+}
+
 /*****************************************************************************
  * context_acquire
  *
@@ -2160,6 +2162,7 @@ struct wined3d_context *context_acquire(IWineD3DDeviceImpl *device, IWineD3DSurf
     TRACE("device %p, target %p, usage %#x.\n", device, target, usage);
 
     context = FindContext(device, target);
+    context_setup_target(device, context, target);
     context_enter(context);
     if (!context->valid) return context;
 




More information about the wine-cvs mailing list