1e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang//
2cec3590a151059813b91b33cd5e000c94f5bccaaGeoff Lang// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
3e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang// Use of this source code is governed by a BSD-style license that can be
4e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang// found in the LICENSE file.
5e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang//
6e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
7e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
9e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang#include "libGLESv2/validationES3.h"
10ce6356958ba86c2b09e62e1250cabd6bab16a082Geoff Lang#include "libGLESv2/validationES.h"
11e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang#include "libGLESv2/Context.h"
12e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang#include "libGLESv2/Texture.h"
13e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang#include "libGLESv2/Framebuffer.h"
14e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang#include "libGLESv2/Renderbuffer.h"
15e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang#include "libGLESv2/formatutils.h"
16e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang#include "libGLESv2/main.h"
17e261b44af7631c31ddca8601490e7445af5a3341Jamie Madill#include "libGLESv2/FramebufferAttachment.h"
18e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
19e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang#include "common/mathutil.h"
20e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
21e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Langnamespace gl
22e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang{
23e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
245d601382b51c29d1670b58c01360416bd929842dGeoff Langstruct ES3FormatCombination
255d601382b51c29d1670b58c01360416bd929842dGeoff Lang{
265d601382b51c29d1670b58c01360416bd929842dGeoff Lang    GLenum internalFormat;
275d601382b51c29d1670b58c01360416bd929842dGeoff Lang    GLenum format;
285d601382b51c29d1670b58c01360416bd929842dGeoff Lang    GLenum type;
295d601382b51c29d1670b58c01360416bd929842dGeoff Lang};
305d601382b51c29d1670b58c01360416bd929842dGeoff Lang
315d601382b51c29d1670b58c01360416bd929842dGeoff Langbool operator<(const ES3FormatCombination& a, const ES3FormatCombination& b)
325d601382b51c29d1670b58c01360416bd929842dGeoff Lang{
335d601382b51c29d1670b58c01360416bd929842dGeoff Lang    return memcmp(&a, &b, sizeof(ES3FormatCombination)) < 0;
345d601382b51c29d1670b58c01360416bd929842dGeoff Lang}
355d601382b51c29d1670b58c01360416bd929842dGeoff Lang
365d601382b51c29d1670b58c01360416bd929842dGeoff Langtypedef std::set<ES3FormatCombination> ES3FormatCombinationSet;
375d601382b51c29d1670b58c01360416bd929842dGeoff Lang
385d601382b51c29d1670b58c01360416bd929842dGeoff Langstatic inline void InsertES3FormatCombo(ES3FormatCombinationSet *set, GLenum internalFormat, GLenum format, GLenum type)
395d601382b51c29d1670b58c01360416bd929842dGeoff Lang{
405d601382b51c29d1670b58c01360416bd929842dGeoff Lang    ES3FormatCombination info;
415d601382b51c29d1670b58c01360416bd929842dGeoff Lang    info.internalFormat = internalFormat;
425d601382b51c29d1670b58c01360416bd929842dGeoff Lang    info.format = format;
435d601382b51c29d1670b58c01360416bd929842dGeoff Lang    info.type = type;
445d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set->insert(info);
455d601382b51c29d1670b58c01360416bd929842dGeoff Lang}
465d601382b51c29d1670b58c01360416bd929842dGeoff Lang
475d601382b51c29d1670b58c01360416bd929842dGeoff LangES3FormatCombinationSet BuildES3FormatSet()
485d601382b51c29d1670b58c01360416bd929842dGeoff Lang{
495d601382b51c29d1670b58c01360416bd929842dGeoff Lang    ES3FormatCombinationSet set;
505d601382b51c29d1670b58c01360416bd929842dGeoff Lang
515d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // Format combinations from ES 3.0.1 spec, table 3.2
525d601382b51c29d1670b58c01360416bd929842dGeoff Lang
535d601382b51c29d1670b58c01360416bd929842dGeoff Lang    //                        | Internal format      | Format            | Type                            |
545d601382b51c29d1670b58c01360416bd929842dGeoff Lang    //                        |                      |                   |                                 |
555d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGBA8,              GL_RGBA,            GL_UNSIGNED_BYTE                 );
565d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB5_A1,            GL_RGBA,            GL_UNSIGNED_BYTE                 );
575d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGBA4,              GL_RGBA,            GL_UNSIGNED_BYTE                 );
585d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8,       GL_RGBA,            GL_UNSIGNED_BYTE                 );
595d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGBA8_SNORM,        GL_RGBA,            GL_BYTE                          );
605d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGBA4,              GL_RGBA,            GL_UNSIGNED_SHORT_4_4_4_4        );
615d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB10_A2,           GL_RGBA,            GL_UNSIGNED_INT_2_10_10_10_REV   );
625d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB5_A1,            GL_RGBA,            GL_UNSIGNED_INT_2_10_10_10_REV   );
635d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB5_A1,            GL_RGBA,            GL_UNSIGNED_SHORT_5_5_5_1        );
645d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGBA16F,            GL_RGBA,            GL_HALF_FLOAT                    );
655d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGBA16F,            GL_RGBA,            GL_HALF_FLOAT_OES                );
665d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGBA32F,            GL_RGBA,            GL_FLOAT                         );
675d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGBA16F,            GL_RGBA,            GL_FLOAT                         );
685d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGBA8UI,            GL_RGBA_INTEGER,    GL_UNSIGNED_BYTE                 );
695d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGBA8I,             GL_RGBA_INTEGER,    GL_BYTE                          );
705d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGBA16UI,           GL_RGBA_INTEGER,    GL_UNSIGNED_SHORT                );
715d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGBA16I,            GL_RGBA_INTEGER,    GL_SHORT                         );
725d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGBA32UI,           GL_RGBA_INTEGER,    GL_UNSIGNED_INT                  );
735d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGBA32I,            GL_RGBA_INTEGER,    GL_INT                           );
745d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB10_A2UI,         GL_RGBA_INTEGER,    GL_UNSIGNED_INT_2_10_10_10_REV   );
755d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB8,               GL_RGB,             GL_UNSIGNED_BYTE                 );
765d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB565,             GL_RGB,             GL_UNSIGNED_BYTE                 );
775d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_SRGB8,              GL_RGB,             GL_UNSIGNED_BYTE                 );
785d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB8_SNORM,         GL_RGB,             GL_BYTE                          );
795d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB565,             GL_RGB,             GL_UNSIGNED_SHORT_5_6_5          );
805d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_R11F_G11F_B10F,     GL_RGB,             GL_UNSIGNED_INT_10F_11F_11F_REV  );
815d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB9_E5,            GL_RGB,             GL_UNSIGNED_INT_5_9_9_9_REV      );
825d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB16F,             GL_RGB,             GL_HALF_FLOAT                    );
835d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB16F,             GL_RGB,             GL_HALF_FLOAT_OES                );
845d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_R11F_G11F_B10F,     GL_RGB,             GL_HALF_FLOAT                    );
855d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_R11F_G11F_B10F,     GL_RGB,             GL_HALF_FLOAT_OES                );
865d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB9_E5,            GL_RGB,             GL_HALF_FLOAT                    );
875d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB9_E5,            GL_RGB,             GL_HALF_FLOAT_OES                );
885d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB32F,             GL_RGB,             GL_FLOAT                         );
895d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB16F,             GL_RGB,             GL_FLOAT                         );
905d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_R11F_G11F_B10F,     GL_RGB,             GL_FLOAT                         );
915d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB9_E5,            GL_RGB,             GL_FLOAT                         );
925d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB8UI,             GL_RGB_INTEGER,     GL_UNSIGNED_BYTE                 );
935d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB8I,              GL_RGB_INTEGER,     GL_BYTE                          );
945d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB16UI,            GL_RGB_INTEGER,     GL_UNSIGNED_SHORT                );
955d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB16I,             GL_RGB_INTEGER,     GL_SHORT                         );
965d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB32UI,            GL_RGB_INTEGER,     GL_UNSIGNED_INT                  );
975d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB32I,             GL_RGB_INTEGER,     GL_INT                           );
985d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RG8,                GL_RG,              GL_UNSIGNED_BYTE                 );
995d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RG8_SNORM,          GL_RG,              GL_BYTE                          );
1005d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RG16F,              GL_RG,              GL_HALF_FLOAT                    );
1015d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RG16F,              GL_RG,              GL_HALF_FLOAT_OES                );
1025d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RG32F,              GL_RG,              GL_FLOAT                         );
1035d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RG16F,              GL_RG,              GL_FLOAT                         );
1045d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RG8UI,              GL_RG_INTEGER,      GL_UNSIGNED_BYTE                 );
1055d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RG8I,               GL_RG_INTEGER,      GL_BYTE                          );
1065d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RG16UI,             GL_RG_INTEGER,      GL_UNSIGNED_SHORT                );
1075d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RG16I,              GL_RG_INTEGER,      GL_SHORT                         );
1085d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RG32UI,             GL_RG_INTEGER,      GL_UNSIGNED_INT                  );
1095d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RG32I,              GL_RG_INTEGER,      GL_INT                           );
1105d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_R8,                 GL_RED,             GL_UNSIGNED_BYTE                 );
1115d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_R8_SNORM,           GL_RED,             GL_BYTE                          );
1125d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_R16F,               GL_RED,             GL_HALF_FLOAT                    );
1135d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_R16F,               GL_RED,             GL_HALF_FLOAT_OES                );
1145d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_R32F,               GL_RED,             GL_FLOAT                         );
1155d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_R16F,               GL_RED,             GL_FLOAT                         );
1165d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_R8UI,               GL_RED_INTEGER,     GL_UNSIGNED_BYTE                 );
1175d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_R8I,                GL_RED_INTEGER,     GL_BYTE                          );
1185d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_R16UI,              GL_RED_INTEGER,     GL_UNSIGNED_SHORT                );
1195d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_R16I,               GL_RED_INTEGER,     GL_SHORT                         );
1205d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_R32UI,              GL_RED_INTEGER,     GL_UNSIGNED_INT                  );
1215d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_R32I,               GL_RED_INTEGER,     GL_INT                           );
1225d601382b51c29d1670b58c01360416bd929842dGeoff Lang
1235d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // Unsized formats
1245d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGBA,               GL_RGBA,            GL_UNSIGNED_BYTE                 );
1255d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGBA,               GL_RGBA,            GL_UNSIGNED_SHORT_4_4_4_4        );
1265d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGBA,               GL_RGBA,            GL_UNSIGNED_SHORT_5_5_5_1        );
1275d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB,                GL_RGB,             GL_UNSIGNED_BYTE                 );
1285d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_RGB,                GL_RGB,             GL_UNSIGNED_SHORT_5_6_5          );
1295d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA,    GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE                 );
1305d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_LUMINANCE,          GL_LUMINANCE,       GL_UNSIGNED_BYTE                 );
1315d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_ALPHA,              GL_ALPHA,           GL_UNSIGNED_BYTE                 );
1325d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_SRGB_ALPHA_EXT,     GL_SRGB_ALPHA_EXT,  GL_UNSIGNED_BYTE                 );
1335d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_SRGB_EXT,           GL_SRGB_EXT,        GL_UNSIGNED_BYTE                 );
1345d601382b51c29d1670b58c01360416bd929842dGeoff Lang
1355d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // Depth stencil formats
1365d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16,  GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT                );
1375d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT24,  GL_DEPTH_COMPONENT, GL_UNSIGNED_INT                  );
1385d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16,  GL_DEPTH_COMPONENT, GL_UNSIGNED_INT                  );
1395d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT                         );
1405d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_DEPTH24_STENCIL8,   GL_DEPTH_STENCIL,   GL_UNSIGNED_INT_24_8             );
1415d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_DEPTH32F_STENCIL8,  GL_DEPTH_STENCIL,   GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
1425d601382b51c29d1670b58c01360416bd929842dGeoff Lang
1435d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // From GL_EXT_sRGB
1445d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8_EXT,   GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE                  );
1455d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_SRGB8,              GL_SRGB_EXT,       GL_UNSIGNED_BYTE                  );
1465d601382b51c29d1670b58c01360416bd929842dGeoff Lang
1475d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // From GL_OES_texture_float
1485d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA,    GL_LUMINANCE_ALPHA, GL_FLOAT                         );
1495d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_LUMINANCE,          GL_LUMINANCE,       GL_FLOAT                         );
1505d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_ALPHA,              GL_ALPHA,           GL_FLOAT                         );
1515d601382b51c29d1670b58c01360416bd929842dGeoff Lang
1525d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // From GL_OES_texture_half_float
1535d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA,    GL_LUMINANCE_ALPHA, GL_HALF_FLOAT                    );
1545d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA,    GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES                );
1555d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_LUMINANCE,          GL_LUMINANCE,       GL_HALF_FLOAT                    );
1565d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_LUMINANCE,          GL_LUMINANCE,       GL_HALF_FLOAT_OES                );
1575d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_ALPHA,              GL_ALPHA,           GL_HALF_FLOAT                    );
1585d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_ALPHA,              GL_ALPHA,           GL_HALF_FLOAT_OES                );
1595d601382b51c29d1670b58c01360416bd929842dGeoff Lang
1605d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // From GL_EXT_texture_format_BGRA8888
1615d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_BGRA_EXT,           GL_BGRA_EXT,        GL_UNSIGNED_BYTE                 );
1625d601382b51c29d1670b58c01360416bd929842dGeoff Lang
1635d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // From GL_EXT_texture_storage
1645d601382b51c29d1670b58c01360416bd929842dGeoff Lang    //                    | Internal format          | Format            | Type                            |
1655d601382b51c29d1670b58c01360416bd929842dGeoff Lang    //                    |                          |                   |                                 |
1665d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_ALPHA8_EXT,             GL_ALPHA,           GL_UNSIGNED_BYTE                 );
1675d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_LUMINANCE8_EXT,         GL_LUMINANCE,       GL_UNSIGNED_BYTE                 );
1685d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_LUMINANCE8_ALPHA8_EXT,  GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE                 );
1695d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_ALPHA32F_EXT,           GL_ALPHA,           GL_FLOAT                         );
1705d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_LUMINANCE32F_EXT,       GL_LUMINANCE,       GL_FLOAT                         );
1715d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT                         );
1725d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_ALPHA16F_EXT,           GL_ALPHA,           GL_HALF_FLOAT                    );
1735d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_ALPHA16F_EXT,           GL_ALPHA,           GL_HALF_FLOAT_OES                );
1745d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT,       GL_LUMINANCE,       GL_HALF_FLOAT                    );
1755d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT,       GL_LUMINANCE,       GL_HALF_FLOAT_OES                );
1765d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT                    );
1775d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES                );
1785d601382b51c29d1670b58c01360416bd929842dGeoff Lang
1795d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888
1805d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_BGRA8_EXT,              GL_BGRA_EXT,        GL_UNSIGNED_BYTE                 );
1815d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX,           GL_BGRA_EXT,        GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT);
1825d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX,           GL_BGRA_EXT,        GL_UNSIGNED_BYTE                 );
1835d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX,         GL_BGRA_EXT,        GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT);
1845d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX,         GL_BGRA_EXT,        GL_UNSIGNED_BYTE                 );
1855d601382b51c29d1670b58c01360416bd929842dGeoff Lang
1865d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // From GL_ANGLE_depth_texture
1875d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32_OES,  GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8_OES         );
1885d601382b51c29d1670b58c01360416bd929842dGeoff Lang
1895d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // Compressed formats
1905d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // From ES 3.0.1 spec, table 3.16
1915d601382b51c29d1670b58c01360416bd929842dGeoff Lang    //                    | Internal format                             | Format                                      | Type           |
1925d601382b51c29d1670b58c01360416bd929842dGeoff Lang    //                    |                                             |                                             |                |
1935d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_COMPRESSED_R11_EAC,                        GL_COMPRESSED_R11_EAC,                        GL_UNSIGNED_BYTE);
1945d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_COMPRESSED_R11_EAC,                        GL_COMPRESSED_R11_EAC,                        GL_UNSIGNED_BYTE);
1955d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_COMPRESSED_SIGNED_R11_EAC,                 GL_COMPRESSED_SIGNED_R11_EAC,                 GL_UNSIGNED_BYTE);
1965d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_COMPRESSED_RG11_EAC,                       GL_COMPRESSED_RG11_EAC,                       GL_UNSIGNED_BYTE);
1975d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_COMPRESSED_SIGNED_RG11_EAC,                GL_COMPRESSED_SIGNED_RG11_EAC,                GL_UNSIGNED_BYTE);
1985d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_COMPRESSED_RGB8_ETC2,                      GL_COMPRESSED_RGB8_ETC2,                      GL_UNSIGNED_BYTE);
1995d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_ETC2,                     GL_COMPRESSED_SRGB8_ETC2,                     GL_UNSIGNED_BYTE);
2005d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,  GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,  GL_UNSIGNED_BYTE);
2015d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE);
2025d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA8_ETC2_EAC,                 GL_COMPRESSED_RGBA8_ETC2_EAC,                 GL_UNSIGNED_BYTE);
2035d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,          GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,          GL_UNSIGNED_BYTE);
2045d601382b51c29d1670b58c01360416bd929842dGeoff Lang
2055d601382b51c29d1670b58c01360416bd929842dGeoff Lang
2065d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // From GL_EXT_texture_compression_dxt1
2075d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,              GL_COMPRESSED_RGB_S3TC_DXT1_EXT,              GL_UNSIGNED_BYTE);
2085d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,             GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,             GL_UNSIGNED_BYTE);
2095d601382b51c29d1670b58c01360416bd929842dGeoff Lang
2105d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // From GL_ANGLE_texture_compression_dxt3
2115d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,           GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,           GL_UNSIGNED_BYTE);
2125d601382b51c29d1670b58c01360416bd929842dGeoff Lang
2135d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // From GL_ANGLE_texture_compression_dxt5
2145d601382b51c29d1670b58c01360416bd929842dGeoff Lang    InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,           GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,           GL_UNSIGNED_BYTE);
2155d601382b51c29d1670b58c01360416bd929842dGeoff Lang
2165d601382b51c29d1670b58c01360416bd929842dGeoff Lang    return set;
2175d601382b51c29d1670b58c01360416bd929842dGeoff Lang}
2185d601382b51c29d1670b58c01360416bd929842dGeoff Lang
2195d601382b51c29d1670b58c01360416bd929842dGeoff Langstatic bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
2205d601382b51c29d1670b58c01360416bd929842dGeoff Lang{
2215d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // Note: dEQP 2013.4 expects an INVALID_VALUE error for TexImage3D with an invalid
2225d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // internal format. (dEQP-GLES3.functional.negative_api.texture.teximage3d)
223baadf23a37aff145aa04bf254fd8c6d4a5446ea8Geoff Lang    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
2245d601382b51c29d1670b58c01360416bd929842dGeoff Lang    if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
2255d601382b51c29d1670b58c01360416bd929842dGeoff Lang    {
226b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_ENUM));
227b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
2285d601382b51c29d1670b58c01360416bd929842dGeoff Lang    }
2295d601382b51c29d1670b58c01360416bd929842dGeoff Lang
2305d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // The type and format are valid if any supported internal format has that type and format
2315d601382b51c29d1670b58c01360416bd929842dGeoff Lang    bool formatSupported = false;
2325d601382b51c29d1670b58c01360416bd929842dGeoff Lang    bool typeSupported = false;
2335d601382b51c29d1670b58c01360416bd929842dGeoff Lang
2345d601382b51c29d1670b58c01360416bd929842dGeoff Lang    static const ES3FormatCombinationSet es3FormatSet = BuildES3FormatSet();
2355d601382b51c29d1670b58c01360416bd929842dGeoff Lang    for (ES3FormatCombinationSet::const_iterator i = es3FormatSet.begin(); i != es3FormatSet.end(); i++)
2365d601382b51c29d1670b58c01360416bd929842dGeoff Lang    {
2375d601382b51c29d1670b58c01360416bd929842dGeoff Lang        if (i->format == format || i->type == type)
2385d601382b51c29d1670b58c01360416bd929842dGeoff Lang        {
2395d601382b51c29d1670b58c01360416bd929842dGeoff Lang            const gl::InternalFormat &info = gl::GetInternalFormatInfo(i->internalFormat);
2405d601382b51c29d1670b58c01360416bd929842dGeoff Lang            bool supported = info.textureSupport(context->getClientVersion(), context->getExtensions());
241baadf23a37aff145aa04bf254fd8c6d4a5446ea8Geoff Lang            if (supported && i->type == type)
2425d601382b51c29d1670b58c01360416bd929842dGeoff Lang            {
2435d601382b51c29d1670b58c01360416bd929842dGeoff Lang                typeSupported = true;
2445d601382b51c29d1670b58c01360416bd929842dGeoff Lang            }
245baadf23a37aff145aa04bf254fd8c6d4a5446ea8Geoff Lang            if (supported && i->format == format)
2465d601382b51c29d1670b58c01360416bd929842dGeoff Lang            {
2475d601382b51c29d1670b58c01360416bd929842dGeoff Lang                formatSupported = true;
2485d601382b51c29d1670b58c01360416bd929842dGeoff Lang            }
249baadf23a37aff145aa04bf254fd8c6d4a5446ea8Geoff Lang
250baadf23a37aff145aa04bf254fd8c6d4a5446ea8Geoff Lang            // Early-out if both type and format are supported now
251baadf23a37aff145aa04bf254fd8c6d4a5446ea8Geoff Lang            if (typeSupported && formatSupported)
252baadf23a37aff145aa04bf254fd8c6d4a5446ea8Geoff Lang            {
253baadf23a37aff145aa04bf254fd8c6d4a5446ea8Geoff Lang                break;
254baadf23a37aff145aa04bf254fd8c6d4a5446ea8Geoff Lang            }
2555d601382b51c29d1670b58c01360416bd929842dGeoff Lang        }
2565d601382b51c29d1670b58c01360416bd929842dGeoff Lang    }
2575d601382b51c29d1670b58c01360416bd929842dGeoff Lang
2585d601382b51c29d1670b58c01360416bd929842dGeoff Lang    if (!typeSupported || !formatSupported)
2595d601382b51c29d1670b58c01360416bd929842dGeoff Lang    {
260b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_ENUM));
261b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
2625d601382b51c29d1670b58c01360416bd929842dGeoff Lang    }
2635d601382b51c29d1670b58c01360416bd929842dGeoff Lang
2645d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // Check if this is a valid format combination to load texture data
2655d601382b51c29d1670b58c01360416bd929842dGeoff Lang    ES3FormatCombination searchFormat;
2665d601382b51c29d1670b58c01360416bd929842dGeoff Lang    searchFormat.internalFormat = internalFormat;
2675d601382b51c29d1670b58c01360416bd929842dGeoff Lang    searchFormat.format = format;
2685d601382b51c29d1670b58c01360416bd929842dGeoff Lang    searchFormat.type = type;
2695d601382b51c29d1670b58c01360416bd929842dGeoff Lang
2705d601382b51c29d1670b58c01360416bd929842dGeoff Lang    if (es3FormatSet.find(searchFormat) == es3FormatSet.end())
2715d601382b51c29d1670b58c01360416bd929842dGeoff Lang    {
272b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_OPERATION));
273b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
2745d601382b51c29d1670b58c01360416bd929842dGeoff Lang    }
2755d601382b51c29d1670b58c01360416bd929842dGeoff Lang
2765d601382b51c29d1670b58c01360416bd929842dGeoff Lang    return true;
2775d601382b51c29d1670b58c01360416bd929842dGeoff Lang}
2785d601382b51c29d1670b58c01360416bd929842dGeoff Lang
279b119668772ee960d8fc9e3846617c59530b90d5fGeoff Langbool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
280e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                                   GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
281efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill                                   GLint border, GLenum format, GLenum type, const GLvoid *pixels)
282e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang{
2836f38f823362c24062bed35ff7fbf5c35dc7d7f84Jamie Madill    if (!ValidTexture2DDestinationTarget(context, target))
2846f38f823362c24062bed35ff7fbf5c35dc7d7f84Jamie Madill    {
285b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_ENUM));
286b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
2876f38f823362c24062bed35ff7fbf5c35dc7d7f84Jamie Madill    }
2886f38f823362c24062bed35ff7fbf5c35dc7d7f84Jamie Madill
289e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    // Validate image size
290ce6356958ba86c2b09e62e1250cabd6bab16a082Geoff Lang    if (!ValidImageSize(context, target, level, width, height, depth))
291e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
292b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_VALUE));
293b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
294e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
295e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
296e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    // Verify zero border
297e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    if (border != 0)
298e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
299b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_VALUE));
300b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
301e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
302e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
3036f38f823362c24062bed35ff7fbf5c35dc7d7f84Jamie Madill    if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
3046f38f823362c24062bed35ff7fbf5c35dc7d7f84Jamie Madill        std::numeric_limits<GLsizei>::max() - xoffset < width ||
3056f38f823362c24062bed35ff7fbf5c35dc7d7f84Jamie Madill        std::numeric_limits<GLsizei>::max() - yoffset < height ||
3066f38f823362c24062bed35ff7fbf5c35dc7d7f84Jamie Madill        std::numeric_limits<GLsizei>::max() - zoffset < depth)
3076f38f823362c24062bed35ff7fbf5c35dc7d7f84Jamie Madill    {
308b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_VALUE));
309b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
3106f38f823362c24062bed35ff7fbf5c35dc7d7f84Jamie Madill    }
3116f38f823362c24062bed35ff7fbf5c35dc7d7f84Jamie Madill
312aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang    const gl::Caps &caps = context->getCaps();
313aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang
314e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    gl::Texture *texture = NULL;
315e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    bool textureCompressed = false;
316e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    GLenum textureInternalFormat = GL_NONE;
317e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    GLint textureLevelWidth = 0;
318e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    GLint textureLevelHeight = 0;
319e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    GLint textureLevelDepth = 0;
320e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    switch (target)
321e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
322e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      case GL_TEXTURE_2D:
323e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
324aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang            if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
325aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang                static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
326e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
327b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                context->recordError(Error(GL_INVALID_VALUE));
328b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                return false;
329e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
330e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
331e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            gl::Texture2D *texture2d = context->getTexture2D();
332e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            if (texture2d)
333e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
334e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                textureCompressed = texture2d->isCompressed(level);
335e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                textureInternalFormat = texture2d->getInternalFormat(level);
336e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                textureLevelWidth = texture2d->getWidth(level);
337e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                textureLevelHeight = texture2d->getHeight(level);
338e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                textureLevelDepth = 1;
339e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                texture = texture2d;
340e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
341e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
342e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        break;
343e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
344e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
345e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
346e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
347e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
348e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
349e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
350e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
351e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            if (!isSubImage && width != height)
352e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
353b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                context->recordError(Error(GL_INVALID_VALUE));
354b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                return false;
355e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
356e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
357aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang            if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
358e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
359b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                context->recordError(Error(GL_INVALID_VALUE));
360b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                return false;
361e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
362e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
363e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
364e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            if (textureCube)
365e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
366e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                textureCompressed = textureCube->isCompressed(target, level);
367e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                textureInternalFormat = textureCube->getInternalFormat(target, level);
368e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                textureLevelWidth = textureCube->getWidth(target, level);
369e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                textureLevelHeight = textureCube->getHeight(target, level);
370e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                textureLevelDepth = 1;
371e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                texture = textureCube;
372e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
373e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
374e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        break;
375e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
376e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      case GL_TEXTURE_3D:
377e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
378aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang            if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
379aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang                static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
380aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang                static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
381e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
382b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                context->recordError(Error(GL_INVALID_VALUE));
383b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                return false;
384e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
385e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
386e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            gl::Texture3D *texture3d = context->getTexture3D();
387e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            if (texture3d)
388e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
389e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                textureCompressed = texture3d->isCompressed(level);
390e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                textureInternalFormat = texture3d->getInternalFormat(level);
391e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                textureLevelWidth = texture3d->getWidth(level);
392e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                textureLevelHeight = texture3d->getHeight(level);
393e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                textureLevelDepth = texture3d->getDepth(level);
394e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                texture = texture3d;
395e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
396e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
397e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        break;
398e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
399e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        case GL_TEXTURE_2D_ARRAY:
400e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang          {
401aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang              if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
402aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang                  static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
403aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang                  static_cast<GLuint>(depth) > (caps.maxArrayTextureLayers >> level))
404e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang              {
405b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                  context->recordError(Error(GL_INVALID_VALUE));
406b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                  return false;
407e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang              }
408e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
409e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang              gl::Texture2DArray *texture2darray = context->getTexture2DArray();
410e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang              if (texture2darray)
411e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang              {
412e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                  textureCompressed = texture2darray->isCompressed(level);
413e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                  textureInternalFormat = texture2darray->getInternalFormat(level);
414e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                  textureLevelWidth = texture2darray->getWidth(level);
415e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                  textureLevelHeight = texture2darray->getHeight(level);
416b8f8b89b1305f5c56ea890e2d10fd2ec9cc1f2adJamie Madill                  textureLevelDepth = texture2darray->getLayers(level);
417e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                  texture = texture2darray;
418e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang              }
419e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang          }
420e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang          break;
421e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
422e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      default:
423b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_ENUM));
424b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
425e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
426e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
427e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    if (!texture)
428e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
429b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_OPERATION));
430b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
431e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
432e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
433e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    if (texture->isImmutable() && !isSubImage)
434e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
435b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_OPERATION));
436b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
437e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
438e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
439e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    // Validate texture formats
440e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
4415d601382b51c29d1670b58c01360416bd929842dGeoff Lang    const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
442e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    if (isCompressed)
443e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
444d4f180b2a52c1a11160a9756e2dbc1586337dd19Geoff Lang        if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
445d4f180b2a52c1a11160a9756e2dbc1586337dd19Geoff Lang        {
446b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            context->recordError(Error(GL_INVALID_OPERATION));
447b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            return false;
448d4f180b2a52c1a11160a9756e2dbc1586337dd19Geoff Lang        }
449d4f180b2a52c1a11160a9756e2dbc1586337dd19Geoff Lang
4505d601382b51c29d1670b58c01360416bd929842dGeoff Lang        if (!actualFormatInfo.compressed)
451e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
452b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            context->recordError(Error(GL_INVALID_ENUM));
453b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            return false;
454e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
455e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
456e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        if (target == GL_TEXTURE_3D)
457e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
458b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            context->recordError(Error(GL_INVALID_OPERATION));
459b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            return false;
460e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
461e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
462e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    else
463e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
464baadf23a37aff145aa04bf254fd8c6d4a5446ea8Geoff Lang        if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
465e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
4665d601382b51c29d1670b58c01360416bd929842dGeoff Lang            return false;
467e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
468e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
469e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
470e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
471b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            context->recordError(Error(GL_INVALID_OPERATION));
472b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            return false;
473e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
474e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
475e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
476e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    // Validate sub image parameters
477e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    if (isSubImage)
478e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
479e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        if (isCompressed != textureCompressed)
480e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
481b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            context->recordError(Error(GL_INVALID_OPERATION));
482b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            return false;
483e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
484e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
485e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        if (isCompressed)
486e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
487e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            if ((width % 4 != 0 && width != textureLevelWidth) ||
488e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                (height % 4 != 0 && height != textureLevelHeight))
489e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
490b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                context->recordError(Error(GL_INVALID_OPERATION));
491b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                return false;
492e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
493e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
494e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
495e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        if (width == 0 || height == 0 || depth == 0)
496e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
497e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            return false;
498e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
499e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
500e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        if (xoffset < 0 || yoffset < 0 || zoffset < 0)
501e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
502b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            context->recordError(Error(GL_INVALID_VALUE));
503b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            return false;
504e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
505e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
506e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
507e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            std::numeric_limits<GLsizei>::max() - yoffset < height ||
508e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            std::numeric_limits<GLsizei>::max() - zoffset < depth)
509e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
510b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            context->recordError(Error(GL_INVALID_VALUE));
511b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            return false;
512e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
513e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
514e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        if (xoffset + width > textureLevelWidth ||
515e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            yoffset + height > textureLevelHeight ||
516e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            zoffset + depth > textureLevelDepth)
517e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
518b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            context->recordError(Error(GL_INVALID_VALUE));
519b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            return false;
520e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
521e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
522e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
523efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill    // Check for pixel unpack buffer related API errors
52453a94a8238621e36e437975e7a17a91cf995aed9Shannon Woods    gl::Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
525efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill    if (pixelUnpackBuffer != NULL)
526efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill    {
527efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill        // ...the data would be unpacked from the buffer object such that the memory reads required
528efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill        // would exceed the data store size.
529efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill        size_t widthSize = static_cast<size_t>(width);
530efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill        size_t heightSize = static_cast<size_t>(height);
531efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill        size_t depthSize = static_cast<size_t>(depth);
5325d601382b51c29d1670b58c01360416bd929842dGeoff Lang        GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type);
5336f38f823362c24062bed35ff7fbf5c35dc7d7f84Jamie Madill
5345d601382b51c29d1670b58c01360416bd929842dGeoff Lang        size_t pixelBytes = static_cast<size_t>(gl::GetInternalFormatInfo(sizedFormat).pixelBytes);
535efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill
536efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill        if (!rx::IsUnsignedMultiplicationSafe(widthSize, heightSize) ||
537efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill            !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize, depthSize) ||
538efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill            !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize * depthSize, pixelBytes))
539efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill        {
540efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill            // Overflow past the end of the buffer
541b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            context->recordError(Error(GL_INVALID_OPERATION));
542b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            return false;
543efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill        }
544efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill
545efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill        size_t copyBytes = widthSize * heightSize * depthSize * pixelBytes;
546efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill        size_t offset = reinterpret_cast<size_t>(pixels);
547efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill
5486f38f823362c24062bed35ff7fbf5c35dc7d7f84Jamie Madill        if (!rx::IsUnsignedAdditionSafe(offset, copyBytes) ||
549d38f926ad0a14e8927db2468df840a3ecf330924Brandon Jones            ((offset + copyBytes) > static_cast<size_t>(pixelUnpackBuffer->getSize())))
550efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill        {
551efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill            // Overflow past the end of the buffer
552b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            context->recordError(Error(GL_INVALID_OPERATION));
553b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            return false;
554efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill        }
555efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill
556efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill        // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
557efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill        // indicated by type.
5585d601382b51c29d1670b58c01360416bd929842dGeoff Lang        size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
559efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill
560efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill        if ((offset % dataBytesPerPixel) != 0)
561efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill        {
562b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            context->recordError(Error(GL_INVALID_OPERATION));
563b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            return false;
564efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill        }
565efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill
5667a5f738bcf0773177a533c73bd51330a353e4004Jamie Madill        // ...the buffer object's data store is currently mapped.
567d38f926ad0a14e8927db2468df840a3ecf330924Brandon Jones        if (pixelUnpackBuffer->isMapped())
5687a5f738bcf0773177a533c73bd51330a353e4004Jamie Madill        {
569b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            context->recordError(Error(GL_INVALID_OPERATION));
570b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            return false;
5717a5f738bcf0773177a533c73bd51330a353e4004Jamie Madill        }
572efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill    }
573efb2a6fff4d3287ed20ae9d028fd980065ea7d70Jamie Madill
574e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    return true;
575e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang}
576e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
5775d601382b51c29d1670b58c01360416bd929842dGeoff Langstruct EffectiveInternalFormatInfo
5785d601382b51c29d1670b58c01360416bd929842dGeoff Lang{
5795d601382b51c29d1670b58c01360416bd929842dGeoff Lang    GLenum mEffectiveFormat;
5805d601382b51c29d1670b58c01360416bd929842dGeoff Lang    GLenum mDestFormat;
5815d601382b51c29d1670b58c01360416bd929842dGeoff Lang    GLuint mMinRedBits;
5825d601382b51c29d1670b58c01360416bd929842dGeoff Lang    GLuint mMaxRedBits;
5835d601382b51c29d1670b58c01360416bd929842dGeoff Lang    GLuint mMinGreenBits;
5845d601382b51c29d1670b58c01360416bd929842dGeoff Lang    GLuint mMaxGreenBits;
5855d601382b51c29d1670b58c01360416bd929842dGeoff Lang    GLuint mMinBlueBits;
5865d601382b51c29d1670b58c01360416bd929842dGeoff Lang    GLuint mMaxBlueBits;
5875d601382b51c29d1670b58c01360416bd929842dGeoff Lang    GLuint mMinAlphaBits;
5885d601382b51c29d1670b58c01360416bd929842dGeoff Lang    GLuint mMaxAlphaBits;
5895d601382b51c29d1670b58c01360416bd929842dGeoff Lang
5905d601382b51c29d1670b58c01360416bd929842dGeoff Lang    EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits,
5915d601382b51c29d1670b58c01360416bd929842dGeoff Lang                                GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits,
5925d601382b51c29d1670b58c01360416bd929842dGeoff Lang                                GLuint minAlphaBits, GLuint maxAlphaBits)
5935d601382b51c29d1670b58c01360416bd929842dGeoff Lang        : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits),
5945d601382b51c29d1670b58c01360416bd929842dGeoff Lang          mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits),
5955d601382b51c29d1670b58c01360416bd929842dGeoff Lang          mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits),
5965d601382b51c29d1670b58c01360416bd929842dGeoff Lang          mMaxAlphaBits(maxAlphaBits) {};
5975d601382b51c29d1670b58c01360416bd929842dGeoff Lang};
5985d601382b51c29d1670b58c01360416bd929842dGeoff Lang
5995d601382b51c29d1670b58c01360416bd929842dGeoff Langtypedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
6005d601382b51c29d1670b58c01360416bd929842dGeoff Lang
6015d601382b51c29d1670b58c01360416bd929842dGeoff Langstatic EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList()
6025d601382b51c29d1670b58c01360416bd929842dGeoff Lang{
6035d601382b51c29d1670b58c01360416bd929842dGeoff Lang    EffectiveInternalFormatList list;
6045d601382b51c29d1670b58c01360416bd929842dGeoff Lang
6055d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
6065d601382b51c29d1670b58c01360416bd929842dGeoff Lang    //                                                    linear source buffer component sizes.
6075d601382b51c29d1670b58c01360416bd929842dGeoff Lang    //                                                                            | Source channel min/max sizes |
6085d601382b51c29d1670b58c01360416bd929842dGeoff Lang    //                                         Effective Internal Format |  N/A   |  R   |  G   |  B   |  A      |
6095d601382b51c29d1670b58c01360416bd929842dGeoff Lang    list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT,              GL_NONE, 0,  0, 0,  0, 0,  0, 1, 8));
6105d601382b51c29d1670b58c01360416bd929842dGeoff Lang    list.push_back(EffectiveInternalFormatInfo(GL_R8,                      GL_NONE, 1,  8, 0,  0, 0,  0, 0, 0));
6115d601382b51c29d1670b58c01360416bd929842dGeoff Lang    list.push_back(EffectiveInternalFormatInfo(GL_RG8,                     GL_NONE, 1,  8, 1,  8, 0,  0, 0, 0));
6125d601382b51c29d1670b58c01360416bd929842dGeoff Lang    list.push_back(EffectiveInternalFormatInfo(GL_RGB565,                  GL_NONE, 1,  5, 1,  6, 1,  5, 0, 0));
6135d601382b51c29d1670b58c01360416bd929842dGeoff Lang    list.push_back(EffectiveInternalFormatInfo(GL_RGB8,                    GL_NONE, 6,  8, 7,  8, 6,  8, 0, 0));
6145d601382b51c29d1670b58c01360416bd929842dGeoff Lang    list.push_back(EffectiveInternalFormatInfo(GL_RGBA4,                   GL_NONE, 1,  4, 1,  4, 1,  4, 1, 4));
6155d601382b51c29d1670b58c01360416bd929842dGeoff Lang    list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1,                 GL_NONE, 5,  5, 5,  5, 5,  5, 1, 1));
6165d601382b51c29d1670b58c01360416bd929842dGeoff Lang    list.push_back(EffectiveInternalFormatInfo(GL_RGBA8,                   GL_NONE, 5,  8, 5,  8, 5,  8, 2, 8));
6175d601382b51c29d1670b58c01360416bd929842dGeoff Lang    list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2,                GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2));
6185d601382b51c29d1670b58c01360416bd929842dGeoff Lang
6195d601382b51c29d1670b58c01360416bd929842dGeoff Lang    return list;
6205d601382b51c29d1670b58c01360416bd929842dGeoff Lang}
6215d601382b51c29d1670b58c01360416bd929842dGeoff Lang
6225d601382b51c29d1670b58c01360416bd929842dGeoff Langstatic EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList()
6235d601382b51c29d1670b58c01360416bd929842dGeoff Lang{
6245d601382b51c29d1670b58c01360416bd929842dGeoff Lang    EffectiveInternalFormatList list;
6255d601382b51c29d1670b58c01360416bd929842dGeoff Lang
6265d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
6275d601382b51c29d1670b58c01360416bd929842dGeoff Lang    //                                                    linear source buffer component sizes.
6285d601382b51c29d1670b58c01360416bd929842dGeoff Lang    //                                                                                        |          Source channel min/max sizes            |
6295d601382b51c29d1670b58c01360416bd929842dGeoff Lang    //                                         Effective Internal Format |    Dest Format     |     R     |      G     |      B     |      A     |
6305d601382b51c29d1670b58c01360416bd929842dGeoff Lang    list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT,              GL_ALPHA,           0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1,        8));
6315d601382b51c29d1670b58c01360416bd929842dGeoff Lang    list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT,          GL_LUMINANCE,       1,        8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX));
6325d601382b51c29d1670b58c01360416bd929842dGeoff Lang    list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT,   GL_LUMINANCE_ALPHA, 1,        8, 0, UINT_MAX, 0, UINT_MAX, 1,        8));
6335d601382b51c29d1670b58c01360416bd929842dGeoff Lang    list.push_back(EffectiveInternalFormatInfo(GL_RGB565,                  GL_RGB,             1,        5, 1,        6, 1,        5, 0, UINT_MAX));
6345d601382b51c29d1670b58c01360416bd929842dGeoff Lang    list.push_back(EffectiveInternalFormatInfo(GL_RGB8,                    GL_RGB,             6,        8, 7,        8, 6,        8, 0, UINT_MAX));
6355d601382b51c29d1670b58c01360416bd929842dGeoff Lang    list.push_back(EffectiveInternalFormatInfo(GL_RGBA4,                   GL_RGBA,            1,        4, 1,        4, 1,        4, 1,        4));
6365d601382b51c29d1670b58c01360416bd929842dGeoff Lang    list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1,                 GL_RGBA,            5,        5, 5,        5, 5,        5, 1,        1));
6375d601382b51c29d1670b58c01360416bd929842dGeoff Lang    list.push_back(EffectiveInternalFormatInfo(GL_RGBA8,                   GL_RGBA,            5,        8, 5,        8, 5,        8, 5,        8));
6385d601382b51c29d1670b58c01360416bd929842dGeoff Lang
6395d601382b51c29d1670b58c01360416bd929842dGeoff Lang    return list;
6405d601382b51c29d1670b58c01360416bd929842dGeoff Lang}
6415d601382b51c29d1670b58c01360416bd929842dGeoff Lang
6425d601382b51c29d1670b58c01360416bd929842dGeoff Langstatic bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
6435d601382b51c29d1670b58c01360416bd929842dGeoff Lang                                       GLenum *outEffectiveFormat)
6445d601382b51c29d1670b58c01360416bd929842dGeoff Lang{
6455d601382b51c29d1670b58c01360416bd929842dGeoff Lang    const EffectiveInternalFormatList *list = NULL;
6465d601382b51c29d1670b58c01360416bd929842dGeoff Lang    GLenum targetFormat = GL_NONE;
6475d601382b51c29d1670b58c01360416bd929842dGeoff Lang
6485d601382b51c29d1670b58c01360416bd929842dGeoff Lang    if (destFormat.pixelBytes > 0)
6495d601382b51c29d1670b58c01360416bd929842dGeoff Lang    {
6505d601382b51c29d1670b58c01360416bd929842dGeoff Lang        static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList();
6515d601382b51c29d1670b58c01360416bd929842dGeoff Lang        list = &sizedList;
6525d601382b51c29d1670b58c01360416bd929842dGeoff Lang    }
6535d601382b51c29d1670b58c01360416bd929842dGeoff Lang    else
6545d601382b51c29d1670b58c01360416bd929842dGeoff Lang    {
6555d601382b51c29d1670b58c01360416bd929842dGeoff Lang        static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList();
6565d601382b51c29d1670b58c01360416bd929842dGeoff Lang        list = &unsizedList;
6575d601382b51c29d1670b58c01360416bd929842dGeoff Lang        targetFormat = destFormat.format;
6585d601382b51c29d1670b58c01360416bd929842dGeoff Lang    }
6595d601382b51c29d1670b58c01360416bd929842dGeoff Lang
6605d601382b51c29d1670b58c01360416bd929842dGeoff Lang    for (size_t curFormat = 0; curFormat < list->size(); ++curFormat)
6615d601382b51c29d1670b58c01360416bd929842dGeoff Lang    {
6625d601382b51c29d1670b58c01360416bd929842dGeoff Lang        const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat);
6635d601382b51c29d1670b58c01360416bd929842dGeoff Lang        if ((formatInfo.mDestFormat == targetFormat) &&
6645d601382b51c29d1670b58c01360416bd929842dGeoff Lang            (formatInfo.mMinRedBits   <= srcFormat.redBits   && formatInfo.mMaxRedBits   >= srcFormat.redBits)   &&
6655d601382b51c29d1670b58c01360416bd929842dGeoff Lang            (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) &&
6665d601382b51c29d1670b58c01360416bd929842dGeoff Lang            (formatInfo.mMinBlueBits  <= srcFormat.blueBits  && formatInfo.mMaxBlueBits  >= srcFormat.blueBits)  &&
6675d601382b51c29d1670b58c01360416bd929842dGeoff Lang            (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits))
6685d601382b51c29d1670b58c01360416bd929842dGeoff Lang        {
6695d601382b51c29d1670b58c01360416bd929842dGeoff Lang            *outEffectiveFormat = formatInfo.mEffectiveFormat;
6705d601382b51c29d1670b58c01360416bd929842dGeoff Lang            return true;
6715d601382b51c29d1670b58c01360416bd929842dGeoff Lang        }
6725d601382b51c29d1670b58c01360416bd929842dGeoff Lang    }
6735d601382b51c29d1670b58c01360416bd929842dGeoff Lang
6745d601382b51c29d1670b58c01360416bd929842dGeoff Lang    return false;
6755d601382b51c29d1670b58c01360416bd929842dGeoff Lang}
6765d601382b51c29d1670b58c01360416bd929842dGeoff Lang
6775d601382b51c29d1670b58c01360416bd929842dGeoff Langstruct CopyConversion
6785d601382b51c29d1670b58c01360416bd929842dGeoff Lang{
6795d601382b51c29d1670b58c01360416bd929842dGeoff Lang    GLenum mTextureFormat;
6805d601382b51c29d1670b58c01360416bd929842dGeoff Lang    GLenum mFramebufferFormat;
6815d601382b51c29d1670b58c01360416bd929842dGeoff Lang
6825d601382b51c29d1670b58c01360416bd929842dGeoff Lang    CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
6835d601382b51c29d1670b58c01360416bd929842dGeoff Lang        : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
6845d601382b51c29d1670b58c01360416bd929842dGeoff Lang
6855d601382b51c29d1670b58c01360416bd929842dGeoff Lang    bool operator<(const CopyConversion& other) const
6865d601382b51c29d1670b58c01360416bd929842dGeoff Lang    {
6875d601382b51c29d1670b58c01360416bd929842dGeoff Lang        return memcmp(this, &other, sizeof(CopyConversion)) < 0;
6885d601382b51c29d1670b58c01360416bd929842dGeoff Lang    }
6895d601382b51c29d1670b58c01360416bd929842dGeoff Lang};
6905d601382b51c29d1670b58c01360416bd929842dGeoff Lang
6915d601382b51c29d1670b58c01360416bd929842dGeoff Langtypedef std::set<CopyConversion> CopyConversionSet;
6925d601382b51c29d1670b58c01360416bd929842dGeoff Lang
6935d601382b51c29d1670b58c01360416bd929842dGeoff Langstatic CopyConversionSet BuildValidES3CopyTexImageCombinations()
6945d601382b51c29d1670b58c01360416bd929842dGeoff Lang{
6955d601382b51c29d1670b58c01360416bd929842dGeoff Lang    CopyConversionSet set;
6965d601382b51c29d1670b58c01360416bd929842dGeoff Lang
6975d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // From ES 3.0.1 spec, table 3.15
6985d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
6995d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
7005d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
7015d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
7025d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
7035d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
7045d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RED, GL_RED));
7055d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RED, GL_RG));
7065d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RED, GL_RGB));
7075d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RED, GL_RGBA));
7085d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RG, GL_RG));
7095d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RG, GL_RGB));
7105d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RG, GL_RGBA));
7115d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RGB, GL_RGB));
7125d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RGB, GL_RGBA));
7135d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RGBA, GL_RGBA));
7145d601382b51c29d1670b58c01360416bd929842dGeoff Lang
7155d601382b51c29d1670b58c01360416bd929842dGeoff Lang    // Necessary for ANGLE back-buffers
7165d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
7175d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
7185d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
7195d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
7205d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
7215d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
7225d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
7235d601382b51c29d1670b58c01360416bd929842dGeoff Lang
7245d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
7255d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
7265d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
7275d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
7285d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
7295d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
7305d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
7315d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
7325d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
7335d601382b51c29d1670b58c01360416bd929842dGeoff Lang    set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
7345d601382b51c29d1670b58c01360416bd929842dGeoff Lang
7355d601382b51c29d1670b58c01360416bd929842dGeoff Lang    return set;
7365d601382b51c29d1670b58c01360416bd929842dGeoff Lang}
7375d601382b51c29d1670b58c01360416bd929842dGeoff Lang
7385d601382b51c29d1670b58c01360416bd929842dGeoff Langstatic bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle)
7395d601382b51c29d1670b58c01360416bd929842dGeoff Lang{
7405d601382b51c29d1670b58c01360416bd929842dGeoff Lang    const InternalFormat &textureInternalFormatInfo = GetInternalFormatInfo(textureInternalFormat);
7415d601382b51c29d1670b58c01360416bd929842dGeoff Lang    const InternalFormat &framebufferInternalFormatInfo = GetInternalFormatInfo(frameBufferInternalFormat);
7425d601382b51c29d1670b58c01360416bd929842dGeoff Lang
7435d601382b51c29d1670b58c01360416bd929842dGeoff Lang    static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
7445d601382b51c29d1670b58c01360416bd929842dGeoff Lang    if (conversionSet.find(CopyConversion(textureInternalFormatInfo.format, framebufferInternalFormatInfo.format)) != conversionSet.end())
7455d601382b51c29d1670b58c01360416bd929842dGeoff Lang    {
7465d601382b51c29d1670b58c01360416bd929842dGeoff Lang        // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
7475d601382b51c29d1670b58c01360416bd929842dGeoff Lang        // must both be signed, unsigned, or fixed point and both source and destinations
7485d601382b51c29d1670b58c01360416bd929842dGeoff Lang        // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
7495d601382b51c29d1670b58c01360416bd929842dGeoff Lang        // conversion between fixed and floating point.
7505d601382b51c29d1670b58c01360416bd929842dGeoff Lang
7515d601382b51c29d1670b58c01360416bd929842dGeoff Lang        if ((textureInternalFormatInfo.colorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.colorEncoding == GL_SRGB))
7525d601382b51c29d1670b58c01360416bd929842dGeoff Lang        {
7535d601382b51c29d1670b58c01360416bd929842dGeoff Lang            return false;
7545d601382b51c29d1670b58c01360416bd929842dGeoff Lang        }
7555d601382b51c29d1670b58c01360416bd929842dGeoff Lang
7565d601382b51c29d1670b58c01360416bd929842dGeoff Lang        if (((textureInternalFormatInfo.componentType == GL_INT)          != (framebufferInternalFormatInfo.componentType == GL_INT         )) ||
7575d601382b51c29d1670b58c01360416bd929842dGeoff Lang            ((textureInternalFormatInfo.componentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.componentType == GL_UNSIGNED_INT)))
7585d601382b51c29d1670b58c01360416bd929842dGeoff Lang        {
7595d601382b51c29d1670b58c01360416bd929842dGeoff Lang            return false;
7605d601382b51c29d1670b58c01360416bd929842dGeoff Lang        }
7615d601382b51c29d1670b58c01360416bd929842dGeoff Lang
7625d601382b51c29d1670b58c01360416bd929842dGeoff Lang        if ((textureInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
7635d601382b51c29d1670b58c01360416bd929842dGeoff Lang             textureInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
7645d601382b51c29d1670b58c01360416bd929842dGeoff Lang             textureInternalFormatInfo.componentType == GL_FLOAT) &&
7655d601382b51c29d1670b58c01360416bd929842dGeoff Lang            !(framebufferInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
7665d601382b51c29d1670b58c01360416bd929842dGeoff Lang              framebufferInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
7675d601382b51c29d1670b58c01360416bd929842dGeoff Lang              framebufferInternalFormatInfo.componentType == GL_FLOAT))
7685d601382b51c29d1670b58c01360416bd929842dGeoff Lang        {
7695d601382b51c29d1670b58c01360416bd929842dGeoff Lang            return false;
7705d601382b51c29d1670b58c01360416bd929842dGeoff Lang        }
7715d601382b51c29d1670b58c01360416bd929842dGeoff Lang
7725d601382b51c29d1670b58c01360416bd929842dGeoff Lang        // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
7735d601382b51c29d1670b58c01360416bd929842dGeoff Lang        // The effective internal format of the source buffer is determined with the following rules applied in order:
7745d601382b51c29d1670b58c01360416bd929842dGeoff Lang        //    * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
7755d601382b51c29d1670b58c01360416bd929842dGeoff Lang        //      effective internal format is the source buffer's sized internal format.
7765d601382b51c29d1670b58c01360416bd929842dGeoff Lang        //    * If the source buffer is a texture that was created with an unsized base internal format, then the
7775d601382b51c29d1670b58c01360416bd929842dGeoff Lang        //      effective internal format is the source image array's effective internal format, as specified by table
7785d601382b51c29d1670b58c01360416bd929842dGeoff Lang        //      3.12, which is determined from the <format> and <type> that were used when the source image array was
7795d601382b51c29d1670b58c01360416bd929842dGeoff Lang        //      specified by TexImage*.
7805d601382b51c29d1670b58c01360416bd929842dGeoff Lang        //    * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
7815d601382b51c29d1670b58c01360416bd929842dGeoff Lang        //      Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
7825d601382b51c29d1670b58c01360416bd929842dGeoff Lang        //      with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
7835d601382b51c29d1670b58c01360416bd929842dGeoff Lang        //      FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
7845d601382b51c29d1670b58c01360416bd929842dGeoff Lang        //      is SRGB.
7855d601382b51c29d1670b58c01360416bd929842dGeoff Lang        const InternalFormat *sourceEffectiveFormat = NULL;
7865d601382b51c29d1670b58c01360416bd929842dGeoff Lang        if (readBufferHandle != 0)
7875d601382b51c29d1670b58c01360416bd929842dGeoff Lang        {
7885d601382b51c29d1670b58c01360416bd929842dGeoff Lang            // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
7895d601382b51c29d1670b58c01360416bd929842dGeoff Lang            if (framebufferInternalFormatInfo.pixelBytes > 0)
7905d601382b51c29d1670b58c01360416bd929842dGeoff Lang            {
7915d601382b51c29d1670b58c01360416bd929842dGeoff Lang                sourceEffectiveFormat = &framebufferInternalFormatInfo;
7925d601382b51c29d1670b58c01360416bd929842dGeoff Lang            }
7935d601382b51c29d1670b58c01360416bd929842dGeoff Lang            else
7945d601382b51c29d1670b58c01360416bd929842dGeoff Lang            {
7955d601382b51c29d1670b58c01360416bd929842dGeoff Lang                // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
7965d601382b51c29d1670b58c01360416bd929842dGeoff Lang                // texture. We can use the same table we use when creating textures to get its effective sized format.
7975d601382b51c29d1670b58c01360416bd929842dGeoff Lang                const FormatType &typeInfo = GetFormatTypeInfo(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type);
7985d601382b51c29d1670b58c01360416bd929842dGeoff Lang                sourceEffectiveFormat = &GetInternalFormatInfo(typeInfo.internalFormat);
7995d601382b51c29d1670b58c01360416bd929842dGeoff Lang            }
8005d601382b51c29d1670b58c01360416bd929842dGeoff Lang        }
8015d601382b51c29d1670b58c01360416bd929842dGeoff Lang        else
8025d601382b51c29d1670b58c01360416bd929842dGeoff Lang        {
8035d601382b51c29d1670b58c01360416bd929842dGeoff Lang            // The effective internal format must be derived from the source framebuffer's channel sizes.
8045d601382b51c29d1670b58c01360416bd929842dGeoff Lang            // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
8055d601382b51c29d1670b58c01360416bd929842dGeoff Lang            if (framebufferInternalFormatInfo.colorEncoding == GL_LINEAR)
8065d601382b51c29d1670b58c01360416bd929842dGeoff Lang            {
8075d601382b51c29d1670b58c01360416bd929842dGeoff Lang                GLenum effectiveFormat;
8085d601382b51c29d1670b58c01360416bd929842dGeoff Lang                if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat))
8095d601382b51c29d1670b58c01360416bd929842dGeoff Lang                {
8105d601382b51c29d1670b58c01360416bd929842dGeoff Lang                    sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
8115d601382b51c29d1670b58c01360416bd929842dGeoff Lang                }
8125d601382b51c29d1670b58c01360416bd929842dGeoff Lang                else
8135d601382b51c29d1670b58c01360416bd929842dGeoff Lang                {
8145d601382b51c29d1670b58c01360416bd929842dGeoff Lang                    return false;
8155d601382b51c29d1670b58c01360416bd929842dGeoff Lang                }
8165d601382b51c29d1670b58c01360416bd929842dGeoff Lang            }
8175d601382b51c29d1670b58c01360416bd929842dGeoff Lang            else if (framebufferInternalFormatInfo.colorEncoding == GL_SRGB)
8185d601382b51c29d1670b58c01360416bd929842dGeoff Lang            {
8195d601382b51c29d1670b58c01360416bd929842dGeoff Lang                // SRGB buffers can only be copied to sized format destinations according to table 3.18
8205d601382b51c29d1670b58c01360416bd929842dGeoff Lang                if ((textureInternalFormatInfo.pixelBytes > 0) &&
8215d601382b51c29d1670b58c01360416bd929842dGeoff Lang                    (framebufferInternalFormatInfo.redBits   >= 1 && framebufferInternalFormatInfo.redBits   <= 8) &&
8225d601382b51c29d1670b58c01360416bd929842dGeoff Lang                    (framebufferInternalFormatInfo.greenBits >= 1 && framebufferInternalFormatInfo.greenBits <= 8) &&
8235d601382b51c29d1670b58c01360416bd929842dGeoff Lang                    (framebufferInternalFormatInfo.blueBits  >= 1 && framebufferInternalFormatInfo.blueBits  <= 8) &&
8245d601382b51c29d1670b58c01360416bd929842dGeoff Lang                    (framebufferInternalFormatInfo.alphaBits >= 1 && framebufferInternalFormatInfo.alphaBits <= 8))
8255d601382b51c29d1670b58c01360416bd929842dGeoff Lang                {
8265d601382b51c29d1670b58c01360416bd929842dGeoff Lang                    sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
8275d601382b51c29d1670b58c01360416bd929842dGeoff Lang                }
8285d601382b51c29d1670b58c01360416bd929842dGeoff Lang                else
8295d601382b51c29d1670b58c01360416bd929842dGeoff Lang                {
8305d601382b51c29d1670b58c01360416bd929842dGeoff Lang                    return false;
8315d601382b51c29d1670b58c01360416bd929842dGeoff Lang                }
8325d601382b51c29d1670b58c01360416bd929842dGeoff Lang            }
8335d601382b51c29d1670b58c01360416bd929842dGeoff Lang            else
8345d601382b51c29d1670b58c01360416bd929842dGeoff Lang            {
8355d601382b51c29d1670b58c01360416bd929842dGeoff Lang                UNREACHABLE();
8365d601382b51c29d1670b58c01360416bd929842dGeoff Lang                return false;
8375d601382b51c29d1670b58c01360416bd929842dGeoff Lang            }
8385d601382b51c29d1670b58c01360416bd929842dGeoff Lang        }
8395d601382b51c29d1670b58c01360416bd929842dGeoff Lang
8405d601382b51c29d1670b58c01360416bd929842dGeoff Lang        if (textureInternalFormatInfo.pixelBytes > 0)
8415d601382b51c29d1670b58c01360416bd929842dGeoff Lang        {
8425d601382b51c29d1670b58c01360416bd929842dGeoff Lang            // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is sized,
8435d601382b51c29d1670b58c01360416bd929842dGeoff Lang            // component sizes of the source and destination formats must exactly match
8445d601382b51c29d1670b58c01360416bd929842dGeoff Lang            if (textureInternalFormatInfo.redBits   != sourceEffectiveFormat->redBits   ||
8455d601382b51c29d1670b58c01360416bd929842dGeoff Lang                textureInternalFormatInfo.greenBits != sourceEffectiveFormat->greenBits ||
8465d601382b51c29d1670b58c01360416bd929842dGeoff Lang                textureInternalFormatInfo.blueBits  != sourceEffectiveFormat->blueBits  ||
8475d601382b51c29d1670b58c01360416bd929842dGeoff Lang                textureInternalFormatInfo.alphaBits != sourceEffectiveFormat->alphaBits)
8485d601382b51c29d1670b58c01360416bd929842dGeoff Lang            {
8495d601382b51c29d1670b58c01360416bd929842dGeoff Lang                return false;
8505d601382b51c29d1670b58c01360416bd929842dGeoff Lang            }
8515d601382b51c29d1670b58c01360416bd929842dGeoff Lang        }
8525d601382b51c29d1670b58c01360416bd929842dGeoff Lang
8535d601382b51c29d1670b58c01360416bd929842dGeoff Lang
8545d601382b51c29d1670b58c01360416bd929842dGeoff Lang        return true; // A conversion function exists, and no rule in the specification has precluded conversion
8555d601382b51c29d1670b58c01360416bd929842dGeoff Lang                     // between these formats.
8565d601382b51c29d1670b58c01360416bd929842dGeoff Lang    }
8575d601382b51c29d1670b58c01360416bd929842dGeoff Lang
8585d601382b51c29d1670b58c01360416bd929842dGeoff Lang    return false;
8595d601382b51c29d1670b58c01360416bd929842dGeoff Lang}
8605d601382b51c29d1670b58c01360416bd929842dGeoff Lang
861b119668772ee960d8fc9e3846617c59530b90d5fGeoff Langbool ValidateES3CopyTexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat,
8626f38f823362c24062bed35ff7fbf5c35dc7d7f84Jamie Madill                                       bool isSubImage, GLint xoffset, GLint yoffset, GLint zoffset,
8636f38f823362c24062bed35ff7fbf5c35dc7d7f84Jamie Madill                                       GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
864e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang{
865560a8d889b6866d7d29da968971818437e9cde36Jamie Madill    GLenum textureInternalFormat;
866560a8d889b6866d7d29da968971818437e9cde36Jamie Madill    if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
8676f38f823362c24062bed35ff7fbf5c35dc7d7f84Jamie Madill                                            xoffset, yoffset, zoffset, x, y, width, height,
8686f38f823362c24062bed35ff7fbf5c35dc7d7f84Jamie Madill                                            border, &textureInternalFormat))
8694dfed837cbbdf55d82b2a602d9f5806201f80fa7Shannon Woods    {
870560a8d889b6866d7d29da968971818437e9cde36Jamie Madill        return false;
871e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
872e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
87353a94a8238621e36e437975e7a17a91cf995aed9Shannon Woods    gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
8743c7fa226aeb81469b93142b54e339f13a46ab835Jamie Madill
8753c7fa226aeb81469b93142b54e339f13a46ab835Jamie Madill    if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
8763c7fa226aeb81469b93142b54e339f13a46ab835Jamie Madill    {
877b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
878b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
8793c7fa226aeb81469b93142b54e339f13a46ab835Jamie Madill    }
8803c7fa226aeb81469b93142b54e339f13a46ab835Jamie Madill
88153a94a8238621e36e437975e7a17a91cf995aed9Shannon Woods    if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0)
8823c7fa226aeb81469b93142b54e339f13a46ab835Jamie Madill    {
883b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_OPERATION));
884b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
8853c7fa226aeb81469b93142b54e339f13a46ab835Jamie Madill    }
8863c7fa226aeb81469b93142b54e339f13a46ab835Jamie Madill
8873c7fa226aeb81469b93142b54e339f13a46ab835Jamie Madill    gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer();
888e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    GLenum colorbufferInternalFormat = source->getInternalFormat();
889e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
890e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    if (isSubImage)
891e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
8925d601382b51c29d1670b58c01360416bd929842dGeoff Lang        if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat,
8935d601382b51c29d1670b58c01360416bd929842dGeoff Lang                                               context->getState().getReadFramebuffer()->id()))
894e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
895b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            context->recordError(Error(GL_INVALID_OPERATION));
896b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            return false;
897e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
898e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
8994d161bad7c290636192645e376395519dadd9159Shannon Woods    else
9004d161bad7c290636192645e376395519dadd9159Shannon Woods    {
9015d601382b51c29d1670b58c01360416bd929842dGeoff Lang        if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat,
9025d601382b51c29d1670b58c01360416bd929842dGeoff Lang                                                context->getState().getReadFramebuffer()->id()))
9034d161bad7c290636192645e376395519dadd9159Shannon Woods        {
904b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            context->recordError(Error(GL_INVALID_OPERATION));
905b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            return false;
9064d161bad7c290636192645e376395519dadd9159Shannon Woods        }
9074d161bad7c290636192645e376395519dadd9159Shannon Woods    }
9084d161bad7c290636192645e376395519dadd9159Shannon Woods
909784a8fd5d851dea834691f975b02f3a0fe2af36eGeoff Lang    // If width or height is zero, it is a no-op.  Return false without setting an error.
910784a8fd5d851dea834691f975b02f3a0fe2af36eGeoff Lang    return (width > 0 && height > 0);
911e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang}
912e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
913b119668772ee960d8fc9e3846617c59530b90d5fGeoff Langbool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
914e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                                     GLsizei width, GLsizei height, GLsizei depth)
915e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang{
916e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    if (width < 1 || height < 1 || depth < 1 || levels < 1)
917e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
918b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_VALUE));
919b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
920e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
921e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
922e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    if (levels > gl::log2(std::max(std::max(width, height), depth)) + 1)
923e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
924b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_OPERATION));
925b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
926e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
927e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
928aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang    const gl::Caps &caps = context->getCaps();
929aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang
930e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    gl::Texture *texture = NULL;
931e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    switch (target)
932e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
933e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      case GL_TEXTURE_2D:
934e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
935e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            texture = context->getTexture2D();
936e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
937aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang            if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
938aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang                static_cast<GLuint>(height) > caps.max2DTextureSize)
939e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
940b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                context->recordError(Error(GL_INVALID_VALUE));
941b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                return false;
942e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
943e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
944e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        break;
945e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
94601c21d283168714e4ba749e4a121da6c8dfc114cGeoff Lang      case GL_TEXTURE_CUBE_MAP:
947e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
948e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            texture = context->getTextureCubeMap();
949e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
950e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            if (width != height)
951e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
952b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                context->recordError(Error(GL_INVALID_VALUE));
953b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                return false;
954e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
955e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
956aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang            if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
957e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
958b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                context->recordError(Error(GL_INVALID_VALUE));
959b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                return false;
960e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
961e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
962e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        break;
963e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
964e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      case GL_TEXTURE_3D:
965e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
966e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            texture = context->getTexture3D();
967e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
968aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang            if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
969aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang                static_cast<GLuint>(height) > caps.max3DTextureSize ||
970aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang                static_cast<GLuint>(depth) > caps.max3DTextureSize)
971e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
972b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                context->recordError(Error(GL_INVALID_VALUE));
973b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                return false;
974e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
975e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
976e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        break;
977e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
978e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      case GL_TEXTURE_2D_ARRAY:
979e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
980e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            texture = context->getTexture2DArray();
981e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
982aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang            if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
983aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang                static_cast<GLuint>(height) > caps.max2DTextureSize ||
984aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang                static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
985e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
986b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                context->recordError(Error(GL_INVALID_VALUE));
987b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                return false;
988e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
989e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
990e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        break;
991e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
992e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      default:
993b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_ENUM));
994b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
995e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
996e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
997e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    if (!texture || texture->id() == 0)
998e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
999b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_OPERATION));
1000b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
1001e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
1002e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
1003e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    if (texture->isImmutable())
1004e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
1005b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_OPERATION));
1006b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
1007e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
1008e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
10095d601382b51c29d1670b58c01360416bd929842dGeoff Lang    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
10105d601382b51c29d1670b58c01360416bd929842dGeoff Lang    if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
1011e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
1012b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_ENUM));
1013b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
1014e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
1015e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
10165d601382b51c29d1670b58c01360416bd929842dGeoff Lang    if (formatInfo.pixelBytes == 0)
1017e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
1018b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_ENUM));
1019b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
1020e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
1021e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
1022e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    return true;
1023e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang}
1024e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
1025b119668772ee960d8fc9e3846617c59530b90d5fGeoff Langbool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
102655ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill                                     GLuint texture, GLint level, GLint layer)
1027e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang{
102855ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill    if (context->getClientVersion() < 3)
1029e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
1030b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_OPERATION));
1031b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
103255ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill    }
103355ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill
103455ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill    if (layer < 0)
103555ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill    {
1036b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_VALUE));
1037b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
1038e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
1039e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
104055ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill    if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1041e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
1042b4472275a0c686fe2ba062e796d80375c4593708Jamie Madill        return false;
1043e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
1044e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
1045aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang    const gl::Caps &caps = context->getCaps();
1046e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    if (texture != 0)
1047e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
1048e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        gl::Texture *tex = context->getTexture(texture);
104955ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill        ASSERT(tex);
1050e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
105155ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill        switch (tex->getTarget())
1052e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
105355ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill          case GL_TEXTURE_2D_ARRAY:
1054e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
105555ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill                if (level > gl::log2(caps.max2DTextureSize))
1056e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                {
1057b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                    context->recordError(Error(GL_INVALID_VALUE));
1058b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                    return false;
1059e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                }
1060e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
106155ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill                if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1062e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                {
1063b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                    context->recordError(Error(GL_INVALID_VALUE));
1064b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                    return false;
1065e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                }
1066e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
106755ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill                gl::Texture2DArray *texArray = static_cast<gl::Texture2DArray *>(tex);
106855ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill                if (texArray->isCompressed(level))
106955ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill                {
1070b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                    context->recordError(Error(GL_INVALID_OPERATION));
1071b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                    return false;
107255ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill                }
1073e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
107455ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill            break;
107555ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill
107655ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill          case GL_TEXTURE_3D:
1077e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
107855ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill                if (level > gl::log2(caps.max3DTextureSize))
1079e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                {
1080b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                    context->recordError(Error(GL_INVALID_VALUE));
1081b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                    return false;
1082e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                }
1083e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
108455ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill                if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1085e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                {
1086b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                    context->recordError(Error(GL_INVALID_VALUE));
1087b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                    return false;
1088e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                }
1089e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
109055ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill                gl::Texture3D *tex3d = static_cast<gl::Texture3D *>(tex);
109155ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill                if (tex3d->isCompressed(level))
109255ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill                {
1093b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                    context->recordError(Error(GL_INVALID_OPERATION));
1094b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                    return false;
109555ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill                }
1096e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
109755ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill            break;
1098e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
109955ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill          default:
1100b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            context->recordError(Error(GL_INVALID_OPERATION));
1101b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang            return false;
110255ec3b111464887e6e3ab1df848cf73509cde418Jamie Madill        }
1103e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
1104e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
1105e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    return true;
1106e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang}
1107e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
1108b119668772ee960d8fc9e3846617c59530b90d5fGeoff Langbool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type)
1109e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang{
11105d601382b51c29d1670b58c01360416bd929842dGeoff Lang    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
11115d601382b51c29d1670b58c01360416bd929842dGeoff Lang
1112e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    switch (format)
1113e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
1114e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      case GL_RGBA:
1115e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        switch (type)
1116e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
1117e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang          case GL_UNSIGNED_BYTE:
1118e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            break;
1119e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang          case GL_UNSIGNED_INT_2_10_10_10_REV:
1120e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            if (internalFormat != GL_RGB10_A2)
1121e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
1122e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                return false;
1123e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
1124e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            break;
11251ec57f80247020c206480b3f6aadea87a52e9d17Geoff Lang          case GL_FLOAT:
11265d601382b51c29d1670b58c01360416bd929842dGeoff Lang            if (internalFormatInfo.componentType != GL_FLOAT)
11271ec57f80247020c206480b3f6aadea87a52e9d17Geoff Lang            {
11281ec57f80247020c206480b3f6aadea87a52e9d17Geoff Lang                return false;
11291ec57f80247020c206480b3f6aadea87a52e9d17Geoff Lang            }
11301ec57f80247020c206480b3f6aadea87a52e9d17Geoff Lang            break;
1131e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang          default:
1132e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            return false;
1133e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
1134e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        break;
1135e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      case GL_RGBA_INTEGER:
1136e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        switch (type)
1137e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
1138e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang          case GL_INT:
11395d601382b51c29d1670b58c01360416bd929842dGeoff Lang            if (internalFormatInfo.componentType != GL_INT)
1140e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
1141e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                return false;
1142e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
1143e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            break;
1144e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang          case GL_UNSIGNED_INT:
11455d601382b51c29d1670b58c01360416bd929842dGeoff Lang            if (internalFormatInfo.componentType != GL_UNSIGNED_INT)
1146e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
1147e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                return false;
1148e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
1149e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            break;
1150e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang          default:
1151e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            return false;
1152e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
1153e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        break;
1154e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      case GL_BGRA_EXT:
1155e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        switch (type)
1156e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
1157e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang          case GL_UNSIGNED_BYTE:
1158e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang          case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1159e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang          case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1160e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            break;
1161e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang          default:
1162e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            return false;
1163e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
1164e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        break;
1165bdc9b2f0ed9e365bf5a4d19799d93a512f07dd32Geoff Lang      case GL_RG_EXT:
1166bdc9b2f0ed9e365bf5a4d19799d93a512f07dd32Geoff Lang      case GL_RED_EXT:
1167c0b9ef4bce04077046ca57b9bc249f26e42d07caGeoff Lang        if (!context->getExtensions().textureRG)
1168bdc9b2f0ed9e365bf5a4d19799d93a512f07dd32Geoff Lang        {
1169bdc9b2f0ed9e365bf5a4d19799d93a512f07dd32Geoff Lang            return false;
1170bdc9b2f0ed9e365bf5a4d19799d93a512f07dd32Geoff Lang        }
1171bdc9b2f0ed9e365bf5a4d19799d93a512f07dd32Geoff Lang        switch (type)
1172bdc9b2f0ed9e365bf5a4d19799d93a512f07dd32Geoff Lang        {
1173bdc9b2f0ed9e365bf5a4d19799d93a512f07dd32Geoff Lang        case GL_UNSIGNED_BYTE:
1174bdc9b2f0ed9e365bf5a4d19799d93a512f07dd32Geoff Lang            break;
1175bdc9b2f0ed9e365bf5a4d19799d93a512f07dd32Geoff Lang        default:
1176bdc9b2f0ed9e365bf5a4d19799d93a512f07dd32Geoff Lang            return false;
1177bdc9b2f0ed9e365bf5a4d19799d93a512f07dd32Geoff Lang        }
1178bdc9b2f0ed9e365bf5a4d19799d93a512f07dd32Geoff Lang        break;
1179e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      default:
1180e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        return false;
1181e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
1182e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    return true;
1183e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang}
1184e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
1185b119668772ee960d8fc9e3846617c59530b90d5fGeoff Langbool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments,
1186e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                                             const GLenum* attachments)
1187e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang{
1188e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    bool defaultFramebuffer = false;
1189e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
1190e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    switch (target)
1191e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
1192e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      case GL_DRAW_FRAMEBUFFER:
1193e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      case GL_FRAMEBUFFER:
119453a94a8238621e36e437975e7a17a91cf995aed9Shannon Woods        defaultFramebuffer = context->getState().getDrawFramebuffer()->id() == 0;
1195e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        break;
1196e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      case GL_READ_FRAMEBUFFER:
119753a94a8238621e36e437975e7a17a91cf995aed9Shannon Woods        defaultFramebuffer = context->getState().getReadFramebuffer()->id() == 0;
1198e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        break;
1199e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang      default:
1200b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang          context->recordError(Error(GL_INVALID_ENUM));
1201b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang          return false;
1202e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
1203e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
1204e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    for (int i = 0; i < numAttachments; ++i)
1205e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    {
1206e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15)
1207e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
1208e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            if (defaultFramebuffer)
1209e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
1210b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                context->recordError(Error(GL_INVALID_ENUM));
1211b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                return false;
1212e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
1213e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
1214aae65a4e53fae703cc0ea92adc649247367917fdGeoff Lang            if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
1215e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
1216b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                context->recordError(Error(GL_INVALID_OPERATION));
1217b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                return false;
1218e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
1219e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
1220e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        else
1221e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        {
1222e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            switch (attachments[i])
1223e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            {
1224e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang              case GL_DEPTH_ATTACHMENT:
1225e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang              case GL_STENCIL_ATTACHMENT:
1226e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang              case GL_DEPTH_STENCIL_ATTACHMENT:
1227e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                if (defaultFramebuffer)
1228e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                {
1229b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                    context->recordError(Error(GL_INVALID_ENUM));
1230b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                    return false;
1231e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                }
1232e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                break;
1233e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang              case GL_COLOR:
1234e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang              case GL_DEPTH:
1235e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang              case GL_STENCIL:
1236e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                if (!defaultFramebuffer)
1237e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                {
1238b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                    context->recordError(Error(GL_INVALID_ENUM));
1239b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                    return false;
1240e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                }
1241e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang                break;
1242e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang              default:
1243b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                context->recordError(Error(GL_INVALID_ENUM));
1244b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang                return false;
1245e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang            }
1246e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang        }
1247e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    }
1248e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
1249e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang    return true;
1250e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang}
1251e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang
1252b119668772ee960d8fc9e3846617c59530b90d5fGeoff Langbool ValidateClearBuffer(Context *context)
125313f7d7dc0b09fd7e508172c7d804ce65219b2bb5Jamie Madill{
125413f7d7dc0b09fd7e508172c7d804ce65219b2bb5Jamie Madill    if (context->getClientVersion() < 3)
125513f7d7dc0b09fd7e508172c7d804ce65219b2bb5Jamie Madill    {
1256b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_OPERATION));
1257b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
125813f7d7dc0b09fd7e508172c7d804ce65219b2bb5Jamie Madill    }
125913f7d7dc0b09fd7e508172c7d804ce65219b2bb5Jamie Madill
126053a94a8238621e36e437975e7a17a91cf995aed9Shannon Woods    const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer();
126113f7d7dc0b09fd7e508172c7d804ce65219b2bb5Jamie Madill    if (!fbo || fbo->completeness() != GL_FRAMEBUFFER_COMPLETE)
126213f7d7dc0b09fd7e508172c7d804ce65219b2bb5Jamie Madill    {
1263b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
1264b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
126513f7d7dc0b09fd7e508172c7d804ce65219b2bb5Jamie Madill    }
126613f7d7dc0b09fd7e508172c7d804ce65219b2bb5Jamie Madill
126713f7d7dc0b09fd7e508172c7d804ce65219b2bb5Jamie Madill    return true;
126813f7d7dc0b09fd7e508172c7d804ce65219b2bb5Jamie Madill}
126913f7d7dc0b09fd7e508172c7d804ce65219b2bb5Jamie Madill
1270b119668772ee960d8fc9e3846617c59530b90d5fGeoff Langbool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
12710063c51742659230ce535eb270acc0f06921d754Jamie Madill{
12720063c51742659230ce535eb270acc0f06921d754Jamie Madill    if (context->getClientVersion() < 3)
12730063c51742659230ce535eb270acc0f06921d754Jamie Madill    {
1274b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        context->recordError(Error(GL_INVALID_OPERATION));
1275b119668772ee960d8fc9e3846617c59530b90d5fGeoff Lang        return false;
12760063c51742659230ce535eb270acc0f06921d754Jamie Madill    }
12770063c51742659230ce535eb270acc0f06921d754Jamie Madill
127878f4180564b36fbb3ab21f298b12e2a1c8b18fcfJamie Madill    return ValidateGetUniformBase(context, program, location);
12790063c51742659230ce535eb270acc0f06921d754Jamie Madill}
12800063c51742659230ce535eb270acc0f06921d754Jamie Madill
1281e8ebe7f6ec21c3e624998d6fc1d10d1dbf6103c9Geoff Lang}
1282