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/Error.h"
20 #include "libANGLE/Version.h"
21 #include "libANGLE/VertexAttribute.h"
22 #include "libANGLE/angletypes.h"
23
24 namespace gl
25 {
26 struct VertexAttribute;
27
28 struct FormatType final
29 {
30 FormatType();
31 FormatType(GLenum format_, GLenum type_);
32 FormatType(const FormatType &other) = default;
33 FormatType &operator=(const FormatType &other) = default;
34
35 bool operator<(const FormatType &other) const;
36
37 GLenum format;
38 GLenum type;
39 };
40
41 struct Type
42 {
TypeType43 Type() : bytes(0), bytesShift(0), specialInterpretation(0) {}
44
TypeType45 explicit Type(uint32_t packedTypeInfo)
46 : bytes(packedTypeInfo & 0xff),
47 bytesShift((packedTypeInfo >> 8) & 0xff),
48 specialInterpretation((packedTypeInfo >> 16) & 1)
49 {}
50
51 GLuint bytes;
52 GLuint bytesShift; // Bit shift by this value to effectively divide/multiply by "bytes" in a
53 // more optimal way
54 bool specialInterpretation;
55 };
56
57 uint32_t GetPackedTypeInfo(GLenum type);
58
GetNonLinearFormat(const GLenum format)59 ANGLE_INLINE GLenum GetNonLinearFormat(const GLenum format)
60 {
61 switch (format)
62 {
63 case GL_BGRA8_EXT:
64 return GL_BGRA8_SRGB_ANGLEX;
65 case GL_RGBA8:
66 return GL_SRGB8_ALPHA8;
67 case GL_RGB8:
68 case GL_BGRX8_ANGLEX:
69 return GL_SRGB8;
70 case GL_RGBA16F:
71 return GL_RGBA16F;
72 default:
73 return GL_NONE;
74 }
75 }
76
ColorspaceFormatOverride(const EGLenum colorspace,GLenum * rendertargetformat)77 ANGLE_INLINE bool ColorspaceFormatOverride(const EGLenum colorspace, GLenum *rendertargetformat)
78 {
79 // Override the rendertargetformat based on colorpsace
80 switch (colorspace)
81 {
82 case EGL_GL_COLORSPACE_LINEAR: // linear colorspace no translation needed
83 case EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT: // linear colorspace no translation needed
84 case EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT: // linear colorspace no translation needed
85 case EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT: // App, not the HW, will specify the
86 // transfer function
87 case EGL_GL_COLORSPACE_SCRGB_EXT: // App, not the HW, will specify the transfer function
88 // No translation
89 return true;
90 case EGL_GL_COLORSPACE_SRGB_KHR:
91 case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
92 {
93 GLenum nonLinearFormat = GetNonLinearFormat(*rendertargetformat);
94 if (nonLinearFormat != GL_NONE)
95 {
96 *rendertargetformat = nonLinearFormat;
97 return true;
98 }
99 else
100 {
101 return false;
102 }
103 }
104 break;
105 default:
106 UNREACHABLE();
107 return false;
108 }
109 }
110
GetTypeInfo(GLenum type)111 ANGLE_INLINE const Type GetTypeInfo(GLenum type)
112 {
113 return Type(GetPackedTypeInfo(type));
114 }
115
116 // This helpers use tricks based on the assumption that the type has certain values.
117 static_assert(static_cast<GLuint>(DrawElementsType::UnsignedByte) == 0, "Please update this code.");
118 static_assert(static_cast<GLuint>(DrawElementsType::UnsignedShort) == 1,
119 "Please update this code.");
120 static_assert(static_cast<GLuint>(DrawElementsType::UnsignedInt) == 2, "Please update this code.");
GetDrawElementsTypeSize(DrawElementsType type)121 ANGLE_INLINE GLuint GetDrawElementsTypeSize(DrawElementsType type)
122 {
123 return (1 << static_cast<GLuint>(type));
124 }
125
GetDrawElementsTypeShift(DrawElementsType type)126 ANGLE_INLINE GLuint GetDrawElementsTypeShift(DrawElementsType type)
127 {
128 return static_cast<GLuint>(type);
129 }
130
131 // Information about an OpenGL internal format. Can be keyed on the internalFormat and type
132 // members.
133 struct InternalFormat
134 {
135 InternalFormat();
136 InternalFormat(const InternalFormat &other);
137
138 GLuint computePixelBytes(GLenum formatType) const;
139
140 ANGLE_NO_DISCARD bool computeRowPitch(GLenum formatType,
141 GLsizei width,
142 GLint alignment,
143 GLint rowLength,
144 GLuint *resultOut) const;
145 ANGLE_NO_DISCARD bool computeDepthPitch(GLsizei height,
146 GLint imageHeight,
147 GLuint rowPitch,
148 GLuint *resultOut) const;
149 ANGLE_NO_DISCARD bool computeDepthPitch(GLenum formatType,
150 GLsizei width,
151 GLsizei height,
152 GLint alignment,
153 GLint rowLength,
154 GLint imageHeight,
155 GLuint *resultOut) const;
156
157 ANGLE_NO_DISCARD bool computeCompressedImageSize(const Extents &size, GLuint *resultOut) const;
158
159 ANGLE_NO_DISCARD bool computeSkipBytes(GLenum formatType,
160 GLuint rowPitch,
161 GLuint depthPitch,
162 const PixelStoreStateBase &state,
163 bool is3D,
164 GLuint *resultOut) const;
165
166 ANGLE_NO_DISCARD bool computePackUnpackEndByte(GLenum formatType,
167 const Extents &size,
168 const PixelStoreStateBase &state,
169 bool is3D,
170 GLuint *resultOut) const;
171
172 bool isLUMA() const;
173 GLenum getReadPixelsFormat(const Extensions &extensions) const;
174 GLenum getReadPixelsType(const Version &version) const;
175
176 // Support upload a portion of image?
177 bool supportSubImage() const;
178
179 // Return true if the format is a required renderbuffer format in the given version of the core
180 // spec. Note that it isn't always clear whether all the rules that apply to core required
181 // renderbuffer formats also apply to additional formats added by extensions. Because of this
182 // extension formats are conservatively not included.
183 bool isRequiredRenderbufferFormat(const Version &version) const;
184
185 bool isInt() const;
186 bool isDepthOrStencil() const;
187
188 bool operator==(const InternalFormat &other) const;
189 bool operator!=(const InternalFormat &other) const;
190
191 GLenum internalFormat;
192
193 bool sized;
194 GLenum sizedInternalFormat;
195
196 GLuint redBits;
197 GLuint greenBits;
198 GLuint blueBits;
199
200 GLuint luminanceBits;
201
202 GLuint alphaBits;
203 GLuint sharedBits;
204
205 GLuint depthBits;
206 GLuint stencilBits;
207
208 GLuint pixelBytes;
209
210 GLuint componentCount;
211
212 bool compressed;
213 GLuint compressedBlockWidth;
214 GLuint compressedBlockHeight;
215 GLuint compressedBlockDepth;
216
217 GLenum format;
218 GLenum type;
219
220 GLenum componentType;
221 GLenum colorEncoding;
222
223 typedef bool (*SupportCheckFunction)(const Version &, const Extensions &);
224 SupportCheckFunction textureSupport;
225 SupportCheckFunction filterSupport;
226 SupportCheckFunction textureAttachmentSupport; // glFramebufferTexture2D
227 SupportCheckFunction renderbufferSupport; // glFramebufferRenderbuffer
228 SupportCheckFunction blendSupport;
229 };
230
231 // A "Format" wraps an InternalFormat struct, querying it from either a sized internal format or
232 // unsized internal format and type.
233 // TODO(geofflang): Remove this, it doesn't add any more information than the InternalFormat object.
234 struct Format
235 {
236 // Sized types only.
237 explicit Format(GLenum internalFormat);
238
239 // Sized or unsized types.
240 explicit Format(const InternalFormat &internalFormat);
241 Format(GLenum internalFormat, GLenum type);
242
243 Format(const Format &other);
244 Format &operator=(const Format &other);
245
246 bool valid() const;
247
248 static Format Invalid();
249 static bool SameSized(const Format &a, const Format &b);
250 static bool EquivalentForBlit(const Format &a, const Format &b);
251
252 friend std::ostream &operator<<(std::ostream &os, const Format &fmt);
253
254 // This is the sized info.
255 const InternalFormat *info;
256 };
257
258 const InternalFormat &GetSizedInternalFormatInfo(GLenum internalFormat);
259 const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, GLenum type);
260
261 // Strip sizing information from an internal format. Doesn't necessarily validate that the internal
262 // format is valid.
263 GLenum GetUnsizedFormat(GLenum internalFormat);
264
265 // Return whether the compressed format requires whole image/mip level to be uploaded to texture.
266 bool CompressedFormatRequiresWholeImage(GLenum internalFormat);
267
268 typedef std::set<GLenum> FormatSet;
269 const FormatSet &GetAllSizedInternalFormats();
270
271 typedef std::unordered_map<GLenum, std::unordered_map<GLenum, InternalFormat>>
272 InternalFormatInfoMap;
273 const InternalFormatInfoMap &GetInternalFormatMap();
274
GetNativeVisualID(const InternalFormat & internalFormat)275 ANGLE_INLINE int GetNativeVisualID(const InternalFormat &internalFormat)
276 {
277 int nativeVisualId = 0;
278 #if defined(ANGLE_PLATFORM_ANDROID)
279 nativeVisualId =
280 angle::android::GLInternalFormatToNativePixelFormat(internalFormat.internalFormat);
281 #endif
282 return nativeVisualId;
283 }
284
285 // From the ESSL 3.00.4 spec:
286 // Vertex shader inputs can only be float, floating-point vectors, matrices, signed and unsigned
287 // integers and integer vectors. Vertex shader inputs cannot be arrays or structures.
288
289 enum AttributeType
290 {
291 ATTRIBUTE_FLOAT,
292 ATTRIBUTE_VEC2,
293 ATTRIBUTE_VEC3,
294 ATTRIBUTE_VEC4,
295 ATTRIBUTE_INT,
296 ATTRIBUTE_IVEC2,
297 ATTRIBUTE_IVEC3,
298 ATTRIBUTE_IVEC4,
299 ATTRIBUTE_UINT,
300 ATTRIBUTE_UVEC2,
301 ATTRIBUTE_UVEC3,
302 ATTRIBUTE_UVEC4,
303 ATTRIBUTE_MAT2,
304 ATTRIBUTE_MAT3,
305 ATTRIBUTE_MAT4,
306 ATTRIBUTE_MAT2x3,
307 ATTRIBUTE_MAT2x4,
308 ATTRIBUTE_MAT3x2,
309 ATTRIBUTE_MAT3x4,
310 ATTRIBUTE_MAT4x2,
311 ATTRIBUTE_MAT4x3,
312 };
313
314 AttributeType GetAttributeType(GLenum enumValue);
315
316 typedef std::vector<angle::FormatID> InputLayout;
317
318 struct VertexFormat : private angle::NonCopyable
319 {
320 VertexFormat(GLenum typeIn, GLboolean normalizedIn, GLuint componentsIn, bool pureIntegerIn);
321
322 GLenum type;
323 GLboolean normalized;
324 GLuint components;
325 bool pureInteger;
326 };
327
328 angle::FormatID GetVertexFormatID(VertexAttribType type,
329 GLboolean normalized,
330 GLuint components,
331 bool pureInteger);
332
333 angle::FormatID GetVertexFormatID(const VertexAttribute &attrib, VertexAttribType currentValueType);
334 angle::FormatID GetCurrentValueFormatID(VertexAttribType currentValueType);
335 const VertexFormat &GetVertexFormatFromID(angle::FormatID vertexFormatID);
336 size_t GetVertexFormatSize(angle::FormatID vertexFormatID);
337
IsS3TCFormat(const GLenum format)338 ANGLE_INLINE bool IsS3TCFormat(const GLenum format)
339 {
340 switch (format)
341 {
342 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
343 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
344 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
345 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
346 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
347 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
348 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
349 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
350 return true;
351
352 default:
353 return false;
354 }
355 }
356
IsRGTCFormat(const GLenum format)357 ANGLE_INLINE bool IsRGTCFormat(const GLenum format)
358 {
359 switch (format)
360 {
361 case GL_COMPRESSED_RED_RGTC1_EXT:
362 case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
363 case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
364 case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
365 return true;
366
367 default:
368 return false;
369 }
370 }
371
IsASTC2DFormat(const GLenum format)372 ANGLE_INLINE bool IsASTC2DFormat(const GLenum format)
373 {
374 if ((format >= GL_COMPRESSED_RGBA_ASTC_4x4_KHR &&
375 format <= GL_COMPRESSED_RGBA_ASTC_12x12_KHR) ||
376 (format >= GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR &&
377 format <= GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR))
378 {
379 return true;
380 }
381 return false;
382 }
383
IsETC2EACFormat(const GLenum format)384 ANGLE_INLINE bool IsETC2EACFormat(const GLenum format)
385 {
386 // ES 3.1, Table 8.19
387 switch (format)
388 {
389 case GL_COMPRESSED_R11_EAC:
390 case GL_COMPRESSED_SIGNED_R11_EAC:
391 case GL_COMPRESSED_RG11_EAC:
392 case GL_COMPRESSED_SIGNED_RG11_EAC:
393 case GL_COMPRESSED_RGB8_ETC2:
394 case GL_COMPRESSED_SRGB8_ETC2:
395 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
396 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
397 case GL_COMPRESSED_RGBA8_ETC2_EAC:
398 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
399 return true;
400
401 default:
402 return false;
403 }
404 }
405
406 // Check if an internal format is ever valid in ES3. Makes no checks about support for a specific
407 // context.
408 bool ValidES3InternalFormat(GLenum internalFormat);
409
410 // Implemented in format_map_autogen.cpp
411 bool ValidES3Format(GLenum format);
412 bool ValidES3Type(GLenum type);
413 bool ValidES3FormatCombination(GLenum format, GLenum type, GLenum internalFormat);
414
415 // Implemented in format_map_desktop.cpp
416 bool ValidDesktopFormat(GLenum format);
417 bool ValidDesktopType(GLenum type);
418 bool ValidDesktopFormatCombination(GLenum format, GLenum type, GLenum internalFormat);
419
420 // Implemented in es3_copy_conversion_table_autogen.cpp
421 bool ValidES3CopyConversion(GLenum textureFormat, GLenum framebufferFormat);
422
GetVertexAttributeComponentType(bool pureInteger,VertexAttribType type)423 ANGLE_INLINE ComponentType GetVertexAttributeComponentType(bool pureInteger, VertexAttribType type)
424 {
425 if (pureInteger)
426 {
427 switch (type)
428 {
429 case VertexAttribType::Byte:
430 case VertexAttribType::Short:
431 case VertexAttribType::Int:
432 return ComponentType::Int;
433
434 case VertexAttribType::UnsignedByte:
435 case VertexAttribType::UnsignedShort:
436 case VertexAttribType::UnsignedInt:
437 return ComponentType::UnsignedInt;
438
439 default:
440 UNREACHABLE();
441 return ComponentType::NoType;
442 }
443 }
444 else
445 {
446 return ComponentType::Float;
447 }
448 }
449 } // namespace gl
450
451 #endif // LIBANGLE_FORMATUTILS_H_
452