aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/main
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/main')
-rw-r--r--mesalib/src/mesa/main/api_validate.c192
-rw-r--r--mesalib/src/mesa/main/api_validate.h26
-rw-r--r--mesalib/src/mesa/main/bufferobj.c14
-rw-r--r--mesalib/src/mesa/main/extensions.c2
-rw-r--r--mesalib/src/mesa/main/get.c5
-rw-r--r--mesalib/src/mesa/main/get_hash_params.py2
-rw-r--r--mesalib/src/mesa/main/mtypes.h3
7 files changed, 244 insertions, 0 deletions
diff --git a/mesalib/src/mesa/main/api_validate.c b/mesalib/src/mesa/main/api_validate.c
index f285c9748..96b178905 100644
--- a/mesalib/src/mesa/main/api_validate.c
+++ b/mesalib/src/mesa/main/api_validate.c
@@ -837,3 +837,195 @@ _mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
return GL_TRUE;
}
+
+static GLboolean
+valid_draw_indirect(struct gl_context *ctx,
+ GLenum mode, const GLvoid *indirect,
+ GLsizei size, const char *name)
+{
+ const GLsizeiptr end = (GLsizeiptr)indirect + size;
+
+ if (!_mesa_valid_prim_mode(ctx, mode, name))
+ return GL_FALSE;
+
+
+ /* From the ARB_draw_indirect specification:
+ * "An INVALID_OPERATION error is generated [...] if <indirect> is no
+ * word aligned."
+ */
+ if ((GLsizeiptr)indirect & (sizeof(GLuint) - 1)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(indirect is not aligned)", name);
+ return GL_FALSE;
+ }
+
+ if (!_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s: no buffer bound to DRAW_INDIRECT_BUFFER", name);
+ return GL_FALSE;
+ }
+
+ if (_mesa_bufferobj_mapped(ctx->DrawIndirectBuffer)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(DRAW_INDIRECT_BUFFER is mapped)", name);
+ return GL_FALSE;
+ }
+
+ /* From the ARB_draw_indirect specification:
+ * "An INVALID_OPERATION error is generated if the commands source data
+ * beyond the end of the buffer object [...]"
+ */
+ if (ctx->DrawIndirectBuffer->Size < end) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(DRAW_INDIRECT_BUFFER too small)", name);
+ return GL_FALSE;
+ }
+
+ if (!check_valid_to_render(ctx, name))
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+static inline GLboolean
+valid_draw_indirect_elements(struct gl_context *ctx,
+ GLenum mode, GLenum type, const GLvoid *indirect,
+ GLsizeiptr size, const char *name)
+{
+ if (!valid_elements_type(ctx, type, name))
+ return GL_FALSE;
+
+ /*
+ * 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.ArrayObj->ElementArrayBufferObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(no buffer bound to GL_ELEMENT_ARRAY_BUFFER)", name);
+ return GL_FALSE;
+ }
+
+ return valid_draw_indirect(ctx, mode, indirect, size, name);
+}
+
+static inline GLboolean
+valid_draw_indirect_multi(struct gl_context *ctx,
+ GLsizei primcount, GLsizei stride,
+ const char *name)
+{
+
+ /* From the ARB_multi_draw_indirect specification:
+ * "INVALID_VALUE is generated by MultiDrawArraysIndirect or
+ * MultiDrawElementsIndirect if <primcount> is negative."
+ *
+ * "<primcount> must be positive, otherwise an INVALID_VALUE error will
+ * be generated."
+ */
+ if (primcount < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(primcount < 0)", name);
+ return GL_FALSE;
+ }
+
+
+ /* From the ARB_multi_draw_indirect specification:
+ * "<stride> must be a multiple of four, otherwise an INVALID_VALUE
+ * error is generated."
+ */
+ if (stride % 4) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride %% 4)", name);
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean
+_mesa_validate_DrawArraysIndirect(struct gl_context *ctx,
+ GLenum mode,
+ const GLvoid *indirect)
+{
+ const unsigned drawArraysNumParams = 4;
+
+ FLUSH_CURRENT(ctx, 0);
+
+ return valid_draw_indirect(ctx, mode,
+ indirect, drawArraysNumParams * sizeof(GLuint),
+ "glDrawArraysIndirect");
+}
+
+GLboolean
+_mesa_validate_DrawElementsIndirect(struct gl_context *ctx,
+ GLenum mode, GLenum type,
+ const GLvoid *indirect)
+{
+ const unsigned drawElementsNumParams = 5;
+
+ FLUSH_CURRENT(ctx, 0);
+
+ return valid_draw_indirect_elements(ctx, mode, type,
+ indirect, drawElementsNumParams * sizeof(GLuint),
+ "glDrawElementsIndirect");
+}
+
+GLboolean
+_mesa_validate_MultiDrawArraysIndirect(struct gl_context *ctx,
+ GLenum mode,
+ const GLvoid *indirect,
+ GLsizei primcount, GLsizei stride)
+{
+ GLsizeiptr size = 0;
+ const unsigned drawArraysNumParams = 4;
+
+ FLUSH_CURRENT(ctx, 0);
+
+ /* caller has converted stride==0 to drawArraysNumParams * sizeof(GLuint) */
+ assert(stride != 0);
+
+ if (!valid_draw_indirect_multi(ctx, primcount, stride,
+ "glMultiDrawArraysIndirect"))
+ return GL_FALSE;
+
+ /* number of bytes of the indirect buffer which will be read */
+ size = primcount
+ ? (primcount - 1) * stride + drawArraysNumParams * sizeof(GLuint)
+ : 0;
+
+ if (!valid_draw_indirect(ctx, mode, indirect, size,
+ "glMultiDrawArraysIndirect"))
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+GLboolean
+_mesa_validate_MultiDrawElementsIndirect(struct gl_context *ctx,
+ GLenum mode, GLenum type,
+ const GLvoid *indirect,
+ GLsizei primcount, GLsizei stride)
+{
+ GLsizeiptr size = 0;
+ const unsigned drawElementsNumParams = 5;
+
+ FLUSH_CURRENT(ctx, 0);
+
+ /* caller has converted stride==0 to drawElementsNumParams * sizeof(GLuint) */
+ assert(stride != 0);
+
+ if (!valid_draw_indirect_multi(ctx, primcount, stride,
+ "glMultiDrawElementsIndirect"))
+ return GL_FALSE;
+
+ /* number of bytes of the indirect buffer which will be read */
+ size = primcount
+ ? (primcount - 1) * stride + drawElementsNumParams * sizeof(GLuint)
+ : 0;
+
+ if (!valid_draw_indirect_elements(ctx, mode, type,
+ indirect, size,
+ "glMultiDrawElementsIndirect"))
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
diff --git a/mesalib/src/mesa/main/api_validate.h b/mesalib/src/mesa/main/api_validate.h
index f2b753ca9..8238df16c 100644
--- a/mesalib/src/mesa/main/api_validate.h
+++ b/mesalib/src/mesa/main/api_validate.h
@@ -87,5 +87,31 @@ _mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
GLuint stream,
GLsizei numInstances);
+extern GLboolean
+_mesa_validate_DrawArraysIndirect(struct gl_context *ctx,
+ GLenum mode,
+ const GLvoid *indirect);
+
+extern GLboolean
+_mesa_validate_DrawElementsIndirect(struct gl_context *ctx,
+ GLenum mode,
+ GLenum type,
+ const GLvoid *indirect);
+
+extern GLboolean
+_mesa_validate_MultiDrawArraysIndirect(struct gl_context *ctx,
+ GLenum mode,
+ const GLvoid *indirect,
+ GLsizei primcount,
+ GLsizei stride);
+
+extern GLboolean
+_mesa_validate_MultiDrawElementsIndirect(struct gl_context *ctx,
+ GLenum mode,
+ GLenum type,
+ const GLvoid *indirect,
+ GLsizei primcount,
+ GLsizei stride);
+
#endif
diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c
index 351934433..3127a8247 100644
--- a/mesalib/src/mesa/main/bufferobj.c
+++ b/mesalib/src/mesa/main/bufferobj.c
@@ -86,6 +86,12 @@ get_buffer_target(struct gl_context *ctx, GLenum target)
return &ctx->CopyReadBuffer;
case GL_COPY_WRITE_BUFFER:
return &ctx->CopyWriteBuffer;
+ case GL_DRAW_INDIRECT_BUFFER:
+ if (ctx->API == API_OPENGL_CORE &&
+ ctx->Extensions.ARB_draw_indirect) {
+ return &ctx->DrawIndirectBuffer;
+ }
+ break;
case GL_TRANSFORM_FEEDBACK_BUFFER:
if (ctx->Extensions.EXT_transform_feedback) {
return &ctx->TransformFeedback.CurrentBuffer;
@@ -626,6 +632,9 @@ _mesa_init_buffer_objects( struct gl_context *ctx )
_mesa_reference_buffer_object(ctx, &ctx->UniformBuffer,
ctx->Shared->NullBufferObj);
+ _mesa_reference_buffer_object(ctx, &ctx->DrawIndirectBuffer,
+ ctx->Shared->NullBufferObj);
+
for (i = 0; i < MAX_COMBINED_UNIFORM_BUFFERS; i++) {
_mesa_reference_buffer_object(ctx,
&ctx->UniformBufferBindings[i].BufferObject,
@@ -875,6 +884,11 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids)
_mesa_BindBuffer( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );
}
+ /* unbind ARB_draw_indirect binding point */
+ if (ctx->DrawIndirectBuffer == bufObj) {
+ _mesa_BindBuffer( GL_DRAW_INDIRECT_BUFFER, 0 );
+ }
+
/* unbind ARB_copy_buffer binding points */
if (ctx->CopyReadBuffer == bufObj) {
_mesa_BindBuffer( GL_COPY_READ_BUFFER, 0 );
diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c
index 104618c23..42da9057c 100644
--- a/mesalib/src/mesa/main/extensions.c
+++ b/mesalib/src/mesa/main/extensions.c
@@ -92,6 +92,7 @@ static const struct extension extension_table[] = {
{ "GL_ARB_draw_buffers", o(dummy_true), GL, 2002 },
{ "GL_ARB_draw_buffers_blend", o(ARB_draw_buffers_blend), GL, 2009 },
{ "GL_ARB_draw_elements_base_vertex", o(ARB_draw_elements_base_vertex), GL, 2009 },
+ { "GL_ARB_draw_indirect", o(ARB_draw_indirect), GLC, 2010 },
{ "GL_ARB_draw_instanced", o(ARB_draw_instanced), GL, 2008 },
{ "GL_ARB_explicit_attrib_location", o(ARB_explicit_attrib_location), GL, 2009 },
{ "GL_ARB_fragment_coord_conventions", o(ARB_fragment_coord_conventions), GL, 2009 },
@@ -109,6 +110,7 @@ static const struct extension extension_table[] = {
{ "GL_ARB_invalidate_subdata", o(dummy_true), GL, 2012 },
{ "GL_ARB_map_buffer_alignment", o(ARB_map_buffer_alignment), GL, 2011 },
{ "GL_ARB_map_buffer_range", o(ARB_map_buffer_range), GL, 2008 },
+ { "GL_ARB_multi_draw_indirect", o(ARB_draw_indirect), GLC, 2012 },
{ "GL_ARB_multisample", o(dummy_true), GLL, 1994 },
{ "GL_ARB_multitexture", o(dummy_true), GLL, 1998 },
{ "GL_ARB_occlusion_query2", o(ARB_occlusion_query2), GL, 2003 },
diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c
index eee855007..7f233409e 100644
--- a/mesalib/src/mesa/main/get.c
+++ b/mesalib/src/mesa/main/get.c
@@ -375,6 +375,7 @@ EXTRA_EXT(ARB_texture_buffer_range);
EXTRA_EXT(ARB_texture_multisample);
EXTRA_EXT(ARB_texture_gather);
EXTRA_EXT(ARB_shader_atomic_counters);
+EXTRA_EXT(ARB_draw_indirect);
static const int
extra_ARB_color_buffer_float_or_glcore[] = {
@@ -913,6 +914,10 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
case GL_ATOMIC_COUNTER_BUFFER_BINDING:
v->value_int = ctx->AtomicBuffer->Name;
break;
+ /* GL_ARB_draw_indirect */
+ case GL_DRAW_INDIRECT_BUFFER_BINDING:
+ v->value_int = ctx->DrawIndirectBuffer->Name;
+ break;
}
}
diff --git a/mesalib/src/mesa/main/get_hash_params.py b/mesalib/src/mesa/main/get_hash_params.py
index c961feeee..781b796ee 100644
--- a/mesalib/src/mesa/main/get_hash_params.py
+++ b/mesalib/src/mesa/main/get_hash_params.py
@@ -747,6 +747,8 @@ descriptor=[
{ "apis": ["GL_CORE"], "params": [
# GL_ARB_texture_buffer_range
[ "TEXTURE_BUFFER_OFFSET_ALIGNMENT", "CONTEXT_INT(Const.TextureBufferOffsetAlignment), extra_ARB_texture_buffer_range" ],
+# GL_ARB_draw_indirect
+ [ "DRAW_INDIRECT_BUFFER_BINDING", "LOC_CUSTOM, TYPE_INT, 0, extra_ARB_draw_indirect" ],
]}
]
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index ecfb5e08f..b4b432f40 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -3326,6 +3326,7 @@ struct gl_extensions
GLboolean ARB_depth_texture;
GLboolean ARB_draw_buffers_blend;
GLboolean ARB_draw_elements_base_vertex;
+ GLboolean ARB_draw_indirect;
GLboolean ARB_draw_instanced;
GLboolean ARB_fragment_coord_conventions;
GLboolean ARB_fragment_program;
@@ -3902,6 +3903,8 @@ struct gl_context
struct gl_perf_monitor_state PerfMonitor;
+ struct gl_buffer_object *DrawIndirectBuffer; /** < GL_ARB_draw_indirect */
+
struct gl_buffer_object *CopyReadBuffer; /**< GL_ARB_copy_buffer */
struct gl_buffer_object *CopyWriteBuffer; /**< GL_ARB_copy_buffer */