1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2020 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/core/SkCompressedDataUtils.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h" 11cb93a386Sopenharmony_ci#include "include/core/SkColorPriv.h" 12cb93a386Sopenharmony_ci#include "include/core/SkData.h" 13cb93a386Sopenharmony_ci#include "include/private/SkColorData.h" 14cb93a386Sopenharmony_ci#include "include/private/SkTPin.h" 15cb93a386Sopenharmony_ci#include "src/core/SkMathPriv.h" 16cb93a386Sopenharmony_ci#include "src/core/SkMipmap.h" 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_cistruct ETC1Block { 19cb93a386Sopenharmony_ci uint32_t fHigh; 20cb93a386Sopenharmony_ci uint32_t fLow; 21cb93a386Sopenharmony_ci}; 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_ciconstexpr uint32_t kFlipBit = 0x1; // set -> T/B sub-blocks; not-set -> L/R sub-blocks 24cb93a386Sopenharmony_ciconstexpr uint32_t kDiffBit = 0x2; // set -> differential; not-set -> individual 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_cistatic inline int extend_4To8bits(int b) { 27cb93a386Sopenharmony_ci int c = b & 0xf; 28cb93a386Sopenharmony_ci return (c << 4) | c; 29cb93a386Sopenharmony_ci} 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_cistatic inline int extend_5To8bits(int b) { 32cb93a386Sopenharmony_ci int c = b & 0x1f; 33cb93a386Sopenharmony_ci return (c << 3) | (c >> 2); 34cb93a386Sopenharmony_ci} 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_cistatic inline int extend_5plus3To8Bits(int base, int diff) { 37cb93a386Sopenharmony_ci static const int kLookup[8] = { 0, 1, 2, 3, -4, -3, -2, -1 }; 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ci return extend_5To8bits((0x1f & base) + kLookup[0x7 & diff]); 40cb93a386Sopenharmony_ci} 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_cistatic const int kNumETC1ModifierTables = 8; 43cb93a386Sopenharmony_cistatic const int kNumETC1PixelIndices = 4; 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_ci// The index of each row in this table is the ETC1 table codeword 46cb93a386Sopenharmony_ci// The index of each column in this table is the ETC1 pixel index value 47cb93a386Sopenharmony_cistatic const int kETC1ModifierTables[kNumETC1ModifierTables][kNumETC1PixelIndices] = { 48cb93a386Sopenharmony_ci /* 0 */ { 2, 8, -2, -8 }, 49cb93a386Sopenharmony_ci /* 1 */ { 5, 17, -5, -17 }, 50cb93a386Sopenharmony_ci /* 2 */ { 9, 29, -9, -29 }, 51cb93a386Sopenharmony_ci /* 3 */ { 13, 42, -13, -42 }, 52cb93a386Sopenharmony_ci /* 4 */ { 18, 60, -18, -60 }, 53cb93a386Sopenharmony_ci /* 5 */ { 24, 80, -24, -80 }, 54cb93a386Sopenharmony_ci /* 6 */ { 33, 106, -33, -106 }, 55cb93a386Sopenharmony_ci /* 7 */ { 47, 183, -47, -183 } 56cb93a386Sopenharmony_ci}; 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_cistatic int num_4x4_blocks(int size) { 59cb93a386Sopenharmony_ci return ((size + 3) & ~3) >> 2; 60cb93a386Sopenharmony_ci} 61cb93a386Sopenharmony_ci 62cb93a386Sopenharmony_ci// Return which sub-block a given x,y location in the overall 4x4 block belongs to 63cb93a386Sopenharmony_cistatic int xy_to_subblock_index(int x, int y, bool flip) { 64cb93a386Sopenharmony_ci SkASSERT(x >= 0 && x < 4); 65cb93a386Sopenharmony_ci SkASSERT(y >= 0 && y < 4); 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ci if (flip) { 68cb93a386Sopenharmony_ci return y < 2 ? 0 : 1; // sub-block 1 is on top of sub-block 2 69cb93a386Sopenharmony_ci } else { 70cb93a386Sopenharmony_ci return x < 2 ? 0 : 1; // sub-block 1 is to the left of sub-block 2 71cb93a386Sopenharmony_ci } 72cb93a386Sopenharmony_ci} 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_cistruct IColor { 75cb93a386Sopenharmony_ci int fR, fG, fB; 76cb93a386Sopenharmony_ci}; 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_cistatic SkPMColor add_delta_and_clamp(const IColor& col, int delta) { 79cb93a386Sopenharmony_ci int r8 = SkTPin(col.fR + delta, 0, 255); 80cb93a386Sopenharmony_ci int g8 = SkTPin(col.fG + delta, 0, 255); 81cb93a386Sopenharmony_ci int b8 = SkTPin(col.fB + delta, 0, 255); 82cb93a386Sopenharmony_ci 83cb93a386Sopenharmony_ci return SkPackARGB32(0xFF, r8, g8, b8); 84cb93a386Sopenharmony_ci} 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_cistatic bool decompress_etc1(SkISize dimensions, const uint8_t* srcData, SkBitmap* dst) { 87cb93a386Sopenharmony_ci const ETC1Block* srcBlocks = reinterpret_cast<const ETC1Block*>(srcData); 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_ci int numXBlocks = num_4x4_blocks(dimensions.width()); 90cb93a386Sopenharmony_ci int numYBlocks = num_4x4_blocks(dimensions.height()); 91cb93a386Sopenharmony_ci 92cb93a386Sopenharmony_ci for (int y = 0; y < numYBlocks; ++y) { 93cb93a386Sopenharmony_ci for (int x = 0; x < numXBlocks; ++x) { 94cb93a386Sopenharmony_ci const ETC1Block* curBlock1 = &srcBlocks[y * numXBlocks + x]; 95cb93a386Sopenharmony_ci uint32_t high = SkBSwap32(curBlock1->fHigh); 96cb93a386Sopenharmony_ci uint32_t low = SkBSwap32(curBlock1->fLow); 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ci bool flipped = SkToBool(high & kFlipBit); 99cb93a386Sopenharmony_ci bool differential = SkToBool(high & kDiffBit); 100cb93a386Sopenharmony_ci 101cb93a386Sopenharmony_ci IColor colors[2]; 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_ci if (differential) { 104cb93a386Sopenharmony_ci colors[0].fR = extend_5To8bits(high >> 27); 105cb93a386Sopenharmony_ci colors[1].fR = extend_5plus3To8Bits(high >> 27, high >> 24); 106cb93a386Sopenharmony_ci colors[0].fG = extend_5To8bits(high >> 19); 107cb93a386Sopenharmony_ci colors[1].fG = extend_5plus3To8Bits(high >> 19, high >> 16); 108cb93a386Sopenharmony_ci colors[0].fB = extend_5To8bits(high >> 11); 109cb93a386Sopenharmony_ci colors[1].fB = extend_5plus3To8Bits(high >> 11, high >> 8); 110cb93a386Sopenharmony_ci } else { 111cb93a386Sopenharmony_ci colors[0].fR = extend_4To8bits(high >> 28); 112cb93a386Sopenharmony_ci colors[1].fR = extend_4To8bits(high >> 24); 113cb93a386Sopenharmony_ci colors[0].fG = extend_4To8bits(high >> 20); 114cb93a386Sopenharmony_ci colors[1].fG = extend_4To8bits(high >> 16); 115cb93a386Sopenharmony_ci colors[0].fB = extend_4To8bits(high >> 12); 116cb93a386Sopenharmony_ci colors[1].fB = extend_4To8bits(high >> 8); 117cb93a386Sopenharmony_ci } 118cb93a386Sopenharmony_ci 119cb93a386Sopenharmony_ci int tableIndex0 = (high >> 5) & 0x7; 120cb93a386Sopenharmony_ci int tableIndex1 = (high >> 2) & 0x7; 121cb93a386Sopenharmony_ci const int* tables[2] = { 122cb93a386Sopenharmony_ci kETC1ModifierTables[tableIndex0], 123cb93a386Sopenharmony_ci kETC1ModifierTables[tableIndex1] 124cb93a386Sopenharmony_ci }; 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_ci int baseShift = 0; 127cb93a386Sopenharmony_ci int offsetX = 4 * x, offsetY = 4 * y; 128cb93a386Sopenharmony_ci for (int i = 0; i < 4; ++i, ++baseShift) { 129cb93a386Sopenharmony_ci for (int j = 0; j < 4; ++j) { 130cb93a386Sopenharmony_ci if (offsetX + j >= dst->width() || offsetY + i >= dst->height()) { 131cb93a386Sopenharmony_ci // This can happen for the topmost levels of a mipmap and for 132cb93a386Sopenharmony_ci // non-multiple of 4 textures 133cb93a386Sopenharmony_ci continue; 134cb93a386Sopenharmony_ci } 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_ci int subBlockIndex = xy_to_subblock_index(j, i, flipped); 137cb93a386Sopenharmony_ci int pixelIndex = ((low >> (baseShift+(j*4))) & 0x1) | 138cb93a386Sopenharmony_ci (low >> (baseShift+(j*4)+15) & 0x2); 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ci SkASSERT(subBlockIndex == 0 || subBlockIndex == 1); 141cb93a386Sopenharmony_ci SkASSERT(pixelIndex >= 0 && pixelIndex < 4); 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_ci int delta = tables[subBlockIndex][pixelIndex]; 144cb93a386Sopenharmony_ci *dst->getAddr32(offsetX + j, offsetY + i) = 145cb93a386Sopenharmony_ci add_delta_and_clamp(colors[subBlockIndex], delta); 146cb93a386Sopenharmony_ci } 147cb93a386Sopenharmony_ci } 148cb93a386Sopenharmony_ci } 149cb93a386Sopenharmony_ci } 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ci return true; 152cb93a386Sopenharmony_ci} 153cb93a386Sopenharmony_ci 154cb93a386Sopenharmony_ci//------------------------------------------------------------------------------------------------ 155cb93a386Sopenharmony_cistruct BC1Block { 156cb93a386Sopenharmony_ci uint16_t fColor0; 157cb93a386Sopenharmony_ci uint16_t fColor1; 158cb93a386Sopenharmony_ci uint32_t fIndices; 159cb93a386Sopenharmony_ci}; 160cb93a386Sopenharmony_ci 161cb93a386Sopenharmony_cistatic SkPMColor from565(uint16_t rgb565) { 162cb93a386Sopenharmony_ci uint8_t r8 = SkR16ToR32((rgb565 >> 11) & 0x1F); 163cb93a386Sopenharmony_ci uint8_t g8 = SkG16ToG32((rgb565 >> 5) & 0x3F); 164cb93a386Sopenharmony_ci uint8_t b8 = SkB16ToB32(rgb565 & 0x1F); 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ci return SkPackARGB32(0xFF, r8, g8, b8); 167cb93a386Sopenharmony_ci} 168cb93a386Sopenharmony_ci 169cb93a386Sopenharmony_ci// return t*col0 + (1-t)*col1 170cb93a386Sopenharmony_cistatic SkPMColor lerp(float t, SkPMColor col0, SkPMColor col1) { 171cb93a386Sopenharmony_ci SkASSERT(SkGetPackedA32(col0) == 0xFF && SkGetPackedA32(col1) == 0xFF); 172cb93a386Sopenharmony_ci 173cb93a386Sopenharmony_ci // TODO: given 't' is only either 1/3 or 2/3 this could be done faster 174cb93a386Sopenharmony_ci uint8_t r8 = SkScalarRoundToInt(t * SkGetPackedR32(col0) + (1.0f - t) * SkGetPackedR32(col1)); 175cb93a386Sopenharmony_ci uint8_t g8 = SkScalarRoundToInt(t * SkGetPackedG32(col0) + (1.0f - t) * SkGetPackedG32(col1)); 176cb93a386Sopenharmony_ci uint8_t b8 = SkScalarRoundToInt(t * SkGetPackedB32(col0) + (1.0f - t) * SkGetPackedB32(col1)); 177cb93a386Sopenharmony_ci return SkPackARGB32(0xFF, r8, g8, b8); 178cb93a386Sopenharmony_ci} 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_cistatic bool decompress_bc1(SkISize dimensions, const uint8_t* srcData, 181cb93a386Sopenharmony_ci bool isOpaque, SkBitmap* dst) { 182cb93a386Sopenharmony_ci const BC1Block* srcBlocks = reinterpret_cast<const BC1Block*>(srcData); 183cb93a386Sopenharmony_ci 184cb93a386Sopenharmony_ci int numXBlocks = num_4x4_blocks(dimensions.width()); 185cb93a386Sopenharmony_ci int numYBlocks = num_4x4_blocks(dimensions.height()); 186cb93a386Sopenharmony_ci 187cb93a386Sopenharmony_ci SkPMColor colors[4]; 188cb93a386Sopenharmony_ci 189cb93a386Sopenharmony_ci for (int y = 0; y < numYBlocks; ++y) { 190cb93a386Sopenharmony_ci for (int x = 0; x < numXBlocks; ++x) { 191cb93a386Sopenharmony_ci const BC1Block* curBlock = &srcBlocks[y * numXBlocks + x]; 192cb93a386Sopenharmony_ci 193cb93a386Sopenharmony_ci colors[0] = from565(curBlock->fColor0); 194cb93a386Sopenharmony_ci colors[1] = from565(curBlock->fColor1); 195cb93a386Sopenharmony_ci if (curBlock->fColor0 <= curBlock->fColor1) { // signal for a transparent block 196cb93a386Sopenharmony_ci colors[2] = SkPackARGB32( 197cb93a386Sopenharmony_ci 0xFF, 198cb93a386Sopenharmony_ci (SkGetPackedR32(colors[0]) + SkGetPackedR32(colors[1])) >> 1, 199cb93a386Sopenharmony_ci (SkGetPackedG32(colors[0]) + SkGetPackedG32(colors[1])) >> 1, 200cb93a386Sopenharmony_ci (SkGetPackedB32(colors[0]) + SkGetPackedB32(colors[1])) >> 1); 201cb93a386Sopenharmony_ci // The opacity of the overall texture trumps the per-block transparency 202cb93a386Sopenharmony_ci colors[3] = SkPackARGB32(isOpaque ? 0xFF : 0, 0, 0, 0); 203cb93a386Sopenharmony_ci } else { 204cb93a386Sopenharmony_ci colors[2] = lerp(2.0f/3.0f, colors[0], colors[1]); 205cb93a386Sopenharmony_ci colors[3] = lerp(1.0f/3.0f, colors[0], colors[1]); 206cb93a386Sopenharmony_ci } 207cb93a386Sopenharmony_ci 208cb93a386Sopenharmony_ci int shift = 0; 209cb93a386Sopenharmony_ci int offsetX = 4 * x, offsetY = 4 * y; 210cb93a386Sopenharmony_ci for (int i = 0; i < 4; ++i) { 211cb93a386Sopenharmony_ci for (int j = 0; j < 4; ++j, shift += 2) { 212cb93a386Sopenharmony_ci if (offsetX + j >= dst->width() || offsetY + i >= dst->height()) { 213cb93a386Sopenharmony_ci // This can happen for the topmost levels of a mipmap and for 214cb93a386Sopenharmony_ci // non-multiple of 4 textures 215cb93a386Sopenharmony_ci continue; 216cb93a386Sopenharmony_ci } 217cb93a386Sopenharmony_ci 218cb93a386Sopenharmony_ci int index = (curBlock->fIndices >> shift) & 0x3; 219cb93a386Sopenharmony_ci *dst->getAddr32(offsetX + j, offsetY + i) = colors[index]; 220cb93a386Sopenharmony_ci } 221cb93a386Sopenharmony_ci } 222cb93a386Sopenharmony_ci } 223cb93a386Sopenharmony_ci } 224cb93a386Sopenharmony_ci 225cb93a386Sopenharmony_ci return true; 226cb93a386Sopenharmony_ci} 227cb93a386Sopenharmony_ci 228cb93a386Sopenharmony_cibool SkDecompress(sk_sp<SkData> data, 229cb93a386Sopenharmony_ci SkISize dimensions, 230cb93a386Sopenharmony_ci SkImage::CompressionType compressionType, 231cb93a386Sopenharmony_ci SkBitmap* dst) { 232cb93a386Sopenharmony_ci using Type = SkImage::CompressionType; 233cb93a386Sopenharmony_ci 234cb93a386Sopenharmony_ci const uint8_t* bytes = data->bytes(); 235cb93a386Sopenharmony_ci switch (compressionType) { 236cb93a386Sopenharmony_ci case Type::kNone: return false; 237cb93a386Sopenharmony_ci case Type::kETC2_RGB8_UNORM: return decompress_etc1(dimensions, bytes, dst); 238cb93a386Sopenharmony_ci case Type::kBC1_RGB8_UNORM: return decompress_bc1(dimensions, bytes, true, dst); 239cb93a386Sopenharmony_ci case Type::kBC1_RGBA8_UNORM: return decompress_bc1(dimensions, bytes, false, dst); 240cb93a386Sopenharmony_ci case Type::kASTC_RGBA8_4x4: return true; 241cb93a386Sopenharmony_ci case Type::kASTC_RGBA8_6x6: return true; 242cb93a386Sopenharmony_ci case Type::kASTC_RGBA8_8x8: return true; 243cb93a386Sopenharmony_ci } 244cb93a386Sopenharmony_ci 245cb93a386Sopenharmony_ci SkUNREACHABLE; 246cb93a386Sopenharmony_ci return false; 247cb93a386Sopenharmony_ci} 248cb93a386Sopenharmony_ci 249cb93a386Sopenharmony_cisize_t SkCompressedDataSize(SkImage::CompressionType type, SkISize dimensions, 250cb93a386Sopenharmony_ci SkTArray<size_t>* individualMipOffsets, bool mipMapped) { 251cb93a386Sopenharmony_ci SkASSERT(!individualMipOffsets || !individualMipOffsets->count()); 252cb93a386Sopenharmony_ci 253cb93a386Sopenharmony_ci int numMipLevels = 1; 254cb93a386Sopenharmony_ci if (mipMapped) { 255cb93a386Sopenharmony_ci numMipLevels = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1; 256cb93a386Sopenharmony_ci } 257cb93a386Sopenharmony_ci 258cb93a386Sopenharmony_ci size_t totalSize = 0; 259cb93a386Sopenharmony_ci switch (type) { 260cb93a386Sopenharmony_ci case SkImage::CompressionType::kNone: 261cb93a386Sopenharmony_ci break; 262cb93a386Sopenharmony_ci case SkImage::CompressionType::kETC2_RGB8_UNORM: 263cb93a386Sopenharmony_ci case SkImage::CompressionType::kBC1_RGB8_UNORM: 264cb93a386Sopenharmony_ci case SkImage::CompressionType::kBC1_RGBA8_UNORM: { 265cb93a386Sopenharmony_ci for (int i = 0; i < numMipLevels; ++i) { 266cb93a386Sopenharmony_ci int numBlocks = num_4x4_blocks(dimensions.width()) * 267cb93a386Sopenharmony_ci num_4x4_blocks(dimensions.height()); 268cb93a386Sopenharmony_ci 269cb93a386Sopenharmony_ci if (individualMipOffsets) { 270cb93a386Sopenharmony_ci individualMipOffsets->push_back(totalSize); 271cb93a386Sopenharmony_ci } 272cb93a386Sopenharmony_ci 273cb93a386Sopenharmony_ci static_assert(sizeof(ETC1Block) == sizeof(BC1Block)); 274cb93a386Sopenharmony_ci totalSize += numBlocks * sizeof(ETC1Block); 275cb93a386Sopenharmony_ci 276cb93a386Sopenharmony_ci dimensions = {std::max(1, dimensions.width()/2), std::max(1, dimensions.height()/2)}; 277cb93a386Sopenharmony_ci } 278cb93a386Sopenharmony_ci break; 279cb93a386Sopenharmony_ci } 280cb93a386Sopenharmony_ci case SkImage::CompressionType::kASTC_RGBA8_4x4: { 281cb93a386Sopenharmony_ci // The evil number 16 here is the size of each ASTC block, which is constant for the ASTC 4x4 format, 282cb93a386Sopenharmony_ci // while the ASTC 4x4 format also explain the evil number 4.0f above 283cb93a386Sopenharmony_ci totalSize = std::ceil(dimensions.width() / 4.0f) * std::ceil(dimensions.height() / 4.0f) * 16; 284cb93a386Sopenharmony_ci if (individualMipOffsets) { 285cb93a386Sopenharmony_ci individualMipOffsets->push_back(0); 286cb93a386Sopenharmony_ci } 287cb93a386Sopenharmony_ci break; 288cb93a386Sopenharmony_ci } 289cb93a386Sopenharmony_ci case SkImage::CompressionType::kASTC_RGBA8_6x6: { 290cb93a386Sopenharmony_ci // The evil number 16 here is the size of each ASTC block, which is constant for the ASTC 4x4 format, 291cb93a386Sopenharmony_ci // while the ASTC 6x6 format also explain the evil number 6.0f above 292cb93a386Sopenharmony_ci totalSize = std::ceil(dimensions.width() / 6.0f) * std::ceil(dimensions.height() / 6.0f) * 16; 293cb93a386Sopenharmony_ci if (individualMipOffsets) { 294cb93a386Sopenharmony_ci individualMipOffsets->push_back(0); 295cb93a386Sopenharmony_ci } 296cb93a386Sopenharmony_ci break; 297cb93a386Sopenharmony_ci } 298cb93a386Sopenharmony_ci case SkImage::CompressionType::kASTC_RGBA8_8x8: { 299cb93a386Sopenharmony_ci // The evil number 16 here is the size of each ASTC block, which is constant for the ASTC 4x4 format, 300cb93a386Sopenharmony_ci // while the ASTC 8x8 format also explain the evil number 8.0f above 301cb93a386Sopenharmony_ci totalSize = std::ceil(dimensions.width() / 8.0f) * std::ceil(dimensions.height() / 8.0f) * 16; 302cb93a386Sopenharmony_ci if (individualMipOffsets) { 303cb93a386Sopenharmony_ci individualMipOffsets->push_back(0); 304cb93a386Sopenharmony_ci } 305cb93a386Sopenharmony_ci break; 306cb93a386Sopenharmony_ci } 307cb93a386Sopenharmony_ci } 308cb93a386Sopenharmony_ci 309cb93a386Sopenharmony_ci return totalSize; 310cb93a386Sopenharmony_ci} 311cb93a386Sopenharmony_ci 312cb93a386Sopenharmony_cisize_t SkCompressedBlockSize(SkImage::CompressionType type) { 313cb93a386Sopenharmony_ci switch (type) { 314cb93a386Sopenharmony_ci case SkImage::CompressionType::kNone: 315cb93a386Sopenharmony_ci return 0; 316cb93a386Sopenharmony_ci case SkImage::CompressionType::kETC2_RGB8_UNORM: 317cb93a386Sopenharmony_ci return sizeof(ETC1Block); 318cb93a386Sopenharmony_ci case SkImage::CompressionType::kBC1_RGB8_UNORM: 319cb93a386Sopenharmony_ci case SkImage::CompressionType::kBC1_RGBA8_UNORM: 320cb93a386Sopenharmony_ci return sizeof(BC1Block); 321cb93a386Sopenharmony_ci case SkImage::CompressionType::kASTC_RGBA8_4x4: 322cb93a386Sopenharmony_ci case SkImage::CompressionType::kASTC_RGBA8_6x6: 323cb93a386Sopenharmony_ci case SkImage::CompressionType::kASTC_RGBA8_8x8: 324cb93a386Sopenharmony_ci // The evil number 16 here is the constant size of ASTC format 325cb93a386Sopenharmony_ci return 16; 326cb93a386Sopenharmony_ci } 327cb93a386Sopenharmony_ci SkUNREACHABLE; 328cb93a386Sopenharmony_ci} 329cb93a386Sopenharmony_ci 330cb93a386Sopenharmony_cisize_t SkCompressedFormatDataSize(SkImage::CompressionType compressionType, 331cb93a386Sopenharmony_ci SkISize dimensions, bool mipMapped) { 332cb93a386Sopenharmony_ci return SkCompressedDataSize(compressionType, dimensions, nullptr, mipMapped); 333cb93a386Sopenharmony_ci} 334