add SPARC ffb DRI driver
[mesa.git] / src / mesa / drivers / dri / ffb / ffb_vb.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_vb.c,v 1.4 2002/02/22 21:32:59 dawes Exp $
2 *
3 * GLX Hardware Device Driver for Sun Creator/Creator3D
4 * Copyright (C) 2000, 2001 David S. Miller
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * DAVID MILLER, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 *
25 * David S. Miller <davem@redhat.com>
26 */
27
28 #include "ffb_xmesa.h"
29 #include "ffb_context.h"
30 #include "ffb_vb.h"
31 #include "mmath.h"
32 #include "imports.h"
33 #include "tnl/t_context.h"
34 #include "swrast_setup/swrast_setup.h"
35 #include "math/m_translate.h"
36
37 #undef VB_DEBUG
38
39 static void ffb_copy_pv_oneside(GLcontext *ctx, GLuint edst, GLuint esrc)
40 {
41 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
42 ffb_vertex *dst = &fmesa->verts[edst];
43 ffb_vertex *src = &fmesa->verts[esrc];
44
45 #ifdef VB_DEBUG
46 fprintf(stderr, "ffb_copy_pv_oneside: edst(%d) esrc(%d)\n", edst, esrc);
47 #endif
48 dst->color[0].alpha = src->color[0].alpha;
49 dst->color[0].red = src->color[0].red;
50 dst->color[0].green = src->color[0].green;
51 dst->color[0].blue = src->color[0].blue;
52 }
53
54 static void ffb_copy_pv_twoside(GLcontext *ctx, GLuint edst, GLuint esrc)
55 {
56 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
57 ffb_vertex *dst = &fmesa->verts[edst];
58 ffb_vertex *src = &fmesa->verts[esrc];
59
60 #ifdef VB_DEBUG
61 fprintf(stderr, "ffb_copy_pv_twoside: edst(%d) esrc(%d)\n", edst, esrc);
62 #endif
63 dst->color[0].alpha = src->color[0].alpha;
64 dst->color[0].red = src->color[0].red;
65 dst->color[0].green = src->color[0].green;
66 dst->color[0].blue = src->color[0].blue;
67 dst->color[1].alpha = src->color[1].alpha;
68 dst->color[1].red = src->color[1].red;
69 dst->color[1].green = src->color[1].green;
70 dst->color[1].blue = src->color[1].blue;
71 }
72
73 #define FFB_VB_RGBA_BIT 0x01
74 #define FFB_VB_XYZ_BIT 0x02
75 #define FFB_VB_TWOSIDE_BIT 0x04
76 #define FFB_VB_MAX 0x08
77
78 typedef void (*emit_func)(GLcontext *, GLuint, GLuint);
79
80 static struct {
81 emit_func emit;
82 interp_func interp;
83 } setup_tab[FFB_VB_MAX];
84
85 static void do_import(struct vertex_buffer *VB,
86 struct gl_client_array *to,
87 struct gl_client_array *from)
88 {
89 GLuint count = VB->Count;
90
91 if (!to->Ptr) {
92 to->Ptr = ALIGN_MALLOC( VB->Size * 4 * sizeof(GLfloat), 32 );
93 to->Type = GL_FLOAT;
94 }
95
96 /* No need to transform the same value 3000 times. */
97 if (!from->StrideB) {
98 to->StrideB = 0;
99 count = 1;
100 } else
101 to->StrideB = 4 * sizeof(GLfloat);
102
103 _math_trans_4f((GLfloat (*)[4]) to->Ptr,
104 from->Ptr, from->StrideB,
105 from->Type, from->Size,
106 0, count);
107 }
108
109 static __inline__ void ffbImportColors(ffbContextPtr fmesa, GLcontext *ctx, int index)
110 {
111 struct gl_client_array *to = &fmesa->FloatColor;
112 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
113 do_import(VB, to, VB->ColorPtr[index]);
114 VB->ColorPtr[index] = to;
115 }
116
117 #define IND (FFB_VB_XYZ_BIT)
118 #define TAG(x) x##_w
119 #include "ffb_vbtmp.h"
120
121 #define IND (FFB_VB_RGBA_BIT)
122 #define TAG(x) x##_g
123 #include "ffb_vbtmp.h"
124
125 #define IND (FFB_VB_XYZ_BIT | FFB_VB_RGBA_BIT)
126 #define TAG(x) x##_wg
127 #include "ffb_vbtmp.h"
128
129 #define IND (FFB_VB_TWOSIDE_BIT)
130 #define TAG(x) x##_t
131 #include "ffb_vbtmp.h"
132
133 #define IND (FFB_VB_XYZ_BIT | FFB_VB_TWOSIDE_BIT)
134 #define TAG(x) x##_wt
135 #include "ffb_vbtmp.h"
136
137 #define IND (FFB_VB_RGBA_BIT | FFB_VB_TWOSIDE_BIT)
138 #define TAG(x) x##_gt
139 #include "ffb_vbtmp.h"
140
141 #define IND (FFB_VB_XYZ_BIT | FFB_VB_RGBA_BIT | FFB_VB_TWOSIDE_BIT)
142 #define TAG(x) x##_wgt
143 #include "ffb_vbtmp.h"
144
145 static void init_setup_tab( void )
146 {
147 init_w();
148 init_g();
149 init_wg();
150 init_t();
151 init_wt();
152 init_gt();
153 init_wgt();
154 }
155
156 #ifdef VB_DEBUG
157 static void ffbPrintSetupFlags(char *msg, GLuint flags)
158 {
159 fprintf(stderr, "%s(%x): %s%s%s\n",
160 msg,
161 (int)flags,
162 (flags & FFB_VB_XYZ_BIT) ? " xyz," : "",
163 (flags & FFB_VB_RGBA_BIT) ? " rgba," : "",
164 (flags & FFB_VB_TWOSIDE_BIT) ? " twoside," : "");
165 }
166 #endif
167
168 static void ffbDDBuildVertices(GLcontext *ctx, GLuint start, GLuint count,
169 GLuint newinputs)
170 {
171 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
172
173 newinputs |= fmesa->setupnewinputs;
174 fmesa->setupnewinputs = 0;
175
176 if (!newinputs)
177 return;
178
179 if (newinputs & VERT_BIT_CLIP) {
180 setup_tab[fmesa->setupindex].emit(ctx, start, count);
181 } else {
182 GLuint ind = 0;
183
184 if (newinputs & VERT_BIT_COLOR0)
185 ind |= (FFB_VB_RGBA_BIT | FFB_VB_TWOSIDE_BIT);
186
187 ind &= fmesa->setupindex;
188
189 if (ind)
190 setup_tab[ind].emit(ctx, start, count);
191 }
192 }
193
194 void ffbChooseVertexState( GLcontext *ctx )
195 {
196 TNLcontext *tnl = TNL_CONTEXT(ctx);
197 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
198 int ind = FFB_VB_XYZ_BIT | FFB_VB_RGBA_BIT;
199
200 if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE)
201 ind |= FFB_VB_TWOSIDE_BIT;
202
203 #ifdef VB_DEBUG
204 ffbPrintSetupFlags("ffb: full setup function", ind);
205 #endif
206
207 fmesa->setupindex = ind;
208
209 tnl->Driver.Render.BuildVertices = ffbDDBuildVertices;
210 tnl->Driver.Render.Interp = setup_tab[ind].interp;
211 if (ind & FFB_VB_TWOSIDE_BIT)
212 tnl->Driver.Render.CopyPV = ffb_copy_pv_twoside;
213 else
214 tnl->Driver.Render.CopyPV = ffb_copy_pv_oneside;
215 }
216
217 void ffbInitVB( GLcontext *ctx )
218 {
219 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
220 GLuint size = TNL_CONTEXT(ctx)->vb.Size;
221
222 fmesa->verts = (ffb_vertex *)ALIGN_MALLOC(size * sizeof(ffb_vertex), 32);
223
224 {
225 static int firsttime = 1;
226 if (firsttime) {
227 init_setup_tab();
228 firsttime = 0;
229 }
230 }
231 }
232
233
234 void ffbFreeVB( GLcontext *ctx )
235 {
236 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
237 if (fmesa->verts) {
238 ALIGN_FREE(fmesa->verts);
239 fmesa->verts = 0;
240 }
241 }