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 "math/m_xform.h"
38 #include "tnl/t_context.h"
40 #include "savagecontext.h"
41 #include "savagestate.h"
42 #include "savageioctl.h"
45 * Standard render tab for Savage4 and smooth shading on Savage3D
49 #define HAVE_LINE_STRIPS 0
50 #define HAVE_TRIANGLES 1
51 #define HAVE_TRI_STRIPS 1
52 #define HAVE_TRI_STRIP_1 0
53 #define HAVE_TRI_FANS 1
54 #define HAVE_POLYGONS 0
56 #define HAVE_QUAD_STRIPS 0
60 #define LOCAL_VARS savageContextPtr imesa = SAVAGE_CONTEXT(ctx)
61 #define INIT( prim ) do { \
62 if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
63 savageFlushVertices(imesa); \
65 case GL_TRIANGLES: imesa->HwPrim = SAVAGE_PRIM_TRILIST; break; \
66 case GL_TRIANGLE_STRIP: imesa->HwPrim = SAVAGE_PRIM_TRISTRIP; break; \
67 case GL_TRIANGLE_FAN: imesa->HwPrim = SAVAGE_PRIM_TRIFAN; break; \
70 #define FLUSH() savageFlushElts(imesa), savageFlushVertices(imesa)
72 #define GET_CURRENT_VB_MAX_VERTS() \
73 ((imesa->bufferSize/4 - imesa->vtxBuf->used) / imesa->HwVertexSize)
74 #define GET_SUBSEQUENT_VB_MAX_VERTS() \
75 (imesa->bufferSize/4 / imesa->HwVertexSize)
77 #define ALLOC_VERTS( nr ) \
78 savageAllocVtxBuf( imesa, (nr) * imesa->HwVertexSize )
79 #define EMIT_VERTS( ctx, j, nr, buf ) \
80 _tnl_emit_vertices_to_buffer(ctx, j, (j)+(nr), buf )
82 #define ELTS_VARS( buf ) GLushort *dest = buf, firstElt = imesa->firstElt
83 #define ELT_INIT( prim ) INIT(prim)
85 /* (size - used - 1 qword for drawing command) * 4 elts per qword */
86 #define GET_CURRENT_VB_MAX_ELTS() \
87 ((imesa->cmdBuf.size - (imesa->cmdBuf.write - imesa->cmdBuf.base) - 1)*4)
88 /* (size - space for initial state - 1 qword for drawing command) * 4 elts
89 * imesa is not defined in validate_render :( */
90 #define GET_SUBSEQUENT_VB_MAX_ELTS() \
91 ((SAVAGE_CONTEXT(ctx)->cmdBuf.size - \
92 (SAVAGE_CONTEXT(ctx)->cmdBuf.start - \
93 SAVAGE_CONTEXT(ctx)->cmdBuf.base) - 1)*4)
95 #define ALLOC_ELTS(nr) savageAllocElts(imesa, nr)
96 #define EMIT_ELT(offset, x) do { \
97 (dest)[offset] = (GLushort) ((x)+firstElt); \
99 #define EMIT_TWO_ELTS(offset, x, y) do { \
100 *(GLuint *)(dest + offset) = (((y)+firstElt) << 16) | \
104 #define INCR_ELTS( nr ) dest += nr
106 #define RELEASE_ELT_VERTS() \
107 savageReleaseIndexedVerts(imesa)
109 #define EMIT_INDEXED_VERTS( ctx, start, count ) do { \
110 GLuint *buf = savageAllocIndexedVerts(imesa, count-start); \
111 EMIT_VERTS(ctx, start, count-start, buf); \
114 #define TAG(x) savage_##x
115 #include "tnl_dd/t_dd_dmatmp.h"
118 * On Savage3D triangle fans and strips are broken with flat
119 * shading. With triangles it wants the color for flat shading in the
120 * first vertex! So we make another template instance which uses
121 * triangles only (with reordered vertices: SAVAGE_PRIM_TRILIST_201).
122 * The reordering is done by the DRM.
124 #undef HAVE_TRI_STRIPS
126 #define HAVE_TRI_STRIPS 0
127 #define HAVE_TRI_FANS 0
130 #define INIT( prim ) do { \
131 if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
132 savageFlushVertices(imesa); \
133 imesa->HwPrim = SAVAGE_PRIM_TRILIST_201; \
137 #define TAG(x) savage_flat_##x##_s3d
138 #include "tnl_dd/t_dd_dmatmp.h"
141 /**********************************************************************/
142 /* Render pipeline stage */
143 /**********************************************************************/
145 static GLboolean savage_run_render( struct gl_context *ctx,
146 struct tnl_pipeline_stage *stage )
148 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
149 TNLcontext *tnl = TNL_CONTEXT(ctx);
150 struct vertex_buffer *VB = &tnl->vb;
151 tnl_render_func *tab, *tab_elts;
155 if (savageHaveIndexedVerts(imesa))
156 savageReleaseIndexedVerts(imesa);
158 if (imesa->savageScreen->chipset < S3_SAVAGE4 &&
159 (ctx->_TriangleCaps & DD_FLATSHADE)) {
160 tab = savage_flat_render_tab_verts_s3d;
161 tab_elts = savage_flat_render_tab_elts_s3d;
162 valid = savage_flat_validate_render_s3d( ctx, VB );
164 tab = savage_render_tab_verts;
165 tab_elts = savage_render_tab_elts;
166 valid = savage_validate_render( ctx, VB );
169 /* Don't handle clipping or vertex manipulations.
171 if (imesa->RenderIndex != 0 || !valid) {
175 tnl->Driver.Render.Start( ctx );
176 /* Check RenderIndex again. The ptexHack is detected late in RenderStart.
177 * Also check for ptex fallbacks detected late.
179 if (imesa->RenderIndex != 0 || imesa->Fallback != 0) {
183 /* setup for hardware culling */
184 imesa->raster_primitive = GL_TRIANGLES;
185 imesa->new_state |= SAVAGE_NEW_CULL;
187 /* update and emit state */
188 savageDDUpdateHwState(ctx);
189 savageEmitChangedState(imesa);
193 if (!savageHaveIndexedVerts(imesa)) {
194 if (VB->Count > GET_SUBSEQUENT_VB_MAX_VERTS())
196 EMIT_INDEXED_VERTS(ctx, 0, VB->Count);
200 for (i = 0 ; i < VB->PrimitiveCount ; i++)
202 GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
203 GLuint start = VB->Primitive[i].start;
204 GLuint length = VB->Primitive[i].count;
207 tab[prim & PRIM_MODE_MASK]( ctx, start, start+length, prim);
210 tnl->Driver.Render.Finish( ctx );
212 return GL_FALSE; /* finished the pipe */
215 struct tnl_pipeline_stage _savage_render_stage =
222 savage_run_render /* run */
226 /**********************************************************************/
227 /* Pipeline stage for texture coordinate normalization */
228 /**********************************************************************/
229 struct texnorm_stage_data {
231 GLvector4f texcoord[MAX_TEXTURE_UNITS];
234 #define TEXNORM_STAGE_DATA(stage) ((struct texnorm_stage_data *)stage->privatePtr)
237 static GLboolean run_texnorm_stage( struct gl_context *ctx,
238 struct tnl_pipeline_stage *stage )
240 struct texnorm_stage_data *store = TEXNORM_STAGE_DATA(stage);
241 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
242 TNLcontext *tnl = TNL_CONTEXT(ctx);
243 struct vertex_buffer *VB = &tnl->vb;
246 if (imesa->Fallback || !store->active)
249 for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
250 const GLbitfield reallyEnabled = ctx->Texture.Unit[i]._ReallyEnabled;
252 const struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current;
253 const GLboolean normalizeS = (texObj->Sampler.WrapS == GL_REPEAT);
254 const GLboolean normalizeT = (reallyEnabled & TEXTURE_2D_BIT) &&
255 (texObj->Sampler.WrapT == GL_REPEAT);
256 const GLfloat *in = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]->data;
257 const GLint instride = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]->stride;
258 GLfloat (*out)[4] = store->texcoord[i].data;
261 if (!ctx->Texture.Unit[i]._ReallyEnabled ||
262 VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]->size == 4)
263 /* Never try to normalize homogenous tex coords! */
266 if (normalizeS && normalizeT) {
267 /* take first texcoords as rough estimate of mean value */
268 GLfloat correctionS = -floor(in[0]+0.5);
269 GLfloat correctionT = -floor(in[1]+0.5);
270 for (j = 0; j < VB->Count; ++j) {
271 out[j][0] = in[0] + correctionS;
272 out[j][1] = in[1] + correctionT;
273 in = (GLfloat *)((GLubyte *)in + instride);
275 } else if (normalizeS) {
276 /* take first texcoords as rough estimate of mean value */
277 GLfloat correctionS = -floor(in[0]+0.5);
278 if (reallyEnabled & TEXTURE_2D_BIT) {
279 for (j = 0; j < VB->Count; ++j) {
280 out[j][0] = in[0] + correctionS;
282 in = (GLfloat *)((GLubyte *)in + instride);
285 for (j = 0; j < VB->Count; ++j) {
286 out[j][0] = in[0] + correctionS;
287 in = (GLfloat *)((GLubyte *)in + instride);
290 } else if (normalizeT) {
291 /* take first texcoords as rough estimate of mean value */
292 GLfloat correctionT = -floor(in[1]+0.5);
293 for (j = 0; j < VB->Count; ++j) {
295 out[j][1] = in[1] + correctionT;
296 in = (GLfloat *)((GLubyte *)in + instride);
300 if (normalizeS || normalizeT)
301 VB->AttribPtr[_TNL_ATTRIB_TEX0 + i] = &store->texcoord[i];
308 /* Called the first time stage->run() is invoked.
310 static GLboolean alloc_texnorm_data( struct gl_context *ctx,
311 struct tnl_pipeline_stage *stage )
313 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
314 struct texnorm_stage_data *store;
317 stage->privatePtr = CALLOC(sizeof(*store));
318 store = TEXNORM_STAGE_DATA(stage);
322 for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
323 _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 );
328 static void validate_texnorm( struct gl_context *ctx,
329 struct tnl_pipeline_stage *stage )
331 struct texnorm_stage_data *store = TEXNORM_STAGE_DATA(stage);
334 if (((ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) &&
335 (ctx->Texture.Unit[0]._Current->Sampler.WrapS == GL_REPEAT)) ||
336 ((ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_2D_BIT) &&
337 (ctx->Texture.Unit[0]._Current->Sampler.WrapT == GL_REPEAT)))
338 flags |= VERT_BIT_TEX0;
340 if (((ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) &&
341 (ctx->Texture.Unit[1]._Current->Sampler.WrapS == GL_REPEAT)) ||
342 ((ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_2D_BIT) &&
343 (ctx->Texture.Unit[1]._Current->Sampler.WrapT == GL_REPEAT)))
344 flags |= VERT_BIT_TEX1;
346 store->active = (flags != 0);
349 static void free_texnorm_data( struct tnl_pipeline_stage *stage )
351 struct texnorm_stage_data *store = TEXNORM_STAGE_DATA(stage);
355 for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
356 if (store->texcoord[i].data)
357 _mesa_vector4f_free( &store->texcoord[i] );
359 stage->privatePtr = 0;
363 struct tnl_pipeline_stage _savage_texnorm_stage =
365 "savage texture coordinate normalization stage", /* name */
366 NULL, /* private data */
367 alloc_texnorm_data, /* run -- initially set to init */
368 free_texnorm_data, /* destructor */