i965: disable using immediate values for MOV instructions
[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.buffer_ptr = 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, GL_FALSE );
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.buffer_ptr, data,
125 exec->vtx.vertex_size * sizeof(GLfloat));
126 exec->vtx.buffer_ptr += 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
188
189 static void vbo_exec_copy_from_current( struct vbo_exec_context *exec )
190 {
191 GLcontext *ctx = exec->ctx;
192 struct vbo_context *vbo = vbo_context(ctx);
193 GLint i;
194
195 for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
196 const GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
197 switch (exec->vtx.attrsz[i]) {
198 case 4: exec->vtx.attrptr[i][3] = current[3];
199 case 3: exec->vtx.attrptr[i][2] = current[2];
200 case 2: exec->vtx.attrptr[i][1] = current[1];
201 case 1: exec->vtx.attrptr[i][0] = current[0];
202 break;
203 }
204 }
205 }
206
207
208 /* Flush existing data, set new attrib size, replay copied vertices.
209 */
210 static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec,
211 GLuint attr,
212 GLuint newsz )
213 {
214 GLcontext *ctx = exec->ctx;
215 struct vbo_context *vbo = vbo_context(ctx);
216 GLint lastcount = exec->vtx.vert_count;
217 GLfloat *tmp;
218 GLuint oldsz;
219 GLuint i;
220
221 /* Run pipeline on current vertices, copy wrapped vertices
222 * to exec->vtx.copied.
223 */
224 vbo_exec_wrap_buffers( exec );
225
226
227 /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
228 * when the attribute already exists in the vertex and is having
229 * its size increased.
230 */
231 vbo_exec_copy_to_current( exec );
232
233
234 /* Heuristic: Attempt to isolate attributes received outside
235 * begin/end so that they don't bloat the vertices.
236 */
237 if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END &&
238 exec->vtx.attrsz[attr] == 0 &&
239 lastcount > 8 &&
240 exec->vtx.vertex_size) {
241 reset_attrfv( exec );
242 }
243
244 /* Fix up sizes:
245 */
246 oldsz = exec->vtx.attrsz[attr];
247 exec->vtx.attrsz[attr] = newsz;
248
249 exec->vtx.vertex_size += newsz - oldsz;
250 exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) /
251 (exec->vtx.vertex_size * sizeof(GLfloat)));
252 exec->vtx.vert_count = 0;
253 exec->vtx.buffer_ptr = exec->vtx.buffer_map;
254
255
256 /* Recalculate all the attrptr[] values
257 */
258 for (i = 0, tmp = exec->vtx.vertex ; i < VBO_ATTRIB_MAX ; i++) {
259 if (exec->vtx.attrsz[i]) {
260 exec->vtx.attrptr[i] = tmp;
261 tmp += exec->vtx.attrsz[i];
262 }
263 else
264 exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */
265 }
266
267 /* Copy from current to repopulate the vertex with correct values.
268 */
269 vbo_exec_copy_from_current( exec );
270
271 /* Replay stored vertices to translate them
272 * to new format here.
273 *
274 * -- No need to replay - just copy piecewise
275 */
276 if (exec->vtx.copied.nr)
277 {
278 GLfloat *data = exec->vtx.copied.buffer;
279 GLfloat *dest = exec->vtx.buffer_ptr;
280 GLuint j;
281
282 assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map);
283
284 for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
285 for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) {
286 if (exec->vtx.attrsz[j]) {
287 if (j == attr) {
288 if (oldsz) {
289 COPY_CLEAN_4V( dest, oldsz, data );
290 data += oldsz;
291 dest += newsz;
292 } else {
293 const GLfloat *current = (const GLfloat *)vbo->currval[j].Ptr;
294 COPY_SZ_4V( dest, newsz, current );
295 dest += newsz;
296 }
297 }
298 else {
299 GLuint sz = exec->vtx.attrsz[j];
300 COPY_SZ_4V( dest, sz, data );
301 dest += sz;
302 data += sz;
303 }
304 }
305 }
306 }
307
308 exec->vtx.buffer_ptr = dest;
309 exec->vtx.vert_count += exec->vtx.copied.nr;
310 exec->vtx.copied.nr = 0;
311 }
312 }
313
314
315 static void vbo_exec_fixup_vertex( GLcontext *ctx,
316 GLuint attr, GLuint sz )
317 {
318 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
319 int i;
320
321 if (sz > exec->vtx.attrsz[attr]) {
322 /* New size is larger. Need to flush existing vertices and get
323 * an enlarged vertex format.
324 */
325 vbo_exec_wrap_upgrade_vertex( exec, attr, sz );
326 }
327 else if (sz < exec->vtx.active_sz[attr]) {
328 static const GLfloat id[4] = { 0, 0, 0, 1 };
329
330 /* New size is smaller - just need to fill in some
331 * zeros. Don't need to flush or wrap.
332 */
333 for (i = sz ; i <= exec->vtx.attrsz[attr] ; i++)
334 exec->vtx.attrptr[attr][i-1] = id[i-1];
335 }
336
337 exec->vtx.active_sz[attr] = sz;
338
339 /* Does setting NeedFlush belong here? Necessitates resetting
340 * vtxfmt on each flush (otherwise flags won't get reset
341 * afterwards).
342 */
343 if (attr == 0)
344 exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
345 }
346
347
348
349
350 /*
351 */
352 #define ATTR( A, N, V0, V1, V2, V3 ) \
353 do { \
354 struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \
355 \
356 if (exec->vtx.active_sz[A] != N) \
357 vbo_exec_fixup_vertex(ctx, A, N); \
358 \
359 { \
360 GLfloat *dest = exec->vtx.attrptr[A]; \
361 if (N>0) dest[0] = V0; \
362 if (N>1) dest[1] = V1; \
363 if (N>2) dest[2] = V2; \
364 if (N>3) dest[3] = V3; \
365 } \
366 \
367 if ((A) == 0) { \
368 GLuint i; \
369 \
370 for (i = 0; i < exec->vtx.vertex_size; i++) \
371 exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i]; \
372 \
373 exec->vtx.buffer_ptr += exec->vtx.vertex_size; \
374 exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \
375 \
376 if (++exec->vtx.vert_count >= exec->vtx.max_vert) \
377 vbo_exec_vtx_wrap( exec ); \
378 } \
379 } while (0)
380
381
382 #define ERROR() _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ )
383 #define TAG(x) vbo_##x
384
385 #include "vbo_attrib_tmp.h"
386
387
388
389
390
391 /* Eval
392 */
393 static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u )
394 {
395 GET_CURRENT_CONTEXT( ctx );
396 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
397
398 {
399 GLint i;
400 if (exec->eval.recalculate_maps)
401 vbo_exec_eval_update( exec );
402
403 for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
404 if (exec->eval.map1[i].map)
405 if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz)
406 vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz );
407 }
408 }
409
410
411 _mesa_memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
412 exec->vtx.vertex_size * sizeof(GLfloat));
413
414 vbo_exec_do_EvalCoord1f( exec, u );
415
416 _mesa_memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
417 exec->vtx.vertex_size * sizeof(GLfloat));
418 }
419
420 static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v )
421 {
422 GET_CURRENT_CONTEXT( ctx );
423 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
424
425 {
426 GLint i;
427 if (exec->eval.recalculate_maps)
428 vbo_exec_eval_update( exec );
429
430 for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
431 if (exec->eval.map2[i].map)
432 if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz)
433 vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz );
434 }
435
436 if (ctx->Eval.AutoNormal)
437 if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3)
438 vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3 );
439 }
440
441 _mesa_memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
442 exec->vtx.vertex_size * sizeof(GLfloat));
443
444 vbo_exec_do_EvalCoord2f( exec, u, v );
445
446 _mesa_memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
447 exec->vtx.vertex_size * sizeof(GLfloat));
448 }
449
450 static void GLAPIENTRY vbo_exec_EvalCoord1fv( const GLfloat *u )
451 {
452 vbo_exec_EvalCoord1f( u[0] );
453 }
454
455 static void GLAPIENTRY vbo_exec_EvalCoord2fv( const GLfloat *u )
456 {
457 vbo_exec_EvalCoord2f( u[0], u[1] );
458 }
459
460 static void GLAPIENTRY vbo_exec_EvalPoint1( GLint i )
461 {
462 GET_CURRENT_CONTEXT( ctx );
463 GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) /
464 (GLfloat) ctx->Eval.MapGrid1un);
465 GLfloat u = i * du + ctx->Eval.MapGrid1u1;
466
467 vbo_exec_EvalCoord1f( u );
468 }
469
470
471 static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j )
472 {
473 GET_CURRENT_CONTEXT( ctx );
474 GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) /
475 (GLfloat) ctx->Eval.MapGrid2un);
476 GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) /
477 (GLfloat) ctx->Eval.MapGrid2vn);
478 GLfloat u = i * du + ctx->Eval.MapGrid2u1;
479 GLfloat v = j * dv + ctx->Eval.MapGrid2v1;
480
481 vbo_exec_EvalCoord2f( u, v );
482 }
483
484
485 /**
486 * Check if programs/shaders are enabled and valid at glBegin time.
487 */
488 GLboolean
489 vbo_validate_shaders(GLcontext *ctx)
490 {
491 if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) ||
492 (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) {
493 return GL_FALSE;
494 }
495 if (ctx->Shader.CurrentProgram && !ctx->Shader.CurrentProgram->LinkStatus) {
496 return GL_FALSE;
497 }
498 return GL_TRUE;
499 }
500
501
502 /* Build a list of primitives on the fly. Keep
503 * ctx->Driver.CurrentExecPrimitive uptodate as well.
504 */
505 static void GLAPIENTRY vbo_exec_Begin( GLenum mode )
506 {
507 GET_CURRENT_CONTEXT( ctx );
508
509 if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) {
510 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
511 int i;
512
513 if (ctx->NewState) {
514 _mesa_update_state( ctx );
515
516 CALL_Begin(ctx->Exec, (mode));
517 return;
518 }
519
520 if (!vbo_validate_shaders(ctx)) {
521 _mesa_error(ctx, GL_INVALID_OPERATION,
522 "glBegin (invalid vertex/fragment program)");
523 return;
524 }
525
526 /* Heuristic: attempt to isolate attributes occuring outside
527 * begin/end pairs.
528 */
529 if (exec->vtx.vertex_size && !exec->vtx.attrsz[0])
530 vbo_exec_FlushVertices_internal( ctx, GL_FALSE );
531
532 i = exec->vtx.prim_count++;
533 exec->vtx.prim[i].mode = mode;
534 exec->vtx.prim[i].begin = 1;
535 exec->vtx.prim[i].end = 0;
536 exec->vtx.prim[i].indexed = 0;
537 exec->vtx.prim[i].weak = 0;
538 exec->vtx.prim[i].pad = 0;
539 exec->vtx.prim[i].start = exec->vtx.vert_count;
540 exec->vtx.prim[i].count = 0;
541
542 ctx->Driver.CurrentExecPrimitive = mode;
543 }
544 else
545 _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
546
547 }
548
549 static void GLAPIENTRY vbo_exec_End( void )
550 {
551 GET_CURRENT_CONTEXT( ctx );
552
553 if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
554 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
555 int idx = exec->vtx.vert_count;
556 int i = exec->vtx.prim_count - 1;
557
558 exec->vtx.prim[i].end = 1;
559 exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start;
560
561 ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
562
563 if (exec->vtx.prim_count == VBO_MAX_PRIM)
564 vbo_exec_vtx_flush( exec, GL_FALSE );
565 }
566 else
567 _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
568 }
569
570
571 static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
572 {
573 GLvertexformat *vfmt = &exec->vtxfmt;
574
575 vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
576 vfmt->Begin = vbo_exec_Begin;
577 #if FEATURE_dlist
578 vfmt->CallList = _mesa_CallList;
579 vfmt->CallLists = _mesa_CallLists;
580 #endif
581 vfmt->End = vbo_exec_End;
582 vfmt->EvalCoord1f = vbo_exec_EvalCoord1f;
583 vfmt->EvalCoord1fv = vbo_exec_EvalCoord1fv;
584 vfmt->EvalCoord2f = vbo_exec_EvalCoord2f;
585 vfmt->EvalCoord2fv = vbo_exec_EvalCoord2fv;
586 vfmt->EvalPoint1 = vbo_exec_EvalPoint1;
587 vfmt->EvalPoint2 = vbo_exec_EvalPoint2;
588
589 vfmt->Rectf = _mesa_noop_Rectf;
590 vfmt->EvalMesh1 = _mesa_noop_EvalMesh1;
591 vfmt->EvalMesh2 = _mesa_noop_EvalMesh2;
592
593
594 /* from attrib_tmp.h:
595 */
596 vfmt->Color3f = vbo_Color3f;
597 vfmt->Color3fv = vbo_Color3fv;
598 vfmt->Color4f = vbo_Color4f;
599 vfmt->Color4fv = vbo_Color4fv;
600 vfmt->FogCoordfEXT = vbo_FogCoordfEXT;
601 vfmt->FogCoordfvEXT = vbo_FogCoordfvEXT;
602 vfmt->MultiTexCoord1fARB = vbo_MultiTexCoord1f;
603 vfmt->MultiTexCoord1fvARB = vbo_MultiTexCoord1fv;
604 vfmt->MultiTexCoord2fARB = vbo_MultiTexCoord2f;
605 vfmt->MultiTexCoord2fvARB = vbo_MultiTexCoord2fv;
606 vfmt->MultiTexCoord3fARB = vbo_MultiTexCoord3f;
607 vfmt->MultiTexCoord3fvARB = vbo_MultiTexCoord3fv;
608 vfmt->MultiTexCoord4fARB = vbo_MultiTexCoord4f;
609 vfmt->MultiTexCoord4fvARB = vbo_MultiTexCoord4fv;
610 vfmt->Normal3f = vbo_Normal3f;
611 vfmt->Normal3fv = vbo_Normal3fv;
612 vfmt->SecondaryColor3fEXT = vbo_SecondaryColor3fEXT;
613 vfmt->SecondaryColor3fvEXT = vbo_SecondaryColor3fvEXT;
614 vfmt->TexCoord1f = vbo_TexCoord1f;
615 vfmt->TexCoord1fv = vbo_TexCoord1fv;
616 vfmt->TexCoord2f = vbo_TexCoord2f;
617 vfmt->TexCoord2fv = vbo_TexCoord2fv;
618 vfmt->TexCoord3f = vbo_TexCoord3f;
619 vfmt->TexCoord3fv = vbo_TexCoord3fv;
620 vfmt->TexCoord4f = vbo_TexCoord4f;
621 vfmt->TexCoord4fv = vbo_TexCoord4fv;
622 vfmt->Vertex2f = vbo_Vertex2f;
623 vfmt->Vertex2fv = vbo_Vertex2fv;
624 vfmt->Vertex3f = vbo_Vertex3f;
625 vfmt->Vertex3fv = vbo_Vertex3fv;
626 vfmt->Vertex4f = vbo_Vertex4f;
627 vfmt->Vertex4fv = vbo_Vertex4fv;
628
629 vfmt->VertexAttrib1fARB = vbo_VertexAttrib1fARB;
630 vfmt->VertexAttrib1fvARB = vbo_VertexAttrib1fvARB;
631 vfmt->VertexAttrib2fARB = vbo_VertexAttrib2fARB;
632 vfmt->VertexAttrib2fvARB = vbo_VertexAttrib2fvARB;
633 vfmt->VertexAttrib3fARB = vbo_VertexAttrib3fARB;
634 vfmt->VertexAttrib3fvARB = vbo_VertexAttrib3fvARB;
635 vfmt->VertexAttrib4fARB = vbo_VertexAttrib4fARB;
636 vfmt->VertexAttrib4fvARB = vbo_VertexAttrib4fvARB;
637
638 vfmt->VertexAttrib1fNV = vbo_VertexAttrib1fNV;
639 vfmt->VertexAttrib1fvNV = vbo_VertexAttrib1fvNV;
640 vfmt->VertexAttrib2fNV = vbo_VertexAttrib2fNV;
641 vfmt->VertexAttrib2fvNV = vbo_VertexAttrib2fvNV;
642 vfmt->VertexAttrib3fNV = vbo_VertexAttrib3fNV;
643 vfmt->VertexAttrib3fvNV = vbo_VertexAttrib3fvNV;
644 vfmt->VertexAttrib4fNV = vbo_VertexAttrib4fNV;
645 vfmt->VertexAttrib4fvNV = vbo_VertexAttrib4fvNV;
646
647 vfmt->Materialfv = vbo_Materialfv;
648
649 vfmt->EdgeFlag = vbo_EdgeFlag;
650 vfmt->Indexf = vbo_Indexf;
651 vfmt->Indexfv = vbo_Indexfv;
652
653 }
654
655
656 /**
657 * Tell the VBO module to use a real OpenGL vertex buffer object to
658 * store accumulated immediate-mode vertex data.
659 * This replaces the malloced buffer which was created in
660 * vb_exec_vtx_init() below.
661 */
662 void vbo_use_buffer_objects(GLcontext *ctx)
663 {
664 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
665 /* Any buffer name but 0 can be used here since this bufferobj won't
666 * go into the bufferobj hashtable.
667 */
668 GLuint bufName = 0xaabbccdd;
669 GLenum target = GL_ARRAY_BUFFER_ARB;
670 GLenum usage = GL_STREAM_DRAW_ARB;
671 GLsizei size = VBO_VERT_BUFFER_SIZE;
672
673 /* Make sure this func is only used once */
674 assert(exec->vtx.bufferobj == ctx->Array.NullBufferObj);
675 if (exec->vtx.buffer_map) {
676 _mesa_align_free(exec->vtx.buffer_map);
677 exec->vtx.buffer_map = NULL;
678 exec->vtx.buffer_ptr = NULL;
679 }
680
681 /* Allocate a real buffer object now */
682 exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName, target);
683 ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj);
684 }
685
686
687
688 void vbo_exec_vtx_init( struct vbo_exec_context *exec )
689 {
690 GLcontext *ctx = exec->ctx;
691 struct vbo_context *vbo = vbo_context(ctx);
692 GLuint i;
693
694 /* Allocate a buffer object. Will just reuse this object
695 * continuously, unless vbo_use_buffer_objects() is called to enable
696 * use of real VBOs.
697 */
698 _mesa_reference_buffer_object(ctx,
699 &exec->vtx.bufferobj,
700 ctx->Array.NullBufferObj);
701
702 ASSERT(!exec->vtx.buffer_map);
703 exec->vtx.buffer_map = (GLfloat *)ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE, 64);
704 exec->vtx.buffer_ptr = exec->vtx.buffer_map;
705
706 vbo_exec_vtxfmt_init( exec );
707
708 /* Hook our functions into the dispatch table.
709 */
710 _mesa_install_exec_vtxfmt( exec->ctx, &exec->vtxfmt );
711
712 for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
713 exec->vtx.attrsz[i] = 0;
714 exec->vtx.active_sz[i] = 0;
715 exec->vtx.inputs[i] = &exec->vtx.arrays[i];
716 }
717
718 {
719 struct gl_client_array *arrays = exec->vtx.arrays;
720 memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0]));
721 memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0]));
722 }
723
724 exec->vtx.vertex_size = 0;
725 }
726
727
728 void vbo_exec_vtx_destroy( struct vbo_exec_context *exec )
729 {
730 if (exec->vtx.bufferobj->Name) {
731 /* using a real VBO for vertex data */
732 GLcontext *ctx = exec->ctx;
733 _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
734 }
735 else {
736 /* just using malloc'd space for vertex data */
737 if (exec->vtx.buffer_map) {
738 ALIGN_FREE(exec->vtx.buffer_map);
739 exec->vtx.buffer_map = NULL;
740 exec->vtx.buffer_ptr = NULL;
741 }
742 }
743 }
744
745 void vbo_exec_BeginVertices( GLcontext *ctx )
746 {
747 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
748 if (0) _mesa_printf("%s\n", __FUNCTION__);
749 vbo_exec_vtx_map( exec );
750
751 assert((exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0);
752 exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
753 }
754
755 void vbo_exec_FlushVertices_internal( GLcontext *ctx, GLboolean unmap )
756 {
757 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
758
759 if (exec->vtx.vert_count || unmap) {
760 vbo_exec_vtx_flush( exec, unmap );
761 }
762
763 if (exec->vtx.vertex_size) {
764 vbo_exec_copy_to_current( exec );
765 reset_attrfv( exec );
766 }
767 }
768
769
770
771 void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags )
772 {
773 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
774
775 if (0) _mesa_printf("%s\n", __FUNCTION__);
776
777 if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
778 if (0) _mesa_printf("%s - inside begin/end\n", __FUNCTION__);
779 return;
780 }
781
782 vbo_exec_FlushVertices_internal( ctx, GL_TRUE );
783
784 /* Need to do this to ensure BeginVertices gets called again:
785 */
786 if (exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) {
787 _mesa_restore_exec_vtxfmt( ctx );
788 exec->ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
789 }
790
791 exec->ctx->Driver.NeedFlush &= ~flags;
792 }
793
794
795 static void reset_attrfv( struct vbo_exec_context *exec )
796 {
797 GLuint i;
798
799 for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
800 exec->vtx.attrsz[i] = 0;
801 exec->vtx.active_sz[i] = 0;
802 }
803
804 exec->vtx.vertex_size = 0;
805 }
806
807
808 void GLAPIENTRY
809 _vbo_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
810 {
811 vbo_Color4f(r, g, b, a);
812 }
813
814
815 void GLAPIENTRY
816 _vbo_Normal3f(GLfloat x, GLfloat y, GLfloat z)
817 {
818 vbo_Normal3f(x, y, z);
819 }
820
821
822 void GLAPIENTRY
823 _vbo_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
824 {
825 vbo_MultiTexCoord4f(target, s, t, r, q);
826 }
827
828 void GLAPIENTRY
829 _vbo_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
830 {
831 vbo_Materialfv(face, pname, params);
832 }
833
834
835 void GLAPIENTRY
836 _vbo_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
837 {
838 vbo_VertexAttrib4fARB(index, x, y, z, w);
839 }