radeon/r200/r300: cleanup some of the renderbuffer code
[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 #if FEATURE_dlist
39 #include "main/dlist.h"
40 #endif
41 #include "main/state.h"
42 #include "main/light.h"
43 #include "main/api_arrayelt.h"
44 #include "main/api_noop.h"
45 #include "glapi/dispatch.h"
46
47 #include "vbo_context.h"
48
49 #ifdef ERROR
50 #undef ERROR
51 #endif
52
53
54 static void reset_attrfv( struct vbo_exec_context *exec );
55
56
57 /* Close off the last primitive, execute the buffer, restart the
58 * primitive.
59 */
60 static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec )
61 {
62 if (exec->vtx.prim_count == 0) {
63 exec->vtx.copied.nr = 0;
64 exec->vtx.vert_count = 0;
65 exec->vtx.vbptr = (GLfloat *)exec->vtx.buffer_map;
66 }
67 else {
68 GLuint last_begin = exec->vtx.prim[exec->vtx.prim_count-1].begin;
69 GLuint last_count;
70
71 if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
72 GLint i = exec->vtx.prim_count - 1;
73 assert(i >= 0);
74 exec->vtx.prim[i].count = (exec->vtx.vert_count -
75 exec->vtx.prim[i].start);
76 }
77
78 last_count = exec->vtx.prim[exec->vtx.prim_count-1].count;
79
80 /* Execute the buffer and save copied vertices.
81 */
82 if (exec->vtx.vert_count)
83 vbo_exec_vtx_flush( exec );
84 else {
85 exec->vtx.prim_count = 0;
86 exec->vtx.copied.nr = 0;
87 }
88
89 /* Emit a glBegin to start the new list.
90 */
91 assert(exec->vtx.prim_count == 0);
92
93 if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
94 exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive;
95 exec->vtx.prim[0].start = 0;
96 exec->vtx.prim[0].count = 0;
97 exec->vtx.prim_count++;
98
99 if (exec->vtx.copied.nr == last_count)
100 exec->vtx.prim[0].begin = last_begin;
101 }
102 }
103 }
104
105
106 /* Deal with buffer wrapping where provoked by the vertex buffer
107 * filling up, as opposed to upgrade_vertex().
108 */
109 void vbo_exec_vtx_wrap( struct vbo_exec_context *exec )
110 {
111 GLfloat *data = exec->vtx.copied.buffer;
112 GLuint i;
113
114 /* Run pipeline on current vertices, copy wrapped vertices
115 * to exec->vtx.copied.
116 */
117 vbo_exec_wrap_buffers( exec );
118
119 /* Copy stored stored vertices to start of new list.
120 */
121 assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr);
122
123 for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
124 _mesa_memcpy( exec->vtx.vbptr, data,
125 exec->vtx.vertex_size * sizeof(GLfloat));
126 exec->vtx.vbptr += exec->vtx.vertex_size;
127 data += exec->vtx.vertex_size;
128 exec->vtx.vert_count++;
129 }
130
131 exec->vtx.copied.nr = 0;
132 }
133
134
135 /*
136 * Copy the active vertex's values to the ctx->Current fields.
137 */
138 static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
139 {
140 GLcontext *ctx = exec->ctx;
141 struct vbo_context *vbo = vbo_context(ctx);
142 GLuint i;
143
144 for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
145 if (exec->vtx.attrsz[i]) {
146 /* Note: the exec->vtx.current[i] pointers point into the
147 * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
148 */
149 GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
150 GLfloat tmp[4];
151
152 COPY_CLEAN_4V(tmp,
153 exec->vtx.attrsz[i],
154 exec->vtx.attrptr[i]);
155
156 if (memcmp(current, tmp, sizeof(tmp)) != 0)
157 {
158 memcpy(current, tmp, sizeof(tmp));
159
160 /* Given that we explicitly state size here, there is no need
161 * for the COPY_CLEAN above, could just copy 16 bytes and be
162 * done. The only problem is when Mesa accesses ctx->Current
163 * directly.
164 */
165 vbo->currval[i].Size = exec->vtx.attrsz[i];
166
167 /* This triggers rather too much recalculation of Mesa state
168 * that doesn't get used (eg light positions).
169 */
170 if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
171 i <= VBO_ATTRIB_MAT_BACK_INDEXES)
172 ctx->NewState |= _NEW_LIGHT;
173
174 ctx->NewState |= _NEW_CURRENT_ATTRIB;
175 }
176 }
177 }
178
179 /* Colormaterial -- this kindof sucks.
180 */
181 if (ctx->Light.ColorMaterialEnabled &&
182 exec->vtx.attrsz[VBO_ATTRIB_COLOR0]) {
183 _mesa_update_color_material(ctx,
184 ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
185 }
186
187 ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
188 }
189
190
191 static void vbo_exec_copy_from_current( struct vbo_exec_context *exec )
192 {
193 GLcontext *ctx = exec->ctx;
194 struct vbo_context *vbo = vbo_context(ctx);
195 GLint i;
196
197 for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
198 const GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
199 switch (exec->vtx.attrsz[i]) {
200 case 4: exec->vtx.attrptr[i][3] = current[3];
201 case 3: exec->vtx.attrptr[i][2] = current[2];
202 case 2: exec->vtx.attrptr[i][1] = current[1];
203 case 1: exec->vtx.attrptr[i][0] = current[0];
204 break;
205 }
206 }
207
208 ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
209 }
210
211
212 /* Flush existing data, set new attrib size, replay copied vertices.
213 */
214 static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec,
215 GLuint attr,
216 GLuint newsz )
217 {
218 GLcontext *ctx = exec->ctx;
219 struct vbo_context *vbo = vbo_context(ctx);
220 GLint lastcount = exec->vtx.vert_count;
221 GLfloat *tmp;
222 GLuint oldsz;
223 GLuint i;
224
225 /* Run pipeline on current vertices, copy wrapped vertices
226 * to exec->vtx.copied.
227 */
228 vbo_exec_wrap_buffers( exec );
229
230
231 /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
232 * when the attribute already exists in the vertex and is having
233 * its size increased.
234 */
235 vbo_exec_copy_to_current( exec );
236
237
238 /* Heuristic: Attempt to isolate attributes received outside
239 * begin/end so that they don't bloat the vertices.
240 */
241 if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END &&
242 exec->vtx.attrsz[attr] == 0 &&
243 lastcount > 8 &&
244 exec->vtx.vertex_size) {
245 reset_attrfv( exec );
246 }
247
248 /* Fix up sizes:
249 */
250 oldsz = exec->vtx.attrsz[attr];
251 exec->vtx.attrsz[attr] = newsz;
252
253 exec->vtx.vertex_size += newsz - oldsz;
254 exec->vtx.max_vert = VBO_VERT_BUFFER_SIZE / exec->vtx.vertex_size;
255 exec->vtx.vert_count = 0;
256 exec->vtx.vbptr = (GLfloat *)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.vbptr;
283 GLuint j;
284
285 assert(exec->vtx.vbptr == (GLfloat *)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.vbptr = 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 else
349 exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
350 }
351
352
353
354
355 /*
356 */
357 #define ATTR( A, N, V0, V1, V2, V3 ) \
358 do { \
359 struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \
360 \
361 if (exec->vtx.active_sz[A] != N) \
362 vbo_exec_fixup_vertex(ctx, A, N); \
363 \
364 { \
365 GLfloat *dest = exec->vtx.attrptr[A]; \
366 if (N>0) dest[0] = V0; \
367 if (N>1) dest[1] = V1; \
368 if (N>2) dest[2] = V2; \
369 if (N>3) dest[3] = V3; \
370 } \
371 \
372 if ((A) == 0) { \
373 GLuint i; \
374 \
375 for (i = 0; i < exec->vtx.vertex_size; i++) \
376 exec->vtx.vbptr[i] = exec->vtx.vertex[i]; \
377 \
378 exec->vtx.vbptr += exec->vtx.vertex_size; \
379 exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \
380 \
381 if (++exec->vtx.vert_count >= exec->vtx.max_vert) \
382 vbo_exec_vtx_wrap( exec ); \
383 } \
384 } while (0)
385
386
387 #define ERROR() _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ )
388 #define TAG(x) vbo_##x
389
390 #include "vbo_attrib_tmp.h"
391
392
393
394
395
396 /* Eval
397 */
398 static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u )
399 {
400 GET_CURRENT_CONTEXT( ctx );
401 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
402
403 {
404 GLint i;
405 if (exec->eval.recalculate_maps)
406 vbo_exec_eval_update( exec );
407
408 for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
409 if (exec->eval.map1[i].map)
410 if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz)
411 vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz );
412 }
413 }
414
415
416 _mesa_memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
417 exec->vtx.vertex_size * sizeof(GLfloat));
418
419 vbo_exec_do_EvalCoord1f( exec, u );
420
421 _mesa_memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
422 exec->vtx.vertex_size * sizeof(GLfloat));
423 }
424
425 static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v )
426 {
427 GET_CURRENT_CONTEXT( ctx );
428 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
429
430 {
431 GLint i;
432 if (exec->eval.recalculate_maps)
433 vbo_exec_eval_update( exec );
434
435 for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
436 if (exec->eval.map2[i].map)
437 if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz)
438 vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz );
439 }
440
441 if (ctx->Eval.AutoNormal)
442 if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3)
443 vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3 );
444 }
445
446 _mesa_memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
447 exec->vtx.vertex_size * sizeof(GLfloat));
448
449 vbo_exec_do_EvalCoord2f( exec, u, v );
450
451 _mesa_memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
452 exec->vtx.vertex_size * sizeof(GLfloat));
453 }
454
455 static void GLAPIENTRY vbo_exec_EvalCoord1fv( const GLfloat *u )
456 {
457 vbo_exec_EvalCoord1f( u[0] );
458 }
459
460 static void GLAPIENTRY vbo_exec_EvalCoord2fv( const GLfloat *u )
461 {
462 vbo_exec_EvalCoord2f( u[0], u[1] );
463 }
464
465 static void GLAPIENTRY vbo_exec_EvalPoint1( GLint i )
466 {
467 GET_CURRENT_CONTEXT( ctx );
468 GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) /
469 (GLfloat) ctx->Eval.MapGrid1un);
470 GLfloat u = i * du + ctx->Eval.MapGrid1u1;
471
472 vbo_exec_EvalCoord1f( u );
473 }
474
475
476 static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j )
477 {
478 GET_CURRENT_CONTEXT( ctx );
479 GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) /
480 (GLfloat) ctx->Eval.MapGrid2un);
481 GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) /
482 (GLfloat) ctx->Eval.MapGrid2vn);
483 GLfloat u = i * du + ctx->Eval.MapGrid2u1;
484 GLfloat v = j * dv + ctx->Eval.MapGrid2v1;
485
486 vbo_exec_EvalCoord2f( u, v );
487 }
488
489
490 /**
491 * Check if programs/shaders are enabled and valid at glBegin time.
492 */
493 GLboolean
494 vbo_validate_shaders(GLcontext *ctx)
495 {
496 if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) ||
497 (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) {
498 return GL_FALSE;
499 }
500 if (ctx->Shader.CurrentProgram && !ctx->Shader.CurrentProgram->LinkStatus) {
501 return GL_FALSE;
502 }
503 return GL_TRUE;
504 }
505
506
507 /* Build a list of primitives on the fly. Keep
508 * ctx->Driver.CurrentExecPrimitive uptodate as well.
509 */
510 static void GLAPIENTRY vbo_exec_Begin( GLenum mode )
511 {
512 GET_CURRENT_CONTEXT( ctx );
513
514 if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) {
515 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
516 int i;
517
518 if (ctx->NewState) {
519 _mesa_update_state( ctx );
520
521 CALL_Begin(ctx->Exec, (mode));
522 return;
523 }
524
525 if (!vbo_validate_shaders(ctx)) {
526 _mesa_error(ctx, GL_INVALID_OPERATION,
527 "glBegin (invalid vertex/fragment program)");
528 return;
529 }
530
531 /* Heuristic: attempt to isolate attributes occuring outside
532 * begin/end pairs.
533 */
534 if (exec->vtx.vertex_size && !exec->vtx.attrsz[0])
535 vbo_exec_FlushVertices( ctx, ~0 );
536
537 i = exec->vtx.prim_count++;
538 exec->vtx.prim[i].mode = mode;
539 exec->vtx.prim[i].begin = 1;
540 exec->vtx.prim[i].end = 0;
541 exec->vtx.prim[i].indexed = 0;
542 exec->vtx.prim[i].weak = 0;
543 exec->vtx.prim[i].pad = 0;
544 exec->vtx.prim[i].start = exec->vtx.vert_count;
545 exec->vtx.prim[i].count = 0;
546
547 ctx->Driver.CurrentExecPrimitive = mode;
548 }
549 else
550 _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
551
552 }
553
554 static void GLAPIENTRY vbo_exec_End( void )
555 {
556 GET_CURRENT_CONTEXT( ctx );
557
558 if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
559 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
560 int idx = exec->vtx.vert_count;
561 int i = exec->vtx.prim_count - 1;
562
563 exec->vtx.prim[i].end = 1;
564 exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start;
565
566 ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
567
568 if (exec->vtx.prim_count == VBO_MAX_PRIM)
569 vbo_exec_vtx_flush( exec );
570 }
571 else
572 _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
573 }
574
575
576 static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
577 {
578 GLvertexformat *vfmt = &exec->vtxfmt;
579
580 vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
581 vfmt->Begin = vbo_exec_Begin;
582 #if FEATURE_dlist
583 vfmt->CallList = _mesa_CallList;
584 vfmt->CallLists = _mesa_CallLists;
585 #endif
586 vfmt->End = vbo_exec_End;
587 vfmt->EvalCoord1f = vbo_exec_EvalCoord1f;
588 vfmt->EvalCoord1fv = vbo_exec_EvalCoord1fv;
589 vfmt->EvalCoord2f = vbo_exec_EvalCoord2f;
590 vfmt->EvalCoord2fv = vbo_exec_EvalCoord2fv;
591 vfmt->EvalPoint1 = vbo_exec_EvalPoint1;
592 vfmt->EvalPoint2 = vbo_exec_EvalPoint2;
593
594 vfmt->Rectf = _mesa_noop_Rectf;
595 vfmt->EvalMesh1 = _mesa_noop_EvalMesh1;
596 vfmt->EvalMesh2 = _mesa_noop_EvalMesh2;
597
598
599 /* from attrib_tmp.h:
600 */
601 vfmt->Color3f = vbo_Color3f;
602 vfmt->Color3fv = vbo_Color3fv;
603 vfmt->Color4f = vbo_Color4f;
604 vfmt->Color4fv = vbo_Color4fv;
605 vfmt->FogCoordfEXT = vbo_FogCoordfEXT;
606 vfmt->FogCoordfvEXT = vbo_FogCoordfvEXT;
607 vfmt->MultiTexCoord1fARB = vbo_MultiTexCoord1f;
608 vfmt->MultiTexCoord1fvARB = vbo_MultiTexCoord1fv;
609 vfmt->MultiTexCoord2fARB = vbo_MultiTexCoord2f;
610 vfmt->MultiTexCoord2fvARB = vbo_MultiTexCoord2fv;
611 vfmt->MultiTexCoord3fARB = vbo_MultiTexCoord3f;
612 vfmt->MultiTexCoord3fvARB = vbo_MultiTexCoord3fv;
613 vfmt->MultiTexCoord4fARB = vbo_MultiTexCoord4f;
614 vfmt->MultiTexCoord4fvARB = vbo_MultiTexCoord4fv;
615 vfmt->Normal3f = vbo_Normal3f;
616 vfmt->Normal3fv = vbo_Normal3fv;
617 vfmt->SecondaryColor3fEXT = vbo_SecondaryColor3fEXT;
618 vfmt->SecondaryColor3fvEXT = vbo_SecondaryColor3fvEXT;
619 vfmt->TexCoord1f = vbo_TexCoord1f;
620 vfmt->TexCoord1fv = vbo_TexCoord1fv;
621 vfmt->TexCoord2f = vbo_TexCoord2f;
622 vfmt->TexCoord2fv = vbo_TexCoord2fv;
623 vfmt->TexCoord3f = vbo_TexCoord3f;
624 vfmt->TexCoord3fv = vbo_TexCoord3fv;
625 vfmt->TexCoord4f = vbo_TexCoord4f;
626 vfmt->TexCoord4fv = vbo_TexCoord4fv;
627 vfmt->Vertex2f = vbo_Vertex2f;
628 vfmt->Vertex2fv = vbo_Vertex2fv;
629 vfmt->Vertex3f = vbo_Vertex3f;
630 vfmt->Vertex3fv = vbo_Vertex3fv;
631 vfmt->Vertex4f = vbo_Vertex4f;
632 vfmt->Vertex4fv = vbo_Vertex4fv;
633
634 vfmt->VertexAttrib1fARB = vbo_VertexAttrib1fARB;
635 vfmt->VertexAttrib1fvARB = vbo_VertexAttrib1fvARB;
636 vfmt->VertexAttrib2fARB = vbo_VertexAttrib2fARB;
637 vfmt->VertexAttrib2fvARB = vbo_VertexAttrib2fvARB;
638 vfmt->VertexAttrib3fARB = vbo_VertexAttrib3fARB;
639 vfmt->VertexAttrib3fvARB = vbo_VertexAttrib3fvARB;
640 vfmt->VertexAttrib4fARB = vbo_VertexAttrib4fARB;
641 vfmt->VertexAttrib4fvARB = vbo_VertexAttrib4fvARB;
642
643 vfmt->VertexAttrib1fNV = vbo_VertexAttrib1fNV;
644 vfmt->VertexAttrib1fvNV = vbo_VertexAttrib1fvNV;
645 vfmt->VertexAttrib2fNV = vbo_VertexAttrib2fNV;
646 vfmt->VertexAttrib2fvNV = vbo_VertexAttrib2fvNV;
647 vfmt->VertexAttrib3fNV = vbo_VertexAttrib3fNV;
648 vfmt->VertexAttrib3fvNV = vbo_VertexAttrib3fvNV;
649 vfmt->VertexAttrib4fNV = vbo_VertexAttrib4fNV;
650 vfmt->VertexAttrib4fvNV = vbo_VertexAttrib4fvNV;
651
652 vfmt->Materialfv = vbo_Materialfv;
653
654 vfmt->EdgeFlag = vbo_EdgeFlag;
655 vfmt->Indexf = vbo_Indexf;
656 vfmt->Indexfv = vbo_Indexfv;
657
658 }
659
660
661 /**
662 * Tell the VBO module to use a real OpenGL vertex buffer object to
663 * store accumulated immediate-mode vertex data.
664 * This replaces the malloced buffer which was created in
665 * vb_exec_vtx_init() below.
666 */
667 void vbo_use_buffer_objects(GLcontext *ctx)
668 {
669 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
670 /* Any buffer name but 0 can be used here since this bufferobj won't
671 * go into the bufferobj hashtable.
672 */
673 GLuint bufName = 0xaabbccdd;
674 GLenum target = GL_ARRAY_BUFFER_ARB;
675 GLenum access = GL_READ_WRITE_ARB;
676 GLenum usage = GL_STREAM_DRAW_ARB;
677 GLsizei size = VBO_VERT_BUFFER_SIZE * sizeof(GLfloat);
678
679 /* Make sure this func is only used once */
680 assert(exec->vtx.bufferobj == ctx->Array.NullBufferObj);
681 if (exec->vtx.buffer_map) {
682 _mesa_align_free(exec->vtx.buffer_map);
683 }
684
685 /* Allocate a real buffer object now */
686 exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName, target);
687 ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj);
688
689 /* and map it */
690 exec->vtx.buffer_map
691 = ctx->Driver.MapBuffer(ctx, target, access, exec->vtx.bufferobj);
692 }
693
694
695
696 void vbo_exec_vtx_init( struct vbo_exec_context *exec )
697 {
698 GLcontext *ctx = exec->ctx;
699 struct vbo_context *vbo = vbo_context(ctx);
700 GLuint i;
701
702 /* Allocate a buffer object. Will just reuse this object
703 * continuously, unless vbo_use_buffer_objects() is called to enable
704 * use of real VBOs.
705 */
706 _mesa_reference_buffer_object(ctx,
707 &exec->vtx.bufferobj,
708 ctx->Array.NullBufferObj);
709
710 ASSERT(!exec->vtx.buffer_map);
711 exec->vtx.buffer_map = ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE * sizeof(GLfloat), 64);
712 vbo_exec_vtxfmt_init( exec );
713
714 /* Hook our functions into the dispatch table.
715 */
716 _mesa_install_exec_vtxfmt( exec->ctx, &exec->vtxfmt );
717
718 for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
719 exec->vtx.attrsz[i] = 0;
720 exec->vtx.active_sz[i] = 0;
721 exec->vtx.inputs[i] = &exec->vtx.arrays[i];
722 }
723
724 {
725 struct gl_client_array *arrays = exec->vtx.arrays;
726 memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0]));
727 memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0]));
728 }
729
730 exec->vtx.vertex_size = 0;
731 }
732
733
734 void vbo_exec_vtx_destroy( struct vbo_exec_context *exec )
735 {
736 if (exec->vtx.bufferobj->Name) {
737 /* using a real VBO for vertex data */
738 GLcontext *ctx = exec->ctx;
739 _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
740 }
741 else {
742 /* just using malloc'd space for vertex data */
743 if (exec->vtx.buffer_map) {
744 ALIGN_FREE(exec->vtx.buffer_map);
745 exec->vtx.buffer_map = NULL;
746 }
747 }
748 }
749
750
751 void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags )
752 {
753 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
754
755 if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END)
756 return;
757
758 if (exec->vtx.vert_count) {
759 vbo_exec_vtx_flush( exec );
760 }
761
762 if (exec->vtx.vertex_size) {
763 vbo_exec_copy_to_current( exec );
764 reset_attrfv( exec );
765 }
766
767 exec->ctx->Driver.NeedFlush = 0;
768 }
769
770
771 static void reset_attrfv( struct vbo_exec_context *exec )
772 {
773 GLuint i;
774
775 for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
776 exec->vtx.attrsz[i] = 0;
777 exec->vtx.active_sz[i] = 0;
778 }
779
780 exec->vtx.vertex_size = 0;
781 }
782
783
784 void GLAPIENTRY
785 _vbo_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
786 {
787 vbo_Color4f(r, g, b, a);
788 }
789
790
791 void GLAPIENTRY
792 _vbo_Normal3f(GLfloat x, GLfloat y, GLfloat z)
793 {
794 vbo_Normal3f(x, y, z);
795 }
796
797
798 void GLAPIENTRY
799 _vbo_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
800 {
801 vbo_MultiTexCoord4f(target, s, t, r, q);
802 }
803
804 void GLAPIENTRY
805 _vbo_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
806 {
807 vbo_Materialfv(face, pname, params);
808 }
809
810
811 void GLAPIENTRY
812 _vbo_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
813 {
814 vbo_VertexAttrib4fARB(index, x, y, z, w);
815 }