Minor r200 vertex program cleanups. Remove disabled leftovers from r300 vertex progra...
[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, VERT_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 (attrsz[i]) {
284 la[nr].target = i;
285 la[nr].sz = attrsz[i];
286 la[nr].func = vert_attrfunc[attrsz[i]-1];
287 nr++;
288 }
289 }
290
291 for (i = BRW_ATTRIB_MAT_FRONT_AMBIENT ;
292 i <= BRW_ATTRIB_MAT_BACK_INDEXES ;
293 i++) {
294 if (attrsz[i]) {
295 la[nr].target = i;
296 la[nr].sz = attrsz[i];
297 la[nr].func = mat_attrfunc[attrsz[i]-1];
298 nr++;
299 }
300 }
301
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;
306 nr++;
307 }
308
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;
313 nr++;
314 }
315
316 /* XXX ARB vertex attribs */
317
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))
321 {
322 loopback_weak_prim( ctx, &prim[i] );
323 }
324 else
325 {
326 loopback_prim( ctx, buffer, &prim[i], wrap_count, vertex_size, la, nr );
327 }
328 }
329 }
330
331
332
333
334
335
336
337
338 static GLboolean do_check_fallback(struct brw_context *brw)
339 {
340 GLcontext *ctx = &brw->intel.ctx;
341 GLuint i;
342
343 /* BRW_NEW_METAOPS
344 */
345 if (brw->metaops.active)
346 return GL_FALSE;
347
348 if (brw->intel.no_rast)
349 return GL_TRUE;
350
351 /* _NEW_BUFFERS
352 */
353 if (ctx->DrawBuffer->_ColorDrawBufferMask[0] != BUFFER_BIT_FRONT_LEFT &&
354 ctx->DrawBuffer->_ColorDrawBufferMask[0] != BUFFER_BIT_BACK_LEFT)
355 return GL_TRUE;
356
357 /* _NEW_RENDERMODE
358 *
359 * XXX: need to save/restore RenderMode in metaops state, or
360 * somehow move to a new attribs pointer:
361 */
362 if (ctx->RenderMode != GL_RENDER)
363 return GL_TRUE;
364
365 /* _NEW_TEXTURE:
366 */
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)
373 return GL_TRUE;
374 }
375 }
376
377 /* _NEW_STENCIL
378 */
379 if (brw->attribs.Stencil->Enabled &&
380 !brw->intel.hw_stencil) {
381 return GL_TRUE;
382 }
383
384
385 return GL_FALSE;
386 }
387
388 static void check_fallback(struct brw_context *brw)
389 {
390 brw->intel.Fallback = do_check_fallback(brw);
391 }
392
393 const struct brw_tracked_state brw_check_fallback = {
394 .dirty = {
395 .mesa = _NEW_BUFFERS | _NEW_RENDERMODE | _NEW_TEXTURE | _NEW_STENCIL,
396 .brw = BRW_NEW_METAOPS,
397 .cache = 0
398 },
399 .update = check_fallback
400 };
401
402
403
404
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.
408 *
409 * Further, all fallbacks are based on GL state, not on eg. primitive
410 * or vertex data.
411 */
412
413 static void do_fallback( struct brw_context *brw,
414 GLboolean fallback )
415 {
416 GLcontext *ctx = &brw->intel.ctx;
417
418 /* flush:
419 */
420 ctx->Driver.Flush( ctx );
421
422 if (fallback) {
423 _swsetup_Wakeup( ctx );
424 _tnl_wakeup_exec( ctx );
425
426 /* Need this because tnl_wakeup_exec does too much:
427 */
428 brw_save_wakeup(ctx);
429 brw_save_fallback(ctx, GL_TRUE);
430 }
431 else {
432 /* Flush vertices and copy-to-current:
433 */
434 FLUSH_CURRENT(ctx, 0);
435
436 _swrast_flush( ctx );
437
438 brw_exec_wakeup(ctx);
439
440 /* Need this because tnl_wakeup_exec does too much:
441 */
442 brw_save_wakeup(ctx);
443 brw_save_fallback(ctx, GL_FALSE);
444 }
445 }
446
447
448 void brw_fallback( GLcontext *ctx )
449 {
450 struct brw_context *brw = brw_context(ctx);
451 do_fallback(brw, 1);
452 }
453
454
455 void brw_unfallback( GLcontext *ctx )
456 {
457 struct brw_context *brw = brw_context(ctx);
458 do_fallback(brw, 0);
459 }
460
461 /* Not used:
462 */
463 void intelFallback( struct intel_context *intel, GLuint bit, GLboolean mode )
464 {
465 }
466
467
468