Merge branch 'master' into i915-unification
[mesa.git] / src / mesa / vbo / vbo_exec_api.c
1 /**************************************************************************
2
3 Copyright 2002 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 "glheader.h"
34 #include "context.h"
35 #include "macros.h"
36 #include "vtxfmt.h"
37 #include "dlist.h"
38 #include "state.h"
39 #include "light.h"
40 #include "api_arrayelt.h"
41 #include "api_noop.h"
42 #include "dispatch.h"
43
44 #include "vbo_context.h"
45
46 static void reset_attrfv( struct vbo_exec_context *exec );
47
48
49 /* Close off the last primitive, execute the buffer, restart the
50 * primitive.
51 */
52 static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec )
53 {
54 if (exec->vtx.prim_count == 0) {
55 exec->vtx.copied.nr = 0;
56 exec->vtx.vert_count = 0;
57 exec->vtx.vbptr = (GLfloat *)exec->vtx.buffer_map;
58 }
59 else {
60 GLuint last_begin = exec->vtx.prim[exec->vtx.prim_count-1].begin;
61 GLuint last_count;
62
63 if (exec->ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
64 GLint i = exec->vtx.prim_count - 1;
65 assert(i >= 0);
66 exec->vtx.prim[i].count = (exec->vtx.vert_count -
67 exec->vtx.prim[i].start);
68 }
69
70 last_count = exec->vtx.prim[exec->vtx.prim_count-1].count;
71
72 /* Execute the buffer and save copied vertices.
73 */
74 if (exec->vtx.vert_count)
75 vbo_exec_vtx_flush( exec );
76 else {
77 exec->vtx.prim_count = 0;
78 exec->vtx.copied.nr = 0;
79 }
80
81 /* Emit a glBegin to start the new list.
82 */
83 assert(exec->vtx.prim_count == 0);
84
85 if (exec->ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
86 exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive;
87 exec->vtx.prim[0].start = 0;
88 exec->vtx.prim[0].count = 0;
89 exec->vtx.prim_count++;
90
91 if (exec->vtx.copied.nr == last_count)
92 exec->vtx.prim[0].begin = last_begin;
93 }
94 }
95 }
96
97
98 /* Deal with buffer wrapping where provoked by the vertex buffer
99 * filling up, as opposed to upgrade_vertex().
100 */
101 void vbo_exec_vtx_wrap( struct vbo_exec_context *exec )
102 {
103 GLfloat *data = exec->vtx.copied.buffer;
104 GLuint i;
105
106 /* Run pipeline on current vertices, copy wrapped vertices
107 * to exec->vtx.copied.
108 */
109 vbo_exec_wrap_buffers( exec );
110
111 /* Copy stored stored vertices to start of new list.
112 */
113 assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr);
114
115 for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
116 _mesa_memcpy( exec->vtx.vbptr, data,
117 exec->vtx.vertex_size * sizeof(GLfloat));
118 exec->vtx.vbptr += exec->vtx.vertex_size;
119 data += exec->vtx.vertex_size;
120 exec->vtx.vert_count++;
121 }
122
123 exec->vtx.copied.nr = 0;
124 }
125
126
127 /*
128 * Copy the active vertex's values to the ctx->Current fields.
129 */
130 static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
131 {
132 GLcontext *ctx = exec->ctx;
133 struct vbo_context *vbo = vbo_context(ctx);
134 GLuint i;
135
136 for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
137 if (exec->vtx.attrsz[i]) {
138 GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
139
140 /* Note: the exec->vtx.current[i] pointers point into the
141 * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
142 */
143 COPY_CLEAN_4V(current,
144 exec->vtx.attrsz[i],
145 exec->vtx.attrptr[i]);
146
147
148 /* Given that we explicitly state size here, there is no need
149 * for the COPY_CLEAN above, could just copy 16 bytes and be
150 * done. The only problem is when Mesa accesses ctx->Current
151 * directly.
152 */
153 vbo->currval[i].Size = exec->vtx.attrsz[i];
154
155 /* This triggers rather too much recalculation of Mesa state
156 * that doesn't get used (eg light positions).
157 */
158 if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
159 i <= VBO_ATTRIB_MAT_BACK_INDEXES)
160 ctx->NewState |= _NEW_LIGHT;
161 }
162 }
163
164 /* Colormaterial -- this kindof sucks.
165 */
166 if (ctx->Light.ColorMaterialEnabled &&
167 exec->vtx.attrsz[VBO_ATTRIB_COLOR0]) {
168 _mesa_update_color_material(ctx,
169 ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
170 }
171
172 ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
173 }
174
175
176 static void vbo_exec_copy_from_current( struct vbo_exec_context *exec )
177 {
178 GLcontext *ctx = exec->ctx;
179 struct vbo_context *vbo = vbo_context(ctx);
180 GLint i;
181
182 for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
183 const GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
184 switch (exec->vtx.attrsz[i]) {
185 case 4: exec->vtx.attrptr[i][3] = current[3];
186 case 3: exec->vtx.attrptr[i][2] = current[2];
187 case 2: exec->vtx.attrptr[i][1] = current[1];
188 case 1: exec->vtx.attrptr[i][0] = current[0];
189 break;
190 }
191 }
192
193 ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
194 }
195
196
197 /* Flush existing data, set new attrib size, replay copied vertices.
198 */
199 static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec,
200 GLuint attr,
201 GLuint newsz )
202 {
203 GLcontext *ctx = exec->ctx;
204 struct vbo_context *vbo = vbo_context(ctx);
205 GLint lastcount = exec->vtx.vert_count;
206 GLfloat *tmp;
207 GLuint oldsz;
208 GLuint i;
209
210 /* Run pipeline on current vertices, copy wrapped vertices
211 * to exec->vtx.copied.
212 */
213 vbo_exec_wrap_buffers( exec );
214
215
216 /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
217 * when the attribute already exists in the vertex and is having
218 * its size increased.
219 */
220 vbo_exec_copy_to_current( exec );
221
222
223 /* Heuristic: Attempt to isolate attributes received outside
224 * begin/end so that they don't bloat the vertices.
225 */
226 if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END &&
227 exec->vtx.attrsz[attr] == 0 &&
228 lastcount > 8 &&
229 exec->vtx.vertex_size) {
230 reset_attrfv( exec );
231 }
232
233 /* Fix up sizes:
234 */
235 oldsz = exec->vtx.attrsz[attr];
236 exec->vtx.attrsz[attr] = newsz;
237
238 exec->vtx.vertex_size += newsz - oldsz;
239 exec->vtx.max_vert = VBO_VERT_BUFFER_SIZE / exec->vtx.vertex_size;
240 exec->vtx.vert_count = 0;
241 exec->vtx.vbptr = (GLfloat *)exec->vtx.buffer_map;
242
243
244 /* Recalculate all the attrptr[] values
245 */
246 for (i = 0, tmp = exec->vtx.vertex ; i < VBO_ATTRIB_MAX ; i++) {
247 if (exec->vtx.attrsz[i]) {
248 exec->vtx.attrptr[i] = tmp;
249 tmp += exec->vtx.attrsz[i];
250 }
251 else
252 exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */
253 }
254
255 /* Copy from current to repopulate the vertex with correct values.
256 */
257 vbo_exec_copy_from_current( exec );
258
259 /* Replay stored vertices to translate them
260 * to new format here.
261 *
262 * -- No need to replay - just copy piecewise
263 */
264 if (exec->vtx.copied.nr)
265 {
266 GLfloat *data = exec->vtx.copied.buffer;
267 GLfloat *dest = exec->vtx.vbptr;
268 GLuint j;
269
270 assert(exec->vtx.vbptr == (GLfloat *)exec->vtx.buffer_map);
271
272 for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
273 for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) {
274 if (exec->vtx.attrsz[j]) {
275 if (j == attr) {
276 if (oldsz) {
277 COPY_CLEAN_4V( dest, oldsz, data );
278 data += oldsz;
279 dest += newsz;
280 } else {
281 const GLfloat *current = (const GLfloat *)vbo->currval[j].Ptr;
282 COPY_SZ_4V( dest, newsz, current );
283 dest += newsz;
284 }
285 }
286 else {
287 GLuint sz = exec->vtx.attrsz[j];
288 COPY_SZ_4V( dest, sz, data );
289 dest += sz;
290 data += sz;
291 }
292 }
293 }
294 }
295
296 exec->vtx.vbptr = dest;
297 exec->vtx.vert_count += exec->vtx.copied.nr;
298 exec->vtx.copied.nr = 0;
299 }
300 }
301
302
303 static void vbo_exec_fixup_vertex( GLcontext *ctx,
304 GLuint attr, GLuint sz )
305 {
306 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
307 int i;
308
309 if (sz > exec->vtx.attrsz[attr]) {
310 /* New size is larger. Need to flush existing vertices and get
311 * an enlarged vertex format.
312 */
313 vbo_exec_wrap_upgrade_vertex( exec, attr, sz );
314 }
315 else if (sz < exec->vtx.active_sz[attr]) {
316 static const GLfloat id[4] = { 0, 0, 0, 1 };
317
318 /* New size is smaller - just need to fill in some
319 * zeros. Don't need to flush or wrap.
320 */
321 for (i = sz ; i <= exec->vtx.attrsz[attr] ; i++)
322 exec->vtx.attrptr[attr][i-1] = id[i-1];
323 }
324
325 exec->vtx.active_sz[attr] = sz;
326
327 /* Does setting NeedFlush belong here? Necessitates resetting
328 * vtxfmt on each flush (otherwise flags won't get reset
329 * afterwards).
330 */
331 if (attr == 0)
332 exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
333 else
334 exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
335 }
336
337
338
339
340 /*
341 */
342 #define ATTR( A, N, V0, V1, V2, V3 ) \
343 do { \
344 struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \
345 \
346 if (exec->vtx.active_sz[A] != N) \
347 vbo_exec_fixup_vertex(ctx, A, N); \
348 \
349 { \
350 GLfloat *dest = exec->vtx.attrptr[A]; \
351 if (N>0) dest[0] = V0; \
352 if (N>1) dest[1] = V1; \
353 if (N>2) dest[2] = V2; \
354 if (N>3) dest[3] = V3; \
355 } \
356 \
357 if ((A) == 0) { \
358 GLuint i; \
359 \
360 for (i = 0; i < exec->vtx.vertex_size; i++) \
361 exec->vtx.vbptr[i] = exec->vtx.vertex[i]; \
362 \
363 exec->vtx.vbptr += exec->vtx.vertex_size; \
364 exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \
365 \
366 if (++exec->vtx.vert_count >= exec->vtx.max_vert) \
367 vbo_exec_vtx_wrap( exec ); \
368 } \
369 } while (0)
370
371
372 #define ERROR() _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ )
373 #define TAG(x) vbo_##x
374
375 #include "vbo_attrib_tmp.h"
376
377
378
379
380
381 /* Eval
382 */
383 static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u )
384 {
385 GET_CURRENT_CONTEXT( ctx );
386 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
387
388 {
389 GLint i;
390 if (exec->eval.recalculate_maps)
391 vbo_exec_eval_update( exec );
392
393 for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
394 if (exec->eval.map1[i].map)
395 if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz)
396 vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz );
397 }
398 }
399
400
401 _mesa_memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
402 exec->vtx.vertex_size * sizeof(GLfloat));
403
404 vbo_exec_do_EvalCoord1f( exec, u );
405
406 _mesa_memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
407 exec->vtx.vertex_size * sizeof(GLfloat));
408 }
409
410 static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v )
411 {
412 GET_CURRENT_CONTEXT( ctx );
413 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
414
415 {
416 GLint i;
417 if (exec->eval.recalculate_maps)
418 vbo_exec_eval_update( exec );
419
420 for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
421 if (exec->eval.map2[i].map)
422 if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz)
423 vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz );
424 }
425
426 if (ctx->Eval.AutoNormal)
427 if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3)
428 vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3 );
429 }
430
431 _mesa_memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
432 exec->vtx.vertex_size * sizeof(GLfloat));
433
434 vbo_exec_do_EvalCoord2f( exec, u, v );
435
436 _mesa_memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
437 exec->vtx.vertex_size * sizeof(GLfloat));
438 }
439
440 static void GLAPIENTRY vbo_exec_EvalCoord1fv( const GLfloat *u )
441 {
442 vbo_exec_EvalCoord1f( u[0] );
443 }
444
445 static void GLAPIENTRY vbo_exec_EvalCoord2fv( const GLfloat *u )
446 {
447 vbo_exec_EvalCoord2f( u[0], u[1] );
448 }
449
450 static void GLAPIENTRY vbo_exec_EvalPoint1( GLint i )
451 {
452 GET_CURRENT_CONTEXT( ctx );
453 GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) /
454 (GLfloat) ctx->Eval.MapGrid1un);
455 GLfloat u = i * du + ctx->Eval.MapGrid1u1;
456
457 vbo_exec_EvalCoord1f( u );
458 }
459
460
461 static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j )
462 {
463 GET_CURRENT_CONTEXT( ctx );
464 GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) /
465 (GLfloat) ctx->Eval.MapGrid2un);
466 GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) /
467 (GLfloat) ctx->Eval.MapGrid2vn);
468 GLfloat u = i * du + ctx->Eval.MapGrid2u1;
469 GLfloat v = j * dv + ctx->Eval.MapGrid2v1;
470
471 vbo_exec_EvalCoord2f( u, v );
472 }
473
474
475 /* Build a list of primitives on the fly. Keep
476 * ctx->Driver.CurrentExecPrimitive uptodate as well.
477 */
478 static void GLAPIENTRY vbo_exec_Begin( GLenum mode )
479 {
480 GET_CURRENT_CONTEXT( ctx );
481
482 if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
483 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
484 int i;
485
486 if (ctx->NewState) {
487 _mesa_update_state( ctx );
488
489 /* XXX also need to check if shader enabled, but invalid */
490 if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) ||
491 (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) {
492 _mesa_error(ctx, GL_INVALID_OPERATION,
493 "glBegin (invalid vertex/fragment program)");
494 return;
495 }
496
497 CALL_Begin(ctx->Exec, (mode));
498 return;
499 }
500
501 /* Heuristic: attempt to isolate attributes occuring outside
502 * begin/end pairs.
503 */
504 if (exec->vtx.vertex_size && !exec->vtx.attrsz[0])
505 vbo_exec_FlushVertices( ctx, ~0 );
506
507 i = exec->vtx.prim_count++;
508 exec->vtx.prim[i].mode = mode;
509 exec->vtx.prim[i].begin = 1;
510 exec->vtx.prim[i].end = 0;
511 exec->vtx.prim[i].indexed = 0;
512 exec->vtx.prim[i].weak = 0;
513 exec->vtx.prim[i].pad = 0;
514 exec->vtx.prim[i].start = exec->vtx.vert_count;
515 exec->vtx.prim[i].count = 0;
516
517 ctx->Driver.CurrentExecPrimitive = mode;
518 }
519 else
520 _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
521
522 }
523
524 static void GLAPIENTRY vbo_exec_End( void )
525 {
526 GET_CURRENT_CONTEXT( ctx );
527
528 if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
529 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
530 int idx = exec->vtx.vert_count;
531 int i = exec->vtx.prim_count - 1;
532
533 exec->vtx.prim[i].end = 1;
534 exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start;
535
536 ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
537
538 if (exec->vtx.prim_count == VBO_MAX_PRIM)
539 vbo_exec_vtx_flush( exec );
540 }
541 else
542 _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
543 }
544
545
546 static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
547 {
548 GLvertexformat *vfmt = &exec->vtxfmt;
549
550 vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
551 vfmt->Begin = vbo_exec_Begin;
552 vfmt->CallList = _mesa_CallList;
553 vfmt->CallLists = _mesa_CallLists;
554 vfmt->End = vbo_exec_End;
555 vfmt->EvalCoord1f = vbo_exec_EvalCoord1f;
556 vfmt->EvalCoord1fv = vbo_exec_EvalCoord1fv;
557 vfmt->EvalCoord2f = vbo_exec_EvalCoord2f;
558 vfmt->EvalCoord2fv = vbo_exec_EvalCoord2fv;
559 vfmt->EvalPoint1 = vbo_exec_EvalPoint1;
560 vfmt->EvalPoint2 = vbo_exec_EvalPoint2;
561
562 vfmt->Rectf = _mesa_noop_Rectf;
563 vfmt->EvalMesh1 = _mesa_noop_EvalMesh1;
564 vfmt->EvalMesh2 = _mesa_noop_EvalMesh2;
565
566
567 /* from attrib_tmp.h:
568 */
569 vfmt->Color3f = vbo_Color3f;
570 vfmt->Color3fv = vbo_Color3fv;
571 vfmt->Color4f = vbo_Color4f;
572 vfmt->Color4fv = vbo_Color4fv;
573 vfmt->FogCoordfEXT = vbo_FogCoordfEXT;
574 vfmt->FogCoordfvEXT = vbo_FogCoordfvEXT;
575 vfmt->MultiTexCoord1fARB = vbo_MultiTexCoord1f;
576 vfmt->MultiTexCoord1fvARB = vbo_MultiTexCoord1fv;
577 vfmt->MultiTexCoord2fARB = vbo_MultiTexCoord2f;
578 vfmt->MultiTexCoord2fvARB = vbo_MultiTexCoord2fv;
579 vfmt->MultiTexCoord3fARB = vbo_MultiTexCoord3f;
580 vfmt->MultiTexCoord3fvARB = vbo_MultiTexCoord3fv;
581 vfmt->MultiTexCoord4fARB = vbo_MultiTexCoord4f;
582 vfmt->MultiTexCoord4fvARB = vbo_MultiTexCoord4fv;
583 vfmt->Normal3f = vbo_Normal3f;
584 vfmt->Normal3fv = vbo_Normal3fv;
585 vfmt->SecondaryColor3fEXT = vbo_SecondaryColor3fEXT;
586 vfmt->SecondaryColor3fvEXT = vbo_SecondaryColor3fvEXT;
587 vfmt->TexCoord1f = vbo_TexCoord1f;
588 vfmt->TexCoord1fv = vbo_TexCoord1fv;
589 vfmt->TexCoord2f = vbo_TexCoord2f;
590 vfmt->TexCoord2fv = vbo_TexCoord2fv;
591 vfmt->TexCoord3f = vbo_TexCoord3f;
592 vfmt->TexCoord3fv = vbo_TexCoord3fv;
593 vfmt->TexCoord4f = vbo_TexCoord4f;
594 vfmt->TexCoord4fv = vbo_TexCoord4fv;
595 vfmt->Vertex2f = vbo_Vertex2f;
596 vfmt->Vertex2fv = vbo_Vertex2fv;
597 vfmt->Vertex3f = vbo_Vertex3f;
598 vfmt->Vertex3fv = vbo_Vertex3fv;
599 vfmt->Vertex4f = vbo_Vertex4f;
600 vfmt->Vertex4fv = vbo_Vertex4fv;
601
602 vfmt->VertexAttrib1fARB = vbo_VertexAttrib1fARB;
603 vfmt->VertexAttrib1fvARB = vbo_VertexAttrib1fvARB;
604 vfmt->VertexAttrib2fARB = vbo_VertexAttrib2fARB;
605 vfmt->VertexAttrib2fvARB = vbo_VertexAttrib2fvARB;
606 vfmt->VertexAttrib3fARB = vbo_VertexAttrib3fARB;
607 vfmt->VertexAttrib3fvARB = vbo_VertexAttrib3fvARB;
608 vfmt->VertexAttrib4fARB = vbo_VertexAttrib4fARB;
609 vfmt->VertexAttrib4fvARB = vbo_VertexAttrib4fvARB;
610
611 vfmt->VertexAttrib1fNV = vbo_VertexAttrib1fNV;
612 vfmt->VertexAttrib1fvNV = vbo_VertexAttrib1fvNV;
613 vfmt->VertexAttrib2fNV = vbo_VertexAttrib2fNV;
614 vfmt->VertexAttrib2fvNV = vbo_VertexAttrib2fvNV;
615 vfmt->VertexAttrib3fNV = vbo_VertexAttrib3fNV;
616 vfmt->VertexAttrib3fvNV = vbo_VertexAttrib3fvNV;
617 vfmt->VertexAttrib4fNV = vbo_VertexAttrib4fNV;
618 vfmt->VertexAttrib4fvNV = vbo_VertexAttrib4fvNV;
619
620 vfmt->Materialfv = vbo_Materialfv;
621
622 vfmt->EdgeFlag = vbo_EdgeFlag;
623 vfmt->Indexf = vbo_Indexf;
624 vfmt->Indexfv = vbo_Indexfv;
625
626 }
627
628
629 void vbo_exec_vtx_init( struct vbo_exec_context *exec )
630 {
631 GLcontext *ctx = exec->ctx;
632 struct vbo_context *vbo = vbo_context(ctx);
633 GLuint i;
634
635 /* Allocate a buffer object. Will just reuse this object
636 * continuously.
637 */
638 exec->vtx.bufferobj = ctx->Array.NullBufferObj;
639 exec->vtx.buffer_map = ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE * sizeof(GLfloat), 64);
640
641 vbo_exec_vtxfmt_init( exec );
642
643 /* Hook our functions into the dispatch table.
644 */
645 _mesa_install_exec_vtxfmt( exec->ctx, &exec->vtxfmt );
646
647 for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
648 exec->vtx.attrsz[i] = 0;
649 exec->vtx.active_sz[i] = 0;
650 exec->vtx.inputs[i] = &exec->vtx.arrays[i];
651 }
652
653 {
654 struct gl_client_array *arrays = exec->vtx.arrays;
655 memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0]));
656 memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0]));
657 }
658
659 exec->vtx.vertex_size = 0;
660 }
661
662
663 void vbo_exec_vtx_destroy( struct vbo_exec_context *exec )
664 {
665 if (exec->vtx.buffer_map) {
666 ALIGN_FREE(exec->vtx.buffer_map);
667 exec->vtx.buffer_map = NULL;
668 }
669 }
670
671
672 void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags )
673 {
674 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
675
676 if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END)
677 return;
678
679 if (exec->vtx.vert_count) {
680 vbo_exec_vtx_flush( exec );
681 }
682
683 if (exec->vtx.vertex_size) {
684 vbo_exec_copy_to_current( exec );
685 reset_attrfv( exec );
686 }
687
688 exec->ctx->Driver.NeedFlush = 0;
689 }
690
691
692 static void reset_attrfv( struct vbo_exec_context *exec )
693 {
694 GLuint i;
695
696 for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
697 exec->vtx.attrsz[i] = 0;
698 exec->vtx.active_sz[i] = 0;
699 }
700
701 exec->vtx.vertex_size = 0;
702 }
703