2 * Copyright 2005 Felix Kuehling
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR
20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 * Render unclipped vertex buffers by emitting vertices directly to
27 * dma buffers. Use strip/fan hardware primitives where possible.
28 * Simulate missing primitives with indexed vertices.
36 #include "tnl/t_context.h"
38 #include "savagecontext.h"
39 #include "savagetris.h"
40 #include "savagestate.h"
41 #include "savageioctl.h"
44 * Standard render tab for Savage4 and smooth shading on Savage3D
48 #define HAVE_LINE_STRIPS 0
49 #define HAVE_TRIANGLES 1
50 #define HAVE_TRI_STRIPS 1
51 #define HAVE_TRI_STRIP_1 0
52 #define HAVE_TRI_FANS 1
53 #define HAVE_POLYGONS 0
55 #define HAVE_QUAD_STRIPS 0
57 #define HAVE_ELTS 0 /* for now */
59 #define LOCAL_VARS savageContextPtr imesa = SAVAGE_CONTEXT(ctx)
60 #define INIT( prim ) do { \
61 if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
62 savageFlushVertices(imesa); \
64 case GL_TRIANGLES: imesa->HwPrim = SAVAGE_PRIM_TRILIST; break; \
65 case GL_TRIANGLE_STRIP: imesa->HwPrim = SAVAGE_PRIM_TRISTRIP; break; \
66 case GL_TRIANGLE_FAN: imesa->HwPrim = SAVAGE_PRIM_TRIFAN; break; \
69 #define FLUSH() savageFlushVertices(imesa)
70 #define GET_CURRENT_VB_MAX_VERTS() \
71 ((imesa->bufferSize/4 - imesa->vtxBuf->used) / imesa->HwVertexSize)
72 #define GET_SUBSEQUENT_VB_MAX_VERTS() \
73 (imesa->bufferSize/4 / imesa->HwVertexSize)
75 #define ALLOC_VERTS( nr ) \
76 savageAllocVtxBuf( imesa, (nr) * imesa->HwVertexSize )
77 #define EMIT_VERTS( ctx, j, nr, buf ) \
78 _tnl_emit_vertices_to_buffer(ctx, j, (j)+(nr), buf )
80 #define TAG(x) savage_##x
81 #include "tnl_dd/t_dd_dmatmp.h"
84 * On Savage3D triangle fans and strips are broken with flat
85 * shading. With triangles it wants the color for flat shading in the
86 * first vertex! So we make another template instance which uses
87 * triangles only (with reordered vertices: SAVAGE_PRIM_TRILIST_201).
88 * The reordering is done by the DRM.
90 #undef HAVE_TRI_STRIPS
92 #define HAVE_TRI_STRIPS 0
93 #define HAVE_TRI_FANS 0
96 #define INIT( prim ) do { \
97 if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
98 savageFlushVertices(imesa); \
99 imesa->HwPrim = SAVAGE_PRIM_TRILIST_201; \
103 #define TAG(x) savage_flat_##x##_s3d
104 #include "tnl_dd/t_dd_dmatmp.h"
107 /**********************************************************************/
108 /* Render pipeline stage */
109 /**********************************************************************/
111 static GLboolean
savage_run_render( GLcontext
*ctx
,
112 struct tnl_pipeline_stage
*stage
)
114 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
115 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
116 struct vertex_buffer
*VB
= &tnl
->vb
;
117 tnl_render_func
*tab
;
121 if (imesa
->savageScreen
->chipset
< S3_SAVAGE4
&&
122 (ctx
->_TriangleCaps
& DD_FLATSHADE
)) {
123 tab
= savage_flat_render_tab_verts_s3d
;
124 valid
= savage_flat_validate_render_s3d( ctx
, VB
);
126 tab
= savage_render_tab_verts
;
127 valid
= savage_validate_render( ctx
, VB
);
130 /* Don't handle clipping or indexed vertices or vertex manipulations.
132 if (imesa
->RenderIndex
!= 0 || !valid
) {
136 tnl
->Driver
.Render
.Start( ctx
);
137 /* Check RenderIndex again. The ptexHack is detected late in RenderStart.
138 * Also check for fallbacks detected late.
140 if (imesa
->RenderIndex
!= 0 || imesa
->Fallback
!= 0) {
144 /* setup for hardware culling */
145 imesa
->raster_primitive
= GL_TRIANGLES
;
146 imesa
->new_state
|= SAVAGE_NEW_CULL
;
147 savageDDUpdateHwState(ctx
);
149 for (i
= 0 ; i
< VB
->PrimitiveCount
; i
++)
151 GLuint prim
= VB
->Primitive
[i
].mode
;
152 GLuint start
= VB
->Primitive
[i
].start
;
153 GLuint length
= VB
->Primitive
[i
].count
;
156 tab
[prim
& PRIM_MODE_MASK
]( ctx
, start
, start
+length
, prim
);
159 tnl
->Driver
.Render
.Finish( ctx
);
161 return GL_FALSE
; /* finished the pipe */
164 static void savage_check_render( GLcontext
*ctx
,
165 struct tnl_pipeline_stage
*stage
)
167 __DRIscreenPrivate
*driScrnPriv
=
168 SAVAGE_CONTEXT(ctx
)->savageScreen
->driScrnPriv
;
169 stage
->inputs
= TNL_CONTEXT(ctx
)->render_inputs
;
170 /* This hack will go away when we depend on 2.2.x for ELTS. */
171 if (driScrnPriv
->drmMinor
<= 1 && driScrnPriv
->drmPatch
< 3) {
172 static GLboolean firstTime
= GL_TRUE
;
173 stage
->active
= GL_FALSE
;
176 "*** Disabling fast path because your DRM version is buggy.\n"
177 "*** You need at least Savage DRM version 2.1.3.\n");
178 firstTime
= GL_FALSE
;
183 static void dtr( struct tnl_pipeline_stage
*stage
)
188 const struct tnl_pipeline_stage _savage_render_stage
=
191 (_DD_NEW_SEPARATE_SPECULAR
|
194 _NEW_RENDERMODE
), /* re-check (new inputs) */
195 0, /* re-run (always runs) */
196 GL_TRUE
, /* active */
197 0, 0, /* inputs (set in check_render), outputs */
198 0, 0, /* changed_inputs, private */
199 dtr
, /* destructor */
200 savage_check_render
, /* check - initially set to alloc data */
201 savage_run_render
/* run */
205 /**********************************************************************/
206 /* Pipeline stage for texture coordinate normalization */
207 /**********************************************************************/
208 struct texnorm_stage_data
{
209 GLvector4f texcoord
[MAX_TEXTURE_UNITS
];
212 #define TEXNORM_STAGE_DATA(stage) ((struct texnorm_stage_data *)stage->privatePtr)
215 static GLboolean
run_texnorm_stage( GLcontext
*ctx
,
216 struct tnl_pipeline_stage
*stage
)
218 struct texnorm_stage_data
*store
= TEXNORM_STAGE_DATA(stage
);
219 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
220 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
221 struct vertex_buffer
*VB
= &tnl
->vb
;
227 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
228 if (!(stage
->inputs
& stage
->changed_inputs
& VERT_BIT_TEX(i
)) ||
229 VB
->TexCoordPtr
[i
]->size
== 4)
230 /* Never try to normalize homogenous tex coords! */
233 GLuint reallyEnabled
= ctx
->Texture
.Unit
[i
]._ReallyEnabled
;
234 struct gl_texture_object
*texObj
= ctx
->Texture
.Unit
[i
]._Current
;
235 GLboolean normalizeS
= (texObj
->WrapS
== GL_REPEAT
);
236 GLboolean normalizeT
= (reallyEnabled
& TEXTURE_2D_BIT
) &&
237 (texObj
->WrapT
== GL_REPEAT
);
238 GLfloat
*in
= (GLfloat
*)VB
->TexCoordPtr
[i
]->data
;
239 GLint instride
= VB
->TexCoordPtr
[i
]->stride
;
240 GLfloat (*out
)[4] = store
->texcoord
[i
].data
;
243 if (normalizeS
&& normalizeT
) {
244 /* take first texcoords as rough estimate of mean value */
245 GLfloat correctionS
= -floor(in
[0]+0.5);
246 GLfloat correctionT
= -floor(in
[1]+0.5);
247 for (j
= 0; j
< VB
->Count
; ++j
) {
248 out
[j
][0] = in
[0] + correctionS
;
249 out
[j
][1] = in
[1] + correctionT
;
250 in
= (GLfloat
*)((GLubyte
*)in
+ instride
);
252 } else if (normalizeS
) {
253 /* take first texcoords as rough estimate of mean value */
254 GLfloat correctionS
= -floor(in
[0]+0.5);
255 if (reallyEnabled
& TEXTURE_2D_BIT
) {
256 for (j
= 0; j
< VB
->Count
; ++j
) {
257 out
[j
][0] = in
[0] + correctionS
;
259 in
= (GLfloat
*)((GLubyte
*)in
+ instride
);
262 for (j
= 0; j
< VB
->Count
; ++j
) {
263 out
[j
][0] = in
[0] + correctionS
;
264 in
= (GLfloat
*)((GLubyte
*)in
+ instride
);
267 } else if (normalizeT
) {
268 /* take first texcoords as rough estimate of mean value */
269 GLfloat correctionT
= -floor(in
[1]+0.5);
270 for (j
= 0; j
< VB
->Count
; ++j
) {
272 out
[j
][1] = in
[1] + correctionT
;
273 in
= (GLfloat
*)((GLubyte
*)in
+ instride
);
277 if (normalizeS
|| normalizeT
)
278 VB
->AttribPtr
[VERT_ATTRIB_TEX0
+i
] = VB
->TexCoordPtr
[i
] = &store
->texcoord
[i
];
284 /* Called the first time stage->run() is invoked.
286 static GLboolean
alloc_texnorm_data( GLcontext
*ctx
,
287 struct tnl_pipeline_stage
*stage
)
289 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
290 struct texnorm_stage_data
*store
;
293 stage
->privatePtr
= CALLOC(sizeof(*store
));
294 store
= TEXNORM_STAGE_DATA(stage
);
298 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++)
299 _mesa_vector4f_alloc( &store
->texcoord
[i
], 0, VB
->Size
, 32 );
301 /* Now run the stage.
303 stage
->run
= run_texnorm_stage
;
304 return stage
->run( ctx
, stage
);
307 static void check_texnorm( GLcontext
*ctx
,
308 struct tnl_pipeline_stage
*stage
)
312 if (((ctx
->Texture
.Unit
[0]._ReallyEnabled
& (TEXTURE_1D_BIT
|TEXTURE_2D_BIT
)) &&
313 (ctx
->Texture
.Unit
[0]._Current
->WrapS
== GL_REPEAT
)) ||
314 ((ctx
->Texture
.Unit
[0]._ReallyEnabled
& TEXTURE_2D_BIT
) &&
315 (ctx
->Texture
.Unit
[0]._Current
->WrapT
== GL_REPEAT
)))
316 flags
|= VERT_BIT_TEX0
;
318 if (((ctx
->Texture
.Unit
[1]._ReallyEnabled
& (TEXTURE_1D_BIT
|TEXTURE_2D_BIT
)) &&
319 (ctx
->Texture
.Unit
[1]._Current
->WrapS
== GL_REPEAT
)) ||
320 ((ctx
->Texture
.Unit
[1]._ReallyEnabled
& TEXTURE_2D_BIT
) &&
321 (ctx
->Texture
.Unit
[1]._Current
->WrapT
== GL_REPEAT
)))
322 flags
|= VERT_BIT_TEX1
;
324 stage
->inputs
= flags
;
325 stage
->outputs
= flags
;
326 stage
->active
= (flags
!= 0);
329 static void free_texnorm_data( struct tnl_pipeline_stage
*stage
)
331 struct texnorm_stage_data
*store
= TEXNORM_STAGE_DATA(stage
);
335 for (i
= 0 ; i
< MAX_TEXTURE_UNITS
; i
++)
336 if (store
->texcoord
[i
].data
)
337 _mesa_vector4f_free( &store
->texcoord
[i
] );
339 stage
->privatePtr
= 0;
343 const struct tnl_pipeline_stage _savage_texnorm_stage
=
345 "savage texture coordinate normalization stage", /* name */
346 _NEW_TEXTURE
, /* check_state */
347 _NEW_TEXTURE
, /* run_state */
348 GL_TRUE
, /* active? */
351 0, /* changed_inputs */
352 NULL
, /* private data */
353 free_texnorm_data
, /* destructor */
354 check_texnorm
, /* check */
355 alloc_texnorm_data
, /* run -- initially set to init */