blob: 231fda460b616406a52310a740268a03e6f228b2 [file] [log] [blame]
junov0cad1f42016-01-07 21:48:511// Copyright (c) 2016 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/gl_utils.h"
6
brettw1ce49f62017-04-27 19:42:327#include <unordered_set>
8
junov0cad1f42016-01-07 21:48:519#include "base/metrics/histogram.h"
geofflang124fd552016-09-08 20:02:5510#include "gpu/command_buffer/common/capabilities.h"
11#include "gpu/command_buffer/service/feature_info.h"
12#include "ui/gl/gl_version_info.h"
junov0cad1f42016-01-07 21:48:5113
14namespace gpu {
15namespace gles2 {
16
geofflang326c8512016-11-03 15:11:2817namespace {
18const char* GetDebugSourceString(GLenum source) {
19 switch (source) {
20 case GL_DEBUG_SOURCE_API:
21 return "OpenGL";
22 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
23 return "Window System";
24 case GL_DEBUG_SOURCE_SHADER_COMPILER:
25 return "Shader Compiler";
26 case GL_DEBUG_SOURCE_THIRD_PARTY:
27 return "Third Party";
28 case GL_DEBUG_SOURCE_APPLICATION:
29 return "Application";
30 case GL_DEBUG_SOURCE_OTHER:
31 return "Other";
32 default:
33 return "UNKNOWN";
34 }
35}
36
37const char* GetDebugTypeString(GLenum type) {
38 switch (type) {
39 case GL_DEBUG_TYPE_ERROR:
40 return "Error";
41 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
42 return "Deprecated behavior";
43 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
44 return "Undefined behavior";
45 case GL_DEBUG_TYPE_PORTABILITY:
46 return "Portability";
47 case GL_DEBUG_TYPE_PERFORMANCE:
48 return "Performance";
49 case GL_DEBUG_TYPE_OTHER:
50 return "Other";
51 case GL_DEBUG_TYPE_MARKER:
52 return "Marker";
53 default:
54 return "UNKNOWN";
55 }
56}
57
58const char* GetDebugSeverityString(GLenum severity) {
59 switch (severity) {
60 case GL_DEBUG_SEVERITY_HIGH:
61 return "High";
62 case GL_DEBUG_SEVERITY_MEDIUM:
63 return "Medium";
64 case GL_DEBUG_SEVERITY_LOW:
65 return "Low";
66 case GL_DEBUG_SEVERITY_NOTIFICATION:
67 return "Notification";
68 default:
69 return "UNKNOWN";
70 }
71}
72}
73
junov0cad1f42016-01-07 21:48:5174std::vector<int> GetAllGLErrors() {
75 int gl_errors[] = {
76 GL_NO_ERROR,
77 GL_INVALID_ENUM,
78 GL_INVALID_VALUE,
79 GL_INVALID_OPERATION,
80 GL_INVALID_FRAMEBUFFER_OPERATION,
81 GL_OUT_OF_MEMORY,
82 };
83 return base::CustomHistogram::ArrayToCustomRanges(gl_errors,
84 arraysize(gl_errors));
85}
86
geofflang124fd552016-09-08 20:02:5587bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
88 GLint rangeMax,
89 GLint precision) {
90 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
91}
92
93void QueryShaderPrecisionFormat(const gl::GLVersionInfo& gl_version_info,
94 GLenum shader_type,
95 GLenum precision_type,
96 GLint* range,
97 GLint* precision) {
98 switch (precision_type) {
99 case GL_LOW_INT:
100 case GL_MEDIUM_INT:
101 case GL_HIGH_INT:
102 // These values are for a 32-bit twos-complement integer format.
103 range[0] = 31;
104 range[1] = 30;
105 *precision = 0;
106 break;
107 case GL_LOW_FLOAT:
108 case GL_MEDIUM_FLOAT:
109 case GL_HIGH_FLOAT:
110 // These values are for an IEEE single-precision floating-point format.
111 range[0] = 127;
112 range[1] = 127;
113 *precision = 23;
114 break;
115 default:
116 NOTREACHED();
117 break;
118 }
119
120 if (gl_version_info.is_es) {
121 // This function is sometimes defined even though it's really just
122 // a stub, so we need to set range and precision as if it weren't
123 // defined before calling it.
124 // On Mac OS with some GPUs, calling this generates a
125 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
126 // platforms.
127 glGetShaderPrecisionFormat(shader_type, precision_type, range, precision);
128
129 // TODO(brianderson): Make the following official workarounds.
130
131 // Some drivers have bugs where they report the ranges as a negative number.
132 // Taking the absolute value here shouldn't hurt because negative numbers
133 // aren't expected anyway.
134 range[0] = abs(range[0]);
135 range[1] = abs(range[1]);
136
137 // If the driver reports a precision for highp float that isn't actually
138 // highp, don't pretend like it's supported because shader compilation will
139 // fail anyway.
140 if (precision_type == GL_HIGH_FLOAT &&
141 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
142 range[0] = 0;
143 range[1] = 0;
144 *precision = 0;
145 }
146 }
147}
148
149void PopulateNumericCapabilities(Capabilities* caps,
150 const FeatureInfo* feature_info) {
151 DCHECK(caps != nullptr);
152
153 const gl::GLVersionInfo& version_info = feature_info->gl_version_info();
154 caps->VisitPrecisions([&version_info](
155 GLenum shader, GLenum type,
156 Capabilities::ShaderPrecision* shader_precision) {
157 GLint range[2] = {0, 0};
158 GLint precision = 0;
159 QueryShaderPrecisionFormat(version_info, shader, type, range, &precision);
160 shader_precision->min_range = range[0];
161 shader_precision->max_range = range[1];
162 shader_precision->precision = precision;
163 });
164
165 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
166 &caps->max_combined_texture_image_units);
167 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &caps->max_cube_map_texture_size);
168 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
169 &caps->max_fragment_uniform_vectors);
170 glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &caps->max_renderbuffer_size);
171 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &caps->max_texture_image_units);
172 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps->max_texture_size);
173 glGetIntegerv(GL_MAX_VARYING_VECTORS, &caps->max_varying_vectors);
174 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps->max_vertex_attribs);
175 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
176 &caps->max_vertex_texture_image_units);
177 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
178 &caps->max_vertex_uniform_vectors);
zmoc95386fb2016-12-09 23:48:55179 {
180 GLint dims[2] = {0, 0};
181 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
182 caps->max_viewport_width = dims[0];
183 caps->max_viewport_height = dims[1];
184 }
geofflang124fd552016-09-08 20:02:55185 glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS,
186 &caps->num_compressed_texture_formats);
187 glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps->num_shader_binary_formats);
188
kaininoe20d23ac2016-11-03 01:03:45189 if (feature_info->IsWebGL2OrES3Context()) {
geofflang124fd552016-09-08 20:02:55190 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &caps->max_3d_texture_size);
191 glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &caps->max_array_texture_layers);
192 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &caps->max_color_attachments);
193 glGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS,
194 &caps->max_combined_fragment_uniform_components);
195 glGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS,
196 &caps->max_combined_uniform_blocks);
197 glGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS,
198 &caps->max_combined_vertex_uniform_components);
199 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &caps->max_draw_buffers);
200 glGetInteger64v(GL_MAX_ELEMENT_INDEX, &caps->max_element_index);
201 glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &caps->max_elements_indices);
202 glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &caps->max_elements_vertices);
203 glGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS,
204 &caps->max_fragment_input_components);
205 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS,
206 &caps->max_fragment_uniform_blocks);
207 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,
208 &caps->max_fragment_uniform_components);
209 glGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET, &caps->max_program_texel_offset);
210 glGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT, &caps->max_server_wait_timeout);
211 glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &caps->max_texture_lod_bias);
212 glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
213 &caps->max_transform_feedback_interleaved_components);
214 glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
215 &caps->max_transform_feedback_separate_attribs);
216 glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,
217 &caps->max_transform_feedback_separate_components);
218 glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &caps->max_uniform_block_size);
219 glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS,
220 &caps->max_uniform_buffer_bindings);
221 glGetIntegerv(GL_MAX_VARYING_COMPONENTS, &caps->max_varying_components);
222 glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS,
223 &caps->max_vertex_output_components);
224 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS,
225 &caps->max_vertex_uniform_blocks);
226 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS,
227 &caps->max_vertex_uniform_components);
228 glGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &caps->min_program_texel_offset);
229 glGetIntegerv(GL_NUM_EXTENSIONS, &caps->num_extensions);
230 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS,
231 &caps->num_program_binary_formats);
232 glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
233 &caps->uniform_buffer_offset_alignment);
234 caps->major_version = 3;
235 caps->minor_version = 0;
236 }
237 if (feature_info->feature_flags().multisampled_render_to_texture ||
238 feature_info->feature_flags().chromium_framebuffer_multisample ||
kaininoe20d23ac2016-11-03 01:03:45239 feature_info->IsWebGL2OrES3Context()) {
geofflang124fd552016-09-08 20:02:55240 glGetIntegerv(GL_MAX_SAMPLES, &caps->max_samples);
241 }
242}
243
geofflang851a4812016-09-14 19:20:29244bool CheckUniqueAndNonNullIds(GLsizei n, const GLuint* client_ids) {
245 if (n <= 0)
246 return true;
247 std::unordered_set<uint32_t> unique_ids(client_ids, client_ids + n);
248 return (unique_ids.size() == static_cast<size_t>(n)) &&
249 (unique_ids.find(0) == unique_ids.end());
250}
251
geofflang67c1fca2016-11-15 21:18:09252const char* GetServiceVersionString(const FeatureInfo* feature_info) {
253 if (feature_info->IsWebGL2OrES3Context())
254 return "OpenGL ES 3.0 Chromium";
255 else
256 return "OpenGL ES 2.0 Chromium";
257}
258
259const char* GetServiceShadingLanguageVersionString(
260 const FeatureInfo* feature_info) {
261 if (feature_info->IsWebGL2OrES3Context())
262 return "OpenGL ES GLSL ES 3.0 Chromium";
263 else
264 return "OpenGL ES GLSL ES 1.0 Chromium";
265}
266
geofflang326c8512016-11-03 15:11:28267void APIENTRY LogGLDebugMessage(GLenum source,
268 GLenum type,
269 GLuint id,
270 GLenum severity,
271 GLsizei length,
272 const GLchar* message,
273 GLvoid* user_param) {
274 LOG(ERROR) << "GL Driver Message (" << GetDebugSourceString(source) << ", "
275 << GetDebugTypeString(type) << ", " << id << ", "
276 << GetDebugSeverityString(severity) << "): " << message;
277}
278
279void InitializeGLDebugLogging() {
280 glEnable(GL_DEBUG_OUTPUT);
281 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
282
283 // Enable logging of medium and high severity messages
284 glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0,
285 nullptr, GL_TRUE);
286 glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM, 0,
287 nullptr, GL_TRUE);
288 glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW, 0,
289 nullptr, GL_FALSE);
290 glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE,
291 GL_DEBUG_SEVERITY_NOTIFICATION, 0, nullptr, GL_FALSE);
292
293 glDebugMessageCallback(&LogGLDebugMessage, nullptr);
294}
295
junov0cad1f42016-01-07 21:48:51296} // namespace gles2
297} // namespace gpu