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.
68 * The compilation process works as follows. All vertex attributes
69 * except position are copied to vbo_save_context::attrptr (see ATTR_UNION).
70 * 'attrptr' are pointers to vbo_save_context::vertex ordered according to the enabled
71 * attributes (se upgrade_vertex).
72 * When the position attribute is received, all the attributes are then
73 * copied to the vertex_store (see the end of ATTR_UNION).
74 * The vertex_store is simply an extensible float array.
75 * When the vertex list needs to be compiled (see compile_vertex_list),
76 * several transformations are performed:
77 * - some primitives are merged together (eg: two consecutive GL_TRIANGLES
78 * with 3 vertices can be merged in a single GL_TRIANGLES with 6 vertices).
79 * - an index buffer is built.
80 * - identical vertices are detected and only one is kept.
81 * At the end of this transformation, the index buffer and the vertex buffer
82 * are uploaded in vRAM in the same buffer object.
83 * This buffer object is shared between multiple display list to allow
84 * draw calls merging later.
86 * The layout of this buffer for two display lists is:
87 * V0A0|V0A1|V1A0|V1A1|P0I0|P0I1|V0A0V0A1V0A2|V1A1V1A1V1A2|...
89 * - VxAy: vertex x, attributes y
90 * - PxIy: draw x, index y
92 * To allow draw call merging, display list must use the same VAO, including
93 * the same Offset in the buffer object. To achieve this, the start values of
94 * the primitive are shifted and the indices adjusted (see offset_diff and
95 * start_offset in compile_vertex_list).
97 * Display list using the loopback code (see vbo_save_playback_vertex_list_loopback),
98 * can't be drawn with an index buffer so this transformation is disabled
103 #include "main/glheader.h"
104 #include "main/arrayobj.h"
105 #include "main/bufferobj.h"
106 #include "main/context.h"
107 #include "main/dlist.h"
108 #include "main/enums.h"
109 #include "main/eval.h"
110 #include "main/macros.h"
111 #include "main/draw_validate.h"
112 #include "main/api_arrayelt.h"
113 #include "main/vtxfmt.h"
114 #include "main/dispatch.h"
115 #include "main/state.h"
116 #include "main/varray.h"
117 #include "util/bitscan.h"
118 #include "util/u_memory.h"
119 #include "util/hash_table.h"
120 #include "util/indices/u_indices.h"
122 #include "gallium/include/pipe/p_state.h"
124 #include "vbo_noop.h"
125 #include "vbo_private.h"
127 #include "state_tracker/st_cb_bufferobjects.h"
133 /* An interesting VBO number/name to help with debugging */
134 #define VBO_BUF_ID 12345
136 static void GLAPIENTRY
137 _save_Materialfv(GLenum face, GLenum pname, const GLfloat *params);
139 static void GLAPIENTRY
140 _save_EvalCoord1f(GLfloat u);
142 static void GLAPIENTRY
143 _save_EvalCoord2f(GLfloat u, GLfloat v);
146 handle_out_of_memory(struct gl_context *ctx)
148 struct vbo_save_context *save = &vbo_context(ctx)->save;
149 _mesa_noop_vtxfmt_init(ctx, &save->vtxfmt);
150 save->out_of_memory = true;
154 * NOTE: Old 'parity' issue is gone, but copying can still be
155 * wrong-footed on replay.
158 copy_vertices(struct gl_context *ctx,
159 const struct vbo_save_vertex_list *node,
160 const fi_type * src_buffer)
162 struct vbo_save_context *save = &vbo_context(ctx)->save;
163 struct _mesa_prim *prim = &node->cold->prims[node->cold->prim_count - 1];
164 GLuint sz = save->vertex_size;
166 if (prim->end || !prim->count || !sz)
169 const fi_type *src = src_buffer + prim->start * sz;
170 assert(save->copied.buffer == NULL);
171 save->copied.buffer = malloc(sizeof(fi_type) * sz * prim->count);
173 unsigned r = vbo_copy_vertices(ctx, prim->mode, prim->start, &prim->count,
174 prim->begin, sz, true, save->copied.buffer, src);
176 free(save->copied.buffer);
177 save->copied.buffer = NULL;
183 static struct vbo_save_primitive_store *
184 realloc_prim_store(struct vbo_save_primitive_store *store, int prim_count)
187 store = CALLOC_STRUCT(vbo_save_primitive_store);
189 uint32_t old_size = store->size;
190 store->size = prim_count;
191 assert (old_size < store->size);
192 store->prims = realloc(store->prims, store->size * sizeof(struct _mesa_prim));
193 memset(&store->prims[old_size], 0, (store->size - old_size) * sizeof(struct _mesa_prim));
200 reset_counters(struct gl_context *ctx)
202 struct vbo_save_context *save = &vbo_context(ctx)->save;
204 save->vertex_store->used = 0;
205 save->prim_store->used = 0;
206 save->dangling_attr_ref = GL_FALSE;
210 * For a list of prims, try merging prims that can just be extensions of the
214 merge_prims(struct gl_context *ctx, struct _mesa_prim *prim_list,
218 struct _mesa_prim *prev_prim = prim_list;
220 for (i = 1; i < *prim_count; i++) {
221 struct _mesa_prim *this_prim = prim_list + i;
223 vbo_try_prim_conversion(&this_prim->mode, &this_prim->count);
225 if (vbo_merge_draws(ctx, true,
226 prev_prim->mode, this_prim->mode,
227 prev_prim->start, this_prim->start,
228 &prev_prim->count, this_prim->count,
229 prev_prim->basevertex, this_prim->basevertex,
231 this_prim->begin, this_prim->end)) {
232 /* We've found a prim that just extend the previous one. Tack it
233 * onto the previous one, and let this primitive struct get dropped.
238 /* If any previous primitives have been dropped, then we need to copy
239 * this later one into the next available slot.
242 if (prev_prim != this_prim)
243 *prev_prim = *this_prim;
246 *prim_count = prev_prim - prim_list + 1;
251 * Convert GL_LINE_LOOP primitive into GL_LINE_STRIP so that drivers
252 * don't have to worry about handling the _mesa_prim::begin/end flags.
253 * See https://bugs.freedesktop.org/show_bug.cgi?id=81174
256 convert_line_loop_to_strip(struct vbo_save_context *save,
257 struct vbo_save_vertex_list *node)
259 struct _mesa_prim *prim = &node->cold->prims[node->cold->prim_count - 1];
261 assert(prim->mode == GL_LINE_LOOP);
264 /* Copy the 0th vertex to end of the buffer and extend the
265 * vertex count by one to finish the line loop.
267 const GLuint sz = save->vertex_size;
269 const fi_type *src = save->vertex_store->buffer_in_ram + prim->start * sz;
271 fi_type *dst = save->vertex_store->buffer_in_ram + (prim->start + prim->count) * sz;
273 memcpy(dst, src, sz * sizeof(float));
276 node->cold->vertex_count++;
277 save->vertex_store->used += sz;
281 /* Drawing the second or later section of a long line loop.
282 * Skip the 0th vertex.
288 prim->mode = GL_LINE_STRIP;
292 /* Compare the present vao if it has the same setup. */
294 compare_vao(gl_vertex_processing_mode mode,
295 const struct gl_vertex_array_object *vao,
296 const struct gl_buffer_object *bo, GLintptr buffer_offset,
297 GLuint stride, GLbitfield64 vao_enabled,
298 const GLubyte size[VBO_ATTRIB_MAX],
299 const GLenum16 type[VBO_ATTRIB_MAX],
300 const GLuint offset[VBO_ATTRIB_MAX])
305 /* If the enabled arrays are not the same we are not equal. */
306 if (vao_enabled != vao->Enabled)
309 /* Check the buffer binding at 0 */
310 if (vao->BufferBinding[0].BufferObj != bo)
312 /* BufferBinding[0].Offset != buffer_offset is checked per attribute */
313 if (vao->BufferBinding[0].Stride != stride)
315 assert(vao->BufferBinding[0].InstanceDivisor == 0);
317 /* Retrieve the mapping from VBO_ATTRIB to VERT_ATTRIB space */
318 const GLubyte *const vao_to_vbo_map = _vbo_attribute_alias_map[mode];
320 /* Now check the enabled arrays */
321 GLbitfield mask = vao_enabled;
323 const int attr = u_bit_scan(&mask);
324 const unsigned char vbo_attr = vao_to_vbo_map[attr];
325 const GLenum16 tp = type[vbo_attr];
326 const GLintptr off = offset[vbo_attr] + buffer_offset;
327 const struct gl_array_attributes *attrib = &vao->VertexAttrib[attr];
328 if (attrib->RelativeOffset + vao->BufferBinding[0].Offset != off)
330 if (attrib->Format.Type != tp)
332 if (attrib->Format.Size != size[vbo_attr])
334 assert(attrib->Format.Format == GL_RGBA);
335 assert(attrib->Format.Normalized == GL_FALSE);
336 assert(attrib->Format.Integer == vbo_attrtype_to_integer_flag(tp));
337 assert(attrib->Format.Doubles == vbo_attrtype_to_double_flag(tp));
338 assert(attrib->BufferBindingIndex == 0);
345 /* Create or reuse the vao for the vertex processing mode. */
347 update_vao(struct gl_context *ctx,
348 gl_vertex_processing_mode mode,
349 struct gl_vertex_array_object **vao,
350 struct gl_buffer_object *bo, GLintptr buffer_offset,
351 GLuint stride, GLbitfield64 vbo_enabled,
352 const GLubyte size[VBO_ATTRIB_MAX],
353 const GLenum16 type[VBO_ATTRIB_MAX],
354 const GLuint offset[VBO_ATTRIB_MAX])
356 /* Compute the bitmasks of vao_enabled arrays */
357 GLbitfield vao_enabled = _vbo_get_vao_enabled_from_vbo(mode, vbo_enabled);
360 * Check if we can possibly reuse the exisiting one.
361 * In the long term we should reset them when something changes.
363 if (compare_vao(mode, *vao, bo, buffer_offset, stride,
364 vao_enabled, size, type, offset))
367 /* The initial refcount is 1 */
368 _mesa_reference_vao(ctx, vao, NULL);
369 *vao = _mesa_new_vao(ctx, ~((GLuint)0));
372 * assert(stride <= ctx->Const.MaxVertexAttribStride);
373 * MaxVertexAttribStride is not set for drivers that does not
374 * expose GL 44 or GLES 31.
377 /* Bind the buffer object at binding point 0 */
378 _mesa_bind_vertex_buffer(ctx, *vao, 0, bo, buffer_offset, stride, false,
381 /* Retrieve the mapping from VBO_ATTRIB to VERT_ATTRIB space
382 * Note that the position/generic0 aliasing is done in the VAO.
384 const GLubyte *const vao_to_vbo_map = _vbo_attribute_alias_map[mode];
385 /* Now set the enable arrays */
386 GLbitfield mask = vao_enabled;
388 const int vao_attr = u_bit_scan(&mask);
389 const GLubyte vbo_attr = vao_to_vbo_map[vao_attr];
390 assert(offset[vbo_attr] <= ctx->Const.MaxVertexAttribRelativeOffset);
392 _vbo_set_attrib_format(ctx, *vao, vao_attr, buffer_offset,
393 size[vbo_attr], type[vbo_attr], offset[vbo_attr]);
394 _mesa_vertex_attrib_binding(ctx, *vao, vao_attr, 0);
396 _mesa_enable_vertex_array_attribs(ctx, *vao, vao_enabled);
397 assert(vao_enabled == (*vao)->Enabled);
398 assert((vao_enabled & ~(*vao)->VertexAttribBufferMask) == 0);
400 /* Finalize and freeze the VAO */
401 _mesa_set_vao_immutable(ctx, *vao);
404 static void wrap_filled_vertex(struct gl_context *ctx);
406 /* Grow the vertex storage to accomodate for vertex_count new vertices */
408 grow_vertex_storage(struct gl_context *ctx, int vertex_count)
410 struct vbo_save_context *save = &vbo_context(ctx)->save;
411 assert (save->vertex_store);
413 int new_size = (save->vertex_store->used +
414 vertex_count * save->vertex_size) * sizeof(GLfloat);
416 /* Limit how much memory we allocate. */
417 if (save->prim_store->used > 0 &&
419 new_size > VBO_SAVE_BUFFER_SIZE) {
420 wrap_filled_vertex(ctx);
421 new_size = VBO_SAVE_BUFFER_SIZE;
424 if (new_size > save->vertex_store->buffer_in_ram_size) {
425 save->vertex_store->buffer_in_ram_size = new_size;
426 save->vertex_store->buffer_in_ram = realloc(save->vertex_store->buffer_in_ram,
427 save->vertex_store->buffer_in_ram_size);
428 if (save->vertex_store->buffer_in_ram == NULL)
429 handle_out_of_memory(ctx);
435 unsigned vertex_size;
436 fi_type *vertex_attributes;
439 static uint32_t _hash_vertex_key(const void *key)
441 struct vertex_key *k = (struct vertex_key*)key;
442 unsigned sz = k->vertex_size;
444 return _mesa_hash_data(k->vertex_attributes, sz * sizeof(float));
447 static bool _compare_vertex_key(const void *key1, const void *key2)
449 struct vertex_key *k1 = (struct vertex_key*)key1;
450 struct vertex_key *k2 = (struct vertex_key*)key2;
451 /* All the compared vertices are going to be drawn with the same VAO,
452 * so we can compare the attributes. */
453 assert (k1->vertex_size == k2->vertex_size);
454 return memcmp(k1->vertex_attributes,
455 k2->vertex_attributes,
456 k1->vertex_size * sizeof(float)) == 0;
459 static void _free_entry(struct hash_entry *entry)
461 free((void*)entry->key);
464 /* Add vertex to the vertex buffer and return its index. If this vertex is a duplicate
465 * of an existing vertex, return the original index instead.
468 add_vertex(struct vbo_save_context *save, struct hash_table *hash_to_index,
469 uint32_t index, fi_type *new_buffer, uint32_t *max_index)
471 /* If vertex deduplication is disabled return the original index. */
475 fi_type *vert = save->vertex_store->buffer_in_ram + save->vertex_size * index;
477 struct vertex_key *key = malloc(sizeof(struct vertex_key));
478 key->vertex_size = save->vertex_size;
479 key->vertex_attributes = vert;
481 struct hash_entry *entry = _mesa_hash_table_search(hash_to_index, key);
484 /* We found an existing vertex with the same hash, return its index. */
485 return (uintptr_t) entry->data;
487 /* This is a new vertex. Determine a new index and copy its attributes to the vertex
488 * buffer. Note that 'new_buffer' is created at each list compilation so we write vertices
489 * starting at index 0.
491 uint32_t n = _mesa_hash_table_num_entries(hash_to_index);
492 *max_index = MAX2(n, *max_index);
494 memcpy(&new_buffer[save->vertex_size * n],
496 save->vertex_size * sizeof(fi_type));
498 _mesa_hash_table_insert(hash_to_index, key, (void*)(uintptr_t)(n));
500 /* The index buffer is shared between list compilations, so add the base index to get
509 get_vertex_count(struct vbo_save_context *save)
511 if (!save->vertex_size)
513 return save->vertex_store->used / save->vertex_size;
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_vertex_list(ctx, !save->dangling_attr_ref && !save->no_current_update);
536 node->cold = calloc(1, sizeof(*node->cold));
538 /* Make sure the pointer is aligned to the size of a pointer */
539 assert((GLintptr) node % sizeof(void *) == 0);
541 const GLsizei stride = save->vertex_size*sizeof(GLfloat);
543 node->cold->vertex_count = get_vertex_count(save);
544 node->cold->wrap_count = save->copied.nr;
545 node->cold->prims = malloc(sizeof(struct _mesa_prim) * save->prim_store->used);
546 memcpy(node->cold->prims, save->prim_store->prims, sizeof(struct _mesa_prim) * save->prim_store->used);
547 node->cold->ib.obj = NULL;
548 node->cold->prim_count = save->prim_store->used;
550 if (save->no_current_update) {
551 node->cold->current_data = NULL;
554 GLuint current_size = save->vertex_size - save->attrsz[0];
555 node->cold->current_data = NULL;
558 node->cold->current_data = malloc(current_size * sizeof(GLfloat));
559 if (node->cold->current_data) {
560 const char *buffer = (const char *)save->vertex_store->buffer_in_ram;
561 unsigned attr_offset = save->attrsz[0] * sizeof(GLfloat);
562 unsigned vertex_offset = 0;
564 if (node->cold->vertex_count)
565 vertex_offset = (node->cold->vertex_count - 1) * stride;
567 memcpy(node->cold->current_data, buffer + vertex_offset + attr_offset,
568 current_size * sizeof(GLfloat));
570 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Current value allocation");
571 handle_out_of_memory(ctx);
576 assert(save->attrsz[VBO_ATTRIB_POS] != 0 || node->cold->vertex_count == 0);
578 if (save->dangling_attr_ref)
579 ctx->ListState.Current.UseLoopback = true;
581 /* Copy duplicated vertices
583 save->copied.nr = copy_vertices(ctx, node, save->vertex_store->buffer_in_ram);
585 if (node->cold->prims[node->cold->prim_count - 1].mode == GL_LINE_LOOP) {
586 convert_line_loop_to_strip(save, node);
589 merge_prims(ctx, node->cold->prims, &node->cold->prim_count);
591 GLintptr buffer_offset = 0;
592 GLuint start_offset = 0;
594 /* Create an index buffer. */
595 node->cold->min_index = node->cold->max_index = 0;
596 if (node->cold->vertex_count == 0 || node->cold->prim_count == 0)
599 /* We won't modify node->prims, so use a const alias to avoid unintended
601 const struct _mesa_prim *original_prims = node->cold->prims;
603 int end = original_prims[node->cold->prim_count - 1].start +
604 original_prims[node->cold->prim_count - 1].count;
605 int total_vert_count = end - original_prims[0].start;
607 node->cold->min_index = node->cold->prims[0].start;
608 node->cold->max_index = end - 1;
610 /* converting primitive types may result in many more indices */
611 bool all_prims_supported = (ctx->Const.DriverSupportedPrimMask & BITFIELD_MASK(PIPE_PRIM_MAX)) == BITFIELD_MASK(PIPE_PRIM_MAX);
612 int max_index_count = total_vert_count * (all_prims_supported ? 2 : 3);
614 int size = max_index_count * sizeof(uint32_t);
615 uint32_t* indices = (uint32_t*) malloc(size);
616 void *tmp_indices = all_prims_supported ? NULL : malloc(size);
617 struct _mesa_prim *merged_prims = NULL;
620 struct hash_table *vertex_to_index = NULL;
621 fi_type *temp_vertices_buffer = NULL;
623 /* The loopback replay code doesn't use the index buffer, so we can't
624 * dedup vertices in this case.
626 if (!ctx->ListState.Current.UseLoopback) {
627 vertex_to_index = _mesa_hash_table_create(NULL, _hash_vertex_key, _compare_vertex_key);
628 temp_vertices_buffer = malloc(save->vertex_store->buffer_in_ram_size);
631 uint32_t max_index = 0;
633 int last_valid_prim = -1;
634 /* Construct indices array. */
635 for (unsigned i = 0; i < node->cold->prim_count; i++) {
636 assert(original_prims[i].basevertex == 0);
637 GLubyte mode = original_prims[i].mode;
638 bool converted_prim = false;
641 int vertex_count = original_prims[i].count;
646 /* Line strips may get converted to lines */
647 if (mode == GL_LINE_STRIP)
650 if (!(ctx->Const.DriverSupportedPrimMask & BITFIELD_BIT(mode))) {
652 u_generate_func trans_func;
653 enum pipe_prim_type pmode = (enum pipe_prim_type)mode;
654 u_index_generator(ctx->Const.DriverSupportedPrimMask,
655 pmode, original_prims[i].start, vertex_count,
657 &pmode, &index_size, &new_count,
660 trans_func(original_prims[i].start, new_count, tmp_indices);
661 vertex_count = new_count;
662 mode = (GLubyte)pmode;
663 converted_prim = true;
667 /* If 2 consecutive prims use the same mode => merge them. */
668 bool merge_prims = last_valid_prim >= 0 &&
669 mode == merged_prims[last_valid_prim].mode &&
670 mode != GL_LINE_LOOP && mode != GL_TRIANGLE_FAN &&
671 mode != GL_QUAD_STRIP && mode != GL_POLYGON &&
674 /* index generation uses uint16_t if the index count is small enough */
675 #define CAST_INDEX(BASE, SIZE, IDX) ((SIZE == 2 ? (uint32_t)(((uint16_t*)BASE)[IDX]) : ((uint32_t*)BASE)[IDX]))
676 /* To be able to merge consecutive triangle strips we need to insert
677 * a degenerate triangle.
680 mode == GL_TRIANGLE_STRIP) {
681 /* Insert a degenerate triangle */
682 assert(merged_prims[last_valid_prim].mode == GL_TRIANGLE_STRIP);
683 unsigned tri_count = merged_prims[last_valid_prim].count - 2;
685 indices[idx] = indices[idx - 1];
686 indices[idx + 1] = add_vertex(save, vertex_to_index,
687 converted_prim ? CAST_INDEX(tmp_indices, index_size, 0) : original_prims[i].start,
688 temp_vertices_buffer, &max_index);
690 merged_prims[last_valid_prim].count += 2;
693 /* Add another index to preserve winding order */
694 indices[idx++] = add_vertex(save, vertex_to_index,
695 converted_prim ? CAST_INDEX(tmp_indices, index_size, 0) : original_prims[i].start,
696 temp_vertices_buffer, &max_index);
697 merged_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 (original_prims[i].mode == GL_LINE_STRIP &&
709 (i < node->cold->prim_count - 1 &&
710 (original_prims[i + 1].mode == GL_LINE_STRIP ||
711 original_prims[i + 1].mode == GL_LINES)))) {
712 for (unsigned j = 0; j < vertex_count; j++) {
713 indices[idx++] = add_vertex(save, vertex_to_index,
714 converted_prim ? CAST_INDEX(tmp_indices, index_size, j) : original_prims[i].start + j,
715 temp_vertices_buffer, &max_index);
716 /* Repeat all but the first/last indices. */
717 if (j && j != vertex_count - 1) {
718 indices[idx++] = add_vertex(save, vertex_to_index,
719 converted_prim ? CAST_INDEX(tmp_indices, index_size, j) : original_prims[i].start + j,
720 temp_vertices_buffer, &max_index);
724 /* We didn't convert to LINES, so restore the original mode */
726 mode = original_prims[i].mode;
728 for (unsigned j = 0; j < vertex_count; j++) {
729 indices[idx++] = add_vertex(save, vertex_to_index,
730 converted_prim ? CAST_INDEX(tmp_indices, index_size, j) : original_prims[i].start + j,
731 temp_vertices_buffer, &max_index);
736 /* Update vertex count. */
737 merged_prims[last_valid_prim].count += idx - start;
739 /* Keep this primitive */
740 last_valid_prim += 1;
741 assert(last_valid_prim <= i);
742 merged_prims = realloc(merged_prims, (1 + last_valid_prim) * sizeof(struct _mesa_prim));
743 merged_prims[last_valid_prim] = original_prims[i];
744 merged_prims[last_valid_prim].start = start;
745 merged_prims[last_valid_prim].count = idx - start;
747 merged_prims[last_valid_prim].mode = mode;
750 assert(idx > 0 && idx <= max_index_count);
752 unsigned merged_prim_count = last_valid_prim + 1;
753 node->cold->ib.ptr = NULL;
754 node->cold->ib.count = idx;
755 node->cold->ib.index_size_shift = (GL_UNSIGNED_INT - GL_UNSIGNED_BYTE) >> 1;
757 /* How many bytes do we need to store the indices and the vertices */
758 total_vert_count = vertex_to_index ? (max_index + 1) : idx;
759 unsigned total_bytes_needed = idx * sizeof(uint32_t) +
760 total_vert_count * save->vertex_size * sizeof(fi_type);
762 const GLintptr old_offset = save->VAO[0] ?
763 save->VAO[0]->BufferBinding[0].Offset + save->VAO[0]->VertexAttrib[VERT_ATTRIB_POS].RelativeOffset : 0;
764 if (old_offset != save->current_bo_bytes_used && stride > 0) {
765 GLintptr offset_diff = save->current_bo_bytes_used - old_offset;
766 while (offset_diff > 0 &&
767 save->current_bo_bytes_used < save->current_bo->Size &&
768 offset_diff % stride != 0) {
769 save->current_bo_bytes_used++;
770 offset_diff = save->current_bo_bytes_used - old_offset;
773 buffer_offset = save->current_bo_bytes_used;
775 /* Can we reuse the previous bo or should we allocate a new one? */
776 int available_bytes = save->current_bo ? save->current_bo->Size - save->current_bo_bytes_used : 0;
777 if (total_bytes_needed > available_bytes) {
778 if (save->current_bo)
779 _mesa_reference_buffer_object(ctx, &save->current_bo, NULL);
780 save->current_bo = st_bufferobj_alloc(ctx, VBO_BUF_ID + 1);
781 bool success = st_bufferobj_data(ctx,
782 GL_ELEMENT_ARRAY_BUFFER_ARB,
783 MAX2(total_bytes_needed, VBO_SAVE_BUFFER_SIZE),
785 GL_STATIC_DRAW_ARB, GL_MAP_WRITE_BIT |
786 MESA_GALLIUM_VERTEX_STATE_STORAGE,
789 _mesa_reference_buffer_object(ctx, &save->current_bo, NULL);
790 _mesa_error(ctx, GL_OUT_OF_MEMORY, "IB allocation");
791 handle_out_of_memory(ctx);
793 save->current_bo_bytes_used = 0;
794 available_bytes = save->current_bo->Size;
798 assert(old_offset <= buffer_offset);
799 const GLintptr offset_diff = buffer_offset - old_offset;
800 if (offset_diff > 0 && stride > 0 && offset_diff % stride == 0) {
801 /* The vertex size is an exact multiple of the buffer offset.
802 * This means that we can use zero-based vertex attribute pointers
803 * and specify the start of the primitive with the _mesa_prim::start
804 * field. This results in issuing several draw calls with identical
805 * vertex attribute information. This can result in fewer state
806 * changes in drivers. In particular, the Gallium CSO module will
807 * filter out redundant vertex buffer changes.
809 /* We cannot immediately update the primitives as some methods below
810 * still need the uncorrected start vertices
812 start_offset = offset_diff/stride;
813 assert(old_offset == buffer_offset - offset_diff);
814 buffer_offset = old_offset;
817 /* Correct the primitive starts, we can only do this here as copy_vertices
818 * and convert_line_loop_to_strip above consume the uncorrected starts.
819 * On the other hand the _vbo_loopback_vertex_list call below needs the
820 * primitives to be corrected already.
822 for (unsigned i = 0; i < node->cold->prim_count; i++) {
823 node->cold->prims[i].start += start_offset;
825 /* start_offset shifts vertices (so v[0] becomes v[start_offset]), so we have
826 * to apply this transformation to all indices and max_index.
828 for (unsigned i = 0; i < idx; i++)
829 indices[i] += start_offset;
830 max_index += start_offset;
833 _mesa_reference_buffer_object(ctx, &node->cold->ib.obj, save->current_bo);
835 /* Upload the vertices first (see buffer_offset) */
836 st_bufferobj_subdata(ctx,
837 save->current_bo_bytes_used,
838 total_vert_count * save->vertex_size * sizeof(fi_type),
839 vertex_to_index ? temp_vertices_buffer : save->vertex_store->buffer_in_ram,
841 save->current_bo_bytes_used += total_vert_count * save->vertex_size * sizeof(fi_type);
843 if (vertex_to_index) {
844 _mesa_hash_table_destroy(vertex_to_index, _free_entry);
845 free(temp_vertices_buffer);
848 /* Since we're append the indices to an existing buffer, we need to adjust the start value of each
849 * primitive (not the indices themselves). */
850 save->current_bo_bytes_used += align(save->current_bo_bytes_used, 4) - save->current_bo_bytes_used;
851 int indices_offset = save->current_bo_bytes_used / 4;
852 for (int i = 0; i < merged_prim_count; i++) {
853 merged_prims[i].start += indices_offset;
856 /* Then upload the indices. */
857 if (node->cold->ib.obj) {
858 st_bufferobj_subdata(ctx,
859 save->current_bo_bytes_used,
860 idx * sizeof(uint32_t),
863 save->current_bo_bytes_used += idx * sizeof(uint32_t);
865 node->cold->vertex_count = 0;
866 node->cold->prim_count = 0;
869 /* Prepare for DrawGallium */
870 memset(&node->cold->info, 0, sizeof(struct pipe_draw_info));
871 /* The other info fields will be updated in vbo_save_playback_vertex_list */
872 node->cold->info.index_size = 4;
873 node->cold->info.instance_count = 1;
874 node->cold->info.index.gl_bo = node->cold->ib.obj;
875 if (merged_prim_count == 1) {
876 node->cold->info.mode = merged_prims[0].mode;
877 node->start_count.start = merged_prims[0].start;
878 node->start_count.count = merged_prims[0].count;
879 node->start_count.index_bias = 0;
882 node->modes = malloc(merged_prim_count * sizeof(unsigned char));
883 node->start_counts = malloc(merged_prim_count * sizeof(struct pipe_draw_start_count_bias));
884 for (unsigned i = 0; i < merged_prim_count; i++) {
885 node->start_counts[i].start = merged_prims[i].start;
886 node->start_counts[i].count = merged_prims[i].count;
887 node->start_counts[i].index_bias = 0;
888 node->modes[i] = merged_prims[i].mode;
891 node->num_draws = merged_prim_count;
892 if (node->num_draws > 1) {
893 bool same_mode = true;
894 for (unsigned i = 1; i < node->num_draws && same_mode; i++) {
895 same_mode = node->modes[i] == node->modes[0];
898 /* All primitives use the same mode, so we can simplify a bit */
899 node->cold->info.mode = node->modes[0];
910 node->draw_begins = node->cold->prims[0].begin;
912 if (!save->current_bo) {
913 save->current_bo = st_bufferobj_alloc(ctx, VBO_BUF_ID + 1);
914 bool success = st_bufferobj_data(ctx,
915 GL_ELEMENT_ARRAY_BUFFER_ARB,
916 VBO_SAVE_BUFFER_SIZE,
918 GL_STATIC_DRAW_ARB, GL_MAP_WRITE_BIT |
919 MESA_GALLIUM_VERTEX_STATE_STORAGE,
922 handle_out_of_memory(ctx);
925 GLuint offsets[VBO_ATTRIB_MAX];
926 for (unsigned i = 0, offset = 0; i < VBO_ATTRIB_MAX; ++i) {
928 offset += save->attrsz[i] * sizeof(GLfloat);
930 /* Create a pair of VAOs for the possible VERTEX_PROCESSING_MODEs
931 * Note that this may reuse the previous one of possible.
933 for (gl_vertex_processing_mode vpm = VP_MODE_FF; vpm < VP_MODE_MAX; ++vpm) {
934 /* create or reuse the vao */
935 update_vao(ctx, vpm, &save->VAO[vpm],
936 save->current_bo, buffer_offset, stride,
937 save->enabled, save->attrsz, save->attrtype, offsets);
938 /* Reference the vao in the dlist */
939 node->cold->VAO[vpm] = NULL;
940 _mesa_reference_vao(ctx, &node->cold->VAO[vpm], save->VAO[vpm]);
943 /* Prepare for DrawGalliumVertexState */
944 if (node->num_draws && ctx->Driver.DrawGalliumVertexState) {
945 for (unsigned i = 0; i < VP_MODE_MAX; i++) {
946 uint32_t enabled_attribs = _vbo_get_vao_filter(i) &
947 node->cold->VAO[i]->_EnabledWithMapMode;
950 ctx->Driver.CreateGalliumVertexState(ctx, node->cold->VAO[i],
953 node->private_refcount[i] = 0;
954 node->enabled_attribs[i] = enabled_attribs;
958 node->mode = node->cold->info.mode;
959 assert(node->cold->info.index_size == 4);
962 /* Deal with GL_COMPILE_AND_EXECUTE:
964 if (ctx->ExecuteFlag) {
965 struct _glapi_table *dispatch = GET_DISPATCH();
967 _glapi_set_dispatch(ctx->Exec);
969 /* _vbo_loopback_vertex_list doesn't use the index buffer, so we have to
970 * use buffer_in_ram instead of current_bo which contains all vertices instead
971 * of the deduplicated vertices only in the !UseLoopback case.
973 * The problem is that the VAO offset is based on current_bo's layout,
974 * so we have to use a temp value.
976 struct gl_vertex_array_object *vao = node->cold->VAO[VP_MODE_SHADER];
977 GLintptr original = vao->BufferBinding[0].Offset;
978 if (!ctx->ListState.Current.UseLoopback) {
979 GLintptr new_offset = 0;
980 /* 'start_offset' has been added to all primitives 'start', so undo it here. */
981 new_offset -= start_offset * stride;
982 vao->BufferBinding[0].Offset = new_offset;
984 _vbo_loopback_vertex_list(ctx, node, save->vertex_store->buffer_in_ram);
985 vao->BufferBinding[0].Offset = original;
987 _glapi_set_dispatch(dispatch);
990 /* Reset our structures for the next run of vertices:
997 * This is called when we fill a vertex buffer before we hit a glEnd().
999 * TODO -- If no new vertices have been stored, don't bother saving it.
1002 wrap_buffers(struct gl_context *ctx)
1004 struct vbo_save_context *save = &vbo_context(ctx)->save;
1005 GLint i = save->prim_store->used - 1;
1008 assert(i < (GLint) save->prim_store->size);
1011 /* Close off in-progress primitive.
1013 save->prim_store->prims[i].count = (get_vertex_count(save) - save->prim_store->prims[i].start);
1014 mode = save->prim_store->prims[i].mode;
1016 /* store the copied vertices, and allocate a new list.
1018 compile_vertex_list(ctx);
1020 /* Restart interrupted primitive
1022 save->prim_store->prims[0].mode = mode;
1023 save->prim_store->prims[0].begin = 0;
1024 save->prim_store->prims[0].end = 0;
1025 save->prim_store->prims[0].start = 0;
1026 save->prim_store->prims[0].count = 0;
1027 save->prim_store->used = 1;
1032 * Called only when buffers are wrapped as the result of filling the
1033 * vertex_store struct.
1036 wrap_filled_vertex(struct gl_context *ctx)
1038 struct vbo_save_context *save = &vbo_context(ctx)->save;
1039 unsigned numComponents;
1041 /* Emit a glEnd to close off the last vertex list.
1045 assert(save->vertex_store->used == 0 && save->vertex_store->used == 0);
1047 /* Copy stored stored vertices to start of new list.
1049 numComponents = save->copied.nr * save->vertex_size;
1051 fi_type *buffer_ptr = save->vertex_store->buffer_in_ram;
1052 if (numComponents) {
1053 assert(save->copied.buffer);
1055 save->copied.buffer,
1056 numComponents * sizeof(fi_type));
1057 free(save->copied.buffer);
1058 save->copied.buffer = NULL;
1060 save->vertex_store->used = numComponents;
1065 copy_to_current(struct gl_context *ctx)
1067 struct vbo_save_context *save = &vbo_context(ctx)->save;
1068 GLbitfield64 enabled = save->enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));
1071 const int i = u_bit_scan64(&enabled);
1072 assert(save->attrsz[i]);
1074 if (save->attrtype[i] == GL_DOUBLE ||
1075 save->attrtype[i] == GL_UNSIGNED_INT64_ARB)
1076 memcpy(save->current[i], save->attrptr[i], save->attrsz[i] * sizeof(GLfloat));
1078 COPY_CLEAN_4V_TYPE_AS_UNION(save->current[i], save->attrsz[i],
1079 save->attrptr[i], save->attrtype[i]);
1085 copy_from_current(struct gl_context *ctx)
1087 struct vbo_save_context *save = &vbo_context(ctx)->save;
1088 GLbitfield64 enabled = save->enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));
1091 const int i = u_bit_scan64(&enabled);
1093 switch (save->attrsz[i]) {
1095 save->attrptr[i][3] = save->current[i][3];
1098 save->attrptr[i][2] = save->current[i][2];
1101 save->attrptr[i][1] = save->current[i][1];
1104 save->attrptr[i][0] = save->current[i][0];
1107 unreachable("Unexpected vertex attribute size");
1114 * Called when we increase the size of a vertex attribute. For example,
1115 * if we've seen one or more glTexCoord2f() calls and now we get a
1116 * glTexCoord3f() call.
1117 * Flush existing data, set new attrib size, replay copied vertices.
1120 upgrade_vertex(struct gl_context *ctx, GLuint attr, GLuint newsz)
1122 struct vbo_save_context *save = &vbo_context(ctx)->save;
1127 /* Store the current run of vertices, and emit a GL_END. Emit a
1128 * BEGIN in the new buffer.
1130 if (save->vertex_store->used)
1133 assert(save->copied.nr == 0);
1135 /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
1136 * when the attribute already exists in the vertex and is having
1137 * its size increased.
1139 copy_to_current(ctx);
1143 oldsz = save->attrsz[attr];
1144 save->attrsz[attr] = newsz;
1145 save->enabled |= BITFIELD64_BIT(attr);
1147 save->vertex_size += newsz - oldsz;
1149 /* Recalculate all the attrptr[] values:
1152 for (i = 0; i < VBO_ATTRIB_MAX; i++) {
1153 if (save->attrsz[i]) {
1154 save->attrptr[i] = tmp;
1155 tmp += save->attrsz[i];
1158 save->attrptr[i] = NULL; /* will not be dereferenced. */
1162 /* Copy from current to repopulate the vertex with correct values.
1164 copy_from_current(ctx);
1166 /* Replay stored vertices to translate them to new format here.
1168 * If there are copied vertices and the new (upgraded) attribute
1169 * has not been defined before, this list is somewhat degenerate,
1170 * and will need fixup at runtime.
1172 if (save->copied.nr) {
1173 assert(save->copied.buffer);
1174 const fi_type *data = save->copied.buffer;
1175 grow_vertex_storage(ctx, save->copied.nr);
1176 fi_type *dest = save->vertex_store->buffer_in_ram;
1178 /* Need to note this and fix up at runtime (or loopback):
1180 if (attr != VBO_ATTRIB_POS && save->currentsz[attr][0] == 0) {
1182 save->dangling_attr_ref = GL_TRUE;
1185 for (i = 0; i < save->copied.nr; i++) {
1186 GLbitfield64 enabled = save->enabled;
1188 const int j = u_bit_scan64(&enabled);
1189 assert(save->attrsz[j]);
1192 const fi_type *src = oldsz ? data : save->current[attr];
1193 int copy = oldsz ? oldsz : newsz;
1194 for (k = 0; k < copy; k++)
1196 for (; k < newsz; k++) {
1197 switch (save->attrtype[j]) {
1199 dest[k] = FLOAT_AS_UNION(k == 3);
1202 dest[k] = INT_AS_UNION(k == 3);
1204 case GL_UNSIGNED_INT:
1205 dest[k] = UINT_AS_UNION(k == 3);
1208 dest[k] = FLOAT_AS_UNION(k == 3);
1209 assert(!"Unexpected type in upgrade_vertex");
1216 GLint sz = save->attrsz[j];
1217 for (int k = 0; k < sz; k++)
1225 save->vertex_store->used += save->vertex_size * save->copied.nr;
1226 free(save->copied.buffer);
1227 save->copied.buffer = NULL;
1233 * This is called when the size of a vertex attribute changes.
1234 * For example, after seeing one or more glTexCoord2f() calls we
1235 * get a glTexCoord4f() or glTexCoord1f() call.
1238 fixup_vertex(struct gl_context *ctx, GLuint attr,
1239 GLuint sz, GLenum newType)
1241 struct vbo_save_context *save = &vbo_context(ctx)->save;
1243 if (sz > save->attrsz[attr] ||
1244 newType != save->attrtype[attr]) {
1245 /* New size is larger. Need to flush existing vertices and get
1246 * an enlarged vertex format.
1248 upgrade_vertex(ctx, attr, sz);
1250 else if (sz < save->active_sz[attr]) {
1252 const fi_type *id = vbo_get_default_vals_as_union(save->attrtype[attr]);
1254 /* New size is equal or smaller - just need to fill in some
1257 for (i = sz; i <= save->attrsz[attr]; i++)
1258 save->attrptr[attr][i - 1] = id[i - 1];
1261 save->active_sz[attr] = sz;
1263 grow_vertex_storage(ctx, 1);
1268 * Reset the current size of all vertex attributes to the default
1269 * value of 0. This signals that we haven't yet seen any per-vertex
1270 * commands such as glNormal3f() or glTexCoord2f().
1273 reset_vertex(struct gl_context *ctx)
1275 struct vbo_save_context *save = &vbo_context(ctx)->save;
1277 while (save->enabled) {
1278 const int i = u_bit_scan64(&save->enabled);
1279 assert(save->attrsz[i]);
1280 save->attrsz[i] = 0;
1281 save->active_sz[i] = 0;
1284 save->vertex_size = 0;
1289 * If index=0, does glVertexAttrib*() alias glVertex() to emit a vertex?
1290 * It depends on a few things, including whether we're inside or outside
1294 is_vertex_position(const struct gl_context *ctx, GLuint index)
1296 return (index == 0 &&
1297 _mesa_attr_zero_aliases_vertex(ctx) &&
1298 _mesa_inside_dlist_begin_end(ctx));
1303 #define ERROR(err) _mesa_compile_error(ctx, err, __func__);
1306 /* Only one size for each attribute may be active at once. Eg. if
1307 * Color3f is installed/active, then Color4f may not be, even if the
1308 * vertex actually contains 4 color coordinates. This is because the
1309 * 3f version won't otherwise set color[3] to 1.0 -- this is the job
1310 * of the chooser function when switching between Color4f and Color3f.
1312 #define ATTR_UNION(A, N, T, C, V0, V1, V2, V3) \
1314 struct vbo_save_context *save = &vbo_context(ctx)->save; \
1315 int sz = (sizeof(C) / sizeof(GLfloat)); \
1317 if (save->active_sz[A] != N) \
1318 fixup_vertex(ctx, A, N * sz, T); \
1321 C *dest = (C *)save->attrptr[A]; \
1322 if (N>0) dest[0] = V0; \
1323 if (N>1) dest[1] = V1; \
1324 if (N>2) dest[2] = V2; \
1325 if (N>3) dest[3] = V3; \
1326 save->attrtype[A] = T; \
1329 if ((A) == VBO_ATTRIB_POS) { \
1330 fi_type *buffer_ptr = save->vertex_store->buffer_in_ram + \
1331 save->vertex_store->used; \
1333 for (int i = 0; i < save->vertex_size; i++) \
1334 buffer_ptr[i] = save->vertex[i]; \
1336 save->vertex_store->used += save->vertex_size; \
1337 unsigned used_next = (save->vertex_store->used + \
1338 save->vertex_size) * sizeof(float); \
1339 if (used_next > save->vertex_store->buffer_in_ram_size) { \
1340 grow_vertex_storage(ctx, get_vertex_count(save)); \
1341 assert(used_next <= \
1342 save->vertex_store->buffer_in_ram_size); \
1347 #define TAG(x) _save_##x
1349 #include "vbo_attrib_tmp.h"
1352 #define MAT( ATTR, N, face, params ) \
1354 if (face != GL_BACK) \
1355 MAT_ATTR( ATTR, N, params ); /* front */ \
1356 if (face != GL_FRONT) \
1357 MAT_ATTR( ATTR + 1, N, params ); /* back */ \
1362 * Save a glMaterial call found between glBegin/End.
1363 * glMaterial calls outside Begin/End are handled in dlist.c.
1365 static void GLAPIENTRY
1366 _save_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
1368 GET_CURRENT_CONTEXT(ctx);
1370 if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
1371 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(face)");
1377 MAT(VBO_ATTRIB_MAT_FRONT_EMISSION, 4, face, params);
1380 MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
1383 MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
1386 MAT(VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params);
1389 if (*params < 0 || *params > ctx->Const.MaxShininess) {
1390 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glMaterial(shininess)");
1393 MAT(VBO_ATTRIB_MAT_FRONT_SHININESS, 1, face, params);
1396 case GL_COLOR_INDEXES:
1397 MAT(VBO_ATTRIB_MAT_FRONT_INDEXES, 3, face, params);
1399 case GL_AMBIENT_AND_DIFFUSE:
1400 MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
1401 MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
1404 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(pname)");
1410 /* Cope with EvalCoord/CallList called within a begin/end object:
1411 * -- Flush current buffer
1412 * -- Fallback to opcodes for the rest of the begin/end object.
1415 dlist_fallback(struct gl_context *ctx)
1417 struct vbo_save_context *save = &vbo_context(ctx)->save;
1419 if (save->vertex_store->used || save->prim_store->used) {
1420 if (save->prim_store->used > 0 && save->vertex_store->used > 0) {
1421 assert(save->vertex_size);
1422 /* Close off in-progress primitive. */
1423 GLint i = save->prim_store->used - 1;
1424 save->prim_store->prims[i].count =
1425 get_vertex_count(save) -
1426 save->prim_store->prims[i].start;
1429 /* Need to replay this display list with loopback,
1430 * unfortunately, otherwise this primitive won't be handled
1433 save->dangling_attr_ref = GL_TRUE;
1435 compile_vertex_list(ctx);
1438 copy_to_current(ctx);
1440 if (save->out_of_memory) {
1441 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt);
1444 _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
1446 ctx->Driver.SaveNeedFlush = GL_FALSE;
1450 static void GLAPIENTRY
1451 _save_EvalCoord1f(GLfloat u)
1453 GET_CURRENT_CONTEXT(ctx);
1454 dlist_fallback(ctx);
1455 CALL_EvalCoord1f(ctx->Save, (u));
1458 static void GLAPIENTRY
1459 _save_EvalCoord1fv(const GLfloat * v)
1461 GET_CURRENT_CONTEXT(ctx);
1462 dlist_fallback(ctx);
1463 CALL_EvalCoord1fv(ctx->Save, (v));
1466 static void GLAPIENTRY
1467 _save_EvalCoord2f(GLfloat u, GLfloat v)
1469 GET_CURRENT_CONTEXT(ctx);
1470 dlist_fallback(ctx);
1471 CALL_EvalCoord2f(ctx->Save, (u, v));
1474 static void GLAPIENTRY
1475 _save_EvalCoord2fv(const GLfloat * v)
1477 GET_CURRENT_CONTEXT(ctx);
1478 dlist_fallback(ctx);
1479 CALL_EvalCoord2fv(ctx->Save, (v));
1482 static void GLAPIENTRY
1483 _save_EvalPoint1(GLint i)
1485 GET_CURRENT_CONTEXT(ctx);
1486 dlist_fallback(ctx);
1487 CALL_EvalPoint1(ctx->Save, (i));
1490 static void GLAPIENTRY
1491 _save_EvalPoint2(GLint i, GLint j)
1493 GET_CURRENT_CONTEXT(ctx);
1494 dlist_fallback(ctx);
1495 CALL_EvalPoint2(ctx->Save, (i, j));
1498 static void GLAPIENTRY
1499 _save_CallList(GLuint l)
1501 GET_CURRENT_CONTEXT(ctx);
1502 dlist_fallback(ctx);
1503 CALL_CallList(ctx->Save, (l));
1506 static void GLAPIENTRY
1507 _save_CallLists(GLsizei n, GLenum type, const GLvoid * v)
1509 GET_CURRENT_CONTEXT(ctx);
1510 dlist_fallback(ctx);
1511 CALL_CallLists(ctx->Save, (n, type, v));
1517 * Called when a glBegin is getting compiled into a display list.
1518 * Updating of ctx->Driver.CurrentSavePrimitive is already taken care of.
1521 vbo_save_NotifyBegin(struct gl_context *ctx, GLenum mode,
1522 bool no_current_update)
1524 struct vbo_save_context *save = &vbo_context(ctx)->save;
1525 const GLuint i = save->prim_store->used++;
1527 ctx->Driver.CurrentSavePrimitive = mode;
1529 if (!save->prim_store || i >= save->prim_store->size) {
1530 save->prim_store = realloc_prim_store(save->prim_store, i * 2);
1532 save->prim_store->prims[i].mode = mode & VBO_SAVE_PRIM_MODE_MASK;
1533 save->prim_store->prims[i].begin = 1;
1534 save->prim_store->prims[i].end = 0;
1535 save->prim_store->prims[i].start = get_vertex_count(save);
1536 save->prim_store->prims[i].count = 0;
1538 save->no_current_update = no_current_update;
1540 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt);
1542 /* We need to call vbo_save_SaveFlushVertices() if there's state change */
1543 ctx->Driver.SaveNeedFlush = GL_TRUE;
1547 static void GLAPIENTRY
1550 GET_CURRENT_CONTEXT(ctx);
1551 struct vbo_save_context *save = &vbo_context(ctx)->save;
1552 const GLint i = save->prim_store->used - 1;
1554 ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
1555 save->prim_store->prims[i].end = 1;
1556 save->prim_store->prims[i].count = (get_vertex_count(save) - save->prim_store->prims[i].start);
1558 /* Swap out this vertex format while outside begin/end. Any color,
1559 * etc. received between here and the next begin will be compiled
1562 if (save->out_of_memory) {
1563 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt);
1566 _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
1571 static void GLAPIENTRY
1572 _save_Begin(GLenum mode)
1574 GET_CURRENT_CONTEXT(ctx);
1576 _mesa_compile_error(ctx, GL_INVALID_OPERATION, "Recursive glBegin");
1580 static void GLAPIENTRY
1581 _save_PrimitiveRestartNV(void)
1583 GET_CURRENT_CONTEXT(ctx);
1584 struct vbo_save_context *save = &vbo_context(ctx)->save;
1586 if (save->prim_store->used == 0) {
1587 /* We're not inside a glBegin/End pair, so calling glPrimitiverRestartNV
1590 _mesa_compile_error(ctx, GL_INVALID_OPERATION,
1591 "glPrimitiveRestartNV called outside glBegin/End");
1593 /* get current primitive mode */
1594 GLenum curPrim = save->prim_store->prims[save->prim_store->used - 1].mode;
1595 bool no_current_update = save->no_current_update;
1597 /* restart primitive */
1598 CALL_End(ctx->CurrentServerDispatch, ());
1599 vbo_save_NotifyBegin(ctx, curPrim, no_current_update);
1604 /* Unlike the functions above, these are to be hooked into the vtxfmt
1605 * maintained in ctx->ListState, active when the list is known or
1606 * suspected to be outside any begin/end primitive.
1607 * Note: OBE = Outside Begin/End
1610 save_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
1612 GET_CURRENT_CONTEXT(ctx);
1613 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1615 vbo_save_NotifyBegin(ctx, GL_QUADS, false);
1616 CALL_Vertex2f(dispatch, (x1, y1));
1617 CALL_Vertex2f(dispatch, (x2, y1));
1618 CALL_Vertex2f(dispatch, (x2, y2));
1619 CALL_Vertex2f(dispatch, (x1, y2));
1620 CALL_End(dispatch, ());
1625 save_Rectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)
1627 save_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1631 save_Rectdv(const GLdouble *v1, const GLdouble *v2)
1633 save_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1637 save_Rectfv(const GLfloat *v1, const GLfloat *v2)
1639 save_Rectf(v1[0], v1[1], v2[0], v2[1]);
1643 save_Recti(GLint x1, GLint y1, GLint x2, GLint y2)
1645 save_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1649 save_Rectiv(const GLint *v1, const GLint *v2)
1651 save_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1655 save_Rects(GLshort x1, GLshort y1, GLshort x2, GLshort y2)
1657 save_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1661 save_Rectsv(const GLshort *v1, const GLshort *v2)
1663 save_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1667 save_DrawArrays(GLenum mode, GLint start, GLsizei count)
1669 GET_CURRENT_CONTEXT(ctx);
1670 struct gl_vertex_array_object *vao = ctx->Array.VAO;
1671 struct vbo_save_context *save = &vbo_context(ctx)->save;
1674 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1675 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawArrays(mode)");
1679 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawArrays(count<0)");
1683 if (save->out_of_memory)
1686 grow_vertex_storage(ctx, count);
1688 /* Make sure to process any VBO binding changes */
1689 _mesa_update_state(ctx);
1691 _mesa_vao_map_arrays(ctx, vao, GL_MAP_READ_BIT);
1693 vbo_save_NotifyBegin(ctx, mode, true);
1695 for (i = 0; i < count; i++)
1696 _mesa_array_element(ctx, start + i);
1697 CALL_End(ctx->CurrentServerDispatch, ());
1699 _mesa_vao_unmap_arrays(ctx, vao);
1704 save_MultiDrawArrays(GLenum mode, const GLint *first,
1705 const GLsizei *count, GLsizei primcount)
1707 GET_CURRENT_CONTEXT(ctx);
1710 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1711 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMultiDrawArrays(mode)");
1715 if (primcount < 0) {
1716 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1717 "glMultiDrawArrays(primcount<0)");
1721 unsigned vertcount = 0;
1722 for (i = 0; i < primcount; i++) {
1724 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1725 "glMultiDrawArrays(count[i]<0)");
1728 vertcount += count[i];
1731 grow_vertex_storage(ctx, vertcount);
1733 for (i = 0; i < primcount; i++) {
1735 save_DrawArrays(mode, first[i], count[i]);
1742 array_element(struct gl_context *ctx,
1743 GLint basevertex, GLuint elt, unsigned index_size_shift)
1745 /* Section 10.3.5 Primitive Restart:
1747 * When one of the *BaseVertex drawing commands specified in section 10.5
1748 * is used, the primitive restart comparison occurs before the basevertex
1749 * offset is added to the array index.
1751 /* If PrimitiveRestart is enabled and the index is the RestartIndex
1752 * then we call PrimitiveRestartNV and return.
1754 if (ctx->Array._PrimitiveRestart[index_size_shift] &&
1755 elt == ctx->Array._RestartIndex[index_size_shift]) {
1756 CALL_PrimitiveRestartNV(ctx->CurrentServerDispatch, ());
1760 _mesa_array_element(ctx, basevertex + elt);
1764 /* Could do better by copying the arrays and element list intact and
1765 * then emitting an indexed prim at runtime.
1768 save_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1769 const GLvoid * indices, GLint basevertex)
1771 GET_CURRENT_CONTEXT(ctx);
1772 struct vbo_save_context *save = &vbo_context(ctx)->save;
1773 struct gl_vertex_array_object *vao = ctx->Array.VAO;
1774 struct gl_buffer_object *indexbuf = vao->IndexBufferObj;
1777 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1778 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawElements(mode)");
1782 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawElements(count<0)");
1785 if (type != GL_UNSIGNED_BYTE &&
1786 type != GL_UNSIGNED_SHORT &&
1787 type != GL_UNSIGNED_INT) {
1788 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawElements(count<0)");
1792 if (save->out_of_memory)
1795 grow_vertex_storage(ctx, count);
1797 /* Make sure to process any VBO binding changes */
1798 _mesa_update_state(ctx);
1800 _mesa_vao_map(ctx, vao, GL_MAP_READ_BIT);
1804 ADD_POINTERS(indexbuf->Mappings[MAP_INTERNAL].Pointer, indices);
1806 vbo_save_NotifyBegin(ctx, mode, true);
1809 case GL_UNSIGNED_BYTE:
1810 for (i = 0; i < count; i++)
1811 array_element(ctx, basevertex, ((GLubyte *) indices)[i], 0);
1813 case GL_UNSIGNED_SHORT:
1814 for (i = 0; i < count; i++)
1815 array_element(ctx, basevertex, ((GLushort *) indices)[i], 1);
1817 case GL_UNSIGNED_INT:
1818 for (i = 0; i < count; i++)
1819 array_element(ctx, basevertex, ((GLuint *) indices)[i], 2);
1822 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawElements(type)");
1826 CALL_End(ctx->CurrentServerDispatch, ());
1828 _mesa_vao_unmap(ctx, vao);
1832 save_DrawElements(GLenum mode, GLsizei count, GLenum type,
1833 const GLvoid * indices)
1835 save_DrawElementsBaseVertex(mode, count, type, indices, 0);
1840 save_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
1841 GLsizei count, GLenum type,
1842 const GLvoid * indices)
1844 GET_CURRENT_CONTEXT(ctx);
1845 struct vbo_save_context *save = &vbo_context(ctx)->save;
1847 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1848 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(mode)");
1852 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1853 "glDrawRangeElements(count<0)");
1856 if (type != GL_UNSIGNED_BYTE &&
1857 type != GL_UNSIGNED_SHORT &&
1858 type != GL_UNSIGNED_INT) {
1859 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(type)");
1863 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1864 "glDrawRangeElements(end < start)");
1868 if (save->out_of_memory)
1871 save_DrawElements(mode, count, type, indices);
1876 save_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
1877 const GLvoid * const *indices, GLsizei primcount)
1879 GET_CURRENT_CONTEXT(ctx);
1880 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1884 for (i = 0; i < primcount; i++) {
1885 vertcount += count[i];
1887 grow_vertex_storage(ctx, vertcount);
1889 for (i = 0; i < primcount; i++) {
1891 CALL_DrawElements(dispatch, (mode, count[i], type, indices[i]));
1898 save_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count,
1900 const GLvoid * const *indices,
1902 const GLint *basevertex)
1904 GET_CURRENT_CONTEXT(ctx);
1905 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1909 for (i = 0; i < primcount; i++) {
1910 vertcount += count[i];
1912 grow_vertex_storage(ctx, vertcount);
1914 for (i = 0; i < primcount; i++) {
1916 CALL_DrawElementsBaseVertex(dispatch, (mode, count[i], type,
1925 vtxfmt_init(struct gl_context *ctx)
1927 struct vbo_save_context *save = &vbo_context(ctx)->save;
1928 GLvertexformat *vfmt = &save->vtxfmt;
1930 #define NAME_AE(x) _ae_##x
1931 #define NAME_CALLLIST(x) _save_##x
1932 #define NAME(x) _save_##x
1933 #define NAME_ES(x) _save_##x##ARB
1935 #include "vbo_init_tmp.h"
1940 vbo_save_SaveFlushVertices(struct gl_context *ctx)
1942 struct vbo_save_context *save = &vbo_context(ctx)->save;
1944 /* Noop when we are actually active:
1946 if (ctx->Driver.CurrentSavePrimitive <= PRIM_MAX)
1949 if (save->vertex_store->used || save->prim_store->used)
1950 compile_vertex_list(ctx);
1952 copy_to_current(ctx);
1954 ctx->Driver.SaveNeedFlush = GL_FALSE;
1959 * Called from glNewList when we're starting to compile a display list.
1962 vbo_save_NewList(struct gl_context *ctx, GLuint list, GLenum mode)
1964 struct vbo_save_context *save = &vbo_context(ctx)->save;
1969 if (!save->prim_store)
1970 save->prim_store = realloc_prim_store(NULL, 8);
1972 if (!save->vertex_store)
1973 save->vertex_store = CALLOC_STRUCT(vbo_save_vertex_store);
1976 ctx->Driver.SaveNeedFlush = GL_FALSE;
1981 * Called from glEndList when we're finished compiling a display list.
1984 vbo_save_EndList(struct gl_context *ctx)
1986 struct vbo_save_context *save = &vbo_context(ctx)->save;
1988 /* EndList called inside a (saved) Begin/End pair?
1990 if (_mesa_inside_dlist_begin_end(ctx)) {
1991 if (save->prim_store->used > 0) {
1992 GLint i = save->prim_store->used - 1;
1993 ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
1994 save->prim_store->prims[i].end = 0;
1995 save->prim_store->prims[i].count = get_vertex_count(save) - save->prim_store->prims[i].start;
1998 /* Make sure this vertex list gets replayed by the "loopback"
2001 save->dangling_attr_ref = GL_TRUE;
2002 vbo_save_SaveFlushVertices(ctx);
2004 /* Swap out this vertex format while outside begin/end. Any color,
2005 * etc. received between here and the next begin will be compiled
2008 _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
2011 assert(save->vertex_size == 0);
2015 * Called during context creation/init.
2018 current_init(struct gl_context *ctx)
2020 struct vbo_save_context *save = &vbo_context(ctx)->save;
2023 for (i = VBO_ATTRIB_POS; i <= VBO_ATTRIB_EDGEFLAG; i++) {
2024 const GLuint j = i - VBO_ATTRIB_POS;
2025 assert(j < VERT_ATTRIB_MAX);
2026 save->currentsz[i] = &ctx->ListState.ActiveAttribSize[j];
2027 save->current[i] = (fi_type *) ctx->ListState.CurrentAttrib[j];
2030 for (i = VBO_ATTRIB_FIRST_MATERIAL; i <= VBO_ATTRIB_LAST_MATERIAL; i++) {
2031 const GLuint j = i - VBO_ATTRIB_FIRST_MATERIAL;
2032 assert(j < MAT_ATTRIB_MAX);
2033 save->currentsz[i] = &ctx->ListState.ActiveMaterialSize[j];
2034 save->current[i] = (fi_type *) ctx->ListState.CurrentMaterial[j];
2040 * Initialize the display list compiler. Called during context creation.
2043 vbo_save_api_init(struct vbo_save_context *save)
2045 struct gl_context *ctx = gl_context_from_vbo_save(save);