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
379 #define HAVE_BACK_COLORS 0
380 #define HAVE_HW_FLATSHADE 1
381 #define VERTEX sisVertex
384 #define DEPTH_SCALE smesa->depth_scale
385 #define UNFILLED_TRI unfilled_tri
386 #define UNFILLED_QUAD unfilled_quad
387 #define VERT_X(_v) _v->v.x
388 #define VERT_Y(_v) _v->v.y
389 #define VERT_Z(_v) _v->v.z
390 #define AREA_IS_CCW( a ) (a > 0)
391 #define GET_VERTEX(e) (smesa->verts + (e * smesa->vertex_size * sizeof(int)))
393 #define VERT_SET_RGBA( v, c ) \
395 sis_color_t *color = (sis_color_t *)&((v)->ui[coloroffset]); \
396 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
397 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
398 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
399 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
402 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
404 #define VERT_SET_SPEC( v, c ) \
406 if (specoffset != 0) { \
407 sis_color_t *spec = (sis_color_t *)&((v)->ui[specoffset]); \
408 UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \
409 UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \
410 UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \
413 #define VERT_COPY_SPEC( v0, v1 ) \
415 if (specoffset != 0) { \
416 sis_color_t *spec0 = (sis_color_t *)&((v0)->ui[specoffset]); \
417 sis_color_t *spec1 = (sis_color_t *)&((v1)->ui[specoffset]); \
418 spec0->red = spec1->red; \
419 spec0->green = spec1->green; \
420 spec0->blue = spec1->blue; \
424 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
425 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
426 #define VERT_SAVE_SPEC( idx ) if (specoffset != 0) spec[idx] = v[idx]->ui[specoffset]
427 #define VERT_RESTORE_SPEC( idx ) if (specoffset != 0) v[idx]->ui[specoffset] = spec[idx]
429 #define LOCAL_VARS(n) \
430 sisContextPtr smesa = SIS_CONTEXT(ctx); \
431 GLuint color[n] = { 0 }; \
432 GLuint spec[n] = { 0 }; \
433 GLuint coloroffset = smesa->coloroffset; \
434 GLuint specoffset = smesa->specoffset; \
435 (void) color; (void) spec; (void) coloroffset; (void) specoffset;
437 /***********************************************************************
438 * Helpers for rendering unfilled primitives *
439 ***********************************************************************/
441 #define RASTERIZE(x) if (smesa->hw_primitive != hw_prim[x]) \
442 sisRasterPrimitive( ctx, hw_prim[x] )
443 #define RENDER_PRIMITIVE smesa->render_primitive
444 #define IND SIS_FALLBACK_BIT
446 #include "tnl_dd/t_dd_unfilled.h"
450 /***********************************************************************
451 * Generate GL render functions *
452 ***********************************************************************/
457 #include "tnl_dd/t_dd_tritmp.h"
459 #define IND (SIS_OFFSET_BIT)
460 #define TAG(x) x##_offset
461 #include "tnl_dd/t_dd_tritmp.h"
463 #define IND (SIS_TWOSIDE_BIT)
464 #define TAG(x) x##_twoside
465 #include "tnl_dd/t_dd_tritmp.h"
467 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT)
468 #define TAG(x) x##_twoside_offset
469 #include "tnl_dd/t_dd_tritmp.h"
471 #define IND (SIS_UNFILLED_BIT)
472 #define TAG(x) x##_unfilled
473 #include "tnl_dd/t_dd_tritmp.h"
475 #define IND (SIS_OFFSET_BIT|SIS_UNFILLED_BIT)
476 #define TAG(x) x##_offset_unfilled
477 #include "tnl_dd/t_dd_tritmp.h"
479 #define IND (SIS_TWOSIDE_BIT|SIS_UNFILLED_BIT)
480 #define TAG(x) x##_twoside_unfilled
481 #include "tnl_dd/t_dd_tritmp.h"
483 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT|SIS_UNFILLED_BIT)
484 #define TAG(x) x##_twoside_offset_unfilled
485 #include "tnl_dd/t_dd_tritmp.h"
487 #define IND (SIS_FALLBACK_BIT)
488 #define TAG(x) x##_fallback
489 #include "tnl_dd/t_dd_tritmp.h"
491 #define IND (SIS_OFFSET_BIT|SIS_FALLBACK_BIT)
492 #define TAG(x) x##_offset_fallback
493 #include "tnl_dd/t_dd_tritmp.h"
495 #define IND (SIS_TWOSIDE_BIT|SIS_FALLBACK_BIT)
496 #define TAG(x) x##_twoside_fallback
497 #include "tnl_dd/t_dd_tritmp.h"
499 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT|SIS_FALLBACK_BIT)
500 #define TAG(x) x##_twoside_offset_fallback
501 #include "tnl_dd/t_dd_tritmp.h"
503 #define IND (SIS_UNFILLED_BIT|SIS_FALLBACK_BIT)
504 #define TAG(x) x##_unfilled_fallback
505 #include "tnl_dd/t_dd_tritmp.h"
507 #define IND (SIS_OFFSET_BIT|SIS_UNFILLED_BIT|SIS_FALLBACK_BIT)
508 #define TAG(x) x##_offset_unfilled_fallback
509 #include "tnl_dd/t_dd_tritmp.h"
511 #define IND (SIS_TWOSIDE_BIT|SIS_UNFILLED_BIT|SIS_FALLBACK_BIT)
512 #define TAG(x) x##_twoside_unfilled_fallback
513 #include "tnl_dd/t_dd_tritmp.h"
515 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT|SIS_UNFILLED_BIT| \
517 #define TAG(x) x##_twoside_offset_unfilled_fallback
518 #include "tnl_dd/t_dd_tritmp.h"
521 static void init_rast_tab( void )
526 init_twoside_offset();
528 init_offset_unfilled();
529 init_twoside_unfilled();
530 init_twoside_offset_unfilled();
532 init_offset_fallback();
533 init_twoside_fallback();
534 init_twoside_offset_fallback();
535 init_unfilled_fallback();
536 init_offset_unfilled_fallback();
537 init_twoside_unfilled_fallback();
538 init_twoside_offset_unfilled_fallback();
543 /***********************************************************************
544 * Rasterization fallback helpers *
545 ***********************************************************************/
548 /* This code is hit only when a mix of accelerated and unaccelerated
549 * primitives are being drawn, and only for the unaccelerated
554 sis_fallback_tri( sisContextPtr smesa
,
559 GLcontext
*ctx
= smesa
->glCtx
;
561 _swsetup_Translate( ctx
, v0
, &v
[0] );
562 _swsetup_Translate( ctx
, v1
, &v
[1] );
563 _swsetup_Translate( ctx
, v2
, &v
[2] );
564 sisSpanRenderStart( ctx
);
565 _swrast_Triangle( ctx
, &v
[0], &v
[1], &v
[2] );
566 sisSpanRenderFinish( ctx
);
567 _swrast_flush( ctx
);
572 sis_fallback_line( sisContextPtr smesa
,
576 GLcontext
*ctx
= smesa
->glCtx
;
578 _swsetup_Translate( ctx
, v0
, &v
[0] );
579 _swsetup_Translate( ctx
, v1
, &v
[1] );
580 sisSpanRenderStart( ctx
);
581 _swrast_Line( ctx
, &v
[0], &v
[1] );
582 sisSpanRenderFinish( ctx
);
583 _swrast_flush( ctx
);
588 sis_fallback_point( sisContextPtr smesa
,
591 GLcontext
*ctx
= smesa
->glCtx
;
593 _swsetup_Translate( ctx
, v0
, &v
[0] );
594 sisSpanRenderStart( ctx
);
595 _swrast_Point( ctx
, &v
[0] );
596 sisSpanRenderFinish( ctx
);
597 _swrast_flush( ctx
);
602 /**********************************************************************/
603 /* Render unclipped begin/end objects */
604 /**********************************************************************/
607 #define V(x) (sisVertex *)(vertptr + (x * vertsize * sizeof(int)))
608 #define RENDER_POINTS( start, count ) \
609 for ( ; start < count ; start++) \
610 POINT( V(ELT(start)) )
611 #define RENDER_LINE( v0, v1 ) LINE( V(v0), V(v1) )
612 #define RENDER_TRI( v0, v1, v2 ) TRI( V(v0), V(v1), V(v2) )
613 #define RENDER_QUAD( v0, v1, v2, v3 ) QUAD( V(v0), V(v1), V(v2), V(v3) )
614 #define INIT(x) sisRenderPrimitive( ctx, x )
617 sisContextPtr smesa = SIS_CONTEXT(ctx); \
618 const GLuint vertsize = smesa->vertex_size; \
619 const char *vertptr = (char *)smesa->verts; \
620 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
622 #define RESET_STIPPLE
623 #define RESET_OCCLUSION
624 #define PRESERVE_VB_DEFS
626 #define TAG(x) sis_##x##_verts
627 #include "tnl/t_vb_rendertmp.h"
630 #define TAG(x) sis_##x##_elts
631 #define ELT(x) elt[x]
632 #include "tnl/t_vb_rendertmp.h"
635 /**********************************************************************/
636 /* Choose render functions */
637 /**********************************************************************/
639 #define POINT_FALLBACK (DD_POINT_SMOOTH)
640 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
641 #define TRI_FALLBACK (DD_TRI_STIPPLE|DD_TRI_SMOOTH)
642 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
643 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
644 #define _SIS_NEW_RENDER_STATE (ANY_RASTER_FLAGS | ANY_FALLBACK_FLAGS)
646 static void sisChooseRenderState(GLcontext
*ctx
)
648 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
649 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
650 GLuint flags
= ctx
->_TriangleCaps
;
656 if (flags
& (ANY_RASTER_FLAGS
|ANY_FALLBACK_FLAGS
)) {
658 if (flags
& ANY_RASTER_FLAGS
) {
659 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= SIS_TWOSIDE_BIT
;
660 if (flags
& DD_TRI_OFFSET
) index
|= SIS_OFFSET_BIT
;
661 if (flags
& DD_TRI_UNFILLED
) index
|= SIS_UNFILLED_BIT
;
664 smesa
->draw_point
= sis_point
;
665 smesa
->draw_line
= sis_line
;
666 smesa
->draw_tri
= sis_triangle
;
667 /* Hook in fallbacks for specific primitives.
669 if (flags
& ANY_FALLBACK_FLAGS
) {
670 if (flags
& POINT_FALLBACK
)
671 smesa
->draw_point
= sis_fallback_point
;
672 if (flags
& LINE_FALLBACK
)
673 smesa
->draw_line
= sis_fallback_line
;
674 if (flags
& TRI_FALLBACK
)
675 smesa
->draw_tri
= sis_fallback_tri
;
676 index
|= SIS_FALLBACK_BIT
;
680 if (index
!= smesa
->RenderIndex
) {
681 smesa
->RenderIndex
= index
;
683 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
684 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
685 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
686 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
687 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
690 tnl
->Driver
.Render
.PrimTabVerts
= sis_render_tab_verts
;
691 tnl
->Driver
.Render
.PrimTabElts
= sis_render_tab_elts
;
692 tnl
->Driver
.Render
.ClippedPolygon
= sis_fast_clipped_poly
;
694 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
695 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
696 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
701 /**********************************************************************/
702 /* Multipass rendering for front buffering */
703 /**********************************************************************/
704 static GLboolean
multipass_cliprect( GLcontext
*ctx
, GLuint pass
)
706 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
708 if (pass
>= smesa
->driDrawable
->numClipRects
) {
711 GLint x1
, y1
, x2
, y2
;
713 x1
= smesa
->driDrawable
->pClipRects
[pass
].x1
- smesa
->driDrawable
->x
;
714 y1
= smesa
->driDrawable
->pClipRects
[pass
].y1
- smesa
->driDrawable
->y
;
715 x2
= smesa
->driDrawable
->pClipRects
[pass
].x2
- smesa
->driDrawable
->x
;
716 y2
= smesa
->driDrawable
->pClipRects
[pass
].y2
- smesa
->driDrawable
->y
;
718 if (ctx
->Scissor
.Enabled
) {
719 GLint scisy1
= Y_FLIP(ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
- 1);
720 GLint scisy2
= Y_FLIP(ctx
->Scissor
.Y
);
722 if (ctx
->Scissor
.X
> x1
)
726 if (ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1 < x2
)
727 x2
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
732 MMIO(REG_3D_ClipTopBottom
, y1
<< 13 | y2
);
733 MMIO(REG_3D_ClipLeftRight
, x1
<< 13 | x2
);
734 /* Mark that we clobbered these registers */
735 smesa
->GlobalFlag
|= GFLAG_CLIPPING
;
742 /**********************************************************************/
743 /* Validate state at pipeline start */
744 /**********************************************************************/
746 static void sisRunPipeline( GLcontext
*ctx
)
748 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
750 if (smesa
->NewGLState
) {
751 SIS_FIREVERTICES(smesa
);
752 if (smesa
->NewGLState
& _NEW_TEXTURE
) {
753 sisUpdateTextureState(ctx
);
756 if (smesa
->NewGLState
& _SIS_NEW_RENDER_STATE
)
757 sisChooseRenderState( ctx
);
759 smesa
->NewGLState
= 0;
762 _tnl_run_pipeline( ctx
);
764 /* XXX: If we put flushing in sis_state.c and friends, we can avoid this.
767 SIS_FIREVERTICES(smesa
);
770 /**********************************************************************/
771 /* High level hooks for t_vb_render.c */
772 /**********************************************************************/
774 /* This is called when Mesa switches between rendering triangle
775 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
776 * and lines, points and bitmaps.
779 static void sisRasterPrimitive( GLcontext
*ctx
, GLuint hwprim
)
781 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
782 if (smesa
->hw_primitive
!= hwprim
) {
783 SIS_FIREVERTICES(smesa
);
784 smesa
->hw_primitive
= hwprim
;
786 smesa
->AGPParseSet
&= ~(MASK_PsDataType
| MASK_PsShadingMode
);
787 smesa
->AGPParseSet
|= hw_prim_agp_type
[hwprim
];
790 smesa
->dwPrimitiveSet
&= ~(MASK_6326_DrawPrimitiveCommand
|
791 MASK_6326_SetFirePosition
| MASK_6326_ShadingMode
);
792 smesa
->dwPrimitiveSet
|= hwprim
| hw_prim_6326_mmio_fire
[hwprim
];
794 smesa
->dwPrimitiveSet
&= ~(MASK_DrawPrimitiveCommand
|
795 MASK_SetFirePosition
| MASK_ShadingMode
);
796 smesa
->dwPrimitiveSet
|= hwprim
| hw_prim_mmio_fire
[hwprim
];
799 if (ctx
->Light
.ShadeModel
== GL_FLAT
) {
800 smesa
->AGPParseSet
|= hw_prim_agp_shade
[hwprim
];
801 smesa
->dwPrimitiveSet
|= hw_prim_mmio_shade
[hwprim
];
803 smesa
->AGPParseSet
|= MASK_PsShadingSmooth
;
805 smesa
->dwPrimitiveSet
|= OP_6326_3D_SHADE_FLAT_GOURAUD
;
807 smesa
->dwPrimitiveSet
|= SHADE_GOURAUD
;
813 static void sisRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
815 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
817 smesa
->render_primitive
= prim
;
819 if (prim
>= GL_TRIANGLES
&& (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
821 sisRasterPrimitive( ctx
, hw_prim
[prim
] );
824 #define EMIT_ATTR( ATTR, STYLE) \
826 smesa->vertex_attrs[smesa->vertex_attr_count].attrib = (ATTR); \
827 smesa->vertex_attrs[smesa->vertex_attr_count].format = (STYLE); \
828 smesa->vertex_attr_count++; \
831 #define EMIT_PAD( N ) \
833 smesa->vertex_attrs[smesa->vertex_attr_count].attrib = 0; \
834 smesa->vertex_attrs[smesa->vertex_attr_count].format = EMIT_PAD; \
835 smesa->vertex_attrs[smesa->vertex_attr_count].offset = (N); \
836 smesa->vertex_attr_count++; \
839 static void sisRenderStart( GLcontext
*ctx
)
841 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
842 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
843 struct vertex_buffer
*VB
= &tnl
->vb
;
844 DECLARE_RENDERINPUTS(index_bitset
);
845 GLuint AGPParseSet
= smesa
->AGPParseSet
;
846 GLboolean tex_fallback
= GL_FALSE
;
848 RENDERINPUTS_COPY( index_bitset
, tnl
->render_inputs_bitset
);
850 if (ctx
->DrawBuffer
->_ColorDrawBufferIndexes
[0] == BUFFER_FRONT_LEFT
&&
851 smesa
->driDrawable
->numClipRects
!= 0)
853 multipass_cliprect(ctx
, 0);
854 if (smesa
->driDrawable
->numClipRects
> 1)
855 tnl
->Driver
.Render
.Multipass
= multipass_cliprect
;
857 tnl
->Driver
.Render
.Multipass
= NULL
;
859 tnl
->Driver
.Render
.Multipass
= NULL
;
864 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->NdcPtr
;
865 smesa
->vertex_attr_count
= 0;
867 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to build up a
871 AGPParseSet
&= ~(MASK_VertexDWSize
| MASK_VertexDataFormat
);
872 AGPParseSet
|= SiS_PS_HAS_XYZ
| SiS_PS_HAS_DIFFUSE
;
873 if (RENDERINPUTS_TEST_RANGE( index_bitset
, _TNL_FIRST_TEX
, _TNL_LAST_TEX
)) {
874 EMIT_ATTR(_TNL_ATTRIB_POS
, EMIT_4F_VIEWPORT
);
875 AGPParseSet
|= SiS_PS_HAS_W
;
876 smesa
->coloroffset
= 4;
878 EMIT_ATTR(_TNL_ATTRIB_POS
, EMIT_3F_VIEWPORT
);
879 smesa
->coloroffset
= 3;
882 EMIT_ATTR(_TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_BGRA
);
884 smesa
->specoffset
= 0;
885 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_COLOR1
) ||
886 RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_FOG
)) {
887 AGPParseSet
|= SiS_PS_HAS_SPECULAR
;
889 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_COLOR1
)) {
890 EMIT_ATTR(_TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_BGR
);
891 smesa
->specoffset
= smesa
->coloroffset
+ 1;
896 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_FOG
)) {
897 EMIT_ATTR(_TNL_ATTRIB_FOG
, EMIT_1UB_1F
);
903 /* projective textures are not supported by the hardware */
904 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_TEX0
)) {
905 if (VB
->AttribPtr
[_TNL_ATTRIB_TEX0
]->size
> 2)
906 tex_fallback
= GL_TRUE
;
907 EMIT_ATTR(_TNL_ATTRIB_TEX0
, EMIT_2F
);
908 AGPParseSet
|= SiS_PS_HAS_UV0
;
910 /* Will only hit tex1 on SiS300 */
911 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_TEX1
)) {
912 if (VB
->AttribPtr
[_TNL_ATTRIB_TEX1
]->size
> 2)
913 tex_fallback
= GL_TRUE
;
914 EMIT_ATTR(_TNL_ATTRIB_TEX1
, EMIT_2F
);
915 AGPParseSet
|= SiS_PS_HAS_UV1
;
917 FALLBACK(smesa
, SIS_FALLBACK_TEXTURE
, tex_fallback
);
919 if (!RENDERINPUTS_EQUAL( smesa
->last_tcl_state_bitset
, index_bitset
)) {
920 smesa
->AGPParseSet
= AGPParseSet
;
922 smesa
->vertex_size
= _tnl_install_attrs( ctx
, smesa
->vertex_attrs
,
923 smesa
->vertex_attr_count
, smesa
->hw_viewport
, 0 );
925 smesa
->vertex_size
>>= 2;
926 smesa
->AGPParseSet
|= smesa
->vertex_size
<< 28;
930 static void sisRenderFinish( GLcontext
*ctx
)
934 /**********************************************************************/
935 /* AGP/PCI vertex submission */
936 /**********************************************************************/
939 sisFlushPrimsLocked(sisContextPtr smesa
)
941 if (smesa
->vb_cur
== smesa
->vb_last
)
945 sis6326UpdateHWState(smesa
->glCtx
);
947 sisUpdateHWState(smesa
->glCtx
);
949 if (smesa
->using_agp
) {
952 MMIO(REG_3D_AGPCmBase
, (smesa
->vb_last
- smesa
->vb
) +
953 smesa
->vb_agp_offset
);
954 MMIO(REG_3D_AGPTtDwNum
, ((smesa
->vb_cur
- smesa
->vb_last
) / 4) |
956 MMIO(REG_3D_ParsingSet
, smesa
->AGPParseSet
);
957 MMIO(REG_3D_AGPCmFire
, (GLint
)(-1));
960 int mmio_index
= 0, incr
= 0;
961 void (*sis_emit_func
)(sisContextPtr smesa
, char *verts
) = NULL
;
963 if (smesa
->AGPParseSet
& MASK_PsShadingSmooth
)
964 mmio_index
|= VERT_SMOOTH
;
965 if (smesa
->AGPParseSet
& SiS_PS_HAS_SPECULAR
)
966 mmio_index
|= VERT_SPEC
;
967 if (smesa
->AGPParseSet
& SiS_PS_HAS_W
)
968 mmio_index
|= VERT_W
;
969 if (smesa
->AGPParseSet
& SiS_PS_HAS_UV0
)
970 mmio_index
|= VERT_UV0
;
971 if (smesa
->AGPParseSet
& SiS_PS_HAS_UV1
)
972 mmio_index
|= VERT_UV1
;
974 mmio_index
|= VERT_6326
;
976 switch (smesa
->AGPParseSet
& MASK_PsDataType
) {
977 case MASK_PsPointList
:
978 incr
= smesa
->vertex_size
* 4;
979 sis_emit_func
= sis_point_func_mmio
[mmio_index
];
981 case MASK_PsLineList
:
982 incr
= smesa
->vertex_size
* 4 * 2;
983 sis_emit_func
= sis_line_func_mmio
[mmio_index
];
985 case MASK_PsTriangleList
:
986 incr
= smesa
->vertex_size
* 4 * 3;
987 sis_emit_func
= sis_tri_func_mmio
[mmio_index
];
991 if (!smesa
->is6326
) {
993 MMIO(REG_3D_PrimitiveSet
, smesa
->dwPrimitiveSet
);
995 while (smesa
->vb_last
< smesa
->vb_cur
) {
996 assert(sis_emit_func
);
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
;