X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fvbo%2Fvbo_exec_array.c;h=58bba208db10d79a63cc06fb23cff386dcb730ba;hb=fb6dc8e8945117cfc9f8e1d8a5f27137a6bb902d;hp=507821ee52c6444fba3acdf7b86511a02ecc15c9;hpb=3bbf8d9042c93d410666c94e078f852cccc330ea;p=mesa.git diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index 507821ee52c..58bba208db1 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -31,7 +31,7 @@ #include "main/glheader.h" #include "main/context.h" #include "main/state.h" -#include "main/api_validate.h" +#include "main/draw_validate.h" #include "main/dispatch.h" #include "main/varray.h" #include "main/bufferobj.h" @@ -39,7 +39,20 @@ #include "main/macros.h" #include "main/transformfeedback.h" -#include "vbo_context.h" +typedef struct { + GLuint count; + GLuint primCount; + GLuint first; + GLuint baseInstance; +} DrawArraysIndirectCommand; + +typedef struct { + GLuint count; + GLuint primCount; + GLuint firstIndex; + GLint baseVertex; + GLuint baseInstance; +} DrawElementsIndirectCommand; /** @@ -284,16 +297,34 @@ print_draw_arrays(struct gl_context *ctx, MAP_INTERNAL); int offset = (int) (GLintptr) _mesa_vertex_attrib_address(array, binding); + + unsigned multiplier; + switch (array->Type) { + case GL_DOUBLE: + case GL_INT64_ARB: + case GL_UNSIGNED_INT64_ARB: + multiplier = 2; + break; + default: + multiplier = 1; + } + float *f = (float *) (p + offset); int *k = (int *) f; - int i; - int n = (count * binding->Stride) / 4; + int i = 0; + int n = (count - 1) * (binding->Stride / (4 * multiplier)) + + array->Size; if (n > 32) n = 32; printf(" Data at offset %d:\n", offset); - for (i = 0; i < n; i++) { - printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]); - } + do { + if (multiplier == 2) + printf(" double[%d] = 0x%016llx %lf\n", i, + ((unsigned long long *) k)[i], ((double *) f)[i]); + else + printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]); + i++; + } while (i < n); ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_INTERNAL); } } @@ -301,168 +332,43 @@ print_draw_arrays(struct gl_context *ctx, /** - * Set the vbo->exec->inputs[] pointers to point to the enabled - * vertex arrays. This depends on the current vertex program/shader - * being executed because of whether or not generic vertex arrays - * alias the conventional vertex arrays. - * For arrays that aren't enabled, we set the input[attrib] pointer - * to point at a zero-stride current value "array". + * Return a filter mask for the net enabled vao arrays. + * This is to mask out arrays that would otherwise supersed required current + * values for the fixed function shaders for example. */ -static void -recalculate_input_bindings(struct gl_context *ctx) +static GLbitfield +enabled_filter(const struct gl_context *ctx) { - struct vbo_context *vbo = vbo_context(ctx); - struct vbo_exec_context *exec = &vbo->exec; - const struct gl_array_attributes *array = ctx->Array.VAO->VertexAttrib; - struct gl_vertex_array *vertexAttrib = ctx->Array.VAO->_VertexAttrib; - const struct gl_vertex_array **inputs = &exec->array.inputs[0]; - GLbitfield const_inputs = 0x0; - GLuint i; - - switch (get_program_mode(ctx)) { - case VP_NONE: + switch (ctx->VertexProgram._VPMode) { + case VP_MODE_FF: /* When no vertex program is active (or the vertex program is generated * from fixed-function state). We put the material values into the - * generic slots. This is the only situation where material values - * are available as per-vertex attributes. + * generic slots. Since the vao has no material arrays, mute these + * slots from the enabled arrays so that the current material values + * are pulled instead of the vao arrays. */ - for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) { - if (array[VERT_ATTRIB_FF(i)].Enabled) - inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)]; - else { - inputs[i] = &vbo->currval[VBO_ATTRIB_POS + i]; - const_inputs |= VERT_BIT(i); - } - } + return VERT_BIT_FF_ALL; - for (i = 0; i < MAT_ATTRIB_MAX; i++) { - inputs[VERT_ATTRIB_GENERIC(i)] = - &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT + i]; - const_inputs |= VERT_BIT_GENERIC(i); - } - - /* Could use just about anything, just to fill in the empty - * slots: - */ - for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_GENERIC_MAX; i++) { - inputs[VERT_ATTRIB_GENERIC(i)] = - &vbo->currval[VBO_ATTRIB_GENERIC0 + i]; - const_inputs |= VERT_BIT_GENERIC(i); - } - break; - - case VP_ARB: + case VP_MODE_SHADER: /* There are no shaders in OpenGL ES 1.x, so this code path should be * impossible to reach. The meta code is careful to not use shaders in * ES1. */ assert(ctx->API != API_OPENGLES); - /* In the compatibility profile of desktop OpenGL, the generic[0] - * attribute array aliases and overrides the legacy position array. - * Otherwise, legacy attributes available in the legacy slots, - * generic attributes in the generic slots and materials are not - * available as per-vertex attributes. - * - * In all other APIs, only the generic attributes exist, and none of the - * slots are considered "magic." + /* Other parts of the code assume that inputs[VERT_ATTRIB_POS] through + * inputs[VERT_ATTRIB_FF_MAX] will be non-NULL. However, in OpenGL + * ES 2.0+ or OpenGL core profile, none of these arrays should ever + * be enabled. */ - if (ctx->API == API_OPENGL_COMPAT) { - if (array[VERT_ATTRIB_GENERIC0].Enabled) - inputs[0] = &vertexAttrib[VERT_ATTRIB_GENERIC0]; - else if (array[VERT_ATTRIB_POS].Enabled) - inputs[0] = &vertexAttrib[VERT_ATTRIB_POS]; - else { - inputs[0] = &vbo->currval[VBO_ATTRIB_GENERIC0]; - const_inputs |= VERT_BIT_POS; - } + if (ctx->API != API_OPENGL_COMPAT) + return VERT_BIT_GENERIC_ALL; - for (i = 1; i < VERT_ATTRIB_FF_MAX; i++) { - if (array[VERT_ATTRIB_FF(i)].Enabled) - inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)]; - else { - inputs[i] = &vbo->currval[VBO_ATTRIB_POS + i]; - const_inputs |= VERT_BIT_FF(i); - } - } + return VERT_BIT_ALL; - for (i = 1; i < VERT_ATTRIB_GENERIC_MAX; i++) { - if (array[VERT_ATTRIB_GENERIC(i)].Enabled) - inputs[VERT_ATTRIB_GENERIC(i)] = - &vertexAttrib[VERT_ATTRIB_GENERIC(i)]; - else { - inputs[VERT_ATTRIB_GENERIC(i)] = - &vbo->currval[VBO_ATTRIB_GENERIC0 + i]; - const_inputs |= VERT_BIT_GENERIC(i); - } - } - - inputs[VERT_ATTRIB_GENERIC0] = inputs[0]; - } else { - /* Other parts of the code assume that inputs[0] through - * inputs[VERT_ATTRIB_FF_MAX] will be non-NULL. However, in OpenGL - * ES 2.0+ or OpenGL core profile, none of these arrays should ever - * be enabled. - */ - for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) { - assert(!array[VERT_ATTRIB_FF(i)].Enabled); - - inputs[i] = &vbo->currval[VBO_ATTRIB_POS + i]; - const_inputs |= VERT_BIT_FF(i); - } - - for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) { - if (array[VERT_ATTRIB_GENERIC(i)].Enabled) - inputs[VERT_ATTRIB_GENERIC(i)] = - &vertexAttrib[VERT_ATTRIB_GENERIC(i)]; - else { - inputs[VERT_ATTRIB_GENERIC(i)] = - &vbo->currval[VBO_ATTRIB_GENERIC0 + i]; - const_inputs |= VERT_BIT_GENERIC(i); - } - } - } - - break; - } - - _mesa_set_varying_vp_inputs(ctx, VERT_BIT_ALL & (~const_inputs)); - ctx->NewDriverState |= ctx->DriverFlags.NewArray; -} - - -/** - * Examine the enabled vertex arrays to set the exec->array.inputs[] values. - * These will point to the arrays to actually use for drawing. Some will - * be user-provided arrays, other will be zero-stride const-valued arrays. - * Note that this might set the _NEW_VARYING_VP_INPUTS dirty flag so state - * validation must be done after this call. - */ -static void -vbo_bind_arrays(struct gl_context *ctx) -{ - struct vbo_context *vbo = vbo_context(ctx); - struct vbo_exec_context *exec = &vbo->exec; - - vbo_draw_method(vbo, DRAW_ARRAYS); - - if (exec->array.recalculate_inputs) { - recalculate_input_bindings(ctx); - exec->array.recalculate_inputs = GL_FALSE; - - /* Again... because we may have changed the bitmask of per-vertex varying - * attributes. If we regenerate the fixed-function vertex program now - * we may be able to prune down the number of vertex attributes which we - * need in the shader. - */ - if (ctx->NewState) { - /* Setting "validating" to TRUE prevents _mesa_update_state from - * invalidating what we just did. - */ - exec->validating = GL_TRUE; - _mesa_update_state(ctx); - exec->validating = GL_FALSE; - } + default: + assert(0); + return 0; } } @@ -478,14 +384,11 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start, GLsizei count, GLuint numInstances, GLuint baseInstance, GLuint drawID) { - struct vbo_context *vbo = vbo_context(ctx); struct _mesa_prim prim; if (skip_validated_draw(ctx)) return; - vbo_bind_arrays(ctx); - /* OpenGL 4.5 says that primitive restart is ignored with non-indexed * draws. */ @@ -500,8 +403,8 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start, prim.start = start; prim.count = count; - vbo->draw_prims(ctx, &prim, 1, NULL, - GL_TRUE, start, start + count - 1, NULL, 0, NULL); + ctx->Driver.Draw(ctx, &prim, 1, NULL, + GL_TRUE, start, start + count - 1, NULL, 0, NULL); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); @@ -642,12 +545,16 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count) _mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n", _mesa_enum_to_string(mode), start, count); + FLUSH_FOR_DRAW(ctx); + if (_mesa_is_no_error_enabled(ctx)) { - FLUSH_CURRENT(ctx, 0); + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); if (ctx->NewState) _mesa_update_state(ctx); } else { + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); + if (!_mesa_validate_DrawArrays(ctx, mode, count)) return; } @@ -676,13 +583,16 @@ vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count, _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n", _mesa_enum_to_string(mode), start, count, numInstances); + FLUSH_FOR_DRAW(ctx); if (_mesa_is_no_error_enabled(ctx)) { - FLUSH_CURRENT(ctx, 0); + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); if (ctx->NewState) _mesa_update_state(ctx); } else { + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); + if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, numInstances)) return; @@ -714,12 +624,16 @@ vbo_exec_DrawArraysInstancedBaseInstance(GLenum mode, GLint first, _mesa_enum_to_string(mode), first, count, numInstances, baseInstance); + FLUSH_FOR_DRAW(ctx); + if (_mesa_is_no_error_enabled(ctx)) { - FLUSH_CURRENT(ctx, 0); + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); if (ctx->NewState) _mesa_update_state(ctx); } else { + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); + if (!_mesa_validate_DrawArraysInstanced(ctx, mode, first, count, numInstances)) return; @@ -750,12 +664,16 @@ vbo_exec_MultiDrawArrays(GLenum mode, const GLint *first, "glMultiDrawArrays(%s, %p, %p, %d)\n", _mesa_enum_to_string(mode), first, count, primcount); + FLUSH_FOR_DRAW(ctx); + if (_mesa_is_no_error_enabled(ctx)) { - FLUSH_CURRENT(ctx, 0); + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); if (ctx->NewState) _mesa_update_state(ctx); } else { + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); + if (!_mesa_validate_MultiDrawArrays(ctx, mode, count, primcount)) return; } @@ -875,7 +793,6 @@ vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode, GLint basevertex, GLuint numInstances, GLuint baseInstance) { - struct vbo_context *vbo = vbo_context(ctx); struct _mesa_index_buffer ib; struct _mesa_prim prim; @@ -887,8 +804,6 @@ vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode, if (skip_draw_elements(ctx, count, indices)) return; - vbo_bind_arrays(ctx); - ib.count = count; ib.index_size = sizeof_ib_type(type); ib.obj = ctx->Array.VAO->IndexBufferObj; @@ -939,8 +854,8 @@ vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode, * for the latter case elsewhere. */ - vbo->draw_prims(ctx, &prim, 1, &ib, - index_bounds_valid, start, end, NULL, 0, NULL); + ctx->Driver.Draw(ctx, &prim, 1, &ib, + index_bounds_valid, start, end, NULL, 0, NULL); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); @@ -972,12 +887,16 @@ vbo_exec_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, _mesa_enum_to_string(mode), start, end, count, _mesa_enum_to_string(type), indices, basevertex); + FLUSH_FOR_DRAW(ctx); + if (_mesa_is_no_error_enabled(ctx)) { - FLUSH_CURRENT(ctx, 0); + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); if (ctx->NewState) _mesa_update_state(ctx); } else { + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); + if (!_mesa_validate_DrawRangeElements(ctx, mode, start, end, count, type, indices)) return; @@ -1079,12 +998,16 @@ vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, _mesa_enum_to_string(mode), count, _mesa_enum_to_string(type), indices); + FLUSH_FOR_DRAW(ctx); + if (_mesa_is_no_error_enabled(ctx)) { - FLUSH_CURRENT(ctx, 0); + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); if (ctx->NewState) _mesa_update_state(ctx); } else { + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); + if (!_mesa_validate_DrawElements(ctx, mode, count, type, indices)) return; } @@ -1108,12 +1031,16 @@ vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, _mesa_enum_to_string(mode), count, _mesa_enum_to_string(type), indices); + FLUSH_FOR_DRAW(ctx); + if (_mesa_is_no_error_enabled(ctx)) { - FLUSH_CURRENT(ctx, 0); + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); if (ctx->NewState) _mesa_update_state(ctx); } else { + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); + if (!_mesa_validate_DrawElements(ctx, mode, count, type, indices)) return; } @@ -1137,12 +1064,16 @@ vbo_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, _mesa_enum_to_string(mode), count, _mesa_enum_to_string(type), indices); + FLUSH_FOR_DRAW(ctx); + if (_mesa_is_no_error_enabled(ctx)) { - FLUSH_CURRENT(ctx, 0); + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); if (ctx->NewState) _mesa_update_state(ctx); } else { + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); + if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices, numInstances)) return; @@ -1172,12 +1103,16 @@ vbo_exec_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, _mesa_enum_to_string(type), indices, numInstances, basevertex); + FLUSH_FOR_DRAW(ctx); + if (_mesa_is_no_error_enabled(ctx)) { - FLUSH_CURRENT(ctx, 0); + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); if (ctx->NewState) _mesa_update_state(ctx); } else { + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); + if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices, numInstances)) return; @@ -1209,12 +1144,16 @@ vbo_exec_DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, _mesa_enum_to_string(type), indices, numInstances, baseInstance); + FLUSH_FOR_DRAW(ctx); + if (_mesa_is_no_error_enabled(ctx)) { - FLUSH_CURRENT(ctx, 0); + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); if (ctx->NewState) _mesa_update_state(ctx); } else { + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); + if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices, numInstances)) return; @@ -1248,12 +1187,16 @@ vbo_exec_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, _mesa_enum_to_string(type), indices, numInstances, basevertex, baseInstance); + FLUSH_FOR_DRAW(ctx); + if (_mesa_is_no_error_enabled(ctx)) { - FLUSH_CURRENT(ctx, 0); + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); if (ctx->NewState) _mesa_update_state(ctx); } else { + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); + if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices, numInstances)) return; @@ -1276,7 +1219,6 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode, const GLvoid * const *indices, GLsizei primcount, const GLint *basevertex) { - struct vbo_context *vbo = vbo_context(ctx); struct _mesa_index_buffer ib; struct _mesa_prim *prim; unsigned int index_type_size = sizeof_ib_type(type); @@ -1293,8 +1235,6 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode, return; } - vbo_bind_arrays(ctx); - min_index_ptr = (uintptr_t) indices[0]; max_index_ptr = 0; for (i = 0; i < primcount; i++) { @@ -1362,8 +1302,8 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode, prim[i].basevertex = 0; } - vbo->draw_prims(ctx, prim, primcount, &ib, - false, 0, ~0, NULL, 0, NULL); + ctx->Driver.Draw(ctx, prim, primcount, &ib, + false, 0, ~0, NULL, 0, NULL); } else { /* render one prim at a time */ @@ -1392,7 +1332,7 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode, else prim[0].basevertex = 0; - vbo->draw_prims(ctx, prim, 1, &ib, false, 0, ~0, NULL, 0, NULL); + ctx->Driver.Draw(ctx, prim, 1, &ib, false, 0, ~0, NULL, 0, NULL); } } @@ -1411,6 +1351,10 @@ vbo_exec_MultiDrawElements(GLenum mode, { GET_CURRENT_CONTEXT(ctx); + FLUSH_FOR_DRAW(ctx); + + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); + if (!_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices, primcount)) return; @@ -1432,12 +1376,16 @@ vbo_exec_MultiDrawElementsBaseVertex(GLenum mode, { GET_CURRENT_CONTEXT(ctx); + FLUSH_FOR_DRAW(ctx); + if (_mesa_is_no_error_enabled(ctx)) { - FLUSH_CURRENT(ctx, 0); + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); if (ctx->NewState) _mesa_update_state(ctx); } else { + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); + if (!_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices, primcount)) return; @@ -1451,20 +1399,31 @@ vbo_exec_MultiDrawElementsBaseVertex(GLenum mode, } +/** + * Draw a GL primitive using a vertex count obtained from transform feedback. + * \param mode the type of GL primitive to draw + * \param obj the transform feedback object to use + * \param stream index of the transform feedback stream from which to + * get the primitive count. + * \param numInstances number of instances to draw + */ static void vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode, struct gl_transform_feedback_object *obj, GLuint stream, GLuint numInstances) { - struct vbo_context *vbo = vbo_context(ctx); struct _mesa_prim prim; + FLUSH_FOR_DRAW(ctx); + if (_mesa_is_no_error_enabled(ctx)) { - FLUSH_CURRENT(ctx, 0); + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); if (ctx->NewState) _mesa_update_state(ctx); } else { + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); + if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj, stream, numInstances)) { return; @@ -1483,8 +1442,6 @@ vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode, if (skip_validated_draw(ctx)) return; - vbo_bind_arrays(ctx); - /* init most fields to zero */ memset(&prim, 0, sizeof(prim)); prim.begin = 1; @@ -1498,7 +1455,7 @@ vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode, * (like in DrawArrays), but we have no way to know how many vertices * will be rendered. */ - vbo->draw_prims(ctx, &prim, 1, NULL, GL_FALSE, 0, ~0, obj, stream, NULL); + ctx->Driver.Draw(ctx, &prim, 1, NULL, GL_FALSE, 0, ~0, obj, stream, NULL); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); @@ -1582,11 +1539,7 @@ static void vbo_validated_drawarraysindirect(struct gl_context *ctx, GLenum mode, const GLvoid *indirect) { - struct vbo_context *vbo = vbo_context(ctx); - - vbo_bind_arrays(ctx); - - vbo->draw_indirect_prims(ctx, mode, + ctx->Driver.DrawIndirect(ctx, mode, ctx->DrawIndirectBuffer, (GLsizeiptr) indirect, 1 /* draw_count */ , 16 /* stride */ , NULL, 0, NULL); @@ -1602,15 +1555,12 @@ vbo_validated_multidrawarraysindirect(struct gl_context *ctx, const GLvoid *indirect, GLsizei primcount, GLsizei stride) { - struct vbo_context *vbo = vbo_context(ctx); GLsizeiptr offset = (GLsizeiptr) indirect; if (primcount == 0) return; - vbo_bind_arrays(ctx); - - vbo->draw_indirect_prims(ctx, mode, ctx->DrawIndirectBuffer, offset, + ctx->Driver.DrawIndirect(ctx, mode, ctx->DrawIndirectBuffer, offset, primcount, stride, NULL, 0, NULL); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) @@ -1623,17 +1573,14 @@ vbo_validated_drawelementsindirect(struct gl_context *ctx, GLenum mode, GLenum type, const GLvoid *indirect) { - struct vbo_context *vbo = vbo_context(ctx); struct _mesa_index_buffer ib; - vbo_bind_arrays(ctx); - ib.count = 0; /* unknown */ ib.index_size = sizeof_ib_type(type); ib.obj = ctx->Array.VAO->IndexBufferObj; ib.ptr = NULL; - vbo->draw_indirect_prims(ctx, mode, + ctx->Driver.DrawIndirect(ctx, mode, ctx->DrawIndirectBuffer, (GLsizeiptr) indirect, 1 /* draw_count */ , 20 /* stride */ , NULL, 0, &ib); @@ -1649,15 +1596,12 @@ vbo_validated_multidrawelementsindirect(struct gl_context *ctx, const GLvoid *indirect, GLsizei primcount, GLsizei stride) { - struct vbo_context *vbo = vbo_context(ctx); struct _mesa_index_buffer ib; GLsizeiptr offset = (GLsizeiptr) indirect; if (primcount == 0) return; - vbo_bind_arrays(ctx); - /* NOTE: IndexBufferObj is guaranteed to be a VBO. */ ib.count = 0; /* unknown */ @@ -1665,7 +1609,7 @@ vbo_validated_multidrawelementsindirect(struct gl_context *ctx, ib.obj = ctx->Array.VAO->IndexBufferObj; ib.ptr = NULL; - vbo->draw_indirect_prims(ctx, mode, + ctx->Driver.DrawIndirect(ctx, mode, ctx->DrawIndirectBuffer, offset, primcount, stride, NULL, 0, &ib); @@ -1687,12 +1631,33 @@ vbo_exec_DrawArraysIndirect(GLenum mode, const GLvoid *indirect) _mesa_debug(ctx, "glDrawArraysIndirect(%s, %p)\n", _mesa_enum_to_string(mode), indirect); + /* From the ARB_draw_indirect spec: + * + * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the + * compatibility profile, this indicates that DrawArraysIndirect and + * DrawElementsIndirect are to source their arguments directly from the + * pointer passed as their parameters." + */ + if (ctx->API == API_OPENGL_COMPAT && + !_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) { + DrawArraysIndirectCommand *cmd = (DrawArraysIndirectCommand *) indirect; + + vbo_exec_DrawArraysInstancedBaseInstance(mode, cmd->first, cmd->count, + cmd->primCount, + cmd->baseInstance); + return; + } + + FLUSH_FOR_DRAW(ctx); + if (_mesa_is_no_error_enabled(ctx)) { - FLUSH_CURRENT(ctx, 0); + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); if (ctx->NewState) _mesa_update_state(ctx); } else { + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); + if (!_mesa_validate_DrawArraysIndirect(ctx, mode, indirect)) return; } @@ -1714,12 +1679,53 @@ vbo_exec_DrawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect) _mesa_enum_to_string(mode), _mesa_enum_to_string(type), indirect); + /* From the ARB_draw_indirect spec: + * + * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the + * compatibility profile, this indicates that DrawArraysIndirect and + * DrawElementsIndirect are to source their arguments directly from the + * pointer passed as their parameters." + */ + if (ctx->API == API_OPENGL_COMPAT && + !_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) { + /* + * Unlike regular DrawElementsInstancedBaseVertex commands, the indices + * may not come from a client array and must come from an index buffer. + * If no element array buffer is bound, an INVALID_OPERATION error is + * generated. + */ + if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawElementsIndirect(no buffer bound " + "to GL_ELEMENT_ARRAY_BUFFER)"); + } else { + DrawElementsIndirectCommand *cmd = + (DrawElementsIndirectCommand *) indirect; + + /* Convert offset to pointer */ + void *offset = (void *) + ((cmd->firstIndex * _mesa_sizeof_type(type)) & 0xffffffffUL); + + vbo_exec_DrawElementsInstancedBaseVertexBaseInstance(mode, cmd->count, + type, offset, + cmd->primCount, + cmd->baseVertex, + cmd->baseInstance); + } + + return; + } + + FLUSH_FOR_DRAW(ctx); + if (_mesa_is_no_error_enabled(ctx)) { - FLUSH_CURRENT(ctx, 0); + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); if (ctx->NewState) _mesa_update_state(ctx); } else { + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); + if (!_mesa_validate_DrawElementsIndirect(ctx, mode, type, indirect)) return; } @@ -1743,14 +1749,49 @@ vbo_exec_MultiDrawArraysIndirect(GLenum mode, const GLvoid *indirect, /* If is zero, the array elements are treated as tightly packed. */ if (stride == 0) - stride = 4 * sizeof(GLuint); /* sizeof(DrawArraysIndirectCommand) */ + stride = sizeof(DrawArraysIndirectCommand); + + /* From the ARB_draw_indirect spec: + * + * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the + * compatibility profile, this indicates that DrawArraysIndirect and + * DrawElementsIndirect are to source their arguments directly from the + * pointer passed as their parameters." + */ + if (ctx->API == API_OPENGL_COMPAT && + !_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) { + + if (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride, + "glMultiDrawArraysIndirect")) + return; + + const ubyte *ptr = (const ubyte *) indirect; + for (unsigned i = 0; i < primcount; i++) { + DrawArraysIndirectCommand *cmd = (DrawArraysIndirectCommand *) ptr; + vbo_exec_DrawArraysInstancedBaseInstance(mode, cmd->first, + cmd->count, cmd->primCount, + cmd->baseInstance); + + if (stride == 0) { + ptr += sizeof(DrawArraysIndirectCommand); + } else { + ptr += stride; + } + } + + return; + } + + FLUSH_FOR_DRAW(ctx); if (_mesa_is_no_error_enabled(ctx)) { - FLUSH_CURRENT(ctx, 0); + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); if (ctx->NewState) _mesa_update_state(ctx); } else { + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); + if (!_mesa_validate_MultiDrawArraysIndirect(ctx, mode, indirect, primcount, stride)) return; @@ -1778,14 +1819,60 @@ vbo_exec_MultiDrawElementsIndirect(GLenum mode, GLenum type, /* If is zero, the array elements are treated as tightly packed. */ if (stride == 0) - stride = 5 * sizeof(GLuint); /* sizeof(DrawElementsIndirectCommand) */ + stride = sizeof(DrawElementsIndirectCommand); + + + /* From the ARB_draw_indirect spec: + * + * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the + * compatibility profile, this indicates that DrawArraysIndirect and + * DrawElementsIndirect are to source their arguments directly from the + * pointer passed as their parameters." + */ + if (ctx->API == API_OPENGL_COMPAT && + !_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) { + /* + * Unlike regular DrawElementsInstancedBaseVertex commands, the indices + * may not come from a client array and must come from an index buffer. + * If no element array buffer is bound, an INVALID_OPERATION error is + * generated. + */ + if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMultiDrawElementsIndirect(no buffer bound " + "to GL_ELEMENT_ARRAY_BUFFER)"); + + return; + } + + if (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride, + "glMultiDrawArraysIndirect")) + return; + + const ubyte *ptr = (const ubyte *) indirect; + for (unsigned i = 0; i < primcount; i++) { + vbo_exec_DrawElementsIndirect(mode, type, ptr); + + if (stride == 0) { + ptr += sizeof(DrawElementsIndirectCommand); + } else { + ptr += stride; + } + } + + return; + } + + FLUSH_FOR_DRAW(ctx); if (_mesa_is_no_error_enabled(ctx)) { - FLUSH_CURRENT(ctx, 0); + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); if (ctx->NewState) _mesa_update_state(ctx); } else { + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); + if (!_mesa_validate_MultiDrawElementsIndirect(ctx, mode, type, indirect, primcount, stride)) return; @@ -1803,22 +1890,19 @@ static void vbo_validated_multidrawarraysindirectcount(struct gl_context *ctx, GLenum mode, GLintptr indirect, - GLintptr drawcount, + GLintptr drawcount_offset, GLsizei maxdrawcount, GLsizei stride) { - struct vbo_context *vbo = vbo_context(ctx); GLsizeiptr offset = indirect; if (maxdrawcount == 0) return; - vbo_bind_arrays(ctx); - - vbo->draw_indirect_prims(ctx, mode, + ctx->Driver.DrawIndirect(ctx, mode, ctx->DrawIndirectBuffer, offset, maxdrawcount, stride, - ctx->ParameterBuffer, drawcount, NULL); + ctx->ParameterBuffer, drawcount_offset, NULL); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) _mesa_flush(ctx); @@ -1829,19 +1913,16 @@ static void vbo_validated_multidrawelementsindirectcount(struct gl_context *ctx, GLenum mode, GLenum type, GLintptr indirect, - GLintptr drawcount, + GLintptr drawcount_offset, GLsizei maxdrawcount, GLsizei stride) { - struct vbo_context *vbo = vbo_context(ctx); struct _mesa_index_buffer ib; GLsizeiptr offset = (GLsizeiptr) indirect; if (maxdrawcount == 0) return; - vbo_bind_arrays(ctx); - /* NOTE: IndexBufferObj is guaranteed to be a VBO. */ ib.count = 0; /* unknown */ @@ -1849,10 +1930,10 @@ vbo_validated_multidrawelementsindirectcount(struct gl_context *ctx, ib.obj = ctx->Array.VAO->IndexBufferObj; ib.ptr = NULL; - vbo->draw_indirect_prims(ctx, mode, + ctx->Driver.DrawIndirect(ctx, mode, ctx->DrawIndirectBuffer, offset, maxdrawcount, stride, - ctx->ParameterBuffer, drawcount, &ib); + ctx->ParameterBuffer, drawcount_offset, &ib); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) _mesa_flush(ctx); @@ -1861,7 +1942,7 @@ vbo_validated_multidrawelementsindirectcount(struct gl_context *ctx, static void GLAPIENTRY vbo_exec_MultiDrawArraysIndirectCount(GLenum mode, GLintptr indirect, - GLintptr drawcount, + GLintptr drawcount_offset, GLsizei maxdrawcount, GLsizei stride) { GET_CURRENT_CONTEXT(ctx); @@ -1870,21 +1951,26 @@ vbo_exec_MultiDrawArraysIndirectCount(GLenum mode, GLintptr indirect, _mesa_debug(ctx, "glMultiDrawArraysIndirectCountARB" "(%s, %lx, %lx, %i, %i)\n", _mesa_enum_to_string(mode), - (unsigned long) indirect, (unsigned long) drawcount, + (unsigned long) indirect, (unsigned long) drawcount_offset, maxdrawcount, stride); /* If is zero, the array elements are treated as tightly packed. */ if (stride == 0) stride = 4 * sizeof(GLuint); /* sizeof(DrawArraysIndirectCommand) */ + FLUSH_FOR_DRAW(ctx); + if (_mesa_is_no_error_enabled(ctx)) { - FLUSH_CURRENT(ctx, 0); + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); if (ctx->NewState) _mesa_update_state(ctx); } else { + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); + if (!_mesa_validate_MultiDrawArraysIndirectCount(ctx, mode, - indirect, drawcount, + indirect, + drawcount_offset, maxdrawcount, stride)) return; } @@ -1892,14 +1978,16 @@ vbo_exec_MultiDrawArraysIndirectCount(GLenum mode, GLintptr indirect, if (skip_validated_draw(ctx)) return; - vbo_validated_multidrawarraysindirectcount(ctx, mode, indirect, drawcount, + vbo_validated_multidrawarraysindirectcount(ctx, mode, indirect, + drawcount_offset, maxdrawcount, stride); } static void GLAPIENTRY vbo_exec_MultiDrawElementsIndirectCount(GLenum mode, GLenum type, - GLintptr indirect, GLintptr drawcount, + GLintptr indirect, + GLintptr drawcount_offset, GLsizei maxdrawcount, GLsizei stride) { GET_CURRENT_CONTEXT(ctx); @@ -1908,21 +1996,26 @@ vbo_exec_MultiDrawElementsIndirectCount(GLenum mode, GLenum type, _mesa_debug(ctx, "glMultiDrawElementsIndirectCountARB" "(%s, %s, %lx, %lx, %i, %i)\n", _mesa_enum_to_string(mode), _mesa_enum_to_string(type), - (unsigned long) indirect, (unsigned long) drawcount, + (unsigned long) indirect, (unsigned long) drawcount_offset, maxdrawcount, stride); /* If is zero, the array elements are treated as tightly packed. */ if (stride == 0) stride = 5 * sizeof(GLuint); /* sizeof(DrawElementsIndirectCommand) */ + FLUSH_FOR_DRAW(ctx); + if (_mesa_is_no_error_enabled(ctx)) { - FLUSH_CURRENT(ctx, 0); + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); if (ctx->NewState) _mesa_update_state(ctx); } else { + _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); + if (!_mesa_validate_MultiDrawElementsIndirectCount(ctx, mode, type, - indirect, drawcount, + indirect, + drawcount_offset, maxdrawcount, stride)) return; } @@ -1931,7 +2024,7 @@ vbo_exec_MultiDrawElementsIndirectCount(GLenum mode, GLenum type, return; vbo_validated_multidrawelementsindirectcount(ctx, mode, type, indirect, - drawcount, maxdrawcount, + drawcount_offset, maxdrawcount, stride); } @@ -1982,7 +2075,7 @@ vbo_initialize_exec_dispatch(const struct gl_context *ctx, vbo_exec_DrawElementsInstancedBaseVertexBaseInstance); } - if (ctx->API == API_OPENGL_CORE || _mesa_is_gles31(ctx)) { + if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles31(ctx)) { SET_DrawArraysIndirect(exec, vbo_exec_DrawArraysIndirect); SET_DrawElementsIndirect(exec, vbo_exec_DrawElementsIndirect); }