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 CTX_ARG2 smesa
102 #define GET_VERTEX_DWORDS() smesa->vertex_size
103 #define ALLOC_VERTS( n, size ) sisAllocDmaLow( smesa, n * size * sizeof(int) )
106 sisContextPtr smesa = SIS_CONTEXT(ctx); \
107 const char *vertptr = smesa->verts;
108 #define VERT(x) (sisVertex *)(vertptr + (x * vertsize * sizeof(int)))
109 #define VERTEX sisVertex
111 #define TAG(x) sis_##x
112 #include "tnl_dd/t_dd_triemit.h"
116 /***********************************************************************
117 * Dispatch vertices to hardware through MMIO *
118 ***********************************************************************/
120 /* The ARGB write of the last vertex of the primitive fires the 3d engine, so
121 * save it until the end.
123 #define SIS_MMIO_WRITE_VERTEX(_v, i, lastvert) \
125 GLuint __color, __i = 0; \
126 MMIO(REG_3D_TSXa+(i)*0x30, _v->ui[__i++]); \
127 MMIO(REG_3D_TSYa+(i)*0x30, _v->ui[__i++]); \
128 MMIO(REG_3D_TSZa+(i)*0x30, _v->ui[__i++]); \
129 if (SIS_STATES & VERT_W) \
130 MMIO(REG_3D_TSWGa+(i)*0x30, _v->ui[__i++]); \
131 __color = _v->ui[__i++]; \
132 if (SIS_STATES & VERT_SPEC) \
133 MMIO(REG_3D_TSFSa+(i)*0x30, _v->ui[__i++]); \
134 if (SIS_STATES & VERT_UV0) { \
135 MMIO(REG_3D_TSUAa+(i)*0x30, _v->ui[__i++]); \
136 MMIO(REG_3D_TSVAa+(i)*0x30, _v->ui[__i++]); \
138 if (SIS_STATES & VERT_UV1) { \
139 MMIO(REG_3D_TSUBa+(i)*0x30, _v->ui[__i++]); \
140 MMIO(REG_3D_TSVBa+(i)*0x30, _v->ui[__i++]); \
142 if (lastvert || (SIS_STATES & VERT_SMOOTH)) \
143 MMIO(REG_3D_TSARGBa+(i)*0x30, __color); \
146 #define MMIO_VERT_REG_COUNT 10
148 #define VERT_SMOOTH 0x01
150 #define VERT_SPEC 0x04
151 #define VERT_UV0 0x08
152 #define VERT_UV1 0x10
154 typedef void (*mmio_draw_func
)(sisContextPtr smesa
, char *verts
);
155 static mmio_draw_func sis_tri_func_mmio
[32];
156 static mmio_draw_func sis_line_func_mmio
[32];
157 static mmio_draw_func sis_point_func_mmio
[32];
159 #define SIS_STATES (0)
160 #define TAG(x) x##_none
161 #include "sis_tritmp.h"
163 #define SIS_STATES (VERT_SMOOTH)
165 #include "sis_tritmp.h"
167 #define SIS_STATES (VERT_W)
169 #include "sis_tritmp.h"
171 #define SIS_STATES (VERT_SMOOTH | VERT_W)
172 #define TAG(x) x##_gw
173 #include "sis_tritmp.h"
175 #define SIS_STATES (VERT_SPEC)
177 #include "sis_tritmp.h"
179 #define SIS_STATES (VERT_SMOOTH | VERT_SPEC)
180 #define TAG(x) x##_gs
181 #include "sis_tritmp.h"
183 #define SIS_STATES (VERT_W | VERT_SPEC)
184 #define TAG(x) x##_ws
185 #include "sis_tritmp.h"
187 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC)
188 #define TAG(x) x##_gws
189 #include "sis_tritmp.h"
191 #define SIS_STATES (VERT_UV0)
192 #define TAG(x) x##_t0
193 #include "sis_tritmp.h"
195 #define SIS_STATES (VERT_SMOOTH | VERT_UV0)
196 #define TAG(x) x##_gt0
197 #include "sis_tritmp.h"
199 #define SIS_STATES (VERT_W | VERT_UV0)
200 #define TAG(x) x##_wt0
201 #include "sis_tritmp.h"
203 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_UV0)
204 #define TAG(x) x##_gwt0
205 #include "sis_tritmp.h"
207 #define SIS_STATES (VERT_SPEC | VERT_UV0)
208 #define TAG(x) x##_st0
209 #include "sis_tritmp.h"
211 #define SIS_STATES (VERT_SMOOTH | VERT_SPEC | VERT_UV0)
212 #define TAG(x) x##_gst0
213 #include "sis_tritmp.h"
215 #define SIS_STATES (VERT_W | VERT_SPEC | VERT_UV0)
216 #define TAG(x) x##_wst0
217 #include "sis_tritmp.h"
219 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC | VERT_UV0)
220 #define TAG(x) x##_gwst0
221 #include "sis_tritmp.h"
223 #define SIS_STATES (VERT_UV1)
224 #define TAG(x) x##_t1
225 #include "sis_tritmp.h"
227 #define SIS_STATES (VERT_SMOOTH | VERT_UV1)
228 #define TAG(x) x##_gt1
229 #include "sis_tritmp.h"
231 #define SIS_STATES (VERT_W | VERT_UV1)
232 #define TAG(x) x##_wt1
233 #include "sis_tritmp.h"
235 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_UV1)
236 #define TAG(x) x##_gwt1
237 #include "sis_tritmp.h"
239 #define SIS_STATES (VERT_SPEC | VERT_UV1)
240 #define TAG(x) x##_st1
241 #include "sis_tritmp.h"
243 #define SIS_STATES (VERT_SMOOTH | VERT_SPEC | VERT_UV1)
244 #define TAG(x) x##_gst1
245 #include "sis_tritmp.h"
247 #define SIS_STATES (VERT_W | VERT_SPEC | VERT_UV1)
248 #define TAG(x) x##_wst1
249 #include "sis_tritmp.h"
251 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC | VERT_UV1)
252 #define TAG(x) x##_gwst1
253 #include "sis_tritmp.h"
255 #define SIS_STATES (VERT_UV0 | VERT_UV1)
256 #define TAG(x) x##_t0t1
257 #include "sis_tritmp.h"
259 #define SIS_STATES (VERT_SMOOTH | VERT_UV0 | VERT_UV1)
260 #define TAG(x) x##_gt0t1
261 #include "sis_tritmp.h"
263 #define SIS_STATES (VERT_W | VERT_UV0 | VERT_UV1)
264 #define TAG(x) x##_wt0t1
265 #include "sis_tritmp.h"
267 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_UV0 | VERT_UV1)
268 #define TAG(x) x##_gwt0t1
269 #include "sis_tritmp.h"
271 #define SIS_STATES (VERT_SPEC | VERT_UV0 | VERT_UV1)
272 #define TAG(x) x##_st0t1
273 #include "sis_tritmp.h"
275 #define SIS_STATES (VERT_SMOOTH | VERT_SPEC | VERT_UV0 | VERT_UV1)
276 #define TAG(x) x##_gst0t1
277 #include "sis_tritmp.h"
279 #define SIS_STATES (VERT_W | VERT_SPEC | VERT_UV0 | VERT_UV1)
280 #define TAG(x) x##_wst0t1
281 #include "sis_tritmp.h"
283 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC | VERT_UV0 | VERT_UV1)
284 #define TAG(x) x##_gwst0t1
285 #include "sis_tritmp.h"
287 /***********************************************************************
288 * Macros for t_dd_tritmp.h to draw basic primitives *
289 ***********************************************************************/
291 #define TRI( a, b, c ) \
294 smesa->draw_tri( smesa, a, b, c ); \
296 sis_triangle( smesa, a, b, c ); \
299 #define QUAD( a, b, c, d ) \
302 smesa->draw_tri( smesa, a, b, d ); \
303 smesa->draw_tri( smesa, b, c, d ); \
305 sis_quad( smesa, a, b, c, d ); \
308 #define LINE( v0, v1 ) \
311 smesa->draw_line( smesa, v0, v1 ); \
313 sis_line( smesa, v0, v1 ); \
316 #define POINT( v0 ) \
319 smesa->draw_point( smesa, v0 ); \
321 sis_point( smesa, v0 ); \
324 /***********************************************************************
325 * Build render functions from dd templates *
326 ***********************************************************************/
328 #define SIS_OFFSET_BIT 0x01
329 #define SIS_TWOSIDE_BIT 0x02
330 #define SIS_UNFILLED_BIT 0x04
331 #define SIS_FALLBACK_BIT 0x08
332 #define SIS_MAX_TRIFUNC 0x10
338 triangle_func triangle
;
340 } rast_tab
[SIS_MAX_TRIFUNC
];
343 #define DO_FALLBACK (IND & SIS_FALLBACK_BIT)
344 #define DO_OFFSET (IND & SIS_OFFSET_BIT)
345 #define DO_UNFILLED (IND & SIS_UNFILLED_BIT)
346 #define DO_TWOSIDE (IND & SIS_TWOSIDE_BIT)
352 #define DO_FULL_QUAD 1
356 #define HAVE_BACK_COLORS 0
357 #define HAVE_HW_FLATSHADE 1
358 #define VERTEX sisVertex
361 #define DEPTH_SCALE smesa->depth_scale
362 #define UNFILLED_TRI unfilled_tri
363 #define UNFILLED_QUAD unfilled_quad
364 #define VERT_X(_v) _v->v.x
365 #define VERT_Y(_v) _v->v.y
366 #define VERT_Z(_v) _v->v.z
367 #define AREA_IS_CCW( a ) (a > 0)
368 #define GET_VERTEX(e) (smesa->verts + (e * smesa->vertex_size * sizeof(int)))
370 #define VERT_SET_RGBA( v, c ) \
372 sis_color_t *color = (sis_color_t *)&((v)->ui[coloroffset]); \
373 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
374 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
375 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
376 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
379 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
381 #define VERT_SET_SPEC( v0, c ) \
384 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.red, (c)[0]); \
385 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.green, (c)[1]); \
386 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.blue, (c)[2]); \
389 #define VERT_COPY_SPEC( v0, v1 ) \
392 v0->v.specular.red = v1->v.specular.red; \
393 v0->v.specular.green = v1->v.specular.green; \
394 v0->v.specular.blue = v1->v.specular.blue; \
398 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
399 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
400 #define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5]
401 #define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx]
403 #define LOCAL_VARS(n) \
404 sisContextPtr smesa = SIS_CONTEXT(ctx); \
405 GLuint color[n], spec[n]; \
406 GLuint coloroffset = (smesa->vertex_size == 4 ? 3 : 4); \
407 GLboolean havespec = (smesa->vertex_size == 4 ? 0 : 1); \
408 (void) color; (void) spec; (void) coloroffset; (void) havespec;
410 /***********************************************************************
411 * Helpers for rendering unfilled primitives *
412 ***********************************************************************/
414 #define RASTERIZE(x) if (smesa->hw_primitive != hw_prim[x]) \
415 sisRasterPrimitive( ctx, hw_prim[x] )
416 #define RENDER_PRIMITIVE smesa->render_primitive
417 #define IND SIS_FALLBACK_BIT
419 #include "tnl_dd/t_dd_unfilled.h"
423 /***********************************************************************
424 * Generate GL render functions *
425 ***********************************************************************/
430 #include "tnl_dd/t_dd_tritmp.h"
432 #define IND (SIS_OFFSET_BIT)
433 #define TAG(x) x##_offset
434 #include "tnl_dd/t_dd_tritmp.h"
436 #define IND (SIS_TWOSIDE_BIT)
437 #define TAG(x) x##_twoside
438 #include "tnl_dd/t_dd_tritmp.h"
440 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT)
441 #define TAG(x) x##_twoside_offset
442 #include "tnl_dd/t_dd_tritmp.h"
444 #define IND (SIS_UNFILLED_BIT)
445 #define TAG(x) x##_unfilled
446 #include "tnl_dd/t_dd_tritmp.h"
448 #define IND (SIS_OFFSET_BIT|SIS_UNFILLED_BIT)
449 #define TAG(x) x##_offset_unfilled
450 #include "tnl_dd/t_dd_tritmp.h"
452 #define IND (SIS_TWOSIDE_BIT|SIS_UNFILLED_BIT)
453 #define TAG(x) x##_twoside_unfilled
454 #include "tnl_dd/t_dd_tritmp.h"
456 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT|SIS_UNFILLED_BIT)
457 #define TAG(x) x##_twoside_offset_unfilled
458 #include "tnl_dd/t_dd_tritmp.h"
460 #define IND (SIS_FALLBACK_BIT)
461 #define TAG(x) x##_fallback
462 #include "tnl_dd/t_dd_tritmp.h"
464 #define IND (SIS_OFFSET_BIT|SIS_FALLBACK_BIT)
465 #define TAG(x) x##_offset_fallback
466 #include "tnl_dd/t_dd_tritmp.h"
468 #define IND (SIS_TWOSIDE_BIT|SIS_FALLBACK_BIT)
469 #define TAG(x) x##_twoside_fallback
470 #include "tnl_dd/t_dd_tritmp.h"
472 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT|SIS_FALLBACK_BIT)
473 #define TAG(x) x##_twoside_offset_fallback
474 #include "tnl_dd/t_dd_tritmp.h"
476 #define IND (SIS_UNFILLED_BIT|SIS_FALLBACK_BIT)
477 #define TAG(x) x##_unfilled_fallback
478 #include "tnl_dd/t_dd_tritmp.h"
480 #define IND (SIS_OFFSET_BIT|SIS_UNFILLED_BIT|SIS_FALLBACK_BIT)
481 #define TAG(x) x##_offset_unfilled_fallback
482 #include "tnl_dd/t_dd_tritmp.h"
484 #define IND (SIS_TWOSIDE_BIT|SIS_UNFILLED_BIT|SIS_FALLBACK_BIT)
485 #define TAG(x) x##_twoside_unfilled_fallback
486 #include "tnl_dd/t_dd_tritmp.h"
488 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT|SIS_UNFILLED_BIT| \
490 #define TAG(x) x##_twoside_offset_unfilled_fallback
491 #include "tnl_dd/t_dd_tritmp.h"
494 static void init_rast_tab( void )
499 init_twoside_offset();
501 init_offset_unfilled();
502 init_twoside_unfilled();
503 init_twoside_offset_unfilled();
505 init_offset_fallback();
506 init_twoside_fallback();
507 init_twoside_offset_fallback();
508 init_unfilled_fallback();
509 init_offset_unfilled_fallback();
510 init_twoside_unfilled_fallback();
511 init_twoside_offset_unfilled_fallback();
516 /***********************************************************************
517 * Rasterization fallback helpers *
518 ***********************************************************************/
521 /* This code is hit only when a mix of accelerated and unaccelerated
522 * primitives are being drawn, and only for the unaccelerated
527 sis_fallback_tri( sisContextPtr smesa
,
532 GLcontext
*ctx
= smesa
->glCtx
;
534 _swsetup_Translate( ctx
, v0
, &v
[0] );
535 _swsetup_Translate( ctx
, v1
, &v
[1] );
536 _swsetup_Translate( ctx
, v2
, &v
[2] );
537 sisSpanRenderStart( ctx
);
538 _swrast_Triangle( ctx
, &v
[0], &v
[1], &v
[2] );
539 sisSpanRenderFinish( ctx
);
540 _swrast_flush( ctx
);
545 sis_fallback_line( sisContextPtr smesa
,
549 GLcontext
*ctx
= smesa
->glCtx
;
551 _swsetup_Translate( ctx
, v0
, &v
[0] );
552 _swsetup_Translate( ctx
, v1
, &v
[1] );
553 sisSpanRenderStart( ctx
);
554 _swrast_Line( ctx
, &v
[0], &v
[1] );
555 sisSpanRenderFinish( ctx
);
556 _swrast_flush( ctx
);
561 sis_fallback_point( sisContextPtr smesa
,
564 GLcontext
*ctx
= smesa
->glCtx
;
566 _swsetup_Translate( ctx
, v0
, &v
[0] );
567 sisSpanRenderStart( ctx
);
568 _swrast_Point( ctx
, &v
[0] );
569 sisSpanRenderFinish( ctx
);
570 _swrast_flush( ctx
);
575 /**********************************************************************/
576 /* Render unclipped begin/end objects */
577 /**********************************************************************/
580 #define V(x) (sisVertex *)(vertptr + (x * vertsize * sizeof(int)))
581 #define RENDER_POINTS( start, count ) \
582 for ( ; start < count ; start++) \
583 POINT( V(ELT(start)) )
584 #define RENDER_LINE( v0, v1 ) LINE( V(v0), V(v1) )
585 #define RENDER_TRI( v0, v1, v2 ) TRI( V(v0), V(v1), V(v2) )
586 #define RENDER_QUAD( v0, v1, v2, v3 ) QUAD( V(v0), V(v1), V(v2), V(v3) )
587 #define INIT(x) sisRenderPrimitive( ctx, x )
590 sisContextPtr smesa = SIS_CONTEXT(ctx); \
591 const GLuint vertsize = smesa->vertex_size; \
592 const char *vertptr = (char *)smesa->verts; \
593 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
595 #define RESET_STIPPLE
596 #define RESET_OCCLUSION
597 #define PRESERVE_VB_DEFS
599 #define TAG(x) sis_##x##_verts
600 #include "tnl/t_vb_rendertmp.h"
603 #define TAG(x) sis_##x##_elts
604 #define ELT(x) elt[x]
605 #include "tnl/t_vb_rendertmp.h"
608 /**********************************************************************/
609 /* Choose render functions */
610 /**********************************************************************/
612 #define _SIS_NEW_RENDER_STATE (_DD_NEW_LINE_STIPPLE | \
613 _DD_NEW_LINE_SMOOTH | \
614 _DD_NEW_POINT_SMOOTH | \
615 _DD_NEW_TRI_SMOOTH | \
616 _DD_NEW_TRI_UNFILLED | \
617 _DD_NEW_TRI_LIGHT_TWOSIDE | \
618 _DD_NEW_TRI_OFFSET) \
621 #define POINT_FALLBACK (DD_POINT_SMOOTH)
622 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
623 #define TRI_FALLBACK (DD_TRI_SMOOTH)
624 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
625 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
628 static void sisChooseRenderState(GLcontext
*ctx
)
630 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
631 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
632 GLuint flags
= ctx
->_TriangleCaps
;
635 if (flags
& (ANY_RASTER_FLAGS
|ANY_FALLBACK_FLAGS
)) {
637 if (flags
& ANY_RASTER_FLAGS
) {
638 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= SIS_TWOSIDE_BIT
;
639 if (flags
& DD_TRI_OFFSET
) index
|= SIS_OFFSET_BIT
;
640 if (flags
& DD_TRI_UNFILLED
) index
|= SIS_UNFILLED_BIT
;
643 smesa
->draw_point
= sis_point
;
644 smesa
->draw_line
= sis_line
;
645 smesa
->draw_tri
= sis_triangle
;
646 /* Hook in fallbacks for specific primitives.
648 if (flags
& ANY_FALLBACK_FLAGS
) {
649 if (flags
& POINT_FALLBACK
)
650 smesa
->draw_point
= sis_fallback_point
;
651 if (flags
& LINE_FALLBACK
)
652 smesa
->draw_line
= sis_fallback_line
;
653 if (flags
& TRI_FALLBACK
)
654 smesa
->draw_tri
= sis_fallback_tri
;
655 index
|= SIS_FALLBACK_BIT
;
659 if (index
!= smesa
->RenderIndex
) {
660 smesa
->RenderIndex
= index
;
662 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
663 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
664 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
665 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
666 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
669 tnl
->Driver
.Render
.PrimTabVerts
= sis_render_tab_verts
;
670 tnl
->Driver
.Render
.PrimTabElts
= sis_render_tab_elts
;
671 tnl
->Driver
.Render
.ClippedPolygon
= sis_fast_clipped_poly
;
673 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
674 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
675 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
680 /**********************************************************************/
681 /* Multipass rendering for front buffering */
682 /**********************************************************************/
683 static GLboolean
multipass_cliprect( GLcontext
*ctx
, GLuint pass
)
685 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
687 if (pass
>= smesa
->driDrawable
->numClipRects
) {
690 GLint x1
, y1
, x2
, y2
;
692 x1
= smesa
->driDrawable
->pClipRects
[pass
].x1
- smesa
->driDrawable
->x
;
693 y1
= smesa
->driDrawable
->pClipRects
[pass
].y1
- smesa
->driDrawable
->y
;
694 x2
= smesa
->driDrawable
->pClipRects
[pass
].x2
- smesa
->driDrawable
->x
;
695 y2
= smesa
->driDrawable
->pClipRects
[pass
].y2
- smesa
->driDrawable
->y
;
697 if (ctx
->Scissor
.Enabled
) {
698 GLint scisy1
= Y_FLIP(ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
- 1);
699 GLint scisy2
= Y_FLIP(ctx
->Scissor
.Y
);
701 if (ctx
->Scissor
.X
> x1
)
705 if (ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1 < x2
)
706 x2
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
711 MMIO(REG_3D_ClipTopBottom
, y1
<< 13 | y2
);
712 MMIO(REG_3D_ClipLeftRight
, x1
<< 13 | x2
);
713 /* Mark that we clobbered these registers */
714 smesa
->GlobalFlag
|= GFLAG_CLIPPING
;
721 /**********************************************************************/
722 /* Validate state at pipeline start */
723 /**********************************************************************/
725 static void sisRunPipeline( GLcontext
*ctx
)
727 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
729 if (!smesa
->Fallback
&& smesa
->NewGLState
) {
730 if (smesa
->NewGLState
& _NEW_TEXTURE
) {
731 SIS_FIREVERTICES(smesa
);
732 sisUpdateTextureState(ctx
);
735 if (smesa
->NewGLState
& (_SIS_NEW_RENDER_STATE
| _NEW_TEXTURE
))
736 sisChooseRenderState( ctx
);
738 smesa
->NewGLState
= 0;
741 _tnl_run_pipeline( ctx
);
743 /* XXX: If we put flushing in sis_state.c and friends, we can avoid this.
746 SIS_FIREVERTICES(smesa
);
749 /**********************************************************************/
750 /* High level hooks for t_vb_render.c */
751 /**********************************************************************/
753 /* This is called when Mesa switches between rendering triangle
754 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
755 * and lines, points and bitmaps.
758 static void sisRasterPrimitive( GLcontext
*ctx
, GLuint hwprim
)
760 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
761 if (smesa
->hw_primitive
!= hwprim
) {
762 SIS_FIREVERTICES(smesa
);
763 smesa
->hw_primitive
= hwprim
;
764 smesa
->AGPParseSet
&= ~(MASK_PsDataType
| MASK_PsShadingMode
);
765 smesa
->dwPrimitiveSet
&= ~(MASK_DrawPrimitiveCommand
|
766 MASK_SetFirePosition
| MASK_ShadingMode
);
767 smesa
->AGPParseSet
|= hw_prim_agp_type
[hwprim
];
768 smesa
->dwPrimitiveSet
|= hwprim
| hw_prim_mmio_fire
[hwprim
];
769 if (ctx
->Light
.ShadeModel
== GL_FLAT
) {
770 smesa
->AGPParseSet
|= hw_prim_agp_shade
[hwprim
];
771 smesa
->dwPrimitiveSet
|= hw_prim_mmio_shade
[hwprim
];
773 smesa
->AGPParseSet
|= MASK_PsShadingSmooth
;
774 smesa
->dwPrimitiveSet
|= SHADE_GOURAUD
;
779 static void sisRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
781 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
783 smesa
->render_primitive
= prim
;
785 if (prim
>= GL_TRIANGLES
&& (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
787 sisRasterPrimitive( ctx
, hw_prim
[prim
] );
790 #define EMIT_ATTR( ATTR, STYLE) \
792 smesa->vertex_attrs[smesa->vertex_attr_count].attrib = (ATTR); \
793 smesa->vertex_attrs[smesa->vertex_attr_count].format = (STYLE); \
794 smesa->vertex_attr_count++; \
797 #define EMIT_PAD( N ) \
799 smesa->vertex_attrs[smesa->vertex_attr_count].attrib = 0; \
800 smesa->vertex_attrs[smesa->vertex_attr_count].format = EMIT_PAD; \
801 smesa->vertex_attrs[smesa->vertex_attr_count].offset = (N); \
802 smesa->vertex_attr_count++; \
805 #define SIS_TCL_STATE_BITS \
806 (_TNL_BITS_TEX_ANY | _TNL_BIT_COLOR1 | _TNL_BIT_FOG)
808 static void sisRenderStart( GLcontext
*ctx
)
810 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
811 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
812 struct vertex_buffer
*VB
= &tnl
->vb
;
813 GLuint index
= tnl
->render_inputs
;
814 GLuint AGPParseSet
= smesa
->AGPParseSet
;
815 GLboolean tex_fallback
= GL_FALSE
;
817 if (ctx
->Color
._DrawDestMask
== DD_FRONT_LEFT_BIT
&&
818 smesa
->driDrawable
->numClipRects
!= 0)
820 multipass_cliprect(ctx
, 0);
821 if (smesa
->driDrawable
->numClipRects
> 1)
822 tnl
->Driver
.Render
.Multipass
= multipass_cliprect
;
824 tnl
->Driver
.Render
.Multipass
= NULL
;
826 tnl
->Driver
.Render
.Multipass
= NULL
;
831 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->NdcPtr
;
832 smesa
->vertex_attr_count
= 0;
834 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to build up a
838 AGPParseSet
&= ~(MASK_VertexDWSize
| MASK_VertexDataFormat
);
839 AGPParseSet
|= SiS_PS_HAS_XYZ
| SiS_PS_HAS_DIFFUSE
;
840 if (index
& _TNL_BITS_TEX_ANY
) {
841 EMIT_ATTR(_TNL_ATTRIB_POS
, EMIT_4F_VIEWPORT
);
842 AGPParseSet
|= SiS_PS_HAS_W
;
844 EMIT_ATTR(_TNL_ATTRIB_POS
, EMIT_3F_VIEWPORT
);
847 EMIT_ATTR(_TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_BGRA
);
849 if (index
& (_TNL_BIT_COLOR1
|_TNL_BIT_FOG
)) {
850 AGPParseSet
|= SiS_PS_HAS_SPECULAR
;
852 if (index
& _TNL_BIT_COLOR1
) {
853 EMIT_ATTR(_TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_BGR
);
858 if (index
& _TNL_BIT_FOG
)
859 EMIT_ATTR(_TNL_ATTRIB_FOG
, EMIT_1UB_1F
);
864 /* projective textures are not supported by the hardware */
865 if (index
& _TNL_BIT_TEX(0)) {
866 if (VB
->TexCoordPtr
[0]->size
> 2)
867 tex_fallback
= GL_TRUE
;
868 EMIT_ATTR(_TNL_ATTRIB_TEX0
, EMIT_2F
);
869 AGPParseSet
|= SiS_PS_HAS_UV0
;
871 if (index
& _TNL_BIT_TEX(1)) {
872 if (VB
->TexCoordPtr
[1]->size
> 2)
873 tex_fallback
= GL_TRUE
;
874 EMIT_ATTR(_TNL_ATTRIB_TEX1
, EMIT_2F
);
875 AGPParseSet
|= SiS_PS_HAS_UV1
;
877 FALLBACK(smesa
, SIS_FALLBACK_TEXTURE
, tex_fallback
);
879 if (smesa
->last_tcl_state
!= index
) {
880 smesa
->AGPParseSet
= AGPParseSet
;
882 smesa
->vertex_size
= _tnl_install_attrs( ctx
, smesa
->vertex_attrs
,
883 smesa
->vertex_attr_count
, smesa
->hw_viewport
, 0 );
885 smesa
->vertex_size
>>= 2;
886 smesa
->AGPParseSet
|= smesa
->vertex_size
<< 28;
890 static void sisRenderFinish( GLcontext
*ctx
)
894 /**********************************************************************/
895 /* AGP/PCI vertex submission */
896 /**********************************************************************/
899 sisFlushPrimsLocked(sisContextPtr smesa
)
903 sisUpdateHWState(smesa
->glCtx
);
905 if (smesa
->using_agp
) {
908 MMIO(REG_3D_AGPCmBase
, (smesa
->vb_last
- smesa
->vb
) +
909 smesa
->vb_agp_offset
);
910 MMIO(REG_3D_AGPTtDwNum
, (smesa
->vb_cur
- smesa
->vb_last
) / 4 |
912 MMIO(REG_3D_ParsingSet
, smesa
->AGPParseSet
);
913 MMIO(REG_3D_AGPCmFire
, (GLint
)(-1));
916 int mmio_index
= 0, incr
= 0;
917 void (*emit_func
)(sisContextPtr smesa
, char *verts
) = NULL
;
919 if (smesa
->AGPParseSet
& MASK_PsShadingSmooth
)
920 mmio_index
|= VERT_SMOOTH
;
921 if (smesa
->AGPParseSet
& SiS_PS_HAS_SPECULAR
)
922 mmio_index
|= VERT_SPEC
;
923 if (smesa
->AGPParseSet
& SiS_PS_HAS_W
)
924 mmio_index
|= VERT_W
;
925 if (smesa
->AGPParseSet
& SiS_PS_HAS_UV0
)
926 mmio_index
|= VERT_UV0
;
927 if (smesa
->AGPParseSet
& SiS_PS_HAS_UV1
)
928 mmio_index
|= VERT_UV1
;
930 switch (smesa
->AGPParseSet
& MASK_PsDataType
) {
931 case MASK_PsPointList
:
932 incr
= smesa
->vertex_size
* 4;
933 emit_func
= sis_point_func_mmio
[mmio_index
];
935 case MASK_PsLineList
:
936 incr
= smesa
->vertex_size
* 4 * 2;
937 emit_func
= sis_line_func_mmio
[mmio_index
];
939 case MASK_PsTriangleList
:
940 incr
= smesa
->vertex_size
* 4 * 3;
941 emit_func
= sis_tri_func_mmio
[mmio_index
];
946 MMIO(REG_3D_PrimitiveSet
, smesa
->dwPrimitiveSet
);
947 while (smesa
->vb_last
< smesa
->vb_cur
) {
948 emit_func(smesa
, smesa
->vb_last
);
949 smesa
->vb_last
+= incr
;
954 /* With PCI, we can just start writing to the start of the VB again. */
955 smesa
->vb_cur
= smesa
->vb
;
957 smesa
->vb_last
= smesa
->vb_cur
;
960 void sisFlushPrims(sisContextPtr smesa
)
963 sisFlushPrimsLocked(smesa
);
967 /**********************************************************************/
968 /* Transition to/from hardware rasterization. */
969 /**********************************************************************/
971 void sisFallback( GLcontext
*ctx
, GLuint bit
, GLboolean mode
)
973 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
974 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
975 GLuint oldfallback
= smesa
->Fallback
;
978 smesa
->Fallback
|= bit
;
979 if (oldfallback
== 0) {
980 SIS_FIREVERTICES(smesa
);
981 _swsetup_Wakeup( ctx
);
982 smesa
->RenderIndex
= ~0;
986 smesa
->Fallback
&= ~bit
;
987 if (oldfallback
== bit
) {
988 _swrast_flush( ctx
);
989 tnl
->Driver
.Render
.Start
= sisRenderStart
;
990 tnl
->Driver
.Render
.PrimitiveNotify
= sisRenderPrimitive
;
991 tnl
->Driver
.Render
.Finish
= sisRenderFinish
;
993 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
994 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
995 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
997 _tnl_invalidate_vertex_state( ctx
, ~0 );
998 _tnl_invalidate_vertices( ctx
, ~0 );
999 _tnl_install_attrs( ctx
,
1000 smesa
->vertex_attrs
,
1001 smesa
->vertex_attr_count
,
1002 smesa
->hw_viewport
, 0 );
1004 smesa
->NewGLState
|= _SIS_NEW_RENDER_STATE
;
1010 /**********************************************************************/
1011 /* Initialization. */
1012 /**********************************************************************/
1014 void sisInitTriFuncs( GLcontext
*ctx
)
1016 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
1017 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1018 static int firsttime
= 1;
1024 sis_vert_init_none();
1031 sis_vert_init_gws();
1033 sis_vert_init_gt0();
1034 sis_vert_init_wt0();
1035 sis_vert_init_gwt0();
1036 sis_vert_init_st0();
1037 sis_vert_init_gst0();
1038 sis_vert_init_wst0();
1039 sis_vert_init_gwst0();
1041 sis_vert_init_gt1();
1042 sis_vert_init_wt1();
1043 sis_vert_init_gwt1();
1044 sis_vert_init_st1();
1045 sis_vert_init_gst1();
1046 sis_vert_init_wst1();
1047 sis_vert_init_gwst1();
1048 sis_vert_init_t0t1();
1049 sis_vert_init_gt0t1();
1050 sis_vert_init_wt0t1();
1051 sis_vert_init_gwt0t1();
1052 sis_vert_init_st0t1();
1053 sis_vert_init_gst0t1();
1054 sis_vert_init_wst0t1();
1055 sis_vert_init_gwst0t1();
1058 if (driQueryOptionb(&smesa
->optionCache
, "fallback_force"))
1059 sisFallback(ctx
, SIS_FALLBACK_FORCE
, 1);
1061 sisFallback(ctx
, SIS_FALLBACK_FORCE
, 0);
1063 smesa
->RenderIndex
= ~0;
1064 smesa
->NewGLState
|= _SIS_NEW_RENDER_STATE
;
1066 tnl
->Driver
.RunPipeline
= sisRunPipeline
;
1067 tnl
->Driver
.Render
.Start
= sisRenderStart
;
1068 tnl
->Driver
.Render
.Finish
= sisRenderFinish
;
1069 tnl
->Driver
.Render
.PrimitiveNotify
= sisRenderPrimitive
;
1070 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1072 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
1073 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
1074 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
1076 _tnl_init_vertices( ctx
, ctx
->Const
.MaxArrayLockSize
+ 12,
1077 (6 + 2*ctx
->Const
.MaxTextureUnits
) * sizeof(GLfloat
) );
1079 smesa
->verts
= (char *)tnl
->clipspace
.vertex_buf
;