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