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
336 tnl_points_func points
;
338 tnl_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 POINT_FALLBACK (DD_POINT_SMOOTH)
613 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
614 #define TRI_FALLBACK (DD_TRI_STIPPLE|DD_TRI_SMOOTH)
615 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
616 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
617 #define _SIS_NEW_RENDER_STATE (ANY_RASTER_FLAGS | ANY_FALLBACK_FLAGS)
619 static void sisChooseRenderState(GLcontext
*ctx
)
621 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
622 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
623 GLuint flags
= ctx
->_TriangleCaps
;
626 if (flags
& (ANY_RASTER_FLAGS
|ANY_FALLBACK_FLAGS
)) {
628 if (flags
& ANY_RASTER_FLAGS
) {
629 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= SIS_TWOSIDE_BIT
;
630 if (flags
& DD_TRI_OFFSET
) index
|= SIS_OFFSET_BIT
;
631 if (flags
& DD_TRI_UNFILLED
) index
|= SIS_UNFILLED_BIT
;
634 smesa
->draw_point
= sis_point
;
635 smesa
->draw_line
= sis_line
;
636 smesa
->draw_tri
= sis_triangle
;
637 /* Hook in fallbacks for specific primitives.
639 if (flags
& ANY_FALLBACK_FLAGS
) {
640 if (flags
& POINT_FALLBACK
)
641 smesa
->draw_point
= sis_fallback_point
;
642 if (flags
& LINE_FALLBACK
)
643 smesa
->draw_line
= sis_fallback_line
;
644 if (flags
& TRI_FALLBACK
)
645 smesa
->draw_tri
= sis_fallback_tri
;
646 index
|= SIS_FALLBACK_BIT
;
650 if (index
!= smesa
->RenderIndex
) {
651 smesa
->RenderIndex
= index
;
653 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
654 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
655 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
656 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
657 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
660 tnl
->Driver
.Render
.PrimTabVerts
= sis_render_tab_verts
;
661 tnl
->Driver
.Render
.PrimTabElts
= sis_render_tab_elts
;
662 tnl
->Driver
.Render
.ClippedPolygon
= sis_fast_clipped_poly
;
664 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
665 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
666 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
671 /**********************************************************************/
672 /* Multipass rendering for front buffering */
673 /**********************************************************************/
674 static GLboolean
multipass_cliprect( GLcontext
*ctx
, GLuint pass
)
676 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
678 if (pass
>= smesa
->driDrawable
->numClipRects
) {
681 GLint x1
, y1
, x2
, y2
;
683 x1
= smesa
->driDrawable
->pClipRects
[pass
].x1
- smesa
->driDrawable
->x
;
684 y1
= smesa
->driDrawable
->pClipRects
[pass
].y1
- smesa
->driDrawable
->y
;
685 x2
= smesa
->driDrawable
->pClipRects
[pass
].x2
- smesa
->driDrawable
->x
;
686 y2
= smesa
->driDrawable
->pClipRects
[pass
].y2
- smesa
->driDrawable
->y
;
688 if (ctx
->Scissor
.Enabled
) {
689 GLint scisy1
= Y_FLIP(ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
- 1);
690 GLint scisy2
= Y_FLIP(ctx
->Scissor
.Y
);
692 if (ctx
->Scissor
.X
> x1
)
696 if (ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1 < x2
)
697 x2
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
702 MMIO(REG_3D_ClipTopBottom
, y1
<< 13 | y2
);
703 MMIO(REG_3D_ClipLeftRight
, x1
<< 13 | x2
);
704 /* Mark that we clobbered these registers */
705 smesa
->GlobalFlag
|= GFLAG_CLIPPING
;
712 /**********************************************************************/
713 /* Validate state at pipeline start */
714 /**********************************************************************/
716 static void sisRunPipeline( GLcontext
*ctx
)
718 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
720 if (!smesa
->Fallback
&& smesa
->NewGLState
) {
721 if (smesa
->NewGLState
& _NEW_TEXTURE
) {
722 SIS_FIREVERTICES(smesa
);
723 sisUpdateTextureState(ctx
);
726 if (smesa
->NewGLState
& _SIS_NEW_RENDER_STATE
)
727 sisChooseRenderState( ctx
);
729 smesa
->NewGLState
= 0;
732 _tnl_run_pipeline( ctx
);
734 /* XXX: If we put flushing in sis_state.c and friends, we can avoid this.
737 SIS_FIREVERTICES(smesa
);
740 /**********************************************************************/
741 /* High level hooks for t_vb_render.c */
742 /**********************************************************************/
744 /* This is called when Mesa switches between rendering triangle
745 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
746 * and lines, points and bitmaps.
749 static void sisRasterPrimitive( GLcontext
*ctx
, GLuint hwprim
)
751 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
752 if (smesa
->hw_primitive
!= hwprim
) {
753 SIS_FIREVERTICES(smesa
);
754 smesa
->hw_primitive
= hwprim
;
755 smesa
->AGPParseSet
&= ~(MASK_PsDataType
| MASK_PsShadingMode
);
756 smesa
->dwPrimitiveSet
&= ~(MASK_DrawPrimitiveCommand
|
757 MASK_SetFirePosition
| MASK_ShadingMode
);
758 smesa
->AGPParseSet
|= hw_prim_agp_type
[hwprim
];
759 smesa
->dwPrimitiveSet
|= hwprim
| hw_prim_mmio_fire
[hwprim
];
760 if (ctx
->Light
.ShadeModel
== GL_FLAT
) {
761 smesa
->AGPParseSet
|= hw_prim_agp_shade
[hwprim
];
762 smesa
->dwPrimitiveSet
|= hw_prim_mmio_shade
[hwprim
];
764 smesa
->AGPParseSet
|= MASK_PsShadingSmooth
;
765 smesa
->dwPrimitiveSet
|= SHADE_GOURAUD
;
770 static void sisRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
772 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
774 smesa
->render_primitive
= prim
;
776 if (prim
>= GL_TRIANGLES
&& (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
778 sisRasterPrimitive( ctx
, hw_prim
[prim
] );
781 #define EMIT_ATTR( ATTR, STYLE) \
783 smesa->vertex_attrs[smesa->vertex_attr_count].attrib = (ATTR); \
784 smesa->vertex_attrs[smesa->vertex_attr_count].format = (STYLE); \
785 smesa->vertex_attr_count++; \
788 #define EMIT_PAD( N ) \
790 smesa->vertex_attrs[smesa->vertex_attr_count].attrib = 0; \
791 smesa->vertex_attrs[smesa->vertex_attr_count].format = EMIT_PAD; \
792 smesa->vertex_attrs[smesa->vertex_attr_count].offset = (N); \
793 smesa->vertex_attr_count++; \
796 #define SIS_TCL_STATE_BITS \
797 (_TNL_BITS_TEX_ANY | _TNL_BIT_COLOR1 | _TNL_BIT_FOG)
799 static void sisRenderStart( GLcontext
*ctx
)
801 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
802 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
803 struct vertex_buffer
*VB
= &tnl
->vb
;
804 GLuint index
= tnl
->render_inputs
;
805 GLuint AGPParseSet
= smesa
->AGPParseSet
;
806 GLboolean tex_fallback
= GL_FALSE
;
808 if (ctx
->Color
._DrawDestMask
[0] == DD_FRONT_LEFT_BIT
&&
809 smesa
->driDrawable
->numClipRects
!= 0)
811 multipass_cliprect(ctx
, 0);
812 if (smesa
->driDrawable
->numClipRects
> 1)
813 tnl
->Driver
.Render
.Multipass
= multipass_cliprect
;
815 tnl
->Driver
.Render
.Multipass
= NULL
;
817 tnl
->Driver
.Render
.Multipass
= NULL
;
822 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->NdcPtr
;
823 smesa
->vertex_attr_count
= 0;
825 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to build up a
829 AGPParseSet
&= ~(MASK_VertexDWSize
| MASK_VertexDataFormat
);
830 AGPParseSet
|= SiS_PS_HAS_XYZ
| SiS_PS_HAS_DIFFUSE
;
831 if (index
& _TNL_BITS_TEX_ANY
) {
832 EMIT_ATTR(_TNL_ATTRIB_POS
, EMIT_4F_VIEWPORT
);
833 AGPParseSet
|= SiS_PS_HAS_W
;
835 EMIT_ATTR(_TNL_ATTRIB_POS
, EMIT_3F_VIEWPORT
);
838 EMIT_ATTR(_TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_BGRA
);
840 if (index
& (_TNL_BIT_COLOR1
|_TNL_BIT_FOG
)) {
841 AGPParseSet
|= SiS_PS_HAS_SPECULAR
;
843 if (index
& _TNL_BIT_COLOR1
) {
844 EMIT_ATTR(_TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_BGR
);
849 if (index
& _TNL_BIT_FOG
)
850 EMIT_ATTR(_TNL_ATTRIB_FOG
, EMIT_1UB_1F
);
855 /* projective textures are not supported by the hardware */
856 if (index
& _TNL_BIT_TEX(0)) {
857 if (VB
->TexCoordPtr
[0]->size
> 2)
858 tex_fallback
= GL_TRUE
;
859 EMIT_ATTR(_TNL_ATTRIB_TEX0
, EMIT_2F
);
860 AGPParseSet
|= SiS_PS_HAS_UV0
;
862 if (index
& _TNL_BIT_TEX(1)) {
863 if (VB
->TexCoordPtr
[1]->size
> 2)
864 tex_fallback
= GL_TRUE
;
865 EMIT_ATTR(_TNL_ATTRIB_TEX1
, EMIT_2F
);
866 AGPParseSet
|= SiS_PS_HAS_UV1
;
868 FALLBACK(smesa
, SIS_FALLBACK_TEXTURE
, tex_fallback
);
870 if (smesa
->last_tcl_state
!= index
) {
871 smesa
->AGPParseSet
= AGPParseSet
;
873 smesa
->vertex_size
= _tnl_install_attrs( ctx
, smesa
->vertex_attrs
,
874 smesa
->vertex_attr_count
, smesa
->hw_viewport
, 0 );
876 smesa
->vertex_size
>>= 2;
877 smesa
->AGPParseSet
|= smesa
->vertex_size
<< 28;
881 static void sisRenderFinish( GLcontext
*ctx
)
885 /**********************************************************************/
886 /* AGP/PCI vertex submission */
887 /**********************************************************************/
890 sisFlushPrimsLocked(sisContextPtr smesa
)
892 if (smesa
->vb_cur
== smesa
->vb_last
)
895 sisUpdateHWState(smesa
->glCtx
);
897 if (smesa
->using_agp
) {
900 MMIO(REG_3D_AGPCmBase
, (smesa
->vb_last
- smesa
->vb
) +
901 smesa
->vb_agp_offset
);
902 MMIO(REG_3D_AGPTtDwNum
, ((smesa
->vb_cur
- smesa
->vb_last
) / 4) |
904 MMIO(REG_3D_ParsingSet
, smesa
->AGPParseSet
);
905 MMIO(REG_3D_AGPCmFire
, (GLint
)(-1));
908 int mmio_index
= 0, incr
= 0;
909 void (*sis_emit_func
)(sisContextPtr smesa
, char *verts
) = NULL
;
911 if (smesa
->AGPParseSet
& MASK_PsShadingSmooth
)
912 mmio_index
|= VERT_SMOOTH
;
913 if (smesa
->AGPParseSet
& SiS_PS_HAS_SPECULAR
)
914 mmio_index
|= VERT_SPEC
;
915 if (smesa
->AGPParseSet
& SiS_PS_HAS_W
)
916 mmio_index
|= VERT_W
;
917 if (smesa
->AGPParseSet
& SiS_PS_HAS_UV0
)
918 mmio_index
|= VERT_UV0
;
919 if (smesa
->AGPParseSet
& SiS_PS_HAS_UV1
)
920 mmio_index
|= VERT_UV1
;
922 switch (smesa
->AGPParseSet
& MASK_PsDataType
) {
923 case MASK_PsPointList
:
924 incr
= smesa
->vertex_size
* 4;
925 sis_emit_func
= sis_point_func_mmio
[mmio_index
];
927 case MASK_PsLineList
:
928 incr
= smesa
->vertex_size
* 4 * 2;
929 sis_emit_func
= sis_line_func_mmio
[mmio_index
];
931 case MASK_PsTriangleList
:
932 incr
= smesa
->vertex_size
* 4 * 3;
933 sis_emit_func
= sis_tri_func_mmio
[mmio_index
];
938 MMIO(REG_3D_PrimitiveSet
, smesa
->dwPrimitiveSet
);
939 while (smesa
->vb_last
< smesa
->vb_cur
) {
940 sis_emit_func(smesa
, smesa
->vb_last
);
941 smesa
->vb_last
+= incr
;
946 /* With PCI, we can just start writing to the start of the VB again. */
947 smesa
->vb_cur
= smesa
->vb
;
949 smesa
->vb_last
= smesa
->vb_cur
;
952 void sisFlushPrims(sisContextPtr smesa
)
955 sisFlushPrimsLocked(smesa
);
959 /**********************************************************************/
960 /* Transition to/from hardware rasterization. */
961 /**********************************************************************/
963 void sisFallback( GLcontext
*ctx
, GLuint bit
, GLboolean mode
)
965 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
966 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
967 GLuint oldfallback
= smesa
->Fallback
;
970 smesa
->Fallback
|= bit
;
971 if (oldfallback
== 0) {
972 SIS_FIREVERTICES(smesa
);
973 _swsetup_Wakeup( ctx
);
974 smesa
->RenderIndex
= ~0;
978 smesa
->Fallback
&= ~bit
;
979 if (oldfallback
== bit
) {
980 _swrast_flush( ctx
);
981 tnl
->Driver
.Render
.Start
= sisRenderStart
;
982 tnl
->Driver
.Render
.PrimitiveNotify
= sisRenderPrimitive
;
983 tnl
->Driver
.Render
.Finish
= sisRenderFinish
;
985 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
986 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
987 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
989 _tnl_invalidate_vertex_state( ctx
, ~0 );
990 _tnl_invalidate_vertices( ctx
, ~0 );
991 _tnl_install_attrs( ctx
,
993 smesa
->vertex_attr_count
,
994 smesa
->hw_viewport
, 0 );
996 smesa
->NewGLState
|= _SIS_NEW_RENDER_STATE
;
1002 /**********************************************************************/
1003 /* Initialization. */
1004 /**********************************************************************/
1006 void sisInitTriFuncs( GLcontext
*ctx
)
1008 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
1009 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1010 static int firsttime
= 1;
1016 sis_vert_init_none();
1023 sis_vert_init_gws();
1025 sis_vert_init_gt0();
1026 sis_vert_init_wt0();
1027 sis_vert_init_gwt0();
1028 sis_vert_init_st0();
1029 sis_vert_init_gst0();
1030 sis_vert_init_wst0();
1031 sis_vert_init_gwst0();
1033 sis_vert_init_gt1();
1034 sis_vert_init_wt1();
1035 sis_vert_init_gwt1();
1036 sis_vert_init_st1();
1037 sis_vert_init_gst1();
1038 sis_vert_init_wst1();
1039 sis_vert_init_gwst1();
1040 sis_vert_init_t0t1();
1041 sis_vert_init_gt0t1();
1042 sis_vert_init_wt0t1();
1043 sis_vert_init_gwt0t1();
1044 sis_vert_init_st0t1();
1045 sis_vert_init_gst0t1();
1046 sis_vert_init_wst0t1();
1047 sis_vert_init_gwst0t1();
1050 if (driQueryOptionb(&smesa
->optionCache
, "fallback_force"))
1051 sisFallback(ctx
, SIS_FALLBACK_FORCE
, 1);
1053 sisFallback(ctx
, SIS_FALLBACK_FORCE
, 0);
1055 smesa
->RenderIndex
= ~0;
1056 smesa
->NewGLState
|= _SIS_NEW_RENDER_STATE
;
1058 tnl
->Driver
.RunPipeline
= sisRunPipeline
;
1059 tnl
->Driver
.Render
.Start
= sisRenderStart
;
1060 tnl
->Driver
.Render
.Finish
= sisRenderFinish
;
1061 tnl
->Driver
.Render
.PrimitiveNotify
= sisRenderPrimitive
;
1062 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1064 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
1065 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
1066 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
1068 _tnl_init_vertices( ctx
, ctx
->Const
.MaxArrayLockSize
+ 12,
1069 (6 + 2*ctx
->Const
.MaxTextureUnits
) * sizeof(GLfloat
) );
1071 smesa
->verts
= (char *)tnl
->clipspace
.vertex_buf
;