Minor r200 vertex program cleanups. Remove disabled leftovers from r300 vertex progra...
[mesa.git] / src / mesa / drivers / dri / i965 / brw_save_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
34
35 /* Display list compiler attempts to store lists of vertices with the
36 * same vertex layout. Additionally it attempts to minimize the need
37 * for execute-time fixup of these vertex lists, allowing them to be
38 * cached on hardware.
39 *
40 * There are still some circumstances where this can be thwarted, for
41 * example by building a list that consists of one very long primitive
42 * (eg Begin(Triangles), 1000 vertices, End), and calling that list
43 * from inside a different begin/end object (Begin(Lines), CallList,
44 * End).
45 *
46 * In that case the code will have to replay the list as individual
47 * commands through the Exec dispatch table, or fix up the copied
48 * vertices at execute-time.
49 *
50 * The other case where fixup is required is when a vertex attribute
51 * is introduced in the middle of a primitive. Eg:
52 * Begin(Lines)
53 * TexCoord1f() Vertex2f()
54 * TexCoord1f() Color3f() Vertex2f()
55 * End()
56 *
57 * If the current value of Color isn't known at compile-time, this
58 * primitive will require fixup.
59 *
60 *
61 * The list compiler currently doesn't attempt to compile lists
62 * containing EvalCoord or EvalPoint commands. On encountering one of
63 * these, compilation falls back to opcodes.
64 *
65 * This could be improved to fallback only when a mix of EvalCoord and
66 * Vertex commands are issued within a single primitive.
67 */
68
69
70 #include "glheader.h"
71 #include "context.h"
72 #include "dlist.h"
73 #include "enums.h"
74 #include "macros.h"
75 #include "api_validate.h"
76 #include "api_arrayelt.h"
77 #include "vtxfmt.h"
78 #include "dispatch.h"
79
80 #include "brw_save.h"
81 #include "brw_fallback.h"
82
83
84
85
86 /*
87 * NOTE: Old 'parity' issue is gone, but copying can still be
88 * wrong-footed on replay.
89 */
90 static GLuint _save_copy_vertices( GLcontext *ctx,
91 const struct brw_save_vertex_list *node,
92 const GLfloat *src_buffer)
93 {
94 struct brw_save_context *save = IMM_CONTEXT( ctx )->save;
95 const struct brw_draw_prim *prim = &node->prim[node->prim_count-1];
96 GLuint nr = prim->count;
97 GLuint sz = save->vertex_size;
98 const GLfloat *src = src_buffer + prim->start * sz;
99 GLfloat *dst = save->copied.buffer;
100 GLuint ovf, i;
101
102 if (prim->end)
103 return 0;
104
105 switch( prim->mode )
106 {
107 case GL_POINTS:
108 return 0;
109 case GL_LINES:
110 ovf = nr&1;
111 for (i = 0 ; i < ovf ; i++)
112 _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
113 return i;
114 case GL_TRIANGLES:
115 ovf = nr%3;
116 for (i = 0 ; i < ovf ; i++)
117 _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
118 return i;
119 case GL_QUADS:
120 ovf = nr&3;
121 for (i = 0 ; i < ovf ; i++)
122 _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
123 return i;
124 case GL_LINE_STRIP:
125 if (nr == 0)
126 return 0;
127 else {
128 _mesa_memcpy( dst, src+(nr-1)*sz, sz*sizeof(GLfloat) );
129 return 1;
130 }
131 case GL_LINE_LOOP:
132 case GL_TRIANGLE_FAN:
133 case GL_POLYGON:
134 if (nr == 0)
135 return 0;
136 else if (nr == 1) {
137 _mesa_memcpy( dst, src+0, sz*sizeof(GLfloat) );
138 return 1;
139 } else {
140 _mesa_memcpy( dst, src+0, sz*sizeof(GLfloat) );
141 _mesa_memcpy( dst+sz, src+(nr-1)*sz, sz*sizeof(GLfloat) );
142 return 2;
143 }
144 case GL_TRIANGLE_STRIP:
145 case GL_QUAD_STRIP:
146 switch (nr) {
147 case 0: ovf = 0; break;
148 case 1: ovf = 1; break;
149 default: ovf = 2 + (nr&1); break;
150 }
151 for (i = 0 ; i < ovf ; i++)
152 _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
153 return i;
154 default:
155 assert(0);
156 return 0;
157 }
158 }
159
160
161 static struct brw_save_vertex_store *alloc_vertex_store( GLcontext *ctx )
162 {
163 struct brw_save_vertex_store *vertex_store = CALLOC_STRUCT(brw_save_vertex_store);
164
165 /* obj->Name needs to be non-zero, but won't ever be examined more
166 * closely than that. In particular these buffers won't be entered
167 * into the hash and can never be confused with ones visible to the
168 * user. Perhaps there could be a special number for internal
169 * buffers:
170 */
171 vertex_store->bufferobj = ctx->Driver.NewBufferObject(ctx, 1, GL_ARRAY_BUFFER_ARB);
172
173 ctx->Driver.BufferData( ctx,
174 GL_ARRAY_BUFFER_ARB,
175 BRW_SAVE_BUFFER_SIZE * sizeof(GLfloat),
176 NULL,
177 GL_STATIC_DRAW_ARB,
178 vertex_store->bufferobj);
179
180 vertex_store->buffer = NULL;
181 vertex_store->used = 0;
182 vertex_store->refcount = 1;
183
184 return vertex_store;
185 }
186
187 static void free_vertex_store( GLcontext *ctx, struct brw_save_vertex_store *vertex_store )
188 {
189 assert(!vertex_store->buffer);
190
191 if (vertex_store->bufferobj)
192 ctx->Driver.DeleteBuffer( ctx, vertex_store->bufferobj );
193
194 FREE( vertex_store );
195 }
196
197 static GLfloat *map_vertex_store( GLcontext *ctx, struct brw_save_vertex_store *vertex_store )
198 {
199 assert(vertex_store->bufferobj);
200 assert(!vertex_store->buffer);
201 vertex_store->buffer = (GLfloat *)ctx->Driver.MapBuffer(ctx,
202 GL_ARRAY_BUFFER_ARB, /* not used */
203 GL_STATIC_DRAW_ARB, /* not used */
204 vertex_store->bufferobj);
205
206 assert(vertex_store->buffer);
207 return vertex_store->buffer + vertex_store->used;
208 }
209
210 static void unmap_vertex_store( GLcontext *ctx, struct brw_save_vertex_store *vertex_store )
211 {
212 ctx->Driver.UnmapBuffer( ctx, GL_ARRAY_BUFFER_ARB, vertex_store->bufferobj );
213 vertex_store->buffer = NULL;
214 }
215
216
217 static struct brw_save_primitive_store *alloc_prim_store( GLcontext *ctx )
218 {
219 struct brw_save_primitive_store *store = CALLOC_STRUCT(brw_save_primitive_store);
220 (void) ctx;
221 store->used = 0;
222 store->refcount = 1;
223 return store;
224 }
225
226 static void _save_reset_counters( GLcontext *ctx )
227 {
228 struct brw_save_context *save = IMM_CONTEXT(ctx)->save;
229
230 save->prim = save->prim_store->buffer + save->prim_store->used;
231 save->buffer = (save->vertex_store->buffer +
232 save->vertex_store->used);
233
234 assert(save->buffer == save->vbptr);
235
236 if (save->vertex_size)
237 save->max_vert = ((BRW_SAVE_BUFFER_SIZE - save->vertex_store->used) /
238 save->vertex_size);
239 else
240 save->max_vert = 0;
241
242 save->vert_count = 0;
243 save->prim_count = 0;
244 save->prim_max = BRW_SAVE_PRIM_SIZE - save->prim_store->used;
245 save->dangling_attr_ref = 0;
246 }
247
248
249 /* Insert the active immediate struct onto the display list currently
250 * being built.
251 */
252 static void _save_compile_vertex_list( GLcontext *ctx )
253 {
254 struct brw_save_context *save = IMM_CONTEXT(ctx)->save;
255 struct brw_save_vertex_list *node;
256
257 /* Allocate space for this structure in the display list currently
258 * being compiled.
259 */
260 node = (struct brw_save_vertex_list *)
261 _mesa_alloc_instruction(ctx, save->opcode_vertex_list, sizeof(*node));
262
263 if (!node)
264 return;
265
266 /* Duplicate our template, increment refcounts to the storage structs:
267 */
268 _mesa_memcpy(node->attrsz, save->attrsz, sizeof(node->attrsz));
269 node->vertex_size = save->vertex_size;
270 node->buffer_offset = (save->buffer - save->vertex_store->buffer) * sizeof(GLfloat);
271 node->count = save->vert_count;
272 node->wrap_count = save->copied.nr;
273 node->dangling_attr_ref = save->dangling_attr_ref;
274 node->prim = save->prim;
275 node->prim_count = save->prim_count;
276 node->vertex_store = save->vertex_store;
277 node->prim_store = save->prim_store;
278
279 node->vertex_store->refcount++;
280 node->prim_store->refcount++;
281
282 assert(node->attrsz[BRW_ATTRIB_POS] != 0 ||
283 node->count == 0);
284
285 if (save->dangling_attr_ref)
286 ctx->ListState.CurrentList->flags |= MESA_DLIST_DANGLING_REFS;
287
288 save->vertex_store->used += save->vertex_size * node->count;
289 save->prim_store->used += node->prim_count;
290
291
292 /* Copy duplicated vertices
293 */
294 save->copied.nr = _save_copy_vertices( ctx, node, save->buffer );
295
296
297 /* Deal with GL_COMPILE_AND_EXECUTE:
298 */
299 if (ctx->ExecuteFlag) {
300 struct _glapi_table *dispatch = GET_DISPATCH();
301
302 _glapi_set_dispatch(ctx->Exec);
303
304 brw_loopback_vertex_list( ctx,
305 (const GLfloat *)((const char *)save->vertex_store->buffer +
306 node->buffer_offset),
307 node->attrsz,
308 node->prim,
309 node->prim_count,
310 node->wrap_count,
311 node->vertex_size);
312
313 _glapi_set_dispatch(dispatch);
314 }
315
316
317 /* Decide whether the storage structs are full, or can be used for
318 * the next vertex lists as well.
319 */
320 if (save->vertex_store->used >
321 BRW_SAVE_BUFFER_SIZE - 16 * (save->vertex_size + 4)) {
322
323 /* Unmap old store:
324 */
325 unmap_vertex_store( ctx, save->vertex_store );
326
327 /* Release old reference:
328 */
329 save->vertex_store->refcount--;
330 assert(save->vertex_store->refcount != 0);
331 save->vertex_store = NULL;
332
333 /* Allocate and map new store:
334 */
335 save->vertex_store = alloc_vertex_store( ctx );
336 save->vbptr = map_vertex_store( ctx, save->vertex_store );
337 }
338
339 if (save->prim_store->used > BRW_SAVE_PRIM_SIZE - 6) {
340 save->prim_store->refcount--;
341 assert(save->prim_store->refcount != 0);
342 save->prim_store = alloc_prim_store( ctx );
343 }
344
345 /* Reset our structures for the next run of vertices:
346 */
347 _save_reset_counters( ctx );
348 }
349
350
351 /* TODO -- If no new vertices have been stored, don't bother saving
352 * it.
353 */
354 static void _save_wrap_buffers( GLcontext *ctx )
355 {
356 struct brw_save_context *save = IMM_CONTEXT(ctx)->save;
357 GLint i = save->prim_count - 1;
358 GLenum mode;
359 GLboolean weak;
360
361 assert(i < (GLint) save->prim_max);
362 assert(i >= 0);
363
364 /* Close off in-progress primitive.
365 */
366 save->prim[i].count = (save->vert_count -
367 save->prim[i].start);
368 mode = save->prim[i].mode;
369 weak = save->prim[i].weak;
370
371 /* store the copied vertices, and allocate a new list.
372 */
373 _save_compile_vertex_list( ctx );
374
375 /* Restart interrupted primitive
376 */
377 save->prim[0].mode = mode;
378 save->prim[0].weak = weak;
379 save->prim[0].begin = 0;
380 save->prim[0].end = 0;
381 save->prim[0].pad = 0;
382 save->prim[0].start = 0;
383 save->prim[0].count = 0;
384 save->prim_count = 1;
385 }
386
387
388
389 /* Called only when buffers are wrapped as the result of filling the
390 * vertex_store struct.
391 */
392 static void _save_wrap_filled_vertex( GLcontext *ctx )
393 {
394 struct brw_save_context *save = IMM_CONTEXT(ctx)->save;
395 GLfloat *data = save->copied.buffer;
396 GLuint i;
397
398 /* Emit a glEnd to close off the last vertex list.
399 */
400 _save_wrap_buffers( ctx );
401
402 /* Copy stored stored vertices to start of new list.
403 */
404 assert(save->max_vert - save->vert_count > save->copied.nr);
405
406 for (i = 0 ; i < save->copied.nr ; i++) {
407 _mesa_memcpy( save->vbptr, data, save->vertex_size * sizeof(GLfloat));
408 data += save->vertex_size;
409 save->vbptr += save->vertex_size;
410 save->vert_count++;
411 }
412 }
413
414
415 static void _save_copy_to_current( GLcontext *ctx )
416 {
417 struct brw_save_context *save = IMM_CONTEXT(ctx)->save;
418 GLuint i;
419
420 for (i = BRW_ATTRIB_POS+1 ; i <= BRW_ATTRIB_INDEX ; i++) {
421 if (save->attrsz[i]) {
422 save->currentsz[i][0] = save->attrsz[i];
423 COPY_CLEAN_4V(save->current[i],
424 save->attrsz[i],
425 save->attrptr[i]);
426 }
427 }
428
429 /* Edgeflag requires special treatment:
430 *
431 * TODO: change edgeflag to GLfloat in Mesa.
432 */
433 if (save->attrsz[BRW_ATTRIB_EDGEFLAG]) {
434 ctx->ListState.ActiveEdgeFlag = 1;
435 save->CurrentFloatEdgeFlag =
436 save->attrptr[BRW_ATTRIB_EDGEFLAG][0];
437 ctx->ListState.CurrentEdgeFlag =
438 (save->CurrentFloatEdgeFlag == 1.0);
439 }
440 }
441
442
443 static void _save_copy_from_current( GLcontext *ctx )
444 {
445 struct brw_save_context *save = IMM_CONTEXT(ctx)->save;
446 GLint i;
447
448 for (i = BRW_ATTRIB_POS+1 ; i <= BRW_ATTRIB_INDEX ; i++)
449 switch (save->attrsz[i]) {
450 case 4: save->attrptr[i][3] = save->current[i][3];
451 case 3: save->attrptr[i][2] = save->current[i][2];
452 case 2: save->attrptr[i][1] = save->current[i][1];
453 case 1: save->attrptr[i][0] = save->current[i][0];
454 case 0: break;
455 }
456
457 /* Edgeflag requires special treatment:
458 */
459 if (save->attrsz[BRW_ATTRIB_EDGEFLAG]) {
460 save->CurrentFloatEdgeFlag = (GLfloat)ctx->ListState.CurrentEdgeFlag;
461 save->attrptr[BRW_ATTRIB_EDGEFLAG][0] = save->CurrentFloatEdgeFlag;
462 }
463 }
464
465
466
467
468 /* Flush existing data, set new attrib size, replay copied vertices.
469 */
470 static void _save_upgrade_vertex( GLcontext *ctx,
471 GLuint attr,
472 GLuint newsz )
473 {
474 struct brw_save_context *save = IMM_CONTEXT(ctx)->save;
475 GLuint oldsz;
476 GLuint i;
477 GLfloat *tmp;
478
479 /* Store the current run of vertices, and emit a GL_END. Emit a
480 * BEGIN in the new buffer.
481 */
482 if (save->vert_count)
483 _save_wrap_buffers( ctx );
484 else
485 assert( save->copied.nr == 0 );
486
487 /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
488 * when the attribute already exists in the vertex and is having
489 * its size increased.
490 */
491 _save_copy_to_current( ctx );
492
493 /* Fix up sizes:
494 */
495 oldsz = save->attrsz[attr];
496 save->attrsz[attr] = newsz;
497
498 save->vertex_size += newsz - oldsz;
499 save->max_vert = ((BRW_SAVE_BUFFER_SIZE - save->vertex_store->used) /
500 save->vertex_size);
501 save->vert_count = 0;
502
503 /* Recalculate all the attrptr[] values:
504 */
505 for (i = 0, tmp = save->vertex ; i < BRW_ATTRIB_MAX ; i++) {
506 if (save->attrsz[i]) {
507 save->attrptr[i] = tmp;
508 tmp += save->attrsz[i];
509 }
510 else
511 save->attrptr[i] = NULL; /* will not be dereferenced. */
512 }
513
514 /* Copy from current to repopulate the vertex with correct values.
515 */
516 _save_copy_from_current( ctx );
517
518 /* Replay stored vertices to translate them to new format here.
519 *
520 * If there are copied vertices and the new (upgraded) attribute
521 * has not been defined before, this list is somewhat degenerate,
522 * and will need fixup at runtime.
523 */
524 if (save->copied.nr)
525 {
526 GLfloat *data = save->copied.buffer;
527 GLfloat *dest = save->buffer;
528 GLuint j;
529
530 /* Need to note this and fix up at runtime (or loopback):
531 */
532 if (save->currentsz[attr][0] == 0) {
533 assert(oldsz == 0);
534 save->dangling_attr_ref = GL_TRUE;
535 }
536
537 for (i = 0 ; i < save->copied.nr ; i++) {
538 for (j = 0 ; j < BRW_ATTRIB_MAX ; j++) {
539 if (save->attrsz[j]) {
540 if (j == attr) {
541 if (oldsz) {
542 COPY_CLEAN_4V( dest, oldsz, data );
543 data += oldsz;
544 dest += newsz;
545 }
546 else {
547 COPY_SZ_4V( dest, newsz, save->current[attr] );
548 dest += newsz;
549 }
550 }
551 else {
552 GLint sz = save->attrsz[j];
553 COPY_SZ_4V( dest, sz, data );
554 data += sz;
555 dest += sz;
556 }
557 }
558 }
559 }
560
561 save->vbptr = dest;
562 save->vert_count += save->copied.nr;
563 }
564 }
565
566
567
568
569 /* Helper function for 'CHOOSE' macro. Do what's necessary when an
570 * entrypoint is called for the first time.
571 */
572 static void do_choose( GLuint attr, GLuint sz,
573 void (*attr_func)( const GLfloat *),
574 void (*choose1)( const GLfloat *),
575 void (*choose2)( const GLfloat *),
576 void (*choose3)( const GLfloat *),
577 void (*choose4)( const GLfloat *),
578 const GLfloat *v )
579 {
580 GET_CURRENT_CONTEXT( ctx );
581 struct brw_save_context *save = IMM_CONTEXT(ctx)->save;
582 static GLfloat id[4] = { 0, 0, 0, 1 };
583 int i;
584
585 if (save->attrsz[attr] < sz) {
586 /* New size is larger. Need to flush existing vertices and get
587 * an enlarged vertex format.
588 */
589 _save_upgrade_vertex( ctx, attr, sz );
590 }
591 else {
592 /* New size is equal or smaller - just need to fill in some
593 * zeros.
594 */
595 for (i = sz ; i <= save->attrsz[attr] ; i++)
596 save->attrptr[attr][i-1] = id[i-1];
597 }
598
599 /* Reset any active pointers for this attribute
600 */
601 save->tabfv[attr][0] = choose1;
602 save->tabfv[attr][1] = choose2;
603 save->tabfv[attr][2] = choose3;
604 save->tabfv[attr][3] = choose4;
605
606 /* Update the secondary dispatch table with the new function
607 */
608 save->tabfv[attr][sz-1] = attr_func;
609
610 (*attr_func)(v);
611 }
612
613
614
615 /* Only one size for each attribute may be active at once. Eg. if
616 * Color3f is installed/active, then Color4f may not be, even if the
617 * vertex actually contains 4 color coordinates. This is because the
618 * 3f version won't otherwise set color[3] to 1.0 -- this is the job
619 * of the chooser function when switching between Color4f and Color3f.
620 */
621 #define ATTRFV( ATTR, N ) \
622 static void save_choose_##ATTR##_##N( const GLfloat *v ); \
623 \
624 static void save_attrib_##ATTR##_##N( const GLfloat *v ) \
625 { \
626 GET_CURRENT_CONTEXT( ctx ); \
627 struct brw_save_context *save = IMM_CONTEXT(ctx)->save; \
628 \
629 if ((ATTR) == 0) { \
630 GLuint i; \
631 \
632 if (N>0) save->vbptr[0] = v[0]; \
633 if (N>1) save->vbptr[1] = v[1]; \
634 if (N>2) save->vbptr[2] = v[2]; \
635 if (N>3) save->vbptr[3] = v[3]; \
636 \
637 for (i = N; i < save->vertex_size; i++) \
638 save->vbptr[i] = save->vertex[i]; \
639 \
640 save->vbptr += save->vertex_size; \
641 \
642 if (++save->vert_count >= save->max_vert) \
643 _save_wrap_filled_vertex( ctx ); \
644 } \
645 else { \
646 GLfloat *dest = save->attrptr[ATTR]; \
647 if (N>0) dest[0] = v[0]; \
648 if (N>1) dest[1] = v[1]; \
649 if (N>2) dest[2] = v[2]; \
650 if (N>3) dest[3] = v[3]; \
651 } \
652 }
653
654 #define CHOOSE( ATTR, N ) \
655 static void save_choose_##ATTR##_##N( const GLfloat *v ) \
656 { \
657 do_choose(ATTR, N, \
658 save_attrib_##ATTR##_##N, \
659 save_choose_##ATTR##_1, \
660 save_choose_##ATTR##_2, \
661 save_choose_##ATTR##_3, \
662 save_choose_##ATTR##_4, \
663 v ); \
664 }
665
666 #define INIT(ATTR) \
667 static void save_init_##ATTR( struct brw_save_context *save ) \
668 { \
669 save->tabfv[ATTR][0] = save_choose_##ATTR##_1; \
670 save->tabfv[ATTR][1] = save_choose_##ATTR##_2; \
671 save->tabfv[ATTR][2] = save_choose_##ATTR##_3; \
672 save->tabfv[ATTR][3] = save_choose_##ATTR##_4; \
673 }
674
675 #define ATTRS( ATTRIB ) \
676 ATTRFV( ATTRIB, 1 ) \
677 ATTRFV( ATTRIB, 2 ) \
678 ATTRFV( ATTRIB, 3 ) \
679 ATTRFV( ATTRIB, 4 ) \
680 CHOOSE( ATTRIB, 1 ) \
681 CHOOSE( ATTRIB, 2 ) \
682 CHOOSE( ATTRIB, 3 ) \
683 CHOOSE( ATTRIB, 4 ) \
684 INIT( ATTRIB ) \
685
686
687 /* Generate a lot of functions. These are the actual worker
688 * functions, which are equivalent to those generated via codegen
689 * elsewhere.
690 */
691 ATTRS( 0 )
692 ATTRS( 1 )
693 ATTRS( 2 )
694 ATTRS( 3 )
695 ATTRS( 4 )
696 ATTRS( 5 )
697 ATTRS( 6 )
698 ATTRS( 7 )
699 ATTRS( 8 )
700 ATTRS( 9 )
701 ATTRS( 10 )
702 ATTRS( 11 )
703 ATTRS( 12 )
704 ATTRS( 13 )
705 ATTRS( 14 )
706 ATTRS( 15 )
707
708
709 static void _save_reset_vertex( GLcontext *ctx )
710 {
711 struct brw_save_context *save = IMM_CONTEXT(ctx)->save;
712 GLuint i;
713
714 save_init_0( save );
715 save_init_1( save );
716 save_init_2( save );
717 save_init_3( save );
718 save_init_4( save );
719 save_init_5( save );
720 save_init_6( save );
721 save_init_7( save );
722 save_init_8( save );
723 save_init_9( save );
724 save_init_10( save );
725 save_init_11( save );
726 save_init_12( save );
727 save_init_13( save );
728 save_init_14( save );
729 save_init_15( save );
730
731 for (i = 0 ; i < BRW_ATTRIB_MAX ; i++)
732 save->attrsz[i] = 0;
733
734 save->vertex_size = 0;
735 }
736
737
738
739 /* Cope with aliasing of classic Vertex, Normal, etc. and the fan-out
740 * of glMultTexCoord and glProgramParamterNV by routing all these
741 * through a second level dispatch table.
742 */
743 #define DISPATCH_ATTRFV( ATTR, COUNT, P ) \
744 do { \
745 GET_CURRENT_CONTEXT( ctx ); \
746 struct brw_save_context *save = IMM_CONTEXT(ctx)->save; \
747 save->tabfv[ATTR][COUNT-1]( P ); \
748 } while (0)
749
750 #define DISPATCH_ATTR1FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 1, V )
751 #define DISPATCH_ATTR2FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 2, V )
752 #define DISPATCH_ATTR3FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 3, V )
753 #define DISPATCH_ATTR4FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 4, V )
754
755 #define DISPATCH_ATTR1F( ATTR, S ) DISPATCH_ATTRFV( ATTR, 1, &(S) )
756
757 #if defined(USE_X86_ASM) && 0 /* will break register calling convention */
758 /* Naughty cheat:
759 */
760 #define DISPATCH_ATTR2F( ATTR, S,T ) DISPATCH_ATTRFV( ATTR, 2, &(S) )
761 #define DISPATCH_ATTR3F( ATTR, S,T,R ) DISPATCH_ATTRFV( ATTR, 3, &(S) )
762 #define DISPATCH_ATTR4F( ATTR, S,T,R,Q ) DISPATCH_ATTRFV( ATTR, 4, &(S) )
763 #else
764 /* Safe:
765 */
766 #define DISPATCH_ATTR2F( ATTR, S,T ) \
767 do { \
768 GLfloat v[2]; \
769 v[0] = S; v[1] = T; \
770 DISPATCH_ATTR2FV( ATTR, v ); \
771 } while (0)
772 #define DISPATCH_ATTR3F( ATTR, S,T,R ) \
773 do { \
774 GLfloat v[3]; \
775 v[0] = S; v[1] = T; v[2] = R; \
776 DISPATCH_ATTR3FV( ATTR, v ); \
777 } while (0)
778 #define DISPATCH_ATTR4F( ATTR, S,T,R,Q ) \
779 do { \
780 GLfloat v[4]; \
781 v[0] = S; v[1] = T; v[2] = R; v[3] = Q; \
782 DISPATCH_ATTR4FV( ATTR, v ); \
783 } while (0)
784 #endif
785
786
787 static void enum_error( void )
788 {
789 GET_CURRENT_CONTEXT( ctx );
790 _mesa_compile_error( ctx, GL_INVALID_ENUM, "glVertexAttrib" );
791 }
792
793 static void GLAPIENTRY _save_Vertex2f( GLfloat x, GLfloat y )
794 {
795 DISPATCH_ATTR2F( BRW_ATTRIB_POS, x, y );
796 }
797
798 static void GLAPIENTRY _save_Vertex2fv( const GLfloat *v )
799 {
800 DISPATCH_ATTR2FV( BRW_ATTRIB_POS, v );
801 }
802
803 static void GLAPIENTRY _save_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
804 {
805 DISPATCH_ATTR3F( BRW_ATTRIB_POS, x, y, z );
806 }
807
808 static void GLAPIENTRY _save_Vertex3fv( const GLfloat *v )
809 {
810 DISPATCH_ATTR3FV( BRW_ATTRIB_POS, v );
811 }
812
813 static void GLAPIENTRY _save_Vertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
814 {
815 DISPATCH_ATTR4F( BRW_ATTRIB_POS, x, y, z, w );
816 }
817
818 static void GLAPIENTRY _save_Vertex4fv( const GLfloat *v )
819 {
820 DISPATCH_ATTR4FV( BRW_ATTRIB_POS, v );
821 }
822
823 static void GLAPIENTRY _save_TexCoord1f( GLfloat x )
824 {
825 DISPATCH_ATTR1F( BRW_ATTRIB_TEX0, x );
826 }
827
828 static void GLAPIENTRY _save_TexCoord1fv( const GLfloat *v )
829 {
830 DISPATCH_ATTR1FV( BRW_ATTRIB_TEX0, v );
831 }
832
833 static void GLAPIENTRY _save_TexCoord2f( GLfloat x, GLfloat y )
834 {
835 DISPATCH_ATTR2F( BRW_ATTRIB_TEX0, x, y );
836 }
837
838 static void GLAPIENTRY _save_TexCoord2fv( const GLfloat *v )
839 {
840 DISPATCH_ATTR2FV( BRW_ATTRIB_TEX0, v );
841 }
842
843 static void GLAPIENTRY _save_TexCoord3f( GLfloat x, GLfloat y, GLfloat z )
844 {
845 DISPATCH_ATTR3F( BRW_ATTRIB_TEX0, x, y, z );
846 }
847
848 static void GLAPIENTRY _save_TexCoord3fv( const GLfloat *v )
849 {
850 DISPATCH_ATTR3FV( BRW_ATTRIB_TEX0, v );
851 }
852
853 static void GLAPIENTRY _save_TexCoord4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
854 {
855 DISPATCH_ATTR4F( BRW_ATTRIB_TEX0, x, y, z, w );
856 }
857
858 static void GLAPIENTRY _save_TexCoord4fv( const GLfloat *v )
859 {
860 DISPATCH_ATTR4FV( BRW_ATTRIB_TEX0, v );
861 }
862
863 static void GLAPIENTRY _save_Normal3f( GLfloat x, GLfloat y, GLfloat z )
864 {
865 DISPATCH_ATTR3F( BRW_ATTRIB_NORMAL, x, y, z );
866 }
867
868 static void GLAPIENTRY _save_Normal3fv( const GLfloat *v )
869 {
870 DISPATCH_ATTR3FV( BRW_ATTRIB_NORMAL, v );
871 }
872
873 static void GLAPIENTRY _save_FogCoordfEXT( GLfloat x )
874 {
875 DISPATCH_ATTR1F( BRW_ATTRIB_FOG, x );
876 }
877
878 static void GLAPIENTRY _save_FogCoordfvEXT( const GLfloat *v )
879 {
880 DISPATCH_ATTR1FV( BRW_ATTRIB_FOG, v );
881 }
882
883 static void GLAPIENTRY _save_Color3f( GLfloat x, GLfloat y, GLfloat z )
884 {
885 DISPATCH_ATTR3F( BRW_ATTRIB_COLOR0, x, y, z );
886 }
887
888 static void GLAPIENTRY _save_Color3fv( const GLfloat *v )
889 {
890 DISPATCH_ATTR3FV( BRW_ATTRIB_COLOR0, v );
891 }
892
893 static void GLAPIENTRY _save_Color4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
894 {
895 DISPATCH_ATTR4F( BRW_ATTRIB_COLOR0, x, y, z, w );
896 }
897
898 static void GLAPIENTRY _save_Color4fv( const GLfloat *v )
899 {
900 DISPATCH_ATTR4FV( BRW_ATTRIB_COLOR0, v );
901 }
902
903 static void GLAPIENTRY _save_SecondaryColor3fEXT( GLfloat x, GLfloat y, GLfloat z )
904 {
905 DISPATCH_ATTR3F( BRW_ATTRIB_COLOR1, x, y, z );
906 }
907
908 static void GLAPIENTRY _save_SecondaryColor3fvEXT( const GLfloat *v )
909 {
910 DISPATCH_ATTR3FV( BRW_ATTRIB_COLOR1, v );
911 }
912
913 static void GLAPIENTRY _save_MultiTexCoord1f( GLenum target, GLfloat x )
914 {
915 GLuint attr = (target & 0x7) + BRW_ATTRIB_TEX0;
916 DISPATCH_ATTR1F( attr, x );
917 }
918
919 static void GLAPIENTRY _save_MultiTexCoord1fv( GLenum target, const GLfloat *v )
920 {
921 GLuint attr = (target & 0x7) + BRW_ATTRIB_TEX0;
922 DISPATCH_ATTR1FV( attr, v );
923 }
924
925 static void GLAPIENTRY _save_MultiTexCoord2f( GLenum target, GLfloat x, GLfloat y )
926 {
927 GLuint attr = (target & 0x7) + BRW_ATTRIB_TEX0;
928 DISPATCH_ATTR2F( attr, x, y );
929 }
930
931 static void GLAPIENTRY _save_MultiTexCoord2fv( GLenum target, const GLfloat *v )
932 {
933 GLuint attr = (target & 0x7) + BRW_ATTRIB_TEX0;
934 DISPATCH_ATTR2FV( attr, v );
935 }
936
937 static void GLAPIENTRY _save_MultiTexCoord3f( GLenum target, GLfloat x, GLfloat y,
938 GLfloat z)
939 {
940 GLuint attr = (target & 0x7) + BRW_ATTRIB_TEX0;
941 DISPATCH_ATTR3F( attr, x, y, z );
942 }
943
944 static void GLAPIENTRY _save_MultiTexCoord3fv( GLenum target, const GLfloat *v )
945 {
946 GLuint attr = (target & 0x7) + BRW_ATTRIB_TEX0;
947 DISPATCH_ATTR3FV( attr, v );
948 }
949
950 static void GLAPIENTRY _save_MultiTexCoord4f( GLenum target, GLfloat x, GLfloat y,
951 GLfloat z, GLfloat w )
952 {
953 GLuint attr = (target & 0x7) + BRW_ATTRIB_TEX0;
954 DISPATCH_ATTR4F( attr, x, y, z, w );
955 }
956
957 static void GLAPIENTRY _save_MultiTexCoord4fv( GLenum target, const GLfloat *v )
958 {
959 GLuint attr = (target & 0x7) + BRW_ATTRIB_TEX0;
960 DISPATCH_ATTR4FV( attr, v );
961 }
962
963 static void GLAPIENTRY _save_VertexAttrib1fNV( GLuint index, GLfloat x )
964 {
965 if (index < BRW_ATTRIB_FIRST_MATERIAL)
966 DISPATCH_ATTR1F( index, x );
967 else
968 enum_error();
969 }
970
971 static void GLAPIENTRY _save_VertexAttrib1fvNV( GLuint index, const GLfloat *v )
972 {
973 if (index < BRW_ATTRIB_FIRST_MATERIAL)
974 DISPATCH_ATTR1FV( index, v );
975 else
976 enum_error();
977 }
978
979 static void GLAPIENTRY _save_VertexAttrib2fNV( GLuint index, GLfloat x, GLfloat y )
980 {
981 if (index < BRW_ATTRIB_FIRST_MATERIAL)
982 DISPATCH_ATTR2F( index, x, y );
983 else
984 enum_error();
985 }
986
987 static void GLAPIENTRY _save_VertexAttrib2fvNV( GLuint index, const GLfloat *v )
988 {
989 if (index < BRW_ATTRIB_FIRST_MATERIAL)
990 DISPATCH_ATTR2FV( index, v );
991 else
992 enum_error();
993 }
994
995 static void GLAPIENTRY _save_VertexAttrib3fNV( GLuint index, GLfloat x, GLfloat y,
996 GLfloat z )
997 {
998 if (index < BRW_ATTRIB_FIRST_MATERIAL)
999 DISPATCH_ATTR3F( index, x, y, z );
1000 else
1001 enum_error();
1002 }
1003
1004 static void GLAPIENTRY _save_VertexAttrib3fvNV( GLuint index, const GLfloat *v )
1005 {
1006 if (index < BRW_ATTRIB_FIRST_MATERIAL)
1007 DISPATCH_ATTR3FV( index, v );
1008 else
1009 enum_error();
1010 }
1011
1012 static void GLAPIENTRY _save_VertexAttrib4fNV( GLuint index, GLfloat x, GLfloat y,
1013 GLfloat z, GLfloat w )
1014 {
1015 if (index < BRW_ATTRIB_FIRST_MATERIAL)
1016 DISPATCH_ATTR4F( index, x, y, z, w );
1017 else
1018 enum_error();
1019 }
1020
1021 static void GLAPIENTRY _save_VertexAttrib4fvNV( GLuint index, const GLfloat *v )
1022 {
1023 if (index < BRW_ATTRIB_FIRST_MATERIAL)
1024 DISPATCH_ATTR4FV( index, v );
1025 else
1026 enum_error();
1027 }
1028
1029
1030 static void GLAPIENTRY
1031 _save_VertexAttrib1fARB( GLuint index, GLfloat x )
1032 {
1033 if (index < BRW_ATTRIB_FIRST_MATERIAL)
1034 DISPATCH_ATTR1F( index, x );
1035 else
1036 enum_error();
1037 }
1038
1039 static void GLAPIENTRY
1040 _save_VertexAttrib1fvARB( GLuint index, const GLfloat *v )
1041 {
1042 if (index < BRW_ATTRIB_FIRST_MATERIAL)
1043 DISPATCH_ATTR1FV( index, v );
1044 else
1045 enum_error();
1046 }
1047
1048 static void GLAPIENTRY
1049 _save_VertexAttrib2fARB( GLuint index, GLfloat x, GLfloat y )
1050 {
1051 if (index < BRW_ATTRIB_FIRST_MATERIAL)
1052 DISPATCH_ATTR2F( index, x, y );
1053 else
1054 enum_error();
1055 }
1056
1057 static void GLAPIENTRY
1058 _save_VertexAttrib2fvARB( GLuint index, const GLfloat *v )
1059 {
1060 if (index < BRW_ATTRIB_FIRST_MATERIAL)
1061 DISPATCH_ATTR2FV( index, v );
1062 else
1063 enum_error();
1064 }
1065
1066 static void GLAPIENTRY
1067 _save_VertexAttrib3fARB( GLuint index, GLfloat x, GLfloat y, GLfloat z )
1068 {
1069 if (index < BRW_ATTRIB_FIRST_MATERIAL)
1070 DISPATCH_ATTR3F( index, x, y, z );
1071 else
1072 enum_error();
1073 }
1074
1075 static void GLAPIENTRY
1076 _save_VertexAttrib3fvARB( GLuint index, const GLfloat *v )
1077 {
1078 if (index < BRW_ATTRIB_FIRST_MATERIAL)
1079 DISPATCH_ATTR3FV( index, v );
1080 else
1081 enum_error();
1082 }
1083
1084 static void GLAPIENTRY
1085 _save_VertexAttrib4fARB( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w )
1086 {
1087 if (index < BRW_ATTRIB_FIRST_MATERIAL)
1088 DISPATCH_ATTR4F( index, x, y, z, w );
1089 else
1090 enum_error();
1091 }
1092
1093 static void GLAPIENTRY
1094 _save_VertexAttrib4fvARB( GLuint index, const GLfloat *v )
1095 {
1096 if (index < BRW_ATTRIB_FIRST_MATERIAL)
1097 DISPATCH_ATTR4FV( index, v );
1098 else
1099 enum_error();
1100 }
1101
1102
1103 /* Materials:
1104 *
1105 * These are treated as per-vertex attributes, at indices above where
1106 * the NV_vertex_program leaves off. There are a lot of good things
1107 * about treating materials this way.
1108 *
1109 * However: I don't want to double the number of generated functions
1110 * just to cope with this, so I unroll the 'C' varients of CHOOSE and
1111 * ATTRF into this function, and dispense with codegen and
1112 * second-level dispatch.
1113 *
1114 * There is no aliasing of material attributes with other entrypoints.
1115 */
1116 #define MAT_ATTR( A, N, params ) \
1117 do { \
1118 if (save->attrsz[A] < N) { \
1119 _save_upgrade_vertex( ctx, A, N ); \
1120 } \
1121 \
1122 { \
1123 GLfloat *dest = save->attrptr[A]; \
1124 if (N>0) dest[0] = params[0]; \
1125 if (N>1) dest[1] = params[1]; \
1126 if (N>2) dest[2] = params[2]; \
1127 if (N>3) dest[3] = params[3]; \
1128 } \
1129 } while (0)
1130
1131
1132 #define MAT( ATTR, N, face, params ) \
1133 do { \
1134 if (face != GL_BACK) \
1135 MAT_ATTR( ATTR, N, params ); /* front */ \
1136 if (face != GL_FRONT) \
1137 MAT_ATTR( ATTR + 1, N, params ); /* back */ \
1138 } while (0)
1139
1140
1141 /* NOTE: Have to remove/deal-with colormaterial crossovers, probably
1142 * later on - in the meantime just store everything.
1143 */
1144 static void GLAPIENTRY _save_Materialfv( GLenum face, GLenum pname,
1145 const GLfloat *params )
1146 {
1147 GET_CURRENT_CONTEXT( ctx );
1148 struct brw_save_context *save = IMM_CONTEXT(ctx)->save;
1149
1150 switch (pname) {
1151 case GL_EMISSION:
1152 MAT( BRW_ATTRIB_MAT_FRONT_EMISSION, 4, face, params );
1153 break;
1154 case GL_AMBIENT:
1155 MAT( BRW_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params );
1156 break;
1157 case GL_DIFFUSE:
1158 MAT( BRW_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params );
1159 break;
1160 case GL_SPECULAR:
1161 MAT( BRW_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params );
1162 break;
1163 case GL_SHININESS:
1164 MAT( BRW_ATTRIB_MAT_FRONT_SHININESS, 1, face, params );
1165 break;
1166 case GL_COLOR_INDEXES:
1167 MAT( BRW_ATTRIB_MAT_FRONT_INDEXES, 3, face, params );
1168 break;
1169 case GL_AMBIENT_AND_DIFFUSE:
1170 MAT( BRW_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params );
1171 MAT( BRW_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params );
1172 break;
1173 default:
1174 _mesa_compile_error( ctx, GL_INVALID_ENUM, "glMaterialfv" );
1175 return;
1176 }
1177 }
1178
1179
1180 #define IDX_ATTR( A, IDX ) \
1181 do { \
1182 GET_CURRENT_CONTEXT( ctx ); \
1183 struct brw_save_context *save = IMM_CONTEXT(ctx)->save; \
1184 \
1185 if (save->attrsz[A] < 1) { \
1186 _save_upgrade_vertex( ctx, A, 1 ); \
1187 } \
1188 \
1189 { \
1190 GLfloat *dest = save->attrptr[A]; \
1191 dest[0] = IDX; \
1192 } \
1193 } while (0)
1194
1195
1196 static void GLAPIENTRY _save_EdgeFlag( GLboolean b )
1197 {
1198 IDX_ATTR( BRW_ATTRIB_EDGEFLAG, (GLfloat)b );
1199 }
1200
1201 #if 0
1202 static void GLAPIENTRY _save_EdgeFlagv( const GLboolean *v )
1203 {
1204 IDX_ATTR( BRW_ATTRIB_EDGEFLAG, (GLfloat)(v[0]) );
1205 }
1206 #endif
1207
1208 static void GLAPIENTRY _save_Indexf( GLfloat f )
1209 {
1210 IDX_ATTR( BRW_ATTRIB_INDEX, f );
1211 }
1212
1213 static void GLAPIENTRY _save_Indexfv( const GLfloat *f )
1214 {
1215 IDX_ATTR( BRW_ATTRIB_INDEX, f[0] );
1216 }
1217
1218
1219
1220
1221 /* Cope with EvalCoord/CallList called within a begin/end object:
1222 * -- Flush current buffer
1223 * -- Fallback to opcodes for the rest of the begin/end object.
1224 */
1225 #define DO_FALLBACK(ctx) \
1226 do { \
1227 struct brw_save_context *save = IMM_CONTEXT(ctx)->save; \
1228 \
1229 if (save->vert_count || save->prim_count) \
1230 _save_compile_vertex_list( ctx ); \
1231 \
1232 _save_copy_to_current( ctx ); \
1233 _save_reset_vertex( ctx ); \
1234 _save_reset_counters( ctx ); \
1235 _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); \
1236 ctx->Driver.SaveNeedFlush = 0; \
1237 } while (0)
1238
1239 static void GLAPIENTRY _save_EvalCoord1f( GLfloat u )
1240 {
1241 GET_CURRENT_CONTEXT(ctx);
1242 DO_FALLBACK(ctx);
1243 ctx->Save->EvalCoord1f( u );
1244 }
1245
1246 static void GLAPIENTRY _save_EvalCoord1fv( const GLfloat *v )
1247 {
1248 GET_CURRENT_CONTEXT(ctx);
1249 DO_FALLBACK(ctx);
1250 ctx->Save->EvalCoord1fv( v );
1251 }
1252
1253 static void GLAPIENTRY _save_EvalCoord2f( GLfloat u, GLfloat v )
1254 {
1255 GET_CURRENT_CONTEXT(ctx);
1256 DO_FALLBACK(ctx);
1257 ctx->Save->EvalCoord2f( u, v );
1258 }
1259
1260 static void GLAPIENTRY _save_EvalCoord2fv( const GLfloat *v )
1261 {
1262 GET_CURRENT_CONTEXT(ctx);
1263 DO_FALLBACK(ctx);
1264 ctx->Save->EvalCoord2fv( v );
1265 }
1266
1267 static void GLAPIENTRY _save_EvalPoint1( GLint i )
1268 {
1269 GET_CURRENT_CONTEXT(ctx);
1270 DO_FALLBACK(ctx);
1271 ctx->Save->EvalPoint1( i );
1272 }
1273
1274 static void GLAPIENTRY _save_EvalPoint2( GLint i, GLint j )
1275 {
1276 GET_CURRENT_CONTEXT(ctx);
1277 DO_FALLBACK(ctx);
1278 ctx->Save->EvalPoint2( i, j );
1279 }
1280
1281 static void GLAPIENTRY _save_CallList( GLuint l )
1282 {
1283 GET_CURRENT_CONTEXT(ctx);
1284 DO_FALLBACK(ctx);
1285 ctx->Save->CallList( l );
1286 }
1287
1288 static void GLAPIENTRY _save_CallLists( GLsizei n, GLenum type, const GLvoid *v )
1289 {
1290 GET_CURRENT_CONTEXT(ctx);
1291 DO_FALLBACK(ctx);
1292 ctx->Save->CallLists( n, type, v );
1293 }
1294
1295
1296
1297
1298 /* This begin is hooked into ... Updating of
1299 * ctx->Driver.CurrentSavePrimitive is already taken care of.
1300 */
1301 GLboolean brw_save_NotifyBegin( GLcontext *ctx, GLenum mode )
1302 {
1303 struct brw_save_context *save = IMM_CONTEXT(ctx)->save;
1304
1305 GLuint i = save->prim_count++;
1306
1307 assert(i < save->prim_max);
1308 save->prim[i].mode = mode & ~BRW_SAVE_PRIM_WEAK;
1309 save->prim[i].begin = 1;
1310 save->prim[i].end = 0;
1311 save->prim[i].weak = (mode & BRW_SAVE_PRIM_WEAK) ? 1 : 0;
1312 save->prim[i].pad = 0;
1313 save->prim[i].start = save->vert_count;
1314 save->prim[i].count = 0;
1315
1316 _mesa_install_save_vtxfmt( ctx, &save->vtxfmt );
1317 ctx->Driver.SaveNeedFlush = 1;
1318 return GL_TRUE;
1319 }
1320
1321
1322
1323 static void GLAPIENTRY _save_End( void )
1324 {
1325 GET_CURRENT_CONTEXT( ctx );
1326 struct brw_save_context *save = IMM_CONTEXT(ctx)->save;
1327 GLint i = save->prim_count - 1;
1328
1329 ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
1330 save->prim[i].end = 1;
1331 save->prim[i].count = (save->vert_count -
1332 save->prim[i].start);
1333
1334 if (i == (GLint) save->prim_max - 1) {
1335 _save_compile_vertex_list( ctx );
1336 assert(save->copied.nr == 0);
1337 }
1338
1339 /* Swap out this vertex format while outside begin/end. Any color,
1340 * etc. received between here and the next begin will be compiled
1341 * as opcodes.
1342 */
1343 _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
1344 }
1345
1346
1347 /* These are all errors as this vtxfmt is only installed inside
1348 * begin/end pairs.
1349 */
1350 static void GLAPIENTRY _save_DrawElements(GLenum mode, GLsizei count, GLenum type,
1351 const GLvoid *indices)
1352 {
1353 GET_CURRENT_CONTEXT(ctx);
1354 (void) mode; (void) count; (void) type; (void) indices;
1355 _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawElements" );
1356 }
1357
1358
1359 static void GLAPIENTRY _save_DrawRangeElements(GLenum mode,
1360 GLuint start, GLuint end,
1361 GLsizei count, GLenum type,
1362 const GLvoid *indices)
1363 {
1364 GET_CURRENT_CONTEXT(ctx);
1365 (void) mode; (void) start; (void) end; (void) count; (void) type; (void) indices;
1366 _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawRangeElements" );
1367 }
1368
1369 static void GLAPIENTRY _save_DrawArrays(GLenum mode, GLint start, GLsizei count)
1370 {
1371 GET_CURRENT_CONTEXT(ctx);
1372 (void) mode; (void) start; (void) count;
1373 _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawArrays" );
1374 }
1375
1376 static void GLAPIENTRY _save_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
1377 {
1378 GET_CURRENT_CONTEXT(ctx);
1379 (void) x1; (void) y1; (void) x2; (void) y2;
1380 _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glRectf" );
1381 }
1382
1383 static void GLAPIENTRY _save_EvalMesh1( GLenum mode, GLint i1, GLint i2 )
1384 {
1385 GET_CURRENT_CONTEXT(ctx);
1386 (void) mode; (void) i1; (void) i2;
1387 _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glEvalMesh1" );
1388 }
1389
1390 static void GLAPIENTRY _save_EvalMesh2( GLenum mode, GLint i1, GLint i2,
1391 GLint j1, GLint j2 )
1392 {
1393 GET_CURRENT_CONTEXT(ctx);
1394 (void) mode; (void) i1; (void) i2; (void) j1; (void) j2;
1395 _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glEvalMesh2" );
1396 }
1397
1398 static void GLAPIENTRY _save_Begin( GLenum mode )
1399 {
1400 GET_CURRENT_CONTEXT( ctx );
1401 (void) mode;
1402 _mesa_compile_error( ctx, GL_INVALID_OPERATION, "Recursive glBegin" );
1403 }
1404
1405
1406 /* Unlike the functions above, these are to be hooked into the vtxfmt
1407 * maintained in ctx->ListState, active when the list is known or
1408 * suspected to be outside any begin/end primitive.
1409 */
1410 static void GLAPIENTRY _save_OBE_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
1411 {
1412 GET_CURRENT_CONTEXT(ctx);
1413 brw_save_NotifyBegin( ctx, GL_QUADS | BRW_SAVE_PRIM_WEAK );
1414 CALL_Vertex2f(GET_DISPATCH(), ( x1, y1 ));
1415 CALL_Vertex2f(GET_DISPATCH(), ( x2, y1 ));
1416 CALL_Vertex2f(GET_DISPATCH(), ( x2, y2 ));
1417 CALL_Vertex2f(GET_DISPATCH(), ( x1, y2 ));
1418 CALL_End(GET_DISPATCH(), ());
1419 }
1420
1421
1422 static void GLAPIENTRY _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count)
1423 {
1424 GET_CURRENT_CONTEXT(ctx);
1425 GLint i;
1426
1427 if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
1428 return;
1429
1430 brw_save_NotifyBegin( ctx, mode | BRW_SAVE_PRIM_WEAK );
1431 for (i = 0; i < count; i++)
1432 CALL_ArrayElement(GET_DISPATCH(), (start + i));
1433 CALL_End(GET_DISPATCH(), ());
1434 }
1435
1436 /* Could do better by copying the arrays and element list intact and
1437 * then emitting an indexed prim at runtime.
1438 */
1439 static void GLAPIENTRY _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type,
1440 const GLvoid *indices)
1441 {
1442 GET_CURRENT_CONTEXT(ctx);
1443 GLint i;
1444
1445 if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
1446 return;
1447
1448 brw_save_NotifyBegin( ctx, mode | BRW_SAVE_PRIM_WEAK );
1449
1450 switch (type) {
1451 case GL_UNSIGNED_BYTE:
1452 for (i = 0 ; i < count ; i++)
1453 CALL_ArrayElement(GET_DISPATCH(), ( ((GLubyte *)indices)[i] ));
1454 break;
1455 case GL_UNSIGNED_SHORT:
1456 for (i = 0 ; i < count ; i++)
1457 CALL_ArrayElement(GET_DISPATCH(), ( ((GLushort *)indices)[i] ));
1458 break;
1459 case GL_UNSIGNED_INT:
1460 for (i = 0 ; i < count ; i++)
1461 CALL_ArrayElement(GET_DISPATCH(), ( ((GLuint *)indices)[i] ));
1462 break;
1463 default:
1464 _mesa_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
1465 break;
1466 }
1467
1468 CALL_End(GET_DISPATCH(), ());
1469 }
1470
1471 static void GLAPIENTRY _save_OBE_DrawRangeElements(GLenum mode,
1472 GLuint start, GLuint end,
1473 GLsizei count, GLenum type,
1474 const GLvoid *indices)
1475 {
1476 GET_CURRENT_CONTEXT(ctx);
1477 if (_mesa_validate_DrawRangeElements( ctx, mode,
1478 start, end,
1479 count, type, indices ))
1480 _save_OBE_DrawElements( mode, count, type, indices );
1481 }
1482
1483
1484
1485
1486
1487 static void _save_vtxfmt_init( GLcontext *ctx )
1488 {
1489 struct brw_save_context *save = IMM_CONTEXT(ctx)->save;
1490 GLvertexformat *vfmt = &save->vtxfmt;
1491
1492 vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
1493 vfmt->Begin = _save_Begin;
1494 vfmt->Color3f = _save_Color3f;
1495 vfmt->Color3fv = _save_Color3fv;
1496 vfmt->Color4f = _save_Color4f;
1497 vfmt->Color4fv = _save_Color4fv;
1498 vfmt->EdgeFlag = _save_EdgeFlag;
1499 /* vfmt->EdgeFlagv = _save_EdgeFlagv; */
1500 vfmt->End = _save_End;
1501 vfmt->FogCoordfEXT = _save_FogCoordfEXT;
1502 vfmt->FogCoordfvEXT = _save_FogCoordfvEXT;
1503 vfmt->Indexf = _save_Indexf;
1504 vfmt->Indexfv = _save_Indexfv;
1505 vfmt->Materialfv = _save_Materialfv;
1506 vfmt->MultiTexCoord1fARB = _save_MultiTexCoord1f;
1507 vfmt->MultiTexCoord1fvARB = _save_MultiTexCoord1fv;
1508 vfmt->MultiTexCoord2fARB = _save_MultiTexCoord2f;
1509 vfmt->MultiTexCoord2fvARB = _save_MultiTexCoord2fv;
1510 vfmt->MultiTexCoord3fARB = _save_MultiTexCoord3f;
1511 vfmt->MultiTexCoord3fvARB = _save_MultiTexCoord3fv;
1512 vfmt->MultiTexCoord4fARB = _save_MultiTexCoord4f;
1513 vfmt->MultiTexCoord4fvARB = _save_MultiTexCoord4fv;
1514 vfmt->Normal3f = _save_Normal3f;
1515 vfmt->Normal3fv = _save_Normal3fv;
1516 vfmt->SecondaryColor3fEXT = _save_SecondaryColor3fEXT;
1517 vfmt->SecondaryColor3fvEXT = _save_SecondaryColor3fvEXT;
1518 vfmt->TexCoord1f = _save_TexCoord1f;
1519 vfmt->TexCoord1fv = _save_TexCoord1fv;
1520 vfmt->TexCoord2f = _save_TexCoord2f;
1521 vfmt->TexCoord2fv = _save_TexCoord2fv;
1522 vfmt->TexCoord3f = _save_TexCoord3f;
1523 vfmt->TexCoord3fv = _save_TexCoord3fv;
1524 vfmt->TexCoord4f = _save_TexCoord4f;
1525 vfmt->TexCoord4fv = _save_TexCoord4fv;
1526 vfmt->Vertex2f = _save_Vertex2f;
1527 vfmt->Vertex2fv = _save_Vertex2fv;
1528 vfmt->Vertex3f = _save_Vertex3f;
1529 vfmt->Vertex3fv = _save_Vertex3fv;
1530 vfmt->Vertex4f = _save_Vertex4f;
1531 vfmt->Vertex4fv = _save_Vertex4fv;
1532 vfmt->VertexAttrib1fNV = _save_VertexAttrib1fNV;
1533 vfmt->VertexAttrib1fvNV = _save_VertexAttrib1fvNV;
1534 vfmt->VertexAttrib2fNV = _save_VertexAttrib2fNV;
1535 vfmt->VertexAttrib2fvNV = _save_VertexAttrib2fvNV;
1536 vfmt->VertexAttrib3fNV = _save_VertexAttrib3fNV;
1537 vfmt->VertexAttrib3fvNV = _save_VertexAttrib3fvNV;
1538 vfmt->VertexAttrib4fNV = _save_VertexAttrib4fNV;
1539 vfmt->VertexAttrib4fvNV = _save_VertexAttrib4fvNV;
1540 vfmt->VertexAttrib1fARB = _save_VertexAttrib1fARB;
1541 vfmt->VertexAttrib1fvARB = _save_VertexAttrib1fvARB;
1542 vfmt->VertexAttrib2fARB = _save_VertexAttrib2fARB;
1543 vfmt->VertexAttrib2fvARB = _save_VertexAttrib2fvARB;
1544 vfmt->VertexAttrib3fARB = _save_VertexAttrib3fARB;
1545 vfmt->VertexAttrib3fvARB = _save_VertexAttrib3fvARB;
1546 vfmt->VertexAttrib4fARB = _save_VertexAttrib4fARB;
1547 vfmt->VertexAttrib4fvARB = _save_VertexAttrib4fvARB;
1548
1549 /* This will all require us to fallback to saving the list as opcodes:
1550 */
1551 vfmt->CallList = _save_CallList; /* inside begin/end */
1552 vfmt->CallLists = _save_CallLists; /* inside begin/end */
1553 vfmt->EvalCoord1f = _save_EvalCoord1f;
1554 vfmt->EvalCoord1fv = _save_EvalCoord1fv;
1555 vfmt->EvalCoord2f = _save_EvalCoord2f;
1556 vfmt->EvalCoord2fv = _save_EvalCoord2fv;
1557 vfmt->EvalPoint1 = _save_EvalPoint1;
1558 vfmt->EvalPoint2 = _save_EvalPoint2;
1559
1560 /* These are all errors as we at least know we are in some sort of
1561 * begin/end pair:
1562 */
1563 vfmt->EvalMesh1 = _save_EvalMesh1;
1564 vfmt->EvalMesh2 = _save_EvalMesh2;
1565 vfmt->Begin = _save_Begin;
1566 vfmt->Rectf = _save_Rectf;
1567 vfmt->DrawArrays = _save_DrawArrays;
1568 vfmt->DrawElements = _save_DrawElements;
1569 vfmt->DrawRangeElements = _save_DrawRangeElements;
1570
1571 }
1572
1573
1574 void brw_save_SaveFlushVertices( GLcontext *ctx )
1575 {
1576 struct brw_save_context *save = IMM_CONTEXT(ctx)->save;
1577
1578 /* Noop when we are actually active:
1579 */
1580 if (ctx->Driver.CurrentSavePrimitive == PRIM_INSIDE_UNKNOWN_PRIM ||
1581 ctx->Driver.CurrentSavePrimitive <= GL_POLYGON)
1582 return;
1583
1584 if (save->vert_count ||
1585 save->prim_count)
1586 _save_compile_vertex_list( ctx );
1587
1588 _save_copy_to_current( ctx );
1589 _save_reset_vertex( ctx );
1590 _save_reset_counters( ctx );
1591 ctx->Driver.SaveNeedFlush = 0;
1592 }
1593
1594 void brw_save_NewList( GLcontext *ctx, GLuint list, GLenum mode )
1595 {
1596 struct brw_save_context *save = IMM_CONTEXT(ctx)->save;
1597
1598 (void) list; (void) mode;
1599
1600 if (!save->prim_store)
1601 save->prim_store = alloc_prim_store( ctx );
1602
1603 if (!save->vertex_store)
1604 save->vertex_store = alloc_vertex_store( ctx );
1605
1606 save->vbptr = map_vertex_store( ctx, save->vertex_store );
1607
1608 _save_reset_vertex( ctx );
1609 _save_reset_counters( ctx );
1610 ctx->Driver.SaveNeedFlush = 0;
1611 }
1612
1613 void brw_save_EndList( GLcontext *ctx )
1614 {
1615 struct brw_save_context *save = IMM_CONTEXT(ctx)->save;
1616 unmap_vertex_store( ctx, save->vertex_store );
1617
1618 assert(save->vertex_size == 0);
1619 }
1620
1621 void brw_save_BeginCallList( GLcontext *ctx, struct mesa_display_list *dlist )
1622 {
1623 struct brw_save_context *save = IMM_CONTEXT(ctx)->save;
1624 save->replay_flags |= dlist->flags;
1625 }
1626
1627 void brw_save_EndCallList( GLcontext *ctx )
1628 {
1629 struct brw_save_context *save = IMM_CONTEXT(ctx)->save;
1630
1631 if (ctx->ListState.CallDepth == 1) {
1632 /* This is correct: want to keep only the BRW_SAVE_FALLBACK
1633 * flag, if it is set:
1634 */
1635 save->replay_flags &= BRW_SAVE_FALLBACK;
1636 }
1637 }
1638
1639
1640 static void brw_destroy_vertex_list( GLcontext *ctx, void *data )
1641 {
1642 struct brw_save_vertex_list *node = (struct brw_save_vertex_list *)data;
1643 (void) ctx;
1644
1645 if ( --node->vertex_store->refcount == 0 )
1646 free_vertex_store( ctx, node->vertex_store );
1647
1648 if ( --node->prim_store->refcount == 0 )
1649 FREE( node->prim_store );
1650 }
1651
1652
1653 static void brw_print_vertex_list( GLcontext *ctx, void *data )
1654 {
1655 struct brw_save_vertex_list *node = (struct brw_save_vertex_list *)data;
1656 GLuint i;
1657 (void) ctx;
1658
1659 _mesa_debug(NULL, "BRW-VERTEX-LIST, %u vertices %d primitives, %d vertsize\n",
1660 node->count,
1661 node->prim_count,
1662 node->vertex_size);
1663
1664 for (i = 0 ; i < node->prim_count ; i++) {
1665 struct brw_draw_prim *prim = &node->prim[i];
1666 _mesa_debug(NULL, " prim %d: %s%s %d..%d %s %s\n",
1667 i,
1668 _mesa_lookup_enum_by_nr(prim->mode),
1669 prim->weak ? " (weak)" : "",
1670 prim->start,
1671 prim->start + prim->count,
1672 (prim->begin) ? "BEGIN" : "(wrap)",
1673 (prim->end) ? "END" : "(wrap)");
1674 }
1675 }
1676
1677
1678 static void _save_current_init( GLcontext *ctx )
1679 {
1680 struct brw_save_context *save = IMM_CONTEXT(ctx)->save;
1681 GLint i;
1682
1683 for (i = 0; i < BRW_ATTRIB_FIRST_MATERIAL; i++) {
1684 save->currentsz[i] = &ctx->ListState.ActiveAttribSize[i];
1685 save->current[i] = ctx->ListState.CurrentAttrib[i];
1686 }
1687
1688 for (i = BRW_ATTRIB_FIRST_MATERIAL; i < BRW_ATTRIB_INDEX; i++) {
1689 const GLuint j = i - BRW_ATTRIB_FIRST_MATERIAL;
1690 ASSERT(j < MAT_ATTRIB_MAX);
1691 save->currentsz[i] = &ctx->ListState.ActiveMaterialSize[j];
1692 save->current[i] = ctx->ListState.CurrentMaterial[j];
1693 }
1694
1695 save->currentsz[BRW_ATTRIB_INDEX] = &ctx->ListState.ActiveIndex;
1696 save->current[BRW_ATTRIB_INDEX] = &ctx->ListState.CurrentIndex;
1697
1698 save->currentsz[BRW_ATTRIB_EDGEFLAG] = &ctx->ListState.ActiveEdgeFlag;
1699 save->current[BRW_ATTRIB_EDGEFLAG] = &save->CurrentFloatEdgeFlag;
1700 }
1701
1702 /**
1703 * Initialize the display list compiler
1704 */
1705 void brw_save_api_init( struct brw_save_context *save )
1706 {
1707 GLcontext *ctx = save->ctx;
1708 GLuint i;
1709
1710 save->opcode_vertex_list =
1711 _mesa_alloc_opcode( ctx,
1712 sizeof(struct brw_save_vertex_list),
1713 brw_save_playback_vertex_list,
1714 brw_destroy_vertex_list,
1715 brw_print_vertex_list );
1716
1717 ctx->Driver.NotifySaveBegin = brw_save_NotifyBegin;
1718
1719 _save_vtxfmt_init( ctx );
1720 _save_current_init( ctx );
1721
1722 for (i = 0; i < BRW_ATTRIB_MAX; i++)
1723 save->inputs[i] = &save->arrays[i];
1724
1725 /* Hook our array functions into the outside-begin-end vtxfmt in
1726 * ctx->ListState.
1727 */
1728 ctx->ListState.ListVtxfmt.Rectf = _save_OBE_Rectf;
1729 ctx->ListState.ListVtxfmt.DrawArrays = _save_OBE_DrawArrays;
1730 ctx->ListState.ListVtxfmt.DrawElements = _save_OBE_DrawElements;
1731 ctx->ListState.ListVtxfmt.DrawRangeElements = _save_OBE_DrawRangeElements;
1732 _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
1733 }
1734