From e97fb065249c11f83234e5d8b713112725fc3039 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Fri, 11 Oct 2013 10:11:13 +0200
Subject: wined3d: Delete GL contexts through the CS in reset.

Let's see if this fixes the remaining fglrx crashes...
---
 dlls/wined3d/cs.c              | 29 +++++++++++++++++++++++++++++
 dlls/wined3d/device.c          | 26 +++++++++++++++-----------
 dlls/wined3d/wined3d_private.h |  4 ++++
 3 files changed, 48 insertions(+), 11 deletions(-)

diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index b0b86ae..b30bb4e 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -90,6 +90,7 @@ enum wined3d_cs_op
     WINED3D_CS_OP_TEXTURE_CLEANUP,
     WINED3D_CS_OP_CREATE_DUMMY_TEXTURES,
     WINED3D_CS_OP_CREATE_SWAPCHAIN_CONTEXT,
+    WINED3D_CS_OP_DELETE_GL_CONTEXTS,
     WINED3D_CS_OP_STOP,
 };
 
@@ -536,6 +537,12 @@ struct wined3d_cs_create_swapchain_context
     HRESULT *ret;
 };
 
+struct wined3d_cs_delete_gl_contexts
+{
+    enum wined3d_cs_op opcode;
+    struct wined3d_swapchain *swapchain;
+};
+
 static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size)
 {
     LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1);
@@ -2649,6 +2656,27 @@ HRESULT wined3d_cs_emit_create_swapchain_context(struct wined3d_cs *cs, struct w
     return ret;
 }
 
+static UINT wined3d_cs_exec_delete_gl_contexts(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_delete_gl_contexts *op = data;
+
+    device_delete_opengl_contexts_cs(cs->device, op->swapchain);
+
+    return sizeof(*op);
+}
+
+void wined3d_cs_emit_delete_opengl_contexts(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain)
+{
+    struct wined3d_cs_delete_gl_contexts *op;
+
+    op = cs->ops->require_space(cs, sizeof(*op));
+    op->opcode = WINED3D_CS_OP_DELETE_GL_CONTEXTS;
+    op->swapchain = swapchain;
+
+    cs->ops->submit(cs, sizeof(*op));
+    cs->ops->finish(cs);
+}
+
 static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) =
 {
     /* WINED3D_CS_OP_NOP                        */ wined3d_cs_exec_nop,
@@ -2717,6 +2745,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
     /* WINED3D_CS_OP_TEXTURE_CLEANUP            */ wined3d_cs_exec_texture_cleanup,
     /* WINED3D_CS_OP_CREATE_DUMMY_TEXTURES      */ wined3d_cs_exec_create_dummy_textures,
     /* WINED3D_CS_OP_CREATE_SWAPCHAIN_CONTEXT   */ wined3d_cs_exec_create_swapchain_context,
+    /* WINED3D_CS_OP_DELETE_GL_CONTEXTS         */ wined3d_cs_exec_delete_gl_contexts,
 };
 
 static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 525b61b..039b645 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -4409,22 +4409,12 @@ void CDECL wined3d_device_evict_managed_resources(struct wined3d_device *device)
     }
 }
 
-static void delete_opengl_contexts(struct wined3d_device *device, struct wined3d_swapchain *swapchain)
+void device_delete_opengl_contexts_cs(struct wined3d_device *device, struct wined3d_swapchain *swapchain)
 {
-    struct wined3d_resource *resource, *cursor;
     const struct wined3d_gl_info *gl_info;
     struct wined3d_context *context;
     struct wined3d_shader *shader;
 
-    LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry)
-    {
-        TRACE("Unloading resource %p.\n", resource);
-
-        wined3d_cs_emit_evict_resource(device->cs, resource);
-    }
-    if (wined3d_settings.cs_multithreaded)
-        device->cs->ops->finish(device->cs);
-
     LIST_FOR_EACH_ENTRY(shader, &device->shaders, struct wined3d_shader, shader_list_entry)
     {
         device->shader_backend->shader_destroy(shader);
@@ -4454,6 +4444,20 @@ static void delete_opengl_contexts(struct wined3d_device *device, struct wined3d
     swapchain->context = NULL;
 }
 
+static void delete_opengl_contexts(struct wined3d_device *device, struct wined3d_swapchain *swapchain)
+{
+    struct wined3d_resource *resource, *cursor;
+
+    LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry)
+    {
+        TRACE("Unloading resource %p.\n", resource);
+
+        wined3d_cs_emit_evict_resource(device->cs, resource);
+    }
+
+    wined3d_cs_emit_delete_opengl_contexts(device->cs, swapchain);
+}
+
 static HRESULT create_primary_opengl_context(struct wined3d_device *device, struct wined3d_swapchain *swapchain)
 {
     HRESULT hr;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index d5b939c..9f509e5 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2200,6 +2200,8 @@ void wined3d_device_release_bo(struct wined3d_device *device, struct wined3d_gl_
         const struct wined3d_context *context) DECLSPEC_HIDDEN;
 void device_create_dummy_textures(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN;
 void device_create_default_sampler(struct wined3d_device *device);
+void device_delete_opengl_contexts_cs(struct wined3d_device *device,
+        struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 
 static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state)
 {
@@ -2841,6 +2843,8 @@ void wined3d_cs_emit_texture_cleanup(struct wined3d_cs *cs, struct wined3d_textu
 void wined3d_cs_emit_create_dummy_textures(struct wined3d_cs *cs) DECLSPEC_HIDDEN;
 HRESULT wined3d_cs_emit_create_swapchain_context(struct wined3d_cs *cs,
         struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
+void wined3d_cs_emit_delete_opengl_contexts(struct wined3d_cs *cs,
+        struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 
 /* Direct3D terminology with little modifications. We do not have an issued state
  * because only the driver knows about it, but we have a created state because d3d
-- 
2.6.4

