1 /**************************************************************************
3 Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
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:
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
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.
26 **************************************************************************/
30 * Keith Whitwell <keith@tungstengraphics.com>
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
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,
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.
50 * The other case where fixup is required is when a vertex attribute
51 * is introduced in the middle of a primitive. Eg:
53 * TexCoord1f() Vertex2f()
54 * TexCoord1f() Color3f() Vertex2f()
57 * If the current value of Color isn't known at compile-time, this
58 * primitive will require fixup.
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.
65 * This could be improved to fallback only when a mix of EvalCoord and
66 * Vertex commands are issued within a single primitive.
75 #include "api_validate.h"
76 #include "api_arrayelt.h"
81 #include "brw_fallback.h"
87 * NOTE: Old 'parity' issue is gone, but copying can still be
88 * wrong-footed on replay.
90 static GLuint
_save_copy_vertices( GLcontext
*ctx
,
91 const struct brw_save_vertex_list
*node
,
92 const GLfloat
*src_buffer
)
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
;
111 for (i
= 0 ; i
< ovf
; i
++)
112 _mesa_memcpy( dst
+i
*sz
, src
+(nr
-ovf
+i
)*sz
, sz
*sizeof(GLfloat
) );
116 for (i
= 0 ; i
< ovf
; i
++)
117 _mesa_memcpy( dst
+i
*sz
, src
+(nr
-ovf
+i
)*sz
, sz
*sizeof(GLfloat
) );
121 for (i
= 0 ; i
< ovf
; i
++)
122 _mesa_memcpy( dst
+i
*sz
, src
+(nr
-ovf
+i
)*sz
, sz
*sizeof(GLfloat
) );
128 _mesa_memcpy( dst
, src
+(nr
-1)*sz
, sz
*sizeof(GLfloat
) );
132 case GL_TRIANGLE_FAN
:
137 _mesa_memcpy( dst
, src
+0, sz
*sizeof(GLfloat
) );
140 _mesa_memcpy( dst
, src
+0, sz
*sizeof(GLfloat
) );
141 _mesa_memcpy( dst
+sz
, src
+(nr
-1)*sz
, sz
*sizeof(GLfloat
) );
144 case GL_TRIANGLE_STRIP
:
147 case 0: ovf
= 0; break;
148 case 1: ovf
= 1; break;
149 default: ovf
= 2 + (nr
&1); break;
151 for (i
= 0 ; i
< ovf
; i
++)
152 _mesa_memcpy( dst
+i
*sz
, src
+(nr
-ovf
+i
)*sz
, sz
*sizeof(GLfloat
) );
161 static struct brw_save_vertex_store
*alloc_vertex_store( GLcontext
*ctx
)
163 struct brw_save_vertex_store
*vertex_store
= CALLOC_STRUCT(brw_save_vertex_store
);
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
171 vertex_store
->bufferobj
= ctx
->Driver
.NewBufferObject(ctx
, 1, GL_ARRAY_BUFFER_ARB
);
173 ctx
->Driver
.BufferData( ctx
,
175 BRW_SAVE_BUFFER_SIZE
* sizeof(GLfloat
),
178 vertex_store
->bufferobj
);
180 vertex_store
->buffer
= NULL
;
181 vertex_store
->used
= 0;
182 vertex_store
->refcount
= 1;
187 static void free_vertex_store( GLcontext
*ctx
, struct brw_save_vertex_store
*vertex_store
)
189 assert(!vertex_store
->buffer
);
191 if (vertex_store
->bufferobj
)
192 ctx
->Driver
.DeleteBuffer( ctx
, vertex_store
->bufferobj
);
194 FREE( vertex_store
);
197 static GLfloat
*map_vertex_store( GLcontext
*ctx
, struct brw_save_vertex_store
*vertex_store
)
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
);
206 assert(vertex_store
->buffer
);
207 return vertex_store
->buffer
+ vertex_store
->used
;
210 static void unmap_vertex_store( GLcontext
*ctx
, struct brw_save_vertex_store
*vertex_store
)
212 ctx
->Driver
.UnmapBuffer( ctx
, GL_ARRAY_BUFFER_ARB
, vertex_store
->bufferobj
);
213 vertex_store
->buffer
= NULL
;
217 static struct brw_save_primitive_store
*alloc_prim_store( GLcontext
*ctx
)
219 struct brw_save_primitive_store
*store
= CALLOC_STRUCT(brw_save_primitive_store
);
226 static void _save_reset_counters( GLcontext
*ctx
)
228 struct brw_save_context
*save
= IMM_CONTEXT(ctx
)->save
;
230 save
->prim
= save
->prim_store
->buffer
+ save
->prim_store
->used
;
231 save
->buffer
= (save
->vertex_store
->buffer
+
232 save
->vertex_store
->used
);
234 assert(save
->buffer
== save
->vbptr
);
236 if (save
->vertex_size
)
237 save
->max_vert
= ((BRW_SAVE_BUFFER_SIZE
- save
->vertex_store
->used
) /
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;
249 /* Insert the active immediate struct onto the display list currently
252 static void _save_compile_vertex_list( GLcontext
*ctx
)
254 struct brw_save_context
*save
= IMM_CONTEXT(ctx
)->save
;
255 struct brw_save_vertex_list
*node
;
257 /* Allocate space for this structure in the display list currently
260 node
= (struct brw_save_vertex_list
*)
261 _mesa_alloc_instruction(ctx
, save
->opcode_vertex_list
, sizeof(*node
));
266 /* Duplicate our template, increment refcounts to the storage structs:
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
;
279 node
->vertex_store
->refcount
++;
280 node
->prim_store
->refcount
++;
282 assert(node
->attrsz
[BRW_ATTRIB_POS
] != 0 ||
285 if (save
->dangling_attr_ref
)
286 ctx
->ListState
.CurrentList
->flags
|= MESA_DLIST_DANGLING_REFS
;
288 save
->vertex_store
->used
+= save
->vertex_size
* node
->count
;
289 save
->prim_store
->used
+= node
->prim_count
;
292 /* Copy duplicated vertices
294 save
->copied
.nr
= _save_copy_vertices( ctx
, node
, save
->buffer
);
297 /* Deal with GL_COMPILE_AND_EXECUTE:
299 if (ctx
->ExecuteFlag
) {
300 struct _glapi_table
*dispatch
= GET_DISPATCH();
302 _glapi_set_dispatch(ctx
->Exec
);
304 brw_loopback_vertex_list( ctx
,
305 (const GLfloat
*)((const char *)save
->vertex_store
->buffer
+
306 node
->buffer_offset
),
313 _glapi_set_dispatch(dispatch
);
317 /* Decide whether the storage structs are full, or can be used for
318 * the next vertex lists as well.
320 if (save
->vertex_store
->used
>
321 BRW_SAVE_BUFFER_SIZE
- 16 * (save
->vertex_size
+ 4)) {
325 unmap_vertex_store( ctx
, save
->vertex_store
);
327 /* Release old reference:
329 save
->vertex_store
->refcount
--;
330 assert(save
->vertex_store
->refcount
!= 0);
331 save
->vertex_store
= NULL
;
333 /* Allocate and map new store:
335 save
->vertex_store
= alloc_vertex_store( ctx
);
336 save
->vbptr
= map_vertex_store( ctx
, save
->vertex_store
);
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
);
345 /* Reset our structures for the next run of vertices:
347 _save_reset_counters( ctx
);
351 /* TODO -- If no new vertices have been stored, don't bother saving
354 static void _save_wrap_buffers( GLcontext
*ctx
)
356 struct brw_save_context
*save
= IMM_CONTEXT(ctx
)->save
;
357 GLint i
= save
->prim_count
- 1;
361 assert(i
< (GLint
) save
->prim_max
);
364 /* Close off in-progress primitive.
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
;
371 /* store the copied vertices, and allocate a new list.
373 _save_compile_vertex_list( ctx
);
375 /* Restart interrupted primitive
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;
389 /* Called only when buffers are wrapped as the result of filling the
390 * vertex_store struct.
392 static void _save_wrap_filled_vertex( GLcontext
*ctx
)
394 struct brw_save_context
*save
= IMM_CONTEXT(ctx
)->save
;
395 GLfloat
*data
= save
->copied
.buffer
;
398 /* Emit a glEnd to close off the last vertex list.
400 _save_wrap_buffers( ctx
);
402 /* Copy stored stored vertices to start of new list.
404 assert(save
->max_vert
- save
->vert_count
> save
->copied
.nr
);
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
;
415 static void _save_copy_to_current( GLcontext
*ctx
)
417 struct brw_save_context
*save
= IMM_CONTEXT(ctx
)->save
;
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
],
429 /* Edgeflag requires special treatment:
431 * TODO: change edgeflag to GLfloat in Mesa.
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);
443 static void _save_copy_from_current( GLcontext
*ctx
)
445 struct brw_save_context
*save
= IMM_CONTEXT(ctx
)->save
;
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];
457 /* Edgeflag requires special treatment:
459 if (save
->attrsz
[BRW_ATTRIB_EDGEFLAG
]) {
460 save
->CurrentFloatEdgeFlag
= (GLfloat
)ctx
->ListState
.CurrentEdgeFlag
;
461 save
->attrptr
[BRW_ATTRIB_EDGEFLAG
][0] = save
->CurrentFloatEdgeFlag
;
468 /* Flush existing data, set new attrib size, replay copied vertices.
470 static void _save_upgrade_vertex( GLcontext
*ctx
,
474 struct brw_save_context
*save
= IMM_CONTEXT(ctx
)->save
;
479 /* Store the current run of vertices, and emit a GL_END. Emit a
480 * BEGIN in the new buffer.
482 if (save
->vert_count
)
483 _save_wrap_buffers( ctx
);
485 assert( save
->copied
.nr
== 0 );
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.
491 _save_copy_to_current( ctx
);
495 oldsz
= save
->attrsz
[attr
];
496 save
->attrsz
[attr
] = newsz
;
498 save
->vertex_size
+= newsz
- oldsz
;
499 save
->max_vert
= ((BRW_SAVE_BUFFER_SIZE
- save
->vertex_store
->used
) /
501 save
->vert_count
= 0;
503 /* Recalculate all the attrptr[] values:
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
];
511 save
->attrptr
[i
] = NULL
; /* will not be dereferenced. */
514 /* Copy from current to repopulate the vertex with correct values.
516 _save_copy_from_current( ctx
);
518 /* Replay stored vertices to translate them to new format here.
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.
526 GLfloat
*data
= save
->copied
.buffer
;
527 GLfloat
*dest
= save
->buffer
;
530 /* Need to note this and fix up at runtime (or loopback):
532 if (save
->currentsz
[attr
][0] == 0) {
534 save
->dangling_attr_ref
= GL_TRUE
;
537 for (i
= 0 ; i
< save
->copied
.nr
; i
++) {
538 for (j
= 0 ; j
< BRW_ATTRIB_MAX
; j
++) {
539 if (save
->attrsz
[j
]) {
542 COPY_CLEAN_4V( dest
, oldsz
, data
);
547 COPY_SZ_4V( dest
, newsz
, save
->current
[attr
] );
552 GLint sz
= save
->attrsz
[j
];
553 COPY_SZ_4V( dest
, sz
, data
);
562 save
->vert_count
+= save
->copied
.nr
;
569 /* Helper function for 'CHOOSE' macro. Do what's necessary when an
570 * entrypoint is called for the first time.
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
*),
580 GET_CURRENT_CONTEXT( ctx
);
581 struct brw_save_context
*save
= IMM_CONTEXT(ctx
)->save
;
582 static GLfloat id
[4] = { 0, 0, 0, 1 };
585 if (save
->attrsz
[attr
] < sz
) {
586 /* New size is larger. Need to flush existing vertices and get
587 * an enlarged vertex format.
589 _save_upgrade_vertex( ctx
, attr
, sz
);
592 /* New size is equal or smaller - just need to fill in some
595 for (i
= sz
; i
<= save
->attrsz
[attr
] ; i
++)
596 save
->attrptr
[attr
][i
-1] = id
[i
-1];
599 /* Reset any active pointers for this attribute
601 save
->tabfv
[attr
][0] = choose1
;
602 save
->tabfv
[attr
][1] = choose2
;
603 save
->tabfv
[attr
][2] = choose3
;
604 save
->tabfv
[attr
][3] = choose4
;
606 /* Update the secondary dispatch table with the new function
608 save
->tabfv
[attr
][sz
-1] = attr_func
;
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.
621 #define ATTRFV( ATTR, N ) \
622 static void save_choose_##ATTR##_##N( const GLfloat *v ); \
624 static void save_attrib_##ATTR##_##N( const GLfloat *v ) \
626 GET_CURRENT_CONTEXT( ctx ); \
627 struct brw_save_context *save = IMM_CONTEXT(ctx)->save; \
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]; \
637 for (i = N; i < save->vertex_size; i++) \
638 save->vbptr[i] = save->vertex[i]; \
640 save->vbptr += save->vertex_size; \
642 if (++save->vert_count >= save->max_vert) \
643 _save_wrap_filled_vertex( ctx ); \
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]; \
654 #define CHOOSE( ATTR, N ) \
655 static void save_choose_##ATTR##_##N( const GLfloat *v ) \
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, \
667 static void save_init_##ATTR( struct brw_save_context *save ) \
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; \
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 ) \
687 /* Generate a lot of functions. These are the actual worker
688 * functions, which are equivalent to those generated via codegen
709 static void _save_reset_vertex( GLcontext
*ctx
)
711 struct brw_save_context
*save
= IMM_CONTEXT(ctx
)->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
);
731 for (i
= 0 ; i
< BRW_ATTRIB_MAX
; i
++)
734 save
->vertex_size
= 0;
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.
743 #define DISPATCH_ATTRFV( ATTR, COUNT, P ) \
745 GET_CURRENT_CONTEXT( ctx ); \
746 struct brw_save_context *save = IMM_CONTEXT(ctx)->save; \
747 save->tabfv[ATTR][COUNT-1]( P ); \
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 )
755 #define DISPATCH_ATTR1F( ATTR, S ) DISPATCH_ATTRFV( ATTR, 1, &(S) )
757 #if defined(USE_X86_ASM) && 0 /* will break register calling convention */
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) )
766 #define DISPATCH_ATTR2F( ATTR, S,T ) \
769 v[0] = S; v[1] = T; \
770 DISPATCH_ATTR2FV( ATTR, v ); \
772 #define DISPATCH_ATTR3F( ATTR, S,T,R ) \
775 v[0] = S; v[1] = T; v[2] = R; \
776 DISPATCH_ATTR3FV( ATTR, v ); \
778 #define DISPATCH_ATTR4F( ATTR, S,T,R,Q ) \
781 v[0] = S; v[1] = T; v[2] = R; v[3] = Q; \
782 DISPATCH_ATTR4FV( ATTR, v ); \
787 static void enum_error( void )
789 GET_CURRENT_CONTEXT( ctx
);
790 _mesa_compile_error( ctx
, GL_INVALID_ENUM
, "glVertexAttrib" );
793 static void GLAPIENTRY
_save_Vertex2f( GLfloat x
, GLfloat y
)
795 DISPATCH_ATTR2F( BRW_ATTRIB_POS
, x
, y
);
798 static void GLAPIENTRY
_save_Vertex2fv( const GLfloat
*v
)
800 DISPATCH_ATTR2FV( BRW_ATTRIB_POS
, v
);
803 static void GLAPIENTRY
_save_Vertex3f( GLfloat x
, GLfloat y
, GLfloat z
)
805 DISPATCH_ATTR3F( BRW_ATTRIB_POS
, x
, y
, z
);
808 static void GLAPIENTRY
_save_Vertex3fv( const GLfloat
*v
)
810 DISPATCH_ATTR3FV( BRW_ATTRIB_POS
, v
);
813 static void GLAPIENTRY
_save_Vertex4f( GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
815 DISPATCH_ATTR4F( BRW_ATTRIB_POS
, x
, y
, z
, w
);
818 static void GLAPIENTRY
_save_Vertex4fv( const GLfloat
*v
)
820 DISPATCH_ATTR4FV( BRW_ATTRIB_POS
, v
);
823 static void GLAPIENTRY
_save_TexCoord1f( GLfloat x
)
825 DISPATCH_ATTR1F( BRW_ATTRIB_TEX0
, x
);
828 static void GLAPIENTRY
_save_TexCoord1fv( const GLfloat
*v
)
830 DISPATCH_ATTR1FV( BRW_ATTRIB_TEX0
, v
);
833 static void GLAPIENTRY
_save_TexCoord2f( GLfloat x
, GLfloat y
)
835 DISPATCH_ATTR2F( BRW_ATTRIB_TEX0
, x
, y
);
838 static void GLAPIENTRY
_save_TexCoord2fv( const GLfloat
*v
)
840 DISPATCH_ATTR2FV( BRW_ATTRIB_TEX0
, v
);
843 static void GLAPIENTRY
_save_TexCoord3f( GLfloat x
, GLfloat y
, GLfloat z
)
845 DISPATCH_ATTR3F( BRW_ATTRIB_TEX0
, x
, y
, z
);
848 static void GLAPIENTRY
_save_TexCoord3fv( const GLfloat
*v
)
850 DISPATCH_ATTR3FV( BRW_ATTRIB_TEX0
, v
);
853 static void GLAPIENTRY
_save_TexCoord4f( GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
855 DISPATCH_ATTR4F( BRW_ATTRIB_TEX0
, x
, y
, z
, w
);
858 static void GLAPIENTRY
_save_TexCoord4fv( const GLfloat
*v
)
860 DISPATCH_ATTR4FV( BRW_ATTRIB_TEX0
, v
);
863 static void GLAPIENTRY
_save_Normal3f( GLfloat x
, GLfloat y
, GLfloat z
)
865 DISPATCH_ATTR3F( BRW_ATTRIB_NORMAL
, x
, y
, z
);
868 static void GLAPIENTRY
_save_Normal3fv( const GLfloat
*v
)
870 DISPATCH_ATTR3FV( BRW_ATTRIB_NORMAL
, v
);
873 static void GLAPIENTRY
_save_FogCoordfEXT( GLfloat x
)
875 DISPATCH_ATTR1F( BRW_ATTRIB_FOG
, x
);
878 static void GLAPIENTRY
_save_FogCoordfvEXT( const GLfloat
*v
)
880 DISPATCH_ATTR1FV( BRW_ATTRIB_FOG
, v
);
883 static void GLAPIENTRY
_save_Color3f( GLfloat x
, GLfloat y
, GLfloat z
)
885 DISPATCH_ATTR3F( BRW_ATTRIB_COLOR0
, x
, y
, z
);
888 static void GLAPIENTRY
_save_Color3fv( const GLfloat
*v
)
890 DISPATCH_ATTR3FV( BRW_ATTRIB_COLOR0
, v
);
893 static void GLAPIENTRY
_save_Color4f( GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
895 DISPATCH_ATTR4F( BRW_ATTRIB_COLOR0
, x
, y
, z
, w
);
898 static void GLAPIENTRY
_save_Color4fv( const GLfloat
*v
)
900 DISPATCH_ATTR4FV( BRW_ATTRIB_COLOR0
, v
);
903 static void GLAPIENTRY
_save_SecondaryColor3fEXT( GLfloat x
, GLfloat y
, GLfloat z
)
905 DISPATCH_ATTR3F( BRW_ATTRIB_COLOR1
, x
, y
, z
);
908 static void GLAPIENTRY
_save_SecondaryColor3fvEXT( const GLfloat
*v
)
910 DISPATCH_ATTR3FV( BRW_ATTRIB_COLOR1
, v
);
913 static void GLAPIENTRY
_save_MultiTexCoord1f( GLenum target
, GLfloat x
)
915 GLuint attr
= (target
& 0x7) + BRW_ATTRIB_TEX0
;
916 DISPATCH_ATTR1F( attr
, x
);
919 static void GLAPIENTRY
_save_MultiTexCoord1fv( GLenum target
, const GLfloat
*v
)
921 GLuint attr
= (target
& 0x7) + BRW_ATTRIB_TEX0
;
922 DISPATCH_ATTR1FV( attr
, v
);
925 static void GLAPIENTRY
_save_MultiTexCoord2f( GLenum target
, GLfloat x
, GLfloat y
)
927 GLuint attr
= (target
& 0x7) + BRW_ATTRIB_TEX0
;
928 DISPATCH_ATTR2F( attr
, x
, y
);
931 static void GLAPIENTRY
_save_MultiTexCoord2fv( GLenum target
, const GLfloat
*v
)
933 GLuint attr
= (target
& 0x7) + BRW_ATTRIB_TEX0
;
934 DISPATCH_ATTR2FV( attr
, v
);
937 static void GLAPIENTRY
_save_MultiTexCoord3f( GLenum target
, GLfloat x
, GLfloat y
,
940 GLuint attr
= (target
& 0x7) + BRW_ATTRIB_TEX0
;
941 DISPATCH_ATTR3F( attr
, x
, y
, z
);
944 static void GLAPIENTRY
_save_MultiTexCoord3fv( GLenum target
, const GLfloat
*v
)
946 GLuint attr
= (target
& 0x7) + BRW_ATTRIB_TEX0
;
947 DISPATCH_ATTR3FV( attr
, v
);
950 static void GLAPIENTRY
_save_MultiTexCoord4f( GLenum target
, GLfloat x
, GLfloat y
,
951 GLfloat z
, GLfloat w
)
953 GLuint attr
= (target
& 0x7) + BRW_ATTRIB_TEX0
;
954 DISPATCH_ATTR4F( attr
, x
, y
, z
, w
);
957 static void GLAPIENTRY
_save_MultiTexCoord4fv( GLenum target
, const GLfloat
*v
)
959 GLuint attr
= (target
& 0x7) + BRW_ATTRIB_TEX0
;
960 DISPATCH_ATTR4FV( attr
, v
);
963 static void GLAPIENTRY
_save_VertexAttrib1fNV( GLuint index
, GLfloat x
)
965 if (index
< BRW_ATTRIB_FIRST_MATERIAL
)
966 DISPATCH_ATTR1F( index
, x
);
971 static void GLAPIENTRY
_save_VertexAttrib1fvNV( GLuint index
, const GLfloat
*v
)
973 if (index
< BRW_ATTRIB_FIRST_MATERIAL
)
974 DISPATCH_ATTR1FV( index
, v
);
979 static void GLAPIENTRY
_save_VertexAttrib2fNV( GLuint index
, GLfloat x
, GLfloat y
)
981 if (index
< BRW_ATTRIB_FIRST_MATERIAL
)
982 DISPATCH_ATTR2F( index
, x
, y
);
987 static void GLAPIENTRY
_save_VertexAttrib2fvNV( GLuint index
, const GLfloat
*v
)
989 if (index
< BRW_ATTRIB_FIRST_MATERIAL
)
990 DISPATCH_ATTR2FV( index
, v
);
995 static void GLAPIENTRY
_save_VertexAttrib3fNV( GLuint index
, GLfloat x
, GLfloat y
,
998 if (index
< BRW_ATTRIB_FIRST_MATERIAL
)
999 DISPATCH_ATTR3F( index
, x
, y
, z
);
1004 static void GLAPIENTRY
_save_VertexAttrib3fvNV( GLuint index
, const GLfloat
*v
)
1006 if (index
< BRW_ATTRIB_FIRST_MATERIAL
)
1007 DISPATCH_ATTR3FV( index
, v
);
1012 static void GLAPIENTRY
_save_VertexAttrib4fNV( GLuint index
, GLfloat x
, GLfloat y
,
1013 GLfloat z
, GLfloat w
)
1015 if (index
< BRW_ATTRIB_FIRST_MATERIAL
)
1016 DISPATCH_ATTR4F( index
, x
, y
, z
, w
);
1021 static void GLAPIENTRY
_save_VertexAttrib4fvNV( GLuint index
, const GLfloat
*v
)
1023 if (index
< BRW_ATTRIB_FIRST_MATERIAL
)
1024 DISPATCH_ATTR4FV( index
, v
);
1030 static void GLAPIENTRY
1031 _save_VertexAttrib1fARB( GLuint index
, GLfloat x
)
1033 if (index
< BRW_ATTRIB_FIRST_MATERIAL
)
1034 DISPATCH_ATTR1F( index
, x
);
1039 static void GLAPIENTRY
1040 _save_VertexAttrib1fvARB( GLuint index
, const GLfloat
*v
)
1042 if (index
< BRW_ATTRIB_FIRST_MATERIAL
)
1043 DISPATCH_ATTR1FV( index
, v
);
1048 static void GLAPIENTRY
1049 _save_VertexAttrib2fARB( GLuint index
, GLfloat x
, GLfloat y
)
1051 if (index
< BRW_ATTRIB_FIRST_MATERIAL
)
1052 DISPATCH_ATTR2F( index
, x
, y
);
1057 static void GLAPIENTRY
1058 _save_VertexAttrib2fvARB( GLuint index
, const GLfloat
*v
)
1060 if (index
< BRW_ATTRIB_FIRST_MATERIAL
)
1061 DISPATCH_ATTR2FV( index
, v
);
1066 static void GLAPIENTRY
1067 _save_VertexAttrib3fARB( GLuint index
, GLfloat x
, GLfloat y
, GLfloat z
)
1069 if (index
< BRW_ATTRIB_FIRST_MATERIAL
)
1070 DISPATCH_ATTR3F( index
, x
, y
, z
);
1075 static void GLAPIENTRY
1076 _save_VertexAttrib3fvARB( GLuint index
, const GLfloat
*v
)
1078 if (index
< BRW_ATTRIB_FIRST_MATERIAL
)
1079 DISPATCH_ATTR3FV( index
, v
);
1084 static void GLAPIENTRY
1085 _save_VertexAttrib4fARB( GLuint index
, GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
1087 if (index
< BRW_ATTRIB_FIRST_MATERIAL
)
1088 DISPATCH_ATTR4F( index
, x
, y
, z
, w
);
1093 static void GLAPIENTRY
1094 _save_VertexAttrib4fvARB( GLuint index
, const GLfloat
*v
)
1096 if (index
< BRW_ATTRIB_FIRST_MATERIAL
)
1097 DISPATCH_ATTR4FV( index
, v
);
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.
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.
1114 * There is no aliasing of material attributes with other entrypoints.
1116 #define MAT_ATTR( A, N, params ) \
1118 if (save->attrsz[A] < N) { \
1119 _save_upgrade_vertex( ctx, A, N ); \
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]; \
1132 #define MAT( ATTR, N, face, params ) \
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 */ \
1141 /* NOTE: Have to remove/deal-with colormaterial crossovers, probably
1142 * later on - in the meantime just store everything.
1144 static void GLAPIENTRY
_save_Materialfv( GLenum face
, GLenum pname
,
1145 const GLfloat
*params
)
1147 GET_CURRENT_CONTEXT( ctx
);
1148 struct brw_save_context
*save
= IMM_CONTEXT(ctx
)->save
;
1152 MAT( BRW_ATTRIB_MAT_FRONT_EMISSION
, 4, face
, params
);
1155 MAT( BRW_ATTRIB_MAT_FRONT_AMBIENT
, 4, face
, params
);
1158 MAT( BRW_ATTRIB_MAT_FRONT_DIFFUSE
, 4, face
, params
);
1161 MAT( BRW_ATTRIB_MAT_FRONT_SPECULAR
, 4, face
, params
);
1164 MAT( BRW_ATTRIB_MAT_FRONT_SHININESS
, 1, face
, params
);
1166 case GL_COLOR_INDEXES
:
1167 MAT( BRW_ATTRIB_MAT_FRONT_INDEXES
, 3, face
, params
);
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
);
1174 _mesa_compile_error( ctx
, GL_INVALID_ENUM
, "glMaterialfv" );
1180 #define IDX_ATTR( A, IDX ) \
1182 GET_CURRENT_CONTEXT( ctx ); \
1183 struct brw_save_context *save = IMM_CONTEXT(ctx)->save; \
1185 if (save->attrsz[A] < 1) { \
1186 _save_upgrade_vertex( ctx, A, 1 ); \
1190 GLfloat *dest = save->attrptr[A]; \
1196 static void GLAPIENTRY
_save_EdgeFlag( GLboolean b
)
1198 IDX_ATTR( BRW_ATTRIB_EDGEFLAG
, (GLfloat
)b
);
1202 static void GLAPIENTRY
_save_EdgeFlagv( const GLboolean
*v
)
1204 IDX_ATTR( BRW_ATTRIB_EDGEFLAG
, (GLfloat
)(v
[0]) );
1208 static void GLAPIENTRY
_save_Indexf( GLfloat f
)
1210 IDX_ATTR( BRW_ATTRIB_INDEX
, f
);
1213 static void GLAPIENTRY
_save_Indexfv( const GLfloat
*f
)
1215 IDX_ATTR( BRW_ATTRIB_INDEX
, f
[0] );
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.
1225 #define DO_FALLBACK(ctx) \
1227 struct brw_save_context *save = IMM_CONTEXT(ctx)->save; \
1229 if (save->vert_count || save->prim_count) \
1230 _save_compile_vertex_list( ctx ); \
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; \
1239 static void GLAPIENTRY
_save_EvalCoord1f( GLfloat u
)
1241 GET_CURRENT_CONTEXT(ctx
);
1243 ctx
->Save
->EvalCoord1f( u
);
1246 static void GLAPIENTRY
_save_EvalCoord1fv( const GLfloat
*v
)
1248 GET_CURRENT_CONTEXT(ctx
);
1250 ctx
->Save
->EvalCoord1fv( v
);
1253 static void GLAPIENTRY
_save_EvalCoord2f( GLfloat u
, GLfloat v
)
1255 GET_CURRENT_CONTEXT(ctx
);
1257 ctx
->Save
->EvalCoord2f( u
, v
);
1260 static void GLAPIENTRY
_save_EvalCoord2fv( const GLfloat
*v
)
1262 GET_CURRENT_CONTEXT(ctx
);
1264 ctx
->Save
->EvalCoord2fv( v
);
1267 static void GLAPIENTRY
_save_EvalPoint1( GLint i
)
1269 GET_CURRENT_CONTEXT(ctx
);
1271 ctx
->Save
->EvalPoint1( i
);
1274 static void GLAPIENTRY
_save_EvalPoint2( GLint i
, GLint j
)
1276 GET_CURRENT_CONTEXT(ctx
);
1278 ctx
->Save
->EvalPoint2( i
, j
);
1281 static void GLAPIENTRY
_save_CallList( GLuint l
)
1283 GET_CURRENT_CONTEXT(ctx
);
1285 ctx
->Save
->CallList( l
);
1288 static void GLAPIENTRY
_save_CallLists( GLsizei n
, GLenum type
, const GLvoid
*v
)
1290 GET_CURRENT_CONTEXT(ctx
);
1292 ctx
->Save
->CallLists( n
, type
, v
);
1298 /* This begin is hooked into ... Updating of
1299 * ctx->Driver.CurrentSavePrimitive is already taken care of.
1301 GLboolean
brw_save_NotifyBegin( GLcontext
*ctx
, GLenum mode
)
1303 struct brw_save_context
*save
= IMM_CONTEXT(ctx
)->save
;
1305 GLuint i
= save
->prim_count
++;
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;
1316 _mesa_install_save_vtxfmt( ctx
, &save
->vtxfmt
);
1317 ctx
->Driver
.SaveNeedFlush
= 1;
1323 static void GLAPIENTRY
_save_End( void )
1325 GET_CURRENT_CONTEXT( ctx
);
1326 struct brw_save_context
*save
= IMM_CONTEXT(ctx
)->save
;
1327 GLint i
= save
->prim_count
- 1;
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
);
1334 if (i
== (GLint
) save
->prim_max
- 1) {
1335 _save_compile_vertex_list( ctx
);
1336 assert(save
->copied
.nr
== 0);
1339 /* Swap out this vertex format while outside begin/end. Any color,
1340 * etc. received between here and the next begin will be compiled
1343 _mesa_install_save_vtxfmt( ctx
, &ctx
->ListState
.ListVtxfmt
);
1347 /* These are all errors as this vtxfmt is only installed inside
1350 static void GLAPIENTRY
_save_DrawElements(GLenum mode
, GLsizei count
, GLenum type
,
1351 const GLvoid
*indices
)
1353 GET_CURRENT_CONTEXT(ctx
);
1354 (void) mode
; (void) count
; (void) type
; (void) indices
;
1355 _mesa_compile_error( ctx
, GL_INVALID_OPERATION
, "glDrawElements" );
1359 static void GLAPIENTRY
_save_DrawRangeElements(GLenum mode
,
1360 GLuint start
, GLuint end
,
1361 GLsizei count
, GLenum type
,
1362 const GLvoid
*indices
)
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" );
1369 static void GLAPIENTRY
_save_DrawArrays(GLenum mode
, GLint start
, GLsizei count
)
1371 GET_CURRENT_CONTEXT(ctx
);
1372 (void) mode
; (void) start
; (void) count
;
1373 _mesa_compile_error( ctx
, GL_INVALID_OPERATION
, "glDrawArrays" );
1376 static void GLAPIENTRY
_save_Rectf( GLfloat x1
, GLfloat y1
, GLfloat x2
, GLfloat y2
)
1378 GET_CURRENT_CONTEXT(ctx
);
1379 (void) x1
; (void) y1
; (void) x2
; (void) y2
;
1380 _mesa_compile_error( ctx
, GL_INVALID_OPERATION
, "glRectf" );
1383 static void GLAPIENTRY
_save_EvalMesh1( GLenum mode
, GLint i1
, GLint i2
)
1385 GET_CURRENT_CONTEXT(ctx
);
1386 (void) mode
; (void) i1
; (void) i2
;
1387 _mesa_compile_error( ctx
, GL_INVALID_OPERATION
, "glEvalMesh1" );
1390 static void GLAPIENTRY
_save_EvalMesh2( GLenum mode
, GLint i1
, GLint i2
,
1391 GLint j1
, GLint j2
)
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" );
1398 static void GLAPIENTRY
_save_Begin( GLenum mode
)
1400 GET_CURRENT_CONTEXT( ctx
);
1402 _mesa_compile_error( ctx
, GL_INVALID_OPERATION
, "Recursive glBegin" );
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.
1410 static void GLAPIENTRY
_save_OBE_Rectf( GLfloat x1
, GLfloat y1
, GLfloat x2
, GLfloat y2
)
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(), ());
1422 static void GLAPIENTRY
_save_OBE_DrawArrays(GLenum mode
, GLint start
, GLsizei count
)
1424 GET_CURRENT_CONTEXT(ctx
);
1427 if (!_mesa_validate_DrawArrays( ctx
, mode
, start
, count
))
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(), ());
1436 /* Could do better by copying the arrays and element list intact and
1437 * then emitting an indexed prim at runtime.
1439 static void GLAPIENTRY
_save_OBE_DrawElements(GLenum mode
, GLsizei count
, GLenum type
,
1440 const GLvoid
*indices
)
1442 GET_CURRENT_CONTEXT(ctx
);
1445 if (!_mesa_validate_DrawElements( ctx
, mode
, count
, type
, indices
))
1448 brw_save_NotifyBegin( ctx
, mode
| BRW_SAVE_PRIM_WEAK
);
1451 case GL_UNSIGNED_BYTE
:
1452 for (i
= 0 ; i
< count
; i
++)
1453 CALL_ArrayElement(GET_DISPATCH(), ( ((GLubyte
*)indices
)[i
] ));
1455 case GL_UNSIGNED_SHORT
:
1456 for (i
= 0 ; i
< count
; i
++)
1457 CALL_ArrayElement(GET_DISPATCH(), ( ((GLushort
*)indices
)[i
] ));
1459 case GL_UNSIGNED_INT
:
1460 for (i
= 0 ; i
< count
; i
++)
1461 CALL_ArrayElement(GET_DISPATCH(), ( ((GLuint
*)indices
)[i
] ));
1464 _mesa_error( ctx
, GL_INVALID_ENUM
, "glDrawElements(type)" );
1468 CALL_End(GET_DISPATCH(), ());
1471 static void GLAPIENTRY
_save_OBE_DrawRangeElements(GLenum mode
,
1472 GLuint start
, GLuint end
,
1473 GLsizei count
, GLenum type
,
1474 const GLvoid
*indices
)
1476 GET_CURRENT_CONTEXT(ctx
);
1477 if (_mesa_validate_DrawRangeElements( ctx
, mode
,
1479 count
, type
, indices
))
1480 _save_OBE_DrawElements( mode
, count
, type
, indices
);
1487 static void _save_vtxfmt_init( GLcontext
*ctx
)
1489 struct brw_save_context
*save
= IMM_CONTEXT(ctx
)->save
;
1490 GLvertexformat
*vfmt
= &save
->vtxfmt
;
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
;
1549 /* This will all require us to fallback to saving the list as opcodes:
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
;
1560 /* These are all errors as we at least know we are in some sort of
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
;
1574 void brw_save_SaveFlushVertices( GLcontext
*ctx
)
1576 struct brw_save_context
*save
= IMM_CONTEXT(ctx
)->save
;
1578 /* Noop when we are actually active:
1580 if (ctx
->Driver
.CurrentSavePrimitive
== PRIM_INSIDE_UNKNOWN_PRIM
||
1581 ctx
->Driver
.CurrentSavePrimitive
<= GL_POLYGON
)
1584 if (save
->vert_count
||
1586 _save_compile_vertex_list( ctx
);
1588 _save_copy_to_current( ctx
);
1589 _save_reset_vertex( ctx
);
1590 _save_reset_counters( ctx
);
1591 ctx
->Driver
.SaveNeedFlush
= 0;
1594 void brw_save_NewList( GLcontext
*ctx
, GLuint list
, GLenum mode
)
1596 struct brw_save_context
*save
= IMM_CONTEXT(ctx
)->save
;
1598 (void) list
; (void) mode
;
1600 if (!save
->prim_store
)
1601 save
->prim_store
= alloc_prim_store( ctx
);
1603 if (!save
->vertex_store
)
1604 save
->vertex_store
= alloc_vertex_store( ctx
);
1606 save
->vbptr
= map_vertex_store( ctx
, save
->vertex_store
);
1608 _save_reset_vertex( ctx
);
1609 _save_reset_counters( ctx
);
1610 ctx
->Driver
.SaveNeedFlush
= 0;
1613 void brw_save_EndList( GLcontext
*ctx
)
1615 struct brw_save_context
*save
= IMM_CONTEXT(ctx
)->save
;
1616 unmap_vertex_store( ctx
, save
->vertex_store
);
1618 assert(save
->vertex_size
== 0);
1621 void brw_save_BeginCallList( GLcontext
*ctx
, struct mesa_display_list
*dlist
)
1623 struct brw_save_context
*save
= IMM_CONTEXT(ctx
)->save
;
1624 save
->replay_flags
|= dlist
->flags
;
1627 void brw_save_EndCallList( GLcontext
*ctx
)
1629 struct brw_save_context
*save
= IMM_CONTEXT(ctx
)->save
;
1631 if (ctx
->ListState
.CallDepth
== 1) {
1632 /* This is correct: want to keep only the BRW_SAVE_FALLBACK
1633 * flag, if it is set:
1635 save
->replay_flags
&= BRW_SAVE_FALLBACK
;
1640 static void brw_destroy_vertex_list( GLcontext
*ctx
, void *data
)
1642 struct brw_save_vertex_list
*node
= (struct brw_save_vertex_list
*)data
;
1645 if ( --node
->vertex_store
->refcount
== 0 )
1646 free_vertex_store( ctx
, node
->vertex_store
);
1648 if ( --node
->prim_store
->refcount
== 0 )
1649 FREE( node
->prim_store
);
1653 static void brw_print_vertex_list( GLcontext
*ctx
, void *data
)
1655 struct brw_save_vertex_list
*node
= (struct brw_save_vertex_list
*)data
;
1659 _mesa_debug(NULL
, "BRW-VERTEX-LIST, %u vertices %d primitives, %d vertsize\n",
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",
1668 _mesa_lookup_enum_by_nr(prim
->mode
),
1669 prim
->weak
? " (weak)" : "",
1671 prim
->start
+ prim
->count
,
1672 (prim
->begin
) ? "BEGIN" : "(wrap)",
1673 (prim
->end
) ? "END" : "(wrap)");
1678 static void _save_current_init( GLcontext
*ctx
)
1680 struct brw_save_context
*save
= IMM_CONTEXT(ctx
)->save
;
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
];
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
];
1695 save
->currentsz
[BRW_ATTRIB_INDEX
] = &ctx
->ListState
.ActiveIndex
;
1696 save
->current
[BRW_ATTRIB_INDEX
] = &ctx
->ListState
.CurrentIndex
;
1698 save
->currentsz
[BRW_ATTRIB_EDGEFLAG
] = &ctx
->ListState
.ActiveEdgeFlag
;
1699 save
->current
[BRW_ATTRIB_EDGEFLAG
] = &save
->CurrentFloatEdgeFlag
;
1703 * Initialize the display list compiler
1705 void brw_save_api_init( struct brw_save_context
*save
)
1707 GLcontext
*ctx
= save
->ctx
;
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
);
1717 ctx
->Driver
.NotifySaveBegin
= brw_save_NotifyBegin
;
1719 _save_vtxfmt_init( ctx
);
1720 _save_current_init( ctx
);
1722 for (i
= 0; i
< BRW_ATTRIB_MAX
; i
++)
1723 save
->inputs
[i
] = &save
->arrays
[i
];
1725 /* Hook our array functions into the outside-begin-end vtxfmt in
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
);