Merge branch 'mesa_7_7_branch'
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_maos_arrays.c
1 /**************************************************************************
2
3 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
4 Tungsten Graphics Inc., Cedar Park, Texas.
5
6 All Rights Reserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 **************************************************************************/
29
30 /*
31 * Authors:
32 * Keith Whitwell <keith@tungstengraphics.com>
33 */
34
35 #include "main/glheader.h"
36 #include "main/imports.h"
37 #include "main/mtypes.h"
38 #include "main/macros.h"
39
40 #include "swrast_setup/swrast_setup.h"
41 #include "math/m_translate.h"
42 #include "tnl/tnl.h"
43
44 #include "radeon_context.h"
45 #include "radeon_ioctl.h"
46 #include "radeon_state.h"
47 #include "radeon_swtcl.h"
48 #include "radeon_maos.h"
49 #include "radeon_tcl.h"
50
51 static void emit_vecfog(GLcontext *ctx, struct radeon_aos *aos,
52 GLvoid *data, int stride, int count)
53 {
54 int i;
55 uint32_t *out;
56 int size = 1;
57 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
58
59 if (RADEON_DEBUG & RADEON_VERTS)
60 fprintf(stderr, "%s count %d stride %d\n",
61 __FUNCTION__, count, stride);
62
63 if (stride == 0) {
64 radeonAllocDmaRegion( rmesa, &aos->bo, &aos->offset, size * 4, 32 );
65 count = 1;
66 aos->stride = 0;
67 }
68 else {
69 radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, size * 4, 32);
70 aos->stride = size;
71 }
72
73 aos->components = size;
74 aos->count = count;
75
76
77 /* Emit the data
78 */
79 radeon_bo_map(aos->bo, 1);
80 out = (uint32_t*)((char*)aos->bo->ptr + aos->offset);
81 for (i = 0; i < count; i++) {
82 out[0] = radeonComputeFogBlendFactor( ctx, *(GLfloat *)data );
83 out++;
84 data += stride;
85 }
86 radeon_bo_unmap(aos->bo);
87 }
88
89 static void emit_s0_vec(uint32_t *out, GLvoid *data, int stride, int count)
90 {
91 int i;
92 if (RADEON_DEBUG & RADEON_VERTS)
93 fprintf(stderr, "%s count %d stride %d\n",
94 __FUNCTION__, count, stride);
95
96 for (i = 0; i < count; i++) {
97 out[0] = *(int *)data;
98 out[1] = 0;
99 out += 2;
100 data += stride;
101 }
102 }
103
104 static void emit_stq_vec(uint32_t *out, GLvoid *data, int stride, int count)
105 {
106 int i;
107
108 if (RADEON_DEBUG & RADEON_VERTS)
109 fprintf(stderr, "%s count %d stride %d\n",
110 __FUNCTION__, count, stride);
111
112 for (i = 0; i < count; i++) {
113 out[0] = *(int *)data;
114 out[1] = *(int *)(data+4);
115 out[2] = *(int *)(data+12);
116 out += 3;
117 data += stride;
118 }
119 }
120
121
122
123
124 static void emit_tex_vector(GLcontext *ctx, struct radeon_aos *aos,
125 GLvoid *data, int size, int stride, int count)
126 {
127 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
128 int emitsize;
129 uint32_t *out;
130
131 if (RADEON_DEBUG & RADEON_VERTS)
132 fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size);
133
134 switch (size) {
135 case 4: emitsize = 3; break;
136 case 3: emitsize = 3; break;
137 default: emitsize = 2; break;
138 }
139
140
141 if (stride == 0) {
142 radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, emitsize * 4, 32);
143 count = 1;
144 aos->stride = 0;
145 }
146 else {
147 radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, emitsize * count * 4, 32);
148 aos->stride = emitsize;
149 }
150
151 aos->components = emitsize;
152 aos->count = count;
153
154 /* Emit the data
155 */
156 radeon_bo_map(aos->bo, 1);
157 out = (uint32_t*)((char*)aos->bo->ptr + aos->offset);
158 switch (size) {
159 case 1:
160 emit_s0_vec( out, data, stride, count );
161 break;
162 case 2:
163 radeonEmitVec8( out, data, stride, count );
164 break;
165 case 3:
166 radeonEmitVec12( out, data, stride, count );
167 break;
168 case 4:
169 emit_stq_vec( out, data, stride, count );
170 break;
171 default:
172 assert(0);
173 exit(1);
174 break;
175 }
176 radeon_bo_unmap(aos->bo);
177 }
178
179
180
181
182 /* Emit any changed arrays to new GART memory, re-emit a packet to
183 * update the arrays.
184 */
185 void radeonEmitArrays( GLcontext *ctx, GLuint inputs )
186 {
187 r100ContextPtr rmesa = R100_CONTEXT( ctx );
188 struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
189 GLuint nr = 0;
190 GLuint vfmt = 0;
191 GLuint count = VB->Count;
192 GLuint vtx, unit;
193
194 #if 0
195 if (RADEON_DEBUG & RADEON_VERTS)
196 _tnl_print_vert_flags( __FUNCTION__, inputs );
197 #endif
198
199 if (1) {
200 if (!rmesa->tcl.obj.buf)
201 rcommon_emit_vector( ctx,
202 &(rmesa->tcl.aos[nr]),
203 (char *)VB->AttribPtr[_TNL_ATTRIB_POS]->data,
204 VB->AttribPtr[_TNL_ATTRIB_POS]->size,
205 VB->AttribPtr[_TNL_ATTRIB_POS]->stride,
206 count);
207
208 switch( VB->AttribPtr[_TNL_ATTRIB_POS]->size ) {
209 case 4: vfmt |= RADEON_CP_VC_FRMT_W0;
210 case 3: vfmt |= RADEON_CP_VC_FRMT_Z;
211 case 2: vfmt |= RADEON_CP_VC_FRMT_XY;
212 default:
213 break;
214 }
215 nr++;
216 }
217
218
219 if (inputs & VERT_BIT_NORMAL) {
220 if (!rmesa->tcl.norm.buf)
221 rcommon_emit_vector( ctx,
222 &(rmesa->tcl.aos[nr]),
223 (char *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data,
224 3,
225 VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride,
226 count);
227
228 vfmt |= RADEON_CP_VC_FRMT_N0;
229 nr++;
230 }
231
232 if (inputs & VERT_BIT_COLOR0) {
233 int emitsize;
234 if (VB->AttribPtr[_TNL_ATTRIB_COLOR0]->size == 4 &&
235 (VB->AttribPtr[_TNL_ATTRIB_COLOR0]->stride != 0 ||
236 VB->AttribPtr[_TNL_ATTRIB_COLOR0]->data[0][3] != 1.0)) {
237 vfmt |= RADEON_CP_VC_FRMT_FPCOLOR | RADEON_CP_VC_FRMT_FPALPHA;
238 emitsize = 4;
239 }
240
241 else {
242 vfmt |= RADEON_CP_VC_FRMT_FPCOLOR;
243 emitsize = 3;
244 }
245
246 if (!rmesa->tcl.rgba.buf)
247 rcommon_emit_vector( ctx,
248 &(rmesa->tcl.aos[nr]),
249 (char *)VB->AttribPtr[_TNL_ATTRIB_COLOR0]->data,
250 emitsize,
251 VB->AttribPtr[_TNL_ATTRIB_COLOR0]->stride,
252 count);
253
254 nr++;
255 }
256
257
258 if (inputs & VERT_BIT_COLOR1) {
259 if (!rmesa->tcl.spec.buf) {
260
261 rcommon_emit_vector( ctx,
262 &(rmesa->tcl.aos[nr]),
263 (char *)VB->AttribPtr[_TNL_ATTRIB_COLOR1]->data,
264 3,
265 VB->AttribPtr[_TNL_ATTRIB_COLOR1]->stride,
266 count);
267 }
268
269 vfmt |= RADEON_CP_VC_FRMT_FPSPEC;
270 nr++;
271 }
272
273 /* FIXME: not sure if this is correct. May need to stitch this together with
274 secondary color. It seems odd that for primary color color and alpha values
275 are emitted together but for secondary color not. */
276 if (inputs & VERT_BIT_FOG) {
277 if (!rmesa->tcl.fog.buf)
278 emit_vecfog( ctx,
279 &(rmesa->tcl.aos[nr]),
280 (char *)VB->AttribPtr[_TNL_ATTRIB_FOG]->data,
281 VB->AttribPtr[_TNL_ATTRIB_FOG]->stride,
282 count);
283
284 vfmt |= RADEON_CP_VC_FRMT_FPFOG;
285 nr++;
286 }
287
288
289 vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &
290 ~(RADEON_TCL_VTX_Q0|RADEON_TCL_VTX_Q1|RADEON_TCL_VTX_Q2));
291
292 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
293 if (inputs & VERT_BIT_TEX(unit)) {
294 if (!rmesa->tcl.tex[unit].buf)
295 emit_tex_vector( ctx,
296 &(rmesa->tcl.aos[nr]),
297 (char *)VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->data,
298 VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size,
299 VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->stride,
300 count );
301 nr++;
302
303 vfmt |= RADEON_ST_BIT(unit);
304 /* assume we need the 3rd coord if texgen is active for r/q OR at least
305 3 coords are submitted. This may not be 100% correct */
306 if (VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size >= 3) {
307 vtx |= RADEON_Q_BIT(unit);
308 vfmt |= RADEON_Q_BIT(unit);
309 }
310 if ( (ctx->Texture.Unit[unit].TexGenEnabled & (R_BIT | Q_BIT)) )
311 vtx |= RADEON_Q_BIT(unit);
312 else if ((VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size >= 3) &&
313 ((ctx->Texture.Unit[unit]._ReallyEnabled & (TEXTURE_CUBE_BIT)) == 0)) {
314 GLuint swaptexmatcol = (VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size - 3);
315 if (((rmesa->NeedTexMatrix >> unit) & 1) &&
316 (swaptexmatcol != ((rmesa->TexMatColSwap >> unit) & 1)))
317 radeonUploadTexMatrix( rmesa, unit, swaptexmatcol ) ;
318 }
319 }
320 }
321
322 if (vtx != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT]) {
323 RADEON_STATECHANGE( rmesa, tcl );
324 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = vtx;
325 }
326
327 rmesa->tcl.nr_aos_components = nr;
328 rmesa->tcl.vertex_format = vfmt;
329 }
330