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 {
46     const char* mName;
47 
48     /* The (desktop) OpenGL version that provides this feature */
49     GLVersion mOpenGLVersion;
50 
51     /* The OpenGL ES version that provides this feature */
52     GLESVersion mOpenGLESVersion;
53 
54     /* If there is an ARB extension, and its function symbols are
55      * not decorated with an ARB suffix, then its extension ID should go
56      * here, and NOT in mExtensions.  For example, ARB_vertex_array_object
57      * functions do not have an ARB suffix, because it is an extension that
58      * was created to match core GL functionality and will never differ.
59      * Some ARB extensions do have a suffix, if they were created before
60      * a core version of the functionality existed.
61      *
62      * If there is no such ARB extension, pass 0 (GLContext::Extension_None)
63      */
64     GLContext::GLExtensions mARBExtensionWithoutARBSuffix;
65 
66     /* Extensions that also provide this feature */
67     GLContext::GLExtensions mExtensions[kMAX_EXTENSION_GROUP_SIZE];
68 };
69 
70 static const FeatureInfo sFeatureInfoArr[] = {
71     {
72         "bind_buffer_offset",
73         GLVersion::NONE,
74         GLESVersion::NONE,
75         GLContext::Extension_None,
76         {
77 
78             GLContext::EXT_transform_feedback,
79             GLContext::NV_transform_feedback2,
80             GLContext::Extensions_End
81         }
82     },
83     {
84         "blend_minmax",
85         GLVersion::GL2,
86         GLESVersion::ES3,
87         GLContext::Extension_None,
88         {
89             GLContext::EXT_blend_minmax,
90             GLContext::Extensions_End
91         }
92     },
93     {
94         "clear_buffers",
95         GLVersion::GL3,
96         GLESVersion::ES3,
97         GLContext::Extension_None,
98         {
99             GLContext::Extensions_End
100         }
101     },
102     {
103         "copy_buffer",
104         GLVersion::GL3_1,
105         GLESVersion::ES3,
106         GLContext::ARB_copy_buffer,
107         {
108             GLContext::Extensions_End
109         }
110     },
111     {
112         "depth_texture",
113         GLVersion::GL2,
114         GLESVersion::ES3,
115         GLContext::Extension_None,
116         {
117             GLContext::ARB_depth_texture,
118             GLContext::OES_depth_texture,
119             // Intentionally avoid putting ANGLE_depth_texture here,
120             // it does not offer quite the same functionality.
121             GLContext::Extensions_End
122         }
123     },
124     {
125         "draw_buffers",
126         GLVersion::GL2,
127         GLESVersion::ES3,
128         GLContext::Extension_None,
129         {
130             GLContext::ARB_draw_buffers,
131             GLContext::EXT_draw_buffers,
132             GLContext::Extensions_End
133         }
134     },
135     {
136         "draw_instanced",
137         GLVersion::GL3_1,
138         GLESVersion::ES3,
139         GLContext::Extension_None,
140         {
141             GLContext::ARB_draw_instanced,
142             GLContext::EXT_draw_instanced,
143             GLContext::NV_draw_instanced,
144             GLContext::ANGLE_instanced_arrays,
145             GLContext::Extensions_End
146         }
147     },
148     {
149         "draw_range_elements",
150         GLVersion::GL1_2,
151         GLESVersion::ES3,
152         GLContext::Extension_None,
153         {
154             GLContext::EXT_draw_range_elements,
155             GLContext::Extensions_End
156         }
157     },
158     {
159         "element_index_uint",
160         GLVersion::GL2,
161         GLESVersion::ES3,
162         GLContext::Extension_None,
163         {
164             GLContext::OES_element_index_uint,
165             GLContext::Extensions_End
166         }
167     },
168     {
169         "ES2_compatibility",
170         kGLCoreVersionForES2Compat,
171         GLESVersion::ES2, // OpenGL ES version
172         GLContext::ARB_ES2_compatibility, // no suffix on ARB extension
173         {
174             GLContext::Extensions_End
175         }
176     },
177     {
178         "ES3_compatibility",
179         kGLCoreVersionForES3Compat,
180         GLESVersion::ES3, // OpenGL ES version
181         GLContext::ARB_ES3_compatibility, // no suffix on ARB extension
182         {
183             GLContext::Extensions_End
184         }
185     },
186     {
187         "EXT_color_buffer_float",
188         GLVersion::GL3,
189         GLESVersion::ES3_2,
190         GLContext::Extension_None,
191         {
192             GLContext::EXT_color_buffer_float,
193             GLContext::Extensions_End
194         }
195     },
196     {
197         // Removes clamping for float color outputs from frag shaders.
198         "frag_color_float",
199         GLVersion::GL3,
200         GLESVersion::ES3,
201         GLContext::Extension_None,
202         {
203             GLContext::ARB_color_buffer_float,
204             GLContext::EXT_color_buffer_float,
205             GLContext::EXT_color_buffer_half_float,
206             GLContext::Extensions_End
207         }
208     },
209     {
210         "frag_depth",
211         GLVersion::GL2,
212         GLESVersion::ES3,
213         GLContext::Extension_None,
214         {
215             GLContext::EXT_frag_depth,
216             GLContext::Extensions_End
217         }
218     },
219     {
220         // Check for just the blit framebuffer blit part of
221         // ARB_framebuffer_object
222         "framebuffer_blit",
223         GLVersion::GL3,
224         GLESVersion::ES3,
225         GLContext::ARB_framebuffer_object,
226         {
227             GLContext::ANGLE_framebuffer_blit,
228             GLContext::EXT_framebuffer_blit,
229             GLContext::NV_framebuffer_blit,
230             GLContext::Extensions_End
231         }
232     },
233     {
234         // Check for just the multisample renderbuffer part of
235         // ARB_framebuffer_object
236         "framebuffer_multisample",
237         GLVersion::GL3,
238         GLESVersion::ES3,
239         GLContext::ARB_framebuffer_object,
240         {
241             GLContext::ANGLE_framebuffer_multisample,
242             GLContext::APPLE_framebuffer_multisample,
243             GLContext::EXT_framebuffer_multisample,
244             GLContext::EXT_multisampled_render_to_texture,
245             GLContext::Extensions_End
246         }
247     },
248     {
249         // ARB_framebuffer_object support
250         "framebuffer_object",
251         GLVersion::GL3,
252         GLESVersion::ES3,
253         GLContext::ARB_framebuffer_object,
254         {
255             GLContext::Extensions_End
256         }
257     },
258     {
259         // EXT_framebuffer_object/OES_framebuffer_object support
260         "framebuffer_object_EXT_OES",
261         GLVersion::GL3,
262         GLESVersion::ES2,
263         GLContext::Extension_None,
264         {
265             GLContext::EXT_framebuffer_object,
266             GLContext::OES_framebuffer_object,
267             GLContext::Extensions_End
268         }
269     },
270     {
271         "get_integer_indexed",
272         GLVersion::GL3,
273         GLESVersion::ES3,
274         GLContext::Extension_None,
275         {
276             GLContext::EXT_draw_buffers2,
277             GLContext::Extensions_End
278         }
279     },
280     {
281         "get_integer64_indexed",
282         GLVersion::GL3_2,
283         GLESVersion::ES3,
284         GLContext::Extension_None,
285         {
286             GLContext::Extensions_End
287         }
288     },
289     {
290         "get_query_object_i64v",
291         GLVersion::GL3_3,
292         GLESVersion::NONE,
293         GLContext::ARB_timer_query,
294         {
295             GLContext::ANGLE_timer_query,
296             GLContext::EXT_disjoint_timer_query,
297             GLContext::EXT_timer_query,
298             GLContext::Extensions_End
299         }
300     },
301     {
302         "get_query_object_iv",
303         GLVersion::GL2,
304         GLESVersion::NONE,
305         GLContext::Extension_None,
306         {
307             GLContext::Extensions_End
308         }
309         /*
310          * XXX_get_query_object_iv only provide GetQueryObjectiv provided by
311          * ARB_occlusion_query (added by OpenGL 2.0).
312          */
313     },
314     {
315         "get_string_indexed",
316         GLVersion::GL3,
317         GLESVersion::ES3,
318         GLContext::Extension_None,
319         {
320             GLContext::Extensions_End
321         }
322         // glGetStringi
323     },
324     {
325         "gpu_shader4",
326         GLVersion::GL3,
327         GLESVersion::ES3,
328         GLContext::Extension_None,
329         {
330             GLContext::EXT_gpu_shader4,
331             GLContext::Extensions_End
332         }
333     },
334     {
335         "instanced_arrays",
336         GLVersion::GL3_3,
337         GLESVersion::ES3,
338         GLContext::Extension_None,
339         {
340             GLContext::ARB_instanced_arrays,
341             GLContext::NV_instanced_arrays,
342             GLContext::ANGLE_instanced_arrays,
343             GLContext::Extensions_End
344         }
345     },
346     {
347         "instanced_non_arrays",
348         GLVersion::GL3_3,
349         GLESVersion::ES3,
350         GLContext::Extension_None,
351         {
352             GLContext::ARB_instanced_arrays,
353             GLContext::Extensions_End
354         }
355         /* This is an expanded version of `instanced_arrays` that allows for all
356          * enabled active attrib arrays to have non-zero divisors.
357          * ANGLE_instanced_arrays and NV_instanced_arrays forbid this, but GLES3
358          * has no such restriction.
359          */
360     },
361     {
362         "internalformat_query",
363         GLVersion::GL4_2,
364         GLESVersion::ES3,
365         GLContext::ARB_internalformat_query,
366         {
367             GLContext::Extensions_End
368         }
369     },
370     {
371         "invalidate_framebuffer",
372         GLVersion::GL4_3,
373         GLESVersion::ES3,
374         GLContext::ARB_invalidate_subdata,
375         {
376             GLContext::Extensions_End
377         }
378     },
379     {
380         "map_buffer_range",
381         GLVersion::GL3,
382         GLESVersion::ES3,
383         GLContext::ARB_map_buffer_range,
384         {
385             GLContext::Extensions_End
386         }
387     },
388     {
389         "occlusion_query",
390         GLVersion::GL2,
391         GLESVersion::NONE,
392         GLContext::Extension_None,
393         {
394             GLContext::Extensions_End
395         }
396         // XXX_occlusion_query depend on ARB_occlusion_query (added in OpenGL 2.0)
397     },
398     {
399         "occlusion_query_boolean",
400         kGLCoreVersionForES3Compat,
401         GLESVersion::ES3,
402         GLContext::ARB_ES3_compatibility,
403         {
404             GLContext::EXT_occlusion_query_boolean,
405             GLContext::Extensions_End
406         }
407         /*
408          * XXX_occlusion_query_boolean provide ANY_SAMPLES_PASSED_CONSERVATIVE,
409          * but EXT_occlusion_query_boolean is only a OpenGL ES extension. But
410          * it is supported on desktop if ARB_ES3_compatibility because
411          * EXT_occlusion_query_boolean (added in OpenGL ES 3.0).
412          */
413     },
414     {
415         "occlusion_query2",
416         GLVersion::GL3_3,
417         GLESVersion::ES3,
418         GLContext::Extension_None,
419         {
420             GLContext::ARB_occlusion_query2,
421             GLContext::ARB_ES3_compatibility,
422             GLContext::EXT_occlusion_query_boolean,
423             GLContext::Extensions_End
424         }
425         /*
426          * XXX_occlusion_query2 (add in OpenGL 3.3) provide ANY_SAMPLES_PASSED,
427          * which is provided by ARB_occlusion_query2, EXT_occlusion_query_boolean
428          * (added in OpenGL ES 3.0) and ARB_ES3_compatibility
429          */
430     },
431     {
432         "packed_depth_stencil",
433         GLVersion::GL3,
434         GLESVersion::ES3,
435         GLContext::Extension_None,
436         {
437             GLContext::EXT_packed_depth_stencil,
438             GLContext::OES_packed_depth_stencil,
439             GLContext::Extensions_End
440         }
441     },
442     {
443         "prim_restart",
444         GLVersion::GL3_1,
445         GLESVersion::NONE,
446         GLContext::Extension_None,
447         {
448             //GLContext::NV_primitive_restart, // Has different enum values.
449             GLContext::Extensions_End
450         }
451     },
452     {
453         "prim_restart_fixed",
454         kGLCoreVersionForES3Compat,
455         GLESVersion::ES3,
456         GLContext::ARB_ES3_compatibility,
457         {
458             GLContext::Extensions_End
459         }
460     },
461     {
462         "query_counter",
463         GLVersion::GL3_3,
464         GLESVersion::NONE,
465         GLContext::ARB_timer_query,
466         {
467             GLContext::ANGLE_timer_query,
468             GLContext::EXT_disjoint_timer_query,
469             // EXT_timer_query does NOT support GL_TIMESTAMP retrieval with
470             // QueryCounter.
471             GLContext::Extensions_End
472         }
473     },
474     {
475         "query_objects",
476         GLVersion::GL2,
477         GLESVersion::ES3,
478         GLContext::Extension_None,
479         {
480             GLContext::ANGLE_timer_query,
481             GLContext::EXT_disjoint_timer_query,
482             GLContext::EXT_occlusion_query_boolean,
483             GLContext::Extensions_End
484         }
485         /*
486          * XXX_query_objects only provide entry points commonly supported by
487          * ARB_occlusion_query (added in OpenGL 2.0), EXT_occlusion_query_boolean
488          * (added in OpenGL ES 3.0), and ARB_timer_query (added in OpenGL 3.3)
489          */
490     },
491     {
492         "query_time_elapsed",
493         GLVersion::GL3_3,
494         GLESVersion::NONE,
495         GLContext::ARB_timer_query,
496         {
497             GLContext::ANGLE_timer_query,
498             GLContext::EXT_disjoint_timer_query,
499             GLContext::EXT_timer_query,
500             GLContext::Extensions_End
501         }
502     },
503     {
504         "read_buffer",
505         GLVersion::GL2,
506         GLESVersion::ES3,
507         GLContext::Extension_None,
508         {
509             GLContext::Extensions_End
510         }
511     },
512     {
513         "renderbuffer_color_float",
514         GLVersion::GL3,
515         GLESVersion::ES3_2,
516         GLContext::Extension_None,
517         {
518             GLContext::ARB_texture_float,
519             GLContext::EXT_color_buffer_float,
520             GLContext::Extensions_End
521         }
522     },
523     {
524         "renderbuffer_color_half_float",
525         GLVersion::GL3,
526         GLESVersion::ES3_2,
527         GLContext::Extension_None,
528         {
529             GLContext::ARB_texture_float,
530             GLContext::EXT_color_buffer_float,
531             GLContext::EXT_color_buffer_half_float,
532             GLContext::Extensions_End
533         }
534     },
535     {
536         "robustness",
537         GLVersion::NONE,
538         GLESVersion::NONE,
539         GLContext::Extension_None,
540         {
541             GLContext::ARB_robustness,
542             GLContext::EXT_robustness,
543             GLContext::Extensions_End
544         }
545     },
546     {
547         "sRGB_framebuffer",
548         GLVersion::GL3,
549         GLESVersion::ES3,
550         GLContext::ARB_framebuffer_sRGB,
551         {
552             GLContext::EXT_framebuffer_sRGB,
553             GLContext::EXT_sRGB_write_control,
554             GLContext::Extensions_End
555         }
556     },
557     {
558         "sRGB_texture",
559         GLVersion::GL2_1,
560         GLESVersion::ES3,
561         GLContext::Extension_None,
562         {
563             GLContext::EXT_sRGB,
564             GLContext::EXT_texture_sRGB,
565             GLContext::Extensions_End
566         }
567     },
568     {
569         "sampler_objects",
570         GLVersion::GL3_3,
571         GLESVersion::ES3,
572         GLContext::ARB_sampler_objects,
573         {
574             GLContext::Extensions_End
575         }
576     },
577     {
578         "seamless_cube_map_opt_in",
579         GLVersion::GL3_2,
580         GLESVersion::NONE,
581         GLContext::ARB_seamless_cube_map,
582         {
583             GLContext::Extensions_End
584         }
585     },
586     {
587         "shader_texture_lod",
588         GLVersion::NONE,
589         GLESVersion::NONE,
590         GLContext::Extension_None,
591         {
592             GLContext::ARB_shader_texture_lod,
593             GLContext::EXT_shader_texture_lod,
594             GLContext::Extensions_End
595         }
596     },
597     {
598         // Do we have separate DRAW and READ framebuffer bind points?
599         "split_framebuffer",
600         GLVersion::GL3,
601         GLESVersion::ES3,
602         GLContext::ARB_framebuffer_object,
603         {
604             GLContext::ANGLE_framebuffer_blit,
605             GLContext::APPLE_framebuffer_multisample,
606             GLContext::EXT_framebuffer_blit,
607             GLContext::NV_framebuffer_blit,
608             GLContext::Extensions_End
609         }
610     },
611     {
612         "standard_derivatives",
613         GLVersion::GL2,
614         GLESVersion::ES3,
615         GLContext::Extension_None,
616         {
617             GLContext::OES_standard_derivatives,
618             GLContext::Extensions_End
619         }
620     },
621     {
622         "sync",
623         GLVersion::GL3_2,
624         GLESVersion::ES3,
625         GLContext::Extension_None,
626         {
627             GLContext::ARB_sync,
628             GLContext::APPLE_sync,
629             GLContext::Extensions_End
630         }
631     },
632     {
633         "texture_3D",
634         GLVersion::GL1_2,
635         GLESVersion::ES3,
636         GLContext::Extension_None,
637         {
638             GLContext::EXT_texture3D,
639             GLContext::OES_texture_3D,
640             GLContext::Extensions_End
641         }
642     },
643     {
644         "texture_3D_compressed",
645         GLVersion::GL1_3,
646         GLESVersion::ES3,
647         GLContext::Extension_None,
648         {
649             GLContext::ARB_texture_compression,
650             GLContext::OES_texture_3D,
651             GLContext::Extensions_End
652         }
653     },
654     {
655         "texture_3D_copy",
656         GLVersion::GL1_2,
657         GLESVersion::ES3,
658         GLContext::Extension_None,
659         {
660             GLContext::EXT_copy_texture,
661             GLContext::OES_texture_3D,
662             GLContext::Extensions_End
663         }
664     },
665     {
666         "texture_float",
667         GLVersion::GL3,
668         GLESVersion::ES3,
669         GLContext::Extension_None,
670         {
671             GLContext::ARB_texture_float,
672             GLContext::OES_texture_float,
673             GLContext::Extensions_End
674         }
675     },
676     {
677         "texture_float_linear",
678         GLVersion::GL3_1,
679         GLESVersion::ES3,
680         GLContext::Extension_None,
681         {
682             GLContext::ARB_texture_float,
683             GLContext::OES_texture_float_linear,
684             GLContext::Extensions_End
685         }
686     },
687     {
688         "texture_half_float",
689         GLVersion::GL3,
690         GLESVersion::ES3,
691         GLContext::Extension_None,
692         {
693             GLContext::ARB_half_float_pixel,
694             GLContext::ARB_texture_float,
695             GLContext::NV_half_float,
696             GLContext::Extensions_End
697         }
698         /**
699          * We are not including OES_texture_half_float in this feature, because:
700          *   GL_HALF_FLOAT     = 0x140B
701          *   GL_HALF_FLOAT_ARB = 0x140B == GL_HALF_FLOAT
702          *   GL_HALF_FLOAT_NV  = 0x140B == GL_HALF_FLOAT
703          *   GL_HALF_FLOAT_OES = 0x8D61 != GL_HALF_FLOAT
704          * WebGL handles this specifically with an OES_texture_half_float check.
705          */
706     },
707     {
708         "texture_half_float_linear",
709         GLVersion::GL3_1,
710         GLESVersion::ES3,
711         GLContext::Extension_None,
712         {
713             GLContext::ARB_half_float_pixel,
714             GLContext::ARB_texture_float,
715             GLContext::NV_half_float,
716             GLContext::OES_texture_half_float_linear,
717             GLContext::Extensions_End
718         }
719     },
720     {
721         "texture_non_power_of_two",
722         GLVersion::GL2,
723         GLESVersion::ES3,
724         GLContext::Extension_None,
725         {
726             GLContext::ARB_texture_non_power_of_two,
727             GLContext::OES_texture_npot,
728             GLContext::Extensions_End
729         }
730     },
731     {
732         "texture_rg",
733         GLVersion::GL3,
734         GLESVersion::ES3,
735         GLContext::ARB_texture_rg,
736         {
737             GLContext::Extensions_End
738         }
739     },
740     {
741         "texture_storage",
742         GLVersion::GL4_2,
743         GLESVersion::ES3,
744         GLContext::ARB_texture_storage,
745         {
746             /*
747              * Not including GL_EXT_texture_storage here because it
748              * doesn't guarantee glTexStorage3D, which is required for
749              * WebGL 2.
750              */
751             GLContext::Extensions_End
752         }
753     },
754     {
755         "texture_swizzle",
756         GLVersion::GL3_3,
757         GLESVersion::ES3,
758         GLContext::ARB_texture_swizzle,
759         {
760             GLContext::Extensions_End
761         }
762     },
763     {
764         "transform_feedback2",
765         GLVersion::GL4,
766         GLESVersion::ES3,
767         GLContext::ARB_transform_feedback2,
768         {
769             GLContext::NV_transform_feedback2,
770             GLContext::Extensions_End
771         }
772     },
773     {
774         "uniform_buffer_object",
775         GLVersion::GL3_1,
776         GLESVersion::ES3,
777         GLContext::ARB_uniform_buffer_object,
778         {
779             GLContext::Extensions_End
780         }
781     },
782     {
783         "uniform_matrix_nonsquare",
784         GLVersion::GL2_1,
785         GLESVersion::ES3,
786         GLContext::Extension_None,
787         {
788             GLContext::Extensions_End
789         }
790     },
791     {
792         "vertex_array_object",
793         GLVersion::GL3,
794         GLESVersion::ES3,
795         GLContext::ARB_vertex_array_object, // ARB extension
796         {
797             GLContext::OES_vertex_array_object,
798             GLContext::APPLE_vertex_array_object,
799             GLContext::Extensions_End
800         }
801     }
802 };
803 
804 static inline const FeatureInfo&
GetFeatureInfo(GLFeature feature)805 GetFeatureInfo(GLFeature feature)
806 {
807     static_assert(MOZ_ARRAY_LENGTH(sFeatureInfoArr) == size_t(GLFeature::EnumMax),
808                   "Mismatched lengths for sFeatureInfoInfos and GLFeature enums");
809 
810     MOZ_ASSERT(feature < GLFeature::EnumMax,
811                "GLContext::GetFeatureInfoInfo : unknown <feature>");
812 
813     return sFeatureInfoArr[size_t(feature)];
814 }
815 
816 static inline uint32_t
ProfileVersionForFeature(GLFeature feature,ContextProfile profile)817 ProfileVersionForFeature(GLFeature feature, ContextProfile profile)
818 {
819     MOZ_ASSERT(profile != ContextProfile::Unknown,
820                "GLContext::ProfileVersionForFeature : unknown <profile>");
821 
822     const FeatureInfo& featureInfo = GetFeatureInfo(feature);
823 
824     if (profile == ContextProfile::OpenGLES)
825         return (uint32_t)featureInfo.mOpenGLESVersion;
826 
827     return (uint32_t)featureInfo.mOpenGLVersion;
828 }
829 
830 bool
IsFeaturePartOfProfileVersion(GLFeature feature,ContextProfile profile,unsigned int version)831 IsFeaturePartOfProfileVersion(GLFeature feature,
832                               ContextProfile profile, unsigned int version)
833 {
834     unsigned int profileVersion = ProfileVersionForFeature(feature, profile);
835 
836     /**
837      * if `profileVersion` is zero, it means that no version of the profile
838      * added support for the feature.
839      */
840     return profileVersion && version >= profileVersion;
841 }
842 
843 bool
IsFeatureProvidedByCoreSymbols(GLFeature feature)844 GLContext::IsFeatureProvidedByCoreSymbols(GLFeature feature)
845 {
846     if (IsFeaturePartOfProfileVersion(feature, mProfile, mVersion))
847         return true;
848 
849     if (IsExtensionSupported(GetFeatureInfo(feature).mARBExtensionWithoutARBSuffix))
850         return true;
851 
852     return false;
853 }
854 
855 const char*
GetFeatureName(GLFeature feature)856 GLContext::GetFeatureName(GLFeature feature)
857 {
858     return GetFeatureInfo(feature).mName;
859 }
860 
861 void
InitFeatures()862 GLContext::InitFeatures()
863 {
864     for (size_t featureId = 0; featureId < size_t(GLFeature::EnumMax); featureId++) {
865         GLFeature feature = GLFeature(featureId);
866 
867         if (IsFeaturePartOfProfileVersion(feature, mProfile, mVersion)) {
868             mAvailableFeatures[featureId] = true;
869             continue;
870         }
871 
872         mAvailableFeatures[featureId] = false;
873 
874         const FeatureInfo& featureInfo = GetFeatureInfo(feature);
875 
876         if (IsExtensionSupported(featureInfo.mARBExtensionWithoutARBSuffix)) {
877             mAvailableFeatures[featureId] = true;
878             continue;
879         }
880 
881         for (size_t j = 0; true; j++) {
882             MOZ_ASSERT(j < kMAX_EXTENSION_GROUP_SIZE,
883                        "kMAX_EXTENSION_GROUP_SIZE too small");
884 
885             if (featureInfo.mExtensions[j] == GLContext::Extensions_End)
886                 break;
887 
888             if (IsExtensionSupported(featureInfo.mExtensions[j])) {
889                 mAvailableFeatures[featureId] = true;
890                 break;
891             }
892         }
893     }
894 
895     if (ShouldDumpExts()) {
896         for (size_t featureId = 0; featureId < size_t(GLFeature::EnumMax); featureId++) {
897             GLFeature feature = GLFeature(featureId);
898             printf_stderr("[%s] Feature::%s\n",
899                           IsSupported(feature) ? "enabled" : "disabled",
900                           GetFeatureName(feature));
901         }
902     }
903 }
904 
905 void
MarkUnsupported(GLFeature feature)906 GLContext::MarkUnsupported(GLFeature feature)
907 {
908     mAvailableFeatures[size_t(feature)] = false;
909 
910     const FeatureInfo& featureInfo = GetFeatureInfo(feature);
911 
912     for (size_t i = 0; true; i++) {
913         MOZ_ASSERT(i < kMAX_EXTENSION_GROUP_SIZE, "kMAX_EXTENSION_GROUP_SIZE too small");
914 
915         if (featureInfo.mExtensions[i] == GLContext::Extensions_End)
916             break;
917 
918         MarkExtensionUnsupported(featureInfo.mExtensions[i]);
919     }
920 
921     MOZ_ASSERT(!IsSupported(feature), "GLContext::MarkUnsupported has failed!");
922 
923     NS_WARNING(nsPrintfCString("%s marked as unsupported",
924                                GetFeatureName(feature)).get());
925 }
926 
927 } /* namespace gl */
928 } /* namespace mozilla */
929