1 /**************************************************************************
3 * Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
28 #include "swrast_setup/swrast_setup.h"
29 #include "swrast/swrast.h"
32 #include "brw_context.h"
35 #include "brw_fallback.h"
46 typedef void (*attr_func
)( GLcontext
*ctx
, GLint target
, const GLfloat
* );
49 /* Wrapper functions in case glVertexAttrib*fvNV doesn't exist */
50 static void VertexAttrib1fvNV(GLcontext
*ctx
, GLint target
, const GLfloat
*v
)
52 CALL_VertexAttrib1fvNV(ctx
->Exec
, (target
, v
));
55 static void VertexAttrib2fvNV(GLcontext
*ctx
, GLint target
, const GLfloat
*v
)
57 CALL_VertexAttrib2fvNV(ctx
->Exec
, (target
, v
));
60 static void VertexAttrib3fvNV(GLcontext
*ctx
, GLint target
, const GLfloat
*v
)
62 CALL_VertexAttrib3fvNV(ctx
->Exec
, (target
, v
));
65 static void VertexAttrib4fvNV(GLcontext
*ctx
, GLint target
, const GLfloat
*v
)
67 CALL_VertexAttrib4fvNV(ctx
->Exec
, (target
, v
));
70 static attr_func vert_attrfunc
[4] = {
78 static void VertexAttrib1fvARB(GLcontext
*ctx
, GLint target
, const GLfloat
*v
)
80 CALL_VertexAttrib1fvARB(ctx
->Exec
, (target
, v
));
83 static void VertexAttrib2fvARB(GLcontext
*ctx
, GLint target
, const GLfloat
*v
)
85 CALL_VertexAttrib2fvARB(ctx
->Exec
, (target
, v
));
88 static void VertexAttrib3fvARB(GLcontext
*ctx
, GLint target
, const GLfloat
*v
)
90 CALL_VertexAttrib3fvARB(ctx
->Exec
, (target
, v
));
93 static void VertexAttrib4fvARB(GLcontext
*ctx
, GLint target
, const GLfloat
*v
)
95 CALL_VertexAttrib4fvARB(ctx
->Exec
, (target
, v
));
99 static attr_func vert_attrfunc_arb
[4] = {
112 static void mat_attr1fv( GLcontext
*ctx
, GLint target
, const GLfloat
*v
)
115 case BRW_ATTRIB_MAT_FRONT_SHININESS
:
116 CALL_Materialfv(ctx
->Exec
, ( GL_FRONT
, GL_SHININESS
, v
));
118 case BRW_ATTRIB_MAT_BACK_SHININESS
:
119 CALL_Materialfv(ctx
->Exec
, ( GL_BACK
, GL_SHININESS
, v
));
125 static void mat_attr3fv( GLcontext
*ctx
, GLint target
, const GLfloat
*v
)
128 case BRW_ATTRIB_MAT_FRONT_INDEXES
:
129 CALL_Materialfv(ctx
->Exec
, ( GL_FRONT
, GL_COLOR_INDEXES
, v
));
131 case BRW_ATTRIB_MAT_BACK_INDEXES
:
132 CALL_Materialfv(ctx
->Exec
, ( GL_BACK
, GL_COLOR_INDEXES
, v
));
138 static void mat_attr4fv( GLcontext
*ctx
, GLint target
, const GLfloat
*v
)
141 case BRW_ATTRIB_MAT_FRONT_EMISSION
:
142 CALL_Materialfv(ctx
->Exec
, ( GL_FRONT
, GL_EMISSION
, v
));
144 case BRW_ATTRIB_MAT_BACK_EMISSION
:
145 CALL_Materialfv(ctx
->Exec
, ( GL_BACK
, GL_EMISSION
, v
));
147 case BRW_ATTRIB_MAT_FRONT_AMBIENT
:
148 CALL_Materialfv(ctx
->Exec
, ( GL_FRONT
, GL_AMBIENT
, v
));
150 case BRW_ATTRIB_MAT_BACK_AMBIENT
:
151 CALL_Materialfv(ctx
->Exec
, ( GL_BACK
, GL_AMBIENT
, v
));
153 case BRW_ATTRIB_MAT_FRONT_DIFFUSE
:
154 CALL_Materialfv(ctx
->Exec
, ( GL_FRONT
, GL_DIFFUSE
, v
));
156 case BRW_ATTRIB_MAT_BACK_DIFFUSE
:
157 CALL_Materialfv(ctx
->Exec
, ( GL_BACK
, GL_DIFFUSE
, v
));
159 case BRW_ATTRIB_MAT_FRONT_SPECULAR
:
160 CALL_Materialfv(ctx
->Exec
, ( GL_FRONT
, GL_SPECULAR
, v
));
162 case BRW_ATTRIB_MAT_BACK_SPECULAR
:
163 CALL_Materialfv(ctx
->Exec
, ( GL_BACK
, GL_SPECULAR
, v
));
169 static attr_func mat_attrfunc
[4] = {
177 static void index_attr1fv(GLcontext
*ctx
, GLint target
, const GLfloat
*v
)
180 CALL_Indexf(ctx
->Exec
, (v
[0]));
183 static void edgeflag_attr1fv(GLcontext
*ctx
, GLint target
, const GLfloat
*v
)
186 CALL_EdgeFlag(ctx
->Exec
, ((GLboolean
)(v
[0] == 1.0)));
189 struct loopback_attr
{
195 /* Don't emit ends and begins on wrapped primitives. Don't replay
196 * wrapped vertices. If we get here, it's probably because the the
197 * precalculated wrapping is wrong.
199 static void loopback_prim( GLcontext
*ctx
,
200 const GLfloat
*buffer
,
201 const struct brw_draw_prim
*prim
,
204 const struct loopback_attr
*la
, GLuint nr
)
206 GLint start
= prim
->start
;
207 GLint end
= start
+ prim
->count
;
213 _mesa_printf("loopback prim %s(%s,%s) verts %d..%d\n",
214 _mesa_lookup_enum_by_nr(prim
->mode
),
215 prim
->begin
? "begin" : "..",
216 prim
->end
? "end" : "..",
221 CALL_Begin(GET_DISPATCH(), ( prim
->mode
));
228 data
= buffer
+ start
* vertex_size
;
230 for (j
= start
; j
< end
; j
++) {
231 const GLfloat
*tmp
= data
+ la
[0].sz
;
233 for (k
= 1 ; k
< nr
; k
++) {
234 la
[k
].func( ctx
, la
[k
].target
, tmp
);
240 la
[0].func( ctx
, BRW_ATTRIB_POS
, data
);
245 CALL_End(GET_DISPATCH(), ());
249 /* Primitives generated by DrawArrays/DrawElements/Rectf may be
250 * caught here. If there is no primitive in progress, execute them
251 * normally, otherwise need to track and discard the generated
254 static void loopback_weak_prim( GLcontext
*ctx
,
255 const struct brw_draw_prim
*prim
)
257 /* Use the prim_weak flag to ensure that if this primitive
258 * wraps, we don't mistake future vertex_lists for part of the
259 * surrounding primitive.
261 * While this flag is set, we are simply disposing of data
262 * generated by an operation now known to be a noop.
265 ctx
->Driver
.CurrentExecPrimitive
|= BRW_SAVE_PRIM_WEAK
;
267 ctx
->Driver
.CurrentExecPrimitive
&= ~BRW_SAVE_PRIM_WEAK
;
271 void brw_loopback_vertex_list( GLcontext
*ctx
,
272 const GLfloat
*buffer
,
273 const GLubyte
*attrsz
,
274 const struct brw_draw_prim
*prim
,
279 struct loopback_attr la
[BRW_ATTRIB_MAX
];
282 for (i
= 0 ; i
<= BRW_ATTRIB_TEX7
; i
++) {
283 if (i
== BRW_ATTRIB_INDEX
|| i
== BRW_ATTRIB_EDGEFLAG
)
288 la
[nr
].sz
= attrsz
[i
];
289 la
[nr
].func
= vert_attrfunc
[attrsz
[i
]-1];
294 for (i
= BRW_ATTRIB_MAT_FRONT_AMBIENT
;
295 i
<= BRW_ATTRIB_MAT_BACK_INDEXES
;
299 la
[nr
].sz
= attrsz
[i
];
300 la
[nr
].func
= mat_attrfunc
[attrsz
[i
]-1];
305 if (attrsz
[BRW_ATTRIB_EDGEFLAG
]) {
306 la
[nr
].target
= BRW_ATTRIB_EDGEFLAG
;
307 la
[nr
].sz
= attrsz
[BRW_ATTRIB_EDGEFLAG
];
308 la
[nr
].func
= edgeflag_attr1fv
;
312 if (attrsz
[BRW_ATTRIB_INDEX
]) {
313 la
[nr
].target
= BRW_ATTRIB_INDEX
;
314 la
[nr
].sz
= attrsz
[BRW_ATTRIB_INDEX
];
315 la
[nr
].func
= index_attr1fv
;
319 /* XXX ARB vertex attribs */
321 for (i
= 0 ; i
< prim_count
; i
++) {
322 if ((prim
[i
].mode
& BRW_SAVE_PRIM_WEAK
) &&
323 (ctx
->Driver
.CurrentExecPrimitive
!= PRIM_OUTSIDE_BEGIN_END
))
325 loopback_weak_prim( ctx
, &prim
[i
] );
329 loopback_prim( ctx
, buffer
, &prim
[i
], wrap_count
, vertex_size
, la
, nr
);
341 static GLboolean
do_check_fallback(struct brw_context
*brw
)
343 GLcontext
*ctx
= &brw
->intel
.ctx
;
348 if (brw
->metaops
.active
)
351 if (brw
->intel
.no_rast
)
356 if (ctx
->DrawBuffer
->_ColorDrawBufferMask
[0] != BUFFER_BIT_FRONT_LEFT
&&
357 ctx
->DrawBuffer
->_ColorDrawBufferMask
[0] != BUFFER_BIT_BACK_LEFT
)
362 * XXX: need to save/restore RenderMode in metaops state, or
363 * somehow move to a new attribs pointer:
365 if (ctx
->RenderMode
!= GL_RENDER
)
370 for (i
= 0; i
< BRW_MAX_TEX_UNIT
; i
++) {
371 struct gl_texture_unit
*texUnit
= &brw
->attribs
.Texture
->Unit
[i
];
372 if (texUnit
->_ReallyEnabled
) {
373 struct intel_texture_object
*intelObj
= intel_texture_object(texUnit
->_Current
);
374 struct gl_texture_image
*texImage
= intelObj
->base
.Image
[0][intelObj
->firstLevel
];
375 if (texImage
->Border
)
382 if (brw
->attribs
.Stencil
->Enabled
&&
383 !brw
->intel
.hw_stencil
) {
391 static void check_fallback(struct brw_context
*brw
)
393 brw
->intel
.Fallback
= do_check_fallback(brw
);
396 const struct brw_tracked_state brw_check_fallback
= {
398 .mesa
= _NEW_BUFFERS
| _NEW_RENDERMODE
| _NEW_TEXTURE
| _NEW_STENCIL
,
399 .brw
= BRW_NEW_METAOPS
,
402 .update
= check_fallback
408 /* If there is a fallback, fallback to software rasterization and
409 * transformation together. There is never a requirement to have
410 * software t&l but hardware rasterization.
412 * Further, all fallbacks are based on GL state, not on eg. primitive
416 static void do_fallback( struct brw_context
*brw
,
419 GLcontext
*ctx
= &brw
->intel
.ctx
;
423 ctx
->Driver
.Flush( ctx
);
426 _swsetup_Wakeup( ctx
);
427 _tnl_wakeup_exec( ctx
);
429 /* Need this because tnl_wakeup_exec does too much:
431 brw_save_wakeup(ctx
);
432 brw_save_fallback(ctx
, GL_TRUE
);
435 /* Flush vertices and copy-to-current:
437 FLUSH_CURRENT(ctx
, 0);
439 _swrast_flush( ctx
);
441 brw_exec_wakeup(ctx
);
443 /* Need this because tnl_wakeup_exec does too much:
445 brw_save_wakeup(ctx
);
446 brw_save_fallback(ctx
, GL_FALSE
);
451 void brw_fallback( GLcontext
*ctx
)
453 struct brw_context
*brw
= brw_context(ctx
);
458 void brw_unfallback( GLcontext
*ctx
)
460 struct brw_context
*brw
= brw_context(ctx
);
466 void intelFallback( struct intel_context
*intel
, GLuint bit
, GLboolean mode
)