Remove unused CTX_ARG2 define.
[mesa.git] / src / mesa / drivers / dri / sis / sis_tris.c
1 /* $XFree86*/ /* -*- c-basic-offset: 3 -*- */
2 /**************************************************************************
3
4 Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
5 Copyright 2003 Eric Anholt
6 All Rights Reserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the "Software"),
10 to deal in the Software without restriction, including without limitation
11 on the rights to use, copy, modify, merge, publish, distribute, sub
12 license, and/or sell copies of the Software, and to permit persons to whom
13 the Software is furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice (including the next
16 paragraph) shall be included in all copies or substantial portions of the
17 Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
23 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27 **************************************************************************/
28
29 /*
30 * Authors:
31 * Sung-Ching Lin <sclin@sis.com.tw>
32 * Eric Anholt <anholt@FreeBSD.org>
33 */
34
35 #include "glheader.h"
36 #include "mtypes.h"
37 #include "colormac.h"
38 #include "macros.h"
39
40 #include "swrast/swrast.h"
41 #include "swrast_setup/swrast_setup.h"
42 #include "tnl/t_context.h"
43 #include "tnl/t_pipeline.h"
44
45 #include "sis_context.h"
46 #include "sis_tris.h"
47 #include "sis_state.h"
48 #include "sis_lock.h"
49 #include "sis_span.h"
50 #include "sis_alloc.h"
51 #include "sis_tex.h"
52
53 static const GLuint hw_prim[GL_POLYGON+1] = {
54 OP_3D_POINT_DRAW, /* GL_POINTS */
55 OP_3D_LINE_DRAW, /* GL_LINES */
56 OP_3D_LINE_DRAW, /* GL_LINE_LOOP */
57 OP_3D_LINE_DRAW, /* GL_LINE_STRIP */
58 OP_3D_TRIANGLE_DRAW, /* GL_TRIANGLES */
59 OP_3D_TRIANGLE_DRAW, /* GL_TRIANGLE_STRIP */
60 OP_3D_TRIANGLE_DRAW, /* GL_TRIANGLE_FAN */
61 OP_3D_TRIANGLE_DRAW, /* GL_QUADS */
62 OP_3D_TRIANGLE_DRAW, /* GL_QUAD_STRIP */
63 OP_3D_TRIANGLE_DRAW /* GL_POLYGON */
64 };
65
66 static const GLuint hw_prim_mmio_fire[OP_3D_TRIANGLE_DRAW+1] = {
67 OP_3D_FIRE_TSARGBa,
68 OP_3D_FIRE_TSARGBb,
69 OP_3D_FIRE_TSARGBc
70 };
71
72 static const GLuint hw_prim_mmio_shade[OP_3D_TRIANGLE_DRAW+1] = {
73 SHADE_FLAT_VertexA,
74 SHADE_FLAT_VertexB,
75 SHADE_FLAT_VertexC
76 };
77
78 static const GLuint hw_prim_agp_type[OP_3D_TRIANGLE_DRAW+1] = {
79 MASK_PsPointList,
80 MASK_PsLineList,
81 MASK_PsTriangleList
82 };
83
84 static const GLuint hw_prim_agp_shade[OP_3D_TRIANGLE_DRAW+1] = {
85 MASK_PsShadingFlatA,
86 MASK_PsShadingFlatB,
87 MASK_PsShadingFlatC
88 };
89
90 static void sisRasterPrimitive( GLcontext *ctx, GLuint hwprim );
91 static void sisRenderPrimitive( GLcontext *ctx, GLenum prim );
92
93 /***********************************************************************
94 * Emit primitives as inline vertices *
95 ***********************************************************************/
96
97 #define HAVE_QUADS 0
98 #define HAVE_LINES 1
99 #define HAVE_POINTS 1
100 #define CTX_ARG sisContextPtr smesa
101 #define GET_VERTEX_DWORDS() smesa->vertex_size
102 #define ALLOC_VERTS( n, size ) sisAllocDmaLow( smesa, n * size * sizeof(int) )
103 #undef LOCAL_VARS
104 #define LOCAL_VARS \
105 sisContextPtr smesa = SIS_CONTEXT(ctx); \
106 const char *vertptr = smesa->verts;
107 #define VERT(x) (sisVertex *)(vertptr + (x * vertsize * sizeof(int)))
108 #define VERTEX sisVertex
109 #undef TAG
110 #define TAG(x) sis_##x
111 #include "tnl_dd/t_dd_triemit.h"
112 #undef TAG
113 #undef LOCAL_VARS
114
115 /***********************************************************************
116 * Dispatch vertices to hardware through MMIO *
117 ***********************************************************************/
118
119 /* The ARGB write of the last vertex of the primitive fires the 3d engine, so
120 * save it until the end.
121 */
122 #define SIS_MMIO_WRITE_VERTEX(_v, i, lastvert) \
123 do { \
124 GLuint __color, __i = 0; \
125 MMIO(REG_3D_TSXa+(i)*0x30, _v->ui[__i++]); \
126 MMIO(REG_3D_TSYa+(i)*0x30, _v->ui[__i++]); \
127 MMIO(REG_3D_TSZa+(i)*0x30, _v->ui[__i++]); \
128 if (SIS_STATES & VERT_W) \
129 MMIO(REG_3D_TSWGa+(i)*0x30, _v->ui[__i++]); \
130 __color = _v->ui[__i++]; \
131 if (SIS_STATES & VERT_SPEC) \
132 MMIO(REG_3D_TSFSa+(i)*0x30, _v->ui[__i++]); \
133 if (SIS_STATES & VERT_UV0) { \
134 MMIO(REG_3D_TSUAa+(i)*0x30, _v->ui[__i++]); \
135 MMIO(REG_3D_TSVAa+(i)*0x30, _v->ui[__i++]); \
136 } \
137 if (SIS_STATES & VERT_UV1) { \
138 MMIO(REG_3D_TSUBa+(i)*0x30, _v->ui[__i++]); \
139 MMIO(REG_3D_TSVBa+(i)*0x30, _v->ui[__i++]); \
140 } \
141 if (lastvert || (SIS_STATES & VERT_SMOOTH)) \
142 MMIO(REG_3D_TSARGBa+(i)*0x30, __color); \
143 } while (0)
144
145 #define MMIO_VERT_REG_COUNT 10
146
147 #define VERT_SMOOTH 0x01
148 #define VERT_W 0x02
149 #define VERT_SPEC 0x04
150 #define VERT_UV0 0x08
151 #define VERT_UV1 0x10
152
153 typedef void (*mmio_draw_func)(sisContextPtr smesa, char *verts);
154 static mmio_draw_func sis_tri_func_mmio[32];
155 static mmio_draw_func sis_line_func_mmio[32];
156 static mmio_draw_func sis_point_func_mmio[32];
157
158 #define SIS_STATES (0)
159 #define TAG(x) x##_none
160 #include "sis_tritmp.h"
161
162 #define SIS_STATES (VERT_SMOOTH)
163 #define TAG(x) x##_g
164 #include "sis_tritmp.h"
165
166 #define SIS_STATES (VERT_W)
167 #define TAG(x) x##_w
168 #include "sis_tritmp.h"
169
170 #define SIS_STATES (VERT_SMOOTH | VERT_W)
171 #define TAG(x) x##_gw
172 #include "sis_tritmp.h"
173
174 #define SIS_STATES (VERT_SPEC)
175 #define TAG(x) x##_s
176 #include "sis_tritmp.h"
177
178 #define SIS_STATES (VERT_SMOOTH | VERT_SPEC)
179 #define TAG(x) x##_gs
180 #include "sis_tritmp.h"
181
182 #define SIS_STATES (VERT_W | VERT_SPEC)
183 #define TAG(x) x##_ws
184 #include "sis_tritmp.h"
185
186 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC)
187 #define TAG(x) x##_gws
188 #include "sis_tritmp.h"
189
190 #define SIS_STATES (VERT_UV0)
191 #define TAG(x) x##_t0
192 #include "sis_tritmp.h"
193
194 #define SIS_STATES (VERT_SMOOTH | VERT_UV0)
195 #define TAG(x) x##_gt0
196 #include "sis_tritmp.h"
197
198 #define SIS_STATES (VERT_W | VERT_UV0)
199 #define TAG(x) x##_wt0
200 #include "sis_tritmp.h"
201
202 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_UV0)
203 #define TAG(x) x##_gwt0
204 #include "sis_tritmp.h"
205
206 #define SIS_STATES (VERT_SPEC | VERT_UV0)
207 #define TAG(x) x##_st0
208 #include "sis_tritmp.h"
209
210 #define SIS_STATES (VERT_SMOOTH | VERT_SPEC | VERT_UV0)
211 #define TAG(x) x##_gst0
212 #include "sis_tritmp.h"
213
214 #define SIS_STATES (VERT_W | VERT_SPEC | VERT_UV0)
215 #define TAG(x) x##_wst0
216 #include "sis_tritmp.h"
217
218 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC | VERT_UV0)
219 #define TAG(x) x##_gwst0
220 #include "sis_tritmp.h"
221
222 #define SIS_STATES (VERT_UV1)
223 #define TAG(x) x##_t1
224 #include "sis_tritmp.h"
225
226 #define SIS_STATES (VERT_SMOOTH | VERT_UV1)
227 #define TAG(x) x##_gt1
228 #include "sis_tritmp.h"
229
230 #define SIS_STATES (VERT_W | VERT_UV1)
231 #define TAG(x) x##_wt1
232 #include "sis_tritmp.h"
233
234 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_UV1)
235 #define TAG(x) x##_gwt1
236 #include "sis_tritmp.h"
237
238 #define SIS_STATES (VERT_SPEC | VERT_UV1)
239 #define TAG(x) x##_st1
240 #include "sis_tritmp.h"
241
242 #define SIS_STATES (VERT_SMOOTH | VERT_SPEC | VERT_UV1)
243 #define TAG(x) x##_gst1
244 #include "sis_tritmp.h"
245
246 #define SIS_STATES (VERT_W | VERT_SPEC | VERT_UV1)
247 #define TAG(x) x##_wst1
248 #include "sis_tritmp.h"
249
250 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC | VERT_UV1)
251 #define TAG(x) x##_gwst1
252 #include "sis_tritmp.h"
253
254 #define SIS_STATES (VERT_UV0 | VERT_UV1)
255 #define TAG(x) x##_t0t1
256 #include "sis_tritmp.h"
257
258 #define SIS_STATES (VERT_SMOOTH | VERT_UV0 | VERT_UV1)
259 #define TAG(x) x##_gt0t1
260 #include "sis_tritmp.h"
261
262 #define SIS_STATES (VERT_W | VERT_UV0 | VERT_UV1)
263 #define TAG(x) x##_wt0t1
264 #include "sis_tritmp.h"
265
266 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_UV0 | VERT_UV1)
267 #define TAG(x) x##_gwt0t1
268 #include "sis_tritmp.h"
269
270 #define SIS_STATES (VERT_SPEC | VERT_UV0 | VERT_UV1)
271 #define TAG(x) x##_st0t1
272 #include "sis_tritmp.h"
273
274 #define SIS_STATES (VERT_SMOOTH | VERT_SPEC | VERT_UV0 | VERT_UV1)
275 #define TAG(x) x##_gst0t1
276 #include "sis_tritmp.h"
277
278 #define SIS_STATES (VERT_W | VERT_SPEC | VERT_UV0 | VERT_UV1)
279 #define TAG(x) x##_wst0t1
280 #include "sis_tritmp.h"
281
282 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC | VERT_UV0 | VERT_UV1)
283 #define TAG(x) x##_gwst0t1
284 #include "sis_tritmp.h"
285
286 /***********************************************************************
287 * Macros for t_dd_tritmp.h to draw basic primitives *
288 ***********************************************************************/
289
290 #define TRI( a, b, c ) \
291 do { \
292 if (DO_FALLBACK) \
293 smesa->draw_tri( smesa, a, b, c ); \
294 else \
295 sis_triangle( smesa, a, b, c ); \
296 } while (0)
297
298 #define QUAD( a, b, c, d ) \
299 do { \
300 if (DO_FALLBACK) { \
301 smesa->draw_tri( smesa, a, b, d ); \
302 smesa->draw_tri( smesa, b, c, d ); \
303 } else \
304 sis_quad( smesa, a, b, c, d ); \
305 } while (0)
306
307 #define LINE( v0, v1 ) \
308 do { \
309 if (DO_FALLBACK) \
310 smesa->draw_line( smesa, v0, v1 ); \
311 else \
312 sis_line( smesa, v0, v1 ); \
313 } while (0)
314
315 #define POINT( v0 ) \
316 do { \
317 if (DO_FALLBACK) \
318 smesa->draw_point( smesa, v0 ); \
319 else \
320 sis_point( smesa, v0 ); \
321 } while (0)
322
323 /***********************************************************************
324 * Build render functions from dd templates *
325 ***********************************************************************/
326
327 #define SIS_OFFSET_BIT 0x01
328 #define SIS_TWOSIDE_BIT 0x02
329 #define SIS_UNFILLED_BIT 0x04
330 #define SIS_FALLBACK_BIT 0x08
331 #define SIS_MAX_TRIFUNC 0x10
332
333
334 static struct {
335 tnl_points_func points;
336 tnl_line_func line;
337 tnl_triangle_func triangle;
338 tnl_quad_func quad;
339 } rast_tab[SIS_MAX_TRIFUNC];
340
341
342 #define DO_FALLBACK (IND & SIS_FALLBACK_BIT)
343 #define DO_OFFSET (IND & SIS_OFFSET_BIT)
344 #define DO_UNFILLED (IND & SIS_UNFILLED_BIT)
345 #define DO_TWOSIDE (IND & SIS_TWOSIDE_BIT)
346 #define DO_FLAT 0
347 #define DO_TRI 1
348 #define DO_QUAD 1
349 #define DO_LINE 1
350 #define DO_POINTS 1
351 #define DO_FULL_QUAD 1
352
353 #define HAVE_RGBA 1
354 #define HAVE_SPEC 1
355 #define HAVE_BACK_COLORS 0
356 #define HAVE_HW_FLATSHADE 1
357 #define VERTEX sisVertex
358 #define TAB rast_tab
359
360 #define DEPTH_SCALE smesa->depth_scale
361 #define UNFILLED_TRI unfilled_tri
362 #define UNFILLED_QUAD unfilled_quad
363 #define VERT_X(_v) _v->v.x
364 #define VERT_Y(_v) _v->v.y
365 #define VERT_Z(_v) _v->v.z
366 #define AREA_IS_CCW( a ) (a > 0)
367 #define GET_VERTEX(e) (smesa->verts + (e * smesa->vertex_size * sizeof(int)))
368
369 #define VERT_SET_RGBA( v, c ) \
370 do { \
371 sis_color_t *color = (sis_color_t *)&((v)->ui[coloroffset]); \
372 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
373 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
374 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
375 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
376 } while (0)
377
378 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
379
380 #define VERT_SET_SPEC( v0, c ) \
381 do { \
382 if (havespec) { \
383 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.red, (c)[0]); \
384 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.green, (c)[1]); \
385 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.blue, (c)[2]); \
386 } \
387 } while (0)
388 #define VERT_COPY_SPEC( v0, v1 ) \
389 do { \
390 if (havespec) { \
391 v0->v.specular.red = v1->v.specular.red; \
392 v0->v.specular.green = v1->v.specular.green; \
393 v0->v.specular.blue = v1->v.specular.blue; \
394 } \
395 } while (0)
396
397 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
398 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
399 #define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5]
400 #define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx]
401
402 #define LOCAL_VARS(n) \
403 sisContextPtr smesa = SIS_CONTEXT(ctx); \
404 GLuint color[n], spec[n]; \
405 GLuint coloroffset = (smesa->vertex_size == 4 ? 3 : 4); \
406 GLboolean havespec = (smesa->vertex_size == 4 ? 0 : 1); \
407 (void) color; (void) spec; (void) coloroffset; (void) havespec;
408
409 /***********************************************************************
410 * Helpers for rendering unfilled primitives *
411 ***********************************************************************/
412
413 #define RASTERIZE(x) if (smesa->hw_primitive != hw_prim[x]) \
414 sisRasterPrimitive( ctx, hw_prim[x] )
415 #define RENDER_PRIMITIVE smesa->render_primitive
416 #define IND SIS_FALLBACK_BIT
417 #define TAG(x) x
418 #include "tnl_dd/t_dd_unfilled.h"
419 #undef IND
420
421
422 /***********************************************************************
423 * Generate GL render functions *
424 ***********************************************************************/
425
426
427 #define IND (0)
428 #define TAG(x) x
429 #include "tnl_dd/t_dd_tritmp.h"
430
431 #define IND (SIS_OFFSET_BIT)
432 #define TAG(x) x##_offset
433 #include "tnl_dd/t_dd_tritmp.h"
434
435 #define IND (SIS_TWOSIDE_BIT)
436 #define TAG(x) x##_twoside
437 #include "tnl_dd/t_dd_tritmp.h"
438
439 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT)
440 #define TAG(x) x##_twoside_offset
441 #include "tnl_dd/t_dd_tritmp.h"
442
443 #define IND (SIS_UNFILLED_BIT)
444 #define TAG(x) x##_unfilled
445 #include "tnl_dd/t_dd_tritmp.h"
446
447 #define IND (SIS_OFFSET_BIT|SIS_UNFILLED_BIT)
448 #define TAG(x) x##_offset_unfilled
449 #include "tnl_dd/t_dd_tritmp.h"
450
451 #define IND (SIS_TWOSIDE_BIT|SIS_UNFILLED_BIT)
452 #define TAG(x) x##_twoside_unfilled
453 #include "tnl_dd/t_dd_tritmp.h"
454
455 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT|SIS_UNFILLED_BIT)
456 #define TAG(x) x##_twoside_offset_unfilled
457 #include "tnl_dd/t_dd_tritmp.h"
458
459 #define IND (SIS_FALLBACK_BIT)
460 #define TAG(x) x##_fallback
461 #include "tnl_dd/t_dd_tritmp.h"
462
463 #define IND (SIS_OFFSET_BIT|SIS_FALLBACK_BIT)
464 #define TAG(x) x##_offset_fallback
465 #include "tnl_dd/t_dd_tritmp.h"
466
467 #define IND (SIS_TWOSIDE_BIT|SIS_FALLBACK_BIT)
468 #define TAG(x) x##_twoside_fallback
469 #include "tnl_dd/t_dd_tritmp.h"
470
471 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT|SIS_FALLBACK_BIT)
472 #define TAG(x) x##_twoside_offset_fallback
473 #include "tnl_dd/t_dd_tritmp.h"
474
475 #define IND (SIS_UNFILLED_BIT|SIS_FALLBACK_BIT)
476 #define TAG(x) x##_unfilled_fallback
477 #include "tnl_dd/t_dd_tritmp.h"
478
479 #define IND (SIS_OFFSET_BIT|SIS_UNFILLED_BIT|SIS_FALLBACK_BIT)
480 #define TAG(x) x##_offset_unfilled_fallback
481 #include "tnl_dd/t_dd_tritmp.h"
482
483 #define IND (SIS_TWOSIDE_BIT|SIS_UNFILLED_BIT|SIS_FALLBACK_BIT)
484 #define TAG(x) x##_twoside_unfilled_fallback
485 #include "tnl_dd/t_dd_tritmp.h"
486
487 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT|SIS_UNFILLED_BIT| \
488 SIS_FALLBACK_BIT)
489 #define TAG(x) x##_twoside_offset_unfilled_fallback
490 #include "tnl_dd/t_dd_tritmp.h"
491
492
493 static void init_rast_tab( void )
494 {
495 init();
496 init_offset();
497 init_twoside();
498 init_twoside_offset();
499 init_unfilled();
500 init_offset_unfilled();
501 init_twoside_unfilled();
502 init_twoside_offset_unfilled();
503 init_fallback();
504 init_offset_fallback();
505 init_twoside_fallback();
506 init_twoside_offset_fallback();
507 init_unfilled_fallback();
508 init_offset_unfilled_fallback();
509 init_twoside_unfilled_fallback();
510 init_twoside_offset_unfilled_fallback();
511 }
512
513
514
515 /***********************************************************************
516 * Rasterization fallback helpers *
517 ***********************************************************************/
518
519
520 /* This code is hit only when a mix of accelerated and unaccelerated
521 * primitives are being drawn, and only for the unaccelerated
522 * primitives.
523 */
524
525 static void
526 sis_fallback_tri( sisContextPtr smesa,
527 sisVertex *v0,
528 sisVertex *v1,
529 sisVertex *v2 )
530 {
531 GLcontext *ctx = smesa->glCtx;
532 SWvertex v[3];
533 _swsetup_Translate( ctx, v0, &v[0] );
534 _swsetup_Translate( ctx, v1, &v[1] );
535 _swsetup_Translate( ctx, v2, &v[2] );
536 sisSpanRenderStart( ctx );
537 _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
538 sisSpanRenderFinish( ctx );
539 _swrast_flush( ctx );
540 }
541
542
543 static void
544 sis_fallback_line( sisContextPtr smesa,
545 sisVertex *v0,
546 sisVertex *v1 )
547 {
548 GLcontext *ctx = smesa->glCtx;
549 SWvertex v[2];
550 _swsetup_Translate( ctx, v0, &v[0] );
551 _swsetup_Translate( ctx, v1, &v[1] );
552 sisSpanRenderStart( ctx );
553 _swrast_Line( ctx, &v[0], &v[1] );
554 sisSpanRenderFinish( ctx );
555 _swrast_flush( ctx );
556 }
557
558
559 static void
560 sis_fallback_point( sisContextPtr smesa,
561 sisVertex *v0 )
562 {
563 GLcontext *ctx = smesa->glCtx;
564 SWvertex v[1];
565 _swsetup_Translate( ctx, v0, &v[0] );
566 sisSpanRenderStart( ctx );
567 _swrast_Point( ctx, &v[0] );
568 sisSpanRenderFinish( ctx );
569 _swrast_flush( ctx );
570 }
571
572
573
574 /**********************************************************************/
575 /* Render unclipped begin/end objects */
576 /**********************************************************************/
577
578 #define IND 0
579 #define V(x) (sisVertex *)(vertptr + (x * vertsize * sizeof(int)))
580 #define RENDER_POINTS( start, count ) \
581 for ( ; start < count ; start++) \
582 POINT( V(ELT(start)) )
583 #define RENDER_LINE( v0, v1 ) LINE( V(v0), V(v1) )
584 #define RENDER_TRI( v0, v1, v2 ) TRI( V(v0), V(v1), V(v2) )
585 #define RENDER_QUAD( v0, v1, v2, v3 ) QUAD( V(v0), V(v1), V(v2), V(v3) )
586 #define INIT(x) sisRenderPrimitive( ctx, x )
587 #undef LOCAL_VARS
588 #define LOCAL_VARS \
589 sisContextPtr smesa = SIS_CONTEXT(ctx); \
590 const GLuint vertsize = smesa->vertex_size; \
591 const char *vertptr = (char *)smesa->verts; \
592 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
593 (void) elt;
594 #define RESET_STIPPLE
595 #define RESET_OCCLUSION
596 #define PRESERVE_VB_DEFS
597 #define ELT(x) (x)
598 #define TAG(x) sis_##x##_verts
599 #include "tnl/t_vb_rendertmp.h"
600 #undef ELT
601 #undef TAG
602 #define TAG(x) sis_##x##_elts
603 #define ELT(x) elt[x]
604 #include "tnl/t_vb_rendertmp.h"
605
606
607 /**********************************************************************/
608 /* Choose render functions */
609 /**********************************************************************/
610
611 #define POINT_FALLBACK (DD_POINT_SMOOTH)
612 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
613 #define TRI_FALLBACK (DD_TRI_STIPPLE|DD_TRI_SMOOTH)
614 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
615 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
616 #define _SIS_NEW_RENDER_STATE (ANY_RASTER_FLAGS | ANY_FALLBACK_FLAGS)
617
618 static void sisChooseRenderState(GLcontext *ctx)
619 {
620 TNLcontext *tnl = TNL_CONTEXT(ctx);
621 sisContextPtr smesa = SIS_CONTEXT( ctx );
622 GLuint flags = ctx->_TriangleCaps;
623 GLuint index = 0;
624
625 if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) {
626
627 if (flags & ANY_RASTER_FLAGS) {
628 if (flags & DD_TRI_LIGHT_TWOSIDE) index |= SIS_TWOSIDE_BIT;
629 if (flags & DD_TRI_OFFSET) index |= SIS_OFFSET_BIT;
630 if (flags & DD_TRI_UNFILLED) index |= SIS_UNFILLED_BIT;
631 }
632
633 smesa->draw_point = sis_point;
634 smesa->draw_line = sis_line;
635 smesa->draw_tri = sis_triangle;
636 /* Hook in fallbacks for specific primitives.
637 */
638 if (flags & ANY_FALLBACK_FLAGS) {
639 if (flags & POINT_FALLBACK)
640 smesa->draw_point = sis_fallback_point;
641 if (flags & LINE_FALLBACK)
642 smesa->draw_line = sis_fallback_line;
643 if (flags & TRI_FALLBACK)
644 smesa->draw_tri = sis_fallback_tri;
645 index |= SIS_FALLBACK_BIT;
646 }
647 }
648
649 if (index != smesa->RenderIndex) {
650 smesa->RenderIndex = index;
651
652 tnl->Driver.Render.Points = rast_tab[index].points;
653 tnl->Driver.Render.Line = rast_tab[index].line;
654 tnl->Driver.Render.ClippedLine = rast_tab[index].line;
655 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
656 tnl->Driver.Render.Quad = rast_tab[index].quad;
657
658 if (index == 0) {
659 tnl->Driver.Render.PrimTabVerts = sis_render_tab_verts;
660 tnl->Driver.Render.PrimTabElts = sis_render_tab_elts;
661 tnl->Driver.Render.ClippedPolygon = sis_fast_clipped_poly;
662 } else {
663 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
664 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
665 tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
666 }
667 }
668 }
669
670 /**********************************************************************/
671 /* Multipass rendering for front buffering */
672 /**********************************************************************/
673 static GLboolean multipass_cliprect( GLcontext *ctx, GLuint pass )
674 {
675 sisContextPtr smesa = SIS_CONTEXT( ctx );
676
677 if (pass >= smesa->driDrawable->numClipRects) {
678 return GL_FALSE;
679 } else {
680 GLint x1, y1, x2, y2;
681
682 x1 = smesa->driDrawable->pClipRects[pass].x1 - smesa->driDrawable->x;
683 y1 = smesa->driDrawable->pClipRects[pass].y1 - smesa->driDrawable->y;
684 x2 = smesa->driDrawable->pClipRects[pass].x2 - smesa->driDrawable->x;
685 y2 = smesa->driDrawable->pClipRects[pass].y2 - smesa->driDrawable->y;
686
687 if (ctx->Scissor.Enabled) {
688 GLint scisy1 = Y_FLIP(ctx->Scissor.Y + ctx->Scissor.Height - 1);
689 GLint scisy2 = Y_FLIP(ctx->Scissor.Y);
690
691 if (ctx->Scissor.X > x1)
692 x1 = ctx->Scissor.X;
693 if (scisy1 > y1)
694 y1 = scisy1;
695 if (ctx->Scissor.X + ctx->Scissor.Width - 1 < x2)
696 x2 = ctx->Scissor.X + ctx->Scissor.Width - 1;
697 if (scisy2 < y2)
698 y2 = scisy2;
699 }
700
701 MMIO(REG_3D_ClipTopBottom, y1 << 13 | y2);
702 MMIO(REG_3D_ClipLeftRight, x1 << 13 | x2);
703 /* Mark that we clobbered these registers */
704 smesa->GlobalFlag |= GFLAG_CLIPPING;
705 return GL_TRUE;
706 }
707 }
708
709
710
711 /**********************************************************************/
712 /* Validate state at pipeline start */
713 /**********************************************************************/
714
715 static void sisRunPipeline( GLcontext *ctx )
716 {
717 sisContextPtr smesa = SIS_CONTEXT( ctx );
718
719 if (!smesa->Fallback && smesa->NewGLState) {
720 if (smesa->NewGLState & _NEW_TEXTURE) {
721 SIS_FIREVERTICES(smesa);
722 sisUpdateTextureState(ctx);
723 }
724
725 if (smesa->NewGLState & _SIS_NEW_RENDER_STATE)
726 sisChooseRenderState( ctx );
727
728 smesa->NewGLState = 0;
729 }
730
731 _tnl_run_pipeline( ctx );
732
733 /* XXX: If we put flushing in sis_state.c and friends, we can avoid this.
734 * Is it worth it?
735 */
736 SIS_FIREVERTICES(smesa);
737 }
738
739 /**********************************************************************/
740 /* High level hooks for t_vb_render.c */
741 /**********************************************************************/
742
743 /* This is called when Mesa switches between rendering triangle
744 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
745 * and lines, points and bitmaps.
746 */
747
748 static void sisRasterPrimitive( GLcontext *ctx, GLuint hwprim )
749 {
750 sisContextPtr smesa = SIS_CONTEXT(ctx);
751 if (smesa->hw_primitive != hwprim) {
752 SIS_FIREVERTICES(smesa);
753 smesa->hw_primitive = hwprim;
754 smesa->AGPParseSet &= ~(MASK_PsDataType | MASK_PsShadingMode);
755 smesa->dwPrimitiveSet &= ~(MASK_DrawPrimitiveCommand |
756 MASK_SetFirePosition | MASK_ShadingMode);
757 smesa->AGPParseSet |= hw_prim_agp_type[hwprim];
758 smesa->dwPrimitiveSet |= hwprim | hw_prim_mmio_fire[hwprim];
759 if (ctx->Light.ShadeModel == GL_FLAT) {
760 smesa->AGPParseSet |= hw_prim_agp_shade[hwprim];
761 smesa->dwPrimitiveSet |= hw_prim_mmio_shade[hwprim];
762 } else {
763 smesa->AGPParseSet |= MASK_PsShadingSmooth;
764 smesa->dwPrimitiveSet |= SHADE_GOURAUD;
765 }
766 }
767 }
768
769 static void sisRenderPrimitive( GLcontext *ctx, GLenum prim )
770 {
771 sisContextPtr smesa = SIS_CONTEXT(ctx);
772
773 smesa->render_primitive = prim;
774
775 if (prim >= GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
776 return;
777 sisRasterPrimitive( ctx, hw_prim[prim] );
778 }
779
780 #define EMIT_ATTR( ATTR, STYLE) \
781 do { \
782 smesa->vertex_attrs[smesa->vertex_attr_count].attrib = (ATTR); \
783 smesa->vertex_attrs[smesa->vertex_attr_count].format = (STYLE); \
784 smesa->vertex_attr_count++; \
785 } while (0)
786
787 #define EMIT_PAD( N ) \
788 do { \
789 smesa->vertex_attrs[smesa->vertex_attr_count].attrib = 0; \
790 smesa->vertex_attrs[smesa->vertex_attr_count].format = EMIT_PAD; \
791 smesa->vertex_attrs[smesa->vertex_attr_count].offset = (N); \
792 smesa->vertex_attr_count++; \
793 } while (0)
794
795 #define SIS_TCL_STATE_BITS \
796 (_TNL_BITS_TEX_ANY | _TNL_BIT_COLOR1 | _TNL_BIT_FOG)
797
798 static void sisRenderStart( GLcontext *ctx )
799 {
800 TNLcontext *tnl = TNL_CONTEXT(ctx);
801 sisContextPtr smesa = SIS_CONTEXT(ctx);
802 struct vertex_buffer *VB = &tnl->vb;
803 GLuint index = tnl->render_inputs;
804 GLuint AGPParseSet = smesa->AGPParseSet;
805 GLboolean tex_fallback = GL_FALSE;
806
807 if (ctx->DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT &&
808 smesa->driDrawable->numClipRects != 0)
809 {
810 multipass_cliprect(ctx, 0);
811 if (smesa->driDrawable->numClipRects > 1)
812 tnl->Driver.Render.Multipass = multipass_cliprect;
813 else
814 tnl->Driver.Render.Multipass = NULL;
815 } else {
816 tnl->Driver.Render.Multipass = NULL;
817 }
818
819 /* Important:
820 */
821 VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
822 smesa->vertex_attr_count = 0;
823
824 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to build up a
825 * hardware vertex.
826 */
827
828 AGPParseSet &= ~(MASK_VertexDWSize | MASK_VertexDataFormat);
829 AGPParseSet |= SiS_PS_HAS_XYZ | SiS_PS_HAS_DIFFUSE;
830 if (index & _TNL_BITS_TEX_ANY) {
831 EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_4F_VIEWPORT);
832 AGPParseSet |= SiS_PS_HAS_W;
833 } else {
834 EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_3F_VIEWPORT);
835 }
836
837 EMIT_ATTR(_TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA);
838
839 if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
840 AGPParseSet |= SiS_PS_HAS_SPECULAR;
841
842 if (index & _TNL_BIT_COLOR1) {
843 EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR);
844 } else {
845 EMIT_PAD(3);
846 }
847
848 if (index & _TNL_BIT_FOG)
849 EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1UB_1F);
850 else
851 EMIT_PAD(1);
852 }
853
854 /* projective textures are not supported by the hardware */
855 if (index & _TNL_BIT_TEX(0)) {
856 if (VB->TexCoordPtr[0]->size > 2)
857 tex_fallback = GL_TRUE;
858 EMIT_ATTR(_TNL_ATTRIB_TEX0, EMIT_2F);
859 AGPParseSet |= SiS_PS_HAS_UV0;
860 }
861 if (index & _TNL_BIT_TEX(1)) {
862 if (VB->TexCoordPtr[1]->size > 2)
863 tex_fallback = GL_TRUE;
864 EMIT_ATTR(_TNL_ATTRIB_TEX1, EMIT_2F);
865 AGPParseSet |= SiS_PS_HAS_UV1;
866 }
867 FALLBACK(smesa, SIS_FALLBACK_TEXTURE, tex_fallback);
868
869 if (smesa->last_tcl_state != index) {
870 smesa->AGPParseSet = AGPParseSet;
871
872 smesa->vertex_size = _tnl_install_attrs( ctx, smesa->vertex_attrs,
873 smesa->vertex_attr_count, smesa->hw_viewport, 0 );
874
875 smesa->vertex_size >>= 2;
876 smesa->AGPParseSet |= smesa->vertex_size << 28;
877 }
878 }
879
880 static void sisRenderFinish( GLcontext *ctx )
881 {
882 }
883
884 /**********************************************************************/
885 /* AGP/PCI vertex submission */
886 /**********************************************************************/
887
888 void
889 sisFlushPrimsLocked(sisContextPtr smesa)
890 {
891 if (smesa->vb_cur == smesa->vb_last)
892 return;
893
894 sisUpdateHWState(smesa->glCtx);
895
896 if (smesa->using_agp) {
897 mWait3DCmdQueue(8);
898 mEndPrimitive();
899 MMIO(REG_3D_AGPCmBase, (smesa->vb_last - smesa->vb) +
900 smesa->vb_agp_offset);
901 MMIO(REG_3D_AGPTtDwNum, ((smesa->vb_cur - smesa->vb_last) / 4) |
902 0x50000000);
903 MMIO(REG_3D_ParsingSet, smesa->AGPParseSet);
904 MMIO(REG_3D_AGPCmFire, (GLint)(-1));
905 mEndPrimitive();
906 } else {
907 int mmio_index = 0, incr = 0;
908 void (*sis_emit_func)(sisContextPtr smesa, char *verts) = NULL;
909
910 if (smesa->AGPParseSet & MASK_PsShadingSmooth)
911 mmio_index |= VERT_SMOOTH;
912 if (smesa->AGPParseSet & SiS_PS_HAS_SPECULAR)
913 mmio_index |= VERT_SPEC;
914 if (smesa->AGPParseSet & SiS_PS_HAS_W)
915 mmio_index |= VERT_W;
916 if (smesa->AGPParseSet & SiS_PS_HAS_UV0)
917 mmio_index |= VERT_UV0;
918 if (smesa->AGPParseSet & SiS_PS_HAS_UV1)
919 mmio_index |= VERT_UV1;
920
921 switch (smesa->AGPParseSet & MASK_PsDataType) {
922 case MASK_PsPointList:
923 incr = smesa->vertex_size * 4;
924 sis_emit_func = sis_point_func_mmio[mmio_index];
925 break;
926 case MASK_PsLineList:
927 incr = smesa->vertex_size * 4 * 2;
928 sis_emit_func = sis_line_func_mmio[mmio_index];
929 break;
930 case MASK_PsTriangleList:
931 incr = smesa->vertex_size * 4 * 3;
932 sis_emit_func = sis_tri_func_mmio[mmio_index];
933 break;
934 }
935
936 mWait3DCmdQueue(1);
937 MMIO(REG_3D_PrimitiveSet, smesa->dwPrimitiveSet);
938 while (smesa->vb_last < smesa->vb_cur) {
939 sis_emit_func(smesa, smesa->vb_last);
940 smesa->vb_last += incr;
941 }
942 mWait3DCmdQueue(1);
943 mEndPrimitive();
944
945 /* With PCI, we can just start writing to the start of the VB again. */
946 smesa->vb_cur = smesa->vb;
947 }
948 smesa->vb_last = smesa->vb_cur;
949 }
950
951 void sisFlushPrims(sisContextPtr smesa)
952 {
953 LOCK_HARDWARE();
954 sisFlushPrimsLocked(smesa);
955 UNLOCK_HARDWARE();
956 }
957
958 /**********************************************************************/
959 /* Transition to/from hardware rasterization. */
960 /**********************************************************************/
961
962 void sisFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
963 {
964 TNLcontext *tnl = TNL_CONTEXT(ctx);
965 sisContextPtr smesa = SIS_CONTEXT(ctx);
966 GLuint oldfallback = smesa->Fallback;
967
968 if (mode) {
969 smesa->Fallback |= bit;
970 if (oldfallback == 0) {
971 SIS_FIREVERTICES(smesa);
972 _swsetup_Wakeup( ctx );
973 smesa->RenderIndex = ~0;
974 }
975 }
976 else {
977 smesa->Fallback &= ~bit;
978 if (oldfallback == bit) {
979 _swrast_flush( ctx );
980 tnl->Driver.Render.Start = sisRenderStart;
981 tnl->Driver.Render.PrimitiveNotify = sisRenderPrimitive;
982 tnl->Driver.Render.Finish = sisRenderFinish;
983
984 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
985 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
986 tnl->Driver.Render.Interp = _tnl_interp;
987
988 _tnl_invalidate_vertex_state( ctx, ~0 );
989 _tnl_invalidate_vertices( ctx, ~0 );
990 _tnl_install_attrs( ctx,
991 smesa->vertex_attrs,
992 smesa->vertex_attr_count,
993 smesa->hw_viewport, 0 );
994
995 smesa->NewGLState |= _SIS_NEW_RENDER_STATE;
996 }
997 }
998 }
999
1000
1001 /**********************************************************************/
1002 /* Initialization. */
1003 /**********************************************************************/
1004
1005 void sisInitTriFuncs( GLcontext *ctx )
1006 {
1007 sisContextPtr smesa = SIS_CONTEXT(ctx);
1008 TNLcontext *tnl = TNL_CONTEXT(ctx);
1009 static int firsttime = 1;
1010
1011 if (firsttime) {
1012 init_rast_tab();
1013 firsttime = 0;
1014
1015 sis_vert_init_none();
1016 sis_vert_init_g();
1017 sis_vert_init_w();
1018 sis_vert_init_gw();
1019 sis_vert_init_s();
1020 sis_vert_init_gs();
1021 sis_vert_init_ws();
1022 sis_vert_init_gws();
1023 sis_vert_init_t0();
1024 sis_vert_init_gt0();
1025 sis_vert_init_wt0();
1026 sis_vert_init_gwt0();
1027 sis_vert_init_st0();
1028 sis_vert_init_gst0();
1029 sis_vert_init_wst0();
1030 sis_vert_init_gwst0();
1031 sis_vert_init_t1();
1032 sis_vert_init_gt1();
1033 sis_vert_init_wt1();
1034 sis_vert_init_gwt1();
1035 sis_vert_init_st1();
1036 sis_vert_init_gst1();
1037 sis_vert_init_wst1();
1038 sis_vert_init_gwst1();
1039 sis_vert_init_t0t1();
1040 sis_vert_init_gt0t1();
1041 sis_vert_init_wt0t1();
1042 sis_vert_init_gwt0t1();
1043 sis_vert_init_st0t1();
1044 sis_vert_init_gst0t1();
1045 sis_vert_init_wst0t1();
1046 sis_vert_init_gwst0t1();
1047 }
1048
1049 if (driQueryOptionb(&smesa->optionCache, "fallback_force"))
1050 sisFallback(ctx, SIS_FALLBACK_FORCE, 1);
1051 else
1052 sisFallback(ctx, SIS_FALLBACK_FORCE, 0);
1053
1054 smesa->RenderIndex = ~0;
1055 smesa->NewGLState |= _SIS_NEW_RENDER_STATE;
1056
1057 tnl->Driver.RunPipeline = sisRunPipeline;
1058 tnl->Driver.Render.Start = sisRenderStart;
1059 tnl->Driver.Render.Finish = sisRenderFinish;
1060 tnl->Driver.Render.PrimitiveNotify = sisRenderPrimitive;
1061 tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
1062
1063 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1064 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1065 tnl->Driver.Render.Interp = _tnl_interp;
1066
1067 _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
1068 (6 + 2*ctx->Const.MaxTextureUnits) * sizeof(GLfloat) );
1069
1070 smesa->verts = (char *)tnl->clipspace.vertex_buf;
1071 }