From 66a6fe6a092a4fa661e5baab52bbb2c1d7c661de Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Wed, 2 Oct 2013 21:47:08 +0200
Subject: wined3d: Create VBOs through the command stream.

A stop-gap solution to make fglrx happier until buffers are updated.
---
 dlls/wined3d/buffer.c          |  8 ++------
 dlls/wined3d/cs.c              | 32 ++++++++++++++++++++++++++++++++
 dlls/wined3d/wined3d_private.h |  3 +++
 3 files changed, 37 insertions(+), 6 deletions(-)

diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index 8f86a5b..a937b90 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -117,7 +117,7 @@ static void delete_gl_buffer(struct wined3d_buffer *This, const struct wined3d_g
 }
 
 /* Context activation is done by the caller. */
-static void buffer_create_buffer_object(struct wined3d_buffer *This, struct wined3d_context *context)
+void buffer_create_buffer_object(struct wined3d_buffer *This, struct wined3d_context *context)
 {
     GLenum gl_usage = GL_STATIC_DRAW_ARB;
     GLenum error;
@@ -185,8 +185,6 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This, struct wine
         ERR("glBufferData failed with error %s (%#x)\n", debug_glerror(error), error);
         goto fail;
     }
-    if (wined3d_settings.strict_draw_ordering || wined3d_settings.cs_multithreaded)
-        gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
 
     This->buffer_object_usage = gl_usage;
 
@@ -933,9 +931,7 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN
      * on buffer creation won't work either. */
     if (buffer->flags & WINED3D_BUFFER_CREATEBO)
     {
-        context = context_acquire(device, NULL);
-        buffer_create_buffer_object(buffer, context);
-        context_release(context);
+        wined3d_cs_emit_create_vbo(device->cs, buffer);
         buffer->flags &= ~WINED3D_BUFFER_CREATEBO;
     }
 
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index 59b9a9c..33a3b05 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -82,6 +82,7 @@ enum wined3d_cs_op
     WINED3D_CS_OP_VIEW_DESTROY,
     WINED3D_CS_OP_VDECL_DESTROY,
     WINED3D_CS_OP_SHADER_CLEANUP,
+    WINED3D_CS_OP_CREATE_VBO,
     WINED3D_CS_OP_STOP,
 };
 
@@ -480,6 +481,12 @@ struct wined3d_cs_shader_cleanup
     struct wined3d_shader *shader;
 };
 
+struct wined3d_cs_create_vbo
+{
+    enum wined3d_cs_op opcode;
+    struct wined3d_buffer *buffer;
+};
+
 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);
@@ -2421,6 +2428,30 @@ void wined3d_cs_emit_shader_cleanup(struct wined3d_cs *cs, struct wined3d_shader
     cs->ops->submit(cs, sizeof(*op));
 }
 
+static UINT wined3d_cs_exec_create_vbo(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_create_vbo *op = data;
+    struct wined3d_context *context = context_acquire(cs->device, NULL);
+
+    buffer_create_buffer_object(op->buffer, context);
+
+    context_release(context);
+
+    return sizeof(*op);
+}
+
+void wined3d_cs_emit_create_vbo(struct wined3d_cs *cs, struct wined3d_buffer *buffer)
+{
+    struct wined3d_cs_create_vbo *op;
+
+    op = cs->ops->require_space_prio(cs, sizeof(*op));
+    op->opcode = WINED3D_CS_OP_CREATE_VBO;
+    op->buffer = buffer;
+
+    cs->ops->submit_prio(cs, sizeof(*op));
+    cs->ops->finish_prio(cs);
+}
+
 static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) =
 {
     /* WINED3D_CS_OP_NOP                        */ wined3d_cs_exec_nop,
@@ -2481,6 +2512,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
     /* WINED3D_CS_OP_VIEW_DESTROY               */ wined3d_cs_exec_view_destroy,
     /* WINED3D_CS_OP_VDECL_DESTROY              */ wined3d_cs_exec_vertex_declaration_destroy,
     /* WINED3D_CS_OP_SHADER_CLEANUP             */ wined3d_cs_exec_shader_cleanup,
+    /* WINED3D_CS_OP_CREATE_VBO                 */ wined3d_cs_exec_create_vbo,
 };
 
 static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio)
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 9eb3c3a..4d5710a 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2822,6 +2822,7 @@ void wined3d_cs_emit_view_destroy(struct wined3d_cs *cs, struct wined3d_renderta
 void wined3d_cs_emit_vertex_declaration_destroy(struct wined3d_cs *cs,
         struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_shader_cleanup(struct wined3d_cs *cs, struct wined3d_shader *shader) DECLSPEC_HIDDEN;
+void wined3d_cs_emit_create_vbo(struct wined3d_cs *cs, struct wined3d_buffer *buffer) 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
@@ -2910,6 +2911,8 @@ void buffer_internal_preload(struct wined3d_buffer *buffer, struct wined3d_conte
         const struct wined3d_state *state) DECLSPEC_HIDDEN;
 void buffer_invalidate_bo_range(struct wined3d_buffer *This, UINT offset, UINT size) DECLSPEC_HIDDEN;
 void buffer_swap_mem(struct wined3d_buffer *buffer, BYTE *mem) DECLSPEC_HIDDEN;
+void buffer_create_buffer_object(struct wined3d_buffer *This,
+        struct wined3d_context *context) DECLSPEC_HIDDEN;
 HRESULT wined3d_buffer_upload_data(struct wined3d_buffer *buffer,
         const struct wined3d_box *box, const void *data) DECLSPEC_HIDDEN;
 
-- 
2.6.4

