1/* 2 * Copyright (C) 2008-2009 Nicolai Haehnle. 3 * 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sublicense, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial 16 * portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 */ 27 28#include "radeon_program_pair.h" 29 30#include "radeon_compiler_util.h" 31 32#include <stdlib.h> 33 34/** 35 * Return the source slot where we installed the given register access, 36 * or -1 if no slot was free anymore. 37 */ 38int rc_pair_alloc_source(struct rc_pair_instruction *pair, 39 unsigned int rgb, unsigned int alpha, 40 rc_register_file file, unsigned int index) 41{ 42 int candidate = -1; 43 int candidate_quality = -1; 44 unsigned int alpha_used = 0; 45 unsigned int rgb_used = 0; 46 int i; 47 48 if ((!rgb && !alpha) || file == RC_FILE_NONE) 49 return 0; 50 51 /* Make sure only one presubtract operation is used per instruction. */ 52 if (file == RC_FILE_PRESUB) { 53 if (rgb && pair->RGB.Src[RC_PAIR_PRESUB_SRC].Used 54 && index != pair->RGB.Src[RC_PAIR_PRESUB_SRC].Index) { 55 return -1; 56 } 57 58 if (alpha && pair->Alpha.Src[RC_PAIR_PRESUB_SRC].Used 59 && index != pair->Alpha.Src[RC_PAIR_PRESUB_SRC].Index) { 60 return -1; 61 } 62 } 63 64 for(i = 0; i < 3; ++i) { 65 int q = 0; 66 if (rgb) { 67 if (pair->RGB.Src[i].Used) { 68 if (pair->RGB.Src[i].File != file || 69 pair->RGB.Src[i].Index != index) { 70 rgb_used++; 71 continue; 72 } 73 q++; 74 } 75 } 76 if (alpha) { 77 if (pair->Alpha.Src[i].Used) { 78 if (pair->Alpha.Src[i].File != file || 79 pair->Alpha.Src[i].Index != index) { 80 alpha_used++; 81 continue; 82 } 83 q++; 84 } 85 } 86 if (q > candidate_quality) { 87 candidate_quality = q; 88 candidate = i; 89 } 90 } 91 92 if (file == RC_FILE_PRESUB) { 93 candidate = RC_PAIR_PRESUB_SRC; 94 } else if (candidate < 0 || (rgb && rgb_used > 2) 95 || (alpha && alpha_used > 2)) { 96 return -1; 97 } 98 99 /* candidate >= 0 */ 100 101 if (rgb) { 102 pair->RGB.Src[candidate].Used = 1; 103 pair->RGB.Src[candidate].File = file; 104 pair->RGB.Src[candidate].Index = index; 105 if (candidate == RC_PAIR_PRESUB_SRC) { 106 /* For registers with the RC_FILE_PRESUB file, 107 * the index stores the presubtract op. */ 108 int src_regs = rc_presubtract_src_reg_count(index); 109 for(i = 0; i < src_regs; i++) { 110 pair->RGB.Src[i].Used = 1; 111 } 112 } 113 } 114 if (alpha) { 115 pair->Alpha.Src[candidate].Used = 1; 116 pair->Alpha.Src[candidate].File = file; 117 pair->Alpha.Src[candidate].Index = index; 118 if (candidate == RC_PAIR_PRESUB_SRC) { 119 /* For registers with the RC_FILE_PRESUB file, 120 * the index stores the presubtract op. */ 121 int src_regs = rc_presubtract_src_reg_count(index); 122 for(i=0; i < src_regs; i++) { 123 pair->Alpha.Src[i].Used = 1; 124 } 125 } 126 } 127 128 return candidate; 129} 130 131static void pair_foreach_source_callback( 132 struct rc_pair_instruction * pair, 133 void * data, 134 rc_pair_foreach_src_fn cb, 135 unsigned int swz, 136 unsigned int src) 137{ 138 /* swz > 3 means that the swizzle is either not used, or a constant 139 * swizzle (e.g. 0, 1, 0.5). */ 140 if(swz > 3) 141 return; 142 143 if(swz == RC_SWIZZLE_W) { 144 if (src == RC_PAIR_PRESUB_SRC) { 145 unsigned int i; 146 unsigned int src_count = rc_presubtract_src_reg_count( 147 pair->Alpha.Src[RC_PAIR_PRESUB_SRC].Index); 148 for(i = 0; i < src_count; i++) { 149 cb(data, &pair->Alpha.Src[i]); 150 } 151 } else { 152 cb(data, &pair->Alpha.Src[src]); 153 } 154 } else { 155 if (src == RC_PAIR_PRESUB_SRC) { 156 unsigned int i; 157 unsigned int src_count = rc_presubtract_src_reg_count( 158 pair->RGB.Src[RC_PAIR_PRESUB_SRC].Index); 159 for(i = 0; i < src_count; i++) { 160 cb(data, &pair->RGB.Src[i]); 161 } 162 } 163 else { 164 cb(data, &pair->RGB.Src[src]); 165 } 166 } 167} 168 169void rc_pair_foreach_source_that_alpha_reads( 170 struct rc_pair_instruction * pair, 171 void * data, 172 rc_pair_foreach_src_fn cb) 173{ 174 unsigned int i; 175 const struct rc_opcode_info * info = 176 rc_get_opcode_info(pair->Alpha.Opcode); 177 for(i = 0; i < info->NumSrcRegs; i++) { 178 pair_foreach_source_callback(pair, data, cb, 179 GET_SWZ(pair->Alpha.Arg[i].Swizzle, 0), 180 pair->Alpha.Arg[i].Source); 181 } 182} 183 184void rc_pair_foreach_source_that_rgb_reads( 185 struct rc_pair_instruction * pair, 186 void * data, 187 rc_pair_foreach_src_fn cb) 188{ 189 unsigned int i; 190 const struct rc_opcode_info * info = 191 rc_get_opcode_info(pair->RGB.Opcode); 192 for(i = 0; i < info->NumSrcRegs; i++) { 193 unsigned int chan; 194 unsigned int swz = RC_SWIZZLE_UNUSED; 195 /* Find a swizzle that is either X,Y,Z,or W. We assume here 196 * that if one channel swizzles X,Y, or Z, then none of the 197 * other channels swizzle W, and vice-versa. */ 198 for(chan = 0; chan < 4; chan++) { 199 swz = GET_SWZ(pair->RGB.Arg[i].Swizzle, chan); 200 if(swz == RC_SWIZZLE_X || swz == RC_SWIZZLE_Y 201 || swz == RC_SWIZZLE_Z || swz == RC_SWIZZLE_W) 202 continue; 203 } 204 pair_foreach_source_callback(pair, data, cb, 205 swz, 206 pair->RGB.Arg[i].Source); 207 } 208} 209 210struct rc_pair_instruction_source * rc_pair_get_src( 211 struct rc_pair_instruction * pair_inst, 212 struct rc_pair_instruction_arg * arg) 213{ 214 unsigned int type; 215 216 type = rc_source_type_swz(arg->Swizzle); 217 218 if (type & RC_SOURCE_RGB) { 219 return &pair_inst->RGB.Src[arg->Source]; 220 } else if (type & RC_SOURCE_ALPHA) { 221 return &pair_inst->Alpha.Src[arg->Source]; 222 } else { 223 return NULL; 224 } 225} 226 227int rc_pair_get_src_index( 228 struct rc_pair_instruction * pair_inst, 229 struct rc_pair_instruction_source * src) 230{ 231 int i; 232 for (i = 0; i < 3; i++) { 233 if (&pair_inst->RGB.Src[i] == src 234 || &pair_inst->Alpha.Src[i] == src) { 235 return i; 236 } 237 } 238 return -1; 239} 240