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