Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / libGLESv2 / validationES3.cpp
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 // validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8
9 #include "libGLESv2/validationES3.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
21 namespace gl
22 {
23
24 struct ES3FormatCombination
25 {
26     GLenum internalFormat;
27     GLenum format;
28     GLenum type;
29 };
30
31 bool operator<(const ES3FormatCombination& a, const ES3FormatCombination& b)
32 {
33     return memcmp(&a, &b, sizeof(ES3FormatCombination)) < 0;
34 }
35
36 typedef std::set<ES3FormatCombination> ES3FormatCombinationSet;
37
38 static inline void InsertES3FormatCombo(ES3FormatCombinationSet *set, GLenum internalFormat, GLenum format, GLenum type)
39 {
40     ES3FormatCombination info;
41     info.internalFormat = internalFormat;
42     info.format = format;
43     info.type = type;
44     set->insert(info);
45 }
46
47 ES3FormatCombinationSet BuildES3FormatSet()
48 {
49     ES3FormatCombinationSet set;
50
51     // Format combinations from ES 3.0.1 spec, table 3.2
52
53     //                        | Internal format      | Format            | Type                            |
54     //                        |                      |                   |                                 |
55     InsertES3FormatCombo(&set, GL_RGBA8,              GL_RGBA,            GL_UNSIGNED_BYTE                 );
56     InsertES3FormatCombo(&set, GL_RGB5_A1,            GL_RGBA,            GL_UNSIGNED_BYTE                 );
57     InsertES3FormatCombo(&set, GL_RGBA4,              GL_RGBA,            GL_UNSIGNED_BYTE                 );
58     InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8,       GL_RGBA,            GL_UNSIGNED_BYTE                 );
59     InsertES3FormatCombo(&set, GL_RGBA8_SNORM,        GL_RGBA,            GL_BYTE                          );
60     InsertES3FormatCombo(&set, GL_RGBA4,              GL_RGBA,            GL_UNSIGNED_SHORT_4_4_4_4        );
61     InsertES3FormatCombo(&set, GL_RGB10_A2,           GL_RGBA,            GL_UNSIGNED_INT_2_10_10_10_REV   );
62     InsertES3FormatCombo(&set, GL_RGB5_A1,            GL_RGBA,            GL_UNSIGNED_INT_2_10_10_10_REV   );
63     InsertES3FormatCombo(&set, GL_RGB5_A1,            GL_RGBA,            GL_UNSIGNED_SHORT_5_5_5_1        );
64     InsertES3FormatCombo(&set, GL_RGBA16F,            GL_RGBA,            GL_HALF_FLOAT                    );
65     InsertES3FormatCombo(&set, GL_RGBA16F,            GL_RGBA,            GL_HALF_FLOAT_OES                );
66     InsertES3FormatCombo(&set, GL_RGBA32F,            GL_RGBA,            GL_FLOAT                         );
67     InsertES3FormatCombo(&set, GL_RGBA16F,            GL_RGBA,            GL_FLOAT                         );
68     InsertES3FormatCombo(&set, GL_RGBA8UI,            GL_RGBA_INTEGER,    GL_UNSIGNED_BYTE                 );
69     InsertES3FormatCombo(&set, GL_RGBA8I,             GL_RGBA_INTEGER,    GL_BYTE                          );
70     InsertES3FormatCombo(&set, GL_RGBA16UI,           GL_RGBA_INTEGER,    GL_UNSIGNED_SHORT                );
71     InsertES3FormatCombo(&set, GL_RGBA16I,            GL_RGBA_INTEGER,    GL_SHORT                         );
72     InsertES3FormatCombo(&set, GL_RGBA32UI,           GL_RGBA_INTEGER,    GL_UNSIGNED_INT                  );
73     InsertES3FormatCombo(&set, GL_RGBA32I,            GL_RGBA_INTEGER,    GL_INT                           );
74     InsertES3FormatCombo(&set, GL_RGB10_A2UI,         GL_RGBA_INTEGER,    GL_UNSIGNED_INT_2_10_10_10_REV   );
75     InsertES3FormatCombo(&set, GL_RGB8,               GL_RGB,             GL_UNSIGNED_BYTE                 );
76     InsertES3FormatCombo(&set, GL_RGB565,             GL_RGB,             GL_UNSIGNED_BYTE                 );
77     InsertES3FormatCombo(&set, GL_SRGB8,              GL_RGB,             GL_UNSIGNED_BYTE                 );
78     InsertES3FormatCombo(&set, GL_RGB8_SNORM,         GL_RGB,             GL_BYTE                          );
79     InsertES3FormatCombo(&set, GL_RGB565,             GL_RGB,             GL_UNSIGNED_SHORT_5_6_5          );
80     InsertES3FormatCombo(&set, GL_R11F_G11F_B10F,     GL_RGB,             GL_UNSIGNED_INT_10F_11F_11F_REV  );
81     InsertES3FormatCombo(&set, GL_RGB9_E5,            GL_RGB,             GL_UNSIGNED_INT_5_9_9_9_REV      );
82     InsertES3FormatCombo(&set, GL_RGB16F,             GL_RGB,             GL_HALF_FLOAT                    );
83     InsertES3FormatCombo(&set, GL_RGB16F,             GL_RGB,             GL_HALF_FLOAT_OES                );
84     InsertES3FormatCombo(&set, GL_R11F_G11F_B10F,     GL_RGB,             GL_HALF_FLOAT                    );
85     InsertES3FormatCombo(&set, GL_R11F_G11F_B10F,     GL_RGB,             GL_HALF_FLOAT_OES                );
86     InsertES3FormatCombo(&set, GL_RGB9_E5,            GL_RGB,             GL_HALF_FLOAT                    );
87     InsertES3FormatCombo(&set, GL_RGB9_E5,            GL_RGB,             GL_HALF_FLOAT_OES                );
88     InsertES3FormatCombo(&set, GL_RGB32F,             GL_RGB,             GL_FLOAT                         );
89     InsertES3FormatCombo(&set, GL_RGB16F,             GL_RGB,             GL_FLOAT                         );
90     InsertES3FormatCombo(&set, GL_R11F_G11F_B10F,     GL_RGB,             GL_FLOAT                         );
91     InsertES3FormatCombo(&set, GL_RGB9_E5,            GL_RGB,             GL_FLOAT                         );
92     InsertES3FormatCombo(&set, GL_RGB8UI,             GL_RGB_INTEGER,     GL_UNSIGNED_BYTE                 );
93     InsertES3FormatCombo(&set, GL_RGB8I,              GL_RGB_INTEGER,     GL_BYTE                          );
94     InsertES3FormatCombo(&set, GL_RGB16UI,            GL_RGB_INTEGER,     GL_UNSIGNED_SHORT                );
95     InsertES3FormatCombo(&set, GL_RGB16I,             GL_RGB_INTEGER,     GL_SHORT                         );
96     InsertES3FormatCombo(&set, GL_RGB32UI,            GL_RGB_INTEGER,     GL_UNSIGNED_INT                  );
97     InsertES3FormatCombo(&set, GL_RGB32I,             GL_RGB_INTEGER,     GL_INT                           );
98     InsertES3FormatCombo(&set, GL_RG8,                GL_RG,              GL_UNSIGNED_BYTE                 );
99     InsertES3FormatCombo(&set, GL_RG8_SNORM,          GL_RG,              GL_BYTE                          );
100     InsertES3FormatCombo(&set, GL_RG16F,              GL_RG,              GL_HALF_FLOAT                    );
101     InsertES3FormatCombo(&set, GL_RG16F,              GL_RG,              GL_HALF_FLOAT_OES                );
102     InsertES3FormatCombo(&set, GL_RG32F,              GL_RG,              GL_FLOAT                         );
103     InsertES3FormatCombo(&set, GL_RG16F,              GL_RG,              GL_FLOAT                         );
104     InsertES3FormatCombo(&set, GL_RG8UI,              GL_RG_INTEGER,      GL_UNSIGNED_BYTE                 );
105     InsertES3FormatCombo(&set, GL_RG8I,               GL_RG_INTEGER,      GL_BYTE                          );
106     InsertES3FormatCombo(&set, GL_RG16UI,             GL_RG_INTEGER,      GL_UNSIGNED_SHORT                );
107     InsertES3FormatCombo(&set, GL_RG16I,              GL_RG_INTEGER,      GL_SHORT                         );
108     InsertES3FormatCombo(&set, GL_RG32UI,             GL_RG_INTEGER,      GL_UNSIGNED_INT                  );
109     InsertES3FormatCombo(&set, GL_RG32I,              GL_RG_INTEGER,      GL_INT                           );
110     InsertES3FormatCombo(&set, GL_R8,                 GL_RED,             GL_UNSIGNED_BYTE                 );
111     InsertES3FormatCombo(&set, GL_R8_SNORM,           GL_RED,             GL_BYTE                          );
112     InsertES3FormatCombo(&set, GL_R16F,               GL_RED,             GL_HALF_FLOAT                    );
113     InsertES3FormatCombo(&set, GL_R16F,               GL_RED,             GL_HALF_FLOAT_OES                );
114     InsertES3FormatCombo(&set, GL_R32F,               GL_RED,             GL_FLOAT                         );
115     InsertES3FormatCombo(&set, GL_R16F,               GL_RED,             GL_FLOAT                         );
116     InsertES3FormatCombo(&set, GL_R8UI,               GL_RED_INTEGER,     GL_UNSIGNED_BYTE                 );
117     InsertES3FormatCombo(&set, GL_R8I,                GL_RED_INTEGER,     GL_BYTE                          );
118     InsertES3FormatCombo(&set, GL_R16UI,              GL_RED_INTEGER,     GL_UNSIGNED_SHORT                );
119     InsertES3FormatCombo(&set, GL_R16I,               GL_RED_INTEGER,     GL_SHORT                         );
120     InsertES3FormatCombo(&set, GL_R32UI,              GL_RED_INTEGER,     GL_UNSIGNED_INT                  );
121     InsertES3FormatCombo(&set, GL_R32I,               GL_RED_INTEGER,     GL_INT                           );
122
123     // Unsized formats
124     InsertES3FormatCombo(&set, GL_RGBA,               GL_RGBA,            GL_UNSIGNED_BYTE                 );
125     InsertES3FormatCombo(&set, GL_RGBA,               GL_RGBA,            GL_UNSIGNED_SHORT_4_4_4_4        );
126     InsertES3FormatCombo(&set, GL_RGBA,               GL_RGBA,            GL_UNSIGNED_SHORT_5_5_5_1        );
127     InsertES3FormatCombo(&set, GL_RGB,                GL_RGB,             GL_UNSIGNED_BYTE                 );
128     InsertES3FormatCombo(&set, GL_RGB,                GL_RGB,             GL_UNSIGNED_SHORT_5_6_5          );
129     InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA,    GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE                 );
130     InsertES3FormatCombo(&set, GL_LUMINANCE,          GL_LUMINANCE,       GL_UNSIGNED_BYTE                 );
131     InsertES3FormatCombo(&set, GL_ALPHA,              GL_ALPHA,           GL_UNSIGNED_BYTE                 );
132     InsertES3FormatCombo(&set, GL_SRGB_ALPHA_EXT,     GL_SRGB_ALPHA_EXT,  GL_UNSIGNED_BYTE                 );
133     InsertES3FormatCombo(&set, GL_SRGB_EXT,           GL_SRGB_EXT,        GL_UNSIGNED_BYTE                 );
134
135     // Depth stencil formats
136     InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16,  GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT                );
137     InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT24,  GL_DEPTH_COMPONENT, GL_UNSIGNED_INT                  );
138     InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16,  GL_DEPTH_COMPONENT, GL_UNSIGNED_INT                  );
139     InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT                         );
140     InsertES3FormatCombo(&set, GL_DEPTH24_STENCIL8,   GL_DEPTH_STENCIL,   GL_UNSIGNED_INT_24_8             );
141     InsertES3FormatCombo(&set, GL_DEPTH32F_STENCIL8,  GL_DEPTH_STENCIL,   GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
142
143     // From GL_EXT_sRGB
144     InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8_EXT,   GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE                  );
145     InsertES3FormatCombo(&set, GL_SRGB8,              GL_SRGB_EXT,       GL_UNSIGNED_BYTE                  );
146
147     // From GL_OES_texture_float
148     InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA,    GL_LUMINANCE_ALPHA, GL_FLOAT                         );
149     InsertES3FormatCombo(&set, GL_LUMINANCE,          GL_LUMINANCE,       GL_FLOAT                         );
150     InsertES3FormatCombo(&set, GL_ALPHA,              GL_ALPHA,           GL_FLOAT                         );
151
152     // From GL_OES_texture_half_float
153     InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA,    GL_LUMINANCE_ALPHA, GL_HALF_FLOAT                    );
154     InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA,    GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES                );
155     InsertES3FormatCombo(&set, GL_LUMINANCE,          GL_LUMINANCE,       GL_HALF_FLOAT                    );
156     InsertES3FormatCombo(&set, GL_LUMINANCE,          GL_LUMINANCE,       GL_HALF_FLOAT_OES                );
157     InsertES3FormatCombo(&set, GL_ALPHA,              GL_ALPHA,           GL_HALF_FLOAT                    );
158     InsertES3FormatCombo(&set, GL_ALPHA,              GL_ALPHA,           GL_HALF_FLOAT_OES                );
159
160     // From GL_EXT_texture_format_BGRA8888
161     InsertES3FormatCombo(&set, GL_BGRA_EXT,           GL_BGRA_EXT,        GL_UNSIGNED_BYTE                 );
162
163     // From GL_EXT_texture_storage
164     //                    | Internal format          | Format            | Type                            |
165     //                    |                          |                   |                                 |
166     InsertES3FormatCombo(&set, GL_ALPHA8_EXT,             GL_ALPHA,           GL_UNSIGNED_BYTE                 );
167     InsertES3FormatCombo(&set, GL_LUMINANCE8_EXT,         GL_LUMINANCE,       GL_UNSIGNED_BYTE                 );
168     InsertES3FormatCombo(&set, GL_LUMINANCE8_ALPHA8_EXT,  GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE                 );
169     InsertES3FormatCombo(&set, GL_ALPHA32F_EXT,           GL_ALPHA,           GL_FLOAT                         );
170     InsertES3FormatCombo(&set, GL_LUMINANCE32F_EXT,       GL_LUMINANCE,       GL_FLOAT                         );
171     InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT                         );
172     InsertES3FormatCombo(&set, GL_ALPHA16F_EXT,           GL_ALPHA,           GL_HALF_FLOAT                    );
173     InsertES3FormatCombo(&set, GL_ALPHA16F_EXT,           GL_ALPHA,           GL_HALF_FLOAT_OES                );
174     InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT,       GL_LUMINANCE,       GL_HALF_FLOAT                    );
175     InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT,       GL_LUMINANCE,       GL_HALF_FLOAT_OES                );
176     InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT                    );
177     InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES                );
178
179     // From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888
180     InsertES3FormatCombo(&set, GL_BGRA8_EXT,              GL_BGRA_EXT,        GL_UNSIGNED_BYTE                 );
181     InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX,           GL_BGRA_EXT,        GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT);
182     InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX,           GL_BGRA_EXT,        GL_UNSIGNED_BYTE                 );
183     InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX,         GL_BGRA_EXT,        GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT);
184     InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX,         GL_BGRA_EXT,        GL_UNSIGNED_BYTE                 );
185
186     // From GL_ANGLE_depth_texture
187     InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32_OES,  GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8_OES         );
188
189     // Compressed formats
190     // From ES 3.0.1 spec, table 3.16
191     //                    | Internal format                             | Format                                      | Type           |
192     //                    |                                             |                                             |                |
193     InsertES3FormatCombo(&set, GL_COMPRESSED_R11_EAC,                        GL_COMPRESSED_R11_EAC,                        GL_UNSIGNED_BYTE);
194     InsertES3FormatCombo(&set, GL_COMPRESSED_R11_EAC,                        GL_COMPRESSED_R11_EAC,                        GL_UNSIGNED_BYTE);
195     InsertES3FormatCombo(&set, GL_COMPRESSED_SIGNED_R11_EAC,                 GL_COMPRESSED_SIGNED_R11_EAC,                 GL_UNSIGNED_BYTE);
196     InsertES3FormatCombo(&set, GL_COMPRESSED_RG11_EAC,                       GL_COMPRESSED_RG11_EAC,                       GL_UNSIGNED_BYTE);
197     InsertES3FormatCombo(&set, GL_COMPRESSED_SIGNED_RG11_EAC,                GL_COMPRESSED_SIGNED_RG11_EAC,                GL_UNSIGNED_BYTE);
198     InsertES3FormatCombo(&set, GL_COMPRESSED_RGB8_ETC2,                      GL_COMPRESSED_RGB8_ETC2,                      GL_UNSIGNED_BYTE);
199     InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_ETC2,                     GL_COMPRESSED_SRGB8_ETC2,                     GL_UNSIGNED_BYTE);
200     InsertES3FormatCombo(&set, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,  GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,  GL_UNSIGNED_BYTE);
201     InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE);
202     InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA8_ETC2_EAC,                 GL_COMPRESSED_RGBA8_ETC2_EAC,                 GL_UNSIGNED_BYTE);
203     InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,          GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,          GL_UNSIGNED_BYTE);
204
205
206     // From GL_EXT_texture_compression_dxt1
207     InsertES3FormatCombo(&set, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,              GL_COMPRESSED_RGB_S3TC_DXT1_EXT,              GL_UNSIGNED_BYTE);
208     InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,             GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,             GL_UNSIGNED_BYTE);
209
210     // From GL_ANGLE_texture_compression_dxt3
211     InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,           GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,           GL_UNSIGNED_BYTE);
212
213     // From GL_ANGLE_texture_compression_dxt5
214     InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,           GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,           GL_UNSIGNED_BYTE);
215
216     return set;
217 }
218
219 static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
220 {
221     // Note: dEQP 2013.4 expects an INVALID_VALUE error for TexImage3D with an invalid
222     // internal format. (dEQP-GLES3.functional.negative_api.texture.teximage3d)
223     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
224     if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
225     {
226         context->recordError(Error(GL_INVALID_ENUM));
227         return false;
228     }
229
230     // The type and format are valid if any supported internal format has that type and format
231     bool formatSupported = false;
232     bool typeSupported = false;
233
234     static const ES3FormatCombinationSet es3FormatSet = BuildES3FormatSet();
235     for (ES3FormatCombinationSet::const_iterator i = es3FormatSet.begin(); i != es3FormatSet.end(); i++)
236     {
237         if (i->format == format || i->type == type)
238         {
239             const gl::InternalFormat &info = gl::GetInternalFormatInfo(i->internalFormat);
240             bool supported = info.textureSupport(context->getClientVersion(), context->getExtensions());
241             if (supported && i->type == type)
242             {
243                 typeSupported = true;
244             }
245             if (supported && i->format == format)
246             {
247                 formatSupported = true;
248             }
249
250             // Early-out if both type and format are supported now
251             if (typeSupported && formatSupported)
252             {
253                 break;
254             }
255         }
256     }
257
258     if (!typeSupported || !formatSupported)
259     {
260         context->recordError(Error(GL_INVALID_ENUM));
261         return false;
262     }
263
264     // Check if this is a valid format combination to load texture data
265     ES3FormatCombination searchFormat;
266     searchFormat.internalFormat = internalFormat;
267     searchFormat.format = format;
268     searchFormat.type = type;
269
270     if (es3FormatSet.find(searchFormat) == es3FormatSet.end())
271     {
272         context->recordError(Error(GL_INVALID_OPERATION));
273         return false;
274     }
275
276     return true;
277 }
278
279 bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
280                                    GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
281                                    GLint border, GLenum format, GLenum type, const GLvoid *pixels)
282 {
283     if (!ValidTexture2DDestinationTarget(context, target))
284     {
285         context->recordError(Error(GL_INVALID_ENUM));
286         return false;
287     }
288
289     // Validate image size
290     if (!ValidImageSize(context, target, level, width, height, depth))
291     {
292         context->recordError(Error(GL_INVALID_VALUE));
293         return false;
294     }
295
296     // Verify zero border
297     if (border != 0)
298     {
299         context->recordError(Error(GL_INVALID_VALUE));
300         return false;
301     }
302
303     if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
304         std::numeric_limits<GLsizei>::max() - xoffset < width ||
305         std::numeric_limits<GLsizei>::max() - yoffset < height ||
306         std::numeric_limits<GLsizei>::max() - zoffset < depth)
307     {
308         context->recordError(Error(GL_INVALID_VALUE));
309         return false;
310     }
311
312     const gl::Caps &caps = context->getCaps();
313
314     gl::Texture *texture = NULL;
315     bool textureCompressed = false;
316     GLenum textureInternalFormat = GL_NONE;
317     GLint textureLevelWidth = 0;
318     GLint textureLevelHeight = 0;
319     GLint textureLevelDepth = 0;
320     switch (target)
321     {
322       case GL_TEXTURE_2D:
323         {
324             if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
325                 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
326             {
327                 context->recordError(Error(GL_INVALID_VALUE));
328                 return false;
329             }
330
331             gl::Texture2D *texture2d = context->getTexture2D();
332             if (texture2d)
333             {
334                 textureCompressed = texture2d->isCompressed(level);
335                 textureInternalFormat = texture2d->getInternalFormat(level);
336                 textureLevelWidth = texture2d->getWidth(level);
337                 textureLevelHeight = texture2d->getHeight(level);
338                 textureLevelDepth = 1;
339                 texture = texture2d;
340             }
341         }
342         break;
343
344       case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
345       case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
346       case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
347       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
348       case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
349       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
350         {
351             if (!isSubImage && width != height)
352             {
353                 context->recordError(Error(GL_INVALID_VALUE));
354                 return false;
355             }
356
357             if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
358             {
359                 context->recordError(Error(GL_INVALID_VALUE));
360                 return false;
361             }
362
363             gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
364             if (textureCube)
365             {
366                 textureCompressed = textureCube->isCompressed(target, level);
367                 textureInternalFormat = textureCube->getInternalFormat(target, level);
368                 textureLevelWidth = textureCube->getWidth(target, level);
369                 textureLevelHeight = textureCube->getHeight(target, level);
370                 textureLevelDepth = 1;
371                 texture = textureCube;
372             }
373         }
374         break;
375
376       case GL_TEXTURE_3D:
377         {
378             if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
379                 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
380                 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
381             {
382                 context->recordError(Error(GL_INVALID_VALUE));
383                 return false;
384             }
385
386             gl::Texture3D *texture3d = context->getTexture3D();
387             if (texture3d)
388             {
389                 textureCompressed = texture3d->isCompressed(level);
390                 textureInternalFormat = texture3d->getInternalFormat(level);
391                 textureLevelWidth = texture3d->getWidth(level);
392                 textureLevelHeight = texture3d->getHeight(level);
393                 textureLevelDepth = texture3d->getDepth(level);
394                 texture = texture3d;
395             }
396         }
397         break;
398
399         case GL_TEXTURE_2D_ARRAY:
400           {
401               if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
402                   static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
403                   static_cast<GLuint>(depth) > (caps.maxArrayTextureLayers >> level))
404               {
405                   context->recordError(Error(GL_INVALID_VALUE));
406                   return false;
407               }
408
409               gl::Texture2DArray *texture2darray = context->getTexture2DArray();
410               if (texture2darray)
411               {
412                   textureCompressed = texture2darray->isCompressed(level);
413                   textureInternalFormat = texture2darray->getInternalFormat(level);
414                   textureLevelWidth = texture2darray->getWidth(level);
415                   textureLevelHeight = texture2darray->getHeight(level);
416                   textureLevelDepth = texture2darray->getLayers(level);
417                   texture = texture2darray;
418               }
419           }
420           break;
421
422       default:
423         context->recordError(Error(GL_INVALID_ENUM));
424         return false;
425     }
426
427     if (!texture)
428     {
429         context->recordError(Error(GL_INVALID_OPERATION));
430         return false;
431     }
432
433     if (texture->isImmutable() && !isSubImage)
434     {
435         context->recordError(Error(GL_INVALID_OPERATION));
436         return false;
437     }
438
439     // Validate texture formats
440     GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
441     const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
442     if (isCompressed)
443     {
444         if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
445         {
446             context->recordError(Error(GL_INVALID_OPERATION));
447             return false;
448         }
449
450         if (!actualFormatInfo.compressed)
451         {
452             context->recordError(Error(GL_INVALID_ENUM));
453             return false;
454         }
455
456         if (target == GL_TEXTURE_3D)
457         {
458             context->recordError(Error(GL_INVALID_OPERATION));
459             return false;
460         }
461     }
462     else
463     {
464         if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
465         {
466             return false;
467         }
468
469         if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
470         {
471             context->recordError(Error(GL_INVALID_OPERATION));
472             return false;
473         }
474     }
475
476     // Validate sub image parameters
477     if (isSubImage)
478     {
479         if (isCompressed != textureCompressed)
480         {
481             context->recordError(Error(GL_INVALID_OPERATION));
482             return false;
483         }
484
485         if (isCompressed)
486         {
487             if ((width % 4 != 0 && width != textureLevelWidth) ||
488                 (height % 4 != 0 && height != textureLevelHeight))
489             {
490                 context->recordError(Error(GL_INVALID_OPERATION));
491                 return false;
492             }
493         }
494
495         if (width == 0 || height == 0 || depth == 0)
496         {
497             return false;
498         }
499
500         if (xoffset < 0 || yoffset < 0 || zoffset < 0)
501         {
502             context->recordError(Error(GL_INVALID_VALUE));
503             return false;
504         }
505
506         if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
507             std::numeric_limits<GLsizei>::max() - yoffset < height ||
508             std::numeric_limits<GLsizei>::max() - zoffset < depth)
509         {
510             context->recordError(Error(GL_INVALID_VALUE));
511             return false;
512         }
513
514         if (xoffset + width > textureLevelWidth ||
515             yoffset + height > textureLevelHeight ||
516             zoffset + depth > textureLevelDepth)
517         {
518             context->recordError(Error(GL_INVALID_VALUE));
519             return false;
520         }
521     }
522
523     // Check for pixel unpack buffer related API errors
524     gl::Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
525     if (pixelUnpackBuffer != NULL)
526     {
527         // ...the data would be unpacked from the buffer object such that the memory reads required
528         // would exceed the data store size.
529         size_t widthSize = static_cast<size_t>(width);
530         size_t heightSize = static_cast<size_t>(height);
531         size_t depthSize = static_cast<size_t>(depth);
532         GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type);
533
534         size_t pixelBytes = static_cast<size_t>(gl::GetInternalFormatInfo(sizedFormat).pixelBytes);
535
536         if (!rx::IsUnsignedMultiplicationSafe(widthSize, heightSize) ||
537             !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize, depthSize) ||
538             !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize * depthSize, pixelBytes))
539         {
540             // Overflow past the end of the buffer
541             context->recordError(Error(GL_INVALID_OPERATION));
542             return false;
543         }
544
545         size_t copyBytes = widthSize * heightSize * depthSize * pixelBytes;
546         size_t offset = reinterpret_cast<size_t>(pixels);
547
548         if (!rx::IsUnsignedAdditionSafe(offset, copyBytes) ||
549             ((offset + copyBytes) > static_cast<size_t>(pixelUnpackBuffer->getSize())))
550         {
551             // Overflow past the end of the buffer
552             context->recordError(Error(GL_INVALID_OPERATION));
553             return false;
554         }
555
556         // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
557         // indicated by type.
558         size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
559
560         if ((offset % dataBytesPerPixel) != 0)
561         {
562             context->recordError(Error(GL_INVALID_OPERATION));
563             return false;
564         }
565
566         // ...the buffer object's data store is currently mapped.
567         if (pixelUnpackBuffer->isMapped())
568         {
569             context->recordError(Error(GL_INVALID_OPERATION));
570             return false;
571         }
572     }
573
574     return true;
575 }
576
577 struct EffectiveInternalFormatInfo
578 {
579     GLenum mEffectiveFormat;
580     GLenum mDestFormat;
581     GLuint mMinRedBits;
582     GLuint mMaxRedBits;
583     GLuint mMinGreenBits;
584     GLuint mMaxGreenBits;
585     GLuint mMinBlueBits;
586     GLuint mMaxBlueBits;
587     GLuint mMinAlphaBits;
588     GLuint mMaxAlphaBits;
589
590     EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits,
591                                 GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits,
592                                 GLuint minAlphaBits, GLuint maxAlphaBits)
593         : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits),
594           mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits),
595           mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits),
596           mMaxAlphaBits(maxAlphaBits) {};
597 };
598
599 typedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
600
601 static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList()
602 {
603     EffectiveInternalFormatList list;
604
605     // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
606     //                                                    linear source buffer component sizes.
607     //                                                                            | Source channel min/max sizes |
608     //                                         Effective Internal Format |  N/A   |  R   |  G   |  B   |  A      |
609     list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT,              GL_NONE, 0,  0, 0,  0, 0,  0, 1, 8));
610     list.push_back(EffectiveInternalFormatInfo(GL_R8,                      GL_NONE, 1,  8, 0,  0, 0,  0, 0, 0));
611     list.push_back(EffectiveInternalFormatInfo(GL_RG8,                     GL_NONE, 1,  8, 1,  8, 0,  0, 0, 0));
612     list.push_back(EffectiveInternalFormatInfo(GL_RGB565,                  GL_NONE, 1,  5, 1,  6, 1,  5, 0, 0));
613     list.push_back(EffectiveInternalFormatInfo(GL_RGB8,                    GL_NONE, 6,  8, 7,  8, 6,  8, 0, 0));
614     list.push_back(EffectiveInternalFormatInfo(GL_RGBA4,                   GL_NONE, 1,  4, 1,  4, 1,  4, 1, 4));
615     list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1,                 GL_NONE, 5,  5, 5,  5, 5,  5, 1, 1));
616     list.push_back(EffectiveInternalFormatInfo(GL_RGBA8,                   GL_NONE, 5,  8, 5,  8, 5,  8, 2, 8));
617     list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2,                GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2));
618
619     return list;
620 }
621
622 static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList()
623 {
624     EffectiveInternalFormatList list;
625
626     // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
627     //                                                    linear source buffer component sizes.
628     //                                                                                        |          Source channel min/max sizes            |
629     //                                         Effective Internal Format |    Dest Format     |     R     |      G     |      B     |      A     |
630     list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT,              GL_ALPHA,           0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1,        8));
631     list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT,          GL_LUMINANCE,       1,        8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX));
632     list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT,   GL_LUMINANCE_ALPHA, 1,        8, 0, UINT_MAX, 0, UINT_MAX, 1,        8));
633     list.push_back(EffectiveInternalFormatInfo(GL_RGB565,                  GL_RGB,             1,        5, 1,        6, 1,        5, 0, UINT_MAX));
634     list.push_back(EffectiveInternalFormatInfo(GL_RGB8,                    GL_RGB,             6,        8, 7,        8, 6,        8, 0, UINT_MAX));
635     list.push_back(EffectiveInternalFormatInfo(GL_RGBA4,                   GL_RGBA,            1,        4, 1,        4, 1,        4, 1,        4));
636     list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1,                 GL_RGBA,            5,        5, 5,        5, 5,        5, 1,        1));
637     list.push_back(EffectiveInternalFormatInfo(GL_RGBA8,                   GL_RGBA,            5,        8, 5,        8, 5,        8, 5,        8));
638
639     return list;
640 }
641
642 static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
643                                        GLenum *outEffectiveFormat)
644 {
645     const EffectiveInternalFormatList *list = NULL;
646     GLenum targetFormat = GL_NONE;
647
648     if (destFormat.pixelBytes > 0)
649     {
650         static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList();
651         list = &sizedList;
652     }
653     else
654     {
655         static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList();
656         list = &unsizedList;
657         targetFormat = destFormat.format;
658     }
659
660     for (size_t curFormat = 0; curFormat < list->size(); ++curFormat)
661     {
662         const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat);
663         if ((formatInfo.mDestFormat == targetFormat) &&
664             (formatInfo.mMinRedBits   <= srcFormat.redBits   && formatInfo.mMaxRedBits   >= srcFormat.redBits)   &&
665             (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) &&
666             (formatInfo.mMinBlueBits  <= srcFormat.blueBits  && formatInfo.mMaxBlueBits  >= srcFormat.blueBits)  &&
667             (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits))
668         {
669             *outEffectiveFormat = formatInfo.mEffectiveFormat;
670             return true;
671         }
672     }
673
674     return false;
675 }
676
677 struct CopyConversion
678 {
679     GLenum mTextureFormat;
680     GLenum mFramebufferFormat;
681
682     CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
683         : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
684
685     bool operator<(const CopyConversion& other) const
686     {
687         return memcmp(this, &other, sizeof(CopyConversion)) < 0;
688     }
689 };
690
691 typedef std::set<CopyConversion> CopyConversionSet;
692
693 static CopyConversionSet BuildValidES3CopyTexImageCombinations()
694 {
695     CopyConversionSet set;
696
697     // From ES 3.0.1 spec, table 3.15
698     set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
699     set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
700     set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
701     set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
702     set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
703     set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
704     set.insert(CopyConversion(GL_RED, GL_RED));
705     set.insert(CopyConversion(GL_RED, GL_RG));
706     set.insert(CopyConversion(GL_RED, GL_RGB));
707     set.insert(CopyConversion(GL_RED, GL_RGBA));
708     set.insert(CopyConversion(GL_RG, GL_RG));
709     set.insert(CopyConversion(GL_RG, GL_RGB));
710     set.insert(CopyConversion(GL_RG, GL_RGBA));
711     set.insert(CopyConversion(GL_RGB, GL_RGB));
712     set.insert(CopyConversion(GL_RGB, GL_RGBA));
713     set.insert(CopyConversion(GL_RGBA, GL_RGBA));
714
715     // Necessary for ANGLE back-buffers
716     set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
717     set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
718     set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
719     set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
720     set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
721     set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
722     set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
723
724     set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
725     set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
726     set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
727     set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
728     set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
729     set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
730     set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
731     set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
732     set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
733     set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
734
735     return set;
736 }
737
738 static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle)
739 {
740     const InternalFormat &textureInternalFormatInfo = GetInternalFormatInfo(textureInternalFormat);
741     const InternalFormat &framebufferInternalFormatInfo = GetInternalFormatInfo(frameBufferInternalFormat);
742
743     static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
744     if (conversionSet.find(CopyConversion(textureInternalFormatInfo.format, framebufferInternalFormatInfo.format)) != conversionSet.end())
745     {
746         // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
747         // must both be signed, unsigned, or fixed point and both source and destinations
748         // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
749         // conversion between fixed and floating point.
750
751         if ((textureInternalFormatInfo.colorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.colorEncoding == GL_SRGB))
752         {
753             return false;
754         }
755
756         if (((textureInternalFormatInfo.componentType == GL_INT)          != (framebufferInternalFormatInfo.componentType == GL_INT         )) ||
757             ((textureInternalFormatInfo.componentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.componentType == GL_UNSIGNED_INT)))
758         {
759             return false;
760         }
761
762         if ((textureInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
763              textureInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
764              textureInternalFormatInfo.componentType == GL_FLOAT) &&
765             !(framebufferInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
766               framebufferInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
767               framebufferInternalFormatInfo.componentType == GL_FLOAT))
768         {
769             return false;
770         }
771
772         // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
773         // The effective internal format of the source buffer is determined with the following rules applied in order:
774         //    * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
775         //      effective internal format is the source buffer's sized internal format.
776         //    * If the source buffer is a texture that was created with an unsized base internal format, then the
777         //      effective internal format is the source image array's effective internal format, as specified by table
778         //      3.12, which is determined from the <format> and <type> that were used when the source image array was
779         //      specified by TexImage*.
780         //    * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
781         //      Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
782         //      with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
783         //      FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
784         //      is SRGB.
785         const InternalFormat *sourceEffectiveFormat = NULL;
786         if (readBufferHandle != 0)
787         {
788             // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
789             if (framebufferInternalFormatInfo.pixelBytes > 0)
790             {
791                 sourceEffectiveFormat = &framebufferInternalFormatInfo;
792             }
793             else
794             {
795                 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
796                 // texture. We can use the same table we use when creating textures to get its effective sized format.
797                 const FormatType &typeInfo = GetFormatTypeInfo(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type);
798                 sourceEffectiveFormat = &GetInternalFormatInfo(typeInfo.internalFormat);
799             }
800         }
801         else
802         {
803             // The effective internal format must be derived from the source framebuffer's channel sizes.
804             // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
805             if (framebufferInternalFormatInfo.colorEncoding == GL_LINEAR)
806             {
807                 GLenum effectiveFormat;
808                 if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat))
809                 {
810                     sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
811                 }
812                 else
813                 {
814                     return false;
815                 }
816             }
817             else if (framebufferInternalFormatInfo.colorEncoding == GL_SRGB)
818             {
819                 // SRGB buffers can only be copied to sized format destinations according to table 3.18
820                 if ((textureInternalFormatInfo.pixelBytes > 0) &&
821                     (framebufferInternalFormatInfo.redBits   >= 1 && framebufferInternalFormatInfo.redBits   <= 8) &&
822                     (framebufferInternalFormatInfo.greenBits >= 1 && framebufferInternalFormatInfo.greenBits <= 8) &&
823                     (framebufferInternalFormatInfo.blueBits  >= 1 && framebufferInternalFormatInfo.blueBits  <= 8) &&
824                     (framebufferInternalFormatInfo.alphaBits >= 1 && framebufferInternalFormatInfo.alphaBits <= 8))
825                 {
826                     sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
827                 }
828                 else
829                 {
830                     return false;
831                 }
832             }
833             else
834             {
835                 UNREACHABLE();
836                 return false;
837             }
838         }
839
840         if (textureInternalFormatInfo.pixelBytes > 0)
841         {
842             // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is sized,
843             // component sizes of the source and destination formats must exactly match
844             if (textureInternalFormatInfo.redBits   != sourceEffectiveFormat->redBits   ||
845                 textureInternalFormatInfo.greenBits != sourceEffectiveFormat->greenBits ||
846                 textureInternalFormatInfo.blueBits  != sourceEffectiveFormat->blueBits  ||
847                 textureInternalFormatInfo.alphaBits != sourceEffectiveFormat->alphaBits)
848             {
849                 return false;
850             }
851         }
852
853
854         return true; // A conversion function exists, and no rule in the specification has precluded conversion
855                      // between these formats.
856     }
857
858     return false;
859 }
860
861 bool ValidateES3CopyTexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat,
862                                        bool isSubImage, GLint xoffset, GLint yoffset, GLint zoffset,
863                                        GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
864 {
865     GLenum textureInternalFormat;
866     if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
867                                             xoffset, yoffset, zoffset, x, y, width, height,
868                                             border, &textureInternalFormat))
869     {
870         return false;
871     }
872
873     gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
874
875     if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
876     {
877         context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
878         return false;
879     }
880
881     if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0)
882     {
883         context->recordError(Error(GL_INVALID_OPERATION));
884         return false;
885     }
886
887     gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer();
888     GLenum colorbufferInternalFormat = source->getInternalFormat();
889
890     if (isSubImage)
891     {
892         if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat,
893                                                context->getState().getReadFramebuffer()->id()))
894         {
895             context->recordError(Error(GL_INVALID_OPERATION));
896             return false;
897         }
898     }
899     else
900     {
901         if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat,
902                                                 context->getState().getReadFramebuffer()->id()))
903         {
904             context->recordError(Error(GL_INVALID_OPERATION));
905             return false;
906         }
907     }
908
909     // If width or height is zero, it is a no-op.  Return false without setting an error.
910     return (width > 0 && height > 0);
911 }
912
913 bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
914                                      GLsizei width, GLsizei height, GLsizei depth)
915 {
916     if (width < 1 || height < 1 || depth < 1 || levels < 1)
917     {
918         context->recordError(Error(GL_INVALID_VALUE));
919         return false;
920     }
921
922     if (levels > gl::log2(std::max(std::max(width, height), depth)) + 1)
923     {
924         context->recordError(Error(GL_INVALID_OPERATION));
925         return false;
926     }
927
928     const gl::Caps &caps = context->getCaps();
929
930     gl::Texture *texture = NULL;
931     switch (target)
932     {
933       case GL_TEXTURE_2D:
934         {
935             texture = context->getTexture2D();
936
937             if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
938                 static_cast<GLuint>(height) > caps.max2DTextureSize)
939             {
940                 context->recordError(Error(GL_INVALID_VALUE));
941                 return false;
942             }
943         }
944         break;
945
946       case GL_TEXTURE_CUBE_MAP:
947         {
948             texture = context->getTextureCubeMap();
949
950             if (width != height)
951             {
952                 context->recordError(Error(GL_INVALID_VALUE));
953                 return false;
954             }
955
956             if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
957             {
958                 context->recordError(Error(GL_INVALID_VALUE));
959                 return false;
960             }
961         }
962         break;
963
964       case GL_TEXTURE_3D:
965         {
966             texture = context->getTexture3D();
967
968             if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
969                 static_cast<GLuint>(height) > caps.max3DTextureSize ||
970                 static_cast<GLuint>(depth) > caps.max3DTextureSize)
971             {
972                 context->recordError(Error(GL_INVALID_VALUE));
973                 return false;
974             }
975         }
976         break;
977
978       case GL_TEXTURE_2D_ARRAY:
979         {
980             texture = context->getTexture2DArray();
981
982             if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
983                 static_cast<GLuint>(height) > caps.max2DTextureSize ||
984                 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
985             {
986                 context->recordError(Error(GL_INVALID_VALUE));
987                 return false;
988             }
989         }
990         break;
991
992       default:
993         context->recordError(Error(GL_INVALID_ENUM));
994         return false;
995     }
996
997     if (!texture || texture->id() == 0)
998     {
999         context->recordError(Error(GL_INVALID_OPERATION));
1000         return false;
1001     }
1002
1003     if (texture->isImmutable())
1004     {
1005         context->recordError(Error(GL_INVALID_OPERATION));
1006         return false;
1007     }
1008
1009     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1010     if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
1011     {
1012         context->recordError(Error(GL_INVALID_ENUM));
1013         return false;
1014     }
1015
1016     if (formatInfo.pixelBytes == 0)
1017     {
1018         context->recordError(Error(GL_INVALID_ENUM));
1019         return false;
1020     }
1021
1022     return true;
1023 }
1024
1025 bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
1026                                      GLuint texture, GLint level, GLint layer)
1027 {
1028     if (context->getClientVersion() < 3)
1029     {
1030         context->recordError(Error(GL_INVALID_OPERATION));
1031         return false;
1032     }
1033
1034     if (layer < 0)
1035     {
1036         context->recordError(Error(GL_INVALID_VALUE));
1037         return false;
1038     }
1039
1040     if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1041     {
1042         return false;
1043     }
1044
1045     const gl::Caps &caps = context->getCaps();
1046     if (texture != 0)
1047     {
1048         gl::Texture *tex = context->getTexture(texture);
1049         ASSERT(tex);
1050
1051         switch (tex->getTarget())
1052         {
1053           case GL_TEXTURE_2D_ARRAY:
1054             {
1055                 if (level > gl::log2(caps.max2DTextureSize))
1056                 {
1057                     context->recordError(Error(GL_INVALID_VALUE));
1058                     return false;
1059                 }
1060
1061                 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1062                 {
1063                     context->recordError(Error(GL_INVALID_VALUE));
1064                     return false;
1065                 }
1066
1067                 gl::Texture2DArray *texArray = static_cast<gl::Texture2DArray *>(tex);
1068                 if (texArray->isCompressed(level))
1069                 {
1070                     context->recordError(Error(GL_INVALID_OPERATION));
1071                     return false;
1072                 }
1073             }
1074             break;
1075
1076           case GL_TEXTURE_3D:
1077             {
1078                 if (level > gl::log2(caps.max3DTextureSize))
1079                 {
1080                     context->recordError(Error(GL_INVALID_VALUE));
1081                     return false;
1082                 }
1083
1084                 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1085                 {
1086                     context->recordError(Error(GL_INVALID_VALUE));
1087                     return false;
1088                 }
1089
1090                 gl::Texture3D *tex3d = static_cast<gl::Texture3D *>(tex);
1091                 if (tex3d->isCompressed(level))
1092                 {
1093                     context->recordError(Error(GL_INVALID_OPERATION));
1094                     return false;
1095                 }
1096             }
1097             break;
1098
1099           default:
1100             context->recordError(Error(GL_INVALID_OPERATION));
1101             return false;
1102         }
1103     }
1104
1105     return true;
1106 }
1107
1108 bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type)
1109 {
1110     const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
1111
1112     switch (format)
1113     {
1114       case GL_RGBA:
1115         switch (type)
1116         {
1117           case GL_UNSIGNED_BYTE:
1118             break;
1119           case GL_UNSIGNED_INT_2_10_10_10_REV:
1120             if (internalFormat != GL_RGB10_A2)
1121             {
1122                 return false;
1123             }
1124             break;
1125           case GL_FLOAT:
1126             if (internalFormatInfo.componentType != GL_FLOAT)
1127             {
1128                 return false;
1129             }
1130             break;
1131           default:
1132             return false;
1133         }
1134         break;
1135       case GL_RGBA_INTEGER:
1136         switch (type)
1137         {
1138           case GL_INT:
1139             if (internalFormatInfo.componentType != GL_INT)
1140             {
1141                 return false;
1142             }
1143             break;
1144           case GL_UNSIGNED_INT:
1145             if (internalFormatInfo.componentType != GL_UNSIGNED_INT)
1146             {
1147                 return false;
1148             }
1149             break;
1150           default:
1151             return false;
1152         }
1153         break;
1154       case GL_BGRA_EXT:
1155         switch (type)
1156         {
1157           case GL_UNSIGNED_BYTE:
1158           case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1159           case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1160             break;
1161           default:
1162             return false;
1163         }
1164         break;
1165       case GL_RG_EXT:
1166       case GL_RED_EXT:
1167         if (!context->getExtensions().textureRG)
1168         {
1169             return false;
1170         }
1171         switch (type)
1172         {
1173         case GL_UNSIGNED_BYTE:
1174             break;
1175         default:
1176             return false;
1177         }
1178         break;
1179       default:
1180         return false;
1181     }
1182     return true;
1183 }
1184
1185 bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments,
1186                                              const GLenum* attachments)
1187 {
1188     bool defaultFramebuffer = false;
1189
1190     switch (target)
1191     {
1192       case GL_DRAW_FRAMEBUFFER:
1193       case GL_FRAMEBUFFER:
1194         defaultFramebuffer = context->getState().getDrawFramebuffer()->id() == 0;
1195         break;
1196       case GL_READ_FRAMEBUFFER:
1197         defaultFramebuffer = context->getState().getReadFramebuffer()->id() == 0;
1198         break;
1199       default:
1200           context->recordError(Error(GL_INVALID_ENUM));
1201           return false;
1202     }
1203
1204     for (int i = 0; i < numAttachments; ++i)
1205     {
1206         if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15)
1207         {
1208             if (defaultFramebuffer)
1209             {
1210                 context->recordError(Error(GL_INVALID_ENUM));
1211                 return false;
1212             }
1213
1214             if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
1215             {
1216                 context->recordError(Error(GL_INVALID_OPERATION));
1217                 return false;
1218             }
1219         }
1220         else
1221         {
1222             switch (attachments[i])
1223             {
1224               case GL_DEPTH_ATTACHMENT:
1225               case GL_STENCIL_ATTACHMENT:
1226               case GL_DEPTH_STENCIL_ATTACHMENT:
1227                 if (defaultFramebuffer)
1228                 {
1229                     context->recordError(Error(GL_INVALID_ENUM));
1230                     return false;
1231                 }
1232                 break;
1233               case GL_COLOR:
1234               case GL_DEPTH:
1235               case GL_STENCIL:
1236                 if (!defaultFramebuffer)
1237                 {
1238                     context->recordError(Error(GL_INVALID_ENUM));
1239                     return false;
1240                 }
1241                 break;
1242               default:
1243                 context->recordError(Error(GL_INVALID_ENUM));
1244                 return false;
1245             }
1246         }
1247     }
1248
1249     return true;
1250 }
1251
1252 bool ValidateClearBuffer(Context *context)
1253 {
1254     if (context->getClientVersion() < 3)
1255     {
1256         context->recordError(Error(GL_INVALID_OPERATION));
1257         return false;
1258     }
1259
1260     const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer();
1261     if (!fbo || fbo->completeness() != GL_FRAMEBUFFER_COMPLETE)
1262     {
1263         context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
1264         return false;
1265     }
1266
1267     return true;
1268 }
1269
1270 bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
1271 {
1272     if (context->getClientVersion() < 3)
1273     {
1274         context->recordError(Error(GL_INVALID_OPERATION));
1275         return false;
1276     }
1277
1278     return ValidateGetUniformBase(context, program, location);
1279 }
1280
1281 }