Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / tdfx / tdfx_vb.c
1 /*
2  * GLX Hardware Device Driver for Intel i810
3  * Copyright (C) 1999 Keith Whitwell
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, sublicense,
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 shall be included
13  * in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, 
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 
21  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  *
23  *
24  */
25  
26 #include "main/glheader.h"
27 #include "main/mtypes.h"
28 #include "main/imports.h"
29 #include "main/macros.h"
30 #include "main/colormac.h"
31
32 #include "tdfx_context.h"
33 #include "tdfx_vb.h"
34 #include "tdfx_render.h"
35
36 static void copy_pv( struct gl_context *ctx, GLuint edst, GLuint esrc )
37 {
38    tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
39    tdfxVertex *dst = fxMesa->verts + edst;
40    tdfxVertex *src = fxMesa->verts + esrc;
41    *(GLuint *)&dst->color = *(GLuint *)&src->color;
42 }
43
44 static struct {
45    void                (*emit)( struct gl_context *, GLuint, GLuint, void * );
46    tnl_interp_func              interp;
47    tnl_copy_pv_func             copy_pv;
48    GLboolean           (*check_tex_sizes)( struct gl_context *ctx );
49    GLuint               vertex_format;
50 } setup_tab[TDFX_MAX_SETUP];
51
52
53
54
55 #define GET_COLOR(ptr, idx) ((ptr)->data[idx])
56
57
58 static void interp_extras( struct gl_context *ctx,
59                            GLfloat t,
60                            GLuint dst, GLuint out, GLuint in,
61                            GLboolean force_boundary )
62 {
63    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
64
65    /*fprintf(stderr, "%s\n", __FUNCTION__);*/
66
67    if (VB->BackfaceColorPtr) {
68       INTERP_4F( t,
69                  GET_COLOR(VB->BackfaceColorPtr, dst),
70                  GET_COLOR(VB->BackfaceColorPtr, out),
71                  GET_COLOR(VB->BackfaceColorPtr, in) );
72    }
73
74    if (VB->EdgeFlag) {
75       VB->EdgeFlag[dst] = VB->EdgeFlag[out] || force_boundary;
76    }
77
78    setup_tab[TDFX_CONTEXT(ctx)->SetupIndex].interp(ctx, t, dst, out, in,
79                                                    force_boundary);
80 }
81
82 static void copy_pv_extras( struct gl_context *ctx, GLuint dst, GLuint src )
83 {
84    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
85
86    if (VB->BackfaceColorPtr) {
87       COPY_4FV( GET_COLOR(VB->BackfaceColorPtr, dst),
88                 GET_COLOR(VB->BackfaceColorPtr, src) );
89    }
90
91    setup_tab[TDFX_CONTEXT(ctx)->SetupIndex].copy_pv(ctx, dst, src);
92 }
93
94
95
96 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT)
97 #define TAG(x) x##_wg
98 #include "tdfx_vbtmp.h"
99
100 /* Special for tdfx: fog requires w
101  */
102 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT)
103 #define TAG(x) x##_wg_fog
104 #include "tdfx_vbtmp.h"
105
106 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT)
107 #define TAG(x) x##_wgt0
108 #include "tdfx_vbtmp.h"
109
110 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT)
111 #define TAG(x) x##_wgt0t1
112 #include "tdfx_vbtmp.h"
113
114 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_PTEX_BIT)
115 #define TAG(x) x##_wgpt0
116 #include "tdfx_vbtmp.h"
117
118 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT|\
119              TDFX_PTEX_BIT)
120 #define TAG(x) x##_wgpt0t1
121 #include "tdfx_vbtmp.h"
122
123 #define IND (TDFX_RGBA_BIT)
124 #define TAG(x) x##_g
125 #include "tdfx_vbtmp.h"
126
127 #define IND (TDFX_TEX0_BIT)
128 #define TAG(x) x##_t0
129 #include "tdfx_vbtmp.h"
130
131 #define IND (TDFX_TEX0_BIT|TDFX_TEX1_BIT)
132 #define TAG(x) x##_t0t1
133 #include "tdfx_vbtmp.h"
134
135 #define IND (TDFX_RGBA_BIT|TDFX_TEX0_BIT)
136 #define TAG(x) x##_gt0
137 #include "tdfx_vbtmp.h"
138
139 #define IND (TDFX_RGBA_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT)
140 #define TAG(x) x##_gt0t1
141 #include "tdfx_vbtmp.h"
142
143
144 /* fogc { */
145 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_FOGC_BIT)
146 #define TAG(x) x##_wgf
147 #include "tdfx_vbtmp.h"
148
149 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_FOGC_BIT)
150 #define TAG(x) x##_wgt0f
151 #include "tdfx_vbtmp.h"
152
153 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT|TDFX_FOGC_BIT)
154 #define TAG(x) x##_wgt0t1f
155 #include "tdfx_vbtmp.h"
156
157 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_PTEX_BIT|TDFX_FOGC_BIT)
158 #define TAG(x) x##_wgpt0f
159 #include "tdfx_vbtmp.h"
160
161 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT|\
162              TDFX_PTEX_BIT|TDFX_FOGC_BIT)
163 #define TAG(x) x##_wgpt0t1f
164 #include "tdfx_vbtmp.h"
165 /* fogc } */
166
167
168 static void init_setup_tab( void )
169 {
170    init_wg();
171    init_wg_fog();
172    init_wgt0();
173    init_wgt0t1();
174    init_wgpt0();
175    init_wgpt0t1();
176
177    init_g();
178    init_t0();
179    init_t0t1();
180    init_gt0();
181    init_gt0t1();
182
183    /* fogcoord */
184    init_wgf();
185    init_wgt0f();
186    init_wgt0t1f();
187    init_wgpt0f();
188    init_wgpt0t1f();
189 }
190
191
192 void tdfxPrintSetupFlags(char *msg, GLuint flags )
193 {
194    fprintf(stderr, "%s(%x): %s%s%s%s%s%s\n",
195            msg,
196            (int)flags,
197            (flags & TDFX_XYZ_BIT)     ? " xyz," : "", 
198            (flags & TDFX_W_BIT)     ? " w," : "", 
199            (flags & TDFX_RGBA_BIT)     ? " rgba," : "",
200            (flags & TDFX_TEX0_BIT)     ? " tex-0," : "",
201            (flags & TDFX_TEX1_BIT)     ? " tex-1," : "",
202            (flags & TDFX_FOGC_BIT)     ? " fogc," : "");
203 }
204
205
206
207 void tdfxCheckTexSizes( struct gl_context *ctx )
208 {
209    TNLcontext *tnl = TNL_CONTEXT(ctx);
210    tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
211
212    if (!setup_tab[fxMesa->SetupIndex].check_tex_sizes(ctx)) {
213       GLuint ind = fxMesa->SetupIndex |= (TDFX_PTEX_BIT|TDFX_RGBA_BIT);
214
215       /* Tdfx handles projective textures nicely; just have to change
216        * up to the new vertex format.
217        */
218       if (setup_tab[ind].vertex_format != fxMesa->vertexFormat) {
219          FLUSH_BATCH(fxMesa);
220          fxMesa->dirty |= TDFX_UPLOAD_VERTEX_LAYOUT;      
221          fxMesa->vertexFormat = setup_tab[ind].vertex_format;
222
223          /* This is required as we have just changed the vertex
224           * format, so the interp and copy routines must also change.
225           * In the unfilled and twosided cases we are using the
226           * swrast_setup ones anyway, so leave them in place.
227           */
228          if (!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
229             tnl->Driver.Render.Interp = setup_tab[fxMesa->SetupIndex].interp;
230             tnl->Driver.Render.CopyPV = setup_tab[fxMesa->SetupIndex].copy_pv;
231          }
232       }
233    }
234 }
235
236
237 void tdfxBuildVertices( struct gl_context *ctx, GLuint start, GLuint end,
238                         GLuint newinputs )
239 {
240    tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
241    tdfxVertex *v = fxMesa->verts + start;
242
243    newinputs |= fxMesa->SetupNewInputs;
244    fxMesa->SetupNewInputs = 0;
245
246    if (!newinputs)
247       return;
248
249    if (newinputs & VERT_BIT_POS) {
250       setup_tab[fxMesa->SetupIndex].emit( ctx, start, end, v );
251    } else {
252       GLuint ind = 0;
253
254       if (newinputs & VERT_BIT_COLOR0)
255          ind |= TDFX_RGBA_BIT;
256
257       if (newinputs & VERT_BIT_FOG)
258          ind |= TDFX_FOGC_BIT;
259       
260       if (newinputs & VERT_BIT_TEX0)
261          ind |= TDFX_TEX0_BIT;
262
263       if (newinputs & VERT_BIT_TEX1)
264          ind |= TDFX_TEX0_BIT|TDFX_TEX1_BIT;
265
266       if (fxMesa->SetupIndex & TDFX_PTEX_BIT)
267          ind = ~0;
268
269       ind &= fxMesa->SetupIndex;
270
271       if (ind) {
272          setup_tab[ind].emit( ctx, start, end, v );
273       }
274    }
275 }
276
277
278 void tdfxChooseVertexState( struct gl_context *ctx )
279 {
280    TNLcontext *tnl = TNL_CONTEXT(ctx);
281    tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
282    GLuint ind = TDFX_XYZ_BIT|TDFX_RGBA_BIT;
283
284    fxMesa->tmu_source[0] = 0;
285    fxMesa->tmu_source[1] = 1;
286
287    if (ctx->Texture._EnabledUnits & 0x2) {
288       if (ctx->Texture._EnabledUnits & 0x1) {
289          ind |= TDFX_TEX1_BIT;
290       }
291       ind |= TDFX_W_BIT|TDFX_TEX0_BIT;
292       fxMesa->tmu_source[0] = 1;
293       fxMesa->tmu_source[1] = 0;
294    } else if (ctx->Texture._EnabledUnits & 0x1) {
295       /* unit 0 enabled */
296       ind |= TDFX_W_BIT|TDFX_TEX0_BIT;
297    } else if (fxMesa->Fog.Mode != GR_FOG_DISABLE) {
298       ind |= TDFX_W_BIT;
299    }
300
301    if (fxMesa->Fog.Mode == GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT) {
302       ind |= TDFX_FOGC_BIT;
303    }
304
305    fxMesa->SetupIndex = ind;
306
307    if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) {
308       tnl->Driver.Render.Interp = interp_extras;
309       tnl->Driver.Render.CopyPV = copy_pv_extras;
310    } else {
311       tnl->Driver.Render.Interp = setup_tab[ind].interp;
312       tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv;
313    }
314
315    if (setup_tab[ind].vertex_format != fxMesa->vertexFormat) {
316       FLUSH_BATCH(fxMesa);
317       fxMesa->dirty |= TDFX_UPLOAD_VERTEX_LAYOUT;      
318       fxMesa->vertexFormat = setup_tab[ind].vertex_format;
319    }
320 }
321
322
323
324 void tdfxInitVB( struct gl_context *ctx )
325 {
326    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
327    GLuint size = TNL_CONTEXT(ctx)->vb.Size;
328    static int firsttime = 1;
329    if (firsttime) {
330       init_setup_tab();
331       firsttime = 0;
332    }
333
334    fxMesa->verts = _mesa_align_malloc(size * sizeof(tdfxVertex), 32);
335    fxMesa->vertexFormat = TDFX_LAYOUT_TINY;
336    fxMesa->SetupIndex = TDFX_XYZ_BIT|TDFX_RGBA_BIT;
337 }
338
339
340 void tdfxFreeVB( struct gl_context *ctx )
341 {
342    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
343    if (fxMesa->verts) {
344       _mesa_align_free(fxMesa->verts);
345       fxMesa->verts = 0;
346    }
347 }