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