From 4b5e47ede0b1ac538b6439e8b1888e4da542ceee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Sun, 7 Apr 2013 17:33:20 +0200
Subject: wined3d: Send base vertex index updates through the cs

---
 dlls/wined3d/cs.c              | 49 ++++++++++++++++++++++++++++++++++++++----
 dlls/wined3d/device.c          | 17 +++------------
 dlls/wined3d/wined3d_private.h |  2 ++
 3 files changed, 50 insertions(+), 18 deletions(-)

diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index 236e2f2..0525a59 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -66,6 +66,7 @@ enum wined3d_cs_op
     WINED3D_CS_OP_SET_VS_CONSTS_F,
     WINED3D_CS_OP_SET_PS_CONSTS_F,
     WINED3D_CS_OP_GLFINISH,
+    WINED3D_CS_OP_SET_BASE_VERTEX_INDEX,
     WINED3D_CS_OP_STOP,
 };
 
@@ -290,6 +291,12 @@ struct wined3d_cs_finish
     enum wined3d_cs_op opcode;
 };
 
+struct wined3d_cs_set_base_vertex_index
+{
+    enum wined3d_cs_op opcode;
+    UINT base_vertex_index;
+};
+
 /* FIXME: The list synchronization probably isn't particularly fast. */
 static void wined3d_cs_list_enqueue(struct wined3d_cs_list *list, struct wined3d_cs_block *block)
 {
@@ -504,6 +511,21 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *
 static UINT wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data)
 {
     const struct wined3d_cs_draw *op = data;
+    const struct wined3d_gl_info *gl_info = &cs->device->adapter->gl_info;
+
+    if (op->indexed && !gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
+    {
+        if (cs->state.load_base_vertex_index != cs->state.base_vertex_index)
+        {
+            cs->state.load_base_vertex_index = cs->state.base_vertex_index;
+            device_invalidate_state(cs->device, STATE_BASEVERTEXINDEX);
+        }
+    }
+    else if (cs->state.load_base_vertex_index)
+    {
+        cs->state.load_base_vertex_index = 0;
+        device_invalidate_state(cs->device, STATE_BASEVERTEXINDEX);
+    }
 
     draw_primitive(cs->device, &cs->state, op->start_idx, op->index_count,
             op->start_instance, op->instance_count, op->indexed);
@@ -931,8 +953,6 @@ static UINT wined3d_cs_exec_transfer_stateblock(struct wined3d_cs *cs, const voi
     /* Don't memcpy the entire struct, we'll remove single items as we add dedicated
      * ops for setting states */
 
-    cs->state.base_vertex_index = op->state.base_vertex_index;
-    cs->state.load_base_vertex_index = op->state.load_base_vertex_index;
     cs->state.gl_primitive_type = op->state.gl_primitive_type;
 
     memcpy(cs->state.vs_consts_b, op->state.vs_consts_b, sizeof(cs->state.vs_consts_b));
@@ -955,8 +975,6 @@ void wined3d_cs_emit_transfer_stateblock(struct wined3d_cs *cs, const struct win
 
     /* Don't memcpy the entire struct, we'll remove single items as we add dedicated
      * ops for setting states */
-    op->state.base_vertex_index = state->base_vertex_index;
-    op->state.load_base_vertex_index = state->load_base_vertex_index;
     op->state.gl_primitive_type = state->gl_primitive_type;
 
     memcpy(op->state.vs_consts_b, state->vs_consts_b, sizeof(op->state.vs_consts_b));
@@ -1281,6 +1299,28 @@ void wined3d_cs_emit_glfinish(struct wined3d_cs *cs)
     cs->ops->submit(cs);
 }
 
+static UINT wined3d_cs_exec_set_base_vertex_index(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_set_base_vertex_index *op = data;
+
+    cs->state.base_vertex_index = op->base_vertex_index;
+    device_invalidate_state(cs->device, STATE_BASEVERTEXINDEX);
+
+    return sizeof(*op);
+}
+
+void wined3d_cs_emit_set_base_vertex_index(struct wined3d_cs *cs,
+        UINT base_vertex_index)
+{
+    struct wined3d_cs_set_base_vertex_index *op;
+
+    op = cs->ops->require_space(cs, sizeof(*op));
+    op->opcode = WINED3D_CS_OP_SET_BASE_VERTEX_INDEX;
+    op->base_vertex_index = base_vertex_index;
+
+    cs->ops->submit(cs);
+}
+
 static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) =
 {
     /* WINED3D_CS_OP_FENCE                      */ wined3d_cs_exec_fence,
@@ -1313,6 +1353,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
     /* WINED3D_CS_OP_SET_VS_CONSTS_F            */ wined3d_cs_exec_set_vs_consts_f,
     /* WINED3D_CS_OP_SET_PS_CONSTS_F            */ wined3d_cs_exec_set_ps_consts_f,
     /* WINED3D_CS_OP_GLFINISH                   */ wined3d_cs_exec_glfinish,
+    /* WINED3D_CS_OP_SET_BASE_VERTEX_INDEX      */ wined3d_cs_exec_set_base_vertex_index,
 };
 
 static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index dfc0619..a80784b 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1830,6 +1830,9 @@ void CDECL wined3d_device_set_base_vertex_index(struct wined3d_device *device, I
     TRACE("device %p, base_index %d.\n", device, base_index);
 
     device->update_state->base_vertex_index = base_index;
+
+    if (!device->recording)
+        wined3d_cs_emit_set_base_vertex_index(device->cs, base_index);
 }
 
 INT CDECL wined3d_device_get_base_vertex_index(const struct wined3d_device *device)
@@ -3377,12 +3380,6 @@ HRESULT CDECL wined3d_device_draw_primitive(struct wined3d_device *device, UINT
         return WINED3DERR_INVALIDCALL;
     }
 
-    if (device->state.load_base_vertex_index)
-    {
-        device->state.load_base_vertex_index = 0;
-        device_invalidate_state(device, STATE_BASEVERTEXINDEX);
-    }
-
     wined3d_cs_emit_transfer_stateblock(device->cs, &device->state);
     wined3d_cs_emit_draw(device->cs, start_vertex, vertex_count, 0, 0, FALSE);
 
@@ -3391,8 +3388,6 @@ HRESULT CDECL wined3d_device_draw_primitive(struct wined3d_device *device, UINT
 
 HRESULT CDECL wined3d_device_draw_indexed_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count)
 {
-    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
-
     TRACE("device %p, start_idx %u, index_count %u.\n", device, start_idx, index_count);
 
     if (!device->state.index_buffer)
@@ -3411,12 +3406,6 @@ HRESULT CDECL wined3d_device_draw_indexed_primitive(struct wined3d_device *devic
         return WINED3DERR_INVALIDCALL;
     }
 
-    if (!gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX] &&
-        device->state.load_base_vertex_index != device->state.base_vertex_index)
-    {
-        device->state.load_base_vertex_index = device->state.base_vertex_index;
-        device_invalidate_state(device, STATE_BASEVERTEXINDEX);
-    }
 
     wined3d_cs_emit_transfer_stateblock(device->cs, &device->state);
     wined3d_cs_emit_draw(device->cs, start_idx, index_count, 0, 0, TRUE);
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index e4dbd9d..382c120 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2616,6 +2616,8 @@ void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_vi
 void wined3d_cs_emit_set_consts_f(struct wined3d_cs *cs, UINT start_register, const float *constants,
         UINT vector4f_count, enum wined3d_shader_type type) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_glfinish(struct wined3d_cs *cs) DECLSPEC_HIDDEN;
+void wined3d_cs_emit_set_base_vertex_index(struct wined3d_cs *cs,
+        UINT base_vertex_index) 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.1.3

