1 /* $XFree86*/ /* -*- c-basic-offset: 3 -*- */
2 /**************************************************************************
4 Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
5 Copyright 2003 Eric Anholt
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:
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
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.
27 **************************************************************************/
31 * Sung-Ching Lin <sclin@sis.com.tw>
32 * Eric Anholt <anholt@FreeBSD.org>
40 #include "swrast/swrast.h"
41 #include "swrast_setup/swrast_setup.h"
42 #include "tnl/t_context.h"
43 #include "tnl/t_pipeline.h"
45 #include "sis_context.h"
47 #include "sis_state.h"
50 #include "sis_alloc.h"
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 */
66 static const GLuint hw_prim_mmio_fire
[OP_3D_TRIANGLE_DRAW
+1] = {
72 static const GLuint hw_prim_mmio_shade
[OP_3D_TRIANGLE_DRAW
+1] = {
78 static const GLuint hw_prim_agp_type
[OP_3D_TRIANGLE_DRAW
+1] = {
84 static const GLuint hw_prim_agp_shade
[OP_3D_TRIANGLE_DRAW
+1] = {
90 static void sisRasterPrimitive( GLcontext
*ctx
, GLuint hwprim
);
91 static void sisRenderPrimitive( GLcontext
*ctx
, GLenum prim
);
93 /***********************************************************************
94 * Emit primitives as inline vertices *
95 ***********************************************************************/
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) )
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
110 #define TAG(x) sis_##x
111 #include "tnl_dd/t_dd_triemit.h"
115 /***********************************************************************
116 * Dispatch vertices to hardware through MMIO *
117 ***********************************************************************/
119 /* The ARGB write of the last vertex of the primitive fires the 3d engine, so
120 * save it until the end.
122 #define SIS_MMIO_WRITE_VERTEX(_v, i, lastvert) \
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++]); \
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++]); \
141 if (lastvert || (SIS_STATES & VERT_SMOOTH)) \
142 MMIO(REG_3D_TSARGBa+(i)*0x30, __color); \
145 #define MMIO_VERT_REG_COUNT 10
147 #define VERT_SMOOTH 0x01
149 #define VERT_SPEC 0x04
150 #define VERT_UV0 0x08
151 #define VERT_UV1 0x10
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];
158 #define SIS_STATES (0)
159 #define TAG(x) x##_none
160 #include "sis_tritmp.h"
162 #define SIS_STATES (VERT_SMOOTH)
164 #include "sis_tritmp.h"
166 #define SIS_STATES (VERT_W)
168 #include "sis_tritmp.h"
170 #define SIS_STATES (VERT_SMOOTH | VERT_W)
171 #define TAG(x) x##_gw
172 #include "sis_tritmp.h"
174 #define SIS_STATES (VERT_SPEC)
176 #include "sis_tritmp.h"
178 #define SIS_STATES (VERT_SMOOTH | VERT_SPEC)
179 #define TAG(x) x##_gs
180 #include "sis_tritmp.h"
182 #define SIS_STATES (VERT_W | VERT_SPEC)
183 #define TAG(x) x##_ws
184 #include "sis_tritmp.h"
186 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC)
187 #define TAG(x) x##_gws
188 #include "sis_tritmp.h"
190 #define SIS_STATES (VERT_UV0)
191 #define TAG(x) x##_t0
192 #include "sis_tritmp.h"
194 #define SIS_STATES (VERT_SMOOTH | VERT_UV0)
195 #define TAG(x) x##_gt0
196 #include "sis_tritmp.h"
198 #define SIS_STATES (VERT_W | VERT_UV0)
199 #define TAG(x) x##_wt0
200 #include "sis_tritmp.h"
202 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_UV0)
203 #define TAG(x) x##_gwt0
204 #include "sis_tritmp.h"
206 #define SIS_STATES (VERT_SPEC | VERT_UV0)
207 #define TAG(x) x##_st0
208 #include "sis_tritmp.h"
210 #define SIS_STATES (VERT_SMOOTH | VERT_SPEC | VERT_UV0)
211 #define TAG(x) x##_gst0
212 #include "sis_tritmp.h"
214 #define SIS_STATES (VERT_W | VERT_SPEC | VERT_UV0)
215 #define TAG(x) x##_wst0
216 #include "sis_tritmp.h"
218 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC | VERT_UV0)
219 #define TAG(x) x##_gwst0
220 #include "sis_tritmp.h"
222 #define SIS_STATES (VERT_UV1)
223 #define TAG(x) x##_t1
224 #include "sis_tritmp.h"
226 #define SIS_STATES (VERT_SMOOTH | VERT_UV1)
227 #define TAG(x) x##_gt1
228 #include "sis_tritmp.h"
230 #define SIS_STATES (VERT_W | VERT_UV1)
231 #define TAG(x) x##_wt1
232 #include "sis_tritmp.h"
234 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_UV1)
235 #define TAG(x) x##_gwt1
236 #include "sis_tritmp.h"
238 #define SIS_STATES (VERT_SPEC | VERT_UV1)
239 #define TAG(x) x##_st1
240 #include "sis_tritmp.h"
242 #define SIS_STATES (VERT_SMOOTH | VERT_SPEC | VERT_UV1)
243 #define TAG(x) x##_gst1
244 #include "sis_tritmp.h"
246 #define SIS_STATES (VERT_W | VERT_SPEC | VERT_UV1)
247 #define TAG(x) x##_wst1
248 #include "sis_tritmp.h"
250 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC | VERT_UV1)
251 #define TAG(x) x##_gwst1
252 #include "sis_tritmp.h"
254 #define SIS_STATES (VERT_UV0 | VERT_UV1)
255 #define TAG(x) x##_t0t1
256 #include "sis_tritmp.h"
258 #define SIS_STATES (VERT_SMOOTH | VERT_UV0 | VERT_UV1)
259 #define TAG(x) x##_gt0t1
260 #include "sis_tritmp.h"
262 #define SIS_STATES (VERT_W | VERT_UV0 | VERT_UV1)
263 #define TAG(x) x##_wt0t1
264 #include "sis_tritmp.h"
266 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_UV0 | VERT_UV1)
267 #define TAG(x) x##_gwt0t1
268 #include "sis_tritmp.h"
270 #define SIS_STATES (VERT_SPEC | VERT_UV0 | VERT_UV1)
271 #define TAG(x) x##_st0t1
272 #include "sis_tritmp.h"
274 #define SIS_STATES (VERT_SMOOTH | VERT_SPEC | VERT_UV0 | VERT_UV1)
275 #define TAG(x) x##_gst0t1
276 #include "sis_tritmp.h"
278 #define SIS_STATES (VERT_W | VERT_SPEC | VERT_UV0 | VERT_UV1)
279 #define TAG(x) x##_wst0t1
280 #include "sis_tritmp.h"
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"
286 /***********************************************************************
287 * Macros for t_dd_tritmp.h to draw basic primitives *
288 ***********************************************************************/
290 #define TRI( a, b, c ) \
293 smesa->draw_tri( smesa, a, b, c ); \
295 sis_triangle( smesa, a, b, c ); \
298 #define QUAD( a, b, c, d ) \
301 smesa->draw_tri( smesa, a, b, d ); \
302 smesa->draw_tri( smesa, b, c, d ); \
304 sis_quad( smesa, a, b, c, d ); \
307 #define LINE( v0, v1 ) \
310 smesa->draw_line( smesa, v0, v1 ); \
312 sis_line( smesa, v0, v1 ); \
315 #define POINT( v0 ) \
318 smesa->draw_point( smesa, v0 ); \
320 sis_point( smesa, v0 ); \
323 /***********************************************************************
324 * Build render functions from dd templates *
325 ***********************************************************************/
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
335 tnl_points_func points
;
337 tnl_triangle_func triangle
;
339 } rast_tab
[SIS_MAX_TRIFUNC
];
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)
351 #define DO_FULL_QUAD 1
355 #define HAVE_BACK_COLORS 0
356 #define HAVE_HW_FLATSHADE 1
357 #define VERTEX sisVertex
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)))
369 #define VERT_SET_RGBA( v, c ) \
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]); \
378 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
380 #define VERT_SET_SPEC( v0, c ) \
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]); \
388 #define VERT_COPY_SPEC( v0, v1 ) \
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; \
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]
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;
409 /***********************************************************************
410 * Helpers for rendering unfilled primitives *
411 ***********************************************************************/
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
418 #include "tnl_dd/t_dd_unfilled.h"
422 /***********************************************************************
423 * Generate GL render functions *
424 ***********************************************************************/
429 #include "tnl_dd/t_dd_tritmp.h"
431 #define IND (SIS_OFFSET_BIT)
432 #define TAG(x) x##_offset
433 #include "tnl_dd/t_dd_tritmp.h"
435 #define IND (SIS_TWOSIDE_BIT)
436 #define TAG(x) x##_twoside
437 #include "tnl_dd/t_dd_tritmp.h"
439 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT)
440 #define TAG(x) x##_twoside_offset
441 #include "tnl_dd/t_dd_tritmp.h"
443 #define IND (SIS_UNFILLED_BIT)
444 #define TAG(x) x##_unfilled
445 #include "tnl_dd/t_dd_tritmp.h"
447 #define IND (SIS_OFFSET_BIT|SIS_UNFILLED_BIT)
448 #define TAG(x) x##_offset_unfilled
449 #include "tnl_dd/t_dd_tritmp.h"
451 #define IND (SIS_TWOSIDE_BIT|SIS_UNFILLED_BIT)
452 #define TAG(x) x##_twoside_unfilled
453 #include "tnl_dd/t_dd_tritmp.h"
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"
459 #define IND (SIS_FALLBACK_BIT)
460 #define TAG(x) x##_fallback
461 #include "tnl_dd/t_dd_tritmp.h"
463 #define IND (SIS_OFFSET_BIT|SIS_FALLBACK_BIT)
464 #define TAG(x) x##_offset_fallback
465 #include "tnl_dd/t_dd_tritmp.h"
467 #define IND (SIS_TWOSIDE_BIT|SIS_FALLBACK_BIT)
468 #define TAG(x) x##_twoside_fallback
469 #include "tnl_dd/t_dd_tritmp.h"
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"
475 #define IND (SIS_UNFILLED_BIT|SIS_FALLBACK_BIT)
476 #define TAG(x) x##_unfilled_fallback
477 #include "tnl_dd/t_dd_tritmp.h"
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"
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"
487 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT|SIS_UNFILLED_BIT| \
489 #define TAG(x) x##_twoside_offset_unfilled_fallback
490 #include "tnl_dd/t_dd_tritmp.h"
493 static void init_rast_tab( void )
498 init_twoside_offset();
500 init_offset_unfilled();
501 init_twoside_unfilled();
502 init_twoside_offset_unfilled();
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();
515 /***********************************************************************
516 * Rasterization fallback helpers *
517 ***********************************************************************/
520 /* This code is hit only when a mix of accelerated and unaccelerated
521 * primitives are being drawn, and only for the unaccelerated
526 sis_fallback_tri( sisContextPtr smesa
,
531 GLcontext
*ctx
= smesa
->glCtx
;
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
);
544 sis_fallback_line( sisContextPtr smesa
,
548 GLcontext
*ctx
= smesa
->glCtx
;
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
);
560 sis_fallback_point( sisContextPtr smesa
,
563 GLcontext
*ctx
= smesa
->glCtx
;
565 _swsetup_Translate( ctx
, v0
, &v
[0] );
566 sisSpanRenderStart( ctx
);
567 _swrast_Point( ctx
, &v
[0] );
568 sisSpanRenderFinish( ctx
);
569 _swrast_flush( ctx
);
574 /**********************************************************************/
575 /* Render unclipped begin/end objects */
576 /**********************************************************************/
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 )
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; \
594 #define RESET_STIPPLE
595 #define RESET_OCCLUSION
596 #define PRESERVE_VB_DEFS
598 #define TAG(x) sis_##x##_verts
599 #include "tnl/t_vb_rendertmp.h"
602 #define TAG(x) sis_##x##_elts
603 #define ELT(x) elt[x]
604 #include "tnl/t_vb_rendertmp.h"
607 /**********************************************************************/
608 /* Choose render functions */
609 /**********************************************************************/
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)
618 static void sisChooseRenderState(GLcontext
*ctx
)
620 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
621 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
622 GLuint flags
= ctx
->_TriangleCaps
;
628 if (flags
& (ANY_RASTER_FLAGS
|ANY_FALLBACK_FLAGS
)) {
630 if (flags
& ANY_RASTER_FLAGS
) {
631 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= SIS_TWOSIDE_BIT
;
632 if (flags
& DD_TRI_OFFSET
) index
|= SIS_OFFSET_BIT
;
633 if (flags
& DD_TRI_UNFILLED
) index
|= SIS_UNFILLED_BIT
;
636 smesa
->draw_point
= sis_point
;
637 smesa
->draw_line
= sis_line
;
638 smesa
->draw_tri
= sis_triangle
;
639 /* Hook in fallbacks for specific primitives.
641 if (flags
& ANY_FALLBACK_FLAGS
) {
642 if (flags
& POINT_FALLBACK
)
643 smesa
->draw_point
= sis_fallback_point
;
644 if (flags
& LINE_FALLBACK
)
645 smesa
->draw_line
= sis_fallback_line
;
646 if (flags
& TRI_FALLBACK
)
647 smesa
->draw_tri
= sis_fallback_tri
;
648 index
|= SIS_FALLBACK_BIT
;
652 if (index
!= smesa
->RenderIndex
) {
653 smesa
->RenderIndex
= index
;
655 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
656 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
657 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
658 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
659 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
662 tnl
->Driver
.Render
.PrimTabVerts
= sis_render_tab_verts
;
663 tnl
->Driver
.Render
.PrimTabElts
= sis_render_tab_elts
;
664 tnl
->Driver
.Render
.ClippedPolygon
= sis_fast_clipped_poly
;
666 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
667 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
668 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
673 /**********************************************************************/
674 /* Multipass rendering for front buffering */
675 /**********************************************************************/
676 static GLboolean
multipass_cliprect( GLcontext
*ctx
, GLuint pass
)
678 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
680 if (pass
>= smesa
->driDrawable
->numClipRects
) {
683 GLint x1
, y1
, x2
, y2
;
685 x1
= smesa
->driDrawable
->pClipRects
[pass
].x1
- smesa
->driDrawable
->x
;
686 y1
= smesa
->driDrawable
->pClipRects
[pass
].y1
- smesa
->driDrawable
->y
;
687 x2
= smesa
->driDrawable
->pClipRects
[pass
].x2
- smesa
->driDrawable
->x
;
688 y2
= smesa
->driDrawable
->pClipRects
[pass
].y2
- smesa
->driDrawable
->y
;
690 if (ctx
->Scissor
.Enabled
) {
691 GLint scisy1
= Y_FLIP(ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
- 1);
692 GLint scisy2
= Y_FLIP(ctx
->Scissor
.Y
);
694 if (ctx
->Scissor
.X
> x1
)
698 if (ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1 < x2
)
699 x2
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
704 MMIO(REG_3D_ClipTopBottom
, y1
<< 13 | y2
);
705 MMIO(REG_3D_ClipLeftRight
, x1
<< 13 | x2
);
706 /* Mark that we clobbered these registers */
707 smesa
->GlobalFlag
|= GFLAG_CLIPPING
;
714 /**********************************************************************/
715 /* Validate state at pipeline start */
716 /**********************************************************************/
718 static void sisRunPipeline( GLcontext
*ctx
)
720 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
722 if (smesa
->NewGLState
) {
723 SIS_FIREVERTICES(smesa
);
724 if (smesa
->NewGLState
& _NEW_TEXTURE
) {
725 sisUpdateTextureState(ctx
);
728 if (smesa
->NewGLState
& _SIS_NEW_RENDER_STATE
)
729 sisChooseRenderState( ctx
);
731 smesa
->NewGLState
= 0;
734 _tnl_run_pipeline( ctx
);
736 /* XXX: If we put flushing in sis_state.c and friends, we can avoid this.
739 SIS_FIREVERTICES(smesa
);
742 /**********************************************************************/
743 /* High level hooks for t_vb_render.c */
744 /**********************************************************************/
746 /* This is called when Mesa switches between rendering triangle
747 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
748 * and lines, points and bitmaps.
751 static void sisRasterPrimitive( GLcontext
*ctx
, GLuint hwprim
)
753 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
754 if (smesa
->hw_primitive
!= hwprim
) {
755 SIS_FIREVERTICES(smesa
);
756 smesa
->hw_primitive
= hwprim
;
757 smesa
->AGPParseSet
&= ~(MASK_PsDataType
| MASK_PsShadingMode
);
758 smesa
->dwPrimitiveSet
&= ~(MASK_DrawPrimitiveCommand
|
759 MASK_SetFirePosition
| MASK_ShadingMode
);
760 smesa
->AGPParseSet
|= hw_prim_agp_type
[hwprim
];
761 smesa
->dwPrimitiveSet
|= hwprim
| hw_prim_mmio_fire
[hwprim
];
762 if (ctx
->Light
.ShadeModel
== GL_FLAT
) {
763 smesa
->AGPParseSet
|= hw_prim_agp_shade
[hwprim
];
764 smesa
->dwPrimitiveSet
|= hw_prim_mmio_shade
[hwprim
];
766 smesa
->AGPParseSet
|= MASK_PsShadingSmooth
;
767 smesa
->dwPrimitiveSet
|= SHADE_GOURAUD
;
772 static void sisRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
774 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
776 smesa
->render_primitive
= prim
;
778 if (prim
>= GL_TRIANGLES
&& (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
780 sisRasterPrimitive( ctx
, hw_prim
[prim
] );
783 #define EMIT_ATTR( ATTR, STYLE) \
785 smesa->vertex_attrs[smesa->vertex_attr_count].attrib = (ATTR); \
786 smesa->vertex_attrs[smesa->vertex_attr_count].format = (STYLE); \
787 smesa->vertex_attr_count++; \
790 #define EMIT_PAD( N ) \
792 smesa->vertex_attrs[smesa->vertex_attr_count].attrib = 0; \
793 smesa->vertex_attrs[smesa->vertex_attr_count].format = EMIT_PAD; \
794 smesa->vertex_attrs[smesa->vertex_attr_count].offset = (N); \
795 smesa->vertex_attr_count++; \
798 #define SIS_TCL_STATE_BITS \
799 (_TNL_BITS_TEX_ANY | _TNL_BIT_COLOR1 | _TNL_BIT_FOG)
801 static void sisRenderStart( GLcontext
*ctx
)
803 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
804 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
805 struct vertex_buffer
*VB
= &tnl
->vb
;
806 GLuint index
= tnl
->render_inputs
;
807 GLuint AGPParseSet
= smesa
->AGPParseSet
;
808 GLboolean tex_fallback
= GL_FALSE
;
810 if (ctx
->DrawBuffer
->_ColorDrawBufferMask
[0] == BUFFER_BIT_FRONT_LEFT
&&
811 smesa
->driDrawable
->numClipRects
!= 0)
813 multipass_cliprect(ctx
, 0);
814 if (smesa
->driDrawable
->numClipRects
> 1)
815 tnl
->Driver
.Render
.Multipass
= multipass_cliprect
;
817 tnl
->Driver
.Render
.Multipass
= NULL
;
819 tnl
->Driver
.Render
.Multipass
= NULL
;
824 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->NdcPtr
;
825 smesa
->vertex_attr_count
= 0;
827 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to build up a
831 AGPParseSet
&= ~(MASK_VertexDWSize
| MASK_VertexDataFormat
);
832 AGPParseSet
|= SiS_PS_HAS_XYZ
| SiS_PS_HAS_DIFFUSE
;
833 if (index
& _TNL_BITS_TEX_ANY
) {
834 EMIT_ATTR(_TNL_ATTRIB_POS
, EMIT_4F_VIEWPORT
);
835 AGPParseSet
|= SiS_PS_HAS_W
;
837 EMIT_ATTR(_TNL_ATTRIB_POS
, EMIT_3F_VIEWPORT
);
840 EMIT_ATTR(_TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_BGRA
);
842 if (index
& (_TNL_BIT_COLOR1
|_TNL_BIT_FOG
)) {
843 AGPParseSet
|= SiS_PS_HAS_SPECULAR
;
845 if (index
& _TNL_BIT_COLOR1
) {
846 EMIT_ATTR(_TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_BGR
);
851 if (index
& _TNL_BIT_FOG
)
852 EMIT_ATTR(_TNL_ATTRIB_FOG
, EMIT_1UB_1F
);
857 /* projective textures are not supported by the hardware */
858 if (index
& _TNL_BIT_TEX(0)) {
859 if (VB
->TexCoordPtr
[0]->size
> 2)
860 tex_fallback
= GL_TRUE
;
861 EMIT_ATTR(_TNL_ATTRIB_TEX0
, EMIT_2F
);
862 AGPParseSet
|= SiS_PS_HAS_UV0
;
864 if (index
& _TNL_BIT_TEX(1)) {
865 if (VB
->TexCoordPtr
[1]->size
> 2)
866 tex_fallback
= GL_TRUE
;
867 EMIT_ATTR(_TNL_ATTRIB_TEX1
, EMIT_2F
);
868 AGPParseSet
|= SiS_PS_HAS_UV1
;
870 FALLBACK(smesa
, SIS_FALLBACK_TEXTURE
, tex_fallback
);
872 if (smesa
->last_tcl_state
!= index
) {
873 smesa
->AGPParseSet
= AGPParseSet
;
875 smesa
->vertex_size
= _tnl_install_attrs( ctx
, smesa
->vertex_attrs
,
876 smesa
->vertex_attr_count
, smesa
->hw_viewport
, 0 );
878 smesa
->vertex_size
>>= 2;
879 smesa
->AGPParseSet
|= smesa
->vertex_size
<< 28;
883 static void sisRenderFinish( GLcontext
*ctx
)
887 /**********************************************************************/
888 /* AGP/PCI vertex submission */
889 /**********************************************************************/
892 sisFlushPrimsLocked(sisContextPtr smesa
)
894 if (smesa
->vb_cur
== smesa
->vb_last
)
897 sisUpdateHWState(smesa
->glCtx
);
899 if (smesa
->using_agp
) {
902 MMIO(REG_3D_AGPCmBase
, (smesa
->vb_last
- smesa
->vb
) +
903 smesa
->vb_agp_offset
);
904 MMIO(REG_3D_AGPTtDwNum
, ((smesa
->vb_cur
- smesa
->vb_last
) / 4) |
906 MMIO(REG_3D_ParsingSet
, smesa
->AGPParseSet
);
907 MMIO(REG_3D_AGPCmFire
, (GLint
)(-1));
910 int mmio_index
= 0, incr
= 0;
911 void (*sis_emit_func
)(sisContextPtr smesa
, char *verts
) = NULL
;
913 if (smesa
->AGPParseSet
& MASK_PsShadingSmooth
)
914 mmio_index
|= VERT_SMOOTH
;
915 if (smesa
->AGPParseSet
& SiS_PS_HAS_SPECULAR
)
916 mmio_index
|= VERT_SPEC
;
917 if (smesa
->AGPParseSet
& SiS_PS_HAS_W
)
918 mmio_index
|= VERT_W
;
919 if (smesa
->AGPParseSet
& SiS_PS_HAS_UV0
)
920 mmio_index
|= VERT_UV0
;
921 if (smesa
->AGPParseSet
& SiS_PS_HAS_UV1
)
922 mmio_index
|= VERT_UV1
;
924 switch (smesa
->AGPParseSet
& MASK_PsDataType
) {
925 case MASK_PsPointList
:
926 incr
= smesa
->vertex_size
* 4;
927 sis_emit_func
= sis_point_func_mmio
[mmio_index
];
929 case MASK_PsLineList
:
930 incr
= smesa
->vertex_size
* 4 * 2;
931 sis_emit_func
= sis_line_func_mmio
[mmio_index
];
933 case MASK_PsTriangleList
:
934 incr
= smesa
->vertex_size
* 4 * 3;
935 sis_emit_func
= sis_tri_func_mmio
[mmio_index
];
940 MMIO(REG_3D_PrimitiveSet
, smesa
->dwPrimitiveSet
);
941 while (smesa
->vb_last
< smesa
->vb_cur
) {
942 sis_emit_func(smesa
, smesa
->vb_last
);
943 smesa
->vb_last
+= incr
;
948 /* With PCI, we can just start writing to the start of the VB again. */
949 smesa
->vb_cur
= smesa
->vb
;
951 smesa
->vb_last
= smesa
->vb_cur
;
954 void sisFlushPrims(sisContextPtr smesa
)
957 sisFlushPrimsLocked(smesa
);
961 /**********************************************************************/
962 /* Transition to/from hardware rasterization. */
963 /**********************************************************************/
965 static const char * const fallbackStrings
[] = {
969 "Texture 0 env", /* Note: unused */
970 "Texture 1 env", /* Note: unused */
971 "glDrawBuffer(GL_FRONT_AND_BACK)",
972 "glEnable(GL_STENCIL) without hw stencil buffer",
976 static const char *getFallbackString(GLuint bit
)
983 return fallbackStrings
[i
];
986 void sisFallback( GLcontext
*ctx
, GLuint bit
, GLboolean mode
)
988 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
989 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
990 GLuint oldfallback
= smesa
->Fallback
;
993 smesa
->Fallback
|= bit
;
994 if (oldfallback
== 0) {
995 SIS_FIREVERTICES(smesa
);
996 _swsetup_Wakeup( ctx
);
997 smesa
->RenderIndex
= ~0;
998 if (SIS_DEBUG
& DEBUG_FALLBACKS
) {
999 fprintf(stderr
, "SiS begin rasterization fallback: 0x%x %s\n",
1000 bit
, getFallbackString(bit
));
1005 smesa
->Fallback
&= ~bit
;
1006 if (oldfallback
== bit
) {
1007 _swrast_flush( ctx
);
1008 tnl
->Driver
.Render
.Start
= sisRenderStart
;
1009 tnl
->Driver
.Render
.PrimitiveNotify
= sisRenderPrimitive
;
1010 tnl
->Driver
.Render
.Finish
= sisRenderFinish
;
1012 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
1013 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
1014 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
1016 _tnl_invalidate_vertex_state( ctx
, ~0 );
1017 _tnl_invalidate_vertices( ctx
, ~0 );
1018 _tnl_install_attrs( ctx
,
1019 smesa
->vertex_attrs
,
1020 smesa
->vertex_attr_count
,
1021 smesa
->hw_viewport
, 0 );
1023 smesa
->NewGLState
|= _SIS_NEW_RENDER_STATE
;
1024 if (SIS_DEBUG
& DEBUG_FALLBACKS
) {
1025 fprintf(stderr
, "SiS end rasterization fallback: 0x%x %s\n",
1026 bit
, getFallbackString(bit
));
1033 /**********************************************************************/
1034 /* Initialization. */
1035 /**********************************************************************/
1037 void sisInitTriFuncs( GLcontext
*ctx
)
1039 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
1040 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1041 static int firsttime
= 1;
1047 sis_vert_init_none();
1054 sis_vert_init_gws();
1056 sis_vert_init_gt0();
1057 sis_vert_init_wt0();
1058 sis_vert_init_gwt0();
1059 sis_vert_init_st0();
1060 sis_vert_init_gst0();
1061 sis_vert_init_wst0();
1062 sis_vert_init_gwst0();
1064 sis_vert_init_gt1();
1065 sis_vert_init_wt1();
1066 sis_vert_init_gwt1();
1067 sis_vert_init_st1();
1068 sis_vert_init_gst1();
1069 sis_vert_init_wst1();
1070 sis_vert_init_gwst1();
1071 sis_vert_init_t0t1();
1072 sis_vert_init_gt0t1();
1073 sis_vert_init_wt0t1();
1074 sis_vert_init_gwt0t1();
1075 sis_vert_init_st0t1();
1076 sis_vert_init_gst0t1();
1077 sis_vert_init_wst0t1();
1078 sis_vert_init_gwst0t1();
1081 smesa
->RenderIndex
= ~0;
1082 smesa
->NewGLState
|= _SIS_NEW_RENDER_STATE
;
1084 tnl
->Driver
.RunPipeline
= sisRunPipeline
;
1085 tnl
->Driver
.Render
.Start
= sisRenderStart
;
1086 tnl
->Driver
.Render
.Finish
= sisRenderFinish
;
1087 tnl
->Driver
.Render
.PrimitiveNotify
= sisRenderPrimitive
;
1088 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1090 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
1091 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
1092 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
1094 _tnl_init_vertices( ctx
, ctx
->Const
.MaxArrayLockSize
+ 12,
1095 (6 + 2*ctx
->Const
.MaxTextureUnits
) * sizeof(GLfloat
) );
1097 smesa
->verts
= (char *)tnl
->clipspace
.vertex_buf
;