• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
8 
9 #include "libGLESv2/validationES2.h"
10 #include "libGLESv2/validationES.h"
11 #include "libGLESv2/Context.h"
12 #include "libGLESv2/Texture.h"
13 #include "libGLESv2/Framebuffer.h"
14 #include "libGLESv2/Renderbuffer.h"
15 #include "libGLESv2/formatutils.h"
16 #include "libGLESv2/main.h"
17 #include "libGLESv2/FramebufferAttachment.h"
18 
19 #include "common/mathutil.h"
20 #include "common/utilities.h"
21 
22 namespace gl
23 {
24 
ValidateSubImageParams2D(Context * context,bool compressed,GLsizei width,GLsizei height,GLint xoffset,GLint yoffset,GLint level,GLenum format,GLenum type,gl::Texture2D * texture)25 static bool ValidateSubImageParams2D(Context *context, bool compressed, GLsizei width, GLsizei height,
26                                      GLint xoffset, GLint yoffset, GLint level, GLenum format, GLenum type,
27                                      gl::Texture2D *texture)
28 {
29     if (!texture)
30     {
31         context->recordError(Error(GL_INVALID_OPERATION));
32         return false;
33     }
34 
35     if (compressed != texture->isCompressed(level))
36     {
37         context->recordError(Error(GL_INVALID_OPERATION));
38         return false;
39     }
40 
41     if (format != GL_NONE)
42     {
43         if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(level))
44         {
45             context->recordError(Error(GL_INVALID_OPERATION));
46             return false;
47         }
48     }
49 
50     if (compressed)
51     {
52         if ((width % 4 != 0 && width != texture->getWidth(level)) ||
53             (height % 4 != 0 && height != texture->getHeight(level)))
54         {
55             context->recordError(Error(GL_INVALID_OPERATION));
56             return false;
57         }
58     }
59 
60     if (xoffset + width > texture->getWidth(level) ||
61         yoffset + height > texture->getHeight(level))
62     {
63         context->recordError(Error(GL_INVALID_VALUE));
64         return false;
65     }
66 
67     return true;
68 }
69 
ValidateSubImageParamsCube(Context * context,bool compressed,GLsizei width,GLsizei height,GLint xoffset,GLint yoffset,GLenum target,GLint level,GLenum format,GLenum type,gl::TextureCubeMap * texture)70 static bool ValidateSubImageParamsCube(Context *context, bool compressed, GLsizei width, GLsizei height,
71                                        GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, GLenum type,
72                                        gl::TextureCubeMap *texture)
73 {
74     if (!texture)
75     {
76         context->recordError(Error(GL_INVALID_OPERATION));
77         return false;
78     }
79 
80     if (compressed != texture->isCompressed(target, level))
81     {
82         context->recordError(Error(GL_INVALID_OPERATION));
83         return false;
84     }
85 
86     if (format != GL_NONE)
87     {
88         if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(target, level))
89         {
90             context->recordError(Error(GL_INVALID_OPERATION));
91             return false;
92         }
93     }
94 
95     if (compressed)
96     {
97         if ((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
98             (height % 4 != 0 && height != texture->getHeight(target, 0)))
99         {
100             context->recordError(Error(GL_INVALID_OPERATION));
101             return false;
102         }
103     }
104 
105     if (xoffset + width > texture->getWidth(target, level) ||
106         yoffset + height > texture->getHeight(target, level))
107     {
108         context->recordError(Error(GL_INVALID_VALUE));
109         return false;
110     }
111 
112     return true;
113 }
114 
ValidateES2TexImageParameters(Context * context,GLenum target,GLint level,GLenum internalformat,bool isCompressed,bool isSubImage,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,const GLvoid * pixels)115 bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
116                                    GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
117                                    GLint border, GLenum format, GLenum type, const GLvoid *pixels)
118 {
119     if (!ValidTexture2DDestinationTarget(context, target))
120     {
121         context->recordError(Error(GL_INVALID_ENUM));
122         return false;
123     }
124 
125     if (!ValidImageSize(context, target, level, width, height, 1))
126     {
127         context->recordError(Error(GL_INVALID_VALUE));
128         return false;
129     }
130 
131     if (level < 0 || xoffset < 0 ||
132         std::numeric_limits<GLsizei>::max() - xoffset < width ||
133         std::numeric_limits<GLsizei>::max() - yoffset < height)
134     {
135         context->recordError(Error(GL_INVALID_VALUE));
136         return false;
137     }
138 
139     if (!isSubImage && !isCompressed && internalformat != format)
140     {
141         context->recordError(Error(GL_INVALID_OPERATION));
142         return false;
143     }
144 
145     const gl::Caps &caps = context->getCaps();
146 
147     gl::Texture *texture = NULL;
148     bool textureCompressed = false;
149     GLenum textureInternalFormat = GL_NONE;
150     GLint textureLevelWidth = 0;
151     GLint textureLevelHeight = 0;
152     switch (target)
153     {
154       case GL_TEXTURE_2D:
155         {
156             if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
157                 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
158             {
159                 context->recordError(Error(GL_INVALID_VALUE));
160                 return false;
161             }
162 
163             gl::Texture2D *tex2d = context->getTexture2D();
164             if (tex2d)
165             {
166                 textureCompressed = tex2d->isCompressed(level);
167                 textureInternalFormat = tex2d->getInternalFormat(level);
168                 textureLevelWidth = tex2d->getWidth(level);
169                 textureLevelHeight = tex2d->getHeight(level);
170                 texture = tex2d;
171             }
172 
173             if (isSubImage && !ValidateSubImageParams2D(context, isCompressed, width, height, xoffset, yoffset,
174                                                         level, format, type, tex2d))
175             {
176                 return false;
177             }
178 
179             texture = tex2d;
180         }
181         break;
182 
183       case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
184       case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
185       case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
186       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
187       case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
188       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
189         {
190             if (!isSubImage && width != height)
191             {
192                 context->recordError(Error(GL_INVALID_VALUE));
193                 return false;
194             }
195 
196             if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
197                 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
198             {
199                 context->recordError(Error(GL_INVALID_VALUE));
200                 return false;
201             }
202 
203             gl::TextureCubeMap *texCube = context->getTextureCubeMap();
204             if (texCube)
205             {
206                 textureCompressed = texCube->isCompressed(target, level);
207                 textureInternalFormat = texCube->getInternalFormat(target, level);
208                 textureLevelWidth = texCube->getWidth(target, level);
209                 textureLevelHeight = texCube->getHeight(target, level);
210                 texture = texCube;
211             }
212 
213             if (isSubImage && !ValidateSubImageParamsCube(context, isCompressed, width, height, xoffset, yoffset,
214                                                           target, level, format, type, texCube))
215             {
216                 return false;
217             }
218         }
219         break;
220 
221       default:
222         context->recordError(Error(GL_INVALID_ENUM));
223         return false;
224     }
225 
226     if (!texture)
227     {
228         context->recordError(Error(GL_INVALID_OPERATION));
229         return false;
230     }
231 
232     if (!isSubImage && texture->isImmutable())
233     {
234         context->recordError(Error(GL_INVALID_OPERATION));
235         return false;
236     }
237 
238     // Verify zero border
239     if (border != 0)
240     {
241         context->recordError(Error(GL_INVALID_VALUE));
242         return false;
243     }
244 
245     GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
246     if (isCompressed)
247     {
248         if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
249         {
250             context->recordError(Error(GL_INVALID_OPERATION));
251             return false;
252         }
253 
254         switch (actualInternalFormat)
255         {
256           case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
257           case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
258             if (!context->getExtensions().textureCompressionDXT1)
259             {
260                 context->recordError(Error(GL_INVALID_ENUM));
261                 return false;
262             }
263             break;
264           case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
265             if (!context->getExtensions().textureCompressionDXT1)
266             {
267                 context->recordError(Error(GL_INVALID_ENUM));
268                 return false;
269             }
270             break;
271           case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
272             if (!context->getExtensions().textureCompressionDXT5)
273             {
274                 context->recordError(Error(GL_INVALID_ENUM));
275                 return false;
276             }
277             break;
278           default:
279             context->recordError(Error(GL_INVALID_ENUM));
280             return false;
281         }
282     }
283     else
284     {
285         // validate <type> by itself (used as secondary key below)
286         switch (type)
287         {
288           case GL_UNSIGNED_BYTE:
289           case GL_UNSIGNED_SHORT_5_6_5:
290           case GL_UNSIGNED_SHORT_4_4_4_4:
291           case GL_UNSIGNED_SHORT_5_5_5_1:
292           case GL_UNSIGNED_SHORT:
293           case GL_UNSIGNED_INT:
294           case GL_UNSIGNED_INT_24_8_OES:
295           case GL_HALF_FLOAT_OES:
296           case GL_FLOAT:
297             break;
298           default:
299             context->recordError(Error(GL_INVALID_ENUM));
300             return false;
301         }
302 
303         // validate <format> + <type> combinations
304         // - invalid <format> -> sets INVALID_ENUM
305         // - invalid <format>+<type> combination -> sets INVALID_OPERATION
306         switch (format)
307         {
308           case GL_ALPHA:
309           case GL_LUMINANCE:
310           case GL_LUMINANCE_ALPHA:
311             switch (type)
312             {
313               case GL_UNSIGNED_BYTE:
314               case GL_FLOAT:
315               case GL_HALF_FLOAT_OES:
316                 break;
317               default:
318                   context->recordError(Error(GL_INVALID_OPERATION));
319                   return false;
320             }
321             break;
322           case GL_RED:
323           case GL_RG:
324               if (!context->getExtensions().textureRG)
325               {
326                   context->recordError(Error(GL_INVALID_ENUM));
327                   return false;
328               }
329               switch (type)
330               {
331                 case GL_UNSIGNED_BYTE:
332                 case GL_FLOAT:
333                 case GL_HALF_FLOAT_OES:
334                   break;
335                 default:
336                   context->recordError(Error(GL_INVALID_OPERATION));
337                   return false;
338               }
339               break;
340           case GL_RGB:
341             switch (type)
342             {
343               case GL_UNSIGNED_BYTE:
344               case GL_UNSIGNED_SHORT_5_6_5:
345               case GL_FLOAT:
346               case GL_HALF_FLOAT_OES:
347                 break;
348               default:
349                 context->recordError(Error(GL_INVALID_OPERATION));
350                 return false;
351             }
352             break;
353           case GL_RGBA:
354             switch (type)
355             {
356               case GL_UNSIGNED_BYTE:
357               case GL_UNSIGNED_SHORT_4_4_4_4:
358               case GL_UNSIGNED_SHORT_5_5_5_1:
359               case GL_FLOAT:
360               case GL_HALF_FLOAT_OES:
361                 break;
362               default:
363                 context->recordError(Error(GL_INVALID_OPERATION));
364                 return false;
365             }
366             break;
367           case GL_BGRA_EXT:
368             switch (type)
369             {
370               case GL_UNSIGNED_BYTE:
371                 break;
372               default:
373                 context->recordError(Error(GL_INVALID_OPERATION));
374                 return false;
375             }
376             break;
377           case GL_SRGB_EXT:
378           case GL_SRGB_ALPHA_EXT:
379             if (!context->getExtensions().sRGB)
380             {
381                 context->recordError(Error(GL_INVALID_ENUM));
382                 return false;
383             }
384             switch (type)
385             {
386               case GL_UNSIGNED_BYTE:
387                 break;
388               default:
389                 context->recordError(Error(GL_INVALID_OPERATION));
390                 return false;
391             }
392             break;
393           case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:  // error cases for compressed textures are handled below
394           case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
395           case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
396           case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
397             break;
398           case GL_DEPTH_COMPONENT:
399             switch (type)
400             {
401               case GL_UNSIGNED_SHORT:
402               case GL_UNSIGNED_INT:
403                 break;
404               default:
405                 context->recordError(Error(GL_INVALID_OPERATION));
406                 return false;
407             }
408             break;
409           case GL_DEPTH_STENCIL_OES:
410             switch (type)
411             {
412               case GL_UNSIGNED_INT_24_8_OES:
413                 break;
414               default:
415                 context->recordError(Error(GL_INVALID_OPERATION));
416                 return false;
417             }
418             break;
419           default:
420             context->recordError(Error(GL_INVALID_ENUM));
421             return false;
422         }
423 
424         switch (format)
425         {
426           case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
427           case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
428             if (context->getExtensions().textureCompressionDXT1)
429             {
430                 context->recordError(Error(GL_INVALID_OPERATION));
431                 return false;
432             }
433             else
434             {
435                 context->recordError(Error(GL_INVALID_ENUM));
436                 return false;
437             }
438             break;
439           case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
440             if (context->getExtensions().textureCompressionDXT3)
441             {
442                 context->recordError(Error(GL_INVALID_OPERATION));
443                 return false;
444             }
445             else
446             {
447                 context->recordError(Error(GL_INVALID_ENUM));
448                 return false;
449             }
450             break;
451           case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
452             if (context->getExtensions().textureCompressionDXT5)
453             {
454                 context->recordError(Error(GL_INVALID_OPERATION));
455                 return false;
456             }
457             else
458             {
459                 context->recordError(Error(GL_INVALID_ENUM));
460                 return false;
461             }
462             break;
463           case GL_DEPTH_COMPONENT:
464           case GL_DEPTH_STENCIL_OES:
465             if (!context->getExtensions().depthTextures)
466             {
467                 context->recordError(Error(GL_INVALID_VALUE));
468                 return false;
469             }
470             if (target != GL_TEXTURE_2D)
471             {
472                 context->recordError(Error(GL_INVALID_OPERATION));
473                 return false;
474             }
475             // OES_depth_texture supports loading depth data and multiple levels,
476             // but ANGLE_depth_texture does not
477             if (pixels != NULL || level != 0)
478             {
479                 context->recordError(Error(GL_INVALID_OPERATION));
480                 return false;
481             }
482             break;
483           default:
484             break;
485         }
486 
487         if (type == GL_FLOAT)
488         {
489             if (!context->getExtensions().textureFloat)
490             {
491                 context->recordError(Error(GL_INVALID_ENUM));
492                 return false;
493             }
494         }
495         else if (type == GL_HALF_FLOAT_OES)
496         {
497             if (!context->getExtensions().textureHalfFloat)
498             {
499                 context->recordError(Error(GL_INVALID_ENUM));
500                 return false;
501             }
502         }
503     }
504 
505     return true;
506 }
507 
508 
509 
ValidateES2CopyTexImageParameters(Context * context,GLenum target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)510 bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage,
511                                        GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height,
512                                        GLint border)
513 {
514     GLenum textureInternalFormat = GL_NONE;
515 
516     if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
517                                             xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat))
518     {
519         return false;
520     }
521 
522     gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
523     GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat();
524     GLenum textureFormat = gl::GetInternalFormatInfo(textureInternalFormat).format;
525 
526     // [OpenGL ES 2.0.24] table 3.9
527     if (isSubImage)
528     {
529         switch (textureFormat)
530         {
531           case GL_ALPHA:
532             if (colorbufferFormat != GL_ALPHA8_EXT &&
533                 colorbufferFormat != GL_RGBA4 &&
534                 colorbufferFormat != GL_RGB5_A1 &&
535                 colorbufferFormat != GL_RGBA8_OES)
536             {
537                 context->recordError(Error(GL_INVALID_OPERATION));
538                 return false;
539             }
540             break;
541           case GL_LUMINANCE:
542               if (colorbufferFormat != GL_R8_EXT &&
543                   colorbufferFormat != GL_RG8_EXT &&
544                   colorbufferFormat != GL_RGB565 &&
545                   colorbufferFormat != GL_RGB8_OES &&
546                   colorbufferFormat != GL_RGBA4 &&
547                   colorbufferFormat != GL_RGB5_A1 &&
548                   colorbufferFormat != GL_RGBA8_OES)
549               {
550                   context->recordError(Error(GL_INVALID_OPERATION));
551                   return false;
552               }
553               break;
554           case GL_RED_EXT:
555               if (colorbufferFormat != GL_R8_EXT &&
556                   colorbufferFormat != GL_RG8_EXT &&
557                   colorbufferFormat != GL_RGB565 &&
558                   colorbufferFormat != GL_RGB8_OES &&
559                   colorbufferFormat != GL_RGBA4 &&
560                   colorbufferFormat != GL_RGB5_A1 &&
561                   colorbufferFormat != GL_RGBA8_OES)
562               {
563                   context->recordError(Error(GL_INVALID_OPERATION));
564                   return false;
565               }
566               break;
567           case GL_RG_EXT:
568               if (colorbufferFormat != GL_RG8_EXT &&
569                   colorbufferFormat != GL_RGB565 &&
570                   colorbufferFormat != GL_RGB8_OES &&
571                   colorbufferFormat != GL_RGBA4 &&
572                   colorbufferFormat != GL_RGB5_A1 &&
573                   colorbufferFormat != GL_RGBA8_OES)
574               {
575                   context->recordError(Error(GL_INVALID_OPERATION));
576                   return false;
577               }
578               break;
579           case GL_RGB:
580             if (colorbufferFormat != GL_RGB565 &&
581                 colorbufferFormat != GL_RGB8_OES &&
582                 colorbufferFormat != GL_RGBA4 &&
583                 colorbufferFormat != GL_RGB5_A1 &&
584                 colorbufferFormat != GL_RGBA8_OES)
585             {
586                 context->recordError(Error(GL_INVALID_OPERATION));
587                 return false;
588             }
589             break;
590           case GL_LUMINANCE_ALPHA:
591           case GL_RGBA:
592             if (colorbufferFormat != GL_RGBA4 &&
593                 colorbufferFormat != GL_RGB5_A1 &&
594                 colorbufferFormat != GL_RGBA8_OES)
595             {
596                 context->recordError(Error(GL_INVALID_OPERATION));
597                 return false;
598             }
599             break;
600           case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
601           case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
602           case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
603           case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
604             context->recordError(Error(GL_INVALID_OPERATION));
605             return false;
606           case GL_DEPTH_COMPONENT:
607           case GL_DEPTH_STENCIL_OES:
608             context->recordError(Error(GL_INVALID_OPERATION));
609             return false;
610           default:
611             context->recordError(Error(GL_INVALID_OPERATION));
612             return false;
613         }
614     }
615     else
616     {
617         switch (internalformat)
618         {
619           case GL_ALPHA:
620             if (colorbufferFormat != GL_ALPHA8_EXT &&
621                 colorbufferFormat != GL_RGBA4 &&
622                 colorbufferFormat != GL_RGB5_A1 &&
623                 colorbufferFormat != GL_BGRA8_EXT &&
624                 colorbufferFormat != GL_RGBA8_OES)
625             {
626                 context->recordError(Error(GL_INVALID_OPERATION));
627                 return false;
628             }
629             break;
630           case GL_LUMINANCE:
631               if (colorbufferFormat != GL_R8_EXT &&
632                   colorbufferFormat != GL_RG8_EXT &&
633                   colorbufferFormat != GL_RGB565 &&
634                   colorbufferFormat != GL_RGB8_OES &&
635                   colorbufferFormat != GL_RGBA4 &&
636                   colorbufferFormat != GL_RGB5_A1 &&
637                   colorbufferFormat != GL_BGRA8_EXT &&
638                   colorbufferFormat != GL_RGBA8_OES)
639               {
640                   context->recordError(Error(GL_INVALID_OPERATION));
641                   return false;
642               }
643               break;
644           case GL_RED_EXT:
645               if (colorbufferFormat != GL_R8_EXT &&
646                   colorbufferFormat != GL_RG8_EXT &&
647                   colorbufferFormat != GL_RGB565 &&
648                   colorbufferFormat != GL_RGB8_OES &&
649                   colorbufferFormat != GL_RGBA4 &&
650                   colorbufferFormat != GL_RGB5_A1 &&
651                   colorbufferFormat != GL_BGRA8_EXT &&
652                   colorbufferFormat != GL_RGBA8_OES)
653               {
654                   context->recordError(Error(GL_INVALID_OPERATION));
655                   return false;
656               }
657               break;
658           case GL_RG_EXT:
659               if (colorbufferFormat != GL_RG8_EXT &&
660                   colorbufferFormat != GL_RGB565 &&
661                   colorbufferFormat != GL_RGB8_OES &&
662                   colorbufferFormat != GL_RGBA4 &&
663                   colorbufferFormat != GL_RGB5_A1 &&
664                   colorbufferFormat != GL_BGRA8_EXT &&
665                   colorbufferFormat != GL_RGBA8_OES)
666               {
667                   context->recordError(Error(GL_INVALID_OPERATION));
668                   return false;
669               }
670               break;
671           case GL_RGB:
672             if (colorbufferFormat != GL_RGB565 &&
673                 colorbufferFormat != GL_RGB8_OES &&
674                 colorbufferFormat != GL_RGBA4 &&
675                 colorbufferFormat != GL_RGB5_A1 &&
676                 colorbufferFormat != GL_BGRA8_EXT &&
677                 colorbufferFormat != GL_RGBA8_OES)
678             {
679                 context->recordError(Error(GL_INVALID_OPERATION));
680                 return false;
681             }
682             break;
683           case GL_LUMINANCE_ALPHA:
684           case GL_RGBA:
685             if (colorbufferFormat != GL_RGBA4 &&
686                 colorbufferFormat != GL_RGB5_A1 &&
687                 colorbufferFormat != GL_BGRA8_EXT &&
688                 colorbufferFormat != GL_RGBA8_OES)
689             {
690                 context->recordError(Error(GL_INVALID_OPERATION));
691                 return false;
692             }
693             break;
694           case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
695           case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
696             if (context->getExtensions().textureCompressionDXT1)
697             {
698                 context->recordError(Error(GL_INVALID_OPERATION));
699                 return false;
700             }
701             else
702             {
703                 context->recordError(Error(GL_INVALID_ENUM));
704                 return false;
705             }
706             break;
707           case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
708             if (context->getExtensions().textureCompressionDXT3)
709             {
710                 context->recordError(Error(GL_INVALID_OPERATION));
711                 return false;
712             }
713             else
714             {
715                 context->recordError(Error(GL_INVALID_ENUM));
716                 return false;
717             }
718             break;
719           case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
720             if (context->getExtensions().textureCompressionDXT5)
721             {
722                 context->recordError(Error(GL_INVALID_OPERATION));
723                 return false;
724             }
725             else
726             {
727                 context->recordError(Error(GL_INVALID_ENUM));
728                 return false;
729             }
730             break;
731           case GL_DEPTH_COMPONENT:
732           case GL_DEPTH_COMPONENT16:
733           case GL_DEPTH_COMPONENT32_OES:
734           case GL_DEPTH_STENCIL_OES:
735           case GL_DEPTH24_STENCIL8_OES:
736             if (context->getExtensions().depthTextures)
737             {
738                 context->recordError(Error(GL_INVALID_OPERATION));
739                 return false;
740             }
741             else
742             {
743                 context->recordError(Error(GL_INVALID_ENUM));
744                 return false;
745             }
746           default:
747             context->recordError(Error(GL_INVALID_ENUM));
748             return false;
749         }
750     }
751 
752     // If width or height is zero, it is a no-op.  Return false without setting an error.
753     return (width > 0 && height > 0);
754 }
755 
ValidateES2TexStorageParameters(Context * context,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)756 bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
757                                      GLsizei width, GLsizei height)
758 {
759     if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
760     {
761         context->recordError(Error(GL_INVALID_ENUM));
762         return false;
763     }
764 
765     if (width < 1 || height < 1 || levels < 1)
766     {
767         context->recordError(Error(GL_INVALID_VALUE));
768         return false;
769     }
770 
771     if (target == GL_TEXTURE_CUBE_MAP && width != height)
772     {
773         context->recordError(Error(GL_INVALID_VALUE));
774         return false;
775     }
776 
777     if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
778     {
779         context->recordError(Error(GL_INVALID_OPERATION));
780         return false;
781     }
782 
783     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
784     if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
785     {
786         context->recordError(Error(GL_INVALID_ENUM));
787         return false;
788     }
789 
790     const gl::Caps &caps = context->getCaps();
791 
792     switch (target)
793     {
794       case GL_TEXTURE_2D:
795         if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
796             static_cast<GLuint>(height) > caps.max2DTextureSize)
797         {
798             context->recordError(Error(GL_INVALID_VALUE));
799             return false;
800         }
801         break;
802       case GL_TEXTURE_CUBE_MAP:
803         if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
804             static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
805         {
806             context->recordError(Error(GL_INVALID_VALUE));
807             return false;
808         }
809         break;
810       default:
811         context->recordError(Error(GL_INVALID_ENUM));
812         return false;
813     }
814 
815     if (levels != 1 && !context->getExtensions().textureNPOT)
816     {
817         if (!gl::isPow2(width) || !gl::isPow2(height))
818         {
819             context->recordError(Error(GL_INVALID_OPERATION));
820             return false;
821         }
822     }
823 
824     switch (internalformat)
825     {
826       case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
827       case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
828         if (!context->getExtensions().textureCompressionDXT1)
829         {
830             context->recordError(Error(GL_INVALID_ENUM));
831             return false;
832         }
833         break;
834       case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
835         if (!context->getExtensions().textureCompressionDXT3)
836         {
837             context->recordError(Error(GL_INVALID_ENUM));
838             return false;
839         }
840         break;
841       case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
842         if (!context->getExtensions().textureCompressionDXT5)
843         {
844             context->recordError(Error(GL_INVALID_ENUM));
845             return false;
846         }
847         break;
848       case GL_RGBA32F_EXT:
849       case GL_RGB32F_EXT:
850       case GL_ALPHA32F_EXT:
851       case GL_LUMINANCE32F_EXT:
852       case GL_LUMINANCE_ALPHA32F_EXT:
853         if (!context->getExtensions().textureFloat)
854         {
855             context->recordError(Error(GL_INVALID_ENUM));
856             return false;
857         }
858         break;
859       case GL_RGBA16F_EXT:
860       case GL_RGB16F_EXT:
861       case GL_ALPHA16F_EXT:
862       case GL_LUMINANCE16F_EXT:
863       case GL_LUMINANCE_ALPHA16F_EXT:
864         if (!context->getExtensions().textureHalfFloat)
865         {
866             context->recordError(Error(GL_INVALID_ENUM));
867             return false;
868         }
869         break;
870       case GL_R8_EXT:
871       case GL_RG8_EXT:
872       case GL_R16F_EXT:
873       case GL_RG16F_EXT:
874       case GL_R32F_EXT:
875       case GL_RG32F_EXT:
876         if (!context->getExtensions().textureRG)
877         {
878             context->recordError(Error(GL_INVALID_ENUM));
879             return false;
880         }
881         break;
882       case GL_DEPTH_COMPONENT16:
883       case GL_DEPTH_COMPONENT32_OES:
884       case GL_DEPTH24_STENCIL8_OES:
885         if (!context->getExtensions().depthTextures)
886         {
887             context->recordError(Error(GL_INVALID_ENUM));
888             return false;
889         }
890         if (target != GL_TEXTURE_2D)
891         {
892             context->recordError(Error(GL_INVALID_OPERATION));
893             return false;
894         }
895         // ANGLE_depth_texture only supports 1-level textures
896         if (levels != 1)
897         {
898             context->recordError(Error(GL_INVALID_OPERATION));
899             return false;
900         }
901         break;
902       default:
903         break;
904     }
905 
906     gl::Texture *texture = NULL;
907     switch(target)
908     {
909       case GL_TEXTURE_2D:
910         texture = context->getTexture2D();
911         break;
912       case GL_TEXTURE_CUBE_MAP:
913         texture = context->getTextureCubeMap();
914         break;
915       default:
916         UNREACHABLE();
917     }
918 
919     if (!texture || texture->id() == 0)
920     {
921         context->recordError(Error(GL_INVALID_OPERATION));
922         return false;
923     }
924 
925     if (texture->isImmutable())
926     {
927         context->recordError(Error(GL_INVALID_OPERATION));
928         return false;
929     }
930 
931     return true;
932 }
933 
934 // check for combinations of format and type that are valid for ReadPixels
ValidES2ReadFormatType(Context * context,GLenum format,GLenum type)935 bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type)
936 {
937     switch (format)
938     {
939       case GL_RGBA:
940         switch (type)
941         {
942           case GL_UNSIGNED_BYTE:
943             break;
944           default:
945             return false;
946         }
947         break;
948       case GL_BGRA_EXT:
949         switch (type)
950         {
951           case GL_UNSIGNED_BYTE:
952           case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
953           case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
954             break;
955           default:
956             return false;
957         }
958         break;
959       case GL_RG_EXT:
960       case GL_RED_EXT:
961         if (!context->getExtensions().textureRG)
962         {
963             return false;
964         }
965         switch (type)
966         {
967           case GL_UNSIGNED_BYTE:
968             break;
969           default:
970             return false;
971         }
972         break;
973 
974       default:
975         return false;
976     }
977     return true;
978 }
979 
980 }
981