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