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