Stefan Dösinger : wined3d: Use GL_ARB_draw_elements_base_vertex if available.

Alexandre Julliard julliard at winehq.org
Tue Jun 14 11:57:47 CDT 2011


Module: wine
Branch: master
Commit: dafd31861ae6e86745ee61de2674528845af983b
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=dafd31861ae6e86745ee61de2674528845af983b

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Sat Jun 11 16:18:45 2011 +0200

wined3d: Use GL_ARB_draw_elements_base_vertex if available.

---

 dlls/wined3d/device.c          |   24 ++++++++++++++--------
 dlls/wined3d/drawprim.c        |   43 +++++++++++++++++++++++++++++----------
 dlls/wined3d/state.c           |    2 +
 dlls/wined3d/wined3d_private.h |    5 +++-
 4 files changed, 53 insertions(+), 21 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 30d5b95..6a1e639 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -2391,10 +2391,6 @@ HRESULT CDECL wined3d_device_set_base_vertex_index(struct wined3d_device *device
         TRACE("Recording... not performing anything\n");
         return WINED3D_OK;
     }
-
-    /* The base vertex index affects the stream sources */
-    device_invalidate_state(device, STATE_STREAMSRC);
-
     return WINED3D_OK;
 }
 
@@ -4092,7 +4088,7 @@ HRESULT CDECL wined3d_device_draw_primitive(struct wined3d_device *device, UINT
     if (device->stateBlock->state.load_base_vertex_index)
     {
         device->stateBlock->state.load_base_vertex_index = 0;
-        device_invalidate_state(device, STATE_STREAMSRC);
+        device_invalidate_state(device, STATE_BASEVERTEXINDEX);
     }
 
     /* Account for the loading offset due to index buffers. Instead of
@@ -4106,6 +4102,7 @@ HRESULT CDECL wined3d_device_draw_indexed_primitive(struct wined3d_device *devic
     struct wined3d_buffer *index_buffer;
     UINT index_size = 2;
     GLuint vbo;
+    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);
 
@@ -4138,10 +4135,11 @@ HRESULT CDECL wined3d_device_draw_indexed_primitive(struct wined3d_device *devic
     else
         index_size = 4;
 
-    if (device->stateBlock->state.load_base_vertex_index != device->stateBlock->state.base_vertex_index)
+    if (!gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX] &&
+        device->stateBlock->state.load_base_vertex_index != device->stateBlock->state.base_vertex_index)
     {
         device->stateBlock->state.load_base_vertex_index = device->stateBlock->state.base_vertex_index;
-        device_invalidate_state(device, STATE_STREAMSRC);
+        device_invalidate_state(device, STATE_BASEVERTEXINDEX);
     }
 
     drawPrimitive(device, index_count, start_idx, index_size,
@@ -4174,7 +4172,11 @@ HRESULT CDECL wined3d_device_draw_primitive_up(struct wined3d_device *device, UI
     stream->offset = 0;
     stream->stride = stream_stride;
     device->stateBlock->state.user_stream = TRUE;
-    device->stateBlock->state.load_base_vertex_index = 0;
+    if (device->stateBlock->state.load_base_vertex_index)
+    {
+        device->stateBlock->state.load_base_vertex_index = 0;
+        device_invalidate_state(device, STATE_BASEVERTEXINDEX);
+    }
 
     /* TODO: Only mark dirty if drawing from a different UP address */
     device_invalidate_state(device, STATE_STREAMSRC);
@@ -4224,7 +4226,11 @@ HRESULT CDECL wined3d_device_draw_indexed_primitive_up(struct wined3d_device *de
 
     /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
     device->stateBlock->state.base_vertex_index = 0;
-    device->stateBlock->state.load_base_vertex_index = 0;
+    if (device->stateBlock->state.load_base_vertex_index)
+    {
+        device->stateBlock->state.load_base_vertex_index = 0;
+        device_invalidate_state(device, STATE_BASEVERTEXINDEX);
+    }
     /* Mark the state dirty until we have nicer tracking of the stream source pointers */
     device_invalidate_state(device, STATE_VDECL);
     device_invalidate_state(device, STATE_INDEXBUFFER);
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 45ee895..d5a656e 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -33,14 +33,24 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw);
 #include <math.h>
 
 /* GL locking is done by the caller */
-static void drawStridedFast(GLenum primitive_type, UINT count, UINT idx_size, const void *idx_data, UINT start_idx)
+static void drawStridedFast(const struct wined3d_gl_info *gl_info, GLenum primitive_type, UINT count, UINT idx_size,
+        const void *idx_data, UINT start_idx, INT base_vertex_index)
 {
     if (idx_size)
     {
-        glDrawElements(primitive_type, count,
-                idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
-                (const char *)idx_data + (idx_size * start_idx));
-        checkGLcall("glDrawElements");
+        GLenum idxtype = idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
+        if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
+        {
+            GL_EXTCALL(glDrawElementsBaseVertex(primitive_type, count, idxtype,
+                    (const char *)idx_data + (idx_size * start_idx), base_vertex_index));
+            checkGLcall("glDrawElementsBaseVertex");
+        }
+        else
+        {
+            glDrawElements(primitive_type, count,
+                    idxtype, (const char *)idx_data + (idx_size * start_idx));
+            checkGLcall("glDrawElements");
+        }
     }
     else
     {
@@ -469,11 +479,12 @@ static void drawStridedSlowVs(const struct wined3d_gl_info *gl_info, const struc
 /* GL locking is done by the caller */
 static void drawStridedInstanced(const struct wined3d_gl_info *gl_info, const struct wined3d_state *state,
         const struct wined3d_stream_info *si, UINT numberOfVertices, GLenum glPrimitiveType,
-        const void *idxData, UINT idxSize, UINT startIdx)
+        const void *idxData, UINT idxSize, UINT startIdx, UINT base_vertex_index)
 {
     UINT numInstances = 0, i;
     int numInstancedAttribs = 0, j;
     UINT instancedData[sizeof(si->elements) / sizeof(*si->elements) /* 16 */];
+    GLenum idxtype = idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
 
     if (!idxSize)
     {
@@ -530,9 +541,18 @@ static void drawStridedInstanced(const struct wined3d_gl_info *gl_info, const st
             send_attribute(gl_info, si->elements[instancedData[j]].format->id, instancedData[j], ptr);
         }
 
-        glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
-                    (const char *)idxData+(idxSize * startIdx));
-        checkGLcall("glDrawElements");
+        if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
+        {
+            GL_EXTCALL(glDrawElementsBaseVertex(glPrimitiveType, numberOfVertices, idxtype,
+                        (const char *)idxData+(idxSize * startIdx), base_vertex_index));
+            checkGLcall("glDrawElementsBaseVertex");
+        }
+        else
+        {
+            glDrawElements(glPrimitiveType, numberOfVertices, idxtype,
+                        (const char *)idxData+(idxSize * startIdx));
+            checkGLcall("glDrawElements");
+        }
     }
 }
 
@@ -646,6 +666,7 @@ void drawPrimitive(struct wined3d_device *device, UINT index_count, UINT StartId
     ENTER_GL();
     {
         GLenum glPrimType = state->gl_primitive_type;
+        INT base_vertex_index = state->base_vertex_index;
         BOOL emulation = FALSE;
         const struct wined3d_stream_info *stream_info = &device->strided_streams;
         struct wined3d_stream_info stridedlcl;
@@ -711,11 +732,11 @@ void drawPrimitive(struct wined3d_device *device, UINT index_count, UINT StartId
         {
             /* Instancing emulation with mixing immediate mode and arrays */
             drawStridedInstanced(context->gl_info, state, stream_info,
-                    index_count, glPrimType, idxData, idxSize, StartIdx);
+                    index_count, glPrimType, idxData, idxSize, StartIdx, base_vertex_index);
         }
         else
         {
-            drawStridedFast(glPrimType, index_count, idxSize, idxData, StartIdx);
+            drawStridedFast(context->gl_info, glPrimType, index_count, idxSize, idxData, StartIdx, base_vertex_index);
         }
     }
 
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index 6c6ae3a..632388c 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -5062,6 +5062,8 @@ const struct StateEntryTemplate misc_state_template[] = {
     { STATE_SAMPLER(17), /* Vertex sampler 1 */           { STATE_SAMPLER(17),                                  sampler             }, WINED3D_GL_EXT_NONE             },
     { STATE_SAMPLER(18), /* Vertex sampler 2 */           { STATE_SAMPLER(18),                                  sampler             }, WINED3D_GL_EXT_NONE             },
     { STATE_SAMPLER(19), /* Vertex sampler 3 */           { STATE_SAMPLER(19),                                  sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_BASEVERTEXINDEX,                              { 0,                                                  NULL,               }, ARB_DRAW_ELEMENTS_BASE_VERTEX   },
+    { STATE_BASEVERTEXINDEX,                              { STATE_STREAMSRC,                                    NULL,               }, WINED3D_GL_EXT_NONE             },
     {0 /* Terminate */,                                   { 0,                                                  0                   }, WINED3D_GL_EXT_NONE             },
 };
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 44efb85..83fa40f 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -995,7 +995,10 @@ extern glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT] DECLSPEC
 #define STATE_POINTSPRITECOORDORIGIN  (STATE_FRONTFACE + 1)
 #define STATE_IS_POINTSPRITECOORDORIGIN(a) ((a) == STATE_POINTSPRITECOORDORIGIN)
 
-#define STATE_HIGHEST (STATE_POINTSPRITECOORDORIGIN)
+#define STATE_BASEVERTEXINDEX  (STATE_POINTSPRITECOORDORIGIN + 1)
+#define STATE_IS_BASEVERTEXINDEX(a) ((a) == STATE_BASEVERTEXINDEX)
+
+#define STATE_HIGHEST (STATE_BASEVERTEXINDEX)
 
 enum fogsource {
     FOGSOURCE_FFP,




More information about the wine-cvs mailing list