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