/* For OpenGL ES, only draw if we have vertex positions
*/
if (!ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POS].Enabled)
- return false;
+ return false;
break;
case API_OPENGL_CORE:
return GL_FALSE;
}
- /* From the ARB_geometry_shader4 spec:
+ /* From the OpenGL 4.5 specification, section 11.3.1:
*
* The error INVALID_OPERATION is generated if Begin, or any command that
* implicitly calls Begin, is called when a geometry shader is active and:
GLenum mode_before_gs = mode;
if (tes) {
- if (tes->TessEval.PointMode)
+ struct gl_shader *tes_sh = tes->_LinkedShaders[MESA_SHADER_TESS_EVAL];
+ if (tes_sh->TessEval.PointMode)
mode_before_gs = GL_POINTS;
- else if (tes->TessEval.PrimitiveMode == GL_ISOLINES)
+ else if (tes_sh->TessEval.PrimitiveMode == GL_ISOLINES)
mode_before_gs = GL_LINES;
else
/* the GL_QUADS mode generates triangles too */
else if (ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL]) {
struct gl_shader_program *tes =
ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL];
-
- if (tes->TessEval.PointMode)
+ struct gl_shader *tes_sh = tes->_LinkedShaders[MESA_SHADER_TESS_EVAL];
+ if (tes_sh->TessEval.PointMode)
pass = ctx->TransformFeedback.Mode == GL_POINTS;
- else if (tes->TessEval.PrimitiveMode == GL_ISOLINES)
+ else if (tes_sh->TessEval.PrimitiveMode == GL_ISOLINES)
pass = ctx->TransformFeedback.Mode == GL_LINES;
else
pass = ctx->TransformFeedback.Mode == GL_TRIANGLES;
}
if (!pass) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "%s(mode=%s vs transform feedback %s)",
- name,
- _mesa_lookup_prim_by_nr(mode),
- _mesa_lookup_prim_by_nr(ctx->TransformFeedback.Mode));
+ "%s(mode=%s vs transform feedback %s)",
+ name,
+ _mesa_lookup_prim_by_nr(mode),
+ _mesa_lookup_prim_by_nr(ctx->TransformFeedback.Mode));
return GL_FALSE;
}
}
* DrawElementsInstanced, and DrawRangeElements while transform feedback
* is active and not paused, regardless of mode.
*/
- if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) {
+ if (_mesa_is_gles3(ctx) && !ctx->Extensions.OES_geometry_shader &&
+ _mesa_is_xfb_active_and_unpaused(ctx)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(transform feedback active)", caller);
return false;
*/
GLboolean
_mesa_validate_DrawElements(struct gl_context *ctx,
- GLenum mode, GLsizei count, GLenum type,
- const GLvoid *indices)
+ GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices)
{
FLUSH_CURRENT(ctx, 0);
*/
GLboolean
_mesa_validate_DrawRangeElements(struct gl_context *ctx, GLenum mode,
- GLuint start, GLuint end,
- GLsizei count, GLenum type,
- const GLvoid *indices)
+ GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices)
{
FLUSH_CURRENT(ctx, 0);
if (first < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glDrawArraysInstanced(start=%d)", first);
+ "glDrawArraysInstanced(start=%d)", first);
return GL_FALSE;
}
return GL_FALSE;
}
+ /* From the GL 4.5 specification, page 429:
+ * "An INVALID_VALUE error is generated if id is not the name of a
+ * transform feedback object."
+ */
+ if (!obj->EverBound) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glDrawTransformFeedback*(name)");
+ return GL_FALSE;
+ }
+
if (stream >= ctx->Const.MaxVertexStreams) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glDrawTransformFeedbackStream*(index>=MaxVertexStream)");
GLenum mode, const GLvoid *indirect,
GLsizei size, const char *name)
{
- const GLsizeiptr end = (GLsizeiptr)indirect + size;
+ const uint64_t end = (uint64_t) (uintptr_t) indirect + size;
/* OpenGL ES 3.1 spec. section 10.5:
*
return GL_FALSE;
}
+ /* From OpenGL ES 3.1 spec. section 10.5:
+ * "An INVALID_OPERATION error is generated if zero is bound to
+ * VERTEX_ARRAY_BINDING, DRAW_INDIRECT_BUFFER or to any enabled
+ * vertex array."
+ *
+ * Here we check that for each enabled vertex array we have a vertex
+ * buffer bound.
+ */
+ if (_mesa_is_gles31(ctx) &&
+ ctx->Array.VAO->_Enabled != ctx->Array.VAO->VertexAttribBufferMask) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(No VBO bound)", name);
+ return GL_FALSE;
+ }
+
if (!_mesa_valid_prim_mode(ctx, mode, name))
return GL_FALSE;
* "An INVALID_OPERATION error is generated if
* transform feedback is active and not paused."
*/
- if (_mesa_is_gles31(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) {
+ if (_mesa_is_gles31(ctx) && !ctx->Extensions.OES_geometry_shader &&
+ _mesa_is_xfb_active_and_unpaused(ctx)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(TransformFeedback is active and not paused)", name);
}
return GL_TRUE;
}
+static GLboolean
+valid_draw_indirect_parameters(struct gl_context *ctx,
+ const char *name,
+ GLintptr drawcount)
+{
+ /* From the ARB_indirect_parameters specification:
+ * "INVALID_VALUE is generated by MultiDrawArraysIndirectCountARB or
+ * MultiDrawElementsIndirectCountARB if <drawcount> is not a multiple of
+ * four."
+ */
+ if (drawcount & 3) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(drawcount is not a multiple of 4)", name);
+ return GL_FALSE;
+ }
+
+ /* From the ARB_indirect_parameters specification:
+ * "INVALID_OPERATION is generated by MultiDrawArraysIndirectCountARB or
+ * MultiDrawElementsIndirectCountARB if no buffer is bound to the
+ * PARAMETER_BUFFER_ARB binding point."
+ */
+ if (!_mesa_is_bufferobj(ctx->ParameterBuffer)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s: no buffer bound to PARAMETER_BUFFER", name);
+ return GL_FALSE;
+ }
+
+ if (_mesa_check_disallowed_mapping(ctx->ParameterBuffer)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(PARAMETER_BUFFER is mapped)", name);
+ return GL_FALSE;
+ }
+
+ /* From the ARB_indirect_parameters specification:
+ * "INVALID_OPERATION is generated by MultiDrawArraysIndirectCountARB or
+ * MultiDrawElementsIndirectCountARB if reading a <sizei> typed value
+ * from the buffer bound to the PARAMETER_BUFFER_ARB target at the offset
+ * specified by <drawcount> would result in an out-of-bounds access."
+ */
+ if (ctx->ParameterBuffer->Size < drawcount + sizeof(GLsizei)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(PARAMETER_BUFFER too small)", name);
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean
+_mesa_validate_MultiDrawArraysIndirectCount(struct gl_context *ctx,
+ GLenum mode,
+ GLintptr indirect,
+ GLintptr drawcount,
+ GLsizei maxdrawcount,
+ 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, maxdrawcount, stride,
+ "glMultiDrawArraysIndirectCountARB"))
+ return GL_FALSE;
+
+ /* number of bytes of the indirect buffer which will be read */
+ size = maxdrawcount
+ ? (maxdrawcount - 1) * stride + drawArraysNumParams * sizeof(GLuint)
+ : 0;
+
+ if (!valid_draw_indirect(ctx, mode, (void *)indirect, size,
+ "glMultiDrawArraysIndirectCountARB"))
+ return GL_FALSE;
+
+ return valid_draw_indirect_parameters(
+ ctx, "glMultiDrawArraysIndirectCountARB", drawcount);
+}
+
+GLboolean
+_mesa_validate_MultiDrawElementsIndirectCount(struct gl_context *ctx,
+ GLenum mode, GLenum type,
+ GLintptr indirect,
+ GLintptr drawcount,
+ GLsizei maxdrawcount,
+ 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, maxdrawcount, stride,
+ "glMultiDrawElementsIndirectCountARB"))
+ return GL_FALSE;
+
+ /* number of bytes of the indirect buffer which will be read */
+ size = maxdrawcount
+ ? (maxdrawcount - 1) * stride + drawElementsNumParams * sizeof(GLuint)
+ : 0;
+
+ if (!valid_draw_indirect_elements(ctx, mode, type,
+ (void *)indirect, size,
+ "glMultiDrawElementsIndirectCountARB"))
+ return GL_FALSE;
+
+ return valid_draw_indirect_parameters(
+ ctx, "glMultiDrawElementsIndirectCountARB", drawcount);
+}
+
static bool
check_valid_to_compute(struct gl_context *ctx, const char *function)
{
return false;
}
- prog = ctx->Shader.CurrentProgram[MESA_SHADER_COMPUTE];
+ /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders:
+ *
+ * "An INVALID_OPERATION error is generated if there is no active program
+ * for the compute shader stage."
+ */
+ prog = ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE];
if (prog == NULL || prog->_LinkedShaders[MESA_SHADER_COMPUTE] == NULL) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(no active compute shader)",
return GL_FALSE;
for (i = 0; i < 3; i++) {
+ /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders:
+ *
+ * "An INVALID_VALUE error is generated if any of num_groups_x,
+ * num_groups_y and num_groups_z are greater than or equal to the
+ * maximum work group count for the corresponding dimension."
+ *
+ * However, the "or equal to" portions appears to be a specification
+ * bug. In all other areas, the specification appears to indicate that
+ * the number of workgroups can match the MAX_COMPUTE_WORK_GROUP_COUNT
+ * value. For example, under DispatchComputeIndirect:
+ *
+ * "If any of num_groups_x, num_groups_y or num_groups_z is greater than
+ * the value of MAX_COMPUTE_WORK_GROUP_COUNT for the corresponding
+ * dimension then the results are undefined."
+ *
+ * Additionally, the OpenGLES 3.1 specification does not contain "or
+ * equal to" as an error condition.
+ */
if (num_groups[i] > ctx->Const.MaxComputeWorkGroupCount[i]) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glDispatchCompute(num_groups_%c)", 'x' + i);
GLintptr indirect,
GLsizei size, const char *name)
{
- GLintptr end = (GLintptr)indirect + size;
+ const uint64_t end = (uint64_t) indirect + size;
if (!check_valid_to_compute(ctx, name))
return GL_FALSE;
- /* From the ARB_compute_shader specification:
+ /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders:
*
- * "An INVALID_OPERATION error is generated [...] if <indirect> is less
- * than zero or not a multiple of the size, in basic machine units, of
- * uint."
+ * "An INVALID_VALUE error is generated if indirect is negative or is not a
+ * multiple of four."
*/
- if ((GLintptr)indirect & (sizeof(GLuint) - 1)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
+ if (indirect & (sizeof(GLuint) - 1)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
"%s(indirect is not aligned)", name);
return GL_FALSE;
}
- if ((GLintptr)indirect < 0) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
+ if (indirect < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
"%s(indirect is less than zero)", name);
return GL_FALSE;
}
+ /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders:
+ *
+ * "An INVALID_OPERATION error is generated if no buffer is bound to the
+ * DRAW_INDIRECT_BUFFER binding, or if the command would source data
+ * beyond the end of the buffer object."
+ */
if (!_mesa_is_bufferobj(ctx->DispatchIndirectBuffer)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s: no buffer bound to DISPATCH_INDIRECT_BUFFER", name);
return GL_FALSE;
}
- /* From the ARB_compute_shader specification:
- *
- * "An INVALID_OPERATION error is generated if this command sources data
- * beyond the end of the buffer object [...]"
- */
if (ctx->DispatchIndirectBuffer->Size < end) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(DISPATCH_INDIRECT_BUFFER too small)", name);