Updates to tnl_dd_dmatmp.h
[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_size * sizeof(int)))
269
270 #define VERT_SET_RGBA( v, c ) \
271 do { \
272 sis_color_t *color = (sis_color_t *)&((v)->ui[coloroffset]); \
273 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
274 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
275 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
276 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
277 } while (0)
278
279 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
280
281 #define VERT_SET_SPEC( v0, c ) \
282 do { \
283 if (havespec) { \
284 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.red, (c)[0]); \
285 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.green, (c)[1]); \
286 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.blue, (c)[2]); \
287 } \
288 } while (0)
289 #define VERT_COPY_SPEC( v0, v1 ) \
290 do { \
291 if (havespec) { \
292 v0->v.specular.red = v1->v.specular.red; \
293 v0->v.specular.green = v1->v.specular.green; \
294 v0->v.specular.blue = v1->v.specular.blue; \
295 } \
296 } while (0)
297
298 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
299 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
300 #define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5]
301 #define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx]
302
303 #define LOCAL_VARS(n) \
304 sisContextPtr smesa = SIS_CONTEXT(ctx); \
305 GLuint color[n], spec[n]; \
306 GLuint coloroffset = (smesa->vertex_size == 4 ? 3 : 4); \
307 GLboolean havespec = (smesa->vertex_size == 4 ? 0 : 1); \
308 (void) color; (void) spec; (void) coloroffset; (void) havespec;
309
310 /***********************************************************************
311 * Helpers for rendering unfilled primitives *
312 ***********************************************************************/
313
314 #define RASTERIZE(x) if (smesa->hw_primitive != hw_prim[x]) \
315 sisRasterPrimitive( ctx, hw_prim[x] )
316 #define RENDER_PRIMITIVE smesa->render_primitive
317 #define IND SIS_FALLBACK_BIT
318 #define TAG(x) x
319 #include "tnl_dd/t_dd_unfilled.h"
320 #undef IND
321
322
323 /***********************************************************************
324 * Generate GL render functions *
325 ***********************************************************************/
326
327
328 #define IND (0)
329 #define TAG(x) x
330 #include "tnl_dd/t_dd_tritmp.h"
331
332 #define IND (SIS_OFFSET_BIT)
333 #define TAG(x) x##_offset
334 #include "tnl_dd/t_dd_tritmp.h"
335
336 #define IND (SIS_TWOSIDE_BIT)
337 #define TAG(x) x##_twoside
338 #include "tnl_dd/t_dd_tritmp.h"
339
340 #define IND (SIS_TWOSIDE_BIT | SIS_OFFSET_BIT)
341 #define TAG(x) x##_twoside_offset
342 #include "tnl_dd/t_dd_tritmp.h"
343
344 #define IND (SIS_UNFILLED_BIT)
345 #define TAG(x) x##_unfilled
346 #include "tnl_dd/t_dd_tritmp.h"
347
348 #define IND (SIS_OFFSET_BIT | SIS_UNFILLED_BIT)
349 #define TAG(x) x##_offset_unfilled
350 #include "tnl_dd/t_dd_tritmp.h"
351
352 #define IND (SIS_TWOSIDE_BIT | SIS_UNFILLED_BIT)
353 #define TAG(x) x##_twoside_unfilled
354 #include "tnl_dd/t_dd_tritmp.h"
355
356 #define IND (SIS_TWOSIDE_BIT | SIS_OFFSET_BIT | SIS_UNFILLED_BIT)
357 #define TAG(x) x##_twoside_offset_unfilled
358 #include "tnl_dd/t_dd_tritmp.h"
359
360 #define IND (SIS_FALLBACK_BIT)
361 #define TAG(x) x##_fallback
362 #include "tnl_dd/t_dd_tritmp.h"
363
364 #define IND (SIS_OFFSET_BIT | SIS_FALLBACK_BIT)
365 #define TAG(x) x##_offset_fallback
366 #include "tnl_dd/t_dd_tritmp.h"
367
368 #define IND (SIS_TWOSIDE_BIT | SIS_FALLBACK_BIT)
369 #define TAG(x) x##_twoside_fallback
370 #include "tnl_dd/t_dd_tritmp.h"
371
372 #define IND (SIS_TWOSIDE_BIT | SIS_OFFSET_BIT | SIS_FALLBACK_BIT)
373 #define TAG(x) x##_twoside_offset_fallback
374 #include "tnl_dd/t_dd_tritmp.h"
375
376 #define IND (SIS_UNFILLED_BIT | SIS_FALLBACK_BIT)
377 #define TAG(x) x##_unfilled_fallback
378 #include "tnl_dd/t_dd_tritmp.h"
379
380 #define IND (SIS_OFFSET_BIT | SIS_UNFILLED_BIT | SIS_FALLBACK_BIT)
381 #define TAG(x) x##_offset_unfilled_fallback
382 #include "tnl_dd/t_dd_tritmp.h"
383
384 #define IND (SIS_TWOSIDE_BIT | SIS_UNFILLED_BIT | SIS_FALLBACK_BIT)
385 #define TAG(x) x##_twoside_unfilled_fallback
386 #include "tnl_dd/t_dd_tritmp.h"
387
388 #define IND (SIS_TWOSIDE_BIT | SIS_OFFSET_BIT | SIS_UNFILLED_BIT | \
389 SIS_FALLBACK_BIT)
390 #define TAG(x) x##_twoside_offset_unfilled_fallback
391 #include "tnl_dd/t_dd_tritmp.h"
392
393
394 static void init_rast_tab( void )
395 {
396 init();
397 init_offset();
398 init_twoside();
399 init_twoside_offset();
400 init_unfilled();
401 init_offset_unfilled();
402 init_twoside_unfilled();
403 init_twoside_offset_unfilled();
404 init_fallback();
405 init_offset_fallback();
406 init_twoside_fallback();
407 init_twoside_offset_fallback();
408 init_unfilled_fallback();
409 init_offset_unfilled_fallback();
410 init_twoside_unfilled_fallback();
411 init_twoside_offset_unfilled_fallback();
412 }
413
414
415
416 /***********************************************************************
417 * Rasterization fallback helpers *
418 ***********************************************************************/
419
420
421 /* This code is hit only when a mix of accelerated and unaccelerated
422 * primitives are being drawn, and only for the unaccelerated
423 * primitives.
424 */
425 static void
426 sis_fallback_quad( sisContextPtr smesa,
427 sisVertex *v0,
428 sisVertex *v1,
429 sisVertex *v2,
430 sisVertex *v3 )
431 {
432 GLcontext *ctx = smesa->glCtx;
433 SWvertex v[4];
434 sis_translate_vertex( ctx, v0, &v[0] );
435 sis_translate_vertex( ctx, v1, &v[1] );
436 sis_translate_vertex( ctx, v2, &v[2] );
437 sis_translate_vertex( ctx, v3, &v[3] );
438 _swrast_Triangle( ctx, &v[0], &v[1], &v[3] );
439 _swrast_Triangle( ctx, &v[1], &v[2], &v[3] );
440 }
441
442 static void
443 sis_fallback_tri( sisContextPtr smesa,
444 sisVertex *v0,
445 sisVertex *v1,
446 sisVertex *v2 )
447 {
448 GLcontext *ctx = smesa->glCtx;
449 SWvertex v[3];
450 sis_translate_vertex( ctx, v0, &v[0] );
451 sis_translate_vertex( ctx, v1, &v[1] );
452 sis_translate_vertex( ctx, v2, &v[2] );
453 _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
454 }
455
456
457 static void
458 sis_fallback_line( sisContextPtr smesa,
459 sisVertex *v0,
460 sisVertex *v1 )
461 {
462 GLcontext *ctx = smesa->glCtx;
463 SWvertex v[2];
464 sis_translate_vertex( ctx, v0, &v[0] );
465 sis_translate_vertex( ctx, v1, &v[1] );
466 _swrast_Line( ctx, &v[0], &v[1] );
467 }
468
469
470 static void
471 sis_fallback_point( sisContextPtr smesa,
472 sisVertex *v0 )
473 {
474 GLcontext *ctx = smesa->glCtx;
475 SWvertex v[1];
476 sis_translate_vertex( ctx, v0, &v[0] );
477 _swrast_Point( ctx, &v[0] );
478 }
479
480
481
482 /**********************************************************************/
483 /* Render unclipped begin/end objects */
484 /**********************************************************************/
485
486 #define VERT(x) (sisVertex *)(sisverts + (x * vertsize * sizeof(int)))
487 #define RENDER_POINTS( start, count ) \
488 for ( ; start < count ; start++) \
489 smesa->draw_point( smesa, VERT(start) )
490 #define RENDER_LINE( v0, v1 ) smesa->draw_line( smesa, VERT(v0), VERT(v1) )
491 #define RENDER_TRI( v0, v1, v2 ) smesa->draw_tri( smesa, VERT(v0), VERT(v1), \
492 VERT(v2) )
493 #define RENDER_QUAD( v0, v1, v2, v3 ) smesa->draw_quad( smesa, VERT(v0), \
494 VERT(v1), VERT(v2), VERT(v3))
495 #define INIT(x) sisRenderPrimitive( ctx, x )
496 #undef LOCAL_VARS
497 #define LOCAL_VARS \
498 sisContextPtr smesa = SIS_CONTEXT(ctx); \
499 const GLuint vertsize = smesa->vertex_size; \
500 const char *sisverts = (char *)smesa->verts; \
501 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
502 (void) elt;
503 #define RESET_STIPPLE
504 #define RESET_OCCLUSION
505 #define PRESERVE_VB_DEFS
506 #define ELT(x) (x)
507 #define TAG(x) sis_##x##_verts
508 #include "tnl/t_vb_rendertmp.h"
509 #undef ELT
510 #undef TAG
511 #define TAG(x) sis_##x##_elts
512 #define ELT(x) elt[x]
513 #include "tnl/t_vb_rendertmp.h"
514
515
516 /**********************************************************************/
517 /* Render clipped primitives */
518 /**********************************************************************/
519
520 static void sisRenderClippedPoly( GLcontext *ctx, const GLuint *elts, GLuint n )
521 {
522 TNLcontext *tnl = TNL_CONTEXT(ctx);
523 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
524
525 /* Render the new vertices as an unclipped polygon.
526 */
527 {
528 GLuint *tmp = VB->Elts;
529 VB->Elts = (GLuint *)elts;
530 tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
531 VB->Elts = tmp;
532 }
533 }
534
535 static void sisRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
536 {
537 TNLcontext *tnl = TNL_CONTEXT(ctx);
538 tnl->Driver.Render.Line( ctx, ii, jj );
539 }
540
541 #if 0
542 static void sisFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
543 GLuint n )
544 {
545 sisContextPtr smesa = SIS_CONTEXT( ctx );
546 GLuint vertsize = smesa->vertex_size;
547 GLuint *vb = r128AllocDmaLow( rmesa, (n-2) * 3 * 4 * vertsize );
548 GLubyte *sisverts = (GLubyte *)smesa->verts;
549 const GLuint *start = (const GLuint *)VERT(elts[0]);
550 int i,j;
551
552 smesa->num_verts += (n-2) * 3;
553
554 for (i = 2 ; i < n ; i++) {
555 COPY_DWORDS( j, vb, vertsize, (sisVertexPtr) VERT(elts[i-1]) );
556 COPY_DWORDS( j, vb, vertsize, (sisVertexPtr) VERT(elts[i]) );
557 COPY_DWORDS( j, vb, vertsize, (sisVertexPtr) start );
558 }
559 }
560 #endif
561
562
563
564
565 /**********************************************************************/
566 /* Choose render functions */
567 /**********************************************************************/
568
569 #define _SIS_NEW_RENDER_STATE (_DD_NEW_LINE_STIPPLE | \
570 _DD_NEW_LINE_SMOOTH | \
571 _DD_NEW_POINT_SMOOTH | \
572 _DD_NEW_TRI_SMOOTH | \
573 _DD_NEW_TRI_UNFILLED | \
574 _DD_NEW_TRI_LIGHT_TWOSIDE | \
575 _DD_NEW_TRI_OFFSET) \
576
577
578 #define POINT_FALLBACK (DD_POINT_SMOOTH)
579 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
580 #define TRI_FALLBACK (DD_TRI_SMOOTH)
581 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
582 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
583
584
585 static void sisChooseRenderState(GLcontext *ctx)
586 {
587 sisContextPtr smesa = SIS_CONTEXT( ctx );
588 GLuint flags = ctx->_TriangleCaps;
589 GLuint index = 0;
590 GLuint vertindex = 0;
591
592 if (ctx->Texture.Unit[0]._ReallyEnabled)
593 vertindex |= SIS_VERT_TEX0;
594 if (ctx->Texture.Unit[1]._ReallyEnabled)
595 vertindex |= SIS_VERT_TEX1;
596 if (ctx->Light.ShadeModel == GL_SMOOTH)
597 vertindex |= SIS_VERT_SMOOTH;
598
599 if (smesa->AGPCmdModeEnabled) {
600 smesa->draw_quad = sis_quad_func_agp[vertindex];
601 smesa->draw_tri = sis_tri_func_agp[vertindex];
602 smesa->draw_line = sis_line_func_agp[vertindex];
603 smesa->draw_point = sis_point_func_agp[vertindex];
604 } else {
605 smesa->draw_quad = sis_quad_func_mmio[vertindex];
606 smesa->draw_tri = sis_tri_func_mmio[vertindex];
607 smesa->draw_line = sis_line_func_mmio[vertindex];
608 smesa->draw_point = sis_point_func_mmio[vertindex];
609 }
610 smesa->AGPParseSet &= ~(MASK_VertexDWSize | MASK_VertexDataFormat);
611 smesa->AGPParseSet |= AGPParsingValues[vertindex];
612
613 if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) {
614
615 if (flags & ANY_RASTER_FLAGS) {
616 if (flags & DD_TRI_LIGHT_TWOSIDE) index |= SIS_TWOSIDE_BIT;
617 if (flags & DD_TRI_OFFSET) index |= SIS_OFFSET_BIT;
618 if (flags & DD_TRI_UNFILLED) index |= SIS_UNFILLED_BIT;
619 }
620
621 /* Hook in fallbacks for specific primitives.
622 */
623 if (flags & ANY_FALLBACK_FLAGS) {
624 if (flags & POINT_FALLBACK)
625 smesa->draw_point = sis_fallback_point;
626 if (flags & LINE_FALLBACK)
627 smesa->draw_line = sis_fallback_line;
628 if (flags & TRI_FALLBACK) {
629 smesa->draw_quad = sis_fallback_quad;
630 smesa->draw_tri = sis_fallback_tri;
631 }
632 index |= SIS_FALLBACK_BIT;
633 }
634 }
635
636 if (index != smesa->RenderIndex) {
637 TNLcontext *tnl = TNL_CONTEXT(ctx);
638 tnl->Driver.Render.Points = rast_tab[index].points;
639 tnl->Driver.Render.Line = rast_tab[index].line;
640 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
641 tnl->Driver.Render.Quad = rast_tab[index].quad;
642
643 if (index == 0) {
644 tnl->Driver.Render.PrimTabVerts = sis_render_tab_verts;
645 tnl->Driver.Render.PrimTabElts = sis_render_tab_elts;
646 tnl->Driver.Render.ClippedLine = rast_tab[index].line;
647 /*XXX: sisFastRenderClippedPoly*/
648 tnl->Driver.Render.ClippedPolygon = sisRenderClippedPoly;
649 } else {
650 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
651 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
652 tnl->Driver.Render.ClippedLine = sisRenderClippedLine;
653 tnl->Driver.Render.ClippedPolygon = sisRenderClippedPoly;
654 }
655
656 smesa->RenderIndex = index;
657 }
658 }
659
660 /**********************************************************************/
661 /* Multipass rendering for front buffering */
662 /**********************************************************************/
663 static GLboolean multipass_cliprect( GLcontext *ctx, GLuint pass )
664 {
665 sisContextPtr smesa = SIS_CONTEXT( ctx );
666
667 if (pass >= smesa->driDrawable->numClipRects) {
668 return GL_FALSE;
669 } else {
670 GLint x1, y1, x2, y2;
671
672 x1 = smesa->driDrawable->pClipRects[pass].x1 - smesa->driDrawable->x;
673 y1 = smesa->driDrawable->pClipRects[pass].y1 - smesa->driDrawable->y;
674 x2 = smesa->driDrawable->pClipRects[pass].x2 - smesa->driDrawable->x;
675 y2 = smesa->driDrawable->pClipRects[pass].y2 - smesa->driDrawable->y;
676
677 if (ctx->Scissor.Enabled) {
678 GLint scisy1 = Y_FLIP(ctx->Scissor.Y + ctx->Scissor.Height - 1);
679 GLint scisy2 = Y_FLIP(ctx->Scissor.Y);
680
681 if (ctx->Scissor.X > x1)
682 x1 = ctx->Scissor.X;
683 if (scisy1 > y1)
684 y1 = scisy1;
685 if (ctx->Scissor.X + ctx->Scissor.Width - 1 < x2)
686 x2 = ctx->Scissor.X + ctx->Scissor.Width - 1;
687 if (scisy2 < y2)
688 y2 = scisy2;
689 }
690
691 MMIO(REG_3D_ClipTopBottom, y1 << 13 | y2);
692 MMIO(REG_3D_ClipLeftRight, x1 << 13 | x2);
693 /* Mark that we clobbered these registers */
694 smesa->GlobalFlag |= GFLAG_CLIPPING;
695 return GL_TRUE;
696 }
697 }
698
699
700
701 /**********************************************************************/
702 /* Validate state at pipeline start */
703 /**********************************************************************/
704
705 static void sisRunPipeline( GLcontext *ctx )
706 {
707 sisContextPtr smesa = SIS_CONTEXT( ctx );
708
709 LOCK_HARDWARE();
710 sisUpdateHWState( ctx );
711
712 if (smesa->AGPCmdModeEnabled) {
713 AGP_WritePtr = (GLfloat *)smesa->AGPCmdBufBase + *smesa->pAGPCmdBufNext;
714 AGP_StartPtr = AGP_WritePtr;
715 AGP_ReadPtr = (GLfloat *)((long)MMIO_READ(REG_3D_AGPCmBase) -
716 (long)smesa->AGPCmdBufAddr + (long)smesa->AGPCmdBufBase);
717 sisUpdateAGP( smesa );
718 }
719
720 if (!smesa->Fallback && smesa->NewGLState) {
721 if (smesa->NewGLState & _SIS_NEW_VERTEX_STATE)
722 sisChooseVertexState( ctx );
723
724 if (smesa->NewGLState & (_SIS_NEW_RENDER_STATE | _NEW_TEXTURE))
725 sisChooseRenderState( ctx );
726
727 smesa->NewGLState = 0;
728 }
729
730 _tnl_run_pipeline( ctx );
731
732 if (smesa->AGPCmdModeEnabled)
733 sisFireVertsAGP( smesa );
734 else
735 mEndPrimitive();
736 UNLOCK_HARDWARE();
737 }
738
739 /**********************************************************************/
740 /* High level hooks for t_vb_render.c */
741 /**********************************************************************/
742
743 /* This is called when Mesa switches between rendering triangle
744 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
745 * and lines, points and bitmaps.
746 */
747
748 static void sisRasterPrimitive( GLcontext *ctx, GLuint hwprim )
749 {
750 sisContextPtr smesa = SIS_CONTEXT(ctx);
751 if (smesa->hw_primitive != hwprim) {
752 if (smesa->AGPCmdModeEnabled) {
753 sisFireVertsAGP( smesa );
754 smesa->AGPParseSet &= ~(MASK_PsDataType | MASK_PsShadingMode);
755 smesa->AGPParseSet |= hw_prim_agp_type[hwprim];
756 if (ctx->Light.ShadeModel == GL_FLAT)
757 smesa->AGPParseSet |= hw_prim_agp_shade[hwprim];
758 else
759 smesa->AGPParseSet |= MASK_PsShadingSmooth;
760 } else {
761 mEndPrimitive();
762 smesa->dwPrimitiveSet &= ~(MASK_DrawPrimitiveCommand |
763 MASK_SetFirePosition | MASK_ShadingMode);
764 smesa->dwPrimitiveSet |= hwprim | hw_prim_mmio_fire[hwprim];
765 if (ctx->Light.ShadeModel == GL_FLAT)
766 smesa->dwPrimitiveSet |= hw_prim_mmio_shade[hwprim];
767 else
768 smesa->dwPrimitiveSet |= SHADE_GOURAUD;
769 }
770 }
771 smesa->hw_primitive = hwprim;
772 }
773
774 static void sisRenderPrimitive( GLcontext *ctx, GLenum prim )
775 {
776 sisContextPtr smesa = SIS_CONTEXT(ctx);
777
778 smesa->render_primitive = prim;
779 if (prim >= GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
780 return;
781 sisRasterPrimitive( ctx, hw_prim[prim] );
782 }
783
784
785 static void sisRenderStart( GLcontext *ctx )
786 {
787 TNLcontext *tnl = TNL_CONTEXT(ctx);
788 sisContextPtr smesa = SIS_CONTEXT(ctx);
789
790 /* Check for projective texturing. Make sure all texcoord
791 * pointers point to something. (fix in mesa?)
792 */
793 sisCheckTexSizes( ctx );
794
795 if (ctx->Color._DrawDestMask == FRONT_LEFT_BIT &&
796 smesa->driDrawable->numClipRects != 0)
797 {
798 multipass_cliprect(ctx, 0);
799 if (smesa->driDrawable->numClipRects > 1)
800 tnl->Driver.Render.Multipass = multipass_cliprect;
801 else
802 tnl->Driver.Render.Multipass = NULL;
803 } else {
804 tnl->Driver.Render.Multipass = NULL;
805 }
806 }
807
808 static void sisRenderFinish( GLcontext *ctx )
809 {
810 }
811
812 /* Update SpaceLeft after an engine or current write pointer update */
813 static void sisUpdateAGP( sisContextPtr smesa )
814 {
815 /* ReadPtr == WritePtr is the empty case */
816 if (AGP_ReadPtr <= AGP_WritePtr)
817 AGP_SpaceLeft = (long)smesa->AGPCmdBufBase + (long)smesa->AGPCmdBufSize -
818 (long)AGP_WritePtr;
819 else
820 AGP_SpaceLeft = AGP_ReadPtr - AGP_WritePtr - 4;
821 }
822
823 /* Fires a set of vertices that have been written from AGP_StartPtr to
824 * AGP_WritePtr, using the smesa->AGPParseSet format.
825 */
826 void
827 sisFireVertsAGP( sisContextPtr smesa )
828 {
829 if (AGP_WritePtr == AGP_StartPtr)
830 return;
831
832 mWait3DCmdQueue(5);
833 mEndPrimitive();
834 MMIO(REG_3D_AGPCmBase, (long)AGP_StartPtr - (long)smesa->AGPCmdBufBase +
835 (long)smesa->AGPCmdBufAddr);
836 MMIO(REG_3D_AGPTtDwNum, (((long)AGP_WritePtr - (long)AGP_StartPtr) >> 2) |
837 0x50000000);
838 MMIO(REG_3D_ParsingSet, smesa->AGPParseSet);
839
840 MMIO(REG_3D_AGPCmFire, (GLint)(-1));
841 mEndPrimitive();
842
843 *(smesa->pAGPCmdBufNext) = (((long)AGP_WritePtr -
844 (long)smesa->AGPCmdBufBase) + 0xf) & ~0xf;
845 AGP_StartPtr = AGP_WritePtr;
846 sisUpdateAGP( smesa );
847 }
848
849 /* Make sure there are more than num dwords left in the AGP queue. */
850 static void
851 sisMakeRoomAGP( sisContextPtr smesa, GLint num )
852 {
853 int size = num * 4;
854
855 if (size <= AGP_SpaceLeft) {
856 AGP_SpaceLeft -= size;
857 return;
858 }
859 /* Wrapping */
860 if (AGP_WritePtr + num > (GLfloat *)(smesa->AGPCmdBufBase +
861 smesa->AGPCmdBufSize))
862 {
863 sisFireVertsAGP( smesa );
864 AGP_WritePtr = (GLfloat *)smesa->AGPCmdBufBase;
865 AGP_StartPtr = AGP_WritePtr;
866 sisUpdateAGP( smesa );
867 WaitEngIdle( smesa ); /* XXX Why is this necessary? */
868 }
869
870 if (size > AGP_SpaceLeft) {
871 /* Update the cached engine read pointer */
872 AGP_ReadPtr = (GLfloat *)((long)MMIO_READ(REG_3D_AGPCmBase) -
873 (long)smesa->AGPCmdBufAddr + (long)smesa->AGPCmdBufBase);
874 sisUpdateAGP( smesa );
875 while (size > AGP_SpaceLeft) {
876 /* Spin until space is available. */
877 AGP_ReadPtr = (GLfloat *)((long)MMIO_READ(REG_3D_AGPCmBase) -
878 (long)smesa->AGPCmdBufAddr + (long)smesa->AGPCmdBufBase);
879 sisUpdateAGP( smesa );
880 }
881 }
882 AGP_SpaceLeft -= size;
883 }
884
885 /**********************************************************************/
886 /* Transition to/from hardware rasterization. */
887 /**********************************************************************/
888
889 void sisFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
890 {
891 TNLcontext *tnl = TNL_CONTEXT(ctx);
892 sisContextPtr smesa = SIS_CONTEXT(ctx);
893 GLuint oldfallback = smesa->Fallback;
894
895 if (mode) {
896 smesa->Fallback |= bit;
897 if (oldfallback == 0) {
898 _swsetup_Wakeup( ctx );
899 smesa->RenderIndex = ~0;
900 }
901 }
902 else {
903 smesa->Fallback &= ~bit;
904 if (oldfallback == bit) {
905 _swrast_flush( ctx );
906 tnl->Driver.Render.Start = sisRenderStart;
907 tnl->Driver.Render.PrimitiveNotify = sisRenderPrimitive;
908 tnl->Driver.Render.Finish = sisRenderFinish;
909 tnl->Driver.Render.BuildVertices = sisBuildVertices;
910 smesa->NewGLState |= (_SIS_NEW_RENDER_STATE|
911 _SIS_NEW_VERTEX_STATE);
912 }
913 }
914 }
915
916
917 /**********************************************************************/
918 /* Initialization. */
919 /**********************************************************************/
920
921 void sisInitTriFuncs( GLcontext *ctx )
922 {
923 sisContextPtr smesa = SIS_CONTEXT(ctx);
924 TNLcontext *tnl = TNL_CONTEXT(ctx);
925 static int firsttime = 1;
926
927 if (firsttime) {
928 init_rast_tab();
929 firsttime = 0;
930
931 sis_vert_init_none();
932 sis_vert_init_s();
933 sis_vert_init_t0();
934 sis_vert_init_st0();
935 sis_vert_init_t1();
936 sis_vert_init_st1();
937 sis_vert_init_t0t1();
938 sis_vert_init_st0t1();
939 }
940
941 tnl->Driver.RunPipeline = sisRunPipeline;
942 tnl->Driver.Render.Start = sisRenderStart;
943 tnl->Driver.Render.Finish = sisRenderFinish;
944 tnl->Driver.Render.PrimitiveNotify = sisRenderPrimitive;
945 tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
946 tnl->Driver.Render.BuildVertices = sisBuildVertices;
947 tnl->Driver.Render.Multipass = NULL;
948
949 if (driQueryOptionb(&smesa->optionCache, "fallback_force"))
950 sisFallback(ctx, SIS_FALLBACK_FORCE, 1);
951 else
952 sisFallback(ctx, SIS_FALLBACK_FORCE, 0);
953
954 smesa->RenderIndex = ~0;
955 smesa->NewGLState |= (_SIS_NEW_RENDER_STATE|
956 _SIS_NEW_VERTEX_STATE);
957 }