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