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