• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2013 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.h: Queries for GL image formats.
8 
9 #ifndef LIBANGLE_FORMATUTILS_H_
10 #define LIBANGLE_FORMATUTILS_H_
11 
12 #include <stdint.h>
13 #include <cstddef>
14 #include <ostream>
15 
16 #include "angle_gl.h"
17 #include "common/android_util.h"
18 #include "libANGLE/Caps.h"
19 #include "libANGLE/Error.h"
20 #include "libANGLE/Version.h"
21 #include "libANGLE/VertexAttribute.h"
22 #include "libANGLE/angletypes.h"
23 
24 namespace gl
25 {
26 struct VertexAttribute;
27 
28 struct FormatType final
29 {
30     FormatType();
31     FormatType(GLenum format_, GLenum type_);
32     FormatType(const FormatType &other) = default;
33     FormatType &operator=(const FormatType &other) = default;
34 
35     bool operator<(const FormatType &other) const;
36 
37     GLenum format;
38     GLenum type;
39 };
40 
41 struct Type
42 {
TypeType43     Type() : bytes(0), bytesShift(0), specialInterpretation(0) {}
44 
TypeType45     explicit Type(uint32_t packedTypeInfo)
46         : bytes(packedTypeInfo & 0xff),
47           bytesShift((packedTypeInfo >> 8) & 0xff),
48           specialInterpretation((packedTypeInfo >> 16) & 1)
49     {}
50 
51     GLuint bytes;
52     GLuint bytesShift;  // Bit shift by this value to effectively divide/multiply by "bytes" in a
53                         // more optimal way
54     bool specialInterpretation;
55 };
56 
57 uint32_t GetPackedTypeInfo(GLenum type);
58 
GetNonLinearFormat(const GLenum format)59 ANGLE_INLINE GLenum GetNonLinearFormat(const GLenum format)
60 {
61     switch (format)
62     {
63         case GL_BGRA8_EXT:
64             return GL_BGRA8_SRGB_ANGLEX;
65         case GL_RGBA8:
66             return GL_SRGB8_ALPHA8;
67         case GL_RGB8:
68         case GL_BGRX8_ANGLEX:
69             return GL_SRGB8;
70         case GL_RGBA16F:
71             return GL_RGBA16F;
72         default:
73             return GL_NONE;
74     }
75 }
76 
ColorspaceFormatOverride(const EGLenum colorspace,GLenum * rendertargetformat)77 ANGLE_INLINE bool ColorspaceFormatOverride(const EGLenum colorspace, GLenum *rendertargetformat)
78 {
79     // Override the rendertargetformat based on colorpsace
80     switch (colorspace)
81     {
82         case EGL_GL_COLORSPACE_LINEAR:                 // linear colorspace no translation needed
83         case EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT:       // linear colorspace no translation needed
84         case EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT:  // linear colorspace no translation needed
85         case EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT:  // App, not the HW, will specify the
86                                                             // transfer function
87         case EGL_GL_COLORSPACE_SCRGB_EXT:  // App, not the HW, will specify the transfer function
88             // No translation
89             return true;
90         case EGL_GL_COLORSPACE_SRGB_KHR:
91         case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
92         {
93             GLenum nonLinearFormat = GetNonLinearFormat(*rendertargetformat);
94             if (nonLinearFormat != GL_NONE)
95             {
96                 *rendertargetformat = nonLinearFormat;
97                 return true;
98             }
99             else
100             {
101                 return false;
102             }
103         }
104         break;
105         default:
106             UNREACHABLE();
107             return false;
108     }
109 }
110 
GetTypeInfo(GLenum type)111 ANGLE_INLINE const Type GetTypeInfo(GLenum type)
112 {
113     return Type(GetPackedTypeInfo(type));
114 }
115 
116 // This helpers use tricks based on the assumption that the type has certain values.
117 static_assert(static_cast<GLuint>(DrawElementsType::UnsignedByte) == 0, "Please update this code.");
118 static_assert(static_cast<GLuint>(DrawElementsType::UnsignedShort) == 1,
119               "Please update this code.");
120 static_assert(static_cast<GLuint>(DrawElementsType::UnsignedInt) == 2, "Please update this code.");
GetDrawElementsTypeSize(DrawElementsType type)121 ANGLE_INLINE GLuint GetDrawElementsTypeSize(DrawElementsType type)
122 {
123     return (1 << static_cast<GLuint>(type));
124 }
125 
GetDrawElementsTypeShift(DrawElementsType type)126 ANGLE_INLINE GLuint GetDrawElementsTypeShift(DrawElementsType type)
127 {
128     return static_cast<GLuint>(type);
129 }
130 
131 // Information about an OpenGL internal format.  Can be keyed on the internalFormat and type
132 // members.
133 struct InternalFormat
134 {
135     InternalFormat();
136     InternalFormat(const InternalFormat &other);
137 
138     GLuint computePixelBytes(GLenum formatType) const;
139 
140     ANGLE_NO_DISCARD bool computeRowPitch(GLenum formatType,
141                                           GLsizei width,
142                                           GLint alignment,
143                                           GLint rowLength,
144                                           GLuint *resultOut) const;
145     ANGLE_NO_DISCARD bool computeDepthPitch(GLsizei height,
146                                             GLint imageHeight,
147                                             GLuint rowPitch,
148                                             GLuint *resultOut) const;
149     ANGLE_NO_DISCARD bool computeDepthPitch(GLenum formatType,
150                                             GLsizei width,
151                                             GLsizei height,
152                                             GLint alignment,
153                                             GLint rowLength,
154                                             GLint imageHeight,
155                                             GLuint *resultOut) const;
156 
157     ANGLE_NO_DISCARD bool computeCompressedImageSize(const Extents &size, GLuint *resultOut) const;
158 
159     ANGLE_NO_DISCARD bool computeSkipBytes(GLenum formatType,
160                                            GLuint rowPitch,
161                                            GLuint depthPitch,
162                                            const PixelStoreStateBase &state,
163                                            bool is3D,
164                                            GLuint *resultOut) const;
165 
166     ANGLE_NO_DISCARD bool computePackUnpackEndByte(GLenum formatType,
167                                                    const Extents &size,
168                                                    const PixelStoreStateBase &state,
169                                                    bool is3D,
170                                                    GLuint *resultOut) const;
171 
172     bool isLUMA() const;
173     GLenum getReadPixelsFormat(const Extensions &extensions) const;
174     GLenum getReadPixelsType(const Version &version) const;
175 
176     // Support upload a portion of image?
177     bool supportSubImage() const;
178 
179     // Return true if the format is a required renderbuffer format in the given version of the core
180     // spec. Note that it isn't always clear whether all the rules that apply to core required
181     // renderbuffer formats also apply to additional formats added by extensions. Because of this
182     // extension formats are conservatively not included.
183     bool isRequiredRenderbufferFormat(const Version &version) const;
184 
185     bool isInt() const;
186     bool isDepthOrStencil() const;
187 
188     bool operator==(const InternalFormat &other) const;
189     bool operator!=(const InternalFormat &other) const;
190 
191     GLenum internalFormat;
192 
193     bool sized;
194     GLenum sizedInternalFormat;
195 
196     GLuint redBits;
197     GLuint greenBits;
198     GLuint blueBits;
199 
200     GLuint luminanceBits;
201 
202     GLuint alphaBits;
203     GLuint sharedBits;
204 
205     GLuint depthBits;
206     GLuint stencilBits;
207 
208     GLuint pixelBytes;
209 
210     GLuint componentCount;
211 
212     bool compressed;
213     GLuint compressedBlockWidth;
214     GLuint compressedBlockHeight;
215     GLuint compressedBlockDepth;
216 
217     GLenum format;
218     GLenum type;
219 
220     GLenum componentType;
221     GLenum colorEncoding;
222 
223     typedef bool (*SupportCheckFunction)(const Version &, const Extensions &);
224     SupportCheckFunction textureSupport;
225     SupportCheckFunction filterSupport;
226     SupportCheckFunction textureAttachmentSupport;  // glFramebufferTexture2D
227     SupportCheckFunction renderbufferSupport;       // glFramebufferRenderbuffer
228     SupportCheckFunction blendSupport;
229 };
230 
231 // A "Format" wraps an InternalFormat struct, querying it from either a sized internal format or
232 // unsized internal format and type.
233 // TODO(geofflang): Remove this, it doesn't add any more information than the InternalFormat object.
234 struct Format
235 {
236     // Sized types only.
237     explicit Format(GLenum internalFormat);
238 
239     // Sized or unsized types.
240     explicit Format(const InternalFormat &internalFormat);
241     Format(GLenum internalFormat, GLenum type);
242 
243     Format(const Format &other);
244     Format &operator=(const Format &other);
245 
246     bool valid() const;
247 
248     static Format Invalid();
249     static bool SameSized(const Format &a, const Format &b);
250     static bool EquivalentForBlit(const Format &a, const Format &b);
251 
252     friend std::ostream &operator<<(std::ostream &os, const Format &fmt);
253 
254     // This is the sized info.
255     const InternalFormat *info;
256 };
257 
258 const InternalFormat &GetSizedInternalFormatInfo(GLenum internalFormat);
259 const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, GLenum type);
260 
261 // Strip sizing information from an internal format.  Doesn't necessarily validate that the internal
262 // format is valid.
263 GLenum GetUnsizedFormat(GLenum internalFormat);
264 
265 // Return whether the compressed format requires whole image/mip level to be uploaded to texture.
266 bool CompressedFormatRequiresWholeImage(GLenum internalFormat);
267 
268 typedef std::set<GLenum> FormatSet;
269 const FormatSet &GetAllSizedInternalFormats();
270 
271 typedef std::unordered_map<GLenum, std::unordered_map<GLenum, InternalFormat>>
272     InternalFormatInfoMap;
273 const InternalFormatInfoMap &GetInternalFormatMap();
274 
GetNativeVisualID(const InternalFormat & internalFormat)275 ANGLE_INLINE int GetNativeVisualID(const InternalFormat &internalFormat)
276 {
277     int nativeVisualId = 0;
278 #if defined(ANGLE_PLATFORM_ANDROID)
279     nativeVisualId =
280         angle::android::GLInternalFormatToNativePixelFormat(internalFormat.internalFormat);
281 #endif
282     return nativeVisualId;
283 }
284 
285 // From the ESSL 3.00.4 spec:
286 // Vertex shader inputs can only be float, floating-point vectors, matrices, signed and unsigned
287 // integers and integer vectors. Vertex shader inputs cannot be arrays or structures.
288 
289 enum AttributeType
290 {
291     ATTRIBUTE_FLOAT,
292     ATTRIBUTE_VEC2,
293     ATTRIBUTE_VEC3,
294     ATTRIBUTE_VEC4,
295     ATTRIBUTE_INT,
296     ATTRIBUTE_IVEC2,
297     ATTRIBUTE_IVEC3,
298     ATTRIBUTE_IVEC4,
299     ATTRIBUTE_UINT,
300     ATTRIBUTE_UVEC2,
301     ATTRIBUTE_UVEC3,
302     ATTRIBUTE_UVEC4,
303     ATTRIBUTE_MAT2,
304     ATTRIBUTE_MAT3,
305     ATTRIBUTE_MAT4,
306     ATTRIBUTE_MAT2x3,
307     ATTRIBUTE_MAT2x4,
308     ATTRIBUTE_MAT3x2,
309     ATTRIBUTE_MAT3x4,
310     ATTRIBUTE_MAT4x2,
311     ATTRIBUTE_MAT4x3,
312 };
313 
314 AttributeType GetAttributeType(GLenum enumValue);
315 
316 typedef std::vector<angle::FormatID> InputLayout;
317 
318 struct VertexFormat : private angle::NonCopyable
319 {
320     VertexFormat(GLenum typeIn, GLboolean normalizedIn, GLuint componentsIn, bool pureIntegerIn);
321 
322     GLenum type;
323     GLboolean normalized;
324     GLuint components;
325     bool pureInteger;
326 };
327 
328 angle::FormatID GetVertexFormatID(VertexAttribType type,
329                                   GLboolean normalized,
330                                   GLuint components,
331                                   bool pureInteger);
332 
333 angle::FormatID GetVertexFormatID(const VertexAttribute &attrib, VertexAttribType currentValueType);
334 angle::FormatID GetCurrentValueFormatID(VertexAttribType currentValueType);
335 const VertexFormat &GetVertexFormatFromID(angle::FormatID vertexFormatID);
336 size_t GetVertexFormatSize(angle::FormatID vertexFormatID);
337 
IsS3TCFormat(const GLenum format)338 ANGLE_INLINE bool IsS3TCFormat(const GLenum format)
339 {
340     switch (format)
341     {
342         case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
343         case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
344         case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
345         case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
346         case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
347         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
348         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
349         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
350             return true;
351 
352         default:
353             return false;
354     }
355 }
356 
IsRGTCFormat(const GLenum format)357 ANGLE_INLINE bool IsRGTCFormat(const GLenum format)
358 {
359     switch (format)
360     {
361         case GL_COMPRESSED_RED_RGTC1_EXT:
362         case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
363         case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
364         case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
365             return true;
366 
367         default:
368             return false;
369     }
370 }
371 
IsASTC2DFormat(const GLenum format)372 ANGLE_INLINE bool IsASTC2DFormat(const GLenum format)
373 {
374     if ((format >= GL_COMPRESSED_RGBA_ASTC_4x4_KHR &&
375          format <= GL_COMPRESSED_RGBA_ASTC_12x12_KHR) ||
376         (format >= GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR &&
377          format <= GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR))
378     {
379         return true;
380     }
381     return false;
382 }
383 
IsETC2EACFormat(const GLenum format)384 ANGLE_INLINE bool IsETC2EACFormat(const GLenum format)
385 {
386     // ES 3.1, Table 8.19
387     switch (format)
388     {
389         case GL_COMPRESSED_R11_EAC:
390         case GL_COMPRESSED_SIGNED_R11_EAC:
391         case GL_COMPRESSED_RG11_EAC:
392         case GL_COMPRESSED_SIGNED_RG11_EAC:
393         case GL_COMPRESSED_RGB8_ETC2:
394         case GL_COMPRESSED_SRGB8_ETC2:
395         case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
396         case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
397         case GL_COMPRESSED_RGBA8_ETC2_EAC:
398         case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
399             return true;
400 
401         default:
402             return false;
403     }
404 }
405 
406 // Check if an internal format is ever valid in ES3.  Makes no checks about support for a specific
407 // context.
408 bool ValidES3InternalFormat(GLenum internalFormat);
409 
410 // Implemented in format_map_autogen.cpp
411 bool ValidES3Format(GLenum format);
412 bool ValidES3Type(GLenum type);
413 bool ValidES3FormatCombination(GLenum format, GLenum type, GLenum internalFormat);
414 
415 // Implemented in format_map_desktop.cpp
416 bool ValidDesktopFormat(GLenum format);
417 bool ValidDesktopType(GLenum type);
418 bool ValidDesktopFormatCombination(GLenum format, GLenum type, GLenum internalFormat);
419 
420 // Implemented in es3_copy_conversion_table_autogen.cpp
421 bool ValidES3CopyConversion(GLenum textureFormat, GLenum framebufferFormat);
422 
GetVertexAttributeComponentType(bool pureInteger,VertexAttribType type)423 ANGLE_INLINE ComponentType GetVertexAttributeComponentType(bool pureInteger, VertexAttribType type)
424 {
425     if (pureInteger)
426     {
427         switch (type)
428         {
429             case VertexAttribType::Byte:
430             case VertexAttribType::Short:
431             case VertexAttribType::Int:
432                 return ComponentType::Int;
433 
434             case VertexAttribType::UnsignedByte:
435             case VertexAttribType::UnsignedShort:
436             case VertexAttribType::UnsignedInt:
437                 return ComponentType::UnsignedInt;
438 
439             default:
440                 UNREACHABLE();
441                 return ComponentType::NoType;
442         }
443     }
444     else
445     {
446         return ComponentType::Float;
447     }
448 }
449 }  // namespace gl
450 
451 #endif  // LIBANGLE_FORMATUTILS_H_
452