Subversion Repositories Kolibri OS

Rev

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 <keithw@vmware.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.  
  87.    if (new_state & _NEW_EVAL)
  88.       exec->eval.recalculate_maps = GL_TRUE;
  89.  
  90.    _ae_invalidate_state(ctx, new_state);
  91. }
  92.  
  93.  
  94. /**
  95.  * Figure out the number of transform feedback primitives that will be output
  96.  * considering the drawing mode, number of vertices, and instance count,
  97.  * assuming that no geometry shading is done and primitive restart is not
  98.  * used.
  99.  *
  100.  * This is used by driver back-ends in implementing the PRIMITIVES_GENERATED
  101.  * and TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN queries.  It is also used to
  102.  * pre-validate draw calls in GLES3 (where draw calls only succeed if there is
  103.  * enough room in the transform feedback buffer for the result).
  104.  */
  105. size_t
  106. vbo_count_tessellated_primitives(GLenum mode, GLuint count,
  107.                                  GLuint num_instances)
  108. {
  109.    size_t num_primitives;
  110.    switch (mode) {
  111.    case GL_POINTS:
  112.       num_primitives = count;
  113.       break;
  114.    case GL_LINE_STRIP:
  115.       num_primitives = count >= 2 ? count - 1 : 0;
  116.       break;
  117.    case GL_LINE_LOOP:
  118.       num_primitives = count >= 2 ? count : 0;
  119.       break;
  120.    case GL_LINES:
  121.       num_primitives = count / 2;
  122.       break;
  123.    case GL_TRIANGLE_STRIP:
  124.    case GL_TRIANGLE_FAN:
  125.    case GL_POLYGON:
  126.       num_primitives = count >= 3 ? count - 2 : 0;
  127.       break;
  128.    case GL_TRIANGLES:
  129.       num_primitives = count / 3;
  130.       break;
  131.    case GL_QUAD_STRIP:
  132.       num_primitives = count >= 4 ? ((count / 2) - 1) * 2 : 0;
  133.       break;
  134.    case GL_QUADS:
  135.       num_primitives = (count / 4) * 2;
  136.       break;
  137.    case GL_LINES_ADJACENCY:
  138.       num_primitives = count / 4;
  139.       break;
  140.    case GL_LINE_STRIP_ADJACENCY:
  141.       num_primitives = count >= 4 ? count - 3 : 0;
  142.       break;
  143.    case GL_TRIANGLES_ADJACENCY:
  144.       num_primitives = count / 6;
  145.       break;
  146.    case GL_TRIANGLE_STRIP_ADJACENCY:
  147.       num_primitives = count >= 6 ? (count - 4) / 2 : 0;
  148.       break;
  149.    default:
  150.       assert(!"Unexpected primitive type in count_tessellated_primitives");
  151.       num_primitives = 0;
  152.       break;
  153.    }
  154.    return num_primitives * num_instances;
  155. }
  156.  
  157.  
  158.  
  159. /**
  160.  * In some degenarate cases we can improve our ability to merge
  161.  * consecutive primitives.  For example:
  162.  * glBegin(GL_LINE_STRIP);
  163.  * glVertex(1);
  164.  * glVertex(1);
  165.  * glEnd();
  166.  * glBegin(GL_LINE_STRIP);
  167.  * glVertex(1);
  168.  * glVertex(1);
  169.  * glEnd();
  170.  * Can be merged as a GL_LINES prim with four vertices.
  171.  *
  172.  * This function converts 2-vertex line strips/loops into GL_LINES, etc.
  173.  */
  174. void
  175. vbo_try_prim_conversion(struct _mesa_prim *p)
  176. {
  177.    if (p->mode == GL_LINE_STRIP && p->count == 2) {
  178.       /* convert 2-vertex line strip to a separate line */
  179.       p->mode = GL_LINES;
  180.    }
  181.    else if ((p->mode == GL_TRIANGLE_STRIP || p->mode == GL_TRIANGLE_FAN)
  182.        && p->count == 3) {
  183.       /* convert 3-vertex tri strip or fan to a separate triangle */
  184.       p->mode = GL_TRIANGLES;
  185.    }
  186.  
  187.    /* Note: we can't convert a 4-vertex quad strip to a separate quad
  188.     * because the vertex ordering is different.  We'd have to muck
  189.     * around in the vertex data to make it work.
  190.     */
  191. }
  192.  
  193.  
  194. /**
  195.  * Helper function for determining if two subsequent glBegin/glEnd
  196.  * primitives can be combined.  This is only possible for GL_POINTS,
  197.  * GL_LINES, GL_TRIANGLES and GL_QUADS.
  198.  * If we return true, it means that we can concatenate p1 onto p0 (and
  199.  * discard p1).
  200.  */
  201. bool
  202. vbo_can_merge_prims(const struct _mesa_prim *p0, const struct _mesa_prim *p1)
  203. {
  204.    if (!p0->begin ||
  205.        !p1->begin ||
  206.        !p0->end ||
  207.        !p1->end)
  208.       return false;
  209.  
  210.    /* The prim mode must match (ex: both GL_TRIANGLES) */
  211.    if (p0->mode != p1->mode)
  212.       return false;
  213.  
  214.    /* p1's vertices must come right after p0 */
  215.    if (p0->start + p0->count != p1->start)
  216.       return false;
  217.  
  218.    if (p0->basevertex != p1->basevertex ||
  219.        p0->num_instances != p1->num_instances ||
  220.        p0->base_instance != p1->base_instance)
  221.       return false;
  222.  
  223.    /* can always merge subsequent GL_POINTS primitives */
  224.    if (p0->mode == GL_POINTS)
  225.       return true;
  226.  
  227.    /* independent lines with no extra vertices */
  228.    if (p0->mode == GL_LINES && p0->count % 2 == 0 && p1->count % 2 == 0)
  229.       return true;
  230.  
  231.    /* independent tris */
  232.    if (p0->mode == GL_TRIANGLES && p0->count % 3 == 0 && p1->count % 3 == 0)
  233.       return true;
  234.  
  235.    /* independent quads */
  236.    if (p0->mode == GL_QUADS && p0->count % 4 == 0 && p1->count % 4 == 0)
  237.       return true;
  238.  
  239.    return false;
  240. }
  241.  
  242.  
  243. /**
  244.  * If we've determined that p0 and p1 can be merged, this function
  245.  * concatenates p1 onto p0.
  246.  */
  247. void
  248. vbo_merge_prims(struct _mesa_prim *p0, const struct _mesa_prim *p1)
  249. {
  250.    assert(vbo_can_merge_prims(p0, p1));
  251.  
  252.    p0->count += p1->count;
  253.    p0->end = p1->end;
  254. }
  255.