summaryrefslogtreecommitdiffstats
path: root/gfx/gl/GLContextFeatures.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/gl/GLContextFeatures.cpp')
-rw-r--r--gfx/gl/GLContextFeatures.cpp928
1 files changed, 928 insertions, 0 deletions
diff --git a/gfx/gl/GLContextFeatures.cpp b/gfx/gl/GLContextFeatures.cpp
new file mode 100644
index 000000000..0714d9641
--- /dev/null
+++ b/gfx/gl/GLContextFeatures.cpp
@@ -0,0 +1,928 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GLContext.h"
+#include "nsPrintfCString.h"
+
+namespace mozilla {
+namespace gl {
+
+const size_t kMAX_EXTENSION_GROUP_SIZE = 5;
+
+enum class GLVersion : uint32_t {
+ NONE = 0, // Feature is not supported natively by GL
+ GL1_2 = 120,
+ GL1_3 = 130,
+ GL2 = 200,
+ GL2_1 = 210,
+ GL3 = 300,
+ GL3_1 = 310,
+ GL3_2 = 320,
+ GL3_3 = 330,
+ GL4 = 400,
+ GL4_1 = 410,
+ GL4_2 = 420,
+ GL4_3 = 430,
+};
+
+enum class GLESVersion : uint32_t {
+ NONE = 0, // Feature is not support natively by GL ES
+ ES2 = 200,
+ ES3 = 300,
+ ES3_1 = 310,
+ ES3_2 = 320,
+};
+
+// ARB_ES2_compatibility is natively supported in OpenGL 4.1.
+static const GLVersion kGLCoreVersionForES2Compat = GLVersion::GL4_1;
+
+// ARB_ES3_compatibility is natively supported in OpenGL 4.3.
+static const GLVersion kGLCoreVersionForES3Compat = GLVersion::GL4_3;
+
+struct FeatureInfo
+{
+ const char* mName;
+
+ /* The (desktop) OpenGL version that provides this feature */
+ GLVersion mOpenGLVersion;
+
+ /* The OpenGL ES version that provides this feature */
+ GLESVersion mOpenGLESVersion;
+
+ /* If there is an ARB extension, and its function symbols are
+ * not decorated with an ARB suffix, then its extension ID should go
+ * here, and NOT in mExtensions. For example, ARB_vertex_array_object
+ * functions do not have an ARB suffix, because it is an extension that
+ * was created to match core GL functionality and will never differ.
+ * Some ARB extensions do have a suffix, if they were created before
+ * a core version of the functionality existed.
+ *
+ * If there is no such ARB extension, pass 0 (GLContext::Extension_None)
+ */
+ GLContext::GLExtensions mARBExtensionWithoutARBSuffix;
+
+ /* Extensions that also provide this feature */
+ GLContext::GLExtensions mExtensions[kMAX_EXTENSION_GROUP_SIZE];
+};
+
+static const FeatureInfo sFeatureInfoArr[] = {
+ {
+ "bind_buffer_offset",
+ GLVersion::NONE,
+ GLESVersion::NONE,
+ GLContext::Extension_None,
+ {
+
+ GLContext::EXT_transform_feedback,
+ GLContext::NV_transform_feedback2,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "blend_minmax",
+ GLVersion::GL2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::EXT_blend_minmax,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "clear_buffers",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "copy_buffer",
+ GLVersion::GL3_1,
+ GLESVersion::ES3,
+ GLContext::ARB_copy_buffer,
+ {
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "depth_texture",
+ GLVersion::GL2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::ARB_depth_texture,
+ GLContext::OES_depth_texture,
+ // Intentionally avoid putting ANGLE_depth_texture here,
+ // it does not offer quite the same functionality.
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "draw_buffers",
+ GLVersion::GL2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::ARB_draw_buffers,
+ GLContext::EXT_draw_buffers,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "draw_instanced",
+ GLVersion::GL3_1,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::ARB_draw_instanced,
+ GLContext::EXT_draw_instanced,
+ GLContext::NV_draw_instanced,
+ GLContext::ANGLE_instanced_arrays,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "draw_range_elements",
+ GLVersion::GL1_2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::EXT_draw_range_elements,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "element_index_uint",
+ GLVersion::GL2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::OES_element_index_uint,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "ES2_compatibility",
+ kGLCoreVersionForES2Compat,
+ GLESVersion::ES2, // OpenGL ES version
+ GLContext::ARB_ES2_compatibility, // no suffix on ARB extension
+ {
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "ES3_compatibility",
+ kGLCoreVersionForES3Compat,
+ GLESVersion::ES3, // OpenGL ES version
+ GLContext::ARB_ES3_compatibility, // no suffix on ARB extension
+ {
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "EXT_color_buffer_float",
+ GLVersion::GL3,
+ GLESVersion::ES3_2,
+ GLContext::Extension_None,
+ {
+ GLContext::EXT_color_buffer_float,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ // Removes clamping for float color outputs from frag shaders.
+ "frag_color_float",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::ARB_color_buffer_float,
+ GLContext::EXT_color_buffer_float,
+ GLContext::EXT_color_buffer_half_float,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "frag_depth",
+ GLVersion::GL2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::EXT_frag_depth,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ // Check for just the blit framebuffer blit part of
+ // ARB_framebuffer_object
+ "framebuffer_blit",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::ARB_framebuffer_object,
+ {
+ GLContext::ANGLE_framebuffer_blit,
+ GLContext::EXT_framebuffer_blit,
+ GLContext::NV_framebuffer_blit,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ // Check for just the multisample renderbuffer part of
+ // ARB_framebuffer_object
+ "framebuffer_multisample",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::ARB_framebuffer_object,
+ {
+ GLContext::ANGLE_framebuffer_multisample,
+ GLContext::APPLE_framebuffer_multisample,
+ GLContext::EXT_framebuffer_multisample,
+ GLContext::EXT_multisampled_render_to_texture,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ // ARB_framebuffer_object support
+ "framebuffer_object",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::ARB_framebuffer_object,
+ {
+ GLContext::Extensions_End
+ }
+ },
+ {
+ // EXT_framebuffer_object/OES_framebuffer_object support
+ "framebuffer_object_EXT_OES",
+ GLVersion::GL3,
+ GLESVersion::ES2,
+ GLContext::Extension_None,
+ {
+ GLContext::EXT_framebuffer_object,
+ GLContext::OES_framebuffer_object,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "get_integer_indexed",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::EXT_draw_buffers2,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "get_integer64_indexed",
+ GLVersion::GL3_2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "get_query_object_i64v",
+ GLVersion::GL3_3,
+ GLESVersion::NONE,
+ GLContext::ARB_timer_query,
+ {
+ GLContext::ANGLE_timer_query,
+ GLContext::EXT_disjoint_timer_query,
+ GLContext::EXT_timer_query,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "get_query_object_iv",
+ GLVersion::GL2,
+ GLESVersion::NONE,
+ GLContext::Extension_None,
+ {
+ GLContext::Extensions_End
+ }
+ /*
+ * XXX_get_query_object_iv only provide GetQueryObjectiv provided by
+ * ARB_occlusion_query (added by OpenGL 2.0).
+ */
+ },
+ {
+ "get_string_indexed",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::Extensions_End
+ }
+ // glGetStringi
+ },
+ {
+ "gpu_shader4",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::EXT_gpu_shader4,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "instanced_arrays",
+ GLVersion::GL3_3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::ARB_instanced_arrays,
+ GLContext::NV_instanced_arrays,
+ GLContext::ANGLE_instanced_arrays,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "instanced_non_arrays",
+ GLVersion::GL3_3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::ARB_instanced_arrays,
+ GLContext::Extensions_End
+ }
+ /* This is an expanded version of `instanced_arrays` that allows for all
+ * enabled active attrib arrays to have non-zero divisors.
+ * ANGLE_instanced_arrays and NV_instanced_arrays forbid this, but GLES3
+ * has no such restriction.
+ */
+ },
+ {
+ "internalformat_query",
+ GLVersion::GL4_2,
+ GLESVersion::ES3,
+ GLContext::ARB_internalformat_query,
+ {
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "invalidate_framebuffer",
+ GLVersion::GL4_3,
+ GLESVersion::ES3,
+ GLContext::ARB_invalidate_subdata,
+ {
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "map_buffer_range",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::ARB_map_buffer_range,
+ {
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "occlusion_query",
+ GLVersion::GL2,
+ GLESVersion::NONE,
+ GLContext::Extension_None,
+ {
+ GLContext::Extensions_End
+ }
+ // XXX_occlusion_query depend on ARB_occlusion_query (added in OpenGL 2.0)
+ },
+ {
+ "occlusion_query_boolean",
+ kGLCoreVersionForES3Compat,
+ GLESVersion::ES3,
+ GLContext::ARB_ES3_compatibility,
+ {
+ GLContext::EXT_occlusion_query_boolean,
+ GLContext::Extensions_End
+ }
+ /*
+ * XXX_occlusion_query_boolean provide ANY_SAMPLES_PASSED_CONSERVATIVE,
+ * but EXT_occlusion_query_boolean is only a OpenGL ES extension. But
+ * it is supported on desktop if ARB_ES3_compatibility because
+ * EXT_occlusion_query_boolean (added in OpenGL ES 3.0).
+ */
+ },
+ {
+ "occlusion_query2",
+ GLVersion::GL3_3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::ARB_occlusion_query2,
+ GLContext::ARB_ES3_compatibility,
+ GLContext::EXT_occlusion_query_boolean,
+ GLContext::Extensions_End
+ }
+ /*
+ * XXX_occlusion_query2 (add in OpenGL 3.3) provide ANY_SAMPLES_PASSED,
+ * which is provided by ARB_occlusion_query2, EXT_occlusion_query_boolean
+ * (added in OpenGL ES 3.0) and ARB_ES3_compatibility
+ */
+ },
+ {
+ "packed_depth_stencil",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::EXT_packed_depth_stencil,
+ GLContext::OES_packed_depth_stencil,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "prim_restart",
+ GLVersion::GL3_1,
+ GLESVersion::NONE,
+ GLContext::Extension_None,
+ {
+ //GLContext::NV_primitive_restart, // Has different enum values.
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "prim_restart_fixed",
+ kGLCoreVersionForES3Compat,
+ GLESVersion::ES3,
+ GLContext::ARB_ES3_compatibility,
+ {
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "query_counter",
+ GLVersion::GL3_3,
+ GLESVersion::NONE,
+ GLContext::ARB_timer_query,
+ {
+ GLContext::ANGLE_timer_query,
+ GLContext::EXT_disjoint_timer_query,
+ // EXT_timer_query does NOT support GL_TIMESTAMP retrieval with
+ // QueryCounter.
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "query_objects",
+ GLVersion::GL2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::ANGLE_timer_query,
+ GLContext::EXT_disjoint_timer_query,
+ GLContext::EXT_occlusion_query_boolean,
+ GLContext::Extensions_End
+ }
+ /*
+ * XXX_query_objects only provide entry points commonly supported by
+ * ARB_occlusion_query (added in OpenGL 2.0), EXT_occlusion_query_boolean
+ * (added in OpenGL ES 3.0), and ARB_timer_query (added in OpenGL 3.3)
+ */
+ },
+ {
+ "query_time_elapsed",
+ GLVersion::GL3_3,
+ GLESVersion::NONE,
+ GLContext::ARB_timer_query,
+ {
+ GLContext::ANGLE_timer_query,
+ GLContext::EXT_disjoint_timer_query,
+ GLContext::EXT_timer_query,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "read_buffer",
+ GLVersion::GL2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "renderbuffer_color_float",
+ GLVersion::GL3,
+ GLESVersion::ES3_2,
+ GLContext::Extension_None,
+ {
+ GLContext::ARB_texture_float,
+ GLContext::EXT_color_buffer_float,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "renderbuffer_color_half_float",
+ GLVersion::GL3,
+ GLESVersion::ES3_2,
+ GLContext::Extension_None,
+ {
+ GLContext::ARB_texture_float,
+ GLContext::EXT_color_buffer_float,
+ GLContext::EXT_color_buffer_half_float,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "robustness",
+ GLVersion::NONE,
+ GLESVersion::NONE,
+ GLContext::Extension_None,
+ {
+ GLContext::ARB_robustness,
+ GLContext::EXT_robustness,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "sRGB_framebuffer",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::ARB_framebuffer_sRGB,
+ {
+ GLContext::EXT_framebuffer_sRGB,
+ GLContext::EXT_sRGB_write_control,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "sRGB_texture",
+ GLVersion::GL2_1,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::EXT_sRGB,
+ GLContext::EXT_texture_sRGB,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "sampler_objects",
+ GLVersion::GL3_3,
+ GLESVersion::ES3,
+ GLContext::ARB_sampler_objects,
+ {
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "seamless_cube_map_opt_in",
+ GLVersion::GL3_2,
+ GLESVersion::NONE,
+ GLContext::ARB_seamless_cube_map,
+ {
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "shader_texture_lod",
+ GLVersion::NONE,
+ GLESVersion::NONE,
+ GLContext::Extension_None,
+ {
+ GLContext::ARB_shader_texture_lod,
+ GLContext::EXT_shader_texture_lod,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ // Do we have separate DRAW and READ framebuffer bind points?
+ "split_framebuffer",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::ARB_framebuffer_object,
+ {
+ GLContext::ANGLE_framebuffer_blit,
+ GLContext::APPLE_framebuffer_multisample,
+ GLContext::EXT_framebuffer_blit,
+ GLContext::NV_framebuffer_blit,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "standard_derivatives",
+ GLVersion::GL2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::OES_standard_derivatives,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "sync",
+ GLVersion::GL3_2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::ARB_sync,
+ GLContext::APPLE_sync,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "texture_3D",
+ GLVersion::GL1_2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::EXT_texture3D,
+ GLContext::OES_texture_3D,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "texture_3D_compressed",
+ GLVersion::GL1_3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::ARB_texture_compression,
+ GLContext::OES_texture_3D,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "texture_3D_copy",
+ GLVersion::GL1_2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::EXT_copy_texture,
+ GLContext::OES_texture_3D,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "texture_float",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::ARB_texture_float,
+ GLContext::OES_texture_float,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "texture_float_linear",
+ GLVersion::GL3_1,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::ARB_texture_float,
+ GLContext::OES_texture_float_linear,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "texture_half_float",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::ARB_half_float_pixel,
+ GLContext::ARB_texture_float,
+ GLContext::NV_half_float,
+ GLContext::Extensions_End
+ }
+ /**
+ * We are not including OES_texture_half_float in this feature, because:
+ * GL_HALF_FLOAT = 0x140B
+ * GL_HALF_FLOAT_ARB = 0x140B == GL_HALF_FLOAT
+ * GL_HALF_FLOAT_NV = 0x140B == GL_HALF_FLOAT
+ * GL_HALF_FLOAT_OES = 0x8D61 != GL_HALF_FLOAT
+ * WebGL handles this specifically with an OES_texture_half_float check.
+ */
+ },
+ {
+ "texture_half_float_linear",
+ GLVersion::GL3_1,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::ARB_half_float_pixel,
+ GLContext::ARB_texture_float,
+ GLContext::NV_half_float,
+ GLContext::OES_texture_half_float_linear,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "texture_non_power_of_two",
+ GLVersion::GL2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::ARB_texture_non_power_of_two,
+ GLContext::OES_texture_npot,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "texture_rg",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::ARB_texture_rg,
+ {
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "texture_storage",
+ GLVersion::GL4_2,
+ GLESVersion::ES3,
+ GLContext::ARB_texture_storage,
+ {
+ /*
+ * Not including GL_EXT_texture_storage here because it
+ * doesn't guarantee glTexStorage3D, which is required for
+ * WebGL 2.
+ */
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "texture_swizzle",
+ GLVersion::GL3_3,
+ GLESVersion::ES3,
+ GLContext::ARB_texture_swizzle,
+ {
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "transform_feedback2",
+ GLVersion::GL4,
+ GLESVersion::ES3,
+ GLContext::ARB_transform_feedback2,
+ {
+ GLContext::NV_transform_feedback2,
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "uniform_buffer_object",
+ GLVersion::GL3_1,
+ GLESVersion::ES3,
+ GLContext::ARB_uniform_buffer_object,
+ {
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "uniform_matrix_nonsquare",
+ GLVersion::GL2_1,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {
+ GLContext::Extensions_End
+ }
+ },
+ {
+ "vertex_array_object",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::ARB_vertex_array_object, // ARB extension
+ {
+ GLContext::OES_vertex_array_object,
+ GLContext::APPLE_vertex_array_object,
+ GLContext::Extensions_End
+ }
+ }
+};
+
+static inline const FeatureInfo&
+GetFeatureInfo(GLFeature feature)
+{
+ static_assert(MOZ_ARRAY_LENGTH(sFeatureInfoArr) == size_t(GLFeature::EnumMax),
+ "Mismatched lengths for sFeatureInfoInfos and GLFeature enums");
+
+ MOZ_ASSERT(feature < GLFeature::EnumMax,
+ "GLContext::GetFeatureInfoInfo : unknown <feature>");
+
+ return sFeatureInfoArr[size_t(feature)];
+}
+
+static inline uint32_t
+ProfileVersionForFeature(GLFeature feature, ContextProfile profile)
+{
+ MOZ_ASSERT(profile != ContextProfile::Unknown,
+ "GLContext::ProfileVersionForFeature : unknown <profile>");
+
+ const FeatureInfo& featureInfo = GetFeatureInfo(feature);
+
+ if (profile == ContextProfile::OpenGLES)
+ return (uint32_t)featureInfo.mOpenGLESVersion;
+
+ return (uint32_t)featureInfo.mOpenGLVersion;
+}
+
+bool
+IsFeaturePartOfProfileVersion(GLFeature feature,
+ ContextProfile profile, unsigned int version)
+{
+ unsigned int profileVersion = ProfileVersionForFeature(feature, profile);
+
+ /**
+ * if `profileVersion` is zero, it means that no version of the profile
+ * added support for the feature.
+ */
+ return profileVersion && version >= profileVersion;
+}
+
+bool
+GLContext::IsFeatureProvidedByCoreSymbols(GLFeature feature)
+{
+ if (IsFeaturePartOfProfileVersion(feature, mProfile, mVersion))
+ return true;
+
+ if (IsExtensionSupported(GetFeatureInfo(feature).mARBExtensionWithoutARBSuffix))
+ return true;
+
+ return false;
+}
+
+const char*
+GLContext::GetFeatureName(GLFeature feature)
+{
+ return GetFeatureInfo(feature).mName;
+}
+
+void
+GLContext::InitFeatures()
+{
+ for (size_t featureId = 0; featureId < size_t(GLFeature::EnumMax); featureId++) {
+ GLFeature feature = GLFeature(featureId);
+
+ if (IsFeaturePartOfProfileVersion(feature, mProfile, mVersion)) {
+ mAvailableFeatures[featureId] = true;
+ continue;
+ }
+
+ mAvailableFeatures[featureId] = false;
+
+ const FeatureInfo& featureInfo = GetFeatureInfo(feature);
+
+ if (IsExtensionSupported(featureInfo.mARBExtensionWithoutARBSuffix)) {
+ mAvailableFeatures[featureId] = true;
+ continue;
+ }
+
+ for (size_t j = 0; true; j++) {
+ MOZ_ASSERT(j < kMAX_EXTENSION_GROUP_SIZE,
+ "kMAX_EXTENSION_GROUP_SIZE too small");
+
+ if (featureInfo.mExtensions[j] == GLContext::Extensions_End)
+ break;
+
+ if (IsExtensionSupported(featureInfo.mExtensions[j])) {
+ mAvailableFeatures[featureId] = true;
+ break;
+ }
+ }
+ }
+
+ if (ShouldDumpExts()) {
+ for (size_t featureId = 0; featureId < size_t(GLFeature::EnumMax); featureId++) {
+ GLFeature feature = GLFeature(featureId);
+ printf_stderr("[%s] Feature::%s\n",
+ IsSupported(feature) ? "enabled" : "disabled",
+ GetFeatureName(feature));
+ }
+ }
+}
+
+void
+GLContext::MarkUnsupported(GLFeature feature)
+{
+ mAvailableFeatures[size_t(feature)] = false;
+
+ const FeatureInfo& featureInfo = GetFeatureInfo(feature);
+
+ for (size_t i = 0; true; i++) {
+ MOZ_ASSERT(i < kMAX_EXTENSION_GROUP_SIZE, "kMAX_EXTENSION_GROUP_SIZE too small");
+
+ if (featureInfo.mExtensions[i] == GLContext::Extensions_End)
+ break;
+
+ MarkExtensionUnsupported(featureInfo.mExtensions[i]);
+ }
+
+ MOZ_ASSERT(!IsSupported(feature), "GLContext::MarkUnsupported has failed!");
+
+ NS_WARNING(nsPrintfCString("%s marked as unsupported",
+ GetFeatureName(feature)).get());
+}
+
+} /* namespace gl */
+} /* namespace mozilla */