Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / savage / savagerender.c
1 /*
2  * Copyright 2005  Felix Kuehling
3  * All rights reserved.
4  *
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:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
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.
23  */
24
25 /*
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.
29  */
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"
35
36 #include "math/m_xform.h"
37
38 #include "tnl/t_context.h"
39
40 #include "savagecontext.h"
41 #include "savagestate.h"
42 #include "savageioctl.h"
43
44 /*
45  * Standard render tab for Savage4 and smooth shading on Savage3D
46  */
47 #define HAVE_POINTS      0
48 #define HAVE_LINES       0
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
55 #define HAVE_QUADS       0
56 #define HAVE_QUAD_STRIPS 0
57
58 #define HAVE_ELTS        1
59
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);                                          \
64    switch (prim) {                                                      \
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;   \
68    }                                                                    \
69 } while (0)
70 #define FLUSH()         savageFlushElts(imesa), savageFlushVertices(imesa)
71
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)
76
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 )
81
82 #define ELTS_VARS( buf ) GLushort *dest = buf, firstElt = imesa->firstElt
83 #define ELT_INIT( prim ) INIT(prim)
84
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)
94
95 #define ALLOC_ELTS(nr) savageAllocElts(imesa, nr)
96 #define EMIT_ELT(offset, x) do {                                        \
97    (dest)[offset] = (GLushort) ((x)+firstElt);                          \
98 } while (0)
99 #define EMIT_TWO_ELTS(offset, x, y) do {                                \
100    *(GLuint *)(dest + offset) = (((y)+firstElt) << 16) |                \
101                                 ((x)+firstElt);                         \
102 } while (0)
103
104 #define INCR_ELTS( nr ) dest += nr
105 #define ELTPTR dest
106 #define RELEASE_ELT_VERTS() \
107    savageReleaseIndexedVerts(imesa)
108
109 #define EMIT_INDEXED_VERTS( ctx, start, count ) do {                    \
110    GLuint *buf = savageAllocIndexedVerts(imesa, count-start);           \
111    EMIT_VERTS(ctx, start, count-start, buf);                            \
112 } while (0)
113
114 #define TAG(x) savage_##x
115 #include "tnl_dd/t_dd_dmatmp.h"
116
117 /*
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.
123  */
124 #undef  HAVE_TRI_STRIPS
125 #undef  HAVE_TRI_FANS
126 #define HAVE_TRI_STRIPS 0
127 #define HAVE_TRI_FANS   0
128
129 #undef  INIT
130 #define INIT( prim ) do {                                               \
131    if (0) fprintf(stderr, "%s\n", __FUNCTION__);                        \
132    savageFlushVertices(imesa);                                          \
133    imesa->HwPrim = SAVAGE_PRIM_TRILIST_201;                             \
134 } while(0)
135
136 #undef  TAG
137 #define TAG(x) savage_flat_##x##_s3d
138 #include "tnl_dd/t_dd_dmatmp.h"
139
140
141 /**********************************************************************/
142 /*                          Render pipeline stage                     */
143 /**********************************************************************/
144
145 static GLboolean savage_run_render( struct gl_context *ctx,
146                                     struct tnl_pipeline_stage *stage )
147 {
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;
152    GLboolean valid;
153    GLuint i;
154
155    if (savageHaveIndexedVerts(imesa))
156       savageReleaseIndexedVerts(imesa);
157
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 );
163    } else {
164       tab = savage_render_tab_verts;
165       tab_elts = savage_render_tab_elts;
166       valid = savage_validate_render( ctx, VB );
167    }
168
169    /* Don't handle clipping or vertex manipulations.
170     */
171    if (imesa->RenderIndex != 0 || !valid) {
172       return GL_TRUE;
173    }
174    
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.
178     */
179    if (imesa->RenderIndex != 0 || imesa->Fallback != 0) {
180       return GL_TRUE;
181    }
182
183    /* setup for hardware culling */
184    imesa->raster_primitive = GL_TRIANGLES;
185    imesa->new_state |= SAVAGE_NEW_CULL;
186
187    /* update and emit state */
188    savageDDUpdateHwState(ctx);
189    savageEmitChangedState(imesa);
190
191    if (VB->Elts) {
192       tab = tab_elts;
193       if (!savageHaveIndexedVerts(imesa)) {
194          if (VB->Count > GET_SUBSEQUENT_VB_MAX_VERTS())
195             return GL_TRUE;
196          EMIT_INDEXED_VERTS(ctx, 0, VB->Count);
197       }
198    }
199
200    for (i = 0 ; i < VB->PrimitiveCount ; i++)
201    {
202       GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
203       GLuint start = VB->Primitive[i].start;
204       GLuint length = VB->Primitive[i].count;
205
206       if (length)
207          tab[prim & PRIM_MODE_MASK]( ctx, start, start+length, prim);
208    }
209
210    tnl->Driver.Render.Finish( ctx );
211
212    return GL_FALSE;             /* finished the pipe */
213 }
214
215 struct tnl_pipeline_stage _savage_render_stage = 
216
217    "savage render",
218    NULL,
219    NULL,
220    NULL,
221    NULL,
222    savage_run_render            /* run */
223 };
224
225
226 /**********************************************************************/
227 /*         Pipeline stage for texture coordinate normalization        */
228 /**********************************************************************/
229 struct texnorm_stage_data {
230    GLboolean active;
231    GLvector4f texcoord[MAX_TEXTURE_UNITS];
232 };
233
234 #define TEXNORM_STAGE_DATA(stage) ((struct texnorm_stage_data *)stage->privatePtr)
235
236
237 static GLboolean run_texnorm_stage( struct gl_context *ctx,
238                                     struct tnl_pipeline_stage *stage )
239 {
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;
244    GLuint i;
245
246    if (imesa->Fallback || !store->active)
247       return GL_TRUE;
248
249    for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
250       const GLbitfield reallyEnabled = ctx->Texture.Unit[i]._ReallyEnabled;
251       if (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;
259          GLint j;
260
261          if (!ctx->Texture.Unit[i]._ReallyEnabled ||
262              VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]->size == 4)
263             /* Never try to normalize homogenous tex coords! */
264             continue;
265
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);
274             }
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;
281                   out[j][1] = in[1];
282                   in = (GLfloat *)((GLubyte *)in + instride);
283                }
284             } else {
285                for (j = 0; j < VB->Count; ++j) {
286                   out[j][0] = in[0] + correctionS;
287                   in = (GLfloat *)((GLubyte *)in + instride);
288                }
289             }
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) {
294                out[j][0] = in[0];
295                out[j][1] = in[1] + correctionT;
296                in = (GLfloat *)((GLubyte *)in + instride);
297             }
298          }
299
300          if (normalizeS || normalizeT)
301             VB->AttribPtr[_TNL_ATTRIB_TEX0 + i] = &store->texcoord[i];
302       }
303    }
304
305    return GL_TRUE;
306 }
307
308 /* Called the first time stage->run() is invoked.
309  */
310 static GLboolean alloc_texnorm_data( struct gl_context *ctx,
311                                      struct tnl_pipeline_stage *stage )
312 {
313    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
314    struct texnorm_stage_data *store;
315    GLuint i;
316
317    stage->privatePtr = CALLOC(sizeof(*store));
318    store = TEXNORM_STAGE_DATA(stage);
319    if (!store)
320       return GL_FALSE;
321
322    for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
323       _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 );
324    
325    return GL_TRUE;
326 }
327
328 static void validate_texnorm( struct gl_context *ctx,
329                               struct tnl_pipeline_stage *stage )
330 {
331    struct texnorm_stage_data *store = TEXNORM_STAGE_DATA(stage);
332    GLuint flags = 0;
333
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;
339
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;
345
346    store->active = (flags != 0);
347 }
348
349 static void free_texnorm_data( struct tnl_pipeline_stage *stage )
350 {
351    struct texnorm_stage_data *store = TEXNORM_STAGE_DATA(stage);
352    GLuint i;
353
354    if (store) {
355       for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
356          if (store->texcoord[i].data)
357             _mesa_vector4f_free( &store->texcoord[i] );
358       FREE( store );
359       stage->privatePtr = 0;
360    }
361 }
362
363 struct tnl_pipeline_stage _savage_texnorm_stage =
364 {
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 */
369    validate_texnorm,
370    run_texnorm_stage
371 };