de91268ee64dd6ccf8f21f7f650b75964c584942
[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/t_context.h"
43 #include "tnl/t_pipeline.h"
44
45 #include "sis_context.h"
46 #include "sis_tris.h"
47 #include "sis_state.h"
48 #include "sis_lock.h"
49 #include "sis_span.h"
50 #include "sis_alloc.h"
51 #include "sis_tex.h"
52
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 */
64 };
65
66 static const GLuint hw_prim_mmio_fire[OP_3D_TRIANGLE_DRAW+1] = {
67 OP_3D_FIRE_TSARGBa,
68 OP_3D_FIRE_TSARGBb,
69 OP_3D_FIRE_TSARGBc
70 };
71
72 static const GLuint hw_prim_mmio_shade[OP_3D_TRIANGLE_DRAW+1] = {
73 SHADE_FLAT_VertexA,
74 SHADE_FLAT_VertexB,
75 SHADE_FLAT_VertexC
76 };
77
78 static const GLuint hw_prim_agp_type[OP_3D_TRIANGLE_DRAW+1] = {
79 MASK_PsPointList,
80 MASK_PsLineList,
81 MASK_PsTriangleList
82 };
83
84 static const GLuint hw_prim_agp_shade[OP_3D_TRIANGLE_DRAW+1] = {
85 MASK_PsShadingFlatA,
86 MASK_PsShadingFlatB,
87 MASK_PsShadingFlatC
88 };
89
90 static void sisRasterPrimitive( GLcontext *ctx, GLuint hwprim );
91 static void sisRenderPrimitive( GLcontext *ctx, GLenum prim );
92
93 /***********************************************************************
94 * Emit primitives as inline vertices *
95 ***********************************************************************/
96
97 #define HAVE_QUADS 0
98 #define HAVE_LINES 1
99 #define HAVE_POINTS 1
100 #define CTX_ARG sisContextPtr smesa
101 #define GET_VERTEX_DWORDS() smesa->vertex_size
102 #define ALLOC_VERTS( n, size ) sisAllocDmaLow( smesa, n * size * sizeof(int) )
103 #undef LOCAL_VARS
104 #define LOCAL_VARS \
105 sisContextPtr smesa = SIS_CONTEXT(ctx); \
106 const char *vertptr = smesa->verts;
107 #define VERT(x) (sisVertex *)(vertptr + (x * vertsize * sizeof(int)))
108 #define VERTEX sisVertex
109 #undef TAG
110 #define TAG(x) sis_##x
111 #include "tnl_dd/t_dd_triemit.h"
112 #undef TAG
113 #undef LOCAL_VARS
114
115 /***********************************************************************
116 * Dispatch vertices to hardware through MMIO *
117 ***********************************************************************/
118
119 /* The ARGB write of the last vertex of the primitive fires the 3d engine, so
120 * save it until the end.
121 */
122 #define SIS_MMIO_WRITE_VERTEX(_v, i, lastvert) \
123 do { \
124 GLuint __color, __i = 0; \
125 MMIO(REG_3D_TSXa+(i)*0x30, _v->ui[__i++]); \
126 MMIO(REG_3D_TSYa+(i)*0x30, _v->ui[__i++]); \
127 MMIO(REG_3D_TSZa+(i)*0x30, _v->ui[__i++]); \
128 if (SIS_STATES & VERT_W) \
129 MMIO(REG_3D_TSWGa+(i)*0x30, _v->ui[__i++]); \
130 __color = _v->ui[__i++]; \
131 if (SIS_STATES & VERT_SPEC) \
132 MMIO(REG_3D_TSFSa+(i)*0x30, _v->ui[__i++]); \
133 if (SIS_STATES & VERT_UV0) { \
134 MMIO(REG_3D_TSUAa+(i)*0x30, _v->ui[__i++]); \
135 MMIO(REG_3D_TSVAa+(i)*0x30, _v->ui[__i++]); \
136 } \
137 if (SIS_STATES & VERT_UV1) { \
138 MMIO(REG_3D_TSUBa+(i)*0x30, _v->ui[__i++]); \
139 MMIO(REG_3D_TSVBa+(i)*0x30, _v->ui[__i++]); \
140 } \
141 if (lastvert || (SIS_STATES & VERT_SMOOTH)) \
142 MMIO(REG_3D_TSARGBa+(i)*0x30, __color); \
143 } while (0)
144
145 #define MMIO_VERT_REG_COUNT 10
146
147 #define VERT_SMOOTH 0x01
148 #define VERT_W 0x02
149 #define VERT_SPEC 0x04
150 #define VERT_UV0 0x08
151 #define VERT_UV1 0x10
152
153 typedef void (*mmio_draw_func)(sisContextPtr smesa, char *verts);
154 static mmio_draw_func sis_tri_func_mmio[32];
155 static mmio_draw_func sis_line_func_mmio[32];
156 static mmio_draw_func sis_point_func_mmio[32];
157
158 #define SIS_STATES (0)
159 #define TAG(x) x##_none
160 #include "sis_tritmp.h"
161
162 #define SIS_STATES (VERT_SMOOTH)
163 #define TAG(x) x##_g
164 #include "sis_tritmp.h"
165
166 #define SIS_STATES (VERT_W)
167 #define TAG(x) x##_w
168 #include "sis_tritmp.h"
169
170 #define SIS_STATES (VERT_SMOOTH | VERT_W)
171 #define TAG(x) x##_gw
172 #include "sis_tritmp.h"
173
174 #define SIS_STATES (VERT_SPEC)
175 #define TAG(x) x##_s
176 #include "sis_tritmp.h"
177
178 #define SIS_STATES (VERT_SMOOTH | VERT_SPEC)
179 #define TAG(x) x##_gs
180 #include "sis_tritmp.h"
181
182 #define SIS_STATES (VERT_W | VERT_SPEC)
183 #define TAG(x) x##_ws
184 #include "sis_tritmp.h"
185
186 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC)
187 #define TAG(x) x##_gws
188 #include "sis_tritmp.h"
189
190 #define SIS_STATES (VERT_UV0)
191 #define TAG(x) x##_t0
192 #include "sis_tritmp.h"
193
194 #define SIS_STATES (VERT_SMOOTH | VERT_UV0)
195 #define TAG(x) x##_gt0
196 #include "sis_tritmp.h"
197
198 #define SIS_STATES (VERT_W | VERT_UV0)
199 #define TAG(x) x##_wt0
200 #include "sis_tritmp.h"
201
202 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_UV0)
203 #define TAG(x) x##_gwt0
204 #include "sis_tritmp.h"
205
206 #define SIS_STATES (VERT_SPEC | VERT_UV0)
207 #define TAG(x) x##_st0
208 #include "sis_tritmp.h"
209
210 #define SIS_STATES (VERT_SMOOTH | VERT_SPEC | VERT_UV0)
211 #define TAG(x) x##_gst0
212 #include "sis_tritmp.h"
213
214 #define SIS_STATES (VERT_W | VERT_SPEC | VERT_UV0)
215 #define TAG(x) x##_wst0
216 #include "sis_tritmp.h"
217
218 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC | VERT_UV0)
219 #define TAG(x) x##_gwst0
220 #include "sis_tritmp.h"
221
222 #define SIS_STATES (VERT_UV1)
223 #define TAG(x) x##_t1
224 #include "sis_tritmp.h"
225
226 #define SIS_STATES (VERT_SMOOTH | VERT_UV1)
227 #define TAG(x) x##_gt1
228 #include "sis_tritmp.h"
229
230 #define SIS_STATES (VERT_W | VERT_UV1)
231 #define TAG(x) x##_wt1
232 #include "sis_tritmp.h"
233
234 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_UV1)
235 #define TAG(x) x##_gwt1
236 #include "sis_tritmp.h"
237
238 #define SIS_STATES (VERT_SPEC | VERT_UV1)
239 #define TAG(x) x##_st1
240 #include "sis_tritmp.h"
241
242 #define SIS_STATES (VERT_SMOOTH | VERT_SPEC | VERT_UV1)
243 #define TAG(x) x##_gst1
244 #include "sis_tritmp.h"
245
246 #define SIS_STATES (VERT_W | VERT_SPEC | VERT_UV1)
247 #define TAG(x) x##_wst1
248 #include "sis_tritmp.h"
249
250 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC | VERT_UV1)
251 #define TAG(x) x##_gwst1
252 #include "sis_tritmp.h"
253
254 #define SIS_STATES (VERT_UV0 | VERT_UV1)
255 #define TAG(x) x##_t0t1
256 #include "sis_tritmp.h"
257
258 #define SIS_STATES (VERT_SMOOTH | VERT_UV0 | VERT_UV1)
259 #define TAG(x) x##_gt0t1
260 #include "sis_tritmp.h"
261
262 #define SIS_STATES (VERT_W | VERT_UV0 | VERT_UV1)
263 #define TAG(x) x##_wt0t1
264 #include "sis_tritmp.h"
265
266 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_UV0 | VERT_UV1)
267 #define TAG(x) x##_gwt0t1
268 #include "sis_tritmp.h"
269
270 #define SIS_STATES (VERT_SPEC | VERT_UV0 | VERT_UV1)
271 #define TAG(x) x##_st0t1
272 #include "sis_tritmp.h"
273
274 #define SIS_STATES (VERT_SMOOTH | VERT_SPEC | VERT_UV0 | VERT_UV1)
275 #define TAG(x) x##_gst0t1
276 #include "sis_tritmp.h"
277
278 #define SIS_STATES (VERT_W | VERT_SPEC | VERT_UV0 | VERT_UV1)
279 #define TAG(x) x##_wst0t1
280 #include "sis_tritmp.h"
281
282 #define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC | VERT_UV0 | VERT_UV1)
283 #define TAG(x) x##_gwst0t1
284 #include "sis_tritmp.h"
285
286 /***********************************************************************
287 * Macros for t_dd_tritmp.h to draw basic primitives *
288 ***********************************************************************/
289
290 #define TRI( a, b, c ) \
291 do { \
292 if (DO_FALLBACK) \
293 smesa->draw_tri( smesa, a, b, c ); \
294 else \
295 sis_triangle( smesa, a, b, c ); \
296 } while (0)
297
298 #define QUAD( a, b, c, d ) \
299 do { \
300 if (DO_FALLBACK) { \
301 smesa->draw_tri( smesa, a, b, d ); \
302 smesa->draw_tri( smesa, b, c, d ); \
303 } else \
304 sis_quad( smesa, a, b, c, d ); \
305 } while (0)
306
307 #define LINE( v0, v1 ) \
308 do { \
309 if (DO_FALLBACK) \
310 smesa->draw_line( smesa, v0, v1 ); \
311 else \
312 sis_line( smesa, v0, v1 ); \
313 } while (0)
314
315 #define POINT( v0 ) \
316 do { \
317 if (DO_FALLBACK) \
318 smesa->draw_point( smesa, v0 ); \
319 else \
320 sis_point( smesa, v0 ); \
321 } while (0)
322
323 /***********************************************************************
324 * Build render functions from dd templates *
325 ***********************************************************************/
326
327 #define SIS_OFFSET_BIT 0x01
328 #define SIS_TWOSIDE_BIT 0x02
329 #define SIS_UNFILLED_BIT 0x04
330 #define SIS_FALLBACK_BIT 0x08
331 #define SIS_MAX_TRIFUNC 0x10
332
333
334 static struct {
335 tnl_points_func points;
336 tnl_line_func line;
337 tnl_triangle_func triangle;
338 tnl_quad_func quad;
339 } rast_tab[SIS_MAX_TRIFUNC];
340
341
342 #define DO_FALLBACK (IND & SIS_FALLBACK_BIT)
343 #define DO_OFFSET (IND & SIS_OFFSET_BIT)
344 #define DO_UNFILLED (IND & SIS_UNFILLED_BIT)
345 #define DO_TWOSIDE (IND & SIS_TWOSIDE_BIT)
346 #define DO_FLAT 0
347 #define DO_TRI 1
348 #define DO_QUAD 1
349 #define DO_LINE 1
350 #define DO_POINTS 1
351 #define DO_FULL_QUAD 1
352
353 #define HAVE_RGBA 1
354 #define HAVE_SPEC 1
355 #define HAVE_BACK_COLORS 0
356 #define HAVE_HW_FLATSHADE 1
357 #define VERTEX sisVertex
358 #define TAB rast_tab
359
360 #define DEPTH_SCALE smesa->depth_scale
361 #define UNFILLED_TRI unfilled_tri
362 #define UNFILLED_QUAD unfilled_quad
363 #define VERT_X(_v) _v->v.x
364 #define VERT_Y(_v) _v->v.y
365 #define VERT_Z(_v) _v->v.z
366 #define AREA_IS_CCW( a ) (a > 0)
367 #define GET_VERTEX(e) (smesa->verts + (e * smesa->vertex_size * sizeof(int)))
368
369 #define VERT_SET_RGBA( v, c ) \
370 do { \
371 sis_color_t *color = (sis_color_t *)&((v)->ui[coloroffset]); \
372 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
373 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
374 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
375 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
376 } while (0)
377
378 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
379
380 #define VERT_SET_SPEC( v0, c ) \
381 do { \
382 if (havespec) { \
383 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.red, (c)[0]); \
384 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.green, (c)[1]); \
385 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.blue, (c)[2]); \
386 } \
387 } while (0)
388 #define VERT_COPY_SPEC( v0, v1 ) \
389 do { \
390 if (havespec) { \
391 v0->v.specular.red = v1->v.specular.red; \
392 v0->v.specular.green = v1->v.specular.green; \
393 v0->v.specular.blue = v1->v.specular.blue; \
394 } \
395 } while (0)
396
397 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
398 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
399 #define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5]
400 #define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx]
401
402 #define LOCAL_VARS(n) \
403 sisContextPtr smesa = SIS_CONTEXT(ctx); \
404 GLuint color[n], spec[n]; \
405 GLuint coloroffset = (smesa->vertex_size == 4 ? 3 : 4); \
406 GLboolean havespec = (smesa->vertex_size == 4 ? 0 : 1); \
407 (void) color; (void) spec; (void) coloroffset; (void) havespec;
408
409 /***********************************************************************
410 * Helpers for rendering unfilled primitives *
411 ***********************************************************************/
412
413 #define RASTERIZE(x) if (smesa->hw_primitive != hw_prim[x]) \
414 sisRasterPrimitive( ctx, hw_prim[x] )
415 #define RENDER_PRIMITIVE smesa->render_primitive
416 #define IND SIS_FALLBACK_BIT
417 #define TAG(x) x
418 #include "tnl_dd/t_dd_unfilled.h"
419 #undef IND
420
421
422 /***********************************************************************
423 * Generate GL render functions *
424 ***********************************************************************/
425
426
427 #define IND (0)
428 #define TAG(x) x
429 #include "tnl_dd/t_dd_tritmp.h"
430
431 #define IND (SIS_OFFSET_BIT)
432 #define TAG(x) x##_offset
433 #include "tnl_dd/t_dd_tritmp.h"
434
435 #define IND (SIS_TWOSIDE_BIT)
436 #define TAG(x) x##_twoside
437 #include "tnl_dd/t_dd_tritmp.h"
438
439 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT)
440 #define TAG(x) x##_twoside_offset
441 #include "tnl_dd/t_dd_tritmp.h"
442
443 #define IND (SIS_UNFILLED_BIT)
444 #define TAG(x) x##_unfilled
445 #include "tnl_dd/t_dd_tritmp.h"
446
447 #define IND (SIS_OFFSET_BIT|SIS_UNFILLED_BIT)
448 #define TAG(x) x##_offset_unfilled
449 #include "tnl_dd/t_dd_tritmp.h"
450
451 #define IND (SIS_TWOSIDE_BIT|SIS_UNFILLED_BIT)
452 #define TAG(x) x##_twoside_unfilled
453 #include "tnl_dd/t_dd_tritmp.h"
454
455 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT|SIS_UNFILLED_BIT)
456 #define TAG(x) x##_twoside_offset_unfilled
457 #include "tnl_dd/t_dd_tritmp.h"
458
459 #define IND (SIS_FALLBACK_BIT)
460 #define TAG(x) x##_fallback
461 #include "tnl_dd/t_dd_tritmp.h"
462
463 #define IND (SIS_OFFSET_BIT|SIS_FALLBACK_BIT)
464 #define TAG(x) x##_offset_fallback
465 #include "tnl_dd/t_dd_tritmp.h"
466
467 #define IND (SIS_TWOSIDE_BIT|SIS_FALLBACK_BIT)
468 #define TAG(x) x##_twoside_fallback
469 #include "tnl_dd/t_dd_tritmp.h"
470
471 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT|SIS_FALLBACK_BIT)
472 #define TAG(x) x##_twoside_offset_fallback
473 #include "tnl_dd/t_dd_tritmp.h"
474
475 #define IND (SIS_UNFILLED_BIT|SIS_FALLBACK_BIT)
476 #define TAG(x) x##_unfilled_fallback
477 #include "tnl_dd/t_dd_tritmp.h"
478
479 #define IND (SIS_OFFSET_BIT|SIS_UNFILLED_BIT|SIS_FALLBACK_BIT)
480 #define TAG(x) x##_offset_unfilled_fallback
481 #include "tnl_dd/t_dd_tritmp.h"
482
483 #define IND (SIS_TWOSIDE_BIT|SIS_UNFILLED_BIT|SIS_FALLBACK_BIT)
484 #define TAG(x) x##_twoside_unfilled_fallback
485 #include "tnl_dd/t_dd_tritmp.h"
486
487 #define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT|SIS_UNFILLED_BIT| \
488 SIS_FALLBACK_BIT)
489 #define TAG(x) x##_twoside_offset_unfilled_fallback
490 #include "tnl_dd/t_dd_tritmp.h"
491
492
493 static void init_rast_tab( void )
494 {
495 init();
496 init_offset();
497 init_twoside();
498 init_twoside_offset();
499 init_unfilled();
500 init_offset_unfilled();
501 init_twoside_unfilled();
502 init_twoside_offset_unfilled();
503 init_fallback();
504 init_offset_fallback();
505 init_twoside_fallback();
506 init_twoside_offset_fallback();
507 init_unfilled_fallback();
508 init_offset_unfilled_fallback();
509 init_twoside_unfilled_fallback();
510 init_twoside_offset_unfilled_fallback();
511 }
512
513
514
515 /***********************************************************************
516 * Rasterization fallback helpers *
517 ***********************************************************************/
518
519
520 /* This code is hit only when a mix of accelerated and unaccelerated
521 * primitives are being drawn, and only for the unaccelerated
522 * primitives.
523 */
524
525 static void
526 sis_fallback_tri( sisContextPtr smesa,
527 sisVertex *v0,
528 sisVertex *v1,
529 sisVertex *v2 )
530 {
531 GLcontext *ctx = smesa->glCtx;
532 SWvertex v[3];
533 _swsetup_Translate( ctx, v0, &v[0] );
534 _swsetup_Translate( ctx, v1, &v[1] );
535 _swsetup_Translate( ctx, v2, &v[2] );
536 sisSpanRenderStart( ctx );
537 _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
538 sisSpanRenderFinish( ctx );
539 _swrast_flush( ctx );
540 }
541
542
543 static void
544 sis_fallback_line( sisContextPtr smesa,
545 sisVertex *v0,
546 sisVertex *v1 )
547 {
548 GLcontext *ctx = smesa->glCtx;
549 SWvertex v[2];
550 _swsetup_Translate( ctx, v0, &v[0] );
551 _swsetup_Translate( ctx, v1, &v[1] );
552 sisSpanRenderStart( ctx );
553 _swrast_Line( ctx, &v[0], &v[1] );
554 sisSpanRenderFinish( ctx );
555 _swrast_flush( ctx );
556 }
557
558
559 static void
560 sis_fallback_point( sisContextPtr smesa,
561 sisVertex *v0 )
562 {
563 GLcontext *ctx = smesa->glCtx;
564 SWvertex v[1];
565 _swsetup_Translate( ctx, v0, &v[0] );
566 sisSpanRenderStart( ctx );
567 _swrast_Point( ctx, &v[0] );
568 sisSpanRenderFinish( ctx );
569 _swrast_flush( ctx );
570 }
571
572
573
574 /**********************************************************************/
575 /* Render unclipped begin/end objects */
576 /**********************************************************************/
577
578 #define IND 0
579 #define V(x) (sisVertex *)(vertptr + (x * vertsize * sizeof(int)))
580 #define RENDER_POINTS( start, count ) \
581 for ( ; start < count ; start++) \
582 POINT( V(ELT(start)) )
583 #define RENDER_LINE( v0, v1 ) LINE( V(v0), V(v1) )
584 #define RENDER_TRI( v0, v1, v2 ) TRI( V(v0), V(v1), V(v2) )
585 #define RENDER_QUAD( v0, v1, v2, v3 ) QUAD( V(v0), V(v1), V(v2), V(v3) )
586 #define INIT(x) sisRenderPrimitive( ctx, x )
587 #undef LOCAL_VARS
588 #define LOCAL_VARS \
589 sisContextPtr smesa = SIS_CONTEXT(ctx); \
590 const GLuint vertsize = smesa->vertex_size; \
591 const char *vertptr = (char *)smesa->verts; \
592 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
593 (void) elt;
594 #define RESET_STIPPLE
595 #define RESET_OCCLUSION
596 #define PRESERVE_VB_DEFS
597 #define ELT(x) (x)
598 #define TAG(x) sis_##x##_verts
599 #include "tnl/t_vb_rendertmp.h"
600 #undef ELT
601 #undef TAG
602 #define TAG(x) sis_##x##_elts
603 #define ELT(x) elt[x]
604 #include "tnl/t_vb_rendertmp.h"
605
606
607 /**********************************************************************/
608 /* Choose render functions */
609 /**********************************************************************/
610
611 #define POINT_FALLBACK (DD_POINT_SMOOTH)
612 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
613 #define TRI_FALLBACK (DD_TRI_STIPPLE|DD_TRI_SMOOTH)
614 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
615 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
616 #define _SIS_NEW_RENDER_STATE (ANY_RASTER_FLAGS | ANY_FALLBACK_FLAGS)
617
618 static void sisChooseRenderState(GLcontext *ctx)
619 {
620 TNLcontext *tnl = TNL_CONTEXT(ctx);
621 sisContextPtr smesa = SIS_CONTEXT( ctx );
622 GLuint flags = ctx->_TriangleCaps;
623 GLuint index = 0;
624
625 if (smesa->Fallback)
626 return;
627
628 if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) {
629
630 if (flags & ANY_RASTER_FLAGS) {
631 if (flags & DD_TRI_LIGHT_TWOSIDE) index |= SIS_TWOSIDE_BIT;
632 if (flags & DD_TRI_OFFSET) index |= SIS_OFFSET_BIT;
633 if (flags & DD_TRI_UNFILLED) index |= SIS_UNFILLED_BIT;
634 }
635
636 smesa->draw_point = sis_point;
637 smesa->draw_line = sis_line;
638 smesa->draw_tri = sis_triangle;
639 /* Hook in fallbacks for specific primitives.
640 */
641 if (flags & ANY_FALLBACK_FLAGS) {
642 if (flags & POINT_FALLBACK)
643 smesa->draw_point = sis_fallback_point;
644 if (flags & LINE_FALLBACK)
645 smesa->draw_line = sis_fallback_line;
646 if (flags & TRI_FALLBACK)
647 smesa->draw_tri = sis_fallback_tri;
648 index |= SIS_FALLBACK_BIT;
649 }
650 }
651
652 if (index != smesa->RenderIndex) {
653 smesa->RenderIndex = index;
654
655 tnl->Driver.Render.Points = rast_tab[index].points;
656 tnl->Driver.Render.Line = rast_tab[index].line;
657 tnl->Driver.Render.ClippedLine = rast_tab[index].line;
658 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
659 tnl->Driver.Render.Quad = rast_tab[index].quad;
660
661 if (index == 0) {
662 tnl->Driver.Render.PrimTabVerts = sis_render_tab_verts;
663 tnl->Driver.Render.PrimTabElts = sis_render_tab_elts;
664 tnl->Driver.Render.ClippedPolygon = sis_fast_clipped_poly;
665 } else {
666 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
667 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
668 tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
669 }
670 }
671 }
672
673 /**********************************************************************/
674 /* Multipass rendering for front buffering */
675 /**********************************************************************/
676 static GLboolean multipass_cliprect( GLcontext *ctx, GLuint pass )
677 {
678 sisContextPtr smesa = SIS_CONTEXT( ctx );
679
680 if (pass >= smesa->driDrawable->numClipRects) {
681 return GL_FALSE;
682 } else {
683 GLint x1, y1, x2, y2;
684
685 x1 = smesa->driDrawable->pClipRects[pass].x1 - smesa->driDrawable->x;
686 y1 = smesa->driDrawable->pClipRects[pass].y1 - smesa->driDrawable->y;
687 x2 = smesa->driDrawable->pClipRects[pass].x2 - smesa->driDrawable->x;
688 y2 = smesa->driDrawable->pClipRects[pass].y2 - smesa->driDrawable->y;
689
690 if (ctx->Scissor.Enabled) {
691 GLint scisy1 = Y_FLIP(ctx->Scissor.Y + ctx->Scissor.Height - 1);
692 GLint scisy2 = Y_FLIP(ctx->Scissor.Y);
693
694 if (ctx->Scissor.X > x1)
695 x1 = ctx->Scissor.X;
696 if (scisy1 > y1)
697 y1 = scisy1;
698 if (ctx->Scissor.X + ctx->Scissor.Width - 1 < x2)
699 x2 = ctx->Scissor.X + ctx->Scissor.Width - 1;
700 if (scisy2 < y2)
701 y2 = scisy2;
702 }
703
704 MMIO(REG_3D_ClipTopBottom, y1 << 13 | y2);
705 MMIO(REG_3D_ClipLeftRight, x1 << 13 | x2);
706 /* Mark that we clobbered these registers */
707 smesa->GlobalFlag |= GFLAG_CLIPPING;
708 return GL_TRUE;
709 }
710 }
711
712
713
714 /**********************************************************************/
715 /* Validate state at pipeline start */
716 /**********************************************************************/
717
718 static void sisRunPipeline( GLcontext *ctx )
719 {
720 sisContextPtr smesa = SIS_CONTEXT( ctx );
721
722 if (smesa->NewGLState) {
723 SIS_FIREVERTICES(smesa);
724 if (smesa->NewGLState & _NEW_TEXTURE) {
725 sisUpdateTextureState(ctx);
726 }
727
728 if (smesa->NewGLState & _SIS_NEW_RENDER_STATE)
729 sisChooseRenderState( ctx );
730
731 smesa->NewGLState = 0;
732 }
733
734 _tnl_run_pipeline( ctx );
735
736 /* XXX: If we put flushing in sis_state.c and friends, we can avoid this.
737 * Is it worth it?
738 */
739 SIS_FIREVERTICES(smesa);
740 }
741
742 /**********************************************************************/
743 /* High level hooks for t_vb_render.c */
744 /**********************************************************************/
745
746 /* This is called when Mesa switches between rendering triangle
747 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
748 * and lines, points and bitmaps.
749 */
750
751 static void sisRasterPrimitive( GLcontext *ctx, GLuint hwprim )
752 {
753 sisContextPtr smesa = SIS_CONTEXT(ctx);
754 if (smesa->hw_primitive != hwprim) {
755 SIS_FIREVERTICES(smesa);
756 smesa->hw_primitive = hwprim;
757 smesa->AGPParseSet &= ~(MASK_PsDataType | MASK_PsShadingMode);
758 smesa->dwPrimitiveSet &= ~(MASK_DrawPrimitiveCommand |
759 MASK_SetFirePosition | MASK_ShadingMode);
760 smesa->AGPParseSet |= hw_prim_agp_type[hwprim];
761 smesa->dwPrimitiveSet |= hwprim | hw_prim_mmio_fire[hwprim];
762 if (ctx->Light.ShadeModel == GL_FLAT) {
763 smesa->AGPParseSet |= hw_prim_agp_shade[hwprim];
764 smesa->dwPrimitiveSet |= hw_prim_mmio_shade[hwprim];
765 } else {
766 smesa->AGPParseSet |= MASK_PsShadingSmooth;
767 smesa->dwPrimitiveSet |= SHADE_GOURAUD;
768 }
769 }
770 }
771
772 static void sisRenderPrimitive( GLcontext *ctx, GLenum prim )
773 {
774 sisContextPtr smesa = SIS_CONTEXT(ctx);
775
776 smesa->render_primitive = prim;
777
778 if (prim >= GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
779 return;
780 sisRasterPrimitive( ctx, hw_prim[prim] );
781 }
782
783 #define EMIT_ATTR( ATTR, STYLE) \
784 do { \
785 smesa->vertex_attrs[smesa->vertex_attr_count].attrib = (ATTR); \
786 smesa->vertex_attrs[smesa->vertex_attr_count].format = (STYLE); \
787 smesa->vertex_attr_count++; \
788 } while (0)
789
790 #define EMIT_PAD( N ) \
791 do { \
792 smesa->vertex_attrs[smesa->vertex_attr_count].attrib = 0; \
793 smesa->vertex_attrs[smesa->vertex_attr_count].format = EMIT_PAD; \
794 smesa->vertex_attrs[smesa->vertex_attr_count].offset = (N); \
795 smesa->vertex_attr_count++; \
796 } while (0)
797
798 #define SIS_TCL_STATE_BITS \
799 (_TNL_BITS_TEX_ANY | _TNL_BIT_COLOR1 | _TNL_BIT_FOG)
800
801 static void sisRenderStart( GLcontext *ctx )
802 {
803 TNLcontext *tnl = TNL_CONTEXT(ctx);
804 sisContextPtr smesa = SIS_CONTEXT(ctx);
805 struct vertex_buffer *VB = &tnl->vb;
806 GLuint index = tnl->render_inputs;
807 GLuint AGPParseSet = smesa->AGPParseSet;
808 GLboolean tex_fallback = GL_FALSE;
809
810 if (ctx->DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT &&
811 smesa->driDrawable->numClipRects != 0)
812 {
813 multipass_cliprect(ctx, 0);
814 if (smesa->driDrawable->numClipRects > 1)
815 tnl->Driver.Render.Multipass = multipass_cliprect;
816 else
817 tnl->Driver.Render.Multipass = NULL;
818 } else {
819 tnl->Driver.Render.Multipass = NULL;
820 }
821
822 /* Important:
823 */
824 VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
825 smesa->vertex_attr_count = 0;
826
827 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to build up a
828 * hardware vertex.
829 */
830
831 AGPParseSet &= ~(MASK_VertexDWSize | MASK_VertexDataFormat);
832 AGPParseSet |= SiS_PS_HAS_XYZ | SiS_PS_HAS_DIFFUSE;
833 if (index & _TNL_BITS_TEX_ANY) {
834 EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_4F_VIEWPORT);
835 AGPParseSet |= SiS_PS_HAS_W;
836 } else {
837 EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_3F_VIEWPORT);
838 }
839
840 EMIT_ATTR(_TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA);
841
842 if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
843 AGPParseSet |= SiS_PS_HAS_SPECULAR;
844
845 if (index & _TNL_BIT_COLOR1) {
846 EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR);
847 } else {
848 EMIT_PAD(3);
849 }
850
851 if (index & _TNL_BIT_FOG)
852 EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1UB_1F);
853 else
854 EMIT_PAD(1);
855 }
856
857 /* projective textures are not supported by the hardware */
858 if (index & _TNL_BIT_TEX(0)) {
859 if (VB->TexCoordPtr[0]->size > 2)
860 tex_fallback = GL_TRUE;
861 EMIT_ATTR(_TNL_ATTRIB_TEX0, EMIT_2F);
862 AGPParseSet |= SiS_PS_HAS_UV0;
863 }
864 if (index & _TNL_BIT_TEX(1)) {
865 if (VB->TexCoordPtr[1]->size > 2)
866 tex_fallback = GL_TRUE;
867 EMIT_ATTR(_TNL_ATTRIB_TEX1, EMIT_2F);
868 AGPParseSet |= SiS_PS_HAS_UV1;
869 }
870 FALLBACK(smesa, SIS_FALLBACK_TEXTURE, tex_fallback);
871
872 if (smesa->last_tcl_state != index) {
873 smesa->AGPParseSet = AGPParseSet;
874
875 smesa->vertex_size = _tnl_install_attrs( ctx, smesa->vertex_attrs,
876 smesa->vertex_attr_count, smesa->hw_viewport, 0 );
877
878 smesa->vertex_size >>= 2;
879 smesa->AGPParseSet |= smesa->vertex_size << 28;
880 }
881 }
882
883 static void sisRenderFinish( GLcontext *ctx )
884 {
885 }
886
887 /**********************************************************************/
888 /* AGP/PCI vertex submission */
889 /**********************************************************************/
890
891 void
892 sisFlushPrimsLocked(sisContextPtr smesa)
893 {
894 if (smesa->vb_cur == smesa->vb_last)
895 return;
896
897 sisUpdateHWState(smesa->glCtx);
898
899 if (smesa->using_agp) {
900 mWait3DCmdQueue(8);
901 mEndPrimitive();
902 MMIO(REG_3D_AGPCmBase, (smesa->vb_last - smesa->vb) +
903 smesa->vb_agp_offset);
904 MMIO(REG_3D_AGPTtDwNum, ((smesa->vb_cur - smesa->vb_last) / 4) |
905 0x50000000);
906 MMIO(REG_3D_ParsingSet, smesa->AGPParseSet);
907 MMIO(REG_3D_AGPCmFire, (GLint)(-1));
908 mEndPrimitive();
909 } else {
910 int mmio_index = 0, incr = 0;
911 void (*sis_emit_func)(sisContextPtr smesa, char *verts) = NULL;
912
913 if (smesa->AGPParseSet & MASK_PsShadingSmooth)
914 mmio_index |= VERT_SMOOTH;
915 if (smesa->AGPParseSet & SiS_PS_HAS_SPECULAR)
916 mmio_index |= VERT_SPEC;
917 if (smesa->AGPParseSet & SiS_PS_HAS_W)
918 mmio_index |= VERT_W;
919 if (smesa->AGPParseSet & SiS_PS_HAS_UV0)
920 mmio_index |= VERT_UV0;
921 if (smesa->AGPParseSet & SiS_PS_HAS_UV1)
922 mmio_index |= VERT_UV1;
923
924 switch (smesa->AGPParseSet & MASK_PsDataType) {
925 case MASK_PsPointList:
926 incr = smesa->vertex_size * 4;
927 sis_emit_func = sis_point_func_mmio[mmio_index];
928 break;
929 case MASK_PsLineList:
930 incr = smesa->vertex_size * 4 * 2;
931 sis_emit_func = sis_line_func_mmio[mmio_index];
932 break;
933 case MASK_PsTriangleList:
934 incr = smesa->vertex_size * 4 * 3;
935 sis_emit_func = sis_tri_func_mmio[mmio_index];
936 break;
937 }
938
939 mWait3DCmdQueue(1);
940 MMIO(REG_3D_PrimitiveSet, smesa->dwPrimitiveSet);
941 while (smesa->vb_last < smesa->vb_cur) {
942 sis_emit_func(smesa, smesa->vb_last);
943 smesa->vb_last += incr;
944 }
945 mWait3DCmdQueue(1);
946 mEndPrimitive();
947
948 /* With PCI, we can just start writing to the start of the VB again. */
949 smesa->vb_cur = smesa->vb;
950 }
951 smesa->vb_last = smesa->vb_cur;
952 }
953
954 void sisFlushPrims(sisContextPtr smesa)
955 {
956 LOCK_HARDWARE();
957 sisFlushPrimsLocked(smesa);
958 UNLOCK_HARDWARE();
959 }
960
961 /**********************************************************************/
962 /* Transition to/from hardware rasterization. */
963 /**********************************************************************/
964
965 static const char * const fallbackStrings[] = {
966 "Texture mode",
967 "Texture 0 mode",
968 "Texture 1 mode",
969 "Texture 0 env", /* Note: unused */
970 "Texture 1 env", /* Note: unused */
971 "glDrawBuffer(GL_FRONT_AND_BACK)",
972 "glEnable(GL_STENCIL) without hw stencil buffer",
973 "no_rast",
974 };
975
976 static const char *getFallbackString(GLuint bit)
977 {
978 int i = 0;
979 while (bit > 1) {
980 i++;
981 bit >>= 1;
982 }
983 return fallbackStrings[i];
984 }
985
986 void sisFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
987 {
988 TNLcontext *tnl = TNL_CONTEXT(ctx);
989 sisContextPtr smesa = SIS_CONTEXT(ctx);
990 GLuint oldfallback = smesa->Fallback;
991
992 if (mode) {
993 smesa->Fallback |= bit;
994 if (oldfallback == 0) {
995 SIS_FIREVERTICES(smesa);
996 _swsetup_Wakeup( ctx );
997 smesa->RenderIndex = ~0;
998 if (SIS_DEBUG & DEBUG_FALLBACKS) {
999 fprintf(stderr, "SiS begin rasterization fallback: 0x%x %s\n",
1000 bit, getFallbackString(bit));
1001 }
1002 }
1003 }
1004 else {
1005 smesa->Fallback &= ~bit;
1006 if (oldfallback == bit) {
1007 _swrast_flush( ctx );
1008 tnl->Driver.Render.Start = sisRenderStart;
1009 tnl->Driver.Render.PrimitiveNotify = sisRenderPrimitive;
1010 tnl->Driver.Render.Finish = sisRenderFinish;
1011
1012 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1013 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1014 tnl->Driver.Render.Interp = _tnl_interp;
1015
1016 _tnl_invalidate_vertex_state( ctx, ~0 );
1017 _tnl_invalidate_vertices( ctx, ~0 );
1018 _tnl_install_attrs( ctx,
1019 smesa->vertex_attrs,
1020 smesa->vertex_attr_count,
1021 smesa->hw_viewport, 0 );
1022
1023 smesa->NewGLState |= _SIS_NEW_RENDER_STATE;
1024 if (SIS_DEBUG & DEBUG_FALLBACKS) {
1025 fprintf(stderr, "SiS end rasterization fallback: 0x%x %s\n",
1026 bit, getFallbackString(bit));
1027 }
1028 }
1029 }
1030 }
1031
1032
1033 /**********************************************************************/
1034 /* Initialization. */
1035 /**********************************************************************/
1036
1037 void sisInitTriFuncs( GLcontext *ctx )
1038 {
1039 sisContextPtr smesa = SIS_CONTEXT(ctx);
1040 TNLcontext *tnl = TNL_CONTEXT(ctx);
1041 static int firsttime = 1;
1042
1043 if (firsttime) {
1044 init_rast_tab();
1045 firsttime = 0;
1046
1047 sis_vert_init_none();
1048 sis_vert_init_g();
1049 sis_vert_init_w();
1050 sis_vert_init_gw();
1051 sis_vert_init_s();
1052 sis_vert_init_gs();
1053 sis_vert_init_ws();
1054 sis_vert_init_gws();
1055 sis_vert_init_t0();
1056 sis_vert_init_gt0();
1057 sis_vert_init_wt0();
1058 sis_vert_init_gwt0();
1059 sis_vert_init_st0();
1060 sis_vert_init_gst0();
1061 sis_vert_init_wst0();
1062 sis_vert_init_gwst0();
1063 sis_vert_init_t1();
1064 sis_vert_init_gt1();
1065 sis_vert_init_wt1();
1066 sis_vert_init_gwt1();
1067 sis_vert_init_st1();
1068 sis_vert_init_gst1();
1069 sis_vert_init_wst1();
1070 sis_vert_init_gwst1();
1071 sis_vert_init_t0t1();
1072 sis_vert_init_gt0t1();
1073 sis_vert_init_wt0t1();
1074 sis_vert_init_gwt0t1();
1075 sis_vert_init_st0t1();
1076 sis_vert_init_gst0t1();
1077 sis_vert_init_wst0t1();
1078 sis_vert_init_gwst0t1();
1079 }
1080
1081 smesa->RenderIndex = ~0;
1082 smesa->NewGLState |= _SIS_NEW_RENDER_STATE;
1083
1084 tnl->Driver.RunPipeline = sisRunPipeline;
1085 tnl->Driver.Render.Start = sisRenderStart;
1086 tnl->Driver.Render.Finish = sisRenderFinish;
1087 tnl->Driver.Render.PrimitiveNotify = sisRenderPrimitive;
1088 tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
1089
1090 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1091 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1092 tnl->Driver.Render.Interp = _tnl_interp;
1093
1094 _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
1095 (6 + 2*ctx->Const.MaxTextureUnits) * sizeof(GLfloat) );
1096
1097 smesa->verts = (char *)tnl->clipspace.vertex_buf;
1098 }