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
21namespace gl
22{
23
24struct ES3FormatCombination
25{
26    GLenum internalFormat;
27    GLenum format;
28    GLenum type;
29};
30
31bool operator<(const ES3FormatCombination& a, const ES3FormatCombination& b)
32{
33    return memcmp(&a, &b, sizeof(ES3FormatCombination)) < 0;
34}
35
36typedef std::set<ES3FormatCombination> ES3FormatCombinationSet;
37
38static 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
47ES3FormatCombinationSet 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
219static 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
279bool 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
577struct 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
599typedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
600
601static 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
622static 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
642static 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
677struct 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
691typedef std::set<CopyConversion> CopyConversionSet;
692
693static 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
738static 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
861bool 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
913bool 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
1025bool 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
1108bool 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
1185bool 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
1252bool 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
1270bool 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}
1282