Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / state_tracker / st_draw.c
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_vbo().
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/bufferobj.h"
46 #include "main/macros.h"
47 #include "main/mfeatures.h"
48 #include "program/prog_uniform.h"
49
50 #include "vbo/vbo.h"
51
52 #include "st_context.h"
53 #include "st_atom.h"
54 #include "st_cb_bufferobjects.h"
55 #include "st_draw.h"
56 #include "st_program.h"
57
58 #include "pipe/p_context.h"
59 #include "pipe/p_defines.h"
60 #include "util/u_inlines.h"
61 #include "util/u_format.h"
62 #include "util/u_prim.h"
63 #include "util/u_draw_quad.h"
64 #include "draw/draw_context.h"
65 #include "cso_cache/cso_context.h"
66
67
68 static GLuint double_types[4] = {
69    PIPE_FORMAT_R64_FLOAT,
70    PIPE_FORMAT_R64G64_FLOAT,
71    PIPE_FORMAT_R64G64B64_FLOAT,
72    PIPE_FORMAT_R64G64B64A64_FLOAT
73 };
74
75 static GLuint float_types[4] = {
76    PIPE_FORMAT_R32_FLOAT,
77    PIPE_FORMAT_R32G32_FLOAT,
78    PIPE_FORMAT_R32G32B32_FLOAT,
79    PIPE_FORMAT_R32G32B32A32_FLOAT
80 };
81
82 static GLuint half_float_types[4] = {
83    PIPE_FORMAT_R16_FLOAT,
84    PIPE_FORMAT_R16G16_FLOAT,
85    PIPE_FORMAT_R16G16B16_FLOAT,
86    PIPE_FORMAT_R16G16B16A16_FLOAT
87 };
88
89 static GLuint uint_types_norm[4] = {
90    PIPE_FORMAT_R32_UNORM,
91    PIPE_FORMAT_R32G32_UNORM,
92    PIPE_FORMAT_R32G32B32_UNORM,
93    PIPE_FORMAT_R32G32B32A32_UNORM
94 };
95
96 static GLuint uint_types_scale[4] = {
97    PIPE_FORMAT_R32_USCALED,
98    PIPE_FORMAT_R32G32_USCALED,
99    PIPE_FORMAT_R32G32B32_USCALED,
100    PIPE_FORMAT_R32G32B32A32_USCALED
101 };
102
103 static GLuint int_types_norm[4] = {
104    PIPE_FORMAT_R32_SNORM,
105    PIPE_FORMAT_R32G32_SNORM,
106    PIPE_FORMAT_R32G32B32_SNORM,
107    PIPE_FORMAT_R32G32B32A32_SNORM
108 };
109
110 static GLuint int_types_scale[4] = {
111    PIPE_FORMAT_R32_SSCALED,
112    PIPE_FORMAT_R32G32_SSCALED,
113    PIPE_FORMAT_R32G32B32_SSCALED,
114    PIPE_FORMAT_R32G32B32A32_SSCALED
115 };
116
117 static GLuint ushort_types_norm[4] = {
118    PIPE_FORMAT_R16_UNORM,
119    PIPE_FORMAT_R16G16_UNORM,
120    PIPE_FORMAT_R16G16B16_UNORM,
121    PIPE_FORMAT_R16G16B16A16_UNORM
122 };
123
124 static GLuint ushort_types_scale[4] = {
125    PIPE_FORMAT_R16_USCALED,
126    PIPE_FORMAT_R16G16_USCALED,
127    PIPE_FORMAT_R16G16B16_USCALED,
128    PIPE_FORMAT_R16G16B16A16_USCALED
129 };
130
131 static GLuint short_types_norm[4] = {
132    PIPE_FORMAT_R16_SNORM,
133    PIPE_FORMAT_R16G16_SNORM,
134    PIPE_FORMAT_R16G16B16_SNORM,
135    PIPE_FORMAT_R16G16B16A16_SNORM
136 };
137
138 static GLuint short_types_scale[4] = {
139    PIPE_FORMAT_R16_SSCALED,
140    PIPE_FORMAT_R16G16_SSCALED,
141    PIPE_FORMAT_R16G16B16_SSCALED,
142    PIPE_FORMAT_R16G16B16A16_SSCALED
143 };
144
145 static GLuint ubyte_types_norm[4] = {
146    PIPE_FORMAT_R8_UNORM,
147    PIPE_FORMAT_R8G8_UNORM,
148    PIPE_FORMAT_R8G8B8_UNORM,
149    PIPE_FORMAT_R8G8B8A8_UNORM
150 };
151
152 static GLuint ubyte_types_scale[4] = {
153    PIPE_FORMAT_R8_USCALED,
154    PIPE_FORMAT_R8G8_USCALED,
155    PIPE_FORMAT_R8G8B8_USCALED,
156    PIPE_FORMAT_R8G8B8A8_USCALED
157 };
158
159 static GLuint byte_types_norm[4] = {
160    PIPE_FORMAT_R8_SNORM,
161    PIPE_FORMAT_R8G8_SNORM,
162    PIPE_FORMAT_R8G8B8_SNORM,
163    PIPE_FORMAT_R8G8B8A8_SNORM
164 };
165
166 static GLuint byte_types_scale[4] = {
167    PIPE_FORMAT_R8_SSCALED,
168    PIPE_FORMAT_R8G8_SSCALED,
169    PIPE_FORMAT_R8G8B8_SSCALED,
170    PIPE_FORMAT_R8G8B8A8_SSCALED
171 };
172
173 static GLuint fixed_types[4] = {
174    PIPE_FORMAT_R32_FIXED,
175    PIPE_FORMAT_R32G32_FIXED,
176    PIPE_FORMAT_R32G32B32_FIXED,
177    PIPE_FORMAT_R32G32B32A32_FIXED
178 };
179
180
181
182 /**
183  * Return a PIPE_FORMAT_x for the given GL datatype and size.
184  */
185 enum pipe_format
186 st_pipe_vertex_format(GLenum type, GLuint size, GLenum format,
187                       GLboolean normalized)
188 {
189    assert((type >= GL_BYTE && type <= GL_DOUBLE) ||
190           type == GL_FIXED || type == GL_HALF_FLOAT);
191    assert(size >= 1);
192    assert(size <= 4);
193    assert(format == GL_RGBA || format == GL_BGRA);
194
195    if (format == GL_BGRA) {
196       /* this is an odd-ball case */
197       assert(type == GL_UNSIGNED_BYTE);
198       assert(normalized);
199       return PIPE_FORMAT_B8G8R8A8_UNORM;
200    }
201
202    if (normalized) {
203       switch (type) {
204       case GL_DOUBLE: return double_types[size-1];
205       case GL_FLOAT: return float_types[size-1];
206       case GL_HALF_FLOAT: return half_float_types[size-1];
207       case GL_INT: return int_types_norm[size-1];
208       case GL_SHORT: return short_types_norm[size-1];
209       case GL_BYTE: return byte_types_norm[size-1];
210       case GL_UNSIGNED_INT: return uint_types_norm[size-1];
211       case GL_UNSIGNED_SHORT: return ushort_types_norm[size-1];
212       case GL_UNSIGNED_BYTE: return ubyte_types_norm[size-1];
213       case GL_FIXED: return fixed_types[size-1];
214       default: assert(0); return 0;
215       }
216    }
217    else {
218       switch (type) {
219       case GL_DOUBLE: return double_types[size-1];
220       case GL_FLOAT: return float_types[size-1];
221       case GL_HALF_FLOAT: return half_float_types[size-1];
222       case GL_INT: return int_types_scale[size-1];
223       case GL_SHORT: return short_types_scale[size-1];
224       case GL_BYTE: return byte_types_scale[size-1];
225       case GL_UNSIGNED_INT: return uint_types_scale[size-1];
226       case GL_UNSIGNED_SHORT: return ushort_types_scale[size-1];
227       case GL_UNSIGNED_BYTE: return ubyte_types_scale[size-1];
228       case GL_FIXED: return fixed_types[size-1];
229       default: assert(0); return 0;
230       }
231    }
232    return PIPE_FORMAT_NONE; /* silence compiler warning */
233 }
234
235
236 /**
237  * This is very similar to vbo_all_varyings_in_vbos() but we test
238  * the stride.  See bug 38626.
239  */
240 static GLboolean
241 all_varyings_in_vbos(const struct gl_client_array *arrays[])
242 {
243    GLuint i;
244    
245    for (i = 0; i < VERT_ATTRIB_MAX; i++)
246       if (arrays[i]->StrideB && !_mesa_is_bufferobj(arrays[i]->BufferObj))
247          return GL_FALSE;
248
249    return GL_TRUE;
250 }
251
252
253 /**
254  * Examine the active arrays to determine if we have interleaved
255  * vertex arrays all living in one VBO, or all living in user space.
256  */
257 static GLboolean
258 is_interleaved_arrays(const struct st_vertex_program *vp,
259                       const struct st_vp_variant *vpv,
260                       const struct gl_client_array **arrays)
261 {
262    GLuint attr;
263    const struct gl_buffer_object *firstBufObj = NULL;
264    GLint firstStride = -1;
265    const GLubyte *firstPtr = NULL;
266    GLboolean userSpaceBuffer = GL_FALSE;
267
268    for (attr = 0; attr < vpv->num_inputs; attr++) {
269       const GLuint mesaAttr = vp->index_to_input[attr];
270       const struct gl_client_array *array = arrays[mesaAttr];
271       const struct gl_buffer_object *bufObj = array->BufferObj;
272       const GLsizei stride = array->StrideB; /* in bytes */
273
274       if (attr == 0) {
275          /* save info about the first array */
276          firstStride = stride;
277          firstPtr = array->Ptr;         
278          firstBufObj = bufObj;
279          userSpaceBuffer = !bufObj || !bufObj->Name;
280       }
281       else {
282          /* check if other arrays interleave with the first, in same buffer */
283          if (stride != firstStride)
284             return GL_FALSE; /* strides don't match */
285
286          if (bufObj != firstBufObj)
287             return GL_FALSE; /* arrays in different VBOs */
288
289          if (abs(array->Ptr - firstPtr) > firstStride)
290             return GL_FALSE; /* arrays start too far apart */
291
292          if ((!bufObj || !_mesa_is_bufferobj(bufObj)) != userSpaceBuffer)
293             return GL_FALSE; /* mix of VBO and user-space arrays */
294       }
295    }
296
297    return GL_TRUE;
298 }
299
300
301 /**
302  * Set up for drawing interleaved arrays that all live in one VBO
303  * or all live in user space.
304  * \param vbuffer  returns vertex buffer info
305  * \param velements  returns vertex element info
306  */
307 static void
308 setup_interleaved_attribs(struct gl_context *ctx,
309                           const struct st_vertex_program *vp,
310                           const struct st_vp_variant *vpv,
311                           const struct gl_client_array **arrays,
312                           struct pipe_vertex_buffer *vbuffer,
313                           struct pipe_vertex_element velements[],
314                           unsigned max_index,
315                           unsigned num_instances)
316 {
317    struct st_context *st = st_context(ctx);
318    struct pipe_context *pipe = st->pipe;
319    GLuint attr;
320    const GLubyte *low_addr = NULL;
321
322    /* Find the lowest address of the arrays we're drawing */
323    if (vpv->num_inputs) {
324       low_addr = arrays[vp->index_to_input[0]]->Ptr;
325
326       for (attr = 1; attr < vpv->num_inputs; attr++) {
327          const GLubyte *start = arrays[vp->index_to_input[attr]]->Ptr;
328          low_addr = MIN2(low_addr, start);
329       }
330    }
331
332    for (attr = 0; attr < vpv->num_inputs; attr++) {
333       const GLuint mesaAttr = vp->index_to_input[attr];
334       const struct gl_client_array *array = arrays[mesaAttr];
335       struct gl_buffer_object *bufobj = array->BufferObj;
336       struct st_buffer_object *stobj = st_buffer_object(bufobj);
337       unsigned src_offset = (unsigned) (array->Ptr - low_addr);
338       GLuint element_size = array->_ElementSize;
339       GLsizei stride = array->StrideB;
340
341       assert(element_size == array->Size * _mesa_sizeof_type(array->Type));
342
343       if (attr == 0) {
344          if (bufobj && _mesa_is_bufferobj(bufobj)) {
345             vbuffer->buffer = NULL;
346             pipe_resource_reference(&vbuffer->buffer, stobj->buffer);
347             vbuffer->buffer_offset = pointer_to_offset(low_addr);
348          }
349          else {
350             uint divisor = array->InstanceDivisor;
351             uint last_index = divisor ? num_instances / divisor : max_index;
352             uint bytes = src_offset + stride * last_index + element_size;
353
354             vbuffer->buffer = pipe_user_buffer_create(pipe->screen,
355                                                       (void*) low_addr,
356                                                       bytes,
357                                                       PIPE_BIND_VERTEX_BUFFER);
358             vbuffer->buffer_offset = 0;
359
360             /* Track user vertex buffers. */
361             pipe_resource_reference(&st->user_attrib[0].buffer, vbuffer->buffer);
362             st->user_attrib[0].element_size = element_size;
363             st->user_attrib[0].stride = stride;
364             st->num_user_attribs = 1;
365          }
366          vbuffer->stride = stride; /* in bytes */
367       }
368
369       velements[attr].src_offset = src_offset;
370       velements[attr].instance_divisor = array->InstanceDivisor;
371       velements[attr].vertex_buffer_index = 0;
372       velements[attr].src_format = st_pipe_vertex_format(array->Type,
373                                                          array->Size,
374                                                          array->Format,
375                                                          array->Normalized);
376       assert(velements[attr].src_format);
377    }
378 }
379
380
381 /**
382  * Set up a separate pipe_vertex_buffer and pipe_vertex_element for each
383  * vertex attribute.
384  * \param vbuffer  returns vertex buffer info
385  * \param velements  returns vertex element info
386  */
387 static void
388 setup_non_interleaved_attribs(struct gl_context *ctx,
389                               const struct st_vertex_program *vp,
390                               const struct st_vp_variant *vpv,
391                               const struct gl_client_array **arrays,
392                               struct pipe_vertex_buffer vbuffer[],
393                               struct pipe_vertex_element velements[],
394                               unsigned max_index,
395                               unsigned num_instances)
396 {
397    struct st_context *st = st_context(ctx);
398    struct pipe_context *pipe = st->pipe;
399    GLuint attr;
400
401    for (attr = 0; attr < vpv->num_inputs; attr++) {
402       const GLuint mesaAttr = vp->index_to_input[attr];
403       const struct gl_client_array *array = arrays[mesaAttr];
404       struct gl_buffer_object *bufobj = array->BufferObj;
405       GLuint element_size = array->_ElementSize;
406       GLsizei stride = array->StrideB;
407
408       assert(element_size == array->Size * _mesa_sizeof_type(array->Type));
409
410       if (bufobj && _mesa_is_bufferobj(bufobj)) {
411          /* Attribute data is in a VBO.
412           * Recall that for VBOs, the gl_client_array->Ptr field is
413           * really an offset from the start of the VBO, not a pointer.
414           */
415          struct st_buffer_object *stobj = st_buffer_object(bufobj);
416          assert(stobj->buffer);
417
418          vbuffer[attr].buffer = NULL;
419          pipe_resource_reference(&vbuffer[attr].buffer, stobj->buffer);
420          vbuffer[attr].buffer_offset = pointer_to_offset(array->Ptr);
421       }
422       else {
423          /* wrap user data */
424          uint bytes;
425          void *ptr;
426
427          if (array->Ptr) {
428             uint divisor = array->InstanceDivisor;
429             uint last_index = divisor ? num_instances / divisor : max_index;
430
431             bytes = stride * last_index + element_size;
432
433             ptr = (void *) array->Ptr;
434          }
435          else {
436             /* no array, use ctx->Current.Attrib[] value */
437             bytes = element_size = sizeof(ctx->Current.Attrib[0]);
438             ptr = (void *) ctx->Current.Attrib[mesaAttr];
439             stride = 0;
440          }
441
442          assert(ptr);
443          assert(bytes);
444
445          vbuffer[attr].buffer =
446             pipe_user_buffer_create(pipe->screen, ptr, bytes,
447                                     PIPE_BIND_VERTEX_BUFFER);
448
449          vbuffer[attr].buffer_offset = 0;
450
451          /* Track user vertex buffers. */
452          pipe_resource_reference(&st->user_attrib[attr].buffer, vbuffer[attr].buffer);
453          st->user_attrib[attr].element_size = element_size;
454          st->user_attrib[attr].stride = stride;
455          st->num_user_attribs = MAX2(st->num_user_attribs, attr + 1);
456       }
457
458       /* common-case setup */
459       vbuffer[attr].stride = stride; /* in bytes */
460
461       velements[attr].src_offset = 0;
462       velements[attr].instance_divisor = array->InstanceDivisor;
463       velements[attr].vertex_buffer_index = attr;
464       velements[attr].src_format = st_pipe_vertex_format(array->Type,
465                                                          array->Size,
466                                                          array->Format,
467                                                          array->Normalized);
468       assert(velements[attr].src_format);
469    }
470 }
471
472
473 static void
474 setup_index_buffer(struct gl_context *ctx,
475                    const struct _mesa_index_buffer *ib,
476                    struct pipe_index_buffer *ibuffer)
477 {
478    struct st_context *st = st_context(ctx);
479    struct pipe_context *pipe = st->pipe;
480
481    memset(ibuffer, 0, sizeof(*ibuffer));
482    if (ib) {
483       struct gl_buffer_object *bufobj = ib->obj;
484
485       switch (ib->type) {
486       case GL_UNSIGNED_INT:
487          ibuffer->index_size = 4;
488          break;
489       case GL_UNSIGNED_SHORT:
490          ibuffer->index_size = 2;
491          break;
492       case GL_UNSIGNED_BYTE:
493          ibuffer->index_size = 1;
494          break;
495       default:
496          assert(0);
497          return;
498       }
499
500       /* get/create the index buffer object */
501       if (bufobj && _mesa_is_bufferobj(bufobj)) {
502          /* elements/indexes are in a real VBO */
503          struct st_buffer_object *stobj = st_buffer_object(bufobj);
504          pipe_resource_reference(&ibuffer->buffer, stobj->buffer);
505          ibuffer->offset = pointer_to_offset(ib->ptr);
506       }
507       else {
508          /* element/indicies are in user space memory */
509          ibuffer->buffer =
510             pipe_user_buffer_create(pipe->screen, (void *) ib->ptr,
511                                     ib->count * ibuffer->index_size,
512                                     PIPE_BIND_INDEX_BUFFER);
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  */
523 static void
524 check_uniforms(struct gl_context *ctx)
525 {
526    struct gl_shader_program *shProg[3] = {
527       ctx->Shader.CurrentVertexProgram,
528       ctx->Shader.CurrentGeometryProgram,
529       ctx->Shader.CurrentFragmentProgram,
530    };
531    unsigned j;
532
533    for (j = 0; j < 3; j++) {
534       unsigned i;
535
536       if (shProg[j] == NULL || !shProg[j]->LinkStatus)
537          continue;
538
539       for (i = 0; i < shProg[j]->Uniforms->NumUniforms; i++) {
540          const struct gl_uniform *u = &shProg[j]->Uniforms->Uniforms[i];
541          if (!u->Initialized) {
542             _mesa_warning(ctx,
543                           "Using shader with uninitialized uniform: %s",
544                           u->Name);
545          }
546       }
547    }
548 }
549
550
551 /**
552  * Translate OpenGL primtive type (GL_POINTS, GL_TRIANGLE_STRIP, etc) to
553  * the corresponding Gallium type.
554  */
555 static unsigned
556 translate_prim(const struct gl_context *ctx, unsigned prim)
557 {
558    /* GL prims should match Gallium prims, spot-check a few */
559    assert(GL_POINTS == PIPE_PRIM_POINTS);
560    assert(GL_QUADS == PIPE_PRIM_QUADS);
561    assert(GL_TRIANGLE_STRIP_ADJACENCY == PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY);
562
563    /* Avoid quadstrips if it's easy to do so:
564     * Note: it's important to do the correct trimming if we change the
565     * prim type!  We do that wherever this function is called.
566     */
567    if (prim == GL_QUAD_STRIP &&
568        ctx->Light.ShadeModel != GL_FLAT &&
569        ctx->Polygon.FrontMode == GL_FILL &&
570        ctx->Polygon.BackMode == GL_FILL)
571       prim = GL_TRIANGLE_STRIP;
572
573    return prim;
574 }
575
576
577 static void
578 st_validate_varrays(struct gl_context *ctx,
579                     const struct gl_client_array **arrays,
580                     unsigned max_index,
581                     unsigned num_instances)
582 {
583    struct st_context *st = st_context(ctx);
584    const struct st_vertex_program *vp;
585    const struct st_vp_variant *vpv;
586    struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS];
587    struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
588    unsigned num_vbuffers, num_velements;
589    GLuint attr;
590    unsigned i;
591
592    /* must get these after state validation! */
593    vp = st->vp;
594    vpv = st->vp_variant;
595
596    memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs);
597
598    /* Unreference any user vertex buffers. */
599    for (i = 0; i < st->num_user_attribs; i++) {
600       pipe_resource_reference(&st->user_attrib[i].buffer, NULL);
601    }
602    st->num_user_attribs = 0;
603
604    /*
605     * Setup the vbuffer[] and velements[] arrays.
606     */
607    if (is_interleaved_arrays(vp, vpv, arrays)) {
608       setup_interleaved_attribs(ctx, vp, vpv, arrays, vbuffer, velements,
609                                 max_index, num_instances);
610
611       num_vbuffers = 1;
612       num_velements = vpv->num_inputs;
613       if (num_velements == 0)
614          num_vbuffers = 0;
615    }
616    else {
617       setup_non_interleaved_attribs(ctx, vp, vpv, arrays,
618                                     vbuffer, velements, max_index,
619                                     num_instances);
620       num_vbuffers = vpv->num_inputs;
621       num_velements = vpv->num_inputs;
622    }
623
624    cso_set_vertex_buffers(st->cso_context, num_vbuffers, vbuffer);
625    cso_set_vertex_elements(st->cso_context, num_velements, velements);
626
627    /* unreference buffers (frees wrapped user-space buffer objects)
628     * This is OK, because the pipe driver should reference buffers by itself
629     * in set_vertex_buffers. */
630    for (attr = 0; attr < num_vbuffers; attr++) {
631       pipe_resource_reference(&vbuffer[attr].buffer, NULL);
632       assert(!vbuffer[attr].buffer);
633    }
634 }
635
636
637 /**
638  * This function gets plugged into the VBO module and is called when
639  * we have something to render.
640  * Basically, translate the information into the format expected by gallium.
641  */
642 void
643 st_draw_vbo(struct gl_context *ctx,
644             const struct gl_client_array **arrays,
645             const struct _mesa_prim *prims,
646             GLuint nr_prims,
647             const struct _mesa_index_buffer *ib,
648             GLboolean index_bounds_valid,
649             GLuint min_index,
650             GLuint max_index)
651 {
652    struct st_context *st = st_context(ctx);
653    struct pipe_context *pipe = st->pipe;
654    struct pipe_index_buffer ibuffer;
655    struct pipe_draw_info info;
656    unsigned i, num_instances = 1;
657    GLboolean new_array =
658       st->dirty.st &&
659       (st->dirty.mesa & (_NEW_ARRAY | _NEW_PROGRAM | _NEW_BUFFER_OBJECT)) != 0;
660
661    /* Mesa core state should have been validated already */
662    assert(ctx->NewState == 0x0);
663
664    if (ib) {
665       /* Gallium probably doesn't want this in some cases. */
666       if (!index_bounds_valid)
667          if (!all_varyings_in_vbos(arrays))
668             vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
669
670       for (i = 0; i < nr_prims; i++) {
671          num_instances = MAX2(num_instances, prims[i].num_instances);
672       }
673    }
674    else {
675       /* Get min/max index for non-indexed drawing. */
676       min_index = ~0;
677       max_index = 0;
678
679       for (i = 0; i < nr_prims; i++) {
680          min_index = MIN2(min_index, prims[i].start);
681          max_index = MAX2(max_index, prims[i].start + prims[i].count - 1);
682          num_instances = MAX2(num_instances, prims[i].num_instances);
683       }
684    }
685
686    /* Validate state. */
687    if (st->dirty.st) {
688       GLboolean vertDataEdgeFlags;
689
690       /* sanity check for pointer arithmetic below */
691       assert(sizeof(arrays[0]->Ptr[0]) == 1);
692
693       vertDataEdgeFlags = arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj &&
694                           arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj->Name;
695       if (vertDataEdgeFlags != st->vertdata_edgeflags) {
696          st->vertdata_edgeflags = vertDataEdgeFlags;
697          st->dirty.st |= ST_NEW_EDGEFLAGS_DATA;
698       }
699
700       st_validate_state(st);
701
702       if (new_array) {
703          st_validate_varrays(ctx, arrays, max_index, num_instances);
704       }
705
706 #if 0
707       if (MESA_VERBOSE & VERBOSE_GLSL) {
708          check_uniforms(ctx);
709       }
710 #else
711       (void) check_uniforms;
712 #endif
713    }
714
715    /* Notify the driver that the content of user buffers may have been
716     * changed. */
717    assert(max_index >= min_index);
718    if (!new_array && st->num_user_attribs) {
719       for (i = 0; i < st->num_user_attribs; i++) {
720          if (st->user_attrib[i].buffer) {
721             unsigned element_size = st->user_attrib[i].element_size;
722             unsigned stride = st->user_attrib[i].stride;
723             unsigned min_offset = min_index * stride;
724             unsigned max_offset = max_index * stride + element_size;
725
726             assert(max_offset > min_offset);
727
728             pipe->redefine_user_buffer(pipe, st->user_attrib[i].buffer,
729                                        min_offset,
730                                        max_offset - min_offset);
731          }
732       }
733    }
734
735    setup_index_buffer(ctx, ib, &ibuffer);
736    pipe->set_index_buffer(pipe, &ibuffer);
737
738    util_draw_init_info(&info);
739    if (ib) {
740       info.indexed = TRUE;
741       if (min_index != ~0 && max_index != ~0) {
742          info.min_index = min_index;
743          info.max_index = max_index;
744       }
745    }
746
747    info.primitive_restart = ctx->Array.PrimitiveRestart;
748    info.restart_index = ctx->Array.RestartIndex;
749
750    /* do actual drawing */
751    for (i = 0; i < nr_prims; i++) {
752       info.mode = translate_prim( ctx, prims[i].mode );
753       info.start = prims[i].start;
754       info.count = prims[i].count;
755       info.instance_count = prims[i].num_instances;
756       info.index_bias = prims[i].basevertex;
757       if (!ib) {
758          info.min_index = info.start;
759          info.max_index = info.start + info.count - 1;
760       }
761
762       if (u_trim_pipe_prim(info.mode, &info.count))
763          pipe->draw_vbo(pipe, &info);
764    }
765
766    pipe_resource_reference(&ibuffer.buffer, NULL);
767 }
768
769
770 void
771 st_init_draw(struct st_context *st)
772 {
773    struct gl_context *ctx = st->ctx;
774
775    vbo_set_draw_func(ctx, st_draw_vbo);
776
777 #if FEATURE_feedback || FEATURE_rastpos
778    st->draw = draw_create(st->pipe); /* for selection/feedback */
779
780    /* Disable draw options that might convert points/lines to tris, etc.
781     * as that would foul-up feedback/selection mode.
782     */
783    draw_wide_line_threshold(st->draw, 1000.0f);
784    draw_wide_point_threshold(st->draw, 1000.0f);
785    draw_enable_line_stipple(st->draw, FALSE);
786    draw_enable_point_sprites(st->draw, FALSE);
787 #endif
788 }
789
790
791 void
792 st_destroy_draw(struct st_context *st)
793 {
794 #if FEATURE_feedback || FEATURE_rastpos
795    draw_destroy(st->draw);
796 #endif
797 }