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"
29 #include "gamma_macros.h"
31 #include "gamma_tris.h"
33 #include "main/glheader.h"
34 #include "main/mtypes.h"
35 #include "main/macros.h"
36 #include "main/colormac.h"
38 #include "swrast/swrast.h"
39 #include "swrast_setup/swrast_setup.h"
41 #include "tnl/t_context.h"
42 #include "tnl/t_pipeline.h"
45 /***********************************************************************
46 * Build hardware rasterization functions *
47 ***********************************************************************/
49 #define GAMMA_RAST_ALPHA_BIT 0x01
50 #define GAMMA_RAST_TEX_BIT 0x02
51 #define GAMMA_RAST_FLAT_BIT 0x04
53 static gamma_point_func gamma_point_tab
[0x8];
54 static gamma_line_func gamma_line_tab
[0x8];
55 static gamma_tri_func gamma_tri_tab
[0x8];
56 static gamma_quad_func gamma_quad_tab
[0x8];
60 #include "gamma_tritmp.h"
62 #define IND (GAMMA_RAST_ALPHA_BIT)
63 #define TAG(x) x##_alpha
64 #include "gamma_tritmp.h"
66 #define IND (GAMMA_RAST_TEX_BIT)
67 #define TAG(x) x##_tex
68 #include "gamma_tritmp.h"
70 #define IND (GAMMA_RAST_ALPHA_BIT|GAMMA_RAST_TEX_BIT)
71 #define TAG(x) x##_alpha_tex
72 #include "gamma_tritmp.h"
74 #define IND (GAMMA_RAST_FLAT_BIT)
75 #define TAG(x) x##_flat
76 #include "gamma_tritmp.h"
78 #define IND (GAMMA_RAST_ALPHA_BIT|GAMMA_RAST_FLAT_BIT)
79 #define TAG(x) x##_alpha_flat
80 #include "gamma_tritmp.h"
82 #define IND (GAMMA_RAST_TEX_BIT|GAMMA_RAST_FLAT_BIT)
83 #define TAG(x) x##_tex_flat
84 #include "gamma_tritmp.h"
86 #define IND (GAMMA_RAST_ALPHA_BIT|GAMMA_RAST_TEX_BIT|GAMMA_RAST_FLAT_BIT)
87 #define TAG(x) x##_alpha_tex_flat
88 #include "gamma_tritmp.h"
91 static void init_rast_tab( void )
96 gamma_init_alpha_tex();
98 gamma_init_alpha_flat();
99 gamma_init_tex_flat();
100 gamma_init_alpha_tex_flat();
103 /***********************************************************************
104 * Rasterization fallback helpers *
105 ***********************************************************************/
108 /* This code is hit only when a mix of accelerated and unaccelerated
109 * primitives are being drawn, and only for the unaccelerated
113 gamma_fallback_quad( gammaContextPtr gmesa
,
114 const gammaVertex
*v0
,
115 const gammaVertex
*v1
,
116 const gammaVertex
*v2
,
117 const gammaVertex
*v3
)
119 GLcontext
*ctx
= gmesa
->glCtx
;
121 gamma_translate_vertex( ctx
, v0
, &v
[0] );
122 gamma_translate_vertex( ctx
, v1
, &v
[1] );
123 gamma_translate_vertex( ctx
, v2
, &v
[2] );
124 gamma_translate_vertex( ctx
, v3
, &v
[3] );
125 _swrast_Quad( ctx
, &v
[0], &v
[1], &v
[2], &v
[3] );
129 gamma_fallback_tri( gammaContextPtr gmesa
,
130 const gammaVertex
*v0
,
131 const gammaVertex
*v1
,
132 const gammaVertex
*v2
)
134 GLcontext
*ctx
= gmesa
->glCtx
;
136 gamma_translate_vertex( ctx
, v0
, &v
[0] );
137 gamma_translate_vertex( ctx
, v1
, &v
[1] );
138 gamma_translate_vertex( ctx
, v2
, &v
[2] );
139 _swrast_Triangle( ctx
, &v
[0], &v
[1], &v
[2] );
143 gamma_fallback_line( gammaContextPtr gmesa
,
144 const gammaVertex
*v0
,
145 const gammaVertex
*v1
)
147 GLcontext
*ctx
= gmesa
->glCtx
;
149 gamma_translate_vertex( ctx
, v0
, &v
[0] );
150 gamma_translate_vertex( ctx
, v1
, &v
[1] );
151 _swrast_Line( ctx
, &v
[0], &v
[1] );
157 gamma_fallback_point( gammaContextPtr gmesa
,
158 const gammaVertex
*v0
)
160 GLcontext
*ctx
= gmesa
->glCtx
;
162 gamma_translate_vertex( ctx
, v0
, &v
[0] );
163 _swrast_Point( ctx
, &v
[0] );
168 /***********************************************************************
169 * Choose rasterization functions *
170 ***********************************************************************/
172 #define _GAMMA_NEW_RASTER_STATE (_NEW_FOG | \
174 _DD_NEW_TRI_SMOOTH | \
175 _DD_NEW_LINE_SMOOTH | \
176 _DD_NEW_POINT_SMOOTH | \
177 _DD_NEW_TRI_STIPPLE | \
178 _DD_NEW_LINE_STIPPLE)
180 #define LINE_FALLBACK (0)
181 #define TRI_FALLBACK (0)
183 static void gammaChooseRasterState(GLcontext
*ctx
)
185 gammaContextPtr gmesa
= GAMMA_CONTEXT(ctx
);
186 GLuint flags
= ctx
->_TriangleCaps
;
189 if ( ctx
->Line
.SmoothFlag
||
190 ctx
->Polygon
.SmoothFlag
||
191 ctx
->Point
.SmoothFlag
)
192 gmesa
->Begin
|= B_AntiAliasEnable
;
194 gmesa
->Begin
&= ~B_AntiAliasEnable
;
196 if ( ctx
->Texture
.Unit
[0]._ReallyEnabled
) {
197 ind
|= GAMMA_RAST_TEX_BIT
;
198 gmesa
->Begin
|= B_TextureEnable
;
200 gmesa
->Begin
&= ~B_TextureEnable
;
202 if (flags
& DD_LINE_STIPPLE
)
203 gmesa
->Begin
|= B_LineStippleEnable
;
205 gmesa
->Begin
&= ~B_LineStippleEnable
;
207 if (flags
& DD_TRI_STIPPLE
)
208 gmesa
->Begin
|= B_AreaStippleEnable
;
210 gmesa
->Begin
&= ~B_AreaStippleEnable
;
212 if (ctx
->Fog
.Enabled
)
213 gmesa
->Begin
|= B_FogEnable
;
215 gmesa
->Begin
&= ~B_FogEnable
;
217 if (ctx
->Color
.BlendEnabled
|| ctx
->Color
.AlphaEnabled
)
218 ind
|= GAMMA_RAST_ALPHA_BIT
;
220 if ( flags
& DD_FLATSHADE
)
221 ind
|= GAMMA_RAST_FLAT_BIT
;
223 gmesa
->draw_line
= gamma_line_tab
[ind
];
224 gmesa
->draw_tri
= gamma_tri_tab
[ind
];
225 gmesa
->draw_quad
= gamma_quad_tab
[ind
];
226 gmesa
->draw_point
= gamma_point_tab
[ind
];
228 /* Hook in fallbacks for specific primitives. CURRENTLY DISABLED
230 if (flags
& LINE_FALLBACK
)
231 gmesa
->draw_line
= gamma_fallback_line
;
233 if (flags
& TRI_FALLBACK
) {
234 gmesa
->draw_tri
= gamma_fallback_tri
;
235 gmesa
->draw_quad
= gamma_fallback_quad
;
242 /***********************************************************************
243 * Macros for t_dd_tritmp.h to draw basic primitives *
244 ***********************************************************************/
246 #define TRI( a, b, c ) \
248 gmesa->draw_tri( gmesa, a, b, c ); \
251 #define QUAD( a, b, c, d ) \
253 gmesa->draw_quad( gmesa, a, b, c, d ); \
256 #define LINE( v0, v1 ) \
258 gmesa->draw_line( gmesa, v0, v1 ); \
261 #define POINT( v0 ) \
263 gmesa->draw_point( gmesa, v0 ); \
267 /***********************************************************************
268 * Build render functions from dd templates *
269 ***********************************************************************/
271 #define GAMMA_OFFSET_BIT 0x01
272 #define GAMMA_TWOSIDE_BIT 0x02
273 #define GAMMA_UNFILLED_BIT 0x04
274 #define GAMMA_FALLBACK_BIT 0x08
275 #define GAMMA_MAX_TRIFUNC 0x10
279 tnl_points_func points
;
281 tnl_triangle_func triangle
;
283 } rast_tab
[GAMMA_MAX_TRIFUNC
];
286 #define DO_FALLBACK (IND & GAMMA_FALLBACK_BIT)
287 #define DO_OFFSET 0 /* (IND & GAMMA_OFFSET_BIT) */
288 #define DO_UNFILLED 0 /* (IND & GAMMA_UNFILLED_BIT) */
289 #define DO_TWOSIDE (IND & GAMMA_TWOSIDE_BIT)
295 #define DO_FULL_QUAD 1
299 #define HAVE_BACK_COLORS 0
300 #define HAVE_HW_FLATSHADE 1
301 #define VERTEX gammaVertex
304 #define DEPTH_SCALE 1.0
305 #define UNFILLED_TRI unfilled_tri
306 #define UNFILLED_QUAD unfilled_quad
307 #define VERT_X(_v) _v->v.x
308 #define VERT_Y(_v) _v->v.y
309 #define VERT_Z(_v) _v->v.z
310 #define AREA_IS_CCW( a ) (a > 0)
311 #define GET_VERTEX(e) (gmesa->verts + (e * gmesa->vertex_size * sizeof(int)))
313 #define VERT_SET_RGBA( v, c ) \
315 UNCLAMPED_FLOAT_TO_UBYTE(v->ub4[4][0], (c)[0]); \
316 UNCLAMPED_FLOAT_TO_UBYTE(v->ub4[4][1], (c)[1]); \
317 UNCLAMPED_FLOAT_TO_UBYTE(v->ub4[4][2], (c)[2]); \
318 UNCLAMPED_FLOAT_TO_UBYTE(v->ub4[4][3], (c)[3]); \
320 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[4] = v1->ui[4]
321 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[4]
322 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[4] = color[idx]
324 #define LOCAL_VARS(n) \
325 gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); \
326 GLuint color[n] = { 0 }; \
330 /***********************************************************************
331 * Helpers for rendering unfilled primitives *
332 ***********************************************************************/
334 static const GLuint hw_prim
[GL_POLYGON
+1] = {
339 B_PrimType_Triangles
,
340 B_PrimType_Triangles
,
341 B_PrimType_Triangles
,
342 B_PrimType_Triangles
,
343 B_PrimType_Triangles
,
347 static void gammaResetLineStipple( GLcontext
*ctx
);
348 static void gammaRasterPrimitive( GLcontext
*ctx
, GLuint hwprim
);
349 static void gammaRenderPrimitive( GLcontext
*ctx
, GLenum prim
);
351 #define RASTERIZE(x) if (gmesa->hw_primitive != hw_prim[x]) \
352 gammaRasterPrimitive( ctx, hw_prim[x] )
353 #define RENDER_PRIMITIVE gmesa->render_primitive
355 #define IND GAMMA_FALLBACK_BIT
356 #include "tnl_dd/t_dd_unfilled.h"
359 /***********************************************************************
360 * Generate GL render functions *
361 ***********************************************************************/
365 #include "tnl_dd/t_dd_tritmp.h"
367 #define IND (GAMMA_OFFSET_BIT)
368 #define TAG(x) x##_offset
369 #include "tnl_dd/t_dd_tritmp.h"
371 #define IND (GAMMA_TWOSIDE_BIT)
372 #define TAG(x) x##_twoside
373 #include "tnl_dd/t_dd_tritmp.h"
375 #define IND (GAMMA_TWOSIDE_BIT|GAMMA_OFFSET_BIT)
376 #define TAG(x) x##_twoside_offset
377 #include "tnl_dd/t_dd_tritmp.h"
379 #define IND (GAMMA_UNFILLED_BIT)
380 #define TAG(x) x##_unfilled
381 #include "tnl_dd/t_dd_tritmp.h"
383 #define IND (GAMMA_OFFSET_BIT|GAMMA_UNFILLED_BIT)
384 #define TAG(x) x##_offset_unfilled
385 #include "tnl_dd/t_dd_tritmp.h"
387 #define IND (GAMMA_TWOSIDE_BIT|GAMMA_UNFILLED_BIT)
388 #define TAG(x) x##_twoside_unfilled
389 #include "tnl_dd/t_dd_tritmp.h"
391 #define IND (GAMMA_TWOSIDE_BIT|GAMMA_OFFSET_BIT|GAMMA_UNFILLED_BIT)
392 #define TAG(x) x##_twoside_offset_unfilled
393 #include "tnl_dd/t_dd_tritmp.h"
397 static void init_render_tab( void )
402 init_twoside_offset();
404 init_offset_unfilled();
405 init_twoside_unfilled();
406 init_twoside_offset_unfilled();
410 /**********************************************************************/
411 /* Render unclipped begin/end objects */
412 /**********************************************************************/
414 #define VERT(x) (gammaVertex *)(gammaverts + (x * size * sizeof(int)))
415 #define RENDER_POINTS( start, count ) \
416 for ( ; start < count ; start++) \
417 gmesa->draw_point( gmesa, VERT(start) )
418 #define RENDER_LINE( v0, v1 ) \
419 gmesa->draw_line( gmesa, VERT(v0), VERT(v1) )
420 #define RENDER_TRI( v0, v1, v2 ) \
421 gmesa->draw_tri( gmesa, VERT(v0), VERT(v1), VERT(v2) )
422 #define RENDER_QUAD( v0, v1, v2, v3 ) \
423 gmesa->draw_quad( gmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
424 #define INIT(x) gammaRenderPrimitive( ctx, x );
427 gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); \
428 const GLuint size = gmesa->vertex_size; \
429 const char *gammaverts = (char *)gmesa->verts; \
430 const GLboolean stipple = ctx->Line.StippleFlag; \
432 #define RESET_STIPPLE if ( stipple ) gammaResetLineStipple( ctx );
433 #define RESET_OCCLUSION
434 #define PRESERVE_VB_DEFS
436 #define TAG(x) gamma_##x##_verts
437 #include "tnl/t_vb_rendertmp.h"
440 /**********************************************************************/
441 /* Render clipped primitives */
442 /**********************************************************************/
444 static void gammaRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
447 gammaContextPtr gmesa
= GAMMA_CONTEXT(ctx
);
448 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
449 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
450 GLuint prim
= gmesa
->render_primitive
;
452 /* Render the new vertices as an unclipped polygon.
455 GLuint
*tmp
= VB
->Elts
;
456 VB
->Elts
= (GLuint
*)elts
;
457 tnl
->Driver
.Render
.PrimTabElts
[GL_POLYGON
]( ctx
, 0, n
, PRIM_BEGIN
|PRIM_END
);
461 /* Restore the render primitive
463 if (prim
!= GL_POLYGON
)
464 tnl
->Driver
.Render
.PrimitiveNotify( ctx
, prim
);
467 static void gammaRenderClippedLine( GLcontext
*ctx
, GLuint ii
, GLuint jj
)
469 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
470 tnl
->Driver
.Render
.Line( ctx
, ii
, jj
);
474 /**********************************************************************/
475 /* Choose render functions */
476 /**********************************************************************/
480 #define _GAMMA_NEW_RENDERSTATE (_DD_NEW_TRI_UNFILLED | \
481 _DD_NEW_TRI_LIGHT_TWOSIDE | \
484 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
486 static void gammaChooseRenderState(GLcontext
*ctx
)
488 gammaContextPtr gmesa
= GAMMA_CONTEXT(ctx
);
489 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
490 GLuint flags
= ctx
->_TriangleCaps
;
493 if (flags
& ANY_RASTER_FLAGS
) {
494 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= GAMMA_TWOSIDE_BIT
;
495 if (flags
& DD_TRI_OFFSET
) index
|= GAMMA_OFFSET_BIT
;
496 if (flags
& DD_TRI_UNFILLED
) index
|= GAMMA_UNFILLED_BIT
;
499 if (gmesa
->RenderIndex
!= index
) {
500 gmesa
->RenderIndex
= index
;
502 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
503 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
504 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
505 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
507 if (gmesa
->RenderIndex
== 0)
508 tnl
->Driver
.Render
.PrimTabVerts
= gamma_render_tab_verts
;
510 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
511 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
512 tnl
->Driver
.Render
.ClippedLine
= gammaRenderClippedLine
;
513 tnl
->Driver
.Render
.ClippedPolygon
= gammaRenderClippedPoly
;
518 /**********************************************************************/
519 /* High level hooks for t_vb_render.c */
520 /**********************************************************************/
524 /* Determine the rasterized primitive when not drawing unfilled
527 * Used only for the default render stage which always decomposes
528 * primitives to trianges/lines/points. For the accelerated stage,
529 * which renders strips as strips, the equivalent calculations are
530 * performed in gammarender.c.
533 static void gammaRasterPrimitive( GLcontext
*ctx
, GLuint hwprim
)
535 gammaContextPtr gmesa
= GAMMA_CONTEXT(ctx
);
536 if (gmesa
->hw_primitive
!= hwprim
)
537 gmesa
->hw_primitive
= hwprim
;
540 static void gammaRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
542 gammaContextPtr gmesa
= GAMMA_CONTEXT(ctx
);
543 gmesa
->render_primitive
= prim
;
546 static void gammaRunPipeline( GLcontext
*ctx
)
548 gammaContextPtr gmesa
= GAMMA_CONTEXT(ctx
);
550 if ( gmesa
->new_state
)
551 gammaDDUpdateHWState( ctx
);
553 if (gmesa
->new_gl_state
) {
554 if (gmesa
->new_gl_state
& _NEW_TEXTURE
)
555 gammaUpdateTextureState( ctx
);
557 if (!gmesa
->Fallback
) {
558 if (gmesa
->new_gl_state
& _GAMMA_NEW_VERTEX
)
559 gammaChooseVertexState( ctx
);
561 if (gmesa
->new_gl_state
& _GAMMA_NEW_RASTER_STATE
)
562 gammaChooseRasterState( ctx
);
564 if (gmesa
->new_gl_state
& _GAMMA_NEW_RENDERSTATE
)
565 gammaChooseRenderState( ctx
);
568 gmesa
->new_gl_state
= 0;
571 _tnl_run_pipeline( ctx
);
574 static void gammaRenderStart( GLcontext
*ctx
)
576 /* Check for projective texturing. Make sure all texcoord
577 * pointers point to something. (fix in mesa?)
579 gammaCheckTexSizes( ctx
);
582 static void gammaRenderFinish( GLcontext
*ctx
)
585 _swrast_flush( ctx
); /* never needed */
588 static void gammaResetLineStipple( GLcontext
*ctx
)
590 gammaContextPtr gmesa
= GAMMA_CONTEXT(ctx
);
592 /* Reset the hardware stipple counter.
594 CHECK_DMA_BUFFER(gmesa
, 1);
595 WRITE(gmesa
->buf
, UpdateLineStippleCounters
, 0);
599 /**********************************************************************/
600 /* Transition to/from hardware rasterization. */
601 /**********************************************************************/
604 void gammaFallback( gammaContextPtr gmesa
, GLuint bit
, GLboolean mode
)
606 GLcontext
*ctx
= gmesa
->glCtx
;
607 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
608 GLuint oldfallback
= gmesa
->Fallback
;
611 gmesa
->Fallback
|= bit
;
612 if (oldfallback
== 0) {
613 _swsetup_Wakeup( ctx
);
614 _tnl_need_projected_coords( ctx
, GL_TRUE
);
615 gmesa
->RenderIndex
= ~0;
619 gmesa
->Fallback
&= ~bit
;
620 if (oldfallback
== bit
) {
621 _swrast_flush( ctx
);
622 tnl
->Driver
.Render
.Start
= gammaRenderStart
;
623 tnl
->Driver
.Render
.PrimitiveNotify
= gammaRenderPrimitive
;
624 tnl
->Driver
.Render
.Finish
= gammaRenderFinish
;
625 tnl
->Driver
.Render
.BuildVertices
= gammaBuildVertices
;
626 tnl
->Driver
.Render
.ResetLineStipple
= gammaResetLineStipple
;
627 gmesa
->new_gl_state
|= (_GAMMA_NEW_RENDERSTATE
|
628 _GAMMA_NEW_RASTER_STATE
|
635 /**********************************************************************/
636 /* Initialization. */
637 /**********************************************************************/
640 void gammaDDInitTriFuncs( GLcontext
*ctx
)
642 gammaContextPtr gmesa
= GAMMA_CONTEXT(ctx
);
643 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
644 static int firsttime
= 1;
652 gmesa
->RenderIndex
= ~0;
654 tnl
->Driver
.RunPipeline
= gammaRunPipeline
;
655 tnl
->Driver
.Render
.Start
= gammaRenderStart
;
656 tnl
->Driver
.Render
.Finish
= gammaRenderFinish
;
657 tnl
->Driver
.Render
.PrimitiveNotify
= gammaRenderPrimitive
;
658 tnl
->Driver
.Render
.ResetLineStipple
= gammaResetLineStipple
;
659 tnl
->Driver
.Render
.BuildVertices
= gammaBuildVertices
;