diff options
Diffstat (limited to 'mesalib/src/mesa/main')
-rw-r--r-- | mesalib/src/mesa/main/api_validate.c | 192 | ||||
-rw-r--r-- | mesalib/src/mesa/main/api_validate.h | 26 | ||||
-rw-r--r-- | mesalib/src/mesa/main/bufferobj.c | 14 | ||||
-rw-r--r-- | mesalib/src/mesa/main/extensions.c | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/main/get.c | 5 | ||||
-rw-r--r-- | mesalib/src/mesa/main/get_hash_params.py | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/main/mtypes.h | 3 |
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 b27f592e8..8b5ebc489 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 */ |