+#define ADD_ATTR(_attr, _format, _dst_loc, _swizzle, _write_mask) \
+do { \
+ attrs[num_attrs].attr = (_attr); \
+ attrs[num_attrs].format = (_format); \
+ attrs[num_attrs].dst_loc = (_dst_loc); \
+ attrs[num_attrs].swizzle = (_swizzle); \
+ attrs[num_attrs].write_mask = (_write_mask); \
+ ++num_attrs; \
+} while (0)
+
+static void r300SwtclVAPSetup(GLcontext *ctx, GLuint InputsRead, GLuint OutputsWritten, GLuint vap_out_fmt_1)
+{
+ r300ContextPtr rmesa = R300_CONTEXT( ctx );
+ struct vertex_attribute *attrs = rmesa->swtcl.vert_attrs;
+ int i, j, reg_count;
+ uint32_t *vir0 = &rmesa->hw.vir[0].cmd[1];
+ uint32_t *vir1 = &rmesa->hw.vir[1].cmd[1];
+
+ for (i = 0; i < R300_VIR_CMDSIZE-1; ++i)
+ vir0[i] = vir1[i] = 0;
+
+ for (i = 0, j = 0; i < rmesa->radeon.swtcl.vertex_attr_count; ++i) {
+ int tmp, data_format;
+ switch (attrs[i].format) {
+ case EMIT_1F:
+ data_format = R300_DATA_TYPE_FLOAT_1;
+ break;
+ case EMIT_2F:
+ data_format = R300_DATA_TYPE_FLOAT_2;
+ break;
+ case EMIT_3F:
+ data_format = R300_DATA_TYPE_FLOAT_3;
+ break;
+ case EMIT_4F:
+ data_format = R300_DATA_TYPE_FLOAT_4;
+ break;
+ case EMIT_4UB_4F_RGBA:
+ case EMIT_4UB_4F_ABGR:
+ data_format = R300_DATA_TYPE_BYTE | R300_NORMALIZE;
+ break;
+ default:
+ fprintf(stderr, "%s: Invalid data format type", __FUNCTION__);
+ _mesa_exit(-1);
+ break;
+ }
+
+ tmp = data_format | (attrs[i].dst_loc << R300_DST_VEC_LOC_SHIFT);
+ if (i % 2 == 0) {
+ vir0[j] = tmp << R300_DATA_TYPE_0_SHIFT;
+ vir1[j] = attrs[i].swizzle | (attrs[i].write_mask << R300_WRITE_ENA_SHIFT);
+ } else {
+ vir0[j] |= tmp << R300_DATA_TYPE_1_SHIFT;
+ vir1[j] |= (attrs[i].swizzle | (attrs[i].write_mask << R300_WRITE_ENA_SHIFT)) << R300_SWIZZLE1_SHIFT;
+ ++j;
+ }
+ }
+
+ reg_count = (rmesa->radeon.swtcl.vertex_attr_count + 1) >> 1;
+ if (rmesa->radeon.swtcl.vertex_attr_count % 2 != 0) {
+ vir0[reg_count-1] |= R300_LAST_VEC << R300_DATA_TYPE_0_SHIFT;
+ } else {
+ vir0[reg_count-1] |= R300_LAST_VEC << R300_DATA_TYPE_1_SHIFT;
+ }
+
+ R300_STATECHANGE(rmesa, vir[0]);
+ R300_STATECHANGE(rmesa, vir[1]);
+ R300_STATECHANGE(rmesa, vof);
+ R300_STATECHANGE(rmesa, vic);
+
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ rmesa->hw.vir[0].cmd[0] &= 0xC000FFFF;
+ rmesa->hw.vir[1].cmd[0] &= 0xC000FFFF;
+ rmesa->hw.vir[0].cmd[0] |= (reg_count & 0x3FFF) << 16;
+ rmesa->hw.vir[1].cmd[0] |= (reg_count & 0x3FFF) << 16;
+ } else {
+ ((drm_r300_cmd_header_t *) rmesa->hw.vir[0].cmd)->packet0.count = reg_count;
+ ((drm_r300_cmd_header_t *) rmesa->hw.vir[1].cmd)->packet0.count = reg_count;
+ }
+
+ rmesa->hw.vic.cmd[R300_VIC_CNTL_0] = r300VAPInputCntl0(ctx, InputsRead);
+ rmesa->hw.vic.cmd[R300_VIC_CNTL_1] = r300VAPInputCntl1(ctx, InputsRead);
+ rmesa->hw.vof.cmd[R300_VOF_CNTL_0] = r300VAPOutputCntl0(ctx, OutputsWritten);
+ /**
+ * Can't use r300VAPOutputCntl1 function because it assumes
+ * that all texture coords have 4 components and that's the case
+ * for HW TCL path, but not for SW TCL.
+ */
+ rmesa->hw.vof.cmd[R300_VOF_CNTL_1] = vap_out_fmt_1;
+}
+
+