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);
257 assert(store->refcount == 0);
259 store->prims = realloc(store->prims,
260 store->size * sizeof(struct _mesa_prim));
261 memset(store->prims, 0, store->size * sizeof(struct _mesa_prim));
269 reset_counters(struct gl_context *ctx)
271 struct vbo_save_context *save = &vbo_context(ctx)->save;
273 save->prims = save->prim_store->prims + save->prim_store->used;
274 save->buffer_map = save->vertex_store->buffer_map + save->vertex_store->used;
276 assert(save->buffer_map == save->buffer_ptr);
278 if (save->vertex_size)
279 save->max_vert = (save->vertex_store->bufferobj->Size / sizeof(float) - save->vertex_store->used) /
284 save->vert_count = 0;
285 save->prim_count = 0;
286 save->prim_max = save->prim_store->size - save->prim_store->used;
287 save->dangling_attr_ref = GL_FALSE;
291 * For a list of prims, try merging prims that can just be extensions of the
295 merge_prims(struct gl_context *ctx, struct _mesa_prim *prim_list,
299 struct _mesa_prim *prev_prim = prim_list;
301 for (i = 1; i < *prim_count; i++) {
302 struct _mesa_prim *this_prim = prim_list + i;
304 vbo_try_prim_conversion(this_prim);
306 if (vbo_merge_draws(ctx, true, prev_prim, this_prim)) {
307 /* We've found a prim that just extend the previous one. Tack it
308 * onto the previous one, and let this primitive struct get dropped.
313 /* If any previous primitives have been dropped, then we need to copy
314 * this later one into the next available slot.
317 if (prev_prim != this_prim)
318 *prev_prim = *this_prim;
321 *prim_count = prev_prim - prim_list + 1;
326 * Convert GL_LINE_LOOP primitive into GL_LINE_STRIP so that drivers
327 * don't have to worry about handling the _mesa_prim::begin/end flags.
328 * See https://bugs.freedesktop.org/show_bug.cgi?id=81174
331 convert_line_loop_to_strip(struct vbo_save_context *save,
332 struct vbo_save_vertex_list *node)
334 struct _mesa_prim *prim = &node->prims[node->prim_count - 1];
336 assert(prim->mode == GL_LINE_LOOP);
339 /* Copy the 0th vertex to end of the buffer and extend the
340 * vertex count by one to finish the line loop.
342 const GLuint sz = save->vertex_size;
344 const fi_type *src = save->buffer_map + prim->start * sz;
346 fi_type *dst = save->buffer_map + (prim->start + prim->count) * sz;
348 memcpy(dst, src, sz * sizeof(float));
351 node->vertex_count++;
353 save->buffer_ptr += sz;
354 save->vertex_store->used += sz;
358 /* Drawing the second or later section of a long line loop.
359 * Skip the 0th vertex.
365 prim->mode = GL_LINE_STRIP;
369 /* Compare the present vao if it has the same setup. */
371 compare_vao(gl_vertex_processing_mode mode,
372 const struct gl_vertex_array_object *vao,
373 const struct gl_buffer_object *bo, GLintptr buffer_offset,
374 GLuint stride, GLbitfield64 vao_enabled,
375 const GLubyte size[VBO_ATTRIB_MAX],
376 const GLenum16 type[VBO_ATTRIB_MAX],
377 const GLuint offset[VBO_ATTRIB_MAX])
382 /* If the enabled arrays are not the same we are not equal. */
383 if (vao_enabled != vao->Enabled)
386 /* Check the buffer binding at 0 */
387 if (vao->BufferBinding[0].BufferObj != bo)
389 /* BufferBinding[0].Offset != buffer_offset is checked per attribute */
390 if (vao->BufferBinding[0].Stride != stride)
392 assert(vao->BufferBinding[0].InstanceDivisor == 0);
394 /* Retrieve the mapping from VBO_ATTRIB to VERT_ATTRIB space */
395 const GLubyte *const vao_to_vbo_map = _vbo_attribute_alias_map[mode];
397 /* Now check the enabled arrays */
398 GLbitfield mask = vao_enabled;
400 const int attr = u_bit_scan(&mask);
401 const unsigned char vbo_attr = vao_to_vbo_map[attr];
402 const GLenum16 tp = type[vbo_attr];
403 const GLintptr off = offset[vbo_attr] + buffer_offset;
404 const struct gl_array_attributes *attrib = &vao->VertexAttrib[attr];
405 if (attrib->RelativeOffset + vao->BufferBinding[0].Offset != off)
407 if (attrib->Format.Type != tp)
409 if (attrib->Format.Size != size[vbo_attr])
411 assert(attrib->Format.Format == GL_RGBA);
412 assert(attrib->Format.Normalized == GL_FALSE);
413 assert(attrib->Format.Integer == vbo_attrtype_to_integer_flag(tp));
414 assert(attrib->Format.Doubles == vbo_attrtype_to_double_flag(tp));
415 assert(attrib->BufferBindingIndex == 0);
422 /* Create or reuse the vao for the vertex processing mode. */
424 update_vao(struct gl_context *ctx,
425 gl_vertex_processing_mode mode,
426 struct gl_vertex_array_object **vao,
427 struct gl_buffer_object *bo, GLintptr buffer_offset,
428 GLuint stride, GLbitfield64 vbo_enabled,
429 const GLubyte size[VBO_ATTRIB_MAX],
430 const GLenum16 type[VBO_ATTRIB_MAX],
431 const GLuint offset[VBO_ATTRIB_MAX])
433 /* Compute the bitmasks of vao_enabled arrays */
434 GLbitfield vao_enabled = _vbo_get_vao_enabled_from_vbo(mode, vbo_enabled);
437 * Check if we can possibly reuse the exisiting one.
438 * In the long term we should reset them when something changes.
440 if (compare_vao(mode, *vao, bo, buffer_offset, stride,
441 vao_enabled, size, type, offset))
444 /* The initial refcount is 1 */
445 _mesa_reference_vao(ctx, vao, NULL);
446 *vao = _mesa_new_vao(ctx, ~((GLuint)0));
449 * assert(stride <= ctx->Const.MaxVertexAttribStride);
450 * MaxVertexAttribStride is not set for drivers that does not
451 * expose GL 44 or GLES 31.
454 /* Bind the buffer object at binding point 0 */
455 _mesa_bind_vertex_buffer(ctx, *vao, 0, bo, buffer_offset, stride, false,
458 /* Retrieve the mapping from VBO_ATTRIB to VERT_ATTRIB space
459 * Note that the position/generic0 aliasing is done in the VAO.
461 const GLubyte *const vao_to_vbo_map = _vbo_attribute_alias_map[mode];
462 /* Now set the enable arrays */
463 GLbitfield mask = vao_enabled;
465 const int vao_attr = u_bit_scan(&mask);
466 const GLubyte vbo_attr = vao_to_vbo_map[vao_attr];
467 assert(offset[vbo_attr] <= ctx->Const.MaxVertexAttribRelativeOffset);
469 _vbo_set_attrib_format(ctx, *vao, vao_attr, buffer_offset,
470 size[vbo_attr], type[vbo_attr], offset[vbo_attr]);
471 _mesa_vertex_attrib_binding(ctx, *vao, vao_attr, 0);
473 _mesa_enable_vertex_array_attribs(ctx, *vao, vao_enabled);
474 assert(vao_enabled == (*vao)->Enabled);
475 assert((vao_enabled & ~(*vao)->VertexAttribBufferMask) == 0);
477 /* Finalize and freeze the VAO */
478 _mesa_set_vao_immutable(ctx, *vao);
483 realloc_storage(struct gl_context *ctx, int prim_count, int vertex_count)
485 struct vbo_save_context *save = &vbo_context(ctx)->save;
486 if (vertex_count >= 0) {
489 vbo_save_unmap_vertex_store(ctx, save->vertex_store);
491 /* Release old reference:
493 free_vertex_store(ctx, save->vertex_store);
494 save->vertex_store = NULL;
495 /* When we have a new vbo, we will for sure need a new vao */
496 for (gl_vertex_processing_mode vpm = 0; vpm < VP_MODE_MAX; ++vpm)
497 _mesa_reference_vao(ctx, &save->VAO[vpm], NULL);
499 /* Allocate and map new store:
501 save->vertex_store = alloc_vertex_store(ctx, vertex_count);
502 save->buffer_ptr = vbo_save_map_vertex_store(ctx, save->vertex_store);
503 save->out_of_memory = save->buffer_ptr == NULL;
506 if (prim_count >= 0) {
507 save->prim_store->refcount--;
508 save->prim_store = alloc_prim_store(prim_count);
514 * Insert the active immediate struct onto the display list currently
518 compile_vertex_list(struct gl_context *ctx)
520 struct vbo_save_context *save = &vbo_context(ctx)->save;
521 struct vbo_save_vertex_list *node;
523 /* Allocate space for this structure in the display list currently
526 node = (struct vbo_save_vertex_list *)
527 _mesa_dlist_alloc_aligned(ctx, save->opcode_vertex_list, sizeof(*node));
532 /* Make sure the pointer is aligned to the size of a pointer */
533 assert((GLintptr) node % sizeof(void *) == 0);
535 /* Duplicate our template, increment refcounts to the storage structs:
537 GLintptr old_offset = 0;
539 old_offset = save->VAO[0]->BufferBinding[0].Offset
540 + save->VAO[0]->VertexAttrib[VERT_ATTRIB_POS].RelativeOffset;
542 const GLsizei stride = save->vertex_size*sizeof(GLfloat);
543 GLintptr buffer_offset =
544 (save->buffer_map - save->vertex_store->buffer_map) * sizeof(GLfloat);
545 assert(old_offset <= buffer_offset);
546 const GLintptr offset_diff = buffer_offset - old_offset;
547 GLuint start_offset = 0;
548 if (offset_diff > 0 && stride > 0 && offset_diff % stride == 0) {
549 /* The vertex size is an exact multiple of the buffer offset.
550 * This means that we can use zero-based vertex attribute pointers
551 * and specify the start of the primitive with the _mesa_prim::start
552 * field. This results in issuing several draw calls with identical
553 * vertex attribute information. This can result in fewer state
554 * changes in drivers. In particular, the Gallium CSO module will
555 * filter out redundant vertex buffer changes.
557 /* We cannot immediately update the primitives as some methods below
558 * still need the uncorrected start vertices
560 start_offset = offset_diff/stride;
561 assert(old_offset == buffer_offset - offset_diff);
562 buffer_offset = old_offset;
564 GLuint offsets[VBO_ATTRIB_MAX];
565 for (unsigned i = 0, offset = 0; i < VBO_ATTRIB_MAX; ++i) {
567 offset += save->attrsz[i] * sizeof(GLfloat);
569 node->vertex_count = save->vert_count;
570 node->wrap_count = save->copied.nr;
571 node->prims = save->prims;
572 node->prim_count = save->prim_count;
573 node->prim_store = save->prim_store;
575 /* Create a pair of VAOs for the possible VERTEX_PROCESSING_MODEs
576 * Note that this may reuse the previous one of possible.
578 for (gl_vertex_processing_mode vpm = VP_MODE_FF; vpm < VP_MODE_MAX; ++vpm) {
579 /* create or reuse the vao */
580 update_vao(ctx, vpm, &save->VAO[vpm],
581 save->vertex_store->bufferobj, buffer_offset, stride,
582 save->enabled, save->attrsz, save->attrtype, offsets);
583 /* Reference the vao in the dlist */
584 node->VAO[vpm] = NULL;
585 _mesa_reference_vao(ctx, &node->VAO[vpm], save->VAO[vpm]);
588 node->prim_store->refcount++;
590 if (save->no_current_update) {
591 node->current_data = NULL;
594 GLuint current_size = save->vertex_size - save->attrsz[0];
595 node->current_data = NULL;
598 node->current_data = malloc(current_size * sizeof(GLfloat));
599 if (node->current_data) {
600 const char *buffer = (const char *)save->buffer_map;
601 unsigned attr_offset = save->attrsz[0] * sizeof(GLfloat);
602 unsigned vertex_offset = 0;
604 if (node->vertex_count)
605 vertex_offset = (node->vertex_count - 1) * stride;
607 memcpy(node->current_data, buffer + vertex_offset + attr_offset,
608 current_size * sizeof(GLfloat));
610 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Current value allocation");
615 assert(save->attrsz[VBO_ATTRIB_POS] != 0 || node->vertex_count == 0);
617 if (save->dangling_attr_ref)
618 ctx->ListState.CurrentList->Flags |= DLIST_DANGLING_REFS;
620 save->vertex_store->used += save->vertex_size * node->vertex_count;
621 save->prim_store->used += node->prim_count;
623 /* Copy duplicated vertices
625 save->copied.nr = copy_vertices(ctx, node, save->buffer_map);
627 if (node->prims[node->prim_count - 1].mode == GL_LINE_LOOP) {
628 convert_line_loop_to_strip(save, node);
631 merge_prims(ctx, node->prims, &node->prim_count);
633 /* Correct the primitive starts, we can only do this here as copy_vertices
634 * and convert_line_loop_to_strip above consume the uncorrected starts.
635 * On the other hand the _vbo_loopback_vertex_list call below needs the
636 * primitves to be corrected already.
638 for (unsigned i = 0; i < node->prim_count; i++) {
639 node->prims[i].start += start_offset;
642 /* Create an index buffer. */
643 node->min_index = node->max_index = 0;
644 if (save->vert_count) {
645 int end = node->prims[node->prim_count - 1].start +
646 node->prims[node->prim_count - 1].count;
647 int total_vert_count = end - node->prims[0].start;
648 /* Estimate for the worst case: all prims are line strips (the +1 is because
649 * wrap_buffers may call use but the last primitive may not be complete) */
650 int max_indices_count = MAX2(total_vert_count * 2 - (node->prim_count * 2) + 1,
652 int size = max_indices_count * sizeof(uint32_t);
653 uint32_t* indices = (uint32_t*) malloc(size);
654 uint32_t max_index = 0, min_index = 0xFFFFFFFF;
658 int last_valid_prim = -1;
659 /* Construct indices array. */
660 for (unsigned i = 0; i < node->prim_count; i++) {
661 assert(node->prims[i].basevertex == 0);
662 GLubyte mode = node->prims[i].mode;
664 int vertex_count = node->prims[i].count;
669 /* Line strips get converted to lines */
670 if (mode == GL_LINE_STRIP)
673 /* If 2 consecutive prims use the same mode => merge them. */
674 bool merge_prims = last_valid_prim >= 0 &&
675 mode == node->prims[last_valid_prim].mode &&
676 mode != GL_LINE_LOOP && mode != GL_TRIANGLE_FAN &&
677 mode != GL_QUAD_STRIP && mode != GL_POLYGON &&
680 /* To be able to merge consecutive triangle strips we need to insert
681 * a degenerate triangle.
684 mode == GL_TRIANGLE_STRIP) {
685 /* Insert a degenerate triangle */
686 assert(node->prims[last_valid_prim].mode == GL_TRIANGLE_STRIP);
687 unsigned tri_count = node->prims[last_valid_prim].count - 2;
689 indices[idx] = indices[idx - 1];
690 indices[idx + 1] = node->prims[i].start;
692 node->prims[last_valid_prim].count += 2;
695 /* Add another index to preserve winding order */
696 indices[idx++] = node->prims[i].start;
697 node->prims[last_valid_prim].count++;
703 /* Convert line strips to lines if it'll allow if the previous
704 * prim mode is GL_LINES (so merge_prims is true) or if the next
705 * primitive mode is GL_LINES or GL_LINE_LOOP.
707 if (node->prims[i].mode == GL_LINE_STRIP &&
709 (i < node->prim_count - 1 &&
710 (node->prims[i + 1].mode == GL_LINE_STRIP ||
711 node->prims[i + 1].mode == GL_LINES)))) {
712 for (unsigned j = 0; j < vertex_count; j++) {
713 indices[idx++] = node->prims[i].start + j;
714 /* Repeat all but the first/last indices. */
715 if (j && j != vertex_count - 1) {
716 indices[idx++] = node->prims[i].start + j;
717 node->prims[i].count++;
720 node->prims[i].mode = mode;
722 for (unsigned j = 0; j < vertex_count; j++) {
723 indices[idx++] = node->prims[i].start + j;
727 min_index = MIN2(min_index, indices[start]);
728 max_index = MAX2(max_index, indices[idx - 1]);
731 /* Update vertex count. */
732 node->prims[last_valid_prim].count += idx - start;
734 /* Keep this primitive */
735 last_valid_prim += 1;
736 assert(last_valid_prim <= i);
737 node->prims[i].start = start;
738 node->prims[last_valid_prim] = node->prims[i];
745 assert(idx <= max_indices_count);
747 node->prim_count = last_valid_prim + 1;
749 node->ib.count = idx;
750 node->ib.index_size_shift = (GL_UNSIGNED_INT - GL_UNSIGNED_BYTE) >> 1;
751 node->min_index = min_index;
752 node->max_index = max_index;
754 node->ib.obj = ctx->Driver.NewBufferObject(ctx, VBO_BUF_ID + 1);
755 bool success = ctx->Driver.BufferData(ctx,
756 GL_ELEMENT_ARRAY_BUFFER_ARB,
757 idx * sizeof(uint32_t), indices,
758 GL_STATIC_DRAW_ARB, GL_MAP_WRITE_BIT,
764 ctx->Driver.DeleteBuffer(ctx, node->ib.obj);
765 _mesa_error(ctx, GL_OUT_OF_MEMORY, "IB allocation");
769 node->vertex_count = 0;
770 node->prim_count = 0;
778 /* Deal with GL_COMPILE_AND_EXECUTE:
780 if (ctx->ExecuteFlag) {
781 struct _glapi_table *dispatch = GET_DISPATCH();
783 _glapi_set_dispatch(ctx->Exec);
785 /* Note that the range of referenced vertices must be mapped already */
786 _vbo_loopback_vertex_list(ctx, node);
788 _glapi_set_dispatch(dispatch);
791 /* Decide whether the storage structs are full, or can be used for
792 * the next vertex lists as well.
794 if (save->vertex_store->used >
795 save->vertex_store->bufferobj->Size / sizeof(float) - 16 * (save->vertex_size + 4)) {
796 realloc_storage(ctx, -1, 0);
799 /* update buffer_ptr for next vertex */
800 save->buffer_ptr = save->vertex_store->buffer_map
801 + save->vertex_store->used;
804 if (save->prim_store->used > save->prim_store->size - 6) {
805 realloc_storage(ctx, 0, -1);
808 /* Reset our structures for the next run of vertices:
815 * This is called when we fill a vertex buffer before we hit a glEnd().
817 * TODO -- If no new vertices have been stored, don't bother saving it.
820 wrap_buffers(struct gl_context *ctx)
822 struct vbo_save_context *save = &vbo_context(ctx)->save;
823 GLint i = save->prim_count - 1;
826 assert(i < (GLint) save->prim_max);
829 /* Close off in-progress primitive.
831 save->prims[i].count = (save->vert_count - save->prims[i].start);
832 mode = save->prims[i].mode;
834 /* store the copied vertices, and allocate a new list.
836 compile_vertex_list(ctx);
838 /* Restart interrupted primitive
840 save->prims[0].mode = mode;
841 save->prims[0].begin = 0;
842 save->prims[0].end = 0;
843 save->prims[0].start = 0;
844 save->prims[0].count = 0;
845 save->prim_count = 1;
850 * Called only when buffers are wrapped as the result of filling the
851 * vertex_store struct.
854 wrap_filled_vertex(struct gl_context *ctx)
856 struct vbo_save_context *save = &vbo_context(ctx)->save;
857 unsigned numComponents;
859 /* Emit a glEnd to close off the last vertex list.
863 /* Copy stored stored vertices to start of new list.
865 assert(save->max_vert - save->vert_count > save->copied.nr);
867 numComponents = save->copied.nr * save->vertex_size;
868 memcpy(save->buffer_ptr,
870 numComponents * sizeof(fi_type));
871 save->buffer_ptr += numComponents;
872 save->vert_count += save->copied.nr;
877 copy_to_current(struct gl_context *ctx)
879 struct vbo_save_context *save = &vbo_context(ctx)->save;
880 GLbitfield64 enabled = save->enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));
883 const int i = u_bit_scan64(&enabled);
884 assert(save->attrsz[i]);
886 if (save->attrtype[i] == GL_DOUBLE ||
887 save->attrtype[i] == GL_UNSIGNED_INT64_ARB)
888 memcpy(save->current[i], save->attrptr[i], save->attrsz[i] * sizeof(GLfloat));
890 COPY_CLEAN_4V_TYPE_AS_UNION(save->current[i], save->attrsz[i],
891 save->attrptr[i], save->attrtype[i]);
897 copy_from_current(struct gl_context *ctx)
899 struct vbo_save_context *save = &vbo_context(ctx)->save;
900 GLbitfield64 enabled = save->enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));
903 const int i = u_bit_scan64(&enabled);
905 switch (save->attrsz[i]) {
907 save->attrptr[i][3] = save->current[i][3];
910 save->attrptr[i][2] = save->current[i][2];
913 save->attrptr[i][1] = save->current[i][1];
916 save->attrptr[i][0] = save->current[i][0];
919 unreachable("Unexpected vertex attribute size");
926 * Called when we increase the size of a vertex attribute. For example,
927 * if we've seen one or more glTexCoord2f() calls and now we get a
928 * glTexCoord3f() call.
929 * Flush existing data, set new attrib size, replay copied vertices.
932 upgrade_vertex(struct gl_context *ctx, GLuint attr, GLuint newsz)
934 struct vbo_save_context *save = &vbo_context(ctx)->save;
939 /* Store the current run of vertices, and emit a GL_END. Emit a
940 * BEGIN in the new buffer.
942 if (save->vert_count)
945 assert(save->copied.nr == 0);
947 /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
948 * when the attribute already exists in the vertex and is having
949 * its size increased.
951 copy_to_current(ctx);
955 oldsz = save->attrsz[attr];
956 save->attrsz[attr] = newsz;
957 save->enabled |= BITFIELD64_BIT(attr);
959 save->vertex_size += newsz - oldsz;
960 save->max_vert = ((save->vertex_store->bufferobj->Size / sizeof(float) -
961 save->vertex_store->used) /
963 save->vert_count = 0;
965 /* Recalculate all the attrptr[] values:
968 for (i = 0; i < VBO_ATTRIB_MAX; i++) {
969 if (save->attrsz[i]) {
970 save->attrptr[i] = tmp;
971 tmp += save->attrsz[i];
974 save->attrptr[i] = NULL; /* will not be dereferenced. */
978 /* Copy from current to repopulate the vertex with correct values.
980 copy_from_current(ctx);
982 /* Replay stored vertices to translate them to new format here.
984 * If there are copied vertices and the new (upgraded) attribute
985 * has not been defined before, this list is somewhat degenerate,
986 * and will need fixup at runtime.
988 if (save->copied.nr) {
989 const fi_type *data = save->copied.buffer;
990 fi_type *dest = save->buffer_map;
992 /* Need to note this and fix up at runtime (or loopback):
994 if (attr != VBO_ATTRIB_POS && save->currentsz[attr][0] == 0) {
996 save->dangling_attr_ref = GL_TRUE;
999 for (i = 0; i < save->copied.nr; i++) {
1000 GLbitfield64 enabled = save->enabled;
1002 const int j = u_bit_scan64(&enabled);
1003 assert(save->attrsz[j]);
1006 COPY_CLEAN_4V_TYPE_AS_UNION(dest, oldsz, data,
1012 COPY_SZ_4V(dest, newsz, save->current[attr]);
1017 GLint sz = save->attrsz[j];
1018 COPY_SZ_4V(dest, sz, data);
1025 save->buffer_ptr = dest;
1026 save->vert_count += save->copied.nr;
1032 * This is called when the size of a vertex attribute changes.
1033 * For example, after seeing one or more glTexCoord2f() calls we
1034 * get a glTexCoord4f() or glTexCoord1f() call.
1037 fixup_vertex(struct gl_context *ctx, GLuint attr,
1038 GLuint sz, GLenum newType)
1040 struct vbo_save_context *save = &vbo_context(ctx)->save;
1042 if (sz > save->attrsz[attr] ||
1043 newType != save->attrtype[attr]) {
1044 /* New size is larger. Need to flush existing vertices and get
1045 * an enlarged vertex format.
1047 upgrade_vertex(ctx, attr, sz);
1049 else if (sz < save->active_sz[attr]) {
1051 const fi_type *id = vbo_get_default_vals_as_union(save->attrtype[attr]);
1053 /* New size is equal or smaller - just need to fill in some
1056 for (i = sz; i <= save->attrsz[attr]; i++)
1057 save->attrptr[attr][i - 1] = id[i - 1];
1060 save->active_sz[attr] = sz;
1065 * Reset the current size of all vertex attributes to the default
1066 * value of 0. This signals that we haven't yet seen any per-vertex
1067 * commands such as glNormal3f() or glTexCoord2f().
1070 reset_vertex(struct gl_context *ctx)
1072 struct vbo_save_context *save = &vbo_context(ctx)->save;
1074 while (save->enabled) {
1075 const int i = u_bit_scan64(&save->enabled);
1076 assert(save->attrsz[i]);
1077 save->attrsz[i] = 0;
1078 save->active_sz[i] = 0;
1081 save->vertex_size = 0;
1086 * If index=0, does glVertexAttrib*() alias glVertex() to emit a vertex?
1087 * It depends on a few things, including whether we're inside or outside
1091 is_vertex_position(const struct gl_context *ctx, GLuint index)
1093 return (index == 0 &&
1094 _mesa_attr_zero_aliases_vertex(ctx) &&
1095 _mesa_inside_dlist_begin_end(ctx));
1100 #define ERROR(err) _mesa_compile_error(ctx, err, __func__);
1103 /* Only one size for each attribute may be active at once. Eg. if
1104 * Color3f is installed/active, then Color4f may not be, even if the
1105 * vertex actually contains 4 color coordinates. This is because the
1106 * 3f version won't otherwise set color[3] to 1.0 -- this is the job
1107 * of the chooser function when switching between Color4f and Color3f.
1109 #define ATTR_UNION(A, N, T, C, V0, V1, V2, V3) \
1111 struct vbo_save_context *save = &vbo_context(ctx)->save; \
1112 int sz = (sizeof(C) / sizeof(GLfloat)); \
1114 if (save->active_sz[A] != N) \
1115 fixup_vertex(ctx, A, N * sz, T); \
1118 C *dest = (C *)save->attrptr[A]; \
1119 if (N>0) dest[0] = V0; \
1120 if (N>1) dest[1] = V1; \
1121 if (N>2) dest[2] = V2; \
1122 if (N>3) dest[3] = V3; \
1123 save->attrtype[A] = T; \
1129 for (i = 0; i < save->vertex_size; i++) \
1130 save->buffer_ptr[i] = save->vertex[i]; \
1132 save->buffer_ptr += save->vertex_size; \
1134 if (++save->vert_count >= save->max_vert) \
1135 wrap_filled_vertex(ctx); \
1139 #define TAG(x) _save_##x
1141 #include "vbo_attrib_tmp.h"
1145 #define MAT( ATTR, N, face, params ) \
1147 if (face != GL_BACK) \
1148 MAT_ATTR( ATTR, N, params ); /* front */ \
1149 if (face != GL_FRONT) \
1150 MAT_ATTR( ATTR + 1, N, params ); /* back */ \
1155 * Save a glMaterial call found between glBegin/End.
1156 * glMaterial calls outside Begin/End are handled in dlist.c.
1158 static void GLAPIENTRY
1159 _save_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
1161 GET_CURRENT_CONTEXT(ctx);
1163 if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
1164 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(face)");
1170 MAT(VBO_ATTRIB_MAT_FRONT_EMISSION, 4, face, params);
1173 MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
1176 MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
1179 MAT(VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params);
1182 if (*params < 0 || *params > ctx->Const.MaxShininess) {
1183 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glMaterial(shininess)");
1186 MAT(VBO_ATTRIB_MAT_FRONT_SHININESS, 1, face, params);
1189 case GL_COLOR_INDEXES:
1190 MAT(VBO_ATTRIB_MAT_FRONT_INDEXES, 3, face, params);
1192 case GL_AMBIENT_AND_DIFFUSE:
1193 MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
1194 MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
1197 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(pname)");
1203 /* Cope with EvalCoord/CallList called within a begin/end object:
1204 * -- Flush current buffer
1205 * -- Fallback to opcodes for the rest of the begin/end object.
1208 dlist_fallback(struct gl_context *ctx)
1210 struct vbo_save_context *save = &vbo_context(ctx)->save;
1212 if (save->vert_count || save->prim_count) {
1213 if (save->prim_count > 0) {
1214 /* Close off in-progress primitive. */
1215 GLint i = save->prim_count - 1;
1216 save->prims[i].count = save->vert_count - save->prims[i].start;
1219 /* Need to replay this display list with loopback,
1220 * unfortunately, otherwise this primitive won't be handled
1223 save->dangling_attr_ref = GL_TRUE;
1225 compile_vertex_list(ctx);
1228 copy_to_current(ctx);
1230 reset_counters(ctx);
1231 if (save->out_of_memory) {
1232 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
1235 _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
1237 ctx->Driver.SaveNeedFlush = GL_FALSE;
1241 static void GLAPIENTRY
1242 _save_EvalCoord1f(GLfloat u)
1244 GET_CURRENT_CONTEXT(ctx);
1245 dlist_fallback(ctx);
1246 CALL_EvalCoord1f(ctx->Save, (u));
1249 static void GLAPIENTRY
1250 _save_EvalCoord1fv(const GLfloat * v)
1252 GET_CURRENT_CONTEXT(ctx);
1253 dlist_fallback(ctx);
1254 CALL_EvalCoord1fv(ctx->Save, (v));
1257 static void GLAPIENTRY
1258 _save_EvalCoord2f(GLfloat u, GLfloat v)
1260 GET_CURRENT_CONTEXT(ctx);
1261 dlist_fallback(ctx);
1262 CALL_EvalCoord2f(ctx->Save, (u, v));
1265 static void GLAPIENTRY
1266 _save_EvalCoord2fv(const GLfloat * v)
1268 GET_CURRENT_CONTEXT(ctx);
1269 dlist_fallback(ctx);
1270 CALL_EvalCoord2fv(ctx->Save, (v));
1273 static void GLAPIENTRY
1274 _save_EvalPoint1(GLint i)
1276 GET_CURRENT_CONTEXT(ctx);
1277 dlist_fallback(ctx);
1278 CALL_EvalPoint1(ctx->Save, (i));
1281 static void GLAPIENTRY
1282 _save_EvalPoint2(GLint i, GLint j)
1284 GET_CURRENT_CONTEXT(ctx);
1285 dlist_fallback(ctx);
1286 CALL_EvalPoint2(ctx->Save, (i, j));
1289 static void GLAPIENTRY
1290 _save_CallList(GLuint l)
1292 GET_CURRENT_CONTEXT(ctx);
1293 dlist_fallback(ctx);
1294 CALL_CallList(ctx->Save, (l));
1297 static void GLAPIENTRY
1298 _save_CallLists(GLsizei n, GLenum type, const GLvoid * v)
1300 GET_CURRENT_CONTEXT(ctx);
1301 dlist_fallback(ctx);
1302 CALL_CallLists(ctx->Save, (n, type, v));
1308 * Called when a glBegin is getting compiled into a display list.
1309 * Updating of ctx->Driver.CurrentSavePrimitive is already taken care of.
1312 vbo_save_NotifyBegin(struct gl_context *ctx, GLenum mode,
1313 bool no_current_update)
1315 struct vbo_save_context *save = &vbo_context(ctx)->save;
1316 const GLuint i = save->prim_count++;
1318 ctx->Driver.CurrentSavePrimitive = mode;
1320 assert(i < save->prim_max);
1321 save->prims[i].mode = mode & VBO_SAVE_PRIM_MODE_MASK;
1322 save->prims[i].begin = 1;
1323 save->prims[i].end = 0;
1324 save->prims[i].start = save->vert_count;
1325 save->prims[i].count = 0;
1327 save->no_current_update = no_current_update;
1329 if (save->out_of_memory) {
1330 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
1333 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt);
1336 /* We need to call vbo_save_SaveFlushVertices() if there's state change */
1337 ctx->Driver.SaveNeedFlush = GL_TRUE;
1341 static void GLAPIENTRY
1344 GET_CURRENT_CONTEXT(ctx);
1345 struct vbo_save_context *save = &vbo_context(ctx)->save;
1346 const GLint i = save->prim_count - 1;
1348 ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
1349 save->prims[i].end = 1;
1350 save->prims[i].count = (save->vert_count - save->prims[i].start);
1352 if (i == (GLint) save->prim_max - 1) {
1353 compile_vertex_list(ctx);
1354 assert(save->copied.nr == 0);
1357 /* Swap out this vertex format while outside begin/end. Any color,
1358 * etc. received between here and the next begin will be compiled
1361 if (save->out_of_memory) {
1362 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
1365 _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
1370 static void GLAPIENTRY
1371 _save_Begin(GLenum mode)
1373 GET_CURRENT_CONTEXT(ctx);
1375 _mesa_compile_error(ctx, GL_INVALID_OPERATION, "Recursive glBegin");
1379 static void GLAPIENTRY
1380 _save_PrimitiveRestartNV(void)
1382 GET_CURRENT_CONTEXT(ctx);
1383 struct vbo_save_context *save = &vbo_context(ctx)->save;
1385 if (save->prim_count == 0) {
1386 /* We're not inside a glBegin/End pair, so calling glPrimitiverRestartNV
1389 _mesa_compile_error(ctx, GL_INVALID_OPERATION,
1390 "glPrimitiveRestartNV called outside glBegin/End");
1392 /* get current primitive mode */
1393 GLenum curPrim = save->prims[save->prim_count - 1].mode;
1394 bool no_current_update = save->no_current_update;
1396 /* restart primitive */
1397 CALL_End(ctx->CurrentServerDispatch, ());
1398 vbo_save_NotifyBegin(ctx, curPrim, no_current_update);
1403 /* Unlike the functions above, these are to be hooked into the vtxfmt
1404 * maintained in ctx->ListState, active when the list is known or
1405 * suspected to be outside any begin/end primitive.
1406 * Note: OBE = Outside Begin/End
1408 static void GLAPIENTRY
1409 _save_OBE_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
1411 GET_CURRENT_CONTEXT(ctx);
1412 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1414 vbo_save_NotifyBegin(ctx, GL_QUADS, false);
1415 CALL_Vertex2f(dispatch, (x1, y1));
1416 CALL_Vertex2f(dispatch, (x2, y1));
1417 CALL_Vertex2f(dispatch, (x2, y2));
1418 CALL_Vertex2f(dispatch, (x1, y2));
1419 CALL_End(dispatch, ());
1423 static void GLAPIENTRY
1424 _save_OBE_Rectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)
1426 _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1429 static void GLAPIENTRY
1430 _save_OBE_Rectdv(const GLdouble *v1, const GLdouble *v2)
1432 _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1435 static void GLAPIENTRY
1436 _save_OBE_Rectfv(const GLfloat *v1, const GLfloat *v2)
1438 _save_OBE_Rectf(v1[0], v1[1], v2[0], v2[1]);
1441 static void GLAPIENTRY
1442 _save_OBE_Recti(GLint x1, GLint y1, GLint x2, GLint y2)
1444 _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1447 static void GLAPIENTRY
1448 _save_OBE_Rectiv(const GLint *v1, const GLint *v2)
1450 _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1453 static void GLAPIENTRY
1454 _save_OBE_Rects(GLshort x1, GLshort y1, GLshort x2, GLshort y2)
1456 _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1459 static void GLAPIENTRY
1460 _save_OBE_Rectsv(const GLshort *v1, const GLshort *v2)
1462 _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1466 static void GLAPIENTRY
1467 _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count)
1469 GET_CURRENT_CONTEXT(ctx);
1470 struct gl_vertex_array_object *vao = ctx->Array.VAO;
1471 struct vbo_save_context *save = &vbo_context(ctx)->save;
1474 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1475 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawArrays(mode)");
1479 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawArrays(count<0)");
1483 if (save->out_of_memory)
1486 /* Make sure to process any VBO binding changes */
1487 _mesa_update_state(ctx);
1489 _mesa_vao_map_arrays(ctx, vao, GL_MAP_READ_BIT);
1491 vbo_save_NotifyBegin(ctx, mode, true);
1493 for (i = 0; i < count; i++)
1494 _mesa_array_element(ctx, start + i);
1495 CALL_End(ctx->CurrentServerDispatch, ());
1497 _mesa_vao_unmap_arrays(ctx, vao);
1501 static void GLAPIENTRY
1502 _save_OBE_MultiDrawArrays(GLenum mode, const GLint *first,
1503 const GLsizei *count, GLsizei primcount)
1505 GET_CURRENT_CONTEXT(ctx);
1508 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1509 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMultiDrawArrays(mode)");
1513 if (primcount < 0) {
1514 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1515 "glMultiDrawArrays(primcount<0)");
1519 for (i = 0; i < primcount; i++) {
1521 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1522 "glMultiDrawArrays(count[i]<0)");
1527 for (i = 0; i < primcount; i++) {
1529 _save_OBE_DrawArrays(mode, first[i], count[i]);
1536 array_element(struct gl_context *ctx,
1537 GLint basevertex, GLuint elt, unsigned index_size_shift)
1539 /* Section 10.3.5 Primitive Restart:
1541 * When one of the *BaseVertex drawing commands specified in section 10.5
1542 * is used, the primitive restart comparison occurs before the basevertex
1543 * offset is added to the array index.
1545 /* If PrimitiveRestart is enabled and the index is the RestartIndex
1546 * then we call PrimitiveRestartNV and return.
1548 if (ctx->Array._PrimitiveRestart[index_size_shift] &&
1549 elt == ctx->Array._RestartIndex[index_size_shift]) {
1550 CALL_PrimitiveRestartNV(ctx->CurrentServerDispatch, ());
1554 _mesa_array_element(ctx, basevertex + elt);
1558 /* Could do better by copying the arrays and element list intact and
1559 * then emitting an indexed prim at runtime.
1561 static void GLAPIENTRY
1562 _save_OBE_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1563 const GLvoid * indices, GLint basevertex)
1565 GET_CURRENT_CONTEXT(ctx);
1566 struct vbo_save_context *save = &vbo_context(ctx)->save;
1567 struct gl_vertex_array_object *vao = ctx->Array.VAO;
1568 struct gl_buffer_object *indexbuf = vao->IndexBufferObj;
1571 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1572 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawElements(mode)");
1576 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawElements(count<0)");
1579 if (type != GL_UNSIGNED_BYTE &&
1580 type != GL_UNSIGNED_SHORT &&
1581 type != GL_UNSIGNED_INT) {
1582 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawElements(count<0)");
1586 if (save->out_of_memory)
1589 /* Make sure to process any VBO binding changes */
1590 _mesa_update_state(ctx);
1592 _mesa_vao_map(ctx, vao, GL_MAP_READ_BIT);
1596 ADD_POINTERS(indexbuf->Mappings[MAP_INTERNAL].Pointer, indices);
1598 vbo_save_NotifyBegin(ctx, mode, true);
1601 case GL_UNSIGNED_BYTE:
1602 for (i = 0; i < count; i++)
1603 array_element(ctx, basevertex, ((GLubyte *) indices)[i], 0);
1605 case GL_UNSIGNED_SHORT:
1606 for (i = 0; i < count; i++)
1607 array_element(ctx, basevertex, ((GLushort *) indices)[i], 1);
1609 case GL_UNSIGNED_INT:
1610 for (i = 0; i < count; i++)
1611 array_element(ctx, basevertex, ((GLuint *) indices)[i], 2);
1614 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawElements(type)");
1618 CALL_End(ctx->CurrentServerDispatch, ());
1620 _mesa_vao_unmap(ctx, vao);
1623 static void GLAPIENTRY
1624 _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type,
1625 const GLvoid * indices)
1627 _save_OBE_DrawElementsBaseVertex(mode, count, type, indices, 0);
1631 static void GLAPIENTRY
1632 _save_OBE_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
1633 GLsizei count, GLenum type,
1634 const GLvoid * indices)
1636 GET_CURRENT_CONTEXT(ctx);
1637 struct vbo_save_context *save = &vbo_context(ctx)->save;
1639 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1640 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(mode)");
1644 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1645 "glDrawRangeElements(count<0)");
1648 if (type != GL_UNSIGNED_BYTE &&
1649 type != GL_UNSIGNED_SHORT &&
1650 type != GL_UNSIGNED_INT) {
1651 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(type)");
1655 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1656 "glDrawRangeElements(end < start)");
1660 if (save->out_of_memory)
1663 _save_OBE_DrawElements(mode, count, type, indices);
1667 static void GLAPIENTRY
1668 _save_OBE_MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type,
1669 const GLvoid * const *indices, GLsizei primcount)
1671 GET_CURRENT_CONTEXT(ctx);
1672 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1675 for (i = 0; i < primcount; i++) {
1677 CALL_DrawElements(dispatch, (mode, count[i], type, indices[i]));
1683 static void GLAPIENTRY
1684 _save_OBE_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count,
1686 const GLvoid * const *indices,
1688 const GLint *basevertex)
1690 GET_CURRENT_CONTEXT(ctx);
1691 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1694 for (i = 0; i < primcount; i++) {
1696 CALL_DrawElementsBaseVertex(dispatch, (mode, count[i], type,
1705 vtxfmt_init(struct gl_context *ctx)
1707 struct vbo_save_context *save = &vbo_context(ctx)->save;
1708 GLvertexformat *vfmt = &save->vtxfmt;
1710 #define NAME_AE(x) _ae_##x
1711 #define NAME_CALLLIST(x) _save_##x
1712 #define NAME(x) _save_##x
1713 #define NAME_ES(x) _save_##x##ARB
1715 #include "vbo_init_tmp.h"
1720 * Initialize the dispatch table with the VBO functions for display
1724 vbo_initialize_save_dispatch(const struct gl_context *ctx,
1725 struct _glapi_table *exec)
1727 SET_DrawArrays(exec, _save_OBE_DrawArrays);
1728 SET_MultiDrawArrays(exec, _save_OBE_MultiDrawArrays);
1729 SET_DrawElements(exec, _save_OBE_DrawElements);
1730 SET_DrawElementsBaseVertex(exec, _save_OBE_DrawElementsBaseVertex);
1731 SET_DrawRangeElements(exec, _save_OBE_DrawRangeElements);
1732 SET_MultiDrawElementsEXT(exec, _save_OBE_MultiDrawElements);
1733 SET_MultiDrawElementsBaseVertex(exec, _save_OBE_MultiDrawElementsBaseVertex);
1734 SET_Rectf(exec, _save_OBE_Rectf);
1735 SET_Rectd(exec, _save_OBE_Rectd);
1736 SET_Rectdv(exec, _save_OBE_Rectdv);
1737 SET_Rectfv(exec, _save_OBE_Rectfv);
1738 SET_Recti(exec, _save_OBE_Recti);
1739 SET_Rectiv(exec, _save_OBE_Rectiv);
1740 SET_Rects(exec, _save_OBE_Rects);
1741 SET_Rectsv(exec, _save_OBE_Rectsv);
1743 /* Note: other glDraw functins aren't compiled into display lists */
1749 vbo_save_SaveFlushVertices(struct gl_context *ctx)
1751 struct vbo_save_context *save = &vbo_context(ctx)->save;
1753 /* Noop when we are actually active:
1755 if (ctx->Driver.CurrentSavePrimitive <= PRIM_MAX)
1758 if (save->vert_count || save->prim_count)
1759 compile_vertex_list(ctx);
1761 copy_to_current(ctx);
1763 reset_counters(ctx);
1764 ctx->Driver.SaveNeedFlush = GL_FALSE;
1769 * Called from glNewList when we're starting to compile a display list.
1772 vbo_save_NewList(struct gl_context *ctx, GLuint list, GLenum mode)
1774 struct vbo_save_context *save = &vbo_context(ctx)->save;
1779 if (!save->prim_store)
1780 save->prim_store = alloc_prim_store(0);
1782 if (!save->vertex_store)
1783 save->vertex_store = alloc_vertex_store(ctx, 0);
1785 save->buffer_ptr = vbo_save_map_vertex_store(ctx, save->vertex_store);
1788 reset_counters(ctx);
1789 ctx->Driver.SaveNeedFlush = GL_FALSE;
1794 * Called from glEndList when we're finished compiling a display list.
1797 vbo_save_EndList(struct gl_context *ctx)
1799 struct vbo_save_context *save = &vbo_context(ctx)->save;
1801 /* EndList called inside a (saved) Begin/End pair?
1803 if (_mesa_inside_dlist_begin_end(ctx)) {
1804 if (save->prim_count > 0) {
1805 GLint i = save->prim_count - 1;
1806 ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
1807 save->prims[i].end = 0;
1808 save->prims[i].count = save->vert_count - save->prims[i].start;
1811 /* Make sure this vertex list gets replayed by the "loopback"
1814 save->dangling_attr_ref = GL_TRUE;
1815 vbo_save_SaveFlushVertices(ctx);
1817 /* Swap out this vertex format while outside begin/end. Any color,
1818 * etc. received between here and the next begin will be compiled
1821 _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
1824 vbo_save_unmap_vertex_store(ctx, save->vertex_store);
1826 assert(save->vertex_size == 0);
1831 * Called from the display list code when we're about to execute a
1835 vbo_save_BeginCallList(struct gl_context *ctx, struct gl_display_list *dlist)
1837 struct vbo_save_context *save = &vbo_context(ctx)->save;
1838 save->replay_flags |= dlist->Flags;
1843 * Called from the display list code when we're finished executing a
1847 vbo_save_EndCallList(struct gl_context *ctx)
1849 struct vbo_save_context *save = &vbo_context(ctx)->save;
1851 if (ctx->ListState.CallDepth == 1)
1852 save->replay_flags = 0;
1857 * Called by display list code when a display list is being deleted.
1860 vbo_destroy_vertex_list(struct gl_context *ctx, void *data)
1862 struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *) data;
1864 for (gl_vertex_processing_mode vpm = VP_MODE_FF; vpm < VP_MODE_MAX; ++vpm)
1865 _mesa_reference_vao(ctx, &node->VAO[vpm], NULL);
1867 if (--node->prim_store->refcount == 0) {
1868 free(node->prim_store->prims);
1869 free(node->prim_store);
1872 _mesa_reference_buffer_object(ctx, &node->ib.obj, NULL);
1873 free(node->current_data);
1874 node->current_data = NULL;
1879 vbo_print_vertex_list(struct gl_context *ctx, void *data, FILE *f)
1881 struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *) data;
1883 struct gl_buffer_object *buffer = node->VAO[0]->BufferBinding[0].BufferObj;
1884 const GLuint vertex_size = _vbo_save_get_stride(node)/sizeof(GLfloat);
1887 fprintf(f, "VBO-VERTEX-LIST, %u vertices, %d primitives, %d vertsize, "
1889 node->vertex_count, node->prim_count, vertex_size,
1892 for (i = 0; i < node->prim_count; i++) {
1893 struct _mesa_prim *prim = &node->prims[i];
1894 fprintf(f, " prim %d: %s %d..%d %s %s\n",
1896 _mesa_lookup_prim_by_nr(prim->mode),
1898 prim->start + prim->count,
1899 (prim->begin) ? "BEGIN" : "(wrap)",
1900 (prim->end) ? "END" : "(wrap)");
1906 * Called during context creation/init.
1909 current_init(struct gl_context *ctx)
1911 struct vbo_save_context *save = &vbo_context(ctx)->save;
1914 for (i = VBO_ATTRIB_POS; i <= VBO_ATTRIB_GENERIC15; i++) {
1915 const GLuint j = i - VBO_ATTRIB_POS;
1916 assert(j < VERT_ATTRIB_MAX);
1917 save->currentsz[i] = &ctx->ListState.ActiveAttribSize[j];
1918 save->current[i] = (fi_type *) ctx->ListState.CurrentAttrib[j];
1921 for (i = VBO_ATTRIB_FIRST_MATERIAL; i <= VBO_ATTRIB_LAST_MATERIAL; i++) {
1922 const GLuint j = i - VBO_ATTRIB_FIRST_MATERIAL;
1923 assert(j < MAT_ATTRIB_MAX);
1924 save->currentsz[i] = &ctx->ListState.ActiveMaterialSize[j];
1925 save->current[i] = (fi_type *) ctx->ListState.CurrentMaterial[j];
1931 * Initialize the display list compiler. Called during context creation.
1934 vbo_save_api_init(struct vbo_save_context *save)
1936 struct gl_context *ctx = gl_context_from_vbo_save(save);
1938 save->opcode_vertex_list =
1939 _mesa_dlist_alloc_opcode(ctx,
1940 sizeof(struct vbo_save_vertex_list),
1941 vbo_save_playback_vertex_list,
1942 vbo_destroy_vertex_list,
1943 vbo_print_vertex_list);
1947 _mesa_noop_vtxfmt_init(ctx, &save->vtxfmt_noop);