Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included
  14.  * in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  20.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  22.  * OTHER DEALINGS IN THE SOFTWARE.
  23.  *
  24.  * Authors:
  25.  *    Keith Whitwell <keith@tungstengraphics.com>
  26.  */
  27.  
  28.  
  29. #include "main/api_arrayelt.h"
  30. #include "main/glheader.h"
  31. #include "main/mtypes.h"
  32. #include "main/vtxfmt.h"
  33. #include "vbo_context.h"
  34.  
  35.  
  36.  
  37. void vbo_exec_init( struct gl_context *ctx )
  38. {
  39.    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
  40.  
  41.    exec->ctx = ctx;
  42.  
  43.    /* Initialize the arrayelt helper
  44.     */
  45.    if (!ctx->aelt_context &&
  46.        !_ae_create_context( ctx ))
  47.       return;
  48.  
  49.    vbo_exec_vtx_init( exec );
  50.  
  51.    ctx->Driver.NeedFlush = 0;
  52.    ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
  53.    ctx->Driver.BeginVertices = vbo_exec_BeginVertices;
  54.    ctx->Driver.FlushVertices = vbo_exec_FlushVertices;
  55.  
  56.    vbo_exec_invalidate_state( ctx, ~0 );
  57. }
  58.  
  59.  
  60. void vbo_exec_destroy( struct gl_context *ctx )
  61. {
  62.    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
  63.  
  64.    if (ctx->aelt_context) {
  65.       _ae_destroy_context( ctx );
  66.       ctx->aelt_context = NULL;
  67.    }
  68.  
  69.    vbo_exec_vtx_destroy( exec );
  70. }
  71.  
  72.  
  73. /**
  74.  * Really want to install these callbacks to a central facility to be
  75.  * invoked according to the state flags.  That will have to wait for a
  76.  * mesa rework:
  77.  */
  78. void vbo_exec_invalidate_state( struct gl_context *ctx, GLuint new_state )
  79. {
  80.    struct vbo_context *vbo = vbo_context(ctx);
  81.    struct vbo_exec_context *exec = &vbo->exec;
  82.  
  83.    if (!exec->validating && new_state & (_NEW_PROGRAM|_NEW_ARRAY)) {
  84.       exec->array.recalculate_inputs = GL_TRUE;
  85.  
  86.       /* If we ended up here because a VAO was deleted, the _DrawArrays
  87.        * pointer which pointed to the VAO might be invalid now, so set it
  88.        * to NULL.  This prevents crashes in driver functions like Clear
  89.        * where driver state validation might occur, but the vbo module is
  90.        * still in an invalid state.
  91.        *
  92.        * Drivers should skip vertex array state validation if _DrawArrays
  93.        * is NULL.  It also has no effect on performance, because attrib
  94.        * bindings will be recalculated anyway.
  95.        */
  96.       if (vbo->last_draw_method == DRAW_ARRAYS) {
  97.          ctx->Array._DrawArrays = NULL;
  98.          vbo->last_draw_method = DRAW_NONE;
  99.       }
  100.    }
  101.  
  102.    if (new_state & _NEW_EVAL)
  103.       exec->eval.recalculate_maps = 1;
  104.  
  105.    _ae_invalidate_state(ctx, new_state);
  106. }
  107.  
  108.  
  109. /**
  110.  * Figure out the number of transform feedback primitives that will be output
  111.  * considering the drawing mode, number of vertices, and instance count,
  112.  * assuming that no geometry shading is done and primitive restart is not
  113.  * used.
  114.  *
  115.  * This is used by driver back-ends in implementing the PRIMITIVES_GENERATED
  116.  * and TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN queries.  It is also used to
  117.  * pre-validate draw calls in GLES3 (where draw calls only succeed if there is
  118.  * enough room in the transform feedback buffer for the result).
  119.  */
  120. size_t
  121. vbo_count_tessellated_primitives(GLenum mode, GLuint count,
  122.                                  GLuint num_instances)
  123. {
  124.    size_t num_primitives;
  125.    switch (mode) {
  126.    case GL_POINTS:
  127.       num_primitives = count;
  128.       break;
  129.    case GL_LINE_STRIP:
  130.       num_primitives = count >= 2 ? count - 1 : 0;
  131.       break;
  132.    case GL_LINE_LOOP:
  133.       num_primitives = count >= 2 ? count : 0;
  134.       break;
  135.    case GL_LINES:
  136.       num_primitives = count / 2;
  137.       break;
  138.    case GL_TRIANGLE_STRIP:
  139.    case GL_TRIANGLE_FAN:
  140.    case GL_POLYGON:
  141.       num_primitives = count >= 3 ? count - 2 : 0;
  142.       break;
  143.    case GL_TRIANGLES:
  144.       num_primitives = count / 3;
  145.       break;
  146.    case GL_QUAD_STRIP:
  147.       num_primitives = count >= 4 ? ((count / 2) - 1) * 2 : 0;
  148.       break;
  149.    case GL_QUADS:
  150.       num_primitives = (count / 4) * 2;
  151.       break;
  152.    default:
  153.       assert(!"Unexpected primitive type in count_tessellated_primitives");
  154.       num_primitives = 0;
  155.       break;
  156.    }
  157.    return num_primitives * num_instances;
  158. }
  159.  
  160.  
  161.  
  162. /**
  163.  * In some degenarate cases we can improve our ability to merge
  164.  * consecutive primitives.  For example:
  165.  * glBegin(GL_LINE_STRIP);
  166.  * glVertex(1);
  167.  * glVertex(1);
  168.  * glEnd();
  169.  * glBegin(GL_LINE_STRIP);
  170.  * glVertex(1);
  171.  * glVertex(1);
  172.  * glEnd();
  173.  * Can be merged as a GL_LINES prim with four vertices.
  174.  *
  175.  * This function converts 2-vertex line strips/loops into GL_LINES, etc.
  176.  */
  177. void
  178. vbo_try_prim_conversion(struct _mesa_prim *p)
  179. {
  180.    if (p->mode == GL_LINE_STRIP && p->count == 2) {
  181.       /* convert 2-vertex line strip to a separate line */
  182.       p->mode = GL_LINES;
  183.    }
  184.    else if ((p->mode == GL_TRIANGLE_STRIP || p->mode == GL_TRIANGLE_FAN)
  185.        && p->count == 3) {
  186.       /* convert 3-vertex tri strip or fan to a separate triangle */
  187.       p->mode = GL_TRIANGLES;
  188.    }
  189.  
  190.    /* Note: we can't convert a 4-vertex quad strip to a separate quad
  191.     * because the vertex ordering is different.  We'd have to muck
  192.     * around in the vertex data to make it work.
  193.     */
  194. }
  195.  
  196.  
  197. /**
  198.  * Helper function for determining if two subsequent glBegin/glEnd
  199.  * primitives can be combined.  This is only possible for GL_POINTS,
  200.  * GL_LINES, GL_TRIANGLES and GL_QUADS.
  201.  * If we return true, it means that we can concatenate p1 onto p0 (and
  202.  * discard p1).
  203.  */
  204. bool
  205. vbo_can_merge_prims(const struct _mesa_prim *p0, const struct _mesa_prim *p1)
  206. {
  207.    if (!p0->begin ||
  208.        !p1->begin ||
  209.        !p0->end ||
  210.        !p1->end)
  211.       return false;
  212.  
  213.    /* The prim mode must match (ex: both GL_TRIANGLES) */
  214.    if (p0->mode != p1->mode)
  215.       return false;
  216.  
  217.    /* p1's vertices must come right after p0 */
  218.    if (p0->start + p0->count != p1->start)
  219.       return false;
  220.  
  221.    if (p0->basevertex != p1->basevertex ||
  222.        p0->num_instances != p1->num_instances ||
  223.        p0->base_instance != p1->base_instance)
  224.       return false;
  225.  
  226.    /* can always merge subsequent GL_POINTS primitives */
  227.    if (p0->mode == GL_POINTS)
  228.       return true;
  229.  
  230.    /* independent lines with no extra vertices */
  231.    if (p0->mode == GL_LINES && p0->count % 2 == 0 && p1->count % 2 == 0)
  232.       return true;
  233.  
  234.    /* independent tris */
  235.    if (p0->mode == GL_TRIANGLES && p0->count % 3 == 0 && p1->count % 3 == 0)
  236.       return true;
  237.  
  238.    /* independent quads */
  239.    if (p0->mode == GL_QUADS && p0->count % 4 == 0 && p1->count % 4 == 0)
  240.       return true;
  241.  
  242.    return false;
  243. }
  244.  
  245.  
  246. /**
  247.  * If we've determined that p0 and p1 can be merged, this function
  248.  * concatenates p1 onto p0.
  249.  */
  250. void
  251. vbo_merge_prims(struct _mesa_prim *p0, const struct _mesa_prim *p1)
  252. {
  253.    assert(vbo_can_merge_prims(p0, p1));
  254.  
  255.    p0->count += p1->count;
  256.    p0->end = p1->end;
  257. }
  258.