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