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