xref: /aosp_15_r20/external/angle/src/image_util/loadimage_paletted.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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