Rename the various function types in t_context.h to include a tnl_ prefix.
[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 tnl_points_func points;
337 tnl_line_func line;
338 tnl_triangle_func triangle;
339 tnl_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 POINT_FALLBACK (DD_POINT_SMOOTH)
613 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
614 #define TRI_FALLBACK (DD_TRI_SMOOTH)
615 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
616 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
617 #define _SIS_NEW_RENDER_STATE (ANY_RASTER_FLAGS | ANY_FALLBACK_FLAGS)
618
619 static void sisChooseRenderState(GLcontext *ctx)
620 {
621 TNLcontext *tnl = TNL_CONTEXT(ctx);
622 sisContextPtr smesa = SIS_CONTEXT( ctx );
623 GLuint flags = ctx->_TriangleCaps;
624 GLuint index = 0;
625
626 if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) {
627
628 if (flags & ANY_RASTER_FLAGS) {
629 if (flags & DD_TRI_LIGHT_TWOSIDE) index |= SIS_TWOSIDE_BIT;
630 if (flags & DD_TRI_OFFSET) index |= SIS_OFFSET_BIT;
631 if (flags & DD_TRI_UNFILLED) index |= SIS_UNFILLED_BIT;
632 }
633
634 smesa->draw_point = sis_point;
635 smesa->draw_line = sis_line;
636 smesa->draw_tri = sis_triangle;
637 /* Hook in fallbacks for specific primitives.
638 */
639 if (flags & ANY_FALLBACK_FLAGS) {
640 if (flags & POINT_FALLBACK)
641 smesa->draw_point = sis_fallback_point;
642 if (flags & LINE_FALLBACK)
643 smesa->draw_line = sis_fallback_line;
644 if (flags & TRI_FALLBACK)
645 smesa->draw_tri = sis_fallback_tri;
646 index |= SIS_FALLBACK_BIT;
647 }
648 }
649
650 if (index != smesa->RenderIndex) {
651 smesa->RenderIndex = index;
652
653 tnl->Driver.Render.Points = rast_tab[index].points;
654 tnl->Driver.Render.Line = rast_tab[index].line;
655 tnl->Driver.Render.ClippedLine = rast_tab[index].line;
656 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
657 tnl->Driver.Render.Quad = rast_tab[index].quad;
658
659 if (index == 0) {
660 tnl->Driver.Render.PrimTabVerts = sis_render_tab_verts;
661 tnl->Driver.Render.PrimTabElts = sis_render_tab_elts;
662 tnl->Driver.Render.ClippedPolygon = sis_fast_clipped_poly;
663 } else {
664 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
665 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
666 tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
667 }
668 }
669 }
670
671 /**********************************************************************/
672 /* Multipass rendering for front buffering */
673 /**********************************************************************/
674 static GLboolean multipass_cliprect( GLcontext *ctx, GLuint pass )
675 {
676 sisContextPtr smesa = SIS_CONTEXT( ctx );
677
678 if (pass >= smesa->driDrawable->numClipRects) {
679 return GL_FALSE;
680 } else {
681 GLint x1, y1, x2, y2;
682
683 x1 = smesa->driDrawable->pClipRects[pass].x1 - smesa->driDrawable->x;
684 y1 = smesa->driDrawable->pClipRects[pass].y1 - smesa->driDrawable->y;
685 x2 = smesa->driDrawable->pClipRects[pass].x2 - smesa->driDrawable->x;
686 y2 = smesa->driDrawable->pClipRects[pass].y2 - smesa->driDrawable->y;
687
688 if (ctx->Scissor.Enabled) {
689 GLint scisy1 = Y_FLIP(ctx->Scissor.Y + ctx->Scissor.Height - 1);
690 GLint scisy2 = Y_FLIP(ctx->Scissor.Y);
691
692 if (ctx->Scissor.X > x1)
693 x1 = ctx->Scissor.X;
694 if (scisy1 > y1)
695 y1 = scisy1;
696 if (ctx->Scissor.X + ctx->Scissor.Width - 1 < x2)
697 x2 = ctx->Scissor.X + ctx->Scissor.Width - 1;
698 if (scisy2 < y2)
699 y2 = scisy2;
700 }
701
702 MMIO(REG_3D_ClipTopBottom, y1 << 13 | y2);
703 MMIO(REG_3D_ClipLeftRight, x1 << 13 | x2);
704 /* Mark that we clobbered these registers */
705 smesa->GlobalFlag |= GFLAG_CLIPPING;
706 return GL_TRUE;
707 }
708 }
709
710
711
712 /**********************************************************************/
713 /* Validate state at pipeline start */
714 /**********************************************************************/
715
716 static void sisRunPipeline( GLcontext *ctx )
717 {
718 sisContextPtr smesa = SIS_CONTEXT( ctx );
719
720 if (!smesa->Fallback && smesa->NewGLState) {
721 if (smesa->NewGLState & _NEW_TEXTURE) {
722 SIS_FIREVERTICES(smesa);
723 sisUpdateTextureState(ctx);
724 }
725
726 if (smesa->NewGLState & _SIS_NEW_RENDER_STATE)
727 sisChooseRenderState( ctx );
728
729 smesa->NewGLState = 0;
730 }
731
732 _tnl_run_pipeline( ctx );
733
734 /* XXX: If we put flushing in sis_state.c and friends, we can avoid this.
735 * Is it worth it?
736 */
737 SIS_FIREVERTICES(smesa);
738 }
739
740 /**********************************************************************/
741 /* High level hooks for t_vb_render.c */
742 /**********************************************************************/
743
744 /* This is called when Mesa switches between rendering triangle
745 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
746 * and lines, points and bitmaps.
747 */
748
749 static void sisRasterPrimitive( GLcontext *ctx, GLuint hwprim )
750 {
751 sisContextPtr smesa = SIS_CONTEXT(ctx);
752 if (smesa->hw_primitive != hwprim) {
753 SIS_FIREVERTICES(smesa);
754 smesa->hw_primitive = hwprim;
755 smesa->AGPParseSet &= ~(MASK_PsDataType | MASK_PsShadingMode);
756 smesa->dwPrimitiveSet &= ~(MASK_DrawPrimitiveCommand |
757 MASK_SetFirePosition | MASK_ShadingMode);
758 smesa->AGPParseSet |= hw_prim_agp_type[hwprim];
759 smesa->dwPrimitiveSet |= hwprim | hw_prim_mmio_fire[hwprim];
760 if (ctx->Light.ShadeModel == GL_FLAT) {
761 smesa->AGPParseSet |= hw_prim_agp_shade[hwprim];
762 smesa->dwPrimitiveSet |= hw_prim_mmio_shade[hwprim];
763 } else {
764 smesa->AGPParseSet |= MASK_PsShadingSmooth;
765 smesa->dwPrimitiveSet |= SHADE_GOURAUD;
766 }
767 }
768 }
769
770 static void sisRenderPrimitive( GLcontext *ctx, GLenum prim )
771 {
772 sisContextPtr smesa = SIS_CONTEXT(ctx);
773
774 smesa->render_primitive = prim;
775
776 if (prim >= GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
777 return;
778 sisRasterPrimitive( ctx, hw_prim[prim] );
779 }
780
781 #define EMIT_ATTR( ATTR, STYLE) \
782 do { \
783 smesa->vertex_attrs[smesa->vertex_attr_count].attrib = (ATTR); \
784 smesa->vertex_attrs[smesa->vertex_attr_count].format = (STYLE); \
785 smesa->vertex_attr_count++; \
786 } while (0)
787
788 #define EMIT_PAD( N ) \
789 do { \
790 smesa->vertex_attrs[smesa->vertex_attr_count].attrib = 0; \
791 smesa->vertex_attrs[smesa->vertex_attr_count].format = EMIT_PAD; \
792 smesa->vertex_attrs[smesa->vertex_attr_count].offset = (N); \
793 smesa->vertex_attr_count++; \
794 } while (0)
795
796 #define SIS_TCL_STATE_BITS \
797 (_TNL_BITS_TEX_ANY | _TNL_BIT_COLOR1 | _TNL_BIT_FOG)
798
799 static void sisRenderStart( GLcontext *ctx )
800 {
801 TNLcontext *tnl = TNL_CONTEXT(ctx);
802 sisContextPtr smesa = SIS_CONTEXT(ctx);
803 struct vertex_buffer *VB = &tnl->vb;
804 GLuint index = tnl->render_inputs;
805 GLuint AGPParseSet = smesa->AGPParseSet;
806 GLboolean tex_fallback = GL_FALSE;
807
808 if (ctx->Color._DrawDestMask == DD_FRONT_LEFT_BIT &&
809 smesa->driDrawable->numClipRects != 0)
810 {
811 multipass_cliprect(ctx, 0);
812 if (smesa->driDrawable->numClipRects > 1)
813 tnl->Driver.Render.Multipass = multipass_cliprect;
814 else
815 tnl->Driver.Render.Multipass = NULL;
816 } else {
817 tnl->Driver.Render.Multipass = NULL;
818 }
819
820 /* Important:
821 */
822 VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
823 smesa->vertex_attr_count = 0;
824
825 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to build up a
826 * hardware vertex.
827 */
828
829 AGPParseSet &= ~(MASK_VertexDWSize | MASK_VertexDataFormat);
830 AGPParseSet |= SiS_PS_HAS_XYZ | SiS_PS_HAS_DIFFUSE;
831 if (index & _TNL_BITS_TEX_ANY) {
832 EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_4F_VIEWPORT);
833 AGPParseSet |= SiS_PS_HAS_W;
834 } else {
835 EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_3F_VIEWPORT);
836 }
837
838 EMIT_ATTR(_TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA);
839
840 if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
841 AGPParseSet |= SiS_PS_HAS_SPECULAR;
842
843 if (index & _TNL_BIT_COLOR1) {
844 EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR);
845 } else {
846 EMIT_PAD(3);
847 }
848
849 if (index & _TNL_BIT_FOG)
850 EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1UB_1F);
851 else
852 EMIT_PAD(1);
853 }
854
855 /* projective textures are not supported by the hardware */
856 if (index & _TNL_BIT_TEX(0)) {
857 if (VB->TexCoordPtr[0]->size > 2)
858 tex_fallback = GL_TRUE;
859 EMIT_ATTR(_TNL_ATTRIB_TEX0, EMIT_2F);
860 AGPParseSet |= SiS_PS_HAS_UV0;
861 }
862 if (index & _TNL_BIT_TEX(1)) {
863 if (VB->TexCoordPtr[1]->size > 2)
864 tex_fallback = GL_TRUE;
865 EMIT_ATTR(_TNL_ATTRIB_TEX1, EMIT_2F);
866 AGPParseSet |= SiS_PS_HAS_UV1;
867 }
868 FALLBACK(smesa, SIS_FALLBACK_TEXTURE, tex_fallback);
869
870 if (smesa->last_tcl_state != index) {
871 smesa->AGPParseSet = AGPParseSet;
872
873 smesa->vertex_size = _tnl_install_attrs( ctx, smesa->vertex_attrs,
874 smesa->vertex_attr_count, smesa->hw_viewport, 0 );
875
876 smesa->vertex_size >>= 2;
877 smesa->AGPParseSet |= smesa->vertex_size << 28;
878 }
879 }
880
881 static void sisRenderFinish( GLcontext *ctx )
882 {
883 }
884
885 /**********************************************************************/
886 /* AGP/PCI vertex submission */
887 /**********************************************************************/
888
889 void
890 sisFlushPrimsLocked(sisContextPtr smesa)
891 {
892 GLuint *start;
893
894 sisUpdateHWState(smesa->glCtx);
895
896 if (smesa->using_agp) {
897 mWait3DCmdQueue(8);
898 mEndPrimitive();
899 MMIO(REG_3D_AGPCmBase, (smesa->vb_last - smesa->vb) +
900 smesa->vb_agp_offset);
901 MMIO(REG_3D_AGPTtDwNum, (smesa->vb_cur - smesa->vb_last) / 4 |
902 0x50000000);
903 MMIO(REG_3D_ParsingSet, smesa->AGPParseSet);
904 MMIO(REG_3D_AGPCmFire, (GLint)(-1));
905 mEndPrimitive();
906 } else {
907 int mmio_index = 0, incr = 0;
908 void (*sis_emit_func)(sisContextPtr smesa, char *verts) = NULL;
909
910 if (smesa->AGPParseSet & MASK_PsShadingSmooth)
911 mmio_index |= VERT_SMOOTH;
912 if (smesa->AGPParseSet & SiS_PS_HAS_SPECULAR)
913 mmio_index |= VERT_SPEC;
914 if (smesa->AGPParseSet & SiS_PS_HAS_W)
915 mmio_index |= VERT_W;
916 if (smesa->AGPParseSet & SiS_PS_HAS_UV0)
917 mmio_index |= VERT_UV0;
918 if (smesa->AGPParseSet & SiS_PS_HAS_UV1)
919 mmio_index |= VERT_UV1;
920
921 switch (smesa->AGPParseSet & MASK_PsDataType) {
922 case MASK_PsPointList:
923 incr = smesa->vertex_size * 4;
924 sis_emit_func = sis_point_func_mmio[mmio_index];
925 break;
926 case MASK_PsLineList:
927 incr = smesa->vertex_size * 4 * 2;
928 sis_emit_func = sis_line_func_mmio[mmio_index];
929 break;
930 case MASK_PsTriangleList:
931 incr = smesa->vertex_size * 4 * 3;
932 sis_emit_func = sis_tri_func_mmio[mmio_index];
933 break;
934 }
935
936 mWait3DCmdQueue(1);
937 MMIO(REG_3D_PrimitiveSet, smesa->dwPrimitiveSet);
938 while (smesa->vb_last < smesa->vb_cur) {
939 sis_emit_func(smesa, smesa->vb_last);
940 smesa->vb_last += incr;
941 }
942 mWait3DCmdQueue(1);
943 mEndPrimitive();
944
945 /* With PCI, we can just start writing to the start of the VB again. */
946 smesa->vb_cur = smesa->vb;
947 }
948 smesa->vb_last = smesa->vb_cur;
949 }
950
951 void sisFlushPrims(sisContextPtr smesa)
952 {
953 LOCK_HARDWARE();
954 sisFlushPrimsLocked(smesa);
955 UNLOCK_HARDWARE();
956 }
957
958 /**********************************************************************/
959 /* Transition to/from hardware rasterization. */
960 /**********************************************************************/
961
962 void sisFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
963 {
964 TNLcontext *tnl = TNL_CONTEXT(ctx);
965 sisContextPtr smesa = SIS_CONTEXT(ctx);
966 GLuint oldfallback = smesa->Fallback;
967
968 if (mode) {
969 smesa->Fallback |= bit;
970 if (oldfallback == 0) {
971 SIS_FIREVERTICES(smesa);
972 _swsetup_Wakeup( ctx );
973 smesa->RenderIndex = ~0;
974 }
975 }
976 else {
977 smesa->Fallback &= ~bit;
978 if (oldfallback == bit) {
979 _swrast_flush( ctx );
980 tnl->Driver.Render.Start = sisRenderStart;
981 tnl->Driver.Render.PrimitiveNotify = sisRenderPrimitive;
982 tnl->Driver.Render.Finish = sisRenderFinish;
983
984 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
985 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
986 tnl->Driver.Render.Interp = _tnl_interp;
987
988 _tnl_invalidate_vertex_state( ctx, ~0 );
989 _tnl_invalidate_vertices( ctx, ~0 );
990 _tnl_install_attrs( ctx,
991 smesa->vertex_attrs,
992 smesa->vertex_attr_count,
993 smesa->hw_viewport, 0 );
994
995 smesa->NewGLState |= _SIS_NEW_RENDER_STATE;
996 }
997 }
998 }
999
1000
1001 /**********************************************************************/
1002 /* Initialization. */
1003 /**********************************************************************/
1004
1005 void sisInitTriFuncs( GLcontext *ctx )
1006 {
1007 sisContextPtr smesa = SIS_CONTEXT(ctx);
1008 TNLcontext *tnl = TNL_CONTEXT(ctx);
1009 static int firsttime = 1;
1010
1011 if (firsttime) {
1012 init_rast_tab();
1013 firsttime = 0;
1014
1015 sis_vert_init_none();
1016 sis_vert_init_g();
1017 sis_vert_init_w();
1018 sis_vert_init_gw();
1019 sis_vert_init_s();
1020 sis_vert_init_gs();
1021 sis_vert_init_ws();
1022 sis_vert_init_gws();
1023 sis_vert_init_t0();
1024 sis_vert_init_gt0();
1025 sis_vert_init_wt0();
1026 sis_vert_init_gwt0();
1027 sis_vert_init_st0();
1028 sis_vert_init_gst0();
1029 sis_vert_init_wst0();
1030 sis_vert_init_gwst0();
1031 sis_vert_init_t1();
1032 sis_vert_init_gt1();
1033 sis_vert_init_wt1();
1034 sis_vert_init_gwt1();
1035 sis_vert_init_st1();
1036 sis_vert_init_gst1();
1037 sis_vert_init_wst1();
1038 sis_vert_init_gwst1();
1039 sis_vert_init_t0t1();
1040 sis_vert_init_gt0t1();
1041 sis_vert_init_wt0t1();
1042 sis_vert_init_gwt0t1();
1043 sis_vert_init_st0t1();
1044 sis_vert_init_gst0t1();
1045 sis_vert_init_wst0t1();
1046 sis_vert_init_gwst0t1();
1047 }
1048
1049 if (driQueryOptionb(&smesa->optionCache, "fallback_force"))
1050 sisFallback(ctx, SIS_FALLBACK_FORCE, 1);
1051 else
1052 sisFallback(ctx, SIS_FALLBACK_FORCE, 0);
1053
1054 smesa->RenderIndex = ~0;
1055 smesa->NewGLState |= _SIS_NEW_RENDER_STATE;
1056
1057 tnl->Driver.RunPipeline = sisRunPipeline;
1058 tnl->Driver.Render.Start = sisRenderStart;
1059 tnl->Driver.Render.Finish = sisRenderFinish;
1060 tnl->Driver.Render.PrimitiveNotify = sisRenderPrimitive;
1061 tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
1062
1063 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1064 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1065 tnl->Driver.Render.Interp = _tnl_interp;
1066
1067 _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
1068 (6 + 2*ctx->Const.MaxTextureUnits) * sizeof(GLfloat) );
1069
1070 smesa->verts = (char *)tnl->clipspace.vertex_buf;
1071 }