Initial multitexturing support. Old behaviour can be re-enabled by changing ifdefs...
[mesa.git] / src / mesa / drivers / dri / r300 / r300_maos.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/r300/r300_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 "r300_context.h"
48 #include "radeon_ioctl.h"
49 #include "r300_state.h"
50 #include "r300_maos.h"
51 #include "r300_ioctl.h"
52
53 #define DEBUG_ALL DEBUG_VERTS
54
55
56 #if defined(USE_X86_ASM)
57 #define COPY_DWORDS( dst, src, nr ) \
58 do { \
59 int __tmp; \
60 __asm__ __volatile__( "rep ; movsl" \
61 : "=%c" (__tmp), "=D" (dst), "=S" (__tmp) \
62 : "0" (nr), \
63 "D" ((long)dst), \
64 "S" ((long)src) ); \
65 } while (0)
66 #else
67 #define COPY_DWORDS( dst, src, nr ) \
68 do { \
69 int j; \
70 for ( j = 0 ; j < nr ; j++ ) \
71 dst[j] = ((int *)src)[j]; \
72 dst += nr; \
73 } while (0)
74 #endif
75
76 static void emit_vec4(GLcontext * ctx,
77 struct r300_dma_region *rvb,
78 char *data, int stride, int count)
79 {
80 int i;
81 int *out = (int *)(rvb->address + rvb->start);
82
83 if (RADEON_DEBUG & DEBUG_VERTS)
84 fprintf(stderr, "%s count %d stride %d\n",
85 __FUNCTION__, count, stride);
86
87 if (stride == 4)
88 COPY_DWORDS(out, data, count);
89 else
90 for (i = 0; i < count; i++) {
91 out[0] = *(int *)data;
92 out++;
93 data += stride;
94 }
95 }
96
97 static void emit_vec8(GLcontext * ctx,
98 struct r300_dma_region *rvb,
99 char *data, int stride, int count)
100 {
101 int i;
102 int *out = (int *)(rvb->address + rvb->start);
103
104 if (RADEON_DEBUG & DEBUG_VERTS)
105 fprintf(stderr, "%s count %d stride %d\n",
106 __FUNCTION__, count, stride);
107
108 if (stride == 8)
109 COPY_DWORDS(out, data, count * 2);
110 else
111 for (i = 0; i < count; i++) {
112 out[0] = *(int *)data;
113 out[1] = *(int *)(data + 4);
114 out += 2;
115 data += stride;
116 }
117 }
118
119 static void emit_vec12(GLcontext * ctx,
120 struct r300_dma_region *rvb,
121 char *data, int stride, int count)
122 {
123 int i;
124 int *out = (int *)(rvb->address + rvb->start);
125
126 if (RADEON_DEBUG & DEBUG_VERTS)
127 fprintf(stderr, "%s count %d stride %d out %p data %p\n",
128 __FUNCTION__, count, stride, (void *)out, (void *)data);
129
130 if (stride == 12)
131 COPY_DWORDS(out, data, count * 3);
132 else
133 for (i = 0; i < count; i++) {
134 out[0] = *(int *)data;
135 out[1] = *(int *)(data + 4);
136 out[2] = *(int *)(data + 8);
137 out += 3;
138 data += stride;
139 }
140 }
141
142 static void emit_vec16(GLcontext * ctx,
143 struct r300_dma_region *rvb,
144 char *data, int stride, int count)
145 {
146 int i;
147 int *out = (int *)(rvb->address + rvb->start);
148
149 if (RADEON_DEBUG & DEBUG_VERTS)
150 fprintf(stderr, "%s count %d stride %d\n",
151 __FUNCTION__, count, stride);
152
153 if (stride == 16)
154 COPY_DWORDS(out, data, count * 4);
155 else
156 for (i = 0; i < count; i++) {
157 out[0] = *(int *)data;
158 out[1] = *(int *)(data + 4);
159 out[2] = *(int *)(data + 8);
160 out[3] = *(int *)(data + 12);
161 out += 4;
162 data += stride;
163 }
164 }
165
166 static void emit_vector(GLcontext * ctx,
167 struct r300_dma_region *rvb,
168 char *data, int size, int stride, int count)
169 {
170 r300ContextPtr rmesa = R300_CONTEXT(ctx);
171
172 if (RADEON_DEBUG & DEBUG_VERTS)
173 fprintf(stderr, "%s count %d size %d stride %d\n",
174 __FUNCTION__, count, size, stride);
175
176 assert(!rvb->buf);
177
178 if (stride == 0) {
179 r300AllocDmaRegion(rmesa, rvb, size * 4, 4);
180 count = 1;
181 rvb->aos_offset = GET_START(rvb);
182 rvb->aos_stride = 0;
183 rvb->aos_size = size;
184 } else {
185 r300AllocDmaRegion(rmesa, rvb, size * count * 4, 4); /* alignment? */
186 rvb->aos_offset = GET_START(rvb);
187 rvb->aos_stride = size;
188 rvb->aos_size = size;
189 }
190
191 /* Emit the data
192 */
193 switch (size) {
194 case 1:
195 emit_vec4(ctx, rvb, data, stride, count);
196 break;
197 case 2:
198 emit_vec8(ctx, rvb, data, stride, count);
199 break;
200 case 3:
201 emit_vec12(ctx, rvb, data, stride, count);
202 break;
203 case 4:
204 emit_vec16(ctx, rvb, data, stride, count);
205 break;
206 default:
207 assert(0);
208 exit(1);
209 break;
210 }
211
212 }
213
214 void r300EmitElts(GLcontext * ctx, GLuint *elts, unsigned long n_elts)
215 {
216 r300ContextPtr rmesa = R300_CONTEXT(ctx);
217 struct r300_dma_region *rvb=&rmesa->state.elt_dma;
218 unsigned short int *out;
219 int i;
220
221 r300AllocDmaRegion(rmesa, rvb, (n_elts+1)*2 , 0x20);
222
223 out = (unsigned short int *)(rvb->address + rvb->start);
224
225 for(i=0; i < n_elts; i++)
226 out[i]=(unsigned short int)elts[i];
227
228 if(n_elts & 1)
229 out[i]=0;
230 }
231
232 /* Emit vertex data to GART memory (unless immediate mode)
233 * Route inputs to the vertex processor
234 */
235 void r300EmitArrays(GLcontext * ctx, GLboolean immd)
236 {
237 r300ContextPtr rmesa = R300_CONTEXT(ctx);
238 r300ContextPtr r300 = rmesa;
239 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
240 GLuint nr = 0;
241 GLuint count = VB->Count;
242 GLuint dw,mask;
243 GLuint vic_1 = 0; /* R300_VAP_INPUT_CNTL_1 */
244 GLuint aa_vap_reg = 0; /* VAP register assignment */
245 GLuint i;
246 GLuint inputs = 0;
247
248
249 #define CONFIGURE_AOS(r, f, v, sz, cn) { \
250 if (RADEON_DEBUG & DEBUG_STATE) \
251 fprintf(stderr, "Enabling "#v "\n"); \
252 if (++nr >= R300_MAX_AOS_ARRAYS) { \
253 fprintf(stderr, "Aieee! AOS array count exceeded!\n"); \
254 exit(-1); \
255 } \
256 \
257 if (rmesa->current_vp == NULL) \
258 rmesa->state.aos[nr-1].aos_reg = aa_vap_reg++; \
259 rmesa->state.aos[nr-1].aos_format = f; \
260 if (immd) { \
261 rmesa->state.aos[nr-1].aos_size = 4; \
262 rmesa->state.aos[nr-1].aos_stride = 4; \
263 rmesa->state.aos[nr-1].aos_offset = 0; \
264 } else { \
265 emit_vector(ctx, \
266 &rmesa->state.aos[nr-1], \
267 v->data, \
268 sz, \
269 v->stride, \
270 cn); \
271 rmesa->state.vap_reg.r=rmesa->state.aos[nr-1].aos_reg; \
272 } \
273 }
274
275 if (rmesa->current_vp != NULL) {
276 if (rmesa->current_vp->inputs[VERT_ATTRIB_POS] != -1) {
277 inputs |= _TNL_BIT_POS;
278 rmesa->state.aos[nr++].aos_reg = rmesa->current_vp->inputs[VERT_ATTRIB_POS];
279 }
280 if (rmesa->current_vp->inputs[VERT_ATTRIB_NORMAL] != -1) {
281 inputs |= _TNL_BIT_NORMAL;
282 rmesa->state.aos[nr++].aos_reg = rmesa->current_vp->inputs[VERT_ATTRIB_NORMAL];
283 }
284 if (rmesa->current_vp->inputs[VERT_ATTRIB_COLOR0] != -1) {
285 inputs |= _TNL_BIT_COLOR0;
286 rmesa->state.aos[nr++].aos_reg = rmesa->current_vp->inputs[VERT_ATTRIB_COLOR0];
287 }
288 if (rmesa->current_vp->inputs[VERT_ATTRIB_COLOR1] != -1) {
289 inputs |= _TNL_BIT_COLOR1;
290 rmesa->state.aos[nr++].aos_reg = rmesa->current_vp->inputs[VERT_ATTRIB_COLOR1];
291 }
292 if (rmesa->current_vp->inputs[VERT_ATTRIB_FOG] != -1) {
293 inputs |= _TNL_BIT_FOG;
294 rmesa->state.aos[nr++].aos_reg = rmesa->current_vp->inputs[VERT_ATTRIB_FOG];
295 }
296 if(ctx->Const.MaxTextureUnits > 8) { /* Not sure if this can even happen... */
297 fprintf(stderr, "%s: Cant handle that many inputs\n", __FUNCTION__);
298 exit(-1);
299 }
300 for (i=0;i<ctx->Const.MaxTextureUnits;i++) {
301 if (rmesa->current_vp->inputs[VERT_ATTRIB_TEX0+i] != -1) {
302 inputs |= _TNL_BIT_TEX0<<i;
303 rmesa->state.aos[nr++].aos_reg = rmesa->current_vp->inputs[VERT_ATTRIB_TEX0+i];
304 }
305 }
306 nr = 0;
307 } else {
308 inputs = TNL_CONTEXT(ctx)->render_inputs;
309 }
310 rmesa->state.render_inputs = inputs;
311
312 if (inputs & _TNL_BIT_POS) {
313 CONFIGURE_AOS(i_coords, AOS_FORMAT_FLOAT,
314 VB->ObjPtr,
315 immd ? 4 : VB->ObjPtr->size,
316 count);
317
318 vic_1 |= R300_INPUT_CNTL_POS;
319 }
320
321 if (inputs & _TNL_BIT_NORMAL) {
322 CONFIGURE_AOS(i_normal, AOS_FORMAT_FLOAT,
323 VB->NormalPtr,
324 immd ? 4 : VB->NormalPtr->size,
325 count);
326
327 vic_1 |= R300_INPUT_CNTL_NORMAL;
328 }
329
330 if (inputs & _TNL_BIT_COLOR0) {
331 int emitsize=4;
332
333 if (!immd) {
334 if (VB->ColorPtr[0]->size == 4 &&
335 (VB->ColorPtr[0]->stride != 0 ||
336 VB->ColorPtr[0]->data[0][3] != 1.0)) {
337 emitsize = 4;
338 } else {
339 emitsize = 3;
340 }
341 }
342
343 CONFIGURE_AOS(i_color[0], AOS_FORMAT_FLOAT_COLOR,
344 VB->ColorPtr[0],
345 immd ? 4 : emitsize,
346 count);
347
348 vic_1 |= R300_INPUT_CNTL_COLOR;
349 }
350
351 if (inputs & _TNL_BIT_COLOR1) {
352 CONFIGURE_AOS(i_color[1], AOS_FORMAT_FLOAT_COLOR,
353 VB->SecondaryColorPtr[0],
354 immd ? 4 : VB->SecondaryColorPtr[0]->size,
355 count);
356 }
357
358 #if 0
359 if (inputs & _TNL_BIT_FOG) {
360 CONFIGURE_AOS( AOS_FORMAT_FLOAT,
361 VB->FogCoordPtr,
362 immd ? 4 : VB->FogCoordPtr->size,
363 count);
364 }
365 #endif
366
367 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
368 if (inputs & (_TNL_BIT_TEX0 << i)) {
369 CONFIGURE_AOS(i_tex[i], AOS_FORMAT_FLOAT,
370 VB->TexCoordPtr[i],
371 immd ? 4 : VB->TexCoordPtr[i]->size,
372 count);
373
374 vic_1 |= R300_INPUT_CNTL_TC0 << i;
375 }
376 }
377
378
379 int cmd_reserved=0;
380 int cmd_written=0;
381 drm_radeon_cmd_header_t *cmd = NULL;
382
383 #define SHOW_INFO(n) do { \
384 if (RADEON_DEBUG & DEBUG_ALL) { \
385 fprintf(stderr, "RR[%d] - sz=%d, reg=%d, fmt=%d -- st=%d, of=0x%08x\n", \
386 n, \
387 r300->state.aos[n].aos_size, \
388 r300->state.aos[n].aos_reg, \
389 r300->state.aos[n].aos_format, \
390 r300->state.aos[n].aos_stride, \
391 r300->state.aos[n].aos_offset); \
392 } \
393 } while(0);
394
395 /* setup INPUT_ROUTE */
396 R300_STATECHANGE(r300, vir[0]);
397 for(i=0;i+1<nr;i+=2){
398 SHOW_INFO(i)
399 SHOW_INFO(i+1)
400 dw=(r300->state.aos[i].aos_size-1)
401 | ((r300->state.aos[i].aos_reg)<<8)
402 | (r300->state.aos[i].aos_format<<14)
403 | (((r300->state.aos[i+1].aos_size-1)
404 | ((r300->state.aos[i+1].aos_reg)<<8)
405 | (r300->state.aos[i+1].aos_format<<14))<<16);
406
407 if(i+2==nr){
408 dw|=(1<<(13+16));
409 }
410 r300->hw.vir[0].cmd[R300_VIR_CNTL_0+(i>>1)]=dw;
411 }
412 if(nr & 1){
413 SHOW_INFO(nr-1)
414 dw=(r300->state.aos[nr-1].aos_size-1)
415 | (r300->state.aos[nr-1].aos_format<<14)
416 | ((r300->state.aos[nr-1].aos_reg)<<8)
417 | (1<<13);
418 r300->hw.vir[0].cmd[R300_VIR_CNTL_0+(nr>>1)]=dw;
419 //fprintf(stderr, "vir0 dw=%08x\n", dw);
420 }
421 /* Set the rest of INPUT_ROUTE_0 to 0 */
422 //for(i=((count+1)>>1); i<8; i++)r300->hw.vir[0].cmd[R300_VIR_CNTL_0+i]=(0x0);
423 ((drm_r300_cmd_header_t*)r300->hw.vir[0].cmd)->unchecked_state.count = (nr+1)>>1;
424
425
426 /* Mesa assumes that all missing components are from (0, 0, 0, 1) */
427 #define ALL_COMPONENTS ((R300_INPUT_ROUTE_SELECT_X<<R300_INPUT_ROUTE_X_SHIFT) \
428 | (R300_INPUT_ROUTE_SELECT_Y<<R300_INPUT_ROUTE_Y_SHIFT) \
429 | (R300_INPUT_ROUTE_SELECT_Z<<R300_INPUT_ROUTE_Z_SHIFT) \
430 | (R300_INPUT_ROUTE_SELECT_W<<R300_INPUT_ROUTE_W_SHIFT))
431
432 #define ALL_DEFAULT ((R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_X_SHIFT) \
433 | (R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_Y_SHIFT) \
434 | (R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_Z_SHIFT) \
435 | (R300_INPUT_ROUTE_SELECT_ONE<<R300_INPUT_ROUTE_W_SHIFT))
436
437 R300_STATECHANGE(r300, vir[1]);
438
439 for(i=0;i+1<nr;i+=2){
440 /* do i first.. */
441 mask=(1<<(r300->state.aos[i].aos_size*3))-1;
442 dw=(ALL_COMPONENTS & mask)
443 | (ALL_DEFAULT & ~mask)
444 | R300_INPUT_ROUTE_ENABLE;
445
446 /* i+1 */
447 mask=(1<<(r300->state.aos[i+1].aos_size*3))-1;
448 dw|=(
449 (ALL_COMPONENTS & mask)
450 | (ALL_DEFAULT & ~mask)
451 | R300_INPUT_ROUTE_ENABLE
452 )<<16;
453
454 r300->hw.vir[1].cmd[R300_VIR_CNTL_0+(i>>1)]=dw;
455 }
456 if(nr & 1){
457 mask=(1<<(r300->state.aos[nr-1].aos_size*3))-1;
458 dw=(ALL_COMPONENTS & mask)
459 | (ALL_DEFAULT & ~mask)
460 | R300_INPUT_ROUTE_ENABLE;
461 r300->hw.vir[1].cmd[R300_VIR_CNTL_0+(nr>>1)]=dw;
462 //fprintf(stderr, "vir1 dw=%08x\n", dw);
463 }
464 /* Set the rest of INPUT_ROUTE_1 to 0 */
465 //for(i=((count+1)>>1); i<8; i++)r300->hw.vir[1].cmd[R300_VIR_CNTL_0+i]=0x0;
466 ((drm_r300_cmd_header_t*)r300->hw.vir[1].cmd)->unchecked_state.count = (nr+1)>>1;
467
468 /* Set up input_cntl */
469 /* I don't think this is needed for vertex buffers, but it doesn't hurt anything */
470 R300_STATECHANGE(r300, vic);
471 r300->hw.vic.cmd[R300_VIC_CNTL_0]=0x5555; /* Hard coded value, no idea what it means */
472 r300->hw.vic.cmd[R300_VIC_CNTL_1]=vic_1;
473
474 #if 0
475 r300->hw.vic.cmd[R300_VIC_CNTL_1]=0;
476
477 if(r300->state.render_inputs & _TNL_BIT_POS)
478 r300->hw.vic.cmd[R300_VIC_CNTL_1]|=R300_INPUT_CNTL_POS;
479
480 if(r300->state.render_inputs & _TNL_BIT_NORMAL)
481 r300->hw.vic.cmd[R300_VIC_CNTL_1]|=R300_INPUT_CNTL_NORMAL;
482
483 if(r300->state.render_inputs & _TNL_BIT_COLOR0)
484 r300->hw.vic.cmd[R300_VIC_CNTL_1]|=R300_INPUT_CNTL_COLOR;
485
486 for(i=0;i < ctx->Const.MaxTextureUnits;i++)
487 if(r300->state.render_inputs & (_TNL_BIT_TEX0<<i))
488 r300->hw.vic.cmd[R300_VIC_CNTL_1]|=(R300_INPUT_CNTL_TC0<<i);
489 #endif
490
491 /* Stage 3: VAP output */
492 R300_STATECHANGE(r300, vof);
493 r300->hw.vof.cmd[R300_VOF_CNTL_0]=R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT
494 | R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT;
495
496 r300->hw.vof.cmd[R300_VOF_CNTL_1]=0;
497 for(i=0;i < ctx->Const.MaxTextureUnits;i++)
498 if(r300->state.render_inputs & (_TNL_BIT_TEX0<<i))
499 r300->hw.vof.cmd[R300_VOF_CNTL_1]|=(4<<(3*i));
500
501 rmesa->state.aos_count = nr;
502 }
503
504 void r300ReleaseArrays(GLcontext * ctx)
505 {
506 r300ContextPtr rmesa = R300_CONTEXT(ctx);
507 int i;
508
509 r300ReleaseDmaRegion(rmesa, &rmesa->state.elt_dma, __FUNCTION__);
510 for (i=0;i<rmesa->state.aos_count;i++) {
511 r300ReleaseDmaRegion(rmesa, &rmesa->state.aos[i], __FUNCTION__);
512 }
513 }