1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2022 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker
7*8975f5c5SAndroid Build Coastguard Worker // loadimage_paletted.cpp: Decodes GL_PALETTE_* textures.
8*8975f5c5SAndroid Build Coastguard Worker
9*8975f5c5SAndroid Build Coastguard Worker #include "image_util/loadimage.h"
10*8975f5c5SAndroid Build Coastguard Worker
11*8975f5c5SAndroid Build Coastguard Worker #include <type_traits>
12*8975f5c5SAndroid Build Coastguard Worker #include "common/mathutil.h"
13*8975f5c5SAndroid Build Coastguard Worker
14*8975f5c5SAndroid Build Coastguard Worker #include "image_util/imageformats.h"
15*8975f5c5SAndroid Build Coastguard Worker
16*8975f5c5SAndroid Build Coastguard Worker namespace angle
17*8975f5c5SAndroid Build Coastguard Worker {
18*8975f5c5SAndroid Build Coastguard Worker
19*8975f5c5SAndroid Build Coastguard Worker namespace
20*8975f5c5SAndroid Build Coastguard Worker {
21*8975f5c5SAndroid Build Coastguard Worker
22*8975f5c5SAndroid Build Coastguard Worker template <typename T>
ReadColor(const T * src)23*8975f5c5SAndroid Build Coastguard Worker R8G8B8A8 ReadColor(const T *src)
24*8975f5c5SAndroid Build Coastguard Worker {
25*8975f5c5SAndroid Build Coastguard Worker gl::ColorF tmp;
26*8975f5c5SAndroid Build Coastguard Worker T::readColor(&tmp, src);
27*8975f5c5SAndroid Build Coastguard Worker R8G8B8A8 rgba;
28*8975f5c5SAndroid Build Coastguard Worker R8G8B8A8::writeColor(&rgba, &tmp);
29*8975f5c5SAndroid Build Coastguard Worker return rgba;
30*8975f5c5SAndroid Build Coastguard Worker }
31*8975f5c5SAndroid Build Coastguard Worker
DecodeIndexIntoPalette(const uint8_t * row,size_t i,uint32_t indexBits)32*8975f5c5SAndroid Build Coastguard Worker size_t DecodeIndexIntoPalette(const uint8_t *row, size_t i, uint32_t indexBits)
33*8975f5c5SAndroid Build Coastguard Worker {
34*8975f5c5SAndroid Build Coastguard Worker switch (indexBits)
35*8975f5c5SAndroid Build Coastguard Worker {
36*8975f5c5SAndroid Build Coastguard Worker case 4:
37*8975f5c5SAndroid Build Coastguard Worker {
38*8975f5c5SAndroid Build Coastguard Worker // From OES_compressed_paletted_texture, section Additions to
39*8975f5c5SAndroid Build Coastguard Worker // Chapter 3 of the OpenGL 1.3 Specification (Rasterization):
40*8975f5c5SAndroid Build Coastguard Worker //
41*8975f5c5SAndroid Build Coastguard Worker // Texel Data Formats for compressed paletted textures
42*8975f5c5SAndroid Build Coastguard Worker //
43*8975f5c5SAndroid Build Coastguard Worker // PALETTE4_xxx:
44*8975f5c5SAndroid Build Coastguard Worker //
45*8975f5c5SAndroid Build Coastguard Worker // 7 6 5 4 3 2 1 0
46*8975f5c5SAndroid Build Coastguard Worker // ---------------
47*8975f5c5SAndroid Build Coastguard Worker // | 1st | 2nd |
48*8975f5c5SAndroid Build Coastguard Worker // | texel | texel |
49*8975f5c5SAndroid Build Coastguard Worker // ---------------
50*8975f5c5SAndroid Build Coastguard Worker
51*8975f5c5SAndroid Build Coastguard Worker bool even = i % 2 == 0;
52*8975f5c5SAndroid Build Coastguard Worker return (row[i / 2] >> (even ? 4 : 0)) & 0x0f;
53*8975f5c5SAndroid Build Coastguard Worker }
54*8975f5c5SAndroid Build Coastguard Worker
55*8975f5c5SAndroid Build Coastguard Worker case 8:
56*8975f5c5SAndroid Build Coastguard Worker return row[i];
57*8975f5c5SAndroid Build Coastguard Worker
58*8975f5c5SAndroid Build Coastguard Worker default:
59*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
60*8975f5c5SAndroid Build Coastguard Worker return 0;
61*8975f5c5SAndroid Build Coastguard Worker }
62*8975f5c5SAndroid Build Coastguard Worker }
63*8975f5c5SAndroid Build Coastguard Worker
DecodeColor(const uint8_t * src,uint32_t redBlueBits,uint32_t greenBits,uint32_t alphaBits)64*8975f5c5SAndroid Build Coastguard Worker R8G8B8A8 DecodeColor(const uint8_t *src,
65*8975f5c5SAndroid Build Coastguard Worker uint32_t redBlueBits,
66*8975f5c5SAndroid Build Coastguard Worker uint32_t greenBits,
67*8975f5c5SAndroid Build Coastguard Worker uint32_t alphaBits)
68*8975f5c5SAndroid Build Coastguard Worker {
69*8975f5c5SAndroid Build Coastguard Worker switch (redBlueBits)
70*8975f5c5SAndroid Build Coastguard Worker {
71*8975f5c5SAndroid Build Coastguard Worker case 8:
72*8975f5c5SAndroid Build Coastguard Worker ASSERT(greenBits == 8);
73*8975f5c5SAndroid Build Coastguard Worker switch (alphaBits)
74*8975f5c5SAndroid Build Coastguard Worker {
75*8975f5c5SAndroid Build Coastguard Worker case 0:
76*8975f5c5SAndroid Build Coastguard Worker return ReadColor<>(reinterpret_cast<const R8G8B8 *>(src));
77*8975f5c5SAndroid Build Coastguard Worker case 8:
78*8975f5c5SAndroid Build Coastguard Worker return ReadColor<>(reinterpret_cast<const R8G8B8A8 *>(src));
79*8975f5c5SAndroid Build Coastguard Worker default:
80*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
81*8975f5c5SAndroid Build Coastguard Worker break;
82*8975f5c5SAndroid Build Coastguard Worker }
83*8975f5c5SAndroid Build Coastguard Worker break;
84*8975f5c5SAndroid Build Coastguard Worker
85*8975f5c5SAndroid Build Coastguard Worker case 5:
86*8975f5c5SAndroid Build Coastguard Worker switch (greenBits)
87*8975f5c5SAndroid Build Coastguard Worker {
88*8975f5c5SAndroid Build Coastguard Worker case 6:
89*8975f5c5SAndroid Build Coastguard Worker ASSERT(alphaBits == 0);
90*8975f5c5SAndroid Build Coastguard Worker return ReadColor<>(reinterpret_cast<const R5G6B5 *>(src));
91*8975f5c5SAndroid Build Coastguard Worker case 5:
92*8975f5c5SAndroid Build Coastguard Worker ASSERT(alphaBits == 1);
93*8975f5c5SAndroid Build Coastguard Worker return ReadColor<>(reinterpret_cast<const R5G5B5A1 *>(src));
94*8975f5c5SAndroid Build Coastguard Worker default:
95*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
96*8975f5c5SAndroid Build Coastguard Worker break;
97*8975f5c5SAndroid Build Coastguard Worker }
98*8975f5c5SAndroid Build Coastguard Worker break;
99*8975f5c5SAndroid Build Coastguard Worker
100*8975f5c5SAndroid Build Coastguard Worker case 4:
101*8975f5c5SAndroid Build Coastguard Worker ASSERT(greenBits == 4 && alphaBits == 4);
102*8975f5c5SAndroid Build Coastguard Worker return ReadColor<>(reinterpret_cast<const R4G4B4A4 *>(src));
103*8975f5c5SAndroid Build Coastguard Worker
104*8975f5c5SAndroid Build Coastguard Worker default:
105*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
106*8975f5c5SAndroid Build Coastguard Worker break;
107*8975f5c5SAndroid Build Coastguard Worker }
108*8975f5c5SAndroid Build Coastguard Worker
109*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
110*8975f5c5SAndroid Build Coastguard Worker return R8G8B8A8{0, 0, 0, 255};
111*8975f5c5SAndroid Build Coastguard Worker }
112*8975f5c5SAndroid Build Coastguard Worker
113*8975f5c5SAndroid Build Coastguard Worker } // namespace
114*8975f5c5SAndroid Build Coastguard Worker
115*8975f5c5SAndroid Build Coastguard Worker // See LoadPalettedToRGBA8.
LoadPalettedToRGBA8Impl(const ImageLoadContext & context,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)116*8975f5c5SAndroid Build Coastguard Worker void LoadPalettedToRGBA8Impl(const ImageLoadContext &context,
117*8975f5c5SAndroid Build Coastguard Worker size_t width,
118*8975f5c5SAndroid Build Coastguard Worker size_t height,
119*8975f5c5SAndroid Build Coastguard Worker size_t depth,
120*8975f5c5SAndroid Build Coastguard Worker uint32_t indexBits,
121*8975f5c5SAndroid Build Coastguard Worker uint32_t redBlueBits,
122*8975f5c5SAndroid Build Coastguard Worker uint32_t greenBits,
123*8975f5c5SAndroid Build Coastguard Worker uint32_t alphaBits,
124*8975f5c5SAndroid Build Coastguard Worker const uint8_t *input,
125*8975f5c5SAndroid Build Coastguard Worker size_t inputRowPitch,
126*8975f5c5SAndroid Build Coastguard Worker size_t inputDepthPitch,
127*8975f5c5SAndroid Build Coastguard Worker uint8_t *output,
128*8975f5c5SAndroid Build Coastguard Worker size_t outputRowPitch,
129*8975f5c5SAndroid Build Coastguard Worker size_t outputDepthPitch)
130*8975f5c5SAndroid Build Coastguard Worker {
131*8975f5c5SAndroid Build Coastguard Worker size_t colorBytes = (redBlueBits + greenBits + redBlueBits + alphaBits) / 8;
132*8975f5c5SAndroid Build Coastguard Worker size_t paletteSize = 1 << indexBits;
133*8975f5c5SAndroid Build Coastguard Worker size_t paletteBytes = paletteSize * colorBytes;
134*8975f5c5SAndroid Build Coastguard Worker
135*8975f5c5SAndroid Build Coastguard Worker const uint8_t *palette = input;
136*8975f5c5SAndroid Build Coastguard Worker
137*8975f5c5SAndroid Build Coastguard Worker const uint8_t *texels =
138*8975f5c5SAndroid Build Coastguard Worker input + paletteBytes; // + TODO(http://anglebug.com/42266155): mip levels
139*8975f5c5SAndroid Build Coastguard Worker
140*8975f5c5SAndroid Build Coastguard Worker for (size_t z = 0; z < depth; z++)
141*8975f5c5SAndroid Build Coastguard Worker {
142*8975f5c5SAndroid Build Coastguard Worker for (size_t y = 0; y < height; y++)
143*8975f5c5SAndroid Build Coastguard Worker {
144*8975f5c5SAndroid Build Coastguard Worker const uint8_t *srcRow =
145*8975f5c5SAndroid Build Coastguard Worker priv::OffsetDataPointer<uint8_t>(texels, y, z, inputRowPitch, inputDepthPitch);
146*8975f5c5SAndroid Build Coastguard Worker R8G8B8A8 *dstRow =
147*8975f5c5SAndroid Build Coastguard Worker priv::OffsetDataPointer<R8G8B8A8>(output, y, z, outputRowPitch, outputDepthPitch);
148*8975f5c5SAndroid Build Coastguard Worker
149*8975f5c5SAndroid Build Coastguard Worker for (size_t x = 0; x < width; x++)
150*8975f5c5SAndroid Build Coastguard Worker {
151*8975f5c5SAndroid Build Coastguard Worker size_t indexIntoPalette = DecodeIndexIntoPalette(srcRow, x, indexBits);
152*8975f5c5SAndroid Build Coastguard Worker
153*8975f5c5SAndroid Build Coastguard Worker dstRow[x] = DecodeColor(palette + indexIntoPalette * colorBytes, redBlueBits,
154*8975f5c5SAndroid Build Coastguard Worker greenBits, alphaBits);
155*8975f5c5SAndroid Build Coastguard Worker }
156*8975f5c5SAndroid Build Coastguard Worker }
157*8975f5c5SAndroid Build Coastguard Worker }
158*8975f5c5SAndroid Build Coastguard Worker }
159*8975f5c5SAndroid Build Coastguard Worker
160*8975f5c5SAndroid Build Coastguard Worker } // namespace angle
161