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"
121 #include "gallium/include/pipe/p_state.h"
123 #include "vbo_noop.h"
124 #include "vbo_private.h"
131 /* An interesting VBO number/name to help with debugging */
132 #define VBO_BUF_ID 12345
134 static void GLAPIENTRY
135 _save_Materialfv(GLenum face, GLenum pname, const GLfloat *params);
137 static void GLAPIENTRY
138 _save_EvalCoord1f(GLfloat u);
140 static void GLAPIENTRY
141 _save_EvalCoord2f(GLfloat u, GLfloat v);
144 handle_out_of_memory(struct gl_context *ctx)
146 struct vbo_save_context *save = &vbo_context(ctx)->save;
147 _mesa_noop_vtxfmt_init(ctx, &save->vtxfmt);
148 save->out_of_memory = true;
152 * NOTE: Old 'parity' issue is gone, but copying can still be
153 * wrong-footed on replay.
156 copy_vertices(struct gl_context *ctx,
157 const struct vbo_save_vertex_list *node,
158 const fi_type * src_buffer)
160 struct vbo_save_context *save = &vbo_context(ctx)->save;
161 struct _mesa_prim *prim = &node->cold->prims[node->cold->prim_count - 1];
162 GLuint sz = save->vertex_size;
164 if (prim->end || !prim->count || !sz)
167 const fi_type *src = src_buffer + prim->start * sz;
168 assert(save->copied.buffer == NULL);
169 save->copied.buffer = malloc(sizeof(fi_type) * sz * prim->count);
171 return vbo_copy_vertices(ctx, prim->mode, prim->start, &prim->count,
172 prim->begin, sz, true, save->copied.buffer, src);
176 static struct vbo_save_vertex_store *
177 realloc_vertex_store(struct vbo_save_vertex_store *store, uint32_t vertex_size, int vertex_count)
180 store = CALLOC_STRUCT(vbo_save_vertex_store);
182 int new_size = MAX2(vertex_count * vertex_size * sizeof(GLfloat), 1024 * 1024);
183 if (new_size > store->buffer_in_ram_size) {
184 store->buffer_in_ram_size = new_size;
185 store->buffer_in_ram = realloc(store->buffer_in_ram, store->buffer_in_ram_size);
192 static struct vbo_save_primitive_store *
193 realloc_prim_store(struct vbo_save_primitive_store *store, int prim_count)
196 store = CALLOC_STRUCT(vbo_save_primitive_store);
198 uint32_t old_size = store->size;
199 store->size = MAX3(store->size, prim_count, 128);
200 store->prims = realloc(store->prims, store->size * sizeof(struct _mesa_prim));
201 memset(&store->prims[old_size], 0, (store->size - old_size) * sizeof(struct _mesa_prim));
208 reset_counters(struct gl_context *ctx)
210 struct vbo_save_context *save = &vbo_context(ctx)->save;
212 save->vertex_store->used = 0;
213 save->prim_store->used = 0;
214 save->dangling_attr_ref = GL_FALSE;
218 * For a list of prims, try merging prims that can just be extensions of the
222 merge_prims(struct gl_context *ctx, struct _mesa_prim *prim_list,
226 struct _mesa_prim *prev_prim = prim_list;
228 for (i = 1; i < *prim_count; i++) {
229 struct _mesa_prim *this_prim = prim_list + i;
231 vbo_try_prim_conversion(&this_prim->mode, &this_prim->count);
233 if (vbo_merge_draws(ctx, true,
234 prev_prim->mode, this_prim->mode,
235 prev_prim->start, this_prim->start,
236 &prev_prim->count, this_prim->count,
237 prev_prim->basevertex, this_prim->basevertex,
239 this_prim->begin, this_prim->end)) {
240 /* We've found a prim that just extend the previous one. Tack it
241 * onto the previous one, and let this primitive struct get dropped.
246 /* If any previous primitives have been dropped, then we need to copy
247 * this later one into the next available slot.
250 if (prev_prim != this_prim)
251 *prev_prim = *this_prim;
254 *prim_count = prev_prim - prim_list + 1;
259 * Convert GL_LINE_LOOP primitive into GL_LINE_STRIP so that drivers
260 * don't have to worry about handling the _mesa_prim::begin/end flags.
261 * See https://bugs.freedesktop.org/show_bug.cgi?id=81174
264 convert_line_loop_to_strip(struct vbo_save_context *save,
265 struct vbo_save_vertex_list *node)
267 struct _mesa_prim *prim = &node->cold->prims[node->cold->prim_count - 1];
269 assert(prim->mode == GL_LINE_LOOP);
272 /* Copy the 0th vertex to end of the buffer and extend the
273 * vertex count by one to finish the line loop.
275 const GLuint sz = save->vertex_size;
277 const fi_type *src = save->vertex_store->buffer_in_ram + prim->start * sz;
279 fi_type *dst = save->vertex_store->buffer_in_ram + (prim->start + prim->count) * sz;
281 memcpy(dst, src, sz * sizeof(float));
284 node->cold->vertex_count++;
285 save->vertex_store->used += sz;
289 /* Drawing the second or later section of a long line loop.
290 * Skip the 0th vertex.
296 prim->mode = GL_LINE_STRIP;
300 /* Compare the present vao if it has the same setup. */
302 compare_vao(gl_vertex_processing_mode mode,
303 const struct gl_vertex_array_object *vao,
304 const struct gl_buffer_object *bo, GLintptr buffer_offset,
305 GLuint stride, GLbitfield64 vao_enabled,
306 const GLubyte size[VBO_ATTRIB_MAX],
307 const GLenum16 type[VBO_ATTRIB_MAX],
308 const GLuint offset[VBO_ATTRIB_MAX])
313 /* If the enabled arrays are not the same we are not equal. */
314 if (vao_enabled != vao->Enabled)
317 /* Check the buffer binding at 0 */
318 if (vao->BufferBinding[0].BufferObj != bo)
320 /* BufferBinding[0].Offset != buffer_offset is checked per attribute */
321 if (vao->BufferBinding[0].Stride != stride)
323 assert(vao->BufferBinding[0].InstanceDivisor == 0);
325 /* Retrieve the mapping from VBO_ATTRIB to VERT_ATTRIB space */
326 const GLubyte *const vao_to_vbo_map = _vbo_attribute_alias_map[mode];
328 /* Now check the enabled arrays */
329 GLbitfield mask = vao_enabled;
331 const int attr = u_bit_scan(&mask);
332 const unsigned char vbo_attr = vao_to_vbo_map[attr];
333 const GLenum16 tp = type[vbo_attr];
334 const GLintptr off = offset[vbo_attr] + buffer_offset;
335 const struct gl_array_attributes *attrib = &vao->VertexAttrib[attr];
336 if (attrib->RelativeOffset + vao->BufferBinding[0].Offset != off)
338 if (attrib->Format.Type != tp)
340 if (attrib->Format.Size != size[vbo_attr])
342 assert(attrib->Format.Format == GL_RGBA);
343 assert(attrib->Format.Normalized == GL_FALSE);
344 assert(attrib->Format.Integer == vbo_attrtype_to_integer_flag(tp));
345 assert(attrib->Format.Doubles == vbo_attrtype_to_double_flag(tp));
346 assert(attrib->BufferBindingIndex == 0);
353 /* Create or reuse the vao for the vertex processing mode. */
355 update_vao(struct gl_context *ctx,
356 gl_vertex_processing_mode mode,
357 struct gl_vertex_array_object **vao,
358 struct gl_buffer_object *bo, GLintptr buffer_offset,
359 GLuint stride, GLbitfield64 vbo_enabled,
360 const GLubyte size[VBO_ATTRIB_MAX],
361 const GLenum16 type[VBO_ATTRIB_MAX],
362 const GLuint offset[VBO_ATTRIB_MAX])
364 /* Compute the bitmasks of vao_enabled arrays */
365 GLbitfield vao_enabled = _vbo_get_vao_enabled_from_vbo(mode, vbo_enabled);
368 * Check if we can possibly reuse the exisiting one.
369 * In the long term we should reset them when something changes.
371 if (compare_vao(mode, *vao, bo, buffer_offset, stride,
372 vao_enabled, size, type, offset))
375 /* The initial refcount is 1 */
376 _mesa_reference_vao(ctx, vao, NULL);
377 *vao = _mesa_new_vao(ctx, ~((GLuint)0));
380 * assert(stride <= ctx->Const.MaxVertexAttribStride);
381 * MaxVertexAttribStride is not set for drivers that does not
382 * expose GL 44 or GLES 31.
385 /* Bind the buffer object at binding point 0 */
386 _mesa_bind_vertex_buffer(ctx, *vao, 0, bo, buffer_offset, stride, false,
389 /* Retrieve the mapping from VBO_ATTRIB to VERT_ATTRIB space
390 * Note that the position/generic0 aliasing is done in the VAO.
392 const GLubyte *const vao_to_vbo_map = _vbo_attribute_alias_map[mode];
393 /* Now set the enable arrays */
394 GLbitfield mask = vao_enabled;
396 const int vao_attr = u_bit_scan(&mask);
397 const GLubyte vbo_attr = vao_to_vbo_map[vao_attr];
398 assert(offset[vbo_attr] <= ctx->Const.MaxVertexAttribRelativeOffset);
400 _vbo_set_attrib_format(ctx, *vao, vao_attr, buffer_offset,
401 size[vbo_attr], type[vbo_attr], offset[vbo_attr]);
402 _mesa_vertex_attrib_binding(ctx, *vao, vao_attr, 0);
404 _mesa_enable_vertex_array_attribs(ctx, *vao, vao_enabled);
405 assert(vao_enabled == (*vao)->Enabled);
406 assert((vao_enabled & ~(*vao)->VertexAttribBufferMask) == 0);
408 /* Finalize and freeze the VAO */
409 _mesa_set_vao_immutable(ctx, *vao);
413 static void wrap_filled_vertex(struct gl_context *ctx);
414 static void compile_vertex_list(struct gl_context *ctx);
417 realloc_storage(struct gl_context *ctx, int prim_count, int vertex_count)
419 struct vbo_save_context *save = &vbo_context(ctx)->save;
421 /* Limit how much memory we allocate. */
422 if (save->prim_store->used > 0 &&
424 vertex_count * save->vertex_size > VBO_SAVE_BUFFER_SIZE) {
425 wrap_filled_vertex(ctx);
426 vertex_count = VBO_SAVE_BUFFER_SIZE / save->vertex_size;
429 if (prim_count > 0 &&
430 prim_count * sizeof(struct _mesa_prim) > VBO_SAVE_BUFFER_SIZE) {
431 if (save->prim_store->used > 0)
432 compile_vertex_list(ctx);
433 prim_count = VBO_SAVE_BUFFER_SIZE / sizeof(struct _mesa_prim);
436 if (vertex_count >= 0)
437 save->vertex_store = realloc_vertex_store(save->vertex_store, save->vertex_size, vertex_count);
440 save->prim_store = realloc_prim_store(save->prim_store, prim_count);
442 if (save->vertex_store->buffer_in_ram == NULL ||
443 save->prim_store->prims == NULL)
444 handle_out_of_memory(ctx);
448 unsigned vertex_size;
449 fi_type *vertex_attributes;
452 static uint32_t _hash_vertex_key(const void *key)
454 struct vertex_key *k = (struct vertex_key*)key;
455 unsigned sz = k->vertex_size;
457 return _mesa_hash_data(k->vertex_attributes, sz * sizeof(float));
460 static bool _compare_vertex_key(const void *key1, const void *key2)
462 struct vertex_key *k1 = (struct vertex_key*)key1;
463 struct vertex_key *k2 = (struct vertex_key*)key2;
464 /* All the compared vertices are going to be drawn with the same VAO,
465 * so we can compare the attributes. */
466 assert (k1->vertex_size == k2->vertex_size);
467 return memcmp(k1->vertex_attributes,
468 k2->vertex_attributes,
469 k1->vertex_size * sizeof(float)) == 0;
472 static void _free_entry(struct hash_entry *entry)
474 free((void*)entry->key);
477 /* Add vertex to the vertex buffer and return its index. If this vertex is a duplicate
478 * of an existing vertex, return the original index instead.
481 add_vertex(struct vbo_save_context *save, struct hash_table *hash_to_index,
482 uint32_t index, fi_type *new_buffer, uint32_t *max_index)
484 /* If vertex deduplication is disabled return the original index. */
488 fi_type *vert = save->vertex_store->buffer_in_ram + save->vertex_size * index;
490 struct vertex_key *key = malloc(sizeof(struct vertex_key));
491 key->vertex_size = save->vertex_size;
492 key->vertex_attributes = vert;
494 struct hash_entry *entry = _mesa_hash_table_search(hash_to_index, key);
497 /* We found an existing vertex with the same hash, return its index. */
498 return (uintptr_t) entry->data;
500 /* This is a new vertex. Determine a new index and copy its attributes to the vertex
501 * buffer. Note that 'new_buffer' is created at each list compilation so we write vertices
502 * starting at index 0.
504 uint32_t n = _mesa_hash_table_num_entries(hash_to_index);
505 *max_index = MAX2(n, *max_index);
507 memcpy(&new_buffer[save->vertex_size * n],
509 save->vertex_size * sizeof(fi_type));
511 _mesa_hash_table_insert(hash_to_index, key, (void*)(uintptr_t)(n));
513 /* The index buffer is shared between list compilations, so add the base index to get
522 get_vertex_count(struct vbo_save_context *save)
524 if (!save->vertex_size)
526 return save->vertex_store->used / save->vertex_size;
531 * Insert the active immediate struct onto the display list currently
535 compile_vertex_list(struct gl_context *ctx)
537 struct vbo_save_context *save = &vbo_context(ctx)->save;
538 struct vbo_save_vertex_list *node;
540 /* Allocate space for this structure in the display list currently
543 node = (struct vbo_save_vertex_list *)
544 _mesa_dlist_alloc_vertex_list(ctx, !save->dangling_attr_ref && !save->no_current_update);
549 memset(node, 0, sizeof(struct vbo_save_vertex_list));
550 node->cold = calloc(1, sizeof(*node->cold));
552 /* Make sure the pointer is aligned to the size of a pointer */
553 assert((GLintptr) node % sizeof(void *) == 0);
555 const GLsizei stride = save->vertex_size*sizeof(GLfloat);
557 node->cold->vertex_count = get_vertex_count(save);
558 node->cold->wrap_count = save->copied.nr;
559 node->cold->prims = malloc(sizeof(struct _mesa_prim) * save->prim_store->used);
560 memcpy(node->cold->prims, save->prim_store->prims, sizeof(struct _mesa_prim) * save->prim_store->used);
561 node->cold->ib.obj = NULL;
562 node->cold->prim_count = save->prim_store->used;
564 if (save->no_current_update) {
565 node->cold->current_data = NULL;
568 GLuint current_size = save->vertex_size - save->attrsz[0];
569 node->cold->current_data = NULL;
572 node->cold->current_data = malloc(current_size * sizeof(GLfloat));
573 if (node->cold->current_data) {
574 const char *buffer = (const char *)save->vertex_store->buffer_in_ram;
575 unsigned attr_offset = save->attrsz[0] * sizeof(GLfloat);
576 unsigned vertex_offset = 0;
578 if (node->cold->vertex_count)
579 vertex_offset = (node->cold->vertex_count - 1) * stride;
581 memcpy(node->cold->current_data, buffer + vertex_offset + attr_offset,
582 current_size * sizeof(GLfloat));
584 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Current value allocation");
585 handle_out_of_memory(ctx);
590 assert(save->attrsz[VBO_ATTRIB_POS] != 0 || node->cold->vertex_count == 0);
592 if (save->dangling_attr_ref)
593 ctx->ListState.Current.UseLoopback = true;
595 /* Copy duplicated vertices
597 save->copied.nr = copy_vertices(ctx, node, save->vertex_store->buffer_in_ram);
599 if (node->cold->prims[node->cold->prim_count - 1].mode == GL_LINE_LOOP) {
600 convert_line_loop_to_strip(save, node);
603 merge_prims(ctx, node->cold->prims, &node->cold->prim_count);
605 GLintptr buffer_offset = 0;
606 GLuint start_offset = 0;
608 /* Create an index buffer. */
609 node->cold->min_index = node->cold->max_index = 0;
610 if (node->cold->vertex_count == 0 || node->cold->prim_count == 0)
613 /* We won't modify node->prims, so use a const alias to avoid unintended
615 const struct _mesa_prim *original_prims = node->cold->prims;
617 int end = original_prims[node->cold->prim_count - 1].start +
618 original_prims[node->cold->prim_count - 1].count;
619 int total_vert_count = end - original_prims[0].start;
621 node->cold->min_index = node->cold->prims[0].start;
622 node->cold->max_index = end - 1;
624 int max_index_count = total_vert_count * 2;
626 int size = max_index_count * sizeof(uint32_t);
627 uint32_t* indices = (uint32_t*) malloc(size);
628 struct _mesa_prim *merged_prims = NULL;
631 struct hash_table *vertex_to_index = NULL;
632 fi_type *temp_vertices_buffer = NULL;
634 /* The loopback replay code doesn't use the index buffer, so we can't
635 * dedup vertices in this case.
637 if (!ctx->ListState.Current.UseLoopback) {
638 vertex_to_index = _mesa_hash_table_create(NULL, _hash_vertex_key, _compare_vertex_key);
639 temp_vertices_buffer = malloc(save->vertex_store->buffer_in_ram_size);
642 uint32_t max_index = 0;
644 int last_valid_prim = -1;
645 /* Construct indices array. */
646 for (unsigned i = 0; i < node->cold->prim_count; i++) {
647 assert(original_prims[i].basevertex == 0);
648 GLubyte mode = original_prims[i].mode;
650 int vertex_count = original_prims[i].count;
655 /* Line strips may get converted to lines */
656 if (mode == GL_LINE_STRIP)
659 /* If 2 consecutive prims use the same mode => merge them. */
660 bool merge_prims = last_valid_prim >= 0 &&
661 mode == merged_prims[last_valid_prim].mode &&
662 mode != GL_LINE_LOOP && mode != GL_TRIANGLE_FAN &&
663 mode != GL_QUAD_STRIP && mode != GL_POLYGON &&
666 /* To be able to merge consecutive triangle strips we need to insert
667 * a degenerate triangle.
670 mode == GL_TRIANGLE_STRIP) {
671 /* Insert a degenerate triangle */
672 assert(merged_prims[last_valid_prim].mode == GL_TRIANGLE_STRIP);
673 unsigned tri_count = merged_prims[last_valid_prim].count - 2;
675 indices[idx] = indices[idx - 1];
676 indices[idx + 1] = add_vertex(save, vertex_to_index, original_prims[i].start,
677 temp_vertices_buffer, &max_index);
679 merged_prims[last_valid_prim].count += 2;
682 /* Add another index to preserve winding order */
683 indices[idx++] = add_vertex(save, vertex_to_index, original_prims[i].start,
684 temp_vertices_buffer, &max_index);
685 merged_prims[last_valid_prim].count++;
691 /* Convert line strips to lines if it'll allow if the previous
692 * prim mode is GL_LINES (so merge_prims is true) or if the next
693 * primitive mode is GL_LINES or GL_LINE_LOOP.
695 if (original_prims[i].mode == GL_LINE_STRIP &&
697 (i < node->cold->prim_count - 1 &&
698 (original_prims[i + 1].mode == GL_LINE_STRIP ||
699 original_prims[i + 1].mode == GL_LINES)))) {
700 for (unsigned j = 0; j < vertex_count; j++) {
701 indices[idx++] = add_vertex(save, vertex_to_index, original_prims[i].start + j,
702 temp_vertices_buffer, &max_index);
703 /* Repeat all but the first/last indices. */
704 if (j && j != vertex_count - 1) {
705 indices[idx++] = add_vertex(save, vertex_to_index, original_prims[i].start + j,
706 temp_vertices_buffer, &max_index);
710 /* We didn't convert to LINES, so restore the original mode */
711 mode = original_prims[i].mode;
713 for (unsigned j = 0; j < vertex_count; j++) {
714 indices[idx++] = add_vertex(save, vertex_to_index, original_prims[i].start + j,
715 temp_vertices_buffer, &max_index);
720 /* Update vertex count. */
721 merged_prims[last_valid_prim].count += idx - start;
723 /* Keep this primitive */
724 last_valid_prim += 1;
725 assert(last_valid_prim <= i);
726 merged_prims = realloc(merged_prims, (1 + last_valid_prim) * sizeof(struct _mesa_prim));
727 merged_prims[last_valid_prim] = original_prims[i];
728 merged_prims[last_valid_prim].start = start;
729 merged_prims[last_valid_prim].count = idx - start;
731 merged_prims[last_valid_prim].mode = mode;
734 assert(idx > 0 && idx <= max_index_count);
736 unsigned merged_prim_count = last_valid_prim + 1;
737 node->cold->ib.ptr = NULL;
738 node->cold->ib.count = idx;
739 node->cold->ib.index_size_shift = (GL_UNSIGNED_INT - GL_UNSIGNED_BYTE) >> 1;
741 /* How many bytes do we need to store the indices and the vertices */
742 total_vert_count = vertex_to_index ? (max_index + 1) : idx;
743 unsigned total_bytes_needed = idx * sizeof(uint32_t) +
744 total_vert_count * save->vertex_size * sizeof(fi_type);
746 const GLintptr old_offset = save->VAO[0] ?
747 save->VAO[0]->BufferBinding[0].Offset + save->VAO[0]->VertexAttrib[VERT_ATTRIB_POS].RelativeOffset : 0;
748 if (old_offset != save->current_bo_bytes_used && stride > 0) {
749 GLintptr offset_diff = save->current_bo_bytes_used - old_offset;
750 while (offset_diff > 0 &&
751 save->current_bo_bytes_used < save->current_bo->Size &&
752 offset_diff % stride != 0) {
753 save->current_bo_bytes_used++;
754 offset_diff = save->current_bo_bytes_used - old_offset;
757 buffer_offset = save->current_bo_bytes_used;
759 /* Can we reuse the previous bo or should we allocate a new one? */
760 int available_bytes = save->current_bo ? save->current_bo->Size - save->current_bo_bytes_used : 0;
761 if (total_bytes_needed > available_bytes) {
762 if (save->current_bo)
763 _mesa_reference_buffer_object(ctx, &save->current_bo, NULL);
764 save->current_bo = ctx->Driver.NewBufferObject(ctx, VBO_BUF_ID + 1);
765 bool success = ctx->Driver.BufferData(ctx,
766 GL_ELEMENT_ARRAY_BUFFER_ARB,
767 MAX2(total_bytes_needed, VBO_SAVE_BUFFER_SIZE),
769 GL_STATIC_DRAW_ARB, GL_MAP_WRITE_BIT,
772 _mesa_reference_buffer_object(ctx, &save->current_bo, NULL);
773 _mesa_error(ctx, GL_OUT_OF_MEMORY, "IB allocation");
774 handle_out_of_memory(ctx);
776 save->current_bo_bytes_used = 0;
777 available_bytes = save->current_bo->Size;
781 assert(old_offset <= buffer_offset);
782 const GLintptr offset_diff = buffer_offset - old_offset;
783 if (offset_diff > 0 && stride > 0 && offset_diff % stride == 0) {
784 /* The vertex size is an exact multiple of the buffer offset.
785 * This means that we can use zero-based vertex attribute pointers
786 * and specify the start of the primitive with the _mesa_prim::start
787 * field. This results in issuing several draw calls with identical
788 * vertex attribute information. This can result in fewer state
789 * changes in drivers. In particular, the Gallium CSO module will
790 * filter out redundant vertex buffer changes.
792 /* We cannot immediately update the primitives as some methods below
793 * still need the uncorrected start vertices
795 start_offset = offset_diff/stride;
796 assert(old_offset == buffer_offset - offset_diff);
797 buffer_offset = old_offset;
800 /* Correct the primitive starts, we can only do this here as copy_vertices
801 * and convert_line_loop_to_strip above consume the uncorrected starts.
802 * On the other hand the _vbo_loopback_vertex_list call below needs the
803 * primitives to be corrected already.
805 for (unsigned i = 0; i < node->cold->prim_count; i++) {
806 node->cold->prims[i].start += start_offset;
808 /* start_offset shifts vertices (so v[0] becomes v[start_offset]), so we have
809 * to apply this transformation to all indices and max_index.
811 for (unsigned i = 0; i < idx; i++)
812 indices[i] += start_offset;
813 max_index += start_offset;
816 _mesa_reference_buffer_object(ctx, &node->cold->ib.obj, save->current_bo);
818 /* Upload the vertices first (see buffer_offset) */
819 ctx->Driver.BufferSubData(ctx,
820 save->current_bo_bytes_used,
821 total_vert_count * save->vertex_size * sizeof(fi_type),
822 vertex_to_index ? temp_vertices_buffer : save->vertex_store->buffer_in_ram,
824 save->current_bo_bytes_used += total_vert_count * save->vertex_size * sizeof(fi_type);
826 if (vertex_to_index) {
827 _mesa_hash_table_destroy(vertex_to_index, _free_entry);
828 free(temp_vertices_buffer);
831 /* Since we're append the indices to an existing buffer, we need to adjust the start value of each
832 * primitive (not the indices themselves). */
833 save->current_bo_bytes_used += align(save->current_bo_bytes_used, 4) - save->current_bo_bytes_used;
834 int indices_offset = save->current_bo_bytes_used / 4;
835 for (int i = 0; i < merged_prim_count; i++) {
836 merged_prims[i].start += indices_offset;
839 /* Then upload the indices. */
840 if (node->cold->ib.obj) {
841 ctx->Driver.BufferSubData(ctx,
842 save->current_bo_bytes_used,
843 idx * sizeof(uint32_t),
846 save->current_bo_bytes_used += idx * sizeof(uint32_t);
848 node->cold->vertex_count = 0;
849 node->cold->prim_count = 0;
852 /* Prepare for DrawGallium */
853 memset(&node->merged.info, 0, sizeof(struct pipe_draw_info));
854 /* The other info fields will be updated in vbo_save_playback_vertex_list */
855 node->merged.info.index_size = 4;
856 node->merged.info.instance_count = 1;
857 node->merged.info.index.gl_bo = node->cold->ib.obj;
858 if (merged_prim_count == 1) {
859 node->merged.info.mode = merged_prims[0].mode;
860 node->merged.start_count.start = merged_prims[0].start;
861 node->merged.start_count.count = merged_prims[0].count;
862 node->merged.start_count.index_bias = 0;
863 node->merged.mode = NULL;
865 node->merged.mode = malloc(merged_prim_count * sizeof(unsigned char));
866 node->merged.start_counts = malloc(merged_prim_count * sizeof(struct pipe_draw_start_count_bias));
867 for (unsigned i = 0; i < merged_prim_count; i++) {
868 node->merged.start_counts[i].start = merged_prims[i].start;
869 node->merged.start_counts[i].count = merged_prims[i].count;
870 node->merged.start_counts[i].index_bias = 0;
871 node->merged.mode[i] = merged_prims[i].mode;
874 node->merged.num_draws = merged_prim_count;
875 if (node->merged.num_draws > 1) {
876 bool same_mode = true;
877 for (unsigned i = 1; i < node->merged.num_draws && same_mode; i++) {
878 same_mode = node->merged.mode[i] == node->merged.mode[0];
881 /* All primitives use the same mode, so we can simplify a bit */
882 node->merged.info.mode = node->merged.mode[0];
883 free(node->merged.mode);
884 node->merged.mode = NULL;
893 if (!save->current_bo) {
894 save->current_bo = ctx->Driver.NewBufferObject(ctx, VBO_BUF_ID + 1);
895 bool success = ctx->Driver.BufferData(ctx,
896 GL_ELEMENT_ARRAY_BUFFER_ARB,
897 VBO_SAVE_BUFFER_SIZE,
899 GL_STATIC_DRAW_ARB, GL_MAP_WRITE_BIT,
902 handle_out_of_memory(ctx);
905 GLuint offsets[VBO_ATTRIB_MAX];
906 for (unsigned i = 0, offset = 0; i < VBO_ATTRIB_MAX; ++i) {
908 offset += save->attrsz[i] * sizeof(GLfloat);
910 /* Create a pair of VAOs for the possible VERTEX_PROCESSING_MODEs
911 * Note that this may reuse the previous one of possible.
913 for (gl_vertex_processing_mode vpm = VP_MODE_FF; vpm < VP_MODE_MAX; ++vpm) {
914 /* create or reuse the vao */
915 update_vao(ctx, vpm, &save->VAO[vpm],
916 save->current_bo, buffer_offset, stride,
917 save->enabled, save->attrsz, save->attrtype, offsets);
918 /* Reference the vao in the dlist */
919 node->VAO[vpm] = NULL;
920 _mesa_reference_vao(ctx, &node->VAO[vpm], save->VAO[vpm]);
924 /* Deal with GL_COMPILE_AND_EXECUTE:
926 if (ctx->ExecuteFlag) {
927 struct _glapi_table *dispatch = GET_DISPATCH();
929 _glapi_set_dispatch(ctx->Exec);
931 /* _vbo_loopback_vertex_list doesn't use the index buffer, so we have to
932 * use buffer_in_ram instead of current_bo which contains all vertices instead
933 * of the deduplicated vertices only in the !UseLoopback case.
935 * The problem is that the VAO offset is based on current_bo's layout,
936 * so we have to use a temp value.
938 struct gl_vertex_array_object *vao = node->VAO[VP_MODE_SHADER];
939 GLintptr original = vao->BufferBinding[0].Offset;
940 if (!ctx->ListState.Current.UseLoopback) {
941 GLintptr new_offset = 0;
942 /* 'start_offset' has been added to all primitives 'start', so undo it here. */
943 new_offset -= start_offset * stride;
944 vao->BufferBinding[0].Offset = new_offset;
946 _vbo_loopback_vertex_list(ctx, node, save->vertex_store->buffer_in_ram);
947 vao->BufferBinding[0].Offset = original;
949 _glapi_set_dispatch(dispatch);
952 /* Reset our structures for the next run of vertices:
959 * This is called when we fill a vertex buffer before we hit a glEnd().
961 * TODO -- If no new vertices have been stored, don't bother saving it.
964 wrap_buffers(struct gl_context *ctx)
966 struct vbo_save_context *save = &vbo_context(ctx)->save;
967 GLint i = save->prim_store->used - 1;
970 assert(i < (GLint) save->prim_store->size);
973 /* Close off in-progress primitive.
975 save->prim_store->prims[i].count = (get_vertex_count(save) - save->prim_store->prims[i].start);
976 mode = save->prim_store->prims[i].mode;
978 /* store the copied vertices, and allocate a new list.
980 compile_vertex_list(ctx);
982 /* Restart interrupted primitive
984 save->prim_store->prims[0].mode = mode;
985 save->prim_store->prims[0].begin = 0;
986 save->prim_store->prims[0].end = 0;
987 save->prim_store->prims[0].start = 0;
988 save->prim_store->prims[0].count = 0;
989 save->prim_store->used = 1;
994 * Called only when buffers are wrapped as the result of filling the
995 * vertex_store struct.
998 wrap_filled_vertex(struct gl_context *ctx)
1000 struct vbo_save_context *save = &vbo_context(ctx)->save;
1001 unsigned numComponents;
1003 /* Emit a glEnd to close off the last vertex list.
1007 assert(save->vertex_store->used == 0 && save->vertex_store->used == 0);
1009 /* Copy stored stored vertices to start of new list.
1011 numComponents = save->copied.nr * save->vertex_size;
1013 fi_type *buffer_ptr = save->vertex_store->buffer_in_ram;
1014 if (numComponents) {
1015 assert(save->copied.buffer);
1017 save->copied.buffer,
1018 numComponents * sizeof(fi_type));
1019 free(save->copied.buffer);
1020 save->copied.buffer = NULL;
1022 save->vertex_store->used = numComponents;
1027 copy_to_current(struct gl_context *ctx)
1029 struct vbo_save_context *save = &vbo_context(ctx)->save;
1030 GLbitfield64 enabled = save->enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));
1033 const int i = u_bit_scan64(&enabled);
1034 assert(save->attrsz[i]);
1036 if (save->attrtype[i] == GL_DOUBLE ||
1037 save->attrtype[i] == GL_UNSIGNED_INT64_ARB)
1038 memcpy(save->current[i], save->attrptr[i], save->attrsz[i] * sizeof(GLfloat));
1040 COPY_CLEAN_4V_TYPE_AS_UNION(save->current[i], save->attrsz[i],
1041 save->attrptr[i], save->attrtype[i]);
1047 copy_from_current(struct gl_context *ctx)
1049 struct vbo_save_context *save = &vbo_context(ctx)->save;
1050 GLbitfield64 enabled = save->enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));
1053 const int i = u_bit_scan64(&enabled);
1055 switch (save->attrsz[i]) {
1057 save->attrptr[i][3] = save->current[i][3];
1060 save->attrptr[i][2] = save->current[i][2];
1063 save->attrptr[i][1] = save->current[i][1];
1066 save->attrptr[i][0] = save->current[i][0];
1069 unreachable("Unexpected vertex attribute size");
1076 * Called when we increase the size of a vertex attribute. For example,
1077 * if we've seen one or more glTexCoord2f() calls and now we get a
1078 * glTexCoord3f() call.
1079 * Flush existing data, set new attrib size, replay copied vertices.
1082 upgrade_vertex(struct gl_context *ctx, GLuint attr, GLuint newsz)
1084 struct vbo_save_context *save = &vbo_context(ctx)->save;
1089 /* Store the current run of vertices, and emit a GL_END. Emit a
1090 * BEGIN in the new buffer.
1092 if (save->vertex_store->used)
1095 assert(save->copied.nr == 0);
1097 /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
1098 * when the attribute already exists in the vertex and is having
1099 * its size increased.
1101 copy_to_current(ctx);
1105 oldsz = save->attrsz[attr];
1106 save->attrsz[attr] = newsz;
1107 save->enabled |= BITFIELD64_BIT(attr);
1109 save->vertex_size += newsz - oldsz;
1111 /* Recalculate all the attrptr[] values:
1114 for (i = 0; i < VBO_ATTRIB_MAX; i++) {
1115 if (save->attrsz[i]) {
1116 save->attrptr[i] = tmp;
1117 tmp += save->attrsz[i];
1120 save->attrptr[i] = NULL; /* will not be dereferenced. */
1124 /* Copy from current to repopulate the vertex with correct values.
1126 copy_from_current(ctx);
1128 /* Replay stored vertices to translate them to new format here.
1130 * If there are copied vertices and the new (upgraded) attribute
1131 * has not been defined before, this list is somewhat degenerate,
1132 * and will need fixup at runtime.
1134 if (save->copied.nr) {
1135 assert(save->copied.buffer);
1136 const fi_type *data = save->copied.buffer;
1137 fi_type *dest = save->vertex_store->buffer_in_ram;
1139 /* Need to note this and fix up at runtime (or loopback):
1141 if (attr != VBO_ATTRIB_POS && save->currentsz[attr][0] == 0) {
1143 save->dangling_attr_ref = GL_TRUE;
1146 for (i = 0; i < save->copied.nr; i++) {
1147 GLbitfield64 enabled = save->enabled;
1149 const int j = u_bit_scan64(&enabled);
1150 assert(save->attrsz[j]);
1153 COPY_CLEAN_4V_TYPE_AS_UNION(dest, oldsz, data,
1159 COPY_SZ_4V(dest, newsz, save->current[attr]);
1164 GLint sz = save->attrsz[j];
1165 COPY_SZ_4V(dest, sz, data);
1172 save->vertex_store->used += save->vertex_size * save->copied.nr;
1173 free(save->copied.buffer);
1174 save->copied.buffer = NULL;
1180 * This is called when the size of a vertex attribute changes.
1181 * For example, after seeing one or more glTexCoord2f() calls we
1182 * get a glTexCoord4f() or glTexCoord1f() call.
1185 fixup_vertex(struct gl_context *ctx, GLuint attr,
1186 GLuint sz, GLenum newType)
1188 struct vbo_save_context *save = &vbo_context(ctx)->save;
1190 if (sz > save->attrsz[attr] ||
1191 newType != save->attrtype[attr]) {
1192 /* New size is larger. Need to flush existing vertices and get
1193 * an enlarged vertex format.
1195 upgrade_vertex(ctx, attr, sz);
1197 else if (sz < save->active_sz[attr]) {
1199 const fi_type *id = vbo_get_default_vals_as_union(save->attrtype[attr]);
1201 /* New size is equal or smaller - just need to fill in some
1204 for (i = sz; i <= save->attrsz[attr]; i++)
1205 save->attrptr[attr][i - 1] = id[i - 1];
1208 save->active_sz[attr] = sz;
1213 * Reset the current size of all vertex attributes to the default
1214 * value of 0. This signals that we haven't yet seen any per-vertex
1215 * commands such as glNormal3f() or glTexCoord2f().
1218 reset_vertex(struct gl_context *ctx)
1220 struct vbo_save_context *save = &vbo_context(ctx)->save;
1222 while (save->enabled) {
1223 const int i = u_bit_scan64(&save->enabled);
1224 assert(save->attrsz[i]);
1225 save->attrsz[i] = 0;
1226 save->active_sz[i] = 0;
1229 save->vertex_size = 0;
1234 * If index=0, does glVertexAttrib*() alias glVertex() to emit a vertex?
1235 * It depends on a few things, including whether we're inside or outside
1239 is_vertex_position(const struct gl_context *ctx, GLuint index)
1241 return (index == 0 &&
1242 _mesa_attr_zero_aliases_vertex(ctx) &&
1243 _mesa_inside_dlist_begin_end(ctx));
1248 #define ERROR(err) _mesa_compile_error(ctx, err, __func__);
1251 /* Only one size for each attribute may be active at once. Eg. if
1252 * Color3f is installed/active, then Color4f may not be, even if the
1253 * vertex actually contains 4 color coordinates. This is because the
1254 * 3f version won't otherwise set color[3] to 1.0 -- this is the job
1255 * of the chooser function when switching between Color4f and Color3f.
1257 #define ATTR_UNION(A, N, T, C, V0, V1, V2, V3) \
1259 struct vbo_save_context *save = &vbo_context(ctx)->save; \
1260 int sz = (sizeof(C) / sizeof(GLfloat)); \
1262 if (save->active_sz[A] != N) \
1263 fixup_vertex(ctx, A, N * sz, T); \
1266 C *dest = (C *)save->attrptr[A]; \
1267 if (N>0) dest[0] = V0; \
1268 if (N>1) dest[1] = V1; \
1269 if (N>2) dest[2] = V2; \
1270 if (N>3) dest[3] = V3; \
1271 save->attrtype[A] = T; \
1276 fi_type *buffer_ptr = save->vertex_store->buffer_in_ram + save->vertex_store->used; \
1278 for (i = 0; i < save->vertex_size; i++) \
1279 buffer_ptr[i] = save->vertex[i]; \
1281 save->vertex_store->used += save->vertex_size; \
1282 if ((save->vertex_store->used + save->vertex_size) * sizeof(float) >= save->vertex_store->buffer_in_ram_size) { \
1283 realloc_storage(ctx, -1, get_vertex_count(save) * 2); \
1284 assert((save->vertex_store->used + save->vertex_size) * sizeof(float) < save->vertex_store->buffer_in_ram_size); \
1289 #define TAG(x) _save_##x
1291 #include "vbo_attrib_tmp.h"
1295 #define MAT( ATTR, N, face, params ) \
1297 if (face != GL_BACK) \
1298 MAT_ATTR( ATTR, N, params ); /* front */ \
1299 if (face != GL_FRONT) \
1300 MAT_ATTR( ATTR + 1, N, params ); /* back */ \
1305 * Save a glMaterial call found between glBegin/End.
1306 * glMaterial calls outside Begin/End are handled in dlist.c.
1308 static void GLAPIENTRY
1309 _save_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
1311 GET_CURRENT_CONTEXT(ctx);
1313 if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
1314 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(face)");
1320 MAT(VBO_ATTRIB_MAT_FRONT_EMISSION, 4, face, params);
1323 MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
1326 MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
1329 MAT(VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params);
1332 if (*params < 0 || *params > ctx->Const.MaxShininess) {
1333 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glMaterial(shininess)");
1336 MAT(VBO_ATTRIB_MAT_FRONT_SHININESS, 1, face, params);
1339 case GL_COLOR_INDEXES:
1340 MAT(VBO_ATTRIB_MAT_FRONT_INDEXES, 3, face, params);
1342 case GL_AMBIENT_AND_DIFFUSE:
1343 MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
1344 MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
1347 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(pname)");
1353 /* Cope with EvalCoord/CallList called within a begin/end object:
1354 * -- Flush current buffer
1355 * -- Fallback to opcodes for the rest of the begin/end object.
1358 dlist_fallback(struct gl_context *ctx)
1360 struct vbo_save_context *save = &vbo_context(ctx)->save;
1362 if (save->vertex_store->used || save->prim_store->used) {
1363 if (save->prim_store->used > 0 && save->vertex_store->used > 0) {
1364 assert(save->vertex_size);
1365 /* Close off in-progress primitive. */
1366 GLint i = save->prim_store->used - 1;
1367 save->prim_store->prims[i].count =
1368 get_vertex_count(save) -
1369 save->prim_store->prims[i].start;
1372 /* Need to replay this display list with loopback,
1373 * unfortunately, otherwise this primitive won't be handled
1376 save->dangling_attr_ref = GL_TRUE;
1378 compile_vertex_list(ctx);
1381 copy_to_current(ctx);
1383 if (save->out_of_memory) {
1384 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt);
1387 _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
1389 ctx->Driver.SaveNeedFlush = GL_FALSE;
1393 static void GLAPIENTRY
1394 _save_EvalCoord1f(GLfloat u)
1396 GET_CURRENT_CONTEXT(ctx);
1397 dlist_fallback(ctx);
1398 CALL_EvalCoord1f(ctx->Save, (u));
1401 static void GLAPIENTRY
1402 _save_EvalCoord1fv(const GLfloat * v)
1404 GET_CURRENT_CONTEXT(ctx);
1405 dlist_fallback(ctx);
1406 CALL_EvalCoord1fv(ctx->Save, (v));
1409 static void GLAPIENTRY
1410 _save_EvalCoord2f(GLfloat u, GLfloat v)
1412 GET_CURRENT_CONTEXT(ctx);
1413 dlist_fallback(ctx);
1414 CALL_EvalCoord2f(ctx->Save, (u, v));
1417 static void GLAPIENTRY
1418 _save_EvalCoord2fv(const GLfloat * v)
1420 GET_CURRENT_CONTEXT(ctx);
1421 dlist_fallback(ctx);
1422 CALL_EvalCoord2fv(ctx->Save, (v));
1425 static void GLAPIENTRY
1426 _save_EvalPoint1(GLint i)
1428 GET_CURRENT_CONTEXT(ctx);
1429 dlist_fallback(ctx);
1430 CALL_EvalPoint1(ctx->Save, (i));
1433 static void GLAPIENTRY
1434 _save_EvalPoint2(GLint i, GLint j)
1436 GET_CURRENT_CONTEXT(ctx);
1437 dlist_fallback(ctx);
1438 CALL_EvalPoint2(ctx->Save, (i, j));
1441 static void GLAPIENTRY
1442 _save_CallList(GLuint l)
1444 GET_CURRENT_CONTEXT(ctx);
1445 dlist_fallback(ctx);
1446 CALL_CallList(ctx->Save, (l));
1449 static void GLAPIENTRY
1450 _save_CallLists(GLsizei n, GLenum type, const GLvoid * v)
1452 GET_CURRENT_CONTEXT(ctx);
1453 dlist_fallback(ctx);
1454 CALL_CallLists(ctx->Save, (n, type, v));
1460 * Called when a glBegin is getting compiled into a display list.
1461 * Updating of ctx->Driver.CurrentSavePrimitive is already taken care of.
1464 vbo_save_NotifyBegin(struct gl_context *ctx, GLenum mode,
1465 bool no_current_update)
1467 struct vbo_save_context *save = &vbo_context(ctx)->save;
1468 const GLuint i = save->prim_store->used++;
1470 ctx->Driver.CurrentSavePrimitive = mode;
1472 assert(i < save->prim_store->size);
1473 save->prim_store->prims[i].mode = mode & VBO_SAVE_PRIM_MODE_MASK;
1474 save->prim_store->prims[i].begin = 1;
1475 save->prim_store->prims[i].end = 0;
1476 save->prim_store->prims[i].start = get_vertex_count(save);
1477 save->prim_store->prims[i].count = 0;
1479 save->no_current_update = no_current_update;
1481 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt);
1483 /* We need to call vbo_save_SaveFlushVertices() if there's state change */
1484 ctx->Driver.SaveNeedFlush = GL_TRUE;
1488 static void GLAPIENTRY
1491 GET_CURRENT_CONTEXT(ctx);
1492 struct vbo_save_context *save = &vbo_context(ctx)->save;
1493 const GLint i = save->prim_store->used - 1;
1495 ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
1496 save->prim_store->prims[i].end = 1;
1497 save->prim_store->prims[i].count = (get_vertex_count(save) - save->prim_store->prims[i].start);
1499 if (i == (GLint) save->prim_store->size - 1) {
1500 compile_vertex_list(ctx);
1501 assert(save->copied.nr == 0);
1504 /* Swap out this vertex format while outside begin/end. Any color,
1505 * etc. received between here and the next begin will be compiled
1508 if (save->out_of_memory) {
1509 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt);
1512 _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
1517 static void GLAPIENTRY
1518 _save_Begin(GLenum mode)
1520 GET_CURRENT_CONTEXT(ctx);
1522 _mesa_compile_error(ctx, GL_INVALID_OPERATION, "Recursive glBegin");
1526 static void GLAPIENTRY
1527 _save_PrimitiveRestartNV(void)
1529 GET_CURRENT_CONTEXT(ctx);
1530 struct vbo_save_context *save = &vbo_context(ctx)->save;
1532 if (save->prim_store->used == 0) {
1533 /* We're not inside a glBegin/End pair, so calling glPrimitiverRestartNV
1536 _mesa_compile_error(ctx, GL_INVALID_OPERATION,
1537 "glPrimitiveRestartNV called outside glBegin/End");
1539 /* get current primitive mode */
1540 GLenum curPrim = save->prim_store->prims[save->prim_store->used - 1].mode;
1541 bool no_current_update = save->no_current_update;
1543 /* restart primitive */
1544 CALL_End(ctx->CurrentServerDispatch, ());
1545 vbo_save_NotifyBegin(ctx, curPrim, no_current_update);
1550 /* Unlike the functions above, these are to be hooked into the vtxfmt
1551 * maintained in ctx->ListState, active when the list is known or
1552 * suspected to be outside any begin/end primitive.
1553 * Note: OBE = Outside Begin/End
1555 static void GLAPIENTRY
1556 _save_OBE_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
1558 GET_CURRENT_CONTEXT(ctx);
1559 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1561 vbo_save_NotifyBegin(ctx, GL_QUADS, false);
1562 CALL_Vertex2f(dispatch, (x1, y1));
1563 CALL_Vertex2f(dispatch, (x2, y1));
1564 CALL_Vertex2f(dispatch, (x2, y2));
1565 CALL_Vertex2f(dispatch, (x1, y2));
1566 CALL_End(dispatch, ());
1570 static void GLAPIENTRY
1571 _save_OBE_Rectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)
1573 _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1576 static void GLAPIENTRY
1577 _save_OBE_Rectdv(const GLdouble *v1, const GLdouble *v2)
1579 _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1582 static void GLAPIENTRY
1583 _save_OBE_Rectfv(const GLfloat *v1, const GLfloat *v2)
1585 _save_OBE_Rectf(v1[0], v1[1], v2[0], v2[1]);
1588 static void GLAPIENTRY
1589 _save_OBE_Recti(GLint x1, GLint y1, GLint x2, GLint y2)
1591 _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1594 static void GLAPIENTRY
1595 _save_OBE_Rectiv(const GLint *v1, const GLint *v2)
1597 _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1600 static void GLAPIENTRY
1601 _save_OBE_Rects(GLshort x1, GLshort y1, GLshort x2, GLshort y2)
1603 _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1606 static void GLAPIENTRY
1607 _save_OBE_Rectsv(const GLshort *v1, const GLshort *v2)
1609 _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1613 _ensure_draws_fits_in_storage(struct gl_context *ctx, int primcount, int vertcount)
1615 struct vbo_save_context *save = &vbo_context(ctx)->save;
1617 bool realloc_prim = save->prim_store->used + primcount > save->prim_store->size;
1618 bool realloc_vert = save->vertex_size &&
1619 (save->vertex_store->used + vertcount * save->vertex_size) >=
1620 save->vertex_store->buffer_in_ram_size;
1622 if (realloc_prim || realloc_vert)
1623 realloc_storage(ctx, realloc_prim ? primcount : -1, realloc_vert ? vertcount : -1);
1627 static void GLAPIENTRY
1628 _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count)
1630 GET_CURRENT_CONTEXT(ctx);
1631 struct gl_vertex_array_object *vao = ctx->Array.VAO;
1632 struct vbo_save_context *save = &vbo_context(ctx)->save;
1635 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1636 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawArrays(mode)");
1640 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawArrays(count<0)");
1644 if (save->out_of_memory)
1647 _ensure_draws_fits_in_storage(ctx, 1, count);
1649 /* Make sure to process any VBO binding changes */
1650 _mesa_update_state(ctx);
1652 _mesa_vao_map_arrays(ctx, vao, GL_MAP_READ_BIT);
1654 vbo_save_NotifyBegin(ctx, mode, true);
1656 for (i = 0; i < count; i++)
1657 _mesa_array_element(ctx, start + i);
1658 CALL_End(ctx->CurrentServerDispatch, ());
1660 _mesa_vao_unmap_arrays(ctx, vao);
1664 static void GLAPIENTRY
1665 _save_OBE_MultiDrawArrays(GLenum mode, const GLint *first,
1666 const GLsizei *count, GLsizei primcount)
1668 GET_CURRENT_CONTEXT(ctx);
1671 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1672 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMultiDrawArrays(mode)");
1676 if (primcount < 0) {
1677 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1678 "glMultiDrawArrays(primcount<0)");
1682 unsigned vertcount = 0;
1683 for (i = 0; i < primcount; i++) {
1685 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1686 "glMultiDrawArrays(count[i]<0)");
1689 vertcount += count[i];
1692 _ensure_draws_fits_in_storage(ctx, primcount, vertcount);
1694 for (i = 0; i < primcount; i++) {
1696 _save_OBE_DrawArrays(mode, first[i], count[i]);
1703 array_element(struct gl_context *ctx,
1704 GLint basevertex, GLuint elt, unsigned index_size_shift)
1706 /* Section 10.3.5 Primitive Restart:
1708 * When one of the *BaseVertex drawing commands specified in section 10.5
1709 * is used, the primitive restart comparison occurs before the basevertex
1710 * offset is added to the array index.
1712 /* If PrimitiveRestart is enabled and the index is the RestartIndex
1713 * then we call PrimitiveRestartNV and return.
1715 if (ctx->Array._PrimitiveRestart[index_size_shift] &&
1716 elt == ctx->Array._RestartIndex[index_size_shift]) {
1717 CALL_PrimitiveRestartNV(ctx->CurrentServerDispatch, ());
1721 _mesa_array_element(ctx, basevertex + elt);
1725 /* Could do better by copying the arrays and element list intact and
1726 * then emitting an indexed prim at runtime.
1728 static void GLAPIENTRY
1729 _save_OBE_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1730 const GLvoid * indices, GLint basevertex)
1732 GET_CURRENT_CONTEXT(ctx);
1733 struct vbo_save_context *save = &vbo_context(ctx)->save;
1734 struct gl_vertex_array_object *vao = ctx->Array.VAO;
1735 struct gl_buffer_object *indexbuf = vao->IndexBufferObj;
1738 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1739 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawElements(mode)");
1743 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawElements(count<0)");
1746 if (type != GL_UNSIGNED_BYTE &&
1747 type != GL_UNSIGNED_SHORT &&
1748 type != GL_UNSIGNED_INT) {
1749 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawElements(count<0)");
1753 if (save->out_of_memory)
1756 _ensure_draws_fits_in_storage(ctx, 1, count);
1758 /* Make sure to process any VBO binding changes */
1759 _mesa_update_state(ctx);
1761 _mesa_vao_map(ctx, vao, GL_MAP_READ_BIT);
1765 ADD_POINTERS(indexbuf->Mappings[MAP_INTERNAL].Pointer, indices);
1767 vbo_save_NotifyBegin(ctx, mode, true);
1770 case GL_UNSIGNED_BYTE:
1771 for (i = 0; i < count; i++)
1772 array_element(ctx, basevertex, ((GLubyte *) indices)[i], 0);
1774 case GL_UNSIGNED_SHORT:
1775 for (i = 0; i < count; i++)
1776 array_element(ctx, basevertex, ((GLushort *) indices)[i], 1);
1778 case GL_UNSIGNED_INT:
1779 for (i = 0; i < count; i++)
1780 array_element(ctx, basevertex, ((GLuint *) indices)[i], 2);
1783 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawElements(type)");
1787 CALL_End(ctx->CurrentServerDispatch, ());
1789 _mesa_vao_unmap(ctx, vao);
1792 static void GLAPIENTRY
1793 _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type,
1794 const GLvoid * indices)
1796 _save_OBE_DrawElementsBaseVertex(mode, count, type, indices, 0);
1800 static void GLAPIENTRY
1801 _save_OBE_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
1802 GLsizei count, GLenum type,
1803 const GLvoid * indices)
1805 GET_CURRENT_CONTEXT(ctx);
1806 struct vbo_save_context *save = &vbo_context(ctx)->save;
1808 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1809 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(mode)");
1813 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1814 "glDrawRangeElements(count<0)");
1817 if (type != GL_UNSIGNED_BYTE &&
1818 type != GL_UNSIGNED_SHORT &&
1819 type != GL_UNSIGNED_INT) {
1820 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(type)");
1824 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1825 "glDrawRangeElements(end < start)");
1829 if (save->out_of_memory)
1832 _save_OBE_DrawElements(mode, count, type, indices);
1836 static void GLAPIENTRY
1837 _save_OBE_MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type,
1838 const GLvoid * const *indices, GLsizei primcount)
1840 GET_CURRENT_CONTEXT(ctx);
1841 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1845 for (i = 0; i < primcount; i++) {
1846 vertcount += count[i];
1848 _ensure_draws_fits_in_storage(ctx, primcount, vertcount);
1850 for (i = 0; i < primcount; i++) {
1852 CALL_DrawElements(dispatch, (mode, count[i], type, indices[i]));
1858 static void GLAPIENTRY
1859 _save_OBE_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count,
1861 const GLvoid * const *indices,
1863 const GLint *basevertex)
1865 GET_CURRENT_CONTEXT(ctx);
1866 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1870 for (i = 0; i < primcount; i++) {
1871 vertcount += count[i];
1873 _ensure_draws_fits_in_storage(ctx, primcount, vertcount);
1875 for (i = 0; i < primcount; i++) {
1877 CALL_DrawElementsBaseVertex(dispatch, (mode, count[i], type,
1886 vtxfmt_init(struct gl_context *ctx)
1888 struct vbo_save_context *save = &vbo_context(ctx)->save;
1889 GLvertexformat *vfmt = &save->vtxfmt;
1891 #define NAME_AE(x) _ae_##x
1892 #define NAME_CALLLIST(x) _save_##x
1893 #define NAME(x) _save_##x
1894 #define NAME_ES(x) _save_##x##ARB
1896 #include "vbo_init_tmp.h"
1901 * Initialize the dispatch table with the VBO functions for display
1905 vbo_initialize_save_dispatch(const struct gl_context *ctx,
1906 struct _glapi_table *exec)
1908 SET_DrawArrays(exec, _save_OBE_DrawArrays);
1909 SET_MultiDrawArrays(exec, _save_OBE_MultiDrawArrays);
1910 SET_DrawElements(exec, _save_OBE_DrawElements);
1911 SET_DrawElementsBaseVertex(exec, _save_OBE_DrawElementsBaseVertex);
1912 SET_DrawRangeElements(exec, _save_OBE_DrawRangeElements);
1913 SET_MultiDrawElementsEXT(exec, _save_OBE_MultiDrawElements);
1914 SET_MultiDrawElementsBaseVertex(exec, _save_OBE_MultiDrawElementsBaseVertex);
1915 SET_Rectf(exec, _save_OBE_Rectf);
1916 SET_Rectd(exec, _save_OBE_Rectd);
1917 SET_Rectdv(exec, _save_OBE_Rectdv);
1918 SET_Rectfv(exec, _save_OBE_Rectfv);
1919 SET_Recti(exec, _save_OBE_Recti);
1920 SET_Rectiv(exec, _save_OBE_Rectiv);
1921 SET_Rects(exec, _save_OBE_Rects);
1922 SET_Rectsv(exec, _save_OBE_Rectsv);
1924 /* Note: other glDraw functins aren't compiled into display lists */
1930 vbo_save_SaveFlushVertices(struct gl_context *ctx)
1932 struct vbo_save_context *save = &vbo_context(ctx)->save;
1934 /* Noop when we are actually active:
1936 if (ctx->Driver.CurrentSavePrimitive <= PRIM_MAX)
1939 if (save->vertex_store->used || save->prim_store->used)
1940 compile_vertex_list(ctx);
1942 copy_to_current(ctx);
1944 ctx->Driver.SaveNeedFlush = GL_FALSE;
1949 * Called from glNewList when we're starting to compile a display list.
1952 vbo_save_NewList(struct gl_context *ctx, GLuint list, GLenum mode)
1954 struct vbo_save_context *save = &vbo_context(ctx)->save;
1959 if (!save->prim_store)
1960 save->prim_store = realloc_prim_store(NULL, 8);
1962 if (!save->vertex_store)
1963 save->vertex_store = realloc_vertex_store(NULL, save->vertex_size, 8);
1966 ctx->Driver.SaveNeedFlush = GL_FALSE;
1971 * Called from glEndList when we're finished compiling a display list.
1974 vbo_save_EndList(struct gl_context *ctx)
1976 struct vbo_save_context *save = &vbo_context(ctx)->save;
1978 /* EndList called inside a (saved) Begin/End pair?
1980 if (_mesa_inside_dlist_begin_end(ctx)) {
1981 if (save->prim_store->used > 0) {
1982 GLint i = save->prim_store->used - 1;
1983 ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
1984 save->prim_store->prims[i].end = 0;
1985 save->prim_store->prims[i].count = get_vertex_count(save) - save->prim_store->prims[i].start;
1988 /* Make sure this vertex list gets replayed by the "loopback"
1991 save->dangling_attr_ref = GL_TRUE;
1992 vbo_save_SaveFlushVertices(ctx);
1994 /* Swap out this vertex format while outside begin/end. Any color,
1995 * etc. received between here and the next begin will be compiled
1998 _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
2001 assert(save->vertex_size == 0);
2005 * Called during context creation/init.
2008 current_init(struct gl_context *ctx)
2010 struct vbo_save_context *save = &vbo_context(ctx)->save;
2013 for (i = VBO_ATTRIB_POS; i <= VBO_ATTRIB_EDGEFLAG; i++) {
2014 const GLuint j = i - VBO_ATTRIB_POS;
2015 assert(j < VERT_ATTRIB_MAX);
2016 save->currentsz[i] = &ctx->ListState.ActiveAttribSize[j];
2017 save->current[i] = (fi_type *) ctx->ListState.CurrentAttrib[j];
2020 for (i = VBO_ATTRIB_FIRST_MATERIAL; i <= VBO_ATTRIB_LAST_MATERIAL; i++) {
2021 const GLuint j = i - VBO_ATTRIB_FIRST_MATERIAL;
2022 assert(j < MAT_ATTRIB_MAX);
2023 save->currentsz[i] = &ctx->ListState.ActiveMaterialSize[j];
2024 save->current[i] = (fi_type *) ctx->ListState.CurrentMaterial[j];
2030 * Initialize the display list compiler. Called during context creation.
2033 vbo_save_api_init(struct vbo_save_context *save)
2035 struct gl_context *ctx = gl_context_from_vbo_save(save);