1// Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15#include "ETC_Decoder.hpp" 16 17namespace 18{ 19 inline int clampByte(int value) 20 { 21 return (value < 0) ? 0 : ((value > 255) ? 255 : value); 22 } 23 24 inline int clampSByte(int value) 25 { 26 return (value < -128) ? -128 : ((value > 127) ? 127 : value); 27 } 28 29 inline int clampEAC(int value, bool isSigned) 30 { 31 int min = isSigned ? -1023 : 0; 32 int max = isSigned ? 1023 : 2047; 33 return (value < min) ? min : ((value > max) ? max : value); 34 } 35 36 struct bgra8 37 { 38 unsigned char b; 39 unsigned char g; 40 unsigned char r; 41 unsigned char a; 42 43 inline bgra8() 44 { 45 } 46 47 inline void set(int red, int green, int blue) 48 { 49 r = static_cast<unsigned char>(clampByte(red)); 50 g = static_cast<unsigned char>(clampByte(green)); 51 b = static_cast<unsigned char>(clampByte(blue)); 52 } 53 54 inline void set(int red, int green, int blue, int alpha) 55 { 56 r = static_cast<unsigned char>(clampByte(red)); 57 g = static_cast<unsigned char>(clampByte(green)); 58 b = static_cast<unsigned char>(clampByte(blue)); 59 a = static_cast<unsigned char>(clampByte(alpha)); 60 } 61 62 const bgra8& addA(int alpha) 63 { 64 a = alpha; 65 return *this; 66 } 67 }; 68 69 inline int extend_4to8bits(int x) 70 { 71 return (x << 4) | x; 72 } 73 74 inline int extend_5to8bits(int x) 75 { 76 return (x << 3) | (x >> 2); 77 } 78 79 inline int extend_6to8bits(int x) 80 { 81 return (x << 2) | (x >> 4); 82 } 83 84 inline int extend_7to8bits(int x) 85 { 86 return (x << 1) | (x >> 6); 87 } 88 89 struct ETC2 90 { 91 // Decodes unsigned single or dual channel block to bytes 92 static void DecodeBlock(const ETC2** sources, unsigned char *dest, int nbChannels, int x, int y, int w, int h, int pitch, bool isSigned, bool isEAC) 93 { 94 if(isEAC) 95 { 96 for(int j = 0; j < 4 && (y + j) < h; j++) 97 { 98 int* sDst = reinterpret_cast<int*>(dest); 99 for(int i = 0; i < 4 && (x + i) < w; i++) 100 { 101 for(int c = nbChannels - 1; c >= 0; c--) 102 { 103 sDst[i * nbChannels + c] = clampEAC(sources[c]->getSingleChannel(i, j, isSigned, true), isSigned); 104 } 105 } 106 dest += pitch; 107 } 108 } 109 else 110 { 111 if(isSigned) 112 { 113 signed char* sDst = reinterpret_cast<signed char*>(dest); 114 for(int j = 0; j < 4 && (y + j) < h; j++) 115 { 116 for(int i = 0; i < 4 && (x + i) < w; i++) 117 { 118 for(int c = nbChannels - 1; c >= 0; c--) 119 { 120 sDst[i * nbChannels + c] = clampSByte(sources[c]->getSingleChannel(i, j, isSigned, false)); 121 } 122 } 123 sDst += pitch; 124 } 125 } 126 else 127 { 128 for(int j = 0; j < 4 && (y + j) < h; j++) 129 { 130 for(int i = 0; i < 4 && (x + i) < w; i++) 131 { 132 for(int c = nbChannels - 1; c >= 0; c--) 133 { 134 dest[i * nbChannels + c] = clampByte(sources[c]->getSingleChannel(i, j, isSigned, false)); 135 } 136 } 137 dest += pitch; 138 } 139 } 140 } 141 } 142 143 // Decodes RGB block to bgra8 144 void decodeBlock(unsigned char *dest, int x, int y, int w, int h, int pitch, unsigned char alphaValues[4][4], bool punchThroughAlpha) const 145 { 146 bool opaqueBit = diffbit; 147 bool nonOpaquePunchThroughAlpha = punchThroughAlpha && !opaqueBit; 148 149 // Select mode 150 if(diffbit || punchThroughAlpha) 151 { 152 int r = (R + dR); 153 int g = (G + dG); 154 int b = (B + dB); 155 if(r < 0 || r > 31) 156 { 157 decodeTBlock(dest, x, y, w, h, pitch, alphaValues, nonOpaquePunchThroughAlpha); 158 } 159 else if(g < 0 || g > 31) 160 { 161 decodeHBlock(dest, x, y, w, h, pitch, alphaValues, nonOpaquePunchThroughAlpha); 162 } 163 else if(b < 0 || b > 31) 164 { 165 decodePlanarBlock(dest, x, y, w, h, pitch, alphaValues); 166 } 167 else 168 { 169 decodeDifferentialBlock(dest, x, y, w, h, pitch, alphaValues, nonOpaquePunchThroughAlpha); 170 } 171 } 172 else 173 { 174 decodeIndividualBlock(dest, x, y, w, h, pitch, alphaValues, nonOpaquePunchThroughAlpha); 175 } 176 } 177 178 private: 179 struct 180 { 181 union 182 { 183 // Individual, differential, H and T modes 184 struct 185 { 186 union 187 { 188 // Individual and differential modes 189 struct 190 { 191 union 192 { 193 struct // Individual colors 194 { 195 unsigned char R2 : 4; 196 unsigned char R1 : 4; 197 unsigned char G2 : 4; 198 unsigned char G1 : 4; 199 unsigned char B2 : 4; 200 unsigned char B1 : 4; 201 }; 202 203 struct // Differential colors 204 { 205 signed char dR : 3; 206 unsigned char R : 5; 207 signed char dG : 3; 208 unsigned char G : 5; 209 signed char dB : 3; 210 unsigned char B : 5; 211 }; 212 }; 213 214 bool flipbit : 1; 215 bool diffbit : 1; 216 unsigned char cw2 : 3; 217 unsigned char cw1 : 3; 218 }; 219 220 // T mode 221 struct 222 { 223 // Byte 1 224 unsigned char TR1b : 2; 225 unsigned char TdummyB : 1; 226 unsigned char TR1a : 2; 227 unsigned char TdummyA : 3; 228 229 // Byte 2 230 unsigned char TB1 : 4; 231 unsigned char TG1 : 4; 232 233 // Byte 3 234 unsigned char TG2 : 4; 235 unsigned char TR2 : 4; 236 237 // Byte 4 238 unsigned char Tdb : 1; 239 bool Tflipbit : 1; 240 unsigned char Tda : 2; 241 unsigned char TB2 : 4; 242 }; 243 244 // H mode 245 struct 246 { 247 // Byte 1 248 unsigned char HG1a : 3; 249 unsigned char HR1 : 4; 250 unsigned char HdummyA : 1; 251 252 // Byte 2 253 unsigned char HB1b : 2; 254 unsigned char HdummyC : 1; 255 unsigned char HB1a : 1; 256 unsigned char HG1b : 1; 257 unsigned char HdummyB : 3; 258 259 // Byte 3 260 unsigned char HG2a : 3; 261 unsigned char HR2 : 4; 262 unsigned char HB1c : 1; 263 264 // Byte 4 265 unsigned char Hdb : 1; 266 bool Hflipbit : 1; 267 unsigned char Hda : 1; 268 unsigned char HB2 : 4; 269 unsigned char HG2b : 1; 270 }; 271 }; 272 273 unsigned char pixelIndexMSB[2]; 274 unsigned char pixelIndexLSB[2]; 275 }; 276 277 // planar mode 278 struct 279 { 280 // Byte 1 281 unsigned char GO1 : 1; 282 unsigned char RO : 6; 283 unsigned char PdummyA : 1; 284 285 // Byte 2 286 unsigned char BO1 : 1; 287 unsigned char GO2 : 6; 288 unsigned char PdummyB : 1; 289 290 // Byte 3 291 unsigned char BO3a : 2; 292 unsigned char PdummyD : 1; 293 unsigned char BO2 : 2; 294 unsigned char PdummyC : 3; 295 296 // Byte 4 297 unsigned char RH2 : 1; 298 bool Pflipbit : 1; 299 unsigned char RH1 : 5; 300 unsigned char BO3b : 1; 301 302 // Byte 5 303 unsigned char BHa : 1; 304 unsigned char GH : 7; 305 306 // Byte 6 307 unsigned char RVa : 3; 308 unsigned char BHb : 5; 309 310 // Byte 7 311 unsigned char GVa : 5; 312 unsigned char RVb : 3; 313 314 // Byte 8 315 unsigned char BV : 6; 316 unsigned char GVb : 2; 317 }; 318 319 // Single channel block 320 struct 321 { 322 union 323 { 324 unsigned char base_codeword; 325 signed char signed_base_codeword; 326 }; 327 328 unsigned char table_index : 4; 329 unsigned char multiplier : 4; 330 331 unsigned char mc1 : 2; 332 unsigned char mb : 3; 333 unsigned char ma : 3; 334 335 unsigned char mf1 : 1; 336 unsigned char me : 3; 337 unsigned char md : 3; 338 unsigned char mc2 : 1; 339 340 unsigned char mh : 3; 341 unsigned char mg : 3; 342 unsigned char mf2 : 2; 343 344 unsigned char mk1 : 2; 345 unsigned char mj : 3; 346 unsigned char mi : 3; 347 348 unsigned char mn1 : 1; 349 unsigned char mm : 3; 350 unsigned char ml : 3; 351 unsigned char mk2 : 1; 352 353 unsigned char mp : 3; 354 unsigned char mo : 3; 355 unsigned char mn2 : 2; 356 }; 357 }; 358 }; 359 360 void decodeIndividualBlock(unsigned char *dest, int x, int y, int w, int h, int pitch, unsigned char alphaValues[4][4], bool nonOpaquePunchThroughAlpha) const 361 { 362 int r1 = extend_4to8bits(R1); 363 int g1 = extend_4to8bits(G1); 364 int b1 = extend_4to8bits(B1); 365 366 int r2 = extend_4to8bits(R2); 367 int g2 = extend_4to8bits(G2); 368 int b2 = extend_4to8bits(B2); 369 370 decodeIndividualOrDifferentialBlock(dest, x, y, w, h, pitch, r1, g1, b1, r2, g2, b2, alphaValues, nonOpaquePunchThroughAlpha); 371 } 372 373 void decodeDifferentialBlock(unsigned char *dest, int x, int y, int w, int h, int pitch, unsigned char alphaValues[4][4], bool nonOpaquePunchThroughAlpha) const 374 { 375 int b1 = extend_5to8bits(B); 376 int g1 = extend_5to8bits(G); 377 int r1 = extend_5to8bits(R); 378 379 int r2 = extend_5to8bits(R + dR); 380 int g2 = extend_5to8bits(G + dG); 381 int b2 = extend_5to8bits(B + dB); 382 383 decodeIndividualOrDifferentialBlock(dest, x, y, w, h, pitch, r1, g1, b1, r2, g2, b2, alphaValues, nonOpaquePunchThroughAlpha); 384 } 385 386 void decodeIndividualOrDifferentialBlock(unsigned char *dest, int x, int y, int w, int h, int pitch, int r1, int g1, int b1, int r2, int g2, int b2, unsigned char alphaValues[4][4], bool nonOpaquePunchThroughAlpha) const 387 { 388 // Table 3.17.2 sorted according to table 3.17.3 389 static const int intensityModifierDefault[8][4] = 390 { 391 { 2, 8, -2, -8 }, 392 { 5, 17, -5, -17 }, 393 { 9, 29, -9, -29 }, 394 { 13, 42, -13, -42 }, 395 { 18, 60, -18, -60 }, 396 { 24, 80, -24, -80 }, 397 { 33, 106, -33, -106 }, 398 { 47, 183, -47, -183 } 399 }; 400 401 // Table C.12, intensity modifier for non opaque punchthrough alpha 402 static const int intensityModifierNonOpaque[8][4] = 403 { 404 { 0, 8, 0, -8 }, 405 { 0, 17, 0, -17 }, 406 { 0, 29, 0, -29 }, 407 { 0, 42, 0, -42 }, 408 { 0, 60, 0, -60 }, 409 { 0, 80, 0, -80 }, 410 { 0, 106, 0, -106 }, 411 { 0, 183, 0, -183 } 412 }; 413 414 const int(&intensityModifier)[8][4] = nonOpaquePunchThroughAlpha ? intensityModifierNonOpaque : intensityModifierDefault; 415 416 bgra8 subblockColors0[4]; 417 bgra8 subblockColors1[4]; 418 419 const int i10 = intensityModifier[cw1][0]; 420 const int i11 = intensityModifier[cw1][1]; 421 const int i12 = intensityModifier[cw1][2]; 422 const int i13 = intensityModifier[cw1][3]; 423 424 subblockColors0[0].set(r1 + i10, g1 + i10, b1 + i10); 425 subblockColors0[1].set(r1 + i11, g1 + i11, b1 + i11); 426 subblockColors0[2].set(r1 + i12, g1 + i12, b1 + i12); 427 subblockColors0[3].set(r1 + i13, g1 + i13, b1 + i13); 428 429 const int i20 = intensityModifier[cw2][0]; 430 const int i21 = intensityModifier[cw2][1]; 431 const int i22 = intensityModifier[cw2][2]; 432 const int i23 = intensityModifier[cw2][3]; 433 434 subblockColors1[0].set(r2 + i20, g2 + i20, b2 + i20); 435 subblockColors1[1].set(r2 + i21, g2 + i21, b2 + i21); 436 subblockColors1[2].set(r2 + i22, g2 + i22, b2 + i22); 437 subblockColors1[3].set(r2 + i23, g2 + i23, b2 + i23); 438 439 unsigned char* destStart = dest; 440 441 if(flipbit) 442 { 443 for(int j = 0; j < 2 && (y + j) < h; j++) 444 { 445 bgra8* color = (bgra8*)dest; 446 if((x + 0) < w) color[0] = subblockColors0[getIndex(0, j)].addA(alphaValues[j][0]); 447 if((x + 1) < w) color[1] = subblockColors0[getIndex(1, j)].addA(alphaValues[j][1]); 448 if((x + 2) < w) color[2] = subblockColors0[getIndex(2, j)].addA(alphaValues[j][2]); 449 if((x + 3) < w) color[3] = subblockColors0[getIndex(3, j)].addA(alphaValues[j][3]); 450 dest += pitch; 451 } 452 453 for(int j = 2; j < 4 && (y + j) < h; j++) 454 { 455 bgra8* color = (bgra8*)dest; 456 if((x + 0) < w) color[0] = subblockColors1[getIndex(0, j)].addA(alphaValues[j][0]); 457 if((x + 1) < w) color[1] = subblockColors1[getIndex(1, j)].addA(alphaValues[j][1]); 458 if((x + 2) < w) color[2] = subblockColors1[getIndex(2, j)].addA(alphaValues[j][2]); 459 if((x + 3) < w) color[3] = subblockColors1[getIndex(3, j)].addA(alphaValues[j][3]); 460 dest += pitch; 461 } 462 } 463 else 464 { 465 for(int j = 0; j < 4 && (y + j) < h; j++) 466 { 467 bgra8* color = (bgra8*)dest; 468 if((x + 0) < w) color[0] = subblockColors0[getIndex(0, j)].addA(alphaValues[j][0]); 469 if((x + 1) < w) color[1] = subblockColors0[getIndex(1, j)].addA(alphaValues[j][1]); 470 if((x + 2) < w) color[2] = subblockColors1[getIndex(2, j)].addA(alphaValues[j][2]); 471 if((x + 3) < w) color[3] = subblockColors1[getIndex(3, j)].addA(alphaValues[j][3]); 472 dest += pitch; 473 } 474 } 475 476 if(nonOpaquePunchThroughAlpha) 477 { 478 decodePunchThroughAlphaBlock(destStart, x, y, w, h, pitch); 479 } 480 } 481 482 void decodeTBlock(unsigned char *dest, int x, int y, int w, int h, int pitch, unsigned char alphaValues[4][4], bool nonOpaquePunchThroughAlpha) const 483 { 484 // Table C.8, distance index fot T and H modes 485 static const int distance[8] = { 3, 6, 11, 16, 23, 32, 41, 64 }; 486 487 bgra8 paintColors[4]; 488 489 int r1 = extend_4to8bits(TR1a << 2 | TR1b); 490 int g1 = extend_4to8bits(TG1); 491 int b1 = extend_4to8bits(TB1); 492 493 int r2 = extend_4to8bits(TR2); 494 int g2 = extend_4to8bits(TG2); 495 int b2 = extend_4to8bits(TB2); 496 497 const int d = distance[Tda << 1 | Tdb]; 498 499 paintColors[0].set(r1, g1, b1); 500 paintColors[1].set(r2 + d, g2 + d, b2 + d); 501 paintColors[2].set(r2, g2, b2); 502 paintColors[3].set(r2 - d, g2 - d, b2 - d); 503 504 unsigned char* destStart = dest; 505 506 for(int j = 0; j < 4 && (y + j) < h; j++) 507 { 508 bgra8* color = (bgra8*)dest; 509 if((x + 0) < w) color[0] = paintColors[getIndex(0, j)].addA(alphaValues[j][0]); 510 if((x + 1) < w) color[1] = paintColors[getIndex(1, j)].addA(alphaValues[j][1]); 511 if((x + 2) < w) color[2] = paintColors[getIndex(2, j)].addA(alphaValues[j][2]); 512 if((x + 3) < w) color[3] = paintColors[getIndex(3, j)].addA(alphaValues[j][3]); 513 dest += pitch; 514 } 515 516 if(nonOpaquePunchThroughAlpha) 517 { 518 decodePunchThroughAlphaBlock(destStart, x, y, w, h, pitch); 519 } 520 } 521 522 void decodeHBlock(unsigned char *dest, int x, int y, int w, int h, int pitch, unsigned char alphaValues[4][4], bool nonOpaquePunchThroughAlpha) const 523 { 524 // Table C.8, distance index fot T and H modes 525 static const int distance[8] = { 3, 6, 11, 16, 23, 32, 41, 64 }; 526 527 bgra8 paintColors[4]; 528 529 int r1 = extend_4to8bits(HR1); 530 int g1 = extend_4to8bits(HG1a << 1 | HG1b); 531 int b1 = extend_4to8bits(HB1a << 3 | HB1b << 1 | HB1c); 532 533 int r2 = extend_4to8bits(HR2); 534 int g2 = extend_4to8bits(HG2a << 1 | HG2b); 535 int b2 = extend_4to8bits(HB2); 536 537 const int d = distance[(Hda << 2) | (Hdb << 1) | ((r1 << 16 | g1 << 8 | b1) >= (r2 << 16 | g2 << 8 | b2) ? 1 : 0)]; 538 539 paintColors[0].set(r1 + d, g1 + d, b1 + d); 540 paintColors[1].set(r1 - d, g1 - d, b1 - d); 541 paintColors[2].set(r2 + d, g2 + d, b2 + d); 542 paintColors[3].set(r2 - d, g2 - d, b2 - d); 543 544 unsigned char* destStart = dest; 545 546 for(int j = 0; j < 4 && (y + j) < h; j++) 547 { 548 bgra8* color = (bgra8*)dest; 549 if((x + 0) < w) color[0] = paintColors[getIndex(0, j)].addA(alphaValues[j][0]); 550 if((x + 1) < w) color[1] = paintColors[getIndex(1, j)].addA(alphaValues[j][1]); 551 if((x + 2) < w) color[2] = paintColors[getIndex(2, j)].addA(alphaValues[j][2]); 552 if((x + 3) < w) color[3] = paintColors[getIndex(3, j)].addA(alphaValues[j][3]); 553 dest += pitch; 554 } 555 556 if(nonOpaquePunchThroughAlpha) 557 { 558 decodePunchThroughAlphaBlock(destStart, x, y, w, h, pitch); 559 } 560 } 561 562 void decodePlanarBlock(unsigned char *dest, int x, int y, int w, int h, int pitch, unsigned char alphaValues[4][4]) const 563 { 564 int ro = extend_6to8bits(RO); 565 int go = extend_7to8bits(GO1 << 6 | GO2); 566 int bo = extend_6to8bits(BO1 << 5 | BO2 << 3 | BO3a << 1 | BO3b); 567 568 int rh = extend_6to8bits(RH1 << 1 | RH2); 569 int gh = extend_7to8bits(GH); 570 int bh = extend_6to8bits(BHa << 5 | BHb); 571 572 int rv = extend_6to8bits(RVa << 3 | RVb); 573 int gv = extend_7to8bits(GVa << 2 | GVb); 574 int bv = extend_6to8bits(BV); 575 576 for(int j = 0; j < 4 && (y + j) < h; j++) 577 { 578 int ry = j * (rv - ro) + 2; 579 int gy = j * (gv - go) + 2; 580 int by = j * (bv - bo) + 2; 581 for(int i = 0; i < 4 && (x + i) < w; i++) 582 { 583 ((bgra8*)(dest))[i].set(((i * (rh - ro) + ry) >> 2) + ro, 584 ((i * (gh - go) + gy) >> 2) + go, 585 ((i * (bh - bo) + by) >> 2) + bo, 586 alphaValues[j][i]); 587 } 588 dest += pitch; 589 } 590 } 591 592 // Index for individual, differential, H and T modes 593 inline int getIndex(int x, int y) const 594 { 595 int bitIndex = x * 4 + y; 596 int bitOffset = bitIndex & 7; 597 int lsb = (pixelIndexLSB[1 - (bitIndex >> 3)] >> bitOffset) & 1; 598 int msb = (pixelIndexMSB[1 - (bitIndex >> 3)] >> bitOffset) & 1; 599 600 return (msb << 1) | lsb; 601 } 602 603 void decodePunchThroughAlphaBlock(unsigned char *dest, int x, int y, int w, int h, int pitch) const 604 { 605 for(int j = 0; j < 4 && (y + j) < h; j++) 606 { 607 for(int i = 0; i < 4 && (x + i) < w; i++) 608 { 609 if(getIndex(i, j) == 2) // msb == 1 && lsb == 0 610 { 611 ((bgra8*)dest)[i].set(0, 0, 0, 0); 612 } 613 } 614 dest += pitch; 615 } 616 } 617 618 // Single channel utility functions 619 inline int getSingleChannel(int x, int y, bool isSigned, bool isEAC) const 620 { 621 int codeword = isSigned ? signed_base_codeword : base_codeword; 622 return isEAC ? 623 ((multiplier == 0) ? 624 (codeword * 8 + 4 + getSingleChannelModifier(x, y)) : 625 (codeword * 8 + 4 + getSingleChannelModifier(x, y) * multiplier * 8)) : 626 codeword + getSingleChannelModifier(x, y) * multiplier; 627 } 628 629 inline int getSingleChannelIndex(int x, int y) const 630 { 631 switch(x * 4 + y) 632 { 633 case 0: return ma; 634 case 1: return mb; 635 case 2: return mc1 << 1 | mc2; 636 case 3: return md; 637 case 4: return me; 638 case 5: return mf1 << 2 | mf2; 639 case 6: return mg; 640 case 7: return mh; 641 case 8: return mi; 642 case 9: return mj; 643 case 10: return mk1 << 1 | mk2; 644 case 11: return ml; 645 case 12: return mm; 646 case 13: return mn1 << 2 | mn2; 647 case 14: return mo; 648 default: return mp; // 15 649 } 650 } 651 652 inline int getSingleChannelModifier(int x, int y) const 653 { 654 static const int modifierTable[16][8] = { { -3, -6, -9, -15, 2, 5, 8, 14 }, 655 { -3, -7, -10, -13, 2, 6, 9, 12 }, 656 { -2, -5, -8, -13, 1, 4, 7, 12 }, 657 { -2, -4, -6, -13, 1, 3, 5, 12 }, 658 { -3, -6, -8, -12, 2, 5, 7, 11 }, 659 { -3, -7, -9, -11, 2, 6, 8, 10 }, 660 { -4, -7, -8, -11, 3, 6, 7, 10 }, 661 { -3, -5, -8, -11, 2, 4, 7, 10 }, 662 { -2, -6, -8, -10, 1, 5, 7, 9 }, 663 { -2, -5, -8, -10, 1, 4, 7, 9 }, 664 { -2, -4, -8, -10, 1, 3, 7, 9 }, 665 { -2, -5, -7, -10, 1, 4, 6, 9 }, 666 { -3, -4, -7, -10, 2, 3, 6, 9 }, 667 { -1, -2, -3, -10, 0, 1, 2, 9 }, 668 { -4, -6, -8, -9, 3, 5, 7, 8 }, 669 { -3, -5, -7, -9, 2, 4, 6, 8 } }; 670 671 return modifierTable[table_index][getSingleChannelIndex(x, y)]; 672 } 673 }; 674} 675 676// Decodes 1 to 4 channel images to 8 bit output 677bool ETC_Decoder::Decode(const unsigned char* src, unsigned char *dst, int w, int h, int dstW, int dstH, int dstPitch, int dstBpp, InputType inputType) 678{ 679 const ETC2* sources[2]; 680 sources[0] = (const ETC2*)src; 681 682 unsigned char alphaValues[4][4] = { { 255, 255, 255, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 } }; 683 684 switch(inputType) 685 { 686 case ETC_R_SIGNED: 687 case ETC_R_UNSIGNED: 688 for(int y = 0; y < h; y += 4) 689 { 690 unsigned char *dstRow = dst + (y * dstPitch); 691 for(int x = 0; x < w; x += 4, sources[0]++) 692 { 693 ETC2::DecodeBlock(sources, dstRow + (x * dstBpp), 1, x, y, dstW, dstH, dstPitch, inputType == ETC_R_SIGNED, true); 694 } 695 } 696 break; 697 case ETC_RG_SIGNED: 698 case ETC_RG_UNSIGNED: 699 sources[1] = sources[0] + 1; 700 for(int y = 0; y < h; y += 4) 701 { 702 unsigned char *dstRow = dst + (y * dstPitch); 703 for(int x = 0; x < w; x += 4, sources[0] += 2, sources[1] += 2) 704 { 705 ETC2::DecodeBlock(sources, dstRow + (x * dstBpp), 2, x, y, dstW, dstH, dstPitch, inputType == ETC_RG_SIGNED, true); 706 } 707 } 708 break; 709 case ETC_RGB: 710 case ETC_RGB_PUNCHTHROUGH_ALPHA: 711 for(int y = 0; y < h; y += 4) 712 { 713 unsigned char *dstRow = dst + (y * dstPitch); 714 for(int x = 0; x < w; x += 4, sources[0]++) 715 { 716 sources[0]->decodeBlock(dstRow + (x * dstBpp), x, y, dstW, dstH, dstPitch, alphaValues, inputType == ETC_RGB_PUNCHTHROUGH_ALPHA); 717 } 718 } 719 break; 720 case ETC_RGBA: 721 for(int y = 0; y < h; y += 4) 722 { 723 unsigned char *dstRow = dst + (y * dstPitch); 724 for(int x = 0; x < w; x += 4) 725 { 726 // Decode Alpha 727 ETC2::DecodeBlock(&sources[0], &(alphaValues[0][0]), 1, x, y, dstW, dstH, 4, false, false); 728 sources[0]++; // RGBA packets are 128 bits, so move on to the next 64 bit packet to decode the RGB color 729 730 // Decode RGB 731 sources[0]->decodeBlock(dstRow + (x * dstBpp), x, y, dstW, dstH, dstPitch, alphaValues, false); 732 sources[0]++; 733 } 734 } 735 break; 736 default: 737 return false; 738 } 739 740 return true; 741} 742