1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "gpu/command_buffer/service/feature_info.h" 6 7 #include <set> 8 9 #include "base/command_line.h" 10 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_split.h" 12 #include "base/strings/string_util.h" 13 #include "gpu/command_buffer/service/gl_utils.h" 14 #include "gpu/command_buffer/service/gpu_switches.h" 15 #include "ui/gl/gl_implementation.h" 16 17 #if defined(OS_MACOSX) 18 #include "ui/gl/io_surface_support_mac.h" 19 #endif 20 21 namespace gpu { 22 namespace gles2 { 23 24 namespace { 25 26 struct FormatInfo { 27 GLenum format; 28 const GLenum* types; 29 size_t count; 30 }; 31 32 class StringSet { 33 public: 34 StringSet() {} 35 36 StringSet(const char* s) { 37 Init(s); 38 } 39 40 StringSet(const std::string& str) { 41 Init(str); 42 } 43 44 void Init(const char* s) { 45 std::string str(s ? s : ""); 46 Init(str); 47 } 48 49 void Init(const std::string& str) { 50 std::vector<std::string> tokens; 51 Tokenize(str, " ", &tokens); 52 string_set_.insert(tokens.begin(), tokens.end()); 53 } 54 55 bool Contains(const char* s) { 56 return string_set_.find(s) != string_set_.end(); 57 } 58 59 bool Contains(const std::string& s) { 60 return string_set_.find(s) != string_set_.end(); 61 } 62 63 private: 64 std::set<std::string> string_set_; 65 }; 66 67 // Process a string of wordaround type IDs (seperated by ',') and set up 68 // the corresponding Workaround flags. 69 void StringToWorkarounds( 70 const std::string& types, FeatureInfo::Workarounds* workarounds) { 71 DCHECK(workarounds); 72 std::vector<std::string> pieces; 73 base::SplitString(types, ',', &pieces); 74 for (size_t i = 0; i < pieces.size(); ++i) { 75 int number = 0; 76 bool succeed = base::StringToInt(pieces[i], &number); 77 DCHECK(succeed); 78 switch (number) { 79 #define GPU_OP(type, name) \ 80 case gpu::type: \ 81 workarounds->name = true; \ 82 break; 83 GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP) 84 #undef GPU_OP 85 default: 86 NOTIMPLEMENTED(); 87 } 88 } 89 if (workarounds->max_texture_size_limit_4096) 90 workarounds->max_texture_size = 4096; 91 if (workarounds->max_cube_map_texture_size_limit_4096) 92 workarounds->max_cube_map_texture_size = 4096; 93 if (workarounds->max_cube_map_texture_size_limit_1024) 94 workarounds->max_cube_map_texture_size = 1024; 95 if (workarounds->max_cube_map_texture_size_limit_512) 96 workarounds->max_cube_map_texture_size = 512; 97 } 98 99 } // anonymous namespace. 100 101 FeatureInfo::FeatureFlags::FeatureFlags() 102 : chromium_framebuffer_multisample(false), 103 use_core_framebuffer_multisample(false), 104 multisampled_render_to_texture(false), 105 use_img_for_multisampled_render_to_texture(false), 106 oes_standard_derivatives(false), 107 oes_egl_image_external(false), 108 oes_depth24(false), 109 oes_compressed_etc1_rgb8_texture(false), 110 packed_depth24_stencil8(false), 111 npot_ok(false), 112 enable_texture_float_linear(false), 113 enable_texture_half_float_linear(false), 114 chromium_stream_texture(false), 115 angle_translated_shader_source(false), 116 angle_pack_reverse_row_order(false), 117 arb_texture_rectangle(false), 118 angle_instanced_arrays(false), 119 occlusion_query_boolean(false), 120 use_arb_occlusion_query2_for_occlusion_query_boolean(false), 121 use_arb_occlusion_query_for_occlusion_query_boolean(false), 122 native_vertex_array_object(false), 123 ext_texture_format_bgra8888(false), 124 enable_shader_name_hashing(false), 125 enable_samplers(false), 126 ext_draw_buffers(false), 127 ext_frag_depth(false), 128 use_async_readpixels(false), 129 map_buffer_range(false), 130 ext_discard_framebuffer(false), 131 angle_depth_texture(false), 132 is_angle(false), 133 is_swiftshader(false), 134 angle_texture_usage(false), 135 ext_texture_storage(false) { 136 } 137 138 FeatureInfo::Workarounds::Workarounds() : 139 #define GPU_OP(type, name) name(false), 140 GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP) 141 #undef GPU_OP 142 max_texture_size(0), 143 max_cube_map_texture_size(0) { 144 } 145 146 FeatureInfo::FeatureInfo() { 147 InitializeBasicState(*CommandLine::ForCurrentProcess()); 148 } 149 150 FeatureInfo::FeatureInfo(const CommandLine& command_line) { 151 InitializeBasicState(command_line); 152 } 153 154 void FeatureInfo::InitializeBasicState(const CommandLine& command_line) { 155 if (command_line.HasSwitch(switches::kGpuDriverBugWorkarounds)) { 156 std::string types = command_line.GetSwitchValueASCII( 157 switches::kGpuDriverBugWorkarounds); 158 StringToWorkarounds(types, &workarounds_); 159 } 160 feature_flags_.enable_shader_name_hashing = 161 !command_line.HasSwitch(switches::kDisableShaderNameHashing); 162 163 feature_flags_.is_swiftshader = 164 (command_line.GetSwitchValueASCII(switches::kUseGL) == "swiftshader"); 165 166 static const GLenum kAlphaTypes[] = { 167 GL_UNSIGNED_BYTE, 168 }; 169 static const GLenum kRGBTypes[] = { 170 GL_UNSIGNED_BYTE, 171 GL_UNSIGNED_SHORT_5_6_5, 172 }; 173 static const GLenum kRGBATypes[] = { 174 GL_UNSIGNED_BYTE, 175 GL_UNSIGNED_SHORT_4_4_4_4, 176 GL_UNSIGNED_SHORT_5_5_5_1, 177 }; 178 static const GLenum kLuminanceTypes[] = { 179 GL_UNSIGNED_BYTE, 180 }; 181 static const GLenum kLuminanceAlphaTypes[] = { 182 GL_UNSIGNED_BYTE, 183 }; 184 static const FormatInfo kFormatTypes[] = { 185 { GL_ALPHA, kAlphaTypes, arraysize(kAlphaTypes), }, 186 { GL_RGB, kRGBTypes, arraysize(kRGBTypes), }, 187 { GL_RGBA, kRGBATypes, arraysize(kRGBATypes), }, 188 { GL_LUMINANCE, kLuminanceTypes, arraysize(kLuminanceTypes), }, 189 { GL_LUMINANCE_ALPHA, kLuminanceAlphaTypes, 190 arraysize(kLuminanceAlphaTypes), } , 191 }; 192 for (size_t ii = 0; ii < arraysize(kFormatTypes); ++ii) { 193 const FormatInfo& info = kFormatTypes[ii]; 194 ValueValidator<GLenum>& validator = texture_format_validators_[info.format]; 195 for (size_t jj = 0; jj < info.count; ++jj) { 196 validator.AddValue(info.types[jj]); 197 } 198 } 199 } 200 201 bool FeatureInfo::Initialize() { 202 disallowed_features_ = DisallowedFeatures(); 203 InitializeFeatures(); 204 return true; 205 } 206 207 bool FeatureInfo::Initialize(const DisallowedFeatures& disallowed_features) { 208 disallowed_features_ = disallowed_features; 209 InitializeFeatures(); 210 return true; 211 } 212 213 void FeatureInfo::InitializeFeatures() { 214 // Figure out what extensions to turn on. 215 StringSet extensions( 216 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))); 217 218 bool npot_ok = false; 219 220 const char* renderer_str = 221 reinterpret_cast<const char*>(glGetString(GL_RENDERER)); 222 if (renderer_str) { 223 feature_flags_.is_angle = StartsWithASCII(renderer_str, "ANGLE", true); 224 } 225 226 bool is_es3 = false; 227 const char* version_str = 228 reinterpret_cast<const char*>(glGetString(GL_VERSION)); 229 if (version_str) { 230 std::string lstr(StringToLowerASCII(std::string(version_str))); 231 is_es3 = (lstr.substr(0, 12) == "opengl es 3."); 232 } 233 234 AddExtensionString("GL_ANGLE_translated_shader_source"); 235 AddExtensionString("GL_CHROMIUM_async_pixel_transfers"); 236 AddExtensionString("GL_CHROMIUM_bind_uniform_location"); 237 AddExtensionString("GL_CHROMIUM_command_buffer_query"); 238 AddExtensionString("GL_CHROMIUM_command_buffer_latency_query"); 239 AddExtensionString("GL_CHROMIUM_copy_texture"); 240 AddExtensionString("GL_CHROMIUM_get_error_query"); 241 AddExtensionString("GL_CHROMIUM_lose_context"); 242 AddExtensionString("GL_CHROMIUM_pixel_transfer_buffer_object"); 243 AddExtensionString("GL_CHROMIUM_rate_limit_offscreen_context"); 244 AddExtensionString("GL_CHROMIUM_resize"); 245 AddExtensionString("GL_CHROMIUM_resource_safe"); 246 AddExtensionString("GL_CHROMIUM_strict_attribs"); 247 AddExtensionString("GL_CHROMIUM_stream_texture"); 248 AddExtensionString("GL_CHROMIUM_texture_mailbox"); 249 AddExtensionString("GL_EXT_debug_marker"); 250 251 if (workarounds_.enable_chromium_fast_npot_mo8_textures) 252 AddExtensionString("GL_CHROMIUM_fast_NPOT_MO8_textures"); 253 254 feature_flags_.chromium_stream_texture = true; 255 256 // OES_vertex_array_object is emulated if not present natively, 257 // so the extension string is always exposed. 258 AddExtensionString("GL_OES_vertex_array_object"); 259 260 if (!disallowed_features_.gpu_memory_manager) 261 AddExtensionString("GL_CHROMIUM_gpu_memory_manager"); 262 263 if (extensions.Contains("GL_ANGLE_translated_shader_source")) { 264 feature_flags_.angle_translated_shader_source = true; 265 } 266 267 // Check if we should allow GL_EXT_texture_compression_dxt1 and 268 // GL_EXT_texture_compression_s3tc. 269 bool enable_dxt1 = false; 270 bool enable_dxt3 = false; 271 bool enable_dxt5 = false; 272 bool have_s3tc = extensions.Contains("GL_EXT_texture_compression_s3tc"); 273 bool have_dxt3 = 274 have_s3tc || extensions.Contains("GL_ANGLE_texture_compression_dxt3"); 275 bool have_dxt5 = 276 have_s3tc || extensions.Contains("GL_ANGLE_texture_compression_dxt5"); 277 278 if (extensions.Contains("GL_EXT_texture_compression_dxt1") || have_s3tc) { 279 enable_dxt1 = true; 280 } 281 if (have_dxt3) { 282 enable_dxt3 = true; 283 } 284 if (have_dxt5) { 285 enable_dxt5 = true; 286 } 287 288 if (enable_dxt1) { 289 AddExtensionString("GL_EXT_texture_compression_dxt1"); 290 validators_.compressed_texture_format.AddValue( 291 GL_COMPRESSED_RGB_S3TC_DXT1_EXT); 292 validators_.compressed_texture_format.AddValue( 293 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); 294 } 295 296 if (enable_dxt3) { 297 // The difference between GL_EXT_texture_compression_s3tc and 298 // GL_CHROMIUM_texture_compression_dxt3 is that the former 299 // requires on the fly compression. The latter does not. 300 AddExtensionString("GL_CHROMIUM_texture_compression_dxt3"); 301 validators_.compressed_texture_format.AddValue( 302 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT); 303 } 304 305 if (enable_dxt5) { 306 // The difference between GL_EXT_texture_compression_s3tc and 307 // GL_CHROMIUM_texture_compression_dxt5 is that the former 308 // requires on the fly compression. The latter does not. 309 AddExtensionString("GL_CHROMIUM_texture_compression_dxt5"); 310 validators_.compressed_texture_format.AddValue( 311 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT); 312 } 313 314 // Check if we should enable GL_EXT_texture_filter_anisotropic. 315 if (extensions.Contains("GL_EXT_texture_filter_anisotropic")) { 316 AddExtensionString("GL_EXT_texture_filter_anisotropic"); 317 validators_.texture_parameter.AddValue( 318 GL_TEXTURE_MAX_ANISOTROPY_EXT); 319 validators_.g_l_state.AddValue( 320 GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT); 321 } 322 323 // Check if we should support GL_OES_packed_depth_stencil and/or 324 // GL_GOOGLE_depth_texture / GL_CHROMIUM_depth_texture. 325 // 326 // NOTE: GL_OES_depth_texture requires support for depth cubemaps. 327 // GL_ARB_depth_texture requires other features that 328 // GL_OES_packed_depth_stencil does not provide. 329 // 330 // Therefore we made up GL_GOOGLE_depth_texture / GL_CHROMIUM_depth_texture. 331 // 332 // GL_GOOGLE_depth_texture is legacy. As we exposed it into NaCl we can't 333 // get rid of it. 334 // 335 bool enable_depth_texture = false; 336 if (!workarounds_.disable_depth_texture && 337 (extensions.Contains("GL_ARB_depth_texture") || 338 extensions.Contains("GL_OES_depth_texture") || 339 extensions.Contains("GL_ANGLE_depth_texture") || is_es3)) { 340 enable_depth_texture = true; 341 feature_flags_.angle_depth_texture = 342 extensions.Contains("GL_ANGLE_depth_texture"); 343 } 344 345 if (enable_depth_texture) { 346 AddExtensionString("GL_CHROMIUM_depth_texture"); 347 AddExtensionString("GL_GOOGLE_depth_texture"); 348 texture_format_validators_[GL_DEPTH_COMPONENT].AddValue(GL_UNSIGNED_SHORT); 349 texture_format_validators_[GL_DEPTH_COMPONENT].AddValue(GL_UNSIGNED_INT); 350 validators_.texture_internal_format.AddValue(GL_DEPTH_COMPONENT); 351 validators_.texture_format.AddValue(GL_DEPTH_COMPONENT); 352 validators_.pixel_type.AddValue(GL_UNSIGNED_SHORT); 353 validators_.pixel_type.AddValue(GL_UNSIGNED_INT); 354 } 355 356 if (extensions.Contains("GL_EXT_packed_depth_stencil") || 357 extensions.Contains("GL_OES_packed_depth_stencil") || is_es3) { 358 AddExtensionString("GL_OES_packed_depth_stencil"); 359 feature_flags_.packed_depth24_stencil8 = true; 360 if (enable_depth_texture) { 361 texture_format_validators_[GL_DEPTH_STENCIL] 362 .AddValue(GL_UNSIGNED_INT_24_8); 363 validators_.texture_internal_format.AddValue(GL_DEPTH_STENCIL); 364 validators_.texture_format.AddValue(GL_DEPTH_STENCIL); 365 validators_.pixel_type.AddValue(GL_UNSIGNED_INT_24_8); 366 } 367 validators_.render_buffer_format.AddValue(GL_DEPTH24_STENCIL8); 368 } 369 370 if (extensions.Contains("GL_OES_vertex_array_object") || 371 extensions.Contains("GL_ARB_vertex_array_object") || 372 extensions.Contains("GL_APPLE_vertex_array_object")) { 373 feature_flags_.native_vertex_array_object = true; 374 } 375 376 // If we're using client_side_arrays we have to emulate 377 // vertex array objects since vertex array objects do not work 378 // with client side arrays. 379 if (workarounds_.use_client_side_arrays_for_stream_buffers) { 380 feature_flags_.native_vertex_array_object = false; 381 } 382 383 if (extensions.Contains("GL_OES_element_index_uint") || 384 gfx::HasDesktopGLFeatures()) { 385 AddExtensionString("GL_OES_element_index_uint"); 386 validators_.index_type.AddValue(GL_UNSIGNED_INT); 387 } 388 389 bool enable_texture_format_bgra8888 = false; 390 bool enable_read_format_bgra = false; 391 bool enable_render_buffer_bgra = false; 392 393 // Check if we should allow GL_EXT_texture_format_BGRA8888 394 if (extensions.Contains("GL_EXT_texture_format_BGRA8888") || 395 extensions.Contains("GL_APPLE_texture_format_BGRA8888") || 396 extensions.Contains("GL_EXT_bgra")) { 397 enable_texture_format_bgra8888 = true; 398 } 399 400 if (extensions.Contains("GL_EXT_bgra")) { 401 enable_render_buffer_bgra = true; 402 } 403 404 if (extensions.Contains("GL_EXT_read_format_bgra") || 405 extensions.Contains("GL_EXT_bgra")) { 406 enable_read_format_bgra = true; 407 } 408 409 if (enable_texture_format_bgra8888) { 410 feature_flags_.ext_texture_format_bgra8888 = true; 411 AddExtensionString("GL_EXT_texture_format_BGRA8888"); 412 texture_format_validators_[GL_BGRA_EXT].AddValue(GL_UNSIGNED_BYTE); 413 validators_.texture_internal_format.AddValue(GL_BGRA_EXT); 414 validators_.texture_format.AddValue(GL_BGRA_EXT); 415 } 416 417 if (enable_read_format_bgra) { 418 AddExtensionString("GL_EXT_read_format_bgra"); 419 validators_.read_pixel_format.AddValue(GL_BGRA_EXT); 420 } 421 422 if (enable_render_buffer_bgra) { 423 AddExtensionString("GL_CHROMIUM_renderbuffer_format_BGRA8888"); 424 validators_.render_buffer_format.AddValue(GL_BGRA8_EXT); 425 } 426 427 if (extensions.Contains("GL_OES_rgb8_rgba8") || gfx::HasDesktopGLFeatures()) { 428 AddExtensionString("GL_OES_rgb8_rgba8"); 429 validators_.render_buffer_format.AddValue(GL_RGB8_OES); 430 validators_.render_buffer_format.AddValue(GL_RGBA8_OES); 431 } 432 433 // Check if we should allow GL_OES_texture_npot 434 if (extensions.Contains("GL_ARB_texture_non_power_of_two") || 435 extensions.Contains("GL_OES_texture_npot")) { 436 AddExtensionString("GL_OES_texture_npot"); 437 npot_ok = true; 438 } 439 440 // Check if we should allow GL_OES_texture_float, GL_OES_texture_half_float, 441 // GL_OES_texture_float_linear, GL_OES_texture_half_float_linear 442 bool enable_texture_float = false; 443 bool enable_texture_float_linear = false; 444 bool enable_texture_half_float = false; 445 bool enable_texture_half_float_linear = false; 446 447 bool have_arb_texture_float = extensions.Contains("GL_ARB_texture_float"); 448 449 if (have_arb_texture_float) { 450 enable_texture_float = true; 451 enable_texture_float_linear = true; 452 enable_texture_half_float = true; 453 enable_texture_half_float_linear = true; 454 } else { 455 if (extensions.Contains("GL_OES_texture_float") || have_arb_texture_float) { 456 enable_texture_float = true; 457 if (extensions.Contains("GL_OES_texture_float_linear") || 458 have_arb_texture_float) { 459 enable_texture_float_linear = true; 460 } 461 } 462 if (extensions.Contains("GL_OES_texture_half_float") || 463 have_arb_texture_float) { 464 enable_texture_half_float = true; 465 if (extensions.Contains("GL_OES_texture_half_float_linear") || 466 have_arb_texture_float) { 467 enable_texture_half_float_linear = true; 468 } 469 } 470 } 471 472 if (enable_texture_float) { 473 texture_format_validators_[GL_ALPHA].AddValue(GL_FLOAT); 474 texture_format_validators_[GL_RGB].AddValue(GL_FLOAT); 475 texture_format_validators_[GL_RGBA].AddValue(GL_FLOAT); 476 texture_format_validators_[GL_LUMINANCE].AddValue(GL_FLOAT); 477 texture_format_validators_[GL_LUMINANCE_ALPHA].AddValue(GL_FLOAT); 478 validators_.pixel_type.AddValue(GL_FLOAT); 479 validators_.read_pixel_type.AddValue(GL_FLOAT); 480 AddExtensionString("GL_OES_texture_float"); 481 if (enable_texture_float_linear) { 482 AddExtensionString("GL_OES_texture_float_linear"); 483 } 484 } 485 486 if (enable_texture_half_float) { 487 texture_format_validators_[GL_ALPHA].AddValue(GL_HALF_FLOAT_OES); 488 texture_format_validators_[GL_RGB].AddValue(GL_HALF_FLOAT_OES); 489 texture_format_validators_[GL_RGBA].AddValue(GL_HALF_FLOAT_OES); 490 texture_format_validators_[GL_LUMINANCE].AddValue(GL_HALF_FLOAT_OES); 491 texture_format_validators_[GL_LUMINANCE_ALPHA].AddValue(GL_HALF_FLOAT_OES); 492 validators_.pixel_type.AddValue(GL_HALF_FLOAT_OES); 493 validators_.read_pixel_type.AddValue(GL_HALF_FLOAT_OES); 494 AddExtensionString("GL_OES_texture_half_float"); 495 if (enable_texture_half_float_linear) { 496 AddExtensionString("GL_OES_texture_half_float_linear"); 497 } 498 } 499 500 // Check for multisample support 501 if (!disallowed_features_.multisampling && 502 !workarounds_.disable_framebuffer_multisample) { 503 bool ext_has_multisample = 504 extensions.Contains("GL_EXT_framebuffer_multisample") || is_es3; 505 if (feature_flags_.is_angle) { 506 ext_has_multisample |= 507 extensions.Contains("GL_ANGLE_framebuffer_multisample"); 508 } 509 feature_flags_.use_core_framebuffer_multisample = is_es3; 510 if (ext_has_multisample) { 511 feature_flags_.chromium_framebuffer_multisample = true; 512 validators_.frame_buffer_target.AddValue(GL_READ_FRAMEBUFFER_EXT); 513 validators_.frame_buffer_target.AddValue(GL_DRAW_FRAMEBUFFER_EXT); 514 validators_.g_l_state.AddValue(GL_READ_FRAMEBUFFER_BINDING_EXT); 515 validators_.g_l_state.AddValue(GL_MAX_SAMPLES_EXT); 516 validators_.render_buffer_parameter.AddValue(GL_RENDERBUFFER_SAMPLES_EXT); 517 AddExtensionString("GL_CHROMIUM_framebuffer_multisample"); 518 } else { 519 if (extensions.Contains("GL_EXT_multisampled_render_to_texture")) { 520 feature_flags_.multisampled_render_to_texture = true; 521 } else if (extensions.Contains("GL_IMG_multisampled_render_to_texture")) { 522 feature_flags_.multisampled_render_to_texture = true; 523 feature_flags_.use_img_for_multisampled_render_to_texture = true; 524 } 525 if (feature_flags_.multisampled_render_to_texture) { 526 validators_.render_buffer_parameter.AddValue( 527 GL_RENDERBUFFER_SAMPLES_EXT); 528 validators_.g_l_state.AddValue(GL_MAX_SAMPLES_EXT); 529 validators_.frame_buffer_parameter.AddValue( 530 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT); 531 AddExtensionString("GL_EXT_multisampled_render_to_texture"); 532 } 533 } 534 } 535 536 if (extensions.Contains("GL_OES_depth24") || gfx::HasDesktopGLFeatures() || 537 is_es3) { 538 AddExtensionString("GL_OES_depth24"); 539 feature_flags_.oes_depth24 = true; 540 validators_.render_buffer_format.AddValue(GL_DEPTH_COMPONENT24); 541 } 542 543 if (!workarounds_.disable_oes_standard_derivatives && 544 (extensions.Contains("GL_OES_standard_derivatives") || 545 gfx::HasDesktopGLFeatures())) { 546 AddExtensionString("GL_OES_standard_derivatives"); 547 feature_flags_.oes_standard_derivatives = true; 548 validators_.hint_target.AddValue(GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES); 549 validators_.g_l_state.AddValue(GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES); 550 } 551 552 if (extensions.Contains("GL_OES_EGL_image_external")) { 553 AddExtensionString("GL_OES_EGL_image_external"); 554 feature_flags_.oes_egl_image_external = true; 555 validators_.texture_bind_target.AddValue(GL_TEXTURE_EXTERNAL_OES); 556 validators_.get_tex_param_target.AddValue(GL_TEXTURE_EXTERNAL_OES); 557 validators_.texture_parameter.AddValue(GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES); 558 validators_.g_l_state.AddValue(GL_TEXTURE_BINDING_EXTERNAL_OES); 559 } 560 561 if (extensions.Contains("GL_OES_compressed_ETC1_RGB8_texture")) { 562 AddExtensionString("GL_OES_compressed_ETC1_RGB8_texture"); 563 feature_flags_.oes_compressed_etc1_rgb8_texture = true; 564 validators_.compressed_texture_format.AddValue(GL_ETC1_RGB8_OES); 565 } 566 567 // Ideally we would only expose this extension on Mac OS X, to 568 // support GL_CHROMIUM_iosurface and the compositor. We don't want 569 // applications to start using it; they should use ordinary non- 570 // power-of-two textures. However, for unit testing purposes we 571 // expose it on all supported platforms. 572 if (extensions.Contains("GL_ARB_texture_rectangle")) { 573 AddExtensionString("GL_ARB_texture_rectangle"); 574 feature_flags_.arb_texture_rectangle = true; 575 validators_.texture_bind_target.AddValue(GL_TEXTURE_RECTANGLE_ARB); 576 // For the moment we don't add this enum to the texture_target 577 // validator. This implies that the only way to get image data into a 578 // rectangular texture is via glTexImageIOSurface2DCHROMIUM, which is 579 // just fine since again we don't want applications depending on this 580 // extension. 581 validators_.get_tex_param_target.AddValue(GL_TEXTURE_RECTANGLE_ARB); 582 validators_.g_l_state.AddValue(GL_TEXTURE_BINDING_RECTANGLE_ARB); 583 } 584 585 #if defined(OS_MACOSX) 586 if (IOSurfaceSupport::Initialize()) { 587 AddExtensionString("GL_CHROMIUM_iosurface"); 588 } 589 #endif 590 591 // TODO(gman): Add support for these extensions. 592 // GL_OES_depth32 593 594 feature_flags_.enable_texture_float_linear |= enable_texture_float_linear; 595 feature_flags_.enable_texture_half_float_linear |= 596 enable_texture_half_float_linear; 597 feature_flags_.npot_ok |= npot_ok; 598 599 if (extensions.Contains("GL_ANGLE_pack_reverse_row_order")) { 600 AddExtensionString("GL_ANGLE_pack_reverse_row_order"); 601 feature_flags_.angle_pack_reverse_row_order = true; 602 validators_.pixel_store.AddValue(GL_PACK_REVERSE_ROW_ORDER_ANGLE); 603 validators_.g_l_state.AddValue(GL_PACK_REVERSE_ROW_ORDER_ANGLE); 604 } 605 606 if (extensions.Contains("GL_ANGLE_texture_usage")) { 607 feature_flags_.angle_texture_usage = true; 608 AddExtensionString("GL_ANGLE_texture_usage"); 609 validators_.texture_parameter.AddValue(GL_TEXTURE_USAGE_ANGLE); 610 } 611 612 if (extensions.Contains("GL_EXT_texture_storage")) { 613 feature_flags_.ext_texture_storage = true; 614 AddExtensionString("GL_EXT_texture_storage"); 615 validators_.texture_parameter.AddValue(GL_TEXTURE_IMMUTABLE_FORMAT_EXT); 616 if (enable_texture_format_bgra8888) 617 validators_.texture_internal_format_storage.AddValue(GL_BGRA8_EXT); 618 if (enable_texture_float) { 619 validators_.texture_internal_format_storage.AddValue(GL_RGBA32F_EXT); 620 validators_.texture_internal_format_storage.AddValue(GL_RGB32F_EXT); 621 validators_.texture_internal_format_storage.AddValue(GL_ALPHA32F_EXT); 622 validators_.texture_internal_format_storage.AddValue( 623 GL_LUMINANCE32F_EXT); 624 validators_.texture_internal_format_storage.AddValue( 625 GL_LUMINANCE_ALPHA32F_EXT); 626 } 627 if (enable_texture_half_float) { 628 validators_.texture_internal_format_storage.AddValue(GL_RGBA16F_EXT); 629 validators_.texture_internal_format_storage.AddValue(GL_RGB16F_EXT); 630 validators_.texture_internal_format_storage.AddValue(GL_ALPHA16F_EXT); 631 validators_.texture_internal_format_storage.AddValue( 632 GL_LUMINANCE16F_EXT); 633 validators_.texture_internal_format_storage.AddValue( 634 GL_LUMINANCE_ALPHA16F_EXT); 635 } 636 } 637 638 bool have_ext_occlusion_query_boolean = 639 extensions.Contains("GL_EXT_occlusion_query_boolean"); 640 bool have_arb_occlusion_query2 = 641 extensions.Contains("GL_ARB_occlusion_query2"); 642 bool have_arb_occlusion_query = 643 extensions.Contains("GL_ARB_occlusion_query"); 644 645 if (!workarounds_.disable_ext_occlusion_query && 646 (have_ext_occlusion_query_boolean || 647 have_arb_occlusion_query2 || 648 have_arb_occlusion_query)) { 649 AddExtensionString("GL_EXT_occlusion_query_boolean"); 650 feature_flags_.occlusion_query_boolean = true; 651 feature_flags_.use_arb_occlusion_query2_for_occlusion_query_boolean = 652 !have_ext_occlusion_query_boolean && have_arb_occlusion_query2; 653 feature_flags_.use_arb_occlusion_query_for_occlusion_query_boolean = 654 !have_ext_occlusion_query_boolean && have_arb_occlusion_query && 655 !have_arb_occlusion_query2; 656 } 657 658 if (!workarounds_.disable_angle_instanced_arrays && 659 (extensions.Contains("GL_ANGLE_instanced_arrays") || 660 (extensions.Contains("GL_ARB_instanced_arrays") && 661 extensions.Contains("GL_ARB_draw_instanced")))) { 662 AddExtensionString("GL_ANGLE_instanced_arrays"); 663 feature_flags_.angle_instanced_arrays = true; 664 validators_.vertex_attribute.AddValue(GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE); 665 } 666 667 if (!workarounds_.disable_ext_draw_buffers && 668 (extensions.Contains("GL_ARB_draw_buffers") || 669 extensions.Contains("GL_EXT_draw_buffers"))) { 670 AddExtensionString("GL_EXT_draw_buffers"); 671 feature_flags_.ext_draw_buffers = true; 672 673 GLint max_color_attachments = 0; 674 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &max_color_attachments); 675 for (GLenum i = GL_COLOR_ATTACHMENT1_EXT; 676 i < static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + max_color_attachments); 677 ++i) { 678 validators_.attachment.AddValue(i); 679 } 680 681 validators_.g_l_state.AddValue(GL_MAX_COLOR_ATTACHMENTS_EXT); 682 validators_.g_l_state.AddValue(GL_MAX_DRAW_BUFFERS_ARB); 683 GLint max_draw_buffers = 0; 684 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &max_draw_buffers); 685 for (GLenum i = GL_DRAW_BUFFER0_ARB; 686 i < static_cast<GLenum>(GL_DRAW_BUFFER0_ARB + max_draw_buffers); 687 ++i) { 688 validators_.g_l_state.AddValue(i); 689 } 690 } 691 692 if (extensions.Contains("GL_EXT_frag_depth") || gfx::HasDesktopGLFeatures()) { 693 AddExtensionString("GL_EXT_frag_depth"); 694 feature_flags_.ext_frag_depth = true; 695 } 696 697 bool ui_gl_fence_works = extensions.Contains("GL_NV_fence") || 698 extensions.Contains("GL_ARB_sync") || 699 extensions.Contains("EGL_KHR_fence_sync"); 700 701 feature_flags_.map_buffer_range = 702 is_es3 || extensions.Contains("GL_ARB_map_buffer_range"); 703 704 // Really it's part of core OpenGL 2.1 and up, but let's assume the 705 // extension is still advertised. 706 bool has_pixel_buffers = 707 is_es3 || extensions.Contains("GL_ARB_pixel_buffer_object"); 708 709 // We will use either glMapBuffer() or glMapBufferRange() for async readbacks. 710 if (has_pixel_buffers && ui_gl_fence_works && 711 !workarounds_.disable_async_readpixels) { 712 feature_flags_.use_async_readpixels = true; 713 } 714 715 if (is_es3 || extensions.Contains("GL_ARB_sampler_objects")) { 716 feature_flags_.enable_samplers = true; 717 // TODO(dsinclair): Add AddExtensionString("GL_CHROMIUM_sampler_objects") 718 // when available. 719 } 720 721 if ((is_es3 || extensions.Contains("GL_EXT_discard_framebuffer")) && 722 !workarounds_.disable_ext_discard_framebuffer) { 723 // DiscardFramebufferEXT is automatically bound to InvalidateFramebuffer. 724 AddExtensionString("GL_EXT_discard_framebuffer"); 725 feature_flags_.ext_discard_framebuffer = true; 726 } 727 } 728 729 void FeatureInfo::AddExtensionString(const std::string& str) { 730 if (extensions_.find(str) == std::string::npos) { 731 extensions_ += (extensions_.empty() ? "" : " ") + str; 732 } 733 } 734 735 FeatureInfo::~FeatureInfo() { 736 } 737 738 } // namespace gles2 739 } // namespace gpu 740