st_draw.c revision 4dcdf3b9c67f1481d46c1decba84c9c55698db4c
1/**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28/*
29 * This file implements the st_draw_vbo() function which is called from
30 * Mesa's VBO module.  All point/line/triangle rendering is done through
31 * this function whether the user called glBegin/End, glDrawArrays,
32 * glDrawElements, glEvalMesh, or glCalList, etc.
33 *
34 * We basically convert the VBO's vertex attribute/array information into
35 * Gallium vertex state, bind the vertex buffer objects and call
36 * pipe->draw_elements(), pipe->draw_range_elements() or pipe->draw_arrays().
37 *
38 * Authors:
39 *   Keith Whitwell <keith@tungstengraphics.com>
40 */
41
42
43#include "main/imports.h"
44#include "main/image.h"
45#include "main/macros.h"
46#include "shader/prog_uniform.h"
47
48#include "vbo/vbo.h"
49
50#include "st_context.h"
51#include "st_atom.h"
52#include "st_cb_bufferobjects.h"
53#include "st_draw.h"
54#include "st_program.h"
55
56#include "pipe/p_context.h"
57#include "pipe/p_defines.h"
58#include "pipe/p_inlines.h"
59
60
61static GLuint double_types[4] = {
62   PIPE_FORMAT_R64_FLOAT,
63   PIPE_FORMAT_R64G64_FLOAT,
64   PIPE_FORMAT_R64G64B64_FLOAT,
65   PIPE_FORMAT_R64G64B64A64_FLOAT
66};
67
68static GLuint float_types[4] = {
69   PIPE_FORMAT_R32_FLOAT,
70   PIPE_FORMAT_R32G32_FLOAT,
71   PIPE_FORMAT_R32G32B32_FLOAT,
72   PIPE_FORMAT_R32G32B32A32_FLOAT
73};
74
75static GLuint uint_types_norm[4] = {
76   PIPE_FORMAT_R32_UNORM,
77   PIPE_FORMAT_R32G32_UNORM,
78   PIPE_FORMAT_R32G32B32_UNORM,
79   PIPE_FORMAT_R32G32B32A32_UNORM
80};
81
82static GLuint uint_types_scale[4] = {
83   PIPE_FORMAT_R32_USCALED,
84   PIPE_FORMAT_R32G32_USCALED,
85   PIPE_FORMAT_R32G32B32_USCALED,
86   PIPE_FORMAT_R32G32B32A32_USCALED
87};
88
89static GLuint int_types_norm[4] = {
90   PIPE_FORMAT_R32_SNORM,
91   PIPE_FORMAT_R32G32_SNORM,
92   PIPE_FORMAT_R32G32B32_SNORM,
93   PIPE_FORMAT_R32G32B32A32_SNORM
94};
95
96static GLuint int_types_scale[4] = {
97   PIPE_FORMAT_R32_SSCALED,
98   PIPE_FORMAT_R32G32_SSCALED,
99   PIPE_FORMAT_R32G32B32_SSCALED,
100   PIPE_FORMAT_R32G32B32A32_SSCALED
101};
102
103static GLuint ushort_types_norm[4] = {
104   PIPE_FORMAT_R16_UNORM,
105   PIPE_FORMAT_R16G16_UNORM,
106   PIPE_FORMAT_R16G16B16_UNORM,
107   PIPE_FORMAT_R16G16B16A16_UNORM
108};
109
110static GLuint ushort_types_scale[4] = {
111   PIPE_FORMAT_R16_USCALED,
112   PIPE_FORMAT_R16G16_USCALED,
113   PIPE_FORMAT_R16G16B16_USCALED,
114   PIPE_FORMAT_R16G16B16A16_USCALED
115};
116
117static GLuint short_types_norm[4] = {
118   PIPE_FORMAT_R16_SNORM,
119   PIPE_FORMAT_R16G16_SNORM,
120   PIPE_FORMAT_R16G16B16_SNORM,
121   PIPE_FORMAT_R16G16B16A16_SNORM
122};
123
124static GLuint short_types_scale[4] = {
125   PIPE_FORMAT_R16_SSCALED,
126   PIPE_FORMAT_R16G16_SSCALED,
127   PIPE_FORMAT_R16G16B16_SSCALED,
128   PIPE_FORMAT_R16G16B16A16_SSCALED
129};
130
131static GLuint ubyte_types_norm[4] = {
132   PIPE_FORMAT_R8_UNORM,
133   PIPE_FORMAT_R8G8_UNORM,
134   PIPE_FORMAT_R8G8B8_UNORM,
135   PIPE_FORMAT_R8G8B8A8_UNORM
136};
137
138static GLuint ubyte_types_scale[4] = {
139   PIPE_FORMAT_R8_USCALED,
140   PIPE_FORMAT_R8G8_USCALED,
141   PIPE_FORMAT_R8G8B8_USCALED,
142   PIPE_FORMAT_R8G8B8A8_USCALED
143};
144
145static GLuint byte_types_norm[4] = {
146   PIPE_FORMAT_R8_SNORM,
147   PIPE_FORMAT_R8G8_SNORM,
148   PIPE_FORMAT_R8G8B8_SNORM,
149   PIPE_FORMAT_R8G8B8A8_SNORM
150};
151
152static GLuint byte_types_scale[4] = {
153   PIPE_FORMAT_R8_SSCALED,
154   PIPE_FORMAT_R8G8_SSCALED,
155   PIPE_FORMAT_R8G8B8_SSCALED,
156   PIPE_FORMAT_R8G8B8A8_SSCALED
157};
158
159static GLuint fixed_types[4] = {
160   PIPE_FORMAT_R32_FIXED,
161   PIPE_FORMAT_R32G32_FIXED,
162   PIPE_FORMAT_R32G32B32_FIXED,
163   PIPE_FORMAT_R32G32B32A32_FIXED
164};
165
166
167
168/**
169 * Return a PIPE_FORMAT_x for the given GL datatype and size.
170 */
171GLuint
172st_pipe_vertex_format(GLenum type, GLuint size, GLenum format,
173                      GLboolean normalized)
174{
175   assert((type >= GL_BYTE && type <= GL_DOUBLE) ||
176          type == GL_FIXED);
177   assert(size >= 1);
178   assert(size <= 4);
179   assert(format == GL_RGBA || format == GL_BGRA);
180
181   if (format == GL_BGRA) {
182      /* this is an odd-ball case */
183      assert(type == GL_UNSIGNED_BYTE);
184      assert(normalized);
185      return PIPE_FORMAT_B8G8R8A8_UNORM;
186   }
187
188   if (normalized) {
189      switch (type) {
190      case GL_DOUBLE: return double_types[size-1];
191      case GL_FLOAT: return float_types[size-1];
192      case GL_INT: return int_types_norm[size-1];
193      case GL_SHORT: return short_types_norm[size-1];
194      case GL_BYTE: return byte_types_norm[size-1];
195      case GL_UNSIGNED_INT: return uint_types_norm[size-1];
196      case GL_UNSIGNED_SHORT: return ushort_types_norm[size-1];
197      case GL_UNSIGNED_BYTE: return ubyte_types_norm[size-1];
198      case GL_FIXED: return fixed_types[size-1];
199      default: assert(0); return 0;
200      }
201   }
202   else {
203      switch (type) {
204      case GL_DOUBLE: return double_types[size-1];
205      case GL_FLOAT: return float_types[size-1];
206      case GL_INT: return int_types_scale[size-1];
207      case GL_SHORT: return short_types_scale[size-1];
208      case GL_BYTE: return byte_types_scale[size-1];
209      case GL_UNSIGNED_INT: return uint_types_scale[size-1];
210      case GL_UNSIGNED_SHORT: return ushort_types_scale[size-1];
211      case GL_UNSIGNED_BYTE: return ubyte_types_scale[size-1];
212      case GL_FIXED: return fixed_types[size-1];
213      default: assert(0); return 0;
214      }
215   }
216   return 0; /* silence compiler warning */
217}
218
219
220/*
221 * If edge flags are needed, setup an bitvector of flags and call
222 * pipe->set_edgeflags().
223 * XXX memleak: need to free the returned pointer at some point
224 */
225static void *
226setup_edgeflags(GLcontext *ctx, GLenum primMode, GLint start, GLint count,
227                const struct gl_client_array *array)
228{
229   struct pipe_context *pipe = ctx->st->pipe;
230
231   if ((primMode == GL_TRIANGLES ||
232        primMode == GL_QUADS ||
233        primMode == GL_POLYGON) &&
234       (ctx->Polygon.FrontMode != GL_FILL ||
235        ctx->Polygon.BackMode != GL_FILL)) {
236      /* need edge flags */
237      GLint i;
238      unsigned *vec;
239      struct st_buffer_object *stobj = st_buffer_object(array->BufferObj);
240      ubyte *map;
241
242      if (!stobj || stobj->Base.Name == 0) {
243         /* edge flags are not in a VBO */
244         return NULL;
245      }
246
247      vec = (unsigned *) _mesa_calloc(sizeof(unsigned) * ((count + 31) / 32));
248      if (!vec)
249         return NULL;
250
251      map = pipe_buffer_map(pipe->screen, stobj->buffer, PIPE_BUFFER_USAGE_CPU_READ);
252      map = ADD_POINTERS(map, array->Ptr);
253
254      for (i = 0; i < count; i++) {
255         if (*((float *) map))
256            vec[i/32] |= 1 << (i % 32);
257
258         map += array->StrideB;
259      }
260
261      pipe_buffer_unmap(pipe->screen, stobj->buffer);
262
263      pipe->set_edgeflags(pipe, vec);
264
265      return vec;
266   }
267   else {
268      /* edge flags not needed */
269      pipe->set_edgeflags(pipe, NULL);
270      return NULL;
271   }
272}
273
274
275/**
276 * Examine the active arrays to determine if we have interleaved
277 * vertex arrays all living in one VBO, or all living in user space.
278 * \param userSpace  returns whether the arrays are in user space.
279 */
280static GLboolean
281is_interleaved_arrays(const struct st_vertex_program *vp,
282                      const struct gl_client_array **arrays,
283                      GLboolean *userSpace)
284{
285   GLuint attr;
286   const struct gl_buffer_object *firstBufObj = NULL;
287   GLint firstStride = -1;
288   GLuint num_client_arrays = 0;
289   const GLubyte *client_addr = NULL;
290
291   for (attr = 0; attr < vp->num_inputs; attr++) {
292      const GLuint mesaAttr = vp->index_to_input[attr];
293      const struct gl_buffer_object *bufObj = arrays[mesaAttr]->BufferObj;
294      const GLsizei stride = arrays[mesaAttr]->StrideB; /* in bytes */
295
296      if (firstStride < 0) {
297         firstStride = stride;
298      }
299      else if (firstStride != stride) {
300         return GL_FALSE;
301      }
302
303      if (!bufObj || !bufObj->Name) {
304         num_client_arrays++;
305         /* Try to detect if the client-space arrays are
306          * "close" to each other.
307          */
308         if (!client_addr) {
309            client_addr = arrays[mesaAttr]->Ptr;
310         }
311         else if (abs(arrays[mesaAttr]->Ptr - client_addr) > firstStride) {
312            /* arrays start too far apart */
313            return GL_FALSE;
314         }
315      }
316      else if (!firstBufObj) {
317         firstBufObj = bufObj;
318      }
319      else if (bufObj != firstBufObj) {
320         return GL_FALSE;
321      }
322   }
323
324   *userSpace = (num_client_arrays == vp->num_inputs);
325   /* printf("user space: %d (%d %d)\n", (int) *userSpace,num_client_arrays,vp->num_inputs); */
326
327   return GL_TRUE;
328}
329
330
331/**
332 * Compute the memory range occupied by the arrays.
333 */
334static void
335get_arrays_bounds(const struct st_vertex_program *vp,
336                       const struct gl_client_array **arrays,
337                       GLuint max_index,
338                       const GLubyte **low, const GLubyte **high)
339{
340   const GLubyte *low_addr = NULL;
341   const GLubyte *high_addr = NULL;
342   GLuint attr;
343
344   for (attr = 0; attr < vp->num_inputs; attr++) {
345      const GLuint mesaAttr = vp->index_to_input[attr];
346      const GLint stride = arrays[mesaAttr]->StrideB;
347      const GLubyte *start = arrays[mesaAttr]->Ptr;
348      const unsigned sz = (arrays[mesaAttr]->Size *
349                           _mesa_sizeof_type(arrays[mesaAttr]->Type));
350      const GLubyte *end = start + (max_index * stride) + sz;
351
352      if (attr == 0) {
353         low_addr = start;
354         high_addr = end;
355      }
356      else {
357         low_addr = MIN2(low_addr, start);
358         high_addr = MAX2(high_addr, end);
359      }
360   }
361
362   *low = low_addr;
363   *high = high_addr;
364}
365
366
367/**
368 * Set up for drawing interleaved arrays that all live in one VBO
369 * or all live in user space.
370 * \param vbuffer  returns vertex buffer info
371 * \param velements  returns vertex element info
372 */
373static void
374setup_interleaved_attribs(GLcontext *ctx,
375                          const struct st_vertex_program *vp,
376                          const struct gl_client_array **arrays,
377                          GLuint max_index,
378                          GLboolean userSpace,
379                          struct pipe_vertex_buffer *vbuffer,
380                          struct pipe_vertex_element velements[])
381{
382   struct pipe_context *pipe = ctx->st->pipe;
383   GLuint attr;
384   const GLubyte *offset0;
385
386   for (attr = 0; attr < vp->num_inputs; attr++) {
387      const GLuint mesaAttr = vp->index_to_input[attr];
388      struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
389      struct st_buffer_object *stobj = st_buffer_object(bufobj);
390      GLsizei stride = arrays[mesaAttr]->StrideB;
391
392      /*printf("stobj %u = %p\n", attr, (void*)stobj);*/
393
394      if (attr == 0) {
395         const GLubyte *low, *high;
396
397         get_arrays_bounds(vp, arrays, max_index, &low, &high);
398         /*printf("buffer range: %p %p  %d\n", low, high, high-low);*/
399
400         offset0 = low;
401         if (userSpace) {
402            vbuffer->buffer =
403               pipe_user_buffer_create(pipe->screen, (void *) low, high - low);
404            vbuffer->buffer_offset = 0;
405         }
406         else {
407            vbuffer->buffer = NULL;
408            pipe_buffer_reference(&vbuffer->buffer, stobj->buffer);
409            vbuffer->buffer_offset = pointer_to_offset(low);
410         }
411         vbuffer->stride = stride; /* in bytes */
412         vbuffer->max_index = max_index;
413      }
414
415      velements[attr].src_offset =
416         (unsigned) (arrays[mesaAttr]->Ptr - offset0);
417      velements[attr].vertex_buffer_index = 0;
418      velements[attr].nr_components = arrays[mesaAttr]->Size;
419      velements[attr].src_format =
420         st_pipe_vertex_format(arrays[mesaAttr]->Type,
421                               arrays[mesaAttr]->Size,
422                               arrays[mesaAttr]->Format,
423                               arrays[mesaAttr]->Normalized);
424      assert(velements[attr].src_format);
425   }
426}
427
428
429/**
430 * Set up a separate pipe_vertex_buffer and pipe_vertex_element for each
431 * vertex attribute.
432 * \param vbuffer  returns vertex buffer info
433 * \param velements  returns vertex element info
434 */
435static void
436setup_non_interleaved_attribs(GLcontext *ctx,
437                              const struct st_vertex_program *vp,
438                              const struct gl_client_array **arrays,
439                              GLuint max_index,
440                              GLboolean *userSpace,
441                              struct pipe_vertex_buffer vbuffer[],
442                              struct pipe_vertex_element velements[])
443{
444   struct pipe_context *pipe = ctx->st->pipe;
445   GLuint attr;
446
447   for (attr = 0; attr < vp->num_inputs; attr++) {
448      const GLuint mesaAttr = vp->index_to_input[attr];
449      struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
450      GLsizei stride = arrays[mesaAttr]->StrideB;
451
452      *userSpace = GL_FALSE;
453
454      if (bufobj && bufobj->Name) {
455         /* Attribute data is in a VBO.
456          * Recall that for VBOs, the gl_client_array->Ptr field is
457          * really an offset from the start of the VBO, not a pointer.
458          */
459         struct st_buffer_object *stobj = st_buffer_object(bufobj);
460         assert(stobj->buffer);
461         /*printf("stobj %u = %p\n", attr, (void*) stobj);*/
462
463         vbuffer[attr].buffer = NULL;
464         pipe_buffer_reference(&vbuffer[attr].buffer, stobj->buffer);
465         vbuffer[attr].buffer_offset = pointer_to_offset(arrays[mesaAttr]->Ptr);
466         velements[attr].src_offset = 0;
467      }
468      else {
469         /* attribute data is in user-space memory, not a VBO */
470         uint bytes;
471         /*printf("user-space array %d stride %d\n", attr, stride);*/
472
473         *userSpace = GL_TRUE;
474
475         /* wrap user data */
476         if (arrays[mesaAttr]->Ptr) {
477            /* user's vertex array */
478            if (arrays[mesaAttr]->StrideB) {
479               bytes = arrays[mesaAttr]->StrideB * (max_index + 1);
480            }
481            else {
482               bytes = arrays[mesaAttr]->Size
483                  * _mesa_sizeof_type(arrays[mesaAttr]->Type);
484            }
485            vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen,
486                           (void *) arrays[mesaAttr]->Ptr, bytes);
487         }
488         else {
489            /* no array, use ctx->Current.Attrib[] value */
490            bytes = sizeof(ctx->Current.Attrib[0]);
491            vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen,
492                           (void *) ctx->Current.Attrib[mesaAttr], bytes);
493            stride = 0;
494         }
495
496         vbuffer[attr].buffer_offset = 0;
497         velements[attr].src_offset = 0;
498      }
499
500      assert(velements[attr].src_offset <= 2048); /* 11-bit field */
501
502      /* common-case setup */
503      vbuffer[attr].stride = stride; /* in bytes */
504      vbuffer[attr].max_index = max_index;
505      velements[attr].vertex_buffer_index = attr;
506      velements[attr].nr_components = arrays[mesaAttr]->Size;
507      velements[attr].src_format
508         = st_pipe_vertex_format(arrays[mesaAttr]->Type,
509                                 arrays[mesaAttr]->Size,
510                                 arrays[mesaAttr]->Format,
511                                 arrays[mesaAttr]->Normalized);
512      assert(velements[attr].src_format);
513   }
514}
515
516
517
518/**
519 * Prior to drawing, check that any uniforms referenced by the
520 * current shader have been set.  If a uniform has not been set,
521 * issue a warning.
522 */
523static void
524check_uniforms(GLcontext *ctx)
525{
526   const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
527   if (shProg && shProg->LinkStatus) {
528      GLuint i;
529      for (i = 0; i < shProg->Uniforms->NumUniforms; i++) {
530         const struct gl_uniform *u = &shProg->Uniforms->Uniforms[i];
531         if (!u->Initialized) {
532            _mesa_warning(ctx,
533                          "Using shader with uninitialized uniform: %s",
534                          u->Name);
535         }
536      }
537   }
538}
539
540
541/**
542 * This function gets plugged into the VBO module and is called when
543 * we have something to render.
544 * Basically, translate the information into the format expected by gallium.
545 */
546void
547st_draw_vbo(GLcontext *ctx,
548            const struct gl_client_array **arrays,
549            const struct _mesa_prim *prims,
550            GLuint nr_prims,
551            const struct _mesa_index_buffer *ib,
552	    GLboolean index_bounds_valid,
553            GLuint min_index,
554            GLuint max_index)
555{
556   struct pipe_context *pipe = ctx->st->pipe;
557   const struct st_vertex_program *vp;
558   const struct pipe_shader_state *vs;
559   struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS];
560   GLuint attr;
561   struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
562   unsigned num_vbuffers, num_velements;
563   GLboolean userSpace;
564
565   /* Gallium probably doesn't want this in some cases. */
566   if (!index_bounds_valid)
567      vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
568
569   /* sanity check for pointer arithmetic below */
570   assert(sizeof(arrays[0]->Ptr[0]) == 1);
571
572   st_validate_state(ctx->st);
573
574   /* must get these after state validation! */
575   vp = ctx->st->vp;
576   vs = &ctx->st->vp_varient->state;
577
578#if 0
579   if (MESA_VERBOSE & VERBOSE_GLSL) {
580      check_uniforms(ctx);
581   }
582#else
583   (void) check_uniforms;
584#endif
585
586   /*
587    * Setup the vbuffer[] and velements[] arrays.
588    */
589   if (is_interleaved_arrays(vp, arrays, &userSpace)) {
590      /*printf("Draw interleaved\n");*/
591      setup_interleaved_attribs(ctx, vp, arrays, max_index, userSpace,
592                                vbuffer, velements);
593      num_vbuffers = 1;
594      num_velements = vp->num_inputs;
595      if (num_velements == 0)
596         num_vbuffers = 0;
597   }
598   else {
599      /*printf("Draw non-interleaved\n");*/
600      setup_non_interleaved_attribs(ctx, vp, arrays, max_index,
601                                    &userSpace, vbuffer, velements);
602      num_vbuffers = vp->num_inputs;
603      num_velements = vp->num_inputs;
604   }
605
606#if 0
607   {
608      GLuint i;
609      for (i = 0; i < num_vbuffers; i++) {
610         printf("buffers[%d].stride = %u\n", i, vbuffer[i].stride);
611         printf("buffers[%d].max_index = %u\n", i, vbuffer[i].max_index);
612         printf("buffers[%d].buffer_offset = %u\n", i, vbuffer[i].buffer_offset);
613         printf("buffers[%d].buffer = %p\n", i, (void*) vbuffer[i].buffer);
614      }
615      for (i = 0; i < num_velements; i++) {
616         printf("vlements[%d].vbuffer_index = %u\n", i, velements[i].vertex_buffer_index);
617         printf("vlements[%d].src_offset = %u\n", i, velements[i].src_offset);
618         printf("vlements[%d].nr_comps = %u\n", i, velements[i].nr_components);
619         printf("vlements[%d].format = %s\n", i, pf_name(velements[i].src_format));
620      }
621   }
622#endif
623
624   pipe->set_vertex_buffers(pipe, num_vbuffers, vbuffer);
625   pipe->set_vertex_elements(pipe, num_velements, velements);
626
627   if (num_vbuffers == 0 || num_velements == 0)
628      return;
629
630   /* do actual drawing */
631   if (ib) {
632      /* indexed primitive */
633      struct gl_buffer_object *bufobj = ib->obj;
634      struct pipe_buffer *indexBuf = NULL;
635      unsigned indexSize, indexOffset, i;
636
637      switch (ib->type) {
638      case GL_UNSIGNED_INT:
639         indexSize = 4;
640         break;
641      case GL_UNSIGNED_SHORT:
642         indexSize = 2;
643         break;
644      case GL_UNSIGNED_BYTE:
645         indexSize = 1;
646         break;
647      default:
648         assert(0);
649	 return;
650      }
651
652      /* get/create the index buffer object */
653      if (bufobj && bufobj->Name) {
654         /* elements/indexes are in a real VBO */
655         struct st_buffer_object *stobj = st_buffer_object(bufobj);
656         pipe_buffer_reference(&indexBuf, stobj->buffer);
657         indexOffset = pointer_to_offset(ib->ptr) / indexSize;
658      }
659      else {
660         /* element/indicies are in user space memory */
661         indexBuf = pipe_user_buffer_create(pipe->screen, (void *) ib->ptr,
662                                            ib->count * indexSize);
663         indexOffset = 0;
664      }
665
666      /* draw */
667      if (nr_prims == 1 && pipe->draw_range_elements != NULL) {
668         i = 0;
669
670         /* XXX: exercise temporary path to pass min/max directly
671          * through to driver & draw module.  These interfaces still
672          * need a bit of work...
673          */
674         setup_edgeflags(ctx, prims[i].mode,
675                         prims[i].start + indexOffset, prims[i].count,
676                         arrays[VERT_ATTRIB_EDGEFLAG]);
677
678         pipe->draw_range_elements(pipe, indexBuf, indexSize,
679                                   min_index,
680                                   max_index,
681                                   prims[i].mode,
682                                   prims[i].start + indexOffset, prims[i].count);
683      }
684      else {
685         for (i = 0; i < nr_prims; i++) {
686            setup_edgeflags(ctx, prims[i].mode,
687                            prims[i].start + indexOffset, prims[i].count,
688                            arrays[VERT_ATTRIB_EDGEFLAG]);
689
690            pipe->draw_elements(pipe, indexBuf, indexSize,
691                                prims[i].mode,
692                                prims[i].start + indexOffset, prims[i].count);
693         }
694      }
695
696      pipe_buffer_reference(&indexBuf, NULL);
697   }
698   else {
699      /* non-indexed */
700      GLuint i;
701      for (i = 0; i < nr_prims; i++) {
702         setup_edgeflags(ctx, prims[i].mode,
703                         prims[i].start, prims[i].count,
704                         arrays[VERT_ATTRIB_EDGEFLAG]);
705
706         pipe->draw_arrays(pipe, prims[i].mode, prims[i].start, prims[i].count);
707      }
708   }
709
710   /* unreference buffers (frees wrapped user-space buffer objects) */
711   for (attr = 0; attr < num_vbuffers; attr++) {
712      pipe_buffer_reference(&vbuffer[attr].buffer, NULL);
713      assert(!vbuffer[attr].buffer);
714   }
715
716   if (userSpace)
717   {
718      pipe->set_vertex_buffers(pipe, 0, NULL);
719   }
720}
721
722
723void st_init_draw( struct st_context *st )
724{
725   GLcontext *ctx = st->ctx;
726
727   vbo_set_draw_func(ctx, st_draw_vbo);
728}
729
730
731void st_destroy_draw( struct st_context *st )
732{
733}
734
735
736