1 //
2 // Copyright 2014 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 #include "libANGLE/Caps.h"
8
9 #include "anglebase/no_destructor.h"
10 #include "common/angleutils.h"
11 #include "common/debug.h"
12
13 #include "libANGLE/formatutils.h"
14
15 #include "angle_gl.h"
16
17 #include <algorithm>
18 #include <sstream>
19
InsertExtensionString(const std::string & extension,bool supported,std::vector<std::string> * extensionVector)20 static void InsertExtensionString(const std::string &extension,
21 bool supported,
22 std::vector<std::string> *extensionVector)
23 {
24 if (supported)
25 {
26 extensionVector->push_back(extension);
27 }
28 }
29
30 namespace gl
31 {
32
33 TextureCaps::TextureCaps() = default;
34
35 TextureCaps::TextureCaps(const TextureCaps &other) = default;
36
37 TextureCaps::~TextureCaps() = default;
38
getMaxSamples() const39 GLuint TextureCaps::getMaxSamples() const
40 {
41 return !sampleCounts.empty() ? *sampleCounts.rbegin() : 0;
42 }
43
getNearestSamples(GLuint requestedSamples) const44 GLuint TextureCaps::getNearestSamples(GLuint requestedSamples) const
45 {
46 if (requestedSamples == 0)
47 {
48 return 0;
49 }
50
51 for (SupportedSampleSet::const_iterator i = sampleCounts.begin(); i != sampleCounts.end(); i++)
52 {
53 GLuint samples = *i;
54 if (samples >= requestedSamples)
55 {
56 return samples;
57 }
58 }
59
60 return 0;
61 }
62
GenerateMinimumTextureCaps(GLenum sizedInternalFormat,const Version & clientVersion,const Extensions & extensions)63 TextureCaps GenerateMinimumTextureCaps(GLenum sizedInternalFormat,
64 const Version &clientVersion,
65 const Extensions &extensions)
66 {
67 TextureCaps caps;
68
69 const InternalFormat &internalFormatInfo = GetSizedInternalFormatInfo(sizedInternalFormat);
70 caps.texturable = internalFormatInfo.textureSupport(clientVersion, extensions);
71 caps.filterable = internalFormatInfo.filterSupport(clientVersion, extensions);
72 caps.textureAttachment = internalFormatInfo.textureAttachmentSupport(clientVersion, extensions);
73 caps.renderbuffer = internalFormatInfo.renderbufferSupport(clientVersion, extensions);
74
75 caps.sampleCounts.insert(0);
76 if (internalFormatInfo.isRequiredRenderbufferFormat(clientVersion))
77 {
78 if ((clientVersion.major >= 3 && clientVersion.minor >= 1) ||
79 (clientVersion.major >= 3 && !internalFormatInfo.isInt()))
80 {
81 caps.sampleCounts.insert(4);
82 }
83 }
84
85 return caps;
86 }
87
TextureCapsMap()88 TextureCapsMap::TextureCapsMap() {}
89
~TextureCapsMap()90 TextureCapsMap::~TextureCapsMap() {}
91
insert(GLenum internalFormat,const TextureCaps & caps)92 void TextureCapsMap::insert(GLenum internalFormat, const TextureCaps &caps)
93 {
94 angle::FormatID formatID = angle::Format::InternalFormatToID(internalFormat);
95 get(formatID) = caps;
96 }
97
clear()98 void TextureCapsMap::clear()
99 {
100 mFormatData.fill(TextureCaps());
101 }
102
get(GLenum internalFormat) const103 const TextureCaps &TextureCapsMap::get(GLenum internalFormat) const
104 {
105 angle::FormatID formatID = angle::Format::InternalFormatToID(internalFormat);
106 return get(formatID);
107 }
108
get(angle::FormatID formatID) const109 const TextureCaps &TextureCapsMap::get(angle::FormatID formatID) const
110 {
111 return mFormatData[static_cast<size_t>(formatID)];
112 }
113
get(angle::FormatID formatID)114 TextureCaps &TextureCapsMap::get(angle::FormatID formatID)
115 {
116 return mFormatData[static_cast<size_t>(formatID)];
117 }
118
set(angle::FormatID formatID,const TextureCaps & caps)119 void TextureCapsMap::set(angle::FormatID formatID, const TextureCaps &caps)
120 {
121 get(formatID) = caps;
122 }
123
InitMinimumTextureCapsMap(const Version & clientVersion,const Extensions & extensions,TextureCapsMap * capsMap)124 void InitMinimumTextureCapsMap(const Version &clientVersion,
125 const Extensions &extensions,
126 TextureCapsMap *capsMap)
127 {
128 for (GLenum internalFormat : GetAllSizedInternalFormats())
129 {
130 capsMap->insert(internalFormat,
131 GenerateMinimumTextureCaps(internalFormat, clientVersion, extensions));
132 }
133 }
134
135 Extensions::Extensions() = default;
136
137 Extensions::Extensions(const Extensions &other) = default;
138
getStrings() const139 std::vector<std::string> Extensions::getStrings() const
140 {
141 std::vector<std::string> extensionStrings;
142
143 for (const auto &extensionInfo : GetExtensionInfoMap())
144 {
145 if (this->*(extensionInfo.second.ExtensionsMember))
146 {
147 extensionStrings.push_back(extensionInfo.first);
148 }
149 }
150
151 return extensionStrings;
152 }
153
154 Limitations::Limitations() = default;
155
GetFormatSupportBase(const TextureCapsMap & textureCaps,const GLenum * requiredFormats,size_t requiredFormatsSize,bool requiresTexturing,bool requiresFiltering,bool requiresAttachingTexture,bool requiresRenderbufferSupport)156 static bool GetFormatSupportBase(const TextureCapsMap &textureCaps,
157 const GLenum *requiredFormats,
158 size_t requiredFormatsSize,
159 bool requiresTexturing,
160 bool requiresFiltering,
161 bool requiresAttachingTexture,
162 bool requiresRenderbufferSupport)
163 {
164 for (size_t i = 0; i < requiredFormatsSize; i++)
165 {
166 const TextureCaps &cap = textureCaps.get(requiredFormats[i]);
167
168 if (requiresTexturing && !cap.texturable)
169 {
170 return false;
171 }
172
173 if (requiresFiltering && !cap.filterable)
174 {
175 return false;
176 }
177
178 if (requiresAttachingTexture && !cap.textureAttachment)
179 {
180 return false;
181 }
182
183 if (requiresRenderbufferSupport && !cap.renderbuffer)
184 {
185 return false;
186 }
187 }
188
189 return true;
190 }
191
192 template <size_t N>
GetFormatSupport(const TextureCapsMap & textureCaps,const GLenum (& requiredFormats)[N],bool requiresTexturing,bool requiresFiltering,bool requiresAttachingTexture,bool requiresRenderbufferSupport)193 static bool GetFormatSupport(const TextureCapsMap &textureCaps,
194 const GLenum (&requiredFormats)[N],
195 bool requiresTexturing,
196 bool requiresFiltering,
197 bool requiresAttachingTexture,
198 bool requiresRenderbufferSupport)
199 {
200 return GetFormatSupportBase(textureCaps, requiredFormats, N, requiresTexturing,
201 requiresFiltering, requiresAttachingTexture,
202 requiresRenderbufferSupport);
203 }
204
205 // Check for GL_OES_packed_depth_stencil
DeterminePackedDepthStencilSupport(const TextureCapsMap & textureCaps)206 static bool DeterminePackedDepthStencilSupport(const TextureCapsMap &textureCaps)
207 {
208 constexpr GLenum requiredFormats[] = {
209 GL_DEPTH24_STENCIL8,
210 };
211
212 return GetFormatSupport(textureCaps, requiredFormats, false, false, true, true);
213 }
214
215 // Checks for GL_OES_rgb8_rgba8 support
DetermineRGB8AndRGBA8TextureSupport(const TextureCapsMap & textureCaps)216 static bool DetermineRGB8AndRGBA8TextureSupport(const TextureCapsMap &textureCaps)
217 {
218 constexpr GLenum requiredFormats[] = {
219 GL_RGB8,
220 GL_RGBA8,
221 };
222
223 return GetFormatSupport(textureCaps, requiredFormats, false, false, false, true);
224 }
225
226 // Checks for GL_EXT_texture_format_BGRA8888 support
DetermineBGRA8TextureSupport(const TextureCapsMap & textureCaps)227 static bool DetermineBGRA8TextureSupport(const TextureCapsMap &textureCaps)
228 {
229 constexpr GLenum requiredFormats[] = {
230 GL_BGRA8_EXT,
231 };
232
233 return GetFormatSupport(textureCaps, requiredFormats, true, true, true, true);
234 }
235
236 // Checks for GL_OES_color_buffer_half_float support
DetermineColorBufferHalfFloatSupport(const TextureCapsMap & textureCaps)237 static bool DetermineColorBufferHalfFloatSupport(const TextureCapsMap &textureCaps)
238 {
239 // EXT_color_buffer_half_float issue #2 states that an implementation doesn't need to support
240 // rendering to any of the formats but is expected to be able to render to at least one. WebGL
241 // requires that at least RGBA16F is renderable so we make the same requirement.
242 constexpr GLenum requiredFormats[] = {
243 GL_RGBA16F,
244 };
245
246 return GetFormatSupport(textureCaps, requiredFormats, false, false, true, true);
247 }
248
249 // Checks for GL_OES_texture_half_float support
DetermineHalfFloatTextureSupport(const TextureCapsMap & textureCaps)250 static bool DetermineHalfFloatTextureSupport(const TextureCapsMap &textureCaps)
251 {
252 constexpr GLenum requiredFormats[] = {
253 GL_RGBA16F, GL_RGB16F, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE16F_EXT, GL_ALPHA16F_EXT,
254 };
255
256 return GetFormatSupport(textureCaps, requiredFormats, true, false, false, false);
257 }
258
259 // Checks for GL_OES_texture_half_float_linear support
DetermineHalfFloatTextureFilteringSupport(const TextureCapsMap & textureCaps)260 static bool DetermineHalfFloatTextureFilteringSupport(const TextureCapsMap &textureCaps)
261 {
262 constexpr GLenum requiredFormats[] = {
263 GL_RGBA16F, GL_RGB16F, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE16F_EXT, GL_ALPHA16F_EXT,
264 };
265
266 return GetFormatSupport(textureCaps, requiredFormats, false, true, false, false);
267 }
268
269 // Checks for GL_OES_texture_float support
DetermineFloatTextureSupport(const TextureCapsMap & textureCaps)270 static bool DetermineFloatTextureSupport(const TextureCapsMap &textureCaps)
271 {
272 constexpr GLenum requiredFormats[] = {
273 GL_RGBA32F, GL_RGB32F, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE32F_EXT, GL_ALPHA32F_EXT,
274 };
275
276 return GetFormatSupport(textureCaps, requiredFormats, true, false, false, false);
277 }
278
279 // Checks for GL_OES_texture_float_linear support
DetermineFloatTextureFilteringSupport(const TextureCapsMap & textureCaps)280 static bool DetermineFloatTextureFilteringSupport(const TextureCapsMap &textureCaps)
281 {
282 constexpr GLenum requiredFormats[] = {
283 GL_RGBA32F, GL_RGB32F, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE32F_EXT, GL_ALPHA32F_EXT,
284 };
285
286 return GetFormatSupport(textureCaps, requiredFormats, false, true, false, false);
287 }
288
289 // Checks for GL_EXT_texture_rg support
DetermineRGTextureSupport(const TextureCapsMap & textureCaps,bool checkHalfFloatFormats,bool checkFloatFormats)290 static bool DetermineRGTextureSupport(const TextureCapsMap &textureCaps,
291 bool checkHalfFloatFormats,
292 bool checkFloatFormats)
293 {
294 constexpr GLenum requiredFormats[] = {
295 GL_R8,
296 GL_RG8,
297 };
298 constexpr GLenum requiredHalfFloatFormats[] = {
299 GL_R16F,
300 GL_RG16F,
301 };
302 constexpr GLenum requiredFloatFormats[] = {
303 GL_R32F,
304 GL_RG32F,
305 };
306
307 if (checkHalfFloatFormats &&
308 !GetFormatSupport(textureCaps, requiredHalfFloatFormats, true, false, false, false))
309 {
310 return false;
311 }
312
313 if (checkFloatFormats &&
314 !GetFormatSupport(textureCaps, requiredFloatFormats, true, false, false, false))
315 {
316 return false;
317 }
318
319 return GetFormatSupport(textureCaps, requiredFormats, true, true, true, true);
320 }
321
322 // Check for GL_EXT_texture_compression_dxt1
DetermineDXT1TextureSupport(const TextureCapsMap & textureCaps)323 static bool DetermineDXT1TextureSupport(const TextureCapsMap &textureCaps)
324 {
325 constexpr GLenum requiredFormats[] = {
326 GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
327 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
328 };
329
330 return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false);
331 }
332
333 // Check for GL_ANGLE_texture_compression_dxt3
DetermineDXT3TextureSupport(const TextureCapsMap & textureCaps)334 static bool DetermineDXT3TextureSupport(const TextureCapsMap &textureCaps)
335 {
336 constexpr GLenum requiredFormats[] = {
337 GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,
338 };
339
340 return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false);
341 }
342
343 // Check for GL_ANGLE_texture_compression_dxt5
DetermineDXT5TextureSupport(const TextureCapsMap & textureCaps)344 static bool DetermineDXT5TextureSupport(const TextureCapsMap &textureCaps)
345 {
346 constexpr GLenum requiredFormats[] = {
347 GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,
348 };
349
350 return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false);
351 }
352
353 // Check for GL_EXT_texture_compression_s3tc_srgb
DetermineS3TCsRGBTextureSupport(const TextureCapsMap & textureCaps)354 static bool DetermineS3TCsRGBTextureSupport(const TextureCapsMap &textureCaps)
355 {
356 constexpr GLenum requiredFormats[] = {
357 GL_COMPRESSED_SRGB_S3TC_DXT1_EXT,
358 GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,
359 GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,
360 GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,
361 };
362
363 return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false);
364 }
365
366 // Check for GL_KHR_texture_compression_astc_ldr
DetermineASTCLDRTextureSupport(const TextureCapsMap & textureCaps)367 static bool DetermineASTCLDRTextureSupport(const TextureCapsMap &textureCaps)
368 {
369 constexpr GLenum requiredFormats[] = {
370 GL_COMPRESSED_RGBA_ASTC_4x4_KHR, GL_COMPRESSED_RGBA_ASTC_5x4_KHR,
371 GL_COMPRESSED_RGBA_ASTC_5x5_KHR, GL_COMPRESSED_RGBA_ASTC_6x5_KHR,
372 GL_COMPRESSED_RGBA_ASTC_6x6_KHR, GL_COMPRESSED_RGBA_ASTC_8x5_KHR,
373 GL_COMPRESSED_RGBA_ASTC_8x6_KHR, GL_COMPRESSED_RGBA_ASTC_8x8_KHR,
374 GL_COMPRESSED_RGBA_ASTC_10x5_KHR, GL_COMPRESSED_RGBA_ASTC_10x6_KHR,
375 GL_COMPRESSED_RGBA_ASTC_10x8_KHR, GL_COMPRESSED_RGBA_ASTC_10x10_KHR,
376 GL_COMPRESSED_RGBA_ASTC_12x10_KHR, GL_COMPRESSED_RGBA_ASTC_12x12_KHR,
377 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR,
378 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR,
379 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR,
380 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR,
381 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR,
382 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR,
383 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR,
384 };
385
386 return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false);
387 }
388
389 // Check for GL_OES_texture_compression_astc
DetermineASTCOESTExtureSupport(const TextureCapsMap & textureCaps)390 static bool DetermineASTCOESTExtureSupport(const TextureCapsMap &textureCaps)
391 {
392 if (!DetermineASTCLDRTextureSupport(textureCaps))
393 {
394 return false;
395 }
396
397 // The OES version of the extension also requires the 3D ASTC formats
398 constexpr GLenum requiredFormats[] = {
399 GL_COMPRESSED_RGBA_ASTC_3x3x3_OES, GL_COMPRESSED_RGBA_ASTC_4x3x3_OES,
400 GL_COMPRESSED_RGBA_ASTC_4x4x3_OES, GL_COMPRESSED_RGBA_ASTC_4x4x4_OES,
401 GL_COMPRESSED_RGBA_ASTC_5x4x4_OES, GL_COMPRESSED_RGBA_ASTC_5x5x4_OES,
402 GL_COMPRESSED_RGBA_ASTC_5x5x5_OES, GL_COMPRESSED_RGBA_ASTC_6x5x5_OES,
403 GL_COMPRESSED_RGBA_ASTC_6x6x5_OES, GL_COMPRESSED_RGBA_ASTC_6x6x6_OES,
404 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES,
405 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES,
406 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES,
407 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES,
408 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES,
409 };
410
411 return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false);
412 }
413
414 // Check for GL_ETC1_RGB8_OES
DetermineETC1RGB8TextureSupport(const TextureCapsMap & textureCaps)415 static bool DetermineETC1RGB8TextureSupport(const TextureCapsMap &textureCaps)
416 {
417 constexpr GLenum requiredFormats[] = {
418 GL_ETC1_RGB8_OES,
419 };
420
421 return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false);
422 }
423
424 // Check for OES_compressed_ETC2_RGB8_texture
DetermineETC2RGB8TextureSupport(const TextureCapsMap & textureCaps)425 static bool DetermineETC2RGB8TextureSupport(const TextureCapsMap &textureCaps)
426 {
427 constexpr GLenum requiredFormats[] = {
428 GL_COMPRESSED_RGB8_ETC2,
429 };
430
431 return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false);
432 }
433
434 // Check for OES_compressed_ETC2_sRGB8_texture
DetermineETC2sRGB8TextureSupport(const TextureCapsMap & textureCaps)435 static bool DetermineETC2sRGB8TextureSupport(const TextureCapsMap &textureCaps)
436 {
437 constexpr GLenum requiredFormats[] = {
438 GL_COMPRESSED_SRGB8_ETC2,
439 };
440
441 return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false);
442 }
443
444 // Check for OES_compressed_ETC2_punchthroughA_RGBA8_texture
DetermineETC2PunchthroughARGB8TextureSupport(const TextureCapsMap & textureCaps)445 static bool DetermineETC2PunchthroughARGB8TextureSupport(const TextureCapsMap &textureCaps)
446 {
447 constexpr GLenum requiredFormats[] = {
448 GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
449 };
450
451 return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false);
452 }
453
454 // Check for OES_compressed_ETC2_punchthroughA_sRGB8_alpha_texture
DetermineETC2PunchthroughAsRGB8AlphaTextureSupport(const TextureCapsMap & textureCaps)455 static bool DetermineETC2PunchthroughAsRGB8AlphaTextureSupport(const TextureCapsMap &textureCaps)
456 {
457 constexpr GLenum requiredFormats[] = {
458 GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
459 };
460
461 return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false);
462 }
463
464 // Check for OES_compressed_ETC2_RGBA8_texture
DetermineETC2RGBA8TextureSupport(const TextureCapsMap & textureCaps)465 static bool DetermineETC2RGBA8TextureSupport(const TextureCapsMap &textureCaps)
466 {
467 constexpr GLenum requiredFormats[] = {
468 GL_COMPRESSED_RGBA8_ETC2_EAC,
469 };
470
471 return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false);
472 }
473
474 // Check for OES_compressed_ETC2_sRGB8_alpha8_texture
DetermineETC2sRGB8Alpha8TextureSupport(const TextureCapsMap & textureCaps)475 static bool DetermineETC2sRGB8Alpha8TextureSupport(const TextureCapsMap &textureCaps)
476 {
477 constexpr GLenum requiredFormats[] = {
478 GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
479 };
480
481 return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false);
482 }
483
484 // Check for OES_compressed_EAC_R11_unsigned_texture
DetermineEACR11UnsignedTextureSupport(const TextureCapsMap & textureCaps)485 static bool DetermineEACR11UnsignedTextureSupport(const TextureCapsMap &textureCaps)
486 {
487 constexpr GLenum requiredFormats[] = {
488 GL_COMPRESSED_R11_EAC,
489 };
490
491 return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false);
492 }
493
494 // Check for OES_compressed_EAC_R11_signed_texture
DetermineEACR11SignedTextureSupport(const TextureCapsMap & textureCaps)495 static bool DetermineEACR11SignedTextureSupport(const TextureCapsMap &textureCaps)
496 {
497 constexpr GLenum requiredFormats[] = {
498 GL_COMPRESSED_SIGNED_R11_EAC,
499 };
500
501 return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false);
502 }
503
504 // Check for OES_compressed_EAC_RG11_unsigned_texture
DetermineEACRG11UnsignedTextureSupport(const TextureCapsMap & textureCaps)505 static bool DetermineEACRG11UnsignedTextureSupport(const TextureCapsMap &textureCaps)
506 {
507 constexpr GLenum requiredFormats[] = {
508 GL_COMPRESSED_RG11_EAC,
509 };
510
511 return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false);
512 }
513
514 // Check for OES_compressed_EAC_RG11_signed_texture
DetermineEACRG11SignedTextureSupport(const TextureCapsMap & textureCaps)515 static bool DetermineEACRG11SignedTextureSupport(const TextureCapsMap &textureCaps)
516 {
517 constexpr GLenum requiredFormats[] = {
518 GL_COMPRESSED_SIGNED_RG11_EAC,
519 };
520
521 return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false);
522 }
523
524 // Check for GL_EXT_sRGB
DetermineSRGBTextureSupport(const TextureCapsMap & textureCaps)525 static bool DetermineSRGBTextureSupport(const TextureCapsMap &textureCaps)
526 {
527 constexpr GLenum requiredFilterFormats[] = {
528 GL_SRGB8,
529 GL_SRGB8_ALPHA8,
530 };
531
532 constexpr GLenum requiredRenderFormats[] = {
533 GL_SRGB8_ALPHA8,
534 };
535
536 return GetFormatSupport(textureCaps, requiredFilterFormats, true, true, false, false) &&
537 GetFormatSupport(textureCaps, requiredRenderFormats, true, false, true, true);
538 }
539
540 // Check for GL_ANGLE_depth_texture
DetermineDepthTextureANGLESupport(const TextureCapsMap & textureCaps)541 static bool DetermineDepthTextureANGLESupport(const TextureCapsMap &textureCaps)
542 {
543 constexpr GLenum requiredFormats[] = {
544 GL_DEPTH_COMPONENT16,
545 GL_DEPTH_COMPONENT32_OES,
546 GL_DEPTH24_STENCIL8_OES,
547 };
548
549 return GetFormatSupport(textureCaps, requiredFormats, true, true, true, true);
550 }
551
552 // Check for GL_OES_depth_texture
DetermineDepthTextureOESSupport(const TextureCapsMap & textureCaps)553 static bool DetermineDepthTextureOESSupport(const TextureCapsMap &textureCaps)
554 {
555 constexpr GLenum requiredFormats[] = {
556 GL_DEPTH_COMPONENT16,
557 GL_DEPTH_COMPONENT32_OES,
558 };
559
560 return GetFormatSupport(textureCaps, requiredFormats, true, true, true, true);
561 }
562
563 // Check for GL_OES_depth24
DetermineDepth24OESSupport(const TextureCapsMap & textureCaps)564 static bool DetermineDepth24OESSupport(const TextureCapsMap &textureCaps)
565 {
566 constexpr GLenum requiredFormats[] = {
567 GL_DEPTH_COMPONENT24_OES,
568 };
569
570 return GetFormatSupport(textureCaps, requiredFormats, false, false, false, true);
571 }
572
573 // Check for GL_OES_depth32
DetermineDepth32Support(const TextureCapsMap & textureCaps)574 static bool DetermineDepth32Support(const TextureCapsMap &textureCaps)
575 {
576 constexpr GLenum requiredFormats[] = {
577 GL_DEPTH_COMPONENT32_OES,
578 };
579
580 return GetFormatSupport(textureCaps, requiredFormats, false, false, true, true);
581 }
582
583 // Check for GL_CHROMIUM_color_buffer_float_rgb
DetermineColorBufferFloatRGBSupport(const TextureCapsMap & textureCaps)584 static bool DetermineColorBufferFloatRGBSupport(const TextureCapsMap &textureCaps)
585 {
586 constexpr GLenum requiredFormats[] = {
587 GL_RGB32F,
588 };
589
590 return GetFormatSupport(textureCaps, requiredFormats, true, false, true, false);
591 }
592
593 // Check for GL_CHROMIUM_color_buffer_float_rgba
DetermineColorBufferFloatRGBASupport(const TextureCapsMap & textureCaps)594 static bool DetermineColorBufferFloatRGBASupport(const TextureCapsMap &textureCaps)
595 {
596 constexpr GLenum requiredFormats[] = {
597 GL_RGBA32F,
598 };
599
600 return GetFormatSupport(textureCaps, requiredFormats, true, false, true, true);
601 }
602
603 // Check for GL_EXT_color_buffer_float
DetermineColorBufferFloatSupport(const TextureCapsMap & textureCaps)604 static bool DetermineColorBufferFloatSupport(const TextureCapsMap &textureCaps)
605 {
606 constexpr GLenum requiredFormats[] = {
607 GL_R16F, GL_RG16F, GL_RGBA16F, GL_R32F, GL_RG32F, GL_RGBA32F, GL_R11F_G11F_B10F,
608 };
609
610 return GetFormatSupport(textureCaps, requiredFormats, true, false, true, true);
611 }
612
613 // Check for GL_EXT_texture_norm16
DetermineTextureNorm16Support(const TextureCapsMap & textureCaps)614 static bool DetermineTextureNorm16Support(const TextureCapsMap &textureCaps)
615 {
616 constexpr GLenum requiredFilterFormats[] = {
617 GL_R16_EXT, GL_RG16_EXT, GL_RGB16_EXT, GL_RGBA16_EXT,
618 GL_R16_SNORM_EXT, GL_RG16_SNORM_EXT, GL_RGB16_SNORM_EXT, GL_RGBA16_SNORM_EXT,
619 };
620
621 constexpr GLenum requiredRenderFormats[] = {
622 GL_R16_EXT,
623 GL_RG16_EXT,
624 GL_RGBA16_EXT,
625 };
626
627 return GetFormatSupport(textureCaps, requiredFilterFormats, true, true, false, false) &&
628 GetFormatSupport(textureCaps, requiredRenderFormats, true, false, true, true);
629 }
630
631 // Check for EXT_texture_compression_bptc
DetermineBPTCTextureSupport(const TextureCapsMap & textureCaps)632 static bool DetermineBPTCTextureSupport(const TextureCapsMap &textureCaps)
633 {
634 constexpr GLenum requiredFormats[] = {
635 GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT,
636 GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT};
637
638 return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false);
639 }
640
DetermineCompressedTextureETCSupport(const TextureCapsMap & textureCaps)641 bool DetermineCompressedTextureETCSupport(const TextureCapsMap &textureCaps)
642 {
643 constexpr GLenum requiredFormats[] = {GL_COMPRESSED_R11_EAC,
644 GL_COMPRESSED_SIGNED_R11_EAC,
645 GL_COMPRESSED_RG11_EAC,
646 GL_COMPRESSED_SIGNED_RG11_EAC,
647 GL_COMPRESSED_RGB8_ETC2,
648 GL_COMPRESSED_SRGB8_ETC2,
649 GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
650 GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
651 GL_COMPRESSED_RGBA8_ETC2_EAC,
652 GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC};
653
654 return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false);
655 }
656
setTextureExtensionSupport(const TextureCapsMap & textureCaps)657 void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps)
658 {
659 // TODO(ynovikov): rgb8rgba8, colorBufferHalfFloat, textureHalfFloat, textureHalfFloatLinear,
660 // textureFloat, textureFloatLinear, textureRG, sRGB, colorBufferFloatRGB, colorBufferFloatRGBA
661 // and colorBufferFloat were verified. Verify the rest.
662 packedDepthStencil = DeterminePackedDepthStencilSupport(textureCaps);
663 rgb8rgba8 = DetermineRGB8AndRGBA8TextureSupport(textureCaps);
664 textureFormatBGRA8888 = DetermineBGRA8TextureSupport(textureCaps);
665 textureHalfFloat = DetermineHalfFloatTextureSupport(textureCaps);
666 textureHalfFloatLinear =
667 textureHalfFloat && DetermineHalfFloatTextureFilteringSupport(textureCaps);
668 textureFloat = DetermineFloatTextureSupport(textureCaps);
669 textureFloatLinear = textureFloat && DetermineFloatTextureFilteringSupport(textureCaps);
670 textureRG = DetermineRGTextureSupport(textureCaps, textureHalfFloat, textureFloat);
671 colorBufferHalfFloat = textureHalfFloat && DetermineColorBufferHalfFloatSupport(textureCaps);
672 textureCompressionDXT1 = DetermineDXT1TextureSupport(textureCaps);
673 textureCompressionDXT3 = DetermineDXT3TextureSupport(textureCaps);
674 textureCompressionDXT5 = DetermineDXT5TextureSupport(textureCaps);
675 textureCompressionS3TCsRGB = DetermineS3TCsRGBTextureSupport(textureCaps);
676 textureCompressionASTCLDRKHR = DetermineASTCLDRTextureSupport(textureCaps);
677 textureCompressionASTCOES = DetermineASTCOESTExtureSupport(textureCaps);
678 compressedETC1RGB8Texture = DetermineETC1RGB8TextureSupport(textureCaps);
679 compressedETC2RGB8Texture = DetermineETC2RGB8TextureSupport(textureCaps);
680 compressedETC2sRGB8Texture = DetermineETC2sRGB8TextureSupport(textureCaps);
681 compressedETC2PunchthroughARGB8Texture =
682 DetermineETC2PunchthroughARGB8TextureSupport(textureCaps);
683 compressedETC2PunchthroughAsRGB8AlphaTexture =
684 DetermineETC2PunchthroughAsRGB8AlphaTextureSupport(textureCaps);
685 compressedETC2RGBA8Texture = DetermineETC2RGBA8TextureSupport(textureCaps);
686 compressedETC2sRGB8Alpha8Texture = DetermineETC2sRGB8Alpha8TextureSupport(textureCaps);
687 compressedEACR11UnsignedTexture = DetermineEACR11UnsignedTextureSupport(textureCaps);
688 compressedEACR11SignedTexture = DetermineEACR11SignedTextureSupport(textureCaps);
689 compressedEACRG11UnsignedTexture = DetermineEACRG11UnsignedTextureSupport(textureCaps);
690 compressedEACRG11SignedTexture = DetermineEACRG11SignedTextureSupport(textureCaps);
691 sRGB = DetermineSRGBTextureSupport(textureCaps);
692 depthTextureANGLE = DetermineDepthTextureANGLESupport(textureCaps);
693 depthTextureOES = DetermineDepthTextureOESSupport(textureCaps);
694 depth24OES = DetermineDepth24OESSupport(textureCaps);
695 depth32 = DetermineDepth32Support(textureCaps);
696 colorBufferFloatRGB = DetermineColorBufferFloatRGBSupport(textureCaps);
697 colorBufferFloatRGBA = DetermineColorBufferFloatRGBASupport(textureCaps);
698 colorBufferFloat = DetermineColorBufferFloatSupport(textureCaps);
699 textureNorm16 = DetermineTextureNorm16Support(textureCaps);
700 textureCompressionBPTC = DetermineBPTCTextureSupport(textureCaps);
701 }
702
GetExtensionInfoMap()703 const ExtensionInfoMap &GetExtensionInfoMap()
704 {
705 auto buildExtensionInfoMap = []() {
706 auto enableableExtension = [](ExtensionInfo::ExtensionBool member) {
707 ExtensionInfo info;
708 info.Requestable = true;
709 info.ExtensionsMember = member;
710 return info;
711 };
712
713 auto esOnlyExtension = [](ExtensionInfo::ExtensionBool member) {
714 ExtensionInfo info;
715 info.ExtensionsMember = member;
716 return info;
717 };
718
719 // clang-format off
720 ExtensionInfoMap map;
721 map["GL_OES_element_index_uint"] = enableableExtension(&Extensions::elementIndexUint);
722 map["GL_OES_packed_depth_stencil"] = esOnlyExtension(&Extensions::packedDepthStencil);
723 map["GL_OES_get_program_binary"] = enableableExtension(&Extensions::getProgramBinary);
724 map["GL_OES_rgb8_rgba8"] = enableableExtension(&Extensions::rgb8rgba8);
725 map["GL_EXT_texture_format_BGRA8888"] = enableableExtension(&Extensions::textureFormatBGRA8888);
726 map["GL_EXT_read_format_bgra"] = esOnlyExtension(&Extensions::readFormatBGRA);
727 map["GL_NV_pixel_buffer_object"] = enableableExtension(&Extensions::pixelBufferObject);
728 map["GL_OES_mapbuffer"] = enableableExtension(&Extensions::mapBuffer);
729 map["GL_EXT_map_buffer_range"] = enableableExtension(&Extensions::mapBufferRange);
730 map["GL_EXT_color_buffer_half_float"] = enableableExtension(&Extensions::colorBufferHalfFloat);
731 map["GL_OES_texture_half_float"] = enableableExtension(&Extensions::textureHalfFloat);
732 map["GL_OES_texture_half_float_linear"] = enableableExtension(&Extensions::textureHalfFloatLinear);
733 map["GL_OES_texture_float"] = enableableExtension(&Extensions::textureFloat);
734 map["GL_OES_texture_float_linear"] = enableableExtension(&Extensions::textureFloatLinear);
735 map["GL_EXT_texture_rg"] = enableableExtension(&Extensions::textureRG);
736 map["GL_EXT_texture_compression_dxt1"] = enableableExtension(&Extensions::textureCompressionDXT1);
737 map["GL_ANGLE_texture_compression_dxt3"] = enableableExtension(&Extensions::textureCompressionDXT3);
738 map["GL_ANGLE_texture_compression_dxt5"] = enableableExtension(&Extensions::textureCompressionDXT5);
739 map["GL_EXT_texture_compression_s3tc_srgb"] = enableableExtension(&Extensions::textureCompressionS3TCsRGB);
740 map["GL_KHR_texture_compression_astc_ldr"] = enableableExtension(&Extensions::textureCompressionASTCLDRKHR);
741 map["GL_KHR_texture_compression_astc_hdr"] = enableableExtension(&Extensions::textureCompressionASTCHDRKHR);
742 map["GL_OES_texture_compression_astc"] = enableableExtension(&Extensions::textureCompressionASTCOES);
743 map["GL_EXT_texture_compression_bptc"] = enableableExtension(&Extensions::textureCompressionBPTC);
744 map["GL_OES_compressed_ETC1_RGB8_texture"] = enableableExtension(&Extensions::compressedETC1RGB8Texture);
745 map["OES_compressed_ETC2_RGB8_texture"] = enableableExtension(&Extensions::compressedETC2RGB8Texture);
746 map["OES_compressed_ETC2_sRGB8_texture"] = enableableExtension(&Extensions::compressedETC2sRGB8Texture);
747 map["OES_compressed_ETC2_punchthroughA_RGBA8_texture"] = enableableExtension(&Extensions::compressedETC2PunchthroughARGB8Texture);
748 map["OES_compressed_ETC2_punchthroughA_sRGB8_alpha_texture"] = enableableExtension(&Extensions::compressedETC2PunchthroughAsRGB8AlphaTexture);
749 map["OES_compressed_ETC2_RGBA8_texture"] = enableableExtension(&Extensions::compressedETC2RGBA8Texture);
750 map["OES_compressed_ETC2_sRGB8_alpha8_texture"] = enableableExtension(&Extensions::compressedETC2sRGB8Alpha8Texture);
751 map["OES_compressed_EAC_R11_unsigned_texture"] = enableableExtension(&Extensions::compressedEACR11UnsignedTexture);
752 map["OES_compressed_EAC_R11_signed_texture"] = enableableExtension(&Extensions::compressedEACR11SignedTexture);
753 map["OES_compressed_EAC_RG11_unsigned_texture"] = enableableExtension(&Extensions::compressedEACRG11UnsignedTexture);
754 map["OES_compressed_EAC_RG11_signed_texture"] = enableableExtension(&Extensions::compressedEACRG11SignedTexture);
755 map["GL_CHROMIUM_compressed_texture_etc"] = enableableExtension(&Extensions::compressedTextureETC);
756 map["GL_EXT_sRGB"] = enableableExtension(&Extensions::sRGB);
757 map["GL_ANGLE_depth_texture"] = esOnlyExtension(&Extensions::depthTextureANGLE);
758 map["GL_OES_depth_texture"] = esOnlyExtension(&Extensions::depthTextureOES);
759 map["GL_OES_depth24"] = esOnlyExtension(&Extensions::depth24OES);
760 map["GL_OES_depth32"] = esOnlyExtension(&Extensions::depth32);
761 map["GL_OES_texture_3D"] = enableableExtension(&Extensions::texture3DOES);
762 map["GL_EXT_texture_storage"] = enableableExtension(&Extensions::textureStorage);
763 map["GL_OES_texture_npot"] = enableableExtension(&Extensions::textureNPOT);
764 map["GL_EXT_draw_buffers"] = enableableExtension(&Extensions::drawBuffers);
765 map["GL_EXT_texture_filter_anisotropic"] = enableableExtension(&Extensions::textureFilterAnisotropic);
766 map["GL_EXT_occlusion_query_boolean"] = enableableExtension(&Extensions::occlusionQueryBoolean);
767 map["GL_NV_fence"] = esOnlyExtension(&Extensions::fence);
768 map["GL_EXT_disjoint_timer_query"] = enableableExtension(&Extensions::disjointTimerQuery);
769 map["GL_EXT_robustness"] = esOnlyExtension(&Extensions::robustness);
770 map["GL_KHR_robust_buffer_access_behavior"] = esOnlyExtension(&Extensions::robustBufferAccessBehavior);
771 map["GL_EXT_blend_minmax"] = enableableExtension(&Extensions::blendMinMax);
772 map["GL_ANGLE_framebuffer_blit"] = enableableExtension(&Extensions::framebufferBlit);
773 map["GL_ANGLE_framebuffer_multisample"] = enableableExtension(&Extensions::framebufferMultisample);
774 map["GL_ANGLE_instanced_arrays"] = enableableExtension(&Extensions::instancedArraysANGLE);
775 map["GL_EXT_instanced_arrays"] = enableableExtension(&Extensions::instancedArraysEXT);
776 map["GL_ANGLE_pack_reverse_row_order"] = enableableExtension(&Extensions::packReverseRowOrder);
777 map["GL_OES_standard_derivatives"] = enableableExtension(&Extensions::standardDerivatives);
778 map["GL_EXT_shader_texture_lod"] = enableableExtension(&Extensions::shaderTextureLOD);
779 map["GL_EXT_frag_depth"] = enableableExtension(&Extensions::fragDepth);
780 map["GL_OVR_multiview"] = enableableExtension(&Extensions::multiview);
781 map["GL_OVR_multiview2"] = enableableExtension(&Extensions::multiview2);
782 map["GL_ANGLE_texture_usage"] = enableableExtension(&Extensions::textureUsage);
783 map["GL_ANGLE_translated_shader_source"] = esOnlyExtension(&Extensions::translatedShaderSource);
784 map["GL_OES_fbo_render_mipmap"] = enableableExtension(&Extensions::fboRenderMipmap);
785 map["GL_EXT_discard_framebuffer"] = esOnlyExtension(&Extensions::discardFramebuffer);
786 map["GL_EXT_debug_marker"] = esOnlyExtension(&Extensions::debugMarker);
787 map["GL_OES_EGL_image"] = enableableExtension(&Extensions::eglImage);
788 map["GL_OES_EGL_image_external"] = enableableExtension(&Extensions::eglImageExternal);
789 map["GL_OES_EGL_image_external_essl3"] = enableableExtension(&Extensions::eglImageExternalEssl3);
790 map["GL_OES_EGL_sync"] = esOnlyExtension(&Extensions::eglSync);
791 map["GL_EXT_memory_object"] = enableableExtension(&Extensions::memoryObject);
792 map["GL_EXT_memory_object_fd"] = enableableExtension(&Extensions::memoryObjectFd);
793 map["GL_EXT_semaphore"] = enableableExtension(&Extensions::semaphore);
794 map["GL_EXT_semaphore_fd"] = enableableExtension(&Extensions::semaphoreFd);
795 map["GL_NV_EGL_stream_consumer_external"] = enableableExtension(&Extensions::eglStreamConsumerExternal);
796 map["GL_EXT_unpack_subimage"] = enableableExtension(&Extensions::unpackSubimage);
797 map["GL_NV_pack_subimage"] = enableableExtension(&Extensions::packSubimage);
798 map["GL_EXT_color_buffer_float"] = enableableExtension(&Extensions::colorBufferFloat);
799 map["GL_OES_vertex_half_float"] = enableableExtension(&Extensions::vertexHalfFloat);
800 map["GL_OES_vertex_array_object"] = enableableExtension(&Extensions::vertexArrayObject);
801 map["GL_KHR_debug"] = esOnlyExtension(&Extensions::debug);
802 map["GL_OES_texture_border_clamp"] = enableableExtension(&Extensions::textureBorderClamp);
803 // TODO(jmadill): Enable this when complete.
804 //map["GL_KHR_no_error"] = esOnlyExtension(&Extensions::noError);
805 map["GL_ANGLE_lossy_etc_decode"] = enableableExtension(&Extensions::lossyETCDecode);
806 map["GL_CHROMIUM_bind_uniform_location"] = esOnlyExtension(&Extensions::bindUniformLocation);
807 map["GL_CHROMIUM_sync_query"] = enableableExtension(&Extensions::syncQuery);
808 map["GL_CHROMIUM_copy_texture"] = esOnlyExtension(&Extensions::copyTexture);
809 map["GL_CHROMIUM_copy_compressed_texture"] = esOnlyExtension(&Extensions::copyCompressedTexture);
810 map["GL_ANGLE_copy_texture_3d"] = enableableExtension(&Extensions::copyTexture3d);
811 map["GL_ANGLE_webgl_compatibility"] = esOnlyExtension(&Extensions::webglCompatibility);
812 map["GL_ANGLE_request_extension"] = esOnlyExtension(&Extensions::requestExtension);
813 map["GL_CHROMIUM_bind_generates_resource"] = esOnlyExtension(&Extensions::bindGeneratesResource);
814 map["GL_ANGLE_robust_client_memory"] = esOnlyExtension(&Extensions::robustClientMemory);
815 map["GL_EXT_texture_sRGB_decode"] = esOnlyExtension(&Extensions::textureSRGBDecode);
816 map["GL_EXT_sRGB_write_control"] = esOnlyExtension(&Extensions::sRGBWriteControl);
817 map["GL_CHROMIUM_color_buffer_float_rgb"] = enableableExtension(&Extensions::colorBufferFloatRGB);
818 map["GL_CHROMIUM_color_buffer_float_rgba"] = enableableExtension(&Extensions::colorBufferFloatRGBA);
819 map["GL_EXT_multisample_compatibility"] = esOnlyExtension(&Extensions::multisampleCompatibility);
820 map["GL_CHROMIUM_framebuffer_mixed_samples"] = esOnlyExtension(&Extensions::framebufferMixedSamples);
821 map["GL_EXT_texture_norm16"] = esOnlyExtension(&Extensions::textureNorm16);
822 map["GL_CHROMIUM_path_rendering"] = esOnlyExtension(&Extensions::pathRendering);
823 map["GL_OES_surfaceless_context"] = esOnlyExtension(&Extensions::surfacelessContext);
824 map["GL_ANGLE_client_arrays"] = esOnlyExtension(&Extensions::clientArrays);
825 map["GL_ANGLE_robust_resource_initialization"] = esOnlyExtension(&Extensions::robustResourceInitialization);
826 map["GL_ANGLE_program_cache_control"] = esOnlyExtension(&Extensions::programCacheControl);
827 map["GL_ANGLE_texture_rectangle"] = enableableExtension(&Extensions::textureRectangle);
828 map["GL_EXT_geometry_shader"] = enableableExtension(&Extensions::geometryShader);
829 map["GL_ANGLE_explicit_context_gles1"] = enableableExtension(&Extensions::explicitContextGles1);
830 map["GL_ANGLE_explicit_context"] = enableableExtension(&Extensions::explicitContext);
831 map["GL_KHR_parallel_shader_compile"] = enableableExtension(&Extensions::parallelShaderCompile);
832 map["GL_OES_texture_storage_multisample_2d_array"] = enableableExtension(&Extensions::textureStorageMultisample2DArray);
833 map["GL_ANGLE_multiview_multisample"] = enableableExtension(&Extensions::multiviewMultisample);
834 map["GL_EXT_blend_func_extended"] = enableableExtension(&Extensions::blendFuncExtended);
835 map["GL_EXT_float_blend"] = enableableExtension(&Extensions::floatBlend);
836 map["GL_ANGLE_texture_multisample"] = enableableExtension(&Extensions::textureMultisample);
837 map["GL_ANGLE_multi_draw"] = enableableExtension(&Extensions::multiDraw);
838 map["GL_ANGLE_provoking_vertex"] = enableableExtension(&Extensions::provokingVertex);
839 map["GL_CHROMIUM_lose_context"] = enableableExtension(&Extensions::loseContextCHROMIUM);
840 map["GL_ANGLE_texture_external_update"] = enableableExtension(&Extensions::textureExternalUpdateANGLE);
841 map["GL_ANGLE_base_vertex_base_instance"] = enableableExtension(&Extensions::baseVertexBaseInstance);
842 // GLES1 extensinos
843 map["GL_OES_point_size_array"] = enableableExtension(&Extensions::pointSizeArray);
844 map["GL_OES_texture_cube_map"] = enableableExtension(&Extensions::textureCubeMap);
845 map["GL_OES_point_sprite"] = enableableExtension(&Extensions::pointSprite);
846 map["GL_OES_draw_texture"] = enableableExtension(&Extensions::drawTexture);
847 map["GL_ANGLE_memory_size"] = enableableExtension(&Extensions::memorySize);
848 // clang-format on
849
850 return map;
851 };
852
853 static const angle::base::NoDestructor<ExtensionInfoMap> extensionInfo(buildExtensionInfoMap());
854 return *extensionInfo;
855 }
856
857 TypePrecision::TypePrecision() = default;
858
859 TypePrecision::TypePrecision(const TypePrecision &other) = default;
860
setIEEEFloat()861 void TypePrecision::setIEEEFloat()
862 {
863 range = {{127, 127}};
864 precision = 23;
865 }
866
setTwosComplementInt(unsigned int bits)867 void TypePrecision::setTwosComplementInt(unsigned int bits)
868 {
869 range = {{static_cast<GLint>(bits) - 1, static_cast<GLint>(bits) - 2}};
870 precision = 0;
871 }
872
setSimulatedFloat(unsigned int r,unsigned int p)873 void TypePrecision::setSimulatedFloat(unsigned int r, unsigned int p)
874 {
875 range = {{static_cast<GLint>(r), static_cast<GLint>(r)}};
876 precision = static_cast<GLint>(p);
877 }
878
setSimulatedInt(unsigned int r)879 void TypePrecision::setSimulatedInt(unsigned int r)
880 {
881 range = {{static_cast<GLint>(r), static_cast<GLint>(r)}};
882 precision = 0;
883 }
884
get(GLint * returnRange,GLint * returnPrecision) const885 void TypePrecision::get(GLint *returnRange, GLint *returnPrecision) const
886 {
887 std::copy(range.begin(), range.end(), returnRange);
888 *returnPrecision = precision;
889 }
890
891 Caps::Caps() = default;
892 Caps::Caps(const Caps &other) = default;
893 Caps::~Caps() = default;
894
GenerateMinimumCaps(const Version & clientVersion,const Extensions & extensions)895 Caps GenerateMinimumCaps(const Version &clientVersion, const Extensions &extensions)
896 {
897 Caps caps;
898
899 // GLES1 emulation (Minimums taken from Table 6.20 / 6.22 (ES 1.1 spec))
900 if (clientVersion < Version(2, 0))
901 {
902 caps.maxMultitextureUnits = 2;
903 caps.maxLights = 8;
904 caps.maxClipPlanes = 1;
905
906 caps.maxModelviewMatrixStackDepth = 16;
907 caps.maxProjectionMatrixStackDepth = 2;
908 caps.maxTextureMatrixStackDepth = 2;
909
910 caps.minSmoothPointSize = 1.0f;
911 caps.maxSmoothPointSize = 1.0f;
912 }
913
914 if (clientVersion >= Version(2, 0))
915 {
916 // Table 6.18
917 caps.max2DTextureSize = 64;
918 caps.maxCubeMapTextureSize = 16;
919 caps.maxViewportWidth = caps.max2DTextureSize;
920 caps.maxViewportHeight = caps.max2DTextureSize;
921 caps.minAliasedPointSize = 1;
922 caps.maxAliasedPointSize = 1;
923 caps.minAliasedLineWidth = 1;
924 caps.maxAliasedLineWidth = 1;
925
926 // Table 6.19
927 caps.vertexHighpFloat.setSimulatedFloat(62, 16);
928 caps.vertexMediumpFloat.setSimulatedFloat(14, 10);
929 caps.vertexLowpFloat.setSimulatedFloat(1, 8);
930 caps.vertexHighpInt.setSimulatedInt(16);
931 caps.vertexMediumpInt.setSimulatedInt(10);
932 caps.vertexLowpInt.setSimulatedInt(8);
933 caps.fragmentHighpFloat.setSimulatedFloat(62, 16);
934 caps.fragmentMediumpFloat.setSimulatedFloat(14, 10);
935 caps.fragmentLowpFloat.setSimulatedFloat(1, 8);
936 caps.fragmentHighpInt.setSimulatedInt(16);
937 caps.fragmentMediumpInt.setSimulatedInt(10);
938 caps.fragmentLowpInt.setSimulatedInt(8);
939
940 // Table 6.20
941 caps.maxVertexAttributes = 8;
942 caps.maxVertexUniformVectors = 128;
943 caps.maxVaryingVectors = 8;
944 caps.maxCombinedTextureImageUnits = 8;
945 caps.maxShaderTextureImageUnits[ShaderType::Fragment] = 8;
946 caps.maxFragmentUniformVectors = 16;
947 caps.maxRenderbufferSize = 1;
948 }
949
950 if (clientVersion >= Version(3, 0))
951 {
952 // Table 6.28
953 caps.maxElementIndex = (1 << 24) - 1;
954 caps.max3DTextureSize = 256;
955 caps.max2DTextureSize = 2048;
956 caps.maxArrayTextureLayers = 256;
957 caps.maxLODBias = 2.0f;
958 caps.maxCubeMapTextureSize = 2048;
959 caps.maxRenderbufferSize = 2048;
960 caps.maxDrawBuffers = 4;
961 caps.maxColorAttachments = 4;
962 caps.maxViewportWidth = caps.max2DTextureSize;
963 caps.maxViewportHeight = caps.max2DTextureSize;
964
965 // Table 6.29
966 caps.compressedTextureFormats.push_back(GL_COMPRESSED_R11_EAC);
967 caps.compressedTextureFormats.push_back(GL_COMPRESSED_SIGNED_R11_EAC);
968 caps.compressedTextureFormats.push_back(GL_COMPRESSED_RG11_EAC);
969 caps.compressedTextureFormats.push_back(GL_COMPRESSED_SIGNED_RG11_EAC);
970 caps.compressedTextureFormats.push_back(GL_COMPRESSED_RGB8_ETC2);
971 caps.compressedTextureFormats.push_back(GL_COMPRESSED_SRGB8_ETC2);
972 caps.compressedTextureFormats.push_back(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2);
973 caps.compressedTextureFormats.push_back(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2);
974 caps.compressedTextureFormats.push_back(GL_COMPRESSED_RGBA8_ETC2_EAC);
975 caps.compressedTextureFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC);
976 caps.vertexHighpFloat.setIEEEFloat();
977 caps.vertexHighpInt.setTwosComplementInt(32);
978 caps.vertexMediumpInt.setTwosComplementInt(16);
979 caps.vertexLowpInt.setTwosComplementInt(8);
980 caps.fragmentHighpFloat.setIEEEFloat();
981 caps.fragmentHighpInt.setSimulatedInt(32);
982 caps.fragmentMediumpInt.setTwosComplementInt(16);
983 caps.fragmentLowpInt.setTwosComplementInt(8);
984 caps.maxServerWaitTimeout = 0;
985
986 // Table 6.31
987 caps.maxVertexAttributes = 16;
988 caps.maxShaderUniformComponents[ShaderType::Vertex] = 1024;
989 caps.maxVertexUniformVectors = 256;
990 caps.maxShaderUniformBlocks[ShaderType::Vertex] = 12;
991 caps.maxVertexOutputComponents = 64;
992 caps.maxShaderTextureImageUnits[ShaderType::Vertex] = 16;
993
994 // Table 6.32
995 caps.maxShaderUniformComponents[ShaderType::Fragment] = 896;
996 caps.maxFragmentUniformVectors = 224;
997 caps.maxShaderUniformBlocks[ShaderType::Fragment] = 12;
998 caps.maxFragmentInputComponents = 60;
999 caps.maxShaderTextureImageUnits[ShaderType::Fragment] = 16;
1000 caps.minProgramTexelOffset = -8;
1001 caps.maxProgramTexelOffset = 7;
1002
1003 // Table 6.33
1004 caps.maxUniformBufferBindings = 24;
1005 caps.maxUniformBlockSize = 16384;
1006 caps.uniformBufferOffsetAlignment = 256;
1007 caps.maxCombinedUniformBlocks = 24;
1008 caps.maxVaryingComponents = 60;
1009 caps.maxVaryingVectors = 15;
1010 caps.maxCombinedTextureImageUnits = 32;
1011
1012 // Table 6.34
1013 caps.maxTransformFeedbackInterleavedComponents = 64;
1014 caps.maxTransformFeedbackSeparateAttributes = 4;
1015 caps.maxTransformFeedbackSeparateComponents = 4;
1016
1017 // Table 3.35
1018 caps.maxSamples = 4;
1019 }
1020
1021 if (clientVersion >= Version(3, 1))
1022 {
1023 // Table 20.40
1024 caps.maxFramebufferWidth = 2048;
1025 caps.maxFramebufferHeight = 2048;
1026 caps.maxFramebufferSamples = 4;
1027 caps.maxSampleMaskWords = 1;
1028 caps.maxColorTextureSamples = 1;
1029 caps.maxDepthTextureSamples = 1;
1030 caps.maxIntegerSamples = 1;
1031
1032 // Table 20.41
1033 caps.maxVertexAttribRelativeOffset = 2047;
1034 caps.maxVertexAttribBindings = 16;
1035 caps.maxVertexAttribStride = 2048;
1036
1037 // Table 20.43
1038 caps.maxShaderAtomicCounterBuffers[ShaderType::Vertex] = 0;
1039 caps.maxShaderAtomicCounters[ShaderType::Vertex] = 0;
1040 caps.maxShaderImageUniforms[ShaderType::Vertex] = 0;
1041 caps.maxShaderStorageBlocks[ShaderType::Vertex] = 0;
1042
1043 // Table 20.44
1044 caps.maxShaderUniformComponents[ShaderType::Fragment] = 1024;
1045 caps.maxFragmentUniformVectors = 256;
1046 caps.maxShaderAtomicCounterBuffers[ShaderType::Fragment] = 0;
1047 caps.maxShaderAtomicCounters[ShaderType::Fragment] = 0;
1048 caps.maxShaderImageUniforms[ShaderType::Fragment] = 0;
1049 caps.maxShaderStorageBlocks[ShaderType::Fragment] = 0;
1050 caps.minProgramTextureGatherOffset = 0;
1051 caps.maxProgramTextureGatherOffset = 0;
1052
1053 // Table 20.45
1054 caps.maxComputeWorkGroupCount = {{65535, 65535, 65535}};
1055 caps.maxComputeWorkGroupSize = {{128, 128, 64}};
1056 caps.maxComputeWorkGroupInvocations = 12;
1057 caps.maxShaderUniformBlocks[ShaderType::Compute] = 12;
1058 caps.maxShaderTextureImageUnits[ShaderType::Compute] = 16;
1059 caps.maxComputeSharedMemorySize = 16384;
1060 caps.maxShaderUniformComponents[ShaderType::Compute] = 1024;
1061 caps.maxShaderAtomicCounterBuffers[ShaderType::Compute] = 1;
1062 caps.maxShaderAtomicCounters[ShaderType::Compute] = 8;
1063 caps.maxShaderImageUniforms[ShaderType::Compute] = 4;
1064 caps.maxShaderStorageBlocks[ShaderType::Compute] = 4;
1065
1066 // Table 20.46
1067 caps.maxUniformBufferBindings = 36;
1068 caps.maxCombinedTextureImageUnits = 48;
1069 caps.maxCombinedShaderOutputResources = 4;
1070
1071 // Table 20.47
1072 caps.maxUniformLocations = 1024;
1073 caps.maxAtomicCounterBufferBindings = 1;
1074 caps.maxAtomicCounterBufferSize = 32;
1075 caps.maxCombinedAtomicCounterBuffers = 1;
1076 caps.maxCombinedAtomicCounters = 8;
1077 caps.maxImageUnits = 4;
1078 caps.maxCombinedImageUniforms = 4;
1079 caps.maxShaderStorageBufferBindings = 4;
1080 caps.maxShaderStorageBlockSize = 1 << 27;
1081 caps.maxCombinedShaderStorageBlocks = 4;
1082 caps.shaderStorageBufferOffsetAlignment = 256;
1083 }
1084
1085 if (extensions.textureRectangle)
1086 {
1087 caps.maxRectangleTextureSize = 64;
1088 }
1089
1090 if (extensions.geometryShader)
1091 {
1092 // Table 20.40 (GL_EXT_geometry_shader)
1093 caps.maxFramebufferLayers = 256;
1094 caps.layerProvokingVertex = GL_LAST_VERTEX_CONVENTION_EXT;
1095
1096 // Table 20.43gs (GL_EXT_geometry_shader)
1097 caps.maxShaderUniformComponents[ShaderType::Geometry] = 1024;
1098 caps.maxShaderUniformBlocks[ShaderType::Geometry] = 12;
1099 caps.maxGeometryInputComponents = 64;
1100 caps.maxGeometryOutputComponents = 64;
1101 caps.maxGeometryOutputVertices = 256;
1102 caps.maxGeometryTotalOutputComponents = 1024;
1103 caps.maxShaderTextureImageUnits[ShaderType::Geometry] = 16;
1104 caps.maxShaderAtomicCounterBuffers[ShaderType::Geometry] = 0;
1105 caps.maxShaderAtomicCounters[ShaderType::Geometry] = 0;
1106 caps.maxShaderStorageBlocks[ShaderType::Geometry] = 0;
1107 caps.maxGeometryShaderInvocations = 32;
1108
1109 // Table 20.46 (GL_EXT_geometry_shader)
1110 caps.maxShaderImageUniforms[ShaderType::Geometry] = 0;
1111
1112 // Table 20.46 (GL_EXT_geometry_shader)
1113 caps.maxUniformBufferBindings = 48;
1114 caps.maxCombinedUniformBlocks = 36;
1115 caps.maxCombinedTextureImageUnits = 64;
1116 }
1117
1118 for (ShaderType shaderType : AllShaderTypes())
1119 {
1120 caps.maxCombinedShaderUniformComponents[shaderType] =
1121 caps.maxShaderUniformBlocks[shaderType] *
1122 static_cast<GLuint>(caps.maxUniformBlockSize / 4) +
1123 caps.maxShaderUniformComponents[shaderType];
1124 }
1125
1126 return caps;
1127 }
1128 } // namespace gl
1129
1130 namespace egl
1131 {
1132
1133 Caps::Caps() = default;
1134
1135 DisplayExtensions::DisplayExtensions() = default;
1136
getStrings() const1137 std::vector<std::string> DisplayExtensions::getStrings() const
1138 {
1139 std::vector<std::string> extensionStrings;
1140
1141 // clang-format off
1142 // | Extension name | Supported flag | Output vector |
1143 InsertExtensionString("EGL_EXT_create_context_robustness", createContextRobustness, &extensionStrings);
1144 InsertExtensionString("EGL_ANGLE_d3d_share_handle_client_buffer", d3dShareHandleClientBuffer, &extensionStrings);
1145 InsertExtensionString("EGL_ANGLE_d3d_texture_client_buffer", d3dTextureClientBuffer, &extensionStrings);
1146 InsertExtensionString("EGL_ANGLE_surface_d3d_texture_2d_share_handle", surfaceD3DTexture2DShareHandle, &extensionStrings);
1147 InsertExtensionString("EGL_ANGLE_query_surface_pointer", querySurfacePointer, &extensionStrings);
1148 InsertExtensionString("EGL_ANGLE_window_fixed_size", windowFixedSize, &extensionStrings);
1149 InsertExtensionString("EGL_ANGLE_keyed_mutex", keyedMutex, &extensionStrings);
1150 InsertExtensionString("EGL_ANGLE_surface_orientation", surfaceOrientation, &extensionStrings);
1151 InsertExtensionString("EGL_ANGLE_direct_composition", directComposition, &extensionStrings);
1152 InsertExtensionString("EGL_ANGLE_windows_ui_composition", windowsUIComposition, &extensionStrings);
1153 InsertExtensionString("EGL_NV_post_sub_buffer", postSubBuffer, &extensionStrings);
1154 InsertExtensionString("EGL_KHR_create_context", createContext, &extensionStrings);
1155 InsertExtensionString("EGL_EXT_device_query", deviceQuery, &extensionStrings);
1156 InsertExtensionString("EGL_KHR_image", image, &extensionStrings);
1157 InsertExtensionString("EGL_KHR_image_base", imageBase, &extensionStrings);
1158 InsertExtensionString("EGL_KHR_image_pixmap", imagePixmap, &extensionStrings);
1159 InsertExtensionString("EGL_KHR_gl_texture_2D_image", glTexture2DImage, &extensionStrings);
1160 InsertExtensionString("EGL_KHR_gl_texture_cubemap_image", glTextureCubemapImage, &extensionStrings);
1161 InsertExtensionString("EGL_KHR_gl_texture_3D_image", glTexture3DImage, &extensionStrings);
1162 InsertExtensionString("EGL_KHR_gl_renderbuffer_image", glRenderbufferImage, &extensionStrings);
1163 InsertExtensionString("EGL_KHR_get_all_proc_addresses", getAllProcAddresses, &extensionStrings);
1164 InsertExtensionString("EGL_KHR_stream", stream, &extensionStrings);
1165 InsertExtensionString("EGL_KHR_stream_consumer_gltexture", streamConsumerGLTexture, &extensionStrings);
1166 InsertExtensionString("EGL_NV_stream_consumer_gltexture_yuv", streamConsumerGLTextureYUV, &extensionStrings);
1167 InsertExtensionString("EGL_KHR_fence_sync", fenceSync, &extensionStrings);
1168 InsertExtensionString("EGL_KHR_wait_sync", waitSync, &extensionStrings);
1169 InsertExtensionString("EGL_ANGLE_flexible_surface_compatibility", flexibleSurfaceCompatibility, &extensionStrings);
1170 InsertExtensionString("EGL_ANGLE_stream_producer_d3d_texture", streamProducerD3DTexture, &extensionStrings);
1171 InsertExtensionString("EGL_ANGLE_create_context_webgl_compatibility", createContextWebGLCompatibility, &extensionStrings);
1172 InsertExtensionString("EGL_CHROMIUM_create_context_bind_generates_resource", createContextBindGeneratesResource, &extensionStrings);
1173 InsertExtensionString("EGL_CHROMIUM_sync_control", getSyncValues, &extensionStrings);
1174 InsertExtensionString("EGL_KHR_swap_buffers_with_damage", swapBuffersWithDamage, &extensionStrings);
1175 InsertExtensionString("EGL_EXT_pixel_format_float", pixelFormatFloat, &extensionStrings);
1176 InsertExtensionString("EGL_KHR_surfaceless_context", surfacelessContext, &extensionStrings);
1177 InsertExtensionString("EGL_ANGLE_display_texture_share_group", displayTextureShareGroup, &extensionStrings);
1178 InsertExtensionString("EGL_ANGLE_create_context_client_arrays", createContextClientArrays, &extensionStrings);
1179 InsertExtensionString("EGL_ANGLE_program_cache_control", programCacheControl, &extensionStrings);
1180 InsertExtensionString("EGL_ANGLE_robust_resource_initialization", robustResourceInitialization, &extensionStrings);
1181 InsertExtensionString("EGL_ANGLE_iosurface_client_buffer", iosurfaceClientBuffer, &extensionStrings);
1182 InsertExtensionString("EGL_ANGLE_create_context_extensions_enabled", createContextExtensionsEnabled, &extensionStrings);
1183 InsertExtensionString("EGL_ANDROID_presentation_time", presentationTime, &extensionStrings);
1184 InsertExtensionString("EGL_ANDROID_blob_cache", blobCache, &extensionStrings);
1185 InsertExtensionString("EGL_ANDROID_image_native_buffer", imageNativeBuffer, &extensionStrings);
1186 InsertExtensionString("EGL_ANDROID_get_frame_timestamps", getFrameTimestamps, &extensionStrings);
1187 InsertExtensionString("EGL_ANDROID_recordable", recordable, &extensionStrings);
1188 InsertExtensionString("EGL_ANGLE_power_preference", powerPreference, &extensionStrings);
1189 InsertExtensionString("EGL_ANGLE_image_d3d11_texture", imageD3D11Texture, &extensionStrings);
1190 InsertExtensionString("EGL_ANDROID_get_native_client_buffer", getNativeClientBufferANDROID, &extensionStrings);
1191 InsertExtensionString("EGL_ANDROID_native_fence_sync", nativeFenceSyncANDROID, &extensionStrings);
1192 InsertExtensionString("EGL_ANGLE_create_context_backwards_compatible", createContextBackwardsCompatible, &extensionStrings);
1193 // TODO(jmadill): Enable this when complete.
1194 //InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings);
1195 // clang-format on
1196
1197 return extensionStrings;
1198 }
1199
1200 DeviceExtensions::DeviceExtensions() = default;
1201
getStrings() const1202 std::vector<std::string> DeviceExtensions::getStrings() const
1203 {
1204 std::vector<std::string> extensionStrings;
1205
1206 // clang-format off
1207 // | Extension name | Supported flag | Output vector |
1208 InsertExtensionString("EGL_ANGLE_device_d3d", deviceD3D, &extensionStrings);
1209 // clang-format on
1210
1211 return extensionStrings;
1212 }
1213
1214 ClientExtensions::ClientExtensions() = default;
1215 ClientExtensions::ClientExtensions(const ClientExtensions &other) = default;
1216
getStrings() const1217 std::vector<std::string> ClientExtensions::getStrings() const
1218 {
1219 std::vector<std::string> extensionStrings;
1220
1221 // clang-format off
1222 // | Extension name | Supported flag | Output vector |
1223 InsertExtensionString("EGL_EXT_client_extensions", clientExtensions, &extensionStrings);
1224 InsertExtensionString("EGL_EXT_platform_base", platformBase, &extensionStrings);
1225 InsertExtensionString("EGL_EXT_platform_device", platformDevice, &extensionStrings);
1226 InsertExtensionString("EGL_ANGLE_platform_angle", platformANGLE, &extensionStrings);
1227 InsertExtensionString("EGL_ANGLE_platform_angle_d3d", platformANGLED3D, &extensionStrings);
1228 InsertExtensionString("EGL_ANGLE_platform_angle_opengl", platformANGLEOpenGL, &extensionStrings);
1229 InsertExtensionString("EGL_ANGLE_platform_angle_null", platformANGLENULL, &extensionStrings);
1230 InsertExtensionString("EGL_ANGLE_platform_angle_vulkan", platformANGLEVulkan, &extensionStrings);
1231 InsertExtensionString("EGL_ANGLE_platform_angle_context_virtualization", platformANGLEContextVirtualization, &extensionStrings);
1232 InsertExtensionString("EGL_ANGLE_device_creation", deviceCreation, &extensionStrings);
1233 InsertExtensionString("EGL_ANGLE_device_creation_d3d11", deviceCreationD3D11, &extensionStrings);
1234 InsertExtensionString("EGL_ANGLE_x11_visual", x11Visual, &extensionStrings);
1235 InsertExtensionString("EGL_ANGLE_experimental_present_path", experimentalPresentPath, &extensionStrings);
1236 InsertExtensionString("EGL_KHR_client_get_all_proc_addresses", clientGetAllProcAddresses, &extensionStrings);
1237 InsertExtensionString("EGL_KHR_debug", debug, &extensionStrings);
1238 InsertExtensionString("EGL_ANGLE_explicit_context", explicitContext, &extensionStrings);
1239 InsertExtensionString("EGL_ANGLE_feature_control", featureControlANGLE, &extensionStrings);
1240 // clang-format on
1241
1242 return extensionStrings;
1243 }
1244
1245 } // namespace egl
1246