1 // 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
7 #include <algorithm>
8 #include <unordered_set>
9
10 #include "gpu/command_buffer/common/capabilities.h"
11 #include "gpu/command_buffer/service/error_state.h"
12 #include "gpu/command_buffer/service/feature_info.h"
13 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
14 #include "gpu/command_buffer/service/logger.h"
15 #include "gpu/command_buffer/service/texture_manager.h"
16 #include "ui/gl/gl_version_info.h"
17
18 namespace gpu {
19 namespace gles2 {
20
21 namespace {
22
23 const int kASTCBlockSize = 16;
24 const int kS3TCBlockWidth = 4;
25 const int kS3TCBlockHeight = 4;
26 const int kS3TCDXT1BlockSize = 8;
27 const int kS3TCDXT3AndDXT5BlockSize = 16;
28 const int kEACAndETC2BlockSize = 4;
29 const int kBPTCBlockWidth = 4;
30 const int kBPTCBlockHeight = 4;
31 const int kRGTCBlockWidth = 4;
32 const int kRGTCBlockHeight = 4;
33
34 typedef struct {
35 int blockWidth;
36 int blockHeight;
37 } ASTCBlockArray;
38
39 const ASTCBlockArray kASTCBlockArray[] = {
40 {4, 4}, /* GL_COMPRESSED_RGBA_ASTC_4x4_KHR */
41 {5, 4}, /* and GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR */
42 {5, 5}, {6, 5}, {6, 6}, {8, 5}, {8, 6}, {8, 8},
43 {10, 5}, {10, 6}, {10, 8}, {10, 10}, {12, 10}, {12, 12}};
44
IsValidPVRTCSize(GLint level,GLsizei size)45 bool IsValidPVRTCSize(GLint level, GLsizei size) {
46 return GLES2Util::IsPOT(size);
47 }
48
IsValidS3TCSizeForWebGLAndANGLE(GLint level,GLsizei size)49 bool IsValidS3TCSizeForWebGLAndANGLE(GLint level, GLsizei size) {
50 // WebGL and ANGLE only allow multiple-of-4 sizes, except for levels > 0 where
51 // it also allows 1 or 2. See WEBGL_compressed_texture_s3tc and
52 // ANGLE_compressed_texture_dxt*
53 return (level && size == 1) || (level && size == 2) ||
54 !(size % kS3TCBlockWidth);
55 }
56
GetDebugSourceString(GLenum source)57 const char* GetDebugSourceString(GLenum source) {
58 switch (source) {
59 case GL_DEBUG_SOURCE_API:
60 return "OpenGL";
61 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
62 return "Window System";
63 case GL_DEBUG_SOURCE_SHADER_COMPILER:
64 return "Shader Compiler";
65 case GL_DEBUG_SOURCE_THIRD_PARTY:
66 return "Third Party";
67 case GL_DEBUG_SOURCE_APPLICATION:
68 return "Application";
69 case GL_DEBUG_SOURCE_OTHER:
70 return "Other";
71 default:
72 return "UNKNOWN";
73 }
74 }
75
GetDebugTypeString(GLenum type)76 const char* GetDebugTypeString(GLenum type) {
77 switch (type) {
78 case GL_DEBUG_TYPE_ERROR:
79 return "Error";
80 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
81 return "Deprecated behavior";
82 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
83 return "Undefined behavior";
84 case GL_DEBUG_TYPE_PORTABILITY:
85 return "Portability";
86 case GL_DEBUG_TYPE_PERFORMANCE:
87 return "Performance";
88 case GL_DEBUG_TYPE_OTHER:
89 return "Other";
90 case GL_DEBUG_TYPE_MARKER:
91 return "Marker";
92 default:
93 return "UNKNOWN";
94 }
95 }
96
GetDebugSeverityString(GLenum severity)97 const char* GetDebugSeverityString(GLenum severity) {
98 switch (severity) {
99 case GL_DEBUG_SEVERITY_HIGH:
100 return "High";
101 case GL_DEBUG_SEVERITY_MEDIUM:
102 return "Medium";
103 case GL_DEBUG_SEVERITY_LOW:
104 return "Low";
105 case GL_DEBUG_SEVERITY_NOTIFICATION:
106 return "Notification";
107 default:
108 return "UNKNOWN";
109 }
110 }
111 } // namespace
112
PrecisionMeetsSpecForHighpFloat(GLint rangeMin,GLint rangeMax,GLint precision)113 bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
114 GLint rangeMax,
115 GLint precision) {
116 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
117 }
118
QueryShaderPrecisionFormat(const gl::GLVersionInfo & gl_version_info,GLenum shader_type,GLenum precision_type,GLint * range,GLint * precision)119 void QueryShaderPrecisionFormat(const gl::GLVersionInfo& gl_version_info,
120 GLenum shader_type,
121 GLenum precision_type,
122 GLint* range,
123 GLint* precision) {
124 switch (precision_type) {
125 case GL_LOW_INT:
126 case GL_MEDIUM_INT:
127 case GL_HIGH_INT:
128 // These values are for a 32-bit twos-complement integer format.
129 range[0] = 31;
130 range[1] = 30;
131 *precision = 0;
132 break;
133 case GL_LOW_FLOAT:
134 case GL_MEDIUM_FLOAT:
135 case GL_HIGH_FLOAT:
136 // These values are for an IEEE single-precision floating-point format.
137 range[0] = 127;
138 range[1] = 127;
139 *precision = 23;
140 break;
141 default:
142 NOTREACHED();
143 break;
144 }
145
146 if (gl_version_info.is_es) {
147 // This function is sometimes defined even though it's really just
148 // a stub, so we need to set range and precision as if it weren't
149 // defined before calling it.
150 // On Mac OS with some GPUs, calling this generates a
151 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
152 // platforms.
153 glGetShaderPrecisionFormat(shader_type, precision_type, range, precision);
154
155 // TODO(brianderson): Make the following official workarounds.
156
157 // Some drivers have bugs where they report the ranges as a negative number.
158 // Taking the absolute value here shouldn't hurt because negative numbers
159 // aren't expected anyway.
160 range[0] = abs(range[0]);
161 range[1] = abs(range[1]);
162
163 // If the driver reports a precision for highp float that isn't actually
164 // highp, don't pretend like it's supported because shader compilation will
165 // fail anyway.
166 if (precision_type == GL_HIGH_FLOAT &&
167 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
168 range[0] = 0;
169 range[1] = 0;
170 *precision = 0;
171 }
172 }
173 }
174
PopulateNumericCapabilities(Capabilities * caps,const FeatureInfo * feature_info)175 void PopulateNumericCapabilities(Capabilities* caps,
176 const FeatureInfo* feature_info) {
177 DCHECK(caps != nullptr);
178
179 const gl::GLVersionInfo& version_info = feature_info->gl_version_info();
180 caps->VisitPrecisions([&version_info](
181 GLenum shader, GLenum type,
182 Capabilities::ShaderPrecision* shader_precision) {
183 GLint range[2] = {0, 0};
184 GLint precision = 0;
185 QueryShaderPrecisionFormat(version_info, shader, type, range, &precision);
186 shader_precision->min_range = range[0];
187 shader_precision->max_range = range[1];
188 shader_precision->precision = precision;
189 });
190
191 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
192 &caps->max_combined_texture_image_units);
193 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &caps->max_cube_map_texture_size);
194 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
195 &caps->max_fragment_uniform_vectors);
196 glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &caps->max_renderbuffer_size);
197 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &caps->max_texture_image_units);
198 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps->max_texture_size);
199 glGetIntegerv(GL_MAX_VARYING_VECTORS, &caps->max_varying_vectors);
200 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps->max_vertex_attribs);
201 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
202 &caps->max_vertex_texture_image_units);
203 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
204 &caps->max_vertex_uniform_vectors);
205 {
206 GLint dims[2] = {0, 0};
207 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
208 caps->max_viewport_width = dims[0];
209 caps->max_viewport_height = dims[1];
210 }
211 glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS,
212 &caps->num_compressed_texture_formats);
213 glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps->num_shader_binary_formats);
214
215 if (feature_info->IsWebGL2OrES3OrHigherContext()) {
216 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &caps->max_3d_texture_size);
217 glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &caps->max_array_texture_layers);
218 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &caps->max_color_attachments);
219 glGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS,
220 &caps->max_combined_fragment_uniform_components);
221 glGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS,
222 &caps->max_combined_uniform_blocks);
223 glGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS,
224 &caps->max_combined_vertex_uniform_components);
225 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &caps->max_draw_buffers);
226 glGetInteger64v(GL_MAX_ELEMENT_INDEX, &caps->max_element_index);
227 glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &caps->max_elements_indices);
228 glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &caps->max_elements_vertices);
229 glGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS,
230 &caps->max_fragment_input_components);
231 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS,
232 &caps->max_fragment_uniform_blocks);
233 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,
234 &caps->max_fragment_uniform_components);
235 glGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET, &caps->max_program_texel_offset);
236 glGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT, &caps->max_server_wait_timeout);
237 glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &caps->max_texture_lod_bias);
238 glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
239 &caps->max_transform_feedback_interleaved_components);
240 glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
241 &caps->max_transform_feedback_separate_attribs);
242 glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,
243 &caps->max_transform_feedback_separate_components);
244 glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &caps->max_uniform_block_size);
245 glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS,
246 &caps->max_uniform_buffer_bindings);
247 glGetIntegerv(GL_MAX_VARYING_COMPONENTS, &caps->max_varying_components);
248 glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS,
249 &caps->max_vertex_output_components);
250 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS,
251 &caps->max_vertex_uniform_blocks);
252 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS,
253 &caps->max_vertex_uniform_components);
254 glGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &caps->min_program_texel_offset);
255 glGetIntegerv(GL_NUM_EXTENSIONS, &caps->num_extensions);
256 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS,
257 &caps->num_program_binary_formats);
258 glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
259 &caps->uniform_buffer_offset_alignment);
260 caps->major_version = 3;
261 if (feature_info->IsWebGL2ComputeContext()) {
262 glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS,
263 &caps->max_atomic_counter_buffer_bindings);
264 glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS,
265 &caps->max_shader_storage_buffer_bindings);
266 glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT,
267 &caps->shader_storage_buffer_offset_alignment);
268 caps->minor_version = 1;
269 } else {
270 caps->minor_version = 0;
271 }
272 }
273 if (feature_info->feature_flags().multisampled_render_to_texture ||
274 feature_info->feature_flags().chromium_framebuffer_multisample ||
275 feature_info->IsWebGL2OrES3OrHigherContext()) {
276 glGetIntegerv(GL_MAX_SAMPLES, &caps->max_samples);
277 }
278 }
279
CheckUniqueAndNonNullIds(GLsizei n,const GLuint * client_ids)280 bool CheckUniqueAndNonNullIds(GLsizei n, const GLuint* client_ids) {
281 if (n <= 0)
282 return true;
283 std::unordered_set<uint32_t> unique_ids(client_ids, client_ids + n);
284 return (unique_ids.size() == static_cast<size_t>(n)) &&
285 (unique_ids.find(0) == unique_ids.end());
286 }
287
GetServiceVersionString(const FeatureInfo * feature_info)288 const char* GetServiceVersionString(const FeatureInfo* feature_info) {
289 if (feature_info->IsWebGL2OrES3Context())
290 return "OpenGL ES 3.0 Chromium";
291 else if (feature_info->IsWebGL2ComputeContext()) {
292 return "OpenGL ES 3.1 Chromium";
293 } else
294 return "OpenGL ES 2.0 Chromium";
295 }
296
GetServiceShadingLanguageVersionString(const FeatureInfo * feature_info)297 const char* GetServiceShadingLanguageVersionString(
298 const FeatureInfo* feature_info) {
299 if (feature_info->IsWebGL2OrES3Context())
300 return "OpenGL ES GLSL ES 3.0 Chromium";
301 else if (feature_info->IsWebGL2ComputeContext()) {
302 return "OpenGL ES GLSL ES 3.1 Chromium";
303 } else
304 return "OpenGL ES GLSL ES 1.0 Chromium";
305 }
306
LogGLDebugMessage(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar * message,Logger * error_logger)307 void LogGLDebugMessage(GLenum source,
308 GLenum type,
309 GLuint id,
310 GLenum severity,
311 GLsizei length,
312 const GLchar* message,
313 Logger* error_logger) {
314 std::string id_string = GLES2Util::GetStringEnum(id);
315 if (type == GL_DEBUG_TYPE_ERROR && source == GL_DEBUG_SOURCE_API) {
316 error_logger->LogMessage(__FILE__, __LINE__,
317 " " + id_string + ": " + message);
318 } else {
319 error_logger->LogMessage(
320 __FILE__, __LINE__,
321 std::string("GL Driver Message (") + GetDebugSourceString(source) +
322 ", " + GetDebugTypeString(type) + ", " + id_string + ", " +
323 GetDebugSeverityString(severity) + "): " + message);
324 }
325 }
326
InitializeGLDebugLogging(bool log_non_errors,GLDEBUGPROC callback,const void * user_param)327 void InitializeGLDebugLogging(bool log_non_errors,
328 GLDEBUGPROC callback,
329 const void* user_param) {
330 glEnable(GL_DEBUG_OUTPUT);
331 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
332
333 glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE,
334 0, nullptr, GL_TRUE);
335
336 if (log_non_errors) {
337 // Enable logging of medium and high severity messages
338 glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0,
339 nullptr, GL_TRUE);
340 glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM,
341 0, nullptr, GL_TRUE);
342 glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW, 0,
343 nullptr, GL_FALSE);
344 glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE,
345 GL_DEBUG_SEVERITY_NOTIFICATION, 0, nullptr, GL_FALSE);
346 }
347
348 glDebugMessageCallback(callback, user_param);
349 }
350
ValidContextLostReason(GLenum reason)351 bool ValidContextLostReason(GLenum reason) {
352 switch (reason) {
353 case GL_NO_ERROR:
354 case GL_GUILTY_CONTEXT_RESET_ARB:
355 case GL_INNOCENT_CONTEXT_RESET_ARB:
356 case GL_UNKNOWN_CONTEXT_RESET_ARB:
357 return true;
358 default:
359 return false;
360 }
361 }
362
GetContextLostReasonFromResetStatus(GLenum reset_status)363 error::ContextLostReason GetContextLostReasonFromResetStatus(
364 GLenum reset_status) {
365 switch (reset_status) {
366 case GL_NO_ERROR:
367 // TODO(kbr): improve the precision of the error code in this case.
368 // Consider delegating to context for error code if MakeCurrent fails.
369 return error::kUnknown;
370 case GL_GUILTY_CONTEXT_RESET_ARB:
371 return error::kGuilty;
372 case GL_INNOCENT_CONTEXT_RESET_ARB:
373 return error::kInnocent;
374 case GL_UNKNOWN_CONTEXT_RESET_ARB:
375 return error::kUnknown;
376 }
377
378 NOTREACHED();
379 return error::kUnknown;
380 }
381
GetCompressedTexSizeInBytes(const char * function_name,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei * size_in_bytes,ErrorState * error_state)382 bool GetCompressedTexSizeInBytes(const char* function_name,
383 GLsizei width,
384 GLsizei height,
385 GLsizei depth,
386 GLenum format,
387 GLsizei* size_in_bytes,
388 ErrorState* error_state) {
389 base::CheckedNumeric<GLsizei> bytes_required(0);
390
391 switch (format) {
392 case GL_ATC_RGB_AMD:
393 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
394 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
395 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
396 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
397 case GL_ETC1_RGB8_OES:
398 bytes_required = (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
399 bytes_required *= (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
400 bytes_required *= kS3TCDXT1BlockSize;
401 break;
402 case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
403 case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
404 case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
405 case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
406 case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
407 case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
408 case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
409 case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
410 case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
411 case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
412 case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
413 case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
414 case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
415 case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
416 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
417 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
418 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
419 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
420 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
421 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
422 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
423 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
424 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
425 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
426 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
427 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
428 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
429 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR: {
430 const int index =
431 (format < GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR)
432 ? static_cast<int>(format - GL_COMPRESSED_RGBA_ASTC_4x4_KHR)
433 : static_cast<int>(format -
434 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR);
435
436 const int kBlockWidth = kASTCBlockArray[index].blockWidth;
437 const int kBlockHeight = kASTCBlockArray[index].blockHeight;
438
439 bytes_required = (width + kBlockWidth - 1) / kBlockWidth;
440 bytes_required *= (height + kBlockHeight - 1) / kBlockHeight;
441
442 bytes_required *= kASTCBlockSize;
443 break;
444 }
445 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
446 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
447 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
448 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
449 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
450 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
451 bytes_required = (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
452 bytes_required *= (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
453 bytes_required *= kS3TCDXT3AndDXT5BlockSize;
454 break;
455 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
456 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
457 bytes_required = std::max(width, 8);
458 bytes_required *= std::max(height, 8);
459 bytes_required *= 4;
460 bytes_required += 7;
461 bytes_required /= 8;
462 break;
463 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
464 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
465 bytes_required = std::max(width, 16);
466 bytes_required *= std::max(height, 8);
467 bytes_required *= 2;
468 bytes_required += 7;
469 bytes_required /= 8;
470 break;
471
472 // ES3 formats.
473 case GL_COMPRESSED_R11_EAC:
474 case GL_COMPRESSED_SIGNED_R11_EAC:
475 case GL_COMPRESSED_RGB8_ETC2:
476 case GL_COMPRESSED_SRGB8_ETC2:
477 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
478 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
479 bytes_required =
480 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
481 bytes_required *=
482 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
483 bytes_required *= 8;
484 bytes_required *= depth;
485 break;
486 case GL_COMPRESSED_RG11_EAC:
487 case GL_COMPRESSED_SIGNED_RG11_EAC:
488 case GL_COMPRESSED_RGBA8_ETC2_EAC:
489 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
490 bytes_required =
491 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
492 bytes_required *=
493 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
494 bytes_required *= 16;
495 bytes_required *= depth;
496 break;
497 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
498 case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
499 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
500 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
501 bytes_required = (width + kBPTCBlockWidth - 1) / kBPTCBlockWidth;
502 bytes_required *= (height + kBPTCBlockHeight - 1) / kBPTCBlockHeight;
503 bytes_required *= 16;
504 bytes_required *= depth;
505 break;
506 case GL_COMPRESSED_RED_RGTC1_EXT:
507 case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
508 bytes_required = (width + kRGTCBlockWidth - 1) / kRGTCBlockWidth;
509 bytes_required *= (height + kRGTCBlockHeight - 1) / kRGTCBlockHeight;
510 bytes_required *= 8;
511 bytes_required *= depth;
512 break;
513 case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
514 case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
515 bytes_required = (width + kRGTCBlockWidth - 1) / kRGTCBlockWidth;
516 bytes_required *= (height + kRGTCBlockHeight - 1) / kRGTCBlockHeight;
517 bytes_required *= 16;
518 bytes_required *= depth;
519 break;
520 default:
521 if (function_name && error_state) {
522 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(error_state, function_name, format,
523 "format");
524 }
525 return false;
526 }
527
528 if (!bytes_required.IsValid()) {
529 if (function_name && error_state) {
530 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name,
531 "invalid size");
532 }
533 return false;
534 }
535
536 *size_in_bytes = bytes_required.ValueOrDefault(0);
537 return true;
538 }
539
ValidateCompressedFormatTarget(GLenum target,GLenum format)540 bool ValidateCompressedFormatTarget(GLenum target, GLenum format) {
541 if (target == GL_TEXTURE_3D) {
542 // Formats not supporting 3D Tex
543 switch (format) {
544 // ES 3.1, Section 8.7, page 169.
545 case GL_COMPRESSED_R11_EAC:
546 case GL_COMPRESSED_SIGNED_R11_EAC:
547 case GL_COMPRESSED_RG11_EAC:
548 case GL_COMPRESSED_SIGNED_RG11_EAC:
549 case GL_COMPRESSED_RGB8_ETC2:
550 case GL_COMPRESSED_SRGB8_ETC2:
551 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
552 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
553 case GL_COMPRESSED_RGBA8_ETC2_EAC:
554 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
555 // GL_EXT_texture_compression_s3tc
556 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
557 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
558 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
559 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
560 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
561 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
562 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
563 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
564 // GL_EXT_texture_compression_rgtc
565 case GL_COMPRESSED_RED_RGTC1_EXT:
566 case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
567 case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
568 case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
569 return false;
570 // GL_KHR_texture_compression_astc_hdr, TEXTURE_3D is not supported
571 // without HDR profile. This is guaranteed to be validated beforehand
572 // in GLES2DecoderImpl::TexStorageImpl before calling this.
573 default:
574 break;
575 }
576 }
577
578 return true;
579 }
580
ValidateCompressedTexSubDimensions(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,Texture * texture,const char ** error_message)581 bool ValidateCompressedTexSubDimensions(GLenum target,
582 GLint level,
583 GLint xoffset,
584 GLint yoffset,
585 GLint zoffset,
586 GLsizei width,
587 GLsizei height,
588 GLsizei depth,
589 GLenum format,
590 Texture* texture,
591 const char** error_message) {
592 if (!ValidateCompressedFormatTarget(target, format)) {
593 *error_message = "target invalid for format";
594 return false;
595 }
596
597 if (xoffset < 0 || yoffset < 0 || zoffset < 0) {
598 *error_message = "x/y/z offset < 0";
599 return false;
600 }
601
602 switch (format) {
603 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
604 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
605 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
606 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
607 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
608 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
609 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
610 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: {
611 const int kBlockWidth = 4;
612 const int kBlockHeight = 4;
613 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
614 *error_message = "xoffset or yoffset not multiple of 4";
615 return false;
616 }
617 GLsizei tex_width = 0;
618 GLsizei tex_height = 0;
619 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height,
620 nullptr) ||
621 width - xoffset > tex_width || height - yoffset > tex_height) {
622 *error_message = "dimensions out of range";
623 return false;
624 }
625 if ((((width % kBlockWidth) != 0) && (width + xoffset != tex_width)) ||
626 (((height % kBlockHeight) != 0) &&
627 (height + yoffset != tex_height))) {
628 *error_message = "dimensions do not align to a block boundary";
629 return false;
630 }
631 return true;
632 }
633 case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
634 case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
635 case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
636 case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
637 case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
638 case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
639 case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
640 case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
641 case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
642 case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
643 case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
644 case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
645 case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
646 case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
647 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
648 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
649 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
650 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
651 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
652 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
653 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
654 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
655 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
656 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
657 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
658 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
659 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
660 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR: {
661 const int index =
662 (format < GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR)
663 ? static_cast<int>(format - GL_COMPRESSED_RGBA_ASTC_4x4_KHR)
664 : static_cast<int>(format -
665 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR);
666
667 const int kBlockWidth = kASTCBlockArray[index].blockWidth;
668 const int kBlockHeight = kASTCBlockArray[index].blockHeight;
669
670 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
671 *error_message = "xoffset or yoffset not multiple of 4";
672 return false;
673 }
674 GLsizei tex_width = 0;
675 GLsizei tex_height = 0;
676 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height,
677 nullptr) ||
678 width - xoffset > tex_width || height - yoffset > tex_height) {
679 *error_message = "dimensions out of range";
680 return false;
681 }
682 if ((((width % kBlockWidth) != 0) && (width + xoffset != tex_width)) ||
683 (((height % kBlockHeight) != 0) &&
684 (height + yoffset != tex_height))) {
685 *error_message = "dimensions do not align to a block boundary";
686 return false;
687 }
688 return true;
689 }
690 case GL_ATC_RGB_AMD:
691 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
692 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
693 *error_message = "not supported for ATC textures";
694 return false;
695 }
696 case GL_ETC1_RGB8_OES: {
697 *error_message = "not supported for ECT1_RGB8_OES textures";
698 return false;
699 }
700 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
701 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
702 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
703 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
704 if ((xoffset != 0) || (yoffset != 0)) {
705 *error_message = "xoffset and yoffset must be zero";
706 return false;
707 }
708 GLsizei tex_width = 0;
709 GLsizei tex_height = 0;
710 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height,
711 nullptr) ||
712 width != tex_width || height != tex_height) {
713 *error_message =
714 "dimensions must match existing texture level dimensions";
715 return false;
716 }
717 return ValidateCompressedTexDimensions(target, level, width, height, 1,
718 format, error_message);
719 }
720
721 // ES3 formats
722 case GL_COMPRESSED_R11_EAC:
723 case GL_COMPRESSED_SIGNED_R11_EAC:
724 case GL_COMPRESSED_RG11_EAC:
725 case GL_COMPRESSED_SIGNED_RG11_EAC:
726 case GL_COMPRESSED_RGB8_ETC2:
727 case GL_COMPRESSED_SRGB8_ETC2:
728 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
729 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
730 case GL_COMPRESSED_RGBA8_ETC2_EAC:
731 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
732 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
733 case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
734 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
735 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
736 case GL_COMPRESSED_RED_RGTC1_EXT:
737 case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
738 case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
739 case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: {
740 const int kBlockSize = 4;
741 GLsizei tex_width, tex_height;
742 if (target == GL_TEXTURE_3D ||
743 !texture->GetLevelSize(target, level, &tex_width, &tex_height,
744 nullptr) ||
745 (xoffset % kBlockSize) || (yoffset % kBlockSize) ||
746 ((width % kBlockSize) && xoffset + width != tex_width) ||
747 ((height % kBlockSize) && yoffset + height != tex_height)) {
748 *error_message =
749 "dimensions must match existing texture level dimensions";
750 return false;
751 }
752 return true;
753 }
754 default:
755 *error_message = "unknown compressed texture format";
756 return false;
757 }
758 }
759
ValidateCompressedTexDimensions(GLenum target,GLint level,GLsizei width,GLsizei height,GLsizei depth,GLenum format,const char ** error_message)760 bool ValidateCompressedTexDimensions(GLenum target,
761 GLint level,
762 GLsizei width,
763 GLsizei height,
764 GLsizei depth,
765 GLenum format,
766 const char** error_message) {
767 if (!ValidateCompressedFormatTarget(target, format)) {
768 *error_message = "target invalid for format";
769 return false;
770 }
771 switch (format) {
772 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
773 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
774 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
775 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
776 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
777 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
778 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
779 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
780 if (!IsValidS3TCSizeForWebGLAndANGLE(level, width) ||
781 !IsValidS3TCSizeForWebGLAndANGLE(level, height)) {
782 *error_message = "width or height invalid for level";
783 return false;
784 }
785 return true;
786 case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
787 case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
788 case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
789 case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
790 case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
791 case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
792 case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
793 case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
794 case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
795 case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
796 case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
797 case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
798 case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
799 case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
800 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
801 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
802 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
803 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
804 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
805 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
806 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
807 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
808 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
809 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
810 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
811 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
812 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
813 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
814 case GL_ATC_RGB_AMD:
815 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
816 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
817 case GL_ETC1_RGB8_OES:
818 if (width <= 0 || height <= 0) {
819 *error_message = "width or height invalid for level";
820 return false;
821 }
822 return true;
823 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
824 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
825 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
826 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
827 if (!IsValidPVRTCSize(level, width) || !IsValidPVRTCSize(level, height)) {
828 *error_message = "width or height invalid for level";
829 return false;
830 }
831 return true;
832
833 // ES3 formats.
834 case GL_COMPRESSED_R11_EAC:
835 case GL_COMPRESSED_SIGNED_R11_EAC:
836 case GL_COMPRESSED_RG11_EAC:
837 case GL_COMPRESSED_SIGNED_RG11_EAC:
838 case GL_COMPRESSED_RGB8_ETC2:
839 case GL_COMPRESSED_SRGB8_ETC2:
840 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
841 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
842 case GL_COMPRESSED_RGBA8_ETC2_EAC:
843 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
844 if (width < 0 || height < 0 || depth < 0) {
845 *error_message = "width, height, or depth invalid";
846 return false;
847 }
848 return true;
849 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
850 case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
851 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
852 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
853 if (width < 0 || height < 0 || depth < 0) {
854 *error_message = "width, height, or depth invalid";
855 return false;
856 }
857 if (!(width % kBPTCBlockWidth == 0 && height % kBPTCBlockHeight == 0)) {
858 *error_message = "width or height is not a multiple of four";
859 return false;
860 }
861 return true;
862 case GL_COMPRESSED_RED_RGTC1_EXT:
863 case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
864 case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
865 case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
866 if (width < 0 || height < 0 || depth < 0) {
867 *error_message = "width, height, or depth invalid";
868 return false;
869 }
870 if (!(width % kRGTCBlockWidth == 0 && height % kRGTCBlockHeight == 0)) {
871 *error_message = "width or height is not a multiple of four";
872 return false;
873 }
874 return true;
875 default:
876 return false;
877 }
878 }
879
ValidateCopyTexFormatHelper(const FeatureInfo * feature_info,GLenum internal_format,GLenum read_format,GLenum read_type,std::string * output_error_msg)880 bool ValidateCopyTexFormatHelper(const FeatureInfo* feature_info,
881 GLenum internal_format,
882 GLenum read_format,
883 GLenum read_type,
884 std::string* output_error_msg) {
885 DCHECK(output_error_msg);
886 if (read_format == 0) {
887 *output_error_msg = std::string("no valid color image");
888 return false;
889 }
890 // Check we have compatible formats.
891 uint32_t channels_exist = GLES2Util::GetChannelsForFormat(read_format);
892 uint32_t channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
893 if (!channels_needed ||
894 (channels_needed & channels_exist) != channels_needed) {
895 *output_error_msg = std::string("incompatible format");
896 return false;
897 }
898 if (feature_info->IsWebGL2OrES3OrHigherContext()) {
899 GLint color_encoding =
900 GLES2Util::GetColorEncodingFromInternalFormat(read_format);
901 bool float_mismatch = feature_info->ext_color_buffer_float_available()
902 ? (GLES2Util::IsIntegerFormat(internal_format) !=
903 GLES2Util::IsIntegerFormat(read_format))
904 : GLES2Util::IsFloatFormat(internal_format);
905 if (color_encoding !=
906 GLES2Util::GetColorEncodingFromInternalFormat(internal_format) ||
907 float_mismatch ||
908 (GLES2Util::IsSignedIntegerFormat(internal_format) !=
909 GLES2Util::IsSignedIntegerFormat(read_format)) ||
910 (GLES2Util::IsUnsignedIntegerFormat(internal_format) !=
911 GLES2Util::IsUnsignedIntegerFormat(read_format))) {
912 *output_error_msg = std::string("incompatible format");
913 return false;
914 }
915 }
916 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
917 *output_error_msg =
918 std::string("can not be used with depth or stencil textures");
919 return false;
920 }
921 if (feature_info->IsWebGL2OrES3OrHigherContext() ||
922 (feature_info->feature_flags().chromium_color_buffer_float_rgb &&
923 internal_format == GL_RGB32F) ||
924 (feature_info->feature_flags().chromium_color_buffer_float_rgba &&
925 internal_format == GL_RGBA32F)) {
926 if (GLES2Util::IsSizedColorFormat(internal_format)) {
927 int sr, sg, sb, sa;
928 GLES2Util::GetColorFormatComponentSizes(read_format, read_type, &sr, &sg,
929 &sb, &sa);
930 DCHECK(sr > 0 || sg > 0 || sb > 0 || sa > 0);
931 int dr, dg, db, da;
932 GLES2Util::GetColorFormatComponentSizes(internal_format, 0, &dr, &dg, &db,
933 &da);
934 DCHECK(dr > 0 || dg > 0 || db > 0 || da > 0);
935 if ((dr > 0 && sr != dr) || (dg > 0 && sg != dg) ||
936 (db > 0 && sb != db) || (da > 0 && sa != da)) {
937 *output_error_msg = std::string("incompatible color component sizes");
938 return false;
939 }
940 }
941 }
942 return true;
943 }
944
GetCopyTextureCHROMIUMMethod(const FeatureInfo * feature_info,GLenum source_target,GLint source_level,GLenum source_internal_format,GLenum source_type,GLenum dest_target,GLint dest_level,GLenum dest_internal_format,bool flip_y,bool premultiply_alpha,bool unpremultiply_alpha,bool dither)945 CopyTextureMethod GetCopyTextureCHROMIUMMethod(const FeatureInfo* feature_info,
946 GLenum source_target,
947 GLint source_level,
948 GLenum source_internal_format,
949 GLenum source_type,
950 GLenum dest_target,
951 GLint dest_level,
952 GLenum dest_internal_format,
953 bool flip_y,
954 bool premultiply_alpha,
955 bool unpremultiply_alpha,
956 bool dither) {
957 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha;
958 bool source_format_color_renderable =
959 Texture::ColorRenderable(feature_info, source_internal_format, false);
960 bool dest_format_color_renderable =
961 Texture::ColorRenderable(feature_info, dest_internal_format, false);
962 std::string output_error_msg;
963
964 switch (dest_internal_format) {
965 #if defined(OS_MACOSX)
966 // RGB5_A1 is not color-renderable on NVIDIA Mac, see
967 // https://crbug.com/676209.
968 case GL_RGB5_A1:
969 return CopyTextureMethod::DRAW_AND_READBACK;
970 #endif
971 // RGB9_E5 isn't accepted by glCopyTexImage2D if underlying context is ES.
972 case GL_RGB9_E5:
973 if (feature_info->gl_version_info().is_es)
974 return CopyTextureMethod::DRAW_AND_READBACK;
975 break;
976 // SRGB format has color-space conversion issue. WebGL spec doesn't define
977 // clearly if linear-to-srgb color space conversion is required or not when
978 // uploading DOM elements to SRGB textures. WebGL conformance test expects
979 // no linear-to-srgb conversion, while current GPU path for
980 // CopyTextureCHROMIUM does the conversion. Do a fallback path before the
981 // issue is resolved. see https://github.com/KhronosGroup/WebGL/issues/2165.
982 // TODO(qiankun.miao@intel.com): revisit this once the above issue is
983 // resolved.
984 case GL_SRGB_EXT:
985 case GL_SRGB_ALPHA_EXT:
986 case GL_SRGB8:
987 case GL_SRGB8_ALPHA8:
988 if (feature_info->IsWebGLContext())
989 return CopyTextureMethod::DRAW_AND_READBACK;
990 break;
991 default:
992 break;
993 }
994
995 // CopyTexImage* should not allow internalformat of GL_BGRA_EXT and
996 // GL_BGRA8_EXT. https://crbug.com/663086.
997 bool copy_tex_image_format_valid =
998 source_internal_format != GL_BGRA_EXT &&
999 dest_internal_format != GL_BGRA_EXT &&
1000 source_internal_format != GL_BGRA8_EXT &&
1001 dest_internal_format != GL_BGRA8_EXT &&
1002 ValidateCopyTexFormatHelper(feature_info, dest_internal_format,
1003 source_internal_format, source_type,
1004 &output_error_msg);
1005
1006 // The ES3 spec is vague about whether or not glCopyTexImage2D from a
1007 // GL_RGB10_A2 attachment to an unsized internal format is valid. Most drivers
1008 // interpreted the explicit call out as not valid (and dEQP actually checks
1009 // this), so avoid DIRECT_COPY in that case.
1010 if (feature_info->gl_version_info().is_es &&
1011 source_internal_format == GL_RGB10_A2 &&
1012 dest_internal_format != source_internal_format)
1013 copy_tex_image_format_valid = false;
1014
1015 // TODO(qiankun.miao@intel.com): for WebGL 2.0 or OpenGL ES 3.0, both
1016 // DIRECT_DRAW path for dest_level > 0 and DIRECT_COPY path for source_level >
1017 // 0 are not available due to a framebuffer completeness bug:
1018 // https://crbug.com/678526. Once the bug is fixed, the limitation for WebGL
1019 // 2.0 and OpenGL ES 3.0 can be lifted. For WebGL 1.0 or OpenGL ES 2.0,
1020 // DIRECT_DRAW path isn't available for dest_level > 0 due to level > 0 isn't
1021 // supported by glFramebufferTexture2D in ES2 context. DIRECT_DRAW path isn't
1022 // available for cube map dest texture either due to it may be cube map
1023 // incomplete. Go to DRAW_AND_COPY path in these cases.
1024 if (source_target == GL_TEXTURE_2D &&
1025 (dest_target == GL_TEXTURE_2D || dest_target == GL_TEXTURE_CUBE_MAP) &&
1026 source_format_color_renderable && copy_tex_image_format_valid &&
1027 source_level == 0 && !flip_y && !premultiply_alpha_change && !dither) {
1028 auto source_texture_type = GLES2Util::GetGLReadPixelsImplementationType(
1029 source_internal_format, source_target);
1030 auto dest_texture_type = GLES2Util::GetGLReadPixelsImplementationType(
1031 dest_internal_format, dest_target);
1032 if (source_texture_type != GL_UNSIGNED_SHORT ||
1033 source_texture_type == dest_texture_type) {
1034 // https://crbug.com/1042239. As it is stated in the latest OpenGL ES 3.2
1035 // spec (Oct 22, 2019) it is optional for implementation to support
1036 // conversion between unmatched source and dest effective internal format.
1037 // R16 to R16F direct copy failure is seen on Android Nvidia shield
1038 // devices. So we won't use DIRECT_COPY for this format.
1039 return CopyTextureMethod::DIRECT_COPY;
1040 }
1041 }
1042 if (dest_format_color_renderable && dest_level == 0 &&
1043 dest_target != GL_TEXTURE_CUBE_MAP)
1044 return CopyTextureMethod::DIRECT_DRAW;
1045
1046 // Draw to a fbo attaching level 0 of an intermediate texture,
1047 // then copy from the fbo to dest texture level with glCopyTexImage2D.
1048 return CopyTextureMethod::DRAW_AND_COPY;
1049 }
1050
ValidateCopyTextureCHROMIUMInternalFormats(const FeatureInfo * feature_info,GLenum source_internal_format,GLenum dest_internal_format,std::string * output_error_msg)1051 bool ValidateCopyTextureCHROMIUMInternalFormats(const FeatureInfo* feature_info,
1052 GLenum source_internal_format,
1053 GLenum dest_internal_format,
1054 std::string* output_error_msg) {
1055 bool valid_dest_format = false;
1056 // TODO(qiankun.miao@intel.com): ALPHA, LUMINANCE and LUMINANCE_ALPHA formats
1057 // are not supported on GL core profile. See https://crbug.com/577144. Enable
1058 // the workaround for glCopyTexImage and glCopyTexSubImage in
1059 // gles2_cmd_copy_tex_image.cc for glCopyTextureCHROMIUM implementation.
1060 switch (dest_internal_format) {
1061 case GL_RGB:
1062 case GL_RGBA:
1063 case GL_RGB8:
1064 case GL_RGBA8:
1065 valid_dest_format = true;
1066 break;
1067 case GL_BGRA_EXT:
1068 case GL_BGRA8_EXT:
1069 valid_dest_format =
1070 feature_info->feature_flags().ext_texture_format_bgra8888;
1071 break;
1072 case GL_SRGB_EXT:
1073 case GL_SRGB_ALPHA_EXT:
1074 valid_dest_format = feature_info->feature_flags().ext_srgb;
1075 break;
1076 case GL_R8:
1077 case GL_R8UI:
1078 case GL_RG8:
1079 case GL_RG8UI:
1080 case GL_SRGB8:
1081 case GL_RGB565:
1082 case GL_RGB8UI:
1083 case GL_SRGB8_ALPHA8:
1084 case GL_RGB5_A1:
1085 case GL_RGBA4:
1086 case GL_RGBA8UI:
1087 case GL_RGB10_A2:
1088 valid_dest_format = feature_info->IsWebGL2OrES3OrHigherContext();
1089 break;
1090 case GL_RGB9_E5:
1091 case GL_R16F:
1092 case GL_R32F:
1093 case GL_RG16F:
1094 case GL_RG32F:
1095 case GL_RGB16F:
1096 case GL_RGBA16F:
1097 case GL_R11F_G11F_B10F:
1098 valid_dest_format = feature_info->ext_color_buffer_float_available();
1099 break;
1100 case GL_RGB32F:
1101 valid_dest_format =
1102 feature_info->ext_color_buffer_float_available() ||
1103 feature_info->feature_flags().chromium_color_buffer_float_rgb;
1104 break;
1105 case GL_RGBA32F:
1106 valid_dest_format =
1107 feature_info->ext_color_buffer_float_available() ||
1108 feature_info->feature_flags().chromium_color_buffer_float_rgba;
1109 break;
1110 case GL_ALPHA:
1111 case GL_LUMINANCE:
1112 case GL_LUMINANCE_ALPHA:
1113 valid_dest_format = true;
1114 break;
1115 default:
1116 valid_dest_format = false;
1117 break;
1118 }
1119
1120 // TODO(aleksandar.stojiljkovic): Use sized internal formats:
1121 // https://crbug.com/628064
1122 bool valid_source_format =
1123 source_internal_format == GL_RED || source_internal_format == GL_ALPHA ||
1124 source_internal_format == GL_RGB || source_internal_format == GL_RGBA ||
1125 source_internal_format == GL_RGB8 || source_internal_format == GL_RGBA8 ||
1126 source_internal_format == GL_LUMINANCE ||
1127 source_internal_format == GL_LUMINANCE_ALPHA ||
1128 source_internal_format == GL_BGRA_EXT ||
1129 source_internal_format == GL_BGRA8_EXT ||
1130 source_internal_format == GL_RGB_YCBCR_420V_CHROMIUM ||
1131 source_internal_format == GL_RGB_YCBCR_422_CHROMIUM ||
1132 source_internal_format == GL_RGB_YCBCR_P010_CHROMIUM ||
1133 source_internal_format == GL_R16_EXT ||
1134 source_internal_format == GL_RG16_EXT ||
1135 source_internal_format == GL_RGBA16_EXT ||
1136 source_internal_format == GL_RGB10_A2;
1137 if (!valid_source_format) {
1138 *output_error_msg = "invalid source internal format " +
1139 GLES2Util::GetStringEnum(source_internal_format);
1140 return false;
1141 }
1142 if (!valid_dest_format) {
1143 *output_error_msg = "invalid dest internal format " +
1144 GLES2Util::GetStringEnum(dest_internal_format);
1145 return false;
1146 }
1147
1148 return true;
1149 }
1150
GetTextureBindingQuery(GLenum texture_type)1151 GLenum GetTextureBindingQuery(GLenum texture_type) {
1152 switch (texture_type) {
1153 case GL_TEXTURE_2D:
1154 return GL_TEXTURE_BINDING_2D;
1155 case GL_TEXTURE_2D_ARRAY:
1156 return GL_TEXTURE_BINDING_2D_ARRAY;
1157 case GL_TEXTURE_2D_MULTISAMPLE:
1158 return GL_TEXTURE_BINDING_2D_MULTISAMPLE;
1159 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1160 return GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY;
1161 case GL_TEXTURE_3D:
1162 return GL_TEXTURE_BINDING_3D;
1163 case GL_TEXTURE_EXTERNAL_OES:
1164 return GL_TEXTURE_BINDING_EXTERNAL_OES;
1165 case GL_TEXTURE_RECTANGLE:
1166 return GL_TEXTURE_BINDING_RECTANGLE;
1167 case GL_TEXTURE_CUBE_MAP:
1168 return GL_TEXTURE_BINDING_CUBE_MAP;
1169 default:
1170 NOTREACHED();
1171 return 0;
1172 }
1173 }
1174
GetGFXOverlayTransform(GLenum plane_transform)1175 gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) {
1176 switch (plane_transform) {
1177 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM:
1178 return gfx::OVERLAY_TRANSFORM_NONE;
1179 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM:
1180 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
1181 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM:
1182 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
1183 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM:
1184 return gfx::OVERLAY_TRANSFORM_ROTATE_90;
1185 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM:
1186 return gfx::OVERLAY_TRANSFORM_ROTATE_180;
1187 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM:
1188 return gfx::OVERLAY_TRANSFORM_ROTATE_270;
1189 default:
1190 return gfx::OVERLAY_TRANSFORM_INVALID;
1191 }
1192 }
1193
GetGFXBufferFormat(GLenum internal_format,gfx::BufferFormat * out_format)1194 bool GetGFXBufferFormat(GLenum internal_format, gfx::BufferFormat* out_format) {
1195 switch (internal_format) {
1196 case GL_RGBA8_OES:
1197 *out_format = gfx::BufferFormat::RGBA_8888;
1198 return true;
1199 case GL_BGRA8_EXT:
1200 *out_format = gfx::BufferFormat::BGRA_8888;
1201 return true;
1202 case GL_RGBA16F_EXT:
1203 *out_format = gfx::BufferFormat::RGBA_F16;
1204 return true;
1205 case GL_R8_EXT:
1206 *out_format = gfx::BufferFormat::R_8;
1207 return true;
1208 default:
1209 return false;
1210 }
1211 }
1212
GetGFXBufferUsage(GLenum buffer_usage,gfx::BufferUsage * out_usage)1213 bool GetGFXBufferUsage(GLenum buffer_usage, gfx::BufferUsage* out_usage) {
1214 switch (buffer_usage) {
1215 case GL_SCANOUT_CHROMIUM:
1216 *out_usage = gfx::BufferUsage::SCANOUT;
1217 return true;
1218 default:
1219 return false;
1220 }
1221 }
1222
IsASTCFormat(GLenum internal_format)1223 bool IsASTCFormat(GLenum internal_format) {
1224 switch (internal_format) {
1225 case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
1226 case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
1227 case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
1228 case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
1229 case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
1230 case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
1231 case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
1232 case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
1233 case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
1234 case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
1235 case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
1236 case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
1237 case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
1238 case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
1239 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
1240 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
1241 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
1242 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
1243 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
1244 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
1245 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
1246 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
1247 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
1248 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
1249 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
1250 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
1251 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
1252 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
1253 return true;
1254 default:
1255 break;
1256 }
1257 return false;
1258 }
1259
1260 // This is only called in Texture::SetLevelInfo in texture_manager.cc
1261 // where there is no direct access to decoder->IsCompressedTextureFormat
1262 // or feature_info->validators()->compressed_texture_format.IsValid
IsCompressedTextureFormat(GLenum internal_format)1263 bool IsCompressedTextureFormat(GLenum internal_format) {
1264 switch (internal_format) {
1265 // S3TC
1266 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1267 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1268 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
1269 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
1270 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
1271 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
1272 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
1273 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
1274 // ASTC
1275 case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
1276 case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
1277 case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
1278 case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
1279 case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
1280 case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
1281 case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
1282 case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
1283 case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
1284 case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
1285 case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
1286 case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
1287 case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
1288 case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
1289 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
1290 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
1291 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
1292 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
1293 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
1294 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
1295 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
1296 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
1297 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
1298 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
1299 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
1300 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
1301 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
1302 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
1303 // BPTC
1304 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
1305 case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
1306 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
1307 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
1308 // RGTC
1309 case GL_COMPRESSED_RED_RGTC1_EXT:
1310 case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
1311 case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
1312 case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
1313 // ETC2/EAC
1314 case GL_COMPRESSED_R11_EAC:
1315 case GL_COMPRESSED_SIGNED_R11_EAC:
1316 case GL_COMPRESSED_RGB8_ETC2:
1317 case GL_COMPRESSED_SRGB8_ETC2:
1318 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
1319 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
1320 case GL_COMPRESSED_RG11_EAC:
1321 case GL_COMPRESSED_SIGNED_RG11_EAC:
1322 case GL_COMPRESSED_RGBA8_ETC2_EAC:
1323 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
1324 // ETC1
1325 case GL_ETC1_RGB8_OES:
1326 // PVRTC
1327 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
1328 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
1329 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
1330 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
1331 // ATC
1332 case GL_ATC_RGB_AMD:
1333 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
1334 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
1335 return true;
1336 default:
1337 break;
1338 }
1339 return false;
1340 }
1341
1342 } // namespace gles2
1343 } // namespace gpu
1344