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