1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsPrintfCString.h"
12 const size_t kMAX_EXTENSION_GROUP_SIZE
= 5;
14 enum class GLVersion
: uint32_t {
15 NONE
= 0, // Feature is not supported natively by GL
30 enum class GLESVersion
: uint32_t {
31 NONE
= 0, // Feature is not support natively by GL ES
38 // ARB_ES2_compatibility is natively supported in OpenGL 4.1.
39 static const GLVersion kGLCoreVersionForES2Compat
= GLVersion::GL4_1
;
41 // ARB_ES3_compatibility is natively supported in OpenGL 4.3.
42 static const GLVersion kGLCoreVersionForES3Compat
= GLVersion::GL4_3
;
47 /* The (desktop) OpenGL version that provides this feature */
48 GLVersion mOpenGLVersion
;
50 /* The OpenGL ES version that provides this feature */
51 GLESVersion mOpenGLESVersion
;
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.
61 * If there is no such ARB extension, pass 0 (GLContext::Extension_None)
63 GLContext::GLExtensions mARBExtensionWithoutARBSuffix
;
65 /* Extensions that also provide this feature */
66 GLContext::GLExtensions mExtensions
[kMAX_EXTENSION_GROUP_SIZE
];
69 static const FeatureInfo sFeatureInfoArr
[] = {
70 {"bind_buffer_offset",
73 GLContext::Extension_None
,
76 GLContext::EXT_transform_feedback
, GLContext::NV_transform_feedback2
,
77 GLContext::Extensions_End
}},
81 GLContext::Extension_None
,
82 {GLContext::EXT_blend_minmax
, GLContext::Extensions_End
}},
86 GLContext::Extension_None
,
87 {GLContext::Extensions_End
}},
91 GLContext::ARB_copy_buffer
,
92 {GLContext::Extensions_End
}},
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
}},
104 GLContext::Extension_None
,
105 {GLContext::ARB_draw_buffers
, GLContext::EXT_draw_buffers
,
106 GLContext::Extensions_End
}},
107 {"draw_buffers_indexed",
110 GLContext::Extension_None
,
111 {GLContext::OES_draw_buffers_indexed
, GLContext::Extensions_End
}},
115 GLContext::Extension_None
,
116 {GLContext::ARB_draw_instanced
, GLContext::EXT_draw_instanced
,
117 GLContext::NV_draw_instanced
, GLContext::ANGLE_instanced_arrays
,
118 GLContext::Extensions_End
}},
119 {"element_index_uint",
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",
137 GLContext::Extension_None
,
138 {GLContext::EXT_color_buffer_float
, GLContext::Extensions_End
}},
139 {// Removes clamping for float color outputs from frag shaders.
143 GLContext::Extension_None
,
144 {GLContext::ARB_color_buffer_float
, GLContext::EXT_color_buffer_float
,
145 GLContext::EXT_color_buffer_half_float
,
146 GLContext::CHROMIUM_color_buffer_float_rgba
, GLContext::Extensions_End
}},
150 GLContext::Extension_None
,
151 {GLContext::EXT_frag_depth
, GLContext::Extensions_End
}},
152 {// Check for just the blit framebuffer blit part of
153 // ARB_framebuffer_object
157 GLContext::ARB_framebuffer_object
,
158 {GLContext::ANGLE_framebuffer_blit
, GLContext::EXT_framebuffer_blit
,
159 GLContext::NV_framebuffer_blit
, GLContext::Extensions_End
}},
160 {// Check for just the multisample renderbuffer part of
161 // ARB_framebuffer_object
162 "framebuffer_multisample",
165 GLContext::ARB_framebuffer_object
,
166 {GLContext::ANGLE_framebuffer_multisample
,
167 GLContext::APPLE_framebuffer_multisample
,
168 GLContext::EXT_framebuffer_multisample
,
169 GLContext::EXT_multisampled_render_to_texture
,
170 GLContext::Extensions_End
}},
171 {// ARB_framebuffer_object support
172 "framebuffer_object",
175 GLContext::ARB_framebuffer_object
,
176 {GLContext::Extensions_End
}},
177 {// EXT_framebuffer_object/OES_framebuffer_object support
178 "framebuffer_object_EXT_OES",
181 GLContext::Extension_None
,
182 {GLContext::EXT_framebuffer_object
, GLContext::OES_framebuffer_object
,
183 GLContext::Extensions_End
}},
184 {"get_integer_indexed",
187 GLContext::Extension_None
,
188 {GLContext::EXT_draw_buffers2
, GLContext::Extensions_End
}},
189 {"get_integer64_indexed",
192 GLContext::Extension_None
,
193 {GLContext::Extensions_End
}},
194 {"get_query_object_i64v",
197 GLContext::ARB_timer_query
,
198 {GLContext::ANGLE_timer_query
, GLContext::EXT_disjoint_timer_query
,
199 GLContext::EXT_timer_query
, GLContext::Extensions_End
}},
201 "get_query_object_iv",
204 GLContext::Extension_None
,
205 {GLContext::Extensions_End
}
207 * XXX_get_query_object_iv only provide GetQueryObjectiv provided by
208 * ARB_occlusion_query (added by OpenGL 2.0).
214 GLContext::Extension_None
,
215 {GLContext::EXT_gpu_shader4
, GLContext::Extensions_End
}},
219 GLContext::Extension_None
,
220 {GLContext::ARB_instanced_arrays
, GLContext::NV_instanced_arrays
,
221 GLContext::ANGLE_instanced_arrays
, GLContext::Extensions_End
}},
223 "instanced_non_arrays",
226 GLContext::Extension_None
,
227 {GLContext::ARB_instanced_arrays
, GLContext::Extensions_End
}
228 /* This is an expanded version of `instanced_arrays` that allows for all
229 * enabled active attrib arrays to have non-zero divisors.
230 * ANGLE_instanced_arrays and NV_instanced_arrays forbid this, but GLES3
231 * has no such restriction.
234 {"internalformat_query",
237 GLContext::ARB_internalformat_query
,
238 {GLContext::Extensions_End
}},
239 {"invalidate_framebuffer",
242 GLContext::ARB_invalidate_subdata
,
243 {GLContext::Extensions_End
}},
247 GLContext::ARB_map_buffer_range
,
248 {GLContext::EXT_map_buffer_range
, GLContext::Extensions_End
}},
252 GLContext::Extension_None
,
253 {GLContext::ANGLE_multiview
, GLContext::OVR_multiview2
,
254 GLContext::Extensions_End
}},
259 GLContext::Extension_None
,
260 {GLContext::Extensions_End
}
261 // XXX_occlusion_query depend on ARB_occlusion_query (added in
265 "occlusion_query_boolean",
266 kGLCoreVersionForES3Compat
,
268 GLContext::ARB_ES3_compatibility
,
269 {GLContext::EXT_occlusion_query_boolean
, GLContext::Extensions_End
}
271 * XXX_occlusion_query_boolean provide ANY_SAMPLES_PASSED_CONSERVATIVE,
272 * but EXT_occlusion_query_boolean is only a OpenGL ES extension. But
273 * it is supported on desktop if ARB_ES3_compatibility because
274 * EXT_occlusion_query_boolean (added in OpenGL ES 3.0).
281 GLContext::Extension_None
,
282 {GLContext::ARB_occlusion_query2
, GLContext::ARB_ES3_compatibility
,
283 GLContext::EXT_occlusion_query_boolean
, GLContext::Extensions_End
}
285 * XXX_occlusion_query2 (add in OpenGL 3.3) provide ANY_SAMPLES_PASSED,
286 * which is provided by ARB_occlusion_query2,
287 * EXT_occlusion_query_boolean (added in OpenGL ES 3.0) and
288 * ARB_ES3_compatibility
291 {"packed_depth_stencil",
294 GLContext::Extension_None
,
295 {GLContext::EXT_packed_depth_stencil
, GLContext::OES_packed_depth_stencil
,
296 GLContext::Extensions_End
}},
300 GLContext::Extension_None
,
301 {// GLContext::NV_primitive_restart, // Has different enum values.
302 GLContext::Extensions_End
}},
303 {"prim_restart_fixed",
304 kGLCoreVersionForES3Compat
,
306 GLContext::ARB_ES3_compatibility
,
307 {GLContext::Extensions_End
}},
311 GLContext::ARB_provoking_vertex
,
312 {GLContext::ANGLE_provoking_vertex
, GLContext::EXT_provoking_vertex
,
313 GLContext::Extensions_End
}},
317 GLContext::ARB_timer_query
,
318 {GLContext::ANGLE_timer_query
, GLContext::EXT_disjoint_timer_query
,
319 // EXT_timer_query does NOT support GL_TIMESTAMP retrieval with
321 GLContext::Extensions_End
}},
326 GLContext::Extension_None
,
327 {GLContext::ANGLE_timer_query
, GLContext::EXT_disjoint_timer_query
,
328 GLContext::EXT_occlusion_query_boolean
, GLContext::Extensions_End
}
330 * XXX_query_objects only provide entry points commonly supported by
331 * ARB_occlusion_query (added in OpenGL 2.0),
332 * EXT_occlusion_query_boolean (added in OpenGL ES 3.0), and
333 * ARB_timer_query (added in OpenGL 3.3)
336 {"query_time_elapsed",
339 GLContext::ARB_timer_query
,
340 {GLContext::ANGLE_timer_query
, GLContext::EXT_disjoint_timer_query
,
341 GLContext::EXT_timer_query
, GLContext::Extensions_End
}},
345 GLContext::Extension_None
,
346 {GLContext::Extensions_End
}},
347 {"renderbuffer_color_float",
350 GLContext::Extension_None
,
351 {GLContext::ARB_texture_float
, GLContext::EXT_color_buffer_float
,
352 GLContext::CHROMIUM_color_buffer_float_rgba
, GLContext::Extensions_End
}},
353 {"renderbuffer_color_half_float",
356 GLContext::Extension_None
,
357 {GLContext::ARB_texture_float
, GLContext::EXT_color_buffer_float
,
358 GLContext::EXT_color_buffer_half_float
, GLContext::Extensions_End
}},
359 {"robust_buffer_access_behavior",
362 GLContext::Extension_None
,
363 {GLContext::ARB_robust_buffer_access_behavior
,
364 GLContext::KHR_robust_buffer_access_behavior
, GLContext::Extensions_End
}},
368 GLContext::Extension_None
,
369 {GLContext::ARB_robustness
, GLContext::EXT_robustness
,
370 GLContext::KHR_robustness
, GLContext::Extensions_End
}},
374 GLContext::ARB_framebuffer_sRGB
,
375 {GLContext::EXT_sRGB
, GLContext::EXT_framebuffer_sRGB
,
376 GLContext::Extensions_End
}},
380 GLContext::ARB_sampler_objects
,
381 {GLContext::Extensions_End
}},
382 {"seamless_cube_map_opt_in",
385 GLContext::ARB_seamless_cube_map
,
386 {GLContext::Extensions_End
}},
387 {"shader_texture_lod",
390 GLContext::Extension_None
,
391 {GLContext::ARB_shader_texture_lod
, GLContext::EXT_shader_texture_lod
,
392 GLContext::Extensions_End
}},
393 {// Do we have separate DRAW and READ framebuffer bind points?
397 GLContext::ARB_framebuffer_object
,
398 {GLContext::ANGLE_framebuffer_blit
,
399 GLContext::APPLE_framebuffer_multisample
, GLContext::EXT_framebuffer_blit
,
400 GLContext::NV_framebuffer_blit
, GLContext::Extensions_End
}},
401 {"standard_derivatives",
404 GLContext::Extension_None
,
405 {GLContext::OES_standard_derivatives
, GLContext::Extensions_End
}},
409 GLContext::Extension_None
,
410 {GLContext::ARB_sync
, GLContext::APPLE_sync
, GLContext::Extensions_End
}},
414 GLContext::Extension_None
,
415 {GLContext::OES_texture_3D
, GLContext::Extensions_End
}},
416 {"texture_3D_compressed",
419 GLContext::Extension_None
,
420 {GLContext::ARB_texture_compression
, GLContext::OES_texture_3D
,
421 GLContext::Extensions_End
}},
425 GLContext::Extension_None
,
426 {GLContext::EXT_copy_texture
, GLContext::OES_texture_3D
,
427 GLContext::Extensions_End
}},
428 {"texture_compression_bptc",
431 GLContext::Extension_None
,
432 {GLContext::ARB_texture_compression_bptc
,
433 GLContext::EXT_texture_compression_bptc
, GLContext::Extensions_End
}},
434 {"texture_compression_rgtc",
437 GLContext::Extension_None
,
438 {GLContext::ARB_texture_compression_rgtc
,
439 GLContext::EXT_texture_compression_rgtc
, GLContext::Extensions_End
}},
443 GLContext::Extension_None
,
444 {GLContext::ARB_texture_float
, GLContext::OES_texture_float
,
445 GLContext::Extensions_End
}},
446 {"texture_float_linear",
449 GLContext::Extension_None
,
450 {GLContext::ARB_texture_float
, GLContext::OES_texture_float_linear
,
451 GLContext::Extensions_End
}},
453 "texture_half_float",
456 GLContext::Extension_None
,
457 {GLContext::ARB_half_float_pixel
, GLContext::ARB_texture_float
,
458 GLContext::NV_half_float
, GLContext::Extensions_End
}
460 * We are not including OES_texture_half_float in this feature, because:
461 * GL_HALF_FLOAT = 0x140B
462 * GL_HALF_FLOAT_ARB = 0x140B == GL_HALF_FLOAT
463 * GL_HALF_FLOAT_NV = 0x140B == GL_HALF_FLOAT
464 * GL_HALF_FLOAT_OES = 0x8D61 != GL_HALF_FLOAT
465 * WebGL handles this specifically with an OES_texture_half_float check.
468 {"texture_half_float_linear",
471 GLContext::Extension_None
,
472 {GLContext::ARB_half_float_pixel
, GLContext::ARB_texture_float
,
473 GLContext::NV_half_float
, GLContext::OES_texture_half_float_linear
,
474 GLContext::Extensions_End
}},
475 {"texture_non_power_of_two",
478 GLContext::Extension_None
,
479 {GLContext::ARB_texture_non_power_of_two
, GLContext::OES_texture_npot
,
480 GLContext::Extensions_End
}},
484 GLContext::EXT_texture_norm16
,
485 {GLContext::Extensions_End
}},
489 GLContext::ARB_texture_rg
,
490 {GLContext::Extensions_End
}},
494 GLContext::ARB_texture_storage
,
496 * Not including GL_EXT_texture_storage here because it
497 * doesn't guarantee glTexStorage3D, which is required for
500 GLContext::Extensions_End
}},
504 GLContext::ARB_texture_swizzle
,
505 {GLContext::Extensions_End
}},
506 {"transform_feedback2",
509 GLContext::ARB_transform_feedback2
,
510 {GLContext::NV_transform_feedback2
, GLContext::Extensions_End
}},
511 {"uniform_buffer_object",
514 GLContext::ARB_uniform_buffer_object
,
515 {GLContext::Extensions_End
}},
516 {"uniform_matrix_nonsquare",
519 GLContext::Extension_None
,
520 {GLContext::Extensions_End
}},
521 {"vertex_array_object",
524 GLContext::ARB_vertex_array_object
, // ARB extension
525 {GLContext::OES_vertex_array_object
, GLContext::APPLE_vertex_array_object
,
526 GLContext::Extensions_End
}}};
528 static inline const FeatureInfo
& GetFeatureInfo(GLFeature feature
) {
529 static_assert(MOZ_ARRAY_LENGTH(sFeatureInfoArr
) == size_t(GLFeature::EnumMax
),
530 "Mismatched lengths for sFeatureInfoInfos and GLFeature enums");
532 MOZ_ASSERT(feature
< GLFeature::EnumMax
,
533 "GLContext::GetFeatureInfoInfo : unknown <feature>");
535 return sFeatureInfoArr
[size_t(feature
)];
538 static inline uint32_t ProfileVersionForFeature(GLFeature feature
,
539 ContextProfile profile
) {
540 MOZ_ASSERT(profile
!= ContextProfile::Unknown
,
541 "GLContext::ProfileVersionForFeature : unknown <profile>");
543 const FeatureInfo
& featureInfo
= GetFeatureInfo(feature
);
545 if (profile
== ContextProfile::OpenGLES
)
546 return (uint32_t)featureInfo
.mOpenGLESVersion
;
548 return (uint32_t)featureInfo
.mOpenGLVersion
;
551 static bool IsFeaturePartOfProfileVersion(GLFeature feature
,
552 ContextProfile profile
,
553 unsigned int version
) {
554 unsigned int profileVersion
= ProfileVersionForFeature(feature
, profile
);
557 * if `profileVersion` is zero, it means that no version of the profile
558 * added support for the feature.
560 return profileVersion
&& version
>= profileVersion
;
563 bool GLContext::IsFeatureProvidedByCoreSymbols(GLFeature feature
) {
564 if (IsFeaturePartOfProfileVersion(feature
, mProfile
, mVersion
)) return true;
566 if (IsExtensionSupported(
567 GetFeatureInfo(feature
).mARBExtensionWithoutARBSuffix
))
573 const char* GLContext::GetFeatureName(GLFeature feature
) {
574 return GetFeatureInfo(feature
).mName
;
577 void GLContext::InitFeatures() {
578 for (size_t featureId
= 0; featureId
< size_t(GLFeature::EnumMax
);
580 GLFeature feature
= GLFeature(featureId
);
582 if (IsFeaturePartOfProfileVersion(feature
, mProfile
, mVersion
)) {
583 mAvailableFeatures
[featureId
] = true;
587 mAvailableFeatures
[featureId
] = false;
589 const FeatureInfo
& featureInfo
= GetFeatureInfo(feature
);
591 if (IsExtensionSupported(featureInfo
.mARBExtensionWithoutARBSuffix
)) {
592 mAvailableFeatures
[featureId
] = true;
596 for (size_t j
= 0; true; j
++) {
597 MOZ_ASSERT(j
< kMAX_EXTENSION_GROUP_SIZE
,
598 "kMAX_EXTENSION_GROUP_SIZE too small");
600 if (featureInfo
.mExtensions
[j
] == GLContext::Extensions_End
) break;
602 if (IsExtensionSupported(featureInfo
.mExtensions
[j
])) {
603 mAvailableFeatures
[featureId
] = true;
609 if (ShouldDumpExts()) {
610 for (size_t featureId
= 0; featureId
< size_t(GLFeature::EnumMax
);
612 GLFeature feature
= GLFeature(featureId
);
613 printf_stderr("[%s] Feature::%s\n",
614 IsSupported(feature
) ? "enabled" : "disabled",
615 GetFeatureName(feature
));
620 void GLContext::MarkUnsupported(GLFeature feature
) {
621 mAvailableFeatures
[size_t(feature
)] = false;
623 const FeatureInfo
& featureInfo
= GetFeatureInfo(feature
);
625 for (size_t i
= 0; true; i
++) {
626 MOZ_ASSERT(i
< kMAX_EXTENSION_GROUP_SIZE
,
627 "kMAX_EXTENSION_GROUP_SIZE too small");
629 if (featureInfo
.mExtensions
[i
] == GLContext::Extensions_End
) break;
631 MarkExtensionUnsupported(featureInfo
.mExtensions
[i
]);
634 MOZ_ASSERT(!IsSupported(feature
), "GLContext::MarkUnsupported has failed!");
637 nsPrintfCString("%s marked as unsupported", GetFeatureName(feature
))
642 } /* namespace mozilla */