Import vtx-0-2-branch
[mesa.git] / src / mesa / drivers / dri / r200 / r200_maos_arrays.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_maos_arrays.c,v 1.3 2003/02/23 23:59:01 dawes Exp $ */
2 /*
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
8
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 **************************************************************************/
30
31 /*
32 * Authors:
33 * Keith Whitwell <keith@tungstengraphics.com>
34 */
35
36 #include "glheader.h"
37 #include "mtypes.h"
38 #include "colormac.h"
39 #include "imports.h"
40 #include "macros.h"
41
42 #include "swrast_setup/swrast_setup.h"
43 #include "math/m_translate.h"
44 #include "tnl/tnl.h"
45 #include "tnl/t_context.h"
46
47 #include "r200_context.h"
48 #include "r200_ioctl.h"
49 #include "r200_state.h"
50 #include "r200_swtcl.h"
51 #include "r200_maos.h"
52
53 /* Usage:
54 * - from r200_tcl_render
55 * - call r200EmitArrays to ensure uptodate arrays in dma
56 * - emit primitives (new type?) which reference the data
57 * -- need to use elts for lineloop, quads, quadstrip/flat
58 * -- other primitives are all well-formed (need tristrip-1,fake-poly)
59 *
60 */
61 static void emit_ubyte_rgba3( GLcontext *ctx,
62 struct r200_dma_region *rvb,
63 char *data,
64 int stride,
65 int count )
66 {
67 int i;
68 r200_color_t *out = (r200_color_t *)(rvb->start + rvb->address);
69
70 if (R200_DEBUG & DEBUG_VERTS)
71 fprintf(stderr, "%s count %d stride %d out %p\n",
72 __FUNCTION__, count, stride, out);
73
74 for (i = 0; i < count; i++) {
75 out->red = *data;
76 out->green = *(data+1);
77 out->blue = *(data+2);
78 out->alpha = 0xFF;
79 out++;
80 data += stride;
81 }
82 }
83
84
85 #if defined(USE_X86_ASM)
86 #define COPY_DWORDS( dst, src, nr ) \
87 do { \
88 int __tmp; \
89 __asm__ __volatile__( "rep ; movsl" \
90 : "=%c" (__tmp), "=D" (dst), "=S" (__tmp) \
91 : "0" (nr), \
92 "D" ((long)dst), \
93 "S" ((long)src) ); \
94 } while (0)
95 #else
96 #define COPY_DWORDS( dst, src, nr ) \
97 do { \
98 int j; \
99 for ( j = 0 ; j < nr ; j++ ) \
100 dst[j] = ((int *)src)[j]; \
101 dst += nr; \
102 } while (0)
103 #endif
104
105
106
107 static void emit_ubyte_rgba4( GLcontext *ctx,
108 struct r200_dma_region *rvb,
109 char *data,
110 int stride,
111 int count )
112 {
113 int i;
114 int *out = (int *)(rvb->address + rvb->start);
115
116 if (R200_DEBUG & DEBUG_VERTS)
117 fprintf(stderr, "%s count %d stride %d\n",
118 __FUNCTION__, count, stride);
119
120 if (stride == 4) {
121 for (i = 0; i < count; i++)
122 ((int *)out)[i] = LE32_TO_CPU(((int *)data)[i]);
123 } else {
124 for (i = 0; i < count; i++) {
125 *(int *)out++ = LE32_TO_CPU(*(int *)data);
126 data += stride;
127 }
128 }
129 }
130
131
132 static void emit_ubyte_rgba( GLcontext *ctx,
133 struct r200_dma_region *rvb,
134 char *data,
135 int size,
136 int stride,
137 int count )
138 {
139 r200ContextPtr rmesa = R200_CONTEXT(ctx);
140
141 if (R200_DEBUG & DEBUG_VERTS)
142 fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size);
143
144 assert (!rvb->buf);
145
146 if (stride == 0) {
147 r200AllocDmaRegion( rmesa, rvb, 4, 4 );
148 count = 1;
149 rvb->aos_start = GET_START(rvb);
150 rvb->aos_stride = 0;
151 rvb->aos_size = 1;
152 }
153 else {
154 r200AllocDmaRegion( rmesa, rvb, 4 * count, 4 ); /* alignment? */
155 rvb->aos_start = GET_START(rvb);
156 rvb->aos_stride = 1;
157 rvb->aos_size = 1;
158 }
159
160 /* Emit the data
161 */
162 switch (size) {
163 case 3:
164 emit_ubyte_rgba3( ctx, rvb, data, stride, count );
165 break;
166 case 4:
167 emit_ubyte_rgba4( ctx, rvb, data, stride, count );
168 break;
169 default:
170 assert(0);
171 exit(1);
172 break;
173 }
174 }
175
176
177 static void emit_vec4( GLcontext *ctx,
178 struct r200_dma_region *rvb,
179 char *data,
180 int stride,
181 int count )
182 {
183 int i;
184 int *out = (int *)(rvb->address + rvb->start);
185
186 if (R200_DEBUG & DEBUG_VERTS)
187 fprintf(stderr, "%s count %d stride %d\n",
188 __FUNCTION__, count, stride);
189
190 if (stride == 4)
191 COPY_DWORDS( out, data, count );
192 else
193 for (i = 0; i < count; i++) {
194 out[0] = *(int *)data;
195 out++;
196 data += stride;
197 }
198 }
199
200
201 static void emit_vec8( GLcontext *ctx,
202 struct r200_dma_region *rvb,
203 char *data,
204 int stride,
205 int count )
206 {
207 int i;
208 int *out = (int *)(rvb->address + rvb->start);
209
210 if (R200_DEBUG & DEBUG_VERTS)
211 fprintf(stderr, "%s count %d stride %d\n",
212 __FUNCTION__, count, stride);
213
214 if (stride == 8)
215 COPY_DWORDS( out, data, count*2 );
216 else
217 for (i = 0; i < count; i++) {
218 out[0] = *(int *)data;
219 out[1] = *(int *)(data+4);
220 out += 2;
221 data += stride;
222 }
223 }
224
225 static void emit_vec12( GLcontext *ctx,
226 struct r200_dma_region *rvb,
227 char *data,
228 int stride,
229 int count )
230 {
231 int i;
232 int *out = (int *)(rvb->address + rvb->start);
233
234 if (R200_DEBUG & DEBUG_VERTS)
235 fprintf(stderr, "%s count %d stride %d out %p data %p\n",
236 __FUNCTION__, count, stride, out, data);
237
238 if (stride == 12)
239 COPY_DWORDS( out, data, count*3 );
240 else
241 for (i = 0; i < count; i++) {
242 out[0] = *(int *)data;
243 out[1] = *(int *)(data+4);
244 out[2] = *(int *)(data+8);
245 out += 3;
246 data += stride;
247 }
248 }
249
250 static void emit_vec16( GLcontext *ctx,
251 struct r200_dma_region *rvb,
252 char *data,
253 int stride,
254 int count )
255 {
256 int i;
257 int *out = (int *)(rvb->address + rvb->start);
258
259 if (R200_DEBUG & DEBUG_VERTS)
260 fprintf(stderr, "%s count %d stride %d\n",
261 __FUNCTION__, count, stride);
262
263 if (stride == 16)
264 COPY_DWORDS( out, data, count*4 );
265 else
266 for (i = 0; i < count; i++) {
267 out[0] = *(int *)data;
268 out[1] = *(int *)(data+4);
269 out[2] = *(int *)(data+8);
270 out[3] = *(int *)(data+12);
271 out += 4;
272 data += stride;
273 }
274 }
275
276
277 static void emit_vector( GLcontext *ctx,
278 struct r200_dma_region *rvb,
279 char *data,
280 int size,
281 int stride,
282 int count )
283 {
284 r200ContextPtr rmesa = R200_CONTEXT(ctx);
285
286 if (R200_DEBUG & DEBUG_VERTS)
287 fprintf(stderr, "%s count %d size %d stride %d\n",
288 __FUNCTION__, count, size, stride);
289
290 assert (!rvb->buf);
291
292 if (stride == 0) {
293 r200AllocDmaRegion( rmesa, rvb, size * 4, 4 );
294 count = 1;
295 rvb->aos_start = GET_START(rvb);
296 rvb->aos_stride = 0;
297 rvb->aos_size = size;
298 }
299 else {
300 r200AllocDmaRegion( rmesa, rvb, size * count * 4, 4 ); /* alignment? */
301 rvb->aos_start = GET_START(rvb);
302 rvb->aos_stride = size;
303 rvb->aos_size = size;
304 }
305
306 /* Emit the data
307 */
308 switch (size) {
309 case 1:
310 emit_vec4( ctx, rvb, data, stride, count );
311 break;
312 case 2:
313 emit_vec8( ctx, rvb, data, stride, count );
314 break;
315 case 3:
316 emit_vec12( ctx, rvb, data, stride, count );
317 break;
318 case 4:
319 emit_vec16( ctx, rvb, data, stride, count );
320 break;
321 default:
322 assert(0);
323 exit(1);
324 break;
325 }
326
327 }
328
329
330
331 /* Emit any changed arrays to new GART memory, re-emit a packet to
332 * update the arrays.
333 */
334 void r200EmitArrays( GLcontext *ctx, GLuint inputs )
335 {
336 r200ContextPtr rmesa = R200_CONTEXT( ctx );
337 struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
338 struct r200_dma_region **component = rmesa->tcl.aos_components;
339 GLuint nr = 0;
340 GLuint vfmt0 = 0, vfmt1 = 0;
341 GLuint count = VB->Count;
342
343 if (1) {
344 if (!rmesa->tcl.obj.buf)
345 emit_vector( ctx,
346 &rmesa->tcl.obj,
347 (char *)VB->ObjPtr->data,
348 VB->ObjPtr->size,
349 VB->ObjPtr->stride,
350 count);
351
352 switch( VB->ObjPtr->size ) {
353 case 4: vfmt0 |= R200_VTX_W0;
354 case 3: vfmt0 |= R200_VTX_Z0;
355 case 2:
356 default:
357 break;
358 }
359 component[nr++] = &rmesa->tcl.obj;
360 }
361
362
363 if (inputs & VERT_BIT_NORMAL) {
364 if (!rmesa->tcl.norm.buf)
365 emit_vector( ctx,
366 &(rmesa->tcl.norm),
367 (char *)VB->NormalPtr->data,
368 3,
369 VB->NormalPtr->stride,
370 count);
371
372 vfmt0 |= R200_VTX_N0;
373 component[nr++] = &rmesa->tcl.norm;
374 }
375
376 if (inputs & VERT_BIT_COLOR0) {
377 int emitsize;
378
379 if (VB->ColorPtr[0]->size == 4 &&
380 (VB->ColorPtr[0]->stride != 0 ||
381 VB->ColorPtr[0]->data[0][3] != 1.0)) {
382 vfmt0 |= R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT;
383 emitsize = 4;
384 }
385 else {
386 vfmt0 |= R200_VTX_FP_RGB << R200_VTX_COLOR_0_SHIFT;
387 emitsize = 3;
388 }
389
390 if (!rmesa->tcl.rgba.buf)
391 emit_vector( ctx,
392 &(rmesa->tcl.rgba),
393 (char *)VB->ColorPtr[0]->data,
394 emitsize,
395 VB->ColorPtr[0]->stride,
396 count);
397
398 component[nr++] = &rmesa->tcl.rgba;
399 }
400
401
402 if (inputs & VERT_BIT_COLOR1) {
403 if (!rmesa->tcl.spec.buf) {
404 emit_vector( ctx,
405 &rmesa->tcl.spec,
406 (char *)VB->SecondaryColorPtr[0]->data,
407 3,
408 VB->SecondaryColorPtr[0]->stride,
409 count);
410 }
411
412 /* How does this work?
413 */
414 vfmt0 |= R200_VTX_FP_RGB << R200_VTX_COLOR_1_SHIFT;
415 component[nr++] = &rmesa->tcl.spec;
416 }
417
418 /* vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] & */
419 /* ~(R200_TCL_VTX_Q0|R200_TCL_VTX_Q1)); */
420
421 if (inputs & VERT_BIT_TEX0) {
422 if (!rmesa->tcl.tex[0].buf)
423 emit_vector( ctx,
424 &(rmesa->tcl.tex[0]),
425 (char *)VB->TexCoordPtr[0]->data,
426 VB->TexCoordPtr[0]->size,
427 VB->TexCoordPtr[0]->stride,
428 count );
429
430 vfmt1 |= VB->TexCoordPtr[0]->size << R200_VTX_TEX0_COMP_CNT_SHIFT;
431 component[nr++] = &rmesa->tcl.tex[0];
432 }
433
434 if (inputs & VERT_BIT_TEX1) {
435 if (!rmesa->tcl.tex[1].buf)
436 emit_vector( ctx,
437 &(rmesa->tcl.tex[1]),
438 (char *)VB->TexCoordPtr[1]->data,
439 VB->TexCoordPtr[1]->size,
440 VB->TexCoordPtr[1]->stride,
441 count );
442
443 vfmt1 |= VB->TexCoordPtr[1]->size << R200_VTX_TEX1_COMP_CNT_SHIFT;
444 component[nr++] = &rmesa->tcl.tex[1];
445 }
446
447 if (vfmt0 != rmesa->hw.vtx.cmd[VTX_VTXFMT_0] ||
448 vfmt1 != rmesa->hw.vtx.cmd[VTX_VTXFMT_1]) {
449 R200_STATECHANGE( rmesa, vtx );
450 rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = vfmt0;
451 rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = vfmt1;
452 }
453
454 rmesa->tcl.nr_aos_components = nr;
455 rmesa->tcl.vertex_format = vfmt0;
456 }
457
458
459 void r200ReleaseArrays( GLcontext *ctx, GLuint newinputs )
460 {
461 r200ContextPtr rmesa = R200_CONTEXT( ctx );
462
463 /* if (R200_DEBUG & DEBUG_VERTS) */
464 /* _tnl_print_vert_flags( __FUNCTION__, newinputs ); */
465
466 if (newinputs & VERT_BIT_POS)
467 r200ReleaseDmaRegion( rmesa, &rmesa->tcl.obj, __FUNCTION__ );
468
469 if (newinputs & VERT_BIT_NORMAL)
470 r200ReleaseDmaRegion( rmesa, &rmesa->tcl.norm, __FUNCTION__ );
471
472 if (newinputs & VERT_BIT_COLOR0)
473 r200ReleaseDmaRegion( rmesa, &rmesa->tcl.rgba, __FUNCTION__ );
474
475 if (newinputs & VERT_BIT_COLOR1)
476 r200ReleaseDmaRegion( rmesa, &rmesa->tcl.spec, __FUNCTION__ );
477
478 if (newinputs & VERT_BIT_TEX0)
479 r200ReleaseDmaRegion( rmesa, &rmesa->tcl.tex[0], __FUNCTION__ );
480
481 if (newinputs & VERT_BIT_TEX1)
482 r200ReleaseDmaRegion( rmesa, &rmesa->tcl.tex[1], __FUNCTION__ );
483 }