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>
35 #include "main/glheader.h"
36 #include "main/mtypes.h"
37 #include "main/colormac.h"
38 #include "main/macros.h"
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"
52 /* 6326 and 300-series shared */
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] = {
71 static const GLuint hw_prim_6326_mmio_fire
[OP_3D_TRIANGLE_DRAW
+1] = {
72 OP_6326_3D_FIRE_TSARGBa
,
73 OP_6326_3D_FIRE_TSARGBb
,
74 OP_6326_3D_FIRE_TSARGBc
77 static const GLuint hw_prim_mmio_shade
[OP_3D_TRIANGLE_DRAW
+1] = {
83 static const GLuint hw_prim_agp_type
[OP_3D_TRIANGLE_DRAW
+1] = {
89 static const GLuint hw_prim_agp_shade
[OP_3D_TRIANGLE_DRAW
+1] = {
95 static void sisRasterPrimitive( GLcontext
*ctx
, GLuint hwprim
);
96 static void sisRenderPrimitive( GLcontext
*ctx
, GLenum prim
);
98 /***********************************************************************
99 * Emit primitives as inline vertices *
100 ***********************************************************************/
104 #define HAVE_POINTS 1
105 #define CTX_ARG sisContextPtr smesa
106 #define GET_VERTEX_DWORDS() smesa->vertex_size
107 #define ALLOC_VERTS( n, size ) sisAllocDmaLow( smesa, n * size * sizeof(int) )
110 sisContextPtr smesa = SIS_CONTEXT(ctx); \
111 const char *vertptr = smesa->verts;
112 #define VERT(x) (sisVertex *)(vertptr + (x * vertsize * sizeof(int)))
113 #define VERTEX sisVertex
115 #define TAG(x) sis_##x
116 #include "tnl_dd/t_dd_triemit.h"
120 /***********************************************************************
121 * Dispatch vertices to hardware through MMIO *
122 ***********************************************************************/
124 /* The ARGB write of the last vertex of the primitive fires the 3d engine, so
125 * save it until the end.
127 #define SIS_MMIO_WRITE_VERTEX(_v, i, lastvert) \
129 GLuint __color, __i = 0; \
130 MMIO(REG_3D_TSXa+(i)*0x30, _v->ui[__i++]); \
131 MMIO(REG_3D_TSYa+(i)*0x30, _v->ui[__i++]); \
132 MMIO(REG_3D_TSZa+(i)*0x30, _v->ui[__i++]); \
133 if (SIS_STATES & VERT_W) \
134 MMIO(REG_3D_TSWGa+(i)*0x30, _v->ui[__i++]); \
135 __color = _v->ui[__i++]; \
136 if (SIS_STATES & VERT_SPEC) \
137 MMIO(REG_3D_TSFSa+(i)*0x30, _v->ui[__i++]); \
138 if (SIS_STATES & VERT_UV0) { \
139 MMIO(REG_3D_TSUAa+(i)*0x30, _v->ui[__i++]); \
140 MMIO(REG_3D_TSVAa+(i)*0x30, _v->ui[__i++]); \
142 if (SIS_STATES & VERT_UV1) { \
143 MMIO(REG_3D_TSUBa+(i)*0x30, _v->ui[__i++]); \
144 MMIO(REG_3D_TSVBa+(i)*0x30, _v->ui[__i++]); \
146 if (lastvert || (SIS_STATES & VERT_SMOOTH)) \
147 MMIO(REG_3D_TSARGBa+(i)*0x30, __color); \
150 #define SIS6326_MMIO_WRITE_VERTEX(_v, i, lastvert) \
152 GLuint __color, __i = 0; \
153 MMIO(REG_6326_3D_TSXa+(i)*0x20, _v->ui[__i++]); \
154 MMIO(REG_6326_3D_TSYa+(i)*0x20, _v->ui[__i++]); \
155 MMIO(REG_6326_3D_TSZa+(i)*0x20, _v->ui[__i++]); \
156 if (SIS_STATES & VERT_W) \
157 MMIO(REG_6326_3D_TSWa+(i)*0x20, _v->ui[__i++]); \
158 __color = _v->ui[__i++]; \
159 if (SIS_STATES & VERT_SPEC) \
160 MMIO(REG_6326_3D_TSFSa+(i)*0x20, _v->ui[__i++]); \
161 if (SIS_STATES & VERT_UV0) { \
162 MMIO(REG_6326_3D_TSUa+(i)*0x20, _v->ui[__i++]); \
163 MMIO(REG_6326_3D_TSVa+(i)*0x20, _v->ui[__i++]); \
165 if (lastvert || (SIS_STATES & VERT_SMOOTH)) \
166 MMIO(REG_6326_3D_TSARGBa+(i)*0x30, __color); \
169 #define MMIO_VERT_REG_COUNT 10
171 #define VERT_SMOOTH 0x01
173 #define VERT_SPEC 0x04
174 #define VERT_UV0 0x08
175 #define VERT_UV1 0x10
176 #define VERT_6326 0x20 /* Right after UV1, but won't have a UV1 set */
178 typedef void (*mmio_draw_func
)(sisContextPtr smesa
, char *verts
);
179 static mmio_draw_func sis_tri_func_mmio
[48];
180 static mmio_draw_func sis_line_func_mmio
[48];
181 static mmio_draw_func sis_point_func_mmio
[48];
183 #define SIS_STATES (0)
184 #define TAG(x) x##_none
185 #include "sis_tritmp.h"
187 #define SIS_STATES (VERT_SMOOTH)
189 #include "sis_tritmp.h"
191 #define SIS_STATES (VERT_W)
193 #include "sis_tritmp.h"
195 #define SIS_STATES (VERT_SMOOTH | VERT_W)
196 #define TAG(x) x##_gw
197 #include "sis_tritmp.h"
199 #define SIS_STATES (VERT_SPEC)
201 #include "sis_tritmp.h"
203 #define SIS_STATES (VERT_SMOOTH | VERT_SPEC)
204 #define TAG(x) x##_gs
205 #include "sis_tritmp.h"
207 #define SIS_STATES (VERT_W | VERT_SPEC)
208 #define TAG(x) x##_ws
209 #include "sis_tritmp.h"
211 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC)
212 #define TAG(x) x##_gws
213 #include "sis_tritmp.h"
215 #define SIS_STATES (VERT_UV0)
216 #define TAG(x) x##_t0
217 #include "sis_tritmp.h"
219 #define SIS_STATES (VERT_SMOOTH | VERT_UV0)
220 #define TAG(x) x##_gt0
221 #include "sis_tritmp.h"
223 #define SIS_STATES (VERT_W | VERT_UV0)
224 #define TAG(x) x##_wt0
225 #include "sis_tritmp.h"
227 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_UV0)
228 #define TAG(x) x##_gwt0
229 #include "sis_tritmp.h"
231 #define SIS_STATES (VERT_SPEC | VERT_UV0)
232 #define TAG(x) x##_st0
233 #include "sis_tritmp.h"
235 #define SIS_STATES (VERT_SMOOTH | VERT_SPEC | VERT_UV0)
236 #define TAG(x) x##_gst0
237 #include "sis_tritmp.h"
239 #define SIS_STATES (VERT_W | VERT_SPEC | VERT_UV0)
240 #define TAG(x) x##_wst0
241 #include "sis_tritmp.h"
243 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC | VERT_UV0)
244 #define TAG(x) x##_gwst0
245 #include "sis_tritmp.h"
247 #define SIS_STATES (VERT_UV1)
248 #define TAG(x) x##_t1
249 #include "sis_tritmp.h"
251 #define SIS_STATES (VERT_SMOOTH | VERT_UV1)
252 #define TAG(x) x##_gt1
253 #include "sis_tritmp.h"
255 #define SIS_STATES (VERT_W | VERT_UV1)
256 #define TAG(x) x##_wt1
257 #include "sis_tritmp.h"
259 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_UV1)
260 #define TAG(x) x##_gwt1
261 #include "sis_tritmp.h"
263 #define SIS_STATES (VERT_SPEC | VERT_UV1)
264 #define TAG(x) x##_st1
265 #include "sis_tritmp.h"
267 #define SIS_STATES (VERT_SMOOTH | VERT_SPEC | VERT_UV1)
268 #define TAG(x) x##_gst1
269 #include "sis_tritmp.h"
271 #define SIS_STATES (VERT_W | VERT_SPEC | VERT_UV1)
272 #define TAG(x) x##_wst1
273 #include "sis_tritmp.h"
275 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC | VERT_UV1)
276 #define TAG(x) x##_gwst1
277 #include "sis_tritmp.h"
279 #define SIS_STATES (VERT_UV0 | VERT_UV1)
280 #define TAG(x) x##_t0t1
281 #include "sis_tritmp.h"
283 #define SIS_STATES (VERT_SMOOTH | VERT_UV0 | VERT_UV1)
284 #define TAG(x) x##_gt0t1
285 #include "sis_tritmp.h"
287 #define SIS_STATES (VERT_W | VERT_UV0 | VERT_UV1)
288 #define TAG(x) x##_wt0t1
289 #include "sis_tritmp.h"
291 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_UV0 | VERT_UV1)
292 #define TAG(x) x##_gwt0t1
293 #include "sis_tritmp.h"
295 #define SIS_STATES (VERT_SPEC | VERT_UV0 | VERT_UV1)
296 #define TAG(x) x##_st0t1
297 #include "sis_tritmp.h"
299 #define SIS_STATES (VERT_SMOOTH | VERT_SPEC | VERT_UV0 | VERT_UV1)
300 #define TAG(x) x##_gst0t1
301 #include "sis_tritmp.h"
303 #define SIS_STATES (VERT_W | VERT_SPEC | VERT_UV0 | VERT_UV1)
304 #define TAG(x) x##_wst0t1
305 #include "sis_tritmp.h"
307 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC | VERT_UV0 | VERT_UV1)
308 #define TAG(x) x##_gwst0t1
309 #include "sis_tritmp.h"
311 /***********************************************************************
312 * Macros for t_dd_tritmp.h to draw basic primitives *
313 ***********************************************************************/
315 #define TRI( a, b, c ) \
318 smesa->draw_tri( smesa, a, b, c ); \
320 sis_triangle( smesa, a, b, c ); \
323 #define QUAD( a, b, c, d ) \
326 smesa->draw_tri( smesa, a, b, d ); \
327 smesa->draw_tri( smesa, b, c, d ); \
329 sis_quad( smesa, a, b, c, d ); \
332 #define LINE( v0, v1 ) \
335 smesa->draw_line( smesa, v0, v1 ); \
337 sis_line( smesa, v0, v1 ); \
340 #define POINT( v0 ) \
343 smesa->draw_point( smesa, v0 ); \
345 sis_point( smesa, v0 ); \
348 /***********************************************************************
349 * Build render functions from dd templates *
350 ***********************************************************************/
352 #define SIS_OFFSET_BIT 0x01
353 #define SIS_TWOSIDE_BIT 0x02
354 #define SIS_UNFILLED_BIT 0x04
355 #define SIS_FALLBACK_BIT 0x08
356 #define SIS_MAX_TRIFUNC 0x10
360 tnl_points_func points
;
362 tnl_triangle_func triangle
;
364 } rast_tab
[SIS_MAX_TRIFUNC
];
367 #define DO_FALLBACK (IND & SIS_FALLBACK_BIT)
368 #define DO_OFFSET (IND & SIS_OFFSET_BIT)
369 #define DO_UNFILLED (IND & SIS_UNFILLED_BIT)
370 #define DO_TWOSIDE (IND & SIS_TWOSIDE_BIT)
376 #define DO_FULL_QUAD 1
380 #define HAVE_BACK_COLORS 0
381 #define HAVE_HW_FLATSHADE 1
382 #define VERTEX sisVertex
385 #define DEPTH_SCALE smesa->depth_scale
386 #define UNFILLED_TRI unfilled_tri
387 #define UNFILLED_QUAD unfilled_quad
388 #define VERT_X(_v) _v->v.x
389 #define VERT_Y(_v) _v->v.y
390 #define VERT_Z(_v) _v->v.z
391 #define AREA_IS_CCW( a ) (a > 0)
392 #define GET_VERTEX(e) (smesa->verts + (e * smesa->vertex_size * sizeof(int)))
394 #define VERT_SET_RGBA( v, c ) \
396 sis_color_t *color = (sis_color_t *)&((v)->ui[coloroffset]); \
397 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
398 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
399 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
400 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
403 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
405 #define VERT_SET_SPEC( v, c ) \
407 if (specoffset != 0) { \
408 sis_color_t *spec = (sis_color_t *)&((v)->ui[specoffset]); \
409 UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \
410 UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \
411 UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \
414 #define VERT_COPY_SPEC( v0, v1 ) \
416 if (specoffset != 0) { \
417 sis_color_t *spec0 = (sis_color_t *)&((v0)->ui[specoffset]); \
418 sis_color_t *spec1 = (sis_color_t *)&((v1)->ui[specoffset]); \
419 spec0->red = spec1->red; \
420 spec0->green = spec1->green; \
421 spec0->blue = spec1->blue; \
425 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
426 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
427 #define VERT_SAVE_SPEC( idx ) if (specoffset != 0) spec[idx] = v[idx]->ui[specoffset]
428 #define VERT_RESTORE_SPEC( idx ) if (specoffset != 0) v[idx]->ui[specoffset] = spec[idx]
430 #define LOCAL_VARS(n) \
431 sisContextPtr smesa = SIS_CONTEXT(ctx); \
432 GLuint color[n] = { 0 }; \
433 GLuint spec[n] = { 0 }; \
434 GLuint coloroffset = smesa->coloroffset; \
435 GLuint specoffset = smesa->specoffset; \
436 (void) color; (void) spec; (void) coloroffset; (void) specoffset;
438 /***********************************************************************
439 * Helpers for rendering unfilled primitives *
440 ***********************************************************************/
442 #define RASTERIZE(x) if (smesa->hw_primitive != hw_prim[x]) \
443 sisRasterPrimitive( ctx, hw_prim[x] )
444 #define RENDER_PRIMITIVE smesa->render_primitive
445 #define IND SIS_FALLBACK_BIT
447 #include "tnl_dd/t_dd_unfilled.h"
451 /***********************************************************************
452 * Generate GL render functions *
453 ***********************************************************************/
458 #include "tnl_dd/t_dd_tritmp.h"
460 #define IND (SIS_OFFSET_BIT)
461 #define TAG(x) x##_offset
462 #include "tnl_dd/t_dd_tritmp.h"
464 #define IND (SIS_TWOSIDE_BIT)
465 #define TAG(x) x##_twoside
466 #include "tnl_dd/t_dd_tritmp.h"
468 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT)
469 #define TAG(x) x##_twoside_offset
470 #include "tnl_dd/t_dd_tritmp.h"
472 #define IND (SIS_UNFILLED_BIT)
473 #define TAG(x) x##_unfilled
474 #include "tnl_dd/t_dd_tritmp.h"
476 #define IND (SIS_OFFSET_BIT|SIS_UNFILLED_BIT)
477 #define TAG(x) x##_offset_unfilled
478 #include "tnl_dd/t_dd_tritmp.h"
480 #define IND (SIS_TWOSIDE_BIT|SIS_UNFILLED_BIT)
481 #define TAG(x) x##_twoside_unfilled
482 #include "tnl_dd/t_dd_tritmp.h"
484 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT|SIS_UNFILLED_BIT)
485 #define TAG(x) x##_twoside_offset_unfilled
486 #include "tnl_dd/t_dd_tritmp.h"
488 #define IND (SIS_FALLBACK_BIT)
489 #define TAG(x) x##_fallback
490 #include "tnl_dd/t_dd_tritmp.h"
492 #define IND (SIS_OFFSET_BIT|SIS_FALLBACK_BIT)
493 #define TAG(x) x##_offset_fallback
494 #include "tnl_dd/t_dd_tritmp.h"
496 #define IND (SIS_TWOSIDE_BIT|SIS_FALLBACK_BIT)
497 #define TAG(x) x##_twoside_fallback
498 #include "tnl_dd/t_dd_tritmp.h"
500 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT|SIS_FALLBACK_BIT)
501 #define TAG(x) x##_twoside_offset_fallback
502 #include "tnl_dd/t_dd_tritmp.h"
504 #define IND (SIS_UNFILLED_BIT|SIS_FALLBACK_BIT)
505 #define TAG(x) x##_unfilled_fallback
506 #include "tnl_dd/t_dd_tritmp.h"
508 #define IND (SIS_OFFSET_BIT|SIS_UNFILLED_BIT|SIS_FALLBACK_BIT)
509 #define TAG(x) x##_offset_unfilled_fallback
510 #include "tnl_dd/t_dd_tritmp.h"
512 #define IND (SIS_TWOSIDE_BIT|SIS_UNFILLED_BIT|SIS_FALLBACK_BIT)
513 #define TAG(x) x##_twoside_unfilled_fallback
514 #include "tnl_dd/t_dd_tritmp.h"
516 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT|SIS_UNFILLED_BIT| \
518 #define TAG(x) x##_twoside_offset_unfilled_fallback
519 #include "tnl_dd/t_dd_tritmp.h"
522 static void init_rast_tab( void )
527 init_twoside_offset();
529 init_offset_unfilled();
530 init_twoside_unfilled();
531 init_twoside_offset_unfilled();
533 init_offset_fallback();
534 init_twoside_fallback();
535 init_twoside_offset_fallback();
536 init_unfilled_fallback();
537 init_offset_unfilled_fallback();
538 init_twoside_unfilled_fallback();
539 init_twoside_offset_unfilled_fallback();
544 /***********************************************************************
545 * Rasterization fallback helpers *
546 ***********************************************************************/
549 /* This code is hit only when a mix of accelerated and unaccelerated
550 * primitives are being drawn, and only for the unaccelerated
555 sis_fallback_tri( sisContextPtr smesa
,
560 GLcontext
*ctx
= smesa
->glCtx
;
562 _swsetup_Translate( ctx
, v0
, &v
[0] );
563 _swsetup_Translate( ctx
, v1
, &v
[1] );
564 _swsetup_Translate( ctx
, v2
, &v
[2] );
565 sisSpanRenderStart( ctx
);
566 _swrast_Triangle( ctx
, &v
[0], &v
[1], &v
[2] );
567 sisSpanRenderFinish( ctx
);
568 _swrast_flush( ctx
);
573 sis_fallback_line( sisContextPtr smesa
,
577 GLcontext
*ctx
= smesa
->glCtx
;
579 _swsetup_Translate( ctx
, v0
, &v
[0] );
580 _swsetup_Translate( ctx
, v1
, &v
[1] );
581 sisSpanRenderStart( ctx
);
582 _swrast_Line( ctx
, &v
[0], &v
[1] );
583 sisSpanRenderFinish( ctx
);
584 _swrast_flush( ctx
);
589 sis_fallback_point( sisContextPtr smesa
,
592 GLcontext
*ctx
= smesa
->glCtx
;
594 _swsetup_Translate( ctx
, v0
, &v
[0] );
595 sisSpanRenderStart( ctx
);
596 _swrast_Point( ctx
, &v
[0] );
597 sisSpanRenderFinish( ctx
);
598 _swrast_flush( ctx
);
603 /**********************************************************************/
604 /* Render unclipped begin/end objects */
605 /**********************************************************************/
608 #define V(x) (sisVertex *)(vertptr + (x * vertsize * sizeof(int)))
609 #define RENDER_POINTS( start, count ) \
610 for ( ; start < count ; start++) \
611 POINT( V(ELT(start)) )
612 #define RENDER_LINE( v0, v1 ) LINE( V(v0), V(v1) )
613 #define RENDER_TRI( v0, v1, v2 ) TRI( V(v0), V(v1), V(v2) )
614 #define RENDER_QUAD( v0, v1, v2, v3 ) QUAD( V(v0), V(v1), V(v2), V(v3) )
615 #define INIT(x) sisRenderPrimitive( ctx, x )
618 sisContextPtr smesa = SIS_CONTEXT(ctx); \
619 const GLuint vertsize = smesa->vertex_size; \
620 const char *vertptr = (char *)smesa->verts; \
621 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
623 #define RESET_STIPPLE
624 #define RESET_OCCLUSION
625 #define PRESERVE_VB_DEFS
627 #define TAG(x) sis_##x##_verts
628 #include "tnl/t_vb_rendertmp.h"
631 #define TAG(x) sis_##x##_elts
632 #define ELT(x) elt[x]
633 #include "tnl/t_vb_rendertmp.h"
636 /**********************************************************************/
637 /* Choose render functions */
638 /**********************************************************************/
640 #define POINT_FALLBACK (DD_POINT_SMOOTH)
641 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
642 #define TRI_FALLBACK (DD_TRI_STIPPLE|DD_TRI_SMOOTH)
643 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
644 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
645 #define _SIS_NEW_RENDER_STATE (ANY_RASTER_FLAGS | ANY_FALLBACK_FLAGS)
647 static void sisChooseRenderState(GLcontext
*ctx
)
649 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
650 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
651 GLuint flags
= ctx
->_TriangleCaps
;
657 if (flags
& (ANY_RASTER_FLAGS
|ANY_FALLBACK_FLAGS
)) {
659 if (flags
& ANY_RASTER_FLAGS
) {
660 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= SIS_TWOSIDE_BIT
;
661 if (flags
& DD_TRI_OFFSET
) index
|= SIS_OFFSET_BIT
;
662 if (flags
& DD_TRI_UNFILLED
) index
|= SIS_UNFILLED_BIT
;
665 smesa
->draw_point
= sis_point
;
666 smesa
->draw_line
= sis_line
;
667 smesa
->draw_tri
= sis_triangle
;
668 /* Hook in fallbacks for specific primitives.
670 if (flags
& ANY_FALLBACK_FLAGS
) {
671 if (flags
& POINT_FALLBACK
)
672 smesa
->draw_point
= sis_fallback_point
;
673 if (flags
& LINE_FALLBACK
)
674 smesa
->draw_line
= sis_fallback_line
;
675 if (flags
& TRI_FALLBACK
)
676 smesa
->draw_tri
= sis_fallback_tri
;
677 index
|= SIS_FALLBACK_BIT
;
681 if (index
!= smesa
->RenderIndex
) {
682 smesa
->RenderIndex
= index
;
684 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
685 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
686 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
687 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
688 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
691 tnl
->Driver
.Render
.PrimTabVerts
= sis_render_tab_verts
;
692 tnl
->Driver
.Render
.PrimTabElts
= sis_render_tab_elts
;
693 tnl
->Driver
.Render
.ClippedPolygon
= sis_fast_clipped_poly
;
695 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
696 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
697 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
702 /**********************************************************************/
703 /* Multipass rendering for front buffering */
704 /**********************************************************************/
705 static GLboolean
multipass_cliprect( GLcontext
*ctx
, GLuint pass
)
707 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
709 if (pass
>= smesa
->driDrawable
->numClipRects
) {
712 GLint x1
, y1
, x2
, y2
;
714 x1
= smesa
->driDrawable
->pClipRects
[pass
].x1
- smesa
->driDrawable
->x
;
715 y1
= smesa
->driDrawable
->pClipRects
[pass
].y1
- smesa
->driDrawable
->y
;
716 x2
= smesa
->driDrawable
->pClipRects
[pass
].x2
- smesa
->driDrawable
->x
;
717 y2
= smesa
->driDrawable
->pClipRects
[pass
].y2
- smesa
->driDrawable
->y
;
719 if (ctx
->Scissor
.Enabled
) {
720 GLint scisy1
= Y_FLIP(ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
- 1);
721 GLint scisy2
= Y_FLIP(ctx
->Scissor
.Y
);
723 if (ctx
->Scissor
.X
> x1
)
727 if (ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1 < x2
)
728 x2
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
733 MMIO(REG_3D_ClipTopBottom
, y1
<< 13 | y2
);
734 MMIO(REG_3D_ClipLeftRight
, x1
<< 13 | x2
);
735 /* Mark that we clobbered these registers */
736 smesa
->GlobalFlag
|= GFLAG_CLIPPING
;
743 /**********************************************************************/
744 /* Validate state at pipeline start */
745 /**********************************************************************/
747 static void sisRunPipeline( GLcontext
*ctx
)
749 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
751 if (smesa
->NewGLState
) {
752 SIS_FIREVERTICES(smesa
);
753 if (smesa
->NewGLState
& _NEW_TEXTURE
) {
754 sisUpdateTextureState(ctx
);
757 if (smesa
->NewGLState
& _SIS_NEW_RENDER_STATE
)
758 sisChooseRenderState( ctx
);
760 smesa
->NewGLState
= 0;
763 _tnl_run_pipeline( ctx
);
765 /* XXX: If we put flushing in sis_state.c and friends, we can avoid this.
768 SIS_FIREVERTICES(smesa
);
771 /**********************************************************************/
772 /* High level hooks for t_vb_render.c */
773 /**********************************************************************/
775 /* This is called when Mesa switches between rendering triangle
776 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
777 * and lines, points and bitmaps.
780 static void sisRasterPrimitive( GLcontext
*ctx
, GLuint hwprim
)
782 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
783 if (smesa
->hw_primitive
!= hwprim
) {
784 SIS_FIREVERTICES(smesa
);
785 smesa
->hw_primitive
= hwprim
;
787 smesa
->AGPParseSet
&= ~(MASK_PsDataType
| MASK_PsShadingMode
);
788 smesa
->AGPParseSet
|= hw_prim_agp_type
[hwprim
];
791 smesa
->dwPrimitiveSet
&= ~(MASK_6326_DrawPrimitiveCommand
|
792 MASK_6326_SetFirePosition
| MASK_6326_ShadingMode
);
793 smesa
->dwPrimitiveSet
|= hwprim
| hw_prim_6326_mmio_fire
[hwprim
];
795 smesa
->dwPrimitiveSet
&= ~(MASK_DrawPrimitiveCommand
|
796 MASK_SetFirePosition
| MASK_ShadingMode
);
797 smesa
->dwPrimitiveSet
|= hwprim
| hw_prim_mmio_fire
[hwprim
];
800 if (ctx
->Light
.ShadeModel
== GL_FLAT
) {
801 smesa
->AGPParseSet
|= hw_prim_agp_shade
[hwprim
];
802 smesa
->dwPrimitiveSet
|= hw_prim_mmio_shade
[hwprim
];
804 smesa
->AGPParseSet
|= MASK_PsShadingSmooth
;
806 smesa
->dwPrimitiveSet
|= OP_6326_3D_SHADE_FLAT_GOURAUD
;
808 smesa
->dwPrimitiveSet
|= SHADE_GOURAUD
;
814 static void sisRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
816 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
818 smesa
->render_primitive
= prim
;
820 if (prim
>= GL_TRIANGLES
&& (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
822 sisRasterPrimitive( ctx
, hw_prim
[prim
] );
825 #define EMIT_ATTR( ATTR, STYLE) \
827 smesa->vertex_attrs[smesa->vertex_attr_count].attrib = (ATTR); \
828 smesa->vertex_attrs[smesa->vertex_attr_count].format = (STYLE); \
829 smesa->vertex_attr_count++; \
832 #define EMIT_PAD( N ) \
834 smesa->vertex_attrs[smesa->vertex_attr_count].attrib = 0; \
835 smesa->vertex_attrs[smesa->vertex_attr_count].format = EMIT_PAD; \
836 smesa->vertex_attrs[smesa->vertex_attr_count].offset = (N); \
837 smesa->vertex_attr_count++; \
840 static void sisRenderStart( GLcontext
*ctx
)
842 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
843 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
844 struct vertex_buffer
*VB
= &tnl
->vb
;
845 DECLARE_RENDERINPUTS(index_bitset
);
846 GLuint AGPParseSet
= smesa
->AGPParseSet
;
847 GLboolean tex_fallback
= GL_FALSE
;
849 RENDERINPUTS_COPY( index_bitset
, tnl
->render_inputs_bitset
);
851 if (ctx
->DrawBuffer
->_ColorDrawBufferIndexes
[0] == BUFFER_FRONT_LEFT
&&
852 smesa
->driDrawable
->numClipRects
!= 0)
854 multipass_cliprect(ctx
, 0);
855 if (smesa
->driDrawable
->numClipRects
> 1)
856 tnl
->Driver
.Render
.Multipass
= multipass_cliprect
;
858 tnl
->Driver
.Render
.Multipass
= NULL
;
860 tnl
->Driver
.Render
.Multipass
= NULL
;
865 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->NdcPtr
;
866 smesa
->vertex_attr_count
= 0;
868 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to build up a
872 AGPParseSet
&= ~(MASK_VertexDWSize
| MASK_VertexDataFormat
);
873 AGPParseSet
|= SiS_PS_HAS_XYZ
| SiS_PS_HAS_DIFFUSE
;
874 if (RENDERINPUTS_TEST_RANGE( index_bitset
, _TNL_FIRST_TEX
, _TNL_LAST_TEX
)) {
875 EMIT_ATTR(_TNL_ATTRIB_POS
, EMIT_4F_VIEWPORT
);
876 AGPParseSet
|= SiS_PS_HAS_W
;
877 smesa
->coloroffset
= 4;
879 EMIT_ATTR(_TNL_ATTRIB_POS
, EMIT_3F_VIEWPORT
);
880 smesa
->coloroffset
= 3;
883 EMIT_ATTR(_TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_BGRA
);
885 smesa
->specoffset
= 0;
886 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_COLOR1
) ||
887 RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_FOG
)) {
888 AGPParseSet
|= SiS_PS_HAS_SPECULAR
;
890 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_COLOR1
)) {
891 EMIT_ATTR(_TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_BGR
);
892 smesa
->specoffset
= smesa
->coloroffset
+ 1;
897 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_FOG
)) {
898 EMIT_ATTR(_TNL_ATTRIB_FOG
, EMIT_1UB_1F
);
904 /* projective textures are not supported by the hardware */
905 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_TEX0
)) {
906 if (VB
->AttribPtr
[_TNL_ATTRIB_TEX0
]->size
> 2)
907 tex_fallback
= GL_TRUE
;
908 EMIT_ATTR(_TNL_ATTRIB_TEX0
, EMIT_2F
);
909 AGPParseSet
|= SiS_PS_HAS_UV0
;
911 /* Will only hit tex1 on SiS300 */
912 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_TEX1
)) {
913 if (VB
->AttribPtr
[_TNL_ATTRIB_TEX1
]->size
> 2)
914 tex_fallback
= GL_TRUE
;
915 EMIT_ATTR(_TNL_ATTRIB_TEX1
, EMIT_2F
);
916 AGPParseSet
|= SiS_PS_HAS_UV1
;
918 FALLBACK(smesa
, SIS_FALLBACK_TEXTURE
, tex_fallback
);
920 if (!RENDERINPUTS_EQUAL( smesa
->last_tcl_state_bitset
, index_bitset
)) {
921 smesa
->AGPParseSet
= AGPParseSet
;
923 smesa
->vertex_size
= _tnl_install_attrs( ctx
, smesa
->vertex_attrs
,
924 smesa
->vertex_attr_count
, smesa
->hw_viewport
, 0 );
926 smesa
->vertex_size
>>= 2;
927 smesa
->AGPParseSet
|= smesa
->vertex_size
<< 28;
931 static void sisRenderFinish( GLcontext
*ctx
)
935 /**********************************************************************/
936 /* AGP/PCI vertex submission */
937 /**********************************************************************/
940 sisFlushPrimsLocked(sisContextPtr smesa
)
942 if (smesa
->vb_cur
== smesa
->vb_last
)
946 sis6326UpdateHWState(smesa
->glCtx
);
948 sisUpdateHWState(smesa
->glCtx
);
950 if (smesa
->using_agp
) {
953 MMIO(REG_3D_AGPCmBase
, (smesa
->vb_last
- smesa
->vb
) +
954 smesa
->vb_agp_offset
);
955 MMIO(REG_3D_AGPTtDwNum
, ((smesa
->vb_cur
- smesa
->vb_last
) / 4) |
957 MMIO(REG_3D_ParsingSet
, smesa
->AGPParseSet
);
958 MMIO(REG_3D_AGPCmFire
, (GLint
)(-1));
961 int mmio_index
= 0, incr
= 0;
962 void (*sis_emit_func
)(sisContextPtr smesa
, char *verts
) = NULL
;
964 if (smesa
->AGPParseSet
& MASK_PsShadingSmooth
)
965 mmio_index
|= VERT_SMOOTH
;
966 if (smesa
->AGPParseSet
& SiS_PS_HAS_SPECULAR
)
967 mmio_index
|= VERT_SPEC
;
968 if (smesa
->AGPParseSet
& SiS_PS_HAS_W
)
969 mmio_index
|= VERT_W
;
970 if (smesa
->AGPParseSet
& SiS_PS_HAS_UV0
)
971 mmio_index
|= VERT_UV0
;
972 if (smesa
->AGPParseSet
& SiS_PS_HAS_UV1
)
973 mmio_index
|= VERT_UV1
;
975 mmio_index
|= VERT_6326
;
977 switch (smesa
->AGPParseSet
& MASK_PsDataType
) {
978 case MASK_PsPointList
:
979 incr
= smesa
->vertex_size
* 4;
980 sis_emit_func
= sis_point_func_mmio
[mmio_index
];
982 case MASK_PsLineList
:
983 incr
= smesa
->vertex_size
* 4 * 2;
984 sis_emit_func
= sis_line_func_mmio
[mmio_index
];
986 case MASK_PsTriangleList
:
987 incr
= smesa
->vertex_size
* 4 * 3;
988 sis_emit_func
= sis_tri_func_mmio
[mmio_index
];
992 if (!smesa
->is6326
) {
994 MMIO(REG_3D_PrimitiveSet
, smesa
->dwPrimitiveSet
);
996 while (smesa
->vb_last
< smesa
->vb_cur
) {
997 sis_emit_func(smesa
, (char *)smesa
->vb_last
);
998 smesa
->vb_last
+= incr
;
1003 /* With PCI, we can just start writing to the start of the VB again. */
1004 smesa
->vb_cur
= smesa
->vb
;
1006 smesa
->vb_last
= smesa
->vb_cur
;
1009 void sisFlushPrims(sisContextPtr smesa
)
1012 sisFlushPrimsLocked(smesa
);
1016 /**********************************************************************/
1017 /* Transition to/from hardware rasterization. */
1018 /**********************************************************************/
1020 static const char * const fallbackStrings
[] = {
1024 "Texture 0 env", /* Note: unused */
1025 "Texture 1 env", /* Note: unused */
1026 "glDrawBuffer(GL_FRONT_AND_BACK)",
1027 "glEnable(GL_STENCIL) without hw stencil buffer",
1032 static const char *getFallbackString(GLuint bit
)
1039 return fallbackStrings
[i
];
1042 void sisFallback( GLcontext
*ctx
, GLuint bit
, GLboolean mode
)
1044 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1045 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
1046 GLuint oldfallback
= smesa
->Fallback
;
1049 smesa
->Fallback
|= bit
;
1050 if (oldfallback
== 0) {
1051 SIS_FIREVERTICES(smesa
);
1052 _swsetup_Wakeup( ctx
);
1053 smesa
->RenderIndex
= ~0;
1054 if (SIS_DEBUG
& DEBUG_FALLBACKS
) {
1055 fprintf(stderr
, "SiS begin rasterization fallback: 0x%x %s\n",
1056 bit
, getFallbackString(bit
));
1061 smesa
->Fallback
&= ~bit
;
1062 if (oldfallback
== bit
) {
1063 _swrast_flush( ctx
);
1064 tnl
->Driver
.Render
.Start
= sisRenderStart
;
1065 tnl
->Driver
.Render
.PrimitiveNotify
= sisRenderPrimitive
;
1066 tnl
->Driver
.Render
.Finish
= sisRenderFinish
;
1068 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
1069 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
1070 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
1072 _tnl_invalidate_vertex_state( ctx
, ~0 );
1073 _tnl_invalidate_vertices( ctx
, ~0 );
1074 _tnl_install_attrs( ctx
,
1075 smesa
->vertex_attrs
,
1076 smesa
->vertex_attr_count
,
1077 smesa
->hw_viewport
, 0 );
1079 smesa
->NewGLState
|= _SIS_NEW_RENDER_STATE
;
1080 if (SIS_DEBUG
& DEBUG_FALLBACKS
) {
1081 fprintf(stderr
, "SiS end rasterization fallback: 0x%x %s\n",
1082 bit
, getFallbackString(bit
));
1089 /**********************************************************************/
1090 /* Initialization. */
1091 /**********************************************************************/
1093 void sisInitTriFuncs( GLcontext
*ctx
)
1095 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
1096 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1097 static int firsttime
= 1;
1103 sis_vert_init_none();
1110 sis_vert_init_gws();
1112 sis_vert_init_gt0();
1113 sis_vert_init_wt0();
1114 sis_vert_init_gwt0();
1115 sis_vert_init_st0();
1116 sis_vert_init_gst0();
1117 sis_vert_init_wst0();
1118 sis_vert_init_gwst0();
1120 sis_vert_init_gt1();
1121 sis_vert_init_wt1();
1122 sis_vert_init_gwt1();
1123 sis_vert_init_st1();
1124 sis_vert_init_gst1();
1125 sis_vert_init_wst1();
1126 sis_vert_init_gwst1();
1127 sis_vert_init_t0t1();
1128 sis_vert_init_gt0t1();
1129 sis_vert_init_wt0t1();
1130 sis_vert_init_gwt0t1();
1131 sis_vert_init_st0t1();
1132 sis_vert_init_gst0t1();
1133 sis_vert_init_wst0t1();
1134 sis_vert_init_gwst0t1();
1137 smesa
->RenderIndex
= ~0;
1138 smesa
->NewGLState
|= _SIS_NEW_RENDER_STATE
;
1140 tnl
->Driver
.RunPipeline
= sisRunPipeline
;
1141 tnl
->Driver
.Render
.Start
= sisRenderStart
;
1142 tnl
->Driver
.Render
.Finish
= sisRenderFinish
;
1143 tnl
->Driver
.Render
.PrimitiveNotify
= sisRenderPrimitive
;
1144 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1146 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
1147 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
1148 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
1150 _tnl_init_vertices( ctx
, ctx
->Const
.MaxArrayLockSize
+ 12,
1151 (6 + 2*ctx
->Const
.MaxTextureUnits
) * sizeof(GLfloat
) );
1153 smesa
->verts
= (char *)tnl
->clipspace
.vertex_buf
;