• 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     ANGLE_NO_DISCARD bool computeBufferRowLength(uint32_t width, uint32_t *resultOut) const;
144     ANGLE_NO_DISCARD bool computeBufferImageHeight(uint32_t height, uint32_t *resultOut) const;
145 
146     ANGLE_NO_DISCARD bool computeRowPitch(GLenum formatType,
147                                           GLsizei width,
148                                           GLint alignment,
149                                           GLint rowLength,
150                                           GLuint *resultOut) const;
151     ANGLE_NO_DISCARD bool computeDepthPitch(GLsizei height,
152                                             GLint imageHeight,
153                                             GLuint rowPitch,
154                                             GLuint *resultOut) const;
155     ANGLE_NO_DISCARD 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     ANGLE_NO_DISCARD bool computeCompressedImageSize(const Extents &size, GLuint *resultOut) const;
164 
165     ANGLE_NO_DISCARD std::pair<GLuint, GLuint> getCompressedImageMinBlocks() const;
166 
167     ANGLE_NO_DISCARD bool computeSkipBytes(GLenum formatType,
168                                            GLuint rowPitch,
169                                            GLuint depthPitch,
170                                            const PixelStoreStateBase &state,
171                                            bool is3D,
172                                            GLuint *resultOut) const;
173 
174     ANGLE_NO_DISCARD bool computePackUnpackEndByte(GLenum formatType,
175                                                    const Extents &size,
176                                                    const PixelStoreStateBase &state,
177                                                    bool is3D,
178                                                    GLuint *resultOut) const;
179 
180     bool isLUMA() const;
181     GLenum getReadPixelsFormat(const Extensions &extensions) const;
182     GLenum getReadPixelsType(const Version &version) const;
183 
184     // Support upload a portion of image?
185     bool supportSubImage() const;
186 
isChannelSizeCompatibleInternalFormat187     ANGLE_INLINE bool isChannelSizeCompatible(GLuint redSize,
188                                               GLuint greenSize,
189                                               GLuint blueSize,
190                                               GLuint alphaSize) const
191     {
192         // We only check for equality in all channel sizes
193         return ((redSize == redBits) && (greenSize == greenBits) && (blueSize == blueBits) &&
194                 (alphaSize == alphaBits));
195     }
196 
197     // Return true if the format is a required renderbuffer format in the given version of the core
198     // spec. Note that it isn't always clear whether all the rules that apply to core required
199     // renderbuffer formats also apply to additional formats added by extensions. Because of this
200     // extension formats are conservatively not included.
201     bool isRequiredRenderbufferFormat(const Version &version) const;
202 
203     bool isInt() const;
204     bool isDepthOrStencil() const;
205 
206     bool operator==(const InternalFormat &other) const;
207     bool operator!=(const InternalFormat &other) const;
208 
209     GLenum internalFormat;
210 
211     bool sized;
212     GLenum sizedInternalFormat;
213 
214     GLuint redBits;
215     GLuint greenBits;
216     GLuint blueBits;
217 
218     GLuint luminanceBits;
219 
220     GLuint alphaBits;
221     GLuint sharedBits;
222 
223     GLuint depthBits;
224     GLuint stencilBits;
225 
226     GLuint pixelBytes;
227 
228     GLuint componentCount;
229 
230     bool compressed;
231     GLuint compressedBlockWidth;
232     GLuint compressedBlockHeight;
233     GLuint compressedBlockDepth;
234 
235     GLenum format;
236     GLenum type;
237 
238     GLenum componentType;
239     GLenum colorEncoding;
240 
241     typedef bool (*SupportCheckFunction)(const Version &, const Extensions &);
242     SupportCheckFunction textureSupport;
243     SupportCheckFunction filterSupport;
244     SupportCheckFunction textureAttachmentSupport;  // glFramebufferTexture2D
245     SupportCheckFunction renderbufferSupport;       // glFramebufferRenderbuffer
246     SupportCheckFunction blendSupport;
247 };
248 
249 // A "Format" wraps an InternalFormat struct, querying it from either a sized internal format or
250 // unsized internal format and type.
251 // TODO(geofflang): Remove this, it doesn't add any more information than the InternalFormat object.
252 struct Format
253 {
254     // Sized types only.
255     explicit Format(GLenum internalFormat);
256 
257     // Sized or unsized types.
258     explicit Format(const InternalFormat &internalFormat);
259     Format(GLenum internalFormat, GLenum type);
260 
261     Format(const Format &other);
262     Format &operator=(const Format &other);
263 
264     bool valid() const;
265 
266     static Format Invalid();
267     static bool SameSized(const Format &a, const Format &b);
268     static bool EquivalentForBlit(const Format &a, const Format &b);
269 
270     friend std::ostream &operator<<(std::ostream &os, const Format &fmt);
271 
272     // This is the sized info.
273     const InternalFormat *info;
274 };
275 
276 const InternalFormat &GetSizedInternalFormatInfo(GLenum internalFormat);
277 const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, GLenum type);
278 
279 // Strip sizing information from an internal format.  Doesn't necessarily validate that the internal
280 // format is valid.
281 GLenum GetUnsizedFormat(GLenum internalFormat);
282 
283 // Return whether the compressed format requires whole image/mip level to be uploaded to texture.
284 bool CompressedFormatRequiresWholeImage(GLenum internalFormat);
285 
286 // In support of GetImage, check for LUMA formats and override with real format
287 void MaybeOverrideLuminance(GLenum &format, GLenum &type, GLenum actualFormat, GLenum actualType);
288 
289 typedef std::set<GLenum> FormatSet;
290 const FormatSet &GetAllSizedInternalFormats();
291 
292 typedef angle::HashMap<GLenum, angle::HashMap<GLenum, InternalFormat>> InternalFormatInfoMap;
293 const InternalFormatInfoMap &GetInternalFormatMap();
294 
295 int GetAndroidHardwareBufferFormatFromChannelSizes(const egl::AttributeMap &attribMap);
296 
297 GLenum GetConfigColorBufferFormat(const egl::Config *config);
298 GLenum GetConfigDepthStencilBufferFormat(const egl::Config *config);
299 
GetNativeVisualID(const InternalFormat & internalFormat)300 ANGLE_INLINE int GetNativeVisualID(const InternalFormat &internalFormat)
301 {
302     int nativeVisualId = 0;
303 #if defined(ANGLE_PLATFORM_ANDROID)
304     nativeVisualId =
305         angle::android::GLInternalFormatToNativePixelFormat(internalFormat.internalFormat);
306 #endif
307     return nativeVisualId;
308 }
309 
310 // From the ESSL 3.00.4 spec:
311 // Vertex shader inputs can only be float, floating-point vectors, matrices, signed and unsigned
312 // integers and integer vectors. Vertex shader inputs cannot be arrays or structures.
313 
314 enum AttributeType
315 {
316     ATTRIBUTE_FLOAT,
317     ATTRIBUTE_VEC2,
318     ATTRIBUTE_VEC3,
319     ATTRIBUTE_VEC4,
320     ATTRIBUTE_INT,
321     ATTRIBUTE_IVEC2,
322     ATTRIBUTE_IVEC3,
323     ATTRIBUTE_IVEC4,
324     ATTRIBUTE_UINT,
325     ATTRIBUTE_UVEC2,
326     ATTRIBUTE_UVEC3,
327     ATTRIBUTE_UVEC4,
328     ATTRIBUTE_MAT2,
329     ATTRIBUTE_MAT3,
330     ATTRIBUTE_MAT4,
331     ATTRIBUTE_MAT2x3,
332     ATTRIBUTE_MAT2x4,
333     ATTRIBUTE_MAT3x2,
334     ATTRIBUTE_MAT3x4,
335     ATTRIBUTE_MAT4x2,
336     ATTRIBUTE_MAT4x3,
337 };
338 
339 AttributeType GetAttributeType(GLenum enumValue);
340 
341 typedef std::vector<angle::FormatID> InputLayout;
342 
343 struct VertexFormat : private angle::NonCopyable
344 {
345     VertexFormat(GLenum typeIn, GLboolean normalizedIn, GLuint componentsIn, bool pureIntegerIn);
346 
347     GLenum type;
348     GLboolean normalized;
349     GLuint components;
350     bool pureInteger;
351 };
352 
353 angle::FormatID GetVertexFormatID(VertexAttribType type,
354                                   GLboolean normalized,
355                                   GLuint components,
356                                   bool pureInteger);
357 
358 angle::FormatID GetVertexFormatID(const VertexAttribute &attrib, VertexAttribType currentValueType);
359 angle::FormatID GetCurrentValueFormatID(VertexAttribType currentValueType);
360 const VertexFormat &GetVertexFormatFromID(angle::FormatID vertexFormatID);
361 size_t GetVertexFormatSize(angle::FormatID vertexFormatID);
362 angle::FormatID ConvertFormatSignedness(const angle::Format &format);
363 
IsS3TCFormat(const GLenum format)364 ANGLE_INLINE bool IsS3TCFormat(const GLenum format)
365 {
366     switch (format)
367     {
368         case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
369         case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
370         case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
371         case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
372         case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
373         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
374         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
375         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
376             return true;
377 
378         default:
379             return false;
380     }
381 }
382 
IsRGTCFormat(const GLenum format)383 ANGLE_INLINE bool IsRGTCFormat(const GLenum format)
384 {
385     switch (format)
386     {
387         case GL_COMPRESSED_RED_RGTC1_EXT:
388         case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
389         case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
390         case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
391             return true;
392 
393         default:
394             return false;
395     }
396 }
397 
IsBPTCFormat(const GLenum format)398 ANGLE_INLINE bool IsBPTCFormat(const GLenum format)
399 {
400     switch (format)
401     {
402         case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
403         case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
404         case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
405         case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
406             return true;
407 
408         default:
409             return false;
410     }
411 }
412 
IsASTC2DFormat(const GLenum format)413 ANGLE_INLINE bool IsASTC2DFormat(const GLenum format)
414 {
415     if ((format >= GL_COMPRESSED_RGBA_ASTC_4x4_KHR &&
416          format <= GL_COMPRESSED_RGBA_ASTC_12x12_KHR) ||
417         (format >= GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR &&
418          format <= GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR))
419     {
420         return true;
421     }
422     return false;
423 }
424 
IsETC1Format(const GLenum format)425 ANGLE_INLINE bool IsETC1Format(const GLenum format)
426 {
427     switch (format)
428     {
429         case GL_ETC1_RGB8_OES:
430         case GL_ETC1_SRGB8_NV:
431             return true;
432 
433         default:
434             return false;
435     }
436 }
437 
IsETC2EACFormat(const GLenum format)438 ANGLE_INLINE bool IsETC2EACFormat(const GLenum format)
439 {
440     // ES 3.1, Table 8.19
441     switch (format)
442     {
443         case GL_COMPRESSED_R11_EAC:
444         case GL_COMPRESSED_SIGNED_R11_EAC:
445         case GL_COMPRESSED_RG11_EAC:
446         case GL_COMPRESSED_SIGNED_RG11_EAC:
447         case GL_COMPRESSED_RGB8_ETC2:
448         case GL_COMPRESSED_SRGB8_ETC2:
449         case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
450         case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
451         case GL_COMPRESSED_RGBA8_ETC2_EAC:
452         case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
453             return true;
454 
455         default:
456             return false;
457     }
458 }
459 
IsPVRTC1Format(const GLenum format)460 ANGLE_INLINE bool IsPVRTC1Format(const GLenum format)
461 {
462     switch (format)
463     {
464         case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
465         case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
466         case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
467         case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
468         case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:
469         case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:
470         case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:
471         case GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:
472             return true;
473 
474         default:
475             return false;
476     }
477 }
478 
IsBGRAFormat(const GLenum internalFormat)479 ANGLE_INLINE bool IsBGRAFormat(const GLenum internalFormat)
480 {
481     switch (internalFormat)
482     {
483         case GL_BGRA8_EXT:
484         case GL_BGRA4_ANGLEX:
485         case GL_BGR5_A1_ANGLEX:
486         case GL_BGRA8_SRGB_ANGLEX:
487         case GL_BGRX8_ANGLEX:
488         case GL_RGBX8_ANGLE:
489         case GL_BGR565_ANGLEX:
490         case GL_BGR10_A2_ANGLEX:
491             return true;
492 
493         default:
494             return false;
495     }
496 }
497 
498 // Check if an internal format is ever valid in ES3.  Makes no checks about support for a specific
499 // context.
500 bool ValidES3InternalFormat(GLenum internalFormat);
501 
502 // Implemented in format_map_autogen.cpp
503 bool ValidES3Format(GLenum format);
504 bool ValidES3Type(GLenum type);
505 bool ValidES3FormatCombination(GLenum format, GLenum type, GLenum internalFormat);
506 
507 // Implemented in format_map_desktop.cpp
508 bool ValidDesktopFormat(GLenum format);
509 bool ValidDesktopType(GLenum type);
510 bool ValidDesktopFormatCombination(GLenum format, GLenum type, GLenum internalFormat);
511 
512 // Implemented in es3_copy_conversion_table_autogen.cpp
513 bool ValidES3CopyConversion(GLenum textureFormat, GLenum framebufferFormat);
514 
GetVertexAttributeComponentType(bool pureInteger,VertexAttribType type)515 ANGLE_INLINE ComponentType GetVertexAttributeComponentType(bool pureInteger, VertexAttribType type)
516 {
517     if (pureInteger)
518     {
519         switch (type)
520         {
521             case VertexAttribType::Byte:
522             case VertexAttribType::Short:
523             case VertexAttribType::Int:
524                 return ComponentType::Int;
525 
526             case VertexAttribType::UnsignedByte:
527             case VertexAttribType::UnsignedShort:
528             case VertexAttribType::UnsignedInt:
529                 return ComponentType::UnsignedInt;
530 
531             default:
532                 UNREACHABLE();
533                 return ComponentType::NoType;
534         }
535     }
536     else
537     {
538         return ComponentType::Float;
539     }
540 }
541 
542 constexpr std::size_t kMaxYuvPlaneCount = 3;
543 template <typename T>
544 using YuvPlaneArray = std::array<T, kMaxYuvPlaneCount>;
545 
546 struct YuvFormatInfo
547 {
548     // Sized types only.
549     YuvFormatInfo(GLenum internalFormat, const Extents &yPlaneExtent);
550 
551     GLenum glInternalFormat;
552     uint32_t planeCount;
553     YuvPlaneArray<uint32_t> planeBpp;
554     YuvPlaneArray<Extents> planeExtent;
555     YuvPlaneArray<uint32_t> planePitch;
556     YuvPlaneArray<uint32_t> planeSize;
557     YuvPlaneArray<uint32_t> planeOffset;
558 };
559 
560 bool IsYuvFormat(GLenum format);
561 uint32_t GetPlaneCount(GLenum format);
562 uint32_t GetYPlaneBpp(GLenum format);
563 uint32_t GetChromaPlaneBpp(GLenum format);
564 void GetSubSampleFactor(GLenum format,
565                         int *horizontalSubsampleFactor,
566                         int *verticalSubsampleFactor);
567 }  // namespace gl
568 
569 #endif  // LIBANGLE_FORMATUTILS_H_
570