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