54557c8eda38510132a31e8b453ca2843a682704
[mesa.git] / src / mesa / drivers / dri / r300 / r300_maos.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 "glheader.h"
36 #include "mtypes.h"
37 #include "colormac.h"
38 #include "imports.h"
39 #include "macros.h"
40 #include "image.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 #ifdef USER_BUFFERS
54 #include "r300_mem.h"
55 #endif
56
57 #if SWIZZLE_X != R300_INPUT_ROUTE_SELECT_X || \
58 SWIZZLE_Y != R300_INPUT_ROUTE_SELECT_Y || \
59 SWIZZLE_Z != R300_INPUT_ROUTE_SELECT_Z || \
60 SWIZZLE_W != R300_INPUT_ROUTE_SELECT_W || \
61 SWIZZLE_ZERO != R300_INPUT_ROUTE_SELECT_ZERO || \
62 SWIZZLE_ONE != R300_INPUT_ROUTE_SELECT_ONE
63 #error Cannot change these!
64 #endif
65
66 #define DEBUG_ALL DEBUG_VERTS
67
68 #if defined(USE_X86_ASM)
69 #define COPY_DWORDS( dst, src, nr ) \
70 do { \
71 int __tmp; \
72 __asm__ __volatile__( "rep ; movsl" \
73 : "=%c" (__tmp), "=D" (dst), "=S" (__tmp) \
74 : "0" (nr), \
75 "D" ((long)dst), \
76 "S" ((long)src) ); \
77 } while (0)
78 #else
79 #define COPY_DWORDS( dst, src, nr ) \
80 do { \
81 int j; \
82 for ( j = 0 ; j < nr ; j++ ) \
83 dst[j] = ((int *)src)[j]; \
84 dst += nr; \
85 } while (0)
86 #endif
87
88 static void emit_vec4(GLcontext * ctx,
89 struct r300_dma_region *rvb,
90 GLvoid * data, int stride, int count)
91 {
92 int i;
93 int *out = (int *)(rvb->address + rvb->start);
94
95 if (RADEON_DEBUG & DEBUG_VERTS)
96 fprintf(stderr, "%s count %d stride %d\n",
97 __FUNCTION__, count, stride);
98
99 if (stride == 4)
100 COPY_DWORDS(out, data, count);
101 else
102 for (i = 0; i < count; i++) {
103 out[0] = *(int *)data;
104 out++;
105 data += stride;
106 }
107 }
108
109 static void emit_vec8(GLcontext * ctx,
110 struct r300_dma_region *rvb,
111 GLvoid * data, int stride, int count)
112 {
113 int i;
114 int *out = (int *)(rvb->address + rvb->start);
115
116 if (RADEON_DEBUG & DEBUG_VERTS)
117 fprintf(stderr, "%s count %d stride %d\n",
118 __FUNCTION__, count, stride);
119
120 if (stride == 8)
121 COPY_DWORDS(out, data, count * 2);
122 else
123 for (i = 0; i < count; i++) {
124 out[0] = *(int *)data;
125 out[1] = *(int *)(data + 4);
126 out += 2;
127 data += stride;
128 }
129 }
130
131 static void emit_vec12(GLcontext * ctx,
132 struct r300_dma_region *rvb,
133 GLvoid * data, int stride, int count)
134 {
135 int i;
136 int *out = (int *)(rvb->address + rvb->start);
137
138 if (RADEON_DEBUG & DEBUG_VERTS)
139 fprintf(stderr, "%s count %d stride %d out %p data %p\n",
140 __FUNCTION__, count, stride, (void *)out, (void *)data);
141
142 if (stride == 12)
143 COPY_DWORDS(out, data, count * 3);
144 else
145 for (i = 0; i < count; i++) {
146 out[0] = *(int *)data;
147 out[1] = *(int *)(data + 4);
148 out[2] = *(int *)(data + 8);
149 out += 3;
150 data += stride;
151 }
152 }
153
154 static void emit_vec16(GLcontext * ctx,
155 struct r300_dma_region *rvb,
156 GLvoid * data, int stride, int count)
157 {
158 int i;
159 int *out = (int *)(rvb->address + rvb->start);
160
161 if (RADEON_DEBUG & DEBUG_VERTS)
162 fprintf(stderr, "%s count %d stride %d\n",
163 __FUNCTION__, count, stride);
164
165 if (stride == 16)
166 COPY_DWORDS(out, data, count * 4);
167 else
168 for (i = 0; i < count; i++) {
169 out[0] = *(int *)data;
170 out[1] = *(int *)(data + 4);
171 out[2] = *(int *)(data + 8);
172 out[3] = *(int *)(data + 12);
173 out += 4;
174 data += stride;
175 }
176 }
177
178 static void emit_vector(GLcontext * ctx,
179 struct r300_dma_region *rvb,
180 GLvoid * data, int size, int stride, int count)
181 {
182 r300ContextPtr rmesa = R300_CONTEXT(ctx);
183
184 if (RADEON_DEBUG & DEBUG_VERTS)
185 fprintf(stderr, "%s count %d size %d stride %d\n",
186 __FUNCTION__, count, size, stride);
187
188 /* Gets triggered when playing with future_hw_tcl_on ... */
189 //assert(!rvb->buf);
190
191 if (stride == 0) {
192 r300AllocDmaRegion(rmesa, rvb, size * 4, 4);
193 count = 1;
194 rvb->aos_offset = GET_START(rvb);
195 rvb->aos_stride = 0;
196 } else {
197 r300AllocDmaRegion(rmesa, rvb, size * count * 4, 4); /* alignment? */
198 rvb->aos_offset = GET_START(rvb);
199 rvb->aos_stride = size;
200 }
201
202 /* Emit the data
203 */
204 switch (size) {
205 case 1:
206 emit_vec4(ctx, rvb, data, stride, count);
207 break;
208 case 2:
209 emit_vec8(ctx, rvb, data, stride, count);
210 break;
211 case 3:
212 emit_vec12(ctx, rvb, data, stride, count);
213 break;
214 case 4:
215 emit_vec16(ctx, rvb, data, stride, count);
216 break;
217 default:
218 assert(0);
219 _mesa_exit(-1);
220 break;
221 }
222
223 }
224
225 void r300EmitElts(GLcontext * ctx, void *elts, unsigned long n_elts,
226 int elt_size)
227 {
228 r300ContextPtr rmesa = R300_CONTEXT(ctx);
229 struct r300_dma_region *rvb = &rmesa->state.elt_dma;
230 void *out;
231
232 assert(elt_size == 2 || elt_size == 4);
233
234 if (r300IsGartMemory(rmesa, elts, n_elts * elt_size)) {
235 rvb->address = rmesa->radeon.radeonScreen->gartTextures.map;
236 rvb->start = ((char *)elts) - rvb->address;
237 rvb->aos_offset =
238 rmesa->radeon.radeonScreen->gart_texture_offset +
239 rvb->start;
240
241 return;
242 } else if (r300IsGartMemory(rmesa, elts, 1)) {
243 WARN_ONCE("Pointer not within GART memory!\n");
244 _mesa_exit(-1);
245 }
246
247 r300AllocDmaRegion(rmesa, rvb, n_elts * elt_size, elt_size);
248 rvb->aos_offset = GET_START(rvb);
249
250 out = rvb->address + rvb->start;
251 memcpy(out, elts, n_elts * elt_size);
252 }
253
254 static GLuint t_type(struct dt *dt)
255 {
256 switch (dt->type) {
257 case GL_UNSIGNED_BYTE:
258 return AOS_FORMAT_UBYTE;
259
260 case GL_SHORT:
261 return AOS_FORMAT_USHORT;
262
263 case GL_FLOAT:
264 return AOS_FORMAT_FLOAT;
265
266 default:
267 assert(0);
268 break;
269 }
270
271 return AOS_FORMAT_FLOAT;
272 }
273
274 static GLuint t_vir0_size(struct dt *dt)
275 {
276 switch (dt->type) {
277 case GL_UNSIGNED_BYTE:
278 return 4;
279
280 case GL_SHORT:
281 return 7;
282
283 case GL_FLOAT:
284 return dt->size - 1;
285
286 default:
287 assert(0);
288 break;
289 }
290
291 return 0;
292 }
293
294 static GLuint t_aos_size(struct dt *dt)
295 {
296 switch (dt->type) {
297 case GL_UNSIGNED_BYTE:
298 return 1;
299
300 case GL_SHORT:
301 return 2;
302
303 case GL_FLOAT:
304 return dt->size;
305
306 default:
307 assert(0);
308 break;
309 }
310
311 return 0;
312 }
313
314 static GLuint t_vir0(uint32_t * dst, struct dt *dt, int *inputs,
315 GLint * tab, GLuint nr)
316 {
317 GLuint i, dw;
318
319 for (i = 0; i + 1 < nr; i += 2) {
320 dw = t_vir0_size(&dt[tab[i]]) | (inputs[tab[i]] << 8) |
321 (t_type(&dt[tab[i]]) << 14);
322 dw |=
323 (t_vir0_size(&dt[tab[i + 1]]) |
324 (inputs[tab[i + 1]] << 8) | (t_type(&dt[tab[i + 1]])
325 << 14)) << 16;
326
327 if (i + 2 == nr) {
328 dw |= (1 << (13 + 16));
329 }
330 dst[i >> 1] = dw;
331 }
332
333 if (nr & 1) {
334 dw = t_vir0_size(&dt[tab[nr - 1]]) | (inputs[tab[nr - 1]]
335 << 8) |
336 (t_type(&dt[tab[nr - 1]]) << 14);
337 dw |= 1 << 13;
338
339 dst[nr >> 1] = dw;
340 }
341
342 return (nr + 1) >> 1;
343 }
344
345 static GLuint t_swizzle(int swizzle[4])
346 {
347 return (swizzle[0] << R300_INPUT_ROUTE_X_SHIFT) |
348 (swizzle[1] << R300_INPUT_ROUTE_Y_SHIFT) |
349 (swizzle[2] << R300_INPUT_ROUTE_Z_SHIFT) |
350 (swizzle[3] << R300_INPUT_ROUTE_W_SHIFT);
351 }
352
353 static GLuint t_vir1(uint32_t * dst, int swizzle[][4], GLuint nr)
354 {
355 GLuint i;
356
357 for (i = 0; i + 1 < nr; i += 2) {
358 dst[i >> 1] = t_swizzle(swizzle[i]) | R300_INPUT_ROUTE_ENABLE;
359 dst[i >> 1] |=
360 (t_swizzle(swizzle[i + 1]) | R300_INPUT_ROUTE_ENABLE)
361 << 16;
362 }
363
364 if (nr & 1)
365 dst[nr >> 1] =
366 t_swizzle(swizzle[nr - 1]) | R300_INPUT_ROUTE_ENABLE;
367
368 return (nr + 1) >> 1;
369 }
370
371 static GLuint t_emit_size(struct dt *dt)
372 {
373 return dt->size;
374 }
375
376 static GLuint t_vic(GLcontext * ctx, GLuint InputsRead)
377 {
378 r300ContextPtr r300 = R300_CONTEXT(ctx);
379 GLuint i, vic_1 = 0;
380
381 if (InputsRead & (1 << VERT_ATTRIB_POS))
382 vic_1 |= R300_INPUT_CNTL_POS;
383
384 if (InputsRead & (1 << VERT_ATTRIB_NORMAL))
385 vic_1 |= R300_INPUT_CNTL_NORMAL;
386
387 if (InputsRead & (1 << VERT_ATTRIB_COLOR0))
388 vic_1 |= R300_INPUT_CNTL_COLOR;
389
390 r300->state.texture.tc_count = 0;
391 for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
392 if (InputsRead & (1 << (VERT_ATTRIB_TEX0 + i))) {
393 r300->state.texture.tc_count++;
394 vic_1 |= R300_INPUT_CNTL_TC0 << i;
395 }
396
397 return vic_1;
398 }
399
400 /* Emit vertex data to GART memory
401 * Route inputs to the vertex processor
402 * This function should never return R300_FALLBACK_TCL when using software tcl.
403 */
404
405 int r300EmitArrays(GLcontext * ctx)
406 {
407 r300ContextPtr rmesa = R300_CONTEXT(ctx);
408 r300ContextPtr r300 = rmesa;
409 struct radeon_vertex_buffer *VB = &rmesa->state.VB;
410 GLuint nr;
411 GLuint count = VB->Count;
412 GLuint i;
413 GLuint InputsRead = 0, OutputsWritten = 0;
414 int *inputs = NULL;
415 int vir_inputs[VERT_ATTRIB_MAX];
416 GLint tab[VERT_ATTRIB_MAX];
417 int swizzle[VERT_ATTRIB_MAX][4];
418
419 if (hw_tcl_on) {
420 struct r300_vertex_program *prog =
421 (struct r300_vertex_program *)
422 CURRENT_VERTEX_SHADER(ctx);
423 inputs = prog->inputs;
424 InputsRead = CURRENT_VERTEX_SHADER(ctx)->key.InputsRead;
425 OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->key.OutputsWritten;
426 } else {
427 DECLARE_RENDERINPUTS(inputs_bitset);
428 inputs = r300->state.sw_tcl_inputs;
429
430 RENDERINPUTS_COPY(inputs_bitset,
431 TNL_CONTEXT(ctx)->render_inputs_bitset);
432
433 assert(RENDERINPUTS_TEST(inputs_bitset, _TNL_ATTRIB_POS));
434 InputsRead |= 1 << VERT_ATTRIB_POS;
435 OutputsWritten |= 1 << VERT_RESULT_HPOS;
436
437 assert(RENDERINPUTS_TEST(inputs_bitset, _TNL_ATTRIB_NORMAL)
438 == 0);
439
440 assert(RENDERINPUTS_TEST(inputs_bitset, _TNL_ATTRIB_COLOR0));
441 InputsRead |= 1 << VERT_ATTRIB_COLOR0;
442 OutputsWritten |= 1 << VERT_RESULT_COL0;
443
444 if (RENDERINPUTS_TEST(inputs_bitset, _TNL_ATTRIB_COLOR1)) {
445 InputsRead |= 1 << VERT_ATTRIB_COLOR1;
446 OutputsWritten |= 1 << VERT_RESULT_COL1;
447 }
448
449 for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
450 if (RENDERINPUTS_TEST
451 (inputs_bitset, _TNL_ATTRIB_TEX(i))) {
452 InputsRead |= 1 << (VERT_ATTRIB_TEX0 + i);
453 OutputsWritten |= 1 << (VERT_RESULT_TEX0 + i);
454 }
455
456 for (i = 0, nr = 0; i < VERT_ATTRIB_MAX; i++)
457 if (InputsRead & (1 << i))
458 inputs[i] = nr++;
459 else
460 inputs[i] = -1;
461
462 if (!
463 (r300->radeon.radeonScreen->
464 chip_flags & RADEON_CHIPSET_TCL)) {
465 /* Fixed, apply to vir0 only */
466 memcpy(vir_inputs, inputs,
467 VERT_ATTRIB_MAX * sizeof(int));
468 inputs = vir_inputs;
469
470 if (InputsRead & VERT_ATTRIB_POS)
471 inputs[VERT_ATTRIB_POS] = 0;
472
473 if (InputsRead & (1 << VERT_ATTRIB_COLOR0))
474 inputs[VERT_ATTRIB_COLOR0] = 2;
475
476 if (InputsRead & (1 << VERT_ATTRIB_COLOR1))
477 inputs[VERT_ATTRIB_COLOR1] = 3;
478
479 for (i = VERT_ATTRIB_TEX0; i <= VERT_ATTRIB_TEX7; i++)
480 if (InputsRead & (1 << i))
481 inputs[i] = 6 + (i - VERT_ATTRIB_TEX0);
482 }
483
484 RENDERINPUTS_COPY(rmesa->state.render_inputs_bitset,
485 inputs_bitset);
486 }
487 assert(InputsRead);
488 assert(OutputsWritten);
489
490 for (i = 0, nr = 0; i < VERT_ATTRIB_MAX; i++)
491 if (InputsRead & (1 << i))
492 tab[nr++] = i;
493
494 if (nr > R300_MAX_AOS_ARRAYS)
495 return R300_FALLBACK_TCL;
496
497 for (i = 0; i < nr; i++) {
498 int ci;
499 int comp_size, fix, found = 0;
500
501 swizzle[i][0] = SWIZZLE_ZERO;
502 swizzle[i][1] = SWIZZLE_ZERO;
503 swizzle[i][2] = SWIZZLE_ZERO;
504 swizzle[i][3] = SWIZZLE_ONE;
505
506 for (ci = 0; ci < VB->AttribPtr[tab[i]].size; ci++)
507 swizzle[i][ci] = ci;
508
509 #if MESA_BIG_ENDIAN
510 #define SWAP_INT(a, b) do { \
511 int __temp; \
512 __temp = a;\
513 a = b; \
514 b = __temp; \
515 } while (0)
516
517 if (VB->AttribPtr[tab[i]].type == GL_UNSIGNED_BYTE) {
518 SWAP_INT(swizzle[i][0], swizzle[i][3]);
519 SWAP_INT(swizzle[i][1], swizzle[i][2]);
520 }
521 #endif /* MESA_BIG_ENDIAN */
522
523 if (r300IsGartMemory(rmesa, VB->AttribPtr[tab[i]].data,
524 /*(count-1)*stride */ 4)) {
525 if (VB->AttribPtr[tab[i]].stride % 4)
526 return R300_FALLBACK_TCL;
527
528 rmesa->state.aos[i].address =
529 VB->AttribPtr[tab[i]].data;
530 rmesa->state.aos[i].start = 0;
531 rmesa->state.aos[i].aos_offset =
532 r300GartOffsetFromVirtual(rmesa,
533 VB->
534 AttribPtr[tab[i]].data);
535 rmesa->state.aos[i].aos_stride =
536 VB->AttribPtr[tab[i]].stride / 4;
537
538 rmesa->state.aos[i].aos_size =
539 t_emit_size(&VB->AttribPtr[tab[i]]);
540 } else {
541 /* TODO: emit_vector can only handle 4 byte vectors */
542 if (VB->AttribPtr[tab[i]].type != GL_FLOAT)
543 return R300_FALLBACK_TCL;
544
545 emit_vector(ctx, &rmesa->state.aos[i],
546 VB->AttribPtr[tab[i]].data,
547 t_emit_size(&VB->AttribPtr[tab[i]]),
548 VB->AttribPtr[tab[i]].stride, count);
549 }
550
551 rmesa->state.aos[i].aos_size =
552 t_aos_size(&VB->AttribPtr[tab[i]]);
553
554 comp_size = _mesa_sizeof_type(VB->AttribPtr[tab[i]].type);
555
556 for (fix = 0; fix <= 4 - VB->AttribPtr[tab[i]].size; fix++) {
557 if ((rmesa->state.aos[i].aos_offset -
558 comp_size * fix) % 4)
559 continue;
560
561 found = 1;
562 break;
563 }
564
565 if (found) {
566 if (fix > 0) {
567 WARN_ONCE("Feeling lucky?\n");
568 }
569
570 rmesa->state.aos[i].aos_offset -= comp_size * fix;
571
572 for (ci = 0; ci < VB->AttribPtr[tab[i]].size; ci++)
573 swizzle[i][ci] += fix;
574 } else {
575 WARN_ONCE
576 ("Cannot handle offset %x with stride %d, comp %d\n",
577 rmesa->state.aos[i].aos_offset,
578 rmesa->state.aos[i].aos_stride,
579 VB->AttribPtr[tab[i]].size);
580 return R300_FALLBACK_TCL;
581 }
582 }
583
584 /* setup INPUT_ROUTE */
585 R300_STATECHANGE(r300, vir[0]);
586 ((drm_r300_cmd_header_t *) r300->hw.vir[0].cmd)->packet0.count =
587 t_vir0(&r300->hw.vir[0].cmd[R300_VIR_CNTL_0], VB->AttribPtr,
588 inputs, tab, nr);
589
590 R300_STATECHANGE(r300, vir[1]);
591 ((drm_r300_cmd_header_t *) r300->hw.vir[1].cmd)->packet0.count =
592 t_vir1(&r300->hw.vir[1].cmd[R300_VIR_CNTL_0], swizzle, nr);
593
594 /* Set up input_cntl */
595 /* I don't think this is needed for vertex buffers, but it doesn't hurt anything */
596 R300_STATECHANGE(r300, vic);
597 r300->hw.vic.cmd[R300_VIC_CNTL_0] = 0x5555; /* Hard coded value, no idea what it means */
598 r300->hw.vic.cmd[R300_VIC_CNTL_1] = t_vic(ctx, InputsRead);
599
600 /* Stage 3: VAP output */
601
602 R300_STATECHANGE(r300, vof);
603
604 r300->hw.vof.cmd[R300_VOF_CNTL_0] = 0;
605 r300->hw.vof.cmd[R300_VOF_CNTL_1] = 0;
606
607 if (OutputsWritten & (1 << VERT_RESULT_HPOS))
608 r300->hw.vof.cmd[R300_VOF_CNTL_0] |=
609 R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT;
610
611 if (OutputsWritten & (1 << VERT_RESULT_COL0))
612 r300->hw.vof.cmd[R300_VOF_CNTL_0] |=
613 R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT;
614
615 if (OutputsWritten & (1 << VERT_RESULT_COL1))
616 r300->hw.vof.cmd[R300_VOF_CNTL_0] |=
617 R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT;
618
619 /*if(OutputsWritten & (1 << VERT_RESULT_BFC0))
620 r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT;
621
622 if(OutputsWritten & (1 << VERT_RESULT_BFC1))
623 r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT; */
624 //if(OutputsWritten & (1 << VERT_RESULT_FOGC))
625
626 if (OutputsWritten & (1 << VERT_RESULT_PSIZ))
627 r300->hw.vof.cmd[R300_VOF_CNTL_0] |=
628 R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT;
629
630 for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
631 if (OutputsWritten & (1 << (VERT_RESULT_TEX0 + i)))
632 r300->hw.vof.cmd[R300_VOF_CNTL_1] |= (4 << (3 * i));
633
634 rmesa->state.aos_count = nr;
635
636 return R300_FALLBACK_NONE;
637 }
638
639 #ifdef USER_BUFFERS
640 void r300UseArrays(GLcontext * ctx)
641 {
642 r300ContextPtr rmesa = R300_CONTEXT(ctx);
643 int i;
644
645 if (rmesa->state.elt_dma.buf)
646 r300_mem_use(rmesa, rmesa->state.elt_dma.buf->id);
647
648 for (i = 0; i < rmesa->state.aos_count; i++) {
649 if (rmesa->state.aos[i].buf)
650 r300_mem_use(rmesa, rmesa->state.aos[i].buf->id);
651 }
652 }
653 #endif
654
655 void r300ReleaseArrays(GLcontext * ctx)
656 {
657 r300ContextPtr rmesa = R300_CONTEXT(ctx);
658 int i;
659
660 r300ReleaseDmaRegion(rmesa, &rmesa->state.elt_dma, __FUNCTION__);
661 for (i = 0; i < rmesa->state.aos_count; i++) {
662 r300ReleaseDmaRegion(rmesa, &rmesa->state.aos[i], __FUNCTION__);
663 }
664 }