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