Index: gpu/command_buffer/service/gl_utils.cc |
diff --git a/gpu/command_buffer/service/gl_utils.cc b/gpu/command_buffer/service/gl_utils.cc |
index bb8ce4b013d601c51b63b3ba9861eedadd8b04cb..8fca5d4b82b6a118ae9dbdf2b930be28f1935f82 100644 |
--- a/gpu/command_buffer/service/gl_utils.cc |
+++ b/gpu/command_buffer/service/gl_utils.cc |
@@ -5,6 +5,9 @@ |
#include "gpu/command_buffer/service/gl_utils.h" |
#include "base/metrics/histogram.h" |
+#include "gpu/command_buffer/common/capabilities.h" |
+#include "gpu/command_buffer/service/feature_info.h" |
+#include "ui/gl/gl_version_info.h" |
namespace gpu { |
namespace gles2 { |
@@ -22,5 +25,156 @@ std::vector<int> GetAllGLErrors() { |
arraysize(gl_errors)); |
} |
+bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin, |
+ GLint rangeMax, |
+ GLint precision) { |
+ return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16); |
+} |
+ |
+void QueryShaderPrecisionFormat(const gl::GLVersionInfo& gl_version_info, |
+ GLenum shader_type, |
+ GLenum precision_type, |
+ GLint* range, |
+ GLint* precision) { |
+ switch (precision_type) { |
+ case GL_LOW_INT: |
+ case GL_MEDIUM_INT: |
+ case GL_HIGH_INT: |
+ // These values are for a 32-bit twos-complement integer format. |
+ range[0] = 31; |
+ range[1] = 30; |
+ *precision = 0; |
+ break; |
+ case GL_LOW_FLOAT: |
+ case GL_MEDIUM_FLOAT: |
+ case GL_HIGH_FLOAT: |
+ // These values are for an IEEE single-precision floating-point format. |
+ range[0] = 127; |
+ range[1] = 127; |
+ *precision = 23; |
+ break; |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+ |
+ if (gl_version_info.is_es) { |
+ // This function is sometimes defined even though it's really just |
+ // a stub, so we need to set range and precision as if it weren't |
+ // defined before calling it. |
+ // On Mac OS with some GPUs, calling this generates a |
+ // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2 |
+ // platforms. |
+ glGetShaderPrecisionFormat(shader_type, precision_type, range, precision); |
+ |
+ // TODO(brianderson): Make the following official workarounds. |
+ |
+ // Some drivers have bugs where they report the ranges as a negative number. |
+ // Taking the absolute value here shouldn't hurt because negative numbers |
+ // aren't expected anyway. |
+ range[0] = abs(range[0]); |
+ range[1] = abs(range[1]); |
+ |
+ // If the driver reports a precision for highp float that isn't actually |
+ // highp, don't pretend like it's supported because shader compilation will |
+ // fail anyway. |
+ if (precision_type == GL_HIGH_FLOAT && |
+ !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) { |
+ range[0] = 0; |
+ range[1] = 0; |
+ *precision = 0; |
+ } |
+ } |
+} |
+ |
+void PopulateNumericCapabilities(Capabilities* caps, |
+ const FeatureInfo* feature_info) { |
+ DCHECK(caps != nullptr); |
+ |
+ const gl::GLVersionInfo& version_info = feature_info->gl_version_info(); |
+ caps->VisitPrecisions([&version_info]( |
+ GLenum shader, GLenum type, |
+ Capabilities::ShaderPrecision* shader_precision) { |
+ GLint range[2] = {0, 0}; |
+ GLint precision = 0; |
+ QueryShaderPrecisionFormat(version_info, shader, type, range, &precision); |
+ shader_precision->min_range = range[0]; |
+ shader_precision->max_range = range[1]; |
+ shader_precision->precision = precision; |
+ }); |
+ |
+ glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, |
+ &caps->max_combined_texture_image_units); |
+ glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &caps->max_cube_map_texture_size); |
+ glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, |
+ &caps->max_fragment_uniform_vectors); |
+ glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &caps->max_renderbuffer_size); |
+ glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &caps->max_texture_image_units); |
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps->max_texture_size); |
+ glGetIntegerv(GL_MAX_VARYING_VECTORS, &caps->max_varying_vectors); |
+ glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps->max_vertex_attribs); |
+ glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, |
+ &caps->max_vertex_texture_image_units); |
+ glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, |
+ &caps->max_vertex_uniform_vectors); |
+ glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, |
+ &caps->num_compressed_texture_formats); |
+ glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps->num_shader_binary_formats); |
+ |
+ if (feature_info->IsES3Enabled()) { |
+ glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &caps->max_3d_texture_size); |
+ glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &caps->max_array_texture_layers); |
+ glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &caps->max_color_attachments); |
+ glGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS, |
+ &caps->max_combined_fragment_uniform_components); |
+ glGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS, |
+ &caps->max_combined_uniform_blocks); |
+ glGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS, |
+ &caps->max_combined_vertex_uniform_components); |
+ glGetIntegerv(GL_MAX_DRAW_BUFFERS, &caps->max_draw_buffers); |
+ glGetInteger64v(GL_MAX_ELEMENT_INDEX, &caps->max_element_index); |
+ glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &caps->max_elements_indices); |
+ glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &caps->max_elements_vertices); |
+ glGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, |
+ &caps->max_fragment_input_components); |
+ glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, |
+ &caps->max_fragment_uniform_blocks); |
+ glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, |
+ &caps->max_fragment_uniform_components); |
+ glGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET, &caps->max_program_texel_offset); |
+ glGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT, &caps->max_server_wait_timeout); |
+ glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &caps->max_texture_lod_bias); |
+ glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, |
+ &caps->max_transform_feedback_interleaved_components); |
+ glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, |
+ &caps->max_transform_feedback_separate_attribs); |
+ glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, |
+ &caps->max_transform_feedback_separate_components); |
+ glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &caps->max_uniform_block_size); |
+ glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, |
+ &caps->max_uniform_buffer_bindings); |
+ glGetIntegerv(GL_MAX_VARYING_COMPONENTS, &caps->max_varying_components); |
+ glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, |
+ &caps->max_vertex_output_components); |
+ glGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS, |
+ &caps->max_vertex_uniform_blocks); |
+ glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, |
+ &caps->max_vertex_uniform_components); |
+ glGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &caps->min_program_texel_offset); |
+ glGetIntegerv(GL_NUM_EXTENSIONS, &caps->num_extensions); |
+ glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, |
+ &caps->num_program_binary_formats); |
+ glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, |
+ &caps->uniform_buffer_offset_alignment); |
+ caps->major_version = 3; |
+ caps->minor_version = 0; |
+ } |
+ if (feature_info->feature_flags().multisampled_render_to_texture || |
+ feature_info->feature_flags().chromium_framebuffer_multisample || |
+ feature_info->IsES3Enabled()) { |
+ glGetIntegerv(GL_MAX_SAMPLES, &caps->max_samples); |
+ } |
+} |
+ |
} // namespace gles2 |
} // namespace gpu |