• 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 "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.
FormatFormat305     explicit Format(const InternalFormat &internalFormat) : info(&internalFormat) {}
306 
307     Format(GLenum internalFormat, GLenum type);
308 
309     Format(const Format &other)            = default;
310     Format &operator=(const Format &other) = default;
311 
312     bool valid() const;
313 
314     static Format Invalid();
315     static bool SameSized(const Format &a, const Format &b);
316     static bool EquivalentForBlit(const Format &a, const Format &b);
317 
318     friend std::ostream &operator<<(std::ostream &os, const Format &fmt);
319 
320     // This is the sized info.
321     const InternalFormat *info;
322 };
323 
324 const InternalFormat &GetSizedInternalFormatInfo(GLenum internalFormat);
325 const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, GLenum type);
326 
327 // Strip sizing information from an internal format.  Doesn't necessarily validate that the internal
328 // format is valid.
329 GLenum GetUnsizedFormat(GLenum internalFormat);
330 
331 // Return whether the compressed format requires whole image/mip level to be uploaded to texture.
332 bool CompressedFormatRequiresWholeImage(GLenum internalFormat);
333 
334 // In support of GetImage, check for LUMA formats and override with real format
335 void MaybeOverrideLuminance(GLenum &format, GLenum &type, GLenum actualFormat, GLenum actualType);
336 
337 typedef std::set<GLenum> FormatSet;
338 const FormatSet &GetAllSizedInternalFormats();
339 
340 typedef angle::HashMap<GLenum, angle::HashMap<GLenum, InternalFormat>> InternalFormatInfoMap;
341 const InternalFormatInfoMap &GetInternalFormatMap();
342 
343 int GetAndroidHardwareBufferFormatFromChannelSizes(const egl::AttributeMap &attribMap);
344 
345 GLenum GetConfigColorBufferFormat(const egl::Config *config);
346 GLenum GetConfigDepthStencilBufferFormat(const egl::Config *config);
347 
GetNativeVisualID(const InternalFormat & internalFormat)348 ANGLE_INLINE int GetNativeVisualID(const InternalFormat &internalFormat)
349 {
350     int nativeVisualId = 0;
351 #if defined(ANGLE_PLATFORM_ANDROID)
352     nativeVisualId =
353         angle::android::GLInternalFormatToNativePixelFormat(internalFormat.internalFormat);
354 #endif
355 #if defined(ANGLE_PLATFORM_LINUX) && defined(ANGLE_USES_GBM)
356     nativeVisualId = angle::GLInternalFormatToGbmFourCCFormat(internalFormat.internalFormat);
357 #endif
358 
359     return nativeVisualId;
360 }
361 
362 // From the ESSL 3.00.4 spec:
363 // Vertex shader inputs can only be float, floating-point vectors, matrices, signed and unsigned
364 // integers and integer vectors. Vertex shader inputs cannot be arrays or structures.
365 
366 enum AttributeType
367 {
368     ATTRIBUTE_FLOAT,
369     ATTRIBUTE_VEC2,
370     ATTRIBUTE_VEC3,
371     ATTRIBUTE_VEC4,
372     ATTRIBUTE_INT,
373     ATTRIBUTE_IVEC2,
374     ATTRIBUTE_IVEC3,
375     ATTRIBUTE_IVEC4,
376     ATTRIBUTE_UINT,
377     ATTRIBUTE_UVEC2,
378     ATTRIBUTE_UVEC3,
379     ATTRIBUTE_UVEC4,
380     ATTRIBUTE_MAT2,
381     ATTRIBUTE_MAT3,
382     ATTRIBUTE_MAT4,
383     ATTRIBUTE_MAT2x3,
384     ATTRIBUTE_MAT2x4,
385     ATTRIBUTE_MAT3x2,
386     ATTRIBUTE_MAT3x4,
387     ATTRIBUTE_MAT4x2,
388     ATTRIBUTE_MAT4x3,
389 };
390 
391 AttributeType GetAttributeType(GLenum enumValue);
392 
393 typedef std::vector<angle::FormatID> InputLayout;
394 
395 struct VertexFormat : private angle::NonCopyable
396 {
397     VertexFormat(GLenum typeIn, GLboolean normalizedIn, GLuint componentsIn, bool pureIntegerIn);
398 
399     GLenum type;
400     GLboolean normalized;
401     GLuint components;
402     bool pureInteger;
403 };
404 
405 constexpr uint32_t kVertexFormatCount = static_cast<uint32_t>(VertexAttribType::EnumCount);
406 extern const angle::FormatID kVertexFormatPureInteger[kVertexFormatCount][4];
407 extern const angle::FormatID kVertexFormatNormalized[kVertexFormatCount][4];
408 extern const angle::FormatID kVertexFormatScaled[kVertexFormatCount][4];
409 
GetVertexFormatID(VertexAttribType type,GLboolean normalized,GLuint components,bool pureInteger)410 ANGLE_INLINE angle::FormatID GetVertexFormatID(VertexAttribType type,
411                                                GLboolean normalized,
412                                                GLuint components,
413                                                bool pureInteger)
414 {
415     ASSERT(components >= 1 && components <= 4);
416 
417     angle::FormatID result;
418     int index = static_cast<int>(type);
419     if (pureInteger)
420     {
421         result = kVertexFormatPureInteger[index][components - 1];
422     }
423     else if (normalized)
424     {
425         result = kVertexFormatNormalized[index][components - 1];
426     }
427     else
428     {
429         result = kVertexFormatScaled[index][components - 1];
430     }
431 
432     ASSERT(result != angle::FormatID::NONE);
433     return result;
434 }
435 
436 angle::FormatID GetVertexFormatID(const VertexAttribute &attrib, VertexAttribType currentValueType);
437 angle::FormatID GetCurrentValueFormatID(VertexAttribType currentValueType);
438 const VertexFormat &GetVertexFormatFromID(angle::FormatID vertexFormatID);
439 size_t GetVertexFormatSize(angle::FormatID vertexFormatID);
440 angle::FormatID ConvertFormatSignedness(const angle::Format &format);
441 
IsS3TCFormat(const GLenum format)442 ANGLE_INLINE bool IsS3TCFormat(const GLenum format)
443 {
444     switch (format)
445     {
446         case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
447         case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
448         case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
449         case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
450         case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
451         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
452         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
453         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
454             return true;
455 
456         default:
457             return false;
458     }
459 }
460 
IsRGTCFormat(const GLenum format)461 ANGLE_INLINE bool IsRGTCFormat(const GLenum format)
462 {
463     switch (format)
464     {
465         case GL_COMPRESSED_RED_RGTC1_EXT:
466         case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
467         case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
468         case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
469             return true;
470 
471         default:
472             return false;
473     }
474 }
475 
IsBPTCFormat(const GLenum format)476 ANGLE_INLINE bool IsBPTCFormat(const GLenum format)
477 {
478     switch (format)
479     {
480         case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
481         case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
482         case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
483         case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
484             return true;
485 
486         default:
487             return false;
488     }
489 }
490 
IsASTC2DFormat(const GLenum format)491 ANGLE_INLINE bool IsASTC2DFormat(const GLenum format)
492 {
493     if ((format >= GL_COMPRESSED_RGBA_ASTC_4x4_KHR &&
494          format <= GL_COMPRESSED_RGBA_ASTC_12x12_KHR) ||
495         (format >= GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR &&
496          format <= GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR))
497     {
498         return true;
499     }
500     return false;
501 }
502 
IsETC1Format(const GLenum format)503 ANGLE_INLINE bool IsETC1Format(const GLenum format)
504 {
505     switch (format)
506     {
507         case GL_ETC1_RGB8_OES:
508             return true;
509 
510         default:
511             return false;
512     }
513 }
514 
IsETC2EACFormat(const GLenum format)515 ANGLE_INLINE bool IsETC2EACFormat(const GLenum format)
516 {
517     // ES 3.1, Table 8.19
518     switch (format)
519     {
520         case GL_COMPRESSED_R11_EAC:
521         case GL_COMPRESSED_SIGNED_R11_EAC:
522         case GL_COMPRESSED_RG11_EAC:
523         case GL_COMPRESSED_SIGNED_RG11_EAC:
524         case GL_COMPRESSED_RGB8_ETC2:
525         case GL_COMPRESSED_SRGB8_ETC2:
526         case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
527         case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
528         case GL_COMPRESSED_RGBA8_ETC2_EAC:
529         case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
530             return true;
531 
532         default:
533             return false;
534     }
535 }
536 
IsPVRTC1Format(const GLenum format)537 ANGLE_INLINE constexpr bool IsPVRTC1Format(const GLenum format)
538 {
539     // This function is called for all compressed texture uploads. The expression below generates
540     // fewer instructions than a regular switch statement. Two groups of four consecutive values,
541     // each group starts with two least significant bits unset.
542     return ((format & ~3) == GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG) ||
543            ((format & ~3) == GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT);
544 }
545 static_assert(IsPVRTC1Format(GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG), "0x8C00");
546 static_assert(IsPVRTC1Format(GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG), "0x8C01");
547 static_assert(IsPVRTC1Format(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG), "0x8C02");
548 static_assert(IsPVRTC1Format(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG), "0x8C03");
549 static_assert(IsPVRTC1Format(GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT), "0x8A54");
550 static_assert(IsPVRTC1Format(GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT), "0x8A55");
551 static_assert(IsPVRTC1Format(GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT), "0x8A56");
552 static_assert(IsPVRTC1Format(GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT), "0x8A57");
553 static_assert(!IsPVRTC1Format(0x8BFF) && !IsPVRTC1Format(0x8C04), "invalid");
554 static_assert(!IsPVRTC1Format(0x8A53) && !IsPVRTC1Format(0x8A58), "invalid");
555 
IsBGRAFormat(const GLenum internalFormat)556 ANGLE_INLINE bool IsBGRAFormat(const GLenum internalFormat)
557 {
558     switch (internalFormat)
559     {
560         case GL_BGRA8_EXT:
561         case GL_BGRA4_ANGLEX:
562         case GL_BGR5_A1_ANGLEX:
563         case GL_BGRA8_SRGB_ANGLEX:
564         case GL_BGRX8_ANGLEX:
565         case GL_BGR565_ANGLEX:
566         case GL_BGR10_A2_ANGLEX:
567             return true;
568 
569         default:
570             return false;
571     }
572 }
573 
574 // Check if an internal format is ever valid in ES3.  Makes no checks about support for a specific
575 // context.
576 bool ValidES3InternalFormat(GLenum internalFormat);
577 
578 // Implemented in format_map_autogen.cpp
579 bool ValidES3Format(GLenum format);
580 bool ValidES3Type(GLenum type);
581 bool ValidES3FormatCombination(GLenum format, GLenum type, GLenum internalFormat);
582 
583 // Implemented in es3_copy_conversion_table_autogen.cpp
584 bool ValidES3CopyConversion(GLenum textureFormat, GLenum framebufferFormat);
585 
GetVertexAttributeComponentType(bool pureInteger,VertexAttribType type)586 ANGLE_INLINE ComponentType GetVertexAttributeComponentType(bool pureInteger, VertexAttribType type)
587 {
588     if (pureInteger)
589     {
590         switch (type)
591         {
592             case VertexAttribType::Byte:
593             case VertexAttribType::Short:
594             case VertexAttribType::Int:
595                 return ComponentType::Int;
596 
597             case VertexAttribType::UnsignedByte:
598             case VertexAttribType::UnsignedShort:
599             case VertexAttribType::UnsignedInt:
600                 return ComponentType::UnsignedInt;
601 
602             default:
603                 UNREACHABLE();
604                 return ComponentType::NoType;
605         }
606     }
607     else
608     {
609         return ComponentType::Float;
610     }
611 }
612 
613 constexpr std::size_t kMaxYuvPlaneCount = 3;
614 template <typename T>
615 using YuvPlaneArray = std::array<T, kMaxYuvPlaneCount>;
616 
617 struct YuvFormatInfo
618 {
619     // Sized types only.
620     YuvFormatInfo(GLenum internalFormat, const Extents &yPlaneExtent);
621 
622     GLenum glInternalFormat;
623     uint32_t planeCount;
624     YuvPlaneArray<uint32_t> planeBpp;
625     YuvPlaneArray<Extents> planeExtent;
626     YuvPlaneArray<uint32_t> planePitch;
627     YuvPlaneArray<uint32_t> planeSize;
628     YuvPlaneArray<uint32_t> planeOffset;
629 };
630 
631 bool IsYuvFormat(GLenum format);
632 uint32_t GetPlaneCount(GLenum format);
633 uint32_t GetYPlaneBpp(GLenum format);
634 uint32_t GetChromaPlaneBpp(GLenum format);
635 void GetSubSampleFactor(GLenum format,
636                         int *horizontalSubsampleFactor,
637                         int *verticalSubsampleFactor);
638 }  // namespace gl
639 
640 #endif  // LIBANGLE_FORMATUTILS_H_
641