blob: 2efebcddd4af9f3ad4e02ccd312c96b07e6c4bf9 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES3.h"
10#include "libANGLE/validationES.h"
11#include "libANGLE/Context.h"
12#include "libANGLE/Texture.h"
13#include "libANGLE/Framebuffer.h"
14#include "libANGLE/Renderbuffer.h"
15#include "libANGLE/formatutils.h"
16#include "libANGLE/FramebufferAttachment.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040017
18#include "common/mathutil.h"
Geoff Langa9be0dc2014-12-17 12:34:40 -050019#include "common/utilities.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040020
21namespace gl
22{
23
Geoff Lang5d601382014-07-22 15:14:06 -040024struct ES3FormatCombination
25{
26 GLenum internalFormat;
27 GLenum format;
28 GLenum type;
29};
30
31bool operator<(const ES3FormatCombination& a, const ES3FormatCombination& b)
32{
33 return memcmp(&a, &b, sizeof(ES3FormatCombination)) < 0;
34}
35
36typedef std::set<ES3FormatCombination> ES3FormatCombinationSet;
37
38static inline void InsertES3FormatCombo(ES3FormatCombinationSet *set, GLenum internalFormat, GLenum format, GLenum type)
39{
40 ES3FormatCombination info;
41 info.internalFormat = internalFormat;
42 info.format = format;
43 info.type = type;
44 set->insert(info);
45}
46
47ES3FormatCombinationSet BuildES3FormatSet()
48{
49 ES3FormatCombinationSet set;
50
51 // Format combinations from ES 3.0.1 spec, table 3.2
52
53 // | Internal format | Format | Type |
54 // | | | |
55 InsertES3FormatCombo(&set, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE );
56 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE );
57 InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE );
58 InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE );
59 InsertES3FormatCombo(&set, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE );
60 InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 );
61 InsertES3FormatCombo(&set, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV );
62 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV );
63 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 );
64 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT );
65 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT_OES );
66 InsertES3FormatCombo(&set, GL_RGBA32F, GL_RGBA, GL_FLOAT );
67 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_FLOAT );
68 InsertES3FormatCombo(&set, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE );
69 InsertES3FormatCombo(&set, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE );
70 InsertES3FormatCombo(&set, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT );
71 InsertES3FormatCombo(&set, GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT );
72 InsertES3FormatCombo(&set, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT );
73 InsertES3FormatCombo(&set, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT );
74 InsertES3FormatCombo(&set, GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV );
75 InsertES3FormatCombo(&set, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE );
76 InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE );
77 InsertES3FormatCombo(&set, GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE );
78 InsertES3FormatCombo(&set, GL_RGB8_SNORM, GL_RGB, GL_BYTE );
79 InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 );
80 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV );
81 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV );
82 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT );
83 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT_OES );
84 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT );
85 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT_OES );
86 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT );
87 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT_OES );
88 InsertES3FormatCombo(&set, GL_RGB32F, GL_RGB, GL_FLOAT );
89 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_FLOAT );
90 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT );
91 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_FLOAT );
92 InsertES3FormatCombo(&set, GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE );
93 InsertES3FormatCombo(&set, GL_RGB8I, GL_RGB_INTEGER, GL_BYTE );
94 InsertES3FormatCombo(&set, GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT );
95 InsertES3FormatCombo(&set, GL_RGB16I, GL_RGB_INTEGER, GL_SHORT );
96 InsertES3FormatCombo(&set, GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT );
97 InsertES3FormatCombo(&set, GL_RGB32I, GL_RGB_INTEGER, GL_INT );
98 InsertES3FormatCombo(&set, GL_RG8, GL_RG, GL_UNSIGNED_BYTE );
99 InsertES3FormatCombo(&set, GL_RG8_SNORM, GL_RG, GL_BYTE );
100 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT );
101 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT_OES );
102 InsertES3FormatCombo(&set, GL_RG32F, GL_RG, GL_FLOAT );
103 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_FLOAT );
104 InsertES3FormatCombo(&set, GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE );
105 InsertES3FormatCombo(&set, GL_RG8I, GL_RG_INTEGER, GL_BYTE );
106 InsertES3FormatCombo(&set, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT );
107 InsertES3FormatCombo(&set, GL_RG16I, GL_RG_INTEGER, GL_SHORT );
108 InsertES3FormatCombo(&set, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT );
109 InsertES3FormatCombo(&set, GL_RG32I, GL_RG_INTEGER, GL_INT );
110 InsertES3FormatCombo(&set, GL_R8, GL_RED, GL_UNSIGNED_BYTE );
111 InsertES3FormatCombo(&set, GL_R8_SNORM, GL_RED, GL_BYTE );
112 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT );
113 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT_OES );
114 InsertES3FormatCombo(&set, GL_R32F, GL_RED, GL_FLOAT );
115 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_FLOAT );
116 InsertES3FormatCombo(&set, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE );
117 InsertES3FormatCombo(&set, GL_R8I, GL_RED_INTEGER, GL_BYTE );
118 InsertES3FormatCombo(&set, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT );
119 InsertES3FormatCombo(&set, GL_R16I, GL_RED_INTEGER, GL_SHORT );
120 InsertES3FormatCombo(&set, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT );
121 InsertES3FormatCombo(&set, GL_R32I, GL_RED_INTEGER, GL_INT );
122
123 // Unsized formats
124 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE );
125 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 );
126 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 );
127 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE );
128 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 );
129 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE );
130 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE );
131 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE );
132 InsertES3FormatCombo(&set, GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE );
133 InsertES3FormatCombo(&set, GL_SRGB_EXT, GL_SRGB_EXT, GL_UNSIGNED_BYTE );
Jamie Madill689325c2015-07-20 14:36:53 -0400134 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_UNSIGNED_BYTE );
135 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_FLOAT );
136 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_HALF_FLOAT );
137 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_HALF_FLOAT_OES );
138 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_UNSIGNED_BYTE );
139 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_FLOAT );
140 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_HALF_FLOAT );
141 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_HALF_FLOAT_OES );
142 InsertES3FormatCombo(&set, GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 );
Geoff Lang5d601382014-07-22 15:14:06 -0400143
144 // Depth stencil formats
145 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT );
146 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
147 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
148 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT );
149 InsertES3FormatCombo(&set, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 );
150 InsertES3FormatCombo(&set, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
151
152 // From GL_EXT_sRGB
153 InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE );
154 InsertES3FormatCombo(&set, GL_SRGB8, GL_SRGB_EXT, GL_UNSIGNED_BYTE );
155
156 // From GL_OES_texture_float
Jeff Muizelaarbb1a5be2015-12-02 12:03:46 -0500157 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_FLOAT );
158 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_FLOAT );
Geoff Lang5d601382014-07-22 15:14:06 -0400159 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT );
160 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT );
161 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_FLOAT );
162
163 // From GL_OES_texture_half_float
164 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT );
165 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES );
166 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT );
167 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES );
168 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT );
169 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES );
170
171 // From GL_EXT_texture_format_BGRA8888
172 InsertES3FormatCombo(&set, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
173
174 // From GL_EXT_texture_storage
175 // | Internal format | Format | Type |
176 // | | | |
177 InsertES3FormatCombo(&set, GL_ALPHA8_EXT, GL_ALPHA, GL_UNSIGNED_BYTE );
178 InsertES3FormatCombo(&set, GL_LUMINANCE8_EXT, GL_LUMINANCE, GL_UNSIGNED_BYTE );
179 InsertES3FormatCombo(&set, GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE );
180 InsertES3FormatCombo(&set, GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT );
181 InsertES3FormatCombo(&set, GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT );
182 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT );
183 InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT );
184 InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT_OES );
185 InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT );
186 InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT_OES );
187 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT );
188 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES );
189
190 // From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888
191 InsertES3FormatCombo(&set, GL_BGRA8_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
192 InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT);
193 InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
194 InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT);
195 InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
196
197 // From GL_ANGLE_depth_texture
198 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8_OES );
199
Vincent Lang25ab4512016-05-13 18:13:59 +0200200 // From GL_EXT_texture_norm16
201 InsertES3FormatCombo(&set, GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT);
202 InsertES3FormatCombo(&set, GL_RG16_EXT, GL_RG, GL_UNSIGNED_SHORT);
203 InsertES3FormatCombo(&set, GL_RGB16_EXT, GL_RGB, GL_UNSIGNED_SHORT);
204 InsertES3FormatCombo(&set, GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT);
205 InsertES3FormatCombo(&set, GL_R16_SNORM_EXT, GL_RED, GL_SHORT);
206 InsertES3FormatCombo(&set, GL_RG16_SNORM_EXT, GL_RG, GL_SHORT);
207 InsertES3FormatCombo(&set, GL_RGB16_SNORM_EXT, GL_RGB, GL_SHORT);
208 InsertES3FormatCombo(&set, GL_RGBA16_SNORM_EXT, GL_RGBA, GL_SHORT);
209
Geoff Lang5d601382014-07-22 15:14:06 -0400210 return set;
211}
212
213static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
214{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500215 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
216 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
217 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
218 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
Geoff Langbaadf232014-08-04 13:58:02 -0400219 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400220 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
221 {
Jamie Madill437fa652016-05-03 15:13:24 -0400222 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400223 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400224 }
225
226 // The type and format are valid if any supported internal format has that type and format
227 bool formatSupported = false;
228 bool typeSupported = false;
229
230 static const ES3FormatCombinationSet es3FormatSet = BuildES3FormatSet();
231 for (ES3FormatCombinationSet::const_iterator i = es3FormatSet.begin(); i != es3FormatSet.end(); i++)
232 {
233 if (i->format == format || i->type == type)
234 {
235 const gl::InternalFormat &info = gl::GetInternalFormatInfo(i->internalFormat);
236 bool supported = info.textureSupport(context->getClientVersion(), context->getExtensions());
Geoff Langbaadf232014-08-04 13:58:02 -0400237 if (supported && i->type == type)
Geoff Lang5d601382014-07-22 15:14:06 -0400238 {
239 typeSupported = true;
240 }
Geoff Langbaadf232014-08-04 13:58:02 -0400241 if (supported && i->format == format)
Geoff Lang5d601382014-07-22 15:14:06 -0400242 {
243 formatSupported = true;
244 }
Geoff Langbaadf232014-08-04 13:58:02 -0400245
246 // Early-out if both type and format are supported now
247 if (typeSupported && formatSupported)
248 {
249 break;
250 }
Geoff Lang5d601382014-07-22 15:14:06 -0400251 }
252 }
253
254 if (!typeSupported || !formatSupported)
255 {
Jamie Madill437fa652016-05-03 15:13:24 -0400256 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400257 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400258 }
259
260 // Check if this is a valid format combination to load texture data
261 ES3FormatCombination searchFormat;
262 searchFormat.internalFormat = internalFormat;
263 searchFormat.format = format;
264 searchFormat.type = type;
265
266 if (es3FormatSet.find(searchFormat) == es3FormatSet.end())
267 {
Jamie Madill437fa652016-05-03 15:13:24 -0400268 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400269 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400270 }
271
272 return true;
273}
274
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500275bool ValidateES3TexImageParametersBase(Context *context,
276 GLenum target,
277 GLint level,
278 GLenum internalformat,
279 bool isCompressed,
280 bool isSubImage,
281 GLint xoffset,
282 GLint yoffset,
283 GLint zoffset,
284 GLsizei width,
285 GLsizei height,
286 GLsizei depth,
287 GLint border,
288 GLenum format,
289 GLenum type,
290 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400291{
292 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -0700293 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400294 {
Jamie Madill437fa652016-05-03 15:13:24 -0400295 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400296 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400297 }
298
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400299 // Verify zero border
300 if (border != 0)
301 {
Jamie Madill437fa652016-05-03 15:13:24 -0400302 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400303 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400304 }
305
Jamie Madill6f38f822014-06-06 17:12:20 -0400306 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
307 std::numeric_limits<GLsizei>::max() - xoffset < width ||
308 std::numeric_limits<GLsizei>::max() - yoffset < height ||
309 std::numeric_limits<GLsizei>::max() - zoffset < depth)
310 {
Jamie Madill437fa652016-05-03 15:13:24 -0400311 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400312 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400313 }
314
Geoff Langaae65a42014-05-26 12:43:44 -0400315 const gl::Caps &caps = context->getCaps();
316
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400317 switch (target)
318 {
319 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500320 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
321 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400322 {
Jamie Madill437fa652016-05-03 15:13:24 -0400323 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500324 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400325 }
326 break;
327
328 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
329 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
330 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
331 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
332 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
333 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500334 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400335 {
Jamie Madill437fa652016-05-03 15:13:24 -0400336 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500337 return false;
338 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400339
Geoff Langa9be0dc2014-12-17 12:34:40 -0500340 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
341 {
Jamie Madill437fa652016-05-03 15:13:24 -0400342 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500343 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400344 }
345 break;
346
347 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500348 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
349 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
350 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400351 {
Jamie Madill437fa652016-05-03 15:13:24 -0400352 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500353 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400354 }
355 break;
356
Geoff Langa9be0dc2014-12-17 12:34:40 -0500357 case GL_TEXTURE_2D_ARRAY:
358 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
359 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
Geoff Langb92c1332015-09-04 12:54:55 -0400360 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500361 {
Jamie Madill437fa652016-05-03 15:13:24 -0400362 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500363 return false;
364 }
365 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400366
367 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400368 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400369 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400370 }
371
Geoff Lang691e58c2014-12-19 17:03:25 -0500372 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400373 if (!texture)
374 {
Jamie Madill437fa652016-05-03 15:13:24 -0400375 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400376 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400377 }
378
Geoff Lang69cce582015-09-17 13:20:36 -0400379 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400380 {
Jamie Madill437fa652016-05-03 15:13:24 -0400381 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400382 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400383 }
384
385 // Validate texture formats
Geoff Langa9be0dc2014-12-17 12:34:40 -0500386 GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat;
Geoff Lang5d601382014-07-22 15:14:06 -0400387 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400388 if (isCompressed)
389 {
tmartino7c102692015-10-02 16:43:40 -0400390 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400391 {
Jamie Madill437fa652016-05-03 15:13:24 -0400392 context->handleError(Error(
tmartino7c102692015-10-02 16:43:40 -0400393 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format."));
Geoff Langb1196682014-07-23 13:47:29 -0400394 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400395 }
396
tmartino7c102692015-10-02 16:43:40 -0400397 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400398 {
Jamie Madill437fa652016-05-03 15:13:24 -0400399 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400400 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400401 }
402
Geoff Lang839ce0b2015-10-23 13:13:12 -0400403 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
404 {
Jamie Madill437fa652016-05-03 15:13:24 -0400405 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang839ce0b2015-10-23 13:13:12 -0400406 return false;
407 }
408
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400409 if (target == GL_TEXTURE_3D)
410 {
Jamie Madill437fa652016-05-03 15:13:24 -0400411 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400412 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400413 }
414 }
415 else
416 {
Geoff Langbaadf232014-08-04 13:58:02 -0400417 if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400418 {
Geoff Lang5d601382014-07-22 15:14:06 -0400419 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400420 }
421
422 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
423 {
Jamie Madill437fa652016-05-03 15:13:24 -0400424 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400425 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400426 }
427 }
428
429 // Validate sub image parameters
430 if (isSubImage)
431 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500432 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400433 {
Jamie Madill437fa652016-05-03 15:13:24 -0400434 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400435 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400436 }
437
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400438 if (width == 0 || height == 0 || depth == 0)
439 {
440 return false;
441 }
442
443 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
444 {
Jamie Madill437fa652016-05-03 15:13:24 -0400445 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400446 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400447 }
448
449 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
450 std::numeric_limits<GLsizei>::max() - yoffset < height ||
451 std::numeric_limits<GLsizei>::max() - zoffset < depth)
452 {
Jamie Madill437fa652016-05-03 15:13:24 -0400453 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400454 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400455 }
456
Geoff Langa9be0dc2014-12-17 12:34:40 -0500457 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
458 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
459 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400460 {
Jamie Madill437fa652016-05-03 15:13:24 -0400461 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400462 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400463 }
464 }
465
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400466 // Check for pixel unpack buffer related API errors
Shannon Woods53a94a82014-06-24 15:20:36 -0400467 gl::Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400468 if (pixelUnpackBuffer != NULL)
469 {
470 // ...the data would be unpacked from the buffer object such that the memory reads required
471 // would exceed the data store size.
472 size_t widthSize = static_cast<size_t>(width);
473 size_t heightSize = static_cast<size_t>(height);
474 size_t depthSize = static_cast<size_t>(depth);
Geoff Lang5d601382014-07-22 15:14:06 -0400475 GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type);
Jamie Madill6f38f822014-06-06 17:12:20 -0400476
Geoff Lang5d601382014-07-22 15:14:06 -0400477 size_t pixelBytes = static_cast<size_t>(gl::GetInternalFormatInfo(sizedFormat).pixelBytes);
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400478
479 if (!rx::IsUnsignedMultiplicationSafe(widthSize, heightSize) ||
480 !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize, depthSize) ||
481 !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize * depthSize, pixelBytes))
482 {
483 // Overflow past the end of the buffer
Jamie Madill437fa652016-05-03 15:13:24 -0400484 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400485 return false;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400486 }
487
Jamie Madillc751d1e2014-10-21 17:46:29 -0400488 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
489 size_t copyBytes = formatInfo.computeBlockSize(type, width, height);
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400490 size_t offset = reinterpret_cast<size_t>(pixels);
491
Jamie Madill6f38f822014-06-06 17:12:20 -0400492 if (!rx::IsUnsignedAdditionSafe(offset, copyBytes) ||
Brandon Jonesd38f9262014-06-18 16:26:45 -0700493 ((offset + copyBytes) > static_cast<size_t>(pixelUnpackBuffer->getSize())))
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400494 {
495 // Overflow past the end of the buffer
Jamie Madill437fa652016-05-03 15:13:24 -0400496 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400497 return false;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400498 }
499
500 // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
501 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400502 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400503 {
Jamie Madillc751d1e2014-10-21 17:46:29 -0400504 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
505
506 if ((offset % dataBytesPerPixel) != 0)
507 {
Jamie Madill437fa652016-05-03 15:13:24 -0400508 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400509 return false;
510 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400511 }
512
Jamie Madill7a5f7382014-03-05 15:01:24 -0500513 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700514 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500515 {
Jamie Madill437fa652016-05-03 15:13:24 -0400516 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400517 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500518 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400519 }
520
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400521 return true;
522}
523
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500524bool ValidateES3TexImage2DParameters(Context *context,
525 GLenum target,
526 GLint level,
527 GLenum internalformat,
528 bool isCompressed,
529 bool isSubImage,
530 GLint xoffset,
531 GLint yoffset,
532 GLint zoffset,
533 GLsizei width,
534 GLsizei height,
535 GLsizei depth,
536 GLint border,
537 GLenum format,
538 GLenum type,
539 const GLvoid *pixels)
540{
541 if (!ValidTexture2DDestinationTarget(context, target))
542 {
Jamie Madill437fa652016-05-03 15:13:24 -0400543 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500544 return false;
545 }
546
547 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
548 isSubImage, xoffset, yoffset, zoffset, width, height,
549 depth, border, format, type, pixels);
550}
551
552bool ValidateES3TexImage3DParameters(Context *context,
553 GLenum target,
554 GLint level,
555 GLenum internalformat,
556 bool isCompressed,
557 bool isSubImage,
558 GLint xoffset,
559 GLint yoffset,
560 GLint zoffset,
561 GLsizei width,
562 GLsizei height,
563 GLsizei depth,
564 GLint border,
565 GLenum format,
566 GLenum type,
567 const GLvoid *pixels)
568{
569 if (!ValidTexture3DDestinationTarget(context, target))
570 {
Jamie Madill437fa652016-05-03 15:13:24 -0400571 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500572 return false;
573 }
574
575 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
576 isSubImage, xoffset, yoffset, zoffset, width, height,
577 depth, border, format, type, pixels);
578}
579
Geoff Lang5d601382014-07-22 15:14:06 -0400580struct EffectiveInternalFormatInfo
581{
582 GLenum mEffectiveFormat;
583 GLenum mDestFormat;
584 GLuint mMinRedBits;
585 GLuint mMaxRedBits;
586 GLuint mMinGreenBits;
587 GLuint mMaxGreenBits;
588 GLuint mMinBlueBits;
589 GLuint mMaxBlueBits;
590 GLuint mMinAlphaBits;
591 GLuint mMaxAlphaBits;
592
593 EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits,
594 GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits,
595 GLuint minAlphaBits, GLuint maxAlphaBits)
596 : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits),
597 mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits),
598 mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits),
599 mMaxAlphaBits(maxAlphaBits) {};
600};
601
602typedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
603
604static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList()
605{
606 EffectiveInternalFormatList list;
607
608 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
609 // linear source buffer component sizes.
610 // | Source channel min/max sizes |
611 // Effective Internal Format | N/A | R | G | B | A |
612 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8));
613 list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0));
614 list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0));
615 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0));
616 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0));
617 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4));
618 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1));
619 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8));
620 list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2));
621
622 return list;
623}
624
625static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList()
626{
627 EffectiveInternalFormatList list;
628
629 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
630 // linear source buffer component sizes.
631 // | Source channel min/max sizes |
632 // Effective Internal Format | Dest Format | R | G | B | A |
633 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
634 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX));
635 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
636 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX));
637 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX));
638 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4));
639 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1));
640 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8));
641
642 return list;
643}
644
645static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
646 GLenum *outEffectiveFormat)
647{
648 const EffectiveInternalFormatList *list = NULL;
649 GLenum targetFormat = GL_NONE;
650
651 if (destFormat.pixelBytes > 0)
652 {
653 static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList();
654 list = &sizedList;
655 }
656 else
657 {
658 static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList();
659 list = &unsizedList;
660 targetFormat = destFormat.format;
661 }
662
663 for (size_t curFormat = 0; curFormat < list->size(); ++curFormat)
664 {
665 const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat);
666 if ((formatInfo.mDestFormat == targetFormat) &&
667 (formatInfo.mMinRedBits <= srcFormat.redBits && formatInfo.mMaxRedBits >= srcFormat.redBits) &&
668 (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) &&
669 (formatInfo.mMinBlueBits <= srcFormat.blueBits && formatInfo.mMaxBlueBits >= srcFormat.blueBits) &&
670 (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits))
671 {
672 *outEffectiveFormat = formatInfo.mEffectiveFormat;
673 return true;
674 }
675 }
676
677 return false;
678}
679
680struct CopyConversion
681{
682 GLenum mTextureFormat;
683 GLenum mFramebufferFormat;
684
685 CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
686 : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
687
688 bool operator<(const CopyConversion& other) const
689 {
690 return memcmp(this, &other, sizeof(CopyConversion)) < 0;
691 }
692};
693
694typedef std::set<CopyConversion> CopyConversionSet;
695
696static CopyConversionSet BuildValidES3CopyTexImageCombinations()
697{
698 CopyConversionSet set;
699
700 // From ES 3.0.1 spec, table 3.15
701 set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
702 set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
703 set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
704 set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
705 set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
706 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
707 set.insert(CopyConversion(GL_RED, GL_RED));
708 set.insert(CopyConversion(GL_RED, GL_RG));
709 set.insert(CopyConversion(GL_RED, GL_RGB));
710 set.insert(CopyConversion(GL_RED, GL_RGBA));
711 set.insert(CopyConversion(GL_RG, GL_RG));
712 set.insert(CopyConversion(GL_RG, GL_RGB));
713 set.insert(CopyConversion(GL_RG, GL_RGBA));
714 set.insert(CopyConversion(GL_RGB, GL_RGB));
715 set.insert(CopyConversion(GL_RGB, GL_RGBA));
716 set.insert(CopyConversion(GL_RGBA, GL_RGBA));
717
718 // Necessary for ANGLE back-buffers
719 set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
720 set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
721 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
722 set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
723 set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
724 set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
725 set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
726
727 set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
728 set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
729 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
730 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
731 set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
732 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
733 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
734 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
735 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
736 set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
737
738 return set;
739}
740
Corentin Wallez76287682016-04-25 09:23:38 -0400741static bool EqualOrFirstZero(GLuint first, GLuint second)
742{
743 return first == 0 || first == second;
744}
745
Geoff Lang5d601382014-07-22 15:14:06 -0400746static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle)
747{
748 const InternalFormat &textureInternalFormatInfo = GetInternalFormatInfo(textureInternalFormat);
749 const InternalFormat &framebufferInternalFormatInfo = GetInternalFormatInfo(frameBufferInternalFormat);
750
751 static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
752 if (conversionSet.find(CopyConversion(textureInternalFormatInfo.format, framebufferInternalFormatInfo.format)) != conversionSet.end())
753 {
754 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
755 // must both be signed, unsigned, or fixed point and both source and destinations
756 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
757 // conversion between fixed and floating point.
758
759 if ((textureInternalFormatInfo.colorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.colorEncoding == GL_SRGB))
760 {
761 return false;
762 }
763
764 if (((textureInternalFormatInfo.componentType == GL_INT) != (framebufferInternalFormatInfo.componentType == GL_INT )) ||
765 ((textureInternalFormatInfo.componentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.componentType == GL_UNSIGNED_INT)))
766 {
767 return false;
768 }
769
770 if ((textureInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
771 textureInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
772 textureInternalFormatInfo.componentType == GL_FLOAT) &&
773 !(framebufferInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
774 framebufferInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
775 framebufferInternalFormatInfo.componentType == GL_FLOAT))
776 {
777 return false;
778 }
779
780 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
781 // The effective internal format of the source buffer is determined with the following rules applied in order:
782 // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
783 // effective internal format is the source buffer's sized internal format.
784 // * If the source buffer is a texture that was created with an unsized base internal format, then the
785 // effective internal format is the source image array's effective internal format, as specified by table
786 // 3.12, which is determined from the <format> and <type> that were used when the source image array was
787 // specified by TexImage*.
788 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
789 // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
790 // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
791 // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
792 // is SRGB.
793 const InternalFormat *sourceEffectiveFormat = NULL;
794 if (readBufferHandle != 0)
795 {
796 // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
797 if (framebufferInternalFormatInfo.pixelBytes > 0)
798 {
799 sourceEffectiveFormat = &framebufferInternalFormatInfo;
800 }
801 else
802 {
803 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
804 // texture. We can use the same table we use when creating textures to get its effective sized format.
Geoff Lang051dbc72015-01-05 15:48:58 -0500805 GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type);
806 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400807 }
808 }
809 else
810 {
811 // The effective internal format must be derived from the source framebuffer's channel sizes.
812 // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
813 if (framebufferInternalFormatInfo.colorEncoding == GL_LINEAR)
814 {
815 GLenum effectiveFormat;
816 if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat))
817 {
818 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
819 }
820 else
821 {
822 return false;
823 }
824 }
825 else if (framebufferInternalFormatInfo.colorEncoding == GL_SRGB)
826 {
827 // SRGB buffers can only be copied to sized format destinations according to table 3.18
828 if ((textureInternalFormatInfo.pixelBytes > 0) &&
829 (framebufferInternalFormatInfo.redBits >= 1 && framebufferInternalFormatInfo.redBits <= 8) &&
830 (framebufferInternalFormatInfo.greenBits >= 1 && framebufferInternalFormatInfo.greenBits <= 8) &&
831 (framebufferInternalFormatInfo.blueBits >= 1 && framebufferInternalFormatInfo.blueBits <= 8) &&
832 (framebufferInternalFormatInfo.alphaBits >= 1 && framebufferInternalFormatInfo.alphaBits <= 8))
833 {
834 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
835 }
836 else
837 {
838 return false;
839 }
840 }
841 else
842 {
843 UNREACHABLE();
844 return false;
845 }
846 }
847
848 if (textureInternalFormatInfo.pixelBytes > 0)
849 {
Corentin Wallez76287682016-04-25 09:23:38 -0400850 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination
851 // format is sized, component sizes of the source and destination formats must exactly
852 // match if the destination format exists.
853 if (!EqualOrFirstZero(textureInternalFormatInfo.redBits,
854 sourceEffectiveFormat->redBits) ||
855 !EqualOrFirstZero(textureInternalFormatInfo.greenBits,
856 sourceEffectiveFormat->greenBits) ||
857 !EqualOrFirstZero(textureInternalFormatInfo.blueBits,
858 sourceEffectiveFormat->blueBits) ||
859 !EqualOrFirstZero(textureInternalFormatInfo.alphaBits,
860 sourceEffectiveFormat->alphaBits))
Geoff Lang5d601382014-07-22 15:14:06 -0400861 {
862 return false;
863 }
864 }
865
866
867 return true; // A conversion function exists, and no rule in the specification has precluded conversion
868 // between these formats.
869 }
870
871 return false;
872}
873
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500874bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
875 GLenum target,
876 GLint level,
877 GLenum internalformat,
878 bool isSubImage,
879 GLint xoffset,
880 GLint yoffset,
881 GLint zoffset,
882 GLint x,
883 GLint y,
884 GLsizei width,
885 GLsizei height,
886 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400887{
Jamie Madill560a8d82014-05-21 13:06:20 -0400888 GLenum textureInternalFormat;
889 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill6f38f822014-06-06 17:12:20 -0400890 xoffset, yoffset, zoffset, x, y, width, height,
891 border, &textureInternalFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400892 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400893 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400894 }
895
Jamie Madillc29968b2016-01-20 11:17:23 -0500896 const auto &state = context->getState();
897 const gl::Framebuffer *framebuffer = state.getReadFramebuffer();
898 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400899
Geoff Lang748f74e2014-12-01 11:25:34 -0500900 if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400901 {
Jamie Madill437fa652016-05-03 15:13:24 -0400902 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400903 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400904 }
905
Jamie Madillc29968b2016-01-20 11:17:23 -0500906 if (readFramebufferID != 0 && framebuffer->getSamples(context->getData()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400907 {
Jamie Madill437fa652016-05-03 15:13:24 -0400908 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400909 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400910 }
911
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400912 const gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400913 GLenum colorbufferInternalFormat = source->getInternalFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400914
915 if (isSubImage)
916 {
Geoff Lang5d601382014-07-22 15:14:06 -0400917 if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat,
Jamie Madillc29968b2016-01-20 11:17:23 -0500918 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400919 {
Jamie Madill437fa652016-05-03 15:13:24 -0400920 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400921 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400922 }
923 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400924 else
925 {
Geoff Lang5d601382014-07-22 15:14:06 -0400926 if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat,
Jamie Madillc29968b2016-01-20 11:17:23 -0500927 readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400928 {
Jamie Madill437fa652016-05-03 15:13:24 -0400929 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400930 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400931 }
932 }
933
Geoff Lang784a8fd2013-09-24 12:33:16 -0400934 // If width or height is zero, it is a no-op. Return false without setting an error.
935 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400936}
937
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500938bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
939 GLenum target,
940 GLint level,
941 GLenum internalformat,
942 bool isSubImage,
943 GLint xoffset,
944 GLint yoffset,
945 GLint zoffset,
946 GLint x,
947 GLint y,
948 GLsizei width,
949 GLsizei height,
950 GLint border)
951{
952 if (!ValidTexture2DDestinationTarget(context, target))
953 {
Jamie Madill437fa652016-05-03 15:13:24 -0400954 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500955 return false;
956 }
957
958 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
959 xoffset, yoffset, zoffset, x, y, width, height,
960 border);
961}
962
963bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
964 GLenum target,
965 GLint level,
966 GLenum internalformat,
967 bool isSubImage,
968 GLint xoffset,
969 GLint yoffset,
970 GLint zoffset,
971 GLint x,
972 GLint y,
973 GLsizei width,
974 GLsizei height,
975 GLint border)
976{
977 if (!ValidTexture3DDestinationTarget(context, target))
978 {
Jamie Madill437fa652016-05-03 15:13:24 -0400979 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500980 return false;
981 }
982
983 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
984 xoffset, yoffset, zoffset, x, y, width, height,
985 border);
986}
987
988bool ValidateES3TexStorageParametersBase(Context *context,
989 GLenum target,
990 GLsizei levels,
991 GLenum internalformat,
992 GLsizei width,
993 GLsizei height,
994 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400995{
996 if (width < 1 || height < 1 || depth < 1 || levels < 1)
997 {
Jamie Madill437fa652016-05-03 15:13:24 -0400998 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400999 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001000 }
1001
Geoff Langb92c1332015-09-04 12:54:55 -04001002 GLsizei maxDim = std::max(width, height);
1003 if (target != GL_TEXTURE_2D_ARRAY)
1004 {
1005 maxDim = std::max(maxDim, depth);
1006 }
1007
1008 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001009 {
Jamie Madill437fa652016-05-03 15:13:24 -04001010 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001011 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001012 }
1013
Geoff Langaae65a42014-05-26 12:43:44 -04001014 const gl::Caps &caps = context->getCaps();
1015
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001016 switch (target)
1017 {
1018 case GL_TEXTURE_2D:
1019 {
Geoff Langaae65a42014-05-26 12:43:44 -04001020 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1021 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001022 {
Jamie Madill437fa652016-05-03 15:13:24 -04001023 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001024 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001025 }
1026 }
1027 break;
1028
Geoff Lang01c21d22013-09-24 11:52:16 -04001029 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001030 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001031 if (width != height)
1032 {
Jamie Madill437fa652016-05-03 15:13:24 -04001033 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001034 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001035 }
1036
Geoff Langaae65a42014-05-26 12:43:44 -04001037 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001038 {
Jamie Madill437fa652016-05-03 15:13:24 -04001039 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001040 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001041 }
1042 }
1043 break;
1044
1045 case GL_TEXTURE_3D:
1046 {
Geoff Langaae65a42014-05-26 12:43:44 -04001047 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
1048 static_cast<GLuint>(height) > caps.max3DTextureSize ||
1049 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001050 {
Jamie Madill437fa652016-05-03 15:13:24 -04001051 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001052 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001053 }
1054 }
1055 break;
1056
1057 case GL_TEXTURE_2D_ARRAY:
1058 {
Geoff Langaae65a42014-05-26 12:43:44 -04001059 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1060 static_cast<GLuint>(height) > caps.max2DTextureSize ||
1061 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001062 {
Jamie Madill437fa652016-05-03 15:13:24 -04001063 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001064 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001065 }
1066 }
1067 break;
1068
1069 default:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001070 UNREACHABLE();
Geoff Langb1196682014-07-23 13:47:29 -04001071 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001072 }
1073
Geoff Lang691e58c2014-12-19 17:03:25 -05001074 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001075 if (!texture || texture->id() == 0)
1076 {
Jamie Madill437fa652016-05-03 15:13:24 -04001077 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001078 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001079 }
1080
Geoff Lang69cce582015-09-17 13:20:36 -04001081 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001082 {
Jamie Madill437fa652016-05-03 15:13:24 -04001083 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001084 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001085 }
1086
Geoff Lang5d601382014-07-22 15:14:06 -04001087 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1088 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001089 {
Jamie Madill437fa652016-05-03 15:13:24 -04001090 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001091 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001092 }
1093
Geoff Lang5d601382014-07-22 15:14:06 -04001094 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001095 {
Jamie Madill437fa652016-05-03 15:13:24 -04001096 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001097 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001098 }
1099
1100 return true;
1101}
1102
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001103bool ValidateES3TexStorage2DParameters(Context *context,
1104 GLenum target,
1105 GLsizei levels,
1106 GLenum internalformat,
1107 GLsizei width,
1108 GLsizei height,
1109 GLsizei depth)
1110{
1111 if (!ValidTexture2DTarget(context, target))
1112 {
Jamie Madill437fa652016-05-03 15:13:24 -04001113 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001114 return false;
1115 }
1116
1117 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1118 height, depth);
1119}
1120
1121bool ValidateES3TexStorage3DParameters(Context *context,
1122 GLenum target,
1123 GLsizei levels,
1124 GLenum internalformat,
1125 GLsizei width,
1126 GLsizei height,
1127 GLsizei depth)
1128{
1129 if (!ValidTexture3DTarget(context, target))
1130 {
Jamie Madill437fa652016-05-03 15:13:24 -04001131 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001132 return false;
1133 }
1134
1135 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1136 height, depth);
1137}
1138
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001139bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1140{
1141 if (context->getClientVersion() < 3)
1142 {
Jamie Madill437fa652016-05-03 15:13:24 -04001143 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001144 return false;
1145 }
1146
1147 return ValidateBeginQueryBase(context, target, id);
1148}
1149
1150bool ValidateEndQuery(gl::Context *context, GLenum target)
1151{
1152 if (context->getClientVersion() < 3)
1153 {
Jamie Madill437fa652016-05-03 15:13:24 -04001154 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001155 return false;
1156 }
1157
1158 return ValidateEndQueryBase(context, target);
1159}
1160
1161bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1162{
1163 if (context->getClientVersion() < 3)
1164 {
Jamie Madill437fa652016-05-03 15:13:24 -04001165 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001166 return false;
1167 }
1168
1169 return ValidateGetQueryivBase(context, target, pname);
1170}
1171
1172bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1173{
1174 if (context->getClientVersion() < 3)
1175 {
Jamie Madill437fa652016-05-03 15:13:24 -04001176 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001177 return false;
1178 }
1179
1180 return ValidateGetQueryObjectValueBase(context, id, pname);
1181}
1182
Geoff Langb1196682014-07-23 13:47:29 -04001183bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
Jamie Madill570f7c82014-07-03 10:38:54 -04001184 GLuint texture, GLint level, GLint layer)
1185{
1186 if (context->getClientVersion() < 3)
1187 {
Jamie Madill437fa652016-05-03 15:13:24 -04001188 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001189 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001190 }
1191
Jamie Madill55ec3b12014-07-03 10:38:57 -04001192 if (layer < 0)
1193 {
Jamie Madill437fa652016-05-03 15:13:24 -04001194 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001195 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001196 }
1197
1198 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1199 {
1200 return false;
1201 }
1202
1203 const gl::Caps &caps = context->getCaps();
1204 if (texture != 0)
1205 {
1206 gl::Texture *tex = context->getTexture(texture);
1207 ASSERT(tex);
1208
1209 switch (tex->getTarget())
1210 {
1211 case GL_TEXTURE_2D_ARRAY:
1212 {
1213 if (level > gl::log2(caps.max2DTextureSize))
1214 {
Jamie Madill437fa652016-05-03 15:13:24 -04001215 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001216 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001217 }
1218
1219 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1220 {
Jamie Madill437fa652016-05-03 15:13:24 -04001221 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001222 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001223 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001224 }
1225 break;
1226
1227 case GL_TEXTURE_3D:
1228 {
1229 if (level > gl::log2(caps.max3DTextureSize))
1230 {
Jamie Madill437fa652016-05-03 15:13:24 -04001231 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001232 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001233 }
1234
1235 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1236 {
Jamie Madill437fa652016-05-03 15:13:24 -04001237 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001238 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001239 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001240 }
1241 break;
1242
1243 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001244 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001245 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001246 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001247
1248 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(tex->getTarget(), level));
1249 if (internalFormatInfo.compressed)
1250 {
Jamie Madill437fa652016-05-03 15:13:24 -04001251 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001252 return false;
1253 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001254 }
1255
1256 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001257}
1258
Geoff Langb1196682014-07-23 13:47:29 -04001259bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001260{
Geoff Lang5d601382014-07-22 15:14:06 -04001261 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
1262
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001263 switch (format)
1264 {
1265 case GL_RGBA:
1266 switch (type)
1267 {
1268 case GL_UNSIGNED_BYTE:
1269 break;
Vincent Lang25ab4512016-05-13 18:13:59 +02001270 case GL_UNSIGNED_SHORT:
1271 if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
1272 internalFormatInfo.type != GL_UNSIGNED_SHORT)
1273 {
1274 return false;
1275 }
1276 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001277 case GL_UNSIGNED_INT_2_10_10_10_REV:
1278 if (internalFormat != GL_RGB10_A2)
1279 {
1280 return false;
1281 }
1282 break;
Geoff Lang1ec57f82013-10-16 11:43:23 -04001283 case GL_FLOAT:
Geoff Lang5d601382014-07-22 15:14:06 -04001284 if (internalFormatInfo.componentType != GL_FLOAT)
Geoff Lang1ec57f82013-10-16 11:43:23 -04001285 {
1286 return false;
1287 }
1288 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001289 default:
1290 return false;
1291 }
1292 break;
1293 case GL_RGBA_INTEGER:
1294 switch (type)
1295 {
1296 case GL_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001297 if (internalFormatInfo.componentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001298 {
1299 return false;
1300 }
1301 break;
1302 case GL_UNSIGNED_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001303 if (internalFormatInfo.componentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001304 {
1305 return false;
1306 }
1307 break;
1308 default:
1309 return false;
1310 }
1311 break;
1312 case GL_BGRA_EXT:
1313 switch (type)
1314 {
1315 case GL_UNSIGNED_BYTE:
1316 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1317 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1318 break;
1319 default:
1320 return false;
1321 }
1322 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001323 case GL_RG_EXT:
1324 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001325 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001326 {
1327 return false;
1328 }
1329 switch (type)
1330 {
1331 case GL_UNSIGNED_BYTE:
1332 break;
Vincent Lang25ab4512016-05-13 18:13:59 +02001333 case GL_UNSIGNED_SHORT:
1334 if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
1335 internalFormatInfo.type != GL_UNSIGNED_SHORT)
1336 {
1337 return false;
1338 }
1339 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001340 default:
1341 return false;
1342 }
1343 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001344 default:
1345 return false;
1346 }
1347 return true;
1348}
1349
Corentin Walleze0902642014-11-04 12:32:15 -08001350bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
1351 GLenum internalformat, GLsizei width, GLsizei height)
1352{
1353 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
1354 {
1355 return false;
1356 }
1357
1358 //The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer format if samples is greater than zero.
1359 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1360 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
1361 {
Jamie Madill437fa652016-05-03 15:13:24 -04001362 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -08001363 return false;
1364 }
1365
1366 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
1367 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1368 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1369 {
Jamie Madill437fa652016-05-03 15:13:24 -04001370 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001371 Error(GL_INVALID_OPERATION,
1372 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001373 return false;
1374 }
1375
1376 return true;
1377}
1378
Austin Kinross08332632015-05-05 13:35:47 -07001379bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
1380 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001381{
Austin Kinross08332632015-05-05 13:35:47 -07001382 if (context->getClientVersion() < 3)
1383 {
Jamie Madill437fa652016-05-03 15:13:24 -04001384 context->handleError(
1385 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001386 return false;
1387 }
1388
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389 bool defaultFramebuffer = false;
1390
1391 switch (target)
1392 {
1393 case GL_DRAW_FRAMEBUFFER:
1394 case GL_FRAMEBUFFER:
Shannon Woods53a94a82014-06-24 15:20:36 -04001395 defaultFramebuffer = context->getState().getDrawFramebuffer()->id() == 0;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001396 break;
1397 case GL_READ_FRAMEBUFFER:
Shannon Woods53a94a82014-06-24 15:20:36 -04001398 defaultFramebuffer = context->getState().getReadFramebuffer()->id() == 0;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399 break;
1400 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001401 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001402 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001403 }
1404
Austin Kinross08332632015-05-05 13:35:47 -07001405 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001406}
1407
Jamie Madillc29968b2016-01-20 11:17:23 -05001408bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001409{
1410 if (context->getClientVersion() < 3)
1411 {
Jamie Madill437fa652016-05-03 15:13:24 -04001412 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001413 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001414 }
1415
Shannon Woods53a94a82014-06-24 15:20:36 -04001416 const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer();
Geoff Lang748f74e2014-12-01 11:25:34 -05001417 if (!fbo || fbo->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001418 {
Jamie Madill437fa652016-05-03 15:13:24 -04001419 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001420 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001421 }
1422
1423 return true;
1424}
1425
Olli Etuaho71dfb362016-03-10 14:04:27 +02001426bool ValidateDrawRangeElements(Context *context,
1427 GLenum mode,
1428 GLuint start,
1429 GLuint end,
1430 GLsizei count,
1431 GLenum type,
1432 const GLvoid *indices,
1433 IndexRange *indexRange)
1434{
1435 if (context->getClientVersion() < 3)
1436 {
Jamie Madill437fa652016-05-03 15:13:24 -04001437 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001438 return false;
1439 }
1440
1441 if (end < start)
1442 {
Jamie Madill437fa652016-05-03 15:13:24 -04001443 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001444 return false;
1445 }
1446
1447 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1448 {
1449 return false;
1450 }
1451
1452 if (indexRange->end > end || indexRange->start < start)
1453 {
1454 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001455 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001456 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1457 return false;
1458 }
1459 return true;
1460}
1461
Geoff Langb1196682014-07-23 13:47:29 -04001462bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001463{
1464 if (context->getClientVersion() < 3)
1465 {
Jamie Madill437fa652016-05-03 15:13:24 -04001466 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001467 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001468 }
1469
Jamie Madill78f41802014-08-25 15:47:55 -04001470 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001471}
1472
Jamie Madillb885e572015-02-03 16:16:04 -05001473bool ValidateReadBuffer(Context *context, GLenum src)
1474{
1475 if (context->getClientVersion() < 3)
1476 {
Jamie Madill437fa652016-05-03 15:13:24 -04001477 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001478 return false;
1479 }
1480
1481 Framebuffer *readFBO = context->getState().getReadFramebuffer();
1482
1483 if (readFBO == nullptr)
1484 {
Jamie Madill437fa652016-05-03 15:13:24 -04001485 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001486 return false;
1487 }
1488
1489 if (src == GL_NONE)
1490 {
1491 return true;
1492 }
1493
Olli Etuaho84c9f592016-03-09 14:37:25 +02001494 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001495 {
Jamie Madill437fa652016-05-03 15:13:24 -04001496 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001497 return false;
1498 }
1499
1500 if (readFBO->id() == 0)
1501 {
1502 if (src != GL_BACK)
1503 {
1504 const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001505 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001506 return false;
1507 }
1508 }
1509 else
1510 {
1511 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1512
1513 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1514 {
1515 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001516 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001517 return false;
1518 }
1519 }
1520
1521 return true;
1522}
1523
Jamie Madill86af3d22015-07-21 15:14:07 -04001524bool ValidateCompressedTexImage3D(Context *context,
1525 GLenum target,
1526 GLint level,
1527 GLenum internalformat,
1528 GLsizei width,
1529 GLsizei height,
1530 GLsizei depth,
1531 GLint border,
1532 GLsizei imageSize,
1533 const GLvoid *data)
1534{
1535 if (context->getClientVersion() < 3)
1536 {
Jamie Madill437fa652016-05-03 15:13:24 -04001537 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001538 return false;
1539 }
1540
1541 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
1542 if (imageSize < 0 ||
1543 static_cast<GLuint>(imageSize) !=
1544 formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
1545 {
Jamie Madill437fa652016-05-03 15:13:24 -04001546 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001547 return false;
1548 }
1549
1550 // 3D texture target validation
1551 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1552 {
Jamie Madill437fa652016-05-03 15:13:24 -04001553 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001554 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1555 return false;
1556 }
1557
1558 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001559 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
1560 0, width, height, depth, border, GL_NONE, GL_NONE, data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001561 {
1562 return false;
1563 }
1564
1565 return true;
1566}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001567
1568bool ValidateBindVertexArray(Context *context, GLuint array)
1569{
1570 if (context->getClientVersion() < 3)
1571 {
Jamie Madill437fa652016-05-03 15:13:24 -04001572 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001573 return false;
1574 }
1575
1576 return ValidateBindVertexArrayBase(context, array);
1577}
1578
Austin Kinrossbc781f32015-10-26 09:27:38 -07001579bool ValidateIsVertexArray(Context *context)
1580{
1581 if (context->getClientVersion() < 3)
1582 {
Jamie Madill437fa652016-05-03 15:13:24 -04001583 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001584 return false;
1585 }
1586
1587 return true;
1588}
Geoff Langc5629752015-12-07 16:29:04 -05001589
1590bool ValidateProgramBinary(Context *context,
1591 GLuint program,
1592 GLenum binaryFormat,
1593 const void *binary,
1594 GLint length)
1595{
1596 if (context->getClientVersion() < 3)
1597 {
Jamie Madill437fa652016-05-03 15:13:24 -04001598 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001599 return false;
1600 }
1601
1602 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1603}
1604
1605bool ValidateGetProgramBinary(Context *context,
1606 GLuint program,
1607 GLsizei bufSize,
1608 GLsizei *length,
1609 GLenum *binaryFormat,
1610 void *binary)
1611{
1612 if (context->getClientVersion() < 3)
1613 {
Jamie Madill437fa652016-05-03 15:13:24 -04001614 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001615 return false;
1616 }
1617
1618 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1619}
1620
Olli Etuahof0fee072016-03-30 15:11:58 +03001621bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001622{
1623 if (context->getClientVersion() < 3)
1624 {
Jamie Madill437fa652016-05-03 15:13:24 -04001625 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001626 return false;
1627 }
1628
1629 if (GetValidProgram(context, program) == nullptr)
1630 {
1631 return false;
1632 }
1633
1634 switch (pname)
1635 {
1636 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001637 if (value != GL_FALSE && value != GL_TRUE)
1638 {
Jamie Madill437fa652016-05-03 15:13:24 -04001639 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001640 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1641 return false;
1642 }
Geoff Langc5629752015-12-07 16:29:04 -05001643 break;
1644
1645 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001646 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001647 return false;
1648 }
1649
1650 return true;
1651}
Jamie Madillc29968b2016-01-20 11:17:23 -05001652
1653bool ValidateBlitFramebuffer(Context *context,
1654 GLint srcX0,
1655 GLint srcY0,
1656 GLint srcX1,
1657 GLint srcY1,
1658 GLint dstX0,
1659 GLint dstY0,
1660 GLint dstX1,
1661 GLint dstY1,
1662 GLbitfield mask,
1663 GLenum filter)
1664{
1665 if (context->getClientVersion() < 3)
1666 {
Jamie Madill437fa652016-05-03 15:13:24 -04001667 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001668 return false;
1669 }
1670
1671 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1672 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001673}
Jamie Madillc29968b2016-01-20 11:17:23 -05001674
1675bool ValidateClearBufferiv(ValidationContext *context,
1676 GLenum buffer,
1677 GLint drawbuffer,
1678 const GLint *value)
1679{
1680 switch (buffer)
1681 {
1682 case GL_COLOR:
1683 if (drawbuffer < 0 ||
1684 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1685 {
Jamie Madill437fa652016-05-03 15:13:24 -04001686 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001687 return false;
1688 }
1689 break;
1690
1691 case GL_STENCIL:
1692 if (drawbuffer != 0)
1693 {
Jamie Madill437fa652016-05-03 15:13:24 -04001694 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001695 return false;
1696 }
1697 break;
1698
1699 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001700 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001701 return false;
1702 }
1703
1704 return ValidateClearBuffer(context);
1705}
1706
1707bool ValidateClearBufferuiv(ValidationContext *context,
1708 GLenum buffer,
1709 GLint drawbuffer,
1710 const GLuint *value)
1711{
1712 switch (buffer)
1713 {
1714 case GL_COLOR:
1715 if (drawbuffer < 0 ||
1716 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1717 {
Jamie Madill437fa652016-05-03 15:13:24 -04001718 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001719 return false;
1720 }
1721 break;
1722
1723 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001724 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001725 return false;
1726 }
1727
1728 return ValidateClearBuffer(context);
1729}
1730
1731bool ValidateClearBufferfv(ValidationContext *context,
1732 GLenum buffer,
1733 GLint drawbuffer,
1734 const GLfloat *value)
1735{
1736 switch (buffer)
1737 {
1738 case GL_COLOR:
1739 if (drawbuffer < 0 ||
1740 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1741 {
Jamie Madill437fa652016-05-03 15:13:24 -04001742 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001743 return false;
1744 }
1745 break;
1746
1747 case GL_DEPTH:
1748 if (drawbuffer != 0)
1749 {
Jamie Madill437fa652016-05-03 15:13:24 -04001750 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001751 return false;
1752 }
1753 break;
1754
1755 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001756 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001757 return false;
1758 }
1759
1760 return ValidateClearBuffer(context);
1761}
1762
1763bool ValidateClearBufferfi(ValidationContext *context,
1764 GLenum buffer,
1765 GLint drawbuffer,
1766 GLfloat depth,
1767 GLint stencil)
1768{
1769 switch (buffer)
1770 {
1771 case GL_DEPTH_STENCIL:
1772 if (drawbuffer != 0)
1773 {
Jamie Madill437fa652016-05-03 15:13:24 -04001774 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001775 return false;
1776 }
1777 break;
1778
1779 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001780 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001781 return false;
1782 }
1783
1784 return ValidateClearBuffer(context);
1785}
1786
1787bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1788{
1789 if (context->getClientVersion() < 3)
1790 {
Jamie Madill437fa652016-05-03 15:13:24 -04001791 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001792 return false;
1793 }
1794
1795 return ValidateDrawBuffersBase(context, n, bufs);
1796}
1797
1798bool ValidateCopyTexSubImage3D(Context *context,
1799 GLenum target,
1800 GLint level,
1801 GLint xoffset,
1802 GLint yoffset,
1803 GLint zoffset,
1804 GLint x,
1805 GLint y,
1806 GLsizei width,
1807 GLsizei height)
1808{
1809 if (context->getClientVersion() < 3)
1810 {
Jamie Madill437fa652016-05-03 15:13:24 -04001811 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001812 return false;
1813 }
1814
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001815 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1816 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001817}
1818
Jamie Madill73a84962016-02-12 09:27:23 -05001819bool ValidateTexImage3D(Context *context,
1820 GLenum target,
1821 GLint level,
1822 GLint internalformat,
1823 GLsizei width,
1824 GLsizei height,
1825 GLsizei depth,
1826 GLint border,
1827 GLenum format,
1828 GLenum type,
1829 const GLvoid *pixels)
1830{
1831 if (context->getClientVersion() < 3)
1832 {
Jamie Madill437fa652016-05-03 15:13:24 -04001833 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001834 return false;
1835 }
1836
1837 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1838 0, 0, width, height, depth, border, format, type,
1839 pixels);
1840}
1841
1842bool ValidateTexSubImage3D(Context *context,
1843 GLenum target,
1844 GLint level,
1845 GLint xoffset,
1846 GLint yoffset,
1847 GLint zoffset,
1848 GLsizei width,
1849 GLsizei height,
1850 GLsizei depth,
1851 GLenum format,
1852 GLenum type,
1853 const GLvoid *pixels)
1854{
1855 if (context->getClientVersion() < 3)
1856 {
Jamie Madill437fa652016-05-03 15:13:24 -04001857 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001858 return false;
1859 }
1860
1861 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1862 yoffset, zoffset, width, height, depth, 0, format, type,
1863 pixels);
1864}
1865
1866bool ValidateCompressedTexSubImage3D(Context *context,
1867 GLenum target,
1868 GLint level,
1869 GLint xoffset,
1870 GLint yoffset,
1871 GLint zoffset,
1872 GLsizei width,
1873 GLsizei height,
1874 GLsizei depth,
1875 GLenum format,
1876 GLsizei imageSize,
1877 const GLvoid *data)
1878{
1879 if (context->getClientVersion() < 3)
1880 {
Jamie Madill437fa652016-05-03 15:13:24 -04001881 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001882 return false;
1883 }
1884
1885 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
1886 if (imageSize < 0 ||
1887 static_cast<GLuint>(imageSize) !=
1888 formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
1889 {
Jamie Madill437fa652016-05-03 15:13:24 -04001890 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001891 return false;
1892 }
1893
1894 if (!data)
1895 {
Jamie Madill437fa652016-05-03 15:13:24 -04001896 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001897 return false;
1898 }
1899
1900 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
1901 width, height, depth, 0, GL_NONE, GL_NONE, data);
1902}
1903
Olli Etuaho41997e72016-03-10 13:38:39 +02001904bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1905{
1906 return ValidateGenOrDeleteES3(context, n);
1907}
1908
1909bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1910{
1911 return ValidateGenOrDeleteES3(context, n);
1912}
1913
1914bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1915{
1916 return ValidateGenOrDeleteCountES3(context, count);
1917}
1918
1919bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1920{
1921 return ValidateGenOrDeleteCountES3(context, count);
1922}
1923
1924bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1925{
1926 return ValidateGenOrDeleteES3(context, n);
1927}
1928
1929bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1930{
1931 if (!ValidateGenOrDeleteES3(context, n))
1932 {
1933 return false;
1934 }
1935 for (GLint i = 0; i < n; ++i)
1936 {
1937 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1938 if (transformFeedback != nullptr && transformFeedback->isActive())
1939 {
1940 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001941 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001942 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1943 return false;
1944 }
1945 }
1946 return true;
1947}
1948
1949bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1950{
1951 return ValidateGenOrDeleteES3(context, n);
1952}
1953
1954bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1955{
1956 return ValidateGenOrDeleteES3(context, n);
1957}
1958
1959bool ValidateGenOrDeleteES3(Context *context, GLint n)
1960{
1961 if (context->getClientVersion() < 3)
1962 {
Jamie Madill437fa652016-05-03 15:13:24 -04001963 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001964 return false;
1965 }
1966 return ValidateGenOrDelete(context, n);
1967}
1968
1969bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1970{
1971 if (context->getClientVersion() < 3)
1972 {
Jamie Madill437fa652016-05-03 15:13:24 -04001973 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001974 return false;
1975 }
1976 if (count < 0)
1977 {
Jamie Madill437fa652016-05-03 15:13:24 -04001978 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001979 return false;
1980 }
1981 return true;
1982}
1983
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001984bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1985{
1986 if (context->getClientVersion() < 3)
1987 {
Jamie Madill437fa652016-05-03 15:13:24 -04001988 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001989 return false;
1990 }
1991 switch (primitiveMode)
1992 {
1993 case GL_TRIANGLES:
1994 case GL_LINES:
1995 case GL_POINTS:
1996 break;
1997
1998 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001999 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002000 return false;
2001 }
2002
2003 TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
2004 ASSERT(transformFeedback != nullptr);
2005
2006 if (transformFeedback->isActive())
2007 {
Jamie Madill437fa652016-05-03 15:13:24 -04002008 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002009 return false;
2010 }
2011 return true;
2012}
2013
Olli Etuaho37477912016-03-30 14:54:40 +03002014bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
2015{
2016 if (context->getClientVersion() < 3)
2017 {
Jamie Madill437fa652016-05-03 15:13:24 -04002018 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho37477912016-03-30 14:54:40 +03002019 return false;
2020 }
2021
2022 if (!context->isSampler(sampler))
2023 {
Jamie Madill437fa652016-05-03 15:13:24 -04002024 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho37477912016-03-30 14:54:40 +03002025 return false;
2026 }
2027
2028 if (!ValidateSamplerObjectParameter(context, pname))
2029 {
2030 return false;
2031 }
2032
Ian Ewellbda75592016-04-18 17:25:54 -04002033 if (!ValidateTexParamParameters(context, GL_TEXTURE_2D, pname, param))
Olli Etuaho37477912016-03-30 14:54:40 +03002034 {
2035 return false;
2036 }
2037 return true;
2038}
2039
2040bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
2041{
2042 // The only float parameters are MIN_LOD and MAX_LOD. For these any value is permissible, so
2043 // ValidateSamplerParameteri can be used for validation here.
2044 return ValidateSamplerParameteri(context, sampler, pname, static_cast<GLint>(param));
2045}
2046
Olli Etuaho4f667482016-03-30 15:56:35 +03002047bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
2048{
2049 if (context->getClientVersion() < 3)
2050 {
Jamie Madill437fa652016-05-03 15:13:24 -04002051 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002052 return false;
2053 }
2054
2055 return ValidateGetBufferPointervBase(context, target, pname, params);
2056}
2057
2058bool ValidateUnmapBuffer(Context *context, GLenum target)
2059{
2060 if (context->getClientVersion() < 3)
2061 {
Jamie Madill437fa652016-05-03 15:13:24 -04002062 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03002063 return false;
2064 }
2065
2066 return ValidateUnmapBufferBase(context, target);
2067}
2068
2069bool ValidateMapBufferRange(Context *context,
2070 GLenum target,
2071 GLintptr offset,
2072 GLsizeiptr length,
2073 GLbitfield access)
2074{
2075 if (context->getClientVersion() < 3)
2076 {
Jamie Madill437fa652016-05-03 15:13:24 -04002077 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002078 return false;
2079 }
2080
2081 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2082}
2083
2084bool ValidateFlushMappedBufferRange(Context *context,
2085 GLenum target,
2086 GLintptr offset,
2087 GLsizeiptr length)
2088{
2089 if (context->getClientVersion() < 3)
2090 {
Jamie Madill437fa652016-05-03 15:13:24 -04002091 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002092 return false;
2093 }
2094
2095 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2096}
2097
Jamie Madillc29968b2016-01-20 11:17:23 -05002098} // namespace gl