static void pair_sub_for_all_args( struct rc_instruction * fullinst, struct rc_pair_sub_instruction * sub, rc_pair_read_arg_fn cb, void * userdata) { int i; const struct rc_opcode_info * info = rc_get_opcode_info(sub->Opcode); for(i = 0; i < info->NumSrcRegs; i++) { unsigned int src_type; src_type = rc_source_type_swz(sub->Arg[i].Swizzle); if (src_type == RC_SOURCE_NONE) continue; if (sub->Arg[i].Source == RC_PAIR_PRESUB_SRC) { unsigned int presub_type; unsigned int presub_src_count; struct rc_pair_instruction_source * src_array; unsigned int j; if (src_type & RC_SOURCE_RGB) { presub_type = fullinst-> U.P.RGB.Src[RC_PAIR_PRESUB_SRC].Index; src_array = fullinst->U.P.RGB.Src; } else { presub_type = fullinst-> U.P.Alpha.Src[RC_PAIR_PRESUB_SRC].Index; src_array = fullinst->U.P.Alpha.Src; } presub_src_count = rc_presubtract_src_reg_count(presub_type); for(j = 0; j < presub_src_count; j++) { cb(userdata, fullinst, &sub->Arg[i], &src_array[j]); } } else { struct rc_pair_instruction_source * src = rc_pair_get_src(&fullinst->U.P, &sub->Arg[i]); if (src) { cb(userdata, fullinst, &sub->Arg[i], src); } } } }
static void mark_used( struct rc_instruction * inst, struct rc_pair_sub_instruction * sub) { unsigned int i; const struct rc_opcode_info * info = rc_get_opcode_info(sub->Opcode); for (i = 0; i < info->NumSrcRegs; i++) { unsigned int src_type = rc_source_type_swz(sub->Arg[i].Swizzle); if (src_type & RC_SOURCE_RGB) { inst->U.P.RGB.Src[sub->Arg[i].Source].Used = 1; } if (src_type & RC_SOURCE_ALPHA) { inst->U.P.Alpha.Src[sub->Arg[i].Source].Used = 1; } } }
/* This is a helper function for destructive_merge_instructions(). It helps * merge presubtract sources from two instructions and makes sure the * presubtract sources end up in the correct spot. This function assumes that * dst_full is an rgb instruction, meaning that it has a vector instruction(rgb) * but no scalar instruction (alpha). * @return 0 if merging the presubtract sources fails. * @retrun 1 if merging the presubtract sources succeeds. */ static int merge_presub_sources( struct rc_pair_instruction * dst_full, struct rc_pair_sub_instruction src, unsigned int type) { unsigned int srcp_src, srcp_regs, is_rgb, is_alpha; struct rc_pair_sub_instruction * dst_sub; const struct rc_opcode_info * info; assert(dst_full->Alpha.Opcode == RC_OPCODE_NOP); switch(type) { case RC_SOURCE_RGB: is_rgb = 1; is_alpha = 0; dst_sub = &dst_full->RGB; break; case RC_SOURCE_ALPHA: is_rgb = 0; is_alpha = 1; dst_sub = &dst_full->Alpha; break; default: assert(0); return 0; } info = rc_get_opcode_info(dst_full->RGB.Opcode); if (dst_sub->Src[RC_PAIR_PRESUB_SRC].Used) return 0; srcp_regs = rc_presubtract_src_reg_count( src.Src[RC_PAIR_PRESUB_SRC].Index); for(srcp_src = 0; srcp_src < srcp_regs; srcp_src++) { unsigned int arg; int free_source; unsigned int one_way = 0; struct rc_pair_instruction_source srcp = src.Src[srcp_src]; struct rc_pair_instruction_source temp; free_source = rc_pair_alloc_source(dst_full, is_rgb, is_alpha, srcp.File, srcp.Index); /* If free_source < 0 then there are no free source * slots. */ if (free_source < 0) return 0; temp = dst_sub->Src[srcp_src]; dst_sub->Src[srcp_src] = dst_sub->Src[free_source]; /* srcp needs src0 and src1 to be the same */ if (free_source < srcp_src) { if (!temp.Used) continue; free_source = rc_pair_alloc_source(dst_full, is_rgb, is_alpha, temp.File, temp.Index); if (free_source < 0) return 0; one_way = 1; } else { dst_sub->Src[free_source] = temp; } /* If free_source == srcp_src, then the presubtract * source is already in the correct place. */ if (free_source == srcp_src) continue; /* Shuffle the sources, so we can put the * presubtract source in the correct place. */ for(arg = 0; arg < info->NumSrcRegs; arg++) { /*If this arg does not read from an rgb source, * do nothing. */ if (!(rc_source_type_swz(dst_full->RGB.Arg[arg].Swizzle, 3) & type)) { continue; } if (dst_full->RGB.Arg[arg].Source == srcp_src) dst_full->RGB.Arg[arg].Source = free_source; /* We need to do this just in case register * is one of the sources already, but in the * wrong spot. */ else if(dst_full->RGB.Arg[arg].Source == free_source && !one_way) { dst_full->RGB.Arg[arg].Source = srcp_src; } } } return 1; }