Esempio n. 1
0
GLboolean
_mesa_validate_DrawElementsInstanced(struct gl_context *ctx,
                                     GLenum mode, GLsizei count, GLenum type,
                                     const GLvoid *indices, GLsizei numInstances,
                                     GLint basevertex)
{
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);

   if (count <= 0) {
      if (count < 0)
	 _mesa_error(ctx, GL_INVALID_VALUE,
                     "glDrawElementsInstanced(count=%d)", count);
      return GL_FALSE;
   }

   if (mode > GL_TRIANGLE_STRIP_ADJACENCY_ARB) {
      _mesa_error(ctx, GL_INVALID_ENUM,
                  "glDrawElementsInstanced(mode = 0x%x)", mode);
      return GL_FALSE;
   }

   if (type != GL_UNSIGNED_INT &&
       type != GL_UNSIGNED_BYTE &&
       type != GL_UNSIGNED_SHORT) {
      _mesa_error(ctx, GL_INVALID_ENUM,
                  "glDrawElementsInstanced(type=0x%x)", type);
      return GL_FALSE;
   }

   if (numInstances <= 0) {
      if (numInstances < 0)
         _mesa_error(ctx, GL_INVALID_VALUE,
                     "glDrawElementsInstanced(numInstances=%d)", numInstances);
      return GL_FALSE;
   }

   if (!check_valid_to_render(ctx, "glDrawElementsInstanced"))
      return GL_FALSE;

   /* Vertex buffer object tests */
   if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) {
      /* use indices in the buffer object */
      /* make sure count doesn't go outside buffer bounds */
      if (index_bytes(type, count) > ctx->Array.ElementArrayBufferObj->Size) {
         _mesa_warning(ctx,
                       "glDrawElementsInstanced index out of buffer bounds");
         return GL_FALSE;
      }
   }
   else {
      /* not using a VBO */
      if (!indices)
         return GL_FALSE;
   }

   if (!check_index_bounds(ctx, count, type, indices, basevertex))
      return GL_FALSE;

   return GL_TRUE;
}
Esempio n. 2
0
/**
 * Called from the tnl module to error check the function parameters and
 * verify that we really can draw something.
 * \return GL_TRUE if OK to render, GL_FALSE if error found
 */
GLboolean
_mesa_validate_DrawArrays(struct gl_context *ctx,
			  GLenum mode, GLint start, GLsizei count)
{
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);

   if (count <= 0) {
      if (count < 0)
         _mesa_error(ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
      return GL_FALSE;
   }

   if (mode > GL_TRIANGLE_STRIP_ADJACENCY_ARB) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" );
      return GL_FALSE;
   }

   if (!check_valid_to_render(ctx, "glDrawArrays"))
      return GL_FALSE;

   if (ctx->Const.CheckArrayBounds) {
      if (start + count > (GLint) ctx->Array.ArrayObj->_MaxElement)
         return GL_FALSE;
   }

   return GL_TRUE;
}
Esempio n. 3
0
/**
 * Error checking for glMultiDrawElements().  Includes parameter checking
 * and VBO bounds checking.
 * \return GL_TRUE if OK to render, GL_FALSE if error found
 */
GLboolean
_mesa_validate_MultiDrawElements(struct gl_context *ctx,
                                 GLenum mode, const GLsizei *count,
                                 GLenum type, const GLvoid * const *indices,
                                 GLuint primcount, const GLint *basevertex)
{
   unsigned i;

   FLUSH_CURRENT(ctx, 0);

   for (i = 0; i < primcount; i++) {
      if (count[i] <= 0) {
         if (count[i] < 0)
            _mesa_error(ctx, GL_INVALID_VALUE,
                        "glMultiDrawElements(count)" );
         return GL_FALSE;
      }
   }

   if (!_mesa_valid_prim_mode(ctx, mode, "glMultiDrawElements")) {
      return GL_FALSE;
   }

   if (!valid_elements_type(ctx, type, "glMultiDrawElements"))
      return GL_FALSE;

   if (!check_valid_to_render(ctx, "glMultiDrawElements"))
      return GL_FALSE;

   /* Vertex buffer object tests */
   if (_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
      /* use indices in the buffer object */
      /* make sure count doesn't go outside buffer bounds */
      for (i = 0; i < primcount; i++) {
         if (index_bytes(type, count[i]) >
             ctx->Array.ArrayObj->ElementArrayBufferObj->Size) {
            _mesa_warning(ctx,
                          "glMultiDrawElements index out of buffer bounds");
            return GL_FALSE;
         }
      }
   }
   else {
      /* not using a VBO */
      for (i = 0; i < primcount; i++) {
         if (!indices[i])
            return GL_FALSE;
      }
   }

   for (i = 0; i < primcount; i++) {
      if (!check_index_bounds(ctx, count[i], type, indices[i],
                              basevertex ? basevertex[i] : 0))
         return GL_FALSE;
   }

   return GL_TRUE;
}
Esempio n. 4
0
/**
 * Error checking for glDrawElements().  Includes parameter checking
 * and VBO bounds checking.
 * \return GL_TRUE if OK to render, GL_FALSE if error found
 */
GLboolean
_mesa_validate_DrawElements(struct gl_context *ctx,
			    GLenum mode, GLsizei count, GLenum type,
			    const GLvoid *indices, GLint basevertex)
{
   FLUSH_CURRENT(ctx, 0);

   /* From the GLES3 specification, section 2.14.2 (Transform Feedback
    * Primitive Capture):
    *
    *   The error INVALID_OPERATION is also generated by DrawElements,
    *   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)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glDrawElements(transform feedback active)");
      return GL_FALSE;
   }

   if (count <= 0) {
      if (count < 0)
	 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawElements(count)" );
      return GL_FALSE;
   }

   if (!_mesa_valid_prim_mode(ctx, mode, "glDrawElements")) {
      return GL_FALSE;
   }

   if (!valid_elements_type(ctx, type, "glDrawElements"))
      return GL_FALSE;

   if (!check_valid_to_render(ctx, "glDrawElements"))
      return GL_FALSE;

   /* Vertex buffer object tests */
   if (_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
      /* use indices in the buffer object */
      /* make sure count doesn't go outside buffer bounds */
      if (index_bytes(type, count) > ctx->Array.ArrayObj->ElementArrayBufferObj->Size) {
         _mesa_warning(ctx, "glDrawElements index out of buffer bounds");
         return GL_FALSE;
      }
   }
   else {
      /* not using a VBO */
      if (!indices)
         return GL_FALSE;
   }

   if (!check_index_bounds(ctx, count, type, indices, basevertex))
      return GL_FALSE;

   return GL_TRUE;
}
Esempio n. 5
0
/**
 * Error checking for glDrawRangeElements().  Includes parameter checking
 * and VBO bounds checking.
 * \return GL_TRUE if OK to render, GL_FALSE if error found
 */
GLboolean
_mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode,
				 GLuint start, GLuint end,
				 GLsizei count, GLenum type,
				 const GLvoid *indices, GLint basevertex)
{
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);

   if (count <= 0) {
      if (count < 0)
	 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(count)" );
      return GL_FALSE;
   }

   if (mode > GL_POLYGON) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(mode)" );
      return GL_FALSE;
   }

   if (end < start) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(end<start)");
      return GL_FALSE;
   }

   if (type != GL_UNSIGNED_INT &&
       type != GL_UNSIGNED_BYTE &&
       type != GL_UNSIGNED_SHORT) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(type)" );
      return GL_FALSE;
   }

   if (!check_valid_to_render(ctx, "glDrawRangeElements"))
      return GL_FALSE;

   /* Vertex buffer object tests */
   if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) {
      /* use indices in the buffer object */
      /* make sure count doesn't go outside buffer bounds */
      if (index_bytes(type, count) > ctx->Array.ElementArrayBufferObj->Size) {
         _mesa_warning(ctx, "glDrawRangeElements index out of buffer bounds");
         return GL_FALSE;
      }
   }
   else {
      /* not using a VBO */
      if (!indices)
         return GL_FALSE;
   }

   if (!check_index_bounds(ctx, count, type, indices, basevertex))
      return GL_FALSE;

   return GL_TRUE;
}
GLboolean
_mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
                                     GLenum mode,
                                     struct gl_transform_feedback_object *obj,
                                     GLuint stream,
                                     GLsizei numInstances)
{
   FLUSH_CURRENT(ctx, 0);

   if (!_mesa_valid_prim_mode(ctx, mode, "glDrawTransformFeedback*(mode)")) {
      return GL_FALSE;
   }

   if (!obj) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glDrawTransformFeedback*(name)");
      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)");
      return GL_FALSE;
   }

   if (!obj->EndedAnytime) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawTransformFeedback*");
      return GL_FALSE;
   }

   if (numInstances <= 0) {
      if (numInstances < 0)
         _mesa_error(ctx, GL_INVALID_VALUE,
                     "glDrawTransformFeedback*Instanced(numInstances=%d)",
                     numInstances);
      return GL_FALSE;
   }

   if (!check_valid_to_render(ctx, "glDrawTransformFeedback*")) {
      return GL_FALSE;
   }

   return GL_TRUE;
}
Esempio n. 7
0
/**
 * Called from the tnl module to error check the function parameters and
 * verify that we really can draw something.
 * \return GL_TRUE if OK to render, GL_FALSE if error found
 */
GLboolean
_mesa_validate_DrawArrays(struct gl_context *ctx,
			  GLenum mode, GLint start, GLsizei count)
{
   struct gl_transform_feedback_object *xfb_obj
      = ctx->TransformFeedback.CurrentObject;
   FLUSH_CURRENT(ctx, 0);

   if (count <= 0) {
      if (count < 0)
         _mesa_error(ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
      return GL_FALSE;
   }

   if (!_mesa_valid_prim_mode(ctx, mode, "glDrawArrays")) {
      return GL_FALSE;
   }

   if (!check_valid_to_render(ctx, "glDrawArrays"))
      return GL_FALSE;

   if (ctx->Const.CheckArrayBounds) {
      if (start + count > (GLint) ctx->Array.ArrayObj->_MaxElement)
         return GL_FALSE;
   }

   /* From the GLES3 specification, section 2.14.2 (Transform Feedback
    * Primitive Capture):
    *
    *   The error INVALID_OPERATION is generated by DrawArrays and
    *   DrawArraysInstanced if recording the vertices of a primitive to the
    *   buffer objects being used for transform feedback purposes would result
    *   in either exceeding the limits of any buffer object’s size, or in
    *   exceeding the end position offset + size − 1, as set by
    *   BindBufferRange.
    *
    * This is in contrast to the behaviour of desktop GL, where the extra
    * primitives are silently dropped from the transform feedback buffer.
    */
   if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) {
      size_t prim_count = vbo_count_tessellated_primitives(mode, count, 1);
      if (xfb_obj->GlesRemainingPrims < prim_count) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glDrawArrays(exceeds transform feedback size)");
         return GL_FALSE;
      }
      xfb_obj->GlesRemainingPrims -= prim_count;
   }

   return GL_TRUE;
}
static bool
validate_DrawElements_common(struct gl_context *ctx,
                             GLenum mode, GLsizei count, GLenum type,
                             const GLvoid *indices,
                             const char *caller)
{
   /* From the GLES3 specification, section 2.14.2 (Transform Feedback
    * Primitive Capture):
    *
    *   The error INVALID_OPERATION is also generated by DrawElements,
    *   DrawElementsInstanced, and DrawRangeElements while transform feedback
    *   is active and not paused, regardless of mode.
    */
   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;
   }

   if (count < 0) {
      _mesa_error(ctx, GL_INVALID_VALUE, "%s(count)", caller);
      return false;
   }

   if (!_mesa_valid_prim_mode(ctx, mode, caller)) {
      return false;
   }

   if (!valid_elements_type(ctx, type, caller))
      return false;

   if (!check_valid_to_render(ctx, caller))
      return false;

   /* Not using a VBO for indices, so avoid NULL pointer derefs later.
    */
   if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj) && indices == NULL)
      return false;

   if (count == 0)
      return false;

   return true;
}
Esempio n. 9
0
GLboolean
_mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
                                     GLenum mode,
                                     struct gl_transform_feedback_object *obj,
                                     GLuint stream,
                                     GLsizei numInstances)
{
   FLUSH_CURRENT(ctx, 0);

   if (!_mesa_valid_prim_mode(ctx, mode, "glDrawTransformFeedback*(mode)")) {
      return GL_FALSE;
   }

   if (!obj) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glDrawTransformFeedback*(name)");
      return GL_FALSE;
   }

   if (!obj->EndedAnytime) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawTransformFeedback*");
      return GL_FALSE;
   }

   if (stream >= ctx->Const.MaxVertexStreams) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glDrawTransformFeedbackStream*(index>=MaxVertexStream)");
      return GL_FALSE;
   }

   if (numInstances <= 0) {
      if (numInstances < 0)
         _mesa_error(ctx, GL_INVALID_VALUE,
                     "glDrawTransformFeedback*Instanced(numInstances=%d)",
                     numInstances);
      return GL_FALSE;
   }

   if (!check_valid_to_render(ctx, "glDrawTransformFeedback*")) {
      return GL_FALSE;
   }

   return GL_TRUE;
}
Esempio n. 10
0
GLboolean
_mesa_validate_DrawArraysInstanced(struct gl_context *ctx, GLenum mode, GLint first,
                                   GLsizei count, GLsizei numInstances)
{
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);

   if (count <= 0) {
      if (count < 0)
         _mesa_error(ctx, GL_INVALID_VALUE,
                     "glDrawArraysInstanced(count=%d)", count);
      return GL_FALSE;
   }

   if (mode > GL_TRIANGLE_STRIP_ADJACENCY_ARB) {
      _mesa_error(ctx, GL_INVALID_ENUM,
                  "glDrawArraysInstanced(mode=0x%x)", mode);
      return GL_FALSE;
   }

   if (numInstances <= 0) {
      if (numInstances < 0)
         _mesa_error(ctx, GL_INVALID_VALUE,
                     "glDrawArraysInstanced(numInstances=%d)", numInstances);
      return GL_FALSE;
   }

   if (!check_valid_to_render(ctx, "glDrawArraysInstanced(invalid to render)"))
      return GL_FALSE;

   if (ctx->CompileFlag) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glDrawArraysInstanced(display list");
      return GL_FALSE;
   }

   if (ctx->Const.CheckArrayBounds) {
      if (first + count > (GLint) ctx->Array.ArrayObj->_MaxElement)
         return GL_FALSE;
   }

   return GL_TRUE;
}
Esempio n. 11
0
/**
 * Error checking for glMultiDrawElements().  Includes parameter checking
 * and VBO bounds checking.
 * \return GL_TRUE if OK to render, GL_FALSE if error found
 */
GLboolean
_mesa_validate_MultiDrawElements(struct gl_context *ctx,
                                 GLenum mode, const GLsizei *count,
                                 GLenum type, const GLvoid * const *indices,
                                 GLuint primcount)
{
   unsigned i;

   FLUSH_CURRENT(ctx, 0);

   for (i = 0; i < primcount; i++) {
      if (count[i] < 0) {
         _mesa_error(ctx, GL_INVALID_VALUE,
                     "glMultiDrawElements(count)" );
         return GL_FALSE;
      }
   }

   if (!_mesa_valid_prim_mode(ctx, mode, "glMultiDrawElements")) {
      return GL_FALSE;
   }

   if (!valid_elements_type(ctx, type, "glMultiDrawElements"))
      return GL_FALSE;

   if (!check_valid_to_render(ctx, "glMultiDrawElements"))
      return GL_FALSE;

   /* Not using a VBO for indices, so avoid NULL pointer derefs later.
    */
   if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj)) {
      for (i = 0; i < primcount; i++) {
         if (!indices[i])
            return GL_FALSE;
      }
   }

   return GL_TRUE;
}
Esempio n. 12
0
static GLboolean
valid_draw_indirect(struct gl_context *ctx,
                    GLenum mode, const GLvoid *indirect,
                    GLsizei size, const char *name)
{
   const uint64_t end = (uint64_t) (uintptr_t) indirect + size;

   /* OpenGL ES 3.1 spec. section 10.5:
    *
    *      "DrawArraysIndirect requires that all data sourced for the
    *      command, including the DrawArraysIndirectCommand
    *      structure,  be in buffer objects,  and may not be called when
    *      the default vertex array object is bound."
    */
   if (ctx->Array.VAO == ctx->Array.DefaultVAO) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "(no VAO bound)");
      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;

   /* OpenGL ES 3.1 specification, section 10.5:
    *
    *      "An INVALID_OPERATION error is generated if
    *      transform feedback is active and not paused."
    */
   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);
   }

   /* From OpenGL version 4.4. section 10.5
    * and OpenGL ES 3.1, section 10.6:
    *
    *      "An INVALID_VALUE error is generated if indirect is not a
    *       multiple of the size, in basic machine units, of uint."
    */
   if ((GLsizeiptr)indirect & (sizeof(GLuint) - 1)) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "%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_check_disallowed_mapping(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;
}
Esempio n. 13
0
static bool
validate_draw_arrays(struct gl_context *ctx, const char *func,
                     GLenum mode, GLsizei count, GLsizei numInstances)
{
   struct gl_transform_feedback_object *xfb_obj
      = ctx->TransformFeedback.CurrentObject;
   FLUSH_CURRENT(ctx, 0);

   if (count < 0) {
      _mesa_error(ctx, GL_INVALID_VALUE, "%s(count)", func);
      return false;
   }

   if (!_mesa_valid_prim_mode(ctx, mode, func))
      return false;

   if (!check_valid_to_render(ctx, func))
      return false;

   /* From the GLES3 specification, section 2.14.2 (Transform Feedback
    * Primitive Capture):
    *
    *   The error INVALID_OPERATION is generated by DrawArrays and
    *   DrawArraysInstanced if recording the vertices of a primitive to the
    *   buffer objects being used for transform feedback purposes would result
    *   in either exceeding the limits of any buffer object’s size, or in
    *   exceeding the end position offset + size − 1, as set by
    *   BindBufferRange.
    *
    * This is in contrast to the behaviour of desktop GL, where the extra
    * primitives are silently dropped from the transform feedback buffer.
    *
    * This text is removed in ES 3.2, presumably because it's not really
    * implementable with geometry and tessellation shaders.  In fact,
    * the OES_geometry_shader spec says:
    *
    *    "(13) Does this extension change how transform feedback operates
    *     compared to unextended OpenGL ES 3.0 or 3.1?
    *
    *     RESOLVED: Yes. Because dynamic geometry amplification in a geometry
    *     shader can make it difficult if not impossible to predict the amount
    *     of geometry that may be generated in advance of executing the shader,
    *     the draw-time error for transform feedback buffer overflow conditions
    *     is removed and replaced with the GL behavior (primitives are not
    *     written and the corresponding counter is not updated)..."
    */
   if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx) &&
       !_mesa_has_OES_geometry_shader(ctx) &&
       !_mesa_has_OES_tessellation_shader(ctx)) {
      size_t prim_count = vbo_count_tessellated_primitives(mode, count, 1);
      if (xfb_obj->GlesRemainingPrims < prim_count) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "%s(exceeds transform feedback size)", func);
         return false;
      }
      xfb_obj->GlesRemainingPrims -= prim_count;
   }

   if (count == 0)
      return false;

   return true;
}
Esempio n. 14
0
/**
 * Error checking for glDrawRangeElements().  Includes parameter checking
 * and VBO bounds checking.
 * \return GL_TRUE if OK to render, GL_FALSE if error found
 */
GLboolean
_mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode,
				 GLuint start, GLuint end,
				 GLsizei count, GLenum type,
				 const GLvoid *indices)
{
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);

   if (count <= 0) {
      if (count < 0)
	 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(count)" );
      return GL_FALSE;
   }

   if (mode > GL_POLYGON) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(mode)" );
      return GL_FALSE;
   }

   if (end < start) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(end<start)");
      return GL_FALSE;
   }

   if (type != GL_UNSIGNED_INT &&
       type != GL_UNSIGNED_BYTE &&
       type != GL_UNSIGNED_SHORT) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(type)" );
      return GL_FALSE;
   }

   if (ctx->NewState)
      _mesa_update_state(ctx);

   if (!check_valid_to_render(ctx, "RangeElements"))
      return GL_FALSE;

   /* Vertex buffer object tests */
   if (ctx->Array.ElementArrayBufferObj->Name) {
      /* use indices in the buffer object */
      /* make sure count doesn't go outside buffer bounds */
      if (index_bytes(type, count) > ctx->Array.ElementArrayBufferObj->Size) {
         _mesa_warning(ctx, "glDrawRangeElements index out of buffer bounds");
         return GL_FALSE;
      }
   }
   else {
      /* not using a VBO */
      if (!indices)
         return GL_FALSE;
   }

   if (ctx->Const.CheckArrayBounds) {
      GLuint max = max_buffer_index(ctx, count, type, indices,
                                    ctx->Array.ElementArrayBufferObj);
      if (max >= ctx->Array.ArrayObj->_MaxElement) {
         /* the max element is out of bounds of one or more enabled arrays */
         return GL_FALSE;
      }
   }

   return GL_TRUE;
}
Esempio n. 15
0
static bool
validate_DrawElements_common(struct gl_context *ctx,
                             GLenum mode, GLsizei count, GLenum type,
                             const GLvoid *indices,
                             const char *caller)
{
   /* Section 2.14.2 (Transform Feedback Primitive Capture) of the OpenGL ES
    * 3.1 spec says:
    *
    *   The error INVALID_OPERATION is also generated by DrawElements,
    *   DrawElementsInstanced, and DrawRangeElements while transform feedback
    *   is active and not paused, regardless of mode.
    *
    * The OES_geometry_shader_spec says:
    *
    *    Issues:
    *
    *    ...
    *
    *    (13) Does this extension change how transform feedback operates
    *    compared to unextended OpenGL ES 3.0 or 3.1?
    *
    *    RESOLVED: Yes... Since we no longer require being able to predict how
    *    much geometry will be generated, we also lift the restriction that
    *    only DrawArray* commands are supported and also support the
    *    DrawElements* commands for transform feedback.
    *
    * This should also be reflected in the body of the spec, but that appears
    * to have been overlooked.  The body of the spec only explicitly allows
    * the indirect versions.
    */
   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;
   }

   if (count < 0) {
      _mesa_error(ctx, GL_INVALID_VALUE, "%s(count)", caller);
      return false;
   }

   if (!_mesa_valid_prim_mode(ctx, mode, caller)) {
      return false;
   }

   if (!valid_elements_type(ctx, type, caller))
      return false;

   if (!check_valid_to_render(ctx, caller))
      return false;

   /* Not using a VBO for indices, so avoid NULL pointer derefs later.
    */
   if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj) && indices == NULL)
      return false;

   if (count == 0)
      return false;

   return true;
}