/* * Mesa 3-D graphics library * Version: 6.3 * * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Keith Whitwell */ #include "main/api_arrayelt.h" #include "main/glheader.h" #include "main/mtypes.h" #include "main/vtxfmt.h" #include "vbo_context.h" void vbo_exec_init( struct gl_context *ctx ) { struct vbo_exec_context *exec = &vbo_context(ctx)->exec; exec->ctx = ctx; /* Initialize the arrayelt helper */ if (!ctx->aelt_context && !_ae_create_context( ctx )) return; vbo_exec_vtx_init( exec ); vbo_exec_array_init( exec ); ctx->Driver.NeedFlush = 0; ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; ctx->Driver.BeginVertices = vbo_exec_BeginVertices; ctx->Driver.FlushVertices = vbo_exec_FlushVertices; vbo_exec_invalidate_state( ctx, ~0 ); } void vbo_exec_destroy( struct gl_context *ctx ) { struct vbo_exec_context *exec = &vbo_context(ctx)->exec; if (ctx->aelt_context) { _ae_destroy_context( ctx ); ctx->aelt_context = NULL; } vbo_exec_vtx_destroy( exec ); vbo_exec_array_destroy( exec ); } /** * Really want to install these callbacks to a central facility to be * invoked according to the state flags. That will have to wait for a * mesa rework: */ void vbo_exec_invalidate_state( struct gl_context *ctx, GLuint new_state ) { struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; if (!exec->validating && new_state & (_NEW_PROGRAM|_NEW_ARRAY)) { exec->array.recalculate_inputs = GL_TRUE; /* If we ended up here because a VAO was deleted, the _DrawArrays * pointer which pointed to the VAO might be invalid now, so set it * to NULL. This prevents crashes in driver functions like Clear * where driver state validation might occur, but the vbo module is * still in an invalid state. * * Drivers should skip vertex array state validation if _DrawArrays * is NULL. It also has no effect on performance, because attrib * bindings will be recalculated anyway. */ if (vbo->last_draw_method == DRAW_ARRAYS) { ctx->Array._DrawArrays = NULL; vbo->last_draw_method = DRAW_NONE; } } if (new_state & _NEW_EVAL) exec->eval.recalculate_maps = 1; _ae_invalidate_state(ctx, new_state); } /** * Figure out the number of transform feedback primitives that will be output * considering the drawing mode, number of vertices, and instance count, * assuming that no geometry shading is done and primitive restart is not * used. * * This is used by driver back-ends in implementing the PRIMITIVES_GENERATED * and TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN queries. It is also used to * pre-validate draw calls in GLES3 (where draw calls only succeed if there is * enough room in the transform feedback buffer for the result). */ size_t vbo_count_tessellated_primitives(GLenum mode, GLuint count, GLuint num_instances) { size_t num_primitives; switch (mode) { case GL_POINTS: num_primitives = count; break; case GL_LINE_STRIP: num_primitives = count >= 2 ? count - 1 : 0; break; case GL_LINE_LOOP: num_primitives = count >= 2 ? count : 0; break; case GL_LINES: num_primitives = count / 2; break; case GL_TRIANGLE_STRIP: case GL_TRIANGLE_FAN: case GL_POLYGON: num_primitives = count >= 3 ? count - 2 : 0; break; case GL_TRIANGLES: num_primitives = count / 3; break; case GL_QUAD_STRIP: num_primitives = count >= 4 ? ((count / 2) - 1) * 2 : 0; break; case GL_QUADS: num_primitives = (count / 4) * 2; break; default: assert(!"Unexpected primitive type in count_tessellated_primitives"); num_primitives = 0; break; } return num_primitives * num_instances; }