1 /* 2 * Copyright (C) 2011 Red Hat Inc. 3 * 4 * block compression parts are: 5 * Copyright (C) 2004 Roland Scheidegger All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the next 15 * paragraph) shall be included in all copies or substantial portions of the 16 * Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 * DEALINGS IN THE SOFTWARE. 25 * 26 * Author: 27 * Dave Airlie 28 */ 29 30 /* included by texcompress_rgtc to define byte/ubyte compressors */ 31 32 static void TAG(fetch_texel_rgtc)(unsigned srcRowStride, const TYPE *pixdata, 33 unsigned i, unsigned j, TYPE *value, unsigned comps) 34 { 35 TYPE decode; 36 const TYPE *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8 * comps); 37 const TYPE alpha0 = blksrc[0]; 38 const TYPE alpha1 = blksrc[1]; 39 const char bit_pos = ((j&3) * 4 + (i&3)) * 3; 40 const TYPE acodelow = blksrc[2 + bit_pos / 8]; 41 const TYPE acodehigh = (3 + bit_pos / 8) < 8 ? blksrc[3 + bit_pos / 8] : 0; 42 const TYPE code = (acodelow >> (bit_pos & 0x7) | 43 (acodehigh << (8 - (bit_pos & 0x7)))) & 0x7; 44 45 if (code == 0) 46 decode = alpha0; 47 else if (code == 1) 48 decode = alpha1; 49 else if (alpha0 > alpha1) 50 decode = ((alpha0 * (8 - code) + (alpha1 * (code - 1))) / 7); 51 else if (code < 6) 52 decode = ((alpha0 * (6 - code) + (alpha1 * (code - 1))) / 5); 53 else if (code == 6) 54 decode = T_MIN; 55 else 56 decode = T_MAX; 57 58 *value = decode; 59 } 60 61 static void TAG(write_rgtc_encoded_channel)(TYPE *blkaddr, 62 TYPE alphabase1, 63 TYPE alphabase2, 64 TYPE alphaenc[16]) 65 { 66 *blkaddr++ = alphabase1; 67 *blkaddr++ = alphabase2; 68 *blkaddr++ = alphaenc[0] | (alphaenc[1] << 3) | ((alphaenc[2] & 3) << 6); 69 *blkaddr++ = (alphaenc[2] >> 2) | (alphaenc[3] << 1) | (alphaenc[4] << 4) | ((alphaenc[5] & 1) << 7); 70 *blkaddr++ = (alphaenc[5] >> 1) | (alphaenc[6] << 2) | (alphaenc[7] << 5); 71 *blkaddr++ = alphaenc[8] | (alphaenc[9] << 3) | ((alphaenc[10] & 3) << 6); 72 *blkaddr++ = (alphaenc[10] >> 2) | (alphaenc[11] << 1) | (alphaenc[12] << 4) | ((alphaenc[13] & 1) << 7); 73 *blkaddr++ = (alphaenc[13] >> 1) | (alphaenc[14] << 2) | (alphaenc[15] << 5); 74 } 75 76 static void TAG(encode_rgtc_ubyte)(TYPE *blkaddr, TYPE srccolors[4][4], 77 int numxpixels, int numypixels) 78 { 79 TYPE alphabase[2], alphause[2]; 80 short alphatest[2] = { 0 }; 81 unsigned int alphablockerror1, alphablockerror2, alphablockerror3; 82 TYPE i, j, aindex, acutValues[7]; 83 TYPE alphaenc1[16], alphaenc2[16], alphaenc3[16]; 84 int alphaabsmin = 0, alphaabsmax = 0; 85 short alphadist; 86 87 /* find lowest and highest alpha value in block, alphabase[0] lowest, alphabase[1] highest */ 88 alphabase[0] = T_MAX; alphabase[1] = T_MIN; 89 for (j = 0; j < numypixels; j++) { 90 for (i = 0; i < numxpixels; i++) { 91 if (srccolors[j][i] == T_MIN) 92 alphaabsmin = 1; 93 else if (srccolors[j][i] == T_MAX) 94 alphaabsmax = 1; 95 else { 96 if (srccolors[j][i] > alphabase[1]) 97 alphabase[1] = srccolors[j][i]; 98 if (srccolors[j][i] < alphabase[0]) 99 alphabase[0] = srccolors[j][i]; 100 } 101 } 102 } 103 104 105 if (((alphabase[0] > alphabase[1]) && !(alphaabsmin && alphaabsmax)) 106 || (alphabase[0] == alphabase[1] && !alphaabsmin && !alphaabsmax)) { /* one color, either max or min */ 107 /* shortcut here since it is a very common case (and also avoids later problems) */ 108 /* could also thest for alpha0 == alpha1 (and not min/max), but probably not common, so don't bother */ 109 110 *blkaddr++ = srccolors[0][0]; 111 blkaddr++; 112 *blkaddr++ = 0; 113 *blkaddr++ = 0; 114 *blkaddr++ = 0; 115 *blkaddr++ = 0; 116 *blkaddr++ = 0; 117 *blkaddr++ = 0; 118 #if RGTC_DEBUG 119 fprintf(stderr, "enc0 used\n"); 120 #endif 121 return; 122 } 123 124 /* find best encoding for alpha0 > alpha1 */ 125 /* it's possible this encoding is better even if both alphaabsmin and alphaabsmax are true */ 126 alphablockerror1 = 0x0; 127 alphablockerror2 = 0xffffffff; 128 alphablockerror3 = 0xffffffff; 129 if (alphaabsmin) alphause[0] = T_MIN; 130 else alphause[0] = alphabase[0]; 131 if (alphaabsmax) alphause[1] = T_MAX; 132 else alphause[1] = alphabase[1]; 133 /* calculate the 7 cut values, just the middle between 2 of the computed alpha values */ 134 for (aindex = 0; aindex < 7; aindex++) { 135 /* don't forget here is always rounded down */ 136 acutValues[aindex] = (alphause[0] * (2*aindex + 1) + alphause[1] * (14 - (2*aindex + 1))) / 14; 137 } 138 139 for (j = 0; j < numypixels; j++) { 140 for (i = 0; i < numxpixels; i++) { 141 /* maybe it's overkill to have the most complicated calculation just for the error 142 calculation which we only need to figure out if encoding1 or encoding2 is better... */ 143 if (srccolors[j][i] > acutValues[0]) { 144 alphaenc1[4*j + i] = 0; 145 alphadist = srccolors[j][i] - alphause[1]; 146 } 147 else if (srccolors[j][i] > acutValues[1]) { 148 alphaenc1[4*j + i] = 2; 149 alphadist = srccolors[j][i] - (alphause[1] * 6 + alphause[0] * 1) / 7; 150 } 151 else if (srccolors[j][i] > acutValues[2]) { 152 alphaenc1[4*j + i] = 3; 153 alphadist = srccolors[j][i] - (alphause[1] * 5 + alphause[0] * 2) / 7; 154 } 155 else if (srccolors[j][i] > acutValues[3]) { 156 alphaenc1[4*j + i] = 4; 157 alphadist = srccolors[j][i] - (alphause[1] * 4 + alphause[0] * 3) / 7; 158 } 159 else if (srccolors[j][i] > acutValues[4]) { 160 alphaenc1[4*j + i] = 5; 161 alphadist = srccolors[j][i] - (alphause[1] * 3 + alphause[0] * 4) / 7; 162 } 163 else if (srccolors[j][i] > acutValues[5]) { 164 alphaenc1[4*j + i] = 6; 165 alphadist = srccolors[j][i] - (alphause[1] * 2 + alphause[0] * 5) / 7; 166 } 167 else if (srccolors[j][i] > acutValues[6]) { 168 alphaenc1[4*j + i] = 7; 169 alphadist = srccolors[j][i] - (alphause[1] * 1 + alphause[0] * 6) / 7; 170 } 171 else { 172 alphaenc1[4*j + i] = 1; 173 alphadist = srccolors[j][i] - alphause[0]; 174 } 175 alphablockerror1 += alphadist * alphadist; 176 } 177 } 178 179 #if RGTC_DEBUG 180 for (i = 0; i < 16; i++) { 181 fprintf(stderr, "%d ", alphaenc1[i]); 182 } 183 fprintf(stderr, "cutVals "); 184 for (i = 0; i < 7; i++) { 185 fprintf(stderr, "%d ", acutValues[i]); 186 } 187 fprintf(stderr, "srcVals "); 188 for (j = 0; j < numypixels; j++) { 189 for (i = 0; i < numxpixels; i++) { 190 fprintf(stderr, "%d ", srccolors[j][i]); 191 } 192 } 193 fprintf(stderr, "\n"); 194 #endif 195 196 /* it's not very likely this encoding is better if both alphaabsmin and alphaabsmax 197 are false but try it anyway */ 198 if (alphablockerror1 >= 32) { 199 200 /* don't bother if encoding is already very good, this condition should also imply 201 we have valid alphabase colors which we absolutely need (alphabase[0] <= alphabase[1]) */ 202 alphablockerror2 = 0; 203 for (aindex = 0; aindex < 5; aindex++) { 204 /* don't forget here is always rounded down */ 205 acutValues[aindex] = (alphabase[0] * (10 - (2*aindex + 1)) + alphabase[1] * (2*aindex + 1)) / 10; 206 } 207 for (j = 0; j < numypixels; j++) { 208 for (i = 0; i < numxpixels; i++) { 209 /* maybe it's overkill to have the most complicated calculation just for the error 210 calculation which we only need to figure out if encoding1 or encoding2 is better... */ 211 if (srccolors[j][i] == T_MIN) { 212 alphaenc2[4*j + i] = 6; 213 alphadist = 0; 214 } 215 else if (srccolors[j][i] == T_MAX) { 216 alphaenc2[4*j + i] = 7; 217 alphadist = 0; 218 } 219 else if (srccolors[j][i] <= acutValues[0]) { 220 alphaenc2[4*j + i] = 0; 221 alphadist = srccolors[j][i] - alphabase[0]; 222 } 223 else if (srccolors[j][i] <= acutValues[1]) { 224 alphaenc2[4*j + i] = 2; 225 alphadist = srccolors[j][i] - (alphabase[0] * 4 + alphabase[1] * 1) / 5; 226 } 227 else if (srccolors[j][i] <= acutValues[2]) { 228 alphaenc2[4*j + i] = 3; 229 alphadist = srccolors[j][i] - (alphabase[0] * 3 + alphabase[1] * 2) / 5; 230 } 231 else if (srccolors[j][i] <= acutValues[3]) { 232 alphaenc2[4*j + i] = 4; 233 alphadist = srccolors[j][i] - (alphabase[0] * 2 + alphabase[1] * 3) / 5; 234 } 235 else if (srccolors[j][i] <= acutValues[4]) { 236 alphaenc2[4*j + i] = 5; 237 alphadist = srccolors[j][i] - (alphabase[0] * 1 + alphabase[1] * 4) / 5; 238 } 239 else { 240 alphaenc2[4*j + i] = 1; 241 alphadist = srccolors[j][i] - alphabase[1]; 242 } 243 alphablockerror2 += alphadist * alphadist; 244 } 245 } 246 247 248 /* skip this if the error is already very small 249 this encoding is MUCH better on average than #2 though, but expensive! */ 250 if ((alphablockerror2 > 96) && (alphablockerror1 > 96)) { 251 short blockerrlin1 = 0; 252 short blockerrlin2 = 0; 253 TYPE nralphainrangelow = 0; 254 TYPE nralphainrangehigh = 0; 255 alphatest[0] = T_MAX; 256 alphatest[1] = T_MIN; 257 /* if we have large range it's likely there are values close to 0/255, try to map them to 0/255 */ 258 for (j = 0; j < numypixels; j++) { 259 for (i = 0; i < numxpixels; i++) { 260 if ((srccolors[j][i] > alphatest[1]) && (srccolors[j][i] < (T_MAX -(alphabase[1] - alphabase[0]) / 28))) 261 alphatest[1] = srccolors[j][i]; 262 if ((srccolors[j][i] < alphatest[0]) && (srccolors[j][i] > (alphabase[1] - alphabase[0]) / 28)) 263 alphatest[0] = srccolors[j][i]; 264 } 265 } 266 /* shouldn't happen too often, don't really care about those degenerated cases */ 267 if (alphatest[1] <= alphatest[0]) { 268 alphatest[0] = T_MIN+1; 269 alphatest[1] = T_MAX-1; 270 } 271 for (aindex = 0; aindex < 5; aindex++) { 272 /* don't forget here is always rounded down */ 273 acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10; 274 } 275 276 /* find the "average" difference between the alpha values and the next encoded value. 277 This is then used to calculate new base values. 278 Should there be some weighting, i.e. those values closer to alphatest[x] have more weight, 279 since they will see more improvement, and also because the values in the middle are somewhat 280 likely to get no improvement at all (because the base values might move in different directions)? 281 OTOH it would mean the values in the middle are even less likely to get an improvement 282 */ 283 for (j = 0; j < numypixels; j++) { 284 for (i = 0; i < numxpixels; i++) { 285 if (srccolors[j][i] <= alphatest[0] / 2) { 286 } 287 else if (srccolors[j][i] > ((T_MAX + alphatest[1]) / 2)) { 288 } 289 else if (srccolors[j][i] <= acutValues[0]) { 290 blockerrlin1 += (srccolors[j][i] - alphatest[0]); 291 nralphainrangelow += 1; 292 } 293 else if (srccolors[j][i] <= acutValues[1]) { 294 blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5); 295 blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5); 296 nralphainrangelow += 1; 297 nralphainrangehigh += 1; 298 } 299 else if (srccolors[j][i] <= acutValues[2]) { 300 blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5); 301 blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5); 302 nralphainrangelow += 1; 303 nralphainrangehigh += 1; 304 } 305 else if (srccolors[j][i] <= acutValues[3]) { 306 blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5); 307 blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5); 308 nralphainrangelow += 1; 309 nralphainrangehigh += 1; 310 } 311 else if (srccolors[j][i] <= acutValues[4]) { 312 blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5); 313 blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5); 314 nralphainrangelow += 1; 315 nralphainrangehigh += 1; 316 } 317 else { 318 blockerrlin2 += (srccolors[j][i] - alphatest[1]); 319 nralphainrangehigh += 1; 320 } 321 } 322 } 323 /* shouldn't happen often, needed to avoid div by zero */ 324 if (nralphainrangelow == 0) nralphainrangelow = 1; 325 if (nralphainrangehigh == 0) nralphainrangehigh = 1; 326 alphatest[0] = alphatest[0] + (blockerrlin1 / nralphainrangelow); 327 #if RGTC_DEBUG 328 fprintf(stderr, "block err lin low %d, nr %d\n", blockerrlin1, nralphainrangelow); 329 fprintf(stderr, "block err lin high %d, nr %d\n", blockerrlin2, nralphainrangehigh); 330 #endif 331 /* again shouldn't really happen often... */ 332 if (alphatest[0] < T_MIN) { 333 alphatest[0] = T_MIN; 334 } 335 alphatest[1] = alphatest[1] + (blockerrlin2 / nralphainrangehigh); 336 if (alphatest[1] > T_MAX) { 337 alphatest[1] = T_MAX; 338 } 339 340 alphablockerror3 = 0; 341 for (aindex = 0; aindex < 5; aindex++) { 342 /* don't forget here is always rounded down */ 343 acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10; 344 } 345 for (j = 0; j < numypixels; j++) { 346 for (i = 0; i < numxpixels; i++) { 347 /* maybe it's overkill to have the most complicated calculation just for the error 348 calculation which we only need to figure out if encoding1 or encoding2 is better... */ 349 if (srccolors[j][i] <= alphatest[0] / 2) { 350 alphaenc3[4*j + i] = 6; 351 alphadist = srccolors[j][i]; 352 } 353 else if (srccolors[j][i] > ((T_MAX + alphatest[1]) / 2)) { 354 alphaenc3[4*j + i] = 7; 355 alphadist = T_MAX - srccolors[j][i]; 356 } 357 else if (srccolors[j][i] <= acutValues[0]) { 358 alphaenc3[4*j + i] = 0; 359 alphadist = srccolors[j][i] - alphatest[0]; 360 } 361 else if (srccolors[j][i] <= acutValues[1]) { 362 alphaenc3[4*j + i] = 2; 363 alphadist = srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5; 364 } 365 else if (srccolors[j][i] <= acutValues[2]) { 366 alphaenc3[4*j + i] = 3; 367 alphadist = srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5; 368 } 369 else if (srccolors[j][i] <= acutValues[3]) { 370 alphaenc3[4*j + i] = 4; 371 alphadist = srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5; 372 } 373 else if (srccolors[j][i] <= acutValues[4]) { 374 alphaenc3[4*j + i] = 5; 375 alphadist = srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5; 376 } 377 else { 378 alphaenc3[4*j + i] = 1; 379 alphadist = srccolors[j][i] - alphatest[1]; 380 } 381 alphablockerror3 += alphadist * alphadist; 382 } 383 } 384 } 385 } 386 387 /* write the alpha values and encoding back. */ 388 if ((alphablockerror1 <= alphablockerror2) && (alphablockerror1 <= alphablockerror3)) { 389 #if RGTC_DEBUG 390 if (alphablockerror1 > 96) fprintf(stderr, "enc1 used, error %d\n", alphablockerror1); 391 fprintf(stderr,"w1: min %d max %d au0 %d au1 %d\n", 392 T_MIN, T_MAX, 393 alphause[1], alphause[0]); 394 #endif 395 396 TAG(write_rgtc_encoded_channel)( blkaddr, alphause[1], alphause[0], alphaenc1 ); 397 } 398 else if (alphablockerror2 <= alphablockerror3) { 399 #if RGTC_DEBUG 400 if (alphablockerror2 > 96) fprintf(stderr, "enc2 used, error %d\n", alphablockerror2); 401 fprintf(stderr,"w2: min %d max %d au0 %d au1 %d\n", 402 T_MIN, T_MAX, 403 alphabase[0], alphabase[1]); 404 #endif 405 406 TAG(write_rgtc_encoded_channel)( blkaddr, alphabase[0], alphabase[1], alphaenc2 ); 407 } 408 else { 409 #if RGTC_DEBUG 410 fprintf(stderr, "enc3 used, error %d\n", alphablockerror3); 411 fprintf(stderr,"w3: min %d max %d au0 %d au1 %d\n", 412 T_MIN, T_MAX, 413 alphatest[0], alphatest[1]); 414 #endif 415 416 TAG(write_rgtc_encoded_channel)( blkaddr, (TYPE)alphatest[0], (TYPE)alphatest[1], alphaenc3 ); 417 } 418 } 419