1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/gl/GLContextFeatures.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,540 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 + 1.10 +#include "GLContext.h" 1.11 +#include "nsPrintfCString.h" 1.12 + 1.13 +#ifdef XP_MACOSX 1.14 +#include "nsCocoaFeatures.h" 1.15 +#endif 1.16 + 1.17 +namespace mozilla { 1.18 +namespace gl { 1.19 + 1.20 +const size_t kMAX_EXTENSION_GROUP_SIZE = 5; 1.21 + 1.22 +// ARB_ES2_compatibility is natively supported in OpenGL 4.1. 1.23 +static const unsigned int kGLCoreVersionForES2Compat = 410; 1.24 + 1.25 +// ARB_ES3_compatibility is natively supported in OpenGL 4.3. 1.26 +static const unsigned int kGLCoreVersionForES3Compat = 430; 1.27 + 1.28 +struct FeatureInfo 1.29 +{ 1.30 + const char* mName; 1.31 + unsigned int mOpenGLVersion; 1.32 + unsigned int mOpenGLESVersion; 1.33 + GLContext::GLExtensions mExtensions[kMAX_EXTENSION_GROUP_SIZE]; 1.34 +}; 1.35 + 1.36 +static const FeatureInfo sFeatureInfoArr[] = { 1.37 + { 1.38 + "bind_buffer_offset", 1.39 + 0, // OpenGL version 1.40 + 0, // OpenGL ES version 1.41 + { 1.42 + GLContext::EXT_transform_feedback, 1.43 + GLContext::NV_transform_feedback, 1.44 + GLContext::Extensions_End 1.45 + } 1.46 + }, 1.47 + { 1.48 + "blend_minmax", 1.49 + 200, // OpenGL version 1.50 + 300, // OpenGL ES version 1.51 + { 1.52 + GLContext::EXT_blend_minmax, 1.53 + GLContext::Extensions_End 1.54 + } 1.55 + }, 1.56 + { 1.57 + "depth_texture", 1.58 + 200, // OpenGL version 1.59 + 300, // OpenGL ES version 1.60 + { 1.61 + GLContext::ARB_depth_texture, 1.62 + GLContext::OES_depth_texture, 1.63 + // Intentionally avoid putting ANGLE_depth_texture here, 1.64 + // it does not offer quite the same functionality. 1.65 + GLContext::Extensions_End 1.66 + } 1.67 + }, 1.68 + { 1.69 + "draw_buffers", 1.70 + 200, // OpenGL version 1.71 + 300, // OpenGL ES version 1.72 + { 1.73 + GLContext::ARB_draw_buffers, 1.74 + GLContext::EXT_draw_buffers, 1.75 + GLContext::Extensions_End 1.76 + } 1.77 + }, 1.78 + { 1.79 + "draw_instanced", 1.80 + 310, // OpenGL version 1.81 + 300, // OpenGL ES version 1.82 + { 1.83 + GLContext::ARB_draw_instanced, 1.84 + GLContext::EXT_draw_instanced, 1.85 + GLContext::NV_draw_instanced, 1.86 + GLContext::ANGLE_instanced_arrays, 1.87 + GLContext::Extensions_End 1.88 + } 1.89 + }, 1.90 + { 1.91 + "draw_range_elements", 1.92 + 120, // OpenGL version 1.93 + 300, // OpenGL ES version 1.94 + { 1.95 + GLContext::EXT_draw_range_elements, 1.96 + GLContext::Extensions_End 1.97 + } 1.98 + }, 1.99 + { 1.100 + "element_index_uint", 1.101 + 200, // OpenGL version 1.102 + 300, // OpenGL ES version 1.103 + { 1.104 + GLContext::OES_element_index_uint, 1.105 + GLContext::Extensions_End 1.106 + } 1.107 + }, 1.108 + { 1.109 + "ES2_compatibility", 1.110 + kGLCoreVersionForES2Compat, 1.111 + 200, // OpenGL ES version 1.112 + { 1.113 + GLContext::ARB_ES2_compatibility, 1.114 + GLContext::Extensions_End 1.115 + } 1.116 + }, 1.117 + { 1.118 + "ES3_compatibility", 1.119 + kGLCoreVersionForES3Compat, 1.120 + 300, // OpenGL ES version 1.121 + { 1.122 + GLContext::ARB_ES3_compatibility, 1.123 + GLContext::Extensions_End 1.124 + } 1.125 + }, 1.126 + { 1.127 + // Removes clamping for float color outputs from frag shaders. 1.128 + "frag_color_float", 1.129 + 300, // OpenGL version 1.130 + 300, // OpenGL ES version 1.131 + { 1.132 + GLContext::ARB_color_buffer_float, 1.133 + GLContext::EXT_color_buffer_float, 1.134 + GLContext::EXT_color_buffer_half_float, 1.135 + GLContext::Extensions_End 1.136 + } 1.137 + }, 1.138 + { 1.139 + "frag_depth", 1.140 + 200, // OpenGL version 1.141 + 300, // OpenGL ES version 1.142 + { 1.143 + GLContext::EXT_frag_depth, 1.144 + GLContext::Extensions_End 1.145 + } 1.146 + }, 1.147 + { 1.148 + "framebuffer_blit", 1.149 + 300, // OpenGL version 1.150 + 300, // OpenGL ES version 1.151 + { 1.152 + GLContext::EXT_framebuffer_blit, 1.153 + GLContext::ANGLE_framebuffer_blit, 1.154 + GLContext::Extensions_End 1.155 + } 1.156 + }, 1.157 + { 1.158 + "framebuffer_multisample", 1.159 + 300, // OpenGL version 1.160 + 300, // OpenGL ES version 1.161 + { 1.162 + GLContext::EXT_framebuffer_multisample, 1.163 + GLContext::ANGLE_framebuffer_multisample, 1.164 + GLContext::Extensions_End 1.165 + } 1.166 + }, 1.167 + { 1.168 + "framebuffer_object", 1.169 + 300, // OpenGL version 1.170 + 200, // OpenGL ES version 1.171 + { 1.172 + GLContext::ARB_framebuffer_object, 1.173 + GLContext::EXT_framebuffer_object, 1.174 + GLContext::Extensions_End 1.175 + } 1.176 + }, 1.177 + { 1.178 + "get_query_object_iv", 1.179 + 200, // OpenGL version 1.180 + 0, // OpenGL ES version 1.181 + { 1.182 + GLContext::Extensions_End 1.183 + } 1.184 + /* 1.185 + * XXX_get_query_object_iv only provide GetQueryObjectiv provided by 1.186 + * ARB_occlusion_query (added by OpenGL 2.0). 1.187 + */ 1.188 + }, 1.189 + { 1.190 + "instanced_arrays", 1.191 + 330, // OpenGL version 1.192 + 300, // OpenGL ES version 1.193 + { 1.194 + GLContext::ARB_instanced_arrays, 1.195 + GLContext::NV_instanced_arrays, 1.196 + GLContext::ANGLE_instanced_arrays, 1.197 + GLContext::Extensions_End 1.198 + } 1.199 + }, 1.200 + { 1.201 + "instanced_non_arrays", 1.202 + 330, // OpenGL version 1.203 + 300, // OpenGL ES version 1.204 + { 1.205 + GLContext::ARB_instanced_arrays, 1.206 + GLContext::Extensions_End 1.207 + } 1.208 + /* This is an expanded version of `instanced_arrays` that allows for all 1.209 + * enabled active attrib arrays to have non-zero divisors. 1.210 + * ANGLE_instanced_arrays and NV_instanced_arrays forbid this, but GLES3 1.211 + * has no such restriction. 1.212 + */ 1.213 + }, 1.214 + { 1.215 + "occlusion_query", 1.216 + 200, // OpenGL version 1.217 + 0, // OpenGL ES version 1.218 + { 1.219 + GLContext::Extensions_End 1.220 + } 1.221 + // XXX_occlusion_query depend on ARB_occlusion_query (added in OpenGL 2.0) 1.222 + }, 1.223 + { 1.224 + "occlusion_query_boolean", 1.225 + kGLCoreVersionForES3Compat, 1.226 + 300, // OpenGL ES version 1.227 + { 1.228 + GLContext::ARB_ES3_compatibility, 1.229 + GLContext::EXT_occlusion_query_boolean, 1.230 + GLContext::Extensions_End 1.231 + } 1.232 + /* 1.233 + * XXX_occlusion_query_boolean provide ANY_SAMPLES_PASSED_CONSERVATIVE, 1.234 + * but EXT_occlusion_query_boolean is only a OpenGL ES extension. But 1.235 + * it is supported on desktop if ARB_ES3_compatibility because 1.236 + * EXT_occlusion_query_boolean (added in OpenGL ES 3.0). 1.237 + */ 1.238 + }, 1.239 + { 1.240 + "occlusion_query2", 1.241 + 330, // = min(330, kGLCoreVersionForES3Compat), 1.242 + 300, // OpenGL ES version 1.243 + { 1.244 + GLContext::ARB_occlusion_query2, 1.245 + GLContext::ARB_ES3_compatibility, 1.246 + GLContext::EXT_occlusion_query_boolean, 1.247 + GLContext::Extensions_End 1.248 + } 1.249 + /* 1.250 + * XXX_occlusion_query2 (add in OpenGL 3.3) provide ANY_SAMPLES_PASSED, 1.251 + * which is provided by ARB_occlusion_query2, EXT_occlusion_query_boolean 1.252 + * (added in OpenGL ES 3.0) and ARB_ES3_compatibility 1.253 + */ 1.254 + }, 1.255 + { 1.256 + "packed_depth_stencil", 1.257 + 300, // OpenGL version 1.258 + 300, // OpenGL ES version 1.259 + { 1.260 + GLContext::EXT_packed_depth_stencil, 1.261 + GLContext::OES_packed_depth_stencil, 1.262 + GLContext::Extensions_End 1.263 + } 1.264 + }, 1.265 + { 1.266 + "query_objects", 1.267 + 200, // OpenGL version 1.268 + 300, // OpenGL ES version 1.269 + { 1.270 + GLContext::EXT_occlusion_query_boolean, 1.271 + GLContext::Extensions_End 1.272 + } 1.273 + /* 1.274 + * XXX_query_objects only provide entry points commonly supported by 1.275 + * ARB_occlusion_query (added in OpenGL 2.0) and EXT_occlusion_query_boolean 1.276 + * (added in OpenGL ES 3.0) 1.277 + */ 1.278 + }, 1.279 + { 1.280 + "renderbuffer_float", 1.281 + 300, // OpenGL version 1.282 + 300, // OpenGL ES version 1.283 + { 1.284 + GLContext::ARB_texture_float, 1.285 + GLContext::EXT_color_buffer_float, 1.286 + GLContext::Extensions_End 1.287 + } 1.288 + }, 1.289 + { 1.290 + "renderbuffer_half_float", 1.291 + 300, // OpenGL version 1.292 + 300, // OpenGL ES version 1.293 + { 1.294 + GLContext::ARB_texture_float, 1.295 + GLContext::EXT_color_buffer_half_float, 1.296 + GLContext::Extensions_End 1.297 + } 1.298 + }, 1.299 + { 1.300 + "robustness", 1.301 + 0, // OpenGL version 1.302 + 0, // OpenGL ES version 1.303 + { 1.304 + GLContext::ARB_robustness, 1.305 + GLContext::EXT_robustness, 1.306 + GLContext::Extensions_End 1.307 + } 1.308 + }, 1.309 + { 1.310 + "sRGB", 1.311 + 300, // OpenGL version 1.312 + 300, // OpenGL ES version 1.313 + { 1.314 + GLContext::EXT_sRGB, 1.315 + GLContext::Extensions_End 1.316 + } 1.317 + }, 1.318 + { 1.319 + "standard_derivatives", 1.320 + 200, // OpenGL version 1.321 + 300, // OpenGL ES version 1.322 + { 1.323 + GLContext::OES_standard_derivatives, 1.324 + GLContext::Extensions_End 1.325 + } 1.326 + }, 1.327 + { 1.328 + "texture_float", 1.329 + 300, // OpenGL version 1.330 + 300, // OpenGL ES version 1.331 + { 1.332 + GLContext::ARB_texture_float, 1.333 + GLContext::OES_texture_float, 1.334 + GLContext::Extensions_End 1.335 + } 1.336 + }, 1.337 + { 1.338 + "texture_float_linear", 1.339 + 310, // OpenGL version 1.340 + 300, // OpenGL ES version 1.341 + { 1.342 + GLContext::ARB_texture_float, 1.343 + GLContext::OES_texture_float_linear, 1.344 + GLContext::Extensions_End 1.345 + } 1.346 + }, 1.347 + { 1.348 + "texture_half_float", 1.349 + 300, // OpenGL version 1.350 + 300, // OpenGL ES version 1.351 + { 1.352 + GLContext::ARB_half_float_pixel, 1.353 + GLContext::ARB_texture_float, 1.354 + GLContext::NV_half_float, 1.355 + GLContext::Extensions_End 1.356 + } 1.357 + /** 1.358 + * We are not including OES_texture_half_float in this feature, because: 1.359 + * GL_HALF_FLOAT = 0x140B 1.360 + * GL_HALF_FLOAT_ARB = 0x140B == GL_HALF_FLOAT 1.361 + * GL_HALF_FLOAT_NV = 0x140B == GL_HALF_FLOAT 1.362 + * GL_HALF_FLOAT_OES = 0x8D61 != GL_HALF_FLOAT 1.363 + * WebGL handles this specifically with an OES_texture_half_float check. 1.364 + */ 1.365 + }, 1.366 + { 1.367 + "texture_half_float_linear", 1.368 + 310, // OpenGL version 1.369 + 300, // OpenGL ES version 1.370 + { 1.371 + GLContext::ARB_half_float_pixel, 1.372 + GLContext::ARB_texture_float, 1.373 + GLContext::NV_half_float, 1.374 + GLContext::OES_texture_half_float_linear, 1.375 + GLContext::Extensions_End 1.376 + } 1.377 + }, 1.378 + { 1.379 + "texture_non_power_of_two", 1.380 + 200, // OpenGL version 1.381 + 300, // OpenGL ES version 1.382 + { 1.383 + GLContext::ARB_texture_non_power_of_two, 1.384 + GLContext::OES_texture_npot, 1.385 + GLContext::Extensions_End 1.386 + } 1.387 + }, 1.388 + { 1.389 + "transform_feedback", 1.390 + 300, // OpenGL version 1.391 + 300, // OpenGL ES version 1.392 + { 1.393 + GLContext::EXT_transform_feedback, 1.394 + GLContext::NV_transform_feedback, 1.395 + GLContext::Extensions_End 1.396 + } 1.397 + }, 1.398 + { 1.399 + "vertex_array_object", 1.400 + 300, // OpenGL version 1.401 + 300, // OpenGL ES version 1.402 + { 1.403 + GLContext::ARB_vertex_array_object, 1.404 + GLContext::OES_vertex_array_object, 1.405 + GLContext::APPLE_vertex_array_object, 1.406 + GLContext::Extensions_End 1.407 + } 1.408 + } 1.409 +}; 1.410 + 1.411 +static inline const FeatureInfo& 1.412 +GetFeatureInfo(GLFeature feature) 1.413 +{ 1.414 + static_assert(MOZ_ARRAY_LENGTH(sFeatureInfoArr) == size_t(GLFeature::EnumMax), 1.415 + "Mismatched lengths for sFeatureInfoInfos and GLFeature enums"); 1.416 + 1.417 + MOZ_ASSERT(feature < GLFeature::EnumMax, 1.418 + "GLContext::GetFeatureInfoInfo : unknown <feature>"); 1.419 + 1.420 + return sFeatureInfoArr[size_t(feature)]; 1.421 +} 1.422 + 1.423 +static inline uint32_t 1.424 +ProfileVersionForFeature(GLFeature feature, ContextProfile profile) 1.425 +{ 1.426 + MOZ_ASSERT(profile != ContextProfile::Unknown, 1.427 + "GLContext::ProfileVersionForFeature : unknown <profile>"); 1.428 + 1.429 + const FeatureInfo& featureInfo = GetFeatureInfo(feature); 1.430 + 1.431 + if (profile == ContextProfile::OpenGLES) { 1.432 + return featureInfo.mOpenGLESVersion; 1.433 + } 1.434 + 1.435 + return featureInfo.mOpenGLVersion; 1.436 +} 1.437 + 1.438 +static inline bool 1.439 +IsFeatureIsPartOfProfileVersion(GLFeature feature, 1.440 + ContextProfile profile, unsigned int version) 1.441 +{ 1.442 + unsigned int profileVersion = ProfileVersionForFeature(feature, profile); 1.443 + 1.444 + /** 1.445 + * if `profileVersion` is zero, it means that no version of the profile 1.446 + * added support for the feature. 1.447 + */ 1.448 + return profileVersion && version >= profileVersion; 1.449 +} 1.450 + 1.451 +const char* 1.452 +GLContext::GetFeatureName(GLFeature feature) 1.453 +{ 1.454 + return GetFeatureInfo(feature).mName; 1.455 +} 1.456 + 1.457 +static bool 1.458 +CanReadSRGBFromFBOTexture(GLContext* gl) 1.459 +{ 1.460 + if (!gl->WorkAroundDriverBugs()) 1.461 + return true; 1.462 + 1.463 +#ifdef XP_MACOSX 1.464 + // Bug 843668: 1.465 + // MacOSX 10.6 reports to support EXT_framebuffer_sRGB and 1.466 + // EXT_texture_sRGB but fails to convert from sRGB to linear 1.467 + // when writing to an sRGB texture attached to an FBO. 1.468 + if (!nsCocoaFeatures::OnLionOrLater()) { 1.469 + return false; 1.470 + } 1.471 +#endif // XP_MACOSX 1.472 + return true; 1.473 +} 1.474 + 1.475 +void 1.476 +GLContext::InitFeatures() 1.477 +{ 1.478 + for (size_t feature_index = 0; feature_index < size_t(GLFeature::EnumMax); feature_index++) 1.479 + { 1.480 + GLFeature feature = GLFeature(feature_index); 1.481 + 1.482 + if (IsFeatureIsPartOfProfileVersion(feature, mProfile, mVersion)) { 1.483 + mAvailableFeatures[feature_index] = true; 1.484 + continue; 1.485 + } 1.486 + 1.487 + mAvailableFeatures[feature_index] = false; 1.488 + 1.489 + const FeatureInfo& featureInfo = GetFeatureInfo(feature); 1.490 + 1.491 + for (size_t j = 0; true; j++) 1.492 + { 1.493 + MOZ_ASSERT(j < kMAX_EXTENSION_GROUP_SIZE, "kMAX_EXTENSION_GROUP_SIZE too small"); 1.494 + 1.495 + if (featureInfo.mExtensions[j] == GLContext::Extensions_End) { 1.496 + break; 1.497 + } 1.498 + 1.499 + if (IsExtensionSupported(featureInfo.mExtensions[j])) { 1.500 + mAvailableFeatures[feature_index] = true; 1.501 + break; 1.502 + } 1.503 + } 1.504 + } 1.505 + 1.506 + // Bug 843668: Work around limitation of the feature system. 1.507 + // For sRGB support under OpenGL to match OpenGL ES spec, check for both 1.508 + // EXT_texture_sRGB and EXT_framebuffer_sRGB is required. 1.509 + const bool aresRGBExtensionsAvailable = 1.510 + IsExtensionSupported(EXT_texture_sRGB) && 1.511 + (IsExtensionSupported(ARB_framebuffer_sRGB) || 1.512 + IsExtensionSupported(EXT_framebuffer_sRGB)); 1.513 + 1.514 + mAvailableFeatures[size_t(GLFeature::sRGB)] = 1.515 + aresRGBExtensionsAvailable && 1.516 + CanReadSRGBFromFBOTexture(this); 1.517 +} 1.518 + 1.519 +void 1.520 +GLContext::MarkUnsupported(GLFeature feature) 1.521 +{ 1.522 + mAvailableFeatures[size_t(feature)] = false; 1.523 + 1.524 + const FeatureInfo& featureInfo = GetFeatureInfo(feature); 1.525 + 1.526 + for (size_t i = 0; true; i++) 1.527 + { 1.528 + MOZ_ASSERT(i < kMAX_EXTENSION_GROUP_SIZE, "kMAX_EXTENSION_GROUP_SIZE too small"); 1.529 + 1.530 + if (featureInfo.mExtensions[i] == GLContext::Extensions_End) { 1.531 + break; 1.532 + } 1.533 + 1.534 + MarkExtensionUnsupported(featureInfo.mExtensions[i]); 1.535 + } 1.536 + 1.537 + MOZ_ASSERT(!IsSupported(feature), "GLContext::MarkUnsupported has failed!"); 1.538 + 1.539 + NS_WARNING(nsPrintfCString("%s marked as unsupported", GetFeatureName(feature)).get()); 1.540 +} 1.541 + 1.542 +} /* namespace gl */ 1.543 +} /* namespace mozilla */