/** * 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; } }
/** * 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_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; }