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
, VERT_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
++) {
285 la
[nr
].sz
= attrsz
[i
];
286 la
[nr
].func
= vert_attrfunc
[attrsz
[i
]-1];
291 for (i
= BRW_ATTRIB_MAT_FRONT_AMBIENT
;
292 i
<= BRW_ATTRIB_MAT_BACK_INDEXES
;
296 la
[nr
].sz
= attrsz
[i
];
297 la
[nr
].func
= mat_attrfunc
[attrsz
[i
]-1];
302 if (attrsz
[BRW_ATTRIB_EDGEFLAG
]) {
303 la
[nr
].target
= BRW_ATTRIB_EDGEFLAG
;
304 la
[nr
].sz
= attrsz
[BRW_ATTRIB_EDGEFLAG
];
305 la
[nr
].func
= edgeflag_attr1fv
;
309 if (attrsz
[BRW_ATTRIB_INDEX
]) {
310 la
[nr
].target
= BRW_ATTRIB_INDEX
;
311 la
[nr
].sz
= attrsz
[BRW_ATTRIB_INDEX
];
312 la
[nr
].func
= index_attr1fv
;
316 /* XXX ARB vertex attribs */
318 for (i
= 0 ; i
< prim_count
; i
++) {
319 if ((prim
[i
].mode
& BRW_SAVE_PRIM_WEAK
) &&
320 (ctx
->Driver
.CurrentExecPrimitive
!= PRIM_OUTSIDE_BEGIN_END
))
322 loopback_weak_prim( ctx
, &prim
[i
] );
326 loopback_prim( ctx
, buffer
, &prim
[i
], wrap_count
, vertex_size
, la
, nr
);
338 static GLboolean
do_check_fallback(struct brw_context
*brw
)
340 GLcontext
*ctx
= &brw
->intel
.ctx
;
345 if (brw
->metaops
.active
)
348 if (brw
->intel
.no_rast
)
353 if (ctx
->DrawBuffer
->_ColorDrawBufferMask
[0] != BUFFER_BIT_FRONT_LEFT
&&
354 ctx
->DrawBuffer
->_ColorDrawBufferMask
[0] != BUFFER_BIT_BACK_LEFT
)
359 * XXX: need to save/restore RenderMode in metaops state, or
360 * somehow move to a new attribs pointer:
362 if (ctx
->RenderMode
!= GL_RENDER
)
367 for (i
= 0; i
< BRW_MAX_TEX_UNIT
; i
++) {
368 struct gl_texture_unit
*texUnit
= &brw
->attribs
.Texture
->Unit
[i
];
369 if (texUnit
->_ReallyEnabled
) {
370 struct intel_texture_object
*intelObj
= intel_texture_object(texUnit
->_Current
);
371 struct gl_texture_image
*texImage
= intelObj
->base
.Image
[0][intelObj
->firstLevel
];
372 if (texImage
->Border
)
379 if (brw
->attribs
.Stencil
->Enabled
&&
380 !brw
->intel
.hw_stencil
) {
388 static void check_fallback(struct brw_context
*brw
)
390 brw
->intel
.Fallback
= do_check_fallback(brw
);
393 const struct brw_tracked_state brw_check_fallback
= {
395 .mesa
= _NEW_BUFFERS
| _NEW_RENDERMODE
| _NEW_TEXTURE
| _NEW_STENCIL
,
396 .brw
= BRW_NEW_METAOPS
,
399 .update
= check_fallback
405 /* If there is a fallback, fallback to software rasterization and
406 * transformation together. There is never a requirement to have
407 * software t&l but hardware rasterization.
409 * Further, all fallbacks are based on GL state, not on eg. primitive
413 static void do_fallback( struct brw_context
*brw
,
416 GLcontext
*ctx
= &brw
->intel
.ctx
;
420 ctx
->Driver
.Flush( ctx
);
423 _swsetup_Wakeup( ctx
);
424 _tnl_wakeup_exec( ctx
);
426 /* Need this because tnl_wakeup_exec does too much:
428 brw_save_wakeup(ctx
);
429 brw_save_fallback(ctx
, GL_TRUE
);
432 /* Flush vertices and copy-to-current:
434 FLUSH_CURRENT(ctx
, 0);
436 _swrast_flush( ctx
);
438 brw_exec_wakeup(ctx
);
440 /* Need this because tnl_wakeup_exec does too much:
442 brw_save_wakeup(ctx
);
443 brw_save_fallback(ctx
, GL_FALSE
);
448 void brw_fallback( GLcontext
*ctx
)
450 struct brw_context
*brw
= brw_context(ctx
);
455 void brw_unfallback( GLcontext
*ctx
)
457 struct brw_context
*brw
= brw_context(ctx
);
463 void intelFallback( struct intel_context
*intel
, GLuint bit
, GLboolean mode
)