1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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     {"draw_range_elements",
115      GLVersion::GL1_2,
116      GLESVersion::ES3,
117      GLContext::Extension_None,
118      {GLContext::EXT_draw_range_elements, GLContext::Extensions_End}},
119     {"element_index_uint",
120      GLVersion::GL2,
121      GLESVersion::ES3,
122      GLContext::Extension_None,
123      {GLContext::OES_element_index_uint, GLContext::Extensions_End}},
124     {"ES2_compatibility",
125      kGLCoreVersionForES2Compat,
126      GLESVersion::ES2,                  // OpenGL ES version
127      GLContext::ARB_ES2_compatibility,  // no suffix on ARB extension
128      {GLContext::Extensions_End}},
129     {"ES3_compatibility",
130      kGLCoreVersionForES3Compat,
131      GLESVersion::ES3,                  // OpenGL ES version
132      GLContext::ARB_ES3_compatibility,  // no suffix on ARB extension
133      {GLContext::Extensions_End}},
134     {"EXT_color_buffer_float",
135      GLVersion::GL3,
136      GLESVersion::ES3_2,
137      GLContext::Extension_None,
138      {GLContext::EXT_color_buffer_float, GLContext::Extensions_End}},
139     {// Removes clamping for float color outputs from frag shaders.
140      "frag_color_float",
141      GLVersion::GL3,
142      GLESVersion::ES3,
143      GLContext::Extension_None,
144      {GLContext::ARB_color_buffer_float, GLContext::EXT_color_buffer_float,
145       GLContext::EXT_color_buffer_half_float, GLContext::Extensions_End}},
146     {"frag_depth",
147      GLVersion::GL2,
148      GLESVersion::ES3,
149      GLContext::Extension_None,
150      {GLContext::EXT_frag_depth, GLContext::Extensions_End}},
151     {// Check for just the blit framebuffer blit part of
152      // ARB_framebuffer_object
153      "framebuffer_blit",
154      GLVersion::GL3,
155      GLESVersion::ES3,
156      GLContext::ARB_framebuffer_object,
157      {GLContext::ANGLE_framebuffer_blit, GLContext::EXT_framebuffer_blit,
158       GLContext::NV_framebuffer_blit, GLContext::Extensions_End}},
159     {// Check for just the multisample renderbuffer part of
160      // ARB_framebuffer_object
161      "framebuffer_multisample",
162      GLVersion::GL3,
163      GLESVersion::ES3,
164      GLContext::ARB_framebuffer_object,
165      {GLContext::ANGLE_framebuffer_multisample,
166       GLContext::APPLE_framebuffer_multisample,
167       GLContext::EXT_framebuffer_multisample,
168       GLContext::EXT_multisampled_render_to_texture,
169       GLContext::Extensions_End}},
170     {// ARB_framebuffer_object support
171      "framebuffer_object",
172      GLVersion::GL3,
173      GLESVersion::ES3,
174      GLContext::ARB_framebuffer_object,
175      {GLContext::Extensions_End}},
176     {// EXT_framebuffer_object/OES_framebuffer_object support
177      "framebuffer_object_EXT_OES",
178      GLVersion::GL3,
179      GLESVersion::ES2,
180      GLContext::Extension_None,
181      {GLContext::EXT_framebuffer_object, GLContext::OES_framebuffer_object,
182       GLContext::Extensions_End}},
183     {"get_integer_indexed",
184      GLVersion::GL3,
185      GLESVersion::ES3,
186      GLContext::Extension_None,
187      {GLContext::EXT_draw_buffers2, GLContext::Extensions_End}},
188     {"get_integer64_indexed",
189      GLVersion::GL3_2,
190      GLESVersion::ES3,
191      GLContext::Extension_None,
192      {GLContext::Extensions_End}},
193     {"get_query_object_i64v",
194      GLVersion::GL3_3,
195      GLESVersion::NONE,
196      GLContext::ARB_timer_query,
197      {GLContext::ANGLE_timer_query, GLContext::EXT_disjoint_timer_query,
198       GLContext::EXT_timer_query, GLContext::Extensions_End}},
199     {
200         "get_query_object_iv",
201         GLVersion::GL2,
202         GLESVersion::NONE,
203         GLContext::Extension_None,
204         {GLContext::Extensions_End}
205         /*
206          * XXX_get_query_object_iv only provide GetQueryObjectiv provided by
207          * ARB_occlusion_query (added by OpenGL 2.0).
208          */
209     },
210     {"gpu_shader4",
211      GLVersion::GL3,
212      GLESVersion::ES3,
213      GLContext::Extension_None,
214      {GLContext::EXT_gpu_shader4, GLContext::Extensions_End}},
215     {"instanced_arrays",
216      GLVersion::GL3_3,
217      GLESVersion::ES3,
218      GLContext::Extension_None,
219      {GLContext::ARB_instanced_arrays, GLContext::NV_instanced_arrays,
220       GLContext::ANGLE_instanced_arrays, GLContext::Extensions_End}},
221     {
222         "instanced_non_arrays",
223         GLVersion::GL3_3,
224         GLESVersion::ES3,
225         GLContext::Extension_None,
226         {GLContext::ARB_instanced_arrays, GLContext::Extensions_End}
227         /* This is an expanded version of `instanced_arrays` that allows for all
228          * enabled active attrib arrays to have non-zero divisors.
229          * ANGLE_instanced_arrays and NV_instanced_arrays forbid this, but GLES3
230          * has no such restriction.
231          */
232     },
233     {"internalformat_query",
234      GLVersion::GL4_2,
235      GLESVersion::ES3,
236      GLContext::ARB_internalformat_query,
237      {GLContext::Extensions_End}},
238     {"invalidate_framebuffer",
239      GLVersion::GL4_3,
240      GLESVersion::ES3,
241      GLContext::ARB_invalidate_subdata,
242      {GLContext::Extensions_End}},
243     {"map_buffer_range",
244      GLVersion::GL3,
245      GLESVersion::ES3,
246      GLContext::ARB_map_buffer_range,
247      {GLContext::Extensions_End}},
248     {
249         "occlusion_query",
250         GLVersion::GL2,
251         GLESVersion::NONE,
252         GLContext::Extension_None,
253         {GLContext::Extensions_End}
254         // XXX_occlusion_query depend on ARB_occlusion_query (added in
255         // OpenGL 2.0)
256     },
257     {
258         "occlusion_query_boolean",
259         kGLCoreVersionForES3Compat,
260         GLESVersion::ES3,
261         GLContext::ARB_ES3_compatibility,
262         {GLContext::EXT_occlusion_query_boolean, GLContext::Extensions_End}
263         /*
264          * XXX_occlusion_query_boolean provide ANY_SAMPLES_PASSED_CONSERVATIVE,
265          * but EXT_occlusion_query_boolean is only a OpenGL ES extension. But
266          * it is supported on desktop if ARB_ES3_compatibility because
267          * EXT_occlusion_query_boolean (added in OpenGL ES 3.0).
268          */
269     },
270     {
271         "occlusion_query2",
272         GLVersion::GL3_3,
273         GLESVersion::ES3,
274         GLContext::Extension_None,
275         {GLContext::ARB_occlusion_query2, GLContext::ARB_ES3_compatibility,
276          GLContext::EXT_occlusion_query_boolean, GLContext::Extensions_End}
277         /*
278          * XXX_occlusion_query2 (add in OpenGL 3.3) provide ANY_SAMPLES_PASSED,
279          * which is provided by ARB_occlusion_query2,
280          * EXT_occlusion_query_boolean (added in OpenGL ES 3.0) and
281          * ARB_ES3_compatibility
282          */
283     },
284     {"packed_depth_stencil",
285      GLVersion::GL3,
286      GLESVersion::ES3,
287      GLContext::Extension_None,
288      {GLContext::EXT_packed_depth_stencil, GLContext::OES_packed_depth_stencil,
289       GLContext::Extensions_End}},
290     {"prim_restart",
291      GLVersion::GL3_1,
292      GLESVersion::NONE,
293      GLContext::Extension_None,
294      {// GLContext::NV_primitive_restart, // Has different enum values.
295       GLContext::Extensions_End}},
296     {"prim_restart_fixed",
297      kGLCoreVersionForES3Compat,
298      GLESVersion::ES3,
299      GLContext::ARB_ES3_compatibility,
300      {GLContext::Extensions_End}},
301     {"query_counter",
302      GLVersion::GL3_3,
303      GLESVersion::NONE,
304      GLContext::ARB_timer_query,
305      {GLContext::ANGLE_timer_query, GLContext::EXT_disjoint_timer_query,
306       // EXT_timer_query does NOT support GL_TIMESTAMP retrieval with
307       // QueryCounter.
308       GLContext::Extensions_End}},
309     {
310         "query_objects",
311         GLVersion::GL2,
312         GLESVersion::ES3,
313         GLContext::Extension_None,
314         {GLContext::ANGLE_timer_query, GLContext::EXT_disjoint_timer_query,
315          GLContext::EXT_occlusion_query_boolean, GLContext::Extensions_End}
316         /*
317          * XXX_query_objects only provide entry points commonly supported by
318          * ARB_occlusion_query (added in OpenGL 2.0),
319          * EXT_occlusion_query_boolean (added in OpenGL ES 3.0), and
320          * ARB_timer_query (added in OpenGL 3.3)
321          */
322     },
323     {"query_time_elapsed",
324      GLVersion::GL3_3,
325      GLESVersion::NONE,
326      GLContext::ARB_timer_query,
327      {GLContext::ANGLE_timer_query, GLContext::EXT_disjoint_timer_query,
328       GLContext::EXT_timer_query, GLContext::Extensions_End}},
329     {"read_buffer",
330      GLVersion::GL2,
331      GLESVersion::ES3,
332      GLContext::Extension_None,
333      {GLContext::Extensions_End}},
334     {"renderbuffer_color_float",
335      GLVersion::GL3,
336      GLESVersion::ES3_2,
337      GLContext::Extension_None,
338      {GLContext::ARB_texture_float, GLContext::EXT_color_buffer_float,
339       GLContext::Extensions_End}},
340     {"renderbuffer_color_half_float",
341      GLVersion::GL3,
342      GLESVersion::ES3_2,
343      GLContext::Extension_None,
344      {GLContext::ARB_texture_float, GLContext::EXT_color_buffer_float,
345       GLContext::EXT_color_buffer_half_float, GLContext::Extensions_End}},
346     {"robust_buffer_access_behavior",
347      GLVersion::NONE,
348      GLESVersion::NONE,
349      GLContext::Extension_None,
350      {GLContext::ARB_robust_buffer_access_behavior,
351       GLContext::KHR_robust_buffer_access_behavior, GLContext::Extensions_End}},
352     {"robustness",
353      GLVersion::NONE,
354      GLESVersion::NONE,
355      GLContext::Extension_None,
356      {GLContext::ARB_robustness, GLContext::EXT_robustness,
357       GLContext::KHR_robustness, GLContext::Extensions_End}},
358     {"sRGB",
359      GLVersion::GL3,
360      GLESVersion::ES3,
361      GLContext::ARB_framebuffer_sRGB,
362      {GLContext::EXT_sRGB, GLContext::EXT_framebuffer_sRGB,
363       GLContext::Extensions_End}},
364     {"sampler_objects",
365      GLVersion::GL3_3,
366      GLESVersion::ES3,
367      GLContext::ARB_sampler_objects,
368      {GLContext::Extensions_End}},
369     {"seamless_cube_map_opt_in",
370      GLVersion::GL3_2,
371      GLESVersion::NONE,
372      GLContext::ARB_seamless_cube_map,
373      {GLContext::Extensions_End}},
374     {"shader_texture_lod",
375      GLVersion::GL3,
376      GLESVersion::ES3,
377      GLContext::Extension_None,
378      {GLContext::ARB_shader_texture_lod, GLContext::EXT_shader_texture_lod,
379       GLContext::Extensions_End}},
380     {// Do we have separate DRAW and READ framebuffer bind points?
381      "split_framebuffer",
382      GLVersion::GL3,
383      GLESVersion::ES3,
384      GLContext::ARB_framebuffer_object,
385      {GLContext::ANGLE_framebuffer_blit,
386       GLContext::APPLE_framebuffer_multisample, GLContext::EXT_framebuffer_blit,
387       GLContext::NV_framebuffer_blit, GLContext::Extensions_End}},
388     {"standard_derivatives",
389      GLVersion::GL2,
390      GLESVersion::ES3,
391      GLContext::Extension_None,
392      {GLContext::OES_standard_derivatives, GLContext::Extensions_End}},
393     {"sync",
394      GLVersion::GL3_2,
395      GLESVersion::ES3,
396      GLContext::Extension_None,
397      {GLContext::ARB_sync, GLContext::APPLE_sync, GLContext::Extensions_End}},
398     {"texture_3D",
399      GLVersion::GL1_2,
400      GLESVersion::ES3,
401      GLContext::Extension_None,
402      {GLContext::EXT_texture3D, GLContext::OES_texture_3D,
403       GLContext::Extensions_End}},
404     {"texture_3D_compressed",
405      GLVersion::GL1_3,
406      GLESVersion::ES3,
407      GLContext::Extension_None,
408      {GLContext::ARB_texture_compression, GLContext::OES_texture_3D,
409       GLContext::Extensions_End}},
410     {"texture_3D_copy",
411      GLVersion::GL1_2,
412      GLESVersion::ES3,
413      GLContext::Extension_None,
414      {GLContext::EXT_copy_texture, GLContext::OES_texture_3D,
415       GLContext::Extensions_End}},
416     {"texture_float",
417      GLVersion::GL3,
418      GLESVersion::ES3,
419      GLContext::Extension_None,
420      {GLContext::ARB_texture_float, GLContext::OES_texture_float,
421       GLContext::Extensions_End}},
422     {"texture_float_linear",
423      GLVersion::GL3_1,
424      GLESVersion::ES3,
425      GLContext::Extension_None,
426      {GLContext::ARB_texture_float, GLContext::OES_texture_float_linear,
427       GLContext::Extensions_End}},
428     {
429         "texture_half_float",
430         GLVersion::GL3,
431         GLESVersion::ES3,
432         GLContext::Extension_None,
433         {GLContext::ARB_half_float_pixel, GLContext::ARB_texture_float,
434          GLContext::NV_half_float, GLContext::Extensions_End}
435         /**
436          * We are not including OES_texture_half_float in this feature, because:
437          *   GL_HALF_FLOAT     = 0x140B
438          *   GL_HALF_FLOAT_ARB = 0x140B == GL_HALF_FLOAT
439          *   GL_HALF_FLOAT_NV  = 0x140B == GL_HALF_FLOAT
440          *   GL_HALF_FLOAT_OES = 0x8D61 != GL_HALF_FLOAT
441          * WebGL handles this specifically with an OES_texture_half_float check.
442          */
443     },
444     {"texture_half_float_linear",
445      GLVersion::GL3_1,
446      GLESVersion::ES3,
447      GLContext::Extension_None,
448      {GLContext::ARB_half_float_pixel, GLContext::ARB_texture_float,
449       GLContext::NV_half_float, GLContext::OES_texture_half_float_linear,
450       GLContext::Extensions_End}},
451     {"texture_non_power_of_two",
452      GLVersion::GL2,
453      GLESVersion::ES3,
454      GLContext::Extension_None,
455      {GLContext::ARB_texture_non_power_of_two, GLContext::OES_texture_npot,
456       GLContext::Extensions_End}},
457     {"texture_rg",
458      GLVersion::GL3,
459      GLESVersion::ES3,
460      GLContext::ARB_texture_rg,
461      {GLContext::Extensions_End}},
462     {"texture_storage",
463      GLVersion::GL4_2,
464      GLESVersion::ES3,
465      GLContext::ARB_texture_storage,
466      {/*
467        * Not including GL_EXT_texture_storage here because it
468        * doesn't guarantee glTexStorage3D, which is required for
469        * WebGL 2.
470        */
471       GLContext::Extensions_End}},
472     {"texture_swizzle",
473      GLVersion::GL3_3,
474      GLESVersion::ES3,
475      GLContext::ARB_texture_swizzle,
476      {GLContext::Extensions_End}},
477     {"transform_feedback2",
478      GLVersion::GL4,
479      GLESVersion::ES3,
480      GLContext::ARB_transform_feedback2,
481      {GLContext::NV_transform_feedback2, GLContext::Extensions_End}},
482     {"uniform_buffer_object",
483      GLVersion::GL3_1,
484      GLESVersion::ES3,
485      GLContext::ARB_uniform_buffer_object,
486      {GLContext::Extensions_End}},
487     {"uniform_matrix_nonsquare",
488      GLVersion::GL2_1,
489      GLESVersion::ES3,
490      GLContext::Extension_None,
491      {GLContext::Extensions_End}},
492     {"vertex_array_object",
493      GLVersion::GL3,
494      GLESVersion::ES3,
495      GLContext::ARB_vertex_array_object,  // ARB extension
496      {GLContext::OES_vertex_array_object, GLContext::APPLE_vertex_array_object,
497       GLContext::Extensions_End}}};
498 
GetFeatureInfo(GLFeature feature)499 static inline const FeatureInfo& GetFeatureInfo(GLFeature feature) {
500   static_assert(MOZ_ARRAY_LENGTH(sFeatureInfoArr) == size_t(GLFeature::EnumMax),
501                 "Mismatched lengths for sFeatureInfoInfos and GLFeature enums");
502 
503   MOZ_ASSERT(feature < GLFeature::EnumMax,
504              "GLContext::GetFeatureInfoInfo : unknown <feature>");
505 
506   return sFeatureInfoArr[size_t(feature)];
507 }
508 
ProfileVersionForFeature(GLFeature feature,ContextProfile profile)509 static inline uint32_t ProfileVersionForFeature(GLFeature feature,
510                                                 ContextProfile profile) {
511   MOZ_ASSERT(profile != ContextProfile::Unknown,
512              "GLContext::ProfileVersionForFeature : unknown <profile>");
513 
514   const FeatureInfo& featureInfo = GetFeatureInfo(feature);
515 
516   if (profile == ContextProfile::OpenGLES)
517     return (uint32_t)featureInfo.mOpenGLESVersion;
518 
519   return (uint32_t)featureInfo.mOpenGLVersion;
520 }
521 
IsFeaturePartOfProfileVersion(GLFeature feature,ContextProfile profile,unsigned int version)522 bool IsFeaturePartOfProfileVersion(GLFeature feature, ContextProfile profile,
523                                    unsigned int version) {
524   unsigned int profileVersion = ProfileVersionForFeature(feature, profile);
525 
526   /**
527    * if `profileVersion` is zero, it means that no version of the profile
528    * added support for the feature.
529    */
530   return profileVersion && version >= profileVersion;
531 }
532 
IsFeatureProvidedByCoreSymbols(GLFeature feature)533 bool GLContext::IsFeatureProvidedByCoreSymbols(GLFeature feature) {
534   if (IsFeaturePartOfProfileVersion(feature, mProfile, mVersion)) return true;
535 
536   if (IsExtensionSupported(
537           GetFeatureInfo(feature).mARBExtensionWithoutARBSuffix))
538     return true;
539 
540   return false;
541 }
542 
GetFeatureName(GLFeature feature)543 const char* GLContext::GetFeatureName(GLFeature feature) {
544   return GetFeatureInfo(feature).mName;
545 }
546 
InitFeatures()547 void GLContext::InitFeatures() {
548   for (size_t featureId = 0; featureId < size_t(GLFeature::EnumMax);
549        featureId++) {
550     GLFeature feature = GLFeature(featureId);
551 
552     if (IsFeaturePartOfProfileVersion(feature, mProfile, mVersion)) {
553       mAvailableFeatures[featureId] = true;
554       continue;
555     }
556 
557     mAvailableFeatures[featureId] = false;
558 
559     const FeatureInfo& featureInfo = GetFeatureInfo(feature);
560 
561     if (IsExtensionSupported(featureInfo.mARBExtensionWithoutARBSuffix)) {
562       mAvailableFeatures[featureId] = true;
563       continue;
564     }
565 
566     for (size_t j = 0; true; j++) {
567       MOZ_ASSERT(j < kMAX_EXTENSION_GROUP_SIZE,
568                  "kMAX_EXTENSION_GROUP_SIZE too small");
569 
570       if (featureInfo.mExtensions[j] == GLContext::Extensions_End) break;
571 
572       if (IsExtensionSupported(featureInfo.mExtensions[j])) {
573         mAvailableFeatures[featureId] = true;
574         break;
575       }
576     }
577   }
578 
579   if (ShouldDumpExts()) {
580     for (size_t featureId = 0; featureId < size_t(GLFeature::EnumMax);
581          featureId++) {
582       GLFeature feature = GLFeature(featureId);
583       printf_stderr("[%s] Feature::%s\n",
584                     IsSupported(feature) ? "enabled" : "disabled",
585                     GetFeatureName(feature));
586     }
587   }
588 }
589 
MarkUnsupported(GLFeature feature)590 void GLContext::MarkUnsupported(GLFeature feature) {
591   mAvailableFeatures[size_t(feature)] = false;
592 
593   const FeatureInfo& featureInfo = GetFeatureInfo(feature);
594 
595   for (size_t i = 0; true; i++) {
596     MOZ_ASSERT(i < kMAX_EXTENSION_GROUP_SIZE,
597                "kMAX_EXTENSION_GROUP_SIZE too small");
598 
599     if (featureInfo.mExtensions[i] == GLContext::Extensions_End) break;
600 
601     MarkExtensionUnsupported(featureInfo.mExtensions[i]);
602   }
603 
604   MOZ_ASSERT(!IsSupported(feature), "GLContext::MarkUnsupported has failed!");
605 
606   NS_WARNING(
607       nsPrintfCString("%s marked as unsupported", GetFeatureName(feature))
608           .get());
609 }
610 
611 } /* namespace gl */
612 } /* namespace mozilla */
613