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"
43 #include "tnl/t_context.h"
44 #include "tnl/t_pipeline.h"
47 #include "sis_state.h"
51 static const GLuint hw_prim
[GL_POLYGON
+1] = {
52 OP_3D_POINT_DRAW
, /* GL_POINTS */
53 OP_3D_LINE_DRAW
, /* GL_LINES */
54 OP_3D_LINE_DRAW
, /* GL_LINE_LOOP */
55 OP_3D_LINE_DRAW
, /* GL_LINE_STRIP */
56 OP_3D_TRIANGLE_DRAW
, /* GL_TRIANGLES */
57 OP_3D_TRIANGLE_DRAW
, /* GL_TRIANGLE_STRIP */
58 OP_3D_TRIANGLE_DRAW
, /* GL_TRIANGLE_FAN */
59 OP_3D_TRIANGLE_DRAW
, /* GL_QUADS */
60 OP_3D_TRIANGLE_DRAW
, /* GL_QUAD_STRIP */
61 OP_3D_TRIANGLE_DRAW
/* GL_POLYGON */
64 static const GLuint hw_prim_mmio_fire
[OP_3D_TRIANGLE_DRAW
+1] = {
70 static const GLuint hw_prim_mmio_shade
[OP_3D_TRIANGLE_DRAW
+1] = {
76 static const GLuint hw_prim_agp_type
[OP_3D_TRIANGLE_DRAW
+1] = {
82 static const GLuint hw_prim_agp_shade
[OP_3D_TRIANGLE_DRAW
+1] = {
88 static void sisRasterPrimitive( GLcontext
*ctx
, GLuint hwprim
);
89 static void sisRenderPrimitive( GLcontext
*ctx
, GLenum prim
);
90 static void sisMakeRoomAGP( sisContextPtr smesa
, GLint num
);
91 static void sisUpdateAGP( sisContextPtr smesa
);
92 static void sisFireVertsAGP( sisContextPtr smesa
);
94 static float *AGP_StartPtr
;
95 static float *AGP_WritePtr
; /* Current write position */
96 static float *AGP_ReadPtr
; /* Last known engine readposition */
97 static long AGP_SpaceLeft
; /* Last known engine readposition */
99 /***********************************************************************
100 * Emit primitives as inline vertices *
101 ***********************************************************************/
103 /* Future optimizations:
105 * The previous code only emitted W when fog or textures were enabled.
108 #define SIS_MMIO_WRITE_VERTEX(_v, i, lastvert) \
110 MMIOBase[(REG_3D_TSXa+(i)*0x30)/4] = _v->v.x; \
111 MMIOBase[(REG_3D_TSYa+(i)*0x30)/4] = _v->v.y; \
112 MMIOBase[(REG_3D_TSZa+(i)*0x30)/4] = _v->v.z; \
113 MMIOBase[(REG_3D_TSWGa+(i)*0x30)/4] = _v->v.w; \
114 /*((GLint *) MMIOBase)[(REG_3D_TSFSa+(i)*0x30)/4] = _v->ui[5];*/ \
115 if (SIS_STATES & SIS_VERT_TEX0) { \
116 MMIOBase[(REG_3D_TSUAa+(i)*0x30)/4] = _v->v.u0; \
117 MMIOBase[(REG_3D_TSVAa+(i)*0x30)/4] = _v->v.v0; \
119 if (SIS_STATES & SIS_VERT_TEX1) { \
120 MMIOBase[(REG_3D_TSUBa+(i)*0x30)/4] = _v->v.u1; \
121 MMIOBase[(REG_3D_TSVBa+(i)*0x30)/4] = _v->v.v1; \
123 /*MMIOBase[(REG_3D_TSUCa+(i)*0x30)/4] = _v->v.u2; \
124 MMIOBase[(REG_3D_TSVCa+(i)*0x30)/4] = _v->v.v2;*/ \
125 /* the ARGB write of the last vertex of the primitive fires the 3d engine*/ \
126 if (lastvert || (SIS_STATES & SIS_VERT_SMOOTH)) \
127 ((GLint *) MMIOBase)[(REG_3D_TSARGBa+(i)*0x30)/4] = _v->ui[4]; \
130 #define SIS_AGP_WRITE_VERTEX(_v) \
132 AGP_WritePtr[0] = _v->v.x; \
133 AGP_WritePtr[1] = _v->v.y; \
134 AGP_WritePtr[2] = _v->v.z; \
135 AGP_WritePtr[3] = _v->v.w; \
136 ((GLint *)AGP_WritePtr)[4] = _v->ui[4]; \
138 if (SIS_STATES & SIS_VERT_TEX0) { \
139 AGP_WritePtr[0] = _v->v.u0; \
140 AGP_WritePtr[1] = _v->v.v0; \
143 if (SIS_STATES & SIS_VERT_TEX1) { \
144 AGP_WritePtr[0] = _v->v.u1; \
145 AGP_WritePtr[1] = _v->v.v1; \
150 #define MMIO_VERT_REG_COUNT 10
152 #define SIS_VERT_SMOOTH 0x01
153 #define SIS_VERT_TEX0 0x02
154 #define SIS_VERT_TEX1 0x04
156 static sis_quad_func sis_quad_func_agp
[8];
157 static sis_tri_func sis_tri_func_agp
[8];
158 static sis_line_func sis_line_func_agp
[8];
159 static sis_point_func sis_point_func_agp
[8];
160 static sis_quad_func sis_quad_func_mmio
[8];
161 static sis_tri_func sis_tri_func_mmio
[8];
162 static sis_line_func sis_line_func_mmio
[8];
163 static sis_point_func sis_point_func_mmio
[8];
165 /* XXX: These definitions look questionable */
166 #define USE_XYZ MASK_PsVertex_HAS_RHW
167 #define USE_W MASK_PsVertex_HAS_NORMALXYZ
168 #define USE_RGB MASK_PsVertex_HAS_SPECULAR
169 #define USE_UV1 MASK_PsVertex_HAS_UVSet2
170 #define USE_UV2 MASK_PsVertex_HAS_UVSet3
172 static GLint AGPParsingValues
[8] = {
173 (5 << 28) | USE_XYZ
| USE_W
| USE_RGB
,
174 (5 << 28) | USE_XYZ
| USE_W
| USE_RGB
,
175 (7 << 28) | USE_XYZ
| USE_W
| USE_RGB
| USE_UV1
,
176 (7 << 28) | USE_XYZ
| USE_W
| USE_RGB
| USE_UV1
,
177 (7 << 28) | USE_XYZ
| USE_W
| USE_RGB
| USE_UV2
,
178 (7 << 28) | USE_XYZ
| USE_W
| USE_RGB
| USE_UV2
,
179 (9 << 28) | USE_XYZ
| USE_W
| USE_RGB
| USE_UV1
| USE_UV2
,
180 (9 << 28) | USE_XYZ
| USE_W
| USE_RGB
| USE_UV1
| USE_UV2
,
183 #define SIS_STATES (0)
184 #define TAG(x) x##_none
185 #include "sis_tritmp.h"
187 #define SIS_STATES (SIS_VERT_SMOOTH)
189 #include "sis_tritmp.h"
191 #define SIS_STATES (SIS_VERT_TEX0)
192 #define TAG(x) x##_t0
193 #include "sis_tritmp.h"
195 #define SIS_STATES (SIS_VERT_SMOOTH | SIS_VERT_TEX0)
196 #define TAG(x) x##_st0
197 #include "sis_tritmp.h"
199 #define SIS_STATES (SIS_VERT_TEX1)
200 #define TAG(x) x##_t1
201 #include "sis_tritmp.h"
203 #define SIS_STATES (SIS_VERT_SMOOTH | SIS_VERT_TEX1)
204 #define TAG(x) x##_st1
205 #include "sis_tritmp.h"
207 #define SIS_STATES (SIS_VERT_TEX0 | SIS_VERT_TEX1)
208 #define TAG(x) x##_t0t1
209 #include "sis_tritmp.h"
211 #define SIS_STATES (SIS_VERT_SMOOTH | SIS_VERT_TEX0 | SIS_VERT_TEX1)
212 #define TAG(x) x##_st0t1
213 #include "sis_tritmp.h"
215 /***********************************************************************
216 * Macros for t_dd_tritmp.h to draw basic primitives *
217 ***********************************************************************/
219 #define POINT( v0 ) smesa->draw_point( smesa, v0 )
220 #define LINE( v0, v1 ) smesa->draw_line( smesa, v0, v1 )
221 #define TRI( a, b, c ) smesa->draw_tri( smesa, a, b, c )
222 #define QUAD( a, b, c, d ) smesa->draw_quad( smesa, a, b, c, d )
224 /***********************************************************************
225 * Build render functions from dd templates *
226 ***********************************************************************/
228 #define SIS_OFFSET_BIT 0x01
229 #define SIS_TWOSIDE_BIT 0x02
230 #define SIS_UNFILLED_BIT 0x04
231 #define SIS_FALLBACK_BIT 0x08
232 #define SIS_MAX_TRIFUNC 0x10
238 triangle_func triangle
;
240 } rast_tab
[SIS_MAX_TRIFUNC
];
243 #define DO_FALLBACK (IND & SIS_FALLBACK_BIT)
244 #define DO_OFFSET (IND & SIS_OFFSET_BIT)
245 #define DO_UNFILLED (IND & SIS_UNFILLED_BIT)
246 #define DO_TWOSIDE (IND & SIS_TWOSIDE_BIT)
252 #define DO_FULL_QUAD 1
256 #define HAVE_BACK_COLORS 0
257 #define HAVE_HW_FLATSHADE 1
258 #define VERTEX sisVertex
261 #define DEPTH_SCALE 1.0
262 #define UNFILLED_TRI unfilled_tri
263 #define UNFILLED_QUAD unfilled_quad
264 #define VERT_X(_v) _v->v.x
265 #define VERT_Y(_v) _v->v.y
266 #define VERT_Z(_v) _v->v.z
267 #define AREA_IS_CCW( a ) (a > 0)
268 #define GET_VERTEX(e) (smesa->verts + (e << smesa->vertex_stride_shift))
270 #define VERT_SET_RGBA( v, c ) \
272 sis_color_t *vc = (sis_color_t *)&(v)->ui[coloroffset]; \
274 vc->green = (c)[1]; \
276 vc->alpha = (c)[3]; \
278 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
279 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
280 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
282 #define VERT_SET_SPEC( v0, c ) \
284 (v0)->v.specular.red = (c)[0]; \
285 (v0)->v.specular.green = (c)[1]; \
286 (v0)->v.specular.blue = (c)[2]; \
288 #define VERT_COPY_SPEC( v0, v1 ) \
290 (v0)->v.specular.red = v1->v.specular.red; \
291 (v0)->v.specular.green = v1->v.specular.green; \
292 (v0)->v.specular.blue = v1->v.specular.blue; \
295 #define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5]
296 #define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx]
298 #define LOCAL_VARS(n) \
299 sisContextPtr smesa = SIS_CONTEXT(ctx); \
300 GLuint color[n], spec[n]; \
301 GLuint coloroffset = (smesa->vertex_size == 4 ? 3 : 4); \
302 GLboolean havespec = (smesa->vertex_size == 4 ? 0 : 1); \
303 (void) color; (void) spec; (void) coloroffset; (void) havespec;
305 /***********************************************************************
306 * Helpers for rendering unfilled primitives *
307 ***********************************************************************/
309 #define RASTERIZE(x) if (smesa->hw_primitive != hw_prim[x]) \
310 sisRasterPrimitive( ctx, hw_prim[x] )
311 #define RENDER_PRIMITIVE smesa->render_primitive
312 #define IND SIS_FALLBACK_BIT
314 #include "tnl_dd/t_dd_unfilled.h"
318 /***********************************************************************
319 * Generate GL render functions *
320 ***********************************************************************/
325 #include "tnl_dd/t_dd_tritmp.h"
327 #define IND (SIS_OFFSET_BIT)
328 #define TAG(x) x##_offset
329 #include "tnl_dd/t_dd_tritmp.h"
331 #define IND (SIS_TWOSIDE_BIT)
332 #define TAG(x) x##_twoside
333 #include "tnl_dd/t_dd_tritmp.h"
335 #define IND (SIS_TWOSIDE_BIT | SIS_OFFSET_BIT)
336 #define TAG(x) x##_twoside_offset
337 #include "tnl_dd/t_dd_tritmp.h"
339 #define IND (SIS_UNFILLED_BIT)
340 #define TAG(x) x##_unfilled
341 #include "tnl_dd/t_dd_tritmp.h"
343 #define IND (SIS_OFFSET_BIT | SIS_UNFILLED_BIT)
344 #define TAG(x) x##_offset_unfilled
345 #include "tnl_dd/t_dd_tritmp.h"
347 #define IND (SIS_TWOSIDE_BIT | SIS_UNFILLED_BIT)
348 #define TAG(x) x##_twoside_unfilled
349 #include "tnl_dd/t_dd_tritmp.h"
351 #define IND (SIS_TWOSIDE_BIT | SIS_OFFSET_BIT | SIS_UNFILLED_BIT)
352 #define TAG(x) x##_twoside_offset_unfilled
353 #include "tnl_dd/t_dd_tritmp.h"
355 #define IND (SIS_FALLBACK_BIT)
356 #define TAG(x) x##_fallback
357 #include "tnl_dd/t_dd_tritmp.h"
359 #define IND (SIS_OFFSET_BIT | SIS_FALLBACK_BIT)
360 #define TAG(x) x##_offset_fallback
361 #include "tnl_dd/t_dd_tritmp.h"
363 #define IND (SIS_TWOSIDE_BIT | SIS_FALLBACK_BIT)
364 #define TAG(x) x##_twoside_fallback
365 #include "tnl_dd/t_dd_tritmp.h"
367 #define IND (SIS_TWOSIDE_BIT | SIS_OFFSET_BIT | SIS_FALLBACK_BIT)
368 #define TAG(x) x##_twoside_offset_fallback
369 #include "tnl_dd/t_dd_tritmp.h"
371 #define IND (SIS_UNFILLED_BIT | SIS_FALLBACK_BIT)
372 #define TAG(x) x##_unfilled_fallback
373 #include "tnl_dd/t_dd_tritmp.h"
375 #define IND (SIS_OFFSET_BIT | SIS_UNFILLED_BIT | SIS_FALLBACK_BIT)
376 #define TAG(x) x##_offset_unfilled_fallback
377 #include "tnl_dd/t_dd_tritmp.h"
379 #define IND (SIS_TWOSIDE_BIT | SIS_UNFILLED_BIT | SIS_FALLBACK_BIT)
380 #define TAG(x) x##_twoside_unfilled_fallback
381 #include "tnl_dd/t_dd_tritmp.h"
383 #define IND (SIS_TWOSIDE_BIT | SIS_OFFSET_BIT | SIS_UNFILLED_BIT | \
385 #define TAG(x) x##_twoside_offset_unfilled_fallback
386 #include "tnl_dd/t_dd_tritmp.h"
389 static void init_rast_tab( void )
394 init_twoside_offset();
396 init_offset_unfilled();
397 init_twoside_unfilled();
398 init_twoside_offset_unfilled();
400 init_offset_fallback();
401 init_twoside_fallback();
402 init_twoside_offset_fallback();
403 init_unfilled_fallback();
404 init_offset_unfilled_fallback();
405 init_twoside_unfilled_fallback();
406 init_twoside_offset_unfilled_fallback();
411 /***********************************************************************
412 * Rasterization fallback helpers *
413 ***********************************************************************/
416 /* This code is hit only when a mix of accelerated and unaccelerated
417 * primitives are being drawn, and only for the unaccelerated
421 sis_fallback_quad( sisContextPtr smesa
,
427 GLcontext
*ctx
= smesa
->glCtx
;
429 sis_translate_vertex( ctx
, v0
, &v
[0] );
430 sis_translate_vertex( ctx
, v1
, &v
[1] );
431 sis_translate_vertex( ctx
, v2
, &v
[2] );
432 sis_translate_vertex( ctx
, v3
, &v
[3] );
433 _swrast_Triangle( ctx
, &v
[0], &v
[1], &v
[3] );
434 _swrast_Triangle( ctx
, &v
[1], &v
[2], &v
[3] );
438 sis_fallback_tri( sisContextPtr smesa
,
443 GLcontext
*ctx
= smesa
->glCtx
;
445 sis_translate_vertex( ctx
, v0
, &v
[0] );
446 sis_translate_vertex( ctx
, v1
, &v
[1] );
447 sis_translate_vertex( ctx
, v2
, &v
[2] );
448 _swrast_Triangle( ctx
, &v
[0], &v
[1], &v
[2] );
453 sis_fallback_line( sisContextPtr smesa
,
457 GLcontext
*ctx
= smesa
->glCtx
;
459 sis_translate_vertex( ctx
, v0
, &v
[0] );
460 sis_translate_vertex( ctx
, v1
, &v
[1] );
461 _swrast_Line( ctx
, &v
[0], &v
[1] );
466 sis_fallback_point( sisContextPtr smesa
,
469 GLcontext
*ctx
= smesa
->glCtx
;
471 sis_translate_vertex( ctx
, v0
, &v
[0] );
472 _swrast_Point( ctx
, &v
[0] );
477 /**********************************************************************/
478 /* Render unclipped begin/end objects */
479 /**********************************************************************/
481 #define VERT(x) (sisVertex *)(sisverts + (x << shift))
482 #define RENDER_POINTS( start, count ) \
483 for ( ; start < count ; start++) \
484 smesa->draw_point( smesa, VERT(start) )
485 #define RENDER_LINE( v0, v1 ) smesa->draw_line( smesa, VERT(v0), VERT(v1) )
486 #define RENDER_TRI( v0, v1, v2 ) smesa->draw_tri( smesa, VERT(v0), VERT(v1), \
488 #define RENDER_QUAD( v0, v1, v2, v3 ) smesa->draw_quad( smesa, VERT(v0), \
489 VERT(v1), VERT(v2), VERT(v3))
490 #define INIT(x) sisRenderPrimitive( ctx, x )
493 sisContextPtr smesa = SIS_CONTEXT(ctx); \
494 const GLuint shift = smesa->vertex_stride_shift; \
495 const char *sisverts = (char *)smesa->verts; \
496 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
498 #define RESET_STIPPLE
499 #define RESET_OCCLUSION
500 #define PRESERVE_VB_DEFS
502 #define TAG(x) sis_##x##_verts
503 #include "tnl/t_vb_rendertmp.h"
506 #define TAG(x) sis_##x##_elts
507 #define ELT(x) elt[x]
508 #include "tnl/t_vb_rendertmp.h"
511 /**********************************************************************/
512 /* Render clipped primitives */
513 /**********************************************************************/
515 static void sisRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
, GLuint n
)
517 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
518 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
520 /* Render the new vertices as an unclipped polygon.
523 GLuint
*tmp
= VB
->Elts
;
524 VB
->Elts
= (GLuint
*)elts
;
525 tnl
->Driver
.Render
.PrimTabElts
[GL_POLYGON
]( ctx
, 0, n
, PRIM_BEGIN
|PRIM_END
);
530 static void sisRenderClippedLine( GLcontext
*ctx
, GLuint ii
, GLuint jj
)
532 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
533 tnl
->Driver
.Render
.Line( ctx
, ii
, jj
);
537 static void sisFastRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
540 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
541 GLuint vertsize
= smesa
->vertex_size
;
542 GLuint
*vb
= r128AllocDmaLow( rmesa
, (n
-2) * 3 * 4 * vertsize
);
543 GLubyte
*sisverts
= (GLubyte
*)smesa
->verts
;
544 const GLuint shift
= smesa
->vertex_stride_shift
;
545 const GLuint
*start
= (const GLuint
*)VERT(elts
[0]);
548 smesa
->num_verts
+= (n
-2) * 3;
550 for (i
= 2 ; i
< n
; i
++) {
551 COPY_DWORDS( j
, vb
, vertsize
, (sisVertexPtr
) VERT(elts
[i
-1]) );
552 COPY_DWORDS( j
, vb
, vertsize
, (sisVertexPtr
) VERT(elts
[i
]) );
553 COPY_DWORDS( j
, vb
, vertsize
, (sisVertexPtr
) start
);
561 /**********************************************************************/
562 /* Choose render functions */
563 /**********************************************************************/
565 #define _SIS_NEW_RENDER_STATE (_DD_NEW_LINE_STIPPLE | \
566 _DD_NEW_LINE_SMOOTH | \
567 _DD_NEW_POINT_SMOOTH | \
568 _DD_NEW_TRI_SMOOTH | \
569 _DD_NEW_TRI_UNFILLED | \
570 _DD_NEW_TRI_LIGHT_TWOSIDE | \
571 _DD_NEW_TRI_OFFSET) \
574 #define POINT_FALLBACK (DD_POINT_SMOOTH)
575 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
576 #define TRI_FALLBACK (DD_TRI_SMOOTH)
577 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
578 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
581 static void sisChooseRenderState(GLcontext
*ctx
)
583 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
584 GLuint flags
= ctx
->_TriangleCaps
;
586 GLuint vertindex
= 0;
588 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
)
589 vertindex
|= SIS_VERT_TEX0
;
590 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
)
591 vertindex
|= SIS_VERT_TEX1
;
592 if (ctx
->Light
.ShadeModel
== GL_SMOOTH
)
593 vertindex
|= SIS_VERT_SMOOTH
;
595 if (smesa
->AGPCmdModeEnabled
) {
596 smesa
->draw_quad
= sis_quad_func_agp
[vertindex
];
597 smesa
->draw_tri
= sis_tri_func_agp
[vertindex
];
598 smesa
->draw_line
= sis_line_func_agp
[vertindex
];
599 smesa
->draw_point
= sis_point_func_agp
[vertindex
];
601 smesa
->draw_quad
= sis_quad_func_mmio
[vertindex
];
602 smesa
->draw_tri
= sis_tri_func_mmio
[vertindex
];
603 smesa
->draw_line
= sis_line_func_mmio
[vertindex
];
604 smesa
->draw_point
= sis_point_func_mmio
[vertindex
];
606 smesa
->AGPParseSet
&= ~(MASK_VertexDWSize
| MASK_VertexDataFormat
);
607 smesa
->AGPParseSet
|= AGPParsingValues
[vertindex
];
609 if (flags
& (ANY_RASTER_FLAGS
|ANY_FALLBACK_FLAGS
)) {
611 if (flags
& ANY_RASTER_FLAGS
) {
612 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= SIS_TWOSIDE_BIT
;
613 if (flags
& DD_TRI_OFFSET
) index
|= SIS_OFFSET_BIT
;
614 if (flags
& DD_TRI_UNFILLED
) index
|= SIS_UNFILLED_BIT
;
617 /* Hook in fallbacks for specific primitives.
619 if (flags
& ANY_FALLBACK_FLAGS
) {
620 if (flags
& POINT_FALLBACK
)
621 smesa
->draw_point
= sis_fallback_point
;
622 if (flags
& LINE_FALLBACK
)
623 smesa
->draw_line
= sis_fallback_line
;
624 if (flags
& TRI_FALLBACK
) {
625 smesa
->draw_quad
= sis_fallback_quad
;
626 smesa
->draw_tri
= sis_fallback_tri
;
628 index
|= SIS_FALLBACK_BIT
;
632 if (index
!= smesa
->RenderIndex
) {
633 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
634 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
635 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
636 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
637 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
640 tnl
->Driver
.Render
.PrimTabVerts
= sis_render_tab_verts
;
641 tnl
->Driver
.Render
.PrimTabElts
= sis_render_tab_elts
;
642 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
643 /*XXX: sisFastRenderClippedPoly*/
644 tnl
->Driver
.Render
.ClippedPolygon
= sisRenderClippedPoly
;
646 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
647 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
648 tnl
->Driver
.Render
.ClippedLine
= sisRenderClippedLine
;
649 tnl
->Driver
.Render
.ClippedPolygon
= sisRenderClippedPoly
;
652 smesa
->RenderIndex
= index
;
656 /**********************************************************************/
657 /* Multipass rendering for front buffering */
658 /**********************************************************************/
659 static GLboolean
multipass_cliprect( GLcontext
*ctx
, GLuint pass
)
661 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
663 if (pass
>= smesa
->driDrawable
->numClipRects
) {
666 GLint x1
, y1
, x2
, y2
;
668 x1
= smesa
->driDrawable
->pClipRects
[pass
].x1
- smesa
->driDrawable
->x
;
669 y1
= smesa
->driDrawable
->pClipRects
[pass
].y1
- smesa
->driDrawable
->y
;
670 x2
= smesa
->driDrawable
->pClipRects
[pass
].x2
- smesa
->driDrawable
->x
;
671 y2
= smesa
->driDrawable
->pClipRects
[pass
].y2
- smesa
->driDrawable
->y
;
673 if (ctx
->Scissor
.Enabled
) {
674 GLint scisy1
= Y_FLIP(ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
- 1);
675 GLint scisy2
= Y_FLIP(ctx
->Scissor
.Y
);
677 if (ctx
->Scissor
.X
> x1
)
681 if (ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1 < x2
)
682 x2
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
687 MMIO(REG_3D_ClipTopBottom
, y1
<< 13 | y2
);
688 MMIO(REG_3D_ClipLeftRight
, x1
<< 13 | x2
);
689 /* Mark that we clobbered these registers */
690 smesa
->GlobalFlag
|= GFLAG_CLIPPING
;
697 /**********************************************************************/
698 /* Validate state at pipeline start */
699 /**********************************************************************/
701 static void sisRunPipeline( GLcontext
*ctx
)
703 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
706 sisUpdateHWState( ctx
);
708 if (smesa
->AGPCmdModeEnabled
) {
709 AGP_WritePtr
= (GLfloat
*)smesa
->AGPCmdBufBase
+ *smesa
->pAGPCmdBufNext
;
710 AGP_StartPtr
= AGP_WritePtr
;
711 AGP_ReadPtr
= (GLfloat
*)((long)MMIO_READ(REG_3D_AGPCmBase
) -
712 (long)smesa
->AGPCmdBufAddr
+ (long)smesa
->AGPCmdBufBase
);
713 sisUpdateAGP( smesa
);
716 if (!smesa
->Fallback
&& smesa
->NewGLState
) {
717 if (smesa
->NewGLState
& _SIS_NEW_VERTEX_STATE
)
718 sisChooseVertexState( ctx
);
720 if (smesa
->NewGLState
& (_SIS_NEW_RENDER_STATE
| _NEW_TEXTURE
))
721 sisChooseRenderState( ctx
);
723 smesa
->NewGLState
= 0;
726 _tnl_run_pipeline( ctx
);
728 if (smesa
->AGPCmdModeEnabled
)
729 sisFireVertsAGP( smesa
);
735 /**********************************************************************/
736 /* High level hooks for t_vb_render.c */
737 /**********************************************************************/
739 /* This is called when Mesa switches between rendering triangle
740 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
741 * and lines, points and bitmaps.
744 static void sisRasterPrimitive( GLcontext
*ctx
, GLuint hwprim
)
746 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
747 if (smesa
->hw_primitive
!= hwprim
) {
748 if (smesa
->AGPCmdModeEnabled
) {
749 sisFireVertsAGP( smesa
);
750 smesa
->AGPParseSet
&= ~(MASK_PsDataType
| MASK_PsShadingMode
);
751 smesa
->AGPParseSet
|= hw_prim_agp_type
[hwprim
];
752 if (ctx
->Light
.ShadeModel
== GL_FLAT
)
753 smesa
->AGPParseSet
|= hw_prim_agp_shade
[hwprim
];
755 smesa
->AGPParseSet
|= MASK_PsShadingSmooth
;
758 smesa
->dwPrimitiveSet
&= ~(MASK_DrawPrimitiveCommand
|
759 MASK_SetFirePosition
| MASK_ShadingMode
);
760 smesa
->dwPrimitiveSet
|= hwprim
| hw_prim_mmio_fire
[hwprim
];
761 if (ctx
->Light
.ShadeModel
== GL_FLAT
)
762 smesa
->dwPrimitiveSet
|= hw_prim_mmio_shade
[hwprim
];
764 smesa
->dwPrimitiveSet
|= SHADE_GOURAUD
;
767 smesa
->hw_primitive
= hwprim
;
770 static void sisRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
772 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
774 smesa
->render_primitive
= prim
;
775 if (prim
>= GL_TRIANGLES
&& (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
777 sisRasterPrimitive( ctx
, hw_prim
[prim
] );
781 static void sisRenderStart( GLcontext
*ctx
)
783 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
784 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
786 /* Check for projective texturing. Make sure all texcoord
787 * pointers point to something. (fix in mesa?)
789 sisCheckTexSizes( ctx
);
791 if (ctx
->Color
._DrawDestMask
== FRONT_LEFT_BIT
&&
792 smesa
->driDrawable
->numClipRects
!= 0)
794 multipass_cliprect(ctx
, 0);
795 if (smesa
->driDrawable
->numClipRects
> 1)
796 tnl
->Driver
.Render
.Multipass
= multipass_cliprect
;
798 tnl
->Driver
.Render
.Multipass
= NULL
;
800 tnl
->Driver
.Render
.Multipass
= NULL
;
804 static void sisRenderFinish( GLcontext
*ctx
)
808 /* Update SpaceLeft after an engine or current write pointer update */
809 static void sisUpdateAGP( sisContextPtr smesa
)
811 /* ReadPtr == WritePtr is the empty case */
812 if (AGP_ReadPtr
<= AGP_WritePtr
)
813 AGP_SpaceLeft
= (long)smesa
->AGPCmdBufBase
+ (long)smesa
->AGPCmdBufSize
-
816 AGP_SpaceLeft
= AGP_ReadPtr
- AGP_WritePtr
- 4;
819 /* Fires a set of vertices that have been written from AGP_StartPtr to
820 * AGP_WritePtr, using the smesa->AGPParseSet format.
823 sisFireVertsAGP( sisContextPtr smesa
)
825 if (AGP_WritePtr
== AGP_StartPtr
)
830 MMIO(REG_3D_AGPCmBase
, (long)AGP_StartPtr
- (long)smesa
->AGPCmdBufBase
+
831 (long)smesa
->AGPCmdBufAddr
);
832 MMIO(REG_3D_AGPTtDwNum
, (((long)AGP_WritePtr
- (long)AGP_StartPtr
) >> 2) |
834 MMIO(REG_3D_ParsingSet
, smesa
->AGPParseSet
);
836 MMIO(REG_3D_AGPCmFire
, (GLint
)(-1));
839 *(smesa
->pAGPCmdBufNext
) = (((long)AGP_WritePtr
-
840 (long)smesa
->AGPCmdBufBase
) + 0xf) & ~0xf;
841 AGP_StartPtr
= AGP_WritePtr
;
842 sisUpdateAGP( smesa
);
845 /* Make sure there are more than num dwords left in the AGP queue. */
847 sisMakeRoomAGP( sisContextPtr smesa
, GLint num
)
851 if (size
<= AGP_SpaceLeft
) {
852 AGP_SpaceLeft
-= size
;
856 if (AGP_WritePtr
+ num
> (GLfloat
*)(smesa
->AGPCmdBufBase
+
857 smesa
->AGPCmdBufSize
))
859 sisFireVertsAGP( smesa
);
860 AGP_WritePtr
= (GLfloat
*)smesa
->AGPCmdBufBase
;
861 AGP_StartPtr
= AGP_WritePtr
;
862 sisUpdateAGP( smesa
);
863 WaitEngIdle( smesa
); /* XXX Why is this necessary? */
866 if (size
> AGP_SpaceLeft
) {
867 /* Update the cached engine read pointer */
868 AGP_ReadPtr
= (GLfloat
*)((long)MMIO_READ(REG_3D_AGPCmBase
) -
869 (long)smesa
->AGPCmdBufAddr
+ (long)smesa
->AGPCmdBufBase
);
870 sisUpdateAGP( smesa
);
871 while (size
> AGP_SpaceLeft
) {
872 /* Spin until space is available. */
874 AGP_ReadPtr
= (GLfloat
*)((long)MMIO_READ(REG_3D_AGPCmBase
) -
875 (long)smesa
->AGPCmdBufAddr
+ (long)smesa
->AGPCmdBufBase
);
876 sisUpdateAGP( smesa
);
879 AGP_SpaceLeft
-= size
;
882 /**********************************************************************/
883 /* Transition to/from hardware rasterization. */
884 /**********************************************************************/
886 void sisFallback( GLcontext
*ctx
, GLuint bit
, GLboolean mode
)
888 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
889 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
890 GLuint oldfallback
= smesa
->Fallback
;
893 smesa
->Fallback
|= bit
;
894 if (oldfallback
== 0) {
895 _swsetup_Wakeup( ctx
);
896 smesa
->RenderIndex
= ~0;
900 smesa
->Fallback
&= ~bit
;
901 if (oldfallback
== bit
) {
902 _swrast_flush( ctx
);
903 tnl
->Driver
.Render
.Start
= sisRenderStart
;
904 tnl
->Driver
.Render
.PrimitiveNotify
= sisRenderPrimitive
;
905 tnl
->Driver
.Render
.Finish
= sisRenderFinish
;
906 tnl
->Driver
.Render
.BuildVertices
= sisBuildVertices
;
907 smesa
->NewGLState
|= (_SIS_NEW_RENDER_STATE
|
908 _SIS_NEW_VERTEX_STATE
);
914 /**********************************************************************/
915 /* Initialization. */
916 /**********************************************************************/
918 void sisInitTriFuncs( GLcontext
*ctx
)
920 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
921 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
922 static int firsttime
= 1;
928 sis_vert_init_none();
934 sis_vert_init_t0t1();
935 sis_vert_init_st0t1();
938 tnl
->Driver
.RunPipeline
= sisRunPipeline
;
939 tnl
->Driver
.Render
.Start
= sisRenderStart
;
940 tnl
->Driver
.Render
.Finish
= sisRenderFinish
;
941 tnl
->Driver
.Render
.PrimitiveNotify
= sisRenderPrimitive
;
942 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
943 tnl
->Driver
.Render
.BuildVertices
= sisBuildVertices
;
944 tnl
->Driver
.Render
.Multipass
= NULL
;
946 if (driQueryOptionb(&smesa
->optionCache
, "fallback_force"))
947 sisFallback(ctx
, SIS_FALLBACK_FORCE
, 1);
949 sisFallback(ctx
, SIS_FALLBACK_FORCE
, 0);
951 smesa
->RenderIndex
= ~0;
952 smesa
->NewGLState
|= (_SIS_NEW_RENDER_STATE
|
953 _SIS_NEW_VERTEX_STATE
);