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