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