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"
87 #include "gallium/include/pipe/p_state.h"
90 #include "vbo_private.h"
97 /* An interesting VBO number/name to help with debugging */
98 #define VBO_BUF_ID 12345
100 static void GLAPIENTRY
101 _save_Materialfv(GLenum face, GLenum pname, const GLfloat *params);
103 static void GLAPIENTRY
104 _save_EvalCoord1f(GLfloat u);
106 static void GLAPIENTRY
107 _save_EvalCoord2f(GLfloat u, GLfloat v);
110 * NOTE: Old 'parity' issue is gone, but copying can still be
111 * wrong-footed on replay.
114 copy_vertices(struct gl_context *ctx,
115 const struct vbo_save_vertex_list *node,
116 const fi_type * src_buffer)
118 struct vbo_save_context *save = &vbo_context(ctx)->save;
119 struct _mesa_prim *prim = &node->cold->prims[node->cold->prim_count - 1];
120 GLuint sz = save->vertex_size;
121 const fi_type *src = src_buffer + prim->start * sz;
122 fi_type *dst = save->copied.buffer;
127 return vbo_copy_vertices(ctx, prim->mode, prim->start, &prim->count,
128 prim->begin, sz, true, dst, src);
132 static struct vbo_save_vertex_store *
133 alloc_vertex_store(struct gl_context *ctx, int vertex_count)
135 struct vbo_save_context *save = &vbo_context(ctx)->save;
136 struct vbo_save_vertex_store *vertex_store =
137 CALLOC_STRUCT(vbo_save_vertex_store);
139 int size = MAX2(vertex_count * save->vertex_size, VBO_SAVE_BUFFER_SIZE);
141 /* obj->Name needs to be non-zero, but won't ever be examined more
142 * closely than that. In particular these buffers won't be entered
143 * into the hash and can never be confused with ones visible to the
144 * user. Perhaps there could be a special number for internal
147 vertex_store->bufferobj = ctx->Driver.NewBufferObject(ctx, VBO_BUF_ID);
148 if (vertex_store->bufferobj) {
149 vertex_store->buffer_in_ram_size = size * sizeof(GLfloat);
150 vertex_store->buffer_in_ram = malloc(vertex_store->buffer_in_ram_size);
151 save->out_of_memory = vertex_store->buffer_in_ram == NULL;
152 save->out_of_memory =
153 !ctx->Driver.BufferData(ctx,
155 size * sizeof(GLfloat),
156 NULL, GL_STATIC_DRAW_ARB,
158 vertex_store->bufferobj);
161 save->out_of_memory = GL_TRUE;
164 if (save->out_of_memory) {
165 _mesa_error(ctx, GL_OUT_OF_MEMORY, "internal VBO allocation");
166 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
169 vertex_store->used = 0;
176 free_vertex_store(struct gl_context *ctx,
177 struct vbo_save_vertex_store *vertex_store)
179 free(vertex_store->buffer_in_ram);
181 if (vertex_store->bufferobj) {
182 _mesa_reference_buffer_object(ctx, &vertex_store->bufferobj, NULL);
189 static struct vbo_save_primitive_store *
190 alloc_prim_store(int prim_count)
192 struct vbo_save_primitive_store *store =
193 CALLOC_STRUCT(vbo_save_primitive_store);
194 store->size = MAX2(prim_count, VBO_SAVE_PRIM_SIZE);
195 store->prims = calloc(store->size, sizeof(struct _mesa_prim));
203 reset_counters(struct gl_context *ctx)
205 struct vbo_save_context *save = &vbo_context(ctx)->save;
207 save->prims = save->prim_store->prims + save->prim_store->used;
208 save->buffer_map = save->vertex_store->buffer_in_ram + save->vertex_store->used;
210 assert(save->buffer_map == save->buffer_ptr);
212 if (save->vertex_size)
213 save->max_vert = (save->vertex_store->bufferobj->Size / sizeof(float) - save->vertex_store->used) /
218 save->vert_count = 0;
219 save->prim_count = 0;
220 save->prim_max = save->prim_store->size - save->prim_store->used;
221 save->dangling_attr_ref = GL_FALSE;
225 * For a list of prims, try merging prims that can just be extensions of the
229 merge_prims(struct gl_context *ctx, struct _mesa_prim *prim_list,
233 struct _mesa_prim *prev_prim = prim_list;
235 for (i = 1; i < *prim_count; i++) {
236 struct _mesa_prim *this_prim = prim_list + i;
238 vbo_try_prim_conversion(&this_prim->mode, &this_prim->count);
240 if (vbo_merge_draws(ctx, true,
241 prev_prim->mode, this_prim->mode,
242 prev_prim->start, this_prim->start,
243 &prev_prim->count, this_prim->count,
244 prev_prim->basevertex, this_prim->basevertex,
246 this_prim->begin, this_prim->end)) {
247 /* We've found a prim that just extend the previous one. Tack it
248 * onto the previous one, and let this primitive struct get dropped.
253 /* If any previous primitives have been dropped, then we need to copy
254 * this later one into the next available slot.
257 if (prev_prim != this_prim)
258 *prev_prim = *this_prim;
261 *prim_count = prev_prim - prim_list + 1;
266 * Convert GL_LINE_LOOP primitive into GL_LINE_STRIP so that drivers
267 * don't have to worry about handling the _mesa_prim::begin/end flags.
268 * See https://bugs.freedesktop.org/show_bug.cgi?id=81174
271 convert_line_loop_to_strip(struct vbo_save_context *save,
272 struct vbo_save_vertex_list *node)
274 struct _mesa_prim *prim = &node->cold->prims[node->cold->prim_count - 1];
276 assert(prim->mode == GL_LINE_LOOP);
279 /* Copy the 0th vertex to end of the buffer and extend the
280 * vertex count by one to finish the line loop.
282 const GLuint sz = save->vertex_size;
284 const fi_type *src = save->buffer_map + prim->start * sz;
286 fi_type *dst = save->buffer_map + (prim->start + prim->count) * sz;
288 memcpy(dst, src, sz * sizeof(float));
291 node->cold->vertex_count++;
293 save->buffer_ptr += sz;
294 save->vertex_store->used += sz;
298 /* Drawing the second or later section of a long line loop.
299 * Skip the 0th vertex.
305 prim->mode = GL_LINE_STRIP;
309 /* Compare the present vao if it has the same setup. */
311 compare_vao(gl_vertex_processing_mode mode,
312 const struct gl_vertex_array_object *vao,
313 const struct gl_buffer_object *bo, GLintptr buffer_offset,
314 GLuint stride, GLbitfield64 vao_enabled,
315 const GLubyte size[VBO_ATTRIB_MAX],
316 const GLenum16 type[VBO_ATTRIB_MAX],
317 const GLuint offset[VBO_ATTRIB_MAX])
322 /* If the enabled arrays are not the same we are not equal. */
323 if (vao_enabled != vao->Enabled)
326 /* Check the buffer binding at 0 */
327 if (vao->BufferBinding[0].BufferObj != bo)
329 /* BufferBinding[0].Offset != buffer_offset is checked per attribute */
330 if (vao->BufferBinding[0].Stride != stride)
332 assert(vao->BufferBinding[0].InstanceDivisor == 0);
334 /* Retrieve the mapping from VBO_ATTRIB to VERT_ATTRIB space */
335 const GLubyte *const vao_to_vbo_map = _vbo_attribute_alias_map[mode];
337 /* Now check the enabled arrays */
338 GLbitfield mask = vao_enabled;
340 const int attr = u_bit_scan(&mask);
341 const unsigned char vbo_attr = vao_to_vbo_map[attr];
342 const GLenum16 tp = type[vbo_attr];
343 const GLintptr off = offset[vbo_attr] + buffer_offset;
344 const struct gl_array_attributes *attrib = &vao->VertexAttrib[attr];
345 if (attrib->RelativeOffset + vao->BufferBinding[0].Offset != off)
347 if (attrib->Format.Type != tp)
349 if (attrib->Format.Size != size[vbo_attr])
351 assert(attrib->Format.Format == GL_RGBA);
352 assert(attrib->Format.Normalized == GL_FALSE);
353 assert(attrib->Format.Integer == vbo_attrtype_to_integer_flag(tp));
354 assert(attrib->Format.Doubles == vbo_attrtype_to_double_flag(tp));
355 assert(attrib->BufferBindingIndex == 0);
362 /* Create or reuse the vao for the vertex processing mode. */
364 update_vao(struct gl_context *ctx,
365 gl_vertex_processing_mode mode,
366 struct gl_vertex_array_object **vao,
367 struct gl_buffer_object *bo, GLintptr buffer_offset,
368 GLuint stride, GLbitfield64 vbo_enabled,
369 const GLubyte size[VBO_ATTRIB_MAX],
370 const GLenum16 type[VBO_ATTRIB_MAX],
371 const GLuint offset[VBO_ATTRIB_MAX])
373 /* Compute the bitmasks of vao_enabled arrays */
374 GLbitfield vao_enabled = _vbo_get_vao_enabled_from_vbo(mode, vbo_enabled);
377 * Check if we can possibly reuse the exisiting one.
378 * In the long term we should reset them when something changes.
380 if (compare_vao(mode, *vao, bo, buffer_offset, stride,
381 vao_enabled, size, type, offset))
384 /* The initial refcount is 1 */
385 _mesa_reference_vao(ctx, vao, NULL);
386 *vao = _mesa_new_vao(ctx, ~((GLuint)0));
389 * assert(stride <= ctx->Const.MaxVertexAttribStride);
390 * MaxVertexAttribStride is not set for drivers that does not
391 * expose GL 44 or GLES 31.
394 /* Bind the buffer object at binding point 0 */
395 _mesa_bind_vertex_buffer(ctx, *vao, 0, bo, buffer_offset, stride, false,
398 /* Retrieve the mapping from VBO_ATTRIB to VERT_ATTRIB space
399 * Note that the position/generic0 aliasing is done in the VAO.
401 const GLubyte *const vao_to_vbo_map = _vbo_attribute_alias_map[mode];
402 /* Now set the enable arrays */
403 GLbitfield mask = vao_enabled;
405 const int vao_attr = u_bit_scan(&mask);
406 const GLubyte vbo_attr = vao_to_vbo_map[vao_attr];
407 assert(offset[vbo_attr] <= ctx->Const.MaxVertexAttribRelativeOffset);
409 _vbo_set_attrib_format(ctx, *vao, vao_attr, buffer_offset,
410 size[vbo_attr], type[vbo_attr], offset[vbo_attr]);
411 _mesa_vertex_attrib_binding(ctx, *vao, vao_attr, 0);
413 _mesa_enable_vertex_array_attribs(ctx, *vao, vao_enabled);
414 assert(vao_enabled == (*vao)->Enabled);
415 assert((vao_enabled & ~(*vao)->VertexAttribBufferMask) == 0);
417 /* Finalize and freeze the VAO */
418 _mesa_set_vao_immutable(ctx, *vao);
423 realloc_storage(struct gl_context *ctx, int prim_count, int vertex_count)
425 struct vbo_save_context *save = &vbo_context(ctx)->save;
426 if (vertex_count >= 0) {
427 /* Release old reference:
429 free_vertex_store(ctx, save->vertex_store);
430 save->vertex_store = NULL;
431 /* When we have a new vbo, we will for sure need a new vao */
432 for (gl_vertex_processing_mode vpm = 0; vpm < VP_MODE_MAX; ++vpm)
433 _mesa_reference_vao(ctx, &save->VAO[vpm], NULL);
435 /* Allocate and map new store:
437 save->vertex_store = alloc_vertex_store(ctx, vertex_count);
438 save->buffer_ptr = save->vertex_store->buffer_in_ram + save->vertex_store->used;
439 save->out_of_memory = save->buffer_ptr == NULL;
442 if (prim_count >= 0) {
443 if (--save->prim_store->refcount == 0) {
444 free(save->prim_store->prims);
445 free(save->prim_store);
447 save->prim_store = alloc_prim_store(prim_count);
453 * Insert the active immediate struct onto the display list currently
457 compile_vertex_list(struct gl_context *ctx)
459 struct vbo_save_context *save = &vbo_context(ctx)->save;
460 struct vbo_save_vertex_list *node;
462 /* Allocate space for this structure in the display list currently
465 node = (struct vbo_save_vertex_list *)
466 _mesa_dlist_alloc_vertex_list(ctx, !save->dangling_attr_ref && !save->no_current_update);
471 memset(node, 0, sizeof(struct vbo_save_vertex_list));
472 node->cold = calloc(1, sizeof(*node->cold));
474 /* Make sure the pointer is aligned to the size of a pointer */
475 assert((GLintptr) node % sizeof(void *) == 0);
477 /* Duplicate our template, increment refcounts to the storage structs:
479 GLintptr old_offset = 0;
481 old_offset = save->VAO[0]->BufferBinding[0].Offset
482 + save->VAO[0]->VertexAttrib[VERT_ATTRIB_POS].RelativeOffset;
484 const GLsizei stride = save->vertex_size*sizeof(GLfloat);
485 GLintptr buffer_offset =
486 (save->buffer_map - save->vertex_store->buffer_in_ram) * sizeof(GLfloat);
487 const GLintptr original_buffer_offset = buffer_offset;
488 assert(old_offset <= buffer_offset);
489 const GLintptr offset_diff = buffer_offset - old_offset;
490 GLuint start_offset = 0;
491 if (offset_diff > 0 && stride > 0 && offset_diff % stride == 0) {
492 /* The vertex size is an exact multiple of the buffer offset.
493 * This means that we can use zero-based vertex attribute pointers
494 * and specify the start of the primitive with the _mesa_prim::start
495 * field. This results in issuing several draw calls with identical
496 * vertex attribute information. This can result in fewer state
497 * changes in drivers. In particular, the Gallium CSO module will
498 * filter out redundant vertex buffer changes.
500 /* We cannot immediately update the primitives as some methods below
501 * still need the uncorrected start vertices
503 start_offset = offset_diff/stride;
504 assert(old_offset == buffer_offset - offset_diff);
505 buffer_offset = old_offset;
507 GLuint offsets[VBO_ATTRIB_MAX];
508 for (unsigned i = 0, offset = 0; i < VBO_ATTRIB_MAX; ++i) {
510 offset += save->attrsz[i] * sizeof(GLfloat);
512 node->cold->vertex_count = save->vert_count;
513 node->cold->wrap_count = save->copied.nr;
514 node->cold->prims = save->prims;
515 node->cold->ib.obj = NULL;
516 node->cold->prim_count = save->prim_count;
517 node->cold->prim_store = save->prim_store;
519 /* Create a pair of VAOs for the possible VERTEX_PROCESSING_MODEs
520 * Note that this may reuse the previous one of possible.
522 for (gl_vertex_processing_mode vpm = VP_MODE_FF; vpm < VP_MODE_MAX; ++vpm) {
523 /* create or reuse the vao */
524 update_vao(ctx, vpm, &save->VAO[vpm],
525 save->vertex_store->bufferobj, buffer_offset, stride,
526 save->enabled, save->attrsz, save->attrtype, offsets);
527 /* Reference the vao in the dlist */
528 node->VAO[vpm] = NULL;
529 _mesa_reference_vao(ctx, &node->VAO[vpm], save->VAO[vpm]);
532 node->cold->prim_store->refcount++;
534 if (save->no_current_update) {
535 node->cold->current_data = NULL;
538 GLuint current_size = save->vertex_size - save->attrsz[0];
539 node->cold->current_data = NULL;
542 node->cold->current_data = malloc(current_size * sizeof(GLfloat));
543 if (node->cold->current_data) {
544 const char *buffer = (const char *)save->buffer_map;
545 unsigned attr_offset = save->attrsz[0] * sizeof(GLfloat);
546 unsigned vertex_offset = 0;
548 if (node->cold->vertex_count)
549 vertex_offset = (node->cold->vertex_count - 1) * stride;
551 memcpy(node->cold->current_data, buffer + vertex_offset + attr_offset,
552 current_size * sizeof(GLfloat));
554 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Current value allocation");
559 assert(save->attrsz[VBO_ATTRIB_POS] != 0 || node->cold->vertex_count == 0);
561 if (save->dangling_attr_ref)
562 ctx->ListState.Current.UseLoopback = true;
564 save->vertex_store->used += save->vertex_size * node->cold->vertex_count;
565 save->prim_store->used += node->cold->prim_count;
567 /* Copy duplicated vertices
569 save->copied.nr = copy_vertices(ctx, node, save->buffer_map);
571 if (node->cold->prims[node->cold->prim_count - 1].mode == GL_LINE_LOOP) {
572 convert_line_loop_to_strip(save, node);
575 merge_prims(ctx, node->cold->prims, &node->cold->prim_count);
577 /* Correct the primitive starts, we can only do this here as copy_vertices
578 * and convert_line_loop_to_strip above consume the uncorrected starts.
579 * On the other hand the _vbo_loopback_vertex_list call below needs the
580 * primitves to be corrected already.
582 for (unsigned i = 0; i < node->cold->prim_count; i++) {
583 node->cold->prims[i].start += start_offset;
586 /* Create an index buffer. */
587 node->cold->min_index = node->cold->max_index = 0;
588 if (save->vert_count == 0 || save->prim_count == 0)
591 /* We won't modify node->prims, so use a const alias to avoid unintended
593 const struct _mesa_prim *original_prims = node->cold->prims;
595 int end = original_prims[node->cold->prim_count - 1].start +
596 original_prims[node->cold->prim_count - 1].count;
597 int total_vert_count = end - original_prims[0].start;
599 node->cold->min_index = node->cold->prims[0].start;
600 node->cold->max_index = end - 1;
602 /* Estimate for the worst case: all prims are line strips (the +1 is because
603 * wrap_buffers may call use but the last primitive may not be complete) */
604 int max_indices_count = MAX2(total_vert_count * 2 - (node->cold->prim_count * 2) + 1,
607 int indices_offset = 0;
608 int available = save->previous_ib ? (save->previous_ib->Size / 4 - save->ib_first_free_index) : 0;
609 if (available >= max_indices_count) {
610 indices_offset = save->ib_first_free_index;
612 int size = max_indices_count * sizeof(uint32_t);
613 uint32_t* indices = (uint32_t*) malloc(size);
614 struct _mesa_prim *merged_prims = NULL;
618 int last_valid_prim = -1;
619 /* Construct indices array. */
620 for (unsigned i = 0; i < node->cold->prim_count; i++) {
621 assert(original_prims[i].basevertex == 0);
622 GLubyte mode = original_prims[i].mode;
624 int vertex_count = original_prims[i].count;
629 /* Line strips may get converted to lines */
630 if (mode == GL_LINE_STRIP)
633 /* If 2 consecutive prims use the same mode => merge them. */
634 bool merge_prims = last_valid_prim >= 0 &&
635 mode == merged_prims[last_valid_prim].mode &&
636 mode != GL_LINE_LOOP && mode != GL_TRIANGLE_FAN &&
637 mode != GL_QUAD_STRIP && mode != GL_POLYGON &&
640 /* To be able to merge consecutive triangle strips we need to insert
641 * a degenerate triangle.
644 mode == GL_TRIANGLE_STRIP) {
645 /* Insert a degenerate triangle */
646 assert(merged_prims[last_valid_prim].mode == GL_TRIANGLE_STRIP);
647 unsigned tri_count = merged_prims[last_valid_prim].count - 2;
649 indices[idx] = indices[idx - 1];
650 indices[idx + 1] = original_prims[i].start;
652 merged_prims[last_valid_prim].count += 2;
655 /* Add another index to preserve winding order */
656 indices[idx++] = original_prims[i].start;
657 merged_prims[last_valid_prim].count++;
663 /* Convert line strips to lines if it'll allow if the previous
664 * prim mode is GL_LINES (so merge_prims is true) or if the next
665 * primitive mode is GL_LINES or GL_LINE_LOOP.
667 if (original_prims[i].mode == GL_LINE_STRIP &&
669 (i < node->cold->prim_count - 1 &&
670 (original_prims[i + 1].mode == GL_LINE_STRIP ||
671 original_prims[i + 1].mode == GL_LINES)))) {
672 for (unsigned j = 0; j < vertex_count; j++) {
673 indices[idx++] = original_prims[i].start + j;
674 /* Repeat all but the first/last indices. */
675 if (j && j != vertex_count - 1) {
676 indices[idx++] = original_prims[i].start + j;
680 /* We didn't convert to LINES, so restore the original mode */
681 mode = original_prims[i].mode;
683 for (unsigned j = 0; j < vertex_count; j++) {
684 indices[idx++] = original_prims[i].start + j;
689 /* Update vertex count. */
690 merged_prims[last_valid_prim].count += idx - start;
692 /* Keep this primitive */
693 last_valid_prim += 1;
694 assert(last_valid_prim <= i);
695 merged_prims = realloc(merged_prims, (1 + last_valid_prim) * sizeof(struct _mesa_prim));
696 merged_prims[last_valid_prim] = original_prims[i];
697 merged_prims[last_valid_prim].start = indices_offset + start;
698 merged_prims[last_valid_prim].count = idx - start;
700 merged_prims[last_valid_prim].mode = mode;
703 assert(idx > 0 && idx <= max_indices_count);
705 unsigned merged_prim_count = last_valid_prim + 1;
706 node->cold->ib.ptr = NULL;
707 node->cold->ib.count = idx;
708 node->cold->ib.index_size_shift = (GL_UNSIGNED_INT - GL_UNSIGNED_BYTE) >> 1;
710 if (!indices_offset) {
711 /* Allocate a new index buffer */
712 _mesa_reference_buffer_object(ctx, &save->previous_ib, NULL);
713 save->previous_ib = ctx->Driver.NewBufferObject(ctx, VBO_BUF_ID + 1);
714 bool success = ctx->Driver.BufferData(ctx,
715 GL_ELEMENT_ARRAY_BUFFER_ARB,
716 MAX2(VBO_SAVE_INDEX_SIZE, idx) * sizeof(uint32_t),
718 GL_STATIC_DRAW_ARB, GL_MAP_WRITE_BIT,
721 _mesa_reference_buffer_object(ctx, &save->previous_ib, NULL);
722 _mesa_error(ctx, GL_OUT_OF_MEMORY, "IB allocation");
726 _mesa_reference_buffer_object(ctx, &node->cold->ib.obj, save->previous_ib);
728 if (node->cold->ib.obj) {
729 ctx->Driver.BufferSubData(ctx,
730 indices_offset * sizeof(uint32_t),
731 idx * sizeof(uint32_t),
734 save->ib_first_free_index = indices_offset + idx;
736 node->cold->vertex_count = 0;
737 node->cold->prim_count = 0;
740 ctx->Driver.BufferSubData(ctx,
741 original_buffer_offset,
742 idx * save->vertex_size * sizeof(fi_type),
743 &save->vertex_store->buffer_in_ram[original_buffer_offset / sizeof(float)],
744 save->vertex_store->bufferobj);
746 /* Prepare for DrawGallium */
747 memset(&node->merged.info, 0, sizeof(struct pipe_draw_info));
748 /* The other info fields will be updated in vbo_save_playback_vertex_list */
749 node->merged.info.index_size = 4;
750 node->merged.info.instance_count = 1;
751 node->merged.info.index.gl_bo = node->cold->ib.obj;
752 if (merged_prim_count == 1) {
753 node->merged.info.mode = merged_prims[0].mode;
754 node->merged.start_count.start = merged_prims[0].start;
755 node->merged.start_count.count = merged_prims[0].count;
756 node->merged.start_count.index_bias = 0;
757 node->merged.mode = NULL;
759 node->merged.mode = malloc(merged_prim_count * sizeof(unsigned char));
760 node->merged.start_counts = malloc(merged_prim_count * sizeof(struct pipe_draw_start_count_bias));
761 for (unsigned i = 0; i < merged_prim_count; i++) {
762 node->merged.start_counts[i].start = merged_prims[i].start;
763 node->merged.start_counts[i].count = merged_prims[i].count;
764 node->merged.start_counts[i].index_bias = 0;
765 node->merged.mode[i] = merged_prims[i].mode;
768 node->merged.num_draws = merged_prim_count;
769 if (node->merged.num_draws > 1) {
770 bool same_mode = true;
771 for (unsigned i = 1; i < node->merged.num_draws && same_mode; i++) {
772 same_mode = node->merged.mode[i] == node->merged.mode[0];
775 /* All primitives use the same mode, so we can simplify a bit */
776 node->merged.info.mode = node->merged.mode[0];
777 free(node->merged.mode);
778 node->merged.mode = NULL;
786 /* Deal with GL_COMPILE_AND_EXECUTE:
788 if (ctx->ExecuteFlag) {
789 struct _glapi_table *dispatch = GET_DISPATCH();
791 _glapi_set_dispatch(ctx->Exec);
793 /* Note that the range of referenced vertices must be mapped already */
794 _vbo_loopback_vertex_list(ctx, node, save->vertex_store->buffer_in_ram);
796 _glapi_set_dispatch(dispatch);
799 /* Decide whether the storage structs are full, or can be used for
800 * the next vertex lists as well.
802 if (save->vertex_store->used >
803 save->vertex_store->bufferobj->Size / sizeof(float) - 16 * (save->vertex_size + 4)) {
804 realloc_storage(ctx, -1, 0);
807 /* update buffer_ptr for next vertex */
808 save->buffer_ptr = save->vertex_store->buffer_in_ram
809 + save->vertex_store->used;
812 if (save->prim_store->used > save->prim_store->size - 6) {
813 realloc_storage(ctx, 0, -1);
816 /* Reset our structures for the next run of vertices:
823 * This is called when we fill a vertex buffer before we hit a glEnd().
825 * TODO -- If no new vertices have been stored, don't bother saving it.
828 wrap_buffers(struct gl_context *ctx)
830 struct vbo_save_context *save = &vbo_context(ctx)->save;
831 GLint i = save->prim_count - 1;
834 assert(i < (GLint) save->prim_max);
837 /* Close off in-progress primitive.
839 save->prims[i].count = (save->vert_count - save->prims[i].start);
840 mode = save->prims[i].mode;
842 /* store the copied vertices, and allocate a new list.
844 compile_vertex_list(ctx);
846 /* Restart interrupted primitive
848 save->prims[0].mode = mode;
849 save->prims[0].begin = 0;
850 save->prims[0].end = 0;
851 save->prims[0].start = 0;
852 save->prims[0].count = 0;
853 save->prim_count = 1;
858 * Called only when buffers are wrapped as the result of filling the
859 * vertex_store struct.
862 wrap_filled_vertex(struct gl_context *ctx)
864 struct vbo_save_context *save = &vbo_context(ctx)->save;
865 unsigned numComponents;
867 /* Emit a glEnd to close off the last vertex list.
871 /* Copy stored stored vertices to start of new list.
873 assert(save->max_vert - save->vert_count > save->copied.nr);
875 numComponents = save->copied.nr * save->vertex_size;
876 memcpy(save->buffer_ptr,
878 numComponents * sizeof(fi_type));
879 save->buffer_ptr += numComponents;
880 save->vert_count += save->copied.nr;
885 copy_to_current(struct gl_context *ctx)
887 struct vbo_save_context *save = &vbo_context(ctx)->save;
888 GLbitfield64 enabled = save->enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));
891 const int i = u_bit_scan64(&enabled);
892 assert(save->attrsz[i]);
894 if (save->attrtype[i] == GL_DOUBLE ||
895 save->attrtype[i] == GL_UNSIGNED_INT64_ARB)
896 memcpy(save->current[i], save->attrptr[i], save->attrsz[i] * sizeof(GLfloat));
898 COPY_CLEAN_4V_TYPE_AS_UNION(save->current[i], save->attrsz[i],
899 save->attrptr[i], save->attrtype[i]);
905 copy_from_current(struct gl_context *ctx)
907 struct vbo_save_context *save = &vbo_context(ctx)->save;
908 GLbitfield64 enabled = save->enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));
911 const int i = u_bit_scan64(&enabled);
913 switch (save->attrsz[i]) {
915 save->attrptr[i][3] = save->current[i][3];
918 save->attrptr[i][2] = save->current[i][2];
921 save->attrptr[i][1] = save->current[i][1];
924 save->attrptr[i][0] = save->current[i][0];
927 unreachable("Unexpected vertex attribute size");
934 * Called when we increase the size of a vertex attribute. For example,
935 * if we've seen one or more glTexCoord2f() calls and now we get a
936 * glTexCoord3f() call.
937 * Flush existing data, set new attrib size, replay copied vertices.
940 upgrade_vertex(struct gl_context *ctx, GLuint attr, GLuint newsz)
942 struct vbo_save_context *save = &vbo_context(ctx)->save;
947 /* Store the current run of vertices, and emit a GL_END. Emit a
948 * BEGIN in the new buffer.
950 if (save->vert_count)
953 assert(save->copied.nr == 0);
955 /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
956 * when the attribute already exists in the vertex and is having
957 * its size increased.
959 copy_to_current(ctx);
963 oldsz = save->attrsz[attr];
964 save->attrsz[attr] = newsz;
965 save->enabled |= BITFIELD64_BIT(attr);
967 save->vertex_size += newsz - oldsz;
968 save->max_vert = ((save->vertex_store->bufferobj->Size / sizeof(float) -
969 save->vertex_store->used) /
971 save->vert_count = 0;
973 /* Recalculate all the attrptr[] values:
976 for (i = 0; i < VBO_ATTRIB_MAX; i++) {
977 if (save->attrsz[i]) {
978 save->attrptr[i] = tmp;
979 tmp += save->attrsz[i];
982 save->attrptr[i] = NULL; /* will not be dereferenced. */
986 /* Copy from current to repopulate the vertex with correct values.
988 copy_from_current(ctx);
990 /* Replay stored vertices to translate them to new format here.
992 * If there are copied vertices and the new (upgraded) attribute
993 * has not been defined before, this list is somewhat degenerate,
994 * and will need fixup at runtime.
996 if (save->copied.nr) {
997 const fi_type *data = save->copied.buffer;
998 fi_type *dest = save->buffer_map;
1000 /* Need to note this and fix up at runtime (or loopback):
1002 if (attr != VBO_ATTRIB_POS && save->currentsz[attr][0] == 0) {
1004 save->dangling_attr_ref = GL_TRUE;
1007 for (i = 0; i < save->copied.nr; i++) {
1008 GLbitfield64 enabled = save->enabled;
1010 const int j = u_bit_scan64(&enabled);
1011 assert(save->attrsz[j]);
1014 COPY_CLEAN_4V_TYPE_AS_UNION(dest, oldsz, data,
1020 COPY_SZ_4V(dest, newsz, save->current[attr]);
1025 GLint sz = save->attrsz[j];
1026 COPY_SZ_4V(dest, sz, data);
1033 save->buffer_ptr = dest;
1034 save->vert_count += save->copied.nr;
1040 * This is called when the size of a vertex attribute changes.
1041 * For example, after seeing one or more glTexCoord2f() calls we
1042 * get a glTexCoord4f() or glTexCoord1f() call.
1045 fixup_vertex(struct gl_context *ctx, GLuint attr,
1046 GLuint sz, GLenum newType)
1048 struct vbo_save_context *save = &vbo_context(ctx)->save;
1050 if (sz > save->attrsz[attr] ||
1051 newType != save->attrtype[attr]) {
1052 /* New size is larger. Need to flush existing vertices and get
1053 * an enlarged vertex format.
1055 upgrade_vertex(ctx, attr, sz);
1057 else if (sz < save->active_sz[attr]) {
1059 const fi_type *id = vbo_get_default_vals_as_union(save->attrtype[attr]);
1061 /* New size is equal or smaller - just need to fill in some
1064 for (i = sz; i <= save->attrsz[attr]; i++)
1065 save->attrptr[attr][i - 1] = id[i - 1];
1068 save->active_sz[attr] = sz;
1073 * Reset the current size of all vertex attributes to the default
1074 * value of 0. This signals that we haven't yet seen any per-vertex
1075 * commands such as glNormal3f() or glTexCoord2f().
1078 reset_vertex(struct gl_context *ctx)
1080 struct vbo_save_context *save = &vbo_context(ctx)->save;
1082 while (save->enabled) {
1083 const int i = u_bit_scan64(&save->enabled);
1084 assert(save->attrsz[i]);
1085 save->attrsz[i] = 0;
1086 save->active_sz[i] = 0;
1089 save->vertex_size = 0;
1094 * If index=0, does glVertexAttrib*() alias glVertex() to emit a vertex?
1095 * It depends on a few things, including whether we're inside or outside
1099 is_vertex_position(const struct gl_context *ctx, GLuint index)
1101 return (index == 0 &&
1102 _mesa_attr_zero_aliases_vertex(ctx) &&
1103 _mesa_inside_dlist_begin_end(ctx));
1108 #define ERROR(err) _mesa_compile_error(ctx, err, __func__);
1111 /* Only one size for each attribute may be active at once. Eg. if
1112 * Color3f is installed/active, then Color4f may not be, even if the
1113 * vertex actually contains 4 color coordinates. This is because the
1114 * 3f version won't otherwise set color[3] to 1.0 -- this is the job
1115 * of the chooser function when switching between Color4f and Color3f.
1117 #define ATTR_UNION(A, N, T, C, V0, V1, V2, V3) \
1119 struct vbo_save_context *save = &vbo_context(ctx)->save; \
1120 int sz = (sizeof(C) / sizeof(GLfloat)); \
1122 if (save->active_sz[A] != N) \
1123 fixup_vertex(ctx, A, N * sz, T); \
1126 C *dest = (C *)save->attrptr[A]; \
1127 if (N>0) dest[0] = V0; \
1128 if (N>1) dest[1] = V1; \
1129 if (N>2) dest[2] = V2; \
1130 if (N>3) dest[3] = V3; \
1131 save->attrtype[A] = T; \
1137 for (i = 0; i < save->vertex_size; i++) \
1138 save->buffer_ptr[i] = save->vertex[i]; \
1140 save->buffer_ptr += save->vertex_size; \
1142 if (++save->vert_count >= save->max_vert) \
1143 wrap_filled_vertex(ctx); \
1147 #define TAG(x) _save_##x
1149 #include "vbo_attrib_tmp.h"
1153 #define MAT( ATTR, N, face, params ) \
1155 if (face != GL_BACK) \
1156 MAT_ATTR( ATTR, N, params ); /* front */ \
1157 if (face != GL_FRONT) \
1158 MAT_ATTR( ATTR + 1, N, params ); /* back */ \
1163 * Save a glMaterial call found between glBegin/End.
1164 * glMaterial calls outside Begin/End are handled in dlist.c.
1166 static void GLAPIENTRY
1167 _save_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
1169 GET_CURRENT_CONTEXT(ctx);
1171 if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
1172 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(face)");
1178 MAT(VBO_ATTRIB_MAT_FRONT_EMISSION, 4, face, params);
1181 MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
1184 MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
1187 MAT(VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params);
1190 if (*params < 0 || *params > ctx->Const.MaxShininess) {
1191 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glMaterial(shininess)");
1194 MAT(VBO_ATTRIB_MAT_FRONT_SHININESS, 1, face, params);
1197 case GL_COLOR_INDEXES:
1198 MAT(VBO_ATTRIB_MAT_FRONT_INDEXES, 3, face, params);
1200 case GL_AMBIENT_AND_DIFFUSE:
1201 MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
1202 MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
1205 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(pname)");
1211 /* Cope with EvalCoord/CallList called within a begin/end object:
1212 * -- Flush current buffer
1213 * -- Fallback to opcodes for the rest of the begin/end object.
1216 dlist_fallback(struct gl_context *ctx)
1218 struct vbo_save_context *save = &vbo_context(ctx)->save;
1220 if (save->vert_count || save->prim_count) {
1221 if (save->prim_count > 0) {
1222 /* Close off in-progress primitive. */
1223 GLint i = save->prim_count - 1;
1224 save->prims[i].count = save->vert_count - save->prims[i].start;
1227 /* Need to replay this display list with loopback,
1228 * unfortunately, otherwise this primitive won't be handled
1231 save->dangling_attr_ref = GL_TRUE;
1233 compile_vertex_list(ctx);
1236 copy_to_current(ctx);
1238 reset_counters(ctx);
1239 if (save->out_of_memory) {
1240 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
1243 _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
1245 ctx->Driver.SaveNeedFlush = GL_FALSE;
1249 static void GLAPIENTRY
1250 _save_EvalCoord1f(GLfloat u)
1252 GET_CURRENT_CONTEXT(ctx);
1253 dlist_fallback(ctx);
1254 CALL_EvalCoord1f(ctx->Save, (u));
1257 static void GLAPIENTRY
1258 _save_EvalCoord1fv(const GLfloat * v)
1260 GET_CURRENT_CONTEXT(ctx);
1261 dlist_fallback(ctx);
1262 CALL_EvalCoord1fv(ctx->Save, (v));
1265 static void GLAPIENTRY
1266 _save_EvalCoord2f(GLfloat u, GLfloat v)
1268 GET_CURRENT_CONTEXT(ctx);
1269 dlist_fallback(ctx);
1270 CALL_EvalCoord2f(ctx->Save, (u, v));
1273 static void GLAPIENTRY
1274 _save_EvalCoord2fv(const GLfloat * v)
1276 GET_CURRENT_CONTEXT(ctx);
1277 dlist_fallback(ctx);
1278 CALL_EvalCoord2fv(ctx->Save, (v));
1281 static void GLAPIENTRY
1282 _save_EvalPoint1(GLint i)
1284 GET_CURRENT_CONTEXT(ctx);
1285 dlist_fallback(ctx);
1286 CALL_EvalPoint1(ctx->Save, (i));
1289 static void GLAPIENTRY
1290 _save_EvalPoint2(GLint i, GLint j)
1292 GET_CURRENT_CONTEXT(ctx);
1293 dlist_fallback(ctx);
1294 CALL_EvalPoint2(ctx->Save, (i, j));
1297 static void GLAPIENTRY
1298 _save_CallList(GLuint l)
1300 GET_CURRENT_CONTEXT(ctx);
1301 dlist_fallback(ctx);
1302 CALL_CallList(ctx->Save, (l));
1305 static void GLAPIENTRY
1306 _save_CallLists(GLsizei n, GLenum type, const GLvoid * v)
1308 GET_CURRENT_CONTEXT(ctx);
1309 dlist_fallback(ctx);
1310 CALL_CallLists(ctx->Save, (n, type, v));
1316 * Called when a glBegin is getting compiled into a display list.
1317 * Updating of ctx->Driver.CurrentSavePrimitive is already taken care of.
1320 vbo_save_NotifyBegin(struct gl_context *ctx, GLenum mode,
1321 bool no_current_update)
1323 struct vbo_save_context *save = &vbo_context(ctx)->save;
1324 const GLuint i = save->prim_count++;
1326 ctx->Driver.CurrentSavePrimitive = mode;
1328 assert(i < save->prim_max);
1329 save->prims[i].mode = mode & VBO_SAVE_PRIM_MODE_MASK;
1330 save->prims[i].begin = 1;
1331 save->prims[i].end = 0;
1332 save->prims[i].start = save->vert_count;
1333 save->prims[i].count = 0;
1335 save->no_current_update = no_current_update;
1337 if (save->out_of_memory) {
1338 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
1341 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt);
1344 /* We need to call vbo_save_SaveFlushVertices() if there's state change */
1345 ctx->Driver.SaveNeedFlush = GL_TRUE;
1349 static void GLAPIENTRY
1352 GET_CURRENT_CONTEXT(ctx);
1353 struct vbo_save_context *save = &vbo_context(ctx)->save;
1354 const GLint i = save->prim_count - 1;
1356 ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
1357 save->prims[i].end = 1;
1358 save->prims[i].count = (save->vert_count - save->prims[i].start);
1360 if (i == (GLint) save->prim_max - 1) {
1361 compile_vertex_list(ctx);
1362 assert(save->copied.nr == 0);
1365 /* Swap out this vertex format while outside begin/end. Any color,
1366 * etc. received between here and the next begin will be compiled
1369 if (save->out_of_memory) {
1370 _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
1373 _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
1378 static void GLAPIENTRY
1379 _save_Begin(GLenum mode)
1381 GET_CURRENT_CONTEXT(ctx);
1383 _mesa_compile_error(ctx, GL_INVALID_OPERATION, "Recursive glBegin");
1387 static void GLAPIENTRY
1388 _save_PrimitiveRestartNV(void)
1390 GET_CURRENT_CONTEXT(ctx);
1391 struct vbo_save_context *save = &vbo_context(ctx)->save;
1393 if (save->prim_count == 0) {
1394 /* We're not inside a glBegin/End pair, so calling glPrimitiverRestartNV
1397 _mesa_compile_error(ctx, GL_INVALID_OPERATION,
1398 "glPrimitiveRestartNV called outside glBegin/End");
1400 /* get current primitive mode */
1401 GLenum curPrim = save->prims[save->prim_count - 1].mode;
1402 bool no_current_update = save->no_current_update;
1404 /* restart primitive */
1405 CALL_End(ctx->CurrentServerDispatch, ());
1406 vbo_save_NotifyBegin(ctx, curPrim, no_current_update);
1411 /* Unlike the functions above, these are to be hooked into the vtxfmt
1412 * maintained in ctx->ListState, active when the list is known or
1413 * suspected to be outside any begin/end primitive.
1414 * Note: OBE = Outside Begin/End
1416 static void GLAPIENTRY
1417 _save_OBE_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
1419 GET_CURRENT_CONTEXT(ctx);
1420 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1422 vbo_save_NotifyBegin(ctx, GL_QUADS, false);
1423 CALL_Vertex2f(dispatch, (x1, y1));
1424 CALL_Vertex2f(dispatch, (x2, y1));
1425 CALL_Vertex2f(dispatch, (x2, y2));
1426 CALL_Vertex2f(dispatch, (x1, y2));
1427 CALL_End(dispatch, ());
1431 static void GLAPIENTRY
1432 _save_OBE_Rectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)
1434 _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1437 static void GLAPIENTRY
1438 _save_OBE_Rectdv(const GLdouble *v1, const GLdouble *v2)
1440 _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1443 static void GLAPIENTRY
1444 _save_OBE_Rectfv(const GLfloat *v1, const GLfloat *v2)
1446 _save_OBE_Rectf(v1[0], v1[1], v2[0], v2[1]);
1449 static void GLAPIENTRY
1450 _save_OBE_Recti(GLint x1, GLint y1, GLint x2, GLint y2)
1452 _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1455 static void GLAPIENTRY
1456 _save_OBE_Rectiv(const GLint *v1, const GLint *v2)
1458 _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1461 static void GLAPIENTRY
1462 _save_OBE_Rects(GLshort x1, GLshort y1, GLshort x2, GLshort y2)
1464 _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1467 static void GLAPIENTRY
1468 _save_OBE_Rectsv(const GLshort *v1, const GLshort *v2)
1470 _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1474 _ensure_draws_fits_in_storage(struct gl_context *ctx, int primcount, int vertcount)
1476 struct vbo_save_context *save = &vbo_context(ctx)->save;
1478 bool realloc_prim = save->prim_count + primcount > save->prim_max;
1479 bool realloc_vert = save->vertex_size && (save->vert_count + vertcount >= save->max_vert);
1481 if (realloc_prim || realloc_vert) {
1482 if (save->vert_count || save->prim_count)
1483 compile_vertex_list(ctx);
1484 realloc_storage(ctx, realloc_prim ? primcount : -1, realloc_vert ? vertcount : -1);
1485 reset_counters(ctx);
1486 assert(save->prim_max);
1491 static void GLAPIENTRY
1492 _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count)
1494 GET_CURRENT_CONTEXT(ctx);
1495 struct gl_vertex_array_object *vao = ctx->Array.VAO;
1496 struct vbo_save_context *save = &vbo_context(ctx)->save;
1499 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1500 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawArrays(mode)");
1504 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawArrays(count<0)");
1508 if (save->out_of_memory)
1511 _ensure_draws_fits_in_storage(ctx, 1, count);
1513 /* Make sure to process any VBO binding changes */
1514 _mesa_update_state(ctx);
1516 _mesa_vao_map_arrays(ctx, vao, GL_MAP_READ_BIT);
1518 vbo_save_NotifyBegin(ctx, mode, true);
1520 for (i = 0; i < count; i++)
1521 _mesa_array_element(ctx, start + i);
1522 CALL_End(ctx->CurrentServerDispatch, ());
1524 _mesa_vao_unmap_arrays(ctx, vao);
1528 static void GLAPIENTRY
1529 _save_OBE_MultiDrawArrays(GLenum mode, const GLint *first,
1530 const GLsizei *count, GLsizei primcount)
1532 GET_CURRENT_CONTEXT(ctx);
1535 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1536 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMultiDrawArrays(mode)");
1540 if (primcount < 0) {
1541 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1542 "glMultiDrawArrays(primcount<0)");
1546 unsigned vertcount = 0;
1547 for (i = 0; i < primcount; i++) {
1549 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1550 "glMultiDrawArrays(count[i]<0)");
1553 vertcount += count[i];
1556 _ensure_draws_fits_in_storage(ctx, primcount, vertcount);
1558 for (i = 0; i < primcount; i++) {
1560 _save_OBE_DrawArrays(mode, first[i], count[i]);
1567 array_element(struct gl_context *ctx,
1568 GLint basevertex, GLuint elt, unsigned index_size_shift)
1570 /* Section 10.3.5 Primitive Restart:
1572 * When one of the *BaseVertex drawing commands specified in section 10.5
1573 * is used, the primitive restart comparison occurs before the basevertex
1574 * offset is added to the array index.
1576 /* If PrimitiveRestart is enabled and the index is the RestartIndex
1577 * then we call PrimitiveRestartNV and return.
1579 if (ctx->Array._PrimitiveRestart[index_size_shift] &&
1580 elt == ctx->Array._RestartIndex[index_size_shift]) {
1581 CALL_PrimitiveRestartNV(ctx->CurrentServerDispatch, ());
1585 _mesa_array_element(ctx, basevertex + elt);
1589 /* Could do better by copying the arrays and element list intact and
1590 * then emitting an indexed prim at runtime.
1592 static void GLAPIENTRY
1593 _save_OBE_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1594 const GLvoid * indices, GLint basevertex)
1596 GET_CURRENT_CONTEXT(ctx);
1597 struct vbo_save_context *save = &vbo_context(ctx)->save;
1598 struct gl_vertex_array_object *vao = ctx->Array.VAO;
1599 struct gl_buffer_object *indexbuf = vao->IndexBufferObj;
1602 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1603 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawElements(mode)");
1607 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawElements(count<0)");
1610 if (type != GL_UNSIGNED_BYTE &&
1611 type != GL_UNSIGNED_SHORT &&
1612 type != GL_UNSIGNED_INT) {
1613 _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawElements(count<0)");
1617 if (save->out_of_memory)
1620 _ensure_draws_fits_in_storage(ctx, 1, count);
1622 /* Make sure to process any VBO binding changes */
1623 _mesa_update_state(ctx);
1625 _mesa_vao_map(ctx, vao, GL_MAP_READ_BIT);
1629 ADD_POINTERS(indexbuf->Mappings[MAP_INTERNAL].Pointer, indices);
1631 vbo_save_NotifyBegin(ctx, mode, true);
1634 case GL_UNSIGNED_BYTE:
1635 for (i = 0; i < count; i++)
1636 array_element(ctx, basevertex, ((GLubyte *) indices)[i], 0);
1638 case GL_UNSIGNED_SHORT:
1639 for (i = 0; i < count; i++)
1640 array_element(ctx, basevertex, ((GLushort *) indices)[i], 1);
1642 case GL_UNSIGNED_INT:
1643 for (i = 0; i < count; i++)
1644 array_element(ctx, basevertex, ((GLuint *) indices)[i], 2);
1647 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawElements(type)");
1651 CALL_End(ctx->CurrentServerDispatch, ());
1653 _mesa_vao_unmap(ctx, vao);
1656 static void GLAPIENTRY
1657 _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type,
1658 const GLvoid * indices)
1660 _save_OBE_DrawElementsBaseVertex(mode, count, type, indices, 0);
1664 static void GLAPIENTRY
1665 _save_OBE_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
1666 GLsizei count, GLenum type,
1667 const GLvoid * indices)
1669 GET_CURRENT_CONTEXT(ctx);
1670 struct vbo_save_context *save = &vbo_context(ctx)->save;
1672 if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1673 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(mode)");
1677 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1678 "glDrawRangeElements(count<0)");
1681 if (type != GL_UNSIGNED_BYTE &&
1682 type != GL_UNSIGNED_SHORT &&
1683 type != GL_UNSIGNED_INT) {
1684 _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(type)");
1688 _mesa_compile_error(ctx, GL_INVALID_VALUE,
1689 "glDrawRangeElements(end < start)");
1693 if (save->out_of_memory)
1696 _save_OBE_DrawElements(mode, count, type, indices);
1700 static void GLAPIENTRY
1701 _save_OBE_MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type,
1702 const GLvoid * const *indices, GLsizei primcount)
1704 GET_CURRENT_CONTEXT(ctx);
1705 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1709 for (i = 0; i < primcount; i++) {
1710 vertcount += count[i];
1712 _ensure_draws_fits_in_storage(ctx, primcount, vertcount);
1714 for (i = 0; i < primcount; i++) {
1716 CALL_DrawElements(dispatch, (mode, count[i], type, indices[i]));
1722 static void GLAPIENTRY
1723 _save_OBE_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count,
1725 const GLvoid * const *indices,
1727 const GLint *basevertex)
1729 GET_CURRENT_CONTEXT(ctx);
1730 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1734 for (i = 0; i < primcount; i++) {
1735 vertcount += count[i];
1737 _ensure_draws_fits_in_storage(ctx, primcount, vertcount);
1739 for (i = 0; i < primcount; i++) {
1741 CALL_DrawElementsBaseVertex(dispatch, (mode, count[i], type,
1750 vtxfmt_init(struct gl_context *ctx)
1752 struct vbo_save_context *save = &vbo_context(ctx)->save;
1753 GLvertexformat *vfmt = &save->vtxfmt;
1755 #define NAME_AE(x) _ae_##x
1756 #define NAME_CALLLIST(x) _save_##x
1757 #define NAME(x) _save_##x
1758 #define NAME_ES(x) _save_##x##ARB
1760 #include "vbo_init_tmp.h"
1765 * Initialize the dispatch table with the VBO functions for display
1769 vbo_initialize_save_dispatch(const struct gl_context *ctx,
1770 struct _glapi_table *exec)
1772 SET_DrawArrays(exec, _save_OBE_DrawArrays);
1773 SET_MultiDrawArrays(exec, _save_OBE_MultiDrawArrays);
1774 SET_DrawElements(exec, _save_OBE_DrawElements);
1775 SET_DrawElementsBaseVertex(exec, _save_OBE_DrawElementsBaseVertex);
1776 SET_DrawRangeElements(exec, _save_OBE_DrawRangeElements);
1777 SET_MultiDrawElementsEXT(exec, _save_OBE_MultiDrawElements);
1778 SET_MultiDrawElementsBaseVertex(exec, _save_OBE_MultiDrawElementsBaseVertex);
1779 SET_Rectf(exec, _save_OBE_Rectf);
1780 SET_Rectd(exec, _save_OBE_Rectd);
1781 SET_Rectdv(exec, _save_OBE_Rectdv);
1782 SET_Rectfv(exec, _save_OBE_Rectfv);
1783 SET_Recti(exec, _save_OBE_Recti);
1784 SET_Rectiv(exec, _save_OBE_Rectiv);
1785 SET_Rects(exec, _save_OBE_Rects);
1786 SET_Rectsv(exec, _save_OBE_Rectsv);
1788 /* Note: other glDraw functins aren't compiled into display lists */
1794 vbo_save_SaveFlushVertices(struct gl_context *ctx)
1796 struct vbo_save_context *save = &vbo_context(ctx)->save;
1798 /* Noop when we are actually active:
1800 if (ctx->Driver.CurrentSavePrimitive <= PRIM_MAX)
1803 if (save->vert_count || save->prim_count)
1804 compile_vertex_list(ctx);
1806 copy_to_current(ctx);
1808 reset_counters(ctx);
1809 ctx->Driver.SaveNeedFlush = GL_FALSE;
1814 * Called from glNewList when we're starting to compile a display list.
1817 vbo_save_NewList(struct gl_context *ctx, GLuint list, GLenum mode)
1819 struct vbo_save_context *save = &vbo_context(ctx)->save;
1824 if (!save->prim_store)
1825 save->prim_store = alloc_prim_store(0);
1827 if (!save->vertex_store)
1828 save->vertex_store = alloc_vertex_store(ctx, 0);
1830 save->buffer_ptr = save->vertex_store->buffer_in_ram + save->vertex_store->used;
1833 reset_counters(ctx);
1834 ctx->Driver.SaveNeedFlush = GL_FALSE;
1839 * Called from glEndList when we're finished compiling a display list.
1842 vbo_save_EndList(struct gl_context *ctx)
1844 struct vbo_save_context *save = &vbo_context(ctx)->save;
1846 /* EndList called inside a (saved) Begin/End pair?
1848 if (_mesa_inside_dlist_begin_end(ctx)) {
1849 if (save->prim_count > 0) {
1850 GLint i = save->prim_count - 1;
1851 ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
1852 save->prims[i].end = 0;
1853 save->prims[i].count = save->vert_count - save->prims[i].start;
1856 /* Make sure this vertex list gets replayed by the "loopback"
1859 save->dangling_attr_ref = GL_TRUE;
1860 vbo_save_SaveFlushVertices(ctx);
1862 /* Swap out this vertex format while outside begin/end. Any color,
1863 * etc. received between here and the next begin will be compiled
1866 _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
1869 assert(save->vertex_size == 0);
1873 * Called during context creation/init.
1876 current_init(struct gl_context *ctx)
1878 struct vbo_save_context *save = &vbo_context(ctx)->save;
1881 for (i = VBO_ATTRIB_POS; i <= VBO_ATTRIB_GENERIC15; i++) {
1882 const GLuint j = i - VBO_ATTRIB_POS;
1883 assert(j < VERT_ATTRIB_MAX);
1884 save->currentsz[i] = &ctx->ListState.ActiveAttribSize[j];
1885 save->current[i] = (fi_type *) ctx->ListState.CurrentAttrib[j];
1888 for (i = VBO_ATTRIB_FIRST_MATERIAL; i <= VBO_ATTRIB_LAST_MATERIAL; i++) {
1889 const GLuint j = i - VBO_ATTRIB_FIRST_MATERIAL;
1890 assert(j < MAT_ATTRIB_MAX);
1891 save->currentsz[i] = &ctx->ListState.ActiveMaterialSize[j];
1892 save->current[i] = (fi_type *) ctx->ListState.CurrentMaterial[j];
1898 * Initialize the display list compiler. Called during context creation.
1901 vbo_save_api_init(struct vbo_save_context *save)
1903 struct gl_context *ctx = gl_context_from_vbo_save(save);
1907 _mesa_noop_vtxfmt_init(ctx, &save->vtxfmt_noop);