Minor r200 vertex program cleanups. Remove disabled leftovers from r300 vertex progra...
[mesa.git] / src / mesa / drivers / dri / i965 / brw_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 "brw_exec.h"
45
46 static void reset_attrfv( struct brw_exec_context *exec );
47
48 static brw_attrfv_func choose[BRW_MAX_ATTR_CODEGEN+1][4]; /* +1 for ERROR_ATTRIB */
49 static brw_attrfv_func generic_attr_func[BRW_MAX_ATTR_CODEGEN][4];
50
51
52 /* Close off the last primitive, execute the buffer, restart the
53 * primitive.
54 */
55 static void brw_exec_wrap_buffers( struct brw_exec_context *exec )
56 {
57 if (exec->vtx.prim_count == 0) {
58 exec->vtx.copied.nr = 0;
59 exec->vtx.vert_count = 0;
60 exec->vtx.vbptr = (GLfloat *)exec->vtx.buffer_map;
61 }
62 else {
63 GLuint last_begin = exec->vtx.prim[exec->vtx.prim_count-1].begin;
64 GLuint last_count;
65
66 if (exec->ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
67 GLint i = exec->vtx.prim_count - 1;
68 assert(i >= 0);
69 exec->vtx.prim[i].count = (exec->vtx.vert_count -
70 exec->vtx.prim[i].start);
71 }
72
73 last_count = exec->vtx.prim[exec->vtx.prim_count-1].count;
74
75 /* Execute the buffer and save copied vertices.
76 */
77 if (exec->vtx.vert_count)
78 brw_exec_vtx_flush( exec );
79 else {
80 exec->vtx.prim_count = 0;
81 exec->vtx.copied.nr = 0;
82 }
83
84 /* Emit a glBegin to start the new list.
85 */
86 assert(exec->vtx.prim_count == 0);
87
88 if (exec->ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
89 exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive;
90 exec->vtx.prim[0].start = 0;
91 exec->vtx.prim[0].count = 0;
92 exec->vtx.prim_count++;
93
94 if (exec->vtx.copied.nr == last_count)
95 exec->vtx.prim[0].begin = last_begin;
96 }
97 }
98 }
99
100
101 /* Deal with buffer wrapping where provoked by the vertex buffer
102 * filling up, as opposed to upgrade_vertex().
103 */
104 void brw_exec_vtx_wrap( struct brw_exec_context *exec )
105 {
106 GLfloat *data = exec->vtx.copied.buffer;
107 GLuint i;
108
109 /* Run pipeline on current vertices, copy wrapped vertices
110 * to exec->vtx.copied.
111 */
112 brw_exec_wrap_buffers( exec );
113
114 /* Copy stored stored vertices to start of new list.
115 */
116 assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr);
117
118 for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
119 _mesa_memcpy( exec->vtx.vbptr, data,
120 exec->vtx.vertex_size * sizeof(GLfloat));
121 exec->vtx.vbptr += exec->vtx.vertex_size;
122 data += exec->vtx.vertex_size;
123 exec->vtx.vert_count++;
124 }
125
126 exec->vtx.copied.nr = 0;
127 }
128
129
130 /*
131 * Copy the active vertex's values to the ctx->Current fields.
132 */
133 static void brw_exec_copy_to_current( struct brw_exec_context *exec )
134 {
135 GLcontext *ctx = exec->ctx;
136 GLuint i;
137
138 for (i = BRW_ATTRIB_POS+1 ; i < BRW_ATTRIB_INDEX ; i++) {
139 if (exec->vtx.attrsz[i]) {
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(exec->vtx.current[i],
144 exec->vtx.attrsz[i],
145 exec->vtx.attrptr[i]);
146
147 /* This triggers rather too much recalculation of Mesa state
148 * that doesn't get used (eg light positions).
149 */
150 if (i >= BRW_ATTRIB_MAT_FRONT_AMBIENT &&
151 i <= BRW_ATTRIB_MAT_BACK_INDEXES)
152 ctx->NewState |= _NEW_LIGHT;
153 }
154 }
155
156 /* color index is special (it's not a float[4] so COPY_CLEAN_4V above
157 * will trash adjacent memory!)
158 */
159 if (exec->vtx.attrsz[BRW_ATTRIB_INDEX]) {
160 ctx->Current.Index = exec->vtx.attrptr[BRW_ATTRIB_INDEX][0];
161 }
162
163 /* Edgeflag requires additional treatment:
164 */
165 if (exec->vtx.attrsz[BRW_ATTRIB_EDGEFLAG]) {
166 ctx->Current.EdgeFlag = (exec->vtx.CurrentFloatEdgeFlag == 1.0);
167 }
168
169 #if 1
170 /* Colormaterial -- this kindof sucks.
171 */
172 if (ctx->Light.ColorMaterialEnabled &&
173 exec->vtx.attrsz[VERT_ATTRIB_COLOR0]) {
174 _mesa_update_color_material(ctx,
175 ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
176 }
177 #endif
178
179 ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
180 }
181
182
183 static void brw_exec_copy_from_current( struct brw_exec_context *exec )
184 {
185 GLcontext *ctx = exec->ctx;
186 GLint i;
187
188 /* Edgeflag requires additional treatment:
189 */
190 exec->vtx.CurrentFloatEdgeFlag =
191 (GLfloat)ctx->Current.EdgeFlag;
192
193 for (i = BRW_ATTRIB_POS+1 ; i < BRW_ATTRIB_MAX ; i++)
194 switch (exec->vtx.attrsz[i]) {
195 case 4: exec->vtx.attrptr[i][3] = exec->vtx.current[i][3];
196 case 3: exec->vtx.attrptr[i][2] = exec->vtx.current[i][2];
197 case 2: exec->vtx.attrptr[i][1] = exec->vtx.current[i][1];
198 case 1: exec->vtx.attrptr[i][0] = exec->vtx.current[i][0];
199 break;
200 }
201
202 ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
203 }
204
205
206 /* Flush existing data, set new attrib size, replay copied vertices.
207 */
208 static void brw_exec_wrap_upgrade_vertex( struct brw_exec_context *exec,
209 GLuint attr,
210 GLuint newsz )
211 {
212 GLcontext *ctx = exec->ctx;
213 GLint lastcount = exec->vtx.vert_count;
214 GLfloat *tmp;
215 GLuint oldsz;
216 GLuint i;
217
218 /* Run pipeline on current vertices, copy wrapped vertices
219 * to exec->vtx.copied.
220 */
221 brw_exec_wrap_buffers( exec );
222
223
224 /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
225 * when the attribute already exists in the vertex and is having
226 * its size increased.
227 */
228 brw_exec_copy_to_current( exec );
229
230
231 /* Heuristic: Attempt to isolate attributes received outside
232 * begin/end so that they don't bloat the vertices.
233 */
234 if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END &&
235 exec->vtx.attrsz[attr] == 0 &&
236 lastcount > 8 &&
237 exec->vtx.vertex_size) {
238 reset_attrfv( exec );
239 }
240
241 /* Fix up sizes:
242 */
243 oldsz = exec->vtx.attrsz[attr];
244 exec->vtx.attrsz[attr] = newsz;
245
246 exec->vtx.vertex_size += newsz - oldsz;
247 exec->vtx.max_vert = BRW_VERT_BUFFER_SIZE / exec->vtx.vertex_size;
248 exec->vtx.vert_count = 0;
249 exec->vtx.vbptr = (GLfloat *)exec->vtx.buffer_map;
250
251
252 /* Recalculate all the attrptr[] values
253 */
254 for (i = 0, tmp = exec->vtx.vertex ; i < BRW_ATTRIB_MAX ; i++) {
255 if (exec->vtx.attrsz[i]) {
256 exec->vtx.attrptr[i] = tmp;
257 tmp += exec->vtx.attrsz[i];
258 }
259 else
260 exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */
261 }
262
263 /* Copy from current to repopulate the vertex with correct values.
264 */
265 brw_exec_copy_from_current( exec );
266
267 /* Replay stored vertices to translate them
268 * to new format here.
269 *
270 * -- No need to replay - just copy piecewise
271 */
272 if (exec->vtx.copied.nr)
273 {
274 GLfloat *data = exec->vtx.copied.buffer;
275 GLfloat *dest = exec->vtx.vbptr;
276 GLuint j;
277
278 assert(exec->vtx.vbptr == (GLfloat *)exec->vtx.buffer_map);
279
280 for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
281 for (j = 0 ; j < BRW_ATTRIB_MAX ; j++) {
282 if (exec->vtx.attrsz[j]) {
283 if (j == attr) {
284 if (oldsz) {
285 COPY_CLEAN_4V( dest, oldsz, data );
286 data += oldsz;
287 dest += newsz;
288 } else {
289 COPY_SZ_4V( dest, newsz, exec->vtx.current[j] );
290 dest += newsz;
291 }
292 }
293 else {
294 GLuint sz = exec->vtx.attrsz[j];
295 COPY_SZ_4V( dest, sz, data );
296 dest += sz;
297 data += sz;
298 }
299 }
300 }
301 }
302
303 exec->vtx.vbptr = dest;
304 exec->vtx.vert_count += exec->vtx.copied.nr;
305 exec->vtx.copied.nr = 0;
306 }
307
308 /* For codegen - attrptr's may have changed, so need to redo
309 * codegen. Might be a reasonable place to try & detect attributes
310 * in the vertex which aren't being submitted any more.
311 */
312 for (i = 0 ; i < BRW_ATTRIB_MAX ; i++)
313 if (exec->vtx.attrsz[i]) {
314 GLuint j = exec->vtx.attrsz[i] - 1;
315
316 if (i < BRW_MAX_ATTR_CODEGEN)
317 exec->vtx.tabfv[i][j] = choose[i][j];
318 }
319
320 }
321
322
323 static void brw_exec_fixup_vertex( struct brw_exec_context *exec,
324 GLuint attr, GLuint sz )
325 {
326 static const GLfloat id[4] = { 0, 0, 0, 1 };
327 int i;
328
329 if (exec->vtx.attrsz[attr] < sz) {
330 /* New size is larger. Need to flush existing vertices and get
331 * an enlarged vertex format.
332 */
333 brw_exec_wrap_upgrade_vertex( exec, attr, sz );
334 }
335 else if (exec->vtx.attrsz[attr] > sz) {
336 /* New size is smaller - just need to fill in some
337 * zeros. Don't need to flush or wrap.
338 */
339 for (i = sz ; i <= exec->vtx.attrsz[attr] ; i++)
340 exec->vtx.attrptr[attr][i-1] = id[i-1];
341 }
342
343 /* Does setting NeedFlush belong here? Necessitates resetting
344 * vtxfmt on each flush (otherwise flags won't get reset
345 * afterwards).
346 */
347 if (attr == 0)
348 exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
349 else
350 exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
351 }
352
353
354 /* Helper function for 'CHOOSE' macro. Do what's necessary when an
355 * entrypoint is called for the first time.
356 */
357
358 static brw_attrfv_func do_choose( GLuint attr, GLuint sz )
359 {
360 GET_CURRENT_CONTEXT( ctx );
361 struct brw_exec_context *exec = IMM_CONTEXT(ctx)->exec;
362 GLuint oldsz = exec->vtx.attrsz[attr];
363
364 assert(attr < BRW_MAX_ATTR_CODEGEN);
365
366 if (oldsz != sz) {
367 /* Reset any active pointers for this attribute
368 */
369 if (oldsz)
370 exec->vtx.tabfv[attr][oldsz-1] = choose[attr][oldsz-1];
371
372 brw_exec_fixup_vertex( exec, attr, sz );
373
374 }
375
376 /* Codegen?
377 */
378
379 /* Else use generic version:
380 */
381 exec->vtx.tabfv[attr][sz-1] = generic_attr_func[attr][sz-1];
382
383 return exec->vtx.tabfv[attr][sz-1];
384 }
385
386
387
388 #define CHOOSE( ATTR, N ) \
389 static void choose_##ATTR##_##N( const GLfloat *v ) \
390 { \
391 brw_attrfv_func f = do_choose(ATTR, N); \
392 f( v ); \
393 }
394
395 #define CHOOSERS( ATTRIB ) \
396 CHOOSE( ATTRIB, 1 ) \
397 CHOOSE( ATTRIB, 2 ) \
398 CHOOSE( ATTRIB, 3 ) \
399 CHOOSE( ATTRIB, 4 ) \
400
401
402 #define INIT_CHOOSERS(ATTR) \
403 choose[ATTR][0] = choose_##ATTR##_1; \
404 choose[ATTR][1] = choose_##ATTR##_2; \
405 choose[ATTR][2] = choose_##ATTR##_3; \
406 choose[ATTR][3] = choose_##ATTR##_4;
407
408 CHOOSERS( 0 )
409 CHOOSERS( 1 )
410 CHOOSERS( 2 )
411 CHOOSERS( 3 )
412 CHOOSERS( 4 )
413 CHOOSERS( 5 )
414 CHOOSERS( 6 )
415 CHOOSERS( 7 )
416 CHOOSERS( 8 )
417 CHOOSERS( 9 )
418 CHOOSERS( 10 )
419 CHOOSERS( 11 )
420 CHOOSERS( 12 )
421 CHOOSERS( 13 )
422 CHOOSERS( 14 )
423 CHOOSERS( 15 )
424
425 static void error_attrib( const GLfloat *unused )
426 {
427 GET_CURRENT_CONTEXT( ctx );
428 (void) unused;
429 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttrib" );
430 }
431
432
433
434 static void reset_attrfv( struct brw_exec_context *exec )
435 {
436 GLuint i;
437
438 for (i = 0 ; i < BRW_ATTRIB_MAX ; i++)
439 if (exec->vtx.attrsz[i]) {
440 GLint j = exec->vtx.attrsz[i] - 1;
441 exec->vtx.attrsz[i] = 0;
442
443 if (i < BRW_MAX_ATTR_CODEGEN) {
444 while (j >= 0) {
445 exec->vtx.tabfv[i][j] = choose[i][j];
446 j--;
447 }
448 }
449 }
450
451 exec->vtx.vertex_size = 0;
452 }
453
454
455
456 /* Materials:
457 *
458 * These are treated as per-vertex attributes, at indices above where
459 * the NV_vertex_program leaves off. There are a lot of good things
460 * about treating materials this way.
461 *
462 * However: I don't want to double the number of generated functions
463 * just to cope with this, so I unroll the 'C' varients of CHOOSE and
464 * ATTRF into this function, and dispense with codegen and
465 * second-level dispatch.
466 *
467 * There is no aliasing of material attributes with other entrypoints.
468 */
469 #define OTHER_ATTR( exec, A, N, params ) \
470 do { \
471 if (exec->vtx.attrsz[A] != N) { \
472 brw_exec_fixup_vertex( exec, A, N ); \
473 } \
474 \
475 { \
476 GLfloat *dest = exec->vtx.attrptr[A]; \
477 if (N>0) dest[0] = (params)[0]; \
478 if (N>1) dest[1] = (params)[1]; \
479 if (N>2) dest[2] = (params)[2]; \
480 if (N>3) dest[3] = (params)[3]; \
481 } \
482 } while (0)
483
484
485 #define MAT( exec, ATTR, N, face, params ) \
486 do { \
487 if (face != GL_BACK) \
488 OTHER_ATTR( exec, ATTR, N, params ); /* front */ \
489 if (face != GL_FRONT) \
490 OTHER_ATTR( exec, ATTR + 1, N, params ); /* back */ \
491 } while (0)
492
493
494 /* Colormaterial is dealt with later on.
495 */
496 static void GLAPIENTRY brw_exec_Materialfv( GLenum face, GLenum pname,
497 const GLfloat *params )
498 {
499 GET_CURRENT_CONTEXT( ctx );
500 struct brw_exec_context *exec = IMM_CONTEXT(ctx)->exec;
501
502 switch (face) {
503 case GL_FRONT:
504 case GL_BACK:
505 case GL_FRONT_AND_BACK:
506 break;
507
508 default:
509 _mesa_error( ctx, GL_INVALID_ENUM, "glMaterialfv" );
510 return;
511 }
512
513 switch (pname) {
514 case GL_EMISSION:
515 MAT( exec, BRW_ATTRIB_MAT_FRONT_EMISSION, 4, face, params );
516 break;
517 case GL_AMBIENT:
518 MAT( exec, BRW_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params );
519 break;
520 case GL_DIFFUSE:
521 MAT( exec, BRW_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params );
522 break;
523 case GL_SPECULAR:
524 MAT( exec, BRW_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params );
525 break;
526 case GL_SHININESS:
527 MAT( exec, BRW_ATTRIB_MAT_FRONT_SHININESS, 1, face, params );
528 break;
529 case GL_COLOR_INDEXES:
530 MAT( exec, BRW_ATTRIB_MAT_FRONT_INDEXES, 3, face, params );
531 break;
532 case GL_AMBIENT_AND_DIFFUSE:
533 MAT( exec, BRW_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params );
534 MAT( exec, BRW_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params );
535 break;
536 default:
537 _mesa_error( ctx, GL_INVALID_ENUM, "glMaterialfv" );
538 return;
539 }
540 }
541
542
543 static void GLAPIENTRY brw_exec_EdgeFlag( GLboolean b )
544 {
545 GET_CURRENT_CONTEXT( ctx );
546 struct brw_exec_context *exec = IMM_CONTEXT(ctx)->exec;
547 GLfloat f = (GLfloat)b;
548
549 OTHER_ATTR( exec, BRW_ATTRIB_EDGEFLAG, 1, &f );
550 }
551
552 #if 0
553 static void GLAPIENTRY brw_exec_EdgeFlagv( const GLboolean *v )
554 {
555 GET_CURRENT_CONTEXT( ctx );
556 struct brw_exec_context *exec = IMM_CONTEXT(ctx)->exec;
557 GLfloat f = (GLfloat)v[0];
558
559 OTHER_ATTR( exec, BRW_ATTRIB_EDGEFLAG, 1, &f );
560 }
561 #endif
562
563 static void GLAPIENTRY brw_exec_Indexf( GLfloat f )
564 {
565 GET_CURRENT_CONTEXT( ctx );
566 struct brw_exec_context *exec = IMM_CONTEXT(ctx)->exec;
567
568 OTHER_ATTR( exec, BRW_ATTRIB_INDEX, 1, &f );
569 }
570
571 static void GLAPIENTRY brw_exec_Indexfv( const GLfloat *v )
572 {
573 GET_CURRENT_CONTEXT( ctx );
574 struct brw_exec_context *exec = IMM_CONTEXT(ctx)->exec;
575
576 OTHER_ATTR( exec, BRW_ATTRIB_INDEX, 1, v );
577 }
578
579 /* Eval
580 */
581 static void GLAPIENTRY brw_exec_EvalCoord1f( GLfloat u )
582 {
583 GET_CURRENT_CONTEXT( ctx );
584 struct brw_exec_context *exec = IMM_CONTEXT(ctx)->exec;
585
586 /* TODO: use a CHOOSE() function for this: */
587 {
588 GLint i;
589 if (exec->eval.recalculate_maps)
590 brw_exec_eval_update( exec );
591
592 for (i = 0 ; i <= BRW_ATTRIB_INDEX ; i++) {
593 if (exec->eval.map1[i].map)
594 if (exec->vtx.attrsz[i] != exec->eval.map1[i].sz)
595 brw_exec_fixup_vertex( exec, i, exec->eval.map1[i].sz );
596 }
597 }
598
599
600 _mesa_memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
601 exec->vtx.vertex_size * sizeof(GLfloat));
602
603 brw_exec_do_EvalCoord1f( exec, u );
604
605 _mesa_memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
606 exec->vtx.vertex_size * sizeof(GLfloat));
607 }
608
609 static void GLAPIENTRY brw_exec_EvalCoord2f( GLfloat u, GLfloat v )
610 {
611 GET_CURRENT_CONTEXT( ctx );
612 struct brw_exec_context *exec = IMM_CONTEXT(ctx)->exec;
613
614 /* TODO: use a CHOOSE() function for this: */
615 {
616 GLint i;
617 if (exec->eval.recalculate_maps)
618 brw_exec_eval_update( exec );
619
620 for (i = 0 ; i <= BRW_ATTRIB_INDEX ; i++) {
621 if (exec->eval.map2[i].map)
622 if (exec->vtx.attrsz[i] != exec->eval.map2[i].sz)
623 brw_exec_fixup_vertex( exec, i, exec->eval.map2[i].sz );
624 }
625
626 if (ctx->Eval.AutoNormal)
627 if (exec->vtx.attrsz[BRW_ATTRIB_NORMAL] != 3)
628 brw_exec_fixup_vertex( exec, BRW_ATTRIB_NORMAL, 3 );
629 }
630
631 _mesa_memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
632 exec->vtx.vertex_size * sizeof(GLfloat));
633
634 brw_exec_do_EvalCoord2f( exec, u, v );
635
636 _mesa_memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
637 exec->vtx.vertex_size * sizeof(GLfloat));
638 }
639
640 static void GLAPIENTRY brw_exec_EvalCoord1fv( const GLfloat *u )
641 {
642 brw_exec_EvalCoord1f( u[0] );
643 }
644
645 static void GLAPIENTRY brw_exec_EvalCoord2fv( const GLfloat *u )
646 {
647 brw_exec_EvalCoord2f( u[0], u[1] );
648 }
649
650 static void GLAPIENTRY brw_exec_EvalPoint1( GLint i )
651 {
652 GET_CURRENT_CONTEXT( ctx );
653 GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) /
654 (GLfloat) ctx->Eval.MapGrid1un);
655 GLfloat u = i * du + ctx->Eval.MapGrid1u1;
656
657 brw_exec_EvalCoord1f( u );
658 }
659
660
661 static void GLAPIENTRY brw_exec_EvalPoint2( GLint i, GLint j )
662 {
663 GET_CURRENT_CONTEXT( ctx );
664 GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) /
665 (GLfloat) ctx->Eval.MapGrid2un);
666 GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) /
667 (GLfloat) ctx->Eval.MapGrid2vn);
668 GLfloat u = i * du + ctx->Eval.MapGrid2u1;
669 GLfloat v = j * dv + ctx->Eval.MapGrid2v1;
670
671 brw_exec_EvalCoord2f( u, v );
672 }
673
674
675 /* Build a list of primitives on the fly. Keep
676 * ctx->Driver.CurrentExecPrimitive uptodate as well.
677 */
678 static void GLAPIENTRY brw_exec_Begin( GLenum mode )
679 {
680 GET_CURRENT_CONTEXT( ctx );
681
682 if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
683 struct brw_exec_context *exec = IMM_CONTEXT(ctx)->exec;
684 int i;
685
686 if (ctx->NewState) {
687 _mesa_update_state( ctx );
688
689 if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) ||
690 (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) {
691 _mesa_error(ctx, GL_INVALID_OPERATION,
692 "glBegin (invalid vertex/fragment program)");
693 return;
694 }
695
696 CALL_Begin(ctx->Exec, (mode));
697 return;
698 }
699
700 /* Heuristic: attempt to isolate attributes occuring outside
701 * begin/end pairs.
702 */
703 if (exec->vtx.vertex_size && !exec->vtx.attrsz[0])
704 brw_exec_FlushVertices( ctx, ~0 );
705
706 i = exec->vtx.prim_count++;
707 exec->vtx.prim[i].mode = mode;
708 exec->vtx.prim[i].begin = 1;
709 exec->vtx.prim[i].end = 0;
710 exec->vtx.prim[i].indexed = 0;
711 exec->vtx.prim[i].weak = 0;
712 exec->vtx.prim[i].pad = 0;
713 exec->vtx.prim[i].start = exec->vtx.vert_count;
714 exec->vtx.prim[i].count = 0;
715
716 ctx->Driver.CurrentExecPrimitive = mode;
717 }
718 else
719 _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
720
721 }
722
723 static void GLAPIENTRY brw_exec_End( void )
724 {
725 GET_CURRENT_CONTEXT( ctx );
726
727 if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
728 struct brw_exec_context *exec = IMM_CONTEXT(ctx)->exec;
729 int idx = exec->vtx.vert_count;
730 int i = exec->vtx.prim_count - 1;
731
732 exec->vtx.prim[i].end = 1;
733 exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start;
734
735 ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
736
737 if (exec->vtx.prim_count == BRW_MAX_PRIM)
738 brw_exec_vtx_flush( exec );
739 }
740 else
741 _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
742 }
743
744
745 static void brw_exec_vtxfmt_init( struct brw_exec_context *exec )
746 {
747 GLvertexformat *vfmt = &exec->vtxfmt;
748
749 vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
750 vfmt->Begin = brw_exec_Begin;
751 vfmt->CallList = _mesa_CallList;
752 vfmt->CallLists = _mesa_CallLists;
753 vfmt->EdgeFlag = brw_exec_EdgeFlag;
754 /* vfmt->EdgeFlagv = brw_exec_EdgeFlagv; */
755 vfmt->End = brw_exec_End;
756 vfmt->EvalCoord1f = brw_exec_EvalCoord1f;
757 vfmt->EvalCoord1fv = brw_exec_EvalCoord1fv;
758 vfmt->EvalCoord2f = brw_exec_EvalCoord2f;
759 vfmt->EvalCoord2fv = brw_exec_EvalCoord2fv;
760 vfmt->EvalPoint1 = brw_exec_EvalPoint1;
761 vfmt->EvalPoint2 = brw_exec_EvalPoint2;
762 vfmt->Indexf = brw_exec_Indexf;
763 vfmt->Indexfv = brw_exec_Indexfv;
764 vfmt->Materialfv = brw_exec_Materialfv;
765
766 vfmt->Rectf = _mesa_noop_Rectf;
767 vfmt->EvalMesh1 = _mesa_noop_EvalMesh1;
768 vfmt->EvalMesh2 = _mesa_noop_EvalMesh2;
769 }
770
771
772 static void brw_exec_current_init( struct brw_exec_context *exec )
773 {
774 GLcontext *ctx = exec->ctx;
775 GLint i;
776
777 /* setup the pointers for the typical 16 vertex attributes */
778 for (i = 0; i < BRW_ATTRIB_FIRST_MATERIAL; i++)
779 exec->vtx.current[i] = ctx->Current.Attrib[i];
780
781 /* setup pointers for the 12 material attributes */
782 for (i = 0; i < MAT_ATTRIB_MAX; i++)
783 exec->vtx.current[BRW_ATTRIB_FIRST_MATERIAL + i] =
784 ctx->Light.Material.Attrib[i];
785
786 exec->vtx.current[BRW_ATTRIB_INDEX] = &ctx->Current.Index;
787 exec->vtx.current[BRW_ATTRIB_EDGEFLAG] = &exec->vtx.CurrentFloatEdgeFlag;
788 }
789
790 void brw_exec_vtx_init( struct brw_exec_context *exec )
791 {
792 GLcontext *ctx = exec->ctx;
793 GLuint i;
794 static int firsttime = 1;
795
796 if (firsttime) {
797 firsttime = 0;
798
799 INIT_CHOOSERS( 0 );
800 INIT_CHOOSERS( 1 );
801 INIT_CHOOSERS( 2 );
802 INIT_CHOOSERS( 3 );
803 INIT_CHOOSERS( 4 );
804 INIT_CHOOSERS( 5 );
805 INIT_CHOOSERS( 6 );
806 INIT_CHOOSERS( 7 );
807 INIT_CHOOSERS( 8 );
808 INIT_CHOOSERS( 9 );
809 INIT_CHOOSERS( 10 );
810 INIT_CHOOSERS( 11 );
811 INIT_CHOOSERS( 12 );
812 INIT_CHOOSERS( 13 );
813 INIT_CHOOSERS( 14 );
814 INIT_CHOOSERS( 15 );
815
816 choose[ERROR_ATTRIB][0] = error_attrib;
817 choose[ERROR_ATTRIB][1] = error_attrib;
818 choose[ERROR_ATTRIB][2] = error_attrib;
819 choose[ERROR_ATTRIB][3] = error_attrib;
820
821 brw_exec_generic_attr_table_init( generic_attr_func );
822 }
823
824 /* Allocate a buffer object. Will just reuse this object
825 * continuously.
826 */
827 exec->vtx.bufferobj = ctx->Array.NullBufferObj;
828 exec->vtx.buffer_map = ALIGN_MALLOC(BRW_VERT_BUFFER_SIZE * sizeof(GLfloat), 64);
829
830 brw_exec_current_init( exec );
831 brw_exec_vtxfmt_init( exec );
832 brw_exec_vtx_generic_init( exec );
833
834 /* Hook our functions into the dispatch table.
835 */
836 _mesa_install_exec_vtxfmt( exec->ctx, &exec->vtxfmt );
837
838 memcpy( exec->vtx.tabfv, choose, sizeof(choose) );
839
840 for (i = 0 ; i < BRW_ATTRIB_MAX ; i++) {
841 exec->vtx.attrsz[i] = 0;
842 exec->vtx.inputs[i] = &exec->vtx.arrays[i];
843 }
844
845 exec->vtx.vertex_size = 0;
846 }
847
848
849 void brw_exec_vtx_destroy( struct brw_exec_context *exec )
850 {
851 if (exec->vtx.buffer_map) {
852 ALIGN_FREE(exec->vtx.buffer_map);
853 exec->vtx.buffer_map = NULL;
854 }
855 }
856
857
858 void brw_exec_FlushVertices( GLcontext *ctx, GLuint flags )
859 {
860 struct brw_exec_context *exec = IMM_CONTEXT(ctx)->exec;
861
862 if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END)
863 return;
864
865 if (exec->vtx.vert_count) {
866 brw_exec_vtx_flush( exec );
867 }
868
869 if (exec->vtx.vertex_size) {
870 brw_exec_copy_to_current( exec );
871 reset_attrfv( exec );
872 }
873
874 exec->ctx->Driver.NeedFlush = 0;
875 }
876
877