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