X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fvbo%2Fvbo_exec.c;h=dc26dfd37b48b2f0b34e19e62e8be6a7f2d9ad79;hb=43a6e84927e3b1290f6f211f5dfb184dfe5a719e;hp=1efa74945dd73afd9f5bcc8072cfd83773fb6c51;hpb=bb1b01616b6cb9b0a1cab74e10940ce346cb8a3d;p=mesa.git diff --git a/src/mesa/vbo/vbo_exec.c b/src/mesa/vbo/vbo_exec.c index 1efa74945dd..dc26dfd37b4 100644 --- a/src/mesa/vbo/vbo_exec.c +++ b/src/mesa/vbo/vbo_exec.c @@ -1,6 +1,5 @@ /* * Mesa 3-D graphics library - * Version: 6.3 * * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. * @@ -17,54 +16,47 @@ * 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 - * BRIAN PAUL 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. + * 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 + * Keith Whitwell */ -#include "main/api_arrayelt.h" #include "main/glheader.h" -#include "main/imports.h" -#include "main/context.h" -#include "main/macros.h" #include "main/mtypes.h" -#include "main/dlist.h" #include "main/vtxfmt.h" - #include "vbo_context.h" -void vbo_exec_init( GLcontext *ctx ) + + +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; + /* aelt_context should have been created by the caller */ + assert(ctx->aelt_context); - vbo_exec_vtx_init( exec ); - vbo_exec_array_init( exec ); - - /* Hook our functions into exec and compile dispatch tables. - */ - _mesa_install_exec_vtxfmt( ctx, &exec->vtxfmt ); + vbo_exec_vtx_init(exec); ctx->Driver.NeedFlush = 0; ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; - ctx->Driver.FlushVertices = vbo_exec_FlushVertices; - vbo_exec_invalidate_state( ctx, ~0 ); + /* The aelt_context state should still be dirty from its creation */ + assert(_ae_is_state_dirty(ctx)); + + exec->array.recalculate_inputs = GL_TRUE; + exec->eval.recalculate_maps = GL_TRUE; } -void vbo_exec_destroy( GLcontext *ctx ) +void vbo_exec_destroy( struct gl_context *ctx ) { struct vbo_exec_context *exec = &vbo_context(ctx)->exec; @@ -74,24 +66,167 @@ void vbo_exec_destroy( GLcontext *ctx ) } 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( GLcontext *ctx, GLuint 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) { - struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + 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; + case GL_LINES_ADJACENCY: + num_primitives = count / 4; + break; + case GL_LINE_STRIP_ADJACENCY: + num_primitives = count >= 4 ? count - 3 : 0; + break; + case GL_TRIANGLES_ADJACENCY: + num_primitives = count / 6; + break; + case GL_TRIANGLE_STRIP_ADJACENCY: + num_primitives = count >= 6 ? (count - 4) / 2 : 0; + break; + default: + assert(!"Unexpected primitive type in count_tessellated_primitives"); + num_primitives = 0; + break; + } + return num_primitives * num_instances; +} + - if (new_state & (_NEW_PROGRAM|_NEW_EVAL)) - exec->eval.recalculate_maps = 1; - _ae_invalidate_state(ctx, new_state); +/** + * In some degenarate cases we can improve our ability to merge + * consecutive primitives. For example: + * glBegin(GL_LINE_STRIP); + * glVertex(1); + * glVertex(1); + * glEnd(); + * glBegin(GL_LINE_STRIP); + * glVertex(1); + * glVertex(1); + * glEnd(); + * Can be merged as a GL_LINES prim with four vertices. + * + * This function converts 2-vertex line strips/loops into GL_LINES, etc. + */ +void +vbo_try_prim_conversion(struct _mesa_prim *p) +{ + if (p->mode == GL_LINE_STRIP && p->count == 2) { + /* convert 2-vertex line strip to a separate line */ + p->mode = GL_LINES; + } + else if ((p->mode == GL_TRIANGLE_STRIP || p->mode == GL_TRIANGLE_FAN) + && p->count == 3) { + /* convert 3-vertex tri strip or fan to a separate triangle */ + p->mode = GL_TRIANGLES; + } + + /* Note: we can't convert a 4-vertex quad strip to a separate quad + * because the vertex ordering is different. We'd have to muck + * around in the vertex data to make it work. + */ } +/** + * Helper function for determining if two subsequent glBegin/glEnd + * primitives can be combined. This is only possible for GL_POINTS, + * GL_LINES, GL_TRIANGLES and GL_QUADS. + * If we return true, it means that we can concatenate p1 onto p0 (and + * discard p1). + */ +bool +vbo_can_merge_prims(const struct _mesa_prim *p0, const struct _mesa_prim *p1) +{ + if (!p0->begin || + !p1->begin || + !p0->end || + !p1->end) + return false; + + /* The prim mode must match (ex: both GL_TRIANGLES) */ + if (p0->mode != p1->mode) + return false; + + /* p1's vertices must come right after p0 */ + if (p0->start + p0->count != p1->start) + return false; + + if (p0->basevertex != p1->basevertex || + p0->num_instances != p1->num_instances || + p0->base_instance != p1->base_instance) + return false; + + /* can always merge subsequent GL_POINTS primitives */ + if (p0->mode == GL_POINTS) + return true; + + /* independent lines with no extra vertices */ + if (p0->mode == GL_LINES && p0->count % 2 == 0 && p1->count % 2 == 0) + return true; + + /* independent tris */ + if (p0->mode == GL_TRIANGLES && p0->count % 3 == 0 && p1->count % 3 == 0) + return true; + + /* independent quads */ + if (p0->mode == GL_QUADS && p0->count % 4 == 0 && p1->count % 4 == 0) + return true; + + return false; +} +/** + * If we've determined that p0 and p1 can be merged, this function + * concatenates p1 onto p0. + */ +void +vbo_merge_prims(struct _mesa_prim *p0, const struct _mesa_prim *p1) +{ + assert(vbo_can_merge_prims(p0, p1)); + p0->count += p1->count; + p0->end = p1->end; +}