• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "main/glheader.h"
34 #include "main/bufferobj.h"
35 #include "main/context.h"
36 #include "main/macros.h"
37 #include "main/vtxfmt.h"
38 #include "main/dlist.h"
39 #include "main/eval.h"
40 #include "main/state.h"
41 #include "main/light.h"
42 #include "main/api_arrayelt.h"
43 #include "main/api_validate.h"
44 #include "main/dispatch.h"
45 #include "util/bitscan.h"
46 
47 #include "vbo_context.h"
48 #include "vbo_noop.h"
49 
50 
51 /** ID/name for immediate-mode VBO */
52 #define IMM_BUFFER_NAME 0xaabbccdd
53 
54 
55 static void
56 vbo_reset_all_attr(struct vbo_exec_context *exec);
57 
58 
59 /**
60  * Close off the last primitive, execute the buffer, restart the
61  * primitive.  This is called when we fill a vertex buffer before
62  * hitting glEnd.
63  */
64 static void
vbo_exec_wrap_buffers(struct vbo_exec_context * exec)65 vbo_exec_wrap_buffers(struct vbo_exec_context *exec)
66 {
67    if (exec->vtx.prim_count == 0) {
68       exec->vtx.copied.nr = 0;
69       exec->vtx.vert_count = 0;
70       exec->vtx.buffer_ptr = exec->vtx.buffer_map;
71    }
72    else {
73       struct _mesa_prim *last_prim = &exec->vtx.prim[exec->vtx.prim_count - 1];
74       const GLuint last_begin = last_prim->begin;
75       GLuint last_count;
76 
77       if (_mesa_inside_begin_end(exec->ctx)) {
78          last_prim->count = exec->vtx.vert_count - last_prim->start;
79       }
80 
81       last_count = last_prim->count;
82 
83       /* Special handling for wrapping GL_LINE_LOOP */
84       if (last_prim->mode == GL_LINE_LOOP &&
85           last_count > 0 &&
86           !last_prim->end) {
87          /* draw this section of the incomplete line loop as a line strip */
88          last_prim->mode = GL_LINE_STRIP;
89          if (!last_prim->begin) {
90             /* This is not the first section of the line loop, so don't
91              * draw the 0th vertex.  We're saving it until we draw the
92              * very last section of the loop.
93              */
94             last_prim->start++;
95             last_prim->count--;
96          }
97       }
98 
99       /* Execute the buffer and save copied vertices.
100        */
101       if (exec->vtx.vert_count)
102          vbo_exec_vtx_flush(exec, GL_FALSE);
103       else {
104          exec->vtx.prim_count = 0;
105          exec->vtx.copied.nr = 0;
106       }
107 
108       /* Emit a glBegin to start the new list.
109        */
110       assert(exec->vtx.prim_count == 0);
111 
112       if (_mesa_inside_begin_end(exec->ctx)) {
113          exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive;
114          exec->vtx.prim[0].begin = 0;
115          exec->vtx.prim[0].end = 0;
116          exec->vtx.prim[0].start = 0;
117          exec->vtx.prim[0].count = 0;
118          exec->vtx.prim_count++;
119 
120          if (exec->vtx.copied.nr == last_count)
121             exec->vtx.prim[0].begin = last_begin;
122       }
123    }
124 }
125 
126 
127 /**
128  * Deal with buffer wrapping where provoked by the vertex buffer
129  * filling up, as opposed to upgrade_vertex().
130  */
131 static void
vbo_exec_vtx_wrap(struct vbo_exec_context * exec)132 vbo_exec_vtx_wrap(struct vbo_exec_context *exec)
133 {
134    unsigned numComponents;
135 
136    /* Run pipeline on current vertices, copy wrapped vertices
137     * to exec->vtx.copied.
138     */
139    vbo_exec_wrap_buffers(exec);
140 
141    if (!exec->vtx.buffer_ptr) {
142       /* probably ran out of memory earlier when allocating the VBO */
143       return;
144    }
145 
146    /* Copy stored stored vertices to start of new list.
147     */
148    assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr);
149 
150    numComponents = exec->vtx.copied.nr * exec->vtx.vertex_size;
151    memcpy(exec->vtx.buffer_ptr,
152           exec->vtx.copied.buffer,
153           numComponents * sizeof(fi_type));
154    exec->vtx.buffer_ptr += numComponents;
155    exec->vtx.vert_count += exec->vtx.copied.nr;
156 
157    exec->vtx.copied.nr = 0;
158 }
159 
160 
161 /**
162  * Copy the active vertex's values to the ctx->Current fields.
163  */
164 static void
vbo_exec_copy_to_current(struct vbo_exec_context * exec)165 vbo_exec_copy_to_current(struct vbo_exec_context *exec)
166 {
167    struct gl_context *ctx = exec->ctx;
168    struct vbo_context *vbo = vbo_context(ctx);
169    GLbitfield64 enabled = exec->vtx.enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));
170 
171    while (enabled) {
172       const int i = u_bit_scan64(&enabled);
173 
174       /* Note: the exec->vtx.current[i] pointers point into the
175        * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
176        */
177       GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
178       fi_type tmp[8]; /* space for doubles */
179       int dmul = 1;
180 
181       if (exec->vtx.attrtype[i] == GL_DOUBLE ||
182           exec->vtx.attrtype[i] == GL_UNSIGNED_INT64_ARB)
183          dmul = 2;
184 
185       assert(exec->vtx.attrsz[i]);
186 
187       if (exec->vtx.attrtype[i] == GL_DOUBLE ||
188           exec->vtx.attrtype[i] == GL_UNSIGNED_INT64_ARB) {
189          memset(tmp, 0, sizeof(tmp));
190          memcpy(tmp, exec->vtx.attrptr[i], exec->vtx.attrsz[i] * sizeof(GLfloat));
191       } else {
192          COPY_CLEAN_4V_TYPE_AS_UNION(tmp,
193                                      exec->vtx.attrsz[i],
194                                      exec->vtx.attrptr[i],
195                                      exec->vtx.attrtype[i]);
196       }
197 
198       if (exec->vtx.attrtype[i] != vbo->currval[i].Type ||
199           memcmp(current, tmp, 4 * sizeof(GLfloat) * dmul) != 0) {
200          memcpy(current, tmp, 4 * sizeof(GLfloat) * dmul);
201 
202          /* Given that we explicitly state size here, there is no need
203           * for the COPY_CLEAN above, could just copy 16 bytes and be
204           * done.  The only problem is when Mesa accesses ctx->Current
205           * directly.
206           */
207          /* Size here is in components - not bytes */
208          vbo->currval[i].Size = exec->vtx.attrsz[i] / dmul;
209          vbo->currval[i]._ElementSize =
210             vbo->currval[i].Size * sizeof(GLfloat) * dmul;
211          vbo->currval[i].Type = exec->vtx.attrtype[i];
212          vbo->currval[i].Integer =
213             vbo_attrtype_to_integer_flag(exec->vtx.attrtype[i]);
214          vbo->currval[i].Doubles =
215             vbo_attrtype_to_double_flag(exec->vtx.attrtype[i]);
216 
217          /* This triggers rather too much recalculation of Mesa state
218           * that doesn't get used (eg light positions).
219           */
220          if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
221              i <= VBO_ATTRIB_MAT_BACK_INDEXES)
222             ctx->NewState |= _NEW_LIGHT;
223 
224          ctx->NewState |= _NEW_CURRENT_ATTRIB;
225       }
226    }
227 
228    /* Colormaterial -- this kindof sucks.
229     */
230    if (ctx->Light.ColorMaterialEnabled &&
231        exec->vtx.attrsz[VBO_ATTRIB_COLOR0]) {
232       _mesa_update_color_material(ctx,
233                                   ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
234    }
235 }
236 
237 
238 /**
239  * Copy current vertex attribute values into the current vertex.
240  */
241 static void
vbo_exec_copy_from_current(struct vbo_exec_context * exec)242 vbo_exec_copy_from_current(struct vbo_exec_context *exec)
243 {
244    struct gl_context *ctx = exec->ctx;
245    struct vbo_context *vbo = vbo_context(ctx);
246    GLint i;
247 
248    for (i = VBO_ATTRIB_POS + 1; i < VBO_ATTRIB_MAX; i++) {
249       if (exec->vtx.attrtype[i] == GL_DOUBLE ||
250           exec->vtx.attrtype[i] == GL_UNSIGNED_INT64_ARB) {
251          memcpy(exec->vtx.attrptr[i], vbo->currval[i].Ptr,
252                 exec->vtx.attrsz[i] * sizeof(GLfloat));
253       } else {
254          const fi_type *current = (fi_type *) vbo->currval[i].Ptr;
255          switch (exec->vtx.attrsz[i]) {
256          case 4: exec->vtx.attrptr[i][3] = current[3];
257          case 3: exec->vtx.attrptr[i][2] = current[2];
258          case 2: exec->vtx.attrptr[i][1] = current[1];
259          case 1: exec->vtx.attrptr[i][0] = current[0];
260             break;
261          }
262       }
263    }
264 }
265 
266 
267 /**
268  * Flush existing data, set new attrib size, replay copied vertices.
269  * This is called when we transition from a small vertex attribute size
270  * to a larger one.  Ex: glTexCoord2f -> glTexCoord4f.
271  * We need to go back over the previous 2-component texcoords and insert
272  * zero and one values.
273  * \param attr  VBO_ATTRIB_x vertex attribute value
274  */
275 static void
vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context * exec,GLuint attr,GLuint newSize)276 vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec,
277                              GLuint attr, GLuint newSize)
278 {
279    struct gl_context *ctx = exec->ctx;
280    struct vbo_context *vbo = vbo_context(ctx);
281    const GLint lastcount = exec->vtx.vert_count;
282    fi_type *old_attrptr[VBO_ATTRIB_MAX];
283    const GLuint old_vtx_size = exec->vtx.vertex_size; /* floats per vertex */
284    const GLuint oldSize = exec->vtx.attrsz[attr];
285    GLuint i;
286 
287    assert(attr < VBO_ATTRIB_MAX);
288 
289    /* Run pipeline on current vertices, copy wrapped vertices
290     * to exec->vtx.copied.
291     */
292    vbo_exec_wrap_buffers(exec);
293 
294    if (unlikely(exec->vtx.copied.nr)) {
295       /* We're in the middle of a primitive, keep the old vertex
296        * format around to be able to translate the copied vertices to
297        * the new format.
298        */
299       memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr));
300    }
301 
302    if (unlikely(oldSize)) {
303       /* Do a COPY_TO_CURRENT to ensure back-copying works for the
304        * case when the attribute already exists in the vertex and is
305        * having its size increased.
306        */
307       vbo_exec_copy_to_current(exec);
308    }
309 
310    /* Heuristic: Attempt to isolate attributes received outside
311     * begin/end so that they don't bloat the vertices.
312     */
313    if (!_mesa_inside_begin_end(ctx) &&
314        !oldSize && lastcount > 8 && exec->vtx.vertex_size) {
315       vbo_exec_copy_to_current(exec);
316       vbo_reset_all_attr(exec);
317    }
318 
319    /* Fix up sizes:
320     */
321    exec->vtx.attrsz[attr] = newSize;
322    exec->vtx.vertex_size += newSize - oldSize;
323    exec->vtx.max_vert = vbo_compute_max_verts(exec);
324    exec->vtx.vert_count = 0;
325    exec->vtx.buffer_ptr = exec->vtx.buffer_map;
326    exec->vtx.enabled |= BITFIELD64_BIT(attr);
327 
328    if (unlikely(oldSize)) {
329       /* Size changed, recalculate all the attrptr[] values
330        */
331       fi_type *tmp = exec->vtx.vertex;
332 
333       for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
334          if (exec->vtx.attrsz[i]) {
335             exec->vtx.attrptr[i] = tmp;
336             tmp += exec->vtx.attrsz[i];
337          }
338          else
339             exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */
340       }
341 
342       /* Copy from current to repopulate the vertex with correct
343        * values.
344        */
345       vbo_exec_copy_from_current(exec);
346    }
347    else {
348       /* Just have to append the new attribute at the end */
349       exec->vtx.attrptr[attr] = exec->vtx.vertex +
350         exec->vtx.vertex_size - newSize;
351    }
352 
353    /* Replay stored vertices to translate them
354     * to new format here.
355     *
356     * -- No need to replay - just copy piecewise
357     */
358    if (unlikely(exec->vtx.copied.nr)) {
359       fi_type *data = exec->vtx.copied.buffer;
360       fi_type *dest = exec->vtx.buffer_ptr;
361 
362       assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map);
363 
364       for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
365          GLbitfield64 enabled = exec->vtx.enabled;
366          while (enabled) {
367             const int j = u_bit_scan64(&enabled);
368             GLuint sz = exec->vtx.attrsz[j];
369             GLint old_offset = old_attrptr[j] - exec->vtx.vertex;
370             GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex;
371 
372             assert(sz);
373 
374             if (j == attr) {
375                if (oldSize) {
376                   fi_type tmp[4];
377                   COPY_CLEAN_4V_TYPE_AS_UNION(tmp, oldSize,
378                                               data + old_offset,
379                                               exec->vtx.attrtype[j]);
380                   COPY_SZ_4V(dest + new_offset, newSize, tmp);
381                } else {
382                   fi_type *current = (fi_type *)vbo->currval[j].Ptr;
383                   COPY_SZ_4V(dest + new_offset, sz, current);
384                }
385             }
386             else {
387                COPY_SZ_4V(dest + new_offset, sz, data + old_offset);
388             }
389          }
390 
391          data += old_vtx_size;
392          dest += exec->vtx.vertex_size;
393       }
394 
395       exec->vtx.buffer_ptr = dest;
396       exec->vtx.vert_count += exec->vtx.copied.nr;
397       exec->vtx.copied.nr = 0;
398    }
399 }
400 
401 
402 /**
403  * This is when a vertex attribute transitions to a different size.
404  * For example, we saw a bunch of glTexCoord2f() calls and now we got a
405  * glTexCoord4f() call.  We promote the array from size=2 to size=4.
406  * \param newSize  size of new vertex (number of 32-bit words).
407  * \param attr  VBO_ATTRIB_x vertex attribute value
408  */
409 static void
vbo_exec_fixup_vertex(struct gl_context * ctx,GLuint attr,GLuint newSize,GLenum newType)410 vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr,
411                       GLuint newSize, GLenum newType)
412 {
413    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
414 
415    assert(attr < VBO_ATTRIB_MAX);
416 
417    if (newSize > exec->vtx.attrsz[attr] ||
418        newType != exec->vtx.attrtype[attr]) {
419       /* New size is larger.  Need to flush existing vertices and get
420        * an enlarged vertex format.
421        */
422       vbo_exec_wrap_upgrade_vertex(exec, attr, newSize);
423    }
424    else if (newSize < exec->vtx.active_sz[attr]) {
425       GLuint i;
426       const fi_type *id =
427             vbo_get_default_vals_as_union(exec->vtx.attrtype[attr]);
428 
429       /* New size is smaller - just need to fill in some
430        * zeros.  Don't need to flush or wrap.
431        */
432       for (i = newSize; i <= exec->vtx.attrsz[attr]; i++)
433          exec->vtx.attrptr[attr][i-1] = id[i-1];
434    }
435 
436    exec->vtx.active_sz[attr] = newSize;
437    exec->vtx.attrtype[attr] = newType;
438 
439    /* Does setting NeedFlush belong here?  Necessitates resetting
440     * vtxfmt on each flush (otherwise flags won't get reset
441     * afterwards).
442     */
443    if (attr == 0)
444       ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
445 }
446 
447 
448 /**
449  * Called upon first glVertex, glColor, glTexCoord, etc.
450  */
451 static void
vbo_exec_begin_vertices(struct gl_context * ctx)452 vbo_exec_begin_vertices(struct gl_context *ctx)
453 {
454    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
455 
456    vbo_exec_vtx_map(exec);
457 
458    assert((ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0);
459    assert(exec->begin_vertices_flags);
460 
461    ctx->Driver.NeedFlush |= exec->begin_vertices_flags;
462 }
463 
464 
465 /**
466  * This macro is used to implement all the glVertex, glColor, glTexCoord,
467  * glVertexAttrib, etc functions.
468  * \param A  VBO_ATTRIB_x attribute index
469  * \param N  attribute size (1..4)
470  * \param T  type (GL_FLOAT, GL_DOUBLE, GL_INT, GL_UNSIGNED_INT)
471  * \param C  cast type (fi_type or double)
472  * \param V0, V1, v2, V3  attribute value
473  */
474 #define ATTR_UNION(A, N, T, C, V0, V1, V2, V3)                          \
475 do {                                                                    \
476    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;             \
477    int sz = (sizeof(C) / sizeof(GLfloat));                              \
478                                                                         \
479    assert(sz == 1 || sz == 2);                                          \
480                                                                         \
481    /* check if attribute size or type is changing */                    \
482    if (unlikely(exec->vtx.active_sz[A] != N * sz) ||                    \
483        unlikely(exec->vtx.attrtype[A] != T)) {                          \
484       vbo_exec_fixup_vertex(ctx, A, N * sz, T);                         \
485    }                                                                    \
486                                                                         \
487    /* store vertex attribute in vertex buffer */                        \
488    {                                                                    \
489       C *dest = (C *)exec->vtx.attrptr[A];                              \
490       if (N>0) dest[0] = V0;                                            \
491       if (N>1) dest[1] = V1;                                            \
492       if (N>2) dest[2] = V2;                                            \
493       if (N>3) dest[3] = V3;                                            \
494       assert(exec->vtx.attrtype[A] == T);                               \
495    }                                                                    \
496                                                                         \
497    if ((A) == 0) {                                                      \
498       /* This is a glVertex call */                                     \
499       GLuint i;                                                         \
500                                                                         \
501       if (unlikely((ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0)) { \
502          vbo_exec_begin_vertices(ctx);                                  \
503       }                                                                 \
504                                                                         \
505       if (unlikely(!exec->vtx.buffer_ptr)) {                            \
506          vbo_exec_vtx_map(exec);                                        \
507       }                                                                 \
508       assert(exec->vtx.buffer_ptr);                                     \
509                                                                         \
510       /* copy 32-bit words */                                           \
511       for (i = 0; i < exec->vtx.vertex_size; i++)                       \
512          exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i];                 \
513                                                                         \
514       exec->vtx.buffer_ptr += exec->vtx.vertex_size;                    \
515                                                                         \
516       /* Set FLUSH_STORED_VERTICES to indicate that there's now */      \
517       /* something to draw (not just updating a color or texcoord).*/   \
518       ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;                   \
519                                                                         \
520       if (++exec->vtx.vert_count >= exec->vtx.max_vert)                 \
521          vbo_exec_vtx_wrap(exec);                                       \
522    } else {                                                             \
523       /* we now have accumulated per-vertex attributes */               \
524       ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;                    \
525    }                                                                    \
526 } while (0)
527 
528 
529 #undef ERROR
530 #define ERROR(err) _mesa_error(ctx, err, __func__)
531 #define TAG(x) vbo_##x
532 
533 #include "vbo_attrib_tmp.h"
534 
535 
536 
537 /**
538  * Execute a glMaterial call.  Note that if GL_COLOR_MATERIAL is enabled,
539  * this may be a (partial) no-op.
540  */
541 static void GLAPIENTRY
vbo_Materialfv(GLenum face,GLenum pname,const GLfloat * params)542 vbo_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
543 {
544    GLbitfield updateMats;
545    GET_CURRENT_CONTEXT(ctx);
546 
547    /* This function should be a no-op when it tries to update material
548     * attributes which are currently tracking glColor via glColorMaterial.
549     * The updateMats var will be a mask of the MAT_BIT_FRONT/BACK_x bits
550     * indicating which material attributes can actually be updated below.
551     */
552    if (ctx->Light.ColorMaterialEnabled) {
553       updateMats = ~ctx->Light._ColorMaterialBitmask;
554    }
555    else {
556       /* GL_COLOR_MATERIAL is disabled so don't skip any material updates */
557       updateMats = ALL_MATERIAL_BITS;
558    }
559 
560    if (ctx->API == API_OPENGL_COMPAT && face == GL_FRONT) {
561       updateMats &= FRONT_MATERIAL_BITS;
562    }
563    else if (ctx->API == API_OPENGL_COMPAT && face == GL_BACK) {
564       updateMats &= BACK_MATERIAL_BITS;
565    }
566    else if (face != GL_FRONT_AND_BACK) {
567       _mesa_error(ctx, GL_INVALID_ENUM, "glMaterial(invalid face)");
568       return;
569    }
570 
571    switch (pname) {
572    case GL_EMISSION:
573       if (updateMats & MAT_BIT_FRONT_EMISSION)
574          MAT_ATTR(VBO_ATTRIB_MAT_FRONT_EMISSION, 4, params);
575       if (updateMats & MAT_BIT_BACK_EMISSION)
576          MAT_ATTR(VBO_ATTRIB_MAT_BACK_EMISSION, 4, params);
577       break;
578    case GL_AMBIENT:
579       if (updateMats & MAT_BIT_FRONT_AMBIENT)
580          MAT_ATTR(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, params);
581       if (updateMats & MAT_BIT_BACK_AMBIENT)
582          MAT_ATTR(VBO_ATTRIB_MAT_BACK_AMBIENT, 4, params);
583       break;
584    case GL_DIFFUSE:
585       if (updateMats & MAT_BIT_FRONT_DIFFUSE)
586          MAT_ATTR(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, params);
587       if (updateMats & MAT_BIT_BACK_DIFFUSE)
588          MAT_ATTR(VBO_ATTRIB_MAT_BACK_DIFFUSE, 4, params);
589       break;
590    case GL_SPECULAR:
591       if (updateMats & MAT_BIT_FRONT_SPECULAR)
592          MAT_ATTR(VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, params);
593       if (updateMats & MAT_BIT_BACK_SPECULAR)
594          MAT_ATTR(VBO_ATTRIB_MAT_BACK_SPECULAR, 4, params);
595       break;
596    case GL_SHININESS:
597       if (*params < 0 || *params > ctx->Const.MaxShininess) {
598          _mesa_error(ctx, GL_INVALID_VALUE,
599                      "glMaterial(invalid shininess: %f out range [0, %f])",
600                      *params, ctx->Const.MaxShininess);
601          return;
602       }
603       if (updateMats & MAT_BIT_FRONT_SHININESS)
604          MAT_ATTR(VBO_ATTRIB_MAT_FRONT_SHININESS, 1, params);
605       if (updateMats & MAT_BIT_BACK_SHININESS)
606          MAT_ATTR(VBO_ATTRIB_MAT_BACK_SHININESS, 1, params);
607       break;
608    case GL_COLOR_INDEXES:
609       if (ctx->API != API_OPENGL_COMPAT) {
610          _mesa_error(ctx, GL_INVALID_ENUM, "glMaterialfv(pname)");
611          return;
612       }
613       if (updateMats & MAT_BIT_FRONT_INDEXES)
614          MAT_ATTR(VBO_ATTRIB_MAT_FRONT_INDEXES, 3, params);
615       if (updateMats & MAT_BIT_BACK_INDEXES)
616          MAT_ATTR(VBO_ATTRIB_MAT_BACK_INDEXES, 3, params);
617       break;
618    case GL_AMBIENT_AND_DIFFUSE:
619       if (updateMats & MAT_BIT_FRONT_AMBIENT)
620          MAT_ATTR(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, params);
621       if (updateMats & MAT_BIT_FRONT_DIFFUSE)
622          MAT_ATTR(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, params);
623       if (updateMats & MAT_BIT_BACK_AMBIENT)
624          MAT_ATTR(VBO_ATTRIB_MAT_BACK_AMBIENT, 4, params);
625       if (updateMats & MAT_BIT_BACK_DIFFUSE)
626          MAT_ATTR(VBO_ATTRIB_MAT_BACK_DIFFUSE, 4, params);
627       break;
628    default:
629       _mesa_error(ctx, GL_INVALID_ENUM, "glMaterialfv(pname)");
630       return;
631    }
632 }
633 
634 
635 /**
636  * Flush (draw) vertices.
637  * \param  unmap - leave VBO unmapped after flushing?
638  */
639 static void
vbo_exec_FlushVertices_internal(struct vbo_exec_context * exec,GLboolean unmap)640 vbo_exec_FlushVertices_internal(struct vbo_exec_context *exec, GLboolean unmap)
641 {
642    if (exec->vtx.vert_count || unmap) {
643       vbo_exec_vtx_flush(exec, unmap);
644    }
645 
646    if (exec->vtx.vertex_size) {
647       vbo_exec_copy_to_current(exec);
648       vbo_reset_all_attr(exec);
649    }
650 }
651 
652 
653 static void GLAPIENTRY
vbo_exec_EvalCoord1f(GLfloat u)654 vbo_exec_EvalCoord1f(GLfloat u)
655 {
656    GET_CURRENT_CONTEXT(ctx);
657    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
658 
659    {
660       GLint i;
661       if (exec->eval.recalculate_maps)
662          vbo_exec_eval_update(exec);
663 
664       for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
665          if (exec->eval.map1[i].map)
666             if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz)
667                vbo_exec_fixup_vertex(ctx, i, exec->eval.map1[i].sz, GL_FLOAT);
668       }
669    }
670 
671    memcpy(exec->vtx.copied.buffer, exec->vtx.vertex,
672           exec->vtx.vertex_size * sizeof(GLfloat));
673 
674    vbo_exec_do_EvalCoord1f(exec, u);
675 
676    memcpy(exec->vtx.vertex, exec->vtx.copied.buffer,
677           exec->vtx.vertex_size * sizeof(GLfloat));
678 }
679 
680 
681 static void GLAPIENTRY
vbo_exec_EvalCoord2f(GLfloat u,GLfloat v)682 vbo_exec_EvalCoord2f(GLfloat u, GLfloat v)
683 {
684    GET_CURRENT_CONTEXT(ctx);
685    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
686 
687    {
688       GLint i;
689       if (exec->eval.recalculate_maps)
690          vbo_exec_eval_update(exec);
691 
692       for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
693          if (exec->eval.map2[i].map)
694             if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz)
695                vbo_exec_fixup_vertex(ctx, i, exec->eval.map2[i].sz, GL_FLOAT);
696       }
697 
698       if (ctx->Eval.AutoNormal)
699          if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3)
700             vbo_exec_fixup_vertex(ctx, VBO_ATTRIB_NORMAL, 3, GL_FLOAT);
701    }
702 
703    memcpy(exec->vtx.copied.buffer, exec->vtx.vertex,
704           exec->vtx.vertex_size * sizeof(GLfloat));
705 
706    vbo_exec_do_EvalCoord2f(exec, u, v);
707 
708    memcpy(exec->vtx.vertex, exec->vtx.copied.buffer,
709           exec->vtx.vertex_size * sizeof(GLfloat));
710 }
711 
712 
713 static void GLAPIENTRY
vbo_exec_EvalCoord1fv(const GLfloat * u)714 vbo_exec_EvalCoord1fv(const GLfloat *u)
715 {
716    vbo_exec_EvalCoord1f(u[0]);
717 }
718 
719 
720 static void GLAPIENTRY
vbo_exec_EvalCoord2fv(const GLfloat * u)721 vbo_exec_EvalCoord2fv(const GLfloat *u)
722 {
723    vbo_exec_EvalCoord2f(u[0], u[1]);
724 }
725 
726 
727 static void GLAPIENTRY
vbo_exec_EvalPoint1(GLint i)728 vbo_exec_EvalPoint1(GLint i)
729 {
730    GET_CURRENT_CONTEXT(ctx);
731    GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) /
732                  (GLfloat) ctx->Eval.MapGrid1un);
733    GLfloat u = i * du + ctx->Eval.MapGrid1u1;
734 
735    vbo_exec_EvalCoord1f(u);
736 }
737 
738 
739 static void GLAPIENTRY
vbo_exec_EvalPoint2(GLint i,GLint j)740 vbo_exec_EvalPoint2(GLint i, GLint j)
741 {
742    GET_CURRENT_CONTEXT(ctx);
743    GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) /
744                  (GLfloat) ctx->Eval.MapGrid2un);
745    GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) /
746                  (GLfloat) ctx->Eval.MapGrid2vn);
747    GLfloat u = i * du + ctx->Eval.MapGrid2u1;
748    GLfloat v = j * dv + ctx->Eval.MapGrid2v1;
749 
750    vbo_exec_EvalCoord2f(u, v);
751 }
752 
753 
754 /**
755  * Called via glBegin.
756  */
757 static void GLAPIENTRY
vbo_exec_Begin(GLenum mode)758 vbo_exec_Begin(GLenum mode)
759 {
760    GET_CURRENT_CONTEXT(ctx);
761    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
762    int i;
763 
764    if (_mesa_inside_begin_end(ctx)) {
765       _mesa_error(ctx, GL_INVALID_OPERATION, "glBegin");
766       return;
767    }
768 
769    if (!_mesa_valid_prim_mode(ctx, mode, "glBegin")) {
770       return;
771    }
772 
773    vbo_draw_method(vbo_context(ctx), DRAW_BEGIN_END);
774 
775    if (ctx->NewState) {
776       _mesa_update_state(ctx);
777 
778       CALL_Begin(ctx->Exec, (mode));
779       return;
780    }
781 
782    if (!_mesa_valid_to_render(ctx, "glBegin")) {
783       return;
784    }
785 
786    /* Heuristic: attempt to isolate attributes occurring outside
787     * begin/end pairs.
788     */
789    if (exec->vtx.vertex_size && !exec->vtx.attrsz[0])
790       vbo_exec_FlushVertices_internal(exec, GL_FALSE);
791 
792    i = exec->vtx.prim_count++;
793    exec->vtx.prim[i].mode = mode;
794    exec->vtx.prim[i].begin = 1;
795    exec->vtx.prim[i].end = 0;
796    exec->vtx.prim[i].indexed = 0;
797    exec->vtx.prim[i].weak = 0;
798    exec->vtx.prim[i].pad = 0;
799    exec->vtx.prim[i].start = exec->vtx.vert_count;
800    exec->vtx.prim[i].count = 0;
801    exec->vtx.prim[i].num_instances = 1;
802    exec->vtx.prim[i].base_instance = 0;
803    exec->vtx.prim[i].is_indirect = 0;
804 
805    ctx->Driver.CurrentExecPrimitive = mode;
806 
807    ctx->Exec = ctx->BeginEnd;
808    /* We may have been called from a display list, in which case we should
809     * leave dlist.c's dispatch table in place.
810     */
811    if (ctx->CurrentClientDispatch == ctx->OutsideBeginEnd) {
812       ctx->CurrentClientDispatch = ctx->BeginEnd;
813       _glapi_set_dispatch(ctx->CurrentClientDispatch);
814    } else {
815       assert(ctx->CurrentClientDispatch == ctx->Save);
816    }
817 }
818 
819 
820 /**
821  * Try to merge / concatenate the two most recent VBO primitives.
822  */
823 static void
try_vbo_merge(struct vbo_exec_context * exec)824 try_vbo_merge(struct vbo_exec_context *exec)
825 {
826    struct _mesa_prim *cur =  &exec->vtx.prim[exec->vtx.prim_count - 1];
827 
828    assert(exec->vtx.prim_count >= 1);
829 
830    vbo_try_prim_conversion(cur);
831 
832    if (exec->vtx.prim_count >= 2) {
833       struct _mesa_prim *prev = &exec->vtx.prim[exec->vtx.prim_count - 2];
834       assert(prev == cur - 1);
835 
836       if (vbo_can_merge_prims(prev, cur)) {
837          assert(cur->begin);
838          assert(cur->end);
839          assert(prev->begin);
840          assert(prev->end);
841          vbo_merge_prims(prev, cur);
842          exec->vtx.prim_count--;  /* drop the last primitive */
843       }
844    }
845 }
846 
847 
848 /**
849  * Called via glEnd.
850  */
851 static void GLAPIENTRY
vbo_exec_End(void)852 vbo_exec_End(void)
853 {
854    GET_CURRENT_CONTEXT(ctx);
855    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
856 
857    if (!_mesa_inside_begin_end(ctx)) {
858       _mesa_error(ctx, GL_INVALID_OPERATION, "glEnd");
859       return;
860    }
861 
862    ctx->Exec = ctx->OutsideBeginEnd;
863    if (ctx->CurrentClientDispatch == ctx->BeginEnd) {
864       ctx->CurrentClientDispatch = ctx->OutsideBeginEnd;
865       _glapi_set_dispatch(ctx->CurrentClientDispatch);
866    }
867 
868    if (exec->vtx.prim_count > 0) {
869       /* close off current primitive */
870       struct _mesa_prim *last_prim = &exec->vtx.prim[exec->vtx.prim_count - 1];
871 
872       last_prim->end = 1;
873       last_prim->count = exec->vtx.vert_count - last_prim->start;
874 
875       /* Special handling for GL_LINE_LOOP */
876       if (last_prim->mode == GL_LINE_LOOP && last_prim->begin == 0) {
877          /* We're finishing drawing a line loop.  Append 0th vertex onto
878           * end of vertex buffer so we can draw it as a line strip.
879           */
880          const fi_type *src = exec->vtx.buffer_map +
881             last_prim->start * exec->vtx.vertex_size;
882          fi_type *dst = exec->vtx.buffer_map +
883             exec->vtx.vert_count * exec->vtx.vertex_size;
884 
885          /* copy 0th vertex to end of buffer */
886          memcpy(dst, src, exec->vtx.vertex_size * sizeof(fi_type));
887 
888          last_prim->start++;  /* skip vertex0 */
889          /* note that last_prim->count stays unchanged */
890          last_prim->mode = GL_LINE_STRIP;
891 
892          /* Increment the vertex count so the next primitive doesn't
893           * overwrite the last vertex which we just added.
894           */
895          exec->vtx.vert_count++;
896          exec->vtx.buffer_ptr += exec->vtx.vertex_size;
897       }
898 
899       try_vbo_merge(exec);
900    }
901 
902    ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
903 
904    if (exec->vtx.prim_count == VBO_MAX_PRIM)
905       vbo_exec_vtx_flush(exec, GL_FALSE);
906 
907    if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
908       _mesa_flush(ctx);
909    }
910 }
911 
912 
913 /**
914  * Called via glPrimitiveRestartNV()
915  */
916 static void GLAPIENTRY
vbo_exec_PrimitiveRestartNV(void)917 vbo_exec_PrimitiveRestartNV(void)
918 {
919    GLenum curPrim;
920    GET_CURRENT_CONTEXT(ctx);
921 
922    curPrim = ctx->Driver.CurrentExecPrimitive;
923 
924    if (curPrim == PRIM_OUTSIDE_BEGIN_END) {
925       _mesa_error(ctx, GL_INVALID_OPERATION, "glPrimitiveRestartNV");
926    }
927    else {
928       vbo_exec_End();
929       vbo_exec_Begin(curPrim);
930    }
931 }
932 
933 
934 static void
vbo_exec_vtxfmt_init(struct vbo_exec_context * exec)935 vbo_exec_vtxfmt_init(struct vbo_exec_context *exec)
936 {
937    struct gl_context *ctx = exec->ctx;
938    GLvertexformat *vfmt = &exec->vtxfmt;
939 
940    vfmt->ArrayElement = _ae_ArrayElement;
941 
942    vfmt->Begin = vbo_exec_Begin;
943    vfmt->End = vbo_exec_End;
944    vfmt->PrimitiveRestartNV = vbo_exec_PrimitiveRestartNV;
945 
946    vfmt->CallList = _mesa_CallList;
947    vfmt->CallLists = _mesa_CallLists;
948 
949    vfmt->EvalCoord1f = vbo_exec_EvalCoord1f;
950    vfmt->EvalCoord1fv = vbo_exec_EvalCoord1fv;
951    vfmt->EvalCoord2f = vbo_exec_EvalCoord2f;
952    vfmt->EvalCoord2fv = vbo_exec_EvalCoord2fv;
953    vfmt->EvalPoint1 = vbo_exec_EvalPoint1;
954    vfmt->EvalPoint2 = vbo_exec_EvalPoint2;
955 
956    /* from attrib_tmp.h:
957     */
958    vfmt->Color3f = vbo_Color3f;
959    vfmt->Color3fv = vbo_Color3fv;
960    vfmt->Color4f = vbo_Color4f;
961    vfmt->Color4fv = vbo_Color4fv;
962    vfmt->FogCoordfEXT = vbo_FogCoordfEXT;
963    vfmt->FogCoordfvEXT = vbo_FogCoordfvEXT;
964    vfmt->MultiTexCoord1fARB = vbo_MultiTexCoord1f;
965    vfmt->MultiTexCoord1fvARB = vbo_MultiTexCoord1fv;
966    vfmt->MultiTexCoord2fARB = vbo_MultiTexCoord2f;
967    vfmt->MultiTexCoord2fvARB = vbo_MultiTexCoord2fv;
968    vfmt->MultiTexCoord3fARB = vbo_MultiTexCoord3f;
969    vfmt->MultiTexCoord3fvARB = vbo_MultiTexCoord3fv;
970    vfmt->MultiTexCoord4fARB = vbo_MultiTexCoord4f;
971    vfmt->MultiTexCoord4fvARB = vbo_MultiTexCoord4fv;
972    vfmt->Normal3f = vbo_Normal3f;
973    vfmt->Normal3fv = vbo_Normal3fv;
974    vfmt->SecondaryColor3fEXT = vbo_SecondaryColor3fEXT;
975    vfmt->SecondaryColor3fvEXT = vbo_SecondaryColor3fvEXT;
976    vfmt->TexCoord1f = vbo_TexCoord1f;
977    vfmt->TexCoord1fv = vbo_TexCoord1fv;
978    vfmt->TexCoord2f = vbo_TexCoord2f;
979    vfmt->TexCoord2fv = vbo_TexCoord2fv;
980    vfmt->TexCoord3f = vbo_TexCoord3f;
981    vfmt->TexCoord3fv = vbo_TexCoord3fv;
982    vfmt->TexCoord4f = vbo_TexCoord4f;
983    vfmt->TexCoord4fv = vbo_TexCoord4fv;
984    vfmt->Vertex2f = vbo_Vertex2f;
985    vfmt->Vertex2fv = vbo_Vertex2fv;
986    vfmt->Vertex3f = vbo_Vertex3f;
987    vfmt->Vertex3fv = vbo_Vertex3fv;
988    vfmt->Vertex4f = vbo_Vertex4f;
989    vfmt->Vertex4fv = vbo_Vertex4fv;
990 
991    if (ctx->API == API_OPENGLES2) {
992       vfmt->VertexAttrib1fARB = _es_VertexAttrib1f;
993       vfmt->VertexAttrib1fvARB = _es_VertexAttrib1fv;
994       vfmt->VertexAttrib2fARB = _es_VertexAttrib2f;
995       vfmt->VertexAttrib2fvARB = _es_VertexAttrib2fv;
996       vfmt->VertexAttrib3fARB = _es_VertexAttrib3f;
997       vfmt->VertexAttrib3fvARB = _es_VertexAttrib3fv;
998       vfmt->VertexAttrib4fARB = _es_VertexAttrib4f;
999       vfmt->VertexAttrib4fvARB = _es_VertexAttrib4fv;
1000    } else {
1001       vfmt->VertexAttrib1fARB = vbo_VertexAttrib1fARB;
1002       vfmt->VertexAttrib1fvARB = vbo_VertexAttrib1fvARB;
1003       vfmt->VertexAttrib2fARB = vbo_VertexAttrib2fARB;
1004       vfmt->VertexAttrib2fvARB = vbo_VertexAttrib2fvARB;
1005       vfmt->VertexAttrib3fARB = vbo_VertexAttrib3fARB;
1006       vfmt->VertexAttrib3fvARB = vbo_VertexAttrib3fvARB;
1007       vfmt->VertexAttrib4fARB = vbo_VertexAttrib4fARB;
1008       vfmt->VertexAttrib4fvARB = vbo_VertexAttrib4fvARB;
1009    }
1010 
1011    /* Note that VertexAttrib4fNV is used from dlist.c and api_arrayelt.c so
1012     * they can have a single entrypoint for updating any of the legacy
1013     * attribs.
1014     */
1015    vfmt->VertexAttrib1fNV = vbo_VertexAttrib1fNV;
1016    vfmt->VertexAttrib1fvNV = vbo_VertexAttrib1fvNV;
1017    vfmt->VertexAttrib2fNV = vbo_VertexAttrib2fNV;
1018    vfmt->VertexAttrib2fvNV = vbo_VertexAttrib2fvNV;
1019    vfmt->VertexAttrib3fNV = vbo_VertexAttrib3fNV;
1020    vfmt->VertexAttrib3fvNV = vbo_VertexAttrib3fvNV;
1021    vfmt->VertexAttrib4fNV = vbo_VertexAttrib4fNV;
1022    vfmt->VertexAttrib4fvNV = vbo_VertexAttrib4fvNV;
1023 
1024    /* integer-valued */
1025    vfmt->VertexAttribI1i = vbo_VertexAttribI1i;
1026    vfmt->VertexAttribI2i = vbo_VertexAttribI2i;
1027    vfmt->VertexAttribI3i = vbo_VertexAttribI3i;
1028    vfmt->VertexAttribI4i = vbo_VertexAttribI4i;
1029    vfmt->VertexAttribI2iv = vbo_VertexAttribI2iv;
1030    vfmt->VertexAttribI3iv = vbo_VertexAttribI3iv;
1031    vfmt->VertexAttribI4iv = vbo_VertexAttribI4iv;
1032 
1033    /* unsigned integer-valued */
1034    vfmt->VertexAttribI1ui = vbo_VertexAttribI1ui;
1035    vfmt->VertexAttribI2ui = vbo_VertexAttribI2ui;
1036    vfmt->VertexAttribI3ui = vbo_VertexAttribI3ui;
1037    vfmt->VertexAttribI4ui = vbo_VertexAttribI4ui;
1038    vfmt->VertexAttribI2uiv = vbo_VertexAttribI2uiv;
1039    vfmt->VertexAttribI3uiv = vbo_VertexAttribI3uiv;
1040    vfmt->VertexAttribI4uiv = vbo_VertexAttribI4uiv;
1041 
1042    vfmt->Materialfv = vbo_Materialfv;
1043 
1044    vfmt->EdgeFlag = vbo_EdgeFlag;
1045    vfmt->Indexf = vbo_Indexf;
1046    vfmt->Indexfv = vbo_Indexfv;
1047 
1048    /* ARB_vertex_type_2_10_10_10_rev */
1049    vfmt->VertexP2ui = vbo_VertexP2ui;
1050    vfmt->VertexP2uiv = vbo_VertexP2uiv;
1051    vfmt->VertexP3ui = vbo_VertexP3ui;
1052    vfmt->VertexP3uiv = vbo_VertexP3uiv;
1053    vfmt->VertexP4ui = vbo_VertexP4ui;
1054    vfmt->VertexP4uiv = vbo_VertexP4uiv;
1055 
1056    vfmt->TexCoordP1ui = vbo_TexCoordP1ui;
1057    vfmt->TexCoordP1uiv = vbo_TexCoordP1uiv;
1058    vfmt->TexCoordP2ui = vbo_TexCoordP2ui;
1059    vfmt->TexCoordP2uiv = vbo_TexCoordP2uiv;
1060    vfmt->TexCoordP3ui = vbo_TexCoordP3ui;
1061    vfmt->TexCoordP3uiv = vbo_TexCoordP3uiv;
1062    vfmt->TexCoordP4ui = vbo_TexCoordP4ui;
1063    vfmt->TexCoordP4uiv = vbo_TexCoordP4uiv;
1064 
1065    vfmt->MultiTexCoordP1ui = vbo_MultiTexCoordP1ui;
1066    vfmt->MultiTexCoordP1uiv = vbo_MultiTexCoordP1uiv;
1067    vfmt->MultiTexCoordP2ui = vbo_MultiTexCoordP2ui;
1068    vfmt->MultiTexCoordP2uiv = vbo_MultiTexCoordP2uiv;
1069    vfmt->MultiTexCoordP3ui = vbo_MultiTexCoordP3ui;
1070    vfmt->MultiTexCoordP3uiv = vbo_MultiTexCoordP3uiv;
1071    vfmt->MultiTexCoordP4ui = vbo_MultiTexCoordP4ui;
1072    vfmt->MultiTexCoordP4uiv = vbo_MultiTexCoordP4uiv;
1073 
1074    vfmt->NormalP3ui = vbo_NormalP3ui;
1075    vfmt->NormalP3uiv = vbo_NormalP3uiv;
1076 
1077    vfmt->ColorP3ui = vbo_ColorP3ui;
1078    vfmt->ColorP3uiv = vbo_ColorP3uiv;
1079    vfmt->ColorP4ui = vbo_ColorP4ui;
1080    vfmt->ColorP4uiv = vbo_ColorP4uiv;
1081 
1082    vfmt->SecondaryColorP3ui = vbo_SecondaryColorP3ui;
1083    vfmt->SecondaryColorP3uiv = vbo_SecondaryColorP3uiv;
1084 
1085    vfmt->VertexAttribP1ui = vbo_VertexAttribP1ui;
1086    vfmt->VertexAttribP1uiv = vbo_VertexAttribP1uiv;
1087    vfmt->VertexAttribP2ui = vbo_VertexAttribP2ui;
1088    vfmt->VertexAttribP2uiv = vbo_VertexAttribP2uiv;
1089    vfmt->VertexAttribP3ui = vbo_VertexAttribP3ui;
1090    vfmt->VertexAttribP3uiv = vbo_VertexAttribP3uiv;
1091    vfmt->VertexAttribP4ui = vbo_VertexAttribP4ui;
1092    vfmt->VertexAttribP4uiv = vbo_VertexAttribP4uiv;
1093 
1094    vfmt->VertexAttribL1d = vbo_VertexAttribL1d;
1095    vfmt->VertexAttribL2d = vbo_VertexAttribL2d;
1096    vfmt->VertexAttribL3d = vbo_VertexAttribL3d;
1097    vfmt->VertexAttribL4d = vbo_VertexAttribL4d;
1098 
1099    vfmt->VertexAttribL1dv = vbo_VertexAttribL1dv;
1100    vfmt->VertexAttribL2dv = vbo_VertexAttribL2dv;
1101    vfmt->VertexAttribL3dv = vbo_VertexAttribL3dv;
1102    vfmt->VertexAttribL4dv = vbo_VertexAttribL4dv;
1103 
1104    vfmt->VertexAttribL1ui64ARB = vbo_VertexAttribL1ui64ARB;
1105    vfmt->VertexAttribL1ui64vARB = vbo_VertexAttribL1ui64vARB;
1106 }
1107 
1108 
1109 /**
1110  * Tell the VBO module to use a real OpenGL vertex buffer object to
1111  * store accumulated immediate-mode vertex data.
1112  * This replaces the malloced buffer which was created in
1113  * vb_exec_vtx_init() below.
1114  */
1115 void
vbo_use_buffer_objects(struct gl_context * ctx)1116 vbo_use_buffer_objects(struct gl_context *ctx)
1117 {
1118    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
1119    /* Any buffer name but 0 can be used here since this bufferobj won't
1120     * go into the bufferobj hashtable.
1121     */
1122    GLuint bufName = IMM_BUFFER_NAME;
1123    GLenum target = GL_ARRAY_BUFFER_ARB;
1124    GLenum usage = GL_STREAM_DRAW_ARB;
1125    GLsizei size = VBO_VERT_BUFFER_SIZE;
1126 
1127    /* Make sure this func is only used once */
1128    assert(exec->vtx.bufferobj == ctx->Shared->NullBufferObj);
1129 
1130    _mesa_align_free(exec->vtx.buffer_map);
1131    exec->vtx.buffer_map = NULL;
1132    exec->vtx.buffer_ptr = NULL;
1133 
1134    /* Allocate a real buffer object now */
1135    _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
1136    exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName);
1137    if (!ctx->Driver.BufferData(ctx, target, size, NULL, usage,
1138                                GL_MAP_WRITE_BIT |
1139                                GL_DYNAMIC_STORAGE_BIT |
1140                                GL_CLIENT_STORAGE_BIT,
1141                                exec->vtx.bufferobj)) {
1142       _mesa_error(ctx, GL_OUT_OF_MEMORY, "VBO allocation");
1143    }
1144 }
1145 
1146 
1147 /**
1148  * If this function is called, all VBO buffers will be unmapped when
1149  * we flush.
1150  * Otherwise, if a simple command like glColor3f() is called and we flush,
1151  * the current VBO may be left mapped.
1152  */
1153 void
vbo_always_unmap_buffers(struct gl_context * ctx)1154 vbo_always_unmap_buffers(struct gl_context *ctx)
1155 {
1156    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
1157    exec->begin_vertices_flags |= FLUSH_STORED_VERTICES;
1158 }
1159 
1160 
1161 void
vbo_exec_vtx_init(struct vbo_exec_context * exec)1162 vbo_exec_vtx_init(struct vbo_exec_context *exec)
1163 {
1164    struct gl_context *ctx = exec->ctx;
1165    struct vbo_context *vbo = vbo_context(ctx);
1166    GLuint i;
1167 
1168    /* Allocate a buffer object.  Will just reuse this object
1169     * continuously, unless vbo_use_buffer_objects() is called to enable
1170     * use of real VBOs.
1171     */
1172    _mesa_reference_buffer_object(ctx,
1173                                  &exec->vtx.bufferobj,
1174                                  ctx->Shared->NullBufferObj);
1175 
1176    assert(!exec->vtx.buffer_map);
1177    exec->vtx.buffer_map = _mesa_align_malloc(VBO_VERT_BUFFER_SIZE, 64);
1178    exec->vtx.buffer_ptr = exec->vtx.buffer_map;
1179 
1180    vbo_exec_vtxfmt_init(exec);
1181    _mesa_noop_vtxfmt_init(&exec->vtxfmt_noop);
1182 
1183    exec->vtx.enabled = 0;
1184    for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
1185       assert(i < ARRAY_SIZE(exec->vtx.attrsz));
1186       exec->vtx.attrsz[i] = 0;
1187       assert(i < ARRAY_SIZE(exec->vtx.attrtype));
1188       exec->vtx.attrtype[i] = GL_FLOAT;
1189       assert(i < ARRAY_SIZE(exec->vtx.active_sz));
1190       exec->vtx.active_sz[i] = 0;
1191    }
1192    for (i = 0 ; i < VERT_ATTRIB_MAX; i++) {
1193       assert(i < ARRAY_SIZE(exec->vtx.inputs));
1194       assert(i < ARRAY_SIZE(exec->vtx.arrays));
1195       exec->vtx.inputs[i] = &exec->vtx.arrays[i];
1196    }
1197 
1198    {
1199       struct gl_vertex_array *arrays = exec->vtx.arrays;
1200       unsigned i;
1201 
1202       memcpy(arrays, &vbo->currval[VBO_ATTRIB_POS],
1203              VERT_ATTRIB_FF_MAX * sizeof(arrays[0]));
1204       for (i = 0; i < VERT_ATTRIB_FF_MAX; ++i) {
1205          struct gl_vertex_array *array;
1206          array = &arrays[VERT_ATTRIB_FF(i)];
1207          array->BufferObj = NULL;
1208          _mesa_reference_buffer_object(ctx, &array->BufferObj,
1209                                        vbo->currval[VBO_ATTRIB_POS+i].BufferObj);
1210       }
1211 
1212       memcpy(arrays + VERT_ATTRIB_GENERIC(0),
1213              &vbo->currval[VBO_ATTRIB_GENERIC0],
1214              VERT_ATTRIB_GENERIC_MAX * sizeof(arrays[0]));
1215 
1216       for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; ++i) {
1217          struct gl_vertex_array *array;
1218          array = &arrays[VERT_ATTRIB_GENERIC(i)];
1219          array->BufferObj = NULL;
1220          _mesa_reference_buffer_object(ctx, &array->BufferObj,
1221                            vbo->currval[VBO_ATTRIB_GENERIC0+i].BufferObj);
1222       }
1223    }
1224 
1225    exec->vtx.vertex_size = 0;
1226 
1227    exec->begin_vertices_flags = FLUSH_UPDATE_CURRENT;
1228 }
1229 
1230 
1231 void
vbo_exec_vtx_destroy(struct vbo_exec_context * exec)1232 vbo_exec_vtx_destroy(struct vbo_exec_context *exec)
1233 {
1234    /* using a real VBO for vertex data */
1235    struct gl_context *ctx = exec->ctx;
1236    unsigned i;
1237 
1238    /* True VBOs should already be unmapped
1239     */
1240    if (exec->vtx.buffer_map) {
1241       assert(exec->vtx.bufferobj->Name == 0 ||
1242              exec->vtx.bufferobj->Name == IMM_BUFFER_NAME);
1243       if (exec->vtx.bufferobj->Name == 0) {
1244          _mesa_align_free(exec->vtx.buffer_map);
1245          exec->vtx.buffer_map = NULL;
1246          exec->vtx.buffer_ptr = NULL;
1247       }
1248    }
1249 
1250    /* Drop any outstanding reference to the vertex buffer
1251     */
1252    for (i = 0; i < ARRAY_SIZE(exec->vtx.arrays); i++) {
1253       _mesa_reference_buffer_object(ctx,
1254                                     &exec->vtx.arrays[i].BufferObj,
1255                                     NULL);
1256    }
1257 
1258    /* Free the vertex buffer.  Unmap first if needed.
1259     */
1260    if (_mesa_bufferobj_mapped(exec->vtx.bufferobj, MAP_INTERNAL)) {
1261       ctx->Driver.UnmapBuffer(ctx, exec->vtx.bufferobj, MAP_INTERNAL);
1262    }
1263    _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
1264 }
1265 
1266 
1267 /**
1268  * If inside glBegin()/glEnd(), it should assert(0).  Otherwise, if
1269  * FLUSH_STORED_VERTICES bit in \p flags is set flushes any buffered
1270  * vertices, if FLUSH_UPDATE_CURRENT bit is set updates
1271  * __struct gl_contextRec::Current and gl_light_attrib::Material
1272  *
1273  * Note that the default T&L engine never clears the
1274  * FLUSH_UPDATE_CURRENT bit, even after performing the update.
1275  *
1276  * \param flags  bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT
1277  */
1278 void
vbo_exec_FlushVertices(struct gl_context * ctx,GLuint flags)1279 vbo_exec_FlushVertices(struct gl_context *ctx, GLuint flags)
1280 {
1281    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
1282 
1283 #ifdef DEBUG
1284    /* debug check: make sure we don't get called recursively */
1285    exec->flush_call_depth++;
1286    assert(exec->flush_call_depth == 1);
1287 #endif
1288 
1289    if (_mesa_inside_begin_end(ctx)) {
1290       /* We've had glBegin but not glEnd! */
1291 #ifdef DEBUG
1292       exec->flush_call_depth--;
1293       assert(exec->flush_call_depth == 0);
1294 #endif
1295       return;
1296    }
1297 
1298    /* Flush (draw), and make sure VBO is left unmapped when done */
1299    vbo_exec_FlushVertices_internal(exec, GL_TRUE);
1300 
1301    /* Need to do this to ensure vbo_exec_begin_vertices gets called again:
1302     */
1303    ctx->Driver.NeedFlush &= ~(FLUSH_UPDATE_CURRENT | flags);
1304 
1305 #ifdef DEBUG
1306    exec->flush_call_depth--;
1307    assert(exec->flush_call_depth == 0);
1308 #endif
1309 }
1310 
1311 
1312 /**
1313  * Reset the vertex attribute by setting its size to zero.
1314  */
1315 static void
vbo_reset_attr(struct vbo_exec_context * exec,GLuint attr)1316 vbo_reset_attr(struct vbo_exec_context *exec, GLuint attr)
1317 {
1318    exec->vtx.attrsz[attr] = 0;
1319    exec->vtx.attrtype[attr] = GL_FLOAT;
1320    exec->vtx.active_sz[attr] = 0;
1321 }
1322 
1323 
1324 static void
vbo_reset_all_attr(struct vbo_exec_context * exec)1325 vbo_reset_all_attr(struct vbo_exec_context *exec)
1326 {
1327    while (exec->vtx.enabled) {
1328       const int i = u_bit_scan64(&exec->vtx.enabled);
1329       vbo_reset_attr(exec, i);
1330    }
1331 
1332    exec->vtx.vertex_size = 0;
1333 }
1334 
1335 
1336 void GLAPIENTRY
_es_Color4f(GLfloat r,GLfloat g,GLfloat b,GLfloat a)1337 _es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
1338 {
1339    vbo_Color4f(r, g, b, a);
1340 }
1341 
1342 
1343 void GLAPIENTRY
_es_Normal3f(GLfloat x,GLfloat y,GLfloat z)1344 _es_Normal3f(GLfloat x, GLfloat y, GLfloat z)
1345 {
1346    vbo_Normal3f(x, y, z);
1347 }
1348 
1349 
1350 void GLAPIENTRY
_es_MultiTexCoord4f(GLenum target,GLfloat s,GLfloat t,GLfloat r,GLfloat q)1351 _es_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
1352 {
1353    vbo_MultiTexCoord4f(target, s, t, r, q);
1354 }
1355 
1356 
1357 void GLAPIENTRY
_es_Materialfv(GLenum face,GLenum pname,const GLfloat * params)1358 _es_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
1359 {
1360    vbo_Materialfv(face, pname, params);
1361 }
1362 
1363 
1364 void GLAPIENTRY
_es_Materialf(GLenum face,GLenum pname,GLfloat param)1365 _es_Materialf(GLenum face, GLenum pname, GLfloat param)
1366 {
1367    GLfloat p[4];
1368    p[0] = param;
1369    p[1] = p[2] = p[3] = 0.0F;
1370    vbo_Materialfv(face, pname, p);
1371 }
1372 
1373 
1374 /**
1375  * A special version of glVertexAttrib4f that does not treat index 0 as
1376  * VBO_ATTRIB_POS.
1377  */
1378 static void
VertexAttrib4f_nopos(GLuint index,GLfloat x,GLfloat y,GLfloat z,GLfloat w)1379 VertexAttrib4f_nopos(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1380 {
1381    GET_CURRENT_CONTEXT(ctx);
1382    if (index < MAX_VERTEX_GENERIC_ATTRIBS)
1383       ATTRF(VBO_ATTRIB_GENERIC0 + index, 4, x, y, z, w);
1384    else
1385       ERROR(GL_INVALID_VALUE);
1386 }
1387 
1388 void GLAPIENTRY
_es_VertexAttrib4f(GLuint index,GLfloat x,GLfloat y,GLfloat z,GLfloat w)1389 _es_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1390 {
1391    VertexAttrib4f_nopos(index, x, y, z, w);
1392 }
1393 
1394 
1395 void GLAPIENTRY
_es_VertexAttrib1f(GLuint indx,GLfloat x)1396 _es_VertexAttrib1f(GLuint indx, GLfloat x)
1397 {
1398    VertexAttrib4f_nopos(indx, x, 0.0f, 0.0f, 1.0f);
1399 }
1400 
1401 
1402 void GLAPIENTRY
_es_VertexAttrib1fv(GLuint indx,const GLfloat * values)1403 _es_VertexAttrib1fv(GLuint indx, const GLfloat* values)
1404 {
1405    VertexAttrib4f_nopos(indx, values[0], 0.0f, 0.0f, 1.0f);
1406 }
1407 
1408 
1409 void GLAPIENTRY
_es_VertexAttrib2f(GLuint indx,GLfloat x,GLfloat y)1410 _es_VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
1411 {
1412    VertexAttrib4f_nopos(indx, x, y, 0.0f, 1.0f);
1413 }
1414 
1415 
1416 void GLAPIENTRY
_es_VertexAttrib2fv(GLuint indx,const GLfloat * values)1417 _es_VertexAttrib2fv(GLuint indx, const GLfloat* values)
1418 {
1419    VertexAttrib4f_nopos(indx, values[0], values[1], 0.0f, 1.0f);
1420 }
1421 
1422 
1423 void GLAPIENTRY
_es_VertexAttrib3f(GLuint indx,GLfloat x,GLfloat y,GLfloat z)1424 _es_VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
1425 {
1426    VertexAttrib4f_nopos(indx, x, y, z, 1.0f);
1427 }
1428 
1429 
1430 void GLAPIENTRY
_es_VertexAttrib3fv(GLuint indx,const GLfloat * values)1431 _es_VertexAttrib3fv(GLuint indx, const GLfloat* values)
1432 {
1433    VertexAttrib4f_nopos(indx, values[0], values[1], values[2], 1.0f);
1434 }
1435 
1436 
1437 void GLAPIENTRY
_es_VertexAttrib4fv(GLuint indx,const GLfloat * values)1438 _es_VertexAttrib4fv(GLuint indx, const GLfloat* values)
1439 {
1440    VertexAttrib4f_nopos(indx, values[0], values[1], values[2], values[3]);
1441 }
1442