[PATCH 1/6] wined3d: Prepare GL resources before calling context_apply_fbo_state (v2).

Stefan Dösinger stefan at codeweavers.com
Wed Oct 28 09:29:17 CDT 2015


Version 2: Make callers of context_apply_fbo_state responsible for this
instead of context_apply_fbo_state itself.

Note that we're also attaching FBO parts that are masked out by clear
masks or color / depth write flags. This (still) makes sense IMO because
otherwise we'd have to re-apply the FBO every time one of those masks
changed.

Signed-off-by: Stefan Dösinger <stefan at codeweavers.com>
---
 dlls/wined3d/context.c         |  7 -------
 dlls/wined3d/device.c          | 13 ++++++++----
 dlls/wined3d/drawprim.c        | 20 ++++++++++++------
 dlls/wined3d/surface.c         | 46 ++++++++++++++++++++++++++----------------
 dlls/wined3d/wined3d_private.h |  2 ++
 5 files changed, 54 insertions(+), 34 deletions(-)

diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index e324875..978f7d7 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -141,8 +141,6 @@ static void context_attach_depth_stencil_fbo(struct wined3d_context *context,
             {
                 case WINED3D_LOCATION_TEXTURE_RGB:
                 case WINED3D_LOCATION_TEXTURE_SRGB:
-                    wined3d_texture_prepare_texture(depth_stencil->container, context, FALSE);
-
                     if (format_flags & WINED3DFMT_FLAG_DEPTH)
                     {
                         gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_DEPTH_ATTACHMENT,
@@ -161,13 +159,11 @@ static void context_attach_depth_stencil_fbo(struct wined3d_context *context,
                     break;
 
                 case WINED3D_LOCATION_RB_MULTISAMPLE:
-                    surface_prepare_rb(depth_stencil, gl_info, TRUE);
                     context_attach_depth_stencil_rb(gl_info, fbo_target,
                             format_flags, depth_stencil->rb_multisample);
                     break;
 
                 case WINED3D_LOCATION_RB_RESOLVED:
-                    surface_prepare_rb(depth_stencil, gl_info, FALSE);
                     context_attach_depth_stencil_rb(gl_info, fbo_target,
                             format_flags, depth_stencil->rb_resolved);
                     break;
@@ -217,7 +213,6 @@ static void context_attach_surface_fbo(struct wined3d_context *context,
             case WINED3D_LOCATION_TEXTURE_RGB:
             case WINED3D_LOCATION_TEXTURE_SRGB:
                 srgb = location == WINED3D_LOCATION_TEXTURE_SRGB;
-                wined3d_texture_prepare_texture(surface->container, context, srgb);
                 gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_COLOR_ATTACHMENT0 + idx,
                         surface->texture_target, surface_get_texture_name(surface, gl_info, srgb),
                         surface->texture_level);
@@ -225,14 +220,12 @@ static void context_attach_surface_fbo(struct wined3d_context *context,
                 break;
 
             case WINED3D_LOCATION_RB_MULTISAMPLE:
-                surface_prepare_rb(surface, gl_info, TRUE);
                 gl_info->fbo_ops.glFramebufferRenderbuffer(fbo_target, GL_COLOR_ATTACHMENT0 + idx,
                         GL_RENDERBUFFER, surface->rb_multisample);
                 checkGLcall("glFramebufferRenderbuffer()");
                 break;
 
             case WINED3D_LOCATION_RB_RESOLVED:
-                surface_prepare_rb(surface, gl_info, FALSE);
                 gl_info->fbo_ops.glFramebufferRenderbuffer(fbo_target, GL_COLOR_ATTACHMENT0 + idx,
                         GL_RENDERBUFFER, surface->rb_resolved);
                 checkGLcall("glFramebufferRenderbuffer()");
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 087dc33..d00f263 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -317,13 +317,15 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
      * anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set
      * the drawable up to date. We have to check all settings that limit the clear area though. Do not bother
      * checking all this if the dest surface is in the drawable anyway. */
-    if (flags & WINED3DCLEAR_TARGET && !is_full_clear(target, draw_rect, clear_rect))
+    for (i = 0; i < rt_count; ++i)
     {
-        for (i = 0; i < rt_count; ++i)
+        struct wined3d_surface *rt = wined3d_rendertarget_view_get_surface(fb->render_targets[i]);
+        if (rt && rt->resource.format->id != WINED3DFMT_NULL)
         {
-            struct wined3d_surface *rt = wined3d_rendertarget_view_get_surface(fb->render_targets[i]);
-            if (rt)
+            if (flags & WINED3DCLEAR_TARGET && !is_full_clear(target, draw_rect, clear_rect))
                 surface_load_location(rt, context, rt->container->resource.draw_binding);
+            else
+                wined3d_surface_prepare(rt, context, rt->container->resource.draw_binding);
         }
     }
 
@@ -339,6 +341,9 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
         drawable_height = depth_stencil->pow2Height;
     }
 
+    if (depth_stencil && render_offscreen)
+        wined3d_surface_prepare(depth_stencil, context, depth_stencil->container->resource.draw_binding);
+
     if (flags & WINED3DCLEAR_ZBUFFER)
     {
         DWORD location = render_offscreen ? fb->depth_stencil->resource->draw_binding : WINED3D_LOCATION_DRAWABLE;
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index d2d3bce..3761830 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -620,17 +620,20 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co
     }
     gl_info = context->gl_info;
 
-    if (state->render_states[WINED3D_RS_COLORWRITEENABLE])
+    for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
     {
-        /* Invalidate the back buffer memory so LockRect will read it the next time */
-        for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
+        struct wined3d_surface *target = wined3d_rendertarget_view_get_surface(device->fb.render_targets[i]);
+        if (target && target->resource.format->id != WINED3DFMT_NULL)
         {
-            struct wined3d_surface *target = wined3d_rendertarget_view_get_surface(device->fb.render_targets[i]);
-            if (target)
+            if (state->render_states[WINED3D_RS_COLORWRITEENABLE])
             {
                 surface_load_location(target, context, target->container->resource.draw_binding);
                 surface_invalidate_location(target, ~target->container->resource.draw_binding);
             }
+            else
+            {
+                wined3d_surface_prepare(target, context, target->container->resource.draw_binding);
+            }
         }
     }
 
@@ -643,9 +646,10 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co
          * that we never copy the stencil data.*/
         DWORD location = context->render_offscreen ? device->fb.depth_stencil->resource->draw_binding
                 : WINED3D_LOCATION_DRAWABLE;
+        struct wined3d_surface *ds = wined3d_rendertarget_view_get_surface(device->fb.depth_stencil);
+
         if (state->render_states[WINED3D_RS_ZWRITEENABLE] || state->render_states[WINED3D_RS_ZENABLE])
         {
-            struct wined3d_surface *ds = wined3d_rendertarget_view_get_surface(device->fb.depth_stencil);
             RECT current_rect, draw_rect, r;
 
             if (!context->render_offscreen && ds != device->onscreen_depth_stencil)
@@ -661,7 +665,11 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co
             IntersectRect(&r, &draw_rect, &current_rect);
             if (!EqualRect(&r, &draw_rect))
                 surface_load_ds_location(ds, context, location);
+            else
+                wined3d_surface_prepare(ds, context, location);
         }
+        else
+            wined3d_surface_prepare(ds, context, location);
     }
 
     if (!context_apply_draw_state(context, device))
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index d0b70f3..e1633fc 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -821,6 +821,8 @@ static void surface_depth_blt_fbo(const struct wined3d_device *device,
     surface_load_location(src_surface, context, src_location);
     if (!surface_is_full_rect(dst_surface, dst_rect))
         surface_load_location(dst_surface, context, dst_location);
+    else
+        wined3d_surface_prepare(dst_surface, context, dst_location);
 
     gl_info = context->gl_info;
 
@@ -912,6 +914,9 @@ static void surface_blt_fbo(const struct wined3d_device *device,
     surface_load_location(src_surface, old_ctx, src_location);
     if (!surface_is_full_rect(dst_surface, &dst_rect))
         surface_load_location(dst_surface, old_ctx, dst_location);
+    else
+        wined3d_surface_prepare(dst_surface, old_ctx, dst_location);
+
 
     if (src_location == WINED3D_LOCATION_DRAWABLE) required_rt = src_surface;
     else if (dst_location == WINED3D_LOCATION_DRAWABLE) required_rt = dst_surface;
@@ -3658,23 +3663,7 @@ void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_co
     if (surface->locations & WINED3D_LOCATION_DISCARDED)
     {
         TRACE("Surface was discarded, no need copy data.\n");
-        switch (location)
-        {
-            case WINED3D_LOCATION_TEXTURE_RGB:
-                wined3d_texture_prepare_texture(surface->container, context, FALSE);
-                break;
-            case WINED3D_LOCATION_RB_MULTISAMPLE:
-                surface_prepare_rb(surface, gl_info, TRUE);
-                break;
-            case WINED3D_LOCATION_RB_RESOLVED:
-                surface_prepare_rb(surface, gl_info, FALSE);
-                break;
-            case WINED3D_LOCATION_DRAWABLE:
-                /* Nothing to do */
-                break;
-            default:
-                FIXME("Unhandled location %#x\n", location);
-        }
+        wined3d_surface_prepare(surface, context, location);
         surface->locations &= ~WINED3D_LOCATION_DISCARDED;
         surface->locations |= location;
         surface->ds_current_size.cx = surface->resource.width;
@@ -5497,3 +5486,26 @@ HRESULT wined3d_surface_create(struct wined3d_texture *container, const struct w
 
     return hr;
 }
+
+/* Context activation is done by the caller. */
+void wined3d_surface_prepare(struct wined3d_surface *surface, struct wined3d_context *context, DWORD location)
+{
+    switch (location)
+    {
+        case WINED3D_LOCATION_TEXTURE_RGB:
+            wined3d_texture_prepare_texture(surface->container, context, FALSE);
+            break;
+
+        case WINED3D_LOCATION_TEXTURE_SRGB:
+            wined3d_texture_prepare_texture(surface->container, context, TRUE);
+            break;
+
+        case WINED3D_LOCATION_RB_MULTISAMPLE:
+            surface_prepare_rb(surface, context->gl_info, TRUE);
+            break;
+
+        case WINED3D_LOCATION_RB_RESOLVED:
+            surface_prepare_rb(surface, context->gl_info, FALSE);
+            break;
+    }
+}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index d30b59d..fd7bbc8 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2459,6 +2459,8 @@ void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb,
 HRESULT surface_load_location(struct wined3d_surface *surface,
         struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN;
 void surface_modify_ds_location(struct wined3d_surface *surface, DWORD location, UINT w, UINT h) DECLSPEC_HIDDEN;
+void wined3d_surface_prepare(struct wined3d_surface *surface, struct wined3d_context *context,
+        DWORD location) DECLSPEC_HIDDEN;
 void surface_prepare_rb(struct wined3d_surface *surface,
         const struct wined3d_gl_info *gl_info, BOOL multisample) DECLSPEC_HIDDEN;
 void surface_set_compatible_renderbuffer(struct wined3d_surface *surface,
-- 
2.4.10




More information about the wine-patches mailing list