Subversion Repositories Kolibri OS

Rev

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

  1. /**************************************************************************
  2.  
  3. Copyright 2002-2008 Tungsten Graphics Inc., Cedar Park, Texas.
  4.  
  5. All Rights Reserved.
  6.  
  7. Permission is hereby granted, free of charge, to any person obtaining a
  8. copy of this software and associated documentation files (the "Software"),
  9. to deal in the Software without restriction, including without limitation
  10. on the rights to use, copy, modify, merge, publish, distribute, sub
  11. license, and/or sell copies of the Software, and to permit persons to whom
  12. the Software is furnished to do so, subject to the following conditions:
  13.  
  14. The above copyright notice and this permission notice (including the next
  15. paragraph) shall be included in all copies or substantial portions of the
  16. Software.
  17.  
  18. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  21. TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
  22. DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  23. OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  24. USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  
  26. **************************************************************************/
  27.  
  28. /*
  29.  * Authors:
  30.  *   Keith Whitwell <keith@tungstengraphics.com>
  31.  */
  32.  
  33. #include "main/glheader.h"
  34. #include "main/bufferobj.h"
  35. #include "main/context.h"
  36. #include "main/macros.h"
  37. #include "main/vtxfmt.h"
  38. #include "main/dlist.h"
  39. #include "main/eval.h"
  40. #include "main/state.h"
  41. #include "main/light.h"
  42. #include "main/api_arrayelt.h"
  43. #include "main/api_validate.h"
  44. #include "main/dispatch.h"
  45.  
  46. #include "vbo_context.h"
  47. #include "vbo_noop.h"
  48.  
  49.  
  50. #ifdef ERROR
  51. #undef ERROR
  52. #endif
  53.  
  54.  
  55. /** ID/name for immediate-mode VBO */
  56. #define IMM_BUFFER_NAME 0xaabbccdd
  57.  
  58.  
  59. static void reset_attrfv( struct vbo_exec_context *exec );
  60.  
  61.  
  62. /**
  63.  * Close off the last primitive, execute the buffer, restart the
  64.  * primitive.  
  65.  */
  66. static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec )
  67. {
  68.    if (exec->vtx.prim_count == 0) {
  69.       exec->vtx.copied.nr = 0;
  70.       exec->vtx.vert_count = 0;
  71.       exec->vtx.buffer_ptr = exec->vtx.buffer_map;
  72.    }
  73.    else {
  74.       GLuint last_begin = exec->vtx.prim[exec->vtx.prim_count-1].begin;
  75.       GLuint last_count;
  76.  
  77.       if (_mesa_inside_begin_end(exec->ctx)) {
  78.          GLint i = exec->vtx.prim_count - 1;
  79.          assert(i >= 0);
  80.          exec->vtx.prim[i].count = (exec->vtx.vert_count -
  81.                                     exec->vtx.prim[i].start);
  82.       }
  83.  
  84.       last_count = exec->vtx.prim[exec->vtx.prim_count-1].count;
  85.  
  86.       /* Execute the buffer and save copied vertices.
  87.        */
  88.       if (exec->vtx.vert_count)
  89.          vbo_exec_vtx_flush( exec, GL_FALSE );
  90.       else {
  91.          exec->vtx.prim_count = 0;
  92.          exec->vtx.copied.nr = 0;
  93.       }
  94.  
  95.       /* Emit a glBegin to start the new list.
  96.        */
  97.       assert(exec->vtx.prim_count == 0);
  98.  
  99.       if (_mesa_inside_begin_end(exec->ctx)) {
  100.          exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive;
  101.          exec->vtx.prim[0].start = 0;
  102.          exec->vtx.prim[0].count = 0;
  103.          exec->vtx.prim_count++;
  104.      
  105.          if (exec->vtx.copied.nr == last_count)
  106.             exec->vtx.prim[0].begin = last_begin;
  107.       }
  108.    }
  109. }
  110.  
  111.  
  112. /**
  113.  * Deal with buffer wrapping where provoked by the vertex buffer
  114.  * filling up, as opposed to upgrade_vertex().
  115.  */
  116. void vbo_exec_vtx_wrap( struct vbo_exec_context *exec )
  117. {
  118.    GLfloat *data = exec->vtx.copied.buffer;
  119.    GLuint i;
  120.  
  121.    /* Run pipeline on current vertices, copy wrapped vertices
  122.     * to exec->vtx.copied.
  123.     */
  124.    vbo_exec_wrap_buffers( exec );
  125.    
  126.    if (!exec->vtx.buffer_ptr) {
  127.       /* probably ran out of memory earlier when allocating the VBO */
  128.       return;
  129.    }
  130.  
  131.    /* Copy stored stored vertices to start of new list.
  132.     */
  133.    assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr);
  134.  
  135.    for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
  136.       memcpy( exec->vtx.buffer_ptr, data,
  137.               exec->vtx.vertex_size * sizeof(GLfloat));
  138.       exec->vtx.buffer_ptr += exec->vtx.vertex_size;
  139.       data += exec->vtx.vertex_size;
  140.       exec->vtx.vert_count++;
  141.    }
  142.  
  143.    exec->vtx.copied.nr = 0;
  144. }
  145.  
  146.  
  147. /**
  148.  * Copy the active vertex's values to the ctx->Current fields.
  149.  */
  150. static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
  151. {
  152.    struct gl_context *ctx = exec->ctx;
  153.    struct vbo_context *vbo = vbo_context(ctx);
  154.    GLuint i;
  155.  
  156.    for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
  157.       if (exec->vtx.attrsz[i]) {
  158.          /* Note: the exec->vtx.current[i] pointers point into the
  159.           * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
  160.           */
  161.          GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
  162.          GLfloat tmp[4];
  163.  
  164.          COPY_CLEAN_4V_TYPE_AS_FLOAT(tmp,
  165.                                      exec->vtx.attrsz[i],
  166.                                      exec->vtx.attrptr[i],
  167.                                      exec->vtx.attrtype[i]);
  168.          
  169.          if (exec->vtx.attrtype[i] != vbo->currval[i].Type ||
  170.              memcmp(current, tmp, sizeof(tmp)) != 0) {
  171.             memcpy(current, tmp, sizeof(tmp));
  172.          
  173.             /* Given that we explicitly state size here, there is no need
  174.              * for the COPY_CLEAN above, could just copy 16 bytes and be
  175.              * done.  The only problem is when Mesa accesses ctx->Current
  176.              * directly.
  177.              */
  178.             vbo->currval[i].Size = exec->vtx.attrsz[i];
  179.             vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat);
  180.             vbo->currval[i].Type = exec->vtx.attrtype[i];
  181.             vbo->currval[i].Integer =
  182.                   vbo_attrtype_to_integer_flag(exec->vtx.attrtype[i]);
  183.  
  184.             /* This triggers rather too much recalculation of Mesa state
  185.              * that doesn't get used (eg light positions).
  186.              */
  187.             if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
  188.                 i <= VBO_ATTRIB_MAT_BACK_INDEXES)
  189.                ctx->NewState |= _NEW_LIGHT;
  190.            
  191.             ctx->NewState |= _NEW_CURRENT_ATTRIB;
  192.          }
  193.       }
  194.    }
  195.  
  196.    /* Colormaterial -- this kindof sucks.
  197.     */
  198.    if (ctx->Light.ColorMaterialEnabled &&
  199.        exec->vtx.attrsz[VBO_ATTRIB_COLOR0]) {
  200.       _mesa_update_color_material(ctx,
  201.                                   ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
  202.    }
  203. }
  204.  
  205.  
  206. /**
  207.  * Copy current vertex attribute values into the current vertex.
  208.  */
  209. static void
  210. vbo_exec_copy_from_current(struct vbo_exec_context *exec)
  211. {
  212.    struct gl_context *ctx = exec->ctx;
  213.    struct vbo_context *vbo = vbo_context(ctx);
  214.    GLint i;
  215.  
  216.    for (i = VBO_ATTRIB_POS + 1; i < VBO_ATTRIB_MAX; i++) {
  217.       const GLfloat *current = (GLfloat *) vbo->currval[i].Ptr;
  218.       switch (exec->vtx.attrsz[i]) {
  219.       case 4: exec->vtx.attrptr[i][3] = current[3];
  220.       case 3: exec->vtx.attrptr[i][2] = current[2];
  221.       case 2: exec->vtx.attrptr[i][1] = current[1];
  222.       case 1: exec->vtx.attrptr[i][0] = current[0];
  223.          break;
  224.       }
  225.    }
  226. }
  227.  
  228.  
  229. /**
  230.  * Flush existing data, set new attrib size, replay copied vertices.
  231.  * This is called when we transition from a small vertex attribute size
  232.  * to a larger one.  Ex: glTexCoord2f -> glTexCoord4f.
  233.  * We need to go back over the previous 2-component texcoords and insert
  234.  * zero and one values.
  235.  */
  236. static void
  237. vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec,
  238.                              GLuint attr, GLuint newSize )
  239. {
  240.    struct gl_context *ctx = exec->ctx;
  241.    struct vbo_context *vbo = vbo_context(ctx);
  242.    const GLint lastcount = exec->vtx.vert_count;
  243.    GLfloat *old_attrptr[VBO_ATTRIB_MAX];
  244.    const GLuint old_vtx_size = exec->vtx.vertex_size; /* floats per vertex */
  245.    const GLuint oldSize = exec->vtx.attrsz[attr];
  246.    GLuint i;
  247.  
  248.    /* Run pipeline on current vertices, copy wrapped vertices
  249.     * to exec->vtx.copied.
  250.     */
  251.    vbo_exec_wrap_buffers( exec );
  252.  
  253.    if (unlikely(exec->vtx.copied.nr)) {
  254.       /* We're in the middle of a primitive, keep the old vertex
  255.        * format around to be able to translate the copied vertices to
  256.        * the new format.
  257.        */
  258.       memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr));
  259.    }
  260.  
  261.    if (unlikely(oldSize)) {
  262.       /* Do a COPY_TO_CURRENT to ensure back-copying works for the
  263.        * case when the attribute already exists in the vertex and is
  264.        * having its size increased.
  265.        */
  266.       vbo_exec_copy_to_current( exec );
  267.    }
  268.  
  269.    /* Heuristic: Attempt to isolate attributes received outside
  270.     * begin/end so that they don't bloat the vertices.
  271.     */
  272.    if (!_mesa_inside_begin_end(ctx) &&
  273.        !oldSize && lastcount > 8 && exec->vtx.vertex_size) {
  274.       vbo_exec_copy_to_current( exec );
  275.       reset_attrfv( exec );
  276.    }
  277.  
  278.    /* Fix up sizes:
  279.     */
  280.    exec->vtx.attrsz[attr] = newSize;
  281.    exec->vtx.vertex_size += newSize - oldSize;
  282.    exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) /
  283.                          (exec->vtx.vertex_size * sizeof(GLfloat)));
  284.    exec->vtx.vert_count = 0;
  285.    exec->vtx.buffer_ptr = exec->vtx.buffer_map;
  286.  
  287.    if (unlikely(oldSize)) {
  288.       /* Size changed, recalculate all the attrptr[] values
  289.        */
  290.       GLfloat *tmp = exec->vtx.vertex;
  291.  
  292.       for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
  293.          if (exec->vtx.attrsz[i]) {
  294.             exec->vtx.attrptr[i] = tmp;
  295.             tmp += exec->vtx.attrsz[i];
  296.          }
  297.          else
  298.             exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */
  299.       }
  300.  
  301.       /* Copy from current to repopulate the vertex with correct
  302.        * values.
  303.        */
  304.       vbo_exec_copy_from_current( exec );
  305.    }
  306.    else {
  307.       /* Just have to append the new attribute at the end */
  308.       exec->vtx.attrptr[attr] = exec->vtx.vertex +
  309.          exec->vtx.vertex_size - newSize;
  310.    }
  311.  
  312.    /* Replay stored vertices to translate them
  313.     * to new format here.
  314.     *
  315.     * -- No need to replay - just copy piecewise
  316.     */
  317.    if (unlikely(exec->vtx.copied.nr)) {
  318.       GLfloat *data = exec->vtx.copied.buffer;
  319.       GLfloat *dest = exec->vtx.buffer_ptr;
  320.       GLuint j;
  321.  
  322.       assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map);
  323.  
  324.       for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
  325.          for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) {
  326.             GLuint sz = exec->vtx.attrsz[j];
  327.  
  328.             if (sz) {
  329.                GLint old_offset = old_attrptr[j] - exec->vtx.vertex;
  330.                GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex;
  331.  
  332.                if (j == attr) {
  333.                   if (oldSize) {
  334.                      GLfloat tmp[4];
  335.                      COPY_CLEAN_4V_TYPE_AS_FLOAT(tmp, oldSize,
  336.                                                  data + old_offset,
  337.                                                  exec->vtx.attrtype[j]);
  338.                      COPY_SZ_4V(dest + new_offset, newSize, tmp);
  339.                   } else {
  340.                      GLfloat *current = (GLfloat *)vbo->currval[j].Ptr;
  341.                      COPY_SZ_4V(dest + new_offset, sz, current);
  342.                   }
  343.                }
  344.                else {
  345.                   COPY_SZ_4V(dest + new_offset, sz, data + old_offset);
  346.                }
  347.             }
  348.          }
  349.  
  350.          data += old_vtx_size;
  351.          dest += exec->vtx.vertex_size;
  352.       }
  353.  
  354.       exec->vtx.buffer_ptr = dest;
  355.       exec->vtx.vert_count += exec->vtx.copied.nr;
  356.       exec->vtx.copied.nr = 0;
  357.    }
  358. }
  359.  
  360.  
  361. /**
  362.  * This is when a vertex attribute transitions to a different size.
  363.  * For example, we saw a bunch of glTexCoord2f() calls and now we got a
  364.  * glTexCoord4f() call.  We promote the array from size=2 to size=4.
  365.  */
  366. static void
  367. vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint newSize)
  368. {
  369.    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
  370.  
  371.    if (newSize > exec->vtx.attrsz[attr]) {
  372.       /* New size is larger.  Need to flush existing vertices and get
  373.        * an enlarged vertex format.
  374.        */
  375.       vbo_exec_wrap_upgrade_vertex( exec, attr, newSize );
  376.    }
  377.    else if (newSize < exec->vtx.active_sz[attr]) {
  378.       GLuint i;
  379.       const GLfloat *id =
  380.             vbo_get_default_vals_as_float(exec->vtx.attrtype[attr]);
  381.  
  382.       /* New size is smaller - just need to fill in some
  383.        * zeros.  Don't need to flush or wrap.
  384.        */
  385.       for (i = newSize; i <= exec->vtx.attrsz[attr]; i++)
  386.          exec->vtx.attrptr[attr][i-1] = id[i-1];
  387.    }
  388.  
  389.    exec->vtx.active_sz[attr] = newSize;
  390.  
  391.    /* Does setting NeedFlush belong here?  Necessitates resetting
  392.     * vtxfmt on each flush (otherwise flags won't get reset
  393.     * afterwards).
  394.     */
  395.    if (attr == 0)
  396.       ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
  397. }
  398.  
  399.  
  400. /**
  401.  * This macro is used to implement all the glVertex, glColor, glTexCoord,
  402.  * glVertexAttrib, etc functions.
  403.  */
  404. #define ATTR( A, N, T, V0, V1, V2, V3 )                                 \
  405. do {                                                                    \
  406.    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;             \
  407.                                                                         \
  408.    if (unlikely(!(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT)))       \
  409.       ctx->Driver.BeginVertices( ctx );                                 \
  410.                                                                         \
  411.    if (unlikely(exec->vtx.active_sz[A] != N))                           \
  412.       vbo_exec_fixup_vertex(ctx, A, N);                                 \
  413.                                                                         \
  414.    {                                                                    \
  415.       GLfloat *dest = exec->vtx.attrptr[A];                             \
  416.       if (N>0) dest[0] = V0;                                            \
  417.       if (N>1) dest[1] = V1;                                            \
  418.       if (N>2) dest[2] = V2;                                            \
  419.       if (N>3) dest[3] = V3;                                            \
  420.       exec->vtx.attrtype[A] = T;                                        \
  421.    }                                                                    \
  422.                                                                         \
  423.    if ((A) == 0) {                                                      \
  424.       /* This is a glVertex call */                                     \
  425.       GLuint i;                                                         \
  426.                                                                         \
  427.       for (i = 0; i < exec->vtx.vertex_size; i++)                       \
  428.          exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i];                 \
  429.                                                                         \
  430.       exec->vtx.buffer_ptr += exec->vtx.vertex_size;                    \
  431.                                                                         \
  432.       /* Set FLUSH_STORED_VERTICES to indicate that there's now */      \
  433.       /* something to draw (not just updating a color or texcoord).*/   \
  434.       ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;                   \
  435.                                                                         \
  436.       if (++exec->vtx.vert_count >= exec->vtx.max_vert)                 \
  437.          vbo_exec_vtx_wrap( exec );                                     \
  438.    }                                                                    \
  439. } while (0)
  440.  
  441.  
  442. #define ERROR(err) _mesa_error( ctx, err, __FUNCTION__ )
  443. #define TAG(x) vbo_##x
  444.  
  445. #include "vbo_attrib_tmp.h"
  446.  
  447.  
  448.  
  449. /**
  450.  * Execute a glMaterial call.  Note that if GL_COLOR_MATERIAL is enabled,
  451.  * this may be a (partial) no-op.
  452.  */
  453. static void GLAPIENTRY
  454. vbo_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
  455. {
  456.    GLbitfield updateMats;
  457.    GET_CURRENT_CONTEXT(ctx);
  458.  
  459.    /* This function should be a no-op when it tries to update material
  460.     * attributes which are currently tracking glColor via glColorMaterial.
  461.     * The updateMats var will be a mask of the MAT_BIT_FRONT/BACK_x bits
  462.     * indicating which material attributes can actually be updated below.
  463.     */
  464.    if (ctx->Light.ColorMaterialEnabled) {
  465.       updateMats = ~ctx->Light._ColorMaterialBitmask;
  466.    }
  467.    else {
  468.       /* GL_COLOR_MATERIAL is disabled so don't skip any material updates */
  469.       updateMats = ALL_MATERIAL_BITS;
  470.    }
  471.  
  472.    if (ctx->API == API_OPENGL_COMPAT && face == GL_FRONT) {
  473.       updateMats &= FRONT_MATERIAL_BITS;
  474.    }
  475.    else if (ctx->API == API_OPENGL_COMPAT && face == GL_BACK) {
  476.       updateMats &= BACK_MATERIAL_BITS;
  477.    }
  478.    else if (face != GL_FRONT_AND_BACK) {
  479.       _mesa_error(ctx, GL_INVALID_ENUM, "glMaterial(invalid face)");
  480.       return;
  481.    }
  482.  
  483.    switch (pname) {
  484.    case GL_EMISSION:
  485.       if (updateMats & MAT_BIT_FRONT_EMISSION)
  486.          MAT_ATTR(VBO_ATTRIB_MAT_FRONT_EMISSION, 4, params);
  487.       if (updateMats & MAT_BIT_BACK_EMISSION)
  488.          MAT_ATTR(VBO_ATTRIB_MAT_BACK_EMISSION, 4, params);
  489.       break;
  490.    case GL_AMBIENT:
  491.       if (updateMats & MAT_BIT_FRONT_AMBIENT)
  492.          MAT_ATTR(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, params);
  493.       if (updateMats & MAT_BIT_BACK_AMBIENT)
  494.          MAT_ATTR(VBO_ATTRIB_MAT_BACK_AMBIENT, 4, params);
  495.       break;
  496.    case GL_DIFFUSE:
  497.       if (updateMats & MAT_BIT_FRONT_DIFFUSE)
  498.          MAT_ATTR(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, params);
  499.       if (updateMats & MAT_BIT_BACK_DIFFUSE)
  500.          MAT_ATTR(VBO_ATTRIB_MAT_BACK_DIFFUSE, 4, params);
  501.       break;
  502.    case GL_SPECULAR:
  503.       if (updateMats & MAT_BIT_FRONT_SPECULAR)
  504.          MAT_ATTR(VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, params);
  505.       if (updateMats & MAT_BIT_BACK_SPECULAR)
  506.          MAT_ATTR(VBO_ATTRIB_MAT_BACK_SPECULAR, 4, params);
  507.       break;
  508.    case GL_SHININESS:
  509.       if (*params < 0 || *params > ctx->Const.MaxShininess) {
  510.          _mesa_error(ctx, GL_INVALID_VALUE,
  511.                      "glMaterial(invalid shininess: %f out range [0, %f])",
  512.                      *params, ctx->Const.MaxShininess);
  513.          return;
  514.       }
  515.       if (updateMats & MAT_BIT_FRONT_SHININESS)
  516.          MAT_ATTR(VBO_ATTRIB_MAT_FRONT_SHININESS, 1, params);
  517.       if (updateMats & MAT_BIT_BACK_SHININESS)
  518.          MAT_ATTR(VBO_ATTRIB_MAT_BACK_SHININESS, 1, params);
  519.       break;
  520.    case GL_COLOR_INDEXES:
  521.       if (ctx->API != API_OPENGL_COMPAT) {
  522.          _mesa_error(ctx, GL_INVALID_ENUM, "glMaterialfv(pname)");
  523.          return;
  524.       }
  525.       if (updateMats & MAT_BIT_FRONT_INDEXES)
  526.          MAT_ATTR(VBO_ATTRIB_MAT_FRONT_INDEXES, 3, params);
  527.       if (updateMats & MAT_BIT_BACK_INDEXES)
  528.          MAT_ATTR(VBO_ATTRIB_MAT_BACK_INDEXES, 3, params);
  529.       break;
  530.    case GL_AMBIENT_AND_DIFFUSE:
  531.       if (updateMats & MAT_BIT_FRONT_AMBIENT)
  532.          MAT_ATTR(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, params);
  533.       if (updateMats & MAT_BIT_FRONT_DIFFUSE)
  534.          MAT_ATTR(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, params);
  535.       if (updateMats & MAT_BIT_BACK_AMBIENT)
  536.          MAT_ATTR(VBO_ATTRIB_MAT_BACK_AMBIENT, 4, params);
  537.       if (updateMats & MAT_BIT_BACK_DIFFUSE)
  538.          MAT_ATTR(VBO_ATTRIB_MAT_BACK_DIFFUSE, 4, params);
  539.       break;
  540.    default:
  541.       _mesa_error(ctx, GL_INVALID_ENUM, "glMaterialfv(pname)");
  542.       return;
  543.    }
  544. }
  545.  
  546.  
  547. /**
  548.  * Flush (draw) vertices.
  549.  * \param  unmap - leave VBO unmapped after flushing?
  550.  */
  551. static void
  552. vbo_exec_FlushVertices_internal(struct vbo_exec_context *exec, GLboolean unmap)
  553. {
  554.    if (exec->vtx.vert_count || unmap) {
  555.       vbo_exec_vtx_flush( exec, unmap );
  556.    }
  557.  
  558.    if (exec->vtx.vertex_size) {
  559.       vbo_exec_copy_to_current( exec );
  560.       reset_attrfv( exec );
  561.    }
  562. }
  563.  
  564.  
  565. static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u )
  566. {
  567.    GET_CURRENT_CONTEXT( ctx );
  568.    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
  569.  
  570.    {
  571.       GLint i;
  572.       if (exec->eval.recalculate_maps)
  573.          vbo_exec_eval_update( exec );
  574.  
  575.       for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
  576.          if (exec->eval.map1[i].map)
  577.             if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz)
  578.                vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz );
  579.       }
  580.    }
  581.  
  582.  
  583.    memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
  584.            exec->vtx.vertex_size * sizeof(GLfloat));
  585.  
  586.    vbo_exec_do_EvalCoord1f( exec, u );
  587.  
  588.    memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
  589.            exec->vtx.vertex_size * sizeof(GLfloat));
  590. }
  591.  
  592. static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v )
  593. {
  594.    GET_CURRENT_CONTEXT( ctx );
  595.    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
  596.  
  597.    {
  598.       GLint i;
  599.       if (exec->eval.recalculate_maps)
  600.          vbo_exec_eval_update( exec );
  601.  
  602.       for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
  603.          if (exec->eval.map2[i].map)
  604.             if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz)
  605.                vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz );
  606.       }
  607.  
  608.       if (ctx->Eval.AutoNormal)
  609.          if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3)
  610.             vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3 );
  611.    }
  612.  
  613.    memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
  614.            exec->vtx.vertex_size * sizeof(GLfloat));
  615.  
  616.    vbo_exec_do_EvalCoord2f( exec, u, v );
  617.  
  618.    memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
  619.            exec->vtx.vertex_size * sizeof(GLfloat));
  620. }
  621.  
  622. static void GLAPIENTRY vbo_exec_EvalCoord1fv( const GLfloat *u )
  623. {
  624.    vbo_exec_EvalCoord1f( u[0] );
  625. }
  626.  
  627. static void GLAPIENTRY vbo_exec_EvalCoord2fv( const GLfloat *u )
  628. {
  629.    vbo_exec_EvalCoord2f( u[0], u[1] );
  630. }
  631.  
  632. static void GLAPIENTRY vbo_exec_EvalPoint1( GLint i )
  633. {
  634.    GET_CURRENT_CONTEXT( ctx );
  635.    GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) /
  636.                  (GLfloat) ctx->Eval.MapGrid1un);
  637.    GLfloat u = i * du + ctx->Eval.MapGrid1u1;
  638.  
  639.    vbo_exec_EvalCoord1f( u );
  640. }
  641.  
  642.  
  643. static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j )
  644. {
  645.    GET_CURRENT_CONTEXT( ctx );
  646.    GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) /
  647.                  (GLfloat) ctx->Eval.MapGrid2un);
  648.    GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) /
  649.                  (GLfloat) ctx->Eval.MapGrid2vn);
  650.    GLfloat u = i * du + ctx->Eval.MapGrid2u1;
  651.    GLfloat v = j * dv + ctx->Eval.MapGrid2v1;
  652.  
  653.    vbo_exec_EvalCoord2f( u, v );
  654. }
  655.  
  656.  
  657. /**
  658.  * Called via glBegin.
  659.  */
  660. static void GLAPIENTRY vbo_exec_Begin( GLenum mode )
  661. {
  662.    GET_CURRENT_CONTEXT( ctx );
  663.    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
  664.    int i;
  665.  
  666.    if (_mesa_inside_begin_end(ctx)) {
  667.       _mesa_error(ctx, GL_INVALID_OPERATION, "glBegin");
  668.       return;
  669.    }
  670.  
  671.    if (!_mesa_valid_prim_mode(ctx, mode, "glBegin")) {
  672.       return;
  673.    }
  674.  
  675.    vbo_draw_method(vbo_context(ctx), DRAW_BEGIN_END);
  676.  
  677.    if (ctx->NewState) {
  678.       _mesa_update_state( ctx );
  679.  
  680.       CALL_Begin(ctx->Exec, (mode));
  681.       return;
  682.    }
  683.  
  684.    if (!_mesa_valid_to_render(ctx, "glBegin")) {
  685.       return;
  686.    }
  687.  
  688.    /* Heuristic: attempt to isolate attributes occuring outside
  689.     * begin/end pairs.
  690.     */
  691.    if (exec->vtx.vertex_size && !exec->vtx.attrsz[0])
  692.       vbo_exec_FlushVertices_internal(exec, GL_FALSE);
  693.  
  694.    i = exec->vtx.prim_count++;
  695.    exec->vtx.prim[i].mode = mode;
  696.    exec->vtx.prim[i].begin = 1;
  697.    exec->vtx.prim[i].end = 0;
  698.    exec->vtx.prim[i].indexed = 0;
  699.    exec->vtx.prim[i].weak = 0;
  700.    exec->vtx.prim[i].pad = 0;
  701.    exec->vtx.prim[i].start = exec->vtx.vert_count;
  702.    exec->vtx.prim[i].count = 0;
  703.    exec->vtx.prim[i].num_instances = 1;
  704.    exec->vtx.prim[i].base_instance = 0;
  705.  
  706.    ctx->Driver.CurrentExecPrimitive = mode;
  707.  
  708.    ctx->Exec = ctx->BeginEnd;
  709.    /* We may have been called from a display list, in which case we should
  710.     * leave dlist.c's dispatch table in place.
  711.     */
  712.    if (ctx->CurrentDispatch == ctx->OutsideBeginEnd) {
  713.       ctx->CurrentDispatch = ctx->BeginEnd;
  714.       _glapi_set_dispatch(ctx->CurrentDispatch);
  715.    } else {
  716.       assert(ctx->CurrentDispatch == ctx->Save);
  717.    }
  718. }
  719.  
  720.  
  721. /**
  722.  * Try to merge / concatenate the two most recent VBO primitives.
  723.  */
  724. static void
  725. try_vbo_merge(struct vbo_exec_context *exec)
  726. {
  727.    struct _mesa_prim *cur =  &exec->vtx.prim[exec->vtx.prim_count - 1];
  728.  
  729.    assert(exec->vtx.prim_count >= 1);
  730.  
  731.    vbo_try_prim_conversion(cur);
  732.  
  733.    if (exec->vtx.prim_count >= 2) {
  734.       struct _mesa_prim *prev = &exec->vtx.prim[exec->vtx.prim_count - 2];
  735.       assert(prev == cur - 1);
  736.  
  737.       if (vbo_can_merge_prims(prev, cur)) {
  738.          assert(cur->begin);
  739.          assert(cur->end);
  740.          assert(prev->begin);
  741.          assert(prev->end);
  742.          vbo_merge_prims(prev, cur);
  743.          exec->vtx.prim_count--;  /* drop the last primitive */
  744.       }
  745.    }
  746. }
  747.  
  748.  
  749. /**
  750.  * Called via glEnd.
  751.  */
  752. static void GLAPIENTRY vbo_exec_End( void )
  753. {
  754.    GET_CURRENT_CONTEXT( ctx );
  755.    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
  756.  
  757.    if (!_mesa_inside_begin_end(ctx)) {
  758.       _mesa_error(ctx, GL_INVALID_OPERATION, "glEnd");
  759.       return;
  760.    }
  761.  
  762.    ctx->Exec = ctx->OutsideBeginEnd;
  763.    if (ctx->CurrentDispatch == ctx->BeginEnd) {
  764.       ctx->CurrentDispatch = ctx->OutsideBeginEnd;
  765.       _glapi_set_dispatch(ctx->CurrentDispatch);
  766.    }
  767.  
  768.    if (exec->vtx.prim_count > 0) {
  769.       /* close off current primitive */
  770.       int idx = exec->vtx.vert_count;
  771.       int i = exec->vtx.prim_count - 1;
  772.  
  773.       exec->vtx.prim[i].end = 1;
  774.       exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start;
  775.  
  776.       try_vbo_merge(exec);
  777.    }
  778.  
  779.    ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
  780.  
  781.    if (exec->vtx.prim_count == VBO_MAX_PRIM)
  782.       vbo_exec_vtx_flush( exec, GL_FALSE );
  783.  
  784.    if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
  785.       _mesa_flush(ctx);
  786.    }
  787. }
  788.  
  789.  
  790. /**
  791.  * Called via glPrimitiveRestartNV()
  792.  */
  793. static void GLAPIENTRY
  794. vbo_exec_PrimitiveRestartNV(void)
  795. {
  796.    GLenum curPrim;
  797.    GET_CURRENT_CONTEXT( ctx );
  798.  
  799.    curPrim = ctx->Driver.CurrentExecPrimitive;
  800.  
  801.    if (curPrim == PRIM_OUTSIDE_BEGIN_END) {
  802.       _mesa_error( ctx, GL_INVALID_OPERATION, "glPrimitiveRestartNV" );
  803.    }
  804.    else {
  805.       vbo_exec_End();
  806.       vbo_exec_Begin(curPrim);
  807.    }
  808. }
  809.  
  810.  
  811.  
  812. static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
  813. {
  814.    struct gl_context *ctx = exec->ctx;
  815.    GLvertexformat *vfmt = &exec->vtxfmt;
  816.  
  817.    vfmt->ArrayElement = _ae_ArrayElement;
  818.  
  819.    vfmt->Begin = vbo_exec_Begin;
  820.    vfmt->End = vbo_exec_End;
  821.    vfmt->PrimitiveRestartNV = vbo_exec_PrimitiveRestartNV;
  822.  
  823.    vfmt->CallList = _mesa_CallList;
  824.    vfmt->CallLists = _mesa_CallLists;
  825.  
  826.    vfmt->EvalCoord1f = vbo_exec_EvalCoord1f;
  827.    vfmt->EvalCoord1fv = vbo_exec_EvalCoord1fv;
  828.    vfmt->EvalCoord2f = vbo_exec_EvalCoord2f;
  829.    vfmt->EvalCoord2fv = vbo_exec_EvalCoord2fv;
  830.    vfmt->EvalPoint1 = vbo_exec_EvalPoint1;
  831.    vfmt->EvalPoint2 = vbo_exec_EvalPoint2;
  832.  
  833.    /* from attrib_tmp.h:
  834.     */
  835.    vfmt->Color3f = vbo_Color3f;
  836.    vfmt->Color3fv = vbo_Color3fv;
  837.    vfmt->Color4f = vbo_Color4f;
  838.    vfmt->Color4fv = vbo_Color4fv;
  839.    vfmt->FogCoordfEXT = vbo_FogCoordfEXT;
  840.    vfmt->FogCoordfvEXT = vbo_FogCoordfvEXT;
  841.    vfmt->MultiTexCoord1fARB = vbo_MultiTexCoord1f;
  842.    vfmt->MultiTexCoord1fvARB = vbo_MultiTexCoord1fv;
  843.    vfmt->MultiTexCoord2fARB = vbo_MultiTexCoord2f;
  844.    vfmt->MultiTexCoord2fvARB = vbo_MultiTexCoord2fv;
  845.    vfmt->MultiTexCoord3fARB = vbo_MultiTexCoord3f;
  846.    vfmt->MultiTexCoord3fvARB = vbo_MultiTexCoord3fv;
  847.    vfmt->MultiTexCoord4fARB = vbo_MultiTexCoord4f;
  848.    vfmt->MultiTexCoord4fvARB = vbo_MultiTexCoord4fv;
  849.    vfmt->Normal3f = vbo_Normal3f;
  850.    vfmt->Normal3fv = vbo_Normal3fv;
  851.    vfmt->SecondaryColor3fEXT = vbo_SecondaryColor3fEXT;
  852.    vfmt->SecondaryColor3fvEXT = vbo_SecondaryColor3fvEXT;
  853.    vfmt->TexCoord1f = vbo_TexCoord1f;
  854.    vfmt->TexCoord1fv = vbo_TexCoord1fv;
  855.    vfmt->TexCoord2f = vbo_TexCoord2f;
  856.    vfmt->TexCoord2fv = vbo_TexCoord2fv;
  857.    vfmt->TexCoord3f = vbo_TexCoord3f;
  858.    vfmt->TexCoord3fv = vbo_TexCoord3fv;
  859.    vfmt->TexCoord4f = vbo_TexCoord4f;
  860.    vfmt->TexCoord4fv = vbo_TexCoord4fv;
  861.    vfmt->Vertex2f = vbo_Vertex2f;
  862.    vfmt->Vertex2fv = vbo_Vertex2fv;
  863.    vfmt->Vertex3f = vbo_Vertex3f;
  864.    vfmt->Vertex3fv = vbo_Vertex3fv;
  865.    vfmt->Vertex4f = vbo_Vertex4f;
  866.    vfmt->Vertex4fv = vbo_Vertex4fv;
  867.    
  868.    if (ctx->API == API_OPENGLES2) {
  869.       vfmt->VertexAttrib1fARB = _es_VertexAttrib1f;
  870.       vfmt->VertexAttrib1fvARB = _es_VertexAttrib1fv;
  871.       vfmt->VertexAttrib2fARB = _es_VertexAttrib2f;
  872.       vfmt->VertexAttrib2fvARB = _es_VertexAttrib2fv;
  873.       vfmt->VertexAttrib3fARB = _es_VertexAttrib3f;
  874.       vfmt->VertexAttrib3fvARB = _es_VertexAttrib3fv;
  875.       vfmt->VertexAttrib4fARB = _es_VertexAttrib4f;
  876.       vfmt->VertexAttrib4fvARB = _es_VertexAttrib4fv;
  877.    } else {
  878.       vfmt->VertexAttrib1fARB = vbo_VertexAttrib1fARB;
  879.       vfmt->VertexAttrib1fvARB = vbo_VertexAttrib1fvARB;
  880.       vfmt->VertexAttrib2fARB = vbo_VertexAttrib2fARB;
  881.       vfmt->VertexAttrib2fvARB = vbo_VertexAttrib2fvARB;
  882.       vfmt->VertexAttrib3fARB = vbo_VertexAttrib3fARB;
  883.       vfmt->VertexAttrib3fvARB = vbo_VertexAttrib3fvARB;
  884.       vfmt->VertexAttrib4fARB = vbo_VertexAttrib4fARB;
  885.       vfmt->VertexAttrib4fvARB = vbo_VertexAttrib4fvARB;
  886.    }
  887.  
  888.    /* Note that VertexAttrib4fNV is used from dlist.c and api_arrayelt.c so
  889.     * they can have a single entrypoint for updating any of the legacy
  890.     * attribs.
  891.     */
  892.    vfmt->VertexAttrib1fNV = vbo_VertexAttrib1fNV;
  893.    vfmt->VertexAttrib1fvNV = vbo_VertexAttrib1fvNV;
  894.    vfmt->VertexAttrib2fNV = vbo_VertexAttrib2fNV;
  895.    vfmt->VertexAttrib2fvNV = vbo_VertexAttrib2fvNV;
  896.    vfmt->VertexAttrib3fNV = vbo_VertexAttrib3fNV;
  897.    vfmt->VertexAttrib3fvNV = vbo_VertexAttrib3fvNV;
  898.    vfmt->VertexAttrib4fNV = vbo_VertexAttrib4fNV;
  899.    vfmt->VertexAttrib4fvNV = vbo_VertexAttrib4fvNV;
  900.  
  901.    /* integer-valued */
  902.    vfmt->VertexAttribI1i = vbo_VertexAttribI1i;
  903.    vfmt->VertexAttribI2i = vbo_VertexAttribI2i;
  904.    vfmt->VertexAttribI3i = vbo_VertexAttribI3i;
  905.    vfmt->VertexAttribI4i = vbo_VertexAttribI4i;
  906.    vfmt->VertexAttribI2iv = vbo_VertexAttribI2iv;
  907.    vfmt->VertexAttribI3iv = vbo_VertexAttribI3iv;
  908.    vfmt->VertexAttribI4iv = vbo_VertexAttribI4iv;
  909.  
  910.    /* unsigned integer-valued */
  911.    vfmt->VertexAttribI1ui = vbo_VertexAttribI1ui;
  912.    vfmt->VertexAttribI2ui = vbo_VertexAttribI2ui;
  913.    vfmt->VertexAttribI3ui = vbo_VertexAttribI3ui;
  914.    vfmt->VertexAttribI4ui = vbo_VertexAttribI4ui;
  915.    vfmt->VertexAttribI2uiv = vbo_VertexAttribI2uiv;
  916.    vfmt->VertexAttribI3uiv = vbo_VertexAttribI3uiv;
  917.    vfmt->VertexAttribI4uiv = vbo_VertexAttribI4uiv;
  918.  
  919.    vfmt->Materialfv = vbo_Materialfv;
  920.  
  921.    vfmt->EdgeFlag = vbo_EdgeFlag;
  922.    vfmt->Indexf = vbo_Indexf;
  923.    vfmt->Indexfv = vbo_Indexfv;
  924.  
  925.    /* ARB_vertex_type_2_10_10_10_rev */
  926.    vfmt->VertexP2ui = vbo_VertexP2ui;
  927.    vfmt->VertexP2uiv = vbo_VertexP2uiv;
  928.    vfmt->VertexP3ui = vbo_VertexP3ui;
  929.    vfmt->VertexP3uiv = vbo_VertexP3uiv;
  930.    vfmt->VertexP4ui = vbo_VertexP4ui;
  931.    vfmt->VertexP4uiv = vbo_VertexP4uiv;
  932.  
  933.    vfmt->TexCoordP1ui = vbo_TexCoordP1ui;
  934.    vfmt->TexCoordP1uiv = vbo_TexCoordP1uiv;
  935.    vfmt->TexCoordP2ui = vbo_TexCoordP2ui;
  936.    vfmt->TexCoordP2uiv = vbo_TexCoordP2uiv;
  937.    vfmt->TexCoordP3ui = vbo_TexCoordP3ui;
  938.    vfmt->TexCoordP3uiv = vbo_TexCoordP3uiv;
  939.    vfmt->TexCoordP4ui = vbo_TexCoordP4ui;
  940.    vfmt->TexCoordP4uiv = vbo_TexCoordP4uiv;
  941.  
  942.    vfmt->MultiTexCoordP1ui = vbo_MultiTexCoordP1ui;
  943.    vfmt->MultiTexCoordP1uiv = vbo_MultiTexCoordP1uiv;
  944.    vfmt->MultiTexCoordP2ui = vbo_MultiTexCoordP2ui;
  945.    vfmt->MultiTexCoordP2uiv = vbo_MultiTexCoordP2uiv;
  946.    vfmt->MultiTexCoordP3ui = vbo_MultiTexCoordP3ui;
  947.    vfmt->MultiTexCoordP3uiv = vbo_MultiTexCoordP3uiv;
  948.    vfmt->MultiTexCoordP4ui = vbo_MultiTexCoordP4ui;
  949.    vfmt->MultiTexCoordP4uiv = vbo_MultiTexCoordP4uiv;
  950.    
  951.    vfmt->NormalP3ui = vbo_NormalP3ui;
  952.    vfmt->NormalP3uiv = vbo_NormalP3uiv;
  953.  
  954.    vfmt->ColorP3ui = vbo_ColorP3ui;
  955.    vfmt->ColorP3uiv = vbo_ColorP3uiv;
  956.    vfmt->ColorP4ui = vbo_ColorP4ui;
  957.    vfmt->ColorP4uiv = vbo_ColorP4uiv;
  958.  
  959.    vfmt->SecondaryColorP3ui = vbo_SecondaryColorP3ui;
  960.    vfmt->SecondaryColorP3uiv = vbo_SecondaryColorP3uiv;
  961.  
  962.    vfmt->VertexAttribP1ui = vbo_VertexAttribP1ui;
  963.    vfmt->VertexAttribP1uiv = vbo_VertexAttribP1uiv;
  964.    vfmt->VertexAttribP2ui = vbo_VertexAttribP2ui;
  965.    vfmt->VertexAttribP2uiv = vbo_VertexAttribP2uiv;
  966.    vfmt->VertexAttribP3ui = vbo_VertexAttribP3ui;
  967.    vfmt->VertexAttribP3uiv = vbo_VertexAttribP3uiv;
  968.    vfmt->VertexAttribP4ui = vbo_VertexAttribP4ui;
  969.    vfmt->VertexAttribP4uiv = vbo_VertexAttribP4uiv;
  970. }
  971.  
  972.  
  973. /**
  974.  * Tell the VBO module to use a real OpenGL vertex buffer object to
  975.  * store accumulated immediate-mode vertex data.
  976.  * This replaces the malloced buffer which was created in
  977.  * vb_exec_vtx_init() below.
  978.  */
  979. void vbo_use_buffer_objects(struct gl_context *ctx)
  980. {
  981.    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
  982.    /* Any buffer name but 0 can be used here since this bufferobj won't
  983.     * go into the bufferobj hashtable.
  984.     */
  985.    GLuint bufName = IMM_BUFFER_NAME;
  986.    GLenum target = GL_ARRAY_BUFFER_ARB;
  987.    GLenum usage = GL_STREAM_DRAW_ARB;
  988.    GLsizei size = VBO_VERT_BUFFER_SIZE;
  989.  
  990.    /* Make sure this func is only used once */
  991.    assert(exec->vtx.bufferobj == ctx->Shared->NullBufferObj);
  992.    if (exec->vtx.buffer_map) {
  993.       _mesa_align_free(exec->vtx.buffer_map);
  994.       exec->vtx.buffer_map = NULL;
  995.       exec->vtx.buffer_ptr = NULL;
  996.    }
  997.  
  998.    /* Allocate a real buffer object now */
  999.    _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
  1000.    exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName, target);
  1001.    if (!ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj)) {
  1002.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "VBO allocation");
  1003.    }
  1004. }
  1005.  
  1006.  
  1007. /**
  1008.  * If this function is called, all VBO buffers will be unmapped when
  1009.  * we flush.
  1010.  * Otherwise, if a simple command like glColor3f() is called and we flush,
  1011.  * the current VBO may be left mapped.
  1012.  */
  1013. void
  1014. vbo_always_unmap_buffers(struct gl_context *ctx)
  1015. {
  1016.    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
  1017.    exec->begin_vertices_flags |= FLUSH_STORED_VERTICES;
  1018. }
  1019.  
  1020.  
  1021. void vbo_exec_vtx_init( struct vbo_exec_context *exec )
  1022. {
  1023.    struct gl_context *ctx = exec->ctx;
  1024.    struct vbo_context *vbo = vbo_context(ctx);
  1025.    GLuint i;
  1026.  
  1027.    /* Allocate a buffer object.  Will just reuse this object
  1028.     * continuously, unless vbo_use_buffer_objects() is called to enable
  1029.     * use of real VBOs.
  1030.     */
  1031.    _mesa_reference_buffer_object(ctx,
  1032.                                  &exec->vtx.bufferobj,
  1033.                                  ctx->Shared->NullBufferObj);
  1034.  
  1035.    ASSERT(!exec->vtx.buffer_map);
  1036.    exec->vtx.buffer_map = _mesa_align_malloc(VBO_VERT_BUFFER_SIZE, 64);
  1037.    exec->vtx.buffer_ptr = exec->vtx.buffer_map;
  1038.  
  1039.    vbo_exec_vtxfmt_init( exec );
  1040.    _mesa_noop_vtxfmt_init(&exec->vtxfmt_noop);
  1041.  
  1042.    for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
  1043.       ASSERT(i < Elements(exec->vtx.attrsz));
  1044.       exec->vtx.attrsz[i] = 0;
  1045.       ASSERT(i < Elements(exec->vtx.attrtype));
  1046.       exec->vtx.attrtype[i] = GL_FLOAT;
  1047.       ASSERT(i < Elements(exec->vtx.active_sz));
  1048.       exec->vtx.active_sz[i] = 0;
  1049.    }
  1050.    for (i = 0 ; i < VERT_ATTRIB_MAX; i++) {
  1051.       ASSERT(i < Elements(exec->vtx.inputs));
  1052.       ASSERT(i < Elements(exec->vtx.arrays));
  1053.       exec->vtx.inputs[i] = &exec->vtx.arrays[i];
  1054.    }
  1055.    
  1056.    {
  1057.       struct gl_client_array *arrays = exec->vtx.arrays;
  1058.       unsigned i;
  1059.  
  1060.       memcpy(arrays, &vbo->currval[VBO_ATTRIB_POS],
  1061.              VERT_ATTRIB_FF_MAX * sizeof(arrays[0]));
  1062.       for (i = 0; i < VERT_ATTRIB_FF_MAX; ++i) {
  1063.          struct gl_client_array *array;
  1064.          array = &arrays[VERT_ATTRIB_FF(i)];
  1065.          array->BufferObj = NULL;
  1066.          _mesa_reference_buffer_object(ctx, &arrays->BufferObj,
  1067.                                  vbo->currval[VBO_ATTRIB_POS+i].BufferObj);
  1068.       }
  1069.  
  1070.       memcpy(arrays + VERT_ATTRIB_GENERIC(0),
  1071.              &vbo->currval[VBO_ATTRIB_GENERIC0],
  1072.              VERT_ATTRIB_GENERIC_MAX * sizeof(arrays[0]));
  1073.  
  1074.       for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; ++i) {
  1075.          struct gl_client_array *array;
  1076.          array = &arrays[VERT_ATTRIB_GENERIC(i)];
  1077.          array->BufferObj = NULL;
  1078.          _mesa_reference_buffer_object(ctx, &array->BufferObj,
  1079.                            vbo->currval[VBO_ATTRIB_GENERIC0+i].BufferObj);
  1080.       }
  1081.    }
  1082.  
  1083.    exec->vtx.vertex_size = 0;
  1084.  
  1085.    exec->begin_vertices_flags = FLUSH_UPDATE_CURRENT;
  1086. }
  1087.  
  1088.  
  1089. void vbo_exec_vtx_destroy( struct vbo_exec_context *exec )
  1090. {
  1091.    /* using a real VBO for vertex data */
  1092.    struct gl_context *ctx = exec->ctx;
  1093.    unsigned i;
  1094.  
  1095.    /* True VBOs should already be unmapped
  1096.     */
  1097.    if (exec->vtx.buffer_map) {
  1098.       ASSERT(exec->vtx.bufferobj->Name == 0 ||
  1099.              exec->vtx.bufferobj->Name == IMM_BUFFER_NAME);
  1100.       if (exec->vtx.bufferobj->Name == 0) {
  1101.          _mesa_align_free(exec->vtx.buffer_map);
  1102.          exec->vtx.buffer_map = NULL;
  1103.          exec->vtx.buffer_ptr = NULL;
  1104.       }
  1105.    }
  1106.  
  1107.    /* Drop any outstanding reference to the vertex buffer
  1108.     */
  1109.    for (i = 0; i < Elements(exec->vtx.arrays); i++) {
  1110.       _mesa_reference_buffer_object(ctx,
  1111.                                     &exec->vtx.arrays[i].BufferObj,
  1112.                                     NULL);
  1113.    }
  1114.  
  1115.    /* Free the vertex buffer.  Unmap first if needed.
  1116.     */
  1117.    if (_mesa_bufferobj_mapped(exec->vtx.bufferobj)) {
  1118.       ctx->Driver.UnmapBuffer(ctx, exec->vtx.bufferobj);
  1119.    }
  1120.    _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
  1121. }
  1122.  
  1123.  
  1124. /**
  1125.  * Called upon first glVertex, glColor, glTexCoord, etc.
  1126.  */
  1127. void vbo_exec_BeginVertices( struct gl_context *ctx )
  1128. {
  1129.    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
  1130.  
  1131.    vbo_exec_vtx_map( exec );
  1132.  
  1133.    assert((ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0);
  1134.    assert(exec->begin_vertices_flags);
  1135.  
  1136.    ctx->Driver.NeedFlush |= exec->begin_vertices_flags;
  1137. }
  1138.  
  1139.  
  1140. /**
  1141.  * Called via ctx->Driver.FlushVertices()
  1142.  * \param flags  bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT
  1143.  */
  1144. void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags )
  1145. {
  1146.    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
  1147.  
  1148. #ifdef DEBUG
  1149.    /* debug check: make sure we don't get called recursively */
  1150.    exec->flush_call_depth++;
  1151.    assert(exec->flush_call_depth == 1);
  1152. #endif
  1153.  
  1154.    if (_mesa_inside_begin_end(ctx)) {
  1155.       /* We've had glBegin but not glEnd! */
  1156. #ifdef DEBUG
  1157.       exec->flush_call_depth--;
  1158.       assert(exec->flush_call_depth == 0);
  1159. #endif
  1160.       return;
  1161.    }
  1162.  
  1163.    /* Flush (draw), and make sure VBO is left unmapped when done */
  1164.    vbo_exec_FlushVertices_internal(exec, GL_TRUE);
  1165.  
  1166.    /* Need to do this to ensure BeginVertices gets called again:
  1167.     */
  1168.    ctx->Driver.NeedFlush &= ~(FLUSH_UPDATE_CURRENT | flags);
  1169.  
  1170. #ifdef DEBUG
  1171.    exec->flush_call_depth--;
  1172.    assert(exec->flush_call_depth == 0);
  1173. #endif
  1174. }
  1175.  
  1176.  
  1177. static void reset_attrfv( struct vbo_exec_context *exec )
  1178. {  
  1179.    GLuint i;
  1180.  
  1181.    for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
  1182.       exec->vtx.attrsz[i] = 0;
  1183.       exec->vtx.attrtype[i] = GL_FLOAT;
  1184.       exec->vtx.active_sz[i] = 0;
  1185.    }
  1186.  
  1187.    exec->vtx.vertex_size = 0;
  1188. }
  1189.      
  1190.  
  1191. void GLAPIENTRY
  1192. _es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
  1193. {
  1194.    vbo_Color4f(r, g, b, a);
  1195. }
  1196.  
  1197.  
  1198. void GLAPIENTRY
  1199. _es_Normal3f(GLfloat x, GLfloat y, GLfloat z)
  1200. {
  1201.    vbo_Normal3f(x, y, z);
  1202. }
  1203.  
  1204.  
  1205. void GLAPIENTRY
  1206. _es_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
  1207. {
  1208.    vbo_MultiTexCoord4f(target, s, t, r, q);
  1209. }
  1210.  
  1211.  
  1212. void GLAPIENTRY
  1213. _es_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
  1214. {
  1215.    vbo_Materialfv(face, pname, params);
  1216. }
  1217.  
  1218.  
  1219. void GLAPIENTRY
  1220. _es_Materialf(GLenum face, GLenum pname, GLfloat param)
  1221. {
  1222.    GLfloat p[4];
  1223.    p[0] = param;
  1224.    p[1] = p[2] = p[3] = 0.0F;
  1225.    vbo_Materialfv(face, pname, p);
  1226. }
  1227.  
  1228.  
  1229. /**
  1230.  * A special version of glVertexAttrib4f that does not treat index 0 as
  1231.  * VBO_ATTRIB_POS.
  1232.  */
  1233. static void
  1234. VertexAttrib4f_nopos(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
  1235. {
  1236.    GET_CURRENT_CONTEXT(ctx);
  1237.    if (index < MAX_VERTEX_GENERIC_ATTRIBS)
  1238.       ATTR(VBO_ATTRIB_GENERIC0 + index, 4, GL_FLOAT, x, y, z, w);
  1239.    else
  1240.       ERROR(GL_INVALID_VALUE);
  1241. }
  1242.  
  1243. void GLAPIENTRY
  1244. _es_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
  1245. {
  1246.    VertexAttrib4f_nopos(index, x, y, z, w);
  1247. }
  1248.  
  1249.  
  1250. void GLAPIENTRY
  1251. _es_VertexAttrib1f(GLuint indx, GLfloat x)
  1252. {
  1253.    VertexAttrib4f_nopos(indx, x, 0.0f, 0.0f, 1.0f);
  1254. }
  1255.  
  1256.  
  1257. void GLAPIENTRY
  1258. _es_VertexAttrib1fv(GLuint indx, const GLfloat* values)
  1259. {
  1260.    VertexAttrib4f_nopos(indx, values[0], 0.0f, 0.0f, 1.0f);
  1261. }
  1262.  
  1263.  
  1264. void GLAPIENTRY
  1265. _es_VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
  1266. {
  1267.    VertexAttrib4f_nopos(indx, x, y, 0.0f, 1.0f);
  1268. }
  1269.  
  1270.  
  1271. void GLAPIENTRY
  1272. _es_VertexAttrib2fv(GLuint indx, const GLfloat* values)
  1273. {
  1274.    VertexAttrib4f_nopos(indx, values[0], values[1], 0.0f, 1.0f);
  1275. }
  1276.  
  1277.  
  1278. void GLAPIENTRY
  1279. _es_VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
  1280. {
  1281.    VertexAttrib4f_nopos(indx, x, y, z, 1.0f);
  1282. }
  1283.  
  1284.  
  1285. void GLAPIENTRY
  1286. _es_VertexAttrib3fv(GLuint indx, const GLfloat* values)
  1287. {
  1288.    VertexAttrib4f_nopos(indx, values[0], values[1], values[2], 1.0f);
  1289. }
  1290.  
  1291.  
  1292. void GLAPIENTRY
  1293. _es_VertexAttrib4fv(GLuint indx, const GLfloat* values)
  1294. {
  1295.    VertexAttrib4f_nopos(indx, values[0], values[1], values[2], values[3]);
  1296. }
  1297.