1 /**************************************************************************
3 Copyright 2002-2008 VMware, Inc.
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
30 * Keith Whitwell <keithw@vmware.com>
35 /* Display list compiler attempts to store lists of vertices with the
36 * same vertex layout. Additionally it attempts to minimize the need
37 * for execute-time fixup of these vertex lists, allowing them to be
40 * There are still some circumstances where this can be thwarted, for
41 * example by building a list that consists of one very long primitive
42 * (eg Begin(Triangles), 1000 vertices, End), and calling that list
43 * from inside a different begin/end object (Begin(Lines), CallList,
46 * In that case the code will have to replay the list as individual
47 * commands through the Exec dispatch table, or fix up the copied
48 * vertices at execute-time.
50 * The other case where fixup is required is when a vertex attribute
51 * is introduced in the middle of a primitive. Eg:
53 * TexCoord1f() Vertex2f()
54 * TexCoord1f() Color3f() Vertex2f()
57 * If the current value of Color isn't known at compile-time, this
58 * primitive will require fixup.
61 * The list compiler currently doesn't attempt to compile lists
62 * containing EvalCoord or EvalPoint commands. On encountering one of
63 * these, compilation falls back to opcodes.
65 * This could be improved to fallback only when a mix of EvalCoord and
66 * Vertex commands are issued within a single primitive.
70 #include "main/glheader.h"
71 #include "main/arrayobj.h"
72 #include "main/bufferobj.h"
73 #include "main/context.h"
74 #include "main/dlist.h"
75 #include "main/enums.h"
76 #include "main/eval.h"
77 #include "main/macros.h"
78 #include "main/draw_validate.h"
79 #include "main/api_arrayelt.h"
80 #include "main/vtxfmt.h"
81 #include "main/dispatch.h"
82 #include "main/state.h"
83 #include "main/varray.h"
84 #include "util/bitscan.h"
85 #include "util/u_memory.h"
86 #include "util/hash_table.h"
88 #include "gallium/include/pipe/p_state.h"
91 #include "vbo_private.h"
98 /* An interesting VBO number/name to help with debugging */
99 #define VBO_BUF_ID 12345
101 static void GLAPIENTRY
102 _save_Materialfv(GLenum face, GLenum pname, const GLfloat *params);
104 static void GLAPIENTRY
105 _save_EvalCoord1f(GLfloat u);
107 static void GLAPIENTRY
108 _save_EvalCoord2f(GLfloat u, GLfloat v);
111 * NOTE: Old 'parity' issue is gone, but copying can still be
112 * wrong-footed on replay.
115 copy_vertices(struct gl_context *ctx,
116 const struct vbo_save_vertex_list *node,
117 const fi_type * src_buffer)
119 struct vbo_save_context *save = &vbo_context(ctx)->save;
120 struct _mesa_prim *prim = &node->cold->prims[node->cold->prim_count - 1];
121 GLuint sz = save->vertex_size;
122 const fi_type *src = src_buffer + prim->start * sz;
123 fi_type *dst = save->copied.buffer;
128 return vbo_copy_vertices(ctx, prim->mode, prim->start, &prim->count,
129 prim->begin, sz, true, dst, src);
133 static struct vbo_save_vertex_store *
134 alloc_vertex_store(struct gl_context *ctx, int vertex_count)
136 struct vbo_save_context *save = &vbo_context(ctx)->save;
137 struct vbo_save_vertex_store *vertex_store =
138 CALLOC_STRUCT(vbo_save_vertex_store);
140 int size = MAX2(vertex_count * save->vertex_size, VBO_SAVE_BUFFER_SIZE);
142 /* obj->Name needs to be non-zero, but won't ever be examined more
143 * closely than that. In particular these buffers won't be entered
144 * into the hash and can never be confused with ones visible to the
145 * user. Perhaps there could be a special number for internal
148 vertex_store->buffer_in_ram_size = size * sizeof(GLfloat);
149 vertex_store->buffer_in_ram = malloc(vertex_store->buffer_in_ram_size);
150 save->out_of_memory = vertex_store->buffer_in_ram == NULL;
152 if (save->out_of_memory) {
153 _mesa_error(ctx, GL_OUT_OF_MEMORY, "internal VBO allocation");
154 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
157 vertex_store->used = 0;
164 free_vertex_store(struct gl_context *ctx,
165 struct vbo_save_vertex_store *vertex_store)
167 free(vertex_store->buffer_in_ram);
172 static struct vbo_save_primitive_store *
173 alloc_prim_store(int prim_count)
175 struct vbo_save_primitive_store *store =
176 CALLOC_STRUCT(vbo_save_primitive_store);
177 store->size = MAX2(prim_count, VBO_SAVE_PRIM_SIZE);
178 store->prims = calloc(store->size, sizeof(struct _mesa_prim));
185 reset_counters(struct gl_context *ctx)
187 struct vbo_save_context *save = &vbo_context(ctx)->save;
189 save->buffer_map = save->vertex_store->buffer_in_ram + save->vertex_store->used;
191 assert(save->buffer_map == save->buffer_ptr);
193 if (save->vertex_size)
194 save->max_vert = (save->vertex_store->buffer_in_ram_size / sizeof(float) - save->vertex_store->used) /
199 save->prim_store->used = 0;
200 save->vert_count = 0;
201 save->dangling_attr_ref = GL_FALSE;
205 * For a list of prims, try merging prims that can just be extensions of the
209 merge_prims(struct gl_context *ctx, struct _mesa_prim *prim_list,
213 struct _mesa_prim *prev_prim = prim_list;
215 for (i = 1; i < *prim_count; i++) {
216 struct _mesa_prim *this_prim = prim_list + i;
218 vbo_try_prim_conversion(&this_prim->mode, &this_prim->count);
220 if (vbo_merge_draws(ctx, true,
221 prev_prim->mode, this_prim->mode,
222 prev_prim->start, this_prim->start,
223 &prev_prim->count, this_prim->count,
224 prev_prim->basevertex, this_prim->basevertex,
226 this_prim->begin, this_prim->end)) {
227 /* We've found a prim that just extend the previous one. Tack it
228 * onto the previous one, and let this primitive struct get dropped.
233 /* If any previous primitives have been dropped, then we need to copy
234 * this later one into the next available slot.
237 if (prev_prim != this_prim)
238 *prev_prim = *this_prim;
241 *prim_count = prev_prim - prim_list + 1;
246 * Convert GL_LINE_LOOP primitive into GL_LINE_STRIP so that drivers
247 * don't have to worry about handling the _mesa_prim::begin/end flags.
248 * See https://bugs.freedesktop.org/show_bug.cgi?id=81174
251 convert_line_loop_to_strip(struct vbo_save_context *save,
252 struct vbo_save_vertex_list *node)
254 struct _mesa_prim *prim = &node->cold->prims[node->cold->prim_count - 1];
256 assert(prim->mode == GL_LINE_LOOP);
259 /* Copy the 0th vertex to end of the buffer and extend the
260 * vertex count by one to finish the line loop.
262 const GLuint sz = save->vertex_size;
264 const fi_type *src = save->buffer_map + prim->start * sz;
266 fi_type *dst = save->buffer_map + (prim->start + prim->count) * sz;
268 memcpy(dst, src, sz * sizeof(float));
271 node->cold->vertex_count++;
273 save->buffer_ptr += sz;
274 save->vertex_store->used += sz;
278 /* Drawing the second or later section of a long line loop.
279 * Skip the 0th vertex.
285 prim->mode = GL_LINE_STRIP;
289 /* Compare the present vao if it has the same setup. */
291 compare_vao(gl_vertex_processing_mode mode,
292 const struct gl_vertex_array_object *vao,
293 const struct gl_buffer_object *bo, GLintptr buffer_offset,
294 GLuint stride, GLbitfield64 vao_enabled,
295 const GLubyte size[VBO_ATTRIB_MAX],
296 const GLenum16 type[VBO_ATTRIB_MAX],
297 const GLuint offset[VBO_ATTRIB_MAX])
302 /* If the enabled arrays are not the same we are not equal. */
303 if (vao_enabled != vao->Enabled)
306 /* Check the buffer binding at 0 */
307 if (vao->BufferBinding[0].BufferObj != bo)
309 /* BufferBinding[0].Offset != buffer_offset is checked per attribute */
310 if (vao->BufferBinding[0].Stride != stride)
312 assert(vao->BufferBinding[0].InstanceDivisor == 0);
314 /* Retrieve the mapping from VBO_ATTRIB to VERT_ATTRIB space */
315 const GLubyte *const vao_to_vbo_map = _vbo_attribute_alias_map[mode];
317 /* Now check the enabled arrays */
318 GLbitfield mask = vao_enabled;
320 const int attr = u_bit_scan(&mask);
321 const unsigned char vbo_attr = vao_to_vbo_map[attr];
322 const GLenum16 tp = type[vbo_attr];
323 const GLintptr off = offset[vbo_attr] + buffer_offset;
324 const struct gl_array_attributes *attrib = &vao->VertexAttrib[attr];
325 if (attrib->RelativeOffset + vao->BufferBinding[0].Offset != off)
327 if (attrib->Format.Type != tp)
329 if (attrib->Format.Size != size[vbo_attr])
331 assert(attrib->Format.Format == GL_RGBA);
332 assert(attrib->Format.Normalized == GL_FALSE);
333 assert(attrib->Format.Integer == vbo_attrtype_to_integer_flag(tp));
334 assert(attrib->Format.Doubles == vbo_attrtype_to_double_flag(tp));
335 assert(attrib->BufferBindingIndex == 0);
342 /* Create or reuse the vao for the vertex processing mode. */
344 update_vao(struct gl_context *ctx,
345 gl_vertex_processing_mode mode,
346 struct gl_vertex_array_object **vao,
347 struct gl_buffer_object *bo, GLintptr buffer_offset,
348 GLuint stride, GLbitfield64 vbo_enabled,
349 const GLubyte size[VBO_ATTRIB_MAX],
350 const GLenum16 type[VBO_ATTRIB_MAX],
351 const GLuint offset[VBO_ATTRIB_MAX])
353 /* Compute the bitmasks of vao_enabled arrays */
354 GLbitfield vao_enabled = _vbo_get_vao_enabled_from_vbo(mode, vbo_enabled);
357 * Check if we can possibly reuse the exisiting one.
358 * In the long term we should reset them when something changes.
360 if (compare_vao(mode, *vao, bo, buffer_offset, stride,
361 vao_enabled, size, type, offset))
364 /* The initial refcount is 1 */
365 _mesa_reference_vao(ctx, vao, NULL);
366 *vao = _mesa_new_vao(ctx, ~((GLuint)0));
369 * assert(stride <= ctx->Const.MaxVertexAttribStride);
370 * MaxVertexAttribStride is not set for drivers that does not
371 * expose GL 44 or GLES 31.
374 /* Bind the buffer object at binding point 0 */
375 _mesa_bind_vertex_buffer(ctx, *vao, 0, bo, buffer_offset, stride, false,
378 /* Retrieve the mapping from VBO_ATTRIB to VERT_ATTRIB space
379 * Note that the position/generic0 aliasing is done in the VAO.
381 const GLubyte *const vao_to_vbo_map = _vbo_attribute_alias_map[mode];
382 /* Now set the enable arrays */
383 GLbitfield mask = vao_enabled;
385 const int vao_attr = u_bit_scan(&mask);
386 const GLubyte vbo_attr = vao_to_vbo_map[vao_attr];
387 assert(offset[vbo_attr] <= ctx->Const.MaxVertexAttribRelativeOffset);
389 _vbo_set_attrib_format(ctx, *vao, vao_attr, buffer_offset,
390 size[vbo_attr], type[vbo_attr], offset[vbo_attr]);
391 _mesa_vertex_attrib_binding(ctx, *vao, vao_attr, 0);
393 _mesa_enable_vertex_array_attribs(ctx, *vao, vao_enabled);
394 assert(vao_enabled == (*vao)->Enabled);
395 assert((vao_enabled & ~(*vao)->VertexAttribBufferMask) == 0);
397 /* Finalize and freeze the VAO */
398 _mesa_set_vao_immutable(ctx, *vao);
403 realloc_storage(struct gl_context *ctx, int prim_count, int vertex_count)
405 struct vbo_save_context *save = &vbo_context(ctx)->save;
406 if (vertex_count >= 0) {
407 /* Release old reference:
409 free_vertex_store(ctx, save->vertex_store);
410 save->vertex_store = NULL;
411 /* When we have a new vbo, we will for sure need a new vao */
412 for (gl_vertex_processing_mode vpm = 0; vpm < VP_MODE_MAX; ++vpm)
413 _mesa_reference_vao(ctx, &save->VAO[vpm], NULL);
415 /* Allocate and map new store:
417 save->vertex_store = alloc_vertex_store(ctx, vertex_count);
418 save->buffer_ptr = save->vertex_store->buffer_in_ram + save->vertex_store->used;
419 save->out_of_memory = save->buffer_ptr == NULL;
422 if (prim_count >= 0) {
423 free(save->prim_store->prims);
424 free(save->prim_store);
425 save->prim_store = alloc_prim_store(prim_count);
430 unsigned vertex_size;
431 fi_type *vertex_attributes;
434 static uint32_t _hash_vertex_key(const void *key)
436 struct vertex_key *k = (struct vertex_key*)key;
437 unsigned sz = k->vertex_size;
439 return _mesa_hash_data(k->vertex_attributes, sz * sizeof(float));
442 static bool _compare_vertex_key(const void *key1, const void *key2)
444 struct vertex_key *k1 = (struct vertex_key*)key1;
445 struct vertex_key *k2 = (struct vertex_key*)key2;
446 /* All the compared vertices are going to be drawn with the same VAO,
447 * so we can compare the attributes. */
448 assert (k1->vertex_size == k2->vertex_size);
449 return memcmp(k1->vertex_attributes,
450 k2->vertex_attributes,
451 k1->vertex_size * sizeof(float)) == 0;
454 static void _free_entry(struct hash_entry *entry)
456 free((void*)entry->key);
459 /* Add vertex to the vertex buffer and return its index. If this vertex is a duplicate
460 * of an existing vertex, return the original index instead.
463 add_vertex(struct vbo_save_context *save, struct hash_table *hash_to_index,
464 uint32_t index, fi_type *new_buffer, uint32_t *max_index)
466 /* If vertex deduplication is disabled return the original index. */
470 fi_type *vert = save->buffer_map + save->vertex_size * index;
472 struct vertex_key *key = malloc(sizeof(struct vertex_key));
473 key->vertex_size = save->vertex_size;
474 key->vertex_attributes = vert;
476 struct hash_entry *entry = _mesa_hash_table_search(hash_to_index, key);
479 /* We found an existing vertex with the same hash, return its index. */
480 return (uintptr_t) entry->data;
482 /* This is a new vertex. Determine a new index and copy its attributes to the vertex
483 * buffer. Note that 'new_buffer' is created at each list compilation so we write vertices
484 * starting at index 0.
486 uint32_t n = _mesa_hash_table_num_entries(hash_to_index);
487 *max_index = MAX2(n, *max_index);
489 memcpy(&new_buffer[save->vertex_size * n],
491 save->vertex_size * sizeof(fi_type));
493 _mesa_hash_table_insert(hash_to_index, key, (void*)(uintptr_t)(n));
495 /* The index buffer is shared between list compilations, so add the base index to get
504 * Insert the active immediate struct onto the display list currently
508 compile_vertex_list(struct gl_context *ctx)
510 struct vbo_save_context *save = &vbo_context(ctx)->save;
511 struct vbo_save_vertex_list *node;
513 /* Allocate space for this structure in the display list currently
516 node = (struct vbo_save_vertex_list *)
517 _mesa_dlist_alloc_vertex_list(ctx, !save->dangling_attr_ref && !save->no_current_update);
522 memset(node, 0, sizeof(struct vbo_save_vertex_list));
523 node->cold = calloc(1, sizeof(*node->cold));
525 /* Make sure the pointer is aligned to the size of a pointer */
526 assert((GLintptr) node % sizeof(void *) == 0);
528 const GLsizei stride = save->vertex_size*sizeof(GLfloat);
530 node->cold->vertex_count = save->vert_count;
531 node->cold->wrap_count = save->copied.nr;
532 node->cold->prims = malloc(sizeof(struct _mesa_prim) * save->prim_store->used);
533 memcpy(node->cold->prims, save->prim_store->prims, sizeof(struct _mesa_prim) * save->prim_store->used);
534 node->cold->ib.obj = NULL;
535 node->cold->prim_count = save->prim_store->used;
537 if (save->no_current_update) {
538 node->cold->current_data = NULL;
541 GLuint current_size = save->vertex_size - save->attrsz[0];
542 node->cold->current_data = NULL;
545 node->cold->current_data = malloc(current_size * sizeof(GLfloat));
546 if (node->cold->current_data) {
547 const char *buffer = (const char *)save->buffer_map;
548 unsigned attr_offset = save->attrsz[0] * sizeof(GLfloat);
549 unsigned vertex_offset = 0;
551 if (node->cold->vertex_count)
552 vertex_offset = (node->cold->vertex_count - 1) * stride;
554 memcpy(node->cold->current_data, buffer + vertex_offset + attr_offset,
555 current_size * sizeof(GLfloat));
557 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Current value allocation");
562 assert(save->attrsz[VBO_ATTRIB_POS] != 0 || node->cold->vertex_count == 0);
564 if (save->dangling_attr_ref)
565 ctx->ListState.Current.UseLoopback = true;
567 save->vertex_store->used += save->vertex_size * node->cold->vertex_count;
568 save->prim_store->used += node->cold->prim_count;
570 /* Copy duplicated vertices
572 save->copied.nr = copy_vertices(ctx, node, save->buffer_map);
574 if (node->cold->prims[node->cold->prim_count - 1].mode == GL_LINE_LOOP) {
575 convert_line_loop_to_strip(save, node);
578 merge_prims(ctx, node->cold->prims, &node->cold->prim_count);
580 GLintptr buffer_offset = 0;
581 GLuint start_offset = 0;
583 /* Create an index buffer. */
584 node->cold->min_index = node->cold->max_index = 0;
585 if (save->vert_count == 0 || node->cold->prim_count == 0)
588 /* We won't modify node->prims, so use a const alias to avoid unintended
590 const struct _mesa_prim *original_prims = node->cold->prims;
592 int end = original_prims[node->cold->prim_count - 1].start +
593 original_prims[node->cold->prim_count - 1].count;
594 int total_vert_count = end - original_prims[0].start;
596 node->cold->min_index = node->cold->prims[0].start;
597 node->cold->max_index = end - 1;
599 /* Estimate for the worst case: all prims are line strips (the +1 is because
600 * wrap_buffers may call use but the last primitive may not be complete) */
601 int max_indices_count = MAX2(total_vert_count * 2 - (node->cold->prim_count * 2) + 1,
604 int size = max_indices_count * sizeof(uint32_t);
605 uint32_t* indices = (uint32_t*) malloc(size);
606 struct _mesa_prim *merged_prims = NULL;
609 struct hash_table *vertex_to_index = NULL;
610 fi_type *temp_vertices_buffer = NULL;
612 /* The loopback replay code doesn't use the index buffer, so we can't
613 * dedup vertices in this case.
615 if (!ctx->ListState.Current.UseLoopback) {
616 vertex_to_index = _mesa_hash_table_create(NULL, _hash_vertex_key, _compare_vertex_key);
617 temp_vertices_buffer = malloc(save->vertex_store->buffer_in_ram_size);
620 uint32_t max_index = 0;
622 int last_valid_prim = -1;
623 /* Construct indices array. */
624 for (unsigned i = 0; i < node->cold->prim_count; i++) {
625 assert(original_prims[i].basevertex == 0);
626 GLubyte mode = original_prims[i].mode;
628 int vertex_count = original_prims[i].count;
633 /* Line strips may get converted to lines */
634 if (mode == GL_LINE_STRIP)
637 /* If 2 consecutive prims use the same mode => merge them. */
638 bool merge_prims = last_valid_prim >= 0 &&
639 mode == merged_prims[last_valid_prim].mode &&
640 mode != GL_LINE_LOOP && mode != GL_TRIANGLE_FAN &&
641 mode != GL_QUAD_STRIP && mode != GL_POLYGON &&
644 /* To be able to merge consecutive triangle strips we need to insert
645 * a degenerate triangle.
648 mode == GL_TRIANGLE_STRIP) {
649 /* Insert a degenerate triangle */
650 assert(merged_prims[last_valid_prim].mode == GL_TRIANGLE_STRIP);
651 unsigned tri_count = merged_prims[last_valid_prim].count - 2;
653 indices[idx] = indices[idx - 1];
654 indices[idx + 1] = add_vertex(save, vertex_to_index, original_prims[i].start,
655 temp_vertices_buffer, &max_index);
657 merged_prims[last_valid_prim].count += 2;
660 /* Add another index to preserve winding order */
661 indices[idx++] = add_vertex(save, vertex_to_index, original_prims[i].start,
662 temp_vertices_buffer, &max_index);
663 merged_prims[last_valid_prim].count++;
669 /* Convert line strips to lines if it'll allow if the previous
670 * prim mode is GL_LINES (so merge_prims is true) or if the next
671 * primitive mode is GL_LINES or GL_LINE_LOOP.
673 if (original_prims[i].mode == GL_LINE_STRIP &&
675 (i < node->cold->prim_count - 1 &&
676 (original_prims[i + 1].mode == GL_LINE_STRIP ||
677 original_prims[i + 1].mode == GL_LINES)))) {
678 for (unsigned j = 0; j < vertex_count; j++) {
679 indices[idx++] = add_vertex(save, vertex_to_index, original_prims[i].start + j,
680 temp_vertices_buffer, &max_index);
681 /* Repeat all but the first/last indices. */
682 if (j && j != vertex_count - 1) {
683 indices[idx++] = add_vertex(save, vertex_to_index, original_prims[i].start + j,
684 temp_vertices_buffer, &max_index);
688 /* We didn't convert to LINES, so restore the original mode */
689 mode = original_prims[i].mode;
691 for (unsigned j = 0; j < vertex_count; j++) {
692 indices[idx++] = add_vertex(save, vertex_to_index, original_prims[i].start + j,
693 temp_vertices_buffer, &max_index);
698 /* Update vertex count. */
699 merged_prims[last_valid_prim].count += idx - start;
701 /* Keep this primitive */
702 last_valid_prim += 1;
703 assert(last_valid_prim <= i);
704 merged_prims = realloc(merged_prims, (1 + last_valid_prim) * sizeof(struct _mesa_prim));
705 merged_prims[last_valid_prim] = original_prims[i];
706 merged_prims[last_valid_prim].start = start;
707 merged_prims[last_valid_prim].count = idx - start;
709 merged_prims[last_valid_prim].mode = mode;
712 assert(idx > 0 && idx <= max_indices_count);
714 unsigned merged_prim_count = last_valid_prim + 1;
715 node->cold->ib.ptr = NULL;
716 node->cold->ib.count = idx;
717 node->cold->ib.index_size_shift = (GL_UNSIGNED_INT - GL_UNSIGNED_BYTE) >> 1;
719 /* How many bytes do we need to store the indices and the vertices */
720 total_vert_count = vertex_to_index ? (max_index + 1) : idx;
721 unsigned total_bytes_needed = idx * sizeof(uint32_t) +
722 total_vert_count * save->vertex_size * sizeof(fi_type);
724 const GLintptr old_offset = save->VAO[0] ?
725 save->VAO[0]->BufferBinding[0].Offset + save->VAO[0]->VertexAttrib[VERT_ATTRIB_POS].RelativeOffset : 0;
726 if (old_offset != save->current_bo_bytes_used && stride > 0) {
727 GLintptr offset_diff = save->current_bo_bytes_used - old_offset;
728 while (offset_diff > 0 &&
729 save->current_bo_bytes_used < save->current_bo->Size &&
730 offset_diff % stride != 0) {
731 save->current_bo_bytes_used++;
732 offset_diff = save->current_bo_bytes_used - old_offset;
735 buffer_offset = save->current_bo_bytes_used;
737 /* Can we reuse the previous bo or should we allocate a new one? */
738 int available_bytes = save->current_bo ? save->current_bo->Size - save->current_bo_bytes_used : 0;
739 if (total_bytes_needed > available_bytes) {
740 if (save->current_bo)
741 _mesa_reference_buffer_object(ctx, &save->current_bo, NULL);
742 save->current_bo = ctx->Driver.NewBufferObject(ctx, VBO_BUF_ID + 1);
743 bool success = ctx->Driver.BufferData(ctx,
744 GL_ELEMENT_ARRAY_BUFFER_ARB,
745 MAX2(total_bytes_needed, VBO_SAVE_BUFFER_SIZE * sizeof(uint32_t)),
747 GL_STATIC_DRAW_ARB, GL_MAP_WRITE_BIT,
750 _mesa_reference_buffer_object(ctx, &save->current_bo, NULL);
751 _mesa_error(ctx, GL_OUT_OF_MEMORY, "IB allocation");
753 save->current_bo_bytes_used = 0;
754 available_bytes = save->current_bo->Size;
758 assert(old_offset <= buffer_offset);
759 const GLintptr offset_diff = buffer_offset - old_offset;
760 if (offset_diff > 0 && stride > 0 && offset_diff % stride == 0) {
761 /* The vertex size is an exact multiple of the buffer offset.
762 * This means that we can use zero-based vertex attribute pointers
763 * and specify the start of the primitive with the _mesa_prim::start
764 * field. This results in issuing several draw calls with identical
765 * vertex attribute information. This can result in fewer state
766 * changes in drivers. In particular, the Gallium CSO module will
767 * filter out redundant vertex buffer changes.
769 /* We cannot immediately update the primitives as some methods below
770 * still need the uncorrected start vertices
772 start_offset = offset_diff/stride;
773 assert(old_offset == buffer_offset - offset_diff);
774 buffer_offset = old_offset;
777 /* Correct the primitive starts, we can only do this here as copy_vertices
778 * and convert_line_loop_to_strip above consume the uncorrected starts.
779 * On the other hand the _vbo_loopback_vertex_list call below needs the
780 * primitives to be corrected already.
782 for (unsigned i = 0; i < node->cold->prim_count; i++) {
783 node->cold->prims[i].start += start_offset;
785 /* start_offset shifts vertices (so v[0] becomes v[start_offset]), so we have
786 * to apply this transformation to all indices and max_index.
788 for (unsigned i = 0; i < idx; i++)
789 indices[i] += start_offset;
790 max_index += start_offset;
793 _mesa_reference_buffer_object(ctx, &node->cold->ib.obj, save->current_bo);
795 /* Upload the vertices first (see buffer_offset) */
796 ctx->Driver.BufferSubData(ctx,
797 save->current_bo_bytes_used,
798 total_vert_count * save->vertex_size * sizeof(fi_type),
799 vertex_to_index ? temp_vertices_buffer : save->buffer_map,
801 save->current_bo_bytes_used += total_vert_count * save->vertex_size * sizeof(fi_type);
803 if (vertex_to_index) {
804 _mesa_hash_table_destroy(vertex_to_index, _free_entry);
805 free(temp_vertices_buffer);
808 /* Since we're append the indices to an existing buffer, we need to adjust the start value of each
809 * primitive (not the indices themselves). */
810 save->current_bo_bytes_used += align(save->current_bo_bytes_used, 4) - save->current_bo_bytes_used;
811 int indices_offset = save->current_bo_bytes_used / 4;
812 for (int i = 0; i < merged_prim_count; i++) {
813 merged_prims[i].start += indices_offset;
816 /* Then upload the indices. */
817 if (node->cold->ib.obj) {
818 ctx->Driver.BufferSubData(ctx,
819 save->current_bo_bytes_used,
820 idx * sizeof(uint32_t),
823 save->current_bo_bytes_used += idx * sizeof(uint32_t);
825 node->cold->vertex_count = 0;
826 node->cold->prim_count = 0;
829 /* Prepare for DrawGallium */
830 memset(&node->merged.info, 0, sizeof(struct pipe_draw_info));
831 /* The other info fields will be updated in vbo_save_playback_vertex_list */
832 node->merged.info.index_size = 4;
833 node->merged.info.instance_count = 1;
834 node->merged.info.index.gl_bo = node->cold->ib.obj;
835 if (merged_prim_count == 1) {
836 node->merged.info.mode = merged_prims[0].mode;
837 node->merged.start_count.start = merged_prims[0].start;
838 node->merged.start_count.count = merged_prims[0].count;
839 node->merged.start_count.index_bias = 0;
840 node->merged.mode = NULL;
842 node->merged.mode = malloc(merged_prim_count * sizeof(unsigned char));
843 node->merged.start_counts = malloc(merged_prim_count * sizeof(struct pipe_draw_start_count_bias));
844 for (unsigned i = 0; i < merged_prim_count; i++) {
845 node->merged.start_counts[i].start = merged_prims[i].start;
846 node->merged.start_counts[i].count = merged_prims[i].count;
847 node->merged.start_counts[i].index_bias = 0;
848 node->merged.mode[i] = merged_prims[i].mode;
851 node->merged.num_draws = merged_prim_count;
852 if (node->merged.num_draws > 1) {
853 bool same_mode = true;
854 for (unsigned i = 1; i < node->merged.num_draws && same_mode; i++) {
855 same_mode = node->merged.mode[i] == node->merged.mode[0];
858 /* All primitives use the same mode, so we can simplify a bit */
859 node->merged.info.mode = node->merged.mode[0];
860 free(node->merged.mode);
861 node->merged.mode = NULL;
870 if (!save->current_bo) {
871 save->current_bo = ctx->Driver.NewBufferObject(ctx, VBO_BUF_ID + 1);
872 bool success = ctx->Driver.BufferData(ctx,
873 GL_ELEMENT_ARRAY_BUFFER_ARB,
874 VBO_SAVE_BUFFER_SIZE * sizeof(uint32_t),
876 GL_STATIC_DRAW_ARB, GL_MAP_WRITE_BIT,
880 GLuint offsets[VBO_ATTRIB_MAX];
881 for (unsigned i = 0, offset = 0; i < VBO_ATTRIB_MAX; ++i) {
883 offset += save->attrsz[i] * sizeof(GLfloat);
885 /* Create a pair of VAOs for the possible VERTEX_PROCESSING_MODEs
886 * Note that this may reuse the previous one of possible.
888 for (gl_vertex_processing_mode vpm = VP_MODE_FF; vpm < VP_MODE_MAX; ++vpm) {
889 /* create or reuse the vao */
890 update_vao(ctx, vpm, &save->VAO[vpm],
891 save->current_bo, buffer_offset, stride,
892 save->enabled, save->attrsz, save->attrtype, offsets);
893 /* Reference the vao in the dlist */
894 node->VAO[vpm] = NULL;
895 _mesa_reference_vao(ctx, &node->VAO[vpm], save->VAO[vpm]);
899 /* Deal with GL_COMPILE_AND_EXECUTE:
901 if (ctx->ExecuteFlag) {
902 struct _glapi_table *dispatch = GET_DISPATCH();
904 _glapi_set_dispatch(ctx->Exec);
906 /* _vbo_loopback_vertex_list doesn't use the index buffer, so we have to
907 * use buffer_in_ram instead of current_bo which contains all vertices instead
908 * of the deduplicated vertices only in the !UseLoopback case.
910 * The problem is that the VAO offset is based on current_bo's layout,
911 * so we have to use a temp value.
913 struct gl_vertex_array_object *vao = node->VAO[VP_MODE_SHADER];
914 GLintptr original = vao->BufferBinding[0].Offset;
915 if (!ctx->ListState.Current.UseLoopback) {
916 GLintptr new_offset = (save->buffer_map - save->vertex_store->buffer_in_ram) *
918 /* 'start_offset' has been added to all primitives 'start', so undo it here. */
919 new_offset -= start_offset * stride;
920 vao->BufferBinding[0].Offset = new_offset;
922 _vbo_loopback_vertex_list(ctx, node, save->vertex_store->buffer_in_ram);
923 vao->BufferBinding[0].Offset = original;
925 _glapi_set_dispatch(dispatch);
928 /* Decide whether the storage structs are full, or can be used for
929 * the next vertex lists as well.
931 if (save->vertex_store->used >
932 save->vertex_store->buffer_in_ram_size / sizeof(float) - 16 * (save->vertex_size + 4)) {
933 realloc_storage(ctx, -1, 0);
936 /* update buffer_ptr for next vertex */
937 save->buffer_ptr = save->vertex_store->buffer_in_ram
938 + save->vertex_store->used;
941 if (save->prim_store->used > save->prim_store->size - 6) {
942 realloc_storage(ctx, 0, -1);
945 /* Reset our structures for the next run of vertices:
952 * This is called when we fill a vertex buffer before we hit a glEnd().
954 * TODO -- If no new vertices have been stored, don't bother saving it.
957 wrap_buffers(struct gl_context *ctx)
959 struct vbo_save_context *save = &vbo_context(ctx)->save;
960 GLint i = save->prim_store->used - 1;
963 assert(i < (GLint) save->prim_store->size);
966 /* Close off in-progress primitive.
968 save->prim_store->prims[i].count = (save->vert_count - save->prim_store->prims[i].start);
969 mode = save->prim_store->prims[i].mode;
971 /* store the copied vertices, and allocate a new list.
973 compile_vertex_list(ctx);
975 /* Restart interrupted primitive
977 save->prim_store->prims[0].mode = mode;
978 save->prim_store->prims[0].begin = 0;
979 save->prim_store->prims[0].end = 0;
980 save->prim_store->prims[0].start = 0;
981 save->prim_store->prims[0].count = 0;
982 save->prim_store->used = 1;
987 * Called only when buffers are wrapped as the result of filling the
988 * vertex_store struct.
991 wrap_filled_vertex(struct gl_context *ctx)
993 struct vbo_save_context *save = &vbo_context(ctx)->save;
994 unsigned numComponents;
996 /* Emit a glEnd to close off the last vertex list.
1000 /* Copy stored stored vertices to start of new list.
1002 assert(save->max_vert - save->vert_count > save->copied.nr);
1004 numComponents = save->copied.nr * save->vertex_size;
1005 memcpy(save->buffer_ptr,
1006 save->copied.buffer,
1007 numComponents * sizeof(fi_type));
1008 save->buffer_ptr += numComponents;
1009 save->vert_count += save->copied.nr;
1014 copy_to_current(struct gl_context *ctx)
1016 struct vbo_save_context *save = &vbo_context(ctx)->save;
1017 GLbitfield64 enabled = save->enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));
1020 const int i = u_bit_scan64(&enabled);
1021 assert(save->attrsz[i]);
1023 if (save->attrtype[i] == GL_DOUBLE ||
1024 save->attrtype[i] == GL_UNSIGNED_INT64_ARB)
1025 memcpy(save->current[i], save->attrptr[i], save->attrsz[i] * sizeof(GLfloat));
1027 COPY_CLEAN_4V_TYPE_AS_UNION(save->current[i], save->attrsz[i],
1028 save->attrptr[i], save->attrtype[i]);
1034 copy_from_current(struct gl_context *ctx)
1036 struct vbo_save_context *save = &vbo_context(ctx)->save;
1037 GLbitfield64 enabled = save->enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));
1040 const int i = u_bit_scan64(&enabled);
1042 switch (save->attrsz[i]) {
1044 save->attrptr[i][3] = save->current[i][3];
1047 save->attrptr[i][2] = save->current[i][2];
1050 save->attrptr[i][1] = save->current[i][1];
1053 save->attrptr[i][0] = save->current[i][0];
1056 unreachable("Unexpected vertex attribute size");
1063 * Called when we increase the size of a vertex attribute. For example,
1064 * if we've seen one or more glTexCoord2f() calls and now we get a
1065 * glTexCoord3f() call.
1066 * Flush existing data, set new attrib size, replay copied vertices.
1069 upgrade_vertex(struct gl_context *ctx, GLuint attr, GLuint newsz)
1071 struct vbo_save_context *save = &vbo_context(ctx)->save;
1076 /* Store the current run of vertices, and emit a GL_END. Emit a
1077 * BEGIN in the new buffer.
1079 if (save->vert_count)
1082 assert(save->copied.nr == 0);
1084 /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
1085 * when the attribute already exists in the vertex and is having
1086 * its size increased.
1088 copy_to_current(ctx);
1092 oldsz = save->attrsz[attr];
1093 save->attrsz[attr] = newsz;
1094 save->enabled |= BITFIELD64_BIT(attr);
1096 save->vertex_size += newsz - oldsz;
1097 save->max_vert = ((save->vertex_store->buffer_in_ram_size / sizeof(float) -
1098 save->vertex_store->used) /
1100 save->vert_count = 0;
1102 /* Recalculate all the attrptr[] values:
1105 for (i = 0; i < VBO_ATTRIB_MAX; i++) {
1106 if (save->attrsz[i]) {
1107 save->attrptr[i] = tmp;
1108 tmp += save->attrsz[i];
1111 save->attrptr[i] = NULL; /* will not be dereferenced. */
1115 /* Copy from current to repopulate the vertex with correct values.
1117 copy_from_current(ctx);
1119 /* Replay stored vertices to translate them to new format here.
1121 * If there are copied vertices and the new (upgraded) attribute
1122 * has not been defined before, this list is somewhat degenerate,
1123 * and will need fixup at runtime.
1125 if (save->copied.nr) {
1126 const fi_type *data = save->copied.buffer;
1127 fi_type *dest = save->buffer_map;
1129 /* Need to note this and fix up at runtime (or loopback):
1131 if (attr != VBO_ATTRIB_POS && save->currentsz[attr][0] == 0) {
1133 save->dangling_attr_ref = GL_TRUE;
1136 for (i = 0; i < save->copied.nr; i++) {
1137 GLbitfield64 enabled = save->enabled;
1139 const int j = u_bit_scan64(&enabled);
1140 assert(save->attrsz[j]);
1143 COPY_CLEAN_4V_TYPE_AS_UNION(dest, oldsz, data,
1149 COPY_SZ_4V(dest, newsz, save->current[attr]);
1154 GLint sz = save->attrsz[j];
1155 COPY_SZ_4V(dest, sz, data);
1162 save->buffer_ptr = dest;
1163 save->vert_count += save->copied.nr;
1169 * This is called when the size of a vertex attribute changes.
1170 * For example, after seeing one or more glTexCoord2f() calls we
1171 * get a glTexCoord4f() or glTexCoord1f() call.
1174 fixup_vertex(struct gl_context *ctx, GLuint attr,
1175 GLuint sz, GLenum newType)
1177 struct vbo_save_context *save = &vbo_context(ctx)->save;
1179 if (sz > save->attrsz[attr] ||
1180 newType != save->attrtype[attr]) {
1181 /* New size is larger. Need to flush existing vertices and get
1182 * an enlarged vertex format.
1184 upgrade_vertex(ctx, attr, sz);
1186 else if (sz < save->active_sz[attr]) {
1188 const fi_type *id = vbo_get_default_vals_as_union(save->attrtype[attr]);
1190 /* New size is equal or smaller - just need to fill in some
1193 for (i = sz; i <= save->attrsz[attr]; i++)
1194 save->attrptr[attr][i - 1] = id[i - 1];
1197 save->active_sz[attr] = sz;
1202 * Reset the current size of all vertex attributes to the default
1203 * value of 0. This signals that we haven't yet seen any per-vertex
1204 * commands such as glNormal3f() or glTexCoord2f().
1207 reset_vertex(struct gl_context *ctx)
1209 struct vbo_save_context *save = &vbo_context(ctx)->save;
1211 while (save->enabled) {
1212 const int i = u_bit_scan64(&save->enabled);
1213 assert(save->attrsz[i]);
1214 save->attrsz[i] = 0;
1215 save->active_sz[i] = 0;
1218 save->vertex_size = 0;
1223 * If index=0, does glVertexAttrib*() alias glVertex() to emit a vertex?
1224 * It depends on a few things, including whether we're inside or outside
1228 is_vertex_position(const struct gl_context *ctx, GLuint index)
1230 return (index == 0 &&
1231 _mesa_attr_zero_aliases_vertex(ctx) &&
1232 _mesa_inside_dlist_begin_end(ctx));
1237 #define ERROR(err) _mesa_compile_error(ctx, err, __func__);
1240 /* Only one size for each attribute may be active at once. Eg. if
1241 * Color3f is installed/active, then Color4f may not be, even if the
1242 * vertex actually contains 4 color coordinates. This is because the
1243 * 3f version won't otherwise set color[3] to 1.0 -- this is the job
1244 * of the chooser function when switching between Color4f and Color3f.
1246 #define ATTR_UNION(A, N, T, C, V0, V1, V2, V3) \
1248 struct vbo_save_context *save = &vbo_context(ctx)->save; \
1249 int sz = (sizeof(C) / sizeof(GLfloat)); \
1251 if (save->active_sz[A] != N) \
1252 fixup_vertex(ctx, A, N * sz, T); \
1255 C *dest = (C *)save->attrptr[A]; \
1256 if (N>0) dest[0] = V0; \
1257 if (N>1) dest[1] = V1; \
1258 if (N>2) dest[2] = V2; \
1259 if (N>3) dest[3] = V3; \
1260 save->attrtype[A] = T; \
1266 for (i = 0; i < save->vertex_size; i++) \
1267 save->buffer_ptr[i] = save->vertex[i]; \
1269 save->buffer_ptr += save->vertex_size; \
1271 if (++save->vert_count >= save->max_vert) \
1272 wrap_filled_vertex(ctx); \
1276 #define TAG(x) _save_##x
1278 #include "vbo_attrib_tmp.h"
1282 #define MAT( ATTR, N, face, params ) \
1284 if (face != GL_BACK) \
1285 MAT_ATTR( ATTR, N, params ); /* front */ \
1286 if (face != GL_FRONT) \
1287 MAT_ATTR( ATTR + 1, N, params ); /* back */ \
1292 * Save a glMaterial call found between glBegin/End.
1293 * glMaterial calls outside Begin/End are handled in dlist.c.
1295 static void GLAPIENTRY
1296 _save_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
1298 GET_CURRENT_CONTEXT(ctx);
1300 if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
1301 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(face)");
1307 MAT(VBO_ATTRIB_MAT_FRONT_EMISSION, 4, face, params);
1310 MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
1313 MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
1316 MAT(VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params);
1319 if (*params < 0 || *params > ctx->Const.MaxShininess) {
1320 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glMaterial(shininess)");
1323 MAT(VBO_ATTRIB_MAT_FRONT_SHININESS, 1, face, params);
1326 case GL_COLOR_INDEXES:
1327 MAT(VBO_ATTRIB_MAT_FRONT_INDEXES, 3, face, params);
1329 case GL_AMBIENT_AND_DIFFUSE:
1330 MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
1331 MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
1334 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(pname)");
1340 /* Cope with EvalCoord/CallList called within a begin/end object:
1341 * -- Flush current buffer
1342 * -- Fallback to opcodes for the rest of the begin/end object.
1345 dlist_fallback(struct gl_context *ctx)
1347 struct vbo_save_context *save = &vbo_context(ctx)->save;
1349 if (save->vert_count || save->prim_store->used) {
1350 if (save->prim_store->used > 0) {
1351 /* Close off in-progress primitive. */
1352 GLint i = save->prim_store->used - 1;
1353 save->prim_store->prims[i].count = save->vert_count - save->prim_store->prims[i].start;
1356 /* Need to replay this display list with loopback,
1357 * unfortunately, otherwise this primitive won't be handled
1360 save->dangling_attr_ref = GL_TRUE;
1362 compile_vertex_list(ctx);
1365 copy_to_current(ctx);
1367 reset_counters(ctx);
1368 if (save->out_of_memory) {
1369 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
1372 _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
1374 ctx->Driver.SaveNeedFlush = GL_FALSE;
1378 static void GLAPIENTRY
1379 _save_EvalCoord1f(GLfloat u)
1381 GET_CURRENT_CONTEXT(ctx);
1382 dlist_fallback(ctx);
1383 CALL_EvalCoord1f(ctx->Save, (u));
1386 static void GLAPIENTRY
1387 _save_EvalCoord1fv(const GLfloat * v)
1389 GET_CURRENT_CONTEXT(ctx);
1390 dlist_fallback(ctx);
1391 CALL_EvalCoord1fv(ctx->Save, (v));
1394 static void GLAPIENTRY
1395 _save_EvalCoord2f(GLfloat u, GLfloat v)
1397 GET_CURRENT_CONTEXT(ctx);
1398 dlist_fallback(ctx);
1399 CALL_EvalCoord2f(ctx->Save, (u, v));
1402 static void GLAPIENTRY
1403 _save_EvalCoord2fv(const GLfloat * v)
1405 GET_CURRENT_CONTEXT(ctx);
1406 dlist_fallback(ctx);
1407 CALL_EvalCoord2fv(ctx->Save, (v));
1410 static void GLAPIENTRY
1411 _save_EvalPoint1(GLint i)
1413 GET_CURRENT_CONTEXT(ctx);
1414 dlist_fallback(ctx);
1415 CALL_EvalPoint1(ctx->Save, (i));
1418 static void GLAPIENTRY
1419 _save_EvalPoint2(GLint i, GLint j)
1421 GET_CURRENT_CONTEXT(ctx);
1422 dlist_fallback(ctx);
1423 CALL_EvalPoint2(ctx->Save, (i, j));
1426 static void GLAPIENTRY
1427 _save_CallList(GLuint l)
1429 GET_CURRENT_CONTEXT(ctx);
1430 dlist_fallback(ctx);
1431 CALL_CallList(ctx->Save, (l));
1434 static void GLAPIENTRY
1435 _save_CallLists(GLsizei n, GLenum type, const GLvoid * v)
1437 GET_CURRENT_CONTEXT(ctx);
1438 dlist_fallback(ctx);
1439 CALL_CallLists(ctx->Save, (n, type, v));
1445 * Called when a glBegin is getting compiled into a display list.
1446 * Updating of ctx->Driver.CurrentSavePrimitive is already taken care of.
1449 vbo_save_NotifyBegin(struct gl_context *ctx, GLenum mode,
1450 bool no_current_update)
1452 struct vbo_save_context *save = &vbo_context(ctx)->save;
1453 const GLuint i = save->prim_store->used++;
1455 ctx->Driver.CurrentSavePrimitive = mode;
1457 assert(i < save->prim_store->size);
1458 save->prim_store->prims[i].mode = mode & VBO_SAVE_PRIM_MODE_MASK;
1459 save->prim_store->prims[i].begin = 1;
1460 save->prim_store->prims[i].end = 0;
1461 save->prim_store->prims[i].start = save->vert_count;
1462 save->prim_store->prims[i].count = 0;
1464 save->no_current_update = no_current_update;
1466 if (save->out_of_memory) {
1467 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
1470 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt);
1473 /* We need to call vbo_save_SaveFlushVertices() if there's state change */
1474 ctx->Driver.SaveNeedFlush = GL_TRUE;
1478 static void GLAPIENTRY
1481 GET_CURRENT_CONTEXT(ctx);
1482 struct vbo_save_context *save = &vbo_context(ctx)->save;
1483 const GLint i = save->prim_store->used - 1;
1485 ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
1486 save->prim_store->prims[i].end = 1;
1487 save->prim_store->prims[i].count = (save->vert_count - save->prim_store->prims[i].start);
1489 if (i == (GLint) save->prim_store->size - 1) {
1490 compile_vertex_list(ctx);
1491 assert(save->copied.nr == 0);
1494 /* Swap out this vertex format while outside begin/end. Any color,
1495 * etc. received between here and the next begin will be compiled
1498 if (save->out_of_memory) {
1499 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
1502 _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
1507 static void GLAPIENTRY
1508 _save_Begin(GLenum mode)
1510 GET_CURRENT_CONTEXT(ctx);
1512 _mesa_compile_error(ctx, GL_INVALID_OPERATION, "Recursive glBegin");
1516 static void GLAPIENTRY
1517 _save_PrimitiveRestartNV(void)
1519 GET_CURRENT_CONTEXT(ctx);
1520 struct vbo_save_context *save = &vbo_context(ctx)->save;
1522 if (save->prim_store->used == 0) {
1523 /* We're not inside a glBegin/End pair, so calling glPrimitiverRestartNV
1526 _mesa_compile_error(ctx, GL_INVALID_OPERATION,
1527 "glPrimitiveRestartNV called outside glBegin/End");
1529 /* get current primitive mode */
1530 GLenum curPrim = save->prim_store->prims[save->prim_store->used - 1].mode;
1531 bool no_current_update = save->no_current_update;
1533 /* restart primitive */
1534 CALL_End(ctx->CurrentServerDispatch, ());
1535 vbo_save_NotifyBegin(ctx, curPrim, no_current_update);
1540 /* Unlike the functions above, these are to be hooked into the vtxfmt
1541 * maintained in ctx->ListState, active when the list is known or
1542 * suspected to be outside any begin/end primitive.
1543 * Note: OBE = Outside Begin/End
1545 static void GLAPIENTRY
1546 _save_OBE_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
1548 GET_CURRENT_CONTEXT(ctx);
1549 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1551 vbo_save_NotifyBegin(ctx, GL_QUADS, false);
1552 CALL_Vertex2f(dispatch, (x1, y1));
1553 CALL_Vertex2f(dispatch, (x2, y1));
1554 CALL_Vertex2f(dispatch, (x2, y2));
1555 CALL_Vertex2f(dispatch, (x1, y2));
1556 CALL_End(dispatch, ());
1560 static void GLAPIENTRY
1561 _save_OBE_Rectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)
1563 _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1566 static void GLAPIENTRY
1567 _save_OBE_Rectdv(const GLdouble *v1, const GLdouble *v2)
1569 _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1572 static void GLAPIENTRY
1573 _save_OBE_Rectfv(const GLfloat *v1, const GLfloat *v2)
1575 _save_OBE_Rectf(v1[0], v1[1], v2[0], v2[1]);
1578 static void GLAPIENTRY
1579 _save_OBE_Recti(GLint x1, GLint y1, GLint x2, GLint y2)
1581 _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1584 static void GLAPIENTRY
1585 _save_OBE_Rectiv(const GLint *v1, const GLint *v2)
1587 _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1590 static void GLAPIENTRY
1591 _save_OBE_Rects(GLshort x1, GLshort y1, GLshort x2, GLshort y2)
1593 _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1596 static void GLAPIENTRY
1597 _save_OBE_Rectsv(const GLshort *v1, const GLshort *v2)
1599 _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1603 _ensure_draws_fits_in_storage(struct gl_context *ctx, int primcount, int vertcount)
1605 struct vbo_save_context *save = &vbo_context(ctx)->save;
1607 bool realloc_prim = save->prim_store->used + primcount > save->prim_store->size;
1608 bool realloc_vert = save->vertex_size && (save->vert_count + vertcount >= save->max_vert);
1610 if (realloc_prim || realloc_vert) {
1611 if (save->vert_count || save->prim_store->used) {
1612 /* TODO: this really isn't needed. We should realloc only the CPU-side memory. */
1613 compile_vertex_list(ctx);
1615 realloc_storage(ctx, realloc_prim ? primcount : -1, realloc_vert ? vertcount : -1);
1616 reset_counters(ctx);
1621 static void GLAPIENTRY
1622 _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count)
1624 GET_CURRENT_CONTEXT(ctx);
1625 struct gl_vertex_array_object *vao = ctx->Array.VAO;
1626 struct vbo_save_context *save = &vbo_context(ctx)->save;
1629 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1630 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawArrays(mode)");
1634 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawArrays(count<0)");
1638 if (save->out_of_memory)
1641 _ensure_draws_fits_in_storage(ctx, 1, count);
1643 /* Make sure to process any VBO binding changes */
1644 _mesa_update_state(ctx);
1646 _mesa_vao_map_arrays(ctx, vao, GL_MAP_READ_BIT);
1648 vbo_save_NotifyBegin(ctx, mode, true);
1650 for (i = 0; i < count; i++)
1651 _mesa_array_element(ctx, start + i);
1652 CALL_End(ctx->CurrentServerDispatch, ());
1654 _mesa_vao_unmap_arrays(ctx, vao);
1658 static void GLAPIENTRY
1659 _save_OBE_MultiDrawArrays(GLenum mode, const GLint *first,
1660 const GLsizei *count, GLsizei primcount)
1662 GET_CURRENT_CONTEXT(ctx);
1665 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1666 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMultiDrawArrays(mode)");
1670 if (primcount < 0) {
1671 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1672 "glMultiDrawArrays(primcount<0)");
1676 unsigned vertcount = 0;
1677 for (i = 0; i < primcount; i++) {
1679 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1680 "glMultiDrawArrays(count[i]<0)");
1683 vertcount += count[i];
1686 _ensure_draws_fits_in_storage(ctx, primcount, vertcount);
1688 for (i = 0; i < primcount; i++) {
1690 _save_OBE_DrawArrays(mode, first[i], count[i]);
1697 array_element(struct gl_context *ctx,
1698 GLint basevertex, GLuint elt, unsigned index_size_shift)
1700 /* Section 10.3.5 Primitive Restart:
1702 * When one of the *BaseVertex drawing commands specified in section 10.5
1703 * is used, the primitive restart comparison occurs before the basevertex
1704 * offset is added to the array index.
1706 /* If PrimitiveRestart is enabled and the index is the RestartIndex
1707 * then we call PrimitiveRestartNV and return.
1709 if (ctx->Array._PrimitiveRestart[index_size_shift] &&
1710 elt == ctx->Array._RestartIndex[index_size_shift]) {
1711 CALL_PrimitiveRestartNV(ctx->CurrentServerDispatch, ());
1715 _mesa_array_element(ctx, basevertex + elt);
1719 /* Could do better by copying the arrays and element list intact and
1720 * then emitting an indexed prim at runtime.
1722 static void GLAPIENTRY
1723 _save_OBE_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1724 const GLvoid * indices, GLint basevertex)
1726 GET_CURRENT_CONTEXT(ctx);
1727 struct vbo_save_context *save = &vbo_context(ctx)->save;
1728 struct gl_vertex_array_object *vao = ctx->Array.VAO;
1729 struct gl_buffer_object *indexbuf = vao->IndexBufferObj;
1732 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1733 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawElements(mode)");
1737 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawElements(count<0)");
1740 if (type != GL_UNSIGNED_BYTE &&
1741 type != GL_UNSIGNED_SHORT &&
1742 type != GL_UNSIGNED_INT) {
1743 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawElements(count<0)");
1747 if (save->out_of_memory)
1750 _ensure_draws_fits_in_storage(ctx, 1, count);
1752 /* Make sure to process any VBO binding changes */
1753 _mesa_update_state(ctx);
1755 _mesa_vao_map(ctx, vao, GL_MAP_READ_BIT);
1759 ADD_POINTERS(indexbuf->Mappings[MAP_INTERNAL].Pointer, indices);
1761 vbo_save_NotifyBegin(ctx, mode, true);
1764 case GL_UNSIGNED_BYTE:
1765 for (i = 0; i < count; i++)
1766 array_element(ctx, basevertex, ((GLubyte *) indices)[i], 0);
1768 case GL_UNSIGNED_SHORT:
1769 for (i = 0; i < count; i++)
1770 array_element(ctx, basevertex, ((GLushort *) indices)[i], 1);
1772 case GL_UNSIGNED_INT:
1773 for (i = 0; i < count; i++)
1774 array_element(ctx, basevertex, ((GLuint *) indices)[i], 2);
1777 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawElements(type)");
1781 CALL_End(ctx->CurrentServerDispatch, ());
1783 _mesa_vao_unmap(ctx, vao);
1786 static void GLAPIENTRY
1787 _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type,
1788 const GLvoid * indices)
1790 _save_OBE_DrawElementsBaseVertex(mode, count, type, indices, 0);
1794 static void GLAPIENTRY
1795 _save_OBE_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
1796 GLsizei count, GLenum type,
1797 const GLvoid * indices)
1799 GET_CURRENT_CONTEXT(ctx);
1800 struct vbo_save_context *save = &vbo_context(ctx)->save;
1802 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1803 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(mode)");
1807 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1808 "glDrawRangeElements(count<0)");
1811 if (type != GL_UNSIGNED_BYTE &&
1812 type != GL_UNSIGNED_SHORT &&
1813 type != GL_UNSIGNED_INT) {
1814 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(type)");
1818 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1819 "glDrawRangeElements(end < start)");
1823 if (save->out_of_memory)
1826 _save_OBE_DrawElements(mode, count, type, indices);
1830 static void GLAPIENTRY
1831 _save_OBE_MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type,
1832 const GLvoid * const *indices, GLsizei primcount)
1834 GET_CURRENT_CONTEXT(ctx);
1835 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1839 for (i = 0; i < primcount; i++) {
1840 vertcount += count[i];
1842 _ensure_draws_fits_in_storage(ctx, primcount, vertcount);
1844 for (i = 0; i < primcount; i++) {
1846 CALL_DrawElements(dispatch, (mode, count[i], type, indices[i]));
1852 static void GLAPIENTRY
1853 _save_OBE_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count,
1855 const GLvoid * const *indices,
1857 const GLint *basevertex)
1859 GET_CURRENT_CONTEXT(ctx);
1860 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1864 for (i = 0; i < primcount; i++) {
1865 vertcount += count[i];
1867 _ensure_draws_fits_in_storage(ctx, primcount, vertcount);
1869 for (i = 0; i < primcount; i++) {
1871 CALL_DrawElementsBaseVertex(dispatch, (mode, count[i], type,
1880 vtxfmt_init(struct gl_context *ctx)
1882 struct vbo_save_context *save = &vbo_context(ctx)->save;
1883 GLvertexformat *vfmt = &save->vtxfmt;
1885 #define NAME_AE(x) _ae_##x
1886 #define NAME_CALLLIST(x) _save_##x
1887 #define NAME(x) _save_##x
1888 #define NAME_ES(x) _save_##x##ARB
1890 #include "vbo_init_tmp.h"
1895 * Initialize the dispatch table with the VBO functions for display
1899 vbo_initialize_save_dispatch(const struct gl_context *ctx,
1900 struct _glapi_table *exec)
1902 SET_DrawArrays(exec, _save_OBE_DrawArrays);
1903 SET_MultiDrawArrays(exec, _save_OBE_MultiDrawArrays);
1904 SET_DrawElements(exec, _save_OBE_DrawElements);
1905 SET_DrawElementsBaseVertex(exec, _save_OBE_DrawElementsBaseVertex);
1906 SET_DrawRangeElements(exec, _save_OBE_DrawRangeElements);
1907 SET_MultiDrawElementsEXT(exec, _save_OBE_MultiDrawElements);
1908 SET_MultiDrawElementsBaseVertex(exec, _save_OBE_MultiDrawElementsBaseVertex);
1909 SET_Rectf(exec, _save_OBE_Rectf);
1910 SET_Rectd(exec, _save_OBE_Rectd);
1911 SET_Rectdv(exec, _save_OBE_Rectdv);
1912 SET_Rectfv(exec, _save_OBE_Rectfv);
1913 SET_Recti(exec, _save_OBE_Recti);
1914 SET_Rectiv(exec, _save_OBE_Rectiv);
1915 SET_Rects(exec, _save_OBE_Rects);
1916 SET_Rectsv(exec, _save_OBE_Rectsv);
1918 /* Note: other glDraw functins aren't compiled into display lists */
1924 vbo_save_SaveFlushVertices(struct gl_context *ctx)
1926 struct vbo_save_context *save = &vbo_context(ctx)->save;
1928 /* Noop when we are actually active:
1930 if (ctx->Driver.CurrentSavePrimitive <= PRIM_MAX)
1933 if (save->vert_count || save->prim_store->used)
1934 compile_vertex_list(ctx);
1936 copy_to_current(ctx);
1938 reset_counters(ctx);
1939 ctx->Driver.SaveNeedFlush = GL_FALSE;
1944 * Called from glNewList when we're starting to compile a display list.
1947 vbo_save_NewList(struct gl_context *ctx, GLuint list, GLenum mode)
1949 struct vbo_save_context *save = &vbo_context(ctx)->save;
1954 if (!save->prim_store)
1955 save->prim_store = alloc_prim_store(0);
1957 if (!save->vertex_store)
1958 save->vertex_store = alloc_vertex_store(ctx, 0);
1960 save->buffer_ptr = save->vertex_store->buffer_in_ram + save->vertex_store->used;
1963 reset_counters(ctx);
1964 ctx->Driver.SaveNeedFlush = GL_FALSE;
1969 * Called from glEndList when we're finished compiling a display list.
1972 vbo_save_EndList(struct gl_context *ctx)
1974 struct vbo_save_context *save = &vbo_context(ctx)->save;
1976 /* EndList called inside a (saved) Begin/End pair?
1978 if (_mesa_inside_dlist_begin_end(ctx)) {
1979 if (save->prim_store->used > 0) {
1980 GLint i = save->prim_store->used - 1;
1981 ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
1982 save->prim_store->prims[i].end = 0;
1983 save->prim_store->prims[i].count = save->vert_count - save->prim_store->prims[i].start;
1986 /* Make sure this vertex list gets replayed by the "loopback"
1989 save->dangling_attr_ref = GL_TRUE;
1990 vbo_save_SaveFlushVertices(ctx);
1992 /* Swap out this vertex format while outside begin/end. Any color,
1993 * etc. received between here and the next begin will be compiled
1996 _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
1999 assert(save->vertex_size == 0);
2003 * Called during context creation/init.
2006 current_init(struct gl_context *ctx)
2008 struct vbo_save_context *save = &vbo_context(ctx)->save;
2011 for (i = VBO_ATTRIB_POS; i <= VBO_ATTRIB_EDGEFLAG; i++) {
2012 const GLuint j = i - VBO_ATTRIB_POS;
2013 assert(j < VERT_ATTRIB_MAX);
2014 save->currentsz[i] = &ctx->ListState.ActiveAttribSize[j];
2015 save->current[i] = (fi_type *) ctx->ListState.CurrentAttrib[j];
2018 for (i = VBO_ATTRIB_FIRST_MATERIAL; i <= VBO_ATTRIB_LAST_MATERIAL; i++) {
2019 const GLuint j = i - VBO_ATTRIB_FIRST_MATERIAL;
2020 assert(j < MAT_ATTRIB_MAX);
2021 save->currentsz[i] = &ctx->ListState.ActiveMaterialSize[j];
2022 save->current[i] = (fi_type *) ctx->ListState.CurrentMaterial[j];
2028 * Initialize the display list compiler. Called during context creation.
2031 vbo_save_api_init(struct vbo_save_context *save)
2033 struct gl_context *ctx = gl_context_from_vbo_save(save);
2037 _mesa_noop_vtxfmt_init(ctx, &save->vtxfmt_noop);