r200 driver, brought over by Jon Smirl
[mesa.git] / src / mesa / drivers / dri / r200 / r200_maos_arrays.c
1 /* $XFree86$ */
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 #include "tnl/t_imm_debug.h"
47
48 #include "r200_context.h"
49 #include "r200_ioctl.h"
50 #include "r200_state.h"
51 #include "r200_swtcl.h"
52 #include "r200_maos.h"
53
54 /* Usage:
55 * - from r200_tcl_render
56 * - call r200EmitArrays to ensure uptodate arrays in dma
57 * - emit primitives (new type?) which reference the data
58 * -- need to use elts for lineloop, quads, quadstrip/flat
59 * -- other primitives are all well-formed (need tristrip-1,fake-poly)
60 *
61 */
62 static void emit_ubyte_rgba3( GLcontext *ctx,
63 struct r200_dma_region *rvb,
64 char *data,
65 int stride,
66 int count )
67 {
68 int i;
69 r200_color_t *out = (r200_color_t *)(rvb->start + rvb->address);
70
71 if (R200_DEBUG & DEBUG_VERTS)
72 fprintf(stderr, "%s count %d stride %d out %p\n",
73 __FUNCTION__, count, stride, out);
74
75 for (i = 0; i < count; i++) {
76 out->red = *data;
77 out->green = *(data+1);
78 out->blue = *(data+2);
79 out->alpha = 0xFF;
80 out++;
81 data += stride;
82 }
83 }
84
85
86 #if defined(USE_X86_ASM)
87 #define COPY_DWORDS( dst, src, nr ) \
88 do { \
89 int __tmp; \
90 __asm__ __volatile__( "rep ; movsl" \
91 : "=%c" (__tmp), "=D" (dst), "=S" (__tmp) \
92 : "0" (nr), \
93 "D" ((long)dst), \
94 "S" ((long)src) ); \
95 } while (0)
96 #else
97 #define COPY_DWORDS( dst, src, nr ) \
98 do { \
99 int j; \
100 for ( j = 0 ; j < nr ; j++ ) \
101 dst[j] = ((int *)src)[j]; \
102 dst += nr; \
103 } while (0)
104 #endif
105
106
107
108 static void emit_ubyte_rgba4( GLcontext *ctx,
109 struct r200_dma_region *rvb,
110 char *data,
111 int stride,
112 int count )
113 {
114 int i;
115 int *out = (int *)(rvb->address + rvb->start);
116
117 if (R200_DEBUG & DEBUG_VERTS)
118 fprintf(stderr, "%s count %d stride %d\n",
119 __FUNCTION__, count, stride);
120
121 if (stride == 4) {
122 for (i = 0; i < count; i++)
123 ((int *)out)[i] = LE32_TO_CPU(((int *)data)[i]);
124 } else {
125 for (i = 0; i < count; i++) {
126 *(int *)out++ = LE32_TO_CPU(*(int *)data);
127 data += stride;
128 }
129 }
130 }
131
132
133 static void emit_ubyte_rgba( GLcontext *ctx,
134 struct r200_dma_region *rvb,
135 char *data,
136 int size,
137 int stride,
138 int count )
139 {
140 r200ContextPtr rmesa = R200_CONTEXT(ctx);
141
142 if (R200_DEBUG & DEBUG_VERTS)
143 fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size);
144
145 assert (!rvb->buf);
146
147 if (stride == 0) {
148 r200AllocDmaRegion( rmesa, rvb, 4, 4 );
149 count = 1;
150 rvb->aos_start = GET_START(rvb);
151 rvb->aos_stride = 0;
152 rvb->aos_size = 1;
153 }
154 else {
155 r200AllocDmaRegion( rmesa, rvb, 4 * count, 4 ); /* alignment? */
156 rvb->aos_start = GET_START(rvb);
157 rvb->aos_stride = 1;
158 rvb->aos_size = 1;
159 }
160
161 /* Emit the data
162 */
163 switch (size) {
164 case 3:
165 emit_ubyte_rgba3( ctx, rvb, data, stride, count );
166 break;
167 case 4:
168 emit_ubyte_rgba4( ctx, rvb, data, stride, count );
169 break;
170 default:
171 assert(0);
172 exit(1);
173 break;
174 }
175 }
176
177
178
179
180 static void emit_vec8( GLcontext *ctx,
181 struct r200_dma_region *rvb,
182 char *data,
183 int stride,
184 int count )
185 {
186 int i;
187 int *out = (int *)(rvb->address + rvb->start);
188
189 if (R200_DEBUG & DEBUG_VERTS)
190 fprintf(stderr, "%s count %d stride %d\n",
191 __FUNCTION__, count, stride);
192
193 if (stride == 8)
194 COPY_DWORDS( out, data, count*2 );
195 else
196 for (i = 0; i < count; i++) {
197 out[0] = *(int *)data;
198 out[1] = *(int *)(data+4);
199 out += 2;
200 data += stride;
201 }
202 }
203
204 static void emit_vec12( GLcontext *ctx,
205 struct r200_dma_region *rvb,
206 char *data,
207 int stride,
208 int count )
209 {
210 int i;
211 int *out = (int *)(rvb->address + rvb->start);
212
213 if (R200_DEBUG & DEBUG_VERTS)
214 fprintf(stderr, "%s count %d stride %d out %p data %p\n",
215 __FUNCTION__, count, stride, out, data);
216
217 if (stride == 12)
218 COPY_DWORDS( out, data, count*3 );
219 else
220 for (i = 0; i < count; i++) {
221 out[0] = *(int *)data;
222 out[1] = *(int *)(data+4);
223 out[2] = *(int *)(data+8);
224 out += 3;
225 data += stride;
226 }
227 }
228
229 static void emit_vec16( GLcontext *ctx,
230 struct r200_dma_region *rvb,
231 char *data,
232 int stride,
233 int count )
234 {
235 int i;
236 int *out = (int *)(rvb->address + rvb->start);
237
238 if (R200_DEBUG & DEBUG_VERTS)
239 fprintf(stderr, "%s count %d stride %d\n",
240 __FUNCTION__, count, stride);
241
242 if (stride == 16)
243 COPY_DWORDS( out, data, count*4 );
244 else
245 for (i = 0; i < count; i++) {
246 out[0] = *(int *)data;
247 out[1] = *(int *)(data+4);
248 out[2] = *(int *)(data+8);
249 out[3] = *(int *)(data+12);
250 out += 4;
251 data += stride;
252 }
253 }
254
255
256 static void emit_vector( GLcontext *ctx,
257 struct r200_dma_region *rvb,
258 char *data,
259 int size,
260 int stride,
261 int count )
262 {
263 r200ContextPtr rmesa = R200_CONTEXT(ctx);
264
265 if (R200_DEBUG & DEBUG_VERTS)
266 fprintf(stderr, "%s count %d size %d stride %d\n",
267 __FUNCTION__, count, size, stride);
268
269 assert (!rvb->buf);
270
271 if (stride == 0) {
272 r200AllocDmaRegion( rmesa, rvb, size * 4, 4 );
273 count = 1;
274 rvb->aos_start = GET_START(rvb);
275 rvb->aos_stride = 0;
276 rvb->aos_size = size;
277 }
278 else {
279 r200AllocDmaRegion( rmesa, rvb, size * count * 4, 4 ); /* alignment? */
280 rvb->aos_start = GET_START(rvb);
281 rvb->aos_stride = size;
282 rvb->aos_size = size;
283 }
284
285 /* Emit the data
286 */
287 switch (size) {
288 case 2:
289 emit_vec8( ctx, rvb, data, stride, count );
290 break;
291 case 3:
292 emit_vec12( ctx, rvb, data, stride, count );
293 break;
294 case 4:
295 emit_vec16( ctx, rvb, data, stride, count );
296 break;
297 default:
298 assert(0);
299 exit(1);
300 break;
301 }
302
303 }
304
305
306
307 /* Emit any changed arrays to new agp memory, re-emit a packet to
308 * update the arrays.
309 */
310 void r200EmitArrays( GLcontext *ctx, GLuint inputs )
311 {
312 r200ContextPtr rmesa = R200_CONTEXT( ctx );
313 struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
314 struct r200_dma_region **component = rmesa->tcl.aos_components;
315 GLuint nr = 0;
316 GLuint vfmt0 = 0, vfmt1 = 0;
317 GLuint count = VB->Count;
318
319 if (R200_DEBUG & DEBUG_VERTS)
320 _tnl_print_vert_flags( __FUNCTION__, inputs );
321
322 if (1) {
323 if (!rmesa->tcl.obj.buf)
324 emit_vector( ctx,
325 &rmesa->tcl.obj,
326 (char *)VB->ObjPtr->data,
327 VB->ObjPtr->size,
328 VB->ObjPtr->stride,
329 count);
330
331 switch( VB->ObjPtr->size ) {
332 case 4: vfmt0 |= R200_VTX_W0;
333 case 3: vfmt0 |= R200_VTX_Z0;
334 case 2:
335 default:
336 break;
337 }
338 component[nr++] = &rmesa->tcl.obj;
339 }
340
341
342 if (inputs & VERT_BIT_NORMAL) {
343 if (!rmesa->tcl.norm.buf)
344 emit_vector( ctx,
345 &(rmesa->tcl.norm),
346 (char *)VB->NormalPtr->data,
347 3,
348 VB->NormalPtr->stride,
349 count);
350
351 vfmt0 |= R200_VTX_N0;
352 component[nr++] = &rmesa->tcl.norm;
353 }
354
355 if (inputs & VERT_BIT_COLOR0) {
356 if (VB->ColorPtr[0]->Type == GL_UNSIGNED_BYTE) {
357 if (!rmesa->tcl.rgba.buf)
358 emit_ubyte_rgba( ctx,
359 &rmesa->tcl.rgba,
360 (char *)VB->ColorPtr[0]->Ptr,
361 VB->ColorPtr[0]->Size,
362 VB->ColorPtr[0]->StrideB,
363 count);
364
365 vfmt0 |= R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT;
366 }
367 else {
368 int emitsize;
369
370 if (VB->ColorPtr[0]->Size == 4 &&
371 (VB->ColorPtr[0]->StrideB != 0 ||
372 ((GLfloat *)VB->ColorPtr[0]->Ptr)[3] != 1.0)) {
373 vfmt0 |= R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT;
374 emitsize = 4;
375 }
376 else {
377 vfmt0 |= R200_VTX_FP_RGB << R200_VTX_COLOR_0_SHIFT;
378 emitsize = 3;
379 }
380
381 if (!rmesa->tcl.rgba.buf)
382 emit_vector( ctx,
383 &(rmesa->tcl.rgba),
384 (char *)VB->ColorPtr[0]->Ptr,
385 emitsize,
386 VB->ColorPtr[0]->StrideB,
387 count);
388 }
389
390 component[nr++] = &rmesa->tcl.rgba;
391 }
392
393
394 if (inputs & VERT_BIT_COLOR1) {
395 if (!rmesa->tcl.spec.buf) {
396 if (VB->SecondaryColorPtr[0]->Type != GL_UNSIGNED_BYTE)
397 r200_import_float_spec_colors( ctx );
398
399 emit_ubyte_rgba( ctx,
400 &rmesa->tcl.spec,
401 (char *)VB->SecondaryColorPtr[0]->Ptr,
402 3,
403 VB->SecondaryColorPtr[0]->StrideB,
404 count);
405 }
406
407 /* How does this work?
408 */
409 vfmt0 |= R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT;
410 component[nr++] = &rmesa->tcl.spec;
411 }
412
413 /* vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] & */
414 /* ~(R200_TCL_VTX_Q0|R200_TCL_VTX_Q1)); */
415
416 if (inputs & VERT_BIT_TEX0) {
417 if (!rmesa->tcl.tex[0].buf)
418 emit_vector( ctx,
419 &(rmesa->tcl.tex[0]),
420 (char *)VB->TexCoordPtr[0]->data,
421 VB->TexCoordPtr[0]->size,
422 VB->TexCoordPtr[0]->stride,
423 count );
424
425 vfmt1 |= VB->TexCoordPtr[0]->size << R200_VTX_TEX0_COMP_CNT_SHIFT;
426 component[nr++] = &rmesa->tcl.tex[0];
427 }
428
429 if (inputs & VERT_BIT_TEX1) {
430 if (!rmesa->tcl.tex[1].buf)
431 emit_vector( ctx,
432 &(rmesa->tcl.tex[1]),
433 (char *)VB->TexCoordPtr[1]->data,
434 VB->TexCoordPtr[1]->size,
435 VB->TexCoordPtr[1]->stride,
436 count );
437
438 vfmt1 |= VB->TexCoordPtr[1]->size << R200_VTX_TEX1_COMP_CNT_SHIFT;
439 component[nr++] = &rmesa->tcl.tex[1];
440 }
441
442 if (vfmt0 != rmesa->hw.vtx.cmd[VTX_VTXFMT_0] ||
443 vfmt1 != rmesa->hw.vtx.cmd[VTX_VTXFMT_1]) {
444 R200_STATECHANGE( rmesa, vtx );
445 rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = vfmt0;
446 rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = vfmt1;
447 }
448
449 rmesa->tcl.nr_aos_components = nr;
450 rmesa->tcl.vertex_format = vfmt0;
451 }
452
453
454 void r200ReleaseArrays( GLcontext *ctx, GLuint newinputs )
455 {
456 r200ContextPtr rmesa = R200_CONTEXT( ctx );
457
458 if (R200_DEBUG & DEBUG_VERTS)
459 _tnl_print_vert_flags( __FUNCTION__, newinputs );
460
461 if (newinputs & VERT_BIT_POS)
462 r200ReleaseDmaRegion( rmesa, &rmesa->tcl.obj, __FUNCTION__ );
463
464 if (newinputs & VERT_BIT_NORMAL)
465 r200ReleaseDmaRegion( rmesa, &rmesa->tcl.norm, __FUNCTION__ );
466
467 if (newinputs & VERT_BIT_COLOR0)
468 r200ReleaseDmaRegion( rmesa, &rmesa->tcl.rgba, __FUNCTION__ );
469
470 if (newinputs & VERT_BIT_COLOR1)
471 r200ReleaseDmaRegion( rmesa, &rmesa->tcl.spec, __FUNCTION__ );
472
473 if (newinputs & VERT_BIT_TEX0)
474 r200ReleaseDmaRegion( rmesa, &rmesa->tcl.tex[0], __FUNCTION__ );
475
476 if (newinputs & VERT_BIT_TEX1)
477 r200ReleaseDmaRegion( rmesa, &rmesa->tcl.tex[1], __FUNCTION__ );
478 }