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>
40 #include "api_arrayelt.h"
46 static void reset_attrfv( struct brw_exec_context
*exec
);
48 static brw_attrfv_func choose
[BRW_MAX_ATTR_CODEGEN
+1][4]; /* +1 for ERROR_ATTRIB */
49 static brw_attrfv_func generic_attr_func
[BRW_MAX_ATTR_CODEGEN
][4];
52 /* Close off the last primitive, execute the buffer, restart the
55 static void brw_exec_wrap_buffers( struct brw_exec_context
*exec
)
57 if (exec
->vtx
.prim_count
== 0) {
58 exec
->vtx
.copied
.nr
= 0;
59 exec
->vtx
.vert_count
= 0;
60 exec
->vtx
.vbptr
= (GLfloat
*)exec
->vtx
.buffer_map
;
63 GLuint last_begin
= exec
->vtx
.prim
[exec
->vtx
.prim_count
-1].begin
;
66 if (exec
->ctx
->Driver
.CurrentExecPrimitive
!= GL_POLYGON
+1) {
67 GLint i
= exec
->vtx
.prim_count
- 1;
69 exec
->vtx
.prim
[i
].count
= (exec
->vtx
.vert_count
-
70 exec
->vtx
.prim
[i
].start
);
73 last_count
= exec
->vtx
.prim
[exec
->vtx
.prim_count
-1].count
;
75 /* Execute the buffer and save copied vertices.
77 if (exec
->vtx
.vert_count
)
78 brw_exec_vtx_flush( exec
);
80 exec
->vtx
.prim_count
= 0;
81 exec
->vtx
.copied
.nr
= 0;
84 /* Emit a glBegin to start the new list.
86 assert(exec
->vtx
.prim_count
== 0);
88 if (exec
->ctx
->Driver
.CurrentExecPrimitive
!= GL_POLYGON
+1) {
89 exec
->vtx
.prim
[0].mode
= exec
->ctx
->Driver
.CurrentExecPrimitive
;
90 exec
->vtx
.prim
[0].start
= 0;
91 exec
->vtx
.prim
[0].count
= 0;
92 exec
->vtx
.prim_count
++;
94 if (exec
->vtx
.copied
.nr
== last_count
)
95 exec
->vtx
.prim
[0].begin
= last_begin
;
101 /* Deal with buffer wrapping where provoked by the vertex buffer
102 * filling up, as opposed to upgrade_vertex().
104 void brw_exec_vtx_wrap( struct brw_exec_context
*exec
)
106 GLfloat
*data
= exec
->vtx
.copied
.buffer
;
109 /* Run pipeline on current vertices, copy wrapped vertices
110 * to exec->vtx.copied.
112 brw_exec_wrap_buffers( exec
);
114 /* Copy stored stored vertices to start of new list.
116 assert(exec
->vtx
.max_vert
- exec
->vtx
.vert_count
> exec
->vtx
.copied
.nr
);
118 for (i
= 0 ; i
< exec
->vtx
.copied
.nr
; i
++) {
119 _mesa_memcpy( exec
->vtx
.vbptr
, data
,
120 exec
->vtx
.vertex_size
* sizeof(GLfloat
));
121 exec
->vtx
.vbptr
+= exec
->vtx
.vertex_size
;
122 data
+= exec
->vtx
.vertex_size
;
123 exec
->vtx
.vert_count
++;
126 exec
->vtx
.copied
.nr
= 0;
131 * Copy the active vertex's values to the ctx->Current fields.
133 static void brw_exec_copy_to_current( struct brw_exec_context
*exec
)
135 GLcontext
*ctx
= exec
->ctx
;
138 for (i
= BRW_ATTRIB_POS
+1 ; i
< BRW_ATTRIB_INDEX
; i
++) {
139 if (exec
->vtx
.attrsz
[i
]) {
140 /* Note: the exec->vtx.current[i] pointers point into the
141 * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
143 COPY_CLEAN_4V(exec
->vtx
.current
[i
],
145 exec
->vtx
.attrptr
[i
]);
147 /* This triggers rather too much recalculation of Mesa state
148 * that doesn't get used (eg light positions).
150 if (i
>= BRW_ATTRIB_MAT_FRONT_AMBIENT
&&
151 i
<= BRW_ATTRIB_MAT_BACK_INDEXES
)
152 ctx
->NewState
|= _NEW_LIGHT
;
156 /* color index is special (it's not a float[4] so COPY_CLEAN_4V above
157 * will trash adjacent memory!)
159 if (exec
->vtx
.attrsz
[BRW_ATTRIB_INDEX
]) {
160 ctx
->Current
.Index
= exec
->vtx
.attrptr
[BRW_ATTRIB_INDEX
][0];
163 /* Edgeflag requires additional treatment:
165 if (exec
->vtx
.attrsz
[BRW_ATTRIB_EDGEFLAG
]) {
166 ctx
->Current
.EdgeFlag
= (exec
->vtx
.CurrentFloatEdgeFlag
== 1.0);
170 /* Colormaterial -- this kindof sucks.
172 if (ctx
->Light
.ColorMaterialEnabled
&&
173 exec
->vtx
.attrsz
[VERT_ATTRIB_COLOR0
]) {
174 _mesa_update_color_material(ctx
,
175 ctx
->Current
.Attrib
[VERT_ATTRIB_COLOR0
]);
179 ctx
->Driver
.NeedFlush
&= ~FLUSH_UPDATE_CURRENT
;
183 static void brw_exec_copy_from_current( struct brw_exec_context
*exec
)
185 GLcontext
*ctx
= exec
->ctx
;
188 /* Edgeflag requires additional treatment:
190 exec
->vtx
.CurrentFloatEdgeFlag
=
191 (GLfloat
)ctx
->Current
.EdgeFlag
;
193 for (i
= BRW_ATTRIB_POS
+1 ; i
< BRW_ATTRIB_MAX
; i
++)
194 switch (exec
->vtx
.attrsz
[i
]) {
195 case 4: exec
->vtx
.attrptr
[i
][3] = exec
->vtx
.current
[i
][3];
196 case 3: exec
->vtx
.attrptr
[i
][2] = exec
->vtx
.current
[i
][2];
197 case 2: exec
->vtx
.attrptr
[i
][1] = exec
->vtx
.current
[i
][1];
198 case 1: exec
->vtx
.attrptr
[i
][0] = exec
->vtx
.current
[i
][0];
202 ctx
->Driver
.NeedFlush
|= FLUSH_UPDATE_CURRENT
;
206 /* Flush existing data, set new attrib size, replay copied vertices.
208 static void brw_exec_wrap_upgrade_vertex( struct brw_exec_context
*exec
,
212 GLcontext
*ctx
= exec
->ctx
;
213 GLint lastcount
= exec
->vtx
.vert_count
;
218 /* Run pipeline on current vertices, copy wrapped vertices
219 * to exec->vtx.copied.
221 brw_exec_wrap_buffers( exec
);
224 /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
225 * when the attribute already exists in the vertex and is having
226 * its size increased.
228 brw_exec_copy_to_current( exec
);
231 /* Heuristic: Attempt to isolate attributes received outside
232 * begin/end so that they don't bloat the vertices.
234 if (ctx
->Driver
.CurrentExecPrimitive
== PRIM_OUTSIDE_BEGIN_END
&&
235 exec
->vtx
.attrsz
[attr
] == 0 &&
237 exec
->vtx
.vertex_size
) {
238 reset_attrfv( exec
);
243 oldsz
= exec
->vtx
.attrsz
[attr
];
244 exec
->vtx
.attrsz
[attr
] = newsz
;
246 exec
->vtx
.vertex_size
+= newsz
- oldsz
;
247 exec
->vtx
.max_vert
= BRW_VERT_BUFFER_SIZE
/ exec
->vtx
.vertex_size
;
248 exec
->vtx
.vert_count
= 0;
249 exec
->vtx
.vbptr
= (GLfloat
*)exec
->vtx
.buffer_map
;
252 /* Recalculate all the attrptr[] values
254 for (i
= 0, tmp
= exec
->vtx
.vertex
; i
< BRW_ATTRIB_MAX
; i
++) {
255 if (exec
->vtx
.attrsz
[i
]) {
256 exec
->vtx
.attrptr
[i
] = tmp
;
257 tmp
+= exec
->vtx
.attrsz
[i
];
260 exec
->vtx
.attrptr
[i
] = NULL
; /* will not be dereferenced */
263 /* Copy from current to repopulate the vertex with correct values.
265 brw_exec_copy_from_current( exec
);
267 /* Replay stored vertices to translate them
268 * to new format here.
270 * -- No need to replay - just copy piecewise
272 if (exec
->vtx
.copied
.nr
)
274 GLfloat
*data
= exec
->vtx
.copied
.buffer
;
275 GLfloat
*dest
= exec
->vtx
.vbptr
;
278 assert(exec
->vtx
.vbptr
== (GLfloat
*)exec
->vtx
.buffer_map
);
280 for (i
= 0 ; i
< exec
->vtx
.copied
.nr
; i
++) {
281 for (j
= 0 ; j
< BRW_ATTRIB_MAX
; j
++) {
282 if (exec
->vtx
.attrsz
[j
]) {
285 COPY_CLEAN_4V( dest
, oldsz
, data
);
289 COPY_SZ_4V( dest
, newsz
, exec
->vtx
.current
[j
] );
294 GLuint sz
= exec
->vtx
.attrsz
[j
];
295 COPY_SZ_4V( dest
, sz
, data
);
303 exec
->vtx
.vbptr
= dest
;
304 exec
->vtx
.vert_count
+= exec
->vtx
.copied
.nr
;
305 exec
->vtx
.copied
.nr
= 0;
308 /* For codegen - attrptr's may have changed, so need to redo
309 * codegen. Might be a reasonable place to try & detect attributes
310 * in the vertex which aren't being submitted any more.
312 for (i
= 0 ; i
< BRW_ATTRIB_MAX
; i
++)
313 if (exec
->vtx
.attrsz
[i
]) {
314 GLuint j
= exec
->vtx
.attrsz
[i
] - 1;
316 if (i
< BRW_MAX_ATTR_CODEGEN
)
317 exec
->vtx
.tabfv
[i
][j
] = choose
[i
][j
];
323 static void brw_exec_fixup_vertex( struct brw_exec_context
*exec
,
324 GLuint attr
, GLuint sz
)
326 static const GLfloat id
[4] = { 0, 0, 0, 1 };
329 if (exec
->vtx
.attrsz
[attr
] < sz
) {
330 /* New size is larger. Need to flush existing vertices and get
331 * an enlarged vertex format.
333 brw_exec_wrap_upgrade_vertex( exec
, attr
, sz
);
335 else if (exec
->vtx
.attrsz
[attr
] > sz
) {
336 /* New size is smaller - just need to fill in some
337 * zeros. Don't need to flush or wrap.
339 for (i
= sz
; i
<= exec
->vtx
.attrsz
[attr
] ; i
++)
340 exec
->vtx
.attrptr
[attr
][i
-1] = id
[i
-1];
343 /* Does setting NeedFlush belong here? Necessitates resetting
344 * vtxfmt on each flush (otherwise flags won't get reset
348 exec
->ctx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
350 exec
->ctx
->Driver
.NeedFlush
|= FLUSH_UPDATE_CURRENT
;
354 /* Helper function for 'CHOOSE' macro. Do what's necessary when an
355 * entrypoint is called for the first time.
358 static brw_attrfv_func
do_choose( GLuint attr
, GLuint sz
)
360 GET_CURRENT_CONTEXT( ctx
);
361 struct brw_exec_context
*exec
= IMM_CONTEXT(ctx
)->exec
;
362 GLuint oldsz
= exec
->vtx
.attrsz
[attr
];
364 assert(attr
< BRW_MAX_ATTR_CODEGEN
);
367 /* Reset any active pointers for this attribute
370 exec
->vtx
.tabfv
[attr
][oldsz
-1] = choose
[attr
][oldsz
-1];
372 brw_exec_fixup_vertex( exec
, attr
, sz
);
379 /* Else use generic version:
381 exec
->vtx
.tabfv
[attr
][sz
-1] = generic_attr_func
[attr
][sz
-1];
383 return exec
->vtx
.tabfv
[attr
][sz
-1];
388 #define CHOOSE( ATTR, N ) \
389 static void choose_##ATTR##_##N( const GLfloat *v ) \
391 brw_attrfv_func f = do_choose(ATTR, N); \
395 #define CHOOSERS( ATTRIB ) \
396 CHOOSE( ATTRIB, 1 ) \
397 CHOOSE( ATTRIB, 2 ) \
398 CHOOSE( ATTRIB, 3 ) \
399 CHOOSE( ATTRIB, 4 ) \
402 #define INIT_CHOOSERS(ATTR) \
403 choose[ATTR][0] = choose_##ATTR##_1; \
404 choose[ATTR][1] = choose_##ATTR##_2; \
405 choose[ATTR][2] = choose_##ATTR##_3; \
406 choose[ATTR][3] = choose_##ATTR##_4;
425 static void error_attrib( const GLfloat
*unused
)
427 GET_CURRENT_CONTEXT( ctx
);
429 _mesa_error( ctx
, GL_INVALID_ENUM
, "glVertexAttrib" );
434 static void reset_attrfv( struct brw_exec_context
*exec
)
438 for (i
= 0 ; i
< BRW_ATTRIB_MAX
; i
++)
439 if (exec
->vtx
.attrsz
[i
]) {
440 GLint j
= exec
->vtx
.attrsz
[i
] - 1;
441 exec
->vtx
.attrsz
[i
] = 0;
443 if (i
< BRW_MAX_ATTR_CODEGEN
) {
445 exec
->vtx
.tabfv
[i
][j
] = choose
[i
][j
];
451 exec
->vtx
.vertex_size
= 0;
458 * These are treated as per-vertex attributes, at indices above where
459 * the NV_vertex_program leaves off. There are a lot of good things
460 * about treating materials this way.
462 * However: I don't want to double the number of generated functions
463 * just to cope with this, so I unroll the 'C' varients of CHOOSE and
464 * ATTRF into this function, and dispense with codegen and
465 * second-level dispatch.
467 * There is no aliasing of material attributes with other entrypoints.
469 #define OTHER_ATTR( exec, A, N, params ) \
471 if (exec->vtx.attrsz[A] != N) { \
472 brw_exec_fixup_vertex( exec, A, N ); \
476 GLfloat *dest = exec->vtx.attrptr[A]; \
477 if (N>0) dest[0] = (params)[0]; \
478 if (N>1) dest[1] = (params)[1]; \
479 if (N>2) dest[2] = (params)[2]; \
480 if (N>3) dest[3] = (params)[3]; \
485 #define MAT( exec, ATTR, N, face, params ) \
487 if (face != GL_BACK) \
488 OTHER_ATTR( exec, ATTR, N, params ); /* front */ \
489 if (face != GL_FRONT) \
490 OTHER_ATTR( exec, ATTR + 1, N, params ); /* back */ \
494 /* Colormaterial is dealt with later on.
496 static void GLAPIENTRY
brw_exec_Materialfv( GLenum face
, GLenum pname
,
497 const GLfloat
*params
)
499 GET_CURRENT_CONTEXT( ctx
);
500 struct brw_exec_context
*exec
= IMM_CONTEXT(ctx
)->exec
;
505 case GL_FRONT_AND_BACK
:
509 _mesa_error( ctx
, GL_INVALID_ENUM
, "glMaterialfv" );
515 MAT( exec
, BRW_ATTRIB_MAT_FRONT_EMISSION
, 4, face
, params
);
518 MAT( exec
, BRW_ATTRIB_MAT_FRONT_AMBIENT
, 4, face
, params
);
521 MAT( exec
, BRW_ATTRIB_MAT_FRONT_DIFFUSE
, 4, face
, params
);
524 MAT( exec
, BRW_ATTRIB_MAT_FRONT_SPECULAR
, 4, face
, params
);
527 MAT( exec
, BRW_ATTRIB_MAT_FRONT_SHININESS
, 1, face
, params
);
529 case GL_COLOR_INDEXES
:
530 MAT( exec
, BRW_ATTRIB_MAT_FRONT_INDEXES
, 3, face
, params
);
532 case GL_AMBIENT_AND_DIFFUSE
:
533 MAT( exec
, BRW_ATTRIB_MAT_FRONT_AMBIENT
, 4, face
, params
);
534 MAT( exec
, BRW_ATTRIB_MAT_FRONT_DIFFUSE
, 4, face
, params
);
537 _mesa_error( ctx
, GL_INVALID_ENUM
, "glMaterialfv" );
543 static void GLAPIENTRY
brw_exec_EdgeFlag( GLboolean b
)
545 GET_CURRENT_CONTEXT( ctx
);
546 struct brw_exec_context
*exec
= IMM_CONTEXT(ctx
)->exec
;
547 GLfloat f
= (GLfloat
)b
;
549 OTHER_ATTR( exec
, BRW_ATTRIB_EDGEFLAG
, 1, &f
);
553 static void GLAPIENTRY
brw_exec_EdgeFlagv( const GLboolean
*v
)
555 GET_CURRENT_CONTEXT( ctx
);
556 struct brw_exec_context
*exec
= IMM_CONTEXT(ctx
)->exec
;
557 GLfloat f
= (GLfloat
)v
[0];
559 OTHER_ATTR( exec
, BRW_ATTRIB_EDGEFLAG
, 1, &f
);
563 static void GLAPIENTRY
brw_exec_Indexf( GLfloat f
)
565 GET_CURRENT_CONTEXT( ctx
);
566 struct brw_exec_context
*exec
= IMM_CONTEXT(ctx
)->exec
;
568 OTHER_ATTR( exec
, BRW_ATTRIB_INDEX
, 1, &f
);
571 static void GLAPIENTRY
brw_exec_Indexfv( const GLfloat
*v
)
573 GET_CURRENT_CONTEXT( ctx
);
574 struct brw_exec_context
*exec
= IMM_CONTEXT(ctx
)->exec
;
576 OTHER_ATTR( exec
, BRW_ATTRIB_INDEX
, 1, v
);
581 static void GLAPIENTRY
brw_exec_EvalCoord1f( GLfloat u
)
583 GET_CURRENT_CONTEXT( ctx
);
584 struct brw_exec_context
*exec
= IMM_CONTEXT(ctx
)->exec
;
586 /* TODO: use a CHOOSE() function for this: */
589 if (exec
->eval
.recalculate_maps
)
590 brw_exec_eval_update( exec
);
592 for (i
= 0 ; i
<= BRW_ATTRIB_INDEX
; i
++) {
593 if (exec
->eval
.map1
[i
].map
)
594 if (exec
->vtx
.attrsz
[i
] != exec
->eval
.map1
[i
].sz
)
595 brw_exec_fixup_vertex( exec
, i
, exec
->eval
.map1
[i
].sz
);
600 _mesa_memcpy( exec
->vtx
.copied
.buffer
, exec
->vtx
.vertex
,
601 exec
->vtx
.vertex_size
* sizeof(GLfloat
));
603 brw_exec_do_EvalCoord1f( exec
, u
);
605 _mesa_memcpy( exec
->vtx
.vertex
, exec
->vtx
.copied
.buffer
,
606 exec
->vtx
.vertex_size
* sizeof(GLfloat
));
609 static void GLAPIENTRY
brw_exec_EvalCoord2f( GLfloat u
, GLfloat v
)
611 GET_CURRENT_CONTEXT( ctx
);
612 struct brw_exec_context
*exec
= IMM_CONTEXT(ctx
)->exec
;
614 /* TODO: use a CHOOSE() function for this: */
617 if (exec
->eval
.recalculate_maps
)
618 brw_exec_eval_update( exec
);
620 for (i
= 0 ; i
<= BRW_ATTRIB_INDEX
; i
++) {
621 if (exec
->eval
.map2
[i
].map
)
622 if (exec
->vtx
.attrsz
[i
] != exec
->eval
.map2
[i
].sz
)
623 brw_exec_fixup_vertex( exec
, i
, exec
->eval
.map2
[i
].sz
);
626 if (ctx
->Eval
.AutoNormal
)
627 if (exec
->vtx
.attrsz
[BRW_ATTRIB_NORMAL
] != 3)
628 brw_exec_fixup_vertex( exec
, BRW_ATTRIB_NORMAL
, 3 );
631 _mesa_memcpy( exec
->vtx
.copied
.buffer
, exec
->vtx
.vertex
,
632 exec
->vtx
.vertex_size
* sizeof(GLfloat
));
634 brw_exec_do_EvalCoord2f( exec
, u
, v
);
636 _mesa_memcpy( exec
->vtx
.vertex
, exec
->vtx
.copied
.buffer
,
637 exec
->vtx
.vertex_size
* sizeof(GLfloat
));
640 static void GLAPIENTRY
brw_exec_EvalCoord1fv( const GLfloat
*u
)
642 brw_exec_EvalCoord1f( u
[0] );
645 static void GLAPIENTRY
brw_exec_EvalCoord2fv( const GLfloat
*u
)
647 brw_exec_EvalCoord2f( u
[0], u
[1] );
650 static void GLAPIENTRY
brw_exec_EvalPoint1( GLint i
)
652 GET_CURRENT_CONTEXT( ctx
);
653 GLfloat du
= ((ctx
->Eval
.MapGrid1u2
- ctx
->Eval
.MapGrid1u1
) /
654 (GLfloat
) ctx
->Eval
.MapGrid1un
);
655 GLfloat u
= i
* du
+ ctx
->Eval
.MapGrid1u1
;
657 brw_exec_EvalCoord1f( u
);
661 static void GLAPIENTRY
brw_exec_EvalPoint2( GLint i
, GLint j
)
663 GET_CURRENT_CONTEXT( ctx
);
664 GLfloat du
= ((ctx
->Eval
.MapGrid2u2
- ctx
->Eval
.MapGrid2u1
) /
665 (GLfloat
) ctx
->Eval
.MapGrid2un
);
666 GLfloat dv
= ((ctx
->Eval
.MapGrid2v2
- ctx
->Eval
.MapGrid2v1
) /
667 (GLfloat
) ctx
->Eval
.MapGrid2vn
);
668 GLfloat u
= i
* du
+ ctx
->Eval
.MapGrid2u1
;
669 GLfloat v
= j
* dv
+ ctx
->Eval
.MapGrid2v1
;
671 brw_exec_EvalCoord2f( u
, v
);
675 /* Build a list of primitives on the fly. Keep
676 * ctx->Driver.CurrentExecPrimitive uptodate as well.
678 static void GLAPIENTRY
brw_exec_Begin( GLenum mode
)
680 GET_CURRENT_CONTEXT( ctx
);
682 if (ctx
->Driver
.CurrentExecPrimitive
== GL_POLYGON
+1) {
683 struct brw_exec_context
*exec
= IMM_CONTEXT(ctx
)->exec
;
687 _mesa_update_state( ctx
);
689 if ((ctx
->VertexProgram
.Enabled
&& !ctx
->VertexProgram
._Enabled
) ||
690 (ctx
->FragmentProgram
.Enabled
&& !ctx
->FragmentProgram
._Enabled
)) {
691 _mesa_error(ctx
, GL_INVALID_OPERATION
,
692 "glBegin (invalid vertex/fragment program)");
696 CALL_Begin(ctx
->Exec
, (mode
));
700 /* Heuristic: attempt to isolate attributes occuring outside
703 if (exec
->vtx
.vertex_size
&& !exec
->vtx
.attrsz
[0])
704 brw_exec_FlushVertices( ctx
, ~0 );
706 i
= exec
->vtx
.prim_count
++;
707 exec
->vtx
.prim
[i
].mode
= mode
;
708 exec
->vtx
.prim
[i
].begin
= 1;
709 exec
->vtx
.prim
[i
].end
= 0;
710 exec
->vtx
.prim
[i
].indexed
= 0;
711 exec
->vtx
.prim
[i
].weak
= 0;
712 exec
->vtx
.prim
[i
].pad
= 0;
713 exec
->vtx
.prim
[i
].start
= exec
->vtx
.vert_count
;
714 exec
->vtx
.prim
[i
].count
= 0;
716 ctx
->Driver
.CurrentExecPrimitive
= mode
;
719 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glBegin" );
723 static void GLAPIENTRY
brw_exec_End( void )
725 GET_CURRENT_CONTEXT( ctx
);
727 if (ctx
->Driver
.CurrentExecPrimitive
!= GL_POLYGON
+1) {
728 struct brw_exec_context
*exec
= IMM_CONTEXT(ctx
)->exec
;
729 int idx
= exec
->vtx
.vert_count
;
730 int i
= exec
->vtx
.prim_count
- 1;
732 exec
->vtx
.prim
[i
].end
= 1;
733 exec
->vtx
.prim
[i
].count
= idx
- exec
->vtx
.prim
[i
].start
;
735 ctx
->Driver
.CurrentExecPrimitive
= GL_POLYGON
+1;
737 if (exec
->vtx
.prim_count
== BRW_MAX_PRIM
)
738 brw_exec_vtx_flush( exec
);
741 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glEnd" );
745 static void brw_exec_vtxfmt_init( struct brw_exec_context
*exec
)
747 GLvertexformat
*vfmt
= &exec
->vtxfmt
;
749 vfmt
->ArrayElement
= _ae_loopback_array_elt
; /* generic helper */
750 vfmt
->Begin
= brw_exec_Begin
;
751 vfmt
->CallList
= _mesa_CallList
;
752 vfmt
->CallLists
= _mesa_CallLists
;
753 vfmt
->EdgeFlag
= brw_exec_EdgeFlag
;
754 /* vfmt->EdgeFlagv = brw_exec_EdgeFlagv; */
755 vfmt
->End
= brw_exec_End
;
756 vfmt
->EvalCoord1f
= brw_exec_EvalCoord1f
;
757 vfmt
->EvalCoord1fv
= brw_exec_EvalCoord1fv
;
758 vfmt
->EvalCoord2f
= brw_exec_EvalCoord2f
;
759 vfmt
->EvalCoord2fv
= brw_exec_EvalCoord2fv
;
760 vfmt
->EvalPoint1
= brw_exec_EvalPoint1
;
761 vfmt
->EvalPoint2
= brw_exec_EvalPoint2
;
762 vfmt
->Indexf
= brw_exec_Indexf
;
763 vfmt
->Indexfv
= brw_exec_Indexfv
;
764 vfmt
->Materialfv
= brw_exec_Materialfv
;
766 vfmt
->Rectf
= _mesa_noop_Rectf
;
767 vfmt
->EvalMesh1
= _mesa_noop_EvalMesh1
;
768 vfmt
->EvalMesh2
= _mesa_noop_EvalMesh2
;
772 static void brw_exec_current_init( struct brw_exec_context
*exec
)
774 GLcontext
*ctx
= exec
->ctx
;
777 /* setup the pointers for the typical 16 vertex attributes */
778 for (i
= 0; i
< BRW_ATTRIB_FIRST_MATERIAL
; i
++)
779 exec
->vtx
.current
[i
] = ctx
->Current
.Attrib
[i
];
781 /* setup pointers for the 12 material attributes */
782 for (i
= 0; i
< MAT_ATTRIB_MAX
; i
++)
783 exec
->vtx
.current
[BRW_ATTRIB_FIRST_MATERIAL
+ i
] =
784 ctx
->Light
.Material
.Attrib
[i
];
786 exec
->vtx
.current
[BRW_ATTRIB_INDEX
] = &ctx
->Current
.Index
;
787 exec
->vtx
.current
[BRW_ATTRIB_EDGEFLAG
] = &exec
->vtx
.CurrentFloatEdgeFlag
;
790 void brw_exec_vtx_init( struct brw_exec_context
*exec
)
792 GLcontext
*ctx
= exec
->ctx
;
794 static int firsttime
= 1;
816 choose
[ERROR_ATTRIB
][0] = error_attrib
;
817 choose
[ERROR_ATTRIB
][1] = error_attrib
;
818 choose
[ERROR_ATTRIB
][2] = error_attrib
;
819 choose
[ERROR_ATTRIB
][3] = error_attrib
;
821 brw_exec_generic_attr_table_init( generic_attr_func
);
824 /* Allocate a buffer object. Will just reuse this object
827 exec
->vtx
.bufferobj
= ctx
->Array
.NullBufferObj
;
828 exec
->vtx
.buffer_map
= ALIGN_MALLOC(BRW_VERT_BUFFER_SIZE
* sizeof(GLfloat
), 64);
830 brw_exec_current_init( exec
);
831 brw_exec_vtxfmt_init( exec
);
832 brw_exec_vtx_generic_init( exec
);
834 /* Hook our functions into the dispatch table.
836 _mesa_install_exec_vtxfmt( exec
->ctx
, &exec
->vtxfmt
);
838 memcpy( exec
->vtx
.tabfv
, choose
, sizeof(choose
) );
840 for (i
= 0 ; i
< BRW_ATTRIB_MAX
; i
++) {
841 exec
->vtx
.attrsz
[i
] = 0;
842 exec
->vtx
.inputs
[i
] = &exec
->vtx
.arrays
[i
];
845 exec
->vtx
.vertex_size
= 0;
849 void brw_exec_vtx_destroy( struct brw_exec_context
*exec
)
851 if (exec
->vtx
.buffer_map
) {
852 ALIGN_FREE(exec
->vtx
.buffer_map
);
853 exec
->vtx
.buffer_map
= NULL
;
858 void brw_exec_FlushVertices( GLcontext
*ctx
, GLuint flags
)
860 struct brw_exec_context
*exec
= IMM_CONTEXT(ctx
)->exec
;
862 if (exec
->ctx
->Driver
.CurrentExecPrimitive
!= PRIM_OUTSIDE_BEGIN_END
)
865 if (exec
->vtx
.vert_count
) {
866 brw_exec_vtx_flush( exec
);
869 if (exec
->vtx
.vertex_size
) {
870 brw_exec_copy_to_current( exec
);
871 reset_attrfv( exec
);
874 exec
->ctx
->Driver
.NeedFlush
= 0;