• 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/Config.h"
20 #include "libANGLE/Error.h"
21 #include "libANGLE/Version.h"
22 #include "libANGLE/VertexAttribute.h"
23 #include "libANGLE/angletypes.h"
24 
25 namespace gl
26 {
27 struct VertexAttribute;
28 
29 struct FormatType final
30 {
31     FormatType();
32     FormatType(GLenum format_, GLenum type_);
33     FormatType(const FormatType &other)            = default;
34     FormatType &operator=(const FormatType &other) = default;
35 
36     bool operator<(const FormatType &other) const;
37 
38     GLenum format;
39     GLenum type;
40 };
41 
42 struct Type
43 {
TypeType44     Type() : bytes(0), bytesShift(0), specialInterpretation(0) {}
45 
TypeType46     explicit Type(uint32_t packedTypeInfo)
47         : bytes(packedTypeInfo & 0xff),
48           bytesShift((packedTypeInfo >> 8) & 0xff),
49           specialInterpretation((packedTypeInfo >> 16) & 1)
50     {}
51 
52     GLuint bytes;
53     GLuint bytesShift;  // Bit shift by this value to effectively divide/multiply by "bytes" in a
54                         // more optimal way
55     bool specialInterpretation;
56 };
57 
58 uint32_t GetPackedTypeInfo(GLenum type);
59 
GetNonLinearFormat(const GLenum format)60 ANGLE_INLINE GLenum GetNonLinearFormat(const GLenum format)
61 {
62     switch (format)
63     {
64         case GL_BGRA8_EXT:
65             return GL_BGRA8_SRGB_ANGLEX;
66         case GL_RGBA8:
67             return GL_SRGB8_ALPHA8;
68         case GL_RGB8:
69         case GL_BGRX8_ANGLEX:
70         case GL_RGBX8_ANGLE:
71             return GL_SRGB8;
72         case GL_RGBA16F:
73             return GL_RGBA16F;
74         default:
75             return GL_NONE;
76     }
77 }
78 
ColorspaceFormatOverride(const EGLenum colorspace,GLenum * rendertargetformat)79 ANGLE_INLINE bool ColorspaceFormatOverride(const EGLenum colorspace, GLenum *rendertargetformat)
80 {
81     // Override the rendertargetformat based on colorpsace
82     switch (colorspace)
83     {
84         case EGL_GL_COLORSPACE_LINEAR:                 // linear colorspace no translation needed
85         case EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT:       // linear colorspace no translation needed
86         case EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT:  // linear colorspace no translation needed
87         case EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT:  // App, not the HW, will specify the
88                                                             // transfer function
89         case EGL_GL_COLORSPACE_SCRGB_EXT:  // App, not the HW, will specify the transfer function
90             // No translation
91             return true;
92         case EGL_GL_COLORSPACE_SRGB_KHR:
93         case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
94         {
95             GLenum nonLinearFormat = GetNonLinearFormat(*rendertargetformat);
96             if (nonLinearFormat != GL_NONE)
97             {
98                 *rendertargetformat = nonLinearFormat;
99                 return true;
100             }
101             else
102             {
103                 return false;
104             }
105         }
106         break;
107         default:
108             UNREACHABLE();
109             return false;
110     }
111 }
112 
GetTypeInfo(GLenum type)113 ANGLE_INLINE const Type GetTypeInfo(GLenum type)
114 {
115     return Type(GetPackedTypeInfo(type));
116 }
117 
118 // This helpers use tricks based on the assumption that the type has certain values.
119 static_assert(static_cast<GLuint>(DrawElementsType::UnsignedByte) == 0, "Please update this code.");
120 static_assert(static_cast<GLuint>(DrawElementsType::UnsignedShort) == 1,
121               "Please update this code.");
122 static_assert(static_cast<GLuint>(DrawElementsType::UnsignedInt) == 2, "Please update this code.");
GetDrawElementsTypeSize(DrawElementsType type)123 ANGLE_INLINE GLuint GetDrawElementsTypeSize(DrawElementsType type)
124 {
125     return (1 << static_cast<GLuint>(type));
126 }
127 
GetDrawElementsTypeShift(DrawElementsType type)128 ANGLE_INLINE GLuint GetDrawElementsTypeShift(DrawElementsType type)
129 {
130     return static_cast<GLuint>(type);
131 }
132 
133 // Information about an OpenGL internal format.  Can be keyed on the internalFormat and type
134 // members.
135 struct InternalFormat
136 {
137     InternalFormat();
138     InternalFormat(const InternalFormat &other);
139     InternalFormat &operator=(const InternalFormat &other);
140 
141     GLuint computePixelBytes(GLenum formatType) const;
142 
143     [[nodiscard]] bool computeBufferRowLength(uint32_t width, uint32_t *resultOut) const;
144     [[nodiscard]] bool computeBufferImageHeight(uint32_t height, uint32_t *resultOut) const;
145 
146     [[nodiscard]] bool computeRowPitch(GLenum formatType,
147                                        GLsizei width,
148                                        GLint alignment,
149                                        GLint rowLength,
150                                        GLuint *resultOut) const;
151     [[nodiscard]] bool computeDepthPitch(GLsizei height,
152                                          GLint imageHeight,
153                                          GLuint rowPitch,
154                                          GLuint *resultOut) const;
155     [[nodiscard]] bool computeDepthPitch(GLenum formatType,
156                                          GLsizei width,
157                                          GLsizei height,
158                                          GLint alignment,
159                                          GLint rowLength,
160                                          GLint imageHeight,
161                                          GLuint *resultOut) const;
162 
163     [[nodiscard]] bool computePalettedImageRowPitch(GLsizei width, GLuint *resultOut) const;
164 
165     [[nodiscard]] bool computeCompressedImageSize(const Extents &size, GLuint *resultOut) const;
166 
167     [[nodiscard]] std::pair<GLuint, GLuint> getCompressedImageMinBlocks() const;
168 
169     [[nodiscard]] bool computeSkipBytes(GLenum formatType,
170                                         GLuint rowPitch,
171                                         GLuint depthPitch,
172                                         const PixelStoreStateBase &state,
173                                         bool is3D,
174                                         GLuint *resultOut) const;
175 
176     [[nodiscard]] bool computePackUnpackEndByte(GLenum formatType,
177                                                 const Extents &size,
178                                                 const PixelStoreStateBase &state,
179                                                 bool is3D,
180                                                 GLuint *resultOut) const;
181 
182     bool isLUMA() const;
183     GLenum getReadPixelsFormat(const Extensions &extensions) const;
184     GLenum getReadPixelsType(const Version &version) const;
185 
186     // Support upload a portion of image?
187     bool supportSubImage() const;
188 
isChannelSizeCompatibleInternalFormat189     ANGLE_INLINE bool isChannelSizeCompatible(GLuint redSize,
190                                               GLuint greenSize,
191                                               GLuint blueSize,
192                                               GLuint alphaSize) const
193     {
194         // We only check for equality in all channel sizes
195         return ((redSize == redBits) && (greenSize == greenBits) && (blueSize == blueBits) &&
196                 (alphaSize == alphaBits));
197     }
198 
199     // Return true if the format is a required renderbuffer format in the given version of the core
200     // spec. Note that it isn't always clear whether all the rules that apply to core required
201     // renderbuffer formats also apply to additional formats added by extensions. Because of this
202     // extension formats are conservatively not included.
203     bool isRequiredRenderbufferFormat(const Version &version) const;
204 
205     bool isInt() const;
206     bool isDepthOrStencil() const;
207 
208     GLuint getEGLConfigBufferSize() const;
209 
210     bool operator==(const InternalFormat &other) const;
211     bool operator!=(const InternalFormat &other) const;
212 
213     GLenum internalFormat;
214 
215     bool sized;
216     GLenum sizedInternalFormat;
217 
218     GLuint redBits;
219     GLuint greenBits;
220     GLuint blueBits;
221 
222     GLuint luminanceBits;
223 
224     GLuint alphaBits;
225     GLuint sharedBits;
226 
227     GLuint depthBits;
228     GLuint stencilBits;
229 
230     GLuint pixelBytes;
231 
232     GLuint componentCount;
233 
234     bool compressed;
235     GLuint compressedBlockWidth;
236     GLuint compressedBlockHeight;
237     GLuint compressedBlockDepth;
238 
239     bool paletted;
240     GLuint paletteBits;
241 
242     GLenum format;
243     GLenum type;
244 
245     GLenum componentType;
246     GLenum colorEncoding;
247 
248     typedef bool (*SupportCheckFunction)(const Version &, const Extensions &);
249     SupportCheckFunction textureSupport;
250     SupportCheckFunction filterSupport;
251     SupportCheckFunction textureAttachmentSupport;  // glFramebufferTexture2D
252     SupportCheckFunction renderbufferSupport;       // glFramebufferRenderbuffer
253     SupportCheckFunction blendSupport;
254 };
255 
256 // A "Format" wraps an InternalFormat struct, querying it from either a sized internal format or
257 // unsized internal format and type.
258 // TODO(geofflang): Remove this, it doesn't add any more information than the InternalFormat object.
259 struct Format
260 {
261     // Sized types only.
262     explicit Format(GLenum internalFormat);
263 
264     // Sized or unsized types.
265     explicit Format(const InternalFormat &internalFormat);
266     Format(GLenum internalFormat, GLenum type);
267 
268     Format(const Format &other);
269     Format &operator=(const Format &other);
270 
271     bool valid() const;
272 
273     static Format Invalid();
274     static bool SameSized(const Format &a, const Format &b);
275     static bool EquivalentForBlit(const Format &a, const Format &b);
276 
277     friend std::ostream &operator<<(std::ostream &os, const Format &fmt);
278 
279     // This is the sized info.
280     const InternalFormat *info;
281 };
282 
283 const InternalFormat &GetSizedInternalFormatInfo(GLenum internalFormat);
284 const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, GLenum type);
285 
286 // Strip sizing information from an internal format.  Doesn't necessarily validate that the internal
287 // format is valid.
288 GLenum GetUnsizedFormat(GLenum internalFormat);
289 
290 // Return whether the compressed format requires whole image/mip level to be uploaded to texture.
291 bool CompressedFormatRequiresWholeImage(GLenum internalFormat);
292 
293 // In support of GetImage, check for LUMA formats and override with real format
294 void MaybeOverrideLuminance(GLenum &format, GLenum &type, GLenum actualFormat, GLenum actualType);
295 
296 typedef std::set<GLenum> FormatSet;
297 const FormatSet &GetAllSizedInternalFormats();
298 
299 typedef angle::HashMap<GLenum, angle::HashMap<GLenum, InternalFormat>> InternalFormatInfoMap;
300 const InternalFormatInfoMap &GetInternalFormatMap();
301 
302 int GetAndroidHardwareBufferFormatFromChannelSizes(const egl::AttributeMap &attribMap);
303 
304 GLenum GetConfigColorBufferFormat(const egl::Config *config);
305 GLenum GetConfigDepthStencilBufferFormat(const egl::Config *config);
306 
GetNativeVisualID(const InternalFormat & internalFormat)307 ANGLE_INLINE int GetNativeVisualID(const InternalFormat &internalFormat)
308 {
309     int nativeVisualId = 0;
310 #if defined(ANGLE_PLATFORM_ANDROID)
311     nativeVisualId =
312         angle::android::GLInternalFormatToNativePixelFormat(internalFormat.internalFormat);
313 #endif
314 #if defined(ANGLE_PLATFORM_LINUX) && defined(ANGLE_USES_GBM)
315     nativeVisualId = angle::GLInternalFormatToGbmFourCCFormat(internalFormat.internalFormat);
316 #endif
317 
318     return nativeVisualId;
319 }
320 
321 // From the ESSL 3.00.4 spec:
322 // Vertex shader inputs can only be float, floating-point vectors, matrices, signed and unsigned
323 // integers and integer vectors. Vertex shader inputs cannot be arrays or structures.
324 
325 enum AttributeType
326 {
327     ATTRIBUTE_FLOAT,
328     ATTRIBUTE_VEC2,
329     ATTRIBUTE_VEC3,
330     ATTRIBUTE_VEC4,
331     ATTRIBUTE_INT,
332     ATTRIBUTE_IVEC2,
333     ATTRIBUTE_IVEC3,
334     ATTRIBUTE_IVEC4,
335     ATTRIBUTE_UINT,
336     ATTRIBUTE_UVEC2,
337     ATTRIBUTE_UVEC3,
338     ATTRIBUTE_UVEC4,
339     ATTRIBUTE_MAT2,
340     ATTRIBUTE_MAT3,
341     ATTRIBUTE_MAT4,
342     ATTRIBUTE_MAT2x3,
343     ATTRIBUTE_MAT2x4,
344     ATTRIBUTE_MAT3x2,
345     ATTRIBUTE_MAT3x4,
346     ATTRIBUTE_MAT4x2,
347     ATTRIBUTE_MAT4x3,
348 };
349 
350 AttributeType GetAttributeType(GLenum enumValue);
351 
352 typedef std::vector<angle::FormatID> InputLayout;
353 
354 struct VertexFormat : private angle::NonCopyable
355 {
356     VertexFormat(GLenum typeIn, GLboolean normalizedIn, GLuint componentsIn, bool pureIntegerIn);
357 
358     GLenum type;
359     GLboolean normalized;
360     GLuint components;
361     bool pureInteger;
362 };
363 
364 angle::FormatID GetVertexFormatID(VertexAttribType type,
365                                   GLboolean normalized,
366                                   GLuint components,
367                                   bool pureInteger);
368 
369 angle::FormatID GetVertexFormatID(const VertexAttribute &attrib, VertexAttribType currentValueType);
370 angle::FormatID GetCurrentValueFormatID(VertexAttribType currentValueType);
371 const VertexFormat &GetVertexFormatFromID(angle::FormatID vertexFormatID);
372 size_t GetVertexFormatSize(angle::FormatID vertexFormatID);
373 angle::FormatID ConvertFormatSignedness(const angle::Format &format);
374 
IsS3TCFormat(const GLenum format)375 ANGLE_INLINE bool IsS3TCFormat(const GLenum format)
376 {
377     switch (format)
378     {
379         case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
380         case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
381         case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
382         case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
383         case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
384         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
385         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
386         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
387             return true;
388 
389         default:
390             return false;
391     }
392 }
393 
IsRGTCFormat(const GLenum format)394 ANGLE_INLINE bool IsRGTCFormat(const GLenum format)
395 {
396     switch (format)
397     {
398         case GL_COMPRESSED_RED_RGTC1_EXT:
399         case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
400         case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
401         case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
402             return true;
403 
404         default:
405             return false;
406     }
407 }
408 
IsBPTCFormat(const GLenum format)409 ANGLE_INLINE bool IsBPTCFormat(const GLenum format)
410 {
411     switch (format)
412     {
413         case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
414         case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
415         case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
416         case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
417             return true;
418 
419         default:
420             return false;
421     }
422 }
423 
IsASTC2DFormat(const GLenum format)424 ANGLE_INLINE bool IsASTC2DFormat(const GLenum format)
425 {
426     if ((format >= GL_COMPRESSED_RGBA_ASTC_4x4_KHR &&
427          format <= GL_COMPRESSED_RGBA_ASTC_12x12_KHR) ||
428         (format >= GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR &&
429          format <= GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR))
430     {
431         return true;
432     }
433     return false;
434 }
435 
IsETC1Format(const GLenum format)436 ANGLE_INLINE bool IsETC1Format(const GLenum format)
437 {
438     switch (format)
439     {
440         case GL_ETC1_RGB8_OES:
441             return true;
442 
443         default:
444             return false;
445     }
446 }
447 
IsETC2EACFormat(const GLenum format)448 ANGLE_INLINE bool IsETC2EACFormat(const GLenum format)
449 {
450     // ES 3.1, Table 8.19
451     switch (format)
452     {
453         case GL_COMPRESSED_R11_EAC:
454         case GL_COMPRESSED_SIGNED_R11_EAC:
455         case GL_COMPRESSED_RG11_EAC:
456         case GL_COMPRESSED_SIGNED_RG11_EAC:
457         case GL_COMPRESSED_RGB8_ETC2:
458         case GL_COMPRESSED_SRGB8_ETC2:
459         case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
460         case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
461         case GL_COMPRESSED_RGBA8_ETC2_EAC:
462         case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
463             return true;
464 
465         default:
466             return false;
467     }
468 }
469 
IsPVRTC1Format(const GLenum format)470 ANGLE_INLINE constexpr bool IsPVRTC1Format(const GLenum format)
471 {
472     // This function is called for all compressed texture uploads. The expression below generates
473     // fewer instructions than a regular switch statement. Two groups of four consecutive values,
474     // each group starts with two least significant bits unset.
475     return ((format & ~3) == GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG) ||
476            ((format & ~3) == GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT);
477 }
478 static_assert(IsPVRTC1Format(GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG), "0x8C00");
479 static_assert(IsPVRTC1Format(GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG), "0x8C01");
480 static_assert(IsPVRTC1Format(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG), "0x8C02");
481 static_assert(IsPVRTC1Format(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG), "0x8C03");
482 static_assert(IsPVRTC1Format(GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT), "0x8A54");
483 static_assert(IsPVRTC1Format(GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT), "0x8A55");
484 static_assert(IsPVRTC1Format(GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT), "0x8A56");
485 static_assert(IsPVRTC1Format(GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT), "0x8A57");
486 static_assert(!IsPVRTC1Format(0x8BFF) && !IsPVRTC1Format(0x8C04), "invalid");
487 static_assert(!IsPVRTC1Format(0x8A53) && !IsPVRTC1Format(0x8A58), "invalid");
488 
IsBGRAFormat(const GLenum internalFormat)489 ANGLE_INLINE bool IsBGRAFormat(const GLenum internalFormat)
490 {
491     switch (internalFormat)
492     {
493         case GL_BGRA8_EXT:
494         case GL_BGRA4_ANGLEX:
495         case GL_BGR5_A1_ANGLEX:
496         case GL_BGRA8_SRGB_ANGLEX:
497         case GL_BGRX8_ANGLEX:
498         case GL_RGBX8_ANGLE:
499         case GL_BGR565_ANGLEX:
500         case GL_BGR10_A2_ANGLEX:
501             return true;
502 
503         default:
504             return false;
505     }
506 }
507 
508 // Check if an internal format is ever valid in ES3.  Makes no checks about support for a specific
509 // context.
510 bool ValidES3InternalFormat(GLenum internalFormat);
511 
512 // Implemented in format_map_autogen.cpp
513 bool ValidES3Format(GLenum format);
514 bool ValidES3Type(GLenum type);
515 bool ValidES3FormatCombination(GLenum format, GLenum type, GLenum internalFormat);
516 
517 // Implemented in format_map_desktop.cpp
518 bool ValidDesktopFormat(GLenum format);
519 bool ValidDesktopType(GLenum type);
520 bool ValidDesktopFormatCombination(GLenum format, GLenum type, GLenum internalFormat);
521 
522 // Implemented in es3_copy_conversion_table_autogen.cpp
523 bool ValidES3CopyConversion(GLenum textureFormat, GLenum framebufferFormat);
524 
GetVertexAttributeComponentType(bool pureInteger,VertexAttribType type)525 ANGLE_INLINE ComponentType GetVertexAttributeComponentType(bool pureInteger, VertexAttribType type)
526 {
527     if (pureInteger)
528     {
529         switch (type)
530         {
531             case VertexAttribType::Byte:
532             case VertexAttribType::Short:
533             case VertexAttribType::Int:
534                 return ComponentType::Int;
535 
536             case VertexAttribType::UnsignedByte:
537             case VertexAttribType::UnsignedShort:
538             case VertexAttribType::UnsignedInt:
539                 return ComponentType::UnsignedInt;
540 
541             default:
542                 UNREACHABLE();
543                 return ComponentType::NoType;
544         }
545     }
546     else
547     {
548         return ComponentType::Float;
549     }
550 }
551 
552 constexpr std::size_t kMaxYuvPlaneCount = 3;
553 template <typename T>
554 using YuvPlaneArray = std::array<T, kMaxYuvPlaneCount>;
555 
556 struct YuvFormatInfo
557 {
558     // Sized types only.
559     YuvFormatInfo(GLenum internalFormat, const Extents &yPlaneExtent);
560 
561     GLenum glInternalFormat;
562     uint32_t planeCount;
563     YuvPlaneArray<uint32_t> planeBpp;
564     YuvPlaneArray<Extents> planeExtent;
565     YuvPlaneArray<uint32_t> planePitch;
566     YuvPlaneArray<uint32_t> planeSize;
567     YuvPlaneArray<uint32_t> planeOffset;
568 };
569 
570 bool IsYuvFormat(GLenum format);
571 uint32_t GetPlaneCount(GLenum format);
572 uint32_t GetYPlaneBpp(GLenum format);
573 uint32_t GetChromaPlaneBpp(GLenum format);
574 void GetSubSampleFactor(GLenum format,
575                         int *horizontalSubsampleFactor,
576                         int *verticalSubsampleFactor);
577 }  // namespace gl
578 
579 #endif  // LIBANGLE_FORMATUTILS_H_
580