1 /**************************************************************************
3 Copyright 2002-2008 VMware, Inc.
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
30 * Keith Whitwell <keithw@vmware.com>
35 /* Display list compiler attempts to store lists of vertices with the
36 * same vertex layout. Additionally it attempts to minimize the need
37 * for execute-time fixup of these vertex lists, allowing them to be
40 * There are still some circumstances where this can be thwarted, for
41 * example by building a list that consists of one very long primitive
42 * (eg Begin(Triangles), 1000 vertices, End), and calling that list
43 * from inside a different begin/end object (Begin(Lines), CallList,
46 * In that case the code will have to replay the list as individual
47 * commands through the Exec dispatch table, or fix up the copied
48 * vertices at execute-time.
50 * The other case where fixup is required is when a vertex attribute
51 * is introduced in the middle of a primitive. Eg:
53 * TexCoord1f() Vertex2f()
54 * TexCoord1f() Color3f() Vertex2f()
57 * If the current value of Color isn't known at compile-time, this
58 * primitive will require fixup.
61 * The list compiler currently doesn't attempt to compile lists
62 * containing EvalCoord or EvalPoint commands. On encountering one of
63 * these, compilation falls back to opcodes.
65 * This could be improved to fallback only when a mix of EvalCoord and
66 * Vertex commands are issued within a single primitive.
70 #include "main/glheader.h"
71 #include "main/arrayobj.h"
72 #include "main/bufferobj.h"
73 #include "main/context.h"
74 #include "main/dlist.h"
75 #include "main/enums.h"
76 #include "main/eval.h"
77 #include "main/macros.h"
78 #include "main/draw_validate.h"
79 #include "main/api_arrayelt.h"
80 #include "main/vtxfmt.h"
81 #include "main/dispatch.h"
82 #include "main/state.h"
83 #include "main/varray.h"
84 #include "util/bitscan.h"
85 #include "util/u_memory.h"
88 #include "vbo_private.h"
96 * Display list flag only used by this VBO code.
98 #define DLIST_DANGLING_REFS 0x1
101 /* An interesting VBO number/name to help with debugging */
102 #define VBO_BUF_ID 12345
104 static void GLAPIENTRY
105 _save_Materialfv(GLenum face, GLenum pname, const GLfloat *params);
107 static void GLAPIENTRY
108 _save_EvalCoord1f(GLfloat u);
110 static void GLAPIENTRY
111 _save_EvalCoord2f(GLfloat u, GLfloat v);
114 * NOTE: Old 'parity' issue is gone, but copying can still be
115 * wrong-footed on replay.
118 copy_vertices(struct gl_context *ctx,
119 const struct vbo_save_vertex_list *node,
120 const fi_type * src_buffer)
122 struct vbo_save_context *save = &vbo_context(ctx)->save;
123 struct _mesa_prim *prim = &node->prims[node->prim_count - 1];
124 GLuint sz = save->vertex_size;
125 const fi_type *src = src_buffer + prim->start * sz;
126 fi_type *dst = save->copied.buffer;
131 return vbo_copy_vertices(ctx, prim->mode, prim, sz, true, dst, src);
135 static struct vbo_save_vertex_store *
136 alloc_vertex_store(struct gl_context *ctx, int vertex_count)
138 struct vbo_save_context *save = &vbo_context(ctx)->save;
139 struct vbo_save_vertex_store *vertex_store =
140 CALLOC_STRUCT(vbo_save_vertex_store);
142 int size = MAX2(vertex_count * save->vertex_size, VBO_SAVE_BUFFER_SIZE);
144 /* obj->Name needs to be non-zero, but won't ever be examined more
145 * closely than that. In particular these buffers won't be entered
146 * into the hash and can never be confused with ones visible to the
147 * user. Perhaps there could be a special number for internal
150 vertex_store->bufferobj = ctx->Driver.NewBufferObject(ctx, VBO_BUF_ID);
151 if (vertex_store->bufferobj) {
152 save->out_of_memory =
153 !ctx->Driver.BufferData(ctx,
155 size * sizeof(GLfloat),
156 NULL, GL_STATIC_DRAW_ARB,
158 GL_DYNAMIC_STORAGE_BIT,
159 vertex_store->bufferobj);
162 save->out_of_memory = GL_TRUE;
165 if (save->out_of_memory) {
166 _mesa_error(ctx, GL_OUT_OF_MEMORY, "internal VBO allocation");
167 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
170 vertex_store->buffer_map = NULL;
171 vertex_store->used = 0;
178 free_vertex_store(struct gl_context *ctx,
179 struct vbo_save_vertex_store *vertex_store)
181 assert(!vertex_store->buffer_map);
183 if (vertex_store->bufferobj) {
184 _mesa_reference_buffer_object(ctx, &vertex_store->bufferobj, NULL);
192 vbo_save_map_vertex_store(struct gl_context *ctx,
193 struct vbo_save_vertex_store *vertex_store)
195 const GLbitfield access = (GL_MAP_WRITE_BIT |
196 GL_MAP_INVALIDATE_RANGE_BIT |
197 GL_MAP_UNSYNCHRONIZED_BIT |
198 GL_MAP_FLUSH_EXPLICIT_BIT |
201 assert(vertex_store->bufferobj);
202 assert(!vertex_store->buffer_map); /* the buffer should not be mapped */
204 if (vertex_store->bufferobj->Size > 0) {
205 /* Map the remaining free space in the VBO */
206 GLintptr offset = vertex_store->used * sizeof(GLfloat);
207 GLsizeiptr size = vertex_store->bufferobj->Size - offset;
208 fi_type *range = (fi_type *)
209 ctx->Driver.MapBufferRange(ctx, offset, size, access,
210 vertex_store->bufferobj,
213 /* compute address of start of whole buffer (needed elsewhere) */
214 vertex_store->buffer_map = range - vertex_store->used;
215 assert(vertex_store->buffer_map);
219 vertex_store->buffer_map = NULL;
224 /* probably ran out of memory for buffers */
231 vbo_save_unmap_vertex_store(struct gl_context *ctx,
232 struct vbo_save_vertex_store *vertex_store)
234 if (vertex_store->bufferobj->Size > 0) {
236 GLsizeiptr length = vertex_store->used * sizeof(GLfloat)
237 - vertex_store->bufferobj->Mappings[MAP_INTERNAL].Offset;
239 /* Explicitly flush the region we wrote to */
240 ctx->Driver.FlushMappedBufferRange(ctx, offset, length,
241 vertex_store->bufferobj,
244 ctx->Driver.UnmapBuffer(ctx, vertex_store->bufferobj, MAP_INTERNAL);
246 vertex_store->buffer_map = NULL;
250 static struct vbo_save_primitive_store *
251 alloc_prim_store(int prim_count)
253 struct vbo_save_primitive_store *store =
254 CALLOC_STRUCT(vbo_save_primitive_store);
255 store->size = MAX2(prim_count, VBO_SAVE_PRIM_SIZE);
256 store->prims = calloc(store->size, sizeof(struct _mesa_prim));
264 reset_counters(struct gl_context *ctx)
266 struct vbo_save_context *save = &vbo_context(ctx)->save;
268 save->prims = save->prim_store->prims + save->prim_store->used;
269 save->buffer_map = save->vertex_store->buffer_map + save->vertex_store->used;
271 assert(save->buffer_map == save->buffer_ptr);
273 if (save->vertex_size)
274 save->max_vert = (save->vertex_store->bufferobj->Size / sizeof(float) - save->vertex_store->used) /
279 save->vert_count = 0;
280 save->prim_count = 0;
281 save->prim_max = save->prim_store->size - save->prim_store->used;
282 save->dangling_attr_ref = GL_FALSE;
286 * For a list of prims, try merging prims that can just be extensions of the
290 merge_prims(struct gl_context *ctx, struct _mesa_prim *prim_list,
294 struct _mesa_prim *prev_prim = prim_list;
296 for (i = 1; i < *prim_count; i++) {
297 struct _mesa_prim *this_prim = prim_list + i;
299 vbo_try_prim_conversion(&this_prim->mode, &this_prim->count);
301 if (vbo_merge_draws(ctx, true,
302 prev_prim->mode, this_prim->mode,
303 prev_prim->start, this_prim->start,
304 &prev_prim->count, this_prim->count,
305 prev_prim->basevertex, this_prim->basevertex,
307 this_prim->begin, this_prim->end)) {
308 /* We've found a prim that just extend the previous one. Tack it
309 * onto the previous one, and let this primitive struct get dropped.
314 /* If any previous primitives have been dropped, then we need to copy
315 * this later one into the next available slot.
318 if (prev_prim != this_prim)
319 *prev_prim = *this_prim;
322 *prim_count = prev_prim - prim_list + 1;
327 * Convert GL_LINE_LOOP primitive into GL_LINE_STRIP so that drivers
328 * don't have to worry about handling the _mesa_prim::begin/end flags.
329 * See https://bugs.freedesktop.org/show_bug.cgi?id=81174
332 convert_line_loop_to_strip(struct vbo_save_context *save,
333 struct vbo_save_vertex_list *node)
335 struct _mesa_prim *prim = &node->prims[node->prim_count - 1];
337 assert(prim->mode == GL_LINE_LOOP);
340 /* Copy the 0th vertex to end of the buffer and extend the
341 * vertex count by one to finish the line loop.
343 const GLuint sz = save->vertex_size;
345 const fi_type *src = save->buffer_map + prim->start * sz;
347 fi_type *dst = save->buffer_map + (prim->start + prim->count) * sz;
349 memcpy(dst, src, sz * sizeof(float));
352 node->vertex_count++;
354 save->buffer_ptr += sz;
355 save->vertex_store->used += sz;
359 /* Drawing the second or later section of a long line loop.
360 * Skip the 0th vertex.
366 prim->mode = GL_LINE_STRIP;
370 /* Compare the present vao if it has the same setup. */
372 compare_vao(gl_vertex_processing_mode mode,
373 const struct gl_vertex_array_object *vao,
374 const struct gl_buffer_object *bo, GLintptr buffer_offset,
375 GLuint stride, GLbitfield64 vao_enabled,
376 const GLubyte size[VBO_ATTRIB_MAX],
377 const GLenum16 type[VBO_ATTRIB_MAX],
378 const GLuint offset[VBO_ATTRIB_MAX])
383 /* If the enabled arrays are not the same we are not equal. */
384 if (vao_enabled != vao->Enabled)
387 /* Check the buffer binding at 0 */
388 if (vao->BufferBinding[0].BufferObj != bo)
390 /* BufferBinding[0].Offset != buffer_offset is checked per attribute */
391 if (vao->BufferBinding[0].Stride != stride)
393 assert(vao->BufferBinding[0].InstanceDivisor == 0);
395 /* Retrieve the mapping from VBO_ATTRIB to VERT_ATTRIB space */
396 const GLubyte *const vao_to_vbo_map = _vbo_attribute_alias_map[mode];
398 /* Now check the enabled arrays */
399 GLbitfield mask = vao_enabled;
401 const int attr = u_bit_scan(&mask);
402 const unsigned char vbo_attr = vao_to_vbo_map[attr];
403 const GLenum16 tp = type[vbo_attr];
404 const GLintptr off = offset[vbo_attr] + buffer_offset;
405 const struct gl_array_attributes *attrib = &vao->VertexAttrib[attr];
406 if (attrib->RelativeOffset + vao->BufferBinding[0].Offset != off)
408 if (attrib->Format.Type != tp)
410 if (attrib->Format.Size != size[vbo_attr])
412 assert(attrib->Format.Format == GL_RGBA);
413 assert(attrib->Format.Normalized == GL_FALSE);
414 assert(attrib->Format.Integer == vbo_attrtype_to_integer_flag(tp));
415 assert(attrib->Format.Doubles == vbo_attrtype_to_double_flag(tp));
416 assert(attrib->BufferBindingIndex == 0);
423 /* Create or reuse the vao for the vertex processing mode. */
425 update_vao(struct gl_context *ctx,
426 gl_vertex_processing_mode mode,
427 struct gl_vertex_array_object **vao,
428 struct gl_buffer_object *bo, GLintptr buffer_offset,
429 GLuint stride, GLbitfield64 vbo_enabled,
430 const GLubyte size[VBO_ATTRIB_MAX],
431 const GLenum16 type[VBO_ATTRIB_MAX],
432 const GLuint offset[VBO_ATTRIB_MAX])
434 /* Compute the bitmasks of vao_enabled arrays */
435 GLbitfield vao_enabled = _vbo_get_vao_enabled_from_vbo(mode, vbo_enabled);
438 * Check if we can possibly reuse the exisiting one.
439 * In the long term we should reset them when something changes.
441 if (compare_vao(mode, *vao, bo, buffer_offset, stride,
442 vao_enabled, size, type, offset))
445 /* The initial refcount is 1 */
446 _mesa_reference_vao(ctx, vao, NULL);
447 *vao = _mesa_new_vao(ctx, ~((GLuint)0));
450 * assert(stride <= ctx->Const.MaxVertexAttribStride);
451 * MaxVertexAttribStride is not set for drivers that does not
452 * expose GL 44 or GLES 31.
455 /* Bind the buffer object at binding point 0 */
456 _mesa_bind_vertex_buffer(ctx, *vao, 0, bo, buffer_offset, stride, false,
459 /* Retrieve the mapping from VBO_ATTRIB to VERT_ATTRIB space
460 * Note that the position/generic0 aliasing is done in the VAO.
462 const GLubyte *const vao_to_vbo_map = _vbo_attribute_alias_map[mode];
463 /* Now set the enable arrays */
464 GLbitfield mask = vao_enabled;
466 const int vao_attr = u_bit_scan(&mask);
467 const GLubyte vbo_attr = vao_to_vbo_map[vao_attr];
468 assert(offset[vbo_attr] <= ctx->Const.MaxVertexAttribRelativeOffset);
470 _vbo_set_attrib_format(ctx, *vao, vao_attr, buffer_offset,
471 size[vbo_attr], type[vbo_attr], offset[vbo_attr]);
472 _mesa_vertex_attrib_binding(ctx, *vao, vao_attr, 0);
474 _mesa_enable_vertex_array_attribs(ctx, *vao, vao_enabled);
475 assert(vao_enabled == (*vao)->Enabled);
476 assert((vao_enabled & ~(*vao)->VertexAttribBufferMask) == 0);
478 /* Finalize and freeze the VAO */
479 _mesa_set_vao_immutable(ctx, *vao);
484 realloc_storage(struct gl_context *ctx, int prim_count, int vertex_count)
486 struct vbo_save_context *save = &vbo_context(ctx)->save;
487 if (vertex_count >= 0) {
490 vbo_save_unmap_vertex_store(ctx, save->vertex_store);
492 /* Release old reference:
494 free_vertex_store(ctx, save->vertex_store);
495 save->vertex_store = NULL;
496 /* When we have a new vbo, we will for sure need a new vao */
497 for (gl_vertex_processing_mode vpm = 0; vpm < VP_MODE_MAX; ++vpm)
498 _mesa_reference_vao(ctx, &save->VAO[vpm], NULL);
500 /* Allocate and map new store:
502 save->vertex_store = alloc_vertex_store(ctx, vertex_count);
503 save->buffer_ptr = vbo_save_map_vertex_store(ctx, save->vertex_store);
504 save->out_of_memory = save->buffer_ptr == NULL;
507 if (prim_count >= 0) {
508 if (--save->prim_store->refcount == 0) {
509 free(save->prim_store->prims);
510 free(save->prim_store);
512 save->prim_store = alloc_prim_store(prim_count);
518 * Insert the active immediate struct onto the display list currently
522 compile_vertex_list(struct gl_context *ctx)
524 struct vbo_save_context *save = &vbo_context(ctx)->save;
525 struct vbo_save_vertex_list *node;
527 /* Allocate space for this structure in the display list currently
530 node = (struct vbo_save_vertex_list *)
531 _mesa_dlist_alloc_aligned(ctx, save->opcode_vertex_list, sizeof(*node));
536 /* Make sure the pointer is aligned to the size of a pointer */
537 assert((GLintptr) node % sizeof(void *) == 0);
539 /* Duplicate our template, increment refcounts to the storage structs:
541 GLintptr old_offset = 0;
543 old_offset = save->VAO[0]->BufferBinding[0].Offset
544 + save->VAO[0]->VertexAttrib[VERT_ATTRIB_POS].RelativeOffset;
546 const GLsizei stride = save->vertex_size*sizeof(GLfloat);
547 GLintptr buffer_offset =
548 (save->buffer_map - save->vertex_store->buffer_map) * sizeof(GLfloat);
549 assert(old_offset <= buffer_offset);
550 const GLintptr offset_diff = buffer_offset - old_offset;
551 GLuint start_offset = 0;
552 if (offset_diff > 0 && stride > 0 && offset_diff % stride == 0) {
553 /* The vertex size is an exact multiple of the buffer offset.
554 * This means that we can use zero-based vertex attribute pointers
555 * and specify the start of the primitive with the _mesa_prim::start
556 * field. This results in issuing several draw calls with identical
557 * vertex attribute information. This can result in fewer state
558 * changes in drivers. In particular, the Gallium CSO module will
559 * filter out redundant vertex buffer changes.
561 /* We cannot immediately update the primitives as some methods below
562 * still need the uncorrected start vertices
564 start_offset = offset_diff/stride;
565 assert(old_offset == buffer_offset - offset_diff);
566 buffer_offset = old_offset;
568 GLuint offsets[VBO_ATTRIB_MAX];
569 for (unsigned i = 0, offset = 0; i < VBO_ATTRIB_MAX; ++i) {
571 offset += save->attrsz[i] * sizeof(GLfloat);
573 node->vertex_count = save->vert_count;
574 node->wrap_count = save->copied.nr;
575 node->prims = save->prims;
576 node->merged.prims = NULL;
577 node->merged.ib.obj = NULL;
578 node->merged.prim_count = 0;
579 node->prim_count = save->prim_count;
580 node->prim_store = save->prim_store;
582 /* Create a pair of VAOs for the possible VERTEX_PROCESSING_MODEs
583 * Note that this may reuse the previous one of possible.
585 for (gl_vertex_processing_mode vpm = VP_MODE_FF; vpm < VP_MODE_MAX; ++vpm) {
586 /* create or reuse the vao */
587 update_vao(ctx, vpm, &save->VAO[vpm],
588 save->vertex_store->bufferobj, buffer_offset, stride,
589 save->enabled, save->attrsz, save->attrtype, offsets);
590 /* Reference the vao in the dlist */
591 node->VAO[vpm] = NULL;
592 _mesa_reference_vao(ctx, &node->VAO[vpm], save->VAO[vpm]);
595 node->prim_store->refcount++;
597 if (save->no_current_update) {
598 node->current_data = NULL;
601 GLuint current_size = save->vertex_size - save->attrsz[0];
602 node->current_data = NULL;
605 node->current_data = malloc(current_size * sizeof(GLfloat));
606 if (node->current_data) {
607 const char *buffer = (const char *)save->buffer_map;
608 unsigned attr_offset = save->attrsz[0] * sizeof(GLfloat);
609 unsigned vertex_offset = 0;
611 if (node->vertex_count)
612 vertex_offset = (node->vertex_count - 1) * stride;
614 memcpy(node->current_data, buffer + vertex_offset + attr_offset,
615 current_size * sizeof(GLfloat));
617 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Current value allocation");
622 assert(save->attrsz[VBO_ATTRIB_POS] != 0 || node->vertex_count == 0);
624 if (save->dangling_attr_ref)
625 ctx->ListState.CurrentList->Flags |= DLIST_DANGLING_REFS;
627 save->vertex_store->used += save->vertex_size * node->vertex_count;
628 save->prim_store->used += node->prim_count;
630 /* Copy duplicated vertices
632 save->copied.nr = copy_vertices(ctx, node, save->buffer_map);
634 if (node->prims[node->prim_count - 1].mode == GL_LINE_LOOP) {
635 convert_line_loop_to_strip(save, node);
638 merge_prims(ctx, node->prims, &node->prim_count);
640 /* Correct the primitive starts, we can only do this here as copy_vertices
641 * and convert_line_loop_to_strip above consume the uncorrected starts.
642 * On the other hand the _vbo_loopback_vertex_list call below needs the
643 * primitves to be corrected already.
645 for (unsigned i = 0; i < node->prim_count; i++) {
646 node->prims[i].start += start_offset;
649 /* Create an index buffer. */
650 node->min_index = node->max_index = 0;
651 if (save->vert_count) {
652 /* We won't modify node->prims, so use a const alias to avoid unintended
654 const struct _mesa_prim *original_prims = node->prims;
656 int end = original_prims[node->prim_count - 1].start +
657 original_prims[node->prim_count - 1].count;
658 int total_vert_count = end - original_prims[0].start;
660 node->min_index = node->prims[0].start;
661 node->max_index = end - 1;
663 /* Estimate for the worst case: all prims are line strips (the +1 is because
664 * wrap_buffers may call use but the last primitive may not be complete) */
665 int max_indices_count = MAX2(total_vert_count * 2 - (node->prim_count * 2) + 1,
667 int size = max_indices_count * sizeof(uint32_t);
668 uint32_t* indices = (uint32_t*) malloc(size);
669 uint32_t max_index = 0, min_index = 0xFFFFFFFF;
673 int last_valid_prim = -1;
674 /* Construct indices array. */
675 for (unsigned i = 0; i < node->prim_count; i++) {
676 assert(original_prims[i].basevertex == 0);
677 GLubyte mode = original_prims[i].mode;
679 int vertex_count = original_prims[i].count;
684 /* Line strips get converted to lines */
685 if (mode == GL_LINE_STRIP)
688 /* If 2 consecutive prims use the same mode => merge them. */
689 bool merge_prims = last_valid_prim >= 0 &&
690 mode == node->merged.prims[last_valid_prim].mode &&
691 mode != GL_LINE_LOOP && mode != GL_TRIANGLE_FAN &&
692 mode != GL_QUAD_STRIP && mode != GL_POLYGON &&
695 /* To be able to merge consecutive triangle strips we need to insert
696 * a degenerate triangle.
699 mode == GL_TRIANGLE_STRIP) {
700 /* Insert a degenerate triangle */
701 assert(node->merged.prims[last_valid_prim].mode == GL_TRIANGLE_STRIP);
702 unsigned tri_count = node->merged.prims[last_valid_prim].count - 2;
704 indices[idx] = indices[idx - 1];
705 indices[idx + 1] = original_prims[i].start;
707 node->merged.prims[last_valid_prim].count += 2;
710 /* Add another index to preserve winding order */
711 indices[idx++] = original_prims[i].start;
712 node->merged.prims[last_valid_prim].count++;
718 /* Convert line strips to lines if it'll allow if the previous
719 * prim mode is GL_LINES (so merge_prims is true) or if the next
720 * primitive mode is GL_LINES or GL_LINE_LOOP.
722 if (original_prims[i].mode == GL_LINE_STRIP &&
724 (i < node->prim_count - 1 &&
725 (original_prims[i + 1].mode == GL_LINE_STRIP ||
726 original_prims[i + 1].mode == GL_LINES)))) {
727 for (unsigned j = 0; j < vertex_count; j++) {
728 indices[idx++] = original_prims[i].start + j;
729 /* Repeat all but the first/last indices. */
730 if (j && j != vertex_count - 1) {
731 indices[idx++] = original_prims[i].start + j;
735 for (unsigned j = 0; j < vertex_count; j++) {
736 indices[idx++] = original_prims[i].start + j;
740 min_index = MIN2(min_index, indices[start]);
741 max_index = MAX2(max_index, indices[idx - 1]);
744 /* Update vertex count. */
745 node->merged.prims[last_valid_prim].count += idx - start;
747 /* Keep this primitive */
748 last_valid_prim += 1;
749 assert(last_valid_prim <= i);
750 node->merged.prims = realloc(node->merged.prims, (1 + last_valid_prim) * sizeof(struct _mesa_prim));
751 node->merged.prims[last_valid_prim] = original_prims[i];
752 node->merged.prims[last_valid_prim].start = start;
753 node->merged.prims[last_valid_prim].count = idx - start;
755 node->merged.prims[last_valid_prim].mode = mode;
761 assert(idx <= max_indices_count);
763 node->merged.prim_count = last_valid_prim + 1;
764 node->merged.ib.ptr = NULL;
765 node->merged.ib.count = idx;
766 node->merged.ib.index_size_shift = (GL_UNSIGNED_INT - GL_UNSIGNED_BYTE) >> 1;
767 node->merged.min_index = min_index;
768 node->merged.max_index = max_index;
770 node->merged.ib.obj = ctx->Driver.NewBufferObject(ctx, VBO_BUF_ID + 1);
771 bool success = ctx->Driver.BufferData(ctx,
772 GL_ELEMENT_ARRAY_BUFFER_ARB,
773 idx * sizeof(uint32_t), indices,
774 GL_STATIC_DRAW_ARB, GL_MAP_WRITE_BIT,
775 node->merged.ib.obj);
780 ctx->Driver.DeleteBuffer(ctx, node->merged.ib.obj);
781 _mesa_error(ctx, GL_OUT_OF_MEMORY, "IB allocation");
784 node->merged.ib.obj = NULL;
785 node->vertex_count = 0;
786 node->prim_count = 0;
792 /* Deal with GL_COMPILE_AND_EXECUTE:
794 if (ctx->ExecuteFlag) {
795 struct _glapi_table *dispatch = GET_DISPATCH();
797 _glapi_set_dispatch(ctx->Exec);
799 /* Note that the range of referenced vertices must be mapped already */
800 _vbo_loopback_vertex_list(ctx, node);
802 _glapi_set_dispatch(dispatch);
805 /* Decide whether the storage structs are full, or can be used for
806 * the next vertex lists as well.
808 if (save->vertex_store->used >
809 save->vertex_store->bufferobj->Size / sizeof(float) - 16 * (save->vertex_size + 4)) {
810 realloc_storage(ctx, -1, 0);
813 /* update buffer_ptr for next vertex */
814 save->buffer_ptr = save->vertex_store->buffer_map
815 + save->vertex_store->used;
818 if (save->prim_store->used > save->prim_store->size - 6) {
819 realloc_storage(ctx, 0, -1);
822 /* Reset our structures for the next run of vertices:
829 * This is called when we fill a vertex buffer before we hit a glEnd().
831 * TODO -- If no new vertices have been stored, don't bother saving it.
834 wrap_buffers(struct gl_context *ctx)
836 struct vbo_save_context *save = &vbo_context(ctx)->save;
837 GLint i = save->prim_count - 1;
840 assert(i < (GLint) save->prim_max);
843 /* Close off in-progress primitive.
845 save->prims[i].count = (save->vert_count - save->prims[i].start);
846 mode = save->prims[i].mode;
848 /* store the copied vertices, and allocate a new list.
850 compile_vertex_list(ctx);
852 /* Restart interrupted primitive
854 save->prims[0].mode = mode;
855 save->prims[0].begin = 0;
856 save->prims[0].end = 0;
857 save->prims[0].start = 0;
858 save->prims[0].count = 0;
859 save->prim_count = 1;
864 * Called only when buffers are wrapped as the result of filling the
865 * vertex_store struct.
868 wrap_filled_vertex(struct gl_context *ctx)
870 struct vbo_save_context *save = &vbo_context(ctx)->save;
871 unsigned numComponents;
873 /* Emit a glEnd to close off the last vertex list.
877 /* Copy stored stored vertices to start of new list.
879 assert(save->max_vert - save->vert_count > save->copied.nr);
881 numComponents = save->copied.nr * save->vertex_size;
882 memcpy(save->buffer_ptr,
884 numComponents * sizeof(fi_type));
885 save->buffer_ptr += numComponents;
886 save->vert_count += save->copied.nr;
891 copy_to_current(struct gl_context *ctx)
893 struct vbo_save_context *save = &vbo_context(ctx)->save;
894 GLbitfield64 enabled = save->enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));
897 const int i = u_bit_scan64(&enabled);
898 assert(save->attrsz[i]);
900 if (save->attrtype[i] == GL_DOUBLE ||
901 save->attrtype[i] == GL_UNSIGNED_INT64_ARB)
902 memcpy(save->current[i], save->attrptr[i], save->attrsz[i] * sizeof(GLfloat));
904 COPY_CLEAN_4V_TYPE_AS_UNION(save->current[i], save->attrsz[i],
905 save->attrptr[i], save->attrtype[i]);
911 copy_from_current(struct gl_context *ctx)
913 struct vbo_save_context *save = &vbo_context(ctx)->save;
914 GLbitfield64 enabled = save->enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));
917 const int i = u_bit_scan64(&enabled);
919 switch (save->attrsz[i]) {
921 save->attrptr[i][3] = save->current[i][3];
924 save->attrptr[i][2] = save->current[i][2];
927 save->attrptr[i][1] = save->current[i][1];
930 save->attrptr[i][0] = save->current[i][0];
933 unreachable("Unexpected vertex attribute size");
940 * Called when we increase the size of a vertex attribute. For example,
941 * if we've seen one or more glTexCoord2f() calls and now we get a
942 * glTexCoord3f() call.
943 * Flush existing data, set new attrib size, replay copied vertices.
946 upgrade_vertex(struct gl_context *ctx, GLuint attr, GLuint newsz)
948 struct vbo_save_context *save = &vbo_context(ctx)->save;
953 /* Store the current run of vertices, and emit a GL_END. Emit a
954 * BEGIN in the new buffer.
956 if (save->vert_count)
959 assert(save->copied.nr == 0);
961 /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
962 * when the attribute already exists in the vertex and is having
963 * its size increased.
965 copy_to_current(ctx);
969 oldsz = save->attrsz[attr];
970 save->attrsz[attr] = newsz;
971 save->enabled |= BITFIELD64_BIT(attr);
973 save->vertex_size += newsz - oldsz;
974 save->max_vert = ((save->vertex_store->bufferobj->Size / sizeof(float) -
975 save->vertex_store->used) /
977 save->vert_count = 0;
979 /* Recalculate all the attrptr[] values:
982 for (i = 0; i < VBO_ATTRIB_MAX; i++) {
983 if (save->attrsz[i]) {
984 save->attrptr[i] = tmp;
985 tmp += save->attrsz[i];
988 save->attrptr[i] = NULL; /* will not be dereferenced. */
992 /* Copy from current to repopulate the vertex with correct values.
994 copy_from_current(ctx);
996 /* Replay stored vertices to translate them to new format here.
998 * If there are copied vertices and the new (upgraded) attribute
999 * has not been defined before, this list is somewhat degenerate,
1000 * and will need fixup at runtime.
1002 if (save->copied.nr) {
1003 const fi_type *data = save->copied.buffer;
1004 fi_type *dest = save->buffer_map;
1006 /* Need to note this and fix up at runtime (or loopback):
1008 if (attr != VBO_ATTRIB_POS && save->currentsz[attr][0] == 0) {
1010 save->dangling_attr_ref = GL_TRUE;
1013 for (i = 0; i < save->copied.nr; i++) {
1014 GLbitfield64 enabled = save->enabled;
1016 const int j = u_bit_scan64(&enabled);
1017 assert(save->attrsz[j]);
1020 COPY_CLEAN_4V_TYPE_AS_UNION(dest, oldsz, data,
1026 COPY_SZ_4V(dest, newsz, save->current[attr]);
1031 GLint sz = save->attrsz[j];
1032 COPY_SZ_4V(dest, sz, data);
1039 save->buffer_ptr = dest;
1040 save->vert_count += save->copied.nr;
1046 * This is called when the size of a vertex attribute changes.
1047 * For example, after seeing one or more glTexCoord2f() calls we
1048 * get a glTexCoord4f() or glTexCoord1f() call.
1051 fixup_vertex(struct gl_context *ctx, GLuint attr,
1052 GLuint sz, GLenum newType)
1054 struct vbo_save_context *save = &vbo_context(ctx)->save;
1056 if (sz > save->attrsz[attr] ||
1057 newType != save->attrtype[attr]) {
1058 /* New size is larger. Need to flush existing vertices and get
1059 * an enlarged vertex format.
1061 upgrade_vertex(ctx, attr, sz);
1063 else if (sz < save->active_sz[attr]) {
1065 const fi_type *id = vbo_get_default_vals_as_union(save->attrtype[attr]);
1067 /* New size is equal or smaller - just need to fill in some
1070 for (i = sz; i <= save->attrsz[attr]; i++)
1071 save->attrptr[attr][i - 1] = id[i - 1];
1074 save->active_sz[attr] = sz;
1079 * Reset the current size of all vertex attributes to the default
1080 * value of 0. This signals that we haven't yet seen any per-vertex
1081 * commands such as glNormal3f() or glTexCoord2f().
1084 reset_vertex(struct gl_context *ctx)
1086 struct vbo_save_context *save = &vbo_context(ctx)->save;
1088 while (save->enabled) {
1089 const int i = u_bit_scan64(&save->enabled);
1090 assert(save->attrsz[i]);
1091 save->attrsz[i] = 0;
1092 save->active_sz[i] = 0;
1095 save->vertex_size = 0;
1100 * If index=0, does glVertexAttrib*() alias glVertex() to emit a vertex?
1101 * It depends on a few things, including whether we're inside or outside
1105 is_vertex_position(const struct gl_context *ctx, GLuint index)
1107 return (index == 0 &&
1108 _mesa_attr_zero_aliases_vertex(ctx) &&
1109 _mesa_inside_dlist_begin_end(ctx));
1114 #define ERROR(err) _mesa_compile_error(ctx, err, __func__);
1117 /* Only one size for each attribute may be active at once. Eg. if
1118 * Color3f is installed/active, then Color4f may not be, even if the
1119 * vertex actually contains 4 color coordinates. This is because the
1120 * 3f version won't otherwise set color[3] to 1.0 -- this is the job
1121 * of the chooser function when switching between Color4f and Color3f.
1123 #define ATTR_UNION(A, N, T, C, V0, V1, V2, V3) \
1125 struct vbo_save_context *save = &vbo_context(ctx)->save; \
1126 int sz = (sizeof(C) / sizeof(GLfloat)); \
1128 if (save->active_sz[A] != N) \
1129 fixup_vertex(ctx, A, N * sz, T); \
1132 C *dest = (C *)save->attrptr[A]; \
1133 if (N>0) dest[0] = V0; \
1134 if (N>1) dest[1] = V1; \
1135 if (N>2) dest[2] = V2; \
1136 if (N>3) dest[3] = V3; \
1137 save->attrtype[A] = T; \
1143 for (i = 0; i < save->vertex_size; i++) \
1144 save->buffer_ptr[i] = save->vertex[i]; \
1146 save->buffer_ptr += save->vertex_size; \
1148 if (++save->vert_count >= save->max_vert) \
1149 wrap_filled_vertex(ctx); \
1153 #define TAG(x) _save_##x
1155 #include "vbo_attrib_tmp.h"
1159 #define MAT( ATTR, N, face, params ) \
1161 if (face != GL_BACK) \
1162 MAT_ATTR( ATTR, N, params ); /* front */ \
1163 if (face != GL_FRONT) \
1164 MAT_ATTR( ATTR + 1, N, params ); /* back */ \
1169 * Save a glMaterial call found between glBegin/End.
1170 * glMaterial calls outside Begin/End are handled in dlist.c.
1172 static void GLAPIENTRY
1173 _save_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
1175 GET_CURRENT_CONTEXT(ctx);
1177 if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
1178 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(face)");
1184 MAT(VBO_ATTRIB_MAT_FRONT_EMISSION, 4, face, params);
1187 MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
1190 MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
1193 MAT(VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params);
1196 if (*params < 0 || *params > ctx->Const.MaxShininess) {
1197 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glMaterial(shininess)");
1200 MAT(VBO_ATTRIB_MAT_FRONT_SHININESS, 1, face, params);
1203 case GL_COLOR_INDEXES:
1204 MAT(VBO_ATTRIB_MAT_FRONT_INDEXES, 3, face, params);
1206 case GL_AMBIENT_AND_DIFFUSE:
1207 MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
1208 MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
1211 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(pname)");
1217 /* Cope with EvalCoord/CallList called within a begin/end object:
1218 * -- Flush current buffer
1219 * -- Fallback to opcodes for the rest of the begin/end object.
1222 dlist_fallback(struct gl_context *ctx)
1224 struct vbo_save_context *save = &vbo_context(ctx)->save;
1226 if (save->vert_count || save->prim_count) {
1227 if (save->prim_count > 0) {
1228 /* Close off in-progress primitive. */
1229 GLint i = save->prim_count - 1;
1230 save->prims[i].count = save->vert_count - save->prims[i].start;
1233 /* Need to replay this display list with loopback,
1234 * unfortunately, otherwise this primitive won't be handled
1237 save->dangling_attr_ref = GL_TRUE;
1239 compile_vertex_list(ctx);
1242 copy_to_current(ctx);
1244 reset_counters(ctx);
1245 if (save->out_of_memory) {
1246 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
1249 _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
1251 ctx->Driver.SaveNeedFlush = GL_FALSE;
1255 static void GLAPIENTRY
1256 _save_EvalCoord1f(GLfloat u)
1258 GET_CURRENT_CONTEXT(ctx);
1259 dlist_fallback(ctx);
1260 CALL_EvalCoord1f(ctx->Save, (u));
1263 static void GLAPIENTRY
1264 _save_EvalCoord1fv(const GLfloat * v)
1266 GET_CURRENT_CONTEXT(ctx);
1267 dlist_fallback(ctx);
1268 CALL_EvalCoord1fv(ctx->Save, (v));
1271 static void GLAPIENTRY
1272 _save_EvalCoord2f(GLfloat u, GLfloat v)
1274 GET_CURRENT_CONTEXT(ctx);
1275 dlist_fallback(ctx);
1276 CALL_EvalCoord2f(ctx->Save, (u, v));
1279 static void GLAPIENTRY
1280 _save_EvalCoord2fv(const GLfloat * v)
1282 GET_CURRENT_CONTEXT(ctx);
1283 dlist_fallback(ctx);
1284 CALL_EvalCoord2fv(ctx->Save, (v));
1287 static void GLAPIENTRY
1288 _save_EvalPoint1(GLint i)
1290 GET_CURRENT_CONTEXT(ctx);
1291 dlist_fallback(ctx);
1292 CALL_EvalPoint1(ctx->Save, (i));
1295 static void GLAPIENTRY
1296 _save_EvalPoint2(GLint i, GLint j)
1298 GET_CURRENT_CONTEXT(ctx);
1299 dlist_fallback(ctx);
1300 CALL_EvalPoint2(ctx->Save, (i, j));
1303 static void GLAPIENTRY
1304 _save_CallList(GLuint l)
1306 GET_CURRENT_CONTEXT(ctx);
1307 dlist_fallback(ctx);
1308 CALL_CallList(ctx->Save, (l));
1311 static void GLAPIENTRY
1312 _save_CallLists(GLsizei n, GLenum type, const GLvoid * v)
1314 GET_CURRENT_CONTEXT(ctx);
1315 dlist_fallback(ctx);
1316 CALL_CallLists(ctx->Save, (n, type, v));
1322 * Called when a glBegin is getting compiled into a display list.
1323 * Updating of ctx->Driver.CurrentSavePrimitive is already taken care of.
1326 vbo_save_NotifyBegin(struct gl_context *ctx, GLenum mode,
1327 bool no_current_update)
1329 struct vbo_save_context *save = &vbo_context(ctx)->save;
1330 const GLuint i = save->prim_count++;
1332 ctx->Driver.CurrentSavePrimitive = mode;
1334 assert(i < save->prim_max);
1335 save->prims[i].mode = mode & VBO_SAVE_PRIM_MODE_MASK;
1336 save->prims[i].begin = 1;
1337 save->prims[i].end = 0;
1338 save->prims[i].start = save->vert_count;
1339 save->prims[i].count = 0;
1341 save->no_current_update = no_current_update;
1343 if (save->out_of_memory) {
1344 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
1347 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt);
1350 /* We need to call vbo_save_SaveFlushVertices() if there's state change */
1351 ctx->Driver.SaveNeedFlush = GL_TRUE;
1355 static void GLAPIENTRY
1358 GET_CURRENT_CONTEXT(ctx);
1359 struct vbo_save_context *save = &vbo_context(ctx)->save;
1360 const GLint i = save->prim_count - 1;
1362 ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
1363 save->prims[i].end = 1;
1364 save->prims[i].count = (save->vert_count - save->prims[i].start);
1366 if (i == (GLint) save->prim_max - 1) {
1367 compile_vertex_list(ctx);
1368 assert(save->copied.nr == 0);
1371 /* Swap out this vertex format while outside begin/end. Any color,
1372 * etc. received between here and the next begin will be compiled
1375 if (save->out_of_memory) {
1376 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
1379 _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
1384 static void GLAPIENTRY
1385 _save_Begin(GLenum mode)
1387 GET_CURRENT_CONTEXT(ctx);
1389 _mesa_compile_error(ctx, GL_INVALID_OPERATION, "Recursive glBegin");
1393 static void GLAPIENTRY
1394 _save_PrimitiveRestartNV(void)
1396 GET_CURRENT_CONTEXT(ctx);
1397 struct vbo_save_context *save = &vbo_context(ctx)->save;
1399 if (save->prim_count == 0) {
1400 /* We're not inside a glBegin/End pair, so calling glPrimitiverRestartNV
1403 _mesa_compile_error(ctx, GL_INVALID_OPERATION,
1404 "glPrimitiveRestartNV called outside glBegin/End");
1406 /* get current primitive mode */
1407 GLenum curPrim = save->prims[save->prim_count - 1].mode;
1408 bool no_current_update = save->no_current_update;
1410 /* restart primitive */
1411 CALL_End(ctx->CurrentServerDispatch, ());
1412 vbo_save_NotifyBegin(ctx, curPrim, no_current_update);
1417 /* Unlike the functions above, these are to be hooked into the vtxfmt
1418 * maintained in ctx->ListState, active when the list is known or
1419 * suspected to be outside any begin/end primitive.
1420 * Note: OBE = Outside Begin/End
1422 static void GLAPIENTRY
1423 _save_OBE_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
1425 GET_CURRENT_CONTEXT(ctx);
1426 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1428 vbo_save_NotifyBegin(ctx, GL_QUADS, false);
1429 CALL_Vertex2f(dispatch, (x1, y1));
1430 CALL_Vertex2f(dispatch, (x2, y1));
1431 CALL_Vertex2f(dispatch, (x2, y2));
1432 CALL_Vertex2f(dispatch, (x1, y2));
1433 CALL_End(dispatch, ());
1437 static void GLAPIENTRY
1438 _save_OBE_Rectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)
1440 _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1443 static void GLAPIENTRY
1444 _save_OBE_Rectdv(const GLdouble *v1, const GLdouble *v2)
1446 _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1449 static void GLAPIENTRY
1450 _save_OBE_Rectfv(const GLfloat *v1, const GLfloat *v2)
1452 _save_OBE_Rectf(v1[0], v1[1], v2[0], v2[1]);
1455 static void GLAPIENTRY
1456 _save_OBE_Recti(GLint x1, GLint y1, GLint x2, GLint y2)
1458 _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1461 static void GLAPIENTRY
1462 _save_OBE_Rectiv(const GLint *v1, const GLint *v2)
1464 _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1467 static void GLAPIENTRY
1468 _save_OBE_Rects(GLshort x1, GLshort y1, GLshort x2, GLshort y2)
1470 _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1473 static void GLAPIENTRY
1474 _save_OBE_Rectsv(const GLshort *v1, const GLshort *v2)
1476 _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1480 _ensure_draws_fits_in_storage(struct gl_context *ctx, int primcount, int vertcount)
1482 struct vbo_save_context *save = &vbo_context(ctx)->save;
1484 bool realloc_prim = save->prim_count + primcount > save->prim_max;
1485 bool realloc_vert = save->vertex_size && (save->vert_count + vertcount >= save->max_vert);
1487 if (realloc_prim || realloc_vert) {
1488 if (save->vert_count || save->prim_count)
1489 compile_vertex_list(ctx);
1490 realloc_storage(ctx, realloc_prim ? primcount : -1, realloc_vert ? vertcount : -1);
1491 reset_counters(ctx);
1492 assert(save->prim_max);
1497 static void GLAPIENTRY
1498 _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count)
1500 GET_CURRENT_CONTEXT(ctx);
1501 struct gl_vertex_array_object *vao = ctx->Array.VAO;
1502 struct vbo_save_context *save = &vbo_context(ctx)->save;
1505 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1506 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawArrays(mode)");
1510 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawArrays(count<0)");
1514 if (save->out_of_memory)
1517 _ensure_draws_fits_in_storage(ctx, 1, count);
1519 /* Make sure to process any VBO binding changes */
1520 _mesa_update_state(ctx);
1522 _mesa_vao_map_arrays(ctx, vao, GL_MAP_READ_BIT);
1524 vbo_save_NotifyBegin(ctx, mode, true);
1526 for (i = 0; i < count; i++)
1527 _mesa_array_element(ctx, start + i);
1528 CALL_End(ctx->CurrentServerDispatch, ());
1530 _mesa_vao_unmap_arrays(ctx, vao);
1534 static void GLAPIENTRY
1535 _save_OBE_MultiDrawArrays(GLenum mode, const GLint *first,
1536 const GLsizei *count, GLsizei primcount)
1538 GET_CURRENT_CONTEXT(ctx);
1541 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1542 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMultiDrawArrays(mode)");
1546 if (primcount < 0) {
1547 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1548 "glMultiDrawArrays(primcount<0)");
1552 unsigned vertcount = 0;
1553 for (i = 0; i < primcount; i++) {
1555 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1556 "glMultiDrawArrays(count[i]<0)");
1559 vertcount += count[i];
1562 _ensure_draws_fits_in_storage(ctx, primcount, vertcount);
1564 for (i = 0; i < primcount; i++) {
1566 _save_OBE_DrawArrays(mode, first[i], count[i]);
1573 array_element(struct gl_context *ctx,
1574 GLint basevertex, GLuint elt, unsigned index_size_shift)
1576 /* Section 10.3.5 Primitive Restart:
1578 * When one of the *BaseVertex drawing commands specified in section 10.5
1579 * is used, the primitive restart comparison occurs before the basevertex
1580 * offset is added to the array index.
1582 /* If PrimitiveRestart is enabled and the index is the RestartIndex
1583 * then we call PrimitiveRestartNV and return.
1585 if (ctx->Array._PrimitiveRestart[index_size_shift] &&
1586 elt == ctx->Array._RestartIndex[index_size_shift]) {
1587 CALL_PrimitiveRestartNV(ctx->CurrentServerDispatch, ());
1591 _mesa_array_element(ctx, basevertex + elt);
1595 /* Could do better by copying the arrays and element list intact and
1596 * then emitting an indexed prim at runtime.
1598 static void GLAPIENTRY
1599 _save_OBE_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1600 const GLvoid * indices, GLint basevertex)
1602 GET_CURRENT_CONTEXT(ctx);
1603 struct vbo_save_context *save = &vbo_context(ctx)->save;
1604 struct gl_vertex_array_object *vao = ctx->Array.VAO;
1605 struct gl_buffer_object *indexbuf = vao->IndexBufferObj;
1608 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1609 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawElements(mode)");
1613 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawElements(count<0)");
1616 if (type != GL_UNSIGNED_BYTE &&
1617 type != GL_UNSIGNED_SHORT &&
1618 type != GL_UNSIGNED_INT) {
1619 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawElements(count<0)");
1623 if (save->out_of_memory)
1626 _ensure_draws_fits_in_storage(ctx, 1, count);
1628 /* Make sure to process any VBO binding changes */
1629 _mesa_update_state(ctx);
1631 _mesa_vao_map(ctx, vao, GL_MAP_READ_BIT);
1635 ADD_POINTERS(indexbuf->Mappings[MAP_INTERNAL].Pointer, indices);
1637 vbo_save_NotifyBegin(ctx, mode, true);
1640 case GL_UNSIGNED_BYTE:
1641 for (i = 0; i < count; i++)
1642 array_element(ctx, basevertex, ((GLubyte *) indices)[i], 0);
1644 case GL_UNSIGNED_SHORT:
1645 for (i = 0; i < count; i++)
1646 array_element(ctx, basevertex, ((GLushort *) indices)[i], 1);
1648 case GL_UNSIGNED_INT:
1649 for (i = 0; i < count; i++)
1650 array_element(ctx, basevertex, ((GLuint *) indices)[i], 2);
1653 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawElements(type)");
1657 CALL_End(ctx->CurrentServerDispatch, ());
1659 _mesa_vao_unmap(ctx, vao);
1662 static void GLAPIENTRY
1663 _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type,
1664 const GLvoid * indices)
1666 _save_OBE_DrawElementsBaseVertex(mode, count, type, indices, 0);
1670 static void GLAPIENTRY
1671 _save_OBE_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
1672 GLsizei count, GLenum type,
1673 const GLvoid * indices)
1675 GET_CURRENT_CONTEXT(ctx);
1676 struct vbo_save_context *save = &vbo_context(ctx)->save;
1678 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1679 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(mode)");
1683 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1684 "glDrawRangeElements(count<0)");
1687 if (type != GL_UNSIGNED_BYTE &&
1688 type != GL_UNSIGNED_SHORT &&
1689 type != GL_UNSIGNED_INT) {
1690 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(type)");
1694 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1695 "glDrawRangeElements(end < start)");
1699 if (save->out_of_memory)
1702 _save_OBE_DrawElements(mode, count, type, indices);
1706 static void GLAPIENTRY
1707 _save_OBE_MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type,
1708 const GLvoid * const *indices, GLsizei primcount)
1710 GET_CURRENT_CONTEXT(ctx);
1711 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1715 for (i = 0; i < primcount; i++) {
1716 vertcount += count[i];
1718 _ensure_draws_fits_in_storage(ctx, primcount, vertcount);
1720 for (i = 0; i < primcount; i++) {
1722 CALL_DrawElements(dispatch, (mode, count[i], type, indices[i]));
1728 static void GLAPIENTRY
1729 _save_OBE_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count,
1731 const GLvoid * const *indices,
1733 const GLint *basevertex)
1735 GET_CURRENT_CONTEXT(ctx);
1736 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1740 for (i = 0; i < primcount; i++) {
1741 vertcount += count[i];
1743 _ensure_draws_fits_in_storage(ctx, primcount, vertcount);
1745 for (i = 0; i < primcount; i++) {
1747 CALL_DrawElementsBaseVertex(dispatch, (mode, count[i], type,
1756 vtxfmt_init(struct gl_context *ctx)
1758 struct vbo_save_context *save = &vbo_context(ctx)->save;
1759 GLvertexformat *vfmt = &save->vtxfmt;
1761 #define NAME_AE(x) _ae_##x
1762 #define NAME_CALLLIST(x) _save_##x
1763 #define NAME(x) _save_##x
1764 #define NAME_ES(x) _save_##x##ARB
1766 #include "vbo_init_tmp.h"
1771 * Initialize the dispatch table with the VBO functions for display
1775 vbo_initialize_save_dispatch(const struct gl_context *ctx,
1776 struct _glapi_table *exec)
1778 SET_DrawArrays(exec, _save_OBE_DrawArrays);
1779 SET_MultiDrawArrays(exec, _save_OBE_MultiDrawArrays);
1780 SET_DrawElements(exec, _save_OBE_DrawElements);
1781 SET_DrawElementsBaseVertex(exec, _save_OBE_DrawElementsBaseVertex);
1782 SET_DrawRangeElements(exec, _save_OBE_DrawRangeElements);
1783 SET_MultiDrawElementsEXT(exec, _save_OBE_MultiDrawElements);
1784 SET_MultiDrawElementsBaseVertex(exec, _save_OBE_MultiDrawElementsBaseVertex);
1785 SET_Rectf(exec, _save_OBE_Rectf);
1786 SET_Rectd(exec, _save_OBE_Rectd);
1787 SET_Rectdv(exec, _save_OBE_Rectdv);
1788 SET_Rectfv(exec, _save_OBE_Rectfv);
1789 SET_Recti(exec, _save_OBE_Recti);
1790 SET_Rectiv(exec, _save_OBE_Rectiv);
1791 SET_Rects(exec, _save_OBE_Rects);
1792 SET_Rectsv(exec, _save_OBE_Rectsv);
1794 /* Note: other glDraw functins aren't compiled into display lists */
1800 vbo_save_SaveFlushVertices(struct gl_context *ctx)
1802 struct vbo_save_context *save = &vbo_context(ctx)->save;
1804 /* Noop when we are actually active:
1806 if (ctx->Driver.CurrentSavePrimitive <= PRIM_MAX)
1809 if (save->vert_count || save->prim_count)
1810 compile_vertex_list(ctx);
1812 copy_to_current(ctx);
1814 reset_counters(ctx);
1815 ctx->Driver.SaveNeedFlush = GL_FALSE;
1820 * Called from glNewList when we're starting to compile a display list.
1823 vbo_save_NewList(struct gl_context *ctx, GLuint list, GLenum mode)
1825 struct vbo_save_context *save = &vbo_context(ctx)->save;
1830 if (!save->prim_store)
1831 save->prim_store = alloc_prim_store(0);
1833 if (!save->vertex_store)
1834 save->vertex_store = alloc_vertex_store(ctx, 0);
1836 save->buffer_ptr = vbo_save_map_vertex_store(ctx, save->vertex_store);
1839 reset_counters(ctx);
1840 ctx->Driver.SaveNeedFlush = GL_FALSE;
1845 * Called from glEndList when we're finished compiling a display list.
1848 vbo_save_EndList(struct gl_context *ctx)
1850 struct vbo_save_context *save = &vbo_context(ctx)->save;
1852 /* EndList called inside a (saved) Begin/End pair?
1854 if (_mesa_inside_dlist_begin_end(ctx)) {
1855 if (save->prim_count > 0) {
1856 GLint i = save->prim_count - 1;
1857 ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
1858 save->prims[i].end = 0;
1859 save->prims[i].count = save->vert_count - save->prims[i].start;
1862 /* Make sure this vertex list gets replayed by the "loopback"
1865 save->dangling_attr_ref = GL_TRUE;
1866 vbo_save_SaveFlushVertices(ctx);
1868 /* Swap out this vertex format while outside begin/end. Any color,
1869 * etc. received between here and the next begin will be compiled
1872 _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
1875 vbo_save_unmap_vertex_store(ctx, save->vertex_store);
1877 assert(save->vertex_size == 0);
1882 * Called from the display list code when we're about to execute a
1886 vbo_save_BeginCallList(struct gl_context *ctx, struct gl_display_list *dlist)
1888 struct vbo_save_context *save = &vbo_context(ctx)->save;
1889 save->replay_flags |= dlist->Flags;
1894 * Called from the display list code when we're finished executing a
1898 vbo_save_EndCallList(struct gl_context *ctx)
1900 struct vbo_save_context *save = &vbo_context(ctx)->save;
1902 if (ctx->ListState.CallDepth == 1)
1903 save->replay_flags = 0;
1908 * Called by display list code when a display list is being deleted.
1911 vbo_destroy_vertex_list(struct gl_context *ctx, void *data)
1913 struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *) data;
1915 for (gl_vertex_processing_mode vpm = VP_MODE_FF; vpm < VP_MODE_MAX; ++vpm)
1916 _mesa_reference_vao(ctx, &node->VAO[vpm], NULL);
1918 if (--node->prim_store->refcount == 0) {
1919 free(node->prim_store->prims);
1920 free(node->prim_store);
1923 free(node->merged.prims);
1925 _mesa_reference_buffer_object(ctx, &node->merged.ib.obj, NULL);
1926 free(node->current_data);
1927 node->current_data = NULL;
1932 vbo_print_vertex_list(struct gl_context *ctx, void *data, FILE *f)
1934 struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *) data;
1936 struct gl_buffer_object *buffer = node->VAO[0]->BufferBinding[0].BufferObj;
1937 const GLuint vertex_size = _vbo_save_get_stride(node)/sizeof(GLfloat);
1940 fprintf(f, "VBO-VERTEX-LIST, %u vertices, %d primitives, %d vertsize, "
1942 node->vertex_count, node->prim_count, vertex_size,
1945 for (i = 0; i < node->prim_count; i++) {
1946 struct _mesa_prim *prim = &node->prims[i];
1947 fprintf(f, " prim %d: %s %d..%d %s %s\n",
1949 _mesa_lookup_prim_by_nr(prim->mode),
1951 prim->start + prim->count,
1952 (prim->begin) ? "BEGIN" : "(wrap)",
1953 (prim->end) ? "END" : "(wrap)");
1959 * Called during context creation/init.
1962 current_init(struct gl_context *ctx)
1964 struct vbo_save_context *save = &vbo_context(ctx)->save;
1967 for (i = VBO_ATTRIB_POS; i <= VBO_ATTRIB_GENERIC15; i++) {
1968 const GLuint j = i - VBO_ATTRIB_POS;
1969 assert(j < VERT_ATTRIB_MAX);
1970 save->currentsz[i] = &ctx->ListState.ActiveAttribSize[j];
1971 save->current[i] = (fi_type *) ctx->ListState.CurrentAttrib[j];
1974 for (i = VBO_ATTRIB_FIRST_MATERIAL; i <= VBO_ATTRIB_LAST_MATERIAL; i++) {
1975 const GLuint j = i - VBO_ATTRIB_FIRST_MATERIAL;
1976 assert(j < MAT_ATTRIB_MAX);
1977 save->currentsz[i] = &ctx->ListState.ActiveMaterialSize[j];
1978 save->current[i] = (fi_type *) ctx->ListState.CurrentMaterial[j];
1984 * Initialize the display list compiler. Called during context creation.
1987 vbo_save_api_init(struct vbo_save_context *save)
1989 struct gl_context *ctx = gl_context_from_vbo_save(save);
1991 save->opcode_vertex_list =
1992 _mesa_dlist_alloc_opcode(ctx,
1993 sizeof(struct vbo_save_vertex_list),
1994 vbo_save_playback_vertex_list,
1995 vbo_destroy_vertex_list,
1996 vbo_print_vertex_list);
2000 _mesa_noop_vtxfmt_init(ctx, &save->vtxfmt_noop);