slang: initialize the context
[mesa.git] / src / mesa / drivers / dri / r200 / r200_maos_arrays.c
1 /*
2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
3
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
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/mtypes.h"
37 #include "main/colormac.h"
38 #include "main/imports.h"
39 #include "main/macros.h"
40
41 #include "swrast_setup/swrast_setup.h"
42 #include "math/m_translate.h"
43 #include "tnl/tnl.h"
44 #include "tnl/t_context.h"
45
46 #include "r200_context.h"
47 #include "r200_ioctl.h"
48 #include "r200_state.h"
49 #include "r200_swtcl.h"
50 #include "r200_maos.h"
51 #include "r200_tcl.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 static void emit_vecfog( GLcontext *ctx,
179 struct r200_dma_region *rvb,
180 char *data,
181 int stride,
182 int count )
183 {
184 int i;
185 GLfloat *out;
186
187 r200ContextPtr rmesa = R200_CONTEXT(ctx);
188
189 if (R200_DEBUG & DEBUG_VERTS)
190 fprintf(stderr, "%s count %d stride %d\n",
191 __FUNCTION__, count, stride);
192
193 assert (!rvb->buf);
194
195 if (stride == 0) {
196 r200AllocDmaRegion( rmesa, rvb, 4, 4 );
197 count = 1;
198 rvb->aos_start = GET_START(rvb);
199 rvb->aos_stride = 0;
200 rvb->aos_size = 1;
201 }
202 else {
203 r200AllocDmaRegion( rmesa, rvb, count * 4, 4 ); /* alignment? */
204 rvb->aos_start = GET_START(rvb);
205 rvb->aos_stride = 1;
206 rvb->aos_size = 1;
207 }
208
209 /* Emit the data
210 */
211 out = (GLfloat *)(rvb->address + rvb->start);
212 for (i = 0; i < count; i++) {
213 out[0] = r200ComputeFogBlendFactor( ctx, *(GLfloat *)data );
214 out++;
215 data += stride;
216 }
217
218 }
219
220
221 static void emit_vec4( GLcontext *ctx,
222 struct r200_dma_region *rvb,
223 char *data,
224 int stride,
225 int count )
226 {
227 int i;
228 int *out = (int *)(rvb->address + rvb->start);
229
230 if (R200_DEBUG & DEBUG_VERTS)
231 fprintf(stderr, "%s count %d stride %d\n",
232 __FUNCTION__, count, stride);
233
234 if (stride == 4)
235 COPY_DWORDS( out, data, count );
236 else
237 for (i = 0; i < count; i++) {
238 out[0] = *(int *)data;
239 out++;
240 data += stride;
241 }
242 }
243
244
245 static void emit_vec8( GLcontext *ctx,
246 struct r200_dma_region *rvb,
247 char *data,
248 int stride,
249 int count )
250 {
251 int i;
252 int *out = (int *)(rvb->address + rvb->start);
253
254 if (R200_DEBUG & DEBUG_VERTS)
255 fprintf(stderr, "%s count %d stride %d\n",
256 __FUNCTION__, count, stride);
257
258 if (stride == 8)
259 COPY_DWORDS( out, data, count*2 );
260 else
261 for (i = 0; i < count; i++) {
262 out[0] = *(int *)data;
263 out[1] = *(int *)(data+4);
264 out += 2;
265 data += stride;
266 }
267 }
268
269 static void emit_vec12( GLcontext *ctx,
270 struct r200_dma_region *rvb,
271 char *data,
272 int stride,
273 int count )
274 {
275 int i;
276 int *out = (int *)(rvb->address + rvb->start);
277
278 if (R200_DEBUG & DEBUG_VERTS)
279 fprintf(stderr, "%s count %d stride %d out %p data %p\n",
280 __FUNCTION__, count, stride, (void *)out, (void *)data);
281
282 if (stride == 12)
283 COPY_DWORDS( out, data, count*3 );
284 else
285 for (i = 0; i < count; i++) {
286 out[0] = *(int *)data;
287 out[1] = *(int *)(data+4);
288 out[2] = *(int *)(data+8);
289 out += 3;
290 data += stride;
291 }
292 }
293
294 static void emit_vec16( GLcontext *ctx,
295 struct r200_dma_region *rvb,
296 char *data,
297 int stride,
298 int count )
299 {
300 int i;
301 int *out = (int *)(rvb->address + rvb->start);
302
303 if (R200_DEBUG & DEBUG_VERTS)
304 fprintf(stderr, "%s count %d stride %d\n",
305 __FUNCTION__, count, stride);
306
307 if (stride == 16)
308 COPY_DWORDS( out, data, count*4 );
309 else
310 for (i = 0; i < count; i++) {
311 out[0] = *(int *)data;
312 out[1] = *(int *)(data+4);
313 out[2] = *(int *)(data+8);
314 out[3] = *(int *)(data+12);
315 out += 4;
316 data += stride;
317 }
318 }
319
320
321 static void emit_vector( GLcontext *ctx,
322 struct r200_dma_region *rvb,
323 char *data,
324 int size,
325 int stride,
326 int count )
327 {
328 r200ContextPtr rmesa = R200_CONTEXT(ctx);
329
330 if (R200_DEBUG & DEBUG_VERTS)
331 fprintf(stderr, "%s count %d size %d stride %d\n",
332 __FUNCTION__, count, size, stride);
333
334 assert (!rvb->buf);
335
336 if (stride == 0) {
337 r200AllocDmaRegion( rmesa, rvb, size * 4, 4 );
338 count = 1;
339 rvb->aos_start = GET_START(rvb);
340 rvb->aos_stride = 0;
341 rvb->aos_size = size;
342 }
343 else {
344 r200AllocDmaRegion( rmesa, rvb, size * count * 4, 4 ); /* alignment? */
345 rvb->aos_start = GET_START(rvb);
346 rvb->aos_stride = size;
347 rvb->aos_size = size;
348 }
349
350 /* Emit the data
351 */
352 switch (size) {
353 case 1:
354 emit_vec4( ctx, rvb, data, stride, count );
355 break;
356 case 2:
357 emit_vec8( ctx, rvb, data, stride, count );
358 break;
359 case 3:
360 emit_vec12( ctx, rvb, data, stride, count );
361 break;
362 case 4:
363 emit_vec16( ctx, rvb, data, stride, count );
364 break;
365 default:
366 assert(0);
367 exit(1);
368 break;
369 }
370
371 }
372
373
374
375 /* Emit any changed arrays to new GART memory, re-emit a packet to
376 * update the arrays.
377 */
378 void r200EmitArrays( GLcontext *ctx, GLubyte *vimap_rev )
379 {
380 r200ContextPtr rmesa = R200_CONTEXT( ctx );
381 struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
382 struct r200_dma_region **component = rmesa->tcl.aos_components;
383 GLuint nr = 0;
384 GLuint vfmt0 = 0, vfmt1 = 0;
385 GLuint count = VB->Count;
386 GLuint i, emitsize;
387
388 for ( i = 0; i < 15; i++ ) {
389 GLubyte attrib = vimap_rev[i];
390 if (attrib != 255) {
391 switch (i) {
392 case 0:
393 emitsize = (VB->AttribPtr[attrib]->size);
394 switch (emitsize) {
395 case 4:
396 vfmt0 |= R200_VTX_W0;
397 /* fallthrough */
398 case 3:
399 vfmt0 |= R200_VTX_Z0;
400 break;
401 case 2:
402 break;
403 default: assert(0);
404 }
405 break;
406 case 1:
407 assert(attrib == VERT_ATTRIB_WEIGHT);
408 emitsize = (VB->AttribPtr[attrib]->size);
409 vfmt0 |= emitsize << R200_VTX_WEIGHT_COUNT_SHIFT;
410 break;
411 case 2:
412 assert(attrib == VERT_ATTRIB_NORMAL);
413 emitsize = 3;
414 vfmt0 |= R200_VTX_N0;
415 break;
416 case 3:
417 /* special handling to fix up fog. Will get us into trouble with vbos...*/
418 assert(attrib == VERT_ATTRIB_FOG);
419 if (!rmesa->tcl.vertex_data[i].buf) {
420 if (ctx->VertexProgram._Enabled)
421 emit_vector( ctx,
422 &(rmesa->tcl.vertex_data[i]),
423 (char *)VB->AttribPtr[attrib]->data,
424 1,
425 VB->AttribPtr[attrib]->stride,
426 count);
427 else
428 emit_vecfog( ctx,
429 &(rmesa->tcl.vertex_data[i]),
430 (char *)VB->AttribPtr[attrib]->data,
431 VB->AttribPtr[attrib]->stride,
432 count);
433 }
434 vfmt0 |= R200_VTX_DISCRETE_FOG;
435 goto after_emit;
436 break;
437 case 4:
438 case 5:
439 case 6:
440 case 7:
441 if (VB->AttribPtr[attrib]->size == 4 &&
442 (VB->AttribPtr[attrib]->stride != 0 ||
443 VB->AttribPtr[attrib]->data[0][3] != 1.0)) emitsize = 4;
444 else emitsize = 3;
445 if (emitsize == 4)
446 vfmt0 |= R200_VTX_FP_RGBA << (R200_VTX_COLOR_0_SHIFT + (i - 4) * 2);
447 else {
448 vfmt0 |= R200_VTX_FP_RGB << (R200_VTX_COLOR_0_SHIFT + (i - 4) * 2);
449 }
450 break;
451 case 8:
452 case 9:
453 case 10:
454 case 11:
455 case 12:
456 case 13:
457 emitsize = VB->AttribPtr[attrib]->size;
458 vfmt1 |= emitsize << (R200_VTX_TEX0_COMP_CNT_SHIFT + (i - 8) * 3);
459 break;
460 case 14:
461 emitsize = VB->AttribPtr[attrib]->size >= 2 ? VB->AttribPtr[attrib]->size : 2;
462 switch (emitsize) {
463 case 2:
464 vfmt0 |= R200_VTX_XY1;
465 /* fallthrough */
466 case 3:
467 vfmt0 |= R200_VTX_Z1;
468 /* fallthrough */
469 case 4:
470 vfmt0 |= R200_VTX_W1;
471 break;
472 }
473 default:
474 assert(0);
475 }
476 if (!rmesa->tcl.vertex_data[i].buf) {
477 emit_vector( ctx,
478 &(rmesa->tcl.vertex_data[i]),
479 (char *)VB->AttribPtr[attrib]->data,
480 emitsize,
481 VB->AttribPtr[attrib]->stride,
482 count );
483 }
484 after_emit:
485 assert(nr < 12);
486 component[nr++] = &rmesa->tcl.vertex_data[i];
487 }
488 }
489
490 if (vfmt0 != rmesa->hw.vtx.cmd[VTX_VTXFMT_0] ||
491 vfmt1 != rmesa->hw.vtx.cmd[VTX_VTXFMT_1]) {
492 R200_STATECHANGE( rmesa, vtx );
493 rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = vfmt0;
494 rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = vfmt1;
495 }
496
497 rmesa->tcl.nr_aos_components = nr;
498 }
499
500
501 void r200ReleaseArrays( GLcontext *ctx, GLuint newinputs )
502 {
503 r200ContextPtr rmesa = R200_CONTEXT( ctx );
504
505 /* only do it for changed inputs ? */
506 int i;
507 for (i = 0; i < 15; i++) {
508 if (newinputs & (1 << i))
509 r200ReleaseDmaRegion( rmesa,
510 &rmesa->tcl.vertex_data[i], __FUNCTION__ );
511 }
512 }