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