merge latest DRI sis driver changes from the DRI trunk
[mesa.git] / src / mesa / drivers / dri / sis / sis_tris.c
1 /* $XFree86*/ /* -*- c-basic-offset: 3 -*- */
2 /**************************************************************************
3
4 Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
5 Copyright 2003 Eric Anholt
6 All Rights Reserved.
7
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:
14
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
17 Software.
18
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.
26
27 **************************************************************************/
28
29 /*
30 * Authors:
31 * Sung-Ching Lin <sclin@sis.com.tw>
32 * Eric Anholt <anholt@FreeBSD.org>
33 */
34
35 #include "glheader.h"
36 #include "mtypes.h"
37 #include "colormac.h"
38 #include "macros.h"
39
40 #include "swrast/swrast.h"
41 #include "swrast_setup/swrast_setup.h"
42 #include "tnl/tnl.h"
43 #include "tnl/t_context.h"
44 #include "tnl/t_pipeline.h"
45
46 #include "sis_tris.h"
47 #include "sis_state.h"
48 #include "sis_vb.h"
49 #include "sis_lock.h"
50
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 */
62 };
63
64 static const GLuint hw_prim_mmio_fire[OP_3D_TRIANGLE_DRAW+1] = {
65 OP_3D_FIRE_TSARGBa,
66 OP_3D_FIRE_TSARGBb,
67 OP_3D_FIRE_TSARGBc
68 };
69
70 static const GLuint hw_prim_mmio_shade[OP_3D_TRIANGLE_DRAW+1] = {
71 SHADE_FLAT_VertexA,
72 SHADE_FLAT_VertexB,
73 SHADE_FLAT_VertexC
74 };
75
76 static const GLuint hw_prim_agp_type[OP_3D_TRIANGLE_DRAW+1] = {
77 MASK_PsPointList,
78 MASK_PsLineList,
79 MASK_PsTriangleList
80 };
81
82 static const GLuint hw_prim_agp_shade[OP_3D_TRIANGLE_DRAW+1] = {
83 MASK_PsShadingFlatA,
84 MASK_PsShadingFlatB,
85 MASK_PsShadingFlatC
86 };
87
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 );
93
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 */
98
99 /***********************************************************************
100 * Emit primitives as inline vertices *
101 ***********************************************************************/
102
103 /* Future optimizations:
104 *
105 * The previous code only emitted W when fog or textures were enabled.
106 */
107
108 #define SIS_MMIO_WRITE_VERTEX(_v, i, lastvert) \
109 do { \
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; \
118 } \
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; \
122 } \
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]; \
128 } while (0);
129
130 #define SIS_AGP_WRITE_VERTEX(_v) \
131 do { \
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]; \
137 AGP_WritePtr += 5; \
138 if (SIS_STATES & SIS_VERT_TEX0) { \
139 AGP_WritePtr[0] = _v->v.u0; \
140 AGP_WritePtr[1] = _v->v.v0; \
141 AGP_WritePtr += 2; \
142 } \
143 if (SIS_STATES & SIS_VERT_TEX1) { \
144 AGP_WritePtr[0] = _v->v.u1; \
145 AGP_WritePtr[1] = _v->v.v1; \
146 AGP_WritePtr += 2; \
147 } \
148 } while(0)
149
150 #define MMIO_VERT_REG_COUNT 10
151
152 #define SIS_VERT_SMOOTH 0x01
153 #define SIS_VERT_TEX0 0x02
154 #define SIS_VERT_TEX1 0x04
155
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];
164
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
171
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,
181 };
182
183 #define SIS_STATES (0)
184 #define TAG(x) x##_none
185 #include "sis_tritmp.h"
186
187 #define SIS_STATES (SIS_VERT_SMOOTH)
188 #define TAG(x) x##_s
189 #include "sis_tritmp.h"
190
191 #define SIS_STATES (SIS_VERT_TEX0)
192 #define TAG(x) x##_t0
193 #include "sis_tritmp.h"
194
195 #define SIS_STATES (SIS_VERT_SMOOTH | SIS_VERT_TEX0)
196 #define TAG(x) x##_st0
197 #include "sis_tritmp.h"
198
199 #define SIS_STATES (SIS_VERT_TEX1)
200 #define TAG(x) x##_t1
201 #include "sis_tritmp.h"
202
203 #define SIS_STATES (SIS_VERT_SMOOTH | SIS_VERT_TEX1)
204 #define TAG(x) x##_st1
205 #include "sis_tritmp.h"
206
207 #define SIS_STATES (SIS_VERT_TEX0 | SIS_VERT_TEX1)
208 #define TAG(x) x##_t0t1
209 #include "sis_tritmp.h"
210
211 #define SIS_STATES (SIS_VERT_SMOOTH | SIS_VERT_TEX0 | SIS_VERT_TEX1)
212 #define TAG(x) x##_st0t1
213 #include "sis_tritmp.h"
214
215 /***********************************************************************
216 * Macros for t_dd_tritmp.h to draw basic primitives *
217 ***********************************************************************/
218
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 )
223
224 /***********************************************************************
225 * Build render functions from dd templates *
226 ***********************************************************************/
227
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
233
234
235 static struct {
236 points_func points;
237 line_func line;
238 triangle_func triangle;
239 quad_func quad;
240 } rast_tab[SIS_MAX_TRIFUNC];
241
242
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)
247 #define DO_FLAT 0
248 #define DO_TRI 1
249 #define DO_QUAD 1
250 #define DO_LINE 1
251 #define DO_POINTS 1
252 #define DO_FULL_QUAD 1
253
254 #define HAVE_RGBA 1
255 #define HAVE_SPEC 1
256 #define HAVE_BACK_COLORS 0
257 #define HAVE_HW_FLATSHADE 1
258 #define VERTEX sisVertex
259 #define TAB rast_tab
260
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))
269
270 #define VERT_SET_RGBA( v, c ) \
271 do { \
272 sis_color_t *vc = (sis_color_t *)&(v)->ui[coloroffset]; \
273 vc->blue = (c)[2]; \
274 vc->green = (c)[1]; \
275 vc->red = (c)[0]; \
276 vc->alpha = (c)[3]; \
277 } while (0)
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]
281
282 #define VERT_SET_SPEC( v0, c ) \
283 if (havespec) { \
284 (v0)->v.specular.red = (c)[0]; \
285 (v0)->v.specular.green = (c)[1]; \
286 (v0)->v.specular.blue = (c)[2]; \
287 }
288 #define VERT_COPY_SPEC( v0, v1 ) \
289 if (havespec) { \
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; \
293 }
294
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]
297
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;
304
305 /***********************************************************************
306 * Helpers for rendering unfilled primitives *
307 ***********************************************************************/
308
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
313 #define TAG(x) x
314 #include "tnl_dd/t_dd_unfilled.h"
315 #undef IND
316
317
318 /***********************************************************************
319 * Generate GL render functions *
320 ***********************************************************************/
321
322
323 #define IND (0)
324 #define TAG(x) x
325 #include "tnl_dd/t_dd_tritmp.h"
326
327 #define IND (SIS_OFFSET_BIT)
328 #define TAG(x) x##_offset
329 #include "tnl_dd/t_dd_tritmp.h"
330
331 #define IND (SIS_TWOSIDE_BIT)
332 #define TAG(x) x##_twoside
333 #include "tnl_dd/t_dd_tritmp.h"
334
335 #define IND (SIS_TWOSIDE_BIT | SIS_OFFSET_BIT)
336 #define TAG(x) x##_twoside_offset
337 #include "tnl_dd/t_dd_tritmp.h"
338
339 #define IND (SIS_UNFILLED_BIT)
340 #define TAG(x) x##_unfilled
341 #include "tnl_dd/t_dd_tritmp.h"
342
343 #define IND (SIS_OFFSET_BIT | SIS_UNFILLED_BIT)
344 #define TAG(x) x##_offset_unfilled
345 #include "tnl_dd/t_dd_tritmp.h"
346
347 #define IND (SIS_TWOSIDE_BIT | SIS_UNFILLED_BIT)
348 #define TAG(x) x##_twoside_unfilled
349 #include "tnl_dd/t_dd_tritmp.h"
350
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"
354
355 #define IND (SIS_FALLBACK_BIT)
356 #define TAG(x) x##_fallback
357 #include "tnl_dd/t_dd_tritmp.h"
358
359 #define IND (SIS_OFFSET_BIT | SIS_FALLBACK_BIT)
360 #define TAG(x) x##_offset_fallback
361 #include "tnl_dd/t_dd_tritmp.h"
362
363 #define IND (SIS_TWOSIDE_BIT | SIS_FALLBACK_BIT)
364 #define TAG(x) x##_twoside_fallback
365 #include "tnl_dd/t_dd_tritmp.h"
366
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"
370
371 #define IND (SIS_UNFILLED_BIT | SIS_FALLBACK_BIT)
372 #define TAG(x) x##_unfilled_fallback
373 #include "tnl_dd/t_dd_tritmp.h"
374
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"
378
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"
382
383 #define IND (SIS_TWOSIDE_BIT | SIS_OFFSET_BIT | SIS_UNFILLED_BIT | \
384 SIS_FALLBACK_BIT)
385 #define TAG(x) x##_twoside_offset_unfilled_fallback
386 #include "tnl_dd/t_dd_tritmp.h"
387
388
389 static void init_rast_tab( void )
390 {
391 init();
392 init_offset();
393 init_twoside();
394 init_twoside_offset();
395 init_unfilled();
396 init_offset_unfilled();
397 init_twoside_unfilled();
398 init_twoside_offset_unfilled();
399 init_fallback();
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();
407 }
408
409
410
411 /***********************************************************************
412 * Rasterization fallback helpers *
413 ***********************************************************************/
414
415
416 /* This code is hit only when a mix of accelerated and unaccelerated
417 * primitives are being drawn, and only for the unaccelerated
418 * primitives.
419 */
420 static void
421 sis_fallback_quad( sisContextPtr smesa,
422 sisVertex *v0,
423 sisVertex *v1,
424 sisVertex *v2,
425 sisVertex *v3 )
426 {
427 GLcontext *ctx = smesa->glCtx;
428 SWvertex v[4];
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] );
435 }
436
437 static void
438 sis_fallback_tri( sisContextPtr smesa,
439 sisVertex *v0,
440 sisVertex *v1,
441 sisVertex *v2 )
442 {
443 GLcontext *ctx = smesa->glCtx;
444 SWvertex v[3];
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] );
449 }
450
451
452 static void
453 sis_fallback_line( sisContextPtr smesa,
454 sisVertex *v0,
455 sisVertex *v1 )
456 {
457 GLcontext *ctx = smesa->glCtx;
458 SWvertex v[2];
459 sis_translate_vertex( ctx, v0, &v[0] );
460 sis_translate_vertex( ctx, v1, &v[1] );
461 _swrast_Line( ctx, &v[0], &v[1] );
462 }
463
464
465 static void
466 sis_fallback_point( sisContextPtr smesa,
467 sisVertex *v0 )
468 {
469 GLcontext *ctx = smesa->glCtx;
470 SWvertex v[1];
471 sis_translate_vertex( ctx, v0, &v[0] );
472 _swrast_Point( ctx, &v[0] );
473 }
474
475
476
477 /**********************************************************************/
478 /* Render unclipped begin/end objects */
479 /**********************************************************************/
480
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), \
487 VERT(v2) )
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 )
491 #undef LOCAL_VARS
492 #define LOCAL_VARS \
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; \
497 (void) elt;
498 #define RESET_STIPPLE
499 #define RESET_OCCLUSION
500 #define PRESERVE_VB_DEFS
501 #define ELT(x) (x)
502 #define TAG(x) sis_##x##_verts
503 #include "tnl/t_vb_rendertmp.h"
504 #undef ELT
505 #undef TAG
506 #define TAG(x) sis_##x##_elts
507 #define ELT(x) elt[x]
508 #include "tnl/t_vb_rendertmp.h"
509
510
511 /**********************************************************************/
512 /* Render clipped primitives */
513 /**********************************************************************/
514
515 static void sisRenderClippedPoly( GLcontext *ctx, const GLuint *elts, GLuint n )
516 {
517 TNLcontext *tnl = TNL_CONTEXT(ctx);
518 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
519
520 /* Render the new vertices as an unclipped polygon.
521 */
522 {
523 GLuint *tmp = VB->Elts;
524 VB->Elts = (GLuint *)elts;
525 tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
526 VB->Elts = tmp;
527 }
528 }
529
530 static void sisRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
531 {
532 TNLcontext *tnl = TNL_CONTEXT(ctx);
533 tnl->Driver.Render.Line( ctx, ii, jj );
534 }
535
536 #if 0
537 static void sisFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
538 GLuint n )
539 {
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]);
546 int i,j;
547
548 smesa->num_verts += (n-2) * 3;
549
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 );
554 }
555 }
556 #endif
557
558
559
560
561 /**********************************************************************/
562 /* Choose render functions */
563 /**********************************************************************/
564
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) \
572
573
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)
579
580
581 static void sisChooseRenderState(GLcontext *ctx)
582 {
583 sisContextPtr smesa = SIS_CONTEXT( ctx );
584 GLuint flags = ctx->_TriangleCaps;
585 GLuint index = 0;
586 GLuint vertindex = 0;
587
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;
594
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];
600 } else {
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];
605 }
606 smesa->AGPParseSet &= ~(MASK_VertexDWSize | MASK_VertexDataFormat);
607 smesa->AGPParseSet |= AGPParsingValues[vertindex];
608
609 if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) {
610
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;
615 }
616
617 /* Hook in fallbacks for specific primitives.
618 */
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;
627 }
628 index |= SIS_FALLBACK_BIT;
629 }
630 }
631
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;
638
639 if (index == 0) {
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;
645 } else {
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;
650 }
651
652 smesa->RenderIndex = index;
653 }
654 }
655
656 /**********************************************************************/
657 /* Multipass rendering for front buffering */
658 /**********************************************************************/
659 static GLboolean multipass_cliprect( GLcontext *ctx, GLuint pass )
660 {
661 sisContextPtr smesa = SIS_CONTEXT( ctx );
662
663 if (pass >= smesa->driDrawable->numClipRects) {
664 return GL_FALSE;
665 } else {
666 GLint x1, y1, x2, y2;
667
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;
672
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);
676
677 if (ctx->Scissor.X > x1)
678 x1 = ctx->Scissor.X;
679 if (scisy1 > y1)
680 y1 = scisy1;
681 if (ctx->Scissor.X + ctx->Scissor.Width - 1 < x2)
682 x2 = ctx->Scissor.X + ctx->Scissor.Width - 1;
683 if (scisy2 < y2)
684 y2 = scisy2;
685 }
686
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;
691 return GL_TRUE;
692 }
693 }
694
695
696
697 /**********************************************************************/
698 /* Validate state at pipeline start */
699 /**********************************************************************/
700
701 static void sisRunPipeline( GLcontext *ctx )
702 {
703 sisContextPtr smesa = SIS_CONTEXT( ctx );
704
705 LOCK_HARDWARE();
706 sisUpdateHWState( ctx );
707
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 );
714 }
715
716 if (!smesa->Fallback && smesa->NewGLState) {
717 if (smesa->NewGLState & _SIS_NEW_VERTEX_STATE)
718 sisChooseVertexState( ctx );
719
720 if (smesa->NewGLState & (_SIS_NEW_RENDER_STATE | _NEW_TEXTURE))
721 sisChooseRenderState( ctx );
722
723 smesa->NewGLState = 0;
724 }
725
726 _tnl_run_pipeline( ctx );
727
728 if (smesa->AGPCmdModeEnabled)
729 sisFireVertsAGP( smesa );
730 else
731 mEndPrimitive();
732 UNLOCK_HARDWARE();
733 }
734
735 /**********************************************************************/
736 /* High level hooks for t_vb_render.c */
737 /**********************************************************************/
738
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.
742 */
743
744 static void sisRasterPrimitive( GLcontext *ctx, GLuint hwprim )
745 {
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];
754 else
755 smesa->AGPParseSet |= MASK_PsShadingSmooth;
756 } else {
757 mEndPrimitive();
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];
763 else
764 smesa->dwPrimitiveSet |= SHADE_GOURAUD;
765 }
766 }
767 smesa->hw_primitive = hwprim;
768 }
769
770 static void sisRenderPrimitive( GLcontext *ctx, GLenum prim )
771 {
772 sisContextPtr smesa = SIS_CONTEXT(ctx);
773
774 smesa->render_primitive = prim;
775 if (prim >= GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
776 return;
777 sisRasterPrimitive( ctx, hw_prim[prim] );
778 }
779
780
781 static void sisRenderStart( GLcontext *ctx )
782 {
783 TNLcontext *tnl = TNL_CONTEXT(ctx);
784 sisContextPtr smesa = SIS_CONTEXT(ctx);
785
786 /* Check for projective texturing. Make sure all texcoord
787 * pointers point to something. (fix in mesa?)
788 */
789 sisCheckTexSizes( ctx );
790
791 if (ctx->Color._DrawDestMask == FRONT_LEFT_BIT &&
792 smesa->driDrawable->numClipRects != 0)
793 {
794 multipass_cliprect(ctx, 0);
795 if (smesa->driDrawable->numClipRects > 1)
796 tnl->Driver.Render.Multipass = multipass_cliprect;
797 else
798 tnl->Driver.Render.Multipass = NULL;
799 } else {
800 tnl->Driver.Render.Multipass = NULL;
801 }
802 }
803
804 static void sisRenderFinish( GLcontext *ctx )
805 {
806 }
807
808 /* Update SpaceLeft after an engine or current write pointer update */
809 static void sisUpdateAGP( sisContextPtr smesa )
810 {
811 /* ReadPtr == WritePtr is the empty case */
812 if (AGP_ReadPtr <= AGP_WritePtr)
813 AGP_SpaceLeft = (long)smesa->AGPCmdBufBase + (long)smesa->AGPCmdBufSize -
814 (long)AGP_WritePtr;
815 else
816 AGP_SpaceLeft = AGP_ReadPtr - AGP_WritePtr - 4;
817 }
818
819 /* Fires a set of vertices that have been written from AGP_StartPtr to
820 * AGP_WritePtr, using the smesa->AGPParseSet format.
821 */
822 void
823 sisFireVertsAGP( sisContextPtr smesa )
824 {
825 if (AGP_WritePtr == AGP_StartPtr)
826 return;
827
828 mWait3DCmdQueue(5);
829 mEndPrimitive();
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) |
833 0x50000000);
834 MMIO(REG_3D_ParsingSet, smesa->AGPParseSet);
835
836 MMIO(REG_3D_AGPCmFire, (GLint)(-1));
837 mEndPrimitive();
838
839 *(smesa->pAGPCmdBufNext) = (((long)AGP_WritePtr -
840 (long)smesa->AGPCmdBufBase) + 0xf) & ~0xf;
841 AGP_StartPtr = AGP_WritePtr;
842 sisUpdateAGP( smesa );
843 }
844
845 /* Make sure there are more than num dwords left in the AGP queue. */
846 static void
847 sisMakeRoomAGP( sisContextPtr smesa, GLint num )
848 {
849 int size = num * 4;
850
851 if (size <= AGP_SpaceLeft) {
852 AGP_SpaceLeft -= size;
853 return;
854 }
855 /* Wrapping */
856 if (AGP_WritePtr + num > (GLfloat *)(smesa->AGPCmdBufBase +
857 smesa->AGPCmdBufSize))
858 {
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? */
864 }
865
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. */
873 usleep(1);
874 AGP_ReadPtr = (GLfloat *)((long)MMIO_READ(REG_3D_AGPCmBase) -
875 (long)smesa->AGPCmdBufAddr + (long)smesa->AGPCmdBufBase);
876 sisUpdateAGP( smesa );
877 }
878 }
879 AGP_SpaceLeft -= size;
880 }
881
882 /**********************************************************************/
883 /* Transition to/from hardware rasterization. */
884 /**********************************************************************/
885
886 void sisFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
887 {
888 TNLcontext *tnl = TNL_CONTEXT(ctx);
889 sisContextPtr smesa = SIS_CONTEXT(ctx);
890 GLuint oldfallback = smesa->Fallback;
891
892 if (mode) {
893 smesa->Fallback |= bit;
894 if (oldfallback == 0) {
895 _swsetup_Wakeup( ctx );
896 smesa->RenderIndex = ~0;
897 }
898 }
899 else {
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);
909 }
910 }
911 }
912
913
914 /**********************************************************************/
915 /* Initialization. */
916 /**********************************************************************/
917
918 void sisInitTriFuncs( GLcontext *ctx )
919 {
920 sisContextPtr smesa = SIS_CONTEXT(ctx);
921 TNLcontext *tnl = TNL_CONTEXT(ctx);
922 static int firsttime = 1;
923
924 if (firsttime) {
925 init_rast_tab();
926 firsttime = 0;
927
928 sis_vert_init_none();
929 sis_vert_init_s();
930 sis_vert_init_t0();
931 sis_vert_init_st0();
932 sis_vert_init_t1();
933 sis_vert_init_st1();
934 sis_vert_init_t0t1();
935 sis_vert_init_st0t1();
936 }
937
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;
945
946 if (driQueryOptionb(&smesa->optionCache, "fallback_force"))
947 sisFallback(ctx, SIS_FALLBACK_FORCE, 1);
948 else
949 sisFallback(ctx, SIS_FALLBACK_FORCE, 0);
950
951 smesa->RenderIndex = ~0;
952 smesa->NewGLState |= (_SIS_NEW_RENDER_STATE|
953 _SIS_NEW_VERTEX_STATE);
954 }