Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | 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/varray.h"
  34. #include "main/bufferobj.h"
  35. #include "main/enums.h"
  36. #include "main/macros.h"
  37.  
  38. #include "vbo_context.h"
  39.  
  40.  
  41. /**
  42.  * Compute min and max elements by scanning the index buffer for
  43.  * glDraw[Range]Elements() calls.
  44.  * If primitive restart is enabled, we need to ignore restart
  45.  * indexes when computing min/max.
  46.  */
  47. void
  48. vbo_get_minmax_index(struct gl_context *ctx,
  49.                      const struct _mesa_prim *prim,
  50.                      const struct _mesa_index_buffer *ib,
  51.                      GLuint *min_index, GLuint *max_index)
  52. {
  53.    const GLboolean restart = ctx->Array.PrimitiveRestart;
  54.    const GLuint restartIndex = ctx->Array.RestartIndex;
  55.    const GLuint count = prim->count;
  56.    const void *indices;
  57.    GLuint i;
  58.  
  59.    if (_mesa_is_bufferobj(ib->obj)) {
  60.       const GLvoid *map =
  61.          ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB,
  62.                                GL_READ_ONLY, ib->obj);
  63.       indices = ADD_POINTERS(map, ib->ptr);
  64.    } else {
  65.       indices = ib->ptr;
  66.    }
  67.  
  68.    switch (ib->type) {
  69.    case GL_UNSIGNED_INT: {
  70.       const GLuint *ui_indices = (const GLuint *)indices;
  71.       GLuint max_ui = 0;
  72.       GLuint min_ui = ~0U;
  73.       if (restart) {
  74.          for (i = 0; i < count; i++) {
  75.             if (ui_indices[i] != restartIndex) {
  76.                if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
  77.                if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
  78.             }
  79.          }
  80.       }
  81.       else {
  82.          for (i = 0; i < count; i++) {
  83.             if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
  84.             if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
  85.          }
  86.       }
  87.       *min_index = min_ui;
  88.       *max_index = max_ui;
  89.       break;
  90.    }
  91.    case GL_UNSIGNED_SHORT: {
  92.       const GLushort *us_indices = (const GLushort *)indices;
  93.       GLuint max_us = 0;
  94.       GLuint min_us = ~0U;
  95.       if (restart) {
  96.          for (i = 0; i < count; i++) {
  97.             if (us_indices[i] != restartIndex) {
  98.                if (us_indices[i] > max_us) max_us = us_indices[i];
  99.                if (us_indices[i] < min_us) min_us = us_indices[i];
  100.             }
  101.          }
  102.       }
  103.       else {
  104.          for (i = 0; i < count; i++) {
  105.             if (us_indices[i] > max_us) max_us = us_indices[i];
  106.             if (us_indices[i] < min_us) min_us = us_indices[i];
  107.          }
  108.       }
  109.       *min_index = min_us;
  110.       *max_index = max_us;
  111.       break;
  112.    }
  113.    case GL_UNSIGNED_BYTE: {
  114.       const GLubyte *ub_indices = (const GLubyte *)indices;
  115.       GLuint max_ub = 0;
  116.       GLuint min_ub = ~0U;
  117.       if (restart) {
  118.          for (i = 0; i < count; i++) {
  119.             if (ub_indices[i] != restartIndex) {
  120.                if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
  121.                if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
  122.             }
  123.          }
  124.       }
  125.       else {
  126.          for (i = 0; i < count; i++) {
  127.             if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
  128.             if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
  129.          }
  130.       }
  131.       *min_index = min_ub;
  132.       *max_index = max_ub;
  133.       break;
  134.    }
  135.    default:
  136.       assert(0);
  137.       break;
  138.    }
  139.  
  140.    if (_mesa_is_bufferobj(ib->obj)) {
  141.       ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, ib->obj);
  142.    }
  143. }
  144.  
  145.  
  146. /**
  147.  * Check that element 'j' of the array has reasonable data.
  148.  * Map VBO if needed.
  149.  * For debugging purposes; not normally used.
  150.  */
  151. static void
  152. check_array_data(struct gl_context *ctx, struct gl_client_array *array,
  153.                  GLuint attrib, GLuint j)
  154. {
  155.    if (array->Enabled) {
  156.       const void *data = array->Ptr;
  157.       if (_mesa_is_bufferobj(array->BufferObj)) {
  158.          if (!array->BufferObj->Pointer) {
  159.             /* need to map now */
  160.             array->BufferObj->Pointer =
  161.                ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER_ARB,
  162.                                      GL_READ_ONLY, array->BufferObj);
  163.          }
  164.          data = ADD_POINTERS(data, array->BufferObj->Pointer);
  165.       }
  166.       switch (array->Type) {
  167.       case GL_FLOAT:
  168.          {
  169.             GLfloat *f = (GLfloat *) ((GLubyte *) data + array->StrideB * j);
  170.             GLint k;
  171.             for (k = 0; k < array->Size; k++) {
  172.                if (IS_INF_OR_NAN(f[k]) ||
  173.                    f[k] >= 1.0e20 || f[k] <= -1.0e10) {
  174.                   printf("Bad array data:\n");
  175.                   printf("  Element[%u].%u = %f\n", j, k, f[k]);
  176.                   printf("  Array %u at %p\n", attrib, (void* ) array);
  177.                   printf("  Type 0x%x, Size %d, Stride %d\n",
  178.                          array->Type, array->Size, array->Stride);
  179.                   printf("  Address/offset %p in Buffer Object %u\n",
  180.                          array->Ptr, array->BufferObj->Name);
  181.                   f[k] = 1.0; /* XXX replace the bad value! */
  182.                }
  183.                /*assert(!IS_INF_OR_NAN(f[k]));*/
  184.             }
  185.          }
  186.          break;
  187.       default:
  188.          ;
  189.       }
  190.    }
  191. }
  192.  
  193.  
  194. /**
  195.  * Unmap the buffer object referenced by given array, if mapped.
  196.  */
  197. static void
  198. unmap_array_buffer(struct gl_context *ctx, struct gl_client_array *array)
  199. {
  200.    if (array->Enabled &&
  201.        _mesa_is_bufferobj(array->BufferObj) &&
  202.        _mesa_bufferobj_mapped(array->BufferObj)) {
  203.       ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, array->BufferObj);
  204.    }
  205. }
  206.  
  207.  
  208. /**
  209.  * Examine the array's data for NaNs, etc.
  210.  * For debug purposes; not normally used.
  211.  */
  212. static void
  213. check_draw_elements_data(struct gl_context *ctx, GLsizei count, GLenum elemType,
  214.                          const void *elements, GLint basevertex)
  215. {
  216.    struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
  217.    const void *elemMap;
  218.    GLint i, k;
  219.  
  220.    if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) {
  221.       elemMap = ctx->Driver.MapBuffer(ctx,
  222.                                       GL_ELEMENT_ARRAY_BUFFER_ARB,
  223.                                       GL_READ_ONLY,
  224.                                       ctx->Array.ElementArrayBufferObj);
  225.       elements = ADD_POINTERS(elements, elemMap);
  226.    }
  227.  
  228.    for (i = 0; i < count; i++) {
  229.       GLuint j;
  230.  
  231.       /* j = element[i] */
  232.       switch (elemType) {
  233.       case GL_UNSIGNED_BYTE:
  234.          j = ((const GLubyte *) elements)[i];
  235.          break;
  236.       case GL_UNSIGNED_SHORT:
  237.          j = ((const GLushort *) elements)[i];
  238.          break;
  239.       case GL_UNSIGNED_INT:
  240.          j = ((const GLuint *) elements)[i];
  241.          break;
  242.       default:
  243.          assert(0);
  244.       }
  245.  
  246.       /* check element j of each enabled array */
  247.       check_array_data(ctx, &arrayObj->Vertex, VERT_ATTRIB_POS, j);
  248.       check_array_data(ctx, &arrayObj->Normal, VERT_ATTRIB_NORMAL, j);
  249.       check_array_data(ctx, &arrayObj->Color, VERT_ATTRIB_COLOR0, j);
  250.       check_array_data(ctx, &arrayObj->SecondaryColor, VERT_ATTRIB_COLOR1, j);
  251.       for (k = 0; k < Elements(arrayObj->TexCoord); k++) {
  252.          check_array_data(ctx, &arrayObj->TexCoord[k], VERT_ATTRIB_TEX0 + k, j);
  253.       }
  254.       for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
  255.          check_array_data(ctx, &arrayObj->VertexAttrib[k],
  256.                           VERT_ATTRIB_GENERIC0 + k, j);
  257.       }
  258.    }
  259.  
  260.    if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) {
  261.       ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB,
  262.                               ctx->Array.ElementArrayBufferObj);
  263.    }
  264.  
  265.    unmap_array_buffer(ctx, &arrayObj->Vertex);
  266.    unmap_array_buffer(ctx, &arrayObj->Normal);
  267.    unmap_array_buffer(ctx, &arrayObj->Color);
  268.    for (k = 0; k < Elements(arrayObj->TexCoord); k++) {
  269.       unmap_array_buffer(ctx, &arrayObj->TexCoord[k]);
  270.    }
  271.    for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
  272.       unmap_array_buffer(ctx, &arrayObj->VertexAttrib[k]);
  273.    }
  274. }
  275.  
  276.  
  277. /**
  278.  * Check array data, looking for NaNs, etc.
  279.  */
  280. static void
  281. check_draw_arrays_data(struct gl_context *ctx, GLint start, GLsizei count)
  282. {
  283.    /* TO DO */
  284. }
  285.  
  286.  
  287. /**
  288.  * Print info/data for glDrawArrays(), for debugging.
  289.  */
  290. static void
  291. print_draw_arrays(struct gl_context *ctx,
  292.                   GLenum mode, GLint start, GLsizei count)
  293. {
  294.    struct vbo_context *vbo = vbo_context(ctx);
  295.    struct vbo_exec_context *exec = &vbo->exec;
  296.    int i;
  297.  
  298.    printf("vbo_exec_DrawArrays(mode 0x%x, start %d, count %d):\n",
  299.           mode, start, count);
  300.  
  301.    for (i = 0; i < 32; i++) {
  302.       GLuint bufName = exec->array.inputs[i]->BufferObj->Name;
  303.       GLint stride = exec->array.inputs[i]->Stride;
  304.       printf("attr %2d: size %d stride %d  enabled %d  "
  305.              "ptr %p  Bufobj %u\n",
  306.              i,
  307.              exec->array.inputs[i]->Size,
  308.              stride,
  309.              /*exec->array.inputs[i]->Enabled,*/
  310.              exec->array.legacy_array[i]->Enabled,
  311.              exec->array.inputs[i]->Ptr,
  312.              bufName);
  313.  
  314.       if (bufName) {
  315.          struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, bufName);
  316.          GLubyte *p = ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER_ARB,
  317.                                             GL_READ_ONLY_ARB, buf);
  318.          int offset = (int) (GLintptr) exec->array.inputs[i]->Ptr;
  319.          float *f = (float *) (p + offset);
  320.          int *k = (int *) f;
  321.          int i;
  322.          int n = (count * stride) / 4;
  323.          if (n > 32)
  324.             n = 32;
  325.          printf("  Data at offset %d:\n", offset);
  326.          for (i = 0; i < n; i++) {
  327.             printf("    float[%d] = 0x%08x %f\n", i, k[i], f[i]);
  328.          }
  329.          ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, buf);
  330.       }
  331.    }
  332. }
  333.  
  334.  
  335. /**
  336.  * Bind the VBO executor to the current vertex array object prior
  337.  * to drawing.
  338.  *
  339.  * Just translate the arrayobj into a sane layout.
  340.  */
  341. static void
  342. bind_array_obj(struct gl_context *ctx)
  343. {
  344.    struct vbo_context *vbo = vbo_context(ctx);
  345.    struct vbo_exec_context *exec = &vbo->exec;
  346.    struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
  347.    GLuint i;
  348.  
  349.    /* TODO: Fix the ArrayObj struct to keep legacy arrays in an array
  350.     * rather than as individual named arrays.  Then this function can
  351.     * go away.
  352.     */
  353.    exec->array.legacy_array[VERT_ATTRIB_POS] = &arrayObj->Vertex;
  354.    exec->array.legacy_array[VERT_ATTRIB_WEIGHT] = &arrayObj->Weight;
  355.    exec->array.legacy_array[VERT_ATTRIB_NORMAL] = &arrayObj->Normal;
  356.    exec->array.legacy_array[VERT_ATTRIB_COLOR0] = &arrayObj->Color;
  357.    exec->array.legacy_array[VERT_ATTRIB_COLOR1] = &arrayObj->SecondaryColor;
  358.    exec->array.legacy_array[VERT_ATTRIB_FOG] = &arrayObj->FogCoord;
  359.    exec->array.legacy_array[VERT_ATTRIB_COLOR_INDEX] = &arrayObj->Index;
  360.    if (arrayObj->PointSize.Enabled) {
  361.       /* this aliases COLOR_INDEX */
  362.       exec->array.legacy_array[VERT_ATTRIB_POINT_SIZE] = &arrayObj->PointSize;
  363.    }
  364.    exec->array.legacy_array[VERT_ATTRIB_EDGEFLAG] = &arrayObj->EdgeFlag;
  365.  
  366.    for (i = 0; i < Elements(arrayObj->TexCoord); i++)
  367.       exec->array.legacy_array[VERT_ATTRIB_TEX0 + i] = &arrayObj->TexCoord[i];
  368.  
  369.    for (i = 0; i < Elements(arrayObj->VertexAttrib); i++) {
  370.       assert(i < Elements(exec->array.generic_array));
  371.       exec->array.generic_array[i] = &arrayObj->VertexAttrib[i];
  372.    }
  373.    
  374.    exec->array.array_obj = arrayObj->Name;
  375. }
  376.  
  377.  
  378. /**
  379.  * Set the vbo->exec->inputs[] pointers to point to the enabled
  380.  * vertex arrays.  This depends on the current vertex program/shader
  381.  * being executed because of whether or not generic vertex arrays
  382.  * alias the conventional vertex arrays.
  383.  * For arrays that aren't enabled, we set the input[attrib] pointer
  384.  * to point at a zero-stride current value "array".
  385.  */
  386. static void
  387. recalculate_input_bindings(struct gl_context *ctx)
  388. {
  389.    struct vbo_context *vbo = vbo_context(ctx);
  390.    struct vbo_exec_context *exec = &vbo->exec;
  391.    const struct gl_client_array **inputs = &exec->array.inputs[0];
  392.    GLbitfield const_inputs = 0x0;
  393.    GLuint i;
  394.  
  395.    exec->array.program_mode = get_program_mode(ctx);
  396.    exec->array.enabled_flags = ctx->Array.ArrayObj->_Enabled;
  397.  
  398.    switch (exec->array.program_mode) {
  399.    case VP_NONE:
  400.       /* When no vertex program is active (or the vertex program is generated
  401.        * from fixed-function state).  We put the material values into the
  402.        * generic slots.  This is the only situation where material values
  403.        * are available as per-vertex attributes.
  404.        */
  405.       for (i = 0; i <= VERT_ATTRIB_TEX7; i++) {
  406.          if (exec->array.legacy_array[i]->Enabled)
  407.             inputs[i] = exec->array.legacy_array[i];
  408.          else {
  409.             inputs[i] = &vbo->legacy_currval[i];
  410.             const_inputs |= 1 << i;
  411.          }
  412.       }
  413.  
  414.       for (i = 0; i < MAT_ATTRIB_MAX; i++) {
  415.          inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->mat_currval[i];
  416.          const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
  417.       }
  418.  
  419.       /* Could use just about anything, just to fill in the empty
  420.        * slots:
  421.        */
  422.       for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_MAX - VERT_ATTRIB_GENERIC0; i++) {
  423.          inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i];
  424.          const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
  425.       }
  426.       break;
  427.  
  428.    case VP_NV:
  429.       /* NV_vertex_program - attribute arrays alias and override
  430.        * conventional, legacy arrays.  No materials, and the generic
  431.        * slots are vacant.
  432.        */
  433.       for (i = 0; i <= VERT_ATTRIB_TEX7; i++) {
  434.          if (exec->array.generic_array[i]->Enabled)
  435.             inputs[i] = exec->array.generic_array[i];
  436.          else if (exec->array.legacy_array[i]->Enabled)
  437.             inputs[i] = exec->array.legacy_array[i];
  438.          else {
  439.             inputs[i] = &vbo->legacy_currval[i];
  440.             const_inputs |= 1 << i;
  441.          }
  442.       }
  443.  
  444.       /* Could use just about anything, just to fill in the empty
  445.        * slots:
  446.        */
  447.       for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++) {
  448.          inputs[i] = &vbo->generic_currval[i - VERT_ATTRIB_GENERIC0];
  449.          const_inputs |= 1 << i;
  450.       }
  451.       break;
  452.  
  453.    case VP_ARB:
  454.       /* GL_ARB_vertex_program or GLSL vertex shader - Only the generic[0]
  455.        * attribute array aliases and overrides the legacy position array.  
  456.        *
  457.        * Otherwise, legacy attributes available in the legacy slots,
  458.        * generic attributes in the generic slots and materials are not
  459.        * available as per-vertex attributes.
  460.        */
  461.       if (exec->array.generic_array[0]->Enabled)
  462.          inputs[0] = exec->array.generic_array[0];
  463.       else if (exec->array.legacy_array[0]->Enabled)
  464.          inputs[0] = exec->array.legacy_array[0];
  465.       else {
  466.          inputs[0] = &vbo->legacy_currval[0];
  467.          const_inputs |= 1 << 0;
  468.       }
  469.  
  470.       for (i = 1; i <= VERT_ATTRIB_TEX7; i++) {
  471.          if (exec->array.legacy_array[i]->Enabled)
  472.             inputs[i] = exec->array.legacy_array[i];
  473.          else {
  474.             inputs[i] = &vbo->legacy_currval[i];
  475.             const_inputs |= 1 << i;
  476.          }
  477.       }
  478.  
  479.       for (i = 0; i < MAX_VERTEX_GENERIC_ATTRIBS; i++) {
  480.          if (exec->array.generic_array[i]->Enabled)
  481.             inputs[VERT_ATTRIB_GENERIC0 + i] = exec->array.generic_array[i];
  482.          else {
  483.             inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i];
  484.             const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
  485.          }
  486.  
  487.       }
  488.       break;
  489.    }
  490.  
  491.    _mesa_set_varying_vp_inputs( ctx, ~const_inputs );
  492. }
  493.  
  494.  
  495. /**
  496.  * Examine the enabled vertex arrays to set the exec->array.inputs[] values.
  497.  * These will point to the arrays to actually use for drawing.  Some will
  498.  * be user-provided arrays, other will be zero-stride const-valued arrays.
  499.  * Note that this might set the _NEW_ARRAY dirty flag so state validation
  500.  * must be done after this call.
  501.  */
  502. static void
  503. bind_arrays(struct gl_context *ctx)
  504. {
  505.    bind_array_obj(ctx);
  506.    recalculate_input_bindings(ctx);
  507. }
  508.  
  509.  
  510. /**
  511.  * Helper function called by the other DrawArrays() functions below.
  512.  * This is where we handle primitive restart for drawing non-indexed
  513.  * arrays.  If primitive restart is enabled, it typically means
  514.  * splitting one DrawArrays() into two.
  515.  */
  516. static void
  517. vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
  518.                 GLsizei count, GLuint numInstances)
  519. {
  520.    struct vbo_context *vbo = vbo_context(ctx);
  521.    struct vbo_exec_context *exec = &vbo->exec;
  522.    struct _mesa_prim prim[2];
  523.  
  524.    bind_arrays(ctx);
  525.  
  526.    /* Again... because we may have changed the bitmask of per-vertex varying
  527.     * attributes.  If we regenerate the fixed-function vertex program now
  528.     * we may be able to prune down the number of vertex attributes which we
  529.     * need in the shader.
  530.     */
  531.    if (ctx->NewState)
  532.       _mesa_update_state(ctx);
  533.  
  534.    prim[0].begin = 1;
  535.    prim[0].end = 1;
  536.    prim[0].weak = 0;
  537.    prim[0].pad = 0;
  538.    prim[0].mode = mode;
  539.    prim[0].start = 0; /* filled in below */
  540.    prim[0].count = 0; /* filled in below */
  541.    prim[0].indexed = 0;
  542.    prim[0].basevertex = 0;
  543.    prim[0].num_instances = numInstances;
  544.  
  545.    /* Implement the primitive restart index */
  546.    if (ctx->Array.PrimitiveRestart && ctx->Array.RestartIndex < count) {
  547.       GLuint primCount = 0;
  548.  
  549.       if (ctx->Array.RestartIndex == start) {
  550.          /* special case: RestartIndex at beginning */
  551.          if (count > 1) {
  552.             prim[0].start = start + 1;
  553.             prim[0].count = count - 1;
  554.             primCount = 1;
  555.          }
  556.       }
  557.       else if (ctx->Array.RestartIndex == start + count - 1) {
  558.          /* special case: RestartIndex at end */
  559.          if (count > 1) {
  560.             prim[0].start = start;
  561.             prim[0].count = count - 1;
  562.             primCount = 1;
  563.          }
  564.       }
  565.       else {
  566.          /* general case: RestartIndex in middle, split into two prims */
  567.          prim[0].start = start;
  568.          prim[0].count = ctx->Array.RestartIndex - start;
  569.  
  570.          prim[1] = prim[0];
  571.          prim[1].start = ctx->Array.RestartIndex + 1;
  572.          prim[1].count = count - prim[1].start;
  573.  
  574.          primCount = 2;
  575.       }
  576.  
  577.       if (primCount > 0) {
  578.          /* draw one or two prims */
  579.          vbo->draw_prims(ctx, exec->array.inputs, prim, primCount, NULL,
  580.                          GL_TRUE, start, start + count - 1);
  581.       }
  582.    }
  583.    else {
  584.       /* no prim restart */
  585.       prim[0].start = start;
  586.       prim[0].count = count;
  587.  
  588.       vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL,
  589.                       GL_TRUE, start, start + count - 1);
  590.    }
  591. }
  592.  
  593.  
  594.  
  595. /**
  596.  * Called from glDrawArrays when in immediate mode (not display list mode).
  597.  */
  598. static void GLAPIENTRY
  599. vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
  600. {
  601.    GET_CURRENT_CONTEXT(ctx);
  602.  
  603.    if (MESA_VERBOSE & VERBOSE_DRAW)
  604.       _mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n",
  605.                   _mesa_lookup_enum_by_nr(mode), start, count);
  606.  
  607.    if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
  608.       return;
  609.  
  610.    FLUSH_CURRENT( ctx, 0 );
  611.  
  612.    if (!_mesa_valid_to_render(ctx, "glDrawArrays")) {
  613.       return;
  614.    }
  615.  
  616.    if (0)
  617.       check_draw_arrays_data(ctx, start, count);
  618.  
  619.    vbo_draw_arrays(ctx, mode, start, count, 1);
  620.  
  621.    if (0)
  622.       print_draw_arrays(ctx, mode, start, count);
  623. }
  624.  
  625.  
  626. /**
  627.  * Called from glDrawArraysInstanced when in immediate mode (not
  628.  * display list mode).
  629.  */
  630. static void GLAPIENTRY
  631. vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count,
  632.                              GLsizei primcount)
  633. {
  634.    GET_CURRENT_CONTEXT(ctx);
  635.  
  636.    if (MESA_VERBOSE & VERBOSE_DRAW)
  637.       _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n",
  638.                   _mesa_lookup_enum_by_nr(mode), start, count, primcount);
  639.  
  640.    if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, primcount))
  641.       return;
  642.  
  643.    FLUSH_CURRENT( ctx, 0 );
  644.  
  645.    if (!_mesa_valid_to_render(ctx, "glDrawArraysInstanced")) {
  646.       return;
  647.    }
  648.  
  649.    if (0)
  650.       check_draw_arrays_data(ctx, start, count);
  651.  
  652.    vbo_draw_arrays(ctx, mode, start, count, primcount);
  653.  
  654.    if (0)
  655.       print_draw_arrays(ctx, mode, start, count);
  656. }
  657.  
  658.  
  659. /**
  660.  * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
  661.  * For debugging.
  662.  */
  663. static void
  664. dump_element_buffer(struct gl_context *ctx, GLenum type)
  665. {
  666.    const GLvoid *map = ctx->Driver.MapBuffer(ctx,
  667.                                              GL_ELEMENT_ARRAY_BUFFER_ARB,
  668.                                              GL_READ_ONLY,
  669.                                              ctx->Array.ElementArrayBufferObj);
  670.    switch (type) {
  671.    case GL_UNSIGNED_BYTE:
  672.       {
  673.          const GLubyte *us = (const GLubyte *) map;
  674.          GLint i;
  675.          for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size; i++) {
  676.             printf("%02x ", us[i]);
  677.             if (i % 32 == 31)
  678.                printf("\n");
  679.          }
  680.          printf("\n");
  681.       }
  682.       break;
  683.    case GL_UNSIGNED_SHORT:
  684.       {
  685.          const GLushort *us = (const GLushort *) map;
  686.          GLint i;
  687.          for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size / 2; i++) {
  688.             printf("%04x ", us[i]);
  689.             if (i % 16 == 15)
  690.                printf("\n");
  691.          }
  692.          printf("\n");
  693.       }
  694.       break;
  695.    case GL_UNSIGNED_INT:
  696.       {
  697.          const GLuint *us = (const GLuint *) map;
  698.          GLint i;
  699.          for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size / 4; i++) {
  700.             printf("%08x ", us[i]);
  701.             if (i % 8 == 7)
  702.                printf("\n");
  703.          }
  704.          printf("\n");
  705.       }
  706.       break;
  707.    default:
  708.       ;
  709.    }
  710.  
  711.    ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB,
  712.                            ctx->Array.ElementArrayBufferObj);
  713. }
  714.  
  715.  
  716. /**
  717.  * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements.
  718.  * Do the rendering for a glDrawElements or glDrawRangeElements call after
  719.  * we've validated buffer bounds, etc.
  720.  */
  721. static void
  722. vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
  723.                                 GLboolean index_bounds_valid,
  724.                                 GLuint start, GLuint end,
  725.                                 GLsizei count, GLenum type,
  726.                                 const GLvoid *indices,
  727.                                 GLint basevertex, GLint primcount)
  728. {
  729.    struct vbo_context *vbo = vbo_context(ctx);
  730.    struct vbo_exec_context *exec = &vbo->exec;
  731.    struct _mesa_index_buffer ib;
  732.    struct _mesa_prim prim[1];
  733.  
  734.    FLUSH_CURRENT( ctx, 0 );
  735.  
  736.    if (!_mesa_valid_to_render(ctx, "glDraw[Range]Elements")) {
  737.       return;
  738.    }
  739.  
  740.    bind_arrays( ctx );
  741.  
  742.    /* check for dirty state again */
  743.    if (ctx->NewState)
  744.       _mesa_update_state( ctx );
  745.  
  746.    ib.count = count;
  747.    ib.type = type;
  748.    ib.obj = ctx->Array.ElementArrayBufferObj;
  749.    ib.ptr = indices;
  750.  
  751.    prim[0].begin = 1;
  752.    prim[0].end = 1;
  753.    prim[0].weak = 0;
  754.    prim[0].pad = 0;
  755.    prim[0].mode = mode;
  756.    prim[0].start = 0;
  757.    prim[0].count = count;
  758.    prim[0].indexed = 1;
  759.    prim[0].basevertex = basevertex;
  760.    prim[0].num_instances = primcount;
  761.  
  762.    /* Need to give special consideration to rendering a range of
  763.     * indices starting somewhere above zero.  Typically the
  764.     * application is issuing multiple DrawRangeElements() to draw
  765.     * successive primitives layed out linearly in the vertex arrays.
  766.     * Unless the vertex arrays are all in a VBO (or locked as with
  767.     * CVA), the OpenGL semantics imply that we need to re-read or
  768.     * re-upload the vertex data on each draw call.  
  769.     *
  770.     * In the case of hardware tnl, we want to avoid starting the
  771.     * upload at zero, as it will mean every draw call uploads an
  772.     * increasing amount of not-used vertex data.  Worse - in the
  773.     * software tnl module, all those vertices might be transformed and
  774.     * lit but never rendered.
  775.     *
  776.     * If we just upload or transform the vertices in start..end,
  777.     * however, the indices will be incorrect.
  778.     *
  779.     * At this level, we don't know exactly what the requirements of
  780.     * the backend are going to be, though it will likely boil down to
  781.     * either:
  782.     *
  783.     * 1) Do nothing, everything is in a VBO and is processed once
  784.     *       only.
  785.     *
  786.     * 2) Adjust the indices and vertex arrays so that start becomes
  787.     *    zero.
  788.     *
  789.     * Rather than doing anything here, I'll provide a helper function
  790.     * for the latter case elsewhere.
  791.     */
  792.  
  793.    vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib,
  794.                     index_bounds_valid, start, end );
  795. }
  796.  
  797.  
  798. /**
  799.  * Called by glDrawRangeElementsBaseVertex() in immediate mode.
  800.  */
  801. static void GLAPIENTRY
  802. vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
  803.                                      GLuint start, GLuint end,
  804.                                      GLsizei count, GLenum type,
  805.                                      const GLvoid *indices,
  806.                                      GLint basevertex)
  807. {
  808.    static GLuint warnCount = 0;
  809.    GET_CURRENT_CONTEXT(ctx);
  810.  
  811.    if (MESA_VERBOSE & VERBOSE_DRAW)
  812.       _mesa_debug(ctx,
  813.                 "glDrawRangeElementsBaseVertex(%s, %u, %u, %d, %s, %p, %d)\n",
  814.                 _mesa_lookup_enum_by_nr(mode), start, end, count,
  815.                 _mesa_lookup_enum_by_nr(type), indices, basevertex);
  816.  
  817.    if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
  818.                                           type, indices, basevertex ))
  819.       return;
  820.  
  821.    /* NOTE: It's important that 'end' is a reasonable value.
  822.     * in _tnl_draw_prims(), we use end to determine how many vertices
  823.     * to transform.  If it's too large, we can unnecessarily split prims
  824.     * or we can read/write out of memory in several different places!
  825.     */
  826.  
  827.    /* Catch/fix some potential user errors */
  828.    if (type == GL_UNSIGNED_BYTE) {
  829.       start = MIN2(start, 0xff);
  830.       end = MIN2(end, 0xff);
  831.    }
  832.    else if (type == GL_UNSIGNED_SHORT) {
  833.       start = MIN2(start, 0xffff);
  834.       end = MIN2(end, 0xffff);
  835.    }
  836.  
  837.    if (end >= ctx->Array.ArrayObj->_MaxElement) {
  838.       /* the max element is out of bounds of one or more enabled arrays */
  839.       warnCount++;
  840.  
  841.       if (warnCount < 10) {
  842.          _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, count %d, "
  843.                        "type 0x%x, indices=%p)\n"
  844.                        "\tend is out of bounds (max=%u)  "
  845.                        "Element Buffer %u (size %d)\n"
  846.                        "\tThis should probably be fixed in the application.",
  847.                        start, end, count, type, indices,
  848.                        ctx->Array.ArrayObj->_MaxElement - 1,
  849.                        ctx->Array.ElementArrayBufferObj->Name,
  850.                        (int) ctx->Array.ElementArrayBufferObj->Size);
  851.       }
  852.  
  853.       if (0)
  854.          dump_element_buffer(ctx, type);
  855.  
  856.       if (0)
  857.          _mesa_print_arrays(ctx);
  858.  
  859. #ifdef DEBUG
  860.       /* 'end' was out of bounds, but now let's check the actual array
  861.        * indexes to see if any of them are out of bounds.
  862.        */
  863.       {
  864.          GLuint max = _mesa_max_buffer_index(ctx, count, type, indices,
  865.                                              ctx->Array.ElementArrayBufferObj);
  866.          if (max >= ctx->Array.ArrayObj->_MaxElement) {
  867.             if (warnCount < 10) {
  868.                _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, "
  869.                              "count %d, type 0x%x, indices=%p)\n"
  870.                              "\tindex=%u is out of bounds (max=%u)  "
  871.                              "Element Buffer %u (size %d)\n"
  872.                              "\tSkipping the glDrawRangeElements() call",
  873.                              start, end, count, type, indices, max,
  874.                              ctx->Array.ArrayObj->_MaxElement - 1,
  875.                              ctx->Array.ElementArrayBufferObj->Name,
  876.                              (int) ctx->Array.ElementArrayBufferObj->Size);
  877.             }
  878.          }
  879.          /* XXX we could also find the min index and compare to 'start'
  880.           * to see if start is correct.  But it's more likely to get the
  881.           * upper bound wrong.
  882.           */
  883.       }
  884. #endif
  885.  
  886.       /* Set 'end' to the max possible legal value */
  887.       assert(ctx->Array.ArrayObj->_MaxElement >= 1);
  888.       end = ctx->Array.ArrayObj->_MaxElement - 1;
  889.    }
  890.    else if (0) {
  891.       printf("glDraw[Range]Elements{,BaseVertex}"
  892.              "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
  893.              "base %d\n",
  894.              start, end, type, count,
  895.              ctx->Array.ElementArrayBufferObj->Name,
  896.              basevertex);
  897.    }
  898.  
  899. #if 0
  900.    check_draw_elements_data(ctx, count, type, indices);
  901. #else
  902.    (void) check_draw_elements_data;
  903. #endif
  904.  
  905.    vbo_validated_drawrangeelements(ctx, mode, GL_TRUE, start, end,
  906.                                    count, type, indices, basevertex, 1);
  907. }
  908.  
  909.  
  910. /**
  911.  * Called by glDrawRangeElements() in immediate mode.
  912.  */
  913. static void GLAPIENTRY
  914. vbo_exec_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
  915.                            GLsizei count, GLenum type, const GLvoid *indices)
  916. {
  917.    GET_CURRENT_CONTEXT(ctx);
  918.  
  919.    if (MESA_VERBOSE & VERBOSE_DRAW)
  920.       _mesa_debug(ctx,
  921.                   "glDrawRangeElements(%s, %u, %u, %d, %s, %p)\n",
  922.                   _mesa_lookup_enum_by_nr(mode), start, end, count,
  923.                   _mesa_lookup_enum_by_nr(type), indices);
  924.  
  925.    vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
  926.                                         indices, 0);
  927. }
  928.  
  929.  
  930. /**
  931.  * Called by glDrawElements() in immediate mode.
  932.  */
  933. static void GLAPIENTRY
  934. vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
  935.                       const GLvoid *indices)
  936. {
  937.    GET_CURRENT_CONTEXT(ctx);
  938.  
  939.    if (MESA_VERBOSE & VERBOSE_DRAW)
  940.       _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n",
  941.                   _mesa_lookup_enum_by_nr(mode), count,
  942.                   _mesa_lookup_enum_by_nr(type), indices);
  943.  
  944.    if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
  945.       return;
  946.  
  947.    vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
  948.                                    count, type, indices, 0, 1);
  949. }
  950.  
  951.  
  952. /**
  953.  * Called by glDrawElementsBaseVertex() in immediate mode.
  954.  */
  955. static void GLAPIENTRY
  956. vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
  957.                                 const GLvoid *indices, GLint basevertex)
  958. {
  959.    GET_CURRENT_CONTEXT(ctx);
  960.  
  961.    if (MESA_VERBOSE & VERBOSE_DRAW)
  962.       _mesa_debug(ctx, "glDrawElementsBaseVertex(%s, %d, %s, %p, %d)\n",
  963.                   _mesa_lookup_enum_by_nr(mode), count,
  964.                   _mesa_lookup_enum_by_nr(type), indices, basevertex);
  965.  
  966.    if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices,
  967.                                      basevertex ))
  968.       return;
  969.  
  970.    vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
  971.                                    count, type, indices, basevertex, 1);
  972. }
  973.  
  974.  
  975. /**
  976.  * Called by glDrawElementsInstanced() in immediate mode.
  977.  */
  978. static void GLAPIENTRY
  979. vbo_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
  980.                                const GLvoid *indices, GLsizei primcount)
  981. {
  982.    GET_CURRENT_CONTEXT(ctx);
  983.  
  984.    if (MESA_VERBOSE & VERBOSE_DRAW)
  985.       _mesa_debug(ctx, "glDrawElementsInstanced(%s, %d, %s, %p, %d)\n",
  986.                   _mesa_lookup_enum_by_nr(mode), count,
  987.                   _mesa_lookup_enum_by_nr(type), indices, primcount);
  988.  
  989.    if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
  990.                                              primcount))
  991.       return;
  992.  
  993.    vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
  994.                                    count, type, indices, 0, primcount);
  995. }
  996.  
  997.  
  998. /**
  999.  * Inner support for both _mesa_MultiDrawElements() and
  1000.  * _mesa_MultiDrawRangeElements().
  1001.  * This does the actual rendering after we've checked array indexes, etc.
  1002.  */
  1003. static void
  1004. vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
  1005.                                 const GLsizei *count, GLenum type,
  1006.                                 const GLvoid **indices, GLsizei primcount,
  1007.                                 const GLint *basevertex)
  1008. {
  1009.    struct vbo_context *vbo = vbo_context(ctx);
  1010.    struct vbo_exec_context *exec = &vbo->exec;
  1011.    struct _mesa_index_buffer ib;
  1012.    struct _mesa_prim *prim;
  1013.    unsigned int index_type_size = 0;
  1014.    uintptr_t min_index_ptr, max_index_ptr;
  1015.    GLboolean fallback = GL_FALSE;
  1016.    int i;
  1017.  
  1018.    if (primcount == 0)
  1019.       return;
  1020.  
  1021.    FLUSH_CURRENT( ctx, 0 );
  1022.  
  1023.    if (!_mesa_valid_to_render(ctx, "glMultiDrawElements")) {
  1024.       return;
  1025.    }
  1026.  
  1027.    prim = calloc(1, primcount * sizeof(*prim));
  1028.    if (prim == NULL) {
  1029.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
  1030.       return;
  1031.    }
  1032.  
  1033.    /* Decide if we can do this all as one set of primitives sharing the
  1034.     * same index buffer, or if we have to reset the index pointer per
  1035.     * primitive.
  1036.     */
  1037.    bind_arrays( ctx );
  1038.  
  1039.    /* check for dirty state again */
  1040.    if (ctx->NewState)
  1041.       _mesa_update_state( ctx );
  1042.  
  1043.    switch (type) {
  1044.    case GL_UNSIGNED_INT:
  1045.       index_type_size = 4;
  1046.       break;
  1047.    case GL_UNSIGNED_SHORT:
  1048.       index_type_size = 2;
  1049.       break;
  1050.    case GL_UNSIGNED_BYTE:
  1051.       index_type_size = 1;
  1052.       break;
  1053.    default:
  1054.       assert(0);
  1055.    }
  1056.  
  1057.    min_index_ptr = (uintptr_t)indices[0];
  1058.    max_index_ptr = 0;
  1059.    for (i = 0; i < primcount; i++) {
  1060.       min_index_ptr = MIN2(min_index_ptr, (uintptr_t)indices[i]);
  1061.       max_index_ptr = MAX2(max_index_ptr, (uintptr_t)indices[i] +
  1062.                            index_type_size * count[i]);
  1063.    }
  1064.  
  1065.    /* Check if we can handle this thing as a bunch of index offsets from the
  1066.     * same index pointer.  If we can't, then we have to fall back to doing
  1067.     * a draw_prims per primitive.
  1068.     * Check that the difference between each prim's indexes is a multiple of
  1069.     * the index/element size.
  1070.     */
  1071.    if (index_type_size != 1) {
  1072.       for (i = 0; i < primcount; i++) {
  1073.          if ((((uintptr_t)indices[i] - min_index_ptr) % index_type_size) != 0) {
  1074.             fallback = GL_TRUE;
  1075.             break;
  1076.          }
  1077.       }
  1078.    }
  1079.  
  1080.    /* If the index buffer isn't in a VBO, then treating the application's
  1081.     * subranges of the index buffer as one large index buffer may lead to
  1082.     * us reading unmapped memory.
  1083.     */
  1084.    if (!_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj))
  1085.       fallback = GL_TRUE;
  1086.  
  1087.    if (!fallback) {
  1088.       ib.count = (max_index_ptr - min_index_ptr) / index_type_size;
  1089.       ib.type = type;
  1090.       ib.obj = ctx->Array.ElementArrayBufferObj;
  1091.       ib.ptr = (void *)min_index_ptr;
  1092.  
  1093.       for (i = 0; i < primcount; i++) {
  1094.          prim[i].begin = (i == 0);
  1095.          prim[i].end = (i == primcount - 1);
  1096.          prim[i].weak = 0;
  1097.          prim[i].pad = 0;
  1098.          prim[i].mode = mode;
  1099.          prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size;
  1100.          prim[i].count = count[i];
  1101.          prim[i].indexed = 1;
  1102.          prim[i].num_instances = 1;
  1103.          if (basevertex != NULL)
  1104.             prim[i].basevertex = basevertex[i];
  1105.          else
  1106.             prim[i].basevertex = 0;
  1107.       }
  1108.  
  1109.       vbo->draw_prims(ctx, exec->array.inputs, prim, primcount, &ib,
  1110.                       GL_FALSE, ~0, ~0);
  1111.    } else {
  1112.       /* render one prim at a time */
  1113.       for (i = 0; i < primcount; i++) {
  1114.          ib.count = count[i];
  1115.          ib.type = type;
  1116.          ib.obj = ctx->Array.ElementArrayBufferObj;
  1117.          ib.ptr = indices[i];
  1118.  
  1119.          prim[0].begin = 1;
  1120.          prim[0].end = 1;
  1121.          prim[0].weak = 0;
  1122.          prim[0].pad = 0;
  1123.          prim[0].mode = mode;
  1124.          prim[0].start = 0;
  1125.          prim[0].count = count[i];
  1126.          prim[0].indexed = 1;
  1127.          prim[0].num_instances = 1;
  1128.          if (basevertex != NULL)
  1129.             prim[0].basevertex = basevertex[i];
  1130.          else
  1131.             prim[0].basevertex = 0;
  1132.  
  1133.          vbo->draw_prims(ctx, exec->array.inputs, prim, 1, &ib,
  1134.                          GL_FALSE, ~0, ~0);
  1135.       }
  1136.    }
  1137.  
  1138.    free(prim);
  1139. }
  1140.  
  1141.  
  1142. static void GLAPIENTRY
  1143. vbo_exec_MultiDrawElements(GLenum mode,
  1144.                            const GLsizei *count, GLenum type,
  1145.                            const GLvoid **indices,
  1146.                            GLsizei primcount)
  1147. {
  1148.    GET_CURRENT_CONTEXT(ctx);
  1149.    GLint i;
  1150.  
  1151.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  1152.  
  1153.    for (i = 0; i < primcount; i++) {
  1154.       if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
  1155.                                        0))
  1156.          return;
  1157.    }
  1158.  
  1159.    vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
  1160.                                    NULL);
  1161. }
  1162.  
  1163.  
  1164. static void GLAPIENTRY
  1165. vbo_exec_MultiDrawElementsBaseVertex(GLenum mode,
  1166.                                      const GLsizei *count, GLenum type,
  1167.                                      const GLvoid **indices,
  1168.                                      GLsizei primcount,
  1169.                                      const GLsizei *basevertex)
  1170. {
  1171.    GET_CURRENT_CONTEXT(ctx);
  1172.    GLint i;
  1173.  
  1174.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  1175.  
  1176.    for (i = 0; i < primcount; i++) {
  1177.       if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
  1178.                                        basevertex[i]))
  1179.          return;
  1180.    }
  1181.  
  1182.    vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
  1183.                                    basevertex);
  1184. }
  1185.  
  1186.  
  1187. /**
  1188.  * Plug in the immediate-mode vertex array drawing commands into the
  1189.  * givven vbo_exec_context object.
  1190.  */
  1191. void
  1192. vbo_exec_array_init( struct vbo_exec_context *exec )
  1193. {
  1194.    exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays;
  1195.    exec->vtxfmt.DrawElements = vbo_exec_DrawElements;
  1196.    exec->vtxfmt.DrawRangeElements = vbo_exec_DrawRangeElements;
  1197.    exec->vtxfmt.MultiDrawElementsEXT = vbo_exec_MultiDrawElements;
  1198.    exec->vtxfmt.DrawElementsBaseVertex = vbo_exec_DrawElementsBaseVertex;
  1199.    exec->vtxfmt.DrawRangeElementsBaseVertex = vbo_exec_DrawRangeElementsBaseVertex;
  1200.    exec->vtxfmt.MultiDrawElementsBaseVertex = vbo_exec_MultiDrawElementsBaseVertex;
  1201.    exec->vtxfmt.DrawArraysInstanced = vbo_exec_DrawArraysInstanced;
  1202.    exec->vtxfmt.DrawElementsInstanced = vbo_exec_DrawElementsInstanced;
  1203. }
  1204.  
  1205.  
  1206. void
  1207. vbo_exec_array_destroy( struct vbo_exec_context *exec )
  1208. {
  1209.    /* nothing to do */
  1210. }
  1211.  
  1212.  
  1213.  
  1214. /**
  1215.  * The following functions are only used for OpenGL ES 1/2 support.
  1216.  * And some aren't even supported (yet) in ES 1/2.
  1217.  */
  1218.  
  1219.  
  1220. void GLAPIENTRY
  1221. _mesa_DrawArrays(GLenum mode, GLint first, GLsizei count)
  1222. {
  1223.    vbo_exec_DrawArrays(mode, first, count);
  1224. }
  1225.  
  1226.  
  1227. void GLAPIENTRY
  1228. _mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
  1229.                    const GLvoid *indices)
  1230. {
  1231.    vbo_exec_DrawElements(mode, count, type, indices);
  1232. }
  1233.  
  1234.  
  1235. void GLAPIENTRY
  1236. _mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
  1237.                              const GLvoid *indices, GLint basevertex)
  1238. {
  1239.    vbo_exec_DrawElementsBaseVertex(mode, count, type, indices, basevertex);
  1240. }
  1241.  
  1242.  
  1243. void GLAPIENTRY
  1244. _mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
  1245.                         GLenum type, const GLvoid *indices)
  1246. {
  1247.    vbo_exec_DrawRangeElements(mode, start, end, count, type, indices);
  1248. }
  1249.  
  1250.  
  1251. void GLAPIENTRY
  1252. _mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
  1253.                                   GLsizei count, GLenum type,
  1254.                                   const GLvoid *indices, GLint basevertex)
  1255. {
  1256.    vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
  1257.                                         indices, basevertex);
  1258. }
  1259.  
  1260.  
  1261. void GLAPIENTRY
  1262. _mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
  1263.                            const GLvoid **indices, GLsizei primcount)
  1264. {
  1265.    vbo_exec_MultiDrawElements(mode, count, type, indices, primcount);
  1266. }
  1267.  
  1268.  
  1269. void GLAPIENTRY
  1270. _mesa_MultiDrawElementsBaseVertex(GLenum mode,
  1271.                                   const GLsizei *count, GLenum type,
  1272.                                   const GLvoid **indices, GLsizei primcount,
  1273.                                   const GLint *basevertex)
  1274. {
  1275.    vbo_exec_MultiDrawElementsBaseVertex(mode, count, type, indices,
  1276.                                         primcount, basevertex);
  1277. }
  1278.