draw: corrections to allow for different cliptest cases
[mesa.git] / src / mesa / vbo / vbo_exec_api.c
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/vtxfmt.h"
38 #include "main/dlist.h"
39 #include "main/eval.h"
40 #include "main/state.h"
41 #include "main/light.h"
42 #include "main/api_arrayelt.h"
43 #include "main/api_noop.h"
44 #include "main/dispatch.h"
45
46 #include "vbo_context.h"
47
48 #ifdef ERROR
49 #undef ERROR
50 #endif
51
52
53 /** ID/name for immediate-mode VBO */
54 #define IMM_BUFFER_NAME 0xaabbccdd
55
56
57 static void reset_attrfv( struct vbo_exec_context *exec );
58
59
60 /**
61 * Close off the last primitive, execute the buffer, restart the
62 * primitive.
63 */
64 static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec )
65 {
66 if (exec->vtx.prim_count == 0) {
67 exec->vtx.copied.nr = 0;
68 exec->vtx.vert_count = 0;
69 exec->vtx.buffer_ptr = exec->vtx.buffer_map;
70 }
71 else {
72 GLuint last_begin = exec->vtx.prim[exec->vtx.prim_count-1].begin;
73 GLuint last_count;
74
75 if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
76 GLint i = exec->vtx.prim_count - 1;
77 assert(i >= 0);
78 exec->vtx.prim[i].count = (exec->vtx.vert_count -
79 exec->vtx.prim[i].start);
80 }
81
82 last_count = exec->vtx.prim[exec->vtx.prim_count-1].count;
83
84 /* Execute the buffer and save copied vertices.
85 */
86 if (exec->vtx.vert_count)
87 vbo_exec_vtx_flush( exec, GL_FALSE );
88 else {
89 exec->vtx.prim_count = 0;
90 exec->vtx.copied.nr = 0;
91 }
92
93 /* Emit a glBegin to start the new list.
94 */
95 assert(exec->vtx.prim_count == 0);
96
97 if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
98 exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive;
99 exec->vtx.prim[0].start = 0;
100 exec->vtx.prim[0].count = 0;
101 exec->vtx.prim_count++;
102
103 if (exec->vtx.copied.nr == last_count)
104 exec->vtx.prim[0].begin = last_begin;
105 }
106 }
107 }
108
109
110 /**
111 * Deal with buffer wrapping where provoked by the vertex buffer
112 * filling up, as opposed to upgrade_vertex().
113 */
114 void vbo_exec_vtx_wrap( struct vbo_exec_context *exec )
115 {
116 GLfloat *data = exec->vtx.copied.buffer;
117 GLuint i;
118
119 /* Run pipeline on current vertices, copy wrapped vertices
120 * to exec->vtx.copied.
121 */
122 vbo_exec_wrap_buffers( exec );
123
124 /* Copy stored stored vertices to start of new list.
125 */
126 assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr);
127
128 for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
129 memcpy( exec->vtx.buffer_ptr, data,
130 exec->vtx.vertex_size * sizeof(GLfloat));
131 exec->vtx.buffer_ptr += exec->vtx.vertex_size;
132 data += exec->vtx.vertex_size;
133 exec->vtx.vert_count++;
134 }
135
136 exec->vtx.copied.nr = 0;
137 }
138
139
140 /**
141 * Copy the active vertex's values to the ctx->Current fields.
142 */
143 static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
144 {
145 GLcontext *ctx = exec->ctx;
146 struct vbo_context *vbo = vbo_context(ctx);
147 GLuint i;
148
149 for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
150 if (exec->vtx.attrsz[i]) {
151 /* Note: the exec->vtx.current[i] pointers point into the
152 * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
153 */
154 GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
155 GLfloat tmp[4];
156
157 COPY_CLEAN_4V(tmp,
158 exec->vtx.attrsz[i],
159 exec->vtx.attrptr[i]);
160
161 if (memcmp(current, tmp, sizeof(tmp)) != 0)
162 {
163 memcpy(current, tmp, sizeof(tmp));
164
165 /* Given that we explicitly state size here, there is no need
166 * for the COPY_CLEAN above, could just copy 16 bytes and be
167 * done. The only problem is when Mesa accesses ctx->Current
168 * directly.
169 */
170 vbo->currval[i].Size = exec->vtx.attrsz[i];
171
172 /* This triggers rather too much recalculation of Mesa state
173 * that doesn't get used (eg light positions).
174 */
175 if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
176 i <= VBO_ATTRIB_MAT_BACK_INDEXES)
177 ctx->NewState |= _NEW_LIGHT;
178
179 ctx->NewState |= _NEW_CURRENT_ATTRIB;
180 }
181 }
182 }
183
184 /* Colormaterial -- this kindof sucks.
185 */
186 if (ctx->Light.ColorMaterialEnabled &&
187 exec->vtx.attrsz[VBO_ATTRIB_COLOR0]) {
188 _mesa_update_color_material(ctx,
189 ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
190 }
191 }
192
193
194 static void vbo_exec_copy_from_current( struct vbo_exec_context *exec )
195 {
196 GLcontext *ctx = exec->ctx;
197 struct vbo_context *vbo = vbo_context(ctx);
198 GLint i;
199
200 for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
201 const GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
202 switch (exec->vtx.attrsz[i]) {
203 case 4: exec->vtx.attrptr[i][3] = current[3];
204 case 3: exec->vtx.attrptr[i][2] = current[2];
205 case 2: exec->vtx.attrptr[i][1] = current[1];
206 case 1: exec->vtx.attrptr[i][0] = current[0];
207 break;
208 }
209 }
210 }
211
212
213 /**
214 * Flush existing data, set new attrib size, replay copied vertices.
215 */
216 static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec,
217 GLuint attr,
218 GLuint newsz )
219 {
220 GLcontext *ctx = exec->ctx;
221 struct vbo_context *vbo = vbo_context(ctx);
222 GLint lastcount = exec->vtx.vert_count;
223 GLfloat *tmp;
224 GLuint oldsz;
225 GLuint i;
226
227 /* Run pipeline on current vertices, copy wrapped vertices
228 * to exec->vtx.copied.
229 */
230 vbo_exec_wrap_buffers( exec );
231
232
233 /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
234 * when the attribute already exists in the vertex and is having
235 * its size increased.
236 */
237 vbo_exec_copy_to_current( exec );
238
239
240 /* Heuristic: Attempt to isolate attributes received outside
241 * begin/end so that they don't bloat the vertices.
242 */
243 if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END &&
244 exec->vtx.attrsz[attr] == 0 &&
245 lastcount > 8 &&
246 exec->vtx.vertex_size) {
247 reset_attrfv( exec );
248 }
249
250 /* Fix up sizes:
251 */
252 oldsz = exec->vtx.attrsz[attr];
253 exec->vtx.attrsz[attr] = newsz;
254
255 exec->vtx.vertex_size += newsz - oldsz;
256 exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) /
257 (exec->vtx.vertex_size * sizeof(GLfloat)));
258 exec->vtx.vert_count = 0;
259 exec->vtx.buffer_ptr = exec->vtx.buffer_map;
260
261
262 /* Recalculate all the attrptr[] values
263 */
264 for (i = 0, tmp = exec->vtx.vertex ; i < VBO_ATTRIB_MAX ; i++) {
265 if (exec->vtx.attrsz[i]) {
266 exec->vtx.attrptr[i] = tmp;
267 tmp += exec->vtx.attrsz[i];
268 }
269 else
270 exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */
271 }
272
273 /* Copy from current to repopulate the vertex with correct values.
274 */
275 vbo_exec_copy_from_current( exec );
276
277 /* Replay stored vertices to translate them
278 * to new format here.
279 *
280 * -- No need to replay - just copy piecewise
281 */
282 if (exec->vtx.copied.nr)
283 {
284 GLfloat *data = exec->vtx.copied.buffer;
285 GLfloat *dest = exec->vtx.buffer_ptr;
286 GLuint j;
287
288 assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map);
289
290 for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
291 for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) {
292 if (exec->vtx.attrsz[j]) {
293 if (j == attr) {
294 if (oldsz) {
295 COPY_CLEAN_4V( dest, oldsz, data );
296 data += oldsz;
297 dest += newsz;
298 } else {
299 const GLfloat *current = (const GLfloat *)vbo->currval[j].Ptr;
300 COPY_SZ_4V( dest, newsz, current );
301 dest += newsz;
302 }
303 }
304 else {
305 GLuint sz = exec->vtx.attrsz[j];
306 COPY_SZ_4V( dest, sz, data );
307 dest += sz;
308 data += sz;
309 }
310 }
311 }
312 }
313
314 exec->vtx.buffer_ptr = dest;
315 exec->vtx.vert_count += exec->vtx.copied.nr;
316 exec->vtx.copied.nr = 0;
317 }
318 }
319
320
321 static void vbo_exec_fixup_vertex( GLcontext *ctx,
322 GLuint attr, GLuint sz )
323 {
324 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
325 int i;
326
327 if (sz > exec->vtx.attrsz[attr]) {
328 /* New size is larger. Need to flush existing vertices and get
329 * an enlarged vertex format.
330 */
331 vbo_exec_wrap_upgrade_vertex( exec, attr, sz );
332 }
333 else if (sz < exec->vtx.active_sz[attr]) {
334 static const GLfloat id[4] = { 0, 0, 0, 1 };
335
336 /* New size is smaller - just need to fill in some
337 * zeros. Don't need to flush or wrap.
338 */
339 for (i = sz ; i <= exec->vtx.attrsz[attr] ; i++)
340 exec->vtx.attrptr[attr][i-1] = id[i-1];
341 }
342
343 exec->vtx.active_sz[attr] = sz;
344
345 /* Does setting NeedFlush belong here? Necessitates resetting
346 * vtxfmt on each flush (otherwise flags won't get reset
347 * afterwards).
348 */
349 if (attr == 0)
350 exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
351 }
352
353
354 #if FEATURE_beginend
355
356 /*
357 */
358 #define ATTR( A, N, V0, V1, V2, V3 ) \
359 do { \
360 struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \
361 \
362 if (exec->vtx.active_sz[A] != N) \
363 vbo_exec_fixup_vertex(ctx, A, N); \
364 \
365 { \
366 GLfloat *dest = exec->vtx.attrptr[A]; \
367 if (N>0) dest[0] = V0; \
368 if (N>1) dest[1] = V1; \
369 if (N>2) dest[2] = V2; \
370 if (N>3) dest[3] = V3; \
371 } \
372 \
373 if ((A) == 0) { \
374 GLuint i; \
375 \
376 for (i = 0; i < exec->vtx.vertex_size; i++) \
377 exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i]; \
378 \
379 exec->vtx.buffer_ptr += exec->vtx.vertex_size; \
380 exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \
381 \
382 if (++exec->vtx.vert_count >= exec->vtx.max_vert) \
383 vbo_exec_vtx_wrap( exec ); \
384 } \
385 } while (0)
386
387
388 #define ERROR() _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ )
389 #define TAG(x) vbo_##x
390
391 #include "vbo_attrib_tmp.h"
392
393
394
395
396
397 #if FEATURE_evaluators
398
399 static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u )
400 {
401 GET_CURRENT_CONTEXT( ctx );
402 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
403
404 {
405 GLint i;
406 if (exec->eval.recalculate_maps)
407 vbo_exec_eval_update( exec );
408
409 for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
410 if (exec->eval.map1[i].map)
411 if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz)
412 vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz );
413 }
414 }
415
416
417 memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
418 exec->vtx.vertex_size * sizeof(GLfloat));
419
420 vbo_exec_do_EvalCoord1f( exec, u );
421
422 memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
423 exec->vtx.vertex_size * sizeof(GLfloat));
424 }
425
426 static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v )
427 {
428 GET_CURRENT_CONTEXT( ctx );
429 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
430
431 {
432 GLint i;
433 if (exec->eval.recalculate_maps)
434 vbo_exec_eval_update( exec );
435
436 for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
437 if (exec->eval.map2[i].map)
438 if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz)
439 vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz );
440 }
441
442 if (ctx->Eval.AutoNormal)
443 if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3)
444 vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3 );
445 }
446
447 memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
448 exec->vtx.vertex_size * sizeof(GLfloat));
449
450 vbo_exec_do_EvalCoord2f( exec, u, v );
451
452 memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
453 exec->vtx.vertex_size * sizeof(GLfloat));
454 }
455
456 static void GLAPIENTRY vbo_exec_EvalCoord1fv( const GLfloat *u )
457 {
458 vbo_exec_EvalCoord1f( u[0] );
459 }
460
461 static void GLAPIENTRY vbo_exec_EvalCoord2fv( const GLfloat *u )
462 {
463 vbo_exec_EvalCoord2f( u[0], u[1] );
464 }
465
466 static void GLAPIENTRY vbo_exec_EvalPoint1( GLint i )
467 {
468 GET_CURRENT_CONTEXT( ctx );
469 GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) /
470 (GLfloat) ctx->Eval.MapGrid1un);
471 GLfloat u = i * du + ctx->Eval.MapGrid1u1;
472
473 vbo_exec_EvalCoord1f( u );
474 }
475
476
477 static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j )
478 {
479 GET_CURRENT_CONTEXT( ctx );
480 GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) /
481 (GLfloat) ctx->Eval.MapGrid2un);
482 GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) /
483 (GLfloat) ctx->Eval.MapGrid2vn);
484 GLfloat u = i * du + ctx->Eval.MapGrid2u1;
485 GLfloat v = j * dv + ctx->Eval.MapGrid2v1;
486
487 vbo_exec_EvalCoord2f( u, v );
488 }
489
490 /* use noop eval mesh */
491 #define vbo_exec_EvalMesh1 _mesa_noop_EvalMesh1
492 #define vbo_exec_EvalMesh2 _mesa_noop_EvalMesh2
493
494 #endif /* FEATURE_evaluators */
495
496
497 /**
498 * Called via glBegin.
499 */
500 static void GLAPIENTRY vbo_exec_Begin( GLenum mode )
501 {
502 GET_CURRENT_CONTEXT( ctx );
503
504 if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) {
505 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
506 int i;
507
508 if (ctx->NewState) {
509 _mesa_update_state( ctx );
510
511 CALL_Begin(ctx->Exec, (mode));
512 return;
513 }
514
515 if (!_mesa_valid_to_render(ctx, "glBegin")) {
516 return;
517 }
518
519 /* Heuristic: attempt to isolate attributes occuring outside
520 * begin/end pairs.
521 */
522 if (exec->vtx.vertex_size && !exec->vtx.attrsz[0])
523 vbo_exec_FlushVertices_internal( ctx, GL_FALSE );
524
525 i = exec->vtx.prim_count++;
526 exec->vtx.prim[i].mode = mode;
527 exec->vtx.prim[i].begin = 1;
528 exec->vtx.prim[i].end = 0;
529 exec->vtx.prim[i].indexed = 0;
530 exec->vtx.prim[i].weak = 0;
531 exec->vtx.prim[i].pad = 0;
532 exec->vtx.prim[i].start = exec->vtx.vert_count;
533 exec->vtx.prim[i].count = 0;
534 exec->vtx.prim[i].num_instances = 1;
535
536 ctx->Driver.CurrentExecPrimitive = mode;
537 }
538 else
539 _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
540
541 }
542
543
544 /**
545 * Called via glEnd.
546 */
547 static void GLAPIENTRY vbo_exec_End( void )
548 {
549 GET_CURRENT_CONTEXT( ctx );
550
551 if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
552 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
553 int idx = exec->vtx.vert_count;
554 int i = exec->vtx.prim_count - 1;
555
556 exec->vtx.prim[i].end = 1;
557 exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start;
558
559 ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
560
561 if (exec->vtx.prim_count == VBO_MAX_PRIM)
562 vbo_exec_vtx_flush( exec, GL_FALSE );
563 }
564 else
565 _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
566 }
567
568
569 static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
570 {
571 GLvertexformat *vfmt = &exec->vtxfmt;
572
573 _MESA_INIT_ARRAYELT_VTXFMT(vfmt, _ae_);
574
575 vfmt->Begin = vbo_exec_Begin;
576 vfmt->End = vbo_exec_End;
577
578 _MESA_INIT_DLIST_VTXFMT(vfmt, _mesa_);
579 _MESA_INIT_EVAL_VTXFMT(vfmt, vbo_exec_);
580
581 vfmt->Rectf = _mesa_noop_Rectf;
582
583 /* from attrib_tmp.h:
584 */
585 vfmt->Color3f = vbo_Color3f;
586 vfmt->Color3fv = vbo_Color3fv;
587 vfmt->Color4f = vbo_Color4f;
588 vfmt->Color4fv = vbo_Color4fv;
589 vfmt->FogCoordfEXT = vbo_FogCoordfEXT;
590 vfmt->FogCoordfvEXT = vbo_FogCoordfvEXT;
591 vfmt->MultiTexCoord1fARB = vbo_MultiTexCoord1f;
592 vfmt->MultiTexCoord1fvARB = vbo_MultiTexCoord1fv;
593 vfmt->MultiTexCoord2fARB = vbo_MultiTexCoord2f;
594 vfmt->MultiTexCoord2fvARB = vbo_MultiTexCoord2fv;
595 vfmt->MultiTexCoord3fARB = vbo_MultiTexCoord3f;
596 vfmt->MultiTexCoord3fvARB = vbo_MultiTexCoord3fv;
597 vfmt->MultiTexCoord4fARB = vbo_MultiTexCoord4f;
598 vfmt->MultiTexCoord4fvARB = vbo_MultiTexCoord4fv;
599 vfmt->Normal3f = vbo_Normal3f;
600 vfmt->Normal3fv = vbo_Normal3fv;
601 vfmt->SecondaryColor3fEXT = vbo_SecondaryColor3fEXT;
602 vfmt->SecondaryColor3fvEXT = vbo_SecondaryColor3fvEXT;
603 vfmt->TexCoord1f = vbo_TexCoord1f;
604 vfmt->TexCoord1fv = vbo_TexCoord1fv;
605 vfmt->TexCoord2f = vbo_TexCoord2f;
606 vfmt->TexCoord2fv = vbo_TexCoord2fv;
607 vfmt->TexCoord3f = vbo_TexCoord3f;
608 vfmt->TexCoord3fv = vbo_TexCoord3fv;
609 vfmt->TexCoord4f = vbo_TexCoord4f;
610 vfmt->TexCoord4fv = vbo_TexCoord4fv;
611 vfmt->Vertex2f = vbo_Vertex2f;
612 vfmt->Vertex2fv = vbo_Vertex2fv;
613 vfmt->Vertex3f = vbo_Vertex3f;
614 vfmt->Vertex3fv = vbo_Vertex3fv;
615 vfmt->Vertex4f = vbo_Vertex4f;
616 vfmt->Vertex4fv = vbo_Vertex4fv;
617
618 vfmt->VertexAttrib1fARB = vbo_VertexAttrib1fARB;
619 vfmt->VertexAttrib1fvARB = vbo_VertexAttrib1fvARB;
620 vfmt->VertexAttrib2fARB = vbo_VertexAttrib2fARB;
621 vfmt->VertexAttrib2fvARB = vbo_VertexAttrib2fvARB;
622 vfmt->VertexAttrib3fARB = vbo_VertexAttrib3fARB;
623 vfmt->VertexAttrib3fvARB = vbo_VertexAttrib3fvARB;
624 vfmt->VertexAttrib4fARB = vbo_VertexAttrib4fARB;
625 vfmt->VertexAttrib4fvARB = vbo_VertexAttrib4fvARB;
626
627 vfmt->VertexAttrib1fNV = vbo_VertexAttrib1fNV;
628 vfmt->VertexAttrib1fvNV = vbo_VertexAttrib1fvNV;
629 vfmt->VertexAttrib2fNV = vbo_VertexAttrib2fNV;
630 vfmt->VertexAttrib2fvNV = vbo_VertexAttrib2fvNV;
631 vfmt->VertexAttrib3fNV = vbo_VertexAttrib3fNV;
632 vfmt->VertexAttrib3fvNV = vbo_VertexAttrib3fvNV;
633 vfmt->VertexAttrib4fNV = vbo_VertexAttrib4fNV;
634 vfmt->VertexAttrib4fvNV = vbo_VertexAttrib4fvNV;
635
636 vfmt->Materialfv = vbo_Materialfv;
637
638 vfmt->EdgeFlag = vbo_EdgeFlag;
639 vfmt->Indexf = vbo_Indexf;
640 vfmt->Indexfv = vbo_Indexfv;
641
642 }
643
644
645 #else /* FEATURE_beginend */
646
647
648 #define ATTR( A, N, V0, V1, V2, V3 ) \
649 do { \
650 struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \
651 \
652 /* FLUSH_UPDATE_CURRENT needs to be set manually */ \
653 exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \
654 \
655 if (exec->vtx.active_sz[A] != N) \
656 vbo_exec_fixup_vertex(ctx, A, N); \
657 \
658 { \
659 GLfloat *dest = exec->vtx.attrptr[A]; \
660 if (N>0) dest[0] = V0; \
661 if (N>1) dest[1] = V1; \
662 if (N>2) dest[2] = V2; \
663 if (N>3) dest[3] = V3; \
664 } \
665 } while (0)
666
667 #define ERROR() _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ )
668 #define TAG(x) vbo_##x
669
670 #include "vbo_attrib_tmp.h"
671
672 static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
673 {
674 /* silence warnings */
675 (void) vbo_Color3f;
676 (void) vbo_Color3fv;
677 (void) vbo_Color4f;
678 (void) vbo_Color4fv;
679 (void) vbo_FogCoordfEXT;
680 (void) vbo_FogCoordfvEXT;
681 (void) vbo_MultiTexCoord1f;
682 (void) vbo_MultiTexCoord1fv;
683 (void) vbo_MultiTexCoord2f;
684 (void) vbo_MultiTexCoord2fv;
685 (void) vbo_MultiTexCoord3f;
686 (void) vbo_MultiTexCoord3fv;
687 (void) vbo_MultiTexCoord4f;
688 (void) vbo_MultiTexCoord4fv;
689 (void) vbo_Normal3f;
690 (void) vbo_Normal3fv;
691 (void) vbo_SecondaryColor3fEXT;
692 (void) vbo_SecondaryColor3fvEXT;
693 (void) vbo_TexCoord1f;
694 (void) vbo_TexCoord1fv;
695 (void) vbo_TexCoord2f;
696 (void) vbo_TexCoord2fv;
697 (void) vbo_TexCoord3f;
698 (void) vbo_TexCoord3fv;
699 (void) vbo_TexCoord4f;
700 (void) vbo_TexCoord4fv;
701 (void) vbo_Vertex2f;
702 (void) vbo_Vertex2fv;
703 (void) vbo_Vertex3f;
704 (void) vbo_Vertex3fv;
705 (void) vbo_Vertex4f;
706 (void) vbo_Vertex4fv;
707
708 (void) vbo_VertexAttrib1fARB;
709 (void) vbo_VertexAttrib1fvARB;
710 (void) vbo_VertexAttrib2fARB;
711 (void) vbo_VertexAttrib2fvARB;
712 (void) vbo_VertexAttrib3fARB;
713 (void) vbo_VertexAttrib3fvARB;
714 (void) vbo_VertexAttrib4fARB;
715 (void) vbo_VertexAttrib4fvARB;
716
717 (void) vbo_VertexAttrib1fNV;
718 (void) vbo_VertexAttrib1fvNV;
719 (void) vbo_VertexAttrib2fNV;
720 (void) vbo_VertexAttrib2fvNV;
721 (void) vbo_VertexAttrib3fNV;
722 (void) vbo_VertexAttrib3fvNV;
723 (void) vbo_VertexAttrib4fNV;
724 (void) vbo_VertexAttrib4fvNV;
725
726 (void) vbo_Materialfv;
727
728 (void) vbo_EdgeFlag;
729 (void) vbo_Indexf;
730 (void) vbo_Indexfv;
731 }
732
733
734 #endif /* FEATURE_beginend */
735
736
737 /**
738 * Tell the VBO module to use a real OpenGL vertex buffer object to
739 * store accumulated immediate-mode vertex data.
740 * This replaces the malloced buffer which was created in
741 * vb_exec_vtx_init() below.
742 */
743 void vbo_use_buffer_objects(GLcontext *ctx)
744 {
745 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
746 /* Any buffer name but 0 can be used here since this bufferobj won't
747 * go into the bufferobj hashtable.
748 */
749 GLuint bufName = IMM_BUFFER_NAME;
750 GLenum target = GL_ARRAY_BUFFER_ARB;
751 GLenum usage = GL_STREAM_DRAW_ARB;
752 GLsizei size = VBO_VERT_BUFFER_SIZE;
753
754 /* Make sure this func is only used once */
755 assert(exec->vtx.bufferobj == ctx->Shared->NullBufferObj);
756 if (exec->vtx.buffer_map) {
757 _mesa_align_free(exec->vtx.buffer_map);
758 exec->vtx.buffer_map = NULL;
759 exec->vtx.buffer_ptr = NULL;
760 }
761
762 /* Allocate a real buffer object now */
763 _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
764 exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName, target);
765 ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj);
766 }
767
768
769
770 void vbo_exec_vtx_init( struct vbo_exec_context *exec )
771 {
772 GLcontext *ctx = exec->ctx;
773 struct vbo_context *vbo = vbo_context(ctx);
774 GLuint i;
775
776 /* Allocate a buffer object. Will just reuse this object
777 * continuously, unless vbo_use_buffer_objects() is called to enable
778 * use of real VBOs.
779 */
780 _mesa_reference_buffer_object(ctx,
781 &exec->vtx.bufferobj,
782 ctx->Shared->NullBufferObj);
783
784 ASSERT(!exec->vtx.buffer_map);
785 exec->vtx.buffer_map = (GLfloat *)_mesa_align_malloc(VBO_VERT_BUFFER_SIZE, 64);
786 exec->vtx.buffer_ptr = exec->vtx.buffer_map;
787
788 vbo_exec_vtxfmt_init( exec );
789
790 /* Hook our functions into the dispatch table.
791 */
792 _mesa_install_exec_vtxfmt( exec->ctx, &exec->vtxfmt );
793
794 for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
795 ASSERT(i < Elements(exec->vtx.attrsz));
796 exec->vtx.attrsz[i] = 0;
797 ASSERT(i < Elements(exec->vtx.active_sz));
798 exec->vtx.active_sz[i] = 0;
799 }
800 for (i = 0 ; i < VERT_ATTRIB_MAX; i++) {
801 ASSERT(i < Elements(exec->vtx.inputs));
802 ASSERT(i < Elements(exec->vtx.arrays));
803 exec->vtx.inputs[i] = &exec->vtx.arrays[i];
804 }
805
806 {
807 struct gl_client_array *arrays = exec->vtx.arrays;
808 unsigned i;
809
810 memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0]));
811 memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0]));
812
813 for (i = 0; i < 16; ++i) {
814 arrays[i ].BufferObj = NULL;
815 arrays[i + 16].BufferObj = NULL;
816 _mesa_reference_buffer_object(ctx, &arrays[i ].BufferObj,
817 vbo->legacy_currval[i].BufferObj);
818 _mesa_reference_buffer_object(ctx, &arrays[i + 16].BufferObj,
819 vbo->generic_currval[i].BufferObj);
820 }
821 }
822
823 exec->vtx.vertex_size = 0;
824 }
825
826
827 void vbo_exec_vtx_destroy( struct vbo_exec_context *exec )
828 {
829 /* using a real VBO for vertex data */
830 GLcontext *ctx = exec->ctx;
831 unsigned i;
832
833 /* True VBOs should already be unmapped
834 */
835 if (exec->vtx.buffer_map) {
836 ASSERT(exec->vtx.bufferobj->Name == 0 ||
837 exec->vtx.bufferobj->Name == IMM_BUFFER_NAME);
838 if (exec->vtx.bufferobj->Name == 0) {
839 _mesa_align_free(exec->vtx.buffer_map);
840 exec->vtx.buffer_map = NULL;
841 exec->vtx.buffer_ptr = NULL;
842 }
843 }
844
845 /* Drop any outstanding reference to the vertex buffer
846 */
847 for (i = 0; i < Elements(exec->vtx.arrays); i++) {
848 _mesa_reference_buffer_object(ctx,
849 &exec->vtx.arrays[i].BufferObj,
850 NULL);
851 }
852
853 /* Free the vertex buffer. Unmap first if needed.
854 */
855 if (_mesa_bufferobj_mapped(exec->vtx.bufferobj)) {
856 ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, exec->vtx.bufferobj);
857 }
858 _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
859 }
860
861 void vbo_exec_BeginVertices( GLcontext *ctx )
862 {
863 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
864 if (0) printf("%s\n", __FUNCTION__);
865 vbo_exec_vtx_map( exec );
866
867 assert((exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0);
868 exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
869 }
870
871 void vbo_exec_FlushVertices_internal( GLcontext *ctx, GLboolean unmap )
872 {
873 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
874
875 if (exec->vtx.vert_count || unmap) {
876 vbo_exec_vtx_flush( exec, unmap );
877 }
878
879 if (exec->vtx.vertex_size) {
880 vbo_exec_copy_to_current( exec );
881 reset_attrfv( exec );
882 }
883 }
884
885
886 /**
887 * \param flags bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT
888 */
889 void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags )
890 {
891 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
892
893 #ifdef DEBUG
894 /* debug check: make sure we don't get called recursively */
895 exec->flush_call_depth++;
896 assert(exec->flush_call_depth == 1);
897 #endif
898
899 if (0) printf("%s\n", __FUNCTION__);
900
901 if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
902 if (0) printf("%s - inside begin/end\n", __FUNCTION__);
903 #ifdef DEBUG
904 exec->flush_call_depth--;
905 assert(exec->flush_call_depth == 0);
906 #endif
907 return;
908 }
909
910 vbo_exec_FlushVertices_internal( ctx, GL_TRUE );
911
912 /* Need to do this to ensure BeginVertices gets called again:
913 */
914 if (exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) {
915 _mesa_restore_exec_vtxfmt( ctx );
916 exec->ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
917 }
918
919 exec->ctx->Driver.NeedFlush &= ~flags;
920
921 #ifdef DEBUG
922 exec->flush_call_depth--;
923 assert(exec->flush_call_depth == 0);
924 #endif
925 }
926
927
928 static void reset_attrfv( struct vbo_exec_context *exec )
929 {
930 GLuint i;
931
932 for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
933 exec->vtx.attrsz[i] = 0;
934 exec->vtx.active_sz[i] = 0;
935 }
936
937 exec->vtx.vertex_size = 0;
938 }
939
940
941 void GLAPIENTRY
942 _vbo_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
943 {
944 vbo_Color4f(r, g, b, a);
945 }
946
947
948 void GLAPIENTRY
949 _vbo_Normal3f(GLfloat x, GLfloat y, GLfloat z)
950 {
951 vbo_Normal3f(x, y, z);
952 }
953
954
955 void GLAPIENTRY
956 _vbo_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
957 {
958 vbo_MultiTexCoord4f(target, s, t, r, q);
959 }
960
961
962 void GLAPIENTRY
963 _vbo_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
964 {
965 vbo_Materialfv(face, pname, params);
966 }
967
968
969 void GLAPIENTRY
970 _vbo_Materialf(GLenum face, GLenum pname, GLfloat param)
971 {
972 GLfloat p[4];
973 p[0] = param;
974 p[1] = p[2] = p[3] = 0.0F;
975 vbo_Materialfv(face, pname, p);
976 }
977
978
979 void GLAPIENTRY
980 _vbo_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
981 {
982 vbo_VertexAttrib4fARB(index, x, y, z, w);
983 }
984
985
986 void GLAPIENTRY
987 _vbo_VertexAttrib1f(GLuint indx, GLfloat x)
988 {
989 vbo_VertexAttrib1fARB(indx, x);
990 }
991
992
993 void GLAPIENTRY
994 _vbo_VertexAttrib1fv(GLuint indx, const GLfloat* values)
995 {
996 vbo_VertexAttrib1fvARB(indx, values);
997 }
998
999
1000 void GLAPIENTRY
1001 _vbo_VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
1002 {
1003 vbo_VertexAttrib2fARB(indx, x, y);
1004 }
1005
1006
1007 void GLAPIENTRY
1008 _vbo_VertexAttrib2fv(GLuint indx, const GLfloat* values)
1009 {
1010 vbo_VertexAttrib2fvARB(indx, values);
1011 }
1012
1013
1014 void GLAPIENTRY
1015 _vbo_VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
1016 {
1017 vbo_VertexAttrib3fARB(indx, x, y, z);
1018 }
1019
1020
1021 void GLAPIENTRY
1022 _vbo_VertexAttrib3fv(GLuint indx, const GLfloat* values)
1023 {
1024 vbo_VertexAttrib3fvARB(indx, values);
1025 }
1026
1027
1028 void GLAPIENTRY
1029 _vbo_VertexAttrib4fv(GLuint indx, const GLfloat* values)
1030 {
1031 vbo_VertexAttrib4fvARB(indx, values);
1032 }