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