1//
2// Copyright (c) 2013-2014 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// formatutils.cpp: Queries for GL image formats.
8
9#include "common/mathutil.h"
10#include "libGLESv2/formatutils.h"
11#include "libGLESv2/Context.h"
12#include "libGLESv2/Framebuffer.h"
13#include "libGLESv2/renderer/Renderer.h"
14#include "libGLESv2/renderer/imageformats.h"
15#include "libGLESv2/renderer/copyimage.h"
16
17namespace gl
18{
19
20// ES2 requires that format is equal to internal format at all glTex*Image2D entry points and the implementation
21// can decide the true, sized, internal format. The ES2FormatMap determines the internal format for all valid
22// format and type combinations.
23
24FormatType::FormatType()
25    : internalFormat(GL_NONE),
26      colorWriteFunction(NULL)
27{
28}
29
30typedef std::pair<GLenum, GLenum> FormatTypePair;
31typedef std::pair<FormatTypePair, FormatType> FormatPair;
32typedef std::map<FormatTypePair, FormatType> FormatMap;
33
34// A helper function to insert data into the format map with fewer characters.
35static inline void InsertFormatMapping(FormatMap *map, GLenum format, GLenum type, GLenum internalFormat, ColorWriteFunction writeFunc)
36{
37    FormatType info;
38    info.internalFormat = internalFormat;
39    info.colorWriteFunction = writeFunc;
40    map->insert(FormatPair(FormatTypePair(format, type), info));
41}
42
43FormatMap BuildFormatMap()
44{
45    FormatMap map;
46
47    using namespace rx;
48
49    //                       | Format               | Type                             | Internal format          | Color write function             |
50    InsertFormatMapping(&map, GL_RGBA,               GL_UNSIGNED_BYTE,                  GL_RGBA8,                  WriteColor<R8G8B8A8, GLfloat>     );
51    InsertFormatMapping(&map, GL_RGBA,               GL_BYTE,                           GL_RGBA8_SNORM,            WriteColor<R8G8B8A8S, GLfloat>    );
52    InsertFormatMapping(&map, GL_RGBA,               GL_UNSIGNED_SHORT_4_4_4_4,         GL_RGBA4,                  WriteColor<R4G4B4A4, GLfloat>     );
53    InsertFormatMapping(&map, GL_RGBA,               GL_UNSIGNED_SHORT_5_5_5_1,         GL_RGB5_A1,                WriteColor<R5G5B5A1, GLfloat>     );
54    InsertFormatMapping(&map, GL_RGBA,               GL_UNSIGNED_INT_2_10_10_10_REV,    GL_RGB10_A2,               WriteColor<R10G10B10A2, GLfloat>  );
55    InsertFormatMapping(&map, GL_RGBA,               GL_FLOAT,                          GL_RGBA32F,                WriteColor<R32G32B32A32F, GLfloat>);
56    InsertFormatMapping(&map, GL_RGBA,               GL_HALF_FLOAT,                     GL_RGBA16F,                WriteColor<R16G16B16A16F, GLfloat>);
57    InsertFormatMapping(&map, GL_RGBA,               GL_HALF_FLOAT_OES,                 GL_RGBA16F,                WriteColor<R16G16B16A16F, GLfloat>);
58
59    InsertFormatMapping(&map, GL_RGBA_INTEGER,       GL_UNSIGNED_BYTE,                  GL_RGBA8UI,                WriteColor<R8G8B8A8, GLuint>      );
60    InsertFormatMapping(&map, GL_RGBA_INTEGER,       GL_BYTE,                           GL_RGBA8I,                 WriteColor<R8G8B8A8S, GLint>      );
61    InsertFormatMapping(&map, GL_RGBA_INTEGER,       GL_UNSIGNED_SHORT,                 GL_RGBA16UI,               WriteColor<R16G16B16A16, GLuint>  );
62    InsertFormatMapping(&map, GL_RGBA_INTEGER,       GL_SHORT,                          GL_RGBA16I,                WriteColor<R16G16B16A16S, GLint>  );
63    InsertFormatMapping(&map, GL_RGBA_INTEGER,       GL_UNSIGNED_INT,                   GL_RGBA32UI,               WriteColor<R32G32B32A32, GLuint>  );
64    InsertFormatMapping(&map, GL_RGBA_INTEGER,       GL_INT,                            GL_RGBA32I,                WriteColor<R32G32B32A32S, GLint>  );
65    InsertFormatMapping(&map, GL_RGBA_INTEGER,       GL_UNSIGNED_INT_2_10_10_10_REV,    GL_RGB10_A2UI,             WriteColor<R10G10B10A2, GLuint>   );
66
67    InsertFormatMapping(&map, GL_RGB,                GL_UNSIGNED_BYTE,                  GL_RGB8,                   WriteColor<R8G8B8, GLfloat>       );
68    InsertFormatMapping(&map, GL_RGB,                GL_BYTE,                           GL_RGB8_SNORM,             WriteColor<R8G8B8S, GLfloat>      );
69    InsertFormatMapping(&map, GL_RGB,                GL_UNSIGNED_SHORT_5_6_5,           GL_RGB565,                 WriteColor<R5G6B5, GLfloat>       );
70    InsertFormatMapping(&map, GL_RGB,                GL_UNSIGNED_INT_10F_11F_11F_REV,   GL_R11F_G11F_B10F,         WriteColor<R11G11B10F, GLfloat>   );
71    InsertFormatMapping(&map, GL_RGB,                GL_UNSIGNED_INT_5_9_9_9_REV,       GL_RGB9_E5,                WriteColor<R9G9B9E5, GLfloat>     );
72    InsertFormatMapping(&map, GL_RGB,                GL_FLOAT,                          GL_RGB32F,                 WriteColor<R32G32B32F, GLfloat>   );
73    InsertFormatMapping(&map, GL_RGB,                GL_HALF_FLOAT,                     GL_RGB16F,                 WriteColor<R16G16B16F, GLfloat>   );
74    InsertFormatMapping(&map, GL_RGB,                GL_HALF_FLOAT_OES,                 GL_RGB16F,                 WriteColor<R16G16B16F, GLfloat>   );
75
76    InsertFormatMapping(&map, GL_RGB_INTEGER,        GL_UNSIGNED_BYTE,                  GL_RGB8UI,                 WriteColor<R8G8B8, GLuint>        );
77    InsertFormatMapping(&map, GL_RGB_INTEGER,        GL_BYTE,                           GL_RGB8I,                  WriteColor<R8G8B8S, GLint>        );
78    InsertFormatMapping(&map, GL_RGB_INTEGER,        GL_UNSIGNED_SHORT,                 GL_RGB16UI,                WriteColor<R16G16B16, GLuint>     );
79    InsertFormatMapping(&map, GL_RGB_INTEGER,        GL_SHORT,                          GL_RGB16I,                 WriteColor<R16G16B16S, GLint>     );
80    InsertFormatMapping(&map, GL_RGB_INTEGER,        GL_UNSIGNED_INT,                   GL_RGB32UI,                WriteColor<R32G32B32, GLuint>     );
81    InsertFormatMapping(&map, GL_RGB_INTEGER,        GL_INT,                            GL_RGB32I,                 WriteColor<R32G32B32S, GLint>     );
82
83    InsertFormatMapping(&map, GL_RG,                 GL_UNSIGNED_BYTE,                  GL_RG8,                    WriteColor<R8G8, GLfloat>         );
84    InsertFormatMapping(&map, GL_RG,                 GL_BYTE,                           GL_RG8_SNORM,              WriteColor<R8G8S, GLfloat>        );
85    InsertFormatMapping(&map, GL_RG,                 GL_FLOAT,                          GL_RG32F,                  WriteColor<R32G32F, GLfloat>      );
86    InsertFormatMapping(&map, GL_RG,                 GL_HALF_FLOAT,                     GL_RG16F,                  WriteColor<R16G16F, GLfloat>      );
87    InsertFormatMapping(&map, GL_RG,                 GL_HALF_FLOAT_OES,                 GL_RG16F,                  WriteColor<R16G16F, GLfloat>      );
88
89    InsertFormatMapping(&map, GL_RG_INTEGER,         GL_UNSIGNED_BYTE,                  GL_RG8UI,                  WriteColor<R8G8, GLuint>          );
90    InsertFormatMapping(&map, GL_RG_INTEGER,         GL_BYTE,                           GL_RG8I,                   WriteColor<R8G8S, GLint>          );
91    InsertFormatMapping(&map, GL_RG_INTEGER,         GL_UNSIGNED_SHORT,                 GL_RG16UI,                 WriteColor<R16G16, GLuint>        );
92    InsertFormatMapping(&map, GL_RG_INTEGER,         GL_SHORT,                          GL_RG16I,                  WriteColor<R16G16S, GLint>        );
93    InsertFormatMapping(&map, GL_RG_INTEGER,         GL_UNSIGNED_INT,                   GL_RG32UI,                 WriteColor<R32G32, GLuint>        );
94    InsertFormatMapping(&map, GL_RG_INTEGER,         GL_INT,                            GL_RG32I,                  WriteColor<R32G32S, GLint>        );
95
96    InsertFormatMapping(&map, GL_RED,                GL_UNSIGNED_BYTE,                  GL_R8,                     WriteColor<R8, GLfloat>           );
97    InsertFormatMapping(&map, GL_RED,                GL_BYTE,                           GL_R8_SNORM,               WriteColor<R8S, GLfloat>          );
98    InsertFormatMapping(&map, GL_RED,                GL_FLOAT,                          GL_R32F,                   WriteColor<R32F, GLfloat>         );
99    InsertFormatMapping(&map, GL_RED,                GL_HALF_FLOAT,                     GL_R16F,                   WriteColor<R16F, GLfloat>         );
100    InsertFormatMapping(&map, GL_RED,                GL_HALF_FLOAT_OES,                 GL_R16F,                   WriteColor<R16F, GLfloat>         );
101
102    InsertFormatMapping(&map, GL_RED_INTEGER,        GL_UNSIGNED_BYTE,                  GL_R8UI,                   WriteColor<R8, GLuint>            );
103    InsertFormatMapping(&map, GL_RED_INTEGER,        GL_BYTE,                           GL_R8I,                    WriteColor<R8S, GLint>            );
104    InsertFormatMapping(&map, GL_RED_INTEGER,        GL_UNSIGNED_SHORT,                 GL_R16UI,                  WriteColor<R16, GLuint>           );
105    InsertFormatMapping(&map, GL_RED_INTEGER,        GL_SHORT,                          GL_R16I,                   WriteColor<R16S, GLint>           );
106    InsertFormatMapping(&map, GL_RED_INTEGER,        GL_UNSIGNED_INT,                   GL_R32UI,                  WriteColor<R32, GLuint>           );
107    InsertFormatMapping(&map, GL_RED_INTEGER,        GL_INT,                            GL_R32I,                   WriteColor<R32S, GLint>           );
108
109    InsertFormatMapping(&map, GL_LUMINANCE_ALPHA,    GL_UNSIGNED_BYTE,                  GL_LUMINANCE8_ALPHA8_EXT,  WriteColor<L8A8, GLfloat>         );
110    InsertFormatMapping(&map, GL_LUMINANCE,          GL_UNSIGNED_BYTE,                  GL_LUMINANCE8_EXT,         WriteColor<L8, GLfloat>           );
111    InsertFormatMapping(&map, GL_ALPHA,              GL_UNSIGNED_BYTE,                  GL_ALPHA8_EXT,             WriteColor<A8, GLfloat>           );
112    InsertFormatMapping(&map, GL_LUMINANCE_ALPHA,    GL_FLOAT,                          GL_LUMINANCE_ALPHA32F_EXT, WriteColor<L32A32F, GLfloat>      );
113    InsertFormatMapping(&map, GL_LUMINANCE,          GL_FLOAT,                          GL_LUMINANCE32F_EXT,       WriteColor<L32F, GLfloat>         );
114    InsertFormatMapping(&map, GL_ALPHA,              GL_FLOAT,                          GL_ALPHA32F_EXT,           WriteColor<A32F, GLfloat>         );
115    InsertFormatMapping(&map, GL_LUMINANCE_ALPHA,    GL_HALF_FLOAT,                     GL_LUMINANCE_ALPHA16F_EXT, WriteColor<L16A16F, GLfloat>      );
116    InsertFormatMapping(&map, GL_LUMINANCE_ALPHA,    GL_HALF_FLOAT_OES,                 GL_LUMINANCE_ALPHA16F_EXT, WriteColor<L16A16F, GLfloat>      );
117    InsertFormatMapping(&map, GL_LUMINANCE,          GL_HALF_FLOAT,                     GL_LUMINANCE16F_EXT,       WriteColor<L16F, GLfloat>         );
118    InsertFormatMapping(&map, GL_LUMINANCE,          GL_HALF_FLOAT_OES,                 GL_LUMINANCE16F_EXT,       WriteColor<L16F, GLfloat>         );
119    InsertFormatMapping(&map, GL_ALPHA,              GL_HALF_FLOAT,                     GL_ALPHA16F_EXT,           WriteColor<A16F, GLfloat>         );
120    InsertFormatMapping(&map, GL_ALPHA,              GL_HALF_FLOAT_OES,                 GL_ALPHA16F_EXT,           WriteColor<A16F, GLfloat>         );
121
122    InsertFormatMapping(&map, GL_BGRA_EXT,           GL_UNSIGNED_BYTE,                  GL_BGRA8_EXT,              WriteColor<B8G8R8A8, GLfloat>     );
123    InsertFormatMapping(&map, GL_BGRA_EXT,           GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_BGRA4_ANGLEX,           WriteColor<B4G4R4A4, GLfloat>     );
124    InsertFormatMapping(&map, GL_BGRA_EXT,           GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_BGR5_A1_ANGLEX,         WriteColor<B5G5R5A1, GLfloat>     );
125
126    InsertFormatMapping(&map, GL_SRGB_EXT,           GL_UNSIGNED_BYTE,                  GL_SRGB8,                  WriteColor<R8G8B8, GLfloat>       );
127    InsertFormatMapping(&map, GL_SRGB_ALPHA_EXT,     GL_UNSIGNED_BYTE,                  GL_SRGB8_ALPHA8,           WriteColor<R8G8B8A8, GLfloat>     );
128
129    InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,    GL_UNSIGNED_BYTE,     GL_COMPRESSED_RGB_S3TC_DXT1_EXT,    NULL                     );
130    InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,   GL_UNSIGNED_BYTE,     GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,   NULL                     );
131    InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE,     GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL                     );
132    InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE,     GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL                     );
133
134    InsertFormatMapping(&map, GL_DEPTH_COMPONENT,    GL_UNSIGNED_SHORT,                 GL_DEPTH_COMPONENT16,      NULL                              );
135    InsertFormatMapping(&map, GL_DEPTH_COMPONENT,    GL_UNSIGNED_INT,                   GL_DEPTH_COMPONENT32_OES,  NULL                              );
136    InsertFormatMapping(&map, GL_DEPTH_COMPONENT,    GL_FLOAT,                          GL_DEPTH_COMPONENT32F,     NULL                              );
137
138    InsertFormatMapping(&map, GL_STENCIL,            GL_UNSIGNED_BYTE,                  GL_STENCIL_INDEX8,         NULL                              );
139
140    InsertFormatMapping(&map, GL_DEPTH_STENCIL,      GL_UNSIGNED_INT_24_8,              GL_DEPTH24_STENCIL8,       NULL                              );
141    InsertFormatMapping(&map, GL_DEPTH_STENCIL,      GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_DEPTH32F_STENCIL8,      NULL                              );
142
143    return map;
144}
145
146Type::Type()
147    : bytes(0),
148      specialInterpretation(false)
149{
150}
151
152// Map of sizes of input types
153typedef std::pair<GLenum, Type> TypeInfoPair;
154typedef std::map<GLenum, Type> TypeInfoMap;
155
156static inline void InsertTypeInfo(TypeInfoMap *map, GLenum type, GLuint bytes, bool specialInterpretation)
157{
158    Type info;
159    info.bytes = bytes;
160    info.specialInterpretation = specialInterpretation;
161
162    map->insert(std::make_pair(type, info));
163}
164
165bool operator<(const Type& a, const Type& b)
166{
167    return memcmp(&a, &b, sizeof(Type)) < 0;
168}
169
170static TypeInfoMap BuildTypeInfoMap()
171{
172    TypeInfoMap map;
173
174    InsertTypeInfo(&map, GL_UNSIGNED_BYTE,                  1, false);
175    InsertTypeInfo(&map, GL_BYTE,                           1, false);
176    InsertTypeInfo(&map, GL_UNSIGNED_SHORT,                 2, false);
177    InsertTypeInfo(&map, GL_SHORT,                          2, false);
178    InsertTypeInfo(&map, GL_UNSIGNED_INT,                   4, false);
179    InsertTypeInfo(&map, GL_INT,                            4, false);
180    InsertTypeInfo(&map, GL_HALF_FLOAT,                     2, false);
181    InsertTypeInfo(&map, GL_HALF_FLOAT_OES,                 2, false);
182    InsertTypeInfo(&map, GL_FLOAT,                          4, false);
183    InsertTypeInfo(&map, GL_UNSIGNED_SHORT_5_6_5,           2, true );
184    InsertTypeInfo(&map, GL_UNSIGNED_SHORT_4_4_4_4,         2, true );
185    InsertTypeInfo(&map, GL_UNSIGNED_SHORT_5_5_5_1,         2, true );
186    InsertTypeInfo(&map, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, 2, true );
187    InsertTypeInfo(&map, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, 2, true );
188    InsertTypeInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV,    4, true );
189    InsertTypeInfo(&map, GL_UNSIGNED_INT_24_8,              4, true );
190    InsertTypeInfo(&map, GL_UNSIGNED_INT_10F_11F_11F_REV,   4, true );
191    InsertTypeInfo(&map, GL_UNSIGNED_INT_5_9_9_9_REV,       4, true );
192    InsertTypeInfo(&map, GL_UNSIGNED_INT_24_8_OES,          4, true );
193    InsertTypeInfo(&map, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 8, true );
194
195    return map;
196}
197
198// Information about internal formats
199static bool AlwaysSupported(GLuint, const Extensions &)
200{
201    return true;
202}
203
204static bool UnimplementedSupport(GLuint, const Extensions &)
205{
206    return false;
207}
208
209static bool NeverSupported(GLuint, const Extensions &)
210{
211    return false;
212}
213
214template <GLuint minCoreGLVersion>
215static bool RequireESVersion(GLuint clientVersion, const Extensions &)
216{
217    return clientVersion >= minCoreGLVersion;
218}
219
220// Pointer to a boolean memeber of the Extensions struct
221typedef bool(Extensions::*ExtensionBool);
222
223// Check support for a single extension
224template <ExtensionBool bool1>
225static bool RequireExtension(GLuint, const Extensions & extensions)
226{
227    return extensions.*bool1;
228}
229
230// Check for a minimum client version or a single extension
231template <GLuint minCoreGLVersion, ExtensionBool bool1>
232static bool RequireESVersionOrExtension(GLuint clientVersion, const Extensions &extensions)
233{
234    return clientVersion >= minCoreGLVersion || extensions.*bool1;
235}
236
237// Check for a minimum client version or two extensions
238template <GLuint minCoreGLVersion, ExtensionBool bool1, ExtensionBool bool2>
239static bool RequireESVersionOrExtensions(GLuint clientVersion, const Extensions &extensions)
240{
241    return clientVersion >= minCoreGLVersion || (extensions.*bool1 || extensions.*bool2);
242}
243
244// Check support for two extensions
245template <ExtensionBool bool1, ExtensionBool bool2>
246static bool RequireExtensions(GLuint, const Extensions &extensions)
247{
248    return extensions.*bool1 || extensions.*bool2;
249}
250
251InternalFormat::InternalFormat()
252    : redBits(0),
253      greenBits(0),
254      blueBits(0),
255      luminanceBits(0),
256      alphaBits(0),
257      sharedBits(0),
258      depthBits(0),
259      stencilBits(0),
260      pixelBytes(0),
261      componentCount(0),
262      compressedBlockWidth(0),
263      compressedBlockHeight(0),
264      format(GL_NONE),
265      type(GL_NONE),
266      componentType(GL_NONE),
267      colorEncoding(GL_NONE),
268      compressed(false),
269      textureSupport(NeverSupported),
270      renderSupport(NeverSupported),
271      filterSupport(NeverSupported)
272{
273}
274
275static InternalFormat UnsizedFormat(GLenum format, InternalFormat::SupportCheckFunction textureSupport,
276                                    InternalFormat::SupportCheckFunction renderSupport,
277                                    InternalFormat::SupportCheckFunction filterSupport)
278{
279    InternalFormat formatInfo;
280    formatInfo.format = format;
281    formatInfo.textureSupport = textureSupport;
282    formatInfo.renderSupport = renderSupport;
283    formatInfo.filterSupport = filterSupport;
284    return formatInfo;
285}
286
287static InternalFormat RGBAFormat(GLuint red, GLuint green, GLuint blue, GLuint alpha, GLuint shared,
288                                 GLenum format, GLenum type, GLenum componentType, bool srgb,
289                                 InternalFormat::SupportCheckFunction textureSupport,
290                                 InternalFormat::SupportCheckFunction renderSupport,
291                                 InternalFormat::SupportCheckFunction filterSupport)
292{
293    InternalFormat formatInfo;
294    formatInfo.redBits = red;
295    formatInfo.greenBits = green;
296    formatInfo.blueBits = blue;
297    formatInfo.alphaBits = alpha;
298    formatInfo.sharedBits = shared;
299    formatInfo.pixelBytes = (red + green + blue + alpha + shared) / 8;
300    formatInfo.componentCount = ((red > 0) ? 1 : 0) + ((green > 0) ? 1 : 0) + ((blue > 0) ? 1 : 0) + ((alpha > 0) ? 1 : 0);
301    formatInfo.format = format;
302    formatInfo.type = type;
303    formatInfo.componentType = componentType;
304    formatInfo.colorEncoding = (srgb ? GL_SRGB : GL_LINEAR);
305    formatInfo.textureSupport = textureSupport;
306    formatInfo.renderSupport = renderSupport;
307    formatInfo.filterSupport = filterSupport;
308    return formatInfo;
309}
310
311static InternalFormat LUMAFormat(GLuint luminance, GLuint alpha, GLenum format, GLenum type, GLenum componentType,
312                                 InternalFormat::SupportCheckFunction textureSupport,
313                                 InternalFormat::SupportCheckFunction renderSupport,
314                                 InternalFormat::SupportCheckFunction filterSupport)
315{
316    InternalFormat formatInfo;
317    formatInfo.luminanceBits = luminance;
318    formatInfo.alphaBits = alpha;
319    formatInfo.pixelBytes = (luminance + alpha) / 8;
320    formatInfo.componentCount = ((luminance > 0) ? 1 : 0) + ((alpha > 0) ? 1 : 0);
321    formatInfo.format = format;
322    formatInfo.type = type;
323    formatInfo.componentType = componentType;
324    formatInfo.colorEncoding = GL_LINEAR;
325    formatInfo.textureSupport = textureSupport;
326    formatInfo.renderSupport = renderSupport;
327    formatInfo.filterSupport = filterSupport;
328    return formatInfo;
329}
330
331static InternalFormat DepthStencilFormat(GLuint depthBits, GLuint stencilBits, GLuint unusedBits, GLenum format,
332                                         GLenum type, GLenum componentType, InternalFormat::SupportCheckFunction textureSupport,
333                                         InternalFormat::SupportCheckFunction renderSupport,
334                                         InternalFormat::SupportCheckFunction filterSupport)
335{
336    InternalFormat formatInfo;
337    formatInfo.depthBits = depthBits;
338    formatInfo.stencilBits = stencilBits;
339    formatInfo.pixelBytes = (depthBits + stencilBits + unusedBits) / 8;
340    formatInfo.componentCount = ((depthBits > 0) ? 1 : 0) + ((stencilBits > 0) ? 1 : 0);
341    formatInfo.format = format;
342    formatInfo.type = type;
343    formatInfo.componentType = componentType;
344    formatInfo.colorEncoding = GL_LINEAR;
345    formatInfo.textureSupport = textureSupport;
346    formatInfo.renderSupport = renderSupport;
347    formatInfo.filterSupport = filterSupport;
348    return formatInfo;
349}
350
351static InternalFormat CompressedFormat(GLuint compressedBlockWidth, GLuint compressedBlockHeight, GLuint compressedBlockSize,
352                                       GLuint componentCount, GLenum format, GLenum type, bool srgb,
353                                       InternalFormat::SupportCheckFunction textureSupport,
354                                       InternalFormat::SupportCheckFunction renderSupport,
355                                       InternalFormat::SupportCheckFunction filterSupport)
356{
357    InternalFormat formatInfo;
358    formatInfo.compressedBlockWidth = compressedBlockWidth;
359    formatInfo.compressedBlockHeight = compressedBlockHeight;
360    formatInfo.pixelBytes = compressedBlockSize / 8;
361    formatInfo.componentCount = componentCount;
362    formatInfo.format = format;
363    formatInfo.type = type;
364    formatInfo.componentType = GL_UNSIGNED_NORMALIZED;
365    formatInfo.colorEncoding = (srgb ? GL_SRGB : GL_LINEAR);
366    formatInfo.compressed = true;
367    formatInfo.textureSupport = textureSupport;
368    formatInfo.renderSupport = renderSupport;
369    formatInfo.filterSupport = filterSupport;
370    return formatInfo;
371}
372
373typedef std::pair<GLenum, InternalFormat> InternalFormatInfoPair;
374typedef std::map<GLenum, InternalFormat> InternalFormatInfoMap;
375
376static InternalFormatInfoMap BuildInternalFormatInfoMap()
377{
378    InternalFormatInfoMap map;
379
380    // From ES 3.0.1 spec, table 3.12
381    map.insert(InternalFormatInfoPair(GL_NONE,              InternalFormat()));
382
383    //                               | Internal format     |          | R | G | B | A |S | Format         | Type                           | Component type        | SRGB | Texture supported                                    | Renderable      | Filterable    |
384    map.insert(InternalFormatInfoPair(GL_R8,                RGBAFormat( 8,  0,  0,  0, 0, GL_RED,          GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireESVersionOrExtension<3, &Extensions::textureRG>, AlwaysSupported, AlwaysSupported)));
385    map.insert(InternalFormatInfoPair(GL_R8_SNORM,          RGBAFormat( 8,  0,  0,  0, 0, GL_RED,          GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, RequireESVersion<3>,                                    NeverSupported,  AlwaysSupported)));
386    map.insert(InternalFormatInfoPair(GL_RG8,               RGBAFormat( 8,  8,  0,  0, 0, GL_RG,           GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireESVersionOrExtension<3, &Extensions::textureRG>, AlwaysSupported, AlwaysSupported)));
387    map.insert(InternalFormatInfoPair(GL_RG8_SNORM,         RGBAFormat( 8,  8,  0,  0, 0, GL_RG,           GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, RequireESVersion<3>,                                    NeverSupported,  AlwaysSupported)));
388    map.insert(InternalFormatInfoPair(GL_RGB8,              RGBAFormat( 8,  8,  8,  0, 0, GL_RGB,          GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireESVersionOrExtension<3, &Extensions::rgb8rgba8>, AlwaysSupported, AlwaysSupported)));
389    map.insert(InternalFormatInfoPair(GL_RGB8_SNORM,        RGBAFormat( 8,  8,  8,  0, 0, GL_RGB,          GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, RequireESVersion<3>,                                    NeverSupported,  AlwaysSupported)));
390    map.insert(InternalFormatInfoPair(GL_RGB565,            RGBAFormat( 5,  6,  5,  0, 0, GL_RGB,          GL_UNSIGNED_SHORT_5_6_5,         GL_UNSIGNED_NORMALIZED, false, RequireESVersion<2>,                                    AlwaysSupported, AlwaysSupported)));
391    map.insert(InternalFormatInfoPair(GL_RGBA4,             RGBAFormat( 4,  4,  4,  4, 0, GL_RGBA,         GL_UNSIGNED_SHORT_4_4_4_4,       GL_UNSIGNED_NORMALIZED, false, RequireESVersion<2>,                                    AlwaysSupported, AlwaysSupported)));
392    map.insert(InternalFormatInfoPair(GL_RGB5_A1,           RGBAFormat( 5,  5,  5,  1, 0, GL_RGBA,         GL_UNSIGNED_SHORT_5_5_5_1,       GL_UNSIGNED_NORMALIZED, false, RequireESVersion<2>,                                    AlwaysSupported, AlwaysSupported)));
393    map.insert(InternalFormatInfoPair(GL_RGBA8,             RGBAFormat( 8,  8,  8,  8, 0, GL_RGBA,         GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireESVersionOrExtension<3, &Extensions::rgb8rgba8>, AlwaysSupported, AlwaysSupported)));
394    map.insert(InternalFormatInfoPair(GL_RGBA8_SNORM,       RGBAFormat( 8,  8,  8,  8, 0, GL_RGBA,         GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, RequireESVersion<3>,                                    NeverSupported,  AlwaysSupported)));
395    map.insert(InternalFormatInfoPair(GL_RGB10_A2,          RGBAFormat(10, 10, 10,  2, 0, GL_RGBA,         GL_UNSIGNED_INT_2_10_10_10_REV,  GL_UNSIGNED_NORMALIZED, false, RequireESVersion<3>,                                    AlwaysSupported, AlwaysSupported)));
396    map.insert(InternalFormatInfoPair(GL_RGB10_A2UI,        RGBAFormat(10, 10, 10,  2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV,  GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    NeverSupported,  NeverSupported)));
397    map.insert(InternalFormatInfoPair(GL_SRGB8,             RGBAFormat( 8,  8,  8,  0, 0, GL_RGB,          GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, true,  RequireESVersionOrExtension<3, &Extensions::sRGB>,      NeverSupported,  AlwaysSupported)));
398    map.insert(InternalFormatInfoPair(GL_SRGB8_ALPHA8,      RGBAFormat( 8,  8,  8,  8, 0, GL_RGBA,         GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, true,  RequireESVersionOrExtension<3, &Extensions::sRGB>,      AlwaysSupported, AlwaysSupported)));
399    map.insert(InternalFormatInfoPair(GL_R11F_G11F_B10F,    RGBAFormat(11, 11, 10,  0, 0, GL_RGB,          GL_UNSIGNED_INT_10F_11F_11F_REV, GL_FLOAT,               false, RequireESVersion<3>,                                    RequireExtension<&Extensions::colorBufferFloat>, AlwaysSupported)));
400    map.insert(InternalFormatInfoPair(GL_RGB9_E5,           RGBAFormat( 9,  9,  9,  0, 5, GL_RGB,          GL_UNSIGNED_INT_5_9_9_9_REV,     GL_FLOAT,               false, RequireESVersion<3>,                                    NeverSupported,  AlwaysSupported)));
401    map.insert(InternalFormatInfoPair(GL_R8I,               RGBAFormat( 8,  0,  0,  0, 0, GL_RED_INTEGER,  GL_BYTE,                         GL_INT,                 false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
402    map.insert(InternalFormatInfoPair(GL_R8UI,              RGBAFormat( 8,  0,  0,  0, 0, GL_RED_INTEGER,  GL_UNSIGNED_BYTE,                GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
403    map.insert(InternalFormatInfoPair(GL_R16I,              RGBAFormat(16,  0,  0,  0, 0, GL_RED_INTEGER,  GL_SHORT,                        GL_INT,                 false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
404    map.insert(InternalFormatInfoPair(GL_R16UI,             RGBAFormat(16,  0,  0,  0, 0, GL_RED_INTEGER,  GL_UNSIGNED_SHORT,               GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
405    map.insert(InternalFormatInfoPair(GL_R32I,              RGBAFormat(32,  0,  0,  0, 0, GL_RED_INTEGER,  GL_INT,                          GL_INT,                 false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
406    map.insert(InternalFormatInfoPair(GL_R32UI,             RGBAFormat(32,  0,  0,  0, 0, GL_RED_INTEGER,  GL_UNSIGNED_INT,                 GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
407    map.insert(InternalFormatInfoPair(GL_RG8I,              RGBAFormat( 8,  8,  0,  0, 0, GL_RG_INTEGER,   GL_BYTE,                         GL_INT,                 false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
408    map.insert(InternalFormatInfoPair(GL_RG8UI,             RGBAFormat( 8,  8,  0,  0, 0, GL_RG_INTEGER,   GL_UNSIGNED_BYTE,                GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
409    map.insert(InternalFormatInfoPair(GL_RG16I,             RGBAFormat(16, 16,  0,  0, 0, GL_RG_INTEGER,   GL_SHORT,                        GL_INT,                 false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
410    map.insert(InternalFormatInfoPair(GL_RG16UI,            RGBAFormat(16, 16,  0,  0, 0, GL_RG_INTEGER,   GL_UNSIGNED_SHORT,               GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
411    map.insert(InternalFormatInfoPair(GL_RG32I,             RGBAFormat(32, 32,  0,  0, 0, GL_RG_INTEGER,   GL_INT,                          GL_INT,                 false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
412    map.insert(InternalFormatInfoPair(GL_RG32UI,            RGBAFormat(32, 32,  0,  0, 0, GL_RG_INTEGER,   GL_UNSIGNED_INT,                 GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
413    map.insert(InternalFormatInfoPair(GL_RGB8I,             RGBAFormat( 8,  8,  8,  0, 0, GL_RGB_INTEGER,  GL_BYTE,                         GL_INT,                 false, RequireESVersion<3>,                                    NeverSupported,   NeverSupported)));
414    map.insert(InternalFormatInfoPair(GL_RGB8UI,            RGBAFormat( 8,  8,  8,  0, 0, GL_RGB_INTEGER,  GL_UNSIGNED_BYTE,                GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    NeverSupported,   NeverSupported)));
415    map.insert(InternalFormatInfoPair(GL_RGB16I,            RGBAFormat(16, 16, 16,  0, 0, GL_RGB_INTEGER,  GL_SHORT,                        GL_INT,                 false, RequireESVersion<3>,                                    NeverSupported,   NeverSupported)));
416    map.insert(InternalFormatInfoPair(GL_RGB16UI,           RGBAFormat(16, 16, 16,  0, 0, GL_RGB_INTEGER,  GL_UNSIGNED_SHORT,               GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    NeverSupported,   NeverSupported)));
417    map.insert(InternalFormatInfoPair(GL_RGB32I,            RGBAFormat(32, 32, 32,  0, 0, GL_RGB_INTEGER,  GL_INT,                          GL_INT,                 false, RequireESVersion<3>,                                    NeverSupported,   NeverSupported)));
418    map.insert(InternalFormatInfoPair(GL_RGB32UI,           RGBAFormat(32, 32, 32,  0, 0, GL_RGB_INTEGER,  GL_UNSIGNED_INT,                 GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    NeverSupported,   NeverSupported)));
419    map.insert(InternalFormatInfoPair(GL_RGBA8I,            RGBAFormat( 8,  8,  8,  8, 0, GL_RGBA_INTEGER, GL_BYTE,                         GL_INT,                 false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
420    map.insert(InternalFormatInfoPair(GL_RGBA8UI,           RGBAFormat( 8,  8,  8,  8, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,                GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
421    map.insert(InternalFormatInfoPair(GL_RGBA16I,           RGBAFormat(16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_SHORT,                        GL_INT,                 false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
422    map.insert(InternalFormatInfoPair(GL_RGBA16UI,          RGBAFormat(16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT,               GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
423    map.insert(InternalFormatInfoPair(GL_RGBA32I,           RGBAFormat(32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_INT,                          GL_INT,                 false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
424    map.insert(InternalFormatInfoPair(GL_RGBA32UI,          RGBAFormat(32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT,                 GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
425
426    map.insert(InternalFormatInfoPair(GL_BGRA8_EXT,         RGBAFormat( 8,  8,  8,  8, 0, GL_BGRA_EXT,     GL_UNSIGNED_BYTE,                  GL_UNSIGNED_NORMALIZED, false, RequireExtension<&Extensions::textureFormatBGRA8888>, AlwaysSupported, AlwaysSupported)));
427    map.insert(InternalFormatInfoPair(GL_BGRA4_ANGLEX,      RGBAFormat( 4,  4,  4,  4, 0, GL_BGRA_EXT,     GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExtension<&Extensions::textureFormatBGRA8888>, AlwaysSupported, AlwaysSupported)));
428    map.insert(InternalFormatInfoPair(GL_BGR5_A1_ANGLEX,    RGBAFormat( 5,  5,  5,  1, 0, GL_BGRA_EXT,     GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExtension<&Extensions::textureFormatBGRA8888>, AlwaysSupported, AlwaysSupported)));
429
430    // Floating point renderability and filtering is provided by OES_texture_float and OES_texture_half_float
431    //                               | Internal format     |          | D |S | Format             | Type                           | Comp   | SRGB |  Texture supported                                                                     | Renderable     | Filterable                                          |
432    //                               |                     |          |   |  |                    |                                | type   |      |                                                                                        |                |                                                     |
433    map.insert(InternalFormatInfoPair(GL_R16F,              RGBAFormat(16,  0,  0,  0, 0, GL_RED,          GL_HALF_FLOAT,                   GL_FLOAT, false, RequireESVersionOrExtensions<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, AlwaysSupported, RequireExtension<&Extensions::textureHalfFloatLinear>)));
434    map.insert(InternalFormatInfoPair(GL_RG16F,             RGBAFormat(16, 16,  0,  0, 0, GL_RG,           GL_HALF_FLOAT,                   GL_FLOAT, false, RequireESVersionOrExtensions<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, AlwaysSupported, RequireExtension<&Extensions::textureHalfFloatLinear>)));
435    map.insert(InternalFormatInfoPair(GL_RGB16F,            RGBAFormat(16, 16, 16,  0, 0, GL_RGB,          GL_HALF_FLOAT,                   GL_FLOAT, false, RequireESVersionOrExtension<3, &Extensions::textureHalfFloat>,                          AlwaysSupported, RequireExtension<&Extensions::textureHalfFloatLinear>)));
436    map.insert(InternalFormatInfoPair(GL_RGBA16F,           RGBAFormat(16, 16, 16, 16, 0, GL_RGBA,         GL_HALF_FLOAT,                   GL_FLOAT, false, RequireESVersionOrExtension<3, &Extensions::textureHalfFloat>,                          AlwaysSupported, RequireExtension<&Extensions::textureHalfFloatLinear>)));
437    map.insert(InternalFormatInfoPair(GL_R32F,              RGBAFormat(32,  0,  0,  0, 0, GL_RED,          GL_FLOAT,                        GL_FLOAT, false, RequireESVersionOrExtensions<3, &Extensions::textureFloat, &Extensions::textureRG>,     AlwaysSupported, RequireExtension<&Extensions::textureFloatLinear>    )));
438    map.insert(InternalFormatInfoPair(GL_RG32F,             RGBAFormat(32, 32,  0,  0, 0, GL_RG,           GL_FLOAT,                        GL_FLOAT, false, RequireESVersionOrExtensions<3, &Extensions::textureFloat, &Extensions::textureRG>,     AlwaysSupported, RequireExtension<&Extensions::textureFloatLinear>    )));
439    map.insert(InternalFormatInfoPair(GL_RGB32F,            RGBAFormat(32, 32, 32,  0, 0, GL_RGB,          GL_FLOAT,                        GL_FLOAT, false, RequireESVersionOrExtension<3, &Extensions::textureFloat>,                              AlwaysSupported, RequireExtension<&Extensions::textureFloatLinear>    )));
440    map.insert(InternalFormatInfoPair(GL_RGBA32F,           RGBAFormat(32, 32, 32, 32, 0, GL_RGBA,         GL_FLOAT,                        GL_FLOAT, false, RequireESVersionOrExtension<3, &Extensions::textureFloat>,                              AlwaysSupported, RequireExtension<&Extensions::textureFloatLinear>    )));
441
442    // Depth stencil formats
443    //                               | Internal format         |                  | D |S | X | Format            | Type                             | Component type        | Supported     |
444    map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT16,     DepthStencilFormat(16, 0,  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,                 GL_UNSIGNED_NORMALIZED, RequireESVersion<2>,                                                    AlwaysSupported, RequireESVersionOrExtension<3, &Extensions::depthTextures>)));
445    map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT24,     DepthStencilFormat(24, 0,  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,                   GL_UNSIGNED_NORMALIZED, RequireESVersion<3>,                                                    AlwaysSupported, RequireESVersionOrExtension<3, &Extensions::depthTextures>)));
446    map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32F,    DepthStencilFormat(32, 0,  0, GL_DEPTH_COMPONENT, GL_FLOAT,                          GL_FLOAT,               RequireESVersion<3>,                                                    AlwaysSupported, RequireESVersionOrExtension<3, &Extensions::depthTextures>)));
447    map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32_OES, DepthStencilFormat(32, 0,  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,                   GL_UNSIGNED_NORMALIZED, RequireExtension<&Extensions::depthTextures>,                           AlwaysSupported, AlwaysSupported                                           )));
448    map.insert(InternalFormatInfoPair(GL_DEPTH24_STENCIL8,      DepthStencilFormat(24, 8,  0, GL_DEPTH_STENCIL,   GL_UNSIGNED_INT_24_8,              GL_UNSIGNED_NORMALIZED, RequireESVersionOrExtension<2, &Extensions::depthTextures>,             AlwaysSupported, AlwaysSupported                                           )));
449    map.insert(InternalFormatInfoPair(GL_DEPTH32F_STENCIL8,     DepthStencilFormat(32, 8, 24, GL_DEPTH_STENCIL,   GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT,               RequireESVersion<3>,                                                    AlwaysSupported, AlwaysSupported                                           )));
450    map.insert(InternalFormatInfoPair(GL_STENCIL_INDEX8,        DepthStencilFormat( 0, 8,  0, GL_DEPTH_STENCIL,   GL_UNSIGNED_BYTE,                  GL_UNSIGNED_INT,        RequireESVersion<2>,                                                    AlwaysSupported, NeverSupported                                            )));
451
452    // Luminance alpha formats
453    //                               | Internal format          |          | L | A | Format            | Type            | Component type        | Supported                                                                    | Renderable    | Filterable    |
454    map.insert(InternalFormatInfoPair(GL_ALPHA8_EXT,             LUMAFormat( 0,  8, GL_ALPHA,           GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExtension<&Extensions::textureStorage>,                                 NeverSupported, AlwaysSupported)));
455    map.insert(InternalFormatInfoPair(GL_LUMINANCE8_EXT,         LUMAFormat( 8,  0, GL_LUMINANCE,       GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExtension<&Extensions::textureStorage>,                                 NeverSupported, AlwaysSupported)));
456    map.insert(InternalFormatInfoPair(GL_ALPHA32F_EXT,           LUMAFormat( 0, 32, GL_ALPHA,           GL_FLOAT,         GL_FLOAT,               RequireExtensions<&Extensions::textureStorage, &Extensions::textureFloat>,     NeverSupported, AlwaysSupported)));
457    map.insert(InternalFormatInfoPair(GL_LUMINANCE32F_EXT,       LUMAFormat(32,  0, GL_LUMINANCE,       GL_FLOAT,         GL_FLOAT,               RequireExtensions<&Extensions::textureStorage, &Extensions::textureFloat>,     NeverSupported, AlwaysSupported)));
458    map.insert(InternalFormatInfoPair(GL_ALPHA16F_EXT,           LUMAFormat( 0, 16, GL_ALPHA,           GL_HALF_FLOAT,    GL_FLOAT,               RequireExtensions<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported)));
459    map.insert(InternalFormatInfoPair(GL_LUMINANCE16F_EXT,       LUMAFormat(16,  0, GL_LUMINANCE,       GL_HALF_FLOAT,    GL_FLOAT,               RequireExtensions<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported)));
460    map.insert(InternalFormatInfoPair(GL_LUMINANCE8_ALPHA8_EXT,  LUMAFormat( 8,  8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExtension<&Extensions::textureStorage>,                                 NeverSupported, AlwaysSupported)));
461    map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA32F_EXT, LUMAFormat(32, 32, GL_LUMINANCE_ALPHA, GL_FLOAT,         GL_FLOAT,               RequireExtensions<&Extensions::textureStorage, &Extensions::textureFloat>,     NeverSupported, AlwaysSupported)));
462    map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA16F_EXT, LUMAFormat(16, 16, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT,    GL_FLOAT,               RequireExtensions<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported)));
463
464    // Unsized formats
465    //                               | Internal format   |             | Format            | Supported                                                      | Renderable     | Filterable     |
466    map.insert(InternalFormatInfoPair(GL_ALPHA,           UnsizedFormat(GL_ALPHA,           RequireESVersion<2>,                                             NeverSupported,  AlwaysSupported)));
467    map.insert(InternalFormatInfoPair(GL_LUMINANCE,       UnsizedFormat(GL_LUMINANCE,       RequireESVersion<2>,                                             NeverSupported,  AlwaysSupported)));
468    map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA, UnsizedFormat(GL_LUMINANCE_ALPHA, RequireESVersion<2>,                                             NeverSupported,  AlwaysSupported)));
469    map.insert(InternalFormatInfoPair(GL_RED,             UnsizedFormat(GL_RED,             RequireESVersionOrExtension<3, &Extensions::textureRG>,          NeverSupported,  AlwaysSupported)));
470    map.insert(InternalFormatInfoPair(GL_RG,              UnsizedFormat(GL_RG,              RequireESVersionOrExtension<3, &Extensions::textureRG>,          NeverSupported,  AlwaysSupported)));
471    map.insert(InternalFormatInfoPair(GL_RGB,             UnsizedFormat(GL_RGB,             RequireESVersion<2>,                                             AlwaysSupported, AlwaysSupported)));
472    map.insert(InternalFormatInfoPair(GL_RGBA,            UnsizedFormat(GL_RGBA,            RequireESVersion<2>,                                             AlwaysSupported, AlwaysSupported)));
473    map.insert(InternalFormatInfoPair(GL_RED_INTEGER,     UnsizedFormat(GL_RED_INTEGER,     RequireESVersion<3>,                                             NeverSupported,  NeverSupported )));
474    map.insert(InternalFormatInfoPair(GL_RG_INTEGER,      UnsizedFormat(GL_RG_INTEGER,      RequireESVersion<3>,                                             NeverSupported,  NeverSupported )));
475    map.insert(InternalFormatInfoPair(GL_RGB_INTEGER,     UnsizedFormat(GL_RGB_INTEGER,     RequireESVersion<3>,                                             NeverSupported,  NeverSupported )));
476    map.insert(InternalFormatInfoPair(GL_RGBA_INTEGER,    UnsizedFormat(GL_RGBA_INTEGER,    RequireESVersion<3>,                                             NeverSupported,  NeverSupported )));
477    map.insert(InternalFormatInfoPair(GL_BGRA_EXT,        UnsizedFormat(GL_BGRA_EXT,        RequireExtension<&Extensions::textureFormatBGRA8888>,            AlwaysSupported, AlwaysSupported)));
478    map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT, UnsizedFormat(GL_DEPTH_COMPONENT, RequireESVersion<2>,                                             AlwaysSupported, AlwaysSupported)));
479    map.insert(InternalFormatInfoPair(GL_DEPTH_STENCIL,   UnsizedFormat(GL_DEPTH_STENCIL,   RequireESVersionOrExtension<3, &Extensions::packedDepthStencil>, AlwaysSupported, AlwaysSupported)));
480    map.insert(InternalFormatInfoPair(GL_SRGB_EXT,        UnsizedFormat(GL_RGB,             RequireESVersionOrExtension<3, &Extensions::sRGB>,               NeverSupported,  AlwaysSupported)));
481    map.insert(InternalFormatInfoPair(GL_SRGB_ALPHA_EXT,  UnsizedFormat(GL_RGBA,            RequireESVersionOrExtension<3, &Extensions::sRGB>,               AlwaysSupported, AlwaysSupported)));
482
483    // Compressed formats, From ES 3.0.1 spec, table 3.16
484    //                               | Internal format                             |                |W |H | BS |CC| Format                                      | Type            | SRGB | Supported          | Renderable           | Filterable         |
485    map.insert(InternalFormatInfoPair(GL_COMPRESSED_R11_EAC,                        CompressedFormat(4, 4,  64, 1, GL_COMPRESSED_R11_EAC,                        GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
486    map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_R11_EAC,                 CompressedFormat(4, 4,  64, 1, GL_COMPRESSED_SIGNED_R11_EAC,                 GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
487    map.insert(InternalFormatInfoPair(GL_COMPRESSED_RG11_EAC,                       CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_RG11_EAC,                       GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
488    map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_RG11_EAC,                CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_SIGNED_RG11_EAC,                GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
489    map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_ETC2,                      CompressedFormat(4, 4,  64, 3, GL_COMPRESSED_RGB8_ETC2,                      GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
490    map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ETC2,                     CompressedFormat(4, 4,  64, 3, GL_COMPRESSED_SRGB8_ETC2,                     GL_UNSIGNED_BYTE, true,  UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
491    map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,  CompressedFormat(4, 4,  64, 3, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,  GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
492    map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, CompressedFormat(4, 4,  64, 3, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, true,  UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
493    map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA8_ETC2_EAC,                 CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA8_ETC2_EAC,                 GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
494    map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,          CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,          GL_UNSIGNED_BYTE, true,  UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
495
496    // From GL_EXT_texture_compression_dxt1
497    //                               | Internal format                   |                |W |H | BS |CC| Format                            | Type            | SRGB | Supported                                           | Renderable           | Filterable         |
498    map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT,    CompressedFormat(4, 4,  64, 3, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,    GL_UNSIGNED_BYTE, false, RequireExtension<&Extensions::textureCompressionDXT1>, NeverSupported,       AlwaysSupported     )));
499    map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,   CompressedFormat(4, 4,  64, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,   GL_UNSIGNED_BYTE, false, RequireExtension<&Extensions::textureCompressionDXT1>, NeverSupported,       AlwaysSupported     )));
500
501    // From GL_ANGLE_texture_compression_dxt3
502    map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, false, RequireExtension<&Extensions::textureCompressionDXT5>, NeverSupported,       AlwaysSupported     )));
503
504    // From GL_ANGLE_texture_compression_dxt5
505    map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, false, RequireExtension<&Extensions::textureCompressionDXT5>, NeverSupported,       AlwaysSupported     )));
506
507    return map;
508}
509
510static const InternalFormatInfoMap &GetInternalFormatMap()
511{
512    static const InternalFormatInfoMap formatMap = BuildInternalFormatInfoMap();
513    return formatMap;
514}
515
516static FormatSet BuildAllSizedInternalFormatSet()
517{
518    FormatSet result;
519
520    const InternalFormatInfoMap &formats = GetInternalFormatMap();
521    for (InternalFormatInfoMap::const_iterator i = formats.begin(); i != formats.end(); i++)
522    {
523        if (i->second.pixelBytes > 0)
524        {
525            result.insert(i->first);
526        }
527    }
528
529    return result;
530}
531
532const FormatType &GetFormatTypeInfo(GLenum format, GLenum type)
533{
534    static const FormatMap formatMap = BuildFormatMap();
535    FormatMap::const_iterator iter = formatMap.find(FormatTypePair(format, type));
536    if (iter != formatMap.end())
537    {
538        return iter->second;
539    }
540    else
541    {
542        static const FormatType defaultInfo;
543        return defaultInfo;
544    }
545}
546
547const Type &GetTypeInfo(GLenum type)
548{
549    static const TypeInfoMap infoMap = BuildTypeInfoMap();
550    TypeInfoMap::const_iterator iter = infoMap.find(type);
551    if (iter != infoMap.end())
552    {
553        return iter->second;
554    }
555    else
556    {
557        static const Type defaultInfo;
558        return defaultInfo;
559    }
560}
561
562const InternalFormat &GetInternalFormatInfo(GLenum internalFormat)
563{
564    const InternalFormatInfoMap &formatMap = GetInternalFormatMap();
565    InternalFormatInfoMap::const_iterator iter = formatMap.find(internalFormat);
566    if (iter != formatMap.end())
567    {
568        return iter->second;
569    }
570    else
571    {
572        static const InternalFormat defaultInternalFormat;
573        return defaultInternalFormat;
574    }
575}
576
577GLuint InternalFormat::computeRowPitch(GLenum type, GLsizei width, GLint alignment) const
578{
579    ASSERT(alignment > 0 && isPow2(alignment));
580    return rx::roundUp(computeBlockSize(type, width, 1), static_cast<GLuint>(alignment));
581}
582
583GLuint InternalFormat::computeDepthPitch(GLenum type, GLsizei width, GLsizei height, GLint alignment) const
584{
585    return computeRowPitch(type, width, alignment) * height;
586}
587
588GLuint InternalFormat::computeBlockSize(GLenum type, GLsizei width, GLsizei height) const
589{
590    if (compressed)
591    {
592        GLsizei numBlocksWide = (width + compressedBlockWidth - 1) / compressedBlockWidth;
593        GLsizei numBlocksHight = (height + compressedBlockHeight - 1) / compressedBlockHeight;
594        return (pixelBytes * numBlocksWide * numBlocksHight);
595    }
596    else
597    {
598        const Type &typeInfo = GetTypeInfo(type);
599        if (typeInfo.specialInterpretation)
600        {
601            return typeInfo.bytes * width * height;
602        }
603        else
604        {
605            return componentCount * typeInfo.bytes * width * height;
606        }
607    }
608}
609
610GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type)
611{
612    const InternalFormat& formatInfo = GetInternalFormatInfo(internalFormat);
613    return (formatInfo.pixelBytes > 0) ? internalFormat : GetFormatTypeInfo(internalFormat, type).internalFormat;
614}
615
616const FormatSet &GetAllSizedInternalFormats()
617{
618    static FormatSet formatSet = BuildAllSizedInternalFormatSet();
619    return formatSet;
620}
621
622}
623