From 8842cf6a7d2b87f69462e5fe513f51bc127a8140 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Fri, 5 Apr 2013 14:37:44 +0200
Subject: wined3d: Keep track of the onscreen depth stencil in the command
 stream instead of the device.

Based on a patch by Henri Verbeet.

TODO: Not sure if its the right way to go. There are certainly some
missing bits, e.g. accessing the cs via the device in all but one places
defeats the point of this at the moment.

Since the GL onscreen depth stencil is part of the WGL framebuffer,
which belongs to the swapchain, storing this info in the swapchain might
be the right thing to do. This should help multi-window or multi-head
configurations.
---
 dlls/wined3d/cs.c              | 22 +++++++++++++++++++---
 dlls/wined3d/device.c          | 35 ++++++++++-------------------------
 dlls/wined3d/drawprim.c        |  4 ++--
 dlls/wined3d/swapchain.c       |  6 +++---
 dlls/wined3d/wined3d_private.h | 10 ++++------
 5 files changed, 38 insertions(+), 39 deletions(-)

diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index d5e2c52..b20d32f 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -639,10 +639,10 @@ static UINT wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const
                 || prev_surface->flags & SFLAG_DISCARD))
         {
             surface_modify_ds_location(prev_surface, WINED3D_LOCATION_DISCARDED, prev->width, prev->height);
-            if (prev_surface == device->onscreen_depth_stencil)
+            if (prev_surface == cs->onscreen_depth_stencil)
             {
-                wined3d_texture_decref(device->onscreen_depth_stencil->container);
-                device->onscreen_depth_stencil = NULL;
+                wined3d_texture_decref(cs->onscreen_depth_stencil->container);
+                cs->onscreen_depth_stencil = NULL;
             }
         }
     }
@@ -1480,6 +1480,22 @@ static void wined3d_cs_emit_stop(struct wined3d_cs *cs)
     wined3d_cs_flush(cs);
 }
 
+void wined3d_cs_switch_onscreen_ds(struct wined3d_cs *cs,
+        struct wined3d_context *context, struct wined3d_surface *depth_stencil)
+{
+    if (cs->onscreen_depth_stencil)
+    {
+        surface_load_ds_location(cs->onscreen_depth_stencil, context, WINED3D_LOCATION_TEXTURE_RGB);
+
+        surface_modify_ds_location(cs->onscreen_depth_stencil, WINED3D_LOCATION_TEXTURE_RGB,
+                cs->onscreen_depth_stencil->ds_current_size.cx,
+                cs->onscreen_depth_stencil->ds_current_size.cy);
+        wined3d_texture_decref(cs->onscreen_depth_stencil->container);
+    }
+    cs->onscreen_depth_stencil = depth_stencil;
+    wined3d_texture_incref(cs->onscreen_depth_stencil->container);
+}
+
 static DWORD WINAPI wined3d_cs_run(void *thread_param)
 {
     struct wined3d_cs *cs = thread_param;
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 1fef5ff..4de7eb2 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -198,22 +198,6 @@ void device_context_remove(struct wined3d_device *device, struct wined3d_context
     device->contexts = new_array;
 }
 
-void device_switch_onscreen_ds(struct wined3d_device *device,
-        struct wined3d_context *context, struct wined3d_surface *depth_stencil)
-{
-    if (device->onscreen_depth_stencil)
-    {
-        surface_load_ds_location(device->onscreen_depth_stencil, context, WINED3D_LOCATION_TEXTURE_RGB);
-
-        surface_modify_ds_location(device->onscreen_depth_stencil, WINED3D_LOCATION_TEXTURE_RGB,
-                device->onscreen_depth_stencil->ds_current_size.cx,
-                device->onscreen_depth_stencil->ds_current_size.cy);
-        wined3d_texture_decref(device->onscreen_depth_stencil->container);
-    }
-    device->onscreen_depth_stencil = depth_stencil;
-    wined3d_texture_incref(device->onscreen_depth_stencil->container);
-}
-
 static BOOL is_full_clear(const struct wined3d_surface *target, const RECT *draw_rect, const RECT *clear_rect)
 {
     /* partial draw rect */
@@ -348,8 +332,8 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
     {
         DWORD location = render_offscreen ? fb->depth_stencil->resource->draw_binding : WINED3D_LOCATION_DRAWABLE;
 
-        if (!render_offscreen && depth_stencil != device->onscreen_depth_stencil)
-            device_switch_onscreen_ds(device, context, depth_stencil);
+        if (!render_offscreen && depth_stencil != device->cs->onscreen_depth_stencil)
+            wined3d_cs_switch_onscreen_ds(device->cs, context, depth_stencil);
         prepare_ds_clear(depth_stencil, context, location,
                 draw_rect, rect_count, clear_rect, &ds_rect);
     }
@@ -1064,11 +1048,12 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
     /* Release the buffers (with sanity checks).
      * FIXME: Move this move into a separate patch. I think the idea
      * behind this is that those surfaces should be freed before unloading
-     * remaining resources below. */
-    if (device->onscreen_depth_stencil)
+     * remaining resources below.
+     * FIXME 2: Shouldn't the cs take care of onscreen_depth_stencil? */
+    if (device->cs->onscreen_depth_stencil)
     {
-        surface = device->onscreen_depth_stencil;
-        device->onscreen_depth_stencil = NULL;
+        surface = device->cs->onscreen_depth_stencil;
+        device->cs->onscreen_depth_stencil = NULL;
         wined3d_texture_decref(surface->container);
     }
 
@@ -4561,10 +4546,10 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
         state_unbind_resources(&device->state);
     }
 
-    if (device->onscreen_depth_stencil)
+    if (device->cs->onscreen_depth_stencil)
     {
-        wined3d_texture_decref(device->onscreen_depth_stencil->container);
-        device->onscreen_depth_stencil = NULL;
+        wined3d_texture_decref(device->cs->onscreen_depth_stencil->container);
+        device->cs->onscreen_depth_stencil = NULL;
     }
 
     if (reset_state)
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 21ce53a..9ec380a 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -651,8 +651,8 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s
         {
             RECT current_rect, draw_rect, r;
 
-            if (!context->render_offscreen && ds != device->onscreen_depth_stencil)
-                device_switch_onscreen_ds(device, context, ds);
+            if (!context->render_offscreen && ds != device->cs->onscreen_depth_stencil)
+                wined3d_cs_switch_onscreen_ds(device->cs, context, ds);
 
             if (ds->resource.locations & location)
                 SetRect(&current_rect, 0, 0, ds->ds_current_size.cx, ds->ds_current_size.cy);
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index 6ded6cc..0a8da3d 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -588,10 +588,10 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT
         {
             surface_modify_ds_location(depth_stencil, WINED3D_LOCATION_DISCARDED,
                     depth_stencil->resource.width, depth_stencil->resource.height);
-            if (depth_stencil == swapchain->device->onscreen_depth_stencil)
+            if (depth_stencil == swapchain->device->cs->onscreen_depth_stencil)
             {
-                wined3d_texture_decref(swapchain->device->onscreen_depth_stencil->container);
-                swapchain->device->onscreen_depth_stencil = NULL;
+                wined3d_texture_decref(swapchain->device->cs->onscreen_depth_stencil->container);
+                swapchain->device->cs->onscreen_depth_stencil = NULL;
             }
         }
     }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index dec58e5..035517f 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2116,15 +2116,12 @@ struct wined3d_device
     struct wined3d_rendertarget_view *back_buffer_view;
     struct wined3d_swapchain **swapchains;
     UINT swapchain_count;
+    struct wined3d_rendertarget_view *auto_depth_stencil_view;
 
     struct list             resources; /* a linked list to track resources created by the device */
     struct list             shaders;   /* a linked list to track shaders (pixel and vertex)      */
     struct wine_rb_tree samplers;
 
-    /* Render Target Support */
-    struct wined3d_surface *onscreen_depth_stencil;
-    struct wined3d_rendertarget_view *auto_depth_stencil_view;
-
     /* For rendering to a texture using glCopyTexImage */
     GLuint                  depth_blt_texture;
 
@@ -2166,8 +2163,6 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL
         UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc) DECLSPEC_HIDDEN;
 void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
-void device_switch_onscreen_ds(struct wined3d_device *device, struct wined3d_context *context,
-        struct wined3d_surface *depth_stencil) DECLSPEC_HIDDEN;
 void device_invalidate_state(const struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN;
 
 static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state)
@@ -2667,6 +2662,7 @@ struct wined3d_cs
     struct wined3d_state state;
     HANDLE thread;
     DWORD tls_idx;
+    struct wined3d_surface *onscreen_depth_stencil;
 
     size_t data_size;
     void *data;
@@ -2677,6 +2673,8 @@ struct wined3d_cs
 
 struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) DECLSPEC_HIDDEN;
 void wined3d_cs_destroy(struct wined3d_cs *cs) DECLSPEC_HIDDEN;
+void wined3d_cs_switch_onscreen_ds(struct wined3d_cs *cs, struct wined3d_context *context,
+        struct wined3d_surface *depth_stencil) DECLSPEC_HIDDEN;
 
 void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects,
         DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) DECLSPEC_HIDDEN;
-- 
2.6.2

