Example #1
0
/**
 * Update internal counters based on the the drawing operation described in
 * prim.
 */
static void
brw_update_primitive_count(struct brw_context *brw,
                           const struct _mesa_prim *prim)
{
   uint32_t count
      = vbo_count_tessellated_primitives(prim->mode, prim->count,
                                         prim->num_instances);
   brw->sol.primitives_generated += count;
   if (_mesa_is_xfb_active_and_unpaused(&brw->intel.ctx)) {
      /* Update brw->sol.svbi_0_max_index to reflect the amount by which the
       * hardware is going to increment SVBI 0 when this drawing operation
       * occurs.  This is necessary because the kernel does not (yet) save and
       * restore GPU registers when context switching, so we'll need to be
       * able to reload SVBI 0 with the correct value in case we have to start
       * a new batch buffer.
       */
      unsigned verts = verts_per_prim(prim->mode);
      uint32_t space_avail =
         (brw->sol.svbi_0_max_index - brw->sol.svbi_0_starting_index) / verts;
      uint32_t primitives_written = MIN2 (space_avail, count);
      brw->sol.svbi_0_starting_index += verts * primitives_written;

      /* And update the TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query. */
      brw->sol.primitives_written += primitives_written;
   }
}
Example #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)
{
   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;
}
Example #3
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;
}