vbo/dlist: don't force list compilation if out of prim space
[platform/upstream/mesa.git] / src / mesa / vbo / vbo_save_api.c
1 /**************************************************************************
2
3 Copyright 2002-2008 VMware, Inc.
4
5 All Rights Reserved.
6
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:
13
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
16 Software.
17
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.
25
26 **************************************************************************/
27
28 /*
29  * Authors:
30  *   Keith Whitwell <keithw@vmware.com>
31  */
32
33
34
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
38  * cached on hardware.
39  *
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,
44  * End).
45  *
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.
49  *
50  * The other case where fixup is required is when a vertex attribute
51  * is introduced in the middle of a primitive.  Eg:
52  *  Begin(Lines)
53  *  TexCoord1f()           Vertex2f()
54  *  TexCoord1f() Color3f() Vertex2f()
55  *  End()
56  *
57  *  If the current value of Color isn't known at compile-time, this
58  *  primitive will require fixup.
59  *
60  *
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.
64  *
65  * This could be improved to fallback only when a mix of EvalCoord and
66  * Vertex commands are issued within a single primitive.
67  */
68
69
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"
87
88 #include "gallium/include/pipe/p_state.h"
89
90 #include "vbo_noop.h"
91 #include "vbo_private.h"
92
93
94 #ifdef ERROR
95 #undef ERROR
96 #endif
97
98 /* An interesting VBO number/name to help with debugging */
99 #define VBO_BUF_ID  12345
100
101 static void GLAPIENTRY
102 _save_Materialfv(GLenum face, GLenum pname, const GLfloat *params);
103
104 static void GLAPIENTRY
105 _save_EvalCoord1f(GLfloat u);
106
107 static void GLAPIENTRY
108 _save_EvalCoord2f(GLfloat u, GLfloat v);
109
110 /*
111  * NOTE: Old 'parity' issue is gone, but copying can still be
112  * wrong-footed on replay.
113  */
114 static GLuint
115 copy_vertices(struct gl_context *ctx,
116               const struct vbo_save_vertex_list *node,
117               const fi_type * src_buffer)
118 {
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;
124
125    if (prim->end)
126       return 0;
127
128    return vbo_copy_vertices(ctx, prim->mode, prim->start, &prim->count,
129                             prim->begin, sz, true, dst, src);
130 }
131
132
133 static struct vbo_save_vertex_store *
134 alloc_vertex_store(struct gl_context *ctx, int vertex_count)
135 {
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);
139
140    int size = MAX2(vertex_count * save->vertex_size, VBO_SAVE_BUFFER_SIZE);
141
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
146     * buffers:
147     */
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;
151
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);
155    }
156
157    vertex_store->used = 0;
158
159    return vertex_store;
160 }
161
162
163 static void
164 free_vertex_store(struct gl_context *ctx,
165                   struct vbo_save_vertex_store *vertex_store)
166 {
167    free(vertex_store->buffer_in_ram);
168    free(vertex_store);
169 }
170
171
172 static struct vbo_save_primitive_store *
173 realloc_prim_store(struct vbo_save_primitive_store *store, int prim_count)
174 {
175    if (store == NULL)
176       store = CALLOC_STRUCT(vbo_save_primitive_store);
177    uint32_t old_size = store->size;
178    store->size = MAX3(store->size, prim_count, VBO_SAVE_PRIM_SIZE);
179    store->prims = realloc(store->prims, store->size * sizeof(struct _mesa_prim));
180    memset(&store->prims[old_size], 0, (store->size - old_size) * sizeof(struct _mesa_prim));
181    store->used = 0;
182    return store;
183 }
184
185
186 static void
187 reset_counters(struct gl_context *ctx)
188 {
189    struct vbo_save_context *save = &vbo_context(ctx)->save;
190
191    save->buffer_map = save->vertex_store->buffer_in_ram + save->vertex_store->used;
192
193    assert(save->buffer_map == save->buffer_ptr);
194
195    if (save->vertex_size)
196       save->max_vert = (save->vertex_store->buffer_in_ram_size / sizeof(float) - save->vertex_store->used) /
197                         save->vertex_size;
198    else
199       save->max_vert = 0;
200
201    save->prim_store->used = 0;
202    save->vert_count = 0;
203    save->dangling_attr_ref = GL_FALSE;
204 }
205
206 /**
207  * For a list of prims, try merging prims that can just be extensions of the
208  * previous prim.
209  */
210 static void
211 merge_prims(struct gl_context *ctx, struct _mesa_prim *prim_list,
212             GLuint *prim_count)
213 {
214    GLuint i;
215    struct _mesa_prim *prev_prim = prim_list;
216
217    for (i = 1; i < *prim_count; i++) {
218       struct _mesa_prim *this_prim = prim_list + i;
219
220       vbo_try_prim_conversion(&this_prim->mode, &this_prim->count);
221
222       if (vbo_merge_draws(ctx, true,
223                           prev_prim->mode, this_prim->mode,
224                           prev_prim->start, this_prim->start,
225                           &prev_prim->count, this_prim->count,
226                           prev_prim->basevertex, this_prim->basevertex,
227                           &prev_prim->end,
228                           this_prim->begin, this_prim->end)) {
229          /* We've found a prim that just extend the previous one.  Tack it
230           * onto the previous one, and let this primitive struct get dropped.
231           */
232          continue;
233       }
234
235       /* If any previous primitives have been dropped, then we need to copy
236        * this later one into the next available slot.
237        */
238       prev_prim++;
239       if (prev_prim != this_prim)
240          *prev_prim = *this_prim;
241    }
242
243    *prim_count = prev_prim - prim_list + 1;
244 }
245
246
247 /**
248  * Convert GL_LINE_LOOP primitive into GL_LINE_STRIP so that drivers
249  * don't have to worry about handling the _mesa_prim::begin/end flags.
250  * See https://bugs.freedesktop.org/show_bug.cgi?id=81174
251  */
252 static void
253 convert_line_loop_to_strip(struct vbo_save_context *save,
254                            struct vbo_save_vertex_list *node)
255 {
256    struct _mesa_prim *prim = &node->cold->prims[node->cold->prim_count - 1];
257
258    assert(prim->mode == GL_LINE_LOOP);
259
260    if (prim->end) {
261       /* Copy the 0th vertex to end of the buffer and extend the
262        * vertex count by one to finish the line loop.
263        */
264       const GLuint sz = save->vertex_size;
265       /* 0th vertex: */
266       const fi_type *src = save->buffer_map + prim->start * sz;
267       /* end of buffer: */
268       fi_type *dst = save->buffer_map + (prim->start + prim->count) * sz;
269
270       memcpy(dst, src, sz * sizeof(float));
271
272       prim->count++;
273       node->cold->vertex_count++;
274       save->vert_count++;
275       save->buffer_ptr += sz;
276       save->vertex_store->used += sz;
277    }
278
279    if (!prim->begin) {
280       /* Drawing the second or later section of a long line loop.
281        * Skip the 0th vertex.
282        */
283       prim->start++;
284       prim->count--;
285    }
286
287    prim->mode = GL_LINE_STRIP;
288 }
289
290
291 /* Compare the present vao if it has the same setup. */
292 static bool
293 compare_vao(gl_vertex_processing_mode mode,
294             const struct gl_vertex_array_object *vao,
295             const struct gl_buffer_object *bo, GLintptr buffer_offset,
296             GLuint stride, GLbitfield64 vao_enabled,
297             const GLubyte size[VBO_ATTRIB_MAX],
298             const GLenum16 type[VBO_ATTRIB_MAX],
299             const GLuint offset[VBO_ATTRIB_MAX])
300 {
301    if (!vao)
302       return false;
303
304    /* If the enabled arrays are not the same we are not equal. */
305    if (vao_enabled != vao->Enabled)
306       return false;
307
308    /* Check the buffer binding at 0 */
309    if (vao->BufferBinding[0].BufferObj != bo)
310       return false;
311    /* BufferBinding[0].Offset != buffer_offset is checked per attribute */
312    if (vao->BufferBinding[0].Stride != stride)
313       return false;
314    assert(vao->BufferBinding[0].InstanceDivisor == 0);
315
316    /* Retrieve the mapping from VBO_ATTRIB to VERT_ATTRIB space */
317    const GLubyte *const vao_to_vbo_map = _vbo_attribute_alias_map[mode];
318
319    /* Now check the enabled arrays */
320    GLbitfield mask = vao_enabled;
321    while (mask) {
322       const int attr = u_bit_scan(&mask);
323       const unsigned char vbo_attr = vao_to_vbo_map[attr];
324       const GLenum16 tp = type[vbo_attr];
325       const GLintptr off = offset[vbo_attr] + buffer_offset;
326       const struct gl_array_attributes *attrib = &vao->VertexAttrib[attr];
327       if (attrib->RelativeOffset + vao->BufferBinding[0].Offset != off)
328          return false;
329       if (attrib->Format.Type != tp)
330          return false;
331       if (attrib->Format.Size != size[vbo_attr])
332          return false;
333       assert(attrib->Format.Format == GL_RGBA);
334       assert(attrib->Format.Normalized == GL_FALSE);
335       assert(attrib->Format.Integer == vbo_attrtype_to_integer_flag(tp));
336       assert(attrib->Format.Doubles == vbo_attrtype_to_double_flag(tp));
337       assert(attrib->BufferBindingIndex == 0);
338    }
339
340    return true;
341 }
342
343
344 /* Create or reuse the vao for the vertex processing mode. */
345 static void
346 update_vao(struct gl_context *ctx,
347            gl_vertex_processing_mode mode,
348            struct gl_vertex_array_object **vao,
349            struct gl_buffer_object *bo, GLintptr buffer_offset,
350            GLuint stride, GLbitfield64 vbo_enabled,
351            const GLubyte size[VBO_ATTRIB_MAX],
352            const GLenum16 type[VBO_ATTRIB_MAX],
353            const GLuint offset[VBO_ATTRIB_MAX])
354 {
355    /* Compute the bitmasks of vao_enabled arrays */
356    GLbitfield vao_enabled = _vbo_get_vao_enabled_from_vbo(mode, vbo_enabled);
357
358    /*
359     * Check if we can possibly reuse the exisiting one.
360     * In the long term we should reset them when something changes.
361     */
362    if (compare_vao(mode, *vao, bo, buffer_offset, stride,
363                    vao_enabled, size, type, offset))
364       return;
365
366    /* The initial refcount is 1 */
367    _mesa_reference_vao(ctx, vao, NULL);
368    *vao = _mesa_new_vao(ctx, ~((GLuint)0));
369
370    /*
371     * assert(stride <= ctx->Const.MaxVertexAttribStride);
372     * MaxVertexAttribStride is not set for drivers that does not
373     * expose GL 44 or GLES 31.
374     */
375
376    /* Bind the buffer object at binding point 0 */
377    _mesa_bind_vertex_buffer(ctx, *vao, 0, bo, buffer_offset, stride, false,
378                             false);
379
380    /* Retrieve the mapping from VBO_ATTRIB to VERT_ATTRIB space
381     * Note that the position/generic0 aliasing is done in the VAO.
382     */
383    const GLubyte *const vao_to_vbo_map = _vbo_attribute_alias_map[mode];
384    /* Now set the enable arrays */
385    GLbitfield mask = vao_enabled;
386    while (mask) {
387       const int vao_attr = u_bit_scan(&mask);
388       const GLubyte vbo_attr = vao_to_vbo_map[vao_attr];
389       assert(offset[vbo_attr] <= ctx->Const.MaxVertexAttribRelativeOffset);
390
391       _vbo_set_attrib_format(ctx, *vao, vao_attr, buffer_offset,
392                              size[vbo_attr], type[vbo_attr], offset[vbo_attr]);
393       _mesa_vertex_attrib_binding(ctx, *vao, vao_attr, 0);
394    }
395    _mesa_enable_vertex_array_attribs(ctx, *vao, vao_enabled);
396    assert(vao_enabled == (*vao)->Enabled);
397    assert((vao_enabled & ~(*vao)->VertexAttribBufferMask) == 0);
398
399    /* Finalize and freeze the VAO */
400    _mesa_set_vao_immutable(ctx, *vao);
401 }
402
403
404 static void
405 realloc_storage(struct gl_context *ctx, int prim_count, int vertex_count)
406 {
407    struct vbo_save_context *save = &vbo_context(ctx)->save;
408    if (vertex_count >= 0) {
409       /* Release old reference:
410        */
411       free_vertex_store(ctx, save->vertex_store);
412       save->vertex_store = NULL;
413       /* When we have a new vbo, we will for sure need a new vao */
414       for (gl_vertex_processing_mode vpm = 0; vpm < VP_MODE_MAX; ++vpm)
415          _mesa_reference_vao(ctx, &save->VAO[vpm], NULL);
416
417       /* Allocate and map new store:
418        */
419       save->vertex_store = alloc_vertex_store(ctx, vertex_count);
420       save->buffer_ptr = save->vertex_store->buffer_in_ram + save->vertex_store->used;
421       save->out_of_memory = save->buffer_ptr == NULL;
422    }
423
424    if (prim_count >= 0)
425       save->prim_store = realloc_prim_store(save->prim_store, prim_count);
426 }
427
428 struct vertex_key {
429    unsigned vertex_size;
430    fi_type *vertex_attributes;
431 };
432
433 static uint32_t _hash_vertex_key(const void *key)
434 {
435    struct vertex_key *k = (struct vertex_key*)key;
436    unsigned sz = k->vertex_size;
437    assert(sz);
438    return _mesa_hash_data(k->vertex_attributes, sz * sizeof(float));
439 }
440
441 static bool _compare_vertex_key(const void *key1, const void *key2)
442 {
443    struct vertex_key *k1 = (struct vertex_key*)key1;
444    struct vertex_key *k2 = (struct vertex_key*)key2;
445    /* All the compared vertices are going to be drawn with the same VAO,
446     * so we can compare the attributes. */
447    assert (k1->vertex_size == k2->vertex_size);
448    return memcmp(k1->vertex_attributes,
449                  k2->vertex_attributes,
450                  k1->vertex_size * sizeof(float)) == 0;
451 }
452
453 static void _free_entry(struct hash_entry *entry)
454 {
455    free((void*)entry->key);
456 }
457
458 /* Add vertex to the vertex buffer and return its index. If this vertex is a duplicate
459  * of an existing vertex, return the original index instead.
460  */
461 static uint32_t
462 add_vertex(struct vbo_save_context *save, struct hash_table *hash_to_index,
463            uint32_t index, fi_type *new_buffer, uint32_t *max_index)
464 {
465    /* If vertex deduplication is disabled return the original index. */
466    if (!hash_to_index)
467       return index;
468
469    fi_type *vert = save->buffer_map + save->vertex_size * index;
470
471    struct vertex_key *key = malloc(sizeof(struct vertex_key));
472    key->vertex_size = save->vertex_size;
473    key->vertex_attributes = vert;
474
475    struct hash_entry *entry = _mesa_hash_table_search(hash_to_index, key);
476    if (entry) {
477       free(key);
478       /* We found an existing vertex with the same hash, return its index. */
479       return (uintptr_t) entry->data;
480    } else {
481       /* This is a new vertex. Determine a new index and copy its attributes to the vertex
482        * buffer. Note that 'new_buffer' is created at each list compilation so we write vertices
483        * starting at index 0.
484        */
485       uint32_t n = _mesa_hash_table_num_entries(hash_to_index);
486       *max_index = MAX2(n, *max_index);
487
488       memcpy(&new_buffer[save->vertex_size * n],
489              vert,
490              save->vertex_size * sizeof(fi_type));
491
492       _mesa_hash_table_insert(hash_to_index, key, (void*)(uintptr_t)(n));
493
494       /* The index buffer is shared between list compilations, so add the base index to get
495        * the final index.
496        */
497       return n;
498    }
499 }
500
501
502 /**
503  * Insert the active immediate struct onto the display list currently
504  * being built.
505  */
506 static void
507 compile_vertex_list(struct gl_context *ctx)
508 {
509    struct vbo_save_context *save = &vbo_context(ctx)->save;
510    struct vbo_save_vertex_list *node;
511
512    /* Allocate space for this structure in the display list currently
513     * being compiled.
514     */
515    node = (struct vbo_save_vertex_list *)
516       _mesa_dlist_alloc_vertex_list(ctx, !save->dangling_attr_ref && !save->no_current_update);
517
518    if (!node)
519       return;
520
521    memset(node, 0, sizeof(struct vbo_save_vertex_list));
522    node->cold = calloc(1, sizeof(*node->cold));
523
524    /* Make sure the pointer is aligned to the size of a pointer */
525    assert((GLintptr) node % sizeof(void *) == 0);
526
527    const GLsizei stride = save->vertex_size*sizeof(GLfloat);
528
529    node->cold->vertex_count = save->vert_count;
530    node->cold->wrap_count = save->copied.nr;
531    node->cold->prims = malloc(sizeof(struct _mesa_prim) * save->prim_store->used);
532    memcpy(node->cold->prims, save->prim_store->prims, sizeof(struct _mesa_prim) * save->prim_store->used);
533    node->cold->ib.obj = NULL;
534    node->cold->prim_count = save->prim_store->used;
535
536    if (save->no_current_update) {
537       node->cold->current_data = NULL;
538    }
539    else {
540       GLuint current_size = save->vertex_size - save->attrsz[0];
541       node->cold->current_data = NULL;
542
543       if (current_size) {
544          node->cold->current_data = malloc(current_size * sizeof(GLfloat));
545          if (node->cold->current_data) {
546             const char *buffer = (const char *)save->buffer_map;
547             unsigned attr_offset = save->attrsz[0] * sizeof(GLfloat);
548             unsigned vertex_offset = 0;
549
550             if (node->cold->vertex_count)
551                vertex_offset = (node->cold->vertex_count - 1) * stride;
552
553             memcpy(node->cold->current_data, buffer + vertex_offset + attr_offset,
554                    current_size * sizeof(GLfloat));
555          } else {
556             _mesa_error(ctx, GL_OUT_OF_MEMORY, "Current value allocation");
557          }
558       }
559    }
560
561    assert(save->attrsz[VBO_ATTRIB_POS] != 0 || node->cold->vertex_count == 0);
562
563    if (save->dangling_attr_ref)
564       ctx->ListState.Current.UseLoopback = true;
565
566    save->vertex_store->used += save->vertex_size * node->cold->vertex_count;
567
568    /* Copy duplicated vertices
569     */
570    save->copied.nr = copy_vertices(ctx, node, save->buffer_map);
571
572    if (node->cold->prims[node->cold->prim_count - 1].mode == GL_LINE_LOOP) {
573       convert_line_loop_to_strip(save, node);
574    }
575
576    merge_prims(ctx, node->cold->prims, &node->cold->prim_count);
577
578    GLintptr buffer_offset = 0;
579    GLuint start_offset = 0;
580
581    /* Create an index buffer. */
582    node->cold->min_index = node->cold->max_index = 0;
583    if (save->vert_count == 0 || node->cold->prim_count == 0)
584       goto end;
585
586    /* We won't modify node->prims, so use a const alias to avoid unintended
587     * writes to it. */
588    const struct _mesa_prim *original_prims = node->cold->prims;
589
590    int end = original_prims[node->cold->prim_count - 1].start +
591              original_prims[node->cold->prim_count - 1].count;
592    int total_vert_count = end - original_prims[0].start;
593
594    node->cold->min_index = node->cold->prims[0].start;
595    node->cold->max_index = end - 1;
596
597    /* Estimate for the worst case: all prims are line strips (the +1 is because
598     * wrap_buffers may call use but the last primitive may not be complete) */
599    int max_indices_count = MAX2(total_vert_count * 2 - (node->cold->prim_count * 2) + 1,
600                                 total_vert_count);
601
602    int size = max_indices_count * sizeof(uint32_t);
603    uint32_t* indices = (uint32_t*) malloc(size);
604    struct _mesa_prim *merged_prims = NULL;
605
606    int idx = 0;
607    struct hash_table *vertex_to_index = NULL;
608    fi_type *temp_vertices_buffer = NULL;
609
610    /* The loopback replay code doesn't use the index buffer, so we can't
611     * dedup vertices in this case.
612     */
613    if (!ctx->ListState.Current.UseLoopback) {
614       vertex_to_index = _mesa_hash_table_create(NULL, _hash_vertex_key, _compare_vertex_key);
615       temp_vertices_buffer = malloc(save->vertex_store->buffer_in_ram_size);
616    }
617
618    uint32_t max_index = 0;
619
620    int last_valid_prim = -1;
621    /* Construct indices array. */
622    for (unsigned i = 0; i < node->cold->prim_count; i++) {
623       assert(original_prims[i].basevertex == 0);
624       GLubyte mode = original_prims[i].mode;
625
626       int vertex_count = original_prims[i].count;
627       if (!vertex_count) {
628          continue;
629       }
630
631       /* Line strips may get converted to lines */
632       if (mode == GL_LINE_STRIP)
633          mode = GL_LINES;
634
635       /* If 2 consecutive prims use the same mode => merge them. */
636       bool merge_prims = last_valid_prim >= 0 &&
637                          mode == merged_prims[last_valid_prim].mode &&
638                          mode != GL_LINE_LOOP && mode != GL_TRIANGLE_FAN &&
639                          mode != GL_QUAD_STRIP && mode != GL_POLYGON &&
640                          mode != GL_PATCHES;
641
642       /* To be able to merge consecutive triangle strips we need to insert
643        * a degenerate triangle.
644        */
645       if (merge_prims &&
646           mode == GL_TRIANGLE_STRIP) {
647          /* Insert a degenerate triangle */
648          assert(merged_prims[last_valid_prim].mode == GL_TRIANGLE_STRIP);
649          unsigned tri_count = merged_prims[last_valid_prim].count - 2;
650
651          indices[idx] = indices[idx - 1];
652          indices[idx + 1] = add_vertex(save, vertex_to_index, original_prims[i].start,
653                                        temp_vertices_buffer, &max_index);
654          idx += 2;
655          merged_prims[last_valid_prim].count += 2;
656
657          if (tri_count % 2) {
658             /* Add another index to preserve winding order */
659             indices[idx++] = add_vertex(save, vertex_to_index, original_prims[i].start,
660                                         temp_vertices_buffer, &max_index);
661             merged_prims[last_valid_prim].count++;
662          }
663       }
664
665       int start = idx;
666
667       /* Convert line strips to lines if it'll allow if the previous
668        * prim mode is GL_LINES (so merge_prims is true) or if the next
669        * primitive mode is GL_LINES or GL_LINE_LOOP.
670        */
671       if (original_prims[i].mode == GL_LINE_STRIP &&
672           (merge_prims ||
673            (i < node->cold->prim_count - 1 &&
674             (original_prims[i + 1].mode == GL_LINE_STRIP ||
675              original_prims[i + 1].mode == GL_LINES)))) {
676          for (unsigned j = 0; j < vertex_count; j++) {
677             indices[idx++] = add_vertex(save, vertex_to_index, original_prims[i].start + j,
678                                         temp_vertices_buffer, &max_index);
679             /* Repeat all but the first/last indices. */
680             if (j && j != vertex_count - 1) {
681                indices[idx++] = add_vertex(save, vertex_to_index, original_prims[i].start + j,
682                                            temp_vertices_buffer, &max_index);
683             }
684          }
685       } else {
686          /* We didn't convert to LINES, so restore the original mode */
687          mode = original_prims[i].mode;
688
689          for (unsigned j = 0; j < vertex_count; j++) {
690             indices[idx++] = add_vertex(save, vertex_to_index, original_prims[i].start + j,
691                                         temp_vertices_buffer, &max_index);
692          }
693       }
694
695       if (merge_prims) {
696          /* Update vertex count. */
697          merged_prims[last_valid_prim].count += idx - start;
698       } else {
699          /* Keep this primitive */
700          last_valid_prim += 1;
701          assert(last_valid_prim <= i);
702          merged_prims = realloc(merged_prims, (1 + last_valid_prim) * sizeof(struct _mesa_prim));
703          merged_prims[last_valid_prim] = original_prims[i];
704          merged_prims[last_valid_prim].start = start;
705          merged_prims[last_valid_prim].count = idx - start;
706       }
707       merged_prims[last_valid_prim].mode = mode;
708    }
709
710    assert(idx > 0 && idx <= max_indices_count);
711
712    unsigned merged_prim_count = last_valid_prim + 1;
713    node->cold->ib.ptr = NULL;
714    node->cold->ib.count = idx;
715    node->cold->ib.index_size_shift = (GL_UNSIGNED_INT - GL_UNSIGNED_BYTE) >> 1;
716
717    /* How many bytes do we need to store the indices and the vertices */
718    total_vert_count = vertex_to_index ? (max_index + 1) : idx;
719    unsigned total_bytes_needed = idx * sizeof(uint32_t) +
720                                  total_vert_count * save->vertex_size * sizeof(fi_type);
721
722    const GLintptr old_offset = save->VAO[0] ?
723       save->VAO[0]->BufferBinding[0].Offset + save->VAO[0]->VertexAttrib[VERT_ATTRIB_POS].RelativeOffset : 0;
724    if (old_offset != save->current_bo_bytes_used && stride > 0) {
725       GLintptr offset_diff = save->current_bo_bytes_used - old_offset;
726       while (offset_diff > 0 &&
727              save->current_bo_bytes_used < save->current_bo->Size &&
728              offset_diff % stride != 0) {
729          save->current_bo_bytes_used++;
730          offset_diff = save->current_bo_bytes_used - old_offset;
731       }
732    }
733    buffer_offset = save->current_bo_bytes_used;
734
735    /* Can we reuse the previous bo or should we allocate a new one? */
736    int available_bytes = save->current_bo ? save->current_bo->Size - save->current_bo_bytes_used : 0;
737    if (total_bytes_needed > available_bytes) {
738       if (save->current_bo)
739          _mesa_reference_buffer_object(ctx, &save->current_bo, NULL);
740       save->current_bo = ctx->Driver.NewBufferObject(ctx, VBO_BUF_ID + 1);
741       bool success = ctx->Driver.BufferData(ctx,
742                                             GL_ELEMENT_ARRAY_BUFFER_ARB,
743                                             MAX2(total_bytes_needed, VBO_SAVE_BUFFER_SIZE * sizeof(uint32_t)),
744                                             NULL,
745                                             GL_STATIC_DRAW_ARB, GL_MAP_WRITE_BIT,
746                                             save->current_bo);
747       if (!success) {
748          _mesa_reference_buffer_object(ctx, &save->current_bo, NULL);
749          _mesa_error(ctx, GL_OUT_OF_MEMORY, "IB allocation");
750       } else {
751          save->current_bo_bytes_used = 0;
752          available_bytes = save->current_bo->Size;
753       }
754       buffer_offset = 0;
755    } else {
756       assert(old_offset <= buffer_offset);
757       const GLintptr offset_diff = buffer_offset - old_offset;
758       if (offset_diff > 0 && stride > 0 && offset_diff % stride == 0) {
759          /* The vertex size is an exact multiple of the buffer offset.
760           * This means that we can use zero-based vertex attribute pointers
761           * and specify the start of the primitive with the _mesa_prim::start
762           * field.  This results in issuing several draw calls with identical
763           * vertex attribute information.  This can result in fewer state
764           * changes in drivers.  In particular, the Gallium CSO module will
765           * filter out redundant vertex buffer changes.
766           */
767          /* We cannot immediately update the primitives as some methods below
768           * still need the uncorrected start vertices
769           */
770          start_offset = offset_diff/stride;
771          assert(old_offset == buffer_offset - offset_diff);
772          buffer_offset = old_offset;
773       }
774
775       /* Correct the primitive starts, we can only do this here as copy_vertices
776        * and convert_line_loop_to_strip above consume the uncorrected starts.
777        * On the other hand the _vbo_loopback_vertex_list call below needs the
778        * primitives to be corrected already.
779        */
780       for (unsigned i = 0; i < node->cold->prim_count; i++) {
781          node->cold->prims[i].start += start_offset;
782       }
783       /* start_offset shifts vertices (so v[0] becomes v[start_offset]), so we have
784        * to apply this transformation to all indices and max_index.
785        */
786       for (unsigned i = 0; i < idx; i++)
787          indices[i] += start_offset;
788       max_index += start_offset;
789    }
790
791    _mesa_reference_buffer_object(ctx, &node->cold->ib.obj, save->current_bo);
792
793    /* Upload the vertices first (see buffer_offset) */
794    ctx->Driver.BufferSubData(ctx,
795                              save->current_bo_bytes_used,
796                              total_vert_count * save->vertex_size * sizeof(fi_type),
797                              vertex_to_index ? temp_vertices_buffer : save->buffer_map,
798                              node->cold->ib.obj);
799    save->current_bo_bytes_used += total_vert_count * save->vertex_size * sizeof(fi_type);
800
801   if (vertex_to_index) {
802       _mesa_hash_table_destroy(vertex_to_index, _free_entry);
803       free(temp_vertices_buffer);
804    }
805
806    /* Since we're append the indices to an existing buffer, we need to adjust the start value of each
807     * primitive (not the indices themselves). */
808    save->current_bo_bytes_used += align(save->current_bo_bytes_used, 4) - save->current_bo_bytes_used;
809    int indices_offset = save->current_bo_bytes_used / 4;
810    for (int i = 0; i < merged_prim_count; i++) {
811       merged_prims[i].start += indices_offset;
812    }
813
814    /* Then upload the indices. */
815    if (node->cold->ib.obj) {
816       ctx->Driver.BufferSubData(ctx,
817                                 save->current_bo_bytes_used,
818                                 idx * sizeof(uint32_t),
819                                 indices,
820                                 node->cold->ib.obj);
821       save->current_bo_bytes_used += idx * sizeof(uint32_t);
822    } else {
823       node->cold->vertex_count = 0;
824       node->cold->prim_count = 0;
825    }
826
827    /* Prepare for DrawGallium */
828    memset(&node->merged.info, 0, sizeof(struct pipe_draw_info));
829    /* The other info fields will be updated in vbo_save_playback_vertex_list */
830    node->merged.info.index_size = 4;
831    node->merged.info.instance_count = 1;
832    node->merged.info.index.gl_bo = node->cold->ib.obj;
833    if (merged_prim_count == 1) {
834       node->merged.info.mode = merged_prims[0].mode;
835       node->merged.start_count.start = merged_prims[0].start;
836       node->merged.start_count.count = merged_prims[0].count;
837       node->merged.start_count.index_bias = 0;
838       node->merged.mode = NULL;
839    } else {
840       node->merged.mode = malloc(merged_prim_count * sizeof(unsigned char));
841       node->merged.start_counts = malloc(merged_prim_count * sizeof(struct pipe_draw_start_count_bias));
842       for (unsigned i = 0; i < merged_prim_count; i++) {
843          node->merged.start_counts[i].start = merged_prims[i].start;
844          node->merged.start_counts[i].count = merged_prims[i].count;
845          node->merged.start_counts[i].index_bias = 0;
846          node->merged.mode[i] = merged_prims[i].mode;
847       }
848    }
849    node->merged.num_draws = merged_prim_count;
850    if (node->merged.num_draws > 1) {
851       bool same_mode = true;
852       for (unsigned i = 1; i < node->merged.num_draws && same_mode; i++) {
853          same_mode = node->merged.mode[i] == node->merged.mode[0];
854       }
855       if (same_mode) {
856          /* All primitives use the same mode, so we can simplify a bit */
857          node->merged.info.mode = node->merged.mode[0];
858          free(node->merged.mode);
859          node->merged.mode = NULL;
860       }
861    }
862
863    free(indices);
864    free(merged_prims);
865
866 end:
867
868    if (!save->current_bo) {
869       save->current_bo = ctx->Driver.NewBufferObject(ctx, VBO_BUF_ID + 1);
870       bool success = ctx->Driver.BufferData(ctx,
871                                             GL_ELEMENT_ARRAY_BUFFER_ARB,
872                                             VBO_SAVE_BUFFER_SIZE * sizeof(uint32_t),
873                                             NULL,
874                                             GL_STATIC_DRAW_ARB, GL_MAP_WRITE_BIT,
875                                             save->current_bo);
876    }
877
878    GLuint offsets[VBO_ATTRIB_MAX];
879    for (unsigned i = 0, offset = 0; i < VBO_ATTRIB_MAX; ++i) {
880       offsets[i] = offset;
881       offset += save->attrsz[i] * sizeof(GLfloat);
882    }
883    /* Create a pair of VAOs for the possible VERTEX_PROCESSING_MODEs
884     * Note that this may reuse the previous one of possible.
885     */
886    for (gl_vertex_processing_mode vpm = VP_MODE_FF; vpm < VP_MODE_MAX; ++vpm) {
887       /* create or reuse the vao */
888       update_vao(ctx, vpm, &save->VAO[vpm],
889                  save->current_bo, buffer_offset, stride,
890                  save->enabled, save->attrsz, save->attrtype, offsets);
891       /* Reference the vao in the dlist */
892       node->VAO[vpm] = NULL;
893       _mesa_reference_vao(ctx, &node->VAO[vpm], save->VAO[vpm]);
894    }
895
896
897    /* Deal with GL_COMPILE_AND_EXECUTE:
898     */
899    if (ctx->ExecuteFlag) {
900       struct _glapi_table *dispatch = GET_DISPATCH();
901
902       _glapi_set_dispatch(ctx->Exec);
903
904       /* _vbo_loopback_vertex_list doesn't use the index buffer, so we have to
905        * use buffer_in_ram instead of current_bo which contains all vertices instead
906        * of the deduplicated vertices only in the !UseLoopback case.
907        *
908        * The problem is that the VAO offset is based on current_bo's layout,
909        * so we have to use a temp value.
910        */
911       struct gl_vertex_array_object *vao = node->VAO[VP_MODE_SHADER];
912       GLintptr original = vao->BufferBinding[0].Offset;
913       if (!ctx->ListState.Current.UseLoopback) {
914          GLintptr new_offset = (save->buffer_map - save->vertex_store->buffer_in_ram) *
915                                sizeof(GLfloat);
916          /* 'start_offset' has been added to all primitives 'start', so undo it here. */
917          new_offset -= start_offset * stride;
918          vao->BufferBinding[0].Offset = new_offset;
919       }
920       _vbo_loopback_vertex_list(ctx, node, save->vertex_store->buffer_in_ram);
921       vao->BufferBinding[0].Offset = original;
922
923       _glapi_set_dispatch(dispatch);
924    }
925
926    /* Decide whether the storage structs are full, or can be used for
927     * the next vertex lists as well.
928     */
929    if (save->vertex_store->used >
930        save->vertex_store->buffer_in_ram_size / sizeof(float) - 16 * (save->vertex_size + 4)) {
931       realloc_storage(ctx, -1, 0);
932    }
933    else {
934       /* update buffer_ptr for next vertex */
935       save->buffer_ptr = save->vertex_store->buffer_in_ram
936          + save->vertex_store->used;
937    }
938
939    /* Reset our structures for the next run of vertices:
940     */
941    reset_counters(ctx);
942 }
943
944
945 /**
946  * This is called when we fill a vertex buffer before we hit a glEnd().
947  * We
948  * TODO -- If no new vertices have been stored, don't bother saving it.
949  */
950 static void
951 wrap_buffers(struct gl_context *ctx)
952 {
953    struct vbo_save_context *save = &vbo_context(ctx)->save;
954    GLint i = save->prim_store->used - 1;
955    GLenum mode;
956
957    assert(i < (GLint) save->prim_store->size);
958    assert(i >= 0);
959
960    /* Close off in-progress primitive.
961     */
962    save->prim_store->prims[i].count = (save->vert_count - save->prim_store->prims[i].start);
963    mode = save->prim_store->prims[i].mode;
964
965    /* store the copied vertices, and allocate a new list.
966     */
967    compile_vertex_list(ctx);
968
969    /* Restart interrupted primitive
970     */
971    save->prim_store->prims[0].mode = mode;
972    save->prim_store->prims[0].begin = 0;
973    save->prim_store->prims[0].end = 0;
974    save->prim_store->prims[0].start = 0;
975    save->prim_store->prims[0].count = 0;
976    save->prim_store->used = 1;
977 }
978
979
980 /**
981  * Called only when buffers are wrapped as the result of filling the
982  * vertex_store struct.
983  */
984 static void
985 wrap_filled_vertex(struct gl_context *ctx)
986 {
987    struct vbo_save_context *save = &vbo_context(ctx)->save;
988    unsigned numComponents;
989
990    /* Emit a glEnd to close off the last vertex list.
991     */
992    wrap_buffers(ctx);
993
994    /* Copy stored stored vertices to start of new list.
995     */
996    assert(save->max_vert - save->vert_count > save->copied.nr);
997
998    numComponents = save->copied.nr * save->vertex_size;
999    memcpy(save->buffer_ptr,
1000           save->copied.buffer,
1001           numComponents * sizeof(fi_type));
1002    save->buffer_ptr += numComponents;
1003    save->vert_count += save->copied.nr;
1004 }
1005
1006
1007 static void
1008 copy_to_current(struct gl_context *ctx)
1009 {
1010    struct vbo_save_context *save = &vbo_context(ctx)->save;
1011    GLbitfield64 enabled = save->enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));
1012
1013    while (enabled) {
1014       const int i = u_bit_scan64(&enabled);
1015       assert(save->attrsz[i]);
1016
1017       if (save->attrtype[i] == GL_DOUBLE ||
1018           save->attrtype[i] == GL_UNSIGNED_INT64_ARB)
1019          memcpy(save->current[i], save->attrptr[i], save->attrsz[i] * sizeof(GLfloat));
1020       else
1021          COPY_CLEAN_4V_TYPE_AS_UNION(save->current[i], save->attrsz[i],
1022                                      save->attrptr[i], save->attrtype[i]);
1023    }
1024 }
1025
1026
1027 static void
1028 copy_from_current(struct gl_context *ctx)
1029 {
1030    struct vbo_save_context *save = &vbo_context(ctx)->save;
1031    GLbitfield64 enabled = save->enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));
1032
1033    while (enabled) {
1034       const int i = u_bit_scan64(&enabled);
1035
1036       switch (save->attrsz[i]) {
1037       case 4:
1038          save->attrptr[i][3] = save->current[i][3];
1039          FALLTHROUGH;
1040       case 3:
1041          save->attrptr[i][2] = save->current[i][2];
1042          FALLTHROUGH;
1043       case 2:
1044          save->attrptr[i][1] = save->current[i][1];
1045          FALLTHROUGH;
1046       case 1:
1047          save->attrptr[i][0] = save->current[i][0];
1048          break;
1049       case 0:
1050          unreachable("Unexpected vertex attribute size");
1051       }
1052    }
1053 }
1054
1055
1056 /**
1057  * Called when we increase the size of a vertex attribute.  For example,
1058  * if we've seen one or more glTexCoord2f() calls and now we get a
1059  * glTexCoord3f() call.
1060  * Flush existing data, set new attrib size, replay copied vertices.
1061  */
1062 static void
1063 upgrade_vertex(struct gl_context *ctx, GLuint attr, GLuint newsz)
1064 {
1065    struct vbo_save_context *save = &vbo_context(ctx)->save;
1066    GLuint oldsz;
1067    GLuint i;
1068    fi_type *tmp;
1069
1070    /* Store the current run of vertices, and emit a GL_END.  Emit a
1071     * BEGIN in the new buffer.
1072     */
1073    if (save->vert_count)
1074       wrap_buffers(ctx);
1075    else
1076       assert(save->copied.nr == 0);
1077
1078    /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
1079     * when the attribute already exists in the vertex and is having
1080     * its size increased.
1081     */
1082    copy_to_current(ctx);
1083
1084    /* Fix up sizes:
1085     */
1086    oldsz = save->attrsz[attr];
1087    save->attrsz[attr] = newsz;
1088    save->enabled |= BITFIELD64_BIT(attr);
1089
1090    save->vertex_size += newsz - oldsz;
1091    save->max_vert = ((save->vertex_store->buffer_in_ram_size / sizeof(float) -
1092                       save->vertex_store->used) /
1093                      save->vertex_size);
1094    save->vert_count = 0;
1095
1096    /* Recalculate all the attrptr[] values:
1097     */
1098    tmp = save->vertex;
1099    for (i = 0; i < VBO_ATTRIB_MAX; i++) {
1100       if (save->attrsz[i]) {
1101          save->attrptr[i] = tmp;
1102          tmp += save->attrsz[i];
1103       }
1104       else {
1105          save->attrptr[i] = NULL;       /* will not be dereferenced. */
1106       }
1107    }
1108
1109    /* Copy from current to repopulate the vertex with correct values.
1110     */
1111    copy_from_current(ctx);
1112
1113    /* Replay stored vertices to translate them to new format here.
1114     *
1115     * If there are copied vertices and the new (upgraded) attribute
1116     * has not been defined before, this list is somewhat degenerate,
1117     * and will need fixup at runtime.
1118     */
1119    if (save->copied.nr) {
1120       const fi_type *data = save->copied.buffer;
1121       fi_type *dest = save->buffer_map;
1122
1123       /* Need to note this and fix up at runtime (or loopback):
1124        */
1125       if (attr != VBO_ATTRIB_POS && save->currentsz[attr][0] == 0) {
1126          assert(oldsz == 0);
1127          save->dangling_attr_ref = GL_TRUE;
1128       }
1129
1130       for (i = 0; i < save->copied.nr; i++) {
1131          GLbitfield64 enabled = save->enabled;
1132          while (enabled) {
1133             const int j = u_bit_scan64(&enabled);
1134             assert(save->attrsz[j]);
1135             if (j == attr) {
1136                if (oldsz) {
1137                   COPY_CLEAN_4V_TYPE_AS_UNION(dest, oldsz, data,
1138                                               save->attrtype[j]);
1139                   data += oldsz;
1140                   dest += newsz;
1141                }
1142                else {
1143                   COPY_SZ_4V(dest, newsz, save->current[attr]);
1144                   dest += newsz;
1145                }
1146             }
1147             else {
1148                GLint sz = save->attrsz[j];
1149                COPY_SZ_4V(dest, sz, data);
1150                data += sz;
1151                dest += sz;
1152             }
1153          }
1154       }
1155
1156       save->buffer_ptr = dest;
1157       save->vert_count += save->copied.nr;
1158    }
1159 }
1160
1161
1162 /**
1163  * This is called when the size of a vertex attribute changes.
1164  * For example, after seeing one or more glTexCoord2f() calls we
1165  * get a glTexCoord4f() or glTexCoord1f() call.
1166  */
1167 static void
1168 fixup_vertex(struct gl_context *ctx, GLuint attr,
1169              GLuint sz, GLenum newType)
1170 {
1171    struct vbo_save_context *save = &vbo_context(ctx)->save;
1172
1173    if (sz > save->attrsz[attr] ||
1174        newType != save->attrtype[attr]) {
1175       /* New size is larger.  Need to flush existing vertices and get
1176        * an enlarged vertex format.
1177        */
1178       upgrade_vertex(ctx, attr, sz);
1179    }
1180    else if (sz < save->active_sz[attr]) {
1181       GLuint i;
1182       const fi_type *id = vbo_get_default_vals_as_union(save->attrtype[attr]);
1183
1184       /* New size is equal or smaller - just need to fill in some
1185        * zeros.
1186        */
1187       for (i = sz; i <= save->attrsz[attr]; i++)
1188          save->attrptr[attr][i - 1] = id[i - 1];
1189    }
1190
1191    save->active_sz[attr] = sz;
1192 }
1193
1194
1195 /**
1196  * Reset the current size of all vertex attributes to the default
1197  * value of 0.  This signals that we haven't yet seen any per-vertex
1198  * commands such as glNormal3f() or glTexCoord2f().
1199  */
1200 static void
1201 reset_vertex(struct gl_context *ctx)
1202 {
1203    struct vbo_save_context *save = &vbo_context(ctx)->save;
1204
1205    while (save->enabled) {
1206       const int i = u_bit_scan64(&save->enabled);
1207       assert(save->attrsz[i]);
1208       save->attrsz[i] = 0;
1209       save->active_sz[i] = 0;
1210    }
1211
1212    save->vertex_size = 0;
1213 }
1214
1215
1216 /**
1217  * If index=0, does glVertexAttrib*() alias glVertex() to emit a vertex?
1218  * It depends on a few things, including whether we're inside or outside
1219  * of glBegin/glEnd.
1220  */
1221 static inline bool
1222 is_vertex_position(const struct gl_context *ctx, GLuint index)
1223 {
1224    return (index == 0 &&
1225            _mesa_attr_zero_aliases_vertex(ctx) &&
1226            _mesa_inside_dlist_begin_end(ctx));
1227 }
1228
1229
1230
1231 #define ERROR(err)   _mesa_compile_error(ctx, err, __func__);
1232
1233
1234 /* Only one size for each attribute may be active at once.  Eg. if
1235  * Color3f is installed/active, then Color4f may not be, even if the
1236  * vertex actually contains 4 color coordinates.  This is because the
1237  * 3f version won't otherwise set color[3] to 1.0 -- this is the job
1238  * of the chooser function when switching between Color4f and Color3f.
1239  */
1240 #define ATTR_UNION(A, N, T, C, V0, V1, V2, V3)                  \
1241 do {                                                            \
1242    struct vbo_save_context *save = &vbo_context(ctx)->save;     \
1243    int sz = (sizeof(C) / sizeof(GLfloat));                      \
1244                                                                 \
1245    if (save->active_sz[A] != N)                                 \
1246       fixup_vertex(ctx, A, N * sz, T);                          \
1247                                                                 \
1248    {                                                            \
1249       C *dest = (C *)save->attrptr[A];                          \
1250       if (N>0) dest[0] = V0;                                    \
1251       if (N>1) dest[1] = V1;                                    \
1252       if (N>2) dest[2] = V2;                                    \
1253       if (N>3) dest[3] = V3;                                    \
1254       save->attrtype[A] = T;                                    \
1255    }                                                            \
1256                                                                 \
1257    if ((A) == 0) {                                              \
1258       GLuint i;                                                 \
1259                                                                 \
1260       for (i = 0; i < save->vertex_size; i++)                   \
1261          save->buffer_ptr[i] = save->vertex[i];                 \
1262                                                                 \
1263       save->buffer_ptr += save->vertex_size;                    \
1264                                                                 \
1265       if (++save->vert_count >= save->max_vert)                 \
1266          wrap_filled_vertex(ctx);                               \
1267    }                                                            \
1268 } while (0)
1269
1270 #define TAG(x) _save_##x
1271
1272 #include "vbo_attrib_tmp.h"
1273
1274
1275
1276 #define MAT( ATTR, N, face, params )                    \
1277 do {                                                    \
1278    if (face != GL_BACK)                                 \
1279       MAT_ATTR( ATTR, N, params ); /* front */          \
1280    if (face != GL_FRONT)                                \
1281       MAT_ATTR( ATTR + 1, N, params ); /* back */       \
1282 } while (0)
1283
1284
1285 /**
1286  * Save a glMaterial call found between glBegin/End.
1287  * glMaterial calls outside Begin/End are handled in dlist.c.
1288  */
1289 static void GLAPIENTRY
1290 _save_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
1291 {
1292    GET_CURRENT_CONTEXT(ctx);
1293
1294    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
1295       _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(face)");
1296       return;
1297    }
1298
1299    switch (pname) {
1300    case GL_EMISSION:
1301       MAT(VBO_ATTRIB_MAT_FRONT_EMISSION, 4, face, params);
1302       break;
1303    case GL_AMBIENT:
1304       MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
1305       break;
1306    case GL_DIFFUSE:
1307       MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
1308       break;
1309    case GL_SPECULAR:
1310       MAT(VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params);
1311       break;
1312    case GL_SHININESS:
1313       if (*params < 0 || *params > ctx->Const.MaxShininess) {
1314          _mesa_compile_error(ctx, GL_INVALID_VALUE, "glMaterial(shininess)");
1315       }
1316       else {
1317          MAT(VBO_ATTRIB_MAT_FRONT_SHININESS, 1, face, params);
1318       }
1319       break;
1320    case GL_COLOR_INDEXES:
1321       MAT(VBO_ATTRIB_MAT_FRONT_INDEXES, 3, face, params);
1322       break;
1323    case GL_AMBIENT_AND_DIFFUSE:
1324       MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
1325       MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
1326       break;
1327    default:
1328       _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(pname)");
1329       return;
1330    }
1331 }
1332
1333
1334 /* Cope with EvalCoord/CallList called within a begin/end object:
1335  *     -- Flush current buffer
1336  *     -- Fallback to opcodes for the rest of the begin/end object.
1337  */
1338 static void
1339 dlist_fallback(struct gl_context *ctx)
1340 {
1341    struct vbo_save_context *save = &vbo_context(ctx)->save;
1342
1343    if (save->vert_count || save->prim_store->used) {
1344       if (save->prim_store->used > 0) {
1345          /* Close off in-progress primitive. */
1346          GLint i = save->prim_store->used - 1;
1347          save->prim_store->prims[i].count = save->vert_count - save->prim_store->prims[i].start;
1348       }
1349
1350       /* Need to replay this display list with loopback,
1351        * unfortunately, otherwise this primitive won't be handled
1352        * properly:
1353        */
1354       save->dangling_attr_ref = GL_TRUE;
1355
1356       compile_vertex_list(ctx);
1357    }
1358
1359    copy_to_current(ctx);
1360    reset_vertex(ctx);
1361    reset_counters(ctx);
1362    if (save->out_of_memory) {
1363       _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
1364    }
1365    else {
1366       _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
1367    }
1368    ctx->Driver.SaveNeedFlush = GL_FALSE;
1369 }
1370
1371
1372 static void GLAPIENTRY
1373 _save_EvalCoord1f(GLfloat u)
1374 {
1375    GET_CURRENT_CONTEXT(ctx);
1376    dlist_fallback(ctx);
1377    CALL_EvalCoord1f(ctx->Save, (u));
1378 }
1379
1380 static void GLAPIENTRY
1381 _save_EvalCoord1fv(const GLfloat * v)
1382 {
1383    GET_CURRENT_CONTEXT(ctx);
1384    dlist_fallback(ctx);
1385    CALL_EvalCoord1fv(ctx->Save, (v));
1386 }
1387
1388 static void GLAPIENTRY
1389 _save_EvalCoord2f(GLfloat u, GLfloat v)
1390 {
1391    GET_CURRENT_CONTEXT(ctx);
1392    dlist_fallback(ctx);
1393    CALL_EvalCoord2f(ctx->Save, (u, v));
1394 }
1395
1396 static void GLAPIENTRY
1397 _save_EvalCoord2fv(const GLfloat * v)
1398 {
1399    GET_CURRENT_CONTEXT(ctx);
1400    dlist_fallback(ctx);
1401    CALL_EvalCoord2fv(ctx->Save, (v));
1402 }
1403
1404 static void GLAPIENTRY
1405 _save_EvalPoint1(GLint i)
1406 {
1407    GET_CURRENT_CONTEXT(ctx);
1408    dlist_fallback(ctx);
1409    CALL_EvalPoint1(ctx->Save, (i));
1410 }
1411
1412 static void GLAPIENTRY
1413 _save_EvalPoint2(GLint i, GLint j)
1414 {
1415    GET_CURRENT_CONTEXT(ctx);
1416    dlist_fallback(ctx);
1417    CALL_EvalPoint2(ctx->Save, (i, j));
1418 }
1419
1420 static void GLAPIENTRY
1421 _save_CallList(GLuint l)
1422 {
1423    GET_CURRENT_CONTEXT(ctx);
1424    dlist_fallback(ctx);
1425    CALL_CallList(ctx->Save, (l));
1426 }
1427
1428 static void GLAPIENTRY
1429 _save_CallLists(GLsizei n, GLenum type, const GLvoid * v)
1430 {
1431    GET_CURRENT_CONTEXT(ctx);
1432    dlist_fallback(ctx);
1433    CALL_CallLists(ctx->Save, (n, type, v));
1434 }
1435
1436
1437
1438 /**
1439  * Called when a glBegin is getting compiled into a display list.
1440  * Updating of ctx->Driver.CurrentSavePrimitive is already taken care of.
1441  */
1442 void
1443 vbo_save_NotifyBegin(struct gl_context *ctx, GLenum mode,
1444                      bool no_current_update)
1445 {
1446    struct vbo_save_context *save = &vbo_context(ctx)->save;
1447    const GLuint i = save->prim_store->used++;
1448
1449    ctx->Driver.CurrentSavePrimitive = mode;
1450
1451    assert(i < save->prim_store->size);
1452    save->prim_store->prims[i].mode = mode & VBO_SAVE_PRIM_MODE_MASK;
1453    save->prim_store->prims[i].begin = 1;
1454    save->prim_store->prims[i].end = 0;
1455    save->prim_store->prims[i].start = save->vert_count;
1456    save->prim_store->prims[i].count = 0;
1457
1458    save->no_current_update = no_current_update;
1459
1460    if (save->out_of_memory) {
1461       _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
1462    }
1463    else {
1464       _mesa_install_save_vtxfmt(ctx, &save->vtxfmt);
1465    }
1466
1467    /* We need to call vbo_save_SaveFlushVertices() if there's state change */
1468    ctx->Driver.SaveNeedFlush = GL_TRUE;
1469 }
1470
1471
1472 static void GLAPIENTRY
1473 _save_End(void)
1474 {
1475    GET_CURRENT_CONTEXT(ctx);
1476    struct vbo_save_context *save = &vbo_context(ctx)->save;
1477    const GLint i = save->prim_store->used - 1;
1478
1479    ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
1480    save->prim_store->prims[i].end = 1;
1481    save->prim_store->prims[i].count = (save->vert_count - save->prim_store->prims[i].start);
1482
1483    if (i == (GLint) save->prim_store->size - 1) {
1484       compile_vertex_list(ctx);
1485       assert(save->copied.nr == 0);
1486    }
1487
1488    /* Swap out this vertex format while outside begin/end.  Any color,
1489     * etc. received between here and the next begin will be compiled
1490     * as opcodes.
1491     */
1492    if (save->out_of_memory) {
1493       _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
1494    }
1495    else {
1496       _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
1497    }
1498 }
1499
1500
1501 static void GLAPIENTRY
1502 _save_Begin(GLenum mode)
1503 {
1504    GET_CURRENT_CONTEXT(ctx);
1505    (void) mode;
1506    _mesa_compile_error(ctx, GL_INVALID_OPERATION, "Recursive glBegin");
1507 }
1508
1509
1510 static void GLAPIENTRY
1511 _save_PrimitiveRestartNV(void)
1512 {
1513    GET_CURRENT_CONTEXT(ctx);
1514    struct vbo_save_context *save = &vbo_context(ctx)->save;
1515
1516    if (save->prim_store->used == 0) {
1517       /* We're not inside a glBegin/End pair, so calling glPrimitiverRestartNV
1518        * is an error.
1519        */
1520       _mesa_compile_error(ctx, GL_INVALID_OPERATION,
1521                           "glPrimitiveRestartNV called outside glBegin/End");
1522    } else {
1523       /* get current primitive mode */
1524       GLenum curPrim = save->prim_store->prims[save->prim_store->used - 1].mode;
1525       bool no_current_update = save->no_current_update;
1526
1527       /* restart primitive */
1528       CALL_End(ctx->CurrentServerDispatch, ());
1529       vbo_save_NotifyBegin(ctx, curPrim, no_current_update);
1530    }
1531 }
1532
1533
1534 /* Unlike the functions above, these are to be hooked into the vtxfmt
1535  * maintained in ctx->ListState, active when the list is known or
1536  * suspected to be outside any begin/end primitive.
1537  * Note: OBE = Outside Begin/End
1538  */
1539 static void GLAPIENTRY
1540 _save_OBE_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
1541 {
1542    GET_CURRENT_CONTEXT(ctx);
1543    struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1544
1545    vbo_save_NotifyBegin(ctx, GL_QUADS, false);
1546    CALL_Vertex2f(dispatch, (x1, y1));
1547    CALL_Vertex2f(dispatch, (x2, y1));
1548    CALL_Vertex2f(dispatch, (x2, y2));
1549    CALL_Vertex2f(dispatch, (x1, y2));
1550    CALL_End(dispatch, ());
1551 }
1552
1553
1554 static void GLAPIENTRY
1555 _save_OBE_Rectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)
1556 {
1557    _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1558 }
1559
1560 static void GLAPIENTRY
1561 _save_OBE_Rectdv(const GLdouble *v1, const GLdouble *v2)
1562 {
1563    _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1564 }
1565
1566 static void GLAPIENTRY
1567 _save_OBE_Rectfv(const GLfloat *v1, const GLfloat *v2)
1568 {
1569    _save_OBE_Rectf(v1[0], v1[1], v2[0], v2[1]);
1570 }
1571
1572 static void GLAPIENTRY
1573 _save_OBE_Recti(GLint x1, GLint y1, GLint x2, GLint y2)
1574 {
1575    _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1576 }
1577
1578 static void GLAPIENTRY
1579 _save_OBE_Rectiv(const GLint *v1, const GLint *v2)
1580 {
1581    _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1582 }
1583
1584 static void GLAPIENTRY
1585 _save_OBE_Rects(GLshort x1, GLshort y1, GLshort x2, GLshort y2)
1586 {
1587    _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1588 }
1589
1590 static void GLAPIENTRY
1591 _save_OBE_Rectsv(const GLshort *v1, const GLshort *v2)
1592 {
1593    _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1594 }
1595
1596 static void
1597 _ensure_draws_fits_in_storage(struct gl_context *ctx, int primcount, int vertcount)
1598 {
1599    struct vbo_save_context *save = &vbo_context(ctx)->save;
1600
1601    bool realloc_prim = save->prim_store->used + primcount > save->prim_store->size;
1602    bool realloc_vert = save->vertex_size && (save->vert_count + vertcount >= save->max_vert);
1603
1604    if (realloc_prim || realloc_vert) {
1605       if (realloc_vert && (save->vert_count || save->prim_store->used)) {
1606          /* TODO: this really isn't needed. We should realloc only the CPU-side memory. */
1607          compile_vertex_list(ctx);
1608       }
1609       realloc_storage(ctx, realloc_prim ? primcount : -1, realloc_vert ? vertcount : -1);
1610       reset_counters(ctx);
1611    }
1612 }
1613
1614
1615 static void GLAPIENTRY
1616 _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count)
1617 {
1618    GET_CURRENT_CONTEXT(ctx);
1619    struct gl_vertex_array_object *vao = ctx->Array.VAO;
1620    struct vbo_save_context *save = &vbo_context(ctx)->save;
1621    GLint i;
1622
1623    if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1624       _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawArrays(mode)");
1625       return;
1626    }
1627    if (count < 0) {
1628       _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawArrays(count<0)");
1629       return;
1630    }
1631
1632    if (save->out_of_memory)
1633       return;
1634
1635    _ensure_draws_fits_in_storage(ctx, 1, count);
1636
1637    /* Make sure to process any VBO binding changes */
1638    _mesa_update_state(ctx);
1639
1640    _mesa_vao_map_arrays(ctx, vao, GL_MAP_READ_BIT);
1641
1642    vbo_save_NotifyBegin(ctx, mode, true);
1643
1644    for (i = 0; i < count; i++)
1645       _mesa_array_element(ctx, start + i);
1646    CALL_End(ctx->CurrentServerDispatch, ());
1647
1648    _mesa_vao_unmap_arrays(ctx, vao);
1649 }
1650
1651
1652 static void GLAPIENTRY
1653 _save_OBE_MultiDrawArrays(GLenum mode, const GLint *first,
1654                           const GLsizei *count, GLsizei primcount)
1655 {
1656    GET_CURRENT_CONTEXT(ctx);
1657    GLint i;
1658
1659    if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1660       _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMultiDrawArrays(mode)");
1661       return;
1662    }
1663
1664    if (primcount < 0) {
1665       _mesa_compile_error(ctx, GL_INVALID_VALUE,
1666                           "glMultiDrawArrays(primcount<0)");
1667       return;
1668    }
1669
1670    unsigned vertcount = 0;
1671    for (i = 0; i < primcount; i++) {
1672       if (count[i] < 0) {
1673          _mesa_compile_error(ctx, GL_INVALID_VALUE,
1674                              "glMultiDrawArrays(count[i]<0)");
1675          return;
1676       }
1677       vertcount += count[i];
1678    }
1679
1680    _ensure_draws_fits_in_storage(ctx, primcount, vertcount);
1681
1682    for (i = 0; i < primcount; i++) {
1683       if (count[i] > 0) {
1684          _save_OBE_DrawArrays(mode, first[i], count[i]);
1685       }
1686    }
1687 }
1688
1689
1690 static void
1691 array_element(struct gl_context *ctx,
1692               GLint basevertex, GLuint elt, unsigned index_size_shift)
1693 {
1694    /* Section 10.3.5 Primitive Restart:
1695     * [...]
1696     *    When one of the *BaseVertex drawing commands specified in section 10.5
1697     * is used, the primitive restart comparison occurs before the basevertex
1698     * offset is added to the array index.
1699     */
1700    /* If PrimitiveRestart is enabled and the index is the RestartIndex
1701     * then we call PrimitiveRestartNV and return.
1702     */
1703    if (ctx->Array._PrimitiveRestart[index_size_shift] &&
1704        elt == ctx->Array._RestartIndex[index_size_shift]) {
1705       CALL_PrimitiveRestartNV(ctx->CurrentServerDispatch, ());
1706       return;
1707    }
1708
1709    _mesa_array_element(ctx, basevertex + elt);
1710 }
1711
1712
1713 /* Could do better by copying the arrays and element list intact and
1714  * then emitting an indexed prim at runtime.
1715  */
1716 static void GLAPIENTRY
1717 _save_OBE_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1718                                  const GLvoid * indices, GLint basevertex)
1719 {
1720    GET_CURRENT_CONTEXT(ctx);
1721    struct vbo_save_context *save = &vbo_context(ctx)->save;
1722    struct gl_vertex_array_object *vao = ctx->Array.VAO;
1723    struct gl_buffer_object *indexbuf = vao->IndexBufferObj;
1724    GLint i;
1725
1726    if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1727       _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawElements(mode)");
1728       return;
1729    }
1730    if (count < 0) {
1731       _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawElements(count<0)");
1732       return;
1733    }
1734    if (type != GL_UNSIGNED_BYTE &&
1735        type != GL_UNSIGNED_SHORT &&
1736        type != GL_UNSIGNED_INT) {
1737       _mesa_compile_error(ctx, GL_INVALID_VALUE, "glDrawElements(count<0)");
1738       return;
1739    }
1740
1741    if (save->out_of_memory)
1742       return;
1743
1744    _ensure_draws_fits_in_storage(ctx, 1, count);
1745
1746    /* Make sure to process any VBO binding changes */
1747    _mesa_update_state(ctx);
1748
1749    _mesa_vao_map(ctx, vao, GL_MAP_READ_BIT);
1750
1751    if (indexbuf)
1752       indices =
1753          ADD_POINTERS(indexbuf->Mappings[MAP_INTERNAL].Pointer, indices);
1754
1755    vbo_save_NotifyBegin(ctx, mode, true);
1756
1757    switch (type) {
1758    case GL_UNSIGNED_BYTE:
1759       for (i = 0; i < count; i++)
1760          array_element(ctx, basevertex, ((GLubyte *) indices)[i], 0);
1761       break;
1762    case GL_UNSIGNED_SHORT:
1763       for (i = 0; i < count; i++)
1764          array_element(ctx, basevertex, ((GLushort *) indices)[i], 1);
1765       break;
1766    case GL_UNSIGNED_INT:
1767       for (i = 0; i < count; i++)
1768          array_element(ctx, basevertex, ((GLuint *) indices)[i], 2);
1769       break;
1770    default:
1771       _mesa_error(ctx, GL_INVALID_ENUM, "glDrawElements(type)");
1772       break;
1773    }
1774
1775    CALL_End(ctx->CurrentServerDispatch, ());
1776
1777    _mesa_vao_unmap(ctx, vao);
1778 }
1779
1780 static void GLAPIENTRY
1781 _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type,
1782                        const GLvoid * indices)
1783 {
1784    _save_OBE_DrawElementsBaseVertex(mode, count, type, indices, 0);
1785 }
1786
1787
1788 static void GLAPIENTRY
1789 _save_OBE_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
1790                             GLsizei count, GLenum type,
1791                             const GLvoid * indices)
1792 {
1793    GET_CURRENT_CONTEXT(ctx);
1794    struct vbo_save_context *save = &vbo_context(ctx)->save;
1795
1796    if (!_mesa_is_valid_prim_mode(ctx, mode)) {
1797       _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(mode)");
1798       return;
1799    }
1800    if (count < 0) {
1801       _mesa_compile_error(ctx, GL_INVALID_VALUE,
1802                           "glDrawRangeElements(count<0)");
1803       return;
1804    }
1805    if (type != GL_UNSIGNED_BYTE &&
1806        type != GL_UNSIGNED_SHORT &&
1807        type != GL_UNSIGNED_INT) {
1808       _mesa_compile_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(type)");
1809       return;
1810    }
1811    if (end < start) {
1812       _mesa_compile_error(ctx, GL_INVALID_VALUE,
1813                           "glDrawRangeElements(end < start)");
1814       return;
1815    }
1816
1817    if (save->out_of_memory)
1818       return;
1819
1820    _save_OBE_DrawElements(mode, count, type, indices);
1821 }
1822
1823
1824 static void GLAPIENTRY
1825 _save_OBE_MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type,
1826                             const GLvoid * const *indices, GLsizei primcount)
1827 {
1828    GET_CURRENT_CONTEXT(ctx);
1829    struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1830    GLsizei i;
1831
1832    int vertcount = 0;
1833    for (i = 0; i < primcount; i++) {
1834       vertcount += count[i];
1835    }
1836    _ensure_draws_fits_in_storage(ctx, primcount, vertcount);
1837
1838    for (i = 0; i < primcount; i++) {
1839       if (count[i] > 0) {
1840          CALL_DrawElements(dispatch, (mode, count[i], type, indices[i]));
1841       }
1842    }
1843 }
1844
1845
1846 static void GLAPIENTRY
1847 _save_OBE_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count,
1848                                       GLenum type,
1849                                       const GLvoid * const *indices,
1850                                       GLsizei primcount,
1851                                       const GLint *basevertex)
1852 {
1853    GET_CURRENT_CONTEXT(ctx);
1854    struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1855    GLsizei i;
1856
1857    int vertcount = 0;
1858    for (i = 0; i < primcount; i++) {
1859       vertcount += count[i];
1860    }
1861    _ensure_draws_fits_in_storage(ctx, primcount, vertcount);
1862
1863    for (i = 0; i < primcount; i++) {
1864       if (count[i] > 0) {
1865          CALL_DrawElementsBaseVertex(dispatch, (mode, count[i], type,
1866                                                       indices[i],
1867                                                       basevertex[i]));
1868       }
1869    }
1870 }
1871
1872
1873 static void
1874 vtxfmt_init(struct gl_context *ctx)
1875 {
1876    struct vbo_save_context *save = &vbo_context(ctx)->save;
1877    GLvertexformat *vfmt = &save->vtxfmt;
1878
1879 #define NAME_AE(x) _ae_##x
1880 #define NAME_CALLLIST(x) _save_##x
1881 #define NAME(x) _save_##x
1882 #define NAME_ES(x) _save_##x##ARB
1883
1884 #include "vbo_init_tmp.h"
1885 }
1886
1887
1888 /**
1889  * Initialize the dispatch table with the VBO functions for display
1890  * list compilation.
1891  */
1892 void
1893 vbo_initialize_save_dispatch(const struct gl_context *ctx,
1894                              struct _glapi_table *exec)
1895 {
1896    SET_DrawArrays(exec, _save_OBE_DrawArrays);
1897    SET_MultiDrawArrays(exec, _save_OBE_MultiDrawArrays);
1898    SET_DrawElements(exec, _save_OBE_DrawElements);
1899    SET_DrawElementsBaseVertex(exec, _save_OBE_DrawElementsBaseVertex);
1900    SET_DrawRangeElements(exec, _save_OBE_DrawRangeElements);
1901    SET_MultiDrawElementsEXT(exec, _save_OBE_MultiDrawElements);
1902    SET_MultiDrawElementsBaseVertex(exec, _save_OBE_MultiDrawElementsBaseVertex);
1903    SET_Rectf(exec, _save_OBE_Rectf);
1904    SET_Rectd(exec, _save_OBE_Rectd);
1905    SET_Rectdv(exec, _save_OBE_Rectdv);
1906    SET_Rectfv(exec, _save_OBE_Rectfv);
1907    SET_Recti(exec, _save_OBE_Recti);
1908    SET_Rectiv(exec, _save_OBE_Rectiv);
1909    SET_Rects(exec, _save_OBE_Rects);
1910    SET_Rectsv(exec, _save_OBE_Rectsv);
1911
1912    /* Note: other glDraw functins aren't compiled into display lists */
1913 }
1914
1915
1916
1917 void
1918 vbo_save_SaveFlushVertices(struct gl_context *ctx)
1919 {
1920    struct vbo_save_context *save = &vbo_context(ctx)->save;
1921
1922    /* Noop when we are actually active:
1923     */
1924    if (ctx->Driver.CurrentSavePrimitive <= PRIM_MAX)
1925       return;
1926
1927    if (save->vert_count || save->prim_store->used)
1928       compile_vertex_list(ctx);
1929
1930    copy_to_current(ctx);
1931    reset_vertex(ctx);
1932    reset_counters(ctx);
1933    ctx->Driver.SaveNeedFlush = GL_FALSE;
1934 }
1935
1936
1937 /**
1938  * Called from glNewList when we're starting to compile a display list.
1939  */
1940 void
1941 vbo_save_NewList(struct gl_context *ctx, GLuint list, GLenum mode)
1942 {
1943    struct vbo_save_context *save = &vbo_context(ctx)->save;
1944
1945    (void) list;
1946    (void) mode;
1947
1948    if (!save->prim_store)
1949       save->prim_store = realloc_prim_store(NULL, 8);
1950
1951    if (!save->vertex_store)
1952       save->vertex_store = alloc_vertex_store(ctx, 0);
1953
1954    save->buffer_ptr = save->vertex_store->buffer_in_ram + save->vertex_store->used;
1955
1956    reset_vertex(ctx);
1957    reset_counters(ctx);
1958    ctx->Driver.SaveNeedFlush = GL_FALSE;
1959 }
1960
1961
1962 /**
1963  * Called from glEndList when we're finished compiling a display list.
1964  */
1965 void
1966 vbo_save_EndList(struct gl_context *ctx)
1967 {
1968    struct vbo_save_context *save = &vbo_context(ctx)->save;
1969
1970    /* EndList called inside a (saved) Begin/End pair?
1971     */
1972    if (_mesa_inside_dlist_begin_end(ctx)) {
1973       if (save->prim_store->used > 0) {
1974          GLint i = save->prim_store->used - 1;
1975          ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
1976          save->prim_store->prims[i].end = 0;
1977          save->prim_store->prims[i].count = save->vert_count - save->prim_store->prims[i].start;
1978       }
1979
1980       /* Make sure this vertex list gets replayed by the "loopback"
1981        * mechanism:
1982        */
1983       save->dangling_attr_ref = GL_TRUE;
1984       vbo_save_SaveFlushVertices(ctx);
1985
1986       /* Swap out this vertex format while outside begin/end.  Any color,
1987        * etc. received between here and the next begin will be compiled
1988        * as opcodes.
1989        */
1990       _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
1991    }
1992
1993    assert(save->vertex_size == 0);
1994 }
1995
1996 /**
1997  * Called during context creation/init.
1998  */
1999 static void
2000 current_init(struct gl_context *ctx)
2001 {
2002    struct vbo_save_context *save = &vbo_context(ctx)->save;
2003    GLint i;
2004
2005    for (i = VBO_ATTRIB_POS; i <= VBO_ATTRIB_EDGEFLAG; i++) {
2006       const GLuint j = i - VBO_ATTRIB_POS;
2007       assert(j < VERT_ATTRIB_MAX);
2008       save->currentsz[i] = &ctx->ListState.ActiveAttribSize[j];
2009       save->current[i] = (fi_type *) ctx->ListState.CurrentAttrib[j];
2010    }
2011
2012    for (i = VBO_ATTRIB_FIRST_MATERIAL; i <= VBO_ATTRIB_LAST_MATERIAL; i++) {
2013       const GLuint j = i - VBO_ATTRIB_FIRST_MATERIAL;
2014       assert(j < MAT_ATTRIB_MAX);
2015       save->currentsz[i] = &ctx->ListState.ActiveMaterialSize[j];
2016       save->current[i] = (fi_type *) ctx->ListState.CurrentMaterial[j];
2017    }
2018 }
2019
2020
2021 /**
2022  * Initialize the display list compiler.  Called during context creation.
2023  */
2024 void
2025 vbo_save_api_init(struct vbo_save_context *save)
2026 {
2027    struct gl_context *ctx = gl_context_from_vbo_save(save);
2028
2029    vtxfmt_init(ctx);
2030    current_init(ctx);
2031    _mesa_noop_vtxfmt_init(ctx, &save->vtxfmt_noop);
2032 }