Subversion Repositories Kolibri OS

Rev

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

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
  4.  * Copyright 2009 VMware, Inc.
  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
  9.  * "Software"), to deal in the Software without restriction, including
  10.  * without limitation the rights to use, copy, modify, merge, publish,
  11.  * distribute, sub license, and/or sell copies of the Software, and to
  12.  * permit persons to whom the Software is furnished to do so, subject to
  13.  * the following conditions:
  14.  *
  15.  * The above copyright notice and this permission notice (including the
  16.  * next paragraph) shall be included in all copies or substantial portions
  17.  * of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  21.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  22.  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  23.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  24.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  25.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  26.  *
  27.  **************************************************************************/
  28.  
  29. #include "main/glheader.h"
  30. #include "main/context.h"
  31. #include "main/state.h"
  32. #include "main/api_validate.h"
  33. #include "main/dispatch.h"
  34. #include "main/varray.h"
  35. #include "main/bufferobj.h"
  36. #include "main/enums.h"
  37. #include "main/macros.h"
  38. #include "main/transformfeedback.h"
  39.  
  40. #include "vbo_context.h"
  41.  
  42.  
  43. /**
  44.  * All vertex buffers should be in an unmapped state when we're about
  45.  * to draw.  This debug function checks that.
  46.  */
  47. static void
  48. check_buffers_are_unmapped(const struct gl_client_array **inputs)
  49. {
  50. #ifdef DEBUG
  51.    GLuint i;
  52.  
  53.    for (i = 0; i < VERT_ATTRIB_MAX; i++) {
  54.       if (inputs[i]) {
  55.          struct gl_buffer_object *obj = inputs[i]->BufferObj;
  56.          assert(!_mesa_bufferobj_mapped(obj));
  57.          (void) obj;
  58.       }
  59.    }
  60. #endif
  61. }
  62.  
  63.  
  64. /**
  65.  * A debug function that may be called from other parts of Mesa as
  66.  * needed during debugging.
  67.  */
  68. void
  69. vbo_check_buffers_are_unmapped(struct gl_context *ctx)
  70. {
  71.    struct vbo_context *vbo = vbo_context(ctx);
  72.    struct vbo_exec_context *exec = &vbo->exec;
  73.    /* check the current vertex arrays */
  74.    check_buffers_are_unmapped(exec->array.inputs);
  75.    /* check the current glBegin/glVertex/glEnd-style VBO */
  76.    assert(!_mesa_bufferobj_mapped(exec->vtx.bufferobj));
  77. }
  78.  
  79.  
  80.  
  81. /**
  82.  * Compute min and max elements by scanning the index buffer for
  83.  * glDraw[Range]Elements() calls.
  84.  * If primitive restart is enabled, we need to ignore restart
  85.  * indexes when computing min/max.
  86.  */
  87. static void
  88. vbo_get_minmax_index(struct gl_context *ctx,
  89.                      const struct _mesa_prim *prim,
  90.                      const struct _mesa_index_buffer *ib,
  91.                      GLuint *min_index, GLuint *max_index,
  92.                      const GLuint count)
  93. {
  94.    const GLboolean restart = ctx->Array._PrimitiveRestart;
  95.    const GLuint restartIndex = _mesa_primitive_restart_index(ctx, ib->type);
  96.    const int index_size = vbo_sizeof_ib_type(ib->type);
  97.    const char *indices;
  98.    GLuint i;
  99.  
  100.    indices = (char *) ib->ptr + prim->start * index_size;
  101.    if (_mesa_is_bufferobj(ib->obj)) {
  102.       GLsizeiptr size = MIN2(count * index_size, ib->obj->Size);
  103.       indices = ctx->Driver.MapBufferRange(ctx, (GLintptr) indices, size,
  104.                                            GL_MAP_READ_BIT, ib->obj);
  105.    }
  106.  
  107.    switch (ib->type) {
  108.    case GL_UNSIGNED_INT: {
  109.       const GLuint *ui_indices = (const GLuint *)indices;
  110.       GLuint max_ui = 0;
  111.       GLuint min_ui = ~0U;
  112.       if (restart) {
  113.          for (i = 0; i < count; i++) {
  114.             if (ui_indices[i] != restartIndex) {
  115.                if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
  116.                if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
  117.             }
  118.          }
  119.       }
  120.       else {
  121.          for (i = 0; i < count; i++) {
  122.             if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
  123.             if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
  124.          }
  125.       }
  126.       *min_index = min_ui;
  127.       *max_index = max_ui;
  128.       break;
  129.    }
  130.    case GL_UNSIGNED_SHORT: {
  131.       const GLushort *us_indices = (const GLushort *)indices;
  132.       GLuint max_us = 0;
  133.       GLuint min_us = ~0U;
  134.       if (restart) {
  135.          for (i = 0; i < count; i++) {
  136.             if (us_indices[i] != restartIndex) {
  137.                if (us_indices[i] > max_us) max_us = us_indices[i];
  138.                if (us_indices[i] < min_us) min_us = us_indices[i];
  139.             }
  140.          }
  141.       }
  142.       else {
  143.          for (i = 0; i < count; i++) {
  144.             if (us_indices[i] > max_us) max_us = us_indices[i];
  145.             if (us_indices[i] < min_us) min_us = us_indices[i];
  146.          }
  147.       }
  148.       *min_index = min_us;
  149.       *max_index = max_us;
  150.       break;
  151.    }
  152.    case GL_UNSIGNED_BYTE: {
  153.       const GLubyte *ub_indices = (const GLubyte *)indices;
  154.       GLuint max_ub = 0;
  155.       GLuint min_ub = ~0U;
  156.       if (restart) {
  157.          for (i = 0; i < count; i++) {
  158.             if (ub_indices[i] != restartIndex) {
  159.                if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
  160.                if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
  161.             }
  162.          }
  163.       }
  164.       else {
  165.          for (i = 0; i < count; i++) {
  166.             if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
  167.             if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
  168.          }
  169.       }
  170.       *min_index = min_ub;
  171.       *max_index = max_ub;
  172.       break;
  173.    }
  174.    default:
  175.       assert(0);
  176.       break;
  177.    }
  178.  
  179.    if (_mesa_is_bufferobj(ib->obj)) {
  180.       ctx->Driver.UnmapBuffer(ctx, ib->obj);
  181.    }
  182. }
  183.  
  184. /**
  185.  * Compute min and max elements for nr_prims
  186.  */
  187. void
  188. vbo_get_minmax_indices(struct gl_context *ctx,
  189.                        const struct _mesa_prim *prims,
  190.                        const struct _mesa_index_buffer *ib,
  191.                        GLuint *min_index,
  192.                        GLuint *max_index,
  193.                        GLuint nr_prims)
  194. {
  195.    GLuint tmp_min, tmp_max;
  196.    GLuint i;
  197.    GLuint count;
  198.  
  199.    *min_index = ~0;
  200.    *max_index = 0;
  201.  
  202.    for (i = 0; i < nr_prims; i++) {
  203.       const struct _mesa_prim *start_prim;
  204.  
  205.       start_prim = &prims[i];
  206.       count = start_prim->count;
  207.       /* Do combination if possible to reduce map/unmap count */
  208.       while ((i + 1 < nr_prims) &&
  209.              (prims[i].start + prims[i].count == prims[i+1].start)) {
  210.          count += prims[i+1].count;
  211.          i++;
  212.       }
  213.       vbo_get_minmax_index(ctx, start_prim, ib, &tmp_min, &tmp_max, count);
  214.       *min_index = MIN2(*min_index, tmp_min);
  215.       *max_index = MAX2(*max_index, tmp_max);
  216.    }
  217. }
  218.  
  219.  
  220. /**
  221.  * Check that element 'j' of the array has reasonable data.
  222.  * Map VBO if needed.
  223.  * For debugging purposes; not normally used.
  224.  */
  225. static void
  226. check_array_data(struct gl_context *ctx, struct gl_client_array *array,
  227.                  GLuint attrib, GLuint j)
  228. {
  229.    if (array->Enabled) {
  230.       const void *data = array->Ptr;
  231.       if (_mesa_is_bufferobj(array->BufferObj)) {
  232.          if (!array->BufferObj->Pointer) {
  233.             /* need to map now */
  234.             array->BufferObj->Pointer =
  235.                ctx->Driver.MapBufferRange(ctx, 0, array->BufferObj->Size,
  236.                                           GL_MAP_READ_BIT, array->BufferObj);
  237.          }
  238.          data = ADD_POINTERS(data, array->BufferObj->Pointer);
  239.       }
  240.       switch (array->Type) {
  241.       case GL_FLOAT:
  242.          {
  243.             GLfloat *f = (GLfloat *) ((GLubyte *) data + array->StrideB * j);
  244.             GLint k;
  245.             for (k = 0; k < array->Size; k++) {
  246.                if (IS_INF_OR_NAN(f[k]) ||
  247.                    f[k] >= 1.0e20 || f[k] <= -1.0e10) {
  248.                   printf("Bad array data:\n");
  249.                   printf("  Element[%u].%u = %f\n", j, k, f[k]);
  250.                   printf("  Array %u at %p\n", attrib, (void* ) array);
  251.                   printf("  Type 0x%x, Size %d, Stride %d\n",
  252.                          array->Type, array->Size, array->Stride);
  253.                   printf("  Address/offset %p in Buffer Object %u\n",
  254.                          array->Ptr, array->BufferObj->Name);
  255.                   f[k] = 1.0; /* XXX replace the bad value! */
  256.                }
  257.                /*assert(!IS_INF_OR_NAN(f[k]));*/
  258.             }
  259.          }
  260.          break;
  261.       default:
  262.          ;
  263.       }
  264.    }
  265. }
  266.  
  267.  
  268. /**
  269.  * Unmap the buffer object referenced by given array, if mapped.
  270.  */
  271. static void
  272. unmap_array_buffer(struct gl_context *ctx, struct gl_client_array *array)
  273. {
  274.    if (array->Enabled &&
  275.        _mesa_is_bufferobj(array->BufferObj) &&
  276.        _mesa_bufferobj_mapped(array->BufferObj)) {
  277.       ctx->Driver.UnmapBuffer(ctx, array->BufferObj);
  278.    }
  279. }
  280.  
  281.  
  282. /**
  283.  * Examine the array's data for NaNs, etc.
  284.  * For debug purposes; not normally used.
  285.  */
  286. static void
  287. check_draw_elements_data(struct gl_context *ctx, GLsizei count, GLenum elemType,
  288.                          const void *elements, GLint basevertex)
  289. {
  290.    struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
  291.    const void *elemMap;
  292.    GLint i, k;
  293.  
  294.    if (_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
  295.       elemMap = ctx->Driver.MapBufferRange(ctx, 0,
  296.                                            ctx->Array.ArrayObj->ElementArrayBufferObj->Size,
  297.                                            GL_MAP_READ_BIT,
  298.                                            ctx->Array.ArrayObj->ElementArrayBufferObj);
  299.       elements = ADD_POINTERS(elements, elemMap);
  300.    }
  301.  
  302.    for (i = 0; i < count; i++) {
  303.       GLuint j;
  304.  
  305.       /* j = element[i] */
  306.       switch (elemType) {
  307.       case GL_UNSIGNED_BYTE:
  308.          j = ((const GLubyte *) elements)[i];
  309.          break;
  310.       case GL_UNSIGNED_SHORT:
  311.          j = ((const GLushort *) elements)[i];
  312.          break;
  313.       case GL_UNSIGNED_INT:
  314.          j = ((const GLuint *) elements)[i];
  315.          break;
  316.       default:
  317.          assert(0);
  318.       }
  319.  
  320.       /* check element j of each enabled array */
  321.       for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
  322.          check_array_data(ctx, &arrayObj->VertexAttrib[k], k, j);
  323.       }
  324.    }
  325.  
  326.    if (_mesa_is_bufferobj(arrayObj->ElementArrayBufferObj)) {
  327.       ctx->Driver.UnmapBuffer(ctx, ctx->Array.ArrayObj->ElementArrayBufferObj);
  328.    }
  329.  
  330.    for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
  331.       unmap_array_buffer(ctx, &arrayObj->VertexAttrib[k]);
  332.    }
  333. }
  334.  
  335.  
  336. /**
  337.  * Check array data, looking for NaNs, etc.
  338.  */
  339. static void
  340. check_draw_arrays_data(struct gl_context *ctx, GLint start, GLsizei count)
  341. {
  342.    /* TO DO */
  343. }
  344.  
  345.  
  346. /**
  347.  * Print info/data for glDrawArrays(), for debugging.
  348.  */
  349. static void
  350. print_draw_arrays(struct gl_context *ctx,
  351.                   GLenum mode, GLint start, GLsizei count)
  352. {
  353.    struct vbo_context *vbo = vbo_context(ctx);
  354.    struct vbo_exec_context *exec = &vbo->exec;
  355.    struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
  356.    int i;
  357.  
  358.    printf("vbo_exec_DrawArrays(mode 0x%x, start %d, count %d):\n",
  359.           mode, start, count);
  360.  
  361.    for (i = 0; i < 32; i++) {
  362.       struct gl_buffer_object *bufObj = exec->array.inputs[i]->BufferObj;
  363.       GLuint bufName = bufObj->Name;
  364.       GLint stride = exec->array.inputs[i]->Stride;
  365.       printf("attr %2d: size %d stride %d  enabled %d  "
  366.              "ptr %p  Bufobj %u\n",
  367.              i,
  368.              exec->array.inputs[i]->Size,
  369.              stride,
  370.              /*exec->array.inputs[i]->Enabled,*/
  371.              arrayObj->VertexAttrib[VERT_ATTRIB_FF(i)].Enabled,
  372.              exec->array.inputs[i]->Ptr,
  373.              bufName);
  374.  
  375.       if (bufName) {
  376.          GLubyte *p = ctx->Driver.MapBufferRange(ctx, 0, bufObj->Size,
  377.                                                  GL_MAP_READ_BIT, bufObj);
  378.          int offset = (int) (GLintptr) exec->array.inputs[i]->Ptr;
  379.          float *f = (float *) (p + offset);
  380.          int *k = (int *) f;
  381.          int i;
  382.          int n = (count * stride) / 4;
  383.          if (n > 32)
  384.             n = 32;
  385.          printf("  Data at offset %d:\n", offset);
  386.          for (i = 0; i < n; i++) {
  387.             printf("    float[%d] = 0x%08x %f\n", i, k[i], f[i]);
  388.          }
  389.          ctx->Driver.UnmapBuffer(ctx, bufObj);
  390.       }
  391.    }
  392. }
  393.  
  394.  
  395. /**
  396.  * Set the vbo->exec->inputs[] pointers to point to the enabled
  397.  * vertex arrays.  This depends on the current vertex program/shader
  398.  * being executed because of whether or not generic vertex arrays
  399.  * alias the conventional vertex arrays.
  400.  * For arrays that aren't enabled, we set the input[attrib] pointer
  401.  * to point at a zero-stride current value "array".
  402.  */
  403. static void
  404. recalculate_input_bindings(struct gl_context *ctx)
  405. {
  406.    struct vbo_context *vbo = vbo_context(ctx);
  407.    struct vbo_exec_context *exec = &vbo->exec;
  408.    struct gl_client_array *vertexAttrib = ctx->Array.ArrayObj->VertexAttrib;
  409.    const struct gl_client_array **inputs = &exec->array.inputs[0];
  410.    GLbitfield64 const_inputs = 0x0;
  411.    GLuint i;
  412.  
  413.    switch (get_program_mode(ctx)) {
  414.    case VP_NONE:
  415.       /* When no vertex program is active (or the vertex program is generated
  416.        * from fixed-function state).  We put the material values into the
  417.        * generic slots.  This is the only situation where material values
  418.        * are available as per-vertex attributes.
  419.        */
  420.       for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) {
  421.          if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
  422.             inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
  423.          else {
  424.             inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
  425.             const_inputs |= VERT_BIT(i);
  426.          }
  427.       }
  428.  
  429.       for (i = 0; i < MAT_ATTRIB_MAX; i++) {
  430.          inputs[VERT_ATTRIB_GENERIC(i)] =
  431.             &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT+i];
  432.          const_inputs |= VERT_BIT_GENERIC(i);
  433.       }
  434.  
  435.       /* Could use just about anything, just to fill in the empty
  436.        * slots:
  437.        */
  438.       for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_GENERIC_MAX; i++) {
  439.          inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i];
  440.          const_inputs |= VERT_BIT_GENERIC(i);
  441.       }
  442.       break;
  443.  
  444.    case VP_ARB:
  445.       /* There are no shaders in OpenGL ES 1.x, so this code path should be
  446.        * impossible to reach.  The meta code is careful to not use shaders in
  447.        * ES1.
  448.        */
  449.       assert(ctx->API != API_OPENGLES);
  450.  
  451.       /* In the compatibility profile of desktop OpenGL, the generic[0]
  452.        * attribute array aliases and overrides the legacy position array.
  453.        * Otherwise, legacy attributes available in the legacy slots,
  454.        * generic attributes in the generic slots and materials are not
  455.        * available as per-vertex attributes.
  456.        *
  457.        * In all other APIs, only the generic attributes exist, and none of the
  458.        * slots are considered "magic."
  459.        */
  460.       if (ctx->API == API_OPENGL_COMPAT) {
  461.          if (vertexAttrib[VERT_ATTRIB_GENERIC0].Enabled)
  462.             inputs[0] = &vertexAttrib[VERT_ATTRIB_GENERIC0];
  463.          else if (vertexAttrib[VERT_ATTRIB_POS].Enabled)
  464.             inputs[0] = &vertexAttrib[VERT_ATTRIB_POS];
  465.          else {
  466.             inputs[0] = &vbo->currval[VBO_ATTRIB_POS];
  467.             const_inputs |= VERT_BIT_POS;
  468.          }
  469.  
  470.          for (i = 1; i < VERT_ATTRIB_FF_MAX; i++) {
  471.             if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
  472.                inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
  473.             else {
  474.                inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
  475.                const_inputs |= VERT_BIT_FF(i);
  476.             }
  477.          }
  478.  
  479.          for (i = 1; i < VERT_ATTRIB_GENERIC_MAX; i++) {
  480.             if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
  481.                inputs[VERT_ATTRIB_GENERIC(i)] =
  482.                   &vertexAttrib[VERT_ATTRIB_GENERIC(i)];
  483.             else {
  484.                inputs[VERT_ATTRIB_GENERIC(i)] =
  485.                   &vbo->currval[VBO_ATTRIB_GENERIC0+i];
  486.                const_inputs |= VERT_BIT_GENERIC(i);
  487.             }
  488.          }
  489.  
  490.          inputs[VERT_ATTRIB_GENERIC0] = inputs[0];
  491.       } else {
  492.          /* Other parts of the code assume that inputs[0] through
  493.           * inputs[VERT_ATTRIB_FF_MAX] will be non-NULL.  However, in OpenGL
  494.           * ES 2.0+ or OpenGL core profile, none of these arrays should ever
  495.           * be enabled.
  496.           */
  497.          for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) {
  498.             assert(!vertexAttrib[VERT_ATTRIB_FF(i)].Enabled);
  499.  
  500.             inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
  501.             const_inputs |= VERT_BIT_FF(i);
  502.          }
  503.  
  504.          for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) {
  505.             if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
  506.                inputs[VERT_ATTRIB_GENERIC(i)] =
  507.                   &vertexAttrib[VERT_ATTRIB_GENERIC(i)];
  508.             else {
  509.                inputs[VERT_ATTRIB_GENERIC(i)] =
  510.                   &vbo->currval[VBO_ATTRIB_GENERIC0+i];
  511.                const_inputs |= VERT_BIT_GENERIC(i);
  512.             }
  513.          }
  514.       }
  515.  
  516.       break;
  517.    }
  518.  
  519.    _mesa_set_varying_vp_inputs( ctx, VERT_BIT_ALL & (~const_inputs) );
  520.    ctx->NewDriverState |= ctx->DriverFlags.NewArray;
  521. }
  522.  
  523.  
  524. /**
  525.  * Examine the enabled vertex arrays to set the exec->array.inputs[] values.
  526.  * These will point to the arrays to actually use for drawing.  Some will
  527.  * be user-provided arrays, other will be zero-stride const-valued arrays.
  528.  * Note that this might set the _NEW_VARYING_VP_INPUTS dirty flag so state
  529.  * validation must be done after this call.
  530.  */
  531. void
  532. vbo_bind_arrays(struct gl_context *ctx)
  533. {
  534.    struct vbo_context *vbo = vbo_context(ctx);
  535.    struct vbo_exec_context *exec = &vbo->exec;
  536. ENTER();
  537.    vbo_draw_method(vbo, DRAW_ARRAYS);
  538.  
  539.    if (exec->array.recalculate_inputs) {
  540.       recalculate_input_bindings(ctx);
  541.       exec->array.recalculate_inputs = GL_FALSE;
  542.  
  543.       /* Again... because we may have changed the bitmask of per-vertex varying
  544.        * attributes.  If we regenerate the fixed-function vertex program now
  545.        * we may be able to prune down the number of vertex attributes which we
  546.        * need in the shader.
  547.        */
  548.       if (ctx->NewState) {
  549.          /* Setting "validating" to TRUE prevents _mesa_update_state from
  550.           * invalidating what we just did.
  551.           */
  552.          exec->validating = GL_TRUE;
  553.          _mesa_update_state(ctx);
  554.          exec->validating = GL_FALSE;
  555.       }
  556.    }
  557. LEAVE();
  558. }
  559.  
  560.  
  561. /**
  562.  * Handle a draw case that potentially has primitive restart enabled.
  563.  *
  564.  * If primitive restart is enabled, and PrimitiveRestartInSoftware is
  565.  * set, then vbo_sw_primitive_restart is used to handle the primitive
  566.  * restart case in software.
  567.  */
  568. static void
  569. vbo_handle_primitive_restart(struct gl_context *ctx,
  570.                              const struct _mesa_prim *prim,
  571.                              GLuint nr_prims,
  572.                              const struct _mesa_index_buffer *ib,
  573.                              GLboolean index_bounds_valid,
  574.                              GLuint min_index,
  575.                              GLuint max_index)
  576. {
  577.    struct vbo_context *vbo = vbo_context(ctx);
  578.  
  579.    if ((ib != NULL) &&
  580.        ctx->Const.PrimitiveRestartInSoftware &&
  581.        ctx->Array._PrimitiveRestart) {
  582.       /* Handle primitive restart in software */
  583.       vbo_sw_primitive_restart(ctx, prim, nr_prims, ib);
  584.    } else {
  585.       /* Call driver directly for draw_prims */
  586.       vbo->draw_prims(ctx, prim, nr_prims, ib,
  587.                       index_bounds_valid, min_index, max_index, NULL);
  588.    }
  589. }
  590.  
  591.  
  592. /**
  593.  * Helper function called by the other DrawArrays() functions below.
  594.  * This is where we handle primitive restart for drawing non-indexed
  595.  * arrays.  If primitive restart is enabled, it typically means
  596.  * splitting one DrawArrays() into two.
  597.  */
  598. static void
  599. vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
  600.                 GLsizei count, GLuint numInstances, GLuint baseInstance)
  601. {
  602.    struct vbo_context *vbo = vbo_context(ctx);
  603.    struct vbo_exec_context *exec = &vbo->exec;
  604.    struct _mesa_prim prim[2];
  605. ENTER();
  606.    vbo_bind_arrays(ctx);
  607.  
  608.    /* init most fields to zero */
  609.    memset(prim, 0, sizeof(prim));
  610.    prim[0].begin = 1;
  611.    prim[0].end = 1;
  612.    prim[0].mode = mode;
  613.    prim[0].num_instances = numInstances;
  614.    prim[0].base_instance = baseInstance;
  615.  
  616.    /* Implement the primitive restart index */
  617.    if (ctx->Array.PrimitiveRestart && ctx->Array.RestartIndex < count) {
  618.       GLuint primCount = 0;
  619.  
  620.       if (ctx->Array.RestartIndex == start) {
  621.          /* special case: RestartIndex at beginning */
  622.          if (count > 1) {
  623.             prim[0].start = start + 1;
  624.             prim[0].count = count - 1;
  625.             primCount = 1;
  626.          }
  627.       }
  628.       else if (ctx->Array.RestartIndex == start + count - 1) {
  629.          /* special case: RestartIndex at end */
  630.          if (count > 1) {
  631.             prim[0].start = start;
  632.             prim[0].count = count - 1;
  633.             primCount = 1;
  634.          }
  635.       }
  636.       else {
  637.          /* general case: RestartIndex in middle, split into two prims */
  638.          prim[0].start = start;
  639.          prim[0].count = ctx->Array.RestartIndex - start;
  640.  
  641.          prim[1] = prim[0];
  642.          prim[1].start = ctx->Array.RestartIndex + 1;
  643.          prim[1].count = count - prim[1].start;
  644.  
  645.          primCount = 2;
  646.       }
  647.  
  648.       if (primCount > 0) {
  649.          /* draw one or two prims */
  650.          check_buffers_are_unmapped(exec->array.inputs);
  651.          vbo->draw_prims(ctx, prim, primCount, NULL,
  652.                          GL_TRUE, start, start + count - 1, NULL);
  653.       }
  654.    }
  655.    else {
  656.       /* no prim restart */
  657.       prim[0].start = start;
  658.       prim[0].count = count;
  659.  
  660.       check_buffers_are_unmapped(exec->array.inputs);
  661.       vbo->draw_prims(ctx, prim, 1, NULL,
  662.                       GL_TRUE, start, start + count - 1,
  663.                       NULL);
  664.    }
  665.  
  666.    if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
  667.       _mesa_flush(ctx);
  668.    }
  669. LEAVE();
  670. }
  671.  
  672.  
  673. /**
  674.  * Execute a glRectf() function.
  675.  */
  676. static void GLAPIENTRY
  677. vbo_exec_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
  678. {
  679.    GET_CURRENT_CONTEXT(ctx);
  680.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  681.  
  682.    CALL_Begin(GET_DISPATCH(), (GL_QUADS));
  683.    CALL_Vertex2f(GET_DISPATCH(), (x1, y1));
  684.    CALL_Vertex2f(GET_DISPATCH(), (x2, y1));
  685.    CALL_Vertex2f(GET_DISPATCH(), (x2, y2));
  686.    CALL_Vertex2f(GET_DISPATCH(), (x1, y2));
  687.    CALL_End(GET_DISPATCH(), ());
  688. }
  689.  
  690.  
  691. static void GLAPIENTRY
  692. vbo_exec_EvalMesh1(GLenum mode, GLint i1, GLint i2)
  693. {
  694.    GET_CURRENT_CONTEXT(ctx);
  695.    GLint i;
  696.    GLfloat u, du;
  697.    GLenum prim;
  698.  
  699.    switch (mode) {
  700.    case GL_POINT:
  701.       prim = GL_POINTS;
  702.       break;
  703.    case GL_LINE:
  704.       prim = GL_LINE_STRIP;
  705.       break;
  706.    default:
  707.       _mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh1(mode)" );
  708.       return;
  709.    }
  710.  
  711.    /* No effect if vertex maps disabled.
  712.     */
  713.    if (!ctx->Eval.Map1Vertex4 &&
  714.        !ctx->Eval.Map1Vertex3)
  715.       return;
  716.  
  717.    du = ctx->Eval.MapGrid1du;
  718.    u = ctx->Eval.MapGrid1u1 + i1 * du;
  719.  
  720.    CALL_Begin(GET_DISPATCH(), (prim));
  721.    for (i=i1;i<=i2;i++,u+=du) {
  722.       CALL_EvalCoord1f(GET_DISPATCH(), (u));
  723.    }
  724.    CALL_End(GET_DISPATCH(), ());
  725. }
  726.  
  727.  
  728. static void GLAPIENTRY
  729. vbo_exec_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)
  730. {
  731.    GET_CURRENT_CONTEXT(ctx);
  732.    GLfloat u, du, v, dv, v1, u1;
  733.    GLint i, j;
  734.  
  735.    switch (mode) {
  736.    case GL_POINT:
  737.    case GL_LINE:
  738.    case GL_FILL:
  739.       break;
  740.    default:
  741.       _mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)" );
  742.       return;
  743.    }
  744.  
  745.    /* No effect if vertex maps disabled.
  746.     */
  747.    if (!ctx->Eval.Map2Vertex4 &&
  748.        !ctx->Eval.Map2Vertex3)
  749.       return;
  750.  
  751.    du = ctx->Eval.MapGrid2du;
  752.    dv = ctx->Eval.MapGrid2dv;
  753.    v1 = ctx->Eval.MapGrid2v1 + j1 * dv;
  754.    u1 = ctx->Eval.MapGrid2u1 + i1 * du;
  755.  
  756.    switch (mode) {
  757.    case GL_POINT:
  758.       CALL_Begin(GET_DISPATCH(), (GL_POINTS));
  759.       for (v=v1,j=j1;j<=j2;j++,v+=dv) {
  760.          for (u=u1,i=i1;i<=i2;i++,u+=du) {
  761.             CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
  762.          }
  763.       }
  764.       CALL_End(GET_DISPATCH(), ());
  765.       break;
  766.    case GL_LINE:
  767.       for (v=v1,j=j1;j<=j2;j++,v+=dv) {
  768.          CALL_Begin(GET_DISPATCH(), (GL_LINE_STRIP));
  769.          for (u=u1,i=i1;i<=i2;i++,u+=du) {
  770.             CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
  771.          }
  772.          CALL_End(GET_DISPATCH(), ());
  773.       }
  774.       for (u=u1,i=i1;i<=i2;i++,u+=du) {
  775.          CALL_Begin(GET_DISPATCH(), (GL_LINE_STRIP));
  776.          for (v=v1,j=j1;j<=j2;j++,v+=dv) {
  777.             CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
  778.          }
  779.          CALL_End(GET_DISPATCH(), ());
  780.       }
  781.       break;
  782.    case GL_FILL:
  783.       for (v=v1,j=j1;j<j2;j++,v+=dv) {
  784.          CALL_Begin(GET_DISPATCH(), (GL_TRIANGLE_STRIP));
  785.          for (u=u1,i=i1;i<=i2;i++,u+=du) {
  786.             CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
  787.             CALL_EvalCoord2f(GET_DISPATCH(), (u, v+dv));
  788.          }
  789.          CALL_End(GET_DISPATCH(), ());
  790.       }
  791.       break;
  792.    }
  793. }
  794.  
  795.  
  796. /**
  797.  * Called from glDrawArrays when in immediate mode (not display list mode).
  798.  */
  799. static void GLAPIENTRY
  800. vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
  801. {
  802.    GET_CURRENT_CONTEXT(ctx);
  803.  
  804.    if (MESA_VERBOSE & VERBOSE_DRAW)
  805.       _mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n",
  806.                   _mesa_lookup_enum_by_nr(mode), start, count);
  807.  
  808.    if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
  809.       return;
  810.  
  811.    if (0)
  812.       check_draw_arrays_data(ctx, start, count);
  813.  
  814.    vbo_draw_arrays(ctx, mode, start, count, 1, 0);
  815.  
  816.    if (0)
  817.       print_draw_arrays(ctx, mode, start, count);
  818. }
  819.  
  820.  
  821. /**
  822.  * Called from glDrawArraysInstanced when in immediate mode (not
  823.  * display list mode).
  824.  */
  825. static void GLAPIENTRY
  826. vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count,
  827.                              GLsizei numInstances)
  828. {
  829.    GET_CURRENT_CONTEXT(ctx);
  830.  
  831.    if (MESA_VERBOSE & VERBOSE_DRAW)
  832.       _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n",
  833.                   _mesa_lookup_enum_by_nr(mode), start, count, numInstances);
  834.  
  835.    if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, numInstances))
  836.       return;
  837.  
  838.    if (0)
  839.       check_draw_arrays_data(ctx, start, count);
  840.  
  841.    vbo_draw_arrays(ctx, mode, start, count, numInstances, 0);
  842.  
  843.    if (0)
  844.       print_draw_arrays(ctx, mode, start, count);
  845. }
  846.  
  847.  
  848. /**
  849.  * Called from glDrawArraysInstancedBaseInstance when in immediate mode.
  850.  */
  851. static void GLAPIENTRY
  852. vbo_exec_DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count,
  853.                                          GLsizei numInstances, GLuint baseInstance)
  854. {
  855.    GET_CURRENT_CONTEXT(ctx);
  856.  
  857.    if (MESA_VERBOSE & VERBOSE_DRAW)
  858.       _mesa_debug(ctx, "glDrawArraysInstancedBaseInstance(%s, %d, %d, %d, %d)\n",
  859.                   _mesa_lookup_enum_by_nr(mode), first, count,
  860.                   numInstances, baseInstance);
  861.  
  862.    if (!_mesa_validate_DrawArraysInstanced(ctx, mode, first, count,
  863.                                            numInstances))
  864.       return;
  865.  
  866.    if (0)
  867.       check_draw_arrays_data(ctx, first, count);
  868.  
  869.    vbo_draw_arrays(ctx, mode, first, count, numInstances, baseInstance);
  870.  
  871.    if (0)
  872.       print_draw_arrays(ctx, mode, first, count);
  873. }
  874.  
  875.  
  876.  
  877. /**
  878.  * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
  879.  * For debugging.
  880.  */
  881. #if 0
  882. static void
  883. dump_element_buffer(struct gl_context *ctx, GLenum type)
  884. {
  885.    const GLvoid *map =
  886.       ctx->Driver.MapBufferRange(ctx, 0,
  887.                                  ctx->Array.ArrayObj->ElementArrayBufferObj->Size,
  888.                                  GL_MAP_READ_BIT,
  889.                                  ctx->Array.ArrayObj->ElementArrayBufferObj);
  890.    switch (type) {
  891.    case GL_UNSIGNED_BYTE:
  892.       {
  893.          const GLubyte *us = (const GLubyte *) map;
  894.          GLint i;
  895.          for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size; i++) {
  896.             printf("%02x ", us[i]);
  897.             if (i % 32 == 31)
  898.                printf("\n");
  899.          }
  900.          printf("\n");
  901.       }
  902.       break;
  903.    case GL_UNSIGNED_SHORT:
  904.       {
  905.          const GLushort *us = (const GLushort *) map;
  906.          GLint i;
  907.          for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size / 2; i++) {
  908.             printf("%04x ", us[i]);
  909.             if (i % 16 == 15)
  910.                printf("\n");
  911.          }
  912.          printf("\n");
  913.       }
  914.       break;
  915.    case GL_UNSIGNED_INT:
  916.       {
  917.          const GLuint *us = (const GLuint *) map;
  918.          GLint i;
  919.          for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size / 4; i++) {
  920.             printf("%08x ", us[i]);
  921.             if (i % 8 == 7)
  922.                printf("\n");
  923.          }
  924.          printf("\n");
  925.       }
  926.       break;
  927.    default:
  928.       ;
  929.    }
  930.  
  931.    ctx->Driver.UnmapBuffer(ctx, ctx->Array.ArrayObj->ElementArrayBufferObj);
  932. }
  933. #endif
  934.  
  935.  
  936. /**
  937.  * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements.
  938.  * Do the rendering for a glDrawElements or glDrawRangeElements call after
  939.  * we've validated buffer bounds, etc.
  940.  */
  941. static void
  942. vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
  943.                                 GLboolean index_bounds_valid,
  944.                                 GLuint start, GLuint end,
  945.                                 GLsizei count, GLenum type,
  946.                                 const GLvoid *indices,
  947.                                 GLint basevertex, GLuint numInstances,
  948.                                 GLuint baseInstance)
  949. {
  950.    struct vbo_context *vbo = vbo_context(ctx);
  951.    struct vbo_exec_context *exec = &vbo->exec;
  952.    struct _mesa_index_buffer ib;
  953.    struct _mesa_prim prim[1];
  954.  
  955.    vbo_bind_arrays(ctx);
  956.  
  957.    ib.count = count;
  958.    ib.type = type;
  959.    ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
  960.    ib.ptr = indices;
  961.  
  962.    prim[0].begin = 1;
  963.    prim[0].end = 1;
  964.    prim[0].weak = 0;
  965.    prim[0].pad = 0;
  966.    prim[0].mode = mode;
  967.    prim[0].start = 0;
  968.    prim[0].count = count;
  969.    prim[0].indexed = 1;
  970.    prim[0].basevertex = basevertex;
  971.    prim[0].num_instances = numInstances;
  972.    prim[0].base_instance = baseInstance;
  973.  
  974.    /* Need to give special consideration to rendering a range of
  975.     * indices starting somewhere above zero.  Typically the
  976.     * application is issuing multiple DrawRangeElements() to draw
  977.     * successive primitives layed out linearly in the vertex arrays.
  978.     * Unless the vertex arrays are all in a VBO (or locked as with
  979.     * CVA), the OpenGL semantics imply that we need to re-read or
  980.     * re-upload the vertex data on each draw call.
  981.     *
  982.     * In the case of hardware tnl, we want to avoid starting the
  983.     * upload at zero, as it will mean every draw call uploads an
  984.     * increasing amount of not-used vertex data.  Worse - in the
  985.     * software tnl module, all those vertices might be transformed and
  986.     * lit but never rendered.
  987.     *
  988.     * If we just upload or transform the vertices in start..end,
  989.     * however, the indices will be incorrect.
  990.     *
  991.     * At this level, we don't know exactly what the requirements of
  992.     * the backend are going to be, though it will likely boil down to
  993.     * either:
  994.     *
  995.     * 1) Do nothing, everything is in a VBO and is processed once
  996.     *       only.
  997.     *
  998.     * 2) Adjust the indices and vertex arrays so that start becomes
  999.     *    zero.
  1000.     *
  1001.     * Rather than doing anything here, I'll provide a helper function
  1002.     * for the latter case elsewhere.
  1003.     */
  1004.  
  1005.    check_buffers_are_unmapped(exec->array.inputs);
  1006.    vbo_handle_primitive_restart(ctx, prim, 1, &ib,
  1007.                                 index_bounds_valid, start, end);
  1008.  
  1009.    if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
  1010.       _mesa_flush(ctx);
  1011.    }
  1012. }
  1013.  
  1014.  
  1015. /**
  1016.  * Called by glDrawRangeElementsBaseVertex() in immediate mode.
  1017.  */
  1018. static void GLAPIENTRY
  1019. vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
  1020.                                      GLuint start, GLuint end,
  1021.                                      GLsizei count, GLenum type,
  1022.                                      const GLvoid *indices,
  1023.                                      GLint basevertex)
  1024. {
  1025.    static GLuint warnCount = 0;
  1026.    GLboolean index_bounds_valid = GL_TRUE;
  1027.    GLuint max_element;
  1028.    GET_CURRENT_CONTEXT(ctx);
  1029.  
  1030.    if (MESA_VERBOSE & VERBOSE_DRAW)
  1031.       _mesa_debug(ctx,
  1032.                 "glDrawRangeElementsBaseVertex(%s, %u, %u, %d, %s, %p, %d)\n",
  1033.                 _mesa_lookup_enum_by_nr(mode), start, end, count,
  1034.                 _mesa_lookup_enum_by_nr(type), indices, basevertex);
  1035.  
  1036.    if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
  1037.                                           type, indices, basevertex ))
  1038.       return;
  1039.  
  1040.    if (ctx->Const.CheckArrayBounds) {
  1041.       /* _MaxElement was computed, so we can use it.
  1042.        * This path is used for drivers which need strict bounds checking.
  1043.        */
  1044.       max_element = ctx->Array.ArrayObj->_MaxElement;
  1045.    }
  1046.    else {
  1047.       /* Generally, hardware drivers don't need to know the buffer bounds
  1048.        * if all vertex attributes are in VBOs.
  1049.        * However, if none of vertex attributes are in VBOs, _MaxElement
  1050.        * is always set to some random big number anyway, so bounds checking
  1051.        * is mostly useless.
  1052.        *
  1053.        * This is only useful to catch invalid values in the "end" parameter
  1054.        * like ~0.
  1055.        */
  1056.       max_element = 2 * 1000 * 1000 * 1000; /* just a big number */
  1057.    }
  1058.  
  1059.    if ((int) end + basevertex < 0 ||
  1060.        start + basevertex >= max_element) {
  1061.       /* The application requested we draw using a range of indices that's
  1062.        * outside the bounds of the current VBO.  This is invalid and appears
  1063.        * to give undefined results.  The safest thing to do is to simply
  1064.        * ignore the range, in case the application botched their range tracking
  1065.        * but did provide valid indices.  Also issue a warning indicating that
  1066.        * the application is broken.
  1067.        */
  1068.       if (warnCount++ < 10) {
  1069.          _mesa_warning(ctx, "glDrawRangeElements(start %u, end %u, "
  1070.                        "basevertex %d, count %d, type 0x%x, indices=%p):\n"
  1071.                        "\trange is outside VBO bounds (max=%u); ignoring.\n"
  1072.                        "\tThis should be fixed in the application.",
  1073.                        start, end, basevertex, count, type, indices,
  1074.                        max_element - 1);
  1075.       }
  1076.       index_bounds_valid = GL_FALSE;
  1077.    }
  1078.  
  1079.    /* NOTE: It's important that 'end' is a reasonable value.
  1080.     * in _tnl_draw_prims(), we use end to determine how many vertices
  1081.     * to transform.  If it's too large, we can unnecessarily split prims
  1082.     * or we can read/write out of memory in several different places!
  1083.     */
  1084.  
  1085.    /* Catch/fix some potential user errors */
  1086.    if (type == GL_UNSIGNED_BYTE) {
  1087.       start = MIN2(start, 0xff);
  1088.       end = MIN2(end, 0xff);
  1089.    }
  1090.    else if (type == GL_UNSIGNED_SHORT) {
  1091.       start = MIN2(start, 0xffff);
  1092.       end = MIN2(end, 0xffff);
  1093.    }
  1094.  
  1095.    if (0) {
  1096.       printf("glDraw[Range]Elements{,BaseVertex}"
  1097.              "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
  1098.              "base %d\n",
  1099.              start, end, type, count,
  1100.              ctx->Array.ArrayObj->ElementArrayBufferObj->Name,
  1101.              basevertex);
  1102.    }
  1103.  
  1104.    if ((int) start + basevertex < 0 ||
  1105.        end + basevertex >= max_element)
  1106.       index_bounds_valid = GL_FALSE;
  1107.  
  1108. #if 0
  1109.    check_draw_elements_data(ctx, count, type, indices);
  1110. #else
  1111.    (void) check_draw_elements_data;
  1112. #endif
  1113.  
  1114.    vbo_validated_drawrangeelements(ctx, mode, index_bounds_valid, start, end,
  1115.                                    count, type, indices, basevertex, 1, 0);
  1116. }
  1117.  
  1118.  
  1119. /**
  1120.  * Called by glDrawRangeElements() in immediate mode.
  1121.  */
  1122. static void GLAPIENTRY
  1123. vbo_exec_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
  1124.                            GLsizei count, GLenum type, const GLvoid *indices)
  1125. {
  1126.    if (MESA_VERBOSE & VERBOSE_DRAW) {
  1127.       GET_CURRENT_CONTEXT(ctx);
  1128.       _mesa_debug(ctx,
  1129.                   "glDrawRangeElements(%s, %u, %u, %d, %s, %p)\n",
  1130.                   _mesa_lookup_enum_by_nr(mode), start, end, count,
  1131.                   _mesa_lookup_enum_by_nr(type), indices);
  1132.    }
  1133.  
  1134.    vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
  1135.                                         indices, 0);
  1136. }
  1137.  
  1138.  
  1139. /**
  1140.  * Called by glDrawElements() in immediate mode.
  1141.  */
  1142. static void GLAPIENTRY
  1143. vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
  1144.                       const GLvoid *indices)
  1145. {
  1146.    GET_CURRENT_CONTEXT(ctx);
  1147.  
  1148.    if (MESA_VERBOSE & VERBOSE_DRAW)
  1149.       _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n",
  1150.                   _mesa_lookup_enum_by_nr(mode), count,
  1151.                   _mesa_lookup_enum_by_nr(type), indices);
  1152.  
  1153.    if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
  1154.       return;
  1155.  
  1156.    vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
  1157.                                    count, type, indices, 0, 1, 0);
  1158. }
  1159.  
  1160.  
  1161. /**
  1162.  * Called by glDrawElementsBaseVertex() in immediate mode.
  1163.  */
  1164. static void GLAPIENTRY
  1165. vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
  1166.                                 const GLvoid *indices, GLint basevertex)
  1167. {
  1168.    GET_CURRENT_CONTEXT(ctx);
  1169.  
  1170.    if (MESA_VERBOSE & VERBOSE_DRAW)
  1171.       _mesa_debug(ctx, "glDrawElementsBaseVertex(%s, %d, %s, %p, %d)\n",
  1172.                   _mesa_lookup_enum_by_nr(mode), count,
  1173.                   _mesa_lookup_enum_by_nr(type), indices, basevertex);
  1174.  
  1175.    if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices,
  1176.                                      basevertex ))
  1177.       return;
  1178.  
  1179.    vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
  1180.                                    count, type, indices, basevertex, 1, 0);
  1181. }
  1182.  
  1183.  
  1184. /**
  1185.  * Called by glDrawElementsInstanced() in immediate mode.
  1186.  */
  1187. static void GLAPIENTRY
  1188. vbo_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
  1189.                                const GLvoid *indices, GLsizei numInstances)
  1190. {
  1191.    GET_CURRENT_CONTEXT(ctx);
  1192.  
  1193.    if (MESA_VERBOSE & VERBOSE_DRAW)
  1194.       _mesa_debug(ctx, "glDrawElementsInstanced(%s, %d, %s, %p, %d)\n",
  1195.                   _mesa_lookup_enum_by_nr(mode), count,
  1196.                   _mesa_lookup_enum_by_nr(type), indices, numInstances);
  1197.  
  1198.    if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
  1199.                                              numInstances, 0))
  1200.       return;
  1201.  
  1202.    vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
  1203.                                    count, type, indices, 0, numInstances, 0);
  1204. }
  1205.  
  1206.  
  1207. /**
  1208.  * Called by glDrawElementsInstancedBaseVertex() in immediate mode.
  1209.  */
  1210. static void GLAPIENTRY
  1211. vbo_exec_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type,
  1212.                                const GLvoid *indices, GLsizei numInstances,
  1213.                                GLint basevertex)
  1214. {
  1215.    GET_CURRENT_CONTEXT(ctx);
  1216.  
  1217.    if (MESA_VERBOSE & VERBOSE_DRAW)
  1218.       _mesa_debug(ctx, "glDrawElementsInstancedBaseVertex(%s, %d, %s, %p, %d; %d)\n",
  1219.                   _mesa_lookup_enum_by_nr(mode), count,
  1220.                   _mesa_lookup_enum_by_nr(type), indices,
  1221.                   numInstances, basevertex);
  1222.  
  1223.    if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
  1224.                                              numInstances, basevertex))
  1225.       return;
  1226.  
  1227.    vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
  1228.                                    count, type, indices, basevertex, numInstances, 0);
  1229. }
  1230.  
  1231.  
  1232. /**
  1233.  * Called by glDrawElementsInstancedBaseInstance() in immediate mode.
  1234.  */
  1235. static void GLAPIENTRY
  1236. vbo_exec_DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type,
  1237.                                            const GLvoid *indices, GLsizei numInstances,
  1238.                                            GLuint baseInstance)
  1239. {
  1240.    GET_CURRENT_CONTEXT(ctx);
  1241.  
  1242.    if (MESA_VERBOSE & VERBOSE_DRAW)
  1243.       _mesa_debug(ctx, "glDrawElementsInstancedBaseInstance(%s, %d, %s, %p, %d, %d)\n",
  1244.                   _mesa_lookup_enum_by_nr(mode), count,
  1245.                   _mesa_lookup_enum_by_nr(type), indices,
  1246.                   numInstances, baseInstance);
  1247.  
  1248.    if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
  1249.                                              numInstances, 0))
  1250.       return;
  1251.  
  1252.    vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
  1253.                                    count, type, indices, 0, numInstances,
  1254.                                    baseInstance);
  1255. }
  1256.  
  1257.  
  1258. /**
  1259.  * Called by glDrawElementsInstancedBaseVertexBaseInstance() in immediate mode.
  1260.  */
  1261. static void GLAPIENTRY
  1262. vbo_exec_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type,
  1263.                                                      const GLvoid *indices, GLsizei numInstances,
  1264.                                                      GLint basevertex, GLuint baseInstance)
  1265. {
  1266.    GET_CURRENT_CONTEXT(ctx);
  1267.  
  1268.    if (MESA_VERBOSE & VERBOSE_DRAW)
  1269.       _mesa_debug(ctx, "glDrawElementsInstancedBaseVertexBaseInstance(%s, %d, %s, %p, %d, %d, %d)\n",
  1270.                   _mesa_lookup_enum_by_nr(mode), count,
  1271.                   _mesa_lookup_enum_by_nr(type), indices,
  1272.                   numInstances, basevertex, baseInstance);
  1273.  
  1274.    if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
  1275.                                              numInstances, basevertex))
  1276.       return;
  1277.  
  1278.    vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
  1279.                                    count, type, indices, basevertex, numInstances,
  1280.                                    baseInstance);
  1281. }
  1282.  
  1283.  
  1284. /**
  1285.  * Inner support for both _mesa_MultiDrawElements() and
  1286.  * _mesa_MultiDrawRangeElements().
  1287.  * This does the actual rendering after we've checked array indexes, etc.
  1288.  */
  1289. static void
  1290. vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
  1291.                                 const GLsizei *count, GLenum type,
  1292.                                 const GLvoid * const *indices,
  1293.                                 GLsizei primcount,
  1294.                                 const GLint *basevertex)
  1295. {
  1296.    struct vbo_context *vbo = vbo_context(ctx);
  1297.    struct vbo_exec_context *exec = &vbo->exec;
  1298.    struct _mesa_index_buffer ib;
  1299.    struct _mesa_prim *prim;
  1300.    unsigned int index_type_size = vbo_sizeof_ib_type(type);
  1301.    uintptr_t min_index_ptr, max_index_ptr;
  1302.    GLboolean fallback = GL_FALSE;
  1303.    int i;
  1304.  
  1305.    if (primcount == 0)
  1306.       return;
  1307.  
  1308.    prim = calloc(1, primcount * sizeof(*prim));
  1309.    if (prim == NULL) {
  1310.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
  1311.       return;
  1312.    }
  1313.  
  1314.    vbo_bind_arrays(ctx);
  1315.  
  1316.    min_index_ptr = (uintptr_t)indices[0];
  1317.    max_index_ptr = 0;
  1318.    for (i = 0; i < primcount; i++) {
  1319.       min_index_ptr = MIN2(min_index_ptr, (uintptr_t)indices[i]);
  1320.       max_index_ptr = MAX2(max_index_ptr, (uintptr_t)indices[i] +
  1321.                            index_type_size * count[i]);
  1322.    }
  1323.  
  1324.    /* Check if we can handle this thing as a bunch of index offsets from the
  1325.     * same index pointer.  If we can't, then we have to fall back to doing
  1326.     * a draw_prims per primitive.
  1327.     * Check that the difference between each prim's indexes is a multiple of
  1328.     * the index/element size.
  1329.     */
  1330.    if (index_type_size != 1) {
  1331.       for (i = 0; i < primcount; i++) {
  1332.          if ((((uintptr_t)indices[i] - min_index_ptr) % index_type_size) != 0) {
  1333.             fallback = GL_TRUE;
  1334.             break;
  1335.          }
  1336.       }
  1337.    }
  1338.  
  1339.    /* If the index buffer isn't in a VBO, then treating the application's
  1340.     * subranges of the index buffer as one large index buffer may lead to
  1341.     * us reading unmapped memory.
  1342.     */
  1343.    if (!_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj))
  1344.       fallback = GL_TRUE;
  1345.  
  1346.    if (!fallback) {
  1347.       ib.count = (max_index_ptr - min_index_ptr) / index_type_size;
  1348.       ib.type = type;
  1349.       ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
  1350.       ib.ptr = (void *)min_index_ptr;
  1351.  
  1352.       for (i = 0; i < primcount; i++) {
  1353.          prim[i].begin = (i == 0);
  1354.          prim[i].end = (i == primcount - 1);
  1355.          prim[i].weak = 0;
  1356.          prim[i].pad = 0;
  1357.          prim[i].mode = mode;
  1358.          prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size;
  1359.          prim[i].count = count[i];
  1360.          prim[i].indexed = 1;
  1361.          prim[i].num_instances = 1;
  1362.          prim[i].base_instance = 0;
  1363.          if (basevertex != NULL)
  1364.             prim[i].basevertex = basevertex[i];
  1365.          else
  1366.             prim[i].basevertex = 0;
  1367.       }
  1368.  
  1369.       check_buffers_are_unmapped(exec->array.inputs);
  1370.       vbo_handle_primitive_restart(ctx, prim, primcount, &ib,
  1371.                                    GL_FALSE, ~0, ~0);
  1372.    } else {
  1373.       /* render one prim at a time */
  1374.       for (i = 0; i < primcount; i++) {
  1375.          ib.count = count[i];
  1376.          ib.type = type;
  1377.          ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
  1378.          ib.ptr = indices[i];
  1379.  
  1380.          prim[0].begin = 1;
  1381.          prim[0].end = 1;
  1382.          prim[0].weak = 0;
  1383.          prim[0].pad = 0;
  1384.          prim[0].mode = mode;
  1385.          prim[0].start = 0;
  1386.          prim[0].count = count[i];
  1387.          prim[0].indexed = 1;
  1388.          prim[0].num_instances = 1;
  1389.          prim[0].base_instance = 0;
  1390.          if (basevertex != NULL)
  1391.             prim[0].basevertex = basevertex[i];
  1392.          else
  1393.             prim[0].basevertex = 0;
  1394.  
  1395.          check_buffers_are_unmapped(exec->array.inputs);
  1396.          vbo_handle_primitive_restart(ctx, prim, 1, &ib,
  1397.                                       GL_FALSE, ~0, ~0);
  1398.       }
  1399.    }
  1400.  
  1401.    free(prim);
  1402.  
  1403.    if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
  1404.       _mesa_flush(ctx);
  1405.    }
  1406. }
  1407.  
  1408.  
  1409. static void GLAPIENTRY
  1410. vbo_exec_MultiDrawElements(GLenum mode,
  1411.                            const GLsizei *count, GLenum type,
  1412.                            const GLvoid * const *indices,
  1413.                            GLsizei primcount)
  1414. {
  1415.    GET_CURRENT_CONTEXT(ctx);
  1416.  
  1417.    if (!_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
  1418.                                          primcount, NULL))
  1419.       return;
  1420.  
  1421.    vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
  1422.                                    NULL);
  1423. }
  1424.  
  1425.  
  1426. static void GLAPIENTRY
  1427. vbo_exec_MultiDrawElementsBaseVertex(GLenum mode,
  1428.                                      const GLsizei *count, GLenum type,
  1429.                                      const GLvoid * const *indices,
  1430.                                      GLsizei primcount,
  1431.                                      const GLsizei *basevertex)
  1432. {
  1433.    GET_CURRENT_CONTEXT(ctx);
  1434.  
  1435.    if (!_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
  1436.                                          primcount, basevertex))
  1437.       return;
  1438.  
  1439.    vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
  1440.                                    basevertex);
  1441. }
  1442.  
  1443. static void
  1444. vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
  1445.                             struct gl_transform_feedback_object *obj,
  1446.                             GLuint stream, GLuint numInstances)
  1447. {
  1448.    struct vbo_context *vbo = vbo_context(ctx);
  1449.    struct vbo_exec_context *exec = &vbo->exec;
  1450.    struct _mesa_prim prim[2];
  1451.  
  1452.    if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj, stream,
  1453.                                              numInstances)) {
  1454.       return;
  1455.    }
  1456.  
  1457.    vbo_bind_arrays(ctx);
  1458.  
  1459.    /* init most fields to zero */
  1460.    memset(prim, 0, sizeof(prim));
  1461.    prim[0].begin = 1;
  1462.    prim[0].end = 1;
  1463.    prim[0].mode = mode;
  1464.    prim[0].num_instances = numInstances;
  1465.    prim[0].base_instance = 0;
  1466.  
  1467.    /* Maybe we should do some primitive splitting for primitive restart
  1468.     * (like in DrawArrays), but we have no way to know how many vertices
  1469.     * will be rendered. */
  1470.  
  1471.    check_buffers_are_unmapped(exec->array.inputs);
  1472.    vbo->draw_prims(ctx, prim, 1, NULL,
  1473.                    GL_TRUE, 0, 0, obj);
  1474.  
  1475.    if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
  1476.       _mesa_flush(ctx);
  1477.    }
  1478. }
  1479.  
  1480. /**
  1481.  * Like DrawArrays, but take the count from a transform feedback object.
  1482.  * \param mode  GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc.
  1483.  * \param name  the transform feedback object
  1484.  * User still has to setup of the vertex attribute info with
  1485.  * glVertexPointer, glColorPointer, etc.
  1486.  * Part of GL_ARB_transform_feedback2.
  1487.  */
  1488. static void GLAPIENTRY
  1489. vbo_exec_DrawTransformFeedback(GLenum mode, GLuint name)
  1490. {
  1491.    GET_CURRENT_CONTEXT(ctx);
  1492.    struct gl_transform_feedback_object *obj =
  1493.       _mesa_lookup_transform_feedback_object(ctx, name);
  1494.  
  1495.    if (MESA_VERBOSE & VERBOSE_DRAW)
  1496.       _mesa_debug(ctx, "glDrawTransformFeedback(%s, %d)\n",
  1497.                   _mesa_lookup_enum_by_nr(mode), name);
  1498.  
  1499.    vbo_draw_transform_feedback(ctx, mode, obj, 0, 1);
  1500. }
  1501.  
  1502. static void GLAPIENTRY
  1503. vbo_exec_DrawTransformFeedbackStream(GLenum mode, GLuint name, GLuint stream)
  1504. {
  1505.    GET_CURRENT_CONTEXT(ctx);
  1506.    struct gl_transform_feedback_object *obj =
  1507.       _mesa_lookup_transform_feedback_object(ctx, name);
  1508.  
  1509.    if (MESA_VERBOSE & VERBOSE_DRAW)
  1510.       _mesa_debug(ctx, "glDrawTransformFeedbackStream(%s, %u, %u)\n",
  1511.                   _mesa_lookup_enum_by_nr(mode), name, stream);
  1512.  
  1513.    vbo_draw_transform_feedback(ctx, mode, obj, stream, 1);
  1514. }
  1515.  
  1516. static void GLAPIENTRY
  1517. vbo_exec_DrawTransformFeedbackInstanced(GLenum mode, GLuint name,
  1518.                                         GLsizei primcount)
  1519. {
  1520.    GET_CURRENT_CONTEXT(ctx);
  1521.    struct gl_transform_feedback_object *obj =
  1522.       _mesa_lookup_transform_feedback_object(ctx, name);
  1523.  
  1524.    if (MESA_VERBOSE & VERBOSE_DRAW)
  1525.       _mesa_debug(ctx, "glDrawTransformFeedbackInstanced(%s, %d)\n",
  1526.                   _mesa_lookup_enum_by_nr(mode), name);
  1527.  
  1528.    vbo_draw_transform_feedback(ctx, mode, obj, 0, primcount);
  1529. }
  1530.  
  1531. static void GLAPIENTRY
  1532. vbo_exec_DrawTransformFeedbackStreamInstanced(GLenum mode, GLuint name,
  1533.                                               GLuint stream, GLsizei primcount)
  1534. {
  1535.    GET_CURRENT_CONTEXT(ctx);
  1536.    struct gl_transform_feedback_object *obj =
  1537.       _mesa_lookup_transform_feedback_object(ctx, name);
  1538.  
  1539.    if (MESA_VERBOSE & VERBOSE_DRAW)
  1540.       _mesa_debug(ctx, "glDrawTransformFeedbackStreamInstanced"
  1541.                   "(%s, %u, %u, %i)\n",
  1542.                   _mesa_lookup_enum_by_nr(mode), name, stream, primcount);
  1543.  
  1544.    vbo_draw_transform_feedback(ctx, mode, obj, stream, primcount);
  1545. }
  1546.  
  1547.  
  1548. /**
  1549.  * Initialize the dispatch table with the VBO functions for drawing.
  1550.  */
  1551. void
  1552. vbo_initialize_exec_dispatch(const struct gl_context *ctx,
  1553.                              struct _glapi_table *exec)
  1554. {
  1555.    SET_DrawArrays(exec, vbo_exec_DrawArrays);
  1556.    SET_DrawElements(exec, vbo_exec_DrawElements);
  1557.  
  1558.    if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
  1559.       SET_DrawRangeElements(exec, vbo_exec_DrawRangeElements);
  1560.    }
  1561.  
  1562.    SET_MultiDrawElementsEXT(exec, vbo_exec_MultiDrawElements);
  1563.  
  1564.    if (ctx->API == API_OPENGL_COMPAT) {
  1565.       SET_Rectf(exec, vbo_exec_Rectf);
  1566.       SET_EvalMesh1(exec, vbo_exec_EvalMesh1);
  1567.       SET_EvalMesh2(exec, vbo_exec_EvalMesh2);
  1568.    }
  1569.  
  1570.    if (_mesa_is_desktop_gl(ctx)) {
  1571.       SET_DrawElementsBaseVertex(exec, vbo_exec_DrawElementsBaseVertex);
  1572.       SET_DrawRangeElementsBaseVertex(exec, vbo_exec_DrawRangeElementsBaseVertex);
  1573.       SET_MultiDrawElementsBaseVertex(exec, vbo_exec_MultiDrawElementsBaseVertex);
  1574.       SET_DrawArraysInstancedBaseInstance(exec, vbo_exec_DrawArraysInstancedBaseInstance);
  1575.       SET_DrawElementsInstancedBaseInstance(exec, vbo_exec_DrawElementsInstancedBaseInstance);
  1576.       SET_DrawElementsInstancedBaseVertex(exec, vbo_exec_DrawElementsInstancedBaseVertex);
  1577.       SET_DrawElementsInstancedBaseVertexBaseInstance(exec, vbo_exec_DrawElementsInstancedBaseVertexBaseInstance);
  1578.    }
  1579.  
  1580.    if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
  1581.       SET_DrawArraysInstancedARB(exec, vbo_exec_DrawArraysInstanced);
  1582.       SET_DrawElementsInstancedARB(exec, vbo_exec_DrawElementsInstanced);
  1583.    }
  1584.  
  1585.    if (_mesa_is_desktop_gl(ctx)) {
  1586.       SET_DrawTransformFeedback(exec, vbo_exec_DrawTransformFeedback);
  1587.       SET_DrawTransformFeedbackStream(exec, vbo_exec_DrawTransformFeedbackStream);
  1588.       SET_DrawTransformFeedbackInstanced(exec, vbo_exec_DrawTransformFeedbackInstanced);
  1589.       SET_DrawTransformFeedbackStreamInstanced(exec, vbo_exec_DrawTransformFeedbackStreamInstanced);
  1590.    }
  1591. }
  1592.  
  1593.  
  1594.  
  1595. /**
  1596.  * The following functions are only used for OpenGL ES 1/2 support.
  1597.  * And some aren't even supported (yet) in ES 1/2.
  1598.  */
  1599.  
  1600.  
  1601. void GLAPIENTRY
  1602. _mesa_DrawArrays(GLenum mode, GLint first, GLsizei count)
  1603. {
  1604.    vbo_exec_DrawArrays(mode, first, count);
  1605. }
  1606.  
  1607.  
  1608. void GLAPIENTRY
  1609. _mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
  1610.                    const GLvoid *indices)
  1611. {
  1612.    vbo_exec_DrawElements(mode, count, type, indices);
  1613. }
  1614.  
  1615.  
  1616. void GLAPIENTRY
  1617. _mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
  1618.                              const GLvoid *indices, GLint basevertex)
  1619. {
  1620.    vbo_exec_DrawElementsBaseVertex(mode, count, type, indices, basevertex);
  1621. }
  1622.  
  1623.  
  1624. void GLAPIENTRY
  1625. _mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
  1626.                         GLenum type, const GLvoid *indices)
  1627. {
  1628.    vbo_exec_DrawRangeElements(mode, start, end, count, type, indices);
  1629. }
  1630.  
  1631.  
  1632. void GLAPIENTRY
  1633. _mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
  1634.                                   GLsizei count, GLenum type,
  1635.                                   const GLvoid *indices, GLint basevertex)
  1636. {
  1637.    vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
  1638.                                         indices, basevertex);
  1639. }
  1640.  
  1641.  
  1642. void GLAPIENTRY
  1643. _mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
  1644.                            const GLvoid **indices, GLsizei primcount)
  1645. {
  1646.    vbo_exec_MultiDrawElements(mode, count, type, indices, primcount);
  1647. }
  1648.  
  1649.  
  1650. void GLAPIENTRY
  1651. _mesa_MultiDrawElementsBaseVertex(GLenum mode,
  1652.                                   const GLsizei *count, GLenum type,
  1653.                                   const GLvoid **indices, GLsizei primcount,
  1654.                                   const GLint *basevertex)
  1655. {
  1656.    vbo_exec_MultiDrawElementsBaseVertex(mode, count, type, indices,
  1657.                                         primcount, basevertex);
  1658. }
  1659.  
  1660. void GLAPIENTRY
  1661. _mesa_DrawTransformFeedback(GLenum mode, GLuint name)
  1662. {
  1663.    vbo_exec_DrawTransformFeedback(mode, name);
  1664. }
  1665.