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 multisampled_render_to_texture(false), 104 use_img_for_multisampled_render_to_texture(false), 105 oes_standard_derivatives(false), 106 oes_egl_image_external(false), 107 npot_ok(false), 108 enable_texture_float_linear(false), 109 enable_texture_half_float_linear(false), 110 chromium_stream_texture(false), 111 angle_translated_shader_source(false), 112 angle_pack_reverse_row_order(false), 113 arb_texture_rectangle(false), 114 angle_instanced_arrays(false), 115 occlusion_query_boolean(false), 116 use_arb_occlusion_query2_for_occlusion_query_boolean(false), 117 use_arb_occlusion_query_for_occlusion_query_boolean(false), 118 native_vertex_array_object(false), 119 enable_shader_name_hashing(false), 120 enable_samplers(false), 121 ext_draw_buffers(false), 122 ext_frag_depth(false), 123 use_async_readpixels(false) { 124 } 125 126 FeatureInfo::Workarounds::Workarounds() : 127 #define GPU_OP(type, name) name(false), 128 GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP) 129 #undef GPU_OP 130 max_texture_size(0), 131 max_cube_map_texture_size(0) { 132 } 133 134 FeatureInfo::FeatureInfo() { 135 static const GLenum kAlphaTypes[] = { 136 GL_UNSIGNED_BYTE, 137 }; 138 static const GLenum kRGBTypes[] = { 139 GL_UNSIGNED_BYTE, 140 GL_UNSIGNED_SHORT_5_6_5, 141 }; 142 static const GLenum kRGBATypes[] = { 143 GL_UNSIGNED_BYTE, 144 GL_UNSIGNED_SHORT_4_4_4_4, 145 GL_UNSIGNED_SHORT_5_5_5_1, 146 }; 147 static const GLenum kLuminanceTypes[] = { 148 GL_UNSIGNED_BYTE, 149 }; 150 static const GLenum kLuminanceAlphaTypes[] = { 151 GL_UNSIGNED_BYTE, 152 }; 153 static const FormatInfo kFormatTypes[] = { 154 { GL_ALPHA, kAlphaTypes, arraysize(kAlphaTypes), }, 155 { GL_RGB, kRGBTypes, arraysize(kRGBTypes), }, 156 { GL_RGBA, kRGBATypes, arraysize(kRGBATypes), }, 157 { GL_LUMINANCE, kLuminanceTypes, arraysize(kLuminanceTypes), }, 158 { GL_LUMINANCE_ALPHA, kLuminanceAlphaTypes, 159 arraysize(kLuminanceAlphaTypes), } , 160 }; 161 for (size_t ii = 0; ii < arraysize(kFormatTypes); ++ii) { 162 const FormatInfo& info = kFormatTypes[ii]; 163 ValueValidator<GLenum>& validator = texture_format_validators_[info.format]; 164 for (size_t jj = 0; jj < info.count; ++jj) { 165 validator.AddValue(info.types[jj]); 166 } 167 } 168 } 169 170 bool FeatureInfo::Initialize(const char* allowed_features) { 171 disallowed_features_ = DisallowedFeatures(); 172 AddFeatures(*CommandLine::ForCurrentProcess()); 173 return true; 174 } 175 176 bool FeatureInfo::Initialize(const DisallowedFeatures& disallowed_features, 177 const char* allowed_features) { 178 disallowed_features_ = disallowed_features; 179 AddFeatures(*CommandLine::ForCurrentProcess()); 180 return true; 181 } 182 183 void FeatureInfo::AddFeatures(const CommandLine& command_line) { 184 // Figure out what extensions to turn on. 185 StringSet extensions( 186 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))); 187 188 if (command_line.HasSwitch(switches::kGpuDriverBugWorkarounds)) { 189 std::string types = command_line.GetSwitchValueASCII( 190 switches::kGpuDriverBugWorkarounds); 191 StringToWorkarounds(types, &workarounds_); 192 } 193 194 feature_flags_.enable_shader_name_hashing = 195 !command_line.HasSwitch(switches::kDisableShaderNameHashing); 196 197 bool npot_ok = false; 198 199 AddExtensionString("GL_ANGLE_translated_shader_source"); 200 AddExtensionString("GL_CHROMIUM_async_pixel_transfers"); 201 AddExtensionString("GL_CHROMIUM_bind_uniform_location"); 202 AddExtensionString("GL_CHROMIUM_command_buffer_query"); 203 AddExtensionString("GL_CHROMIUM_command_buffer_latency_query"); 204 AddExtensionString("GL_CHROMIUM_copy_texture"); 205 AddExtensionString("GL_CHROMIUM_discard_backbuffer"); 206 AddExtensionString("GL_CHROMIUM_get_error_query"); 207 AddExtensionString("GL_CHROMIUM_lose_context"); 208 AddExtensionString("GL_CHROMIUM_pixel_transfer_buffer_object"); 209 AddExtensionString("GL_CHROMIUM_rate_limit_offscreen_context"); 210 AddExtensionString("GL_CHROMIUM_resize"); 211 AddExtensionString("GL_CHROMIUM_resource_safe"); 212 AddExtensionString("GL_CHROMIUM_set_visibility"); 213 AddExtensionString("GL_CHROMIUM_strict_attribs"); 214 AddExtensionString("GL_CHROMIUM_stream_texture"); 215 AddExtensionString("GL_CHROMIUM_texture_mailbox"); 216 AddExtensionString("GL_EXT_debug_marker"); 217 218 if (workarounds_.enable_chromium_fast_npot_mo8_textures) 219 AddExtensionString("GL_CHROMIUM_fast_NPOT_MO8_textures"); 220 221 feature_flags_.chromium_stream_texture = true; 222 223 // OES_vertex_array_object is emulated if not present natively, 224 // so the extension string is always exposed. 225 AddExtensionString("GL_OES_vertex_array_object"); 226 227 if (!disallowed_features_.gpu_memory_manager) 228 AddExtensionString("GL_CHROMIUM_gpu_memory_manager"); 229 230 if (extensions.Contains("GL_ANGLE_translated_shader_source")) { 231 feature_flags_.angle_translated_shader_source = true; 232 } 233 234 // Check if we should allow GL_EXT_texture_compression_dxt1 and 235 // GL_EXT_texture_compression_s3tc. 236 bool enable_dxt1 = false; 237 bool enable_dxt3 = false; 238 bool enable_dxt5 = false; 239 bool have_s3tc = extensions.Contains("GL_EXT_texture_compression_s3tc"); 240 bool have_dxt3 = 241 have_s3tc || extensions.Contains("GL_ANGLE_texture_compression_dxt3"); 242 bool have_dxt5 = 243 have_s3tc || extensions.Contains("GL_ANGLE_texture_compression_dxt5"); 244 245 if (extensions.Contains("GL_EXT_texture_compression_dxt1") || have_s3tc) { 246 enable_dxt1 = true; 247 } 248 if (have_dxt3) { 249 enable_dxt3 = true; 250 } 251 if (have_dxt5) { 252 enable_dxt5 = true; 253 } 254 255 if (enable_dxt1) { 256 AddExtensionString("GL_EXT_texture_compression_dxt1"); 257 validators_.compressed_texture_format.AddValue( 258 GL_COMPRESSED_RGB_S3TC_DXT1_EXT); 259 validators_.compressed_texture_format.AddValue( 260 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); 261 } 262 263 if (enable_dxt3) { 264 // The difference between GL_EXT_texture_compression_s3tc and 265 // GL_CHROMIUM_texture_compression_dxt3 is that the former 266 // requires on the fly compression. The latter does not. 267 AddExtensionString("GL_CHROMIUM_texture_compression_dxt3"); 268 validators_.compressed_texture_format.AddValue( 269 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT); 270 } 271 272 if (enable_dxt5) { 273 // The difference between GL_EXT_texture_compression_s3tc and 274 // GL_CHROMIUM_texture_compression_dxt5 is that the former 275 // requires on the fly compression. The latter does not. 276 AddExtensionString("GL_CHROMIUM_texture_compression_dxt5"); 277 validators_.compressed_texture_format.AddValue( 278 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT); 279 } 280 281 // Check if we should enable GL_EXT_texture_filter_anisotropic. 282 if (extensions.Contains("GL_EXT_texture_filter_anisotropic")) { 283 AddExtensionString("GL_EXT_texture_filter_anisotropic"); 284 validators_.texture_parameter.AddValue( 285 GL_TEXTURE_MAX_ANISOTROPY_EXT); 286 validators_.g_l_state.AddValue( 287 GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT); 288 } 289 290 // Check if we should support GL_OES_packed_depth_stencil and/or 291 // GL_GOOGLE_depth_texture / GL_CHROMIUM_depth_texture. 292 // 293 // NOTE: GL_OES_depth_texture requires support for depth cubemaps. 294 // GL_ARB_depth_texture requires other features that 295 // GL_OES_packed_depth_stencil does not provide. 296 // 297 // Therefore we made up GL_GOOGLE_depth_texture / GL_CHROMIUM_depth_texture. 298 // 299 // GL_GOOGLE_depth_texture is legacy. As we exposed it into NaCl we can't 300 // get rid of it. 301 // 302 bool enable_depth_texture = false; 303 if (!workarounds_.disable_depth_texture && 304 (extensions.Contains("GL_ARB_depth_texture") || 305 extensions.Contains("GL_OES_depth_texture") || 306 extensions.Contains("GL_ANGLE_depth_texture"))) { 307 enable_depth_texture = true; 308 } 309 310 if (enable_depth_texture) { 311 AddExtensionString("GL_CHROMIUM_depth_texture"); 312 AddExtensionString("GL_GOOGLE_depth_texture"); 313 texture_format_validators_[GL_DEPTH_COMPONENT].AddValue(GL_UNSIGNED_SHORT); 314 texture_format_validators_[GL_DEPTH_COMPONENT].AddValue(GL_UNSIGNED_INT); 315 validators_.texture_internal_format.AddValue(GL_DEPTH_COMPONENT); 316 validators_.texture_format.AddValue(GL_DEPTH_COMPONENT); 317 validators_.pixel_type.AddValue(GL_UNSIGNED_SHORT); 318 validators_.pixel_type.AddValue(GL_UNSIGNED_INT); 319 } 320 321 if (extensions.Contains("GL_EXT_packed_depth_stencil") || 322 extensions.Contains("GL_OES_packed_depth_stencil")) { 323 AddExtensionString("GL_OES_packed_depth_stencil"); 324 if (enable_depth_texture) { 325 texture_format_validators_[GL_DEPTH_STENCIL].AddValue( 326 GL_UNSIGNED_INT_24_8); 327 validators_.texture_internal_format.AddValue(GL_DEPTH_STENCIL); 328 validators_.texture_format.AddValue(GL_DEPTH_STENCIL); 329 validators_.pixel_type.AddValue(GL_UNSIGNED_INT_24_8); 330 } 331 validators_.render_buffer_format.AddValue(GL_DEPTH24_STENCIL8); 332 } 333 334 if (extensions.Contains("GL_OES_vertex_array_object") || 335 extensions.Contains("GL_ARB_vertex_array_object") || 336 extensions.Contains("GL_APPLE_vertex_array_object")) { 337 feature_flags_.native_vertex_array_object = true; 338 } 339 340 // If we're using client_side_arrays we have to emulate 341 // vertex array objects since vertex array objects do not work 342 // with client side arrays. 343 if (workarounds_.use_client_side_arrays_for_stream_buffers) { 344 feature_flags_.native_vertex_array_object = false; 345 } 346 347 if (extensions.Contains("GL_OES_element_index_uint") || 348 gfx::HasDesktopGLFeatures()) { 349 AddExtensionString("GL_OES_element_index_uint"); 350 validators_.index_type.AddValue(GL_UNSIGNED_INT); 351 } 352 353 bool enable_texture_format_bgra8888 = false; 354 bool enable_read_format_bgra = false; 355 // Check if we should allow GL_EXT_texture_format_BGRA8888 356 if (extensions.Contains("GL_EXT_texture_format_BGRA8888") || 357 extensions.Contains("GL_APPLE_texture_format_BGRA8888") || 358 extensions.Contains("GL_EXT_bgra")) { 359 enable_texture_format_bgra8888 = true; 360 } 361 362 if (extensions.Contains("GL_EXT_bgra")) { 363 enable_texture_format_bgra8888 = true; 364 enable_read_format_bgra = true; 365 } 366 367 if (extensions.Contains("GL_EXT_read_format_bgra") || 368 extensions.Contains("GL_EXT_bgra")) { 369 enable_read_format_bgra = true; 370 } 371 372 if (enable_texture_format_bgra8888) { 373 AddExtensionString("GL_EXT_texture_format_BGRA8888"); 374 texture_format_validators_[GL_BGRA_EXT].AddValue(GL_UNSIGNED_BYTE); 375 validators_.texture_internal_format.AddValue(GL_BGRA_EXT); 376 validators_.texture_format.AddValue(GL_BGRA_EXT); 377 } 378 379 if (enable_read_format_bgra) { 380 AddExtensionString("GL_EXT_read_format_bgra"); 381 validators_.read_pixel_format.AddValue(GL_BGRA_EXT); 382 } 383 384 if (extensions.Contains("GL_OES_rgb8_rgba8") || gfx::HasDesktopGLFeatures()) { 385 AddExtensionString("GL_OES_rgb8_rgba8"); 386 validators_.render_buffer_format.AddValue(GL_RGB8_OES); 387 validators_.render_buffer_format.AddValue(GL_RGBA8_OES); 388 } 389 390 // Check if we should allow GL_OES_texture_npot 391 if (extensions.Contains("GL_ARB_texture_non_power_of_two") || 392 extensions.Contains("GL_OES_texture_npot")) { 393 AddExtensionString("GL_OES_texture_npot"); 394 npot_ok = true; 395 } 396 397 // Check if we should allow GL_OES_texture_float, GL_OES_texture_half_float, 398 // GL_OES_texture_float_linear, GL_OES_texture_half_float_linear 399 bool enable_texture_float = false; 400 bool enable_texture_float_linear = false; 401 bool enable_texture_half_float = false; 402 bool enable_texture_half_float_linear = false; 403 404 bool have_arb_texture_float = extensions.Contains("GL_ARB_texture_float"); 405 406 if (have_arb_texture_float) { 407 enable_texture_float = true; 408 enable_texture_float_linear = true; 409 enable_texture_half_float = true; 410 enable_texture_half_float_linear = true; 411 } else { 412 if (extensions.Contains("GL_OES_texture_float") || have_arb_texture_float) { 413 enable_texture_float = true; 414 if (extensions.Contains("GL_OES_texture_float_linear") || 415 have_arb_texture_float) { 416 enable_texture_float_linear = true; 417 } 418 } 419 if (extensions.Contains("GL_OES_texture_half_float") || 420 have_arb_texture_float) { 421 enable_texture_half_float = true; 422 if (extensions.Contains("GL_OES_texture_half_float_linear") || 423 have_arb_texture_float) { 424 enable_texture_half_float_linear = true; 425 } 426 } 427 } 428 429 if (enable_texture_float) { 430 texture_format_validators_[GL_ALPHA].AddValue(GL_FLOAT); 431 texture_format_validators_[GL_RGB].AddValue(GL_FLOAT); 432 texture_format_validators_[GL_RGBA].AddValue(GL_FLOAT); 433 texture_format_validators_[GL_LUMINANCE].AddValue(GL_FLOAT); 434 texture_format_validators_[GL_LUMINANCE_ALPHA].AddValue(GL_FLOAT); 435 validators_.pixel_type.AddValue(GL_FLOAT); 436 validators_.read_pixel_type.AddValue(GL_FLOAT); 437 AddExtensionString("GL_OES_texture_float"); 438 if (enable_texture_float_linear) { 439 AddExtensionString("GL_OES_texture_float_linear"); 440 } 441 } 442 443 if (enable_texture_half_float) { 444 texture_format_validators_[GL_ALPHA].AddValue(GL_HALF_FLOAT_OES); 445 texture_format_validators_[GL_RGB].AddValue(GL_HALF_FLOAT_OES); 446 texture_format_validators_[GL_RGBA].AddValue(GL_HALF_FLOAT_OES); 447 texture_format_validators_[GL_LUMINANCE].AddValue(GL_HALF_FLOAT_OES); 448 texture_format_validators_[GL_LUMINANCE_ALPHA].AddValue(GL_HALF_FLOAT_OES); 449 validators_.pixel_type.AddValue(GL_HALF_FLOAT_OES); 450 validators_.read_pixel_type.AddValue(GL_HALF_FLOAT_OES); 451 AddExtensionString("GL_OES_texture_half_float"); 452 if (enable_texture_half_float_linear) { 453 AddExtensionString("GL_OES_texture_half_float_linear"); 454 } 455 } 456 457 // Check for multisample support 458 if (!disallowed_features_.multisampling) { 459 bool ext_has_multisample = 460 extensions.Contains("GL_EXT_framebuffer_multisample"); 461 if (!workarounds_.disable_angle_framebuffer_multisample) { 462 ext_has_multisample |= 463 extensions.Contains("GL_ANGLE_framebuffer_multisample"); 464 } 465 if (ext_has_multisample) { 466 feature_flags_.chromium_framebuffer_multisample = true; 467 validators_.frame_buffer_target.AddValue(GL_READ_FRAMEBUFFER_EXT); 468 validators_.frame_buffer_target.AddValue(GL_DRAW_FRAMEBUFFER_EXT); 469 validators_.g_l_state.AddValue(GL_READ_FRAMEBUFFER_BINDING_EXT); 470 validators_.g_l_state.AddValue(GL_MAX_SAMPLES_EXT); 471 validators_.render_buffer_parameter.AddValue(GL_RENDERBUFFER_SAMPLES_EXT); 472 AddExtensionString("GL_CHROMIUM_framebuffer_multisample"); 473 } else { 474 if (extensions.Contains("GL_EXT_multisampled_render_to_texture")) { 475 feature_flags_.multisampled_render_to_texture = true; 476 } else if (extensions.Contains("GL_IMG_multisampled_render_to_texture")) { 477 feature_flags_.multisampled_render_to_texture = true; 478 feature_flags_.use_img_for_multisampled_render_to_texture = true; 479 } 480 if (feature_flags_.multisampled_render_to_texture) { 481 validators_.render_buffer_parameter.AddValue( 482 GL_RENDERBUFFER_SAMPLES_EXT); 483 validators_.g_l_state.AddValue(GL_MAX_SAMPLES_EXT); 484 validators_.frame_buffer_parameter.AddValue( 485 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT); 486 AddExtensionString("GL_EXT_multisampled_render_to_texture"); 487 } 488 } 489 } 490 491 if (extensions.Contains("GL_OES_depth24") || gfx::HasDesktopGLFeatures()) { 492 AddExtensionString("GL_OES_depth24"); 493 validators_.render_buffer_format.AddValue(GL_DEPTH_COMPONENT24); 494 } 495 496 if (!workarounds_.disable_oes_standard_derivatives && 497 (extensions.Contains("GL_OES_standard_derivatives") || 498 gfx::HasDesktopGLFeatures())) { 499 AddExtensionString("GL_OES_standard_derivatives"); 500 feature_flags_.oes_standard_derivatives = true; 501 validators_.hint_target.AddValue(GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES); 502 validators_.g_l_state.AddValue(GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES); 503 } 504 505 if (extensions.Contains("GL_OES_EGL_image_external")) { 506 AddExtensionString("GL_OES_EGL_image_external"); 507 feature_flags_.oes_egl_image_external = true; 508 validators_.texture_bind_target.AddValue(GL_TEXTURE_EXTERNAL_OES); 509 validators_.get_tex_param_target.AddValue(GL_TEXTURE_EXTERNAL_OES); 510 validators_.texture_parameter.AddValue(GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES); 511 validators_.g_l_state.AddValue(GL_TEXTURE_BINDING_EXTERNAL_OES); 512 } 513 514 if (extensions.Contains("GL_OES_compressed_ETC1_RGB8_texture")) { 515 AddExtensionString("GL_OES_compressed_ETC1_RGB8_texture"); 516 validators_.compressed_texture_format.AddValue(GL_ETC1_RGB8_OES); 517 } 518 519 // Ideally we would only expose this extension on Mac OS X, to 520 // support GL_CHROMIUM_iosurface and the compositor. We don't want 521 // applications to start using it; they should use ordinary non- 522 // power-of-two textures. However, for unit testing purposes we 523 // expose it on all supported platforms. 524 if (extensions.Contains("GL_ARB_texture_rectangle")) { 525 AddExtensionString("GL_ARB_texture_rectangle"); 526 feature_flags_.arb_texture_rectangle = true; 527 validators_.texture_bind_target.AddValue(GL_TEXTURE_RECTANGLE_ARB); 528 // For the moment we don't add this enum to the texture_target 529 // validator. This implies that the only way to get image data into a 530 // rectangular texture is via glTexImageIOSurface2DCHROMIUM, which is 531 // just fine since again we don't want applications depending on this 532 // extension. 533 validators_.get_tex_param_target.AddValue(GL_TEXTURE_RECTANGLE_ARB); 534 validators_.g_l_state.AddValue(GL_TEXTURE_BINDING_RECTANGLE_ARB); 535 } 536 537 #if defined(OS_MACOSX) 538 if (IOSurfaceSupport::Initialize()) { 539 AddExtensionString("GL_CHROMIUM_iosurface"); 540 } 541 #endif 542 543 // TODO(gman): Add support for these extensions. 544 // GL_OES_depth32 545 546 feature_flags_.enable_texture_float_linear |= enable_texture_float_linear; 547 feature_flags_.enable_texture_half_float_linear |= 548 enable_texture_half_float_linear; 549 feature_flags_.npot_ok |= npot_ok; 550 551 if (extensions.Contains("GL_ANGLE_pack_reverse_row_order")) { 552 AddExtensionString("GL_ANGLE_pack_reverse_row_order"); 553 feature_flags_.angle_pack_reverse_row_order = true; 554 validators_.pixel_store.AddValue(GL_PACK_REVERSE_ROW_ORDER_ANGLE); 555 validators_.g_l_state.AddValue(GL_PACK_REVERSE_ROW_ORDER_ANGLE); 556 } 557 558 if (extensions.Contains("GL_ANGLE_texture_usage")) { 559 AddExtensionString("GL_ANGLE_texture_usage"); 560 validators_.texture_parameter.AddValue(GL_TEXTURE_USAGE_ANGLE); 561 } 562 563 if (extensions.Contains("GL_EXT_texture_storage")) { 564 AddExtensionString("GL_EXT_texture_storage"); 565 validators_.texture_parameter.AddValue(GL_TEXTURE_IMMUTABLE_FORMAT_EXT); 566 if (enable_texture_format_bgra8888) 567 validators_.texture_internal_format_storage.AddValue(GL_BGRA8_EXT); 568 if (enable_texture_float) { 569 validators_.texture_internal_format_storage.AddValue(GL_RGBA32F_EXT); 570 validators_.texture_internal_format_storage.AddValue(GL_RGB32F_EXT); 571 validators_.texture_internal_format_storage.AddValue(GL_ALPHA32F_EXT); 572 validators_.texture_internal_format_storage.AddValue( 573 GL_LUMINANCE32F_EXT); 574 validators_.texture_internal_format_storage.AddValue( 575 GL_LUMINANCE_ALPHA32F_EXT); 576 } 577 if (enable_texture_half_float) { 578 validators_.texture_internal_format_storage.AddValue(GL_RGBA16F_EXT); 579 validators_.texture_internal_format_storage.AddValue(GL_RGB16F_EXT); 580 validators_.texture_internal_format_storage.AddValue(GL_ALPHA16F_EXT); 581 validators_.texture_internal_format_storage.AddValue( 582 GL_LUMINANCE16F_EXT); 583 validators_.texture_internal_format_storage.AddValue( 584 GL_LUMINANCE_ALPHA16F_EXT); 585 } 586 } 587 588 bool have_ext_occlusion_query_boolean = 589 extensions.Contains("GL_EXT_occlusion_query_boolean"); 590 bool have_arb_occlusion_query2 = 591 extensions.Contains("GL_ARB_occlusion_query2"); 592 bool have_arb_occlusion_query = 593 extensions.Contains("GL_ARB_occlusion_query"); 594 595 if (!workarounds_.disable_ext_occlusion_query && 596 (have_ext_occlusion_query_boolean || 597 have_arb_occlusion_query2 || 598 have_arb_occlusion_query)) { 599 AddExtensionString("GL_EXT_occlusion_query_boolean"); 600 feature_flags_.occlusion_query_boolean = true; 601 feature_flags_.use_arb_occlusion_query2_for_occlusion_query_boolean = 602 !have_ext_occlusion_query_boolean && have_arb_occlusion_query2; 603 feature_flags_.use_arb_occlusion_query_for_occlusion_query_boolean = 604 !have_ext_occlusion_query_boolean && have_arb_occlusion_query && 605 !have_arb_occlusion_query2; 606 } 607 608 if (!workarounds_.disable_angle_instanced_arrays && 609 (extensions.Contains("GL_ANGLE_instanced_arrays") || 610 (extensions.Contains("GL_ARB_instanced_arrays") && 611 extensions.Contains("GL_ARB_draw_instanced")))) { 612 AddExtensionString("GL_ANGLE_instanced_arrays"); 613 feature_flags_.angle_instanced_arrays = true; 614 validators_.vertex_attribute.AddValue(GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE); 615 } 616 617 if (!workarounds_.disable_ext_draw_buffers && 618 (extensions.Contains("GL_ARB_draw_buffers") || 619 extensions.Contains("GL_EXT_draw_buffers"))) { 620 AddExtensionString("GL_EXT_draw_buffers"); 621 feature_flags_.ext_draw_buffers = true; 622 623 GLint max_color_attachments = 0; 624 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &max_color_attachments); 625 for (GLenum i = GL_COLOR_ATTACHMENT1_EXT; 626 i < static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + max_color_attachments); 627 ++i) { 628 validators_.attachment.AddValue(i); 629 } 630 631 validators_.g_l_state.AddValue(GL_MAX_COLOR_ATTACHMENTS_EXT); 632 validators_.g_l_state.AddValue(GL_MAX_DRAW_BUFFERS_ARB); 633 GLint max_draw_buffers = 0; 634 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &max_draw_buffers); 635 for (GLenum i = GL_DRAW_BUFFER0_ARB; 636 i < static_cast<GLenum>(GL_DRAW_BUFFER0_ARB + max_draw_buffers); 637 ++i) { 638 validators_.g_l_state.AddValue(i); 639 } 640 } 641 642 if (extensions.Contains("GL_EXT_frag_depth") || gfx::HasDesktopGLFeatures()) { 643 AddExtensionString("GL_EXT_frag_depth"); 644 feature_flags_.ext_frag_depth = true; 645 } 646 647 bool ui_gl_fence_works = 648 extensions.Contains("GL_NV_fence") || 649 extensions.Contains("GL_ARB_sync"); 650 651 if (ui_gl_fence_works && 652 extensions.Contains("GL_ARB_pixel_buffer_object") && 653 !workarounds_.disable_async_readpixels) { 654 feature_flags_.use_async_readpixels = true; 655 } 656 657 if (!disallowed_features_.swap_buffer_complete_callback) 658 AddExtensionString("GL_CHROMIUM_swapbuffers_complete_callback"); 659 660 bool is_es3 = false; 661 const char* str = reinterpret_cast<const char*>(glGetString(GL_VERSION)); 662 if (str) { 663 std::string lstr(StringToLowerASCII(std::string(str))); 664 is_es3 = (lstr.substr(0, 12) == "opengl es 3."); 665 } 666 667 if (is_es3 || extensions.Contains("GL_ARB_sampler_objects")) { 668 feature_flags_.enable_samplers = true; 669 // TODO(dsinclair): Add AddExtensionString("GL_CHROMIUM_sampler_objects") 670 // when available. 671 } 672 } 673 674 void FeatureInfo::AddExtensionString(const std::string& str) { 675 if (extensions_.find(str) == std::string::npos) { 676 extensions_ += (extensions_.empty() ? "" : " ") + str; 677 } 678 } 679 680 FeatureInfo::~FeatureInfo() { 681 } 682 683 } // namespace gles2 684 } // namespace gpu 685