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