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