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