2 * Copyright 2001 by Alan Hourihane.
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Alan Hourihane not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Alan Hourihane makes no representations
11 * about the suitability of this software for any purpose. It is provided
12 * "as is" without express or implied warranty.
14 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
22 * Authors: Alan Hourihane, <alanh@tungstengraphics.com>
23 * Keith Whitwell, <keith@tungstengraphics.com>
25 * 3DLabs Gamma driver.
28 #include "gamma_context.h"
30 #include "gamma_tris.h"
37 #include "swrast/swrast.h"
38 #include "swrast_setup/swrast_setup.h"
40 #include "tnl/t_context.h"
41 #include "tnl/t_pipeline.h"
44 /***********************************************************************
45 * Build hardware rasterization functions *
46 ***********************************************************************/
48 #define GAMMA_RAST_ALPHA_BIT 0x01
49 #define GAMMA_RAST_TEX_BIT 0x02
50 #define GAMMA_RAST_FLAT_BIT 0x04
52 static gamma_point_func gamma_point_tab
[0x8];
53 static gamma_line_func gamma_line_tab
[0x8];
54 static gamma_tri_func gamma_tri_tab
[0x8];
55 static gamma_quad_func gamma_quad_tab
[0x8];
59 #include "gamma_tritmp.h"
61 #define IND (GAMMA_RAST_ALPHA_BIT)
62 #define TAG(x) x##_alpha
63 #include "gamma_tritmp.h"
65 #define IND (GAMMA_RAST_TEX_BIT)
66 #define TAG(x) x##_tex
67 #include "gamma_tritmp.h"
69 #define IND (GAMMA_RAST_ALPHA_BIT|GAMMA_RAST_TEX_BIT)
70 #define TAG(x) x##_alpha_tex
71 #include "gamma_tritmp.h"
73 #define IND (GAMMA_RAST_FLAT_BIT)
74 #define TAG(x) x##_flat
75 #include "gamma_tritmp.h"
77 #define IND (GAMMA_RAST_ALPHA_BIT|GAMMA_RAST_FLAT_BIT)
78 #define TAG(x) x##_alpha_flat
79 #include "gamma_tritmp.h"
81 #define IND (GAMMA_RAST_TEX_BIT|GAMMA_RAST_FLAT_BIT)
82 #define TAG(x) x##_tex_flat
83 #include "gamma_tritmp.h"
85 #define IND (GAMMA_RAST_ALPHA_BIT|GAMMA_RAST_TEX_BIT|GAMMA_RAST_FLAT_BIT)
86 #define TAG(x) x##_alpha_tex_flat
87 #include "gamma_tritmp.h"
90 static void init_rast_tab( void )
95 gamma_init_alpha_tex();
97 gamma_init_alpha_flat();
98 gamma_init_tex_flat();
99 gamma_init_alpha_tex_flat();
102 /***********************************************************************
103 * Rasterization fallback helpers *
104 ***********************************************************************/
107 /* This code is hit only when a mix of accelerated and unaccelerated
108 * primitives are being drawn, and only for the unaccelerated
112 gamma_fallback_quad( gammaContextPtr gmesa
,
113 const gammaVertex
*v0
,
114 const gammaVertex
*v1
,
115 const gammaVertex
*v2
,
116 const gammaVertex
*v3
)
118 GLcontext
*ctx
= gmesa
->glCtx
;
120 gamma_translate_vertex( ctx
, v0
, &v
[0] );
121 gamma_translate_vertex( ctx
, v1
, &v
[1] );
122 gamma_translate_vertex( ctx
, v2
, &v
[2] );
123 gamma_translate_vertex( ctx
, v3
, &v
[3] );
124 _swrast_Quad( ctx
, &v
[0], &v
[1], &v
[2], &v
[3] );
128 gamma_fallback_tri( gammaContextPtr gmesa
,
129 const gammaVertex
*v0
,
130 const gammaVertex
*v1
,
131 const gammaVertex
*v2
)
133 GLcontext
*ctx
= gmesa
->glCtx
;
135 gamma_translate_vertex( ctx
, v0
, &v
[0] );
136 gamma_translate_vertex( ctx
, v1
, &v
[1] );
137 gamma_translate_vertex( ctx
, v2
, &v
[2] );
138 _swrast_Triangle( ctx
, &v
[0], &v
[1], &v
[2] );
142 gamma_fallback_line( gammaContextPtr gmesa
,
143 const gammaVertex
*v0
,
144 const gammaVertex
*v1
)
146 GLcontext
*ctx
= gmesa
->glCtx
;
148 gamma_translate_vertex( ctx
, v0
, &v
[0] );
149 gamma_translate_vertex( ctx
, v1
, &v
[1] );
150 _swrast_Line( ctx
, &v
[0], &v
[1] );
156 gamma_fallback_point( gammaContextPtr gmesa
,
157 const gammaVertex
*v0
)
159 GLcontext
*ctx
= gmesa
->glCtx
;
161 gamma_translate_vertex( ctx
, v0
, &v
[0] );
162 _swrast_Point( ctx
, &v
[0] );
167 /***********************************************************************
168 * Choose rasterization functions *
169 ***********************************************************************/
171 #define _GAMMA_NEW_RASTER_STATE (_NEW_FOG | \
173 _DD_NEW_TRI_SMOOTH | \
174 _DD_NEW_LINE_SMOOTH | \
175 _DD_NEW_POINT_SMOOTH | \
176 _DD_NEW_TRI_STIPPLE | \
177 _DD_NEW_LINE_STIPPLE)
179 #define LINE_FALLBACK (0)
180 #define TRI_FALLBACK (0)
182 static void gammaChooseRasterState(GLcontext
*ctx
)
184 gammaContextPtr gmesa
= GAMMA_CONTEXT(ctx
);
185 GLuint flags
= ctx
->_TriangleCaps
;
188 if ( ctx
->Line
.SmoothFlag
||
189 ctx
->Polygon
.SmoothFlag
||
190 ctx
->Point
.SmoothFlag
)
191 gmesa
->Begin
|= B_AntiAliasEnable
;
193 gmesa
->Begin
&= ~B_AntiAliasEnable
;
195 if ( ctx
->Texture
.Unit
[0]._ReallyEnabled
) {
196 ind
|= GAMMA_RAST_TEX_BIT
;
197 gmesa
->Begin
|= B_TextureEnable
;
199 gmesa
->Begin
&= ~B_TextureEnable
;
201 if (flags
& DD_LINE_STIPPLE
)
202 gmesa
->Begin
|= B_LineStippleEnable
;
204 gmesa
->Begin
&= ~B_LineStippleEnable
;
206 if (flags
& DD_TRI_STIPPLE
)
207 gmesa
->Begin
|= B_AreaStippleEnable
;
209 gmesa
->Begin
&= ~B_AreaStippleEnable
;
211 if (ctx
->Fog
.Enabled
)
212 gmesa
->Begin
|= B_FogEnable
;
214 gmesa
->Begin
&= ~B_FogEnable
;
216 if (ctx
->Color
.BlendEnabled
|| ctx
->Color
.AlphaEnabled
)
217 ind
|= GAMMA_RAST_ALPHA_BIT
;
219 if ( flags
& DD_FLATSHADE
)
220 ind
|= GAMMA_RAST_FLAT_BIT
;
222 gmesa
->draw_line
= gamma_line_tab
[ind
];
223 gmesa
->draw_tri
= gamma_tri_tab
[ind
];
224 gmesa
->draw_quad
= gamma_quad_tab
[ind
];
225 gmesa
->draw_point
= gamma_point_tab
[ind
];
227 /* Hook in fallbacks for specific primitives. CURRENTLY DISABLED
229 if (flags
& LINE_FALLBACK
)
230 gmesa
->draw_line
= gamma_fallback_line
;
232 if (flags
& TRI_FALLBACK
) {
233 gmesa
->draw_tri
= gamma_fallback_tri
;
234 gmesa
->draw_quad
= gamma_fallback_quad
;
241 /***********************************************************************
242 * Macros for t_dd_tritmp.h to draw basic primitives *
243 ***********************************************************************/
245 #define TRI( a, b, c ) \
247 gmesa->draw_tri( gmesa, a, b, c ); \
250 #define QUAD( a, b, c, d ) \
252 gmesa->draw_quad( gmesa, a, b, c, d ); \
255 #define LINE( v0, v1 ) \
257 gmesa->draw_line( gmesa, v0, v1 ); \
260 #define POINT( v0 ) \
262 gmesa->draw_point( gmesa, v0 ); \
266 /***********************************************************************
267 * Build render functions from dd templates *
268 ***********************************************************************/
270 #define GAMMA_OFFSET_BIT 0x01
271 #define GAMMA_TWOSIDE_BIT 0x02
272 #define GAMMA_UNFILLED_BIT 0x04
273 #define GAMMA_FALLBACK_BIT 0x08
274 #define GAMMA_MAX_TRIFUNC 0x10
278 tnl_points_func points
;
280 tnl_triangle_func triangle
;
282 } rast_tab
[GAMMA_MAX_TRIFUNC
];
285 #define DO_FALLBACK (IND & GAMMA_FALLBACK_BIT)
286 #define DO_OFFSET 0 /* (IND & GAMMA_OFFSET_BIT) */
287 #define DO_UNFILLED 0 /* (IND & GAMMA_UNFILLED_BIT) */
288 #define DO_TWOSIDE (IND & GAMMA_TWOSIDE_BIT)
294 #define DO_FULL_QUAD 1
298 #define HAVE_BACK_COLORS 0
299 #define HAVE_HW_FLATSHADE 1
300 #define VERTEX gammaVertex
303 #define DEPTH_SCALE 1.0
304 #define UNFILLED_TRI unfilled_tri
305 #define UNFILLED_QUAD unfilled_quad
306 #define VERT_X(_v) _v->v.x
307 #define VERT_Y(_v) _v->v.y
308 #define VERT_Z(_v) _v->v.z
309 #define AREA_IS_CCW( a ) (a > 0)
310 #define GET_VERTEX(e) (gmesa->verts + (e * gmesa->vertex_size * sizeof(int)))
312 #define VERT_SET_RGBA( v, c ) \
314 UNCLAMPED_FLOAT_TO_UBYTE(v->ub4[4][0], (c)[0]); \
315 UNCLAMPED_FLOAT_TO_UBYTE(v->ub4[4][1], (c)[1]); \
316 UNCLAMPED_FLOAT_TO_UBYTE(v->ub4[4][2], (c)[2]); \
317 UNCLAMPED_FLOAT_TO_UBYTE(v->ub4[4][3], (c)[3]); \
319 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[4] = v1->ui[4]
320 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[4]
321 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[4] = color[idx]
323 #define LOCAL_VARS(n) \
324 gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); \
329 /***********************************************************************
330 * Helpers for rendering unfilled primitives *
331 ***********************************************************************/
333 static const GLuint hw_prim
[GL_POLYGON
+1] = {
338 B_PrimType_Triangles
,
339 B_PrimType_Triangles
,
340 B_PrimType_Triangles
,
341 B_PrimType_Triangles
,
342 B_PrimType_Triangles
,
346 static void gammaResetLineStipple( GLcontext
*ctx
);
347 static void gammaRasterPrimitive( GLcontext
*ctx
, GLuint hwprim
);
348 static void gammaRenderPrimitive( GLcontext
*ctx
, GLenum prim
);
350 #define RASTERIZE(x) if (gmesa->hw_primitive != hw_prim[x]) \
351 gammaRasterPrimitive( ctx, hw_prim[x] )
352 #define RENDER_PRIMITIVE gmesa->render_primitive
354 #define IND GAMMA_FALLBACK_BIT
355 #include "tnl_dd/t_dd_unfilled.h"
358 /***********************************************************************
359 * Generate GL render functions *
360 ***********************************************************************/
364 #include "tnl_dd/t_dd_tritmp.h"
366 #define IND (GAMMA_OFFSET_BIT)
367 #define TAG(x) x##_offset
368 #include "tnl_dd/t_dd_tritmp.h"
370 #define IND (GAMMA_TWOSIDE_BIT)
371 #define TAG(x) x##_twoside
372 #include "tnl_dd/t_dd_tritmp.h"
374 #define IND (GAMMA_TWOSIDE_BIT|GAMMA_OFFSET_BIT)
375 #define TAG(x) x##_twoside_offset
376 #include "tnl_dd/t_dd_tritmp.h"
378 #define IND (GAMMA_UNFILLED_BIT)
379 #define TAG(x) x##_unfilled
380 #include "tnl_dd/t_dd_tritmp.h"
382 #define IND (GAMMA_OFFSET_BIT|GAMMA_UNFILLED_BIT)
383 #define TAG(x) x##_offset_unfilled
384 #include "tnl_dd/t_dd_tritmp.h"
386 #define IND (GAMMA_TWOSIDE_BIT|GAMMA_UNFILLED_BIT)
387 #define TAG(x) x##_twoside_unfilled
388 #include "tnl_dd/t_dd_tritmp.h"
390 #define IND (GAMMA_TWOSIDE_BIT|GAMMA_OFFSET_BIT|GAMMA_UNFILLED_BIT)
391 #define TAG(x) x##_twoside_offset_unfilled
392 #include "tnl_dd/t_dd_tritmp.h"
396 static void init_render_tab( void )
401 init_twoside_offset();
403 init_offset_unfilled();
404 init_twoside_unfilled();
405 init_twoside_offset_unfilled();
409 /**********************************************************************/
410 /* Render unclipped begin/end objects */
411 /**********************************************************************/
413 #define VERT(x) (gammaVertex *)(gammaverts + (x * size * sizeof(int)))
414 #define RENDER_POINTS( start, count ) \
415 for ( ; start < count ; start++) \
416 gmesa->draw_point( gmesa, VERT(start) )
417 #define RENDER_LINE( v0, v1 ) \
418 gmesa->draw_line( gmesa, VERT(v0), VERT(v1) )
419 #define RENDER_TRI( v0, v1, v2 ) \
420 gmesa->draw_tri( gmesa, VERT(v0), VERT(v1), VERT(v2) )
421 #define RENDER_QUAD( v0, v1, v2, v3 ) \
422 gmesa->draw_quad( gmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
423 #define INIT(x) gammaRenderPrimitive( ctx, x );
426 gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); \
427 const GLuint size = gmesa->vertex_size; \
428 const char *gammaverts = (char *)gmesa->verts; \
429 const GLboolean stipple = ctx->Line.StippleFlag; \
431 #define RESET_STIPPLE if ( stipple ) gammaResetLineStipple( ctx );
432 #define RESET_OCCLUSION
433 #define PRESERVE_VB_DEFS
435 #define TAG(x) gamma_##x##_verts
436 #include "tnl/t_vb_rendertmp.h"
439 /**********************************************************************/
440 /* Render clipped primitives */
441 /**********************************************************************/
443 static void gammaRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
446 gammaContextPtr gmesa
= GAMMA_CONTEXT(ctx
);
447 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
448 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
449 GLuint prim
= gmesa
->render_primitive
;
451 /* Render the new vertices as an unclipped polygon.
454 GLuint
*tmp
= VB
->Elts
;
455 VB
->Elts
= (GLuint
*)elts
;
456 tnl
->Driver
.Render
.PrimTabElts
[GL_POLYGON
]( ctx
, 0, n
, PRIM_BEGIN
|PRIM_END
);
460 /* Restore the render primitive
462 if (prim
!= GL_POLYGON
)
463 tnl
->Driver
.Render
.PrimitiveNotify( ctx
, prim
);
466 static void gammaRenderClippedLine( GLcontext
*ctx
, GLuint ii
, GLuint jj
)
468 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
469 tnl
->Driver
.Render
.Line( ctx
, ii
, jj
);
473 /**********************************************************************/
474 /* Choose render functions */
475 /**********************************************************************/
479 #define _GAMMA_NEW_RENDERSTATE (_DD_NEW_TRI_UNFILLED | \
480 _DD_NEW_TRI_LIGHT_TWOSIDE | \
483 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
485 static void gammaChooseRenderState(GLcontext
*ctx
)
487 gammaContextPtr gmesa
= GAMMA_CONTEXT(ctx
);
488 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
489 GLuint flags
= ctx
->_TriangleCaps
;
492 if (flags
& ANY_RASTER_FLAGS
) {
493 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= GAMMA_TWOSIDE_BIT
;
494 if (flags
& DD_TRI_OFFSET
) index
|= GAMMA_OFFSET_BIT
;
495 if (flags
& DD_TRI_UNFILLED
) index
|= GAMMA_UNFILLED_BIT
;
498 if (gmesa
->RenderIndex
!= index
) {
499 gmesa
->RenderIndex
= index
;
501 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
502 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
503 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
504 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
506 if (gmesa
->RenderIndex
== 0)
507 tnl
->Driver
.Render
.PrimTabVerts
= gamma_render_tab_verts
;
509 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
510 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
511 tnl
->Driver
.Render
.ClippedLine
= gammaRenderClippedLine
;
512 tnl
->Driver
.Render
.ClippedPolygon
= gammaRenderClippedPoly
;
517 /**********************************************************************/
518 /* High level hooks for t_vb_render.c */
519 /**********************************************************************/
523 /* Determine the rasterized primitive when not drawing unfilled
526 * Used only for the default render stage which always decomposes
527 * primitives to trianges/lines/points. For the accelerated stage,
528 * which renders strips as strips, the equivalent calculations are
529 * performed in gammarender.c.
532 static void gammaRasterPrimitive( GLcontext
*ctx
, GLuint hwprim
)
534 gammaContextPtr gmesa
= GAMMA_CONTEXT(ctx
);
535 if (gmesa
->hw_primitive
!= hwprim
)
536 gmesa
->hw_primitive
= hwprim
;
539 static void gammaRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
541 gammaContextPtr gmesa
= GAMMA_CONTEXT(ctx
);
542 gmesa
->render_primitive
= prim
;
545 static void gammaRunPipeline( GLcontext
*ctx
)
547 gammaContextPtr gmesa
= GAMMA_CONTEXT(ctx
);
549 if ( gmesa
->new_state
)
550 gammaDDUpdateHWState( ctx
);
552 if (gmesa
->new_gl_state
) {
553 if (gmesa
->new_gl_state
& _NEW_TEXTURE
)
554 gammaUpdateTextureState( ctx
);
556 if (!gmesa
->Fallback
) {
557 if (gmesa
->new_gl_state
& _GAMMA_NEW_VERTEX
)
558 gammaChooseVertexState( ctx
);
560 if (gmesa
->new_gl_state
& _GAMMA_NEW_RASTER_STATE
)
561 gammaChooseRasterState( ctx
);
563 if (gmesa
->new_gl_state
& _GAMMA_NEW_RENDERSTATE
)
564 gammaChooseRenderState( ctx
);
567 gmesa
->new_gl_state
= 0;
570 _tnl_run_pipeline( ctx
);
573 static void gammaRenderStart( GLcontext
*ctx
)
575 /* Check for projective texturing. Make sure all texcoord
576 * pointers point to something. (fix in mesa?)
578 gammaCheckTexSizes( ctx
);
581 static void gammaRenderFinish( GLcontext
*ctx
)
584 _swrast_flush( ctx
); /* never needed */
587 static void gammaResetLineStipple( GLcontext
*ctx
)
589 gammaContextPtr gmesa
= GAMMA_CONTEXT(ctx
);
591 /* Reset the hardware stipple counter.
593 CHECK_DMA_BUFFER(gmesa
, 1);
594 WRITE(gmesa
->buf
, UpdateLineStippleCounters
, 0);
598 /**********************************************************************/
599 /* Transition to/from hardware rasterization. */
600 /**********************************************************************/
603 void gammaFallback( gammaContextPtr gmesa
, GLuint bit
, GLboolean mode
)
605 GLcontext
*ctx
= gmesa
->glCtx
;
606 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
607 GLuint oldfallback
= gmesa
->Fallback
;
610 gmesa
->Fallback
|= bit
;
611 if (oldfallback
== 0) {
612 _swsetup_Wakeup( ctx
);
613 _tnl_need_projected_coords( ctx
, GL_TRUE
);
614 gmesa
->RenderIndex
= ~0;
618 gmesa
->Fallback
&= ~bit
;
619 if (oldfallback
== bit
) {
620 _swrast_flush( ctx
);
621 tnl
->Driver
.Render
.Start
= gammaRenderStart
;
622 tnl
->Driver
.Render
.PrimitiveNotify
= gammaRenderPrimitive
;
623 tnl
->Driver
.Render
.Finish
= gammaRenderFinish
;
624 tnl
->Driver
.Render
.BuildVertices
= gammaBuildVertices
;
625 tnl
->Driver
.Render
.ResetLineStipple
= gammaResetLineStipple
;
626 gmesa
->new_gl_state
|= (_GAMMA_NEW_RENDERSTATE
|
627 _GAMMA_NEW_RASTER_STATE
|
634 /**********************************************************************/
635 /* Initialization. */
636 /**********************************************************************/
639 void gammaDDInitTriFuncs( GLcontext
*ctx
)
641 gammaContextPtr gmesa
= GAMMA_CONTEXT(ctx
);
642 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
643 static int firsttime
= 1;
651 gmesa
->RenderIndex
= ~0;
653 tnl
->Driver
.RunPipeline
= gammaRunPipeline
;
654 tnl
->Driver
.Render
.Start
= gammaRenderStart
;
655 tnl
->Driver
.Render
.Finish
= gammaRenderFinish
;
656 tnl
->Driver
.Render
.PrimitiveNotify
= gammaRenderPrimitive
;
657 tnl
->Driver
.Render
.ResetLineStipple
= gammaResetLineStipple
;
658 tnl
->Driver
.Render
.BuildVertices
= gammaBuildVertices
;