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