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.
30 #include "main/glheader.h"
31 #include "main/context.h"
32 #include "main/macros.h"
33 #include "main/imports.h"
34 #include "main/mtypes.h"
36 #include "tnl/t_context.h"
38 #include "savagecontext.h"
39 #include "savagestate.h"
40 #include "savageioctl.h"
43 * Standard render tab for Savage4 and smooth shading on Savage3D
47 #define HAVE_LINE_STRIPS 0
48 #define HAVE_TRIANGLES 1
49 #define HAVE_TRI_STRIPS 1
50 #define HAVE_TRI_STRIP_1 0
51 #define HAVE_TRI_FANS 1
52 #define HAVE_POLYGONS 0
54 #define HAVE_QUAD_STRIPS 0
58 #define LOCAL_VARS savageContextPtr imesa = SAVAGE_CONTEXT(ctx)
59 #define INIT( prim ) do { \
60 if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
61 savageFlushVertices(imesa); \
63 case GL_TRIANGLES: imesa->HwPrim = SAVAGE_PRIM_TRILIST; break; \
64 case GL_TRIANGLE_STRIP: imesa->HwPrim = SAVAGE_PRIM_TRISTRIP; break; \
65 case GL_TRIANGLE_FAN: imesa->HwPrim = SAVAGE_PRIM_TRIFAN; break; \
68 #define FLUSH() savageFlushElts(imesa), 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 ELTS_VARS( buf ) GLushort *dest = buf, firstElt = imesa->firstElt
81 #define ELT_INIT( prim ) INIT(prim)
83 /* (size - used - 1 qword for drawing command) * 4 elts per qword */
84 #define GET_CURRENT_VB_MAX_ELTS() \
85 ((imesa->cmdBuf.size - (imesa->cmdBuf.write - imesa->cmdBuf.base) - 1)*4)
86 /* (size - space for initial state - 1 qword for drawing command) * 4 elts
87 * imesa is not defined in validate_render :( */
88 #define GET_SUBSEQUENT_VB_MAX_ELTS() \
89 ((SAVAGE_CONTEXT(ctx)->cmdBuf.size - \
90 (SAVAGE_CONTEXT(ctx)->cmdBuf.start - \
91 SAVAGE_CONTEXT(ctx)->cmdBuf.base) - 1)*4)
93 #define ALLOC_ELTS(nr) savageAllocElts(imesa, nr)
94 #define EMIT_ELT(offset, x) do { \
95 (dest)[offset] = (GLushort) ((x)+firstElt); \
97 #define EMIT_TWO_ELTS(offset, x, y) do { \
98 *(GLuint *)(dest + offset) = (((y)+firstElt) << 16) | \
102 #define INCR_ELTS( nr ) dest += nr
104 #define RELEASE_ELT_VERTS() \
105 savageReleaseIndexedVerts(imesa)
107 #define EMIT_INDEXED_VERTS( ctx, start, count ) do { \
108 GLuint *buf = savageAllocIndexedVerts(imesa, count-start); \
109 EMIT_VERTS(ctx, start, count-start, buf); \
112 #define TAG(x) savage_##x
113 #include "tnl_dd/t_dd_dmatmp.h"
116 * On Savage3D triangle fans and strips are broken with flat
117 * shading. With triangles it wants the color for flat shading in the
118 * first vertex! So we make another template instance which uses
119 * triangles only (with reordered vertices: SAVAGE_PRIM_TRILIST_201).
120 * The reordering is done by the DRM.
122 #undef HAVE_TRI_STRIPS
124 #define HAVE_TRI_STRIPS 0
125 #define HAVE_TRI_FANS 0
128 #define INIT( prim ) do { \
129 if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
130 savageFlushVertices(imesa); \
131 imesa->HwPrim = SAVAGE_PRIM_TRILIST_201; \
135 #define TAG(x) savage_flat_##x##_s3d
136 #include "tnl_dd/t_dd_dmatmp.h"
139 /**********************************************************************/
140 /* Render pipeline stage */
141 /**********************************************************************/
143 static GLboolean
savage_run_render( GLcontext
*ctx
,
144 struct tnl_pipeline_stage
*stage
)
146 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
147 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
148 struct vertex_buffer
*VB
= &tnl
->vb
;
149 tnl_render_func
*tab
, *tab_elts
;
153 if (savageHaveIndexedVerts(imesa
))
154 savageReleaseIndexedVerts(imesa
);
156 if (imesa
->savageScreen
->chipset
< S3_SAVAGE4
&&
157 (ctx
->_TriangleCaps
& DD_FLATSHADE
)) {
158 tab
= savage_flat_render_tab_verts_s3d
;
159 tab_elts
= savage_flat_render_tab_elts_s3d
;
160 valid
= savage_flat_validate_render_s3d( ctx
, VB
);
162 tab
= savage_render_tab_verts
;
163 tab_elts
= savage_render_tab_elts
;
164 valid
= savage_validate_render( ctx
, VB
);
167 /* Don't handle clipping or vertex manipulations.
169 if (imesa
->RenderIndex
!= 0 || !valid
) {
173 tnl
->Driver
.Render
.Start( ctx
);
174 /* Check RenderIndex again. The ptexHack is detected late in RenderStart.
175 * Also check for ptex fallbacks detected late.
177 if (imesa
->RenderIndex
!= 0 || imesa
->Fallback
!= 0) {
181 /* setup for hardware culling */
182 imesa
->raster_primitive
= GL_TRIANGLES
;
183 imesa
->new_state
|= SAVAGE_NEW_CULL
;
185 /* update and emit state */
186 savageDDUpdateHwState(ctx
);
187 savageEmitChangedState(imesa
);
191 if (!savageHaveIndexedVerts(imesa
)) {
192 if (VB
->Count
> GET_SUBSEQUENT_VB_MAX_VERTS())
194 EMIT_INDEXED_VERTS(ctx
, 0, VB
->Count
);
198 for (i
= 0 ; i
< VB
->PrimitiveCount
; i
++)
200 GLuint prim
= _tnl_translate_prim(&VB
->Primitive
[i
]);
201 GLuint start
= VB
->Primitive
[i
].start
;
202 GLuint length
= VB
->Primitive
[i
].count
;
205 tab
[prim
& PRIM_MODE_MASK
]( ctx
, start
, start
+length
, prim
);
208 tnl
->Driver
.Render
.Finish( ctx
);
210 return GL_FALSE
; /* finished the pipe */
213 struct tnl_pipeline_stage _savage_render_stage
=
220 savage_run_render
/* run */
224 /**********************************************************************/
225 /* Pipeline stage for texture coordinate normalization */
226 /**********************************************************************/
227 struct texnorm_stage_data
{
229 GLvector4f texcoord
[MAX_TEXTURE_UNITS
];
232 #define TEXNORM_STAGE_DATA(stage) ((struct texnorm_stage_data *)stage->privatePtr)
235 static GLboolean
run_texnorm_stage( GLcontext
*ctx
,
236 struct tnl_pipeline_stage
*stage
)
238 struct texnorm_stage_data
*store
= TEXNORM_STAGE_DATA(stage
);
239 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
240 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
241 struct vertex_buffer
*VB
= &tnl
->vb
;
244 if (imesa
->Fallback
|| !store
->active
)
247 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
248 const GLbitfield reallyEnabled
= ctx
->Texture
.Unit
[i
]._ReallyEnabled
;
250 const struct gl_texture_object
*texObj
= ctx
->Texture
.Unit
[i
]._Current
;
251 const GLboolean normalizeS
= (texObj
->WrapS
== GL_REPEAT
);
252 const GLboolean normalizeT
= (reallyEnabled
& TEXTURE_2D_BIT
) &&
253 (texObj
->WrapT
== GL_REPEAT
);
254 const GLfloat
*in
= (GLfloat
*)VB
->AttribPtr
[_TNL_ATTRIB_TEX0
+ i
]->data
;
255 const GLint instride
= VB
->AttribPtr
[_TNL_ATTRIB_TEX0
+ i
]->stride
;
256 GLfloat (*out
)[4] = store
->texcoord
[i
].data
;
259 if (!ctx
->Texture
.Unit
[i
]._ReallyEnabled
||
260 VB
->AttribPtr
[_TNL_ATTRIB_TEX0
+ i
]->size
== 4)
261 /* Never try to normalize homogenous tex coords! */
264 if (normalizeS
&& normalizeT
) {
265 /* take first texcoords as rough estimate of mean value */
266 GLfloat correctionS
= -floor(in
[0]+0.5);
267 GLfloat correctionT
= -floor(in
[1]+0.5);
268 for (j
= 0; j
< VB
->Count
; ++j
) {
269 out
[j
][0] = in
[0] + correctionS
;
270 out
[j
][1] = in
[1] + correctionT
;
271 in
= (GLfloat
*)((GLubyte
*)in
+ instride
);
273 } else if (normalizeS
) {
274 /* take first texcoords as rough estimate of mean value */
275 GLfloat correctionS
= -floor(in
[0]+0.5);
276 if (reallyEnabled
& TEXTURE_2D_BIT
) {
277 for (j
= 0; j
< VB
->Count
; ++j
) {
278 out
[j
][0] = in
[0] + correctionS
;
280 in
= (GLfloat
*)((GLubyte
*)in
+ instride
);
283 for (j
= 0; j
< VB
->Count
; ++j
) {
284 out
[j
][0] = in
[0] + correctionS
;
285 in
= (GLfloat
*)((GLubyte
*)in
+ instride
);
288 } else if (normalizeT
) {
289 /* take first texcoords as rough estimate of mean value */
290 GLfloat correctionT
= -floor(in
[1]+0.5);
291 for (j
= 0; j
< VB
->Count
; ++j
) {
293 out
[j
][1] = in
[1] + correctionT
;
294 in
= (GLfloat
*)((GLubyte
*)in
+ instride
);
298 if (normalizeS
|| normalizeT
)
299 VB
->AttribPtr
[_TNL_ATTRIB_TEX0
+ i
] = &store
->texcoord
[i
];
306 /* Called the first time stage->run() is invoked.
308 static GLboolean
alloc_texnorm_data( GLcontext
*ctx
,
309 struct tnl_pipeline_stage
*stage
)
311 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
312 struct texnorm_stage_data
*store
;
315 stage
->privatePtr
= CALLOC(sizeof(*store
));
316 store
= TEXNORM_STAGE_DATA(stage
);
320 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++)
321 _mesa_vector4f_alloc( &store
->texcoord
[i
], 0, VB
->Size
, 32 );
326 static void validate_texnorm( GLcontext
*ctx
,
327 struct tnl_pipeline_stage
*stage
)
329 struct texnorm_stage_data
*store
= TEXNORM_STAGE_DATA(stage
);
332 if (((ctx
->Texture
.Unit
[0]._ReallyEnabled
& (TEXTURE_1D_BIT
|TEXTURE_2D_BIT
)) &&
333 (ctx
->Texture
.Unit
[0]._Current
->WrapS
== GL_REPEAT
)) ||
334 ((ctx
->Texture
.Unit
[0]._ReallyEnabled
& TEXTURE_2D_BIT
) &&
335 (ctx
->Texture
.Unit
[0]._Current
->WrapT
== GL_REPEAT
)))
336 flags
|= VERT_BIT_TEX0
;
338 if (((ctx
->Texture
.Unit
[1]._ReallyEnabled
& (TEXTURE_1D_BIT
|TEXTURE_2D_BIT
)) &&
339 (ctx
->Texture
.Unit
[1]._Current
->WrapS
== GL_REPEAT
)) ||
340 ((ctx
->Texture
.Unit
[1]._ReallyEnabled
& TEXTURE_2D_BIT
) &&
341 (ctx
->Texture
.Unit
[1]._Current
->WrapT
== GL_REPEAT
)))
342 flags
|= VERT_BIT_TEX1
;
344 store
->active
= (flags
!= 0);
347 static void free_texnorm_data( struct tnl_pipeline_stage
*stage
)
349 struct texnorm_stage_data
*store
= TEXNORM_STAGE_DATA(stage
);
353 for (i
= 0 ; i
< MAX_TEXTURE_UNITS
; i
++)
354 if (store
->texcoord
[i
].data
)
355 _mesa_vector4f_free( &store
->texcoord
[i
] );
357 stage
->privatePtr
= 0;
361 struct tnl_pipeline_stage _savage_texnorm_stage
=
363 "savage texture coordinate normalization stage", /* name */
364 NULL
, /* private data */
365 alloc_texnorm_data
, /* run -- initially set to init */
366 free_texnorm_data
, /* destructor */