From dafd31861ae6e86745ee61de2674528845af983b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Sat, 11 Jun 2011 16:18:45 +0200 Subject: [PATCH] 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 30d5b95bc2..6a1e6399d2 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 45ee89552d..d5a656e0b7 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -33,14 +33,24 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw); #include /* 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 6c6ae3a54d..632388c2af 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 44efb857fe..83fa40f751 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,