From 070101f77c342c4eeb49e01d3cc9ca9eaa63fe24 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Thu, 10 Oct 2013 16:43:19 +0200
Subject: wined3d: Create the initial context through the CS.

Very hacky.
---
 dlls/wined3d/cs.c              |  34 ++++++++++++
 dlls/wined3d/swapchain.c       | 118 +++++++++++++++++++++++------------------
 dlls/wined3d/wined3d_private.h |   4 ++
 3 files changed, 103 insertions(+), 53 deletions(-)

diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index 7dc847b..c78ac12 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -89,6 +89,7 @@ enum wined3d_cs_op
     WINED3D_CS_OP_SURFACE_CLEANUP,
     WINED3D_CS_OP_TEXTURE_CLEANUP,
     WINED3D_CS_OP_CREATE_DUMMY_TEXTURES,
+    WINED3D_CS_OP_CREATE_SWAPCHAIN_CONTEXT,
     WINED3D_CS_OP_STOP,
 };
 
@@ -528,6 +529,13 @@ struct wined3d_cs_create_dummy_textures
     enum wined3d_cs_op opcode;
 };
 
+struct wined3d_cs_create_swapchain_context
+{
+    enum wined3d_cs_op opcode;
+    struct wined3d_swapchain *swapchain;
+    HRESULT *ret;
+};
+
 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);
@@ -2615,6 +2623,31 @@ void wined3d_cs_emit_create_dummy_textures(struct wined3d_cs *cs)
     cs->ops->finish(cs);
 }
 
+static UINT wined3d_cs_exec_create_swapchain_context(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_create_swapchain_context *op = data;
+
+    *op->ret = swapchain_create_context_cs(cs->device, op->swapchain);
+
+    return sizeof(*op);
+}
+
+HRESULT wined3d_cs_emit_create_swapchain_context(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain)
+{
+    HRESULT ret;
+    struct wined3d_cs_create_swapchain_context *op;
+
+    op = cs->ops->require_space(cs, sizeof(*op));
+    op->opcode = WINED3D_CS_OP_CREATE_SWAPCHAIN_CONTEXT;
+    op->swapchain = swapchain;
+    op->ret = &ret;
+
+    cs->ops->submit(cs, sizeof(*op));
+    cs->ops->finish(cs);
+
+    return ret;
+}
+
 static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) =
 {
     /* WINED3D_CS_OP_NOP                        */ wined3d_cs_exec_nop,
@@ -2682,6 +2715,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
     /* WINED3D_CS_OP_SURFACE_CLEANUP            */ wined3d_cs_exec_surface_cleanup,
     /* 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,
 };
 
 static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio)
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index efe6987..71e5df6 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -723,6 +723,69 @@ static void swapchain_update_render_to_fbo(struct wined3d_swapchain *swapchain)
     swapchain->render_to_fbo = TRUE;
 }
 
+HRESULT swapchain_create_context_cs(struct wined3d_device *device, struct wined3d_swapchain *swapchain)
+{
+    const struct wined3d_adapter *adapter = device->adapter;
+    unsigned int i;
+    static const enum wined3d_format_id formats[] =
+    {
+        WINED3DFMT_D24_UNORM_S8_UINT,
+        WINED3DFMT_D32_UNORM,
+        WINED3DFMT_R24_UNORM_X8_TYPELESS,
+        WINED3DFMT_D16_UNORM,
+        WINED3DFMT_S1_UINT_D15_UNORM
+    };
+    struct wined3d_surface *front_buffer;
+    const struct wined3d_gl_info *gl_info = &adapter->gl_info;
+
+    swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context));
+    if (!swapchain->context)
+    {
+        ERR("Failed to create the context array.\n");
+        return E_OUTOFMEMORY;
+    }
+    swapchain->num_contexts = 1;
+
+    /* In WGL both color, depth and stencil are features of a pixel format. In case of D3D they are separate.
+     * You are able to add a depth + stencil surface at a later stage when you need it.
+     * In order to support this properly in WineD3D we need the ability to recreate the opengl context and
+     * drawable when this is required. This is very tricky as we need to reapply ALL opengl states for the new
+     * context, need torecreate shaders, textures and other resources.
+     *
+     * The context manager already takes care of the state problem and for the other tasks code from Reset
+     * can be used. These changes are way to risky during the 1.0 code freeze which is taking place right now.
+     * Likely a lot of other new bugs will be exposed. For that reason request a depth stencil surface all the
+     * time. It can cause a slight performance hit but fixes a lot of regressions. A fixme reminds of that this
+     * issue needs to be fixed. */
+    front_buffer = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0));
+    for (i = 0; i < (sizeof(formats) / sizeof(*formats)); i++)
+    {
+        swapchain->ds_format = wined3d_get_format(gl_info, formats[i]);
+        swapchain->context[0] = context_create(swapchain, front_buffer, swapchain->ds_format);
+        if (swapchain->context[0]) break;
+        TRACE("Depth stencil format %s is not supported, trying next format\n",
+                debug_d3dformat(formats[i]));
+    }
+
+    if (!swapchain->context[0])
+    {
+        WARN("Failed to create context.\n");
+        HeapFree(GetProcessHeap(), 0, swapchain->context);
+        swapchain->context = NULL;
+        return WINED3DERR_NOTAVAILABLE;
+    }
+
+    if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
+            && (!swapchain->desc.enable_auto_depth_stencil
+            || swapchain->desc.auto_depth_stencil_format != swapchain->ds_format->id))
+    {
+        FIXME("Add OpenGL context recreation support to context_validate_onscreen_formats\n");
+    }
+    context_release(swapchain->context[0]);
+
+    return WINED3D_OK;
+}
+
 static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3d_device *device,
         struct wined3d_swapchain_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops)
 {
@@ -840,60 +903,9 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
 
     if (!(device->wined3d->flags & WINED3D_NO3D))
     {
-        static const enum wined3d_format_id formats[] =
-        {
-            WINED3DFMT_D24_UNORM_S8_UINT,
-            WINED3DFMT_D32_UNORM,
-            WINED3DFMT_R24_UNORM_X8_TYPELESS,
-            WINED3DFMT_D16_UNORM,
-            WINED3DFMT_S1_UINT_D15_UNORM
-        };
-
-        const struct wined3d_gl_info *gl_info = &adapter->gl_info;
-
-        swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context));
-        if (!swapchain->context)
-        {
-            ERR("Failed to create the context array.\n");
-            hr = E_OUTOFMEMORY;
+        hr = wined3d_cs_emit_create_swapchain_context(device->cs, swapchain);
+        if (FAILED(hr))
             goto err;
-        }
-        swapchain->num_contexts = 1;
-
-        /* In WGL both color, depth and stencil are features of a pixel format. In case of D3D they are separate.
-         * You are able to add a depth + stencil surface at a later stage when you need it.
-         * In order to support this properly in WineD3D we need the ability to recreate the opengl context and
-         * drawable when this is required. This is very tricky as we need to reapply ALL opengl states for the new
-         * context, need torecreate shaders, textures and other resources.
-         *
-         * The context manager already takes care of the state problem and for the other tasks code from Reset
-         * can be used. These changes are way to risky during the 1.0 code freeze which is taking place right now.
-         * Likely a lot of other new bugs will be exposed. For that reason request a depth stencil surface all the
-         * time. It can cause a slight performance hit but fixes a lot of regressions. A fixme reminds of that this
-         * issue needs to be fixed. */
-        for (i = 0; i < (sizeof(formats) / sizeof(*formats)); i++)
-        {
-            swapchain->ds_format = wined3d_get_format(gl_info, formats[i]);
-            swapchain->context[0] = context_create(swapchain, front_buffer, swapchain->ds_format);
-            if (swapchain->context[0]) break;
-            TRACE("Depth stencil format %s is not supported, trying next format\n",
-                  debug_d3dformat(formats[i]));
-        }
-
-        if (!swapchain->context[0])
-        {
-            WARN("Failed to create context.\n");
-            hr = WINED3DERR_NOTAVAILABLE;
-            goto err;
-        }
-
-        if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
-                && (!desc->enable_auto_depth_stencil
-                || swapchain->desc.auto_depth_stencil_format != swapchain->ds_format->id))
-        {
-            FIXME("Add OpenGL context recreation support to context_validate_onscreen_formats\n");
-        }
-        context_release(swapchain->context[0]);
     }
 
     if (swapchain->desc.backbuffer_count > 0)
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index df99c6f..4f2e652 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2804,6 +2804,8 @@ void wined3d_cs_emit_volume_cleanup(struct wined3d_cs *cs, struct wined3d_volume
 void wined3d_cs_emit_surface_cleanup(struct wined3d_cs *cs, struct wined3d_surface *surface) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_texture_cleanup(struct wined3d_cs *cs, struct wined3d_texture *texture) DECLSPEC_HIDDEN;
 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;
 
 /* 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
@@ -2988,6 +2990,8 @@ struct wined3d_context *swapchain_get_context(struct wined3d_swapchain *swapchai
 void swapchain_destroy_contexts(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 HDC swapchain_get_backup_dc(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 void swapchain_update_draw_bindings(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
+HRESULT swapchain_create_context_cs(struct wined3d_device *device,
+        struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 
 /*****************************************************************************
  * Utility function prototypes
-- 
2.5.1

