Merge branch 'master' of git+ssh://znh@git.freedesktop.org/git/mesa/mesa
[mesa.git] / src / mesa / drivers / dri / i965 / brw_fallback.c
1 /**************************************************************************
2 *
3 * Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
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.
25 *
26 **************************************************************************/
27
28 #include "swrast_setup/swrast_setup.h"
29 #include "swrast/swrast.h"
30 #include "tnl/tnl.h"
31 #include "context.h"
32 #include "brw_context.h"
33 #include "brw_exec.h"
34 #include "brw_save.h"
35 #include "brw_fallback.h"
36
37 #include "glheader.h"
38 #include "enums.h"
39 #include "glapi.h"
40 #include "imports.h"
41 #include "macros.h"
42 #include "mtypes.h"
43 #include "dispatch.h"
44
45
46 typedef void (*attr_func)( GLcontext *ctx, GLint target, const GLfloat * );
47
48
49 /* Wrapper functions in case glVertexAttrib*fvNV doesn't exist */
50 static void VertexAttrib1fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
51 {
52 CALL_VertexAttrib1fvNV(ctx->Exec, (target, v));
53 }
54
55 static void VertexAttrib2fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
56 {
57 CALL_VertexAttrib2fvNV(ctx->Exec, (target, v));
58 }
59
60 static void VertexAttrib3fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
61 {
62 CALL_VertexAttrib3fvNV(ctx->Exec, (target, v));
63 }
64
65 static void VertexAttrib4fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
66 {
67 CALL_VertexAttrib4fvNV(ctx->Exec, (target, v));
68 }
69
70 static attr_func vert_attrfunc[4] = {
71 VertexAttrib1fvNV,
72 VertexAttrib2fvNV,
73 VertexAttrib3fvNV,
74 VertexAttrib4fvNV
75 };
76
77 #if 0
78 static void VertexAttrib1fvARB(GLcontext *ctx, GLint target, const GLfloat *v)
79 {
80 CALL_VertexAttrib1fvARB(ctx->Exec, (target, v));
81 }
82
83 static void VertexAttrib2fvARB(GLcontext *ctx, GLint target, const GLfloat *v)
84 {
85 CALL_VertexAttrib2fvARB(ctx->Exec, (target, v));
86 }
87
88 static void VertexAttrib3fvARB(GLcontext *ctx, GLint target, const GLfloat *v)
89 {
90 CALL_VertexAttrib3fvARB(ctx->Exec, (target, v));
91 }
92
93 static void VertexAttrib4fvARB(GLcontext *ctx, GLint target, const GLfloat *v)
94 {
95 CALL_VertexAttrib4fvARB(ctx->Exec, (target, v));
96 }
97
98
99 static attr_func vert_attrfunc_arb[4] = {
100 VertexAttrib1fvARB,
101 VertexAttrib2fvARB,
102 VertexAttrib3fvARB,
103 VertexAttrib4fvARB
104 };
105 #endif
106
107
108
109
110
111
112 static void mat_attr1fv( GLcontext *ctx, GLint target, const GLfloat *v )
113 {
114 switch (target) {
115 case BRW_ATTRIB_MAT_FRONT_SHININESS:
116 CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_SHININESS, v ));
117 break;
118 case BRW_ATTRIB_MAT_BACK_SHININESS:
119 CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_SHININESS, v ));
120 break;
121 }
122 }
123
124
125 static void mat_attr3fv( GLcontext *ctx, GLint target, const GLfloat *v )
126 {
127 switch (target) {
128 case BRW_ATTRIB_MAT_FRONT_INDEXES:
129 CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_COLOR_INDEXES, v ));
130 break;
131 case BRW_ATTRIB_MAT_BACK_INDEXES:
132 CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_COLOR_INDEXES, v ));
133 break;
134 }
135 }
136
137
138 static void mat_attr4fv( GLcontext *ctx, GLint target, const GLfloat *v )
139 {
140 switch (target) {
141 case BRW_ATTRIB_MAT_FRONT_EMISSION:
142 CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_EMISSION, v ));
143 break;
144 case BRW_ATTRIB_MAT_BACK_EMISSION:
145 CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_EMISSION, v ));
146 break;
147 case BRW_ATTRIB_MAT_FRONT_AMBIENT:
148 CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_AMBIENT, v ));
149 break;
150 case BRW_ATTRIB_MAT_BACK_AMBIENT:
151 CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_AMBIENT, v ));
152 break;
153 case BRW_ATTRIB_MAT_FRONT_DIFFUSE:
154 CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_DIFFUSE, v ));
155 break;
156 case BRW_ATTRIB_MAT_BACK_DIFFUSE:
157 CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_DIFFUSE, v ));
158 break;
159 case BRW_ATTRIB_MAT_FRONT_SPECULAR:
160 CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_SPECULAR, v ));
161 break;
162 case BRW_ATTRIB_MAT_BACK_SPECULAR:
163 CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_SPECULAR, v ));
164 break;
165 }
166 }
167
168
169 static attr_func mat_attrfunc[4] = {
170 mat_attr1fv,
171 NULL,
172 mat_attr3fv,
173 mat_attr4fv
174 };
175
176
177 static void index_attr1fv(GLcontext *ctx, GLint target, const GLfloat *v)
178 {
179 (void) target;
180 CALL_Indexf(ctx->Exec, (v[0]));
181 }
182
183 static void edgeflag_attr1fv(GLcontext *ctx, GLint target, const GLfloat *v)
184 {
185 (void) target;
186 CALL_EdgeFlag(ctx->Exec, ((GLboolean)(v[0] == 1.0)));
187 }
188
189 struct loopback_attr {
190 GLint target;
191 GLint sz;
192 attr_func func;
193 };
194
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.
198 */
199 static void loopback_prim( GLcontext *ctx,
200 const GLfloat *buffer,
201 const struct brw_draw_prim *prim,
202 GLuint wrap_count,
203 GLuint vertex_size,
204 const struct loopback_attr *la, GLuint nr )
205 {
206 GLint start = prim->start;
207 GLint end = start + prim->count;
208 const GLfloat *data;
209 GLint j;
210 GLuint k;
211
212 if (0)
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" : "..",
217 start,
218 end);
219
220 if (prim->begin) {
221 CALL_Begin(GET_DISPATCH(), ( prim->mode ));
222 }
223 else {
224 assert(start == 0);
225 start += wrap_count;
226 }
227
228 data = buffer + start * vertex_size;
229
230 for (j = start ; j < end ; j++) {
231 const GLfloat *tmp = data + la[0].sz;
232
233 for (k = 1 ; k < nr ; k++) {
234 la[k].func( ctx, la[k].target, tmp );
235 tmp += la[k].sz;
236 }
237
238 /* Fire the vertex
239 */
240 la[0].func( ctx, BRW_ATTRIB_POS, data );
241 data = tmp;
242 }
243
244 if (prim->end) {
245 CALL_End(GET_DISPATCH(), ());
246 }
247 }
248
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
252 * primitives.
253 */
254 static void loopback_weak_prim( GLcontext *ctx,
255 const struct brw_draw_prim *prim )
256 {
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.
260 *
261 * While this flag is set, we are simply disposing of data
262 * generated by an operation now known to be a noop.
263 */
264 if (prim->begin)
265 ctx->Driver.CurrentExecPrimitive |= BRW_SAVE_PRIM_WEAK;
266 if (prim->end)
267 ctx->Driver.CurrentExecPrimitive &= ~BRW_SAVE_PRIM_WEAK;
268 }
269
270
271 void brw_loopback_vertex_list( GLcontext *ctx,
272 const GLfloat *buffer,
273 const GLubyte *attrsz,
274 const struct brw_draw_prim *prim,
275 GLuint prim_count,
276 GLuint wrap_count,
277 GLuint vertex_size)
278 {
279 struct loopback_attr la[BRW_ATTRIB_MAX];
280 GLuint i, nr = 0;
281
282 for (i = 0 ; i <= BRW_ATTRIB_TEX7 ; i++) {
283 if (i == BRW_ATTRIB_INDEX || i == BRW_ATTRIB_EDGEFLAG)
284 continue;
285
286 if (attrsz[i]) {
287 la[nr].target = i;
288 la[nr].sz = attrsz[i];
289 la[nr].func = vert_attrfunc[attrsz[i]-1];
290 nr++;
291 }
292 }
293
294 for (i = BRW_ATTRIB_MAT_FRONT_AMBIENT ;
295 i <= BRW_ATTRIB_MAT_BACK_INDEXES ;
296 i++) {
297 if (attrsz[i]) {
298 la[nr].target = i;
299 la[nr].sz = attrsz[i];
300 la[nr].func = mat_attrfunc[attrsz[i]-1];
301 nr++;
302 }
303 }
304
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;
309 nr++;
310 }
311
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;
316 nr++;
317 }
318
319 /* XXX ARB vertex attribs */
320
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))
324 {
325 loopback_weak_prim( ctx, &prim[i] );
326 }
327 else
328 {
329 loopback_prim( ctx, buffer, &prim[i], wrap_count, vertex_size, la, nr );
330 }
331 }
332 }
333
334
335
336
337
338
339
340
341 static GLboolean do_check_fallback(struct brw_context *brw)
342 {
343 GLcontext *ctx = &brw->intel.ctx;
344 GLuint i;
345
346 /* BRW_NEW_METAOPS
347 */
348 if (brw->metaops.active)
349 return GL_FALSE;
350
351 if (brw->intel.no_rast)
352 return GL_TRUE;
353
354 /* _NEW_BUFFERS
355 */
356 if (ctx->DrawBuffer->_ColorDrawBufferMask[0] != BUFFER_BIT_FRONT_LEFT &&
357 ctx->DrawBuffer->_ColorDrawBufferMask[0] != BUFFER_BIT_BACK_LEFT)
358 return GL_TRUE;
359
360 /* _NEW_RENDERMODE
361 *
362 * XXX: need to save/restore RenderMode in metaops state, or
363 * somehow move to a new attribs pointer:
364 */
365 if (ctx->RenderMode != GL_RENDER)
366 return GL_TRUE;
367
368 /* _NEW_TEXTURE:
369 */
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)
376 return GL_TRUE;
377 }
378 }
379
380 /* _NEW_STENCIL
381 */
382 if (brw->attribs.Stencil->Enabled &&
383 !brw->intel.hw_stencil) {
384 return GL_TRUE;
385 }
386
387
388 return GL_FALSE;
389 }
390
391 static void check_fallback(struct brw_context *brw)
392 {
393 brw->intel.Fallback = do_check_fallback(brw);
394 }
395
396 const struct brw_tracked_state brw_check_fallback = {
397 .dirty = {
398 .mesa = _NEW_BUFFERS | _NEW_RENDERMODE | _NEW_TEXTURE | _NEW_STENCIL,
399 .brw = BRW_NEW_METAOPS,
400 .cache = 0
401 },
402 .update = check_fallback
403 };
404
405
406
407
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.
411 *
412 * Further, all fallbacks are based on GL state, not on eg. primitive
413 * or vertex data.
414 */
415
416 static void do_fallback( struct brw_context *brw,
417 GLboolean fallback )
418 {
419 GLcontext *ctx = &brw->intel.ctx;
420
421 /* flush:
422 */
423 ctx->Driver.Flush( ctx );
424
425 if (fallback) {
426 _swsetup_Wakeup( ctx );
427 _tnl_wakeup_exec( ctx );
428
429 /* Need this because tnl_wakeup_exec does too much:
430 */
431 brw_save_wakeup(ctx);
432 brw_save_fallback(ctx, GL_TRUE);
433 }
434 else {
435 /* Flush vertices and copy-to-current:
436 */
437 FLUSH_CURRENT(ctx, 0);
438
439 _swrast_flush( ctx );
440
441 brw_exec_wakeup(ctx);
442
443 /* Need this because tnl_wakeup_exec does too much:
444 */
445 brw_save_wakeup(ctx);
446 brw_save_fallback(ctx, GL_FALSE);
447 }
448 }
449
450
451 void brw_fallback( GLcontext *ctx )
452 {
453 struct brw_context *brw = brw_context(ctx);
454 do_fallback(brw, 1);
455 }
456
457
458 void brw_unfallback( GLcontext *ctx )
459 {
460 struct brw_context *brw = brw_context(ctx);
461 do_fallback(brw, 0);
462 }
463
464 /* Not used:
465 */
466 void intelFallback( struct intel_context *intel, GLuint bit, GLboolean mode )
467 {
468 }
469
470
471