1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #include "GLContext.h"
7 #include "nsPrintfCString.h"
8 
9 namespace mozilla {
10 namespace gl {
11 
12 const size_t kMAX_EXTENSION_GROUP_SIZE = 5;
13 
14 enum class GLVersion : uint32_t {
15   NONE = 0,  // Feature is not supported natively by GL
16   GL1_2 = 120,
17   GL1_3 = 130,
18   GL2 = 200,
19   GL2_1 = 210,
20   GL3 = 300,
21   GL3_1 = 310,
22   GL3_2 = 320,
23   GL3_3 = 330,
24   GL4 = 400,
25   GL4_1 = 410,
26   GL4_2 = 420,
27   GL4_3 = 430,
28 };
29 
30 enum class GLESVersion : uint32_t {
31   NONE = 0,  // Feature is not support natively by GL ES
32   ES2 = 200,
33   ES3 = 300,
34   ES3_1 = 310,
35   ES3_2 = 320,
36 };
37 
38 // ARB_ES2_compatibility is natively supported in OpenGL 4.1.
39 static const GLVersion kGLCoreVersionForES2Compat = GLVersion::GL4_1;
40 
41 // ARB_ES3_compatibility is natively supported in OpenGL 4.3.
42 static const GLVersion kGLCoreVersionForES3Compat = GLVersion::GL4_3;
43 
44 struct FeatureInfo {
45   const char* mName;
46 
47   /* The (desktop) OpenGL version that provides this feature */
48   GLVersion mOpenGLVersion;
49 
50   /* The OpenGL ES version that provides this feature */
51   GLESVersion mOpenGLESVersion;
52 
53   /* If there is an ARB extension, and its function symbols are
54    * not decorated with an ARB suffix, then its extension ID should go
55    * here, and NOT in mExtensions.  For example, ARB_vertex_array_object
56    * functions do not have an ARB suffix, because it is an extension that
57    * was created to match core GL functionality and will never differ.
58    * Some ARB extensions do have a suffix, if they were created before
59    * a core version of the functionality existed.
60    *
61    * If there is no such ARB extension, pass 0 (GLContext::Extension_None)
62    */
63   GLContext::GLExtensions mARBExtensionWithoutARBSuffix;
64 
65   /* Extensions that also provide this feature */
66   GLContext::GLExtensions mExtensions[kMAX_EXTENSION_GROUP_SIZE];
67 };
68 
69 static const FeatureInfo sFeatureInfoArr[] = {
70     {"bind_buffer_offset",
71      GLVersion::NONE,
72      GLESVersion::NONE,
73      GLContext::Extension_None,
74      {
75 
76          GLContext::EXT_transform_feedback, GLContext::NV_transform_feedback2,
77          GLContext::Extensions_End}},
78     {"blend_minmax",
79      GLVersion::GL2,
80      GLESVersion::ES3,
81      GLContext::Extension_None,
82      {GLContext::EXT_blend_minmax, GLContext::Extensions_End}},
83     {"clear_buffers",
84      GLVersion::GL3,
85      GLESVersion::ES3,
86      GLContext::Extension_None,
87      {GLContext::Extensions_End}},
88     {"copy_buffer",
89      GLVersion::GL3_1,
90      GLESVersion::ES3,
91      GLContext::ARB_copy_buffer,
92      {GLContext::Extensions_End}},
93     {"depth_texture",
94      GLVersion::GL2,
95      GLESVersion::ES3,
96      GLContext::Extension_None,
97      {GLContext::ARB_depth_texture, GLContext::OES_depth_texture,
98       // Intentionally avoid putting ANGLE_depth_texture here,
99       // it does not offer quite the same functionality.
100       GLContext::Extensions_End}},
101     {"draw_buffers",
102      GLVersion::GL2,
103      GLESVersion::ES3,
104      GLContext::Extension_None,
105      {GLContext::ARB_draw_buffers, GLContext::EXT_draw_buffers,
106       GLContext::Extensions_End}},
107     {"draw_instanced",
108      GLVersion::GL3_1,
109      GLESVersion::ES3,
110      GLContext::Extension_None,
111      {GLContext::ARB_draw_instanced, GLContext::EXT_draw_instanced,
112       GLContext::NV_draw_instanced, GLContext::ANGLE_instanced_arrays,
113       GLContext::Extensions_End}},
114     {"element_index_uint",
115      GLVersion::GL2,
116      GLESVersion::ES3,
117      GLContext::Extension_None,
118      {GLContext::OES_element_index_uint, GLContext::Extensions_End}},
119     {"ES2_compatibility",
120      kGLCoreVersionForES2Compat,
121      GLESVersion::ES2,                  // OpenGL ES version
122      GLContext::ARB_ES2_compatibility,  // no suffix on ARB extension
123      {GLContext::Extensions_End}},
124     {"ES3_compatibility",
125      kGLCoreVersionForES3Compat,
126      GLESVersion::ES3,                  // OpenGL ES version
127      GLContext::ARB_ES3_compatibility,  // no suffix on ARB extension
128      {GLContext::Extensions_End}},
129     {"EXT_color_buffer_float",
130      GLVersion::GL3,
131      GLESVersion::ES3_2,
132      GLContext::Extension_None,
133      {GLContext::EXT_color_buffer_float, GLContext::Extensions_End}},
134     {// Removes clamping for float color outputs from frag shaders.
135      "frag_color_float",
136      GLVersion::GL3,
137      GLESVersion::ES3,
138      GLContext::Extension_None,
139      {GLContext::ARB_color_buffer_float, GLContext::EXT_color_buffer_float,
140       GLContext::EXT_color_buffer_half_float,
141       GLContext::CHROMIUM_color_buffer_float_rgba, GLContext::Extensions_End}},
142     {"frag_depth",
143      GLVersion::GL2,
144      GLESVersion::ES3,
145      GLContext::Extension_None,
146      {GLContext::EXT_frag_depth, GLContext::Extensions_End}},
147     {// Check for just the blit framebuffer blit part of
148      // ARB_framebuffer_object
149      "framebuffer_blit",
150      GLVersion::GL3,
151      GLESVersion::ES3,
152      GLContext::ARB_framebuffer_object,
153      {GLContext::ANGLE_framebuffer_blit, GLContext::EXT_framebuffer_blit,
154       GLContext::NV_framebuffer_blit, GLContext::Extensions_End}},
155     {// Check for just the multisample renderbuffer part of
156      // ARB_framebuffer_object
157      "framebuffer_multisample",
158      GLVersion::GL3,
159      GLESVersion::ES3,
160      GLContext::ARB_framebuffer_object,
161      {GLContext::ANGLE_framebuffer_multisample,
162       GLContext::APPLE_framebuffer_multisample,
163       GLContext::EXT_framebuffer_multisample,
164       GLContext::EXT_multisampled_render_to_texture,
165       GLContext::Extensions_End}},
166     {// ARB_framebuffer_object support
167      "framebuffer_object",
168      GLVersion::GL3,
169      GLESVersion::ES3,
170      GLContext::ARB_framebuffer_object,
171      {GLContext::Extensions_End}},
172     {// EXT_framebuffer_object/OES_framebuffer_object support
173      "framebuffer_object_EXT_OES",
174      GLVersion::GL3,
175      GLESVersion::ES2,
176      GLContext::Extension_None,
177      {GLContext::EXT_framebuffer_object, GLContext::OES_framebuffer_object,
178       GLContext::Extensions_End}},
179     {"get_integer_indexed",
180      GLVersion::GL3,
181      GLESVersion::ES3,
182      GLContext::Extension_None,
183      {GLContext::EXT_draw_buffers2, GLContext::Extensions_End}},
184     {"get_integer64_indexed",
185      GLVersion::GL3_2,
186      GLESVersion::ES3,
187      GLContext::Extension_None,
188      {GLContext::Extensions_End}},
189     {"get_query_object_i64v",
190      GLVersion::GL3_3,
191      GLESVersion::NONE,
192      GLContext::ARB_timer_query,
193      {GLContext::ANGLE_timer_query, GLContext::EXT_disjoint_timer_query,
194       GLContext::EXT_timer_query, GLContext::Extensions_End}},
195     {
196         "get_query_object_iv",
197         GLVersion::GL2,
198         GLESVersion::NONE,
199         GLContext::Extension_None,
200         {GLContext::Extensions_End}
201         /*
202          * XXX_get_query_object_iv only provide GetQueryObjectiv provided by
203          * ARB_occlusion_query (added by OpenGL 2.0).
204          */
205     },
206     {"gpu_shader4",
207      GLVersion::GL3,
208      GLESVersion::ES3,
209      GLContext::Extension_None,
210      {GLContext::EXT_gpu_shader4, GLContext::Extensions_End}},
211     {"instanced_arrays",
212      GLVersion::GL3_3,
213      GLESVersion::ES3,
214      GLContext::Extension_None,
215      {GLContext::ARB_instanced_arrays, GLContext::NV_instanced_arrays,
216       GLContext::ANGLE_instanced_arrays, GLContext::Extensions_End}},
217     {
218         "instanced_non_arrays",
219         GLVersion::GL3_3,
220         GLESVersion::ES3,
221         GLContext::Extension_None,
222         {GLContext::ARB_instanced_arrays, GLContext::Extensions_End}
223         /* This is an expanded version of `instanced_arrays` that allows for all
224          * enabled active attrib arrays to have non-zero divisors.
225          * ANGLE_instanced_arrays and NV_instanced_arrays forbid this, but GLES3
226          * has no such restriction.
227          */
228     },
229     {"internalformat_query",
230      GLVersion::GL4_2,
231      GLESVersion::ES3,
232      GLContext::ARB_internalformat_query,
233      {GLContext::Extensions_End}},
234     {"invalidate_framebuffer",
235      GLVersion::GL4_3,
236      GLESVersion::ES3,
237      GLContext::ARB_invalidate_subdata,
238      {GLContext::Extensions_End}},
239     {"map_buffer_range",
240      GLVersion::GL3,
241      GLESVersion::ES3,
242      GLContext::ARB_map_buffer_range,
243      {GLContext::EXT_map_buffer_range, GLContext::Extensions_End}},
244     {"multiview",
245      GLVersion::NONE,
246      GLESVersion::NONE,
247      GLContext::Extension_None,
248      {GLContext::ANGLE_multiview, GLContext::OVR_multiview2,
249       GLContext::Extensions_End}},
250     {
251         "occlusion_query",
252         GLVersion::GL2,
253         GLESVersion::NONE,
254         GLContext::Extension_None,
255         {GLContext::Extensions_End}
256         // XXX_occlusion_query depend on ARB_occlusion_query (added in
257         // OpenGL 2.0)
258     },
259     {
260         "occlusion_query_boolean",
261         kGLCoreVersionForES3Compat,
262         GLESVersion::ES3,
263         GLContext::ARB_ES3_compatibility,
264         {GLContext::EXT_occlusion_query_boolean, GLContext::Extensions_End}
265         /*
266          * XXX_occlusion_query_boolean provide ANY_SAMPLES_PASSED_CONSERVATIVE,
267          * but EXT_occlusion_query_boolean is only a OpenGL ES extension. But
268          * it is supported on desktop if ARB_ES3_compatibility because
269          * EXT_occlusion_query_boolean (added in OpenGL ES 3.0).
270          */
271     },
272     {
273         "occlusion_query2",
274         GLVersion::GL3_3,
275         GLESVersion::ES3,
276         GLContext::Extension_None,
277         {GLContext::ARB_occlusion_query2, GLContext::ARB_ES3_compatibility,
278          GLContext::EXT_occlusion_query_boolean, GLContext::Extensions_End}
279         /*
280          * XXX_occlusion_query2 (add in OpenGL 3.3) provide ANY_SAMPLES_PASSED,
281          * which is provided by ARB_occlusion_query2,
282          * EXT_occlusion_query_boolean (added in OpenGL ES 3.0) and
283          * ARB_ES3_compatibility
284          */
285     },
286     {"packed_depth_stencil",
287      GLVersion::GL3,
288      GLESVersion::ES3,
289      GLContext::Extension_None,
290      {GLContext::EXT_packed_depth_stencil, GLContext::OES_packed_depth_stencil,
291       GLContext::Extensions_End}},
292     {"prim_restart",
293      GLVersion::GL3_1,
294      GLESVersion::NONE,
295      GLContext::Extension_None,
296      {// GLContext::NV_primitive_restart, // Has different enum values.
297       GLContext::Extensions_End}},
298     {"prim_restart_fixed",
299      kGLCoreVersionForES3Compat,
300      GLESVersion::ES3,
301      GLContext::ARB_ES3_compatibility,
302      {GLContext::Extensions_End}},
303     {"query_counter",
304      GLVersion::GL3_3,
305      GLESVersion::NONE,
306      GLContext::ARB_timer_query,
307      {GLContext::ANGLE_timer_query, GLContext::EXT_disjoint_timer_query,
308       // EXT_timer_query does NOT support GL_TIMESTAMP retrieval with
309       // QueryCounter.
310       GLContext::Extensions_End}},
311     {
312         "query_objects",
313         GLVersion::GL2,
314         GLESVersion::ES3,
315         GLContext::Extension_None,
316         {GLContext::ANGLE_timer_query, GLContext::EXT_disjoint_timer_query,
317          GLContext::EXT_occlusion_query_boolean, GLContext::Extensions_End}
318         /*
319          * XXX_query_objects only provide entry points commonly supported by
320          * ARB_occlusion_query (added in OpenGL 2.0),
321          * EXT_occlusion_query_boolean (added in OpenGL ES 3.0), and
322          * ARB_timer_query (added in OpenGL 3.3)
323          */
324     },
325     {"query_time_elapsed",
326      GLVersion::GL3_3,
327      GLESVersion::NONE,
328      GLContext::ARB_timer_query,
329      {GLContext::ANGLE_timer_query, GLContext::EXT_disjoint_timer_query,
330       GLContext::EXT_timer_query, GLContext::Extensions_End}},
331     {"read_buffer",
332      GLVersion::GL2,
333      GLESVersion::ES3,
334      GLContext::Extension_None,
335      {GLContext::Extensions_End}},
336     {"renderbuffer_color_float",
337      GLVersion::GL3,
338      GLESVersion::ES3_2,
339      GLContext::Extension_None,
340      {GLContext::ARB_texture_float, GLContext::EXT_color_buffer_float,
341       GLContext::CHROMIUM_color_buffer_float_rgba, GLContext::Extensions_End}},
342     {"renderbuffer_color_half_float",
343      GLVersion::GL3,
344      GLESVersion::ES3_2,
345      GLContext::Extension_None,
346      {GLContext::ARB_texture_float, GLContext::EXT_color_buffer_float,
347       GLContext::EXT_color_buffer_half_float, GLContext::Extensions_End}},
348     {"robust_buffer_access_behavior",
349      GLVersion::NONE,
350      GLESVersion::NONE,
351      GLContext::Extension_None,
352      {GLContext::ARB_robust_buffer_access_behavior,
353       GLContext::KHR_robust_buffer_access_behavior, GLContext::Extensions_End}},
354     {"robustness",
355      GLVersion::NONE,
356      GLESVersion::NONE,
357      GLContext::Extension_None,
358      {GLContext::ARB_robustness, GLContext::EXT_robustness,
359       GLContext::KHR_robustness, GLContext::Extensions_End}},
360     {"sRGB",
361      GLVersion::GL3,
362      GLESVersion::ES3,
363      GLContext::ARB_framebuffer_sRGB,
364      {GLContext::EXT_sRGB, GLContext::EXT_framebuffer_sRGB,
365       GLContext::Extensions_End}},
366     {"sampler_objects",
367      GLVersion::GL3_3,
368      GLESVersion::ES3,
369      GLContext::ARB_sampler_objects,
370      {GLContext::Extensions_End}},
371     {"seamless_cube_map_opt_in",
372      GLVersion::GL3_2,
373      GLESVersion::NONE,
374      GLContext::ARB_seamless_cube_map,
375      {GLContext::Extensions_End}},
376     {"shader_texture_lod",
377      GLVersion::GL3,
378      GLESVersion::ES3,
379      GLContext::Extension_None,
380      {GLContext::ARB_shader_texture_lod, GLContext::EXT_shader_texture_lod,
381       GLContext::Extensions_End}},
382     {// Do we have separate DRAW and READ framebuffer bind points?
383      "split_framebuffer",
384      GLVersion::GL3,
385      GLESVersion::ES3,
386      GLContext::ARB_framebuffer_object,
387      {GLContext::ANGLE_framebuffer_blit,
388       GLContext::APPLE_framebuffer_multisample, GLContext::EXT_framebuffer_blit,
389       GLContext::NV_framebuffer_blit, GLContext::Extensions_End}},
390     {"standard_derivatives",
391      GLVersion::GL2,
392      GLESVersion::ES3,
393      GLContext::Extension_None,
394      {GLContext::OES_standard_derivatives, GLContext::Extensions_End}},
395     {"sync",
396      GLVersion::GL3_2,
397      GLESVersion::ES3,
398      GLContext::Extension_None,
399      {GLContext::ARB_sync, GLContext::APPLE_sync, GLContext::Extensions_End}},
400     {"texture_3D",
401      GLVersion::GL1_2,
402      GLESVersion::ES3,
403      GLContext::Extension_None,
404      {GLContext::EXT_texture3D, GLContext::OES_texture_3D,
405       GLContext::Extensions_End}},
406     {"texture_3D_compressed",
407      GLVersion::GL1_3,
408      GLESVersion::ES3,
409      GLContext::Extension_None,
410      {GLContext::ARB_texture_compression, GLContext::OES_texture_3D,
411       GLContext::Extensions_End}},
412     {"texture_3D_copy",
413      GLVersion::GL1_2,
414      GLESVersion::ES3,
415      GLContext::Extension_None,
416      {GLContext::EXT_copy_texture, GLContext::OES_texture_3D,
417       GLContext::Extensions_End}},
418     {"texture_compression_bptc",
419      GLVersion::GL4_2,
420      GLESVersion::NONE,
421      GLContext::Extension_None,
422      {GLContext::ARB_texture_compression_bptc,
423       GLContext::EXT_texture_compression_bptc, GLContext::Extensions_End}},
424     {"texture_compression_rgtc",
425      GLVersion::GL3,
426      GLESVersion::NONE,
427      GLContext::Extension_None,
428      {GLContext::ARB_texture_compression_rgtc,
429       GLContext::EXT_texture_compression_rgtc, GLContext::Extensions_End}},
430     {"texture_float",
431      GLVersion::GL3,
432      GLESVersion::ES3,
433      GLContext::Extension_None,
434      {GLContext::ARB_texture_float, GLContext::OES_texture_float,
435       GLContext::Extensions_End}},
436     {"texture_float_linear",
437      GLVersion::GL3_1,
438      GLESVersion::NONE,
439      GLContext::Extension_None,
440      {GLContext::ARB_texture_float, GLContext::OES_texture_float_linear,
441       GLContext::Extensions_End}},
442     {
443         "texture_half_float",
444         GLVersion::GL3,
445         GLESVersion::ES3,
446         GLContext::Extension_None,
447         {GLContext::ARB_half_float_pixel, GLContext::ARB_texture_float,
448          GLContext::NV_half_float, GLContext::Extensions_End}
449         /**
450          * We are not including OES_texture_half_float in this feature, because:
451          *   GL_HALF_FLOAT     = 0x140B
452          *   GL_HALF_FLOAT_ARB = 0x140B == GL_HALF_FLOAT
453          *   GL_HALF_FLOAT_NV  = 0x140B == GL_HALF_FLOAT
454          *   GL_HALF_FLOAT_OES = 0x8D61 != GL_HALF_FLOAT
455          * WebGL handles this specifically with an OES_texture_half_float check.
456          */
457     },
458     {"texture_half_float_linear",
459      GLVersion::GL3_1,
460      GLESVersion::ES3,
461      GLContext::Extension_None,
462      {GLContext::ARB_half_float_pixel, GLContext::ARB_texture_float,
463       GLContext::NV_half_float, GLContext::OES_texture_half_float_linear,
464       GLContext::Extensions_End}},
465     {"texture_non_power_of_two",
466      GLVersion::GL2,
467      GLESVersion::ES3,
468      GLContext::Extension_None,
469      {GLContext::ARB_texture_non_power_of_two, GLContext::OES_texture_npot,
470       GLContext::Extensions_End}},
471     {"texture_norm16",
472      GLVersion::GL3_1,
473      GLESVersion::ES3_1,
474      GLContext::EXT_texture_norm16,
475      {GLContext::Extensions_End}},
476     {"texture_rg",
477      GLVersion::GL3,
478      GLESVersion::ES3,
479      GLContext::ARB_texture_rg,
480      {GLContext::Extensions_End}},
481     {"texture_storage",
482      GLVersion::GL4_2,
483      GLESVersion::ES3,
484      GLContext::ARB_texture_storage,
485      {/*
486        * Not including GL_EXT_texture_storage here because it
487        * doesn't guarantee glTexStorage3D, which is required for
488        * WebGL 2.
489        */
490       GLContext::Extensions_End}},
491     {"texture_swizzle",
492      GLVersion::GL3_3,
493      GLESVersion::ES3,
494      GLContext::ARB_texture_swizzle,
495      {GLContext::Extensions_End}},
496     {"transform_feedback2",
497      GLVersion::GL4,
498      GLESVersion::ES3,
499      GLContext::ARB_transform_feedback2,
500      {GLContext::NV_transform_feedback2, GLContext::Extensions_End}},
501     {"uniform_buffer_object",
502      GLVersion::GL3_1,
503      GLESVersion::ES3,
504      GLContext::ARB_uniform_buffer_object,
505      {GLContext::Extensions_End}},
506     {"uniform_matrix_nonsquare",
507      GLVersion::GL2_1,
508      GLESVersion::ES3,
509      GLContext::Extension_None,
510      {GLContext::Extensions_End}},
511     {"vertex_array_object",
512      GLVersion::GL3,
513      GLESVersion::ES3,
514      GLContext::ARB_vertex_array_object,  // ARB extension
515      {GLContext::OES_vertex_array_object, GLContext::APPLE_vertex_array_object,
516       GLContext::Extensions_End}}};
517 
GetFeatureInfo(GLFeature feature)518 static inline const FeatureInfo& GetFeatureInfo(GLFeature feature) {
519   static_assert(MOZ_ARRAY_LENGTH(sFeatureInfoArr) == size_t(GLFeature::EnumMax),
520                 "Mismatched lengths for sFeatureInfoInfos and GLFeature enums");
521 
522   MOZ_ASSERT(feature < GLFeature::EnumMax,
523              "GLContext::GetFeatureInfoInfo : unknown <feature>");
524 
525   return sFeatureInfoArr[size_t(feature)];
526 }
527 
ProfileVersionForFeature(GLFeature feature,ContextProfile profile)528 static inline uint32_t ProfileVersionForFeature(GLFeature feature,
529                                                 ContextProfile profile) {
530   MOZ_ASSERT(profile != ContextProfile::Unknown,
531              "GLContext::ProfileVersionForFeature : unknown <profile>");
532 
533   const FeatureInfo& featureInfo = GetFeatureInfo(feature);
534 
535   if (profile == ContextProfile::OpenGLES)
536     return (uint32_t)featureInfo.mOpenGLESVersion;
537 
538   return (uint32_t)featureInfo.mOpenGLVersion;
539 }
540 
IsFeaturePartOfProfileVersion(GLFeature feature,ContextProfile profile,unsigned int version)541 static bool IsFeaturePartOfProfileVersion(GLFeature feature,
542                                           ContextProfile profile,
543                                           unsigned int version) {
544   unsigned int profileVersion = ProfileVersionForFeature(feature, profile);
545 
546   /**
547    * if `profileVersion` is zero, it means that no version of the profile
548    * added support for the feature.
549    */
550   return profileVersion && version >= profileVersion;
551 }
552 
IsFeatureProvidedByCoreSymbols(GLFeature feature)553 bool GLContext::IsFeatureProvidedByCoreSymbols(GLFeature feature) {
554   if (IsFeaturePartOfProfileVersion(feature, mProfile, mVersion)) return true;
555 
556   if (IsExtensionSupported(
557           GetFeatureInfo(feature).mARBExtensionWithoutARBSuffix))
558     return true;
559 
560   return false;
561 }
562 
GetFeatureName(GLFeature feature)563 const char* GLContext::GetFeatureName(GLFeature feature) {
564   return GetFeatureInfo(feature).mName;
565 }
566 
InitFeatures()567 void GLContext::InitFeatures() {
568   for (size_t featureId = 0; featureId < size_t(GLFeature::EnumMax);
569        featureId++) {
570     GLFeature feature = GLFeature(featureId);
571 
572     if (IsFeaturePartOfProfileVersion(feature, mProfile, mVersion)) {
573       mAvailableFeatures[featureId] = true;
574       continue;
575     }
576 
577     mAvailableFeatures[featureId] = false;
578 
579     const FeatureInfo& featureInfo = GetFeatureInfo(feature);
580 
581     if (IsExtensionSupported(featureInfo.mARBExtensionWithoutARBSuffix)) {
582       mAvailableFeatures[featureId] = true;
583       continue;
584     }
585 
586     for (size_t j = 0; true; j++) {
587       MOZ_ASSERT(j < kMAX_EXTENSION_GROUP_SIZE,
588                  "kMAX_EXTENSION_GROUP_SIZE too small");
589 
590       if (featureInfo.mExtensions[j] == GLContext::Extensions_End) break;
591 
592       if (IsExtensionSupported(featureInfo.mExtensions[j])) {
593         mAvailableFeatures[featureId] = true;
594         break;
595       }
596     }
597   }
598 
599   if (ShouldDumpExts()) {
600     for (size_t featureId = 0; featureId < size_t(GLFeature::EnumMax);
601          featureId++) {
602       GLFeature feature = GLFeature(featureId);
603       printf_stderr("[%s] Feature::%s\n",
604                     IsSupported(feature) ? "enabled" : "disabled",
605                     GetFeatureName(feature));
606     }
607   }
608 }
609 
MarkUnsupported(GLFeature feature)610 void GLContext::MarkUnsupported(GLFeature feature) {
611   mAvailableFeatures[size_t(feature)] = false;
612 
613   const FeatureInfo& featureInfo = GetFeatureInfo(feature);
614 
615   for (size_t i = 0; true; i++) {
616     MOZ_ASSERT(i < kMAX_EXTENSION_GROUP_SIZE,
617                "kMAX_EXTENSION_GROUP_SIZE too small");
618 
619     if (featureInfo.mExtensions[i] == GLContext::Extensions_End) break;
620 
621     MarkExtensionUnsupported(featureInfo.mExtensions[i]);
622   }
623 
624   MOZ_ASSERT(!IsSupported(feature), "GLContext::MarkUnsupported has failed!");
625 
626   NS_WARNING(
627       nsPrintfCString("%s marked as unsupported", GetFeatureName(feature))
628           .get());
629 }
630 
631 } /* namespace gl */
632 } /* namespace mozilla */
633