aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar krajcevski <krajcevski@google.com>2014-07-31 08:42:06 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-07-31 08:42:06 -0700
commit14a1df0bcd00734e6efbe4a21629fe95118815ef (patch)
tree62a5f726a29a25b42a764db13799d3bd2f8841da /src
parentada972df35d87600a46facd2ac2c203fc13d7690 (diff)
Add initial pipeline for decompressors
R=robertphillips@google.com Author: krajcevski@google.com Review URL: https://codereview.chromium.org/432503002
Diffstat (limited to 'src')
-rw-r--r--src/utils/SkTextureCompressor.cpp31
-rw-r--r--src/utils/SkTextureCompressor.h28
-rw-r--r--src/utils/SkTextureCompressor_LATC.cpp106
-rw-r--r--src/utils/SkTextureCompressor_LATC.h2
-rw-r--r--src/utils/SkTextureCompressor_R11EAC.cpp46
-rw-r--r--src/utils/SkTextureCompressor_R11EAC.h2
6 files changed, 169 insertions, 46 deletions
diff --git a/src/utils/SkTextureCompressor.cpp b/src/utils/SkTextureCompressor.cpp
index 30fd3072d5..e0b751f3f7 100644
--- a/src/utils/SkTextureCompressor.cpp
+++ b/src/utils/SkTextureCompressor.cpp
@@ -20,15 +20,16 @@
namespace SkTextureCompressor {
-void GetBlockDimensions(Format format, int* dimX, int* dimY) {
+void GetBlockDimensions(Format format, int* dimX, int* dimY, bool matchSpec) {
if (NULL == dimX || NULL == dimY) {
return;
}
- if (SkTextureCompressorGetPlatformDims(format, dimX, dimY)) {
+ if (!matchSpec && SkTextureCompressorGetPlatformDims(format, dimX, dimY)) {
return;
}
+ // No specialized arguments, return the dimensions as they are in the spec.
switch(format) {
// These formats are 64 bits per 4x4 block.
default:
@@ -159,4 +160,30 @@ SkBlitter* CreateBlitterForFormat(int width, int height, void* compressedBuffer,
return NULL;
}
+bool DecompressBufferFromFormat(uint8_t* dst, int dstRowBytes, const uint8_t* src,
+ int width, int height, Format format) {
+ int dimX, dimY;
+ GetBlockDimensions(format, &dimX, &dimY, true);
+
+ if (width < 0 || ((width % dimX) != 0) || height < 0 || ((height % dimY) != 0)) {
+ return false;
+ }
+
+ switch(format) {
+ case kLATC_Format:
+ DecompressLATC(dst, dstRowBytes, src, width, height);
+ return true;
+
+ case kR11_EAC_Format:
+ DecompressR11EAC(dst, dstRowBytes, src, width, height);
+ return true;
+
+ case kASTC_12x12_Format:
+ // TODO(krajcevski) .. right now just fall through and return false.
+ return false;
+ }
+
+ return false;
+}
+
} // namespace SkTextureCompressor
diff --git a/src/utils/SkTextureCompressor.h b/src/utils/SkTextureCompressor.h
index c6305bab45..eac8c5eea3 100644
--- a/src/utils/SkTextureCompressor.h
+++ b/src/utils/SkTextureCompressor.h
@@ -44,6 +44,24 @@ namespace SkTextureCompressor {
int width, int height, int rowBytes, Format format,
bool opt = true /* Use optimization if available */);
+ // Decompresses the given src data from the format specified into the
+ // destination buffer. The width and height of the data passed corresponds
+ // to the width and height of the uncompressed image. The destination buffer (dst)
+ // is assumed to be large enough to hold the entire decompressed image. The
+ // decompressed image colors are determined based on the passed format:
+ //
+ // LATC -> Alpha 8
+ // R11_EAC -> Alpha 8
+ // ASTC -> RGBA
+ //
+ // Note, CompressBufferToFormat compresses A8 data into ASTC. However,
+ // general ASTC data encodes RGBA data, so that is what the decompressor
+ // operates on.
+ //
+ // Returns true if successfully decompresses the src data.
+ bool DecompressBufferFromFormat(uint8_t* dst, int dstRowBytes, const uint8_t* src,
+ int width, int height, Format format);
+
// This typedef defines what the nominal aspects of a compression function
// are. The typedef is not meant to be used by clients of the API, but rather
// allows SIMD optimized compression functions to be implemented.
@@ -57,10 +75,12 @@ namespace SkTextureCompressor {
Format format);
// Returns the desired dimensions of the block size for the given format. These dimensions
- // don't necessarily correspond to the hardware-specified dimensions, since there may
- // be specialized algorithms that operate on multiple blocks at once. These dimensions
- // reflect that optimization and return the appropriate operable dimensions.
- void GetBlockDimensions(Format format, int* dimX, int* dimY);
+ // don't necessarily correspond to the specification's dimensions, since there may
+ // be specialized algorithms that operate on multiple blocks at once. If the
+ // flag 'matchSpec' is true, then the actual dimensions from the specification are
+ // returned. If the flag is false, then these dimensions reflect the appropriate operable
+ // dimensions of the compression functions.
+ void GetBlockDimensions(Format format, int* dimX, int* dimY, bool matchSpec = false);
}
#endif
diff --git a/src/utils/SkTextureCompressor_LATC.cpp b/src/utils/SkTextureCompressor_LATC.cpp
index 9d42b4f71d..5db0fc6c04 100644
--- a/src/utils/SkTextureCompressor_LATC.cpp
+++ b/src/utils/SkTextureCompressor_LATC.cpp
@@ -17,6 +17,46 @@
////////////////////////////////////////////////////////////////////////////////
+// Generates an LATC palette. LATC constructs
+// a palette of eight colors from LUM0 and LUM1 using the algorithm:
+//
+// LUM0, if lum0 > lum1 and code(x,y) == 0
+// LUM1, if lum0 > lum1 and code(x,y) == 1
+// (6*LUM0+ LUM1)/7, if lum0 > lum1 and code(x,y) == 2
+// (5*LUM0+2*LUM1)/7, if lum0 > lum1 and code(x,y) == 3
+// (4*LUM0+3*LUM1)/7, if lum0 > lum1 and code(x,y) == 4
+// (3*LUM0+4*LUM1)/7, if lum0 > lum1 and code(x,y) == 5
+// (2*LUM0+5*LUM1)/7, if lum0 > lum1 and code(x,y) == 6
+// ( LUM0+6*LUM1)/7, if lum0 > lum1 and code(x,y) == 7
+//
+// LUM0, if lum0 <= lum1 and code(x,y) == 0
+// LUM1, if lum0 <= lum1 and code(x,y) == 1
+// (4*LUM0+ LUM1)/5, if lum0 <= lum1 and code(x,y) == 2
+// (3*LUM0+2*LUM1)/5, if lum0 <= lum1 and code(x,y) == 3
+// (2*LUM0+3*LUM1)/5, if lum0 <= lum1 and code(x,y) == 4
+// ( LUM0+4*LUM1)/5, if lum0 <= lum1 and code(x,y) == 5
+// 0, if lum0 <= lum1 and code(x,y) == 6
+// 255, if lum0 <= lum1 and code(x,y) == 7
+
+static const int kLATCPaletteSize = 8;
+static void generate_latc_palette(uint8_t palette[], uint8_t lum0, uint8_t lum1) {
+ palette[0] = lum0;
+ palette[1] = lum1;
+ if (lum0 > lum1) {
+ for (int i = 1; i < 7; i++) {
+ palette[i+1] = ((7-i)*lum0 + i*lum1) / 7;
+ }
+ } else {
+ for (int i = 1; i < 5; i++) {
+ palette[i+1] = ((5-i)*lum0 + i*lum1) / 5;
+ }
+ palette[6] = 0;
+ palette[7] = 255;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
#if COMPRESS_LATC_SLOW
////////////////////////////////////////////////////////////////////////////////
@@ -79,47 +119,9 @@ static bool compress_4x4_a8_to_64bit(uint8_t* dst, const uint8_t* src,
////////////////////////////////////////////////////////////////////////////////
// LATC compressed texels down into square 4x4 blocks
-static const int kLATCPaletteSize = 8;
static const int kLATCBlockSize = 4;
static const int kLATCPixelsPerBlock = kLATCBlockSize * kLATCBlockSize;
-// Generates an LATC palette. LATC constructs
-// a palette of eight colors from LUM0 and LUM1 using the algorithm:
-//
-// LUM0, if lum0 > lum1 and code(x,y) == 0
-// LUM1, if lum0 > lum1 and code(x,y) == 1
-// (6*LUM0+ LUM1)/7, if lum0 > lum1 and code(x,y) == 2
-// (5*LUM0+2*LUM1)/7, if lum0 > lum1 and code(x,y) == 3
-// (4*LUM0+3*LUM1)/7, if lum0 > lum1 and code(x,y) == 4
-// (3*LUM0+4*LUM1)/7, if lum0 > lum1 and code(x,y) == 5
-// (2*LUM0+5*LUM1)/7, if lum0 > lum1 and code(x,y) == 6
-// ( LUM0+6*LUM1)/7, if lum0 > lum1 and code(x,y) == 7
-//
-// LUM0, if lum0 <= lum1 and code(x,y) == 0
-// LUM1, if lum0 <= lum1 and code(x,y) == 1
-// (4*LUM0+ LUM1)/5, if lum0 <= lum1 and code(x,y) == 2
-// (3*LUM0+2*LUM1)/5, if lum0 <= lum1 and code(x,y) == 3
-// (2*LUM0+3*LUM1)/5, if lum0 <= lum1 and code(x,y) == 4
-// ( LUM0+4*LUM1)/5, if lum0 <= lum1 and code(x,y) == 5
-// 0, if lum0 <= lum1 and code(x,y) == 6
-// 255, if lum0 <= lum1 and code(x,y) == 7
-
-static void generate_latc_palette(uint8_t palette[], uint8_t lum0, uint8_t lum1) {
- palette[0] = lum0;
- palette[1] = lum1;
- if (lum0 > lum1) {
- for (int i = 1; i < 7; i++) {
- palette[i+1] = ((7-i)*lum0 + i*lum1) / 7;
- }
- } else {
- for (int i = 1; i < 5; i++) {
- palette[i+1] = ((5-i)*lum0 + i*lum1) / 5;
- }
- palette[6] = 0;
- palette[7] = 255;
- }
-}
-
// Compress a block by using the bounding box of the pixels. It is assumed that
// there are no extremal pixels in this block otherwise we would have used
// compressBlockBBIgnoreExtremal.
@@ -393,6 +395,24 @@ void CompressA8LATCBlockVertical(uint8_t* dst, const uint8_t block[]) {
#endif // COMPRESS_LATC_FAST
+void decompress_latc_block(uint8_t* dst, int dstRowBytes, const uint8_t* src) {
+ uint64_t block = SkEndian_SwapLE64(*(reinterpret_cast<const uint64_t *>(src)));
+ uint8_t lum0 = block & 0xFF;
+ uint8_t lum1 = (block >> 8) & 0xFF;
+
+ uint8_t palette[kLATCPaletteSize];
+ generate_latc_palette(palette, lum0, lum1);
+
+ block >>= 16;
+ for (int j = 0; j < 4; ++j) {
+ for (int i = 0; i < 4; ++i) {
+ dst[i] = palette[block & 0x7];
+ block >>= 3;
+ }
+ dst += dstRowBytes;
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
namespace SkTextureCompressor {
@@ -418,4 +438,14 @@ SkBlitter* CreateLATCBlitter(int width, int height, void* outputBuffer) {
#endif
}
+void DecompressLATC(uint8_t* dst, int dstRowBytes, const uint8_t* src, int width, int height) {
+ for (int j = 0; j < height; j += 4) {
+ for (int i = 0; i < width; i += 4) {
+ decompress_latc_block(dst + i, dstRowBytes, src);
+ src += 8;
+ }
+ dst += 4 * dstRowBytes;
+ }
+}
+
} // SkTextureCompressor
diff --git a/src/utils/SkTextureCompressor_LATC.h b/src/utils/SkTextureCompressor_LATC.h
index e3446b546d..6ee2ff63e2 100644
--- a/src/utils/SkTextureCompressor_LATC.h
+++ b/src/utils/SkTextureCompressor_LATC.h
@@ -16,6 +16,8 @@ namespace SkTextureCompressor {
int width, int height, int rowBytes);
SkBlitter* CreateLATCBlitter(int width, int height, void* outputBuffer);
+
+ void DecompressLATC(uint8_t* dst, int dstRowBytes, const uint8_t* src, int width, int height);
}
#endif // SkTextureCompressor_LATC_DEFINED
diff --git a/src/utils/SkTextureCompressor_R11EAC.cpp b/src/utils/SkTextureCompressor_R11EAC.cpp
index 982fb012ef..7baa219a28 100644
--- a/src/utils/SkTextureCompressor_R11EAC.cpp
+++ b/src/utils/SkTextureCompressor_R11EAC.cpp
@@ -29,8 +29,6 @@
// If mul is zero, then we set mul = 1/8, so that the formula becomes
// clamp[0, 2047](base_cw * 8 + 4 + mod_val)
-#if COMPRESS_R11_EAC_SLOW
-
static const int kNumR11EACPalettes = 16;
static const int kR11EACPaletteSize = 8;
static const int kR11EACModifierPalettes[kNumR11EACPalettes][kR11EACPaletteSize] = {
@@ -52,6 +50,8 @@ static const int kR11EACModifierPalettes[kNumR11EACPalettes][kR11EACPaletteSize]
{-3, -5, -7, -9, 2, 4, 6, 8}
};
+#if COMPRESS_R11_EAC_SLOW
+
// Pack the base codeword, palette, and multiplier into the 64 bits necessary
// to decode it.
static uint64_t pack_r11eac_block(uint16_t base_cw, uint16_t palette, uint16_t multiplier,
@@ -557,6 +557,38 @@ inline void compress_block_vertical(uint8_t* dstPtr, const uint8_t *block) {
static_cast<uint64_t>(packedIndexColumn3));
}
+static inline int get_r11_eac_index(uint64_t block, int x, int y) {
+ SkASSERT(x >= 0 && x < 4);
+ SkASSERT(y >= 0 && y < 4);
+ const int idx = x*4 + y;
+ return (block >> ((15-idx)*3)) & 0x7;
+}
+
+static void decompress_r11_eac_block(uint8_t* dst, int dstRowBytes, const uint8_t* src) {
+ const uint64_t block = SkEndian_SwapBE64(*(reinterpret_cast<const uint64_t *>(src)));
+
+ const int base_cw = (block >> 56) & 0xFF;
+ const int mod = (block >> 52) & 0xF;
+ const int palette_idx = (block >> 48) & 0xF;
+
+ const int* palette = kR11EACModifierPalettes[palette_idx];
+
+ for (int j = 0; j < 4; ++j) {
+ for (int i = 0; i < 4; ++i) {
+ const int idx = get_r11_eac_index(block, i, j);
+ const int val = base_cw*8 + 4 + palette[idx]*mod*8;
+ if (val < 0) {
+ dst[i] = 0;
+ } else if (val > 2047) {
+ dst[i] = 0xFF;
+ } else {
+ dst[i] = (val >> 3) & 0xFF;
+ }
+ }
+ dst += dstRowBytes;
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
namespace SkTextureCompressor {
@@ -582,4 +614,14 @@ SkBlitter* CreateR11EACBlitter(int width, int height, void* outputBuffer) {
(width, height, outputBuffer);
}
+void DecompressR11EAC(uint8_t* dst, int dstRowBytes, const uint8_t* src, int width, int height) {
+ for (int j = 0; j < height; j += 4) {
+ for (int i = 0; i < width; i += 4) {
+ decompress_r11_eac_block(dst + i, dstRowBytes, src);
+ src += 8;
+ }
+ dst += 4 * dstRowBytes;
+ }
+}
+
} // namespace SkTextureCompressor
diff --git a/src/utils/SkTextureCompressor_R11EAC.h b/src/utils/SkTextureCompressor_R11EAC.h
index 5f981ef46f..1dd8e395a8 100644
--- a/src/utils/SkTextureCompressor_R11EAC.h
+++ b/src/utils/SkTextureCompressor_R11EAC.h
@@ -16,6 +16,8 @@ namespace SkTextureCompressor {
int width, int height, int rowBytes);
SkBlitter* CreateR11EACBlitter(int width, int height, void* outputBuffer);
+
+ void DecompressR11EAC(uint8_t* dst, int dstRB, const uint8_t* src, int width, int height);
}
#endif // SkTextureCompressor_R11EAC_DEFINED