summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/image_util/loadimage_paletted.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/image_util/loadimage_paletted.cpp')
-rw-r--r--gfx/angle/checkout/src/image_util/loadimage_paletted.cpp158
1 files changed, 158 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/image_util/loadimage_paletted.cpp b/gfx/angle/checkout/src/image_util/loadimage_paletted.cpp
new file mode 100644
index 0000000000..af36ce3cd6
--- /dev/null
+++ b/gfx/angle/checkout/src/image_util/loadimage_paletted.cpp
@@ -0,0 +1,158 @@
+//
+// Copyright 2022 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// loadimage_paletted.cpp: Decodes GL_PALETTE_* textures.
+
+#include "image_util/loadimage.h"
+
+#include <type_traits>
+#include "common/mathutil.h"
+
+#include "image_util/imageformats.h"
+
+namespace angle
+{
+
+namespace
+{
+
+template <typename T>
+R8G8B8A8 ReadColor(const T *src)
+{
+ gl::ColorF tmp;
+ T::readColor(&tmp, src);
+ R8G8B8A8 rgba;
+ R8G8B8A8::writeColor(&rgba, &tmp);
+ return rgba;
+}
+
+size_t DecodeIndexIntoPalette(const uint8_t *row, size_t i, uint32_t indexBits)
+{
+ switch (indexBits)
+ {
+ case 4:
+ {
+ // From OES_compressed_paletted_texture, section Additions to
+ // Chapter 3 of the OpenGL 1.3 Specification (Rasterization):
+ //
+ // Texel Data Formats for compressed paletted textures
+ //
+ // PALETTE4_xxx:
+ //
+ // 7 6 5 4 3 2 1 0
+ // ---------------
+ // | 1st | 2nd |
+ // | texel | texel |
+ // ---------------
+
+ bool even = i % 2 == 0;
+ return (row[i / 2] >> (even ? 4 : 0)) & 0x0f;
+ }
+
+ case 8:
+ return row[i];
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+R8G8B8A8 DecodeColor(const uint8_t *src,
+ uint32_t redBlueBits,
+ uint32_t greenBits,
+ uint32_t alphaBits)
+{
+ switch (redBlueBits)
+ {
+ case 8:
+ ASSERT(greenBits == 8);
+ switch (alphaBits)
+ {
+ case 0:
+ return ReadColor<>(reinterpret_cast<const R8G8B8 *>(src));
+ case 8:
+ return ReadColor<>(reinterpret_cast<const R8G8B8A8 *>(src));
+ default:
+ UNREACHABLE();
+ break;
+ }
+ break;
+
+ case 5:
+ switch (greenBits)
+ {
+ case 6:
+ ASSERT(alphaBits == 0);
+ return ReadColor<>(reinterpret_cast<const R5G6B5 *>(src));
+ case 5:
+ ASSERT(alphaBits == 1);
+ return ReadColor<>(reinterpret_cast<const R5G5B5A1 *>(src));
+ default:
+ UNREACHABLE();
+ break;
+ }
+ break;
+
+ case 4:
+ ASSERT(greenBits == 4 && alphaBits == 4);
+ return ReadColor<>(reinterpret_cast<const R4G4B4A4 *>(src));
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ UNREACHABLE();
+ return R8G8B8A8{0, 0, 0, 255};
+}
+
+} // namespace
+
+// See LoadPalettedToRGBA8.
+void LoadPalettedToRGBA8Impl(size_t width,
+ size_t height,
+ size_t depth,
+ uint32_t indexBits,
+ uint32_t redBlueBits,
+ uint32_t greenBits,
+ uint32_t alphaBits,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ size_t colorBytes = (redBlueBits + greenBits + redBlueBits + alphaBits) / 8;
+ size_t paletteSize = 1 << indexBits;
+ size_t paletteBytes = paletteSize * colorBytes;
+
+ const uint8_t *palette = input;
+
+ const uint8_t *texels = input + paletteBytes; // + TODO(http://anglebug.com/7688): mip levels
+
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint8_t *srcRow =
+ priv::OffsetDataPointer<uint8_t>(texels, y, z, inputRowPitch, inputDepthPitch);
+ R8G8B8A8 *dstRow =
+ priv::OffsetDataPointer<R8G8B8A8>(output, y, z, outputRowPitch, outputDepthPitch);
+
+ for (size_t x = 0; x < width; x++)
+ {
+ size_t indexIntoPalette = DecodeIndexIntoPalette(srcRow, x, indexBits);
+
+ dstRow[x] = DecodeColor(palette + indexIntoPalette * colorBytes, redBlueBits,
+ greenBits, alphaBits);
+ }
+ }
+ }
+}
+
+} // namespace angle