blob: cfc178e22957864853735d5908e41fba1a2972c6 [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"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES.h"
12#include "libANGLE/Context.h"
13#include "libANGLE/Texture.h"
14#include "libANGLE/Framebuffer.h"
15#include "libANGLE/Renderbuffer.h"
16#include "libANGLE/formatutils.h"
17#include "libANGLE/FramebufferAttachment.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040018
19#include "common/mathutil.h"
Geoff Langa9be0dc2014-12-17 12:34:40 -050020#include "common/utilities.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040021
Jamie Madille2e406c2016-06-02 13:04:10 -040022using namespace angle;
23
Geoff Lange8ebe7f2013-08-05 15:03:13 -040024namespace gl
25{
26
Geoff Lang5d601382014-07-22 15:14:06 -040027struct ES3FormatCombination
28{
29 GLenum internalFormat;
30 GLenum format;
31 GLenum type;
32};
33
34bool operator<(const ES3FormatCombination& a, const ES3FormatCombination& b)
35{
36 return memcmp(&a, &b, sizeof(ES3FormatCombination)) < 0;
37}
38
39typedef std::set<ES3FormatCombination> ES3FormatCombinationSet;
40
41static inline void InsertES3FormatCombo(ES3FormatCombinationSet *set, GLenum internalFormat, GLenum format, GLenum type)
42{
43 ES3FormatCombination info;
44 info.internalFormat = internalFormat;
45 info.format = format;
46 info.type = type;
47 set->insert(info);
48}
49
50ES3FormatCombinationSet BuildES3FormatSet()
51{
52 ES3FormatCombinationSet set;
53
54 // Format combinations from ES 3.0.1 spec, table 3.2
55
56 // | Internal format | Format | Type |
57 // | | | |
58 InsertES3FormatCombo(&set, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE );
59 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE );
60 InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE );
61 InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE );
62 InsertES3FormatCombo(&set, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE );
63 InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 );
64 InsertES3FormatCombo(&set, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV );
65 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV );
66 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 );
67 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT );
68 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT_OES );
69 InsertES3FormatCombo(&set, GL_RGBA32F, GL_RGBA, GL_FLOAT );
70 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_FLOAT );
71 InsertES3FormatCombo(&set, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE );
72 InsertES3FormatCombo(&set, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE );
73 InsertES3FormatCombo(&set, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT );
74 InsertES3FormatCombo(&set, GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT );
75 InsertES3FormatCombo(&set, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT );
76 InsertES3FormatCombo(&set, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT );
77 InsertES3FormatCombo(&set, GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV );
78 InsertES3FormatCombo(&set, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE );
79 InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE );
80 InsertES3FormatCombo(&set, GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE );
81 InsertES3FormatCombo(&set, GL_RGB8_SNORM, GL_RGB, GL_BYTE );
82 InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 );
83 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV );
84 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV );
85 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT );
86 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT_OES );
87 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT );
88 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT_OES );
89 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT );
90 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT_OES );
91 InsertES3FormatCombo(&set, GL_RGB32F, GL_RGB, GL_FLOAT );
92 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_FLOAT );
93 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT );
94 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_FLOAT );
95 InsertES3FormatCombo(&set, GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE );
96 InsertES3FormatCombo(&set, GL_RGB8I, GL_RGB_INTEGER, GL_BYTE );
97 InsertES3FormatCombo(&set, GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT );
98 InsertES3FormatCombo(&set, GL_RGB16I, GL_RGB_INTEGER, GL_SHORT );
99 InsertES3FormatCombo(&set, GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT );
100 InsertES3FormatCombo(&set, GL_RGB32I, GL_RGB_INTEGER, GL_INT );
101 InsertES3FormatCombo(&set, GL_RG8, GL_RG, GL_UNSIGNED_BYTE );
102 InsertES3FormatCombo(&set, GL_RG8_SNORM, GL_RG, GL_BYTE );
103 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT );
104 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT_OES );
105 InsertES3FormatCombo(&set, GL_RG32F, GL_RG, GL_FLOAT );
106 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_FLOAT );
107 InsertES3FormatCombo(&set, GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE );
108 InsertES3FormatCombo(&set, GL_RG8I, GL_RG_INTEGER, GL_BYTE );
109 InsertES3FormatCombo(&set, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT );
110 InsertES3FormatCombo(&set, GL_RG16I, GL_RG_INTEGER, GL_SHORT );
111 InsertES3FormatCombo(&set, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT );
112 InsertES3FormatCombo(&set, GL_RG32I, GL_RG_INTEGER, GL_INT );
113 InsertES3FormatCombo(&set, GL_R8, GL_RED, GL_UNSIGNED_BYTE );
114 InsertES3FormatCombo(&set, GL_R8_SNORM, GL_RED, GL_BYTE );
115 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT );
116 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT_OES );
117 InsertES3FormatCombo(&set, GL_R32F, GL_RED, GL_FLOAT );
118 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_FLOAT );
119 InsertES3FormatCombo(&set, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE );
120 InsertES3FormatCombo(&set, GL_R8I, GL_RED_INTEGER, GL_BYTE );
121 InsertES3FormatCombo(&set, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT );
122 InsertES3FormatCombo(&set, GL_R16I, GL_RED_INTEGER, GL_SHORT );
123 InsertES3FormatCombo(&set, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT );
124 InsertES3FormatCombo(&set, GL_R32I, GL_RED_INTEGER, GL_INT );
125
126 // Unsized formats
127 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE );
128 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 );
129 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 );
130 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE );
131 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 );
132 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE );
133 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE );
134 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE );
135 InsertES3FormatCombo(&set, GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE );
136 InsertES3FormatCombo(&set, GL_SRGB_EXT, GL_SRGB_EXT, GL_UNSIGNED_BYTE );
Jamie Madill689325c2015-07-20 14:36:53 -0400137 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_UNSIGNED_BYTE );
138 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_FLOAT );
139 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_HALF_FLOAT );
140 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_HALF_FLOAT_OES );
141 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_UNSIGNED_BYTE );
142 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_FLOAT );
143 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_HALF_FLOAT );
144 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_HALF_FLOAT_OES );
145 InsertES3FormatCombo(&set, GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 );
Geoff Lang5d601382014-07-22 15:14:06 -0400146
147 // Depth stencil formats
148 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT );
149 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
150 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
151 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT );
152 InsertES3FormatCombo(&set, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 );
153 InsertES3FormatCombo(&set, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
154
155 // From GL_EXT_sRGB
156 InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE );
157 InsertES3FormatCombo(&set, GL_SRGB8, GL_SRGB_EXT, GL_UNSIGNED_BYTE );
158
159 // From GL_OES_texture_float
Jeff Muizelaarbb1a5be2015-12-02 12:03:46 -0500160 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_FLOAT );
161 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_FLOAT );
Geoff Lang5d601382014-07-22 15:14:06 -0400162 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT );
163 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT );
164 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_FLOAT );
165
166 // From GL_OES_texture_half_float
167 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT );
168 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES );
169 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT );
170 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES );
171 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT );
172 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES );
173
174 // From GL_EXT_texture_format_BGRA8888
175 InsertES3FormatCombo(&set, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
176
177 // From GL_EXT_texture_storage
178 // | Internal format | Format | Type |
179 // | | | |
180 InsertES3FormatCombo(&set, GL_ALPHA8_EXT, GL_ALPHA, GL_UNSIGNED_BYTE );
181 InsertES3FormatCombo(&set, GL_LUMINANCE8_EXT, GL_LUMINANCE, GL_UNSIGNED_BYTE );
182 InsertES3FormatCombo(&set, GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE );
183 InsertES3FormatCombo(&set, GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT );
184 InsertES3FormatCombo(&set, GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT );
185 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT );
186 InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT );
187 InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT_OES );
188 InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT );
189 InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT_OES );
190 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT );
191 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES );
192
193 // From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888
194 InsertES3FormatCombo(&set, GL_BGRA8_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
195 InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT);
196 InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
197 InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT);
198 InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
199
200 // From GL_ANGLE_depth_texture
201 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8_OES );
202
Vincent Lang25ab4512016-05-13 18:13:59 +0200203 // From GL_EXT_texture_norm16
204 InsertES3FormatCombo(&set, GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT);
205 InsertES3FormatCombo(&set, GL_RG16_EXT, GL_RG, GL_UNSIGNED_SHORT);
206 InsertES3FormatCombo(&set, GL_RGB16_EXT, GL_RGB, GL_UNSIGNED_SHORT);
207 InsertES3FormatCombo(&set, GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT);
208 InsertES3FormatCombo(&set, GL_R16_SNORM_EXT, GL_RED, GL_SHORT);
209 InsertES3FormatCombo(&set, GL_RG16_SNORM_EXT, GL_RG, GL_SHORT);
210 InsertES3FormatCombo(&set, GL_RGB16_SNORM_EXT, GL_RGB, GL_SHORT);
211 InsertES3FormatCombo(&set, GL_RGBA16_SNORM_EXT, GL_RGBA, GL_SHORT);
212
Geoff Lang5d601382014-07-22 15:14:06 -0400213 return set;
214}
215
216static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
217{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500218 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
219 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
220 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
221 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
Geoff Langbaadf232014-08-04 13:58:02 -0400222 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400223 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
224 {
Jamie Madill437fa652016-05-03 15:13:24 -0400225 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400226 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400227 }
228
229 // The type and format are valid if any supported internal format has that type and format
230 bool formatSupported = false;
231 bool typeSupported = false;
232
233 static const ES3FormatCombinationSet es3FormatSet = BuildES3FormatSet();
234 for (ES3FormatCombinationSet::const_iterator i = es3FormatSet.begin(); i != es3FormatSet.end(); i++)
235 {
236 if (i->format == format || i->type == type)
237 {
238 const gl::InternalFormat &info = gl::GetInternalFormatInfo(i->internalFormat);
239 bool supported = info.textureSupport(context->getClientVersion(), context->getExtensions());
Geoff Langbaadf232014-08-04 13:58:02 -0400240 if (supported && i->type == type)
Geoff Lang5d601382014-07-22 15:14:06 -0400241 {
242 typeSupported = true;
243 }
Geoff Langbaadf232014-08-04 13:58:02 -0400244 if (supported && i->format == format)
Geoff Lang5d601382014-07-22 15:14:06 -0400245 {
246 formatSupported = true;
247 }
Geoff Langbaadf232014-08-04 13:58:02 -0400248
249 // Early-out if both type and format are supported now
250 if (typeSupported && formatSupported)
251 {
252 break;
253 }
Geoff Lang5d601382014-07-22 15:14:06 -0400254 }
255 }
256
257 if (!typeSupported || !formatSupported)
258 {
Jamie Madill437fa652016-05-03 15:13:24 -0400259 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400260 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400261 }
262
263 // Check if this is a valid format combination to load texture data
264 ES3FormatCombination searchFormat;
265 searchFormat.internalFormat = internalFormat;
266 searchFormat.format = format;
267 searchFormat.type = type;
268
269 if (es3FormatSet.find(searchFormat) == es3FormatSet.end())
270 {
Jamie Madill437fa652016-05-03 15:13:24 -0400271 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400272 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400273 }
274
275 return true;
276}
277
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500278bool ValidateES3TexImageParametersBase(Context *context,
279 GLenum target,
280 GLint level,
281 GLenum internalformat,
282 bool isCompressed,
283 bool isSubImage,
284 GLint xoffset,
285 GLint yoffset,
286 GLint zoffset,
287 GLsizei width,
288 GLsizei height,
289 GLsizei depth,
290 GLint border,
291 GLenum format,
292 GLenum type,
293 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400294{
295 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -0700296 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400297 {
Jamie Madill437fa652016-05-03 15:13:24 -0400298 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400299 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400300 }
301
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400302 // Verify zero border
303 if (border != 0)
304 {
Jamie Madill437fa652016-05-03 15:13:24 -0400305 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400306 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400307 }
308
Jamie Madill6f38f822014-06-06 17:12:20 -0400309 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
310 std::numeric_limits<GLsizei>::max() - xoffset < width ||
311 std::numeric_limits<GLsizei>::max() - yoffset < height ||
312 std::numeric_limits<GLsizei>::max() - zoffset < depth)
313 {
Jamie Madill437fa652016-05-03 15:13:24 -0400314 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400315 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400316 }
317
Geoff Langaae65a42014-05-26 12:43:44 -0400318 const gl::Caps &caps = context->getCaps();
319
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400320 switch (target)
321 {
322 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500323 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
324 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400325 {
Jamie Madill437fa652016-05-03 15:13:24 -0400326 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500327 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400328 }
329 break;
330
331 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
332 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
333 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
334 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
335 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
336 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500337 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400338 {
Jamie Madill437fa652016-05-03 15:13:24 -0400339 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500340 return false;
341 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400342
Geoff Langa9be0dc2014-12-17 12:34:40 -0500343 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
344 {
Jamie Madill437fa652016-05-03 15:13:24 -0400345 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500346 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400347 }
348 break;
349
350 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500351 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
352 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
353 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400354 {
Jamie Madill437fa652016-05-03 15:13:24 -0400355 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500356 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400357 }
358 break;
359
Geoff Langa9be0dc2014-12-17 12:34:40 -0500360 case GL_TEXTURE_2D_ARRAY:
361 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
362 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
Geoff Langb92c1332015-09-04 12:54:55 -0400363 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500364 {
Jamie Madill437fa652016-05-03 15:13:24 -0400365 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500366 return false;
367 }
368 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400369
370 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400371 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400372 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400373 }
374
Geoff Lang691e58c2014-12-19 17:03:25 -0500375 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400376 if (!texture)
377 {
Jamie Madill437fa652016-05-03 15:13:24 -0400378 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400379 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400380 }
381
Geoff Lang69cce582015-09-17 13:20:36 -0400382 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400383 {
Jamie Madill437fa652016-05-03 15:13:24 -0400384 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400385 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400386 }
387
388 // Validate texture formats
Geoff Langa9be0dc2014-12-17 12:34:40 -0500389 GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat;
Geoff Lang5d601382014-07-22 15:14:06 -0400390 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400391 if (isCompressed)
392 {
tmartino7c102692015-10-02 16:43:40 -0400393 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400394 {
Jamie Madill437fa652016-05-03 15:13:24 -0400395 context->handleError(Error(
tmartino7c102692015-10-02 16:43:40 -0400396 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format."));
Geoff Langb1196682014-07-23 13:47:29 -0400397 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400398 }
399
tmartino7c102692015-10-02 16:43:40 -0400400 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400401 {
Jamie Madill437fa652016-05-03 15:13:24 -0400402 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400403 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400404 }
405
Geoff Lang839ce0b2015-10-23 13:13:12 -0400406 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
407 {
Jamie Madill437fa652016-05-03 15:13:24 -0400408 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang839ce0b2015-10-23 13:13:12 -0400409 return false;
410 }
411
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400412 if (target == GL_TEXTURE_3D)
413 {
Jamie Madill437fa652016-05-03 15:13:24 -0400414 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400415 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400416 }
417 }
418 else
419 {
Geoff Langbaadf232014-08-04 13:58:02 -0400420 if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400421 {
Geoff Lang5d601382014-07-22 15:14:06 -0400422 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400423 }
424
425 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
426 {
Jamie Madill437fa652016-05-03 15:13:24 -0400427 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400428 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400429 }
430 }
431
432 // Validate sub image parameters
433 if (isSubImage)
434 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500435 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400436 {
Jamie Madill437fa652016-05-03 15:13:24 -0400437 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400438 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400439 }
440
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400441 if (width == 0 || height == 0 || depth == 0)
442 {
443 return false;
444 }
445
446 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
447 {
Jamie Madill437fa652016-05-03 15:13:24 -0400448 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400449 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400450 }
451
452 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
453 std::numeric_limits<GLsizei>::max() - yoffset < height ||
454 std::numeric_limits<GLsizei>::max() - zoffset < depth)
455 {
Jamie Madill437fa652016-05-03 15:13:24 -0400456 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400457 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400458 }
459
Geoff Langa9be0dc2014-12-17 12:34:40 -0500460 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
461 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
462 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400463 {
Jamie Madill437fa652016-05-03 15:13:24 -0400464 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400465 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400466 }
467 }
468
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400469 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700470 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400471 if (pixelUnpackBuffer != NULL)
472 {
473 // ...the data would be unpacked from the buffer object such that the memory reads required
474 // would exceed the data store size.
Geoff Lang5d601382014-07-22 15:14:06 -0400475 GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400476 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -0700477 const gl::Extents size(width, height, depth);
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700478 const auto &unpack = context->getGLState().getUnpackState();
Jamie Madill4b4cdff2016-06-06 13:53:38 -0700479
480 auto copyBytesOrErr = formatInfo.computeUnpackSize(type, size, unpack);
Jamie Madille2e406c2016-06-02 13:04:10 -0400481 if (copyBytesOrErr.isError())
482 {
483 context->handleError(copyBytesOrErr.getError());
484 return false;
485 }
486 CheckedNumeric<size_t> checkedCopyBytes(copyBytesOrErr.getResult());
487 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
488 checkedCopyBytes += checkedOffset;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400489
Jamie Madille2e406c2016-06-02 13:04:10 -0400490 if (!checkedCopyBytes.IsValid() ||
491 (checkedCopyBytes.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400492 {
493 // Overflow past the end of the buffer
Jamie Madill437fa652016-05-03 15:13:24 -0400494 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400495 return false;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400496 }
497
498 // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
499 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400500 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400501 {
Jamie Madillc751d1e2014-10-21 17:46:29 -0400502 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
503
Jamie Madille2e406c2016-06-02 13:04:10 -0400504 if ((checkedOffset.ValueOrDie() % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400505 {
Jamie Madill437fa652016-05-03 15:13:24 -0400506 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400507 return false;
508 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400509 }
510
Jamie Madill7a5f7382014-03-05 15:01:24 -0500511 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700512 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500513 {
Jamie Madill437fa652016-05-03 15:13:24 -0400514 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400515 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500516 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400517 }
518
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400519 return true;
520}
521
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500522bool ValidateES3TexImage2DParameters(Context *context,
523 GLenum target,
524 GLint level,
525 GLenum internalformat,
526 bool isCompressed,
527 bool isSubImage,
528 GLint xoffset,
529 GLint yoffset,
530 GLint zoffset,
531 GLsizei width,
532 GLsizei height,
533 GLsizei depth,
534 GLint border,
535 GLenum format,
536 GLenum type,
537 const GLvoid *pixels)
538{
539 if (!ValidTexture2DDestinationTarget(context, target))
540 {
Jamie Madill437fa652016-05-03 15:13:24 -0400541 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500542 return false;
543 }
544
545 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
546 isSubImage, xoffset, yoffset, zoffset, width, height,
547 depth, border, format, type, pixels);
548}
549
550bool ValidateES3TexImage3DParameters(Context *context,
551 GLenum target,
552 GLint level,
553 GLenum internalformat,
554 bool isCompressed,
555 bool isSubImage,
556 GLint xoffset,
557 GLint yoffset,
558 GLint zoffset,
559 GLsizei width,
560 GLsizei height,
561 GLsizei depth,
562 GLint border,
563 GLenum format,
564 GLenum type,
565 const GLvoid *pixels)
566{
567 if (!ValidTexture3DDestinationTarget(context, target))
568 {
Jamie Madill437fa652016-05-03 15:13:24 -0400569 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500570 return false;
571 }
572
573 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
574 isSubImage, xoffset, yoffset, zoffset, width, height,
575 depth, border, format, type, pixels);
576}
577
Geoff Lang5d601382014-07-22 15:14:06 -0400578struct EffectiveInternalFormatInfo
579{
580 GLenum mEffectiveFormat;
581 GLenum mDestFormat;
582 GLuint mMinRedBits;
583 GLuint mMaxRedBits;
584 GLuint mMinGreenBits;
585 GLuint mMaxGreenBits;
586 GLuint mMinBlueBits;
587 GLuint mMaxBlueBits;
588 GLuint mMinAlphaBits;
589 GLuint mMaxAlphaBits;
590
591 EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits,
592 GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits,
593 GLuint minAlphaBits, GLuint maxAlphaBits)
594 : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits),
595 mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits),
596 mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits),
597 mMaxAlphaBits(maxAlphaBits) {};
598};
599
600typedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
601
602static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList()
603{
604 EffectiveInternalFormatList list;
605
606 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
607 // linear source buffer component sizes.
608 // | Source channel min/max sizes |
609 // Effective Internal Format | N/A | R | G | B | A |
610 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8));
611 list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0));
612 list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0));
613 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0));
614 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0));
615 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4));
616 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1));
617 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8));
618 list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2));
619
620 return list;
621}
622
623static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList()
624{
625 EffectiveInternalFormatList list;
626
627 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
628 // linear source buffer component sizes.
629 // | Source channel min/max sizes |
630 // Effective Internal Format | Dest Format | R | G | B | A |
631 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
632 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX));
633 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
634 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX));
635 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX));
636 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4));
637 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1));
638 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8));
639
640 return list;
641}
642
643static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
644 GLenum *outEffectiveFormat)
645{
646 const EffectiveInternalFormatList *list = NULL;
647 GLenum targetFormat = GL_NONE;
648
649 if (destFormat.pixelBytes > 0)
650 {
651 static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList();
652 list = &sizedList;
653 }
654 else
655 {
656 static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList();
657 list = &unsizedList;
658 targetFormat = destFormat.format;
659 }
660
661 for (size_t curFormat = 0; curFormat < list->size(); ++curFormat)
662 {
663 const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat);
664 if ((formatInfo.mDestFormat == targetFormat) &&
665 (formatInfo.mMinRedBits <= srcFormat.redBits && formatInfo.mMaxRedBits >= srcFormat.redBits) &&
666 (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) &&
667 (formatInfo.mMinBlueBits <= srcFormat.blueBits && formatInfo.mMaxBlueBits >= srcFormat.blueBits) &&
668 (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits))
669 {
670 *outEffectiveFormat = formatInfo.mEffectiveFormat;
671 return true;
672 }
673 }
674
675 return false;
676}
677
678struct CopyConversion
679{
680 GLenum mTextureFormat;
681 GLenum mFramebufferFormat;
682
683 CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
684 : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
685
686 bool operator<(const CopyConversion& other) const
687 {
688 return memcmp(this, &other, sizeof(CopyConversion)) < 0;
689 }
690};
691
692typedef std::set<CopyConversion> CopyConversionSet;
693
694static CopyConversionSet BuildValidES3CopyTexImageCombinations()
695{
696 CopyConversionSet set;
697
698 // From ES 3.0.1 spec, table 3.15
699 set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
700 set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
701 set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
702 set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
703 set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
704 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
705 set.insert(CopyConversion(GL_RED, GL_RED));
706 set.insert(CopyConversion(GL_RED, GL_RG));
707 set.insert(CopyConversion(GL_RED, GL_RGB));
708 set.insert(CopyConversion(GL_RED, GL_RGBA));
709 set.insert(CopyConversion(GL_RG, GL_RG));
710 set.insert(CopyConversion(GL_RG, GL_RGB));
711 set.insert(CopyConversion(GL_RG, GL_RGBA));
712 set.insert(CopyConversion(GL_RGB, GL_RGB));
713 set.insert(CopyConversion(GL_RGB, GL_RGBA));
714 set.insert(CopyConversion(GL_RGBA, GL_RGBA));
715
716 // Necessary for ANGLE back-buffers
717 set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
718 set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
719 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
720 set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
721 set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
722 set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
723 set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
724
725 set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
726 set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
727 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
728 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
729 set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
730 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
731 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
732 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
733 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
734 set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
735
736 return set;
737}
738
Corentin Wallez76287682016-04-25 09:23:38 -0400739static bool EqualOrFirstZero(GLuint first, GLuint second)
740{
741 return first == 0 || first == second;
742}
743
Geoff Lang5d601382014-07-22 15:14:06 -0400744static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle)
745{
746 const InternalFormat &textureInternalFormatInfo = GetInternalFormatInfo(textureInternalFormat);
747 const InternalFormat &framebufferInternalFormatInfo = GetInternalFormatInfo(frameBufferInternalFormat);
748
749 static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
750 if (conversionSet.find(CopyConversion(textureInternalFormatInfo.format, framebufferInternalFormatInfo.format)) != conversionSet.end())
751 {
752 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
753 // must both be signed, unsigned, or fixed point and both source and destinations
754 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
755 // conversion between fixed and floating point.
756
757 if ((textureInternalFormatInfo.colorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.colorEncoding == GL_SRGB))
758 {
759 return false;
760 }
761
762 if (((textureInternalFormatInfo.componentType == GL_INT) != (framebufferInternalFormatInfo.componentType == GL_INT )) ||
763 ((textureInternalFormatInfo.componentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.componentType == GL_UNSIGNED_INT)))
764 {
765 return false;
766 }
767
768 if ((textureInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
769 textureInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
770 textureInternalFormatInfo.componentType == GL_FLOAT) &&
771 !(framebufferInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
772 framebufferInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
773 framebufferInternalFormatInfo.componentType == GL_FLOAT))
774 {
775 return false;
776 }
777
778 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
779 // The effective internal format of the source buffer is determined with the following rules applied in order:
780 // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
781 // effective internal format is the source buffer's sized internal format.
782 // * If the source buffer is a texture that was created with an unsized base internal format, then the
783 // effective internal format is the source image array's effective internal format, as specified by table
784 // 3.12, which is determined from the <format> and <type> that were used when the source image array was
785 // specified by TexImage*.
786 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
787 // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
788 // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
789 // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
790 // is SRGB.
791 const InternalFormat *sourceEffectiveFormat = NULL;
792 if (readBufferHandle != 0)
793 {
794 // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
795 if (framebufferInternalFormatInfo.pixelBytes > 0)
796 {
797 sourceEffectiveFormat = &framebufferInternalFormatInfo;
798 }
799 else
800 {
801 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
802 // 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 -0500803 GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type);
804 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400805 }
806 }
807 else
808 {
809 // The effective internal format must be derived from the source framebuffer's channel sizes.
810 // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
811 if (framebufferInternalFormatInfo.colorEncoding == GL_LINEAR)
812 {
813 GLenum effectiveFormat;
814 if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat))
815 {
816 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
817 }
818 else
819 {
820 return false;
821 }
822 }
823 else if (framebufferInternalFormatInfo.colorEncoding == GL_SRGB)
824 {
825 // SRGB buffers can only be copied to sized format destinations according to table 3.18
826 if ((textureInternalFormatInfo.pixelBytes > 0) &&
827 (framebufferInternalFormatInfo.redBits >= 1 && framebufferInternalFormatInfo.redBits <= 8) &&
828 (framebufferInternalFormatInfo.greenBits >= 1 && framebufferInternalFormatInfo.greenBits <= 8) &&
829 (framebufferInternalFormatInfo.blueBits >= 1 && framebufferInternalFormatInfo.blueBits <= 8) &&
830 (framebufferInternalFormatInfo.alphaBits >= 1 && framebufferInternalFormatInfo.alphaBits <= 8))
831 {
832 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
833 }
834 else
835 {
836 return false;
837 }
838 }
839 else
840 {
841 UNREACHABLE();
842 return false;
843 }
844 }
845
846 if (textureInternalFormatInfo.pixelBytes > 0)
847 {
Corentin Wallez76287682016-04-25 09:23:38 -0400848 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination
849 // format is sized, component sizes of the source and destination formats must exactly
850 // match if the destination format exists.
851 if (!EqualOrFirstZero(textureInternalFormatInfo.redBits,
852 sourceEffectiveFormat->redBits) ||
853 !EqualOrFirstZero(textureInternalFormatInfo.greenBits,
854 sourceEffectiveFormat->greenBits) ||
855 !EqualOrFirstZero(textureInternalFormatInfo.blueBits,
856 sourceEffectiveFormat->blueBits) ||
857 !EqualOrFirstZero(textureInternalFormatInfo.alphaBits,
858 sourceEffectiveFormat->alphaBits))
Geoff Lang5d601382014-07-22 15:14:06 -0400859 {
860 return false;
861 }
862 }
863
864
865 return true; // A conversion function exists, and no rule in the specification has precluded conversion
866 // between these formats.
867 }
868
869 return false;
870}
871
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500872bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
873 GLenum target,
874 GLint level,
875 GLenum internalformat,
876 bool isSubImage,
877 GLint xoffset,
878 GLint yoffset,
879 GLint zoffset,
880 GLint x,
881 GLint y,
882 GLsizei width,
883 GLsizei height,
884 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400885{
Jamie Madill560a8d82014-05-21 13:06:20 -0400886 GLenum textureInternalFormat;
887 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill6f38f822014-06-06 17:12:20 -0400888 xoffset, yoffset, zoffset, x, y, width, height,
889 border, &textureInternalFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400890 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400891 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400892 }
893
Jamie Madill51f40ec2016-06-15 14:06:00 -0400894 const auto &state = context->getGLState();
895 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
896 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400897
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700898 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400899 {
Jamie Madill437fa652016-05-03 15:13:24 -0400900 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400901 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400902 }
903
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700904 if (readFramebufferID != 0 && framebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400905 {
Jamie Madill437fa652016-05-03 15:13:24 -0400906 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400907 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400908 }
909
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400910 const gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400911 GLenum colorbufferInternalFormat = source->getInternalFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400912
913 if (isSubImage)
914 {
Geoff Lang5d601382014-07-22 15:14:06 -0400915 if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat,
Jamie Madillc29968b2016-01-20 11:17:23 -0500916 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400917 {
Jamie Madill437fa652016-05-03 15:13:24 -0400918 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400919 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400920 }
921 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400922 else
923 {
Geoff Lang5d601382014-07-22 15:14:06 -0400924 if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat,
Jamie Madillc29968b2016-01-20 11:17:23 -0500925 readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400926 {
Jamie Madill437fa652016-05-03 15:13:24 -0400927 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400928 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400929 }
930 }
931
Geoff Lang784a8fd2013-09-24 12:33:16 -0400932 // If width or height is zero, it is a no-op. Return false without setting an error.
933 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400934}
935
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500936bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
937 GLenum target,
938 GLint level,
939 GLenum internalformat,
940 bool isSubImage,
941 GLint xoffset,
942 GLint yoffset,
943 GLint zoffset,
944 GLint x,
945 GLint y,
946 GLsizei width,
947 GLsizei height,
948 GLint border)
949{
950 if (!ValidTexture2DDestinationTarget(context, target))
951 {
Jamie Madill437fa652016-05-03 15:13:24 -0400952 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500953 return false;
954 }
955
956 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
957 xoffset, yoffset, zoffset, x, y, width, height,
958 border);
959}
960
961bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
962 GLenum target,
963 GLint level,
964 GLenum internalformat,
965 bool isSubImage,
966 GLint xoffset,
967 GLint yoffset,
968 GLint zoffset,
969 GLint x,
970 GLint y,
971 GLsizei width,
972 GLsizei height,
973 GLint border)
974{
975 if (!ValidTexture3DDestinationTarget(context, target))
976 {
Jamie Madill437fa652016-05-03 15:13:24 -0400977 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500978 return false;
979 }
980
981 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
982 xoffset, yoffset, zoffset, x, y, width, height,
983 border);
984}
985
986bool ValidateES3TexStorageParametersBase(Context *context,
987 GLenum target,
988 GLsizei levels,
989 GLenum internalformat,
990 GLsizei width,
991 GLsizei height,
992 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400993{
994 if (width < 1 || height < 1 || depth < 1 || levels < 1)
995 {
Jamie Madill437fa652016-05-03 15:13:24 -0400996 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400997 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400998 }
999
Geoff Langb92c1332015-09-04 12:54:55 -04001000 GLsizei maxDim = std::max(width, height);
1001 if (target != GL_TEXTURE_2D_ARRAY)
1002 {
1003 maxDim = std::max(maxDim, depth);
1004 }
1005
1006 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001007 {
Jamie Madill437fa652016-05-03 15:13:24 -04001008 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001009 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001010 }
1011
Geoff Langaae65a42014-05-26 12:43:44 -04001012 const gl::Caps &caps = context->getCaps();
1013
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001014 switch (target)
1015 {
1016 case GL_TEXTURE_2D:
1017 {
Geoff Langaae65a42014-05-26 12:43:44 -04001018 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1019 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001020 {
Jamie Madill437fa652016-05-03 15:13:24 -04001021 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001022 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001023 }
1024 }
1025 break;
1026
Geoff Lang01c21d22013-09-24 11:52:16 -04001027 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001028 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001029 if (width != height)
1030 {
Jamie Madill437fa652016-05-03 15:13:24 -04001031 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001032 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001033 }
1034
Geoff Langaae65a42014-05-26 12:43:44 -04001035 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001036 {
Jamie Madill437fa652016-05-03 15:13:24 -04001037 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001038 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001039 }
1040 }
1041 break;
1042
1043 case GL_TEXTURE_3D:
1044 {
Geoff Langaae65a42014-05-26 12:43:44 -04001045 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
1046 static_cast<GLuint>(height) > caps.max3DTextureSize ||
1047 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001048 {
Jamie Madill437fa652016-05-03 15:13:24 -04001049 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001050 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001051 }
1052 }
1053 break;
1054
1055 case GL_TEXTURE_2D_ARRAY:
1056 {
Geoff Langaae65a42014-05-26 12:43:44 -04001057 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1058 static_cast<GLuint>(height) > caps.max2DTextureSize ||
1059 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001060 {
Jamie Madill437fa652016-05-03 15:13:24 -04001061 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001062 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001063 }
1064 }
1065 break;
1066
1067 default:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001068 UNREACHABLE();
Geoff Langb1196682014-07-23 13:47:29 -04001069 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001070 }
1071
Geoff Lang691e58c2014-12-19 17:03:25 -05001072 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001073 if (!texture || texture->id() == 0)
1074 {
Jamie Madill437fa652016-05-03 15:13:24 -04001075 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001076 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001077 }
1078
Geoff Lang69cce582015-09-17 13:20:36 -04001079 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001080 {
Jamie Madill437fa652016-05-03 15:13:24 -04001081 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001082 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001083 }
1084
Geoff Lang5d601382014-07-22 15:14:06 -04001085 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1086 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001087 {
Jamie Madill437fa652016-05-03 15:13:24 -04001088 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001089 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001090 }
1091
Geoff Lang5d601382014-07-22 15:14:06 -04001092 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001093 {
Jamie Madill437fa652016-05-03 15:13:24 -04001094 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001095 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001096 }
1097
1098 return true;
1099}
1100
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001101bool ValidateES3TexStorage2DParameters(Context *context,
1102 GLenum target,
1103 GLsizei levels,
1104 GLenum internalformat,
1105 GLsizei width,
1106 GLsizei height,
1107 GLsizei depth)
1108{
1109 if (!ValidTexture2DTarget(context, target))
1110 {
Jamie Madill437fa652016-05-03 15:13:24 -04001111 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001112 return false;
1113 }
1114
1115 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1116 height, depth);
1117}
1118
1119bool ValidateES3TexStorage3DParameters(Context *context,
1120 GLenum target,
1121 GLsizei levels,
1122 GLenum internalformat,
1123 GLsizei width,
1124 GLsizei height,
1125 GLsizei depth)
1126{
1127 if (!ValidTexture3DTarget(context, target))
1128 {
Jamie Madill437fa652016-05-03 15:13:24 -04001129 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001130 return false;
1131 }
1132
1133 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1134 height, depth);
1135}
1136
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001137bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1138{
1139 if (context->getClientVersion() < 3)
1140 {
Jamie Madill437fa652016-05-03 15:13:24 -04001141 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001142 return false;
1143 }
1144
1145 return ValidateBeginQueryBase(context, target, id);
1146}
1147
1148bool ValidateEndQuery(gl::Context *context, GLenum target)
1149{
1150 if (context->getClientVersion() < 3)
1151 {
Jamie Madill437fa652016-05-03 15:13:24 -04001152 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001153 return false;
1154 }
1155
1156 return ValidateEndQueryBase(context, target);
1157}
1158
1159bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1160{
1161 if (context->getClientVersion() < 3)
1162 {
Jamie Madill437fa652016-05-03 15:13:24 -04001163 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001164 return false;
1165 }
1166
1167 return ValidateGetQueryivBase(context, target, pname);
1168}
1169
1170bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1171{
1172 if (context->getClientVersion() < 3)
1173 {
Jamie Madill437fa652016-05-03 15:13:24 -04001174 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001175 return false;
1176 }
1177
1178 return ValidateGetQueryObjectValueBase(context, id, pname);
1179}
1180
Geoff Langb1196682014-07-23 13:47:29 -04001181bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
Jamie Madill570f7c82014-07-03 10:38:54 -04001182 GLuint texture, GLint level, GLint layer)
1183{
1184 if (context->getClientVersion() < 3)
1185 {
Jamie Madill437fa652016-05-03 15:13:24 -04001186 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001187 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001188 }
1189
Jamie Madill55ec3b12014-07-03 10:38:57 -04001190 if (layer < 0)
1191 {
Jamie Madill437fa652016-05-03 15:13:24 -04001192 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001193 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001194 }
1195
1196 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1197 {
1198 return false;
1199 }
1200
1201 const gl::Caps &caps = context->getCaps();
1202 if (texture != 0)
1203 {
1204 gl::Texture *tex = context->getTexture(texture);
1205 ASSERT(tex);
1206
1207 switch (tex->getTarget())
1208 {
1209 case GL_TEXTURE_2D_ARRAY:
1210 {
1211 if (level > gl::log2(caps.max2DTextureSize))
1212 {
Jamie Madill437fa652016-05-03 15:13:24 -04001213 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001214 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001215 }
1216
1217 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1218 {
Jamie Madill437fa652016-05-03 15:13:24 -04001219 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001220 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001221 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001222 }
1223 break;
1224
1225 case GL_TEXTURE_3D:
1226 {
1227 if (level > gl::log2(caps.max3DTextureSize))
1228 {
Jamie Madill437fa652016-05-03 15:13:24 -04001229 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001230 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001231 }
1232
1233 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1234 {
Jamie Madill437fa652016-05-03 15:13:24 -04001235 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001236 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001237 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001238 }
1239 break;
1240
1241 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001242 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001243 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001244 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001245
1246 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(tex->getTarget(), level));
1247 if (internalFormatInfo.compressed)
1248 {
Jamie Madill437fa652016-05-03 15:13:24 -04001249 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001250 return false;
1251 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001252 }
1253
1254 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001255}
1256
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001257bool ValidES3ReadFormatType(ValidationContext *context,
1258 GLenum internalFormat,
1259 GLenum format,
1260 GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001261{
Geoff Lang5d601382014-07-22 15:14:06 -04001262 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
1263
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001264 switch (format)
1265 {
1266 case GL_RGBA:
1267 switch (type)
1268 {
1269 case GL_UNSIGNED_BYTE:
1270 break;
Vincent Lang25ab4512016-05-13 18:13:59 +02001271 case GL_UNSIGNED_SHORT:
1272 if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
1273 internalFormatInfo.type != GL_UNSIGNED_SHORT)
1274 {
1275 return false;
1276 }
1277 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001278 case GL_UNSIGNED_INT_2_10_10_10_REV:
1279 if (internalFormat != GL_RGB10_A2)
1280 {
1281 return false;
1282 }
1283 break;
Geoff Lang1ec57f82013-10-16 11:43:23 -04001284 case GL_FLOAT:
Geoff Lang5d601382014-07-22 15:14:06 -04001285 if (internalFormatInfo.componentType != GL_FLOAT)
Geoff Lang1ec57f82013-10-16 11:43:23 -04001286 {
1287 return false;
1288 }
1289 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001290 default:
1291 return false;
1292 }
1293 break;
1294 case GL_RGBA_INTEGER:
1295 switch (type)
1296 {
1297 case GL_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001298 if (internalFormatInfo.componentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001299 {
1300 return false;
1301 }
1302 break;
1303 case GL_UNSIGNED_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001304 if (internalFormatInfo.componentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001305 {
1306 return false;
1307 }
1308 break;
1309 default:
1310 return false;
1311 }
1312 break;
1313 case GL_BGRA_EXT:
1314 switch (type)
1315 {
1316 case GL_UNSIGNED_BYTE:
1317 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1318 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1319 break;
1320 default:
1321 return false;
1322 }
1323 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001324 case GL_RG_EXT:
1325 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001326 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001327 {
1328 return false;
1329 }
1330 switch (type)
1331 {
1332 case GL_UNSIGNED_BYTE:
1333 break;
Vincent Lang25ab4512016-05-13 18:13:59 +02001334 case GL_UNSIGNED_SHORT:
1335 if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
1336 internalFormatInfo.type != GL_UNSIGNED_SHORT)
1337 {
1338 return false;
1339 }
1340 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001341 default:
1342 return false;
1343 }
1344 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001345 default:
1346 return false;
1347 }
1348 return true;
1349}
1350
Corentin Walleze0902642014-11-04 12:32:15 -08001351bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
1352 GLenum internalformat, GLsizei width, GLsizei height)
1353{
1354 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
1355 {
1356 return false;
1357 }
1358
1359 //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.
1360 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1361 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
1362 {
Jamie Madill437fa652016-05-03 15:13:24 -04001363 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -08001364 return false;
1365 }
1366
1367 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
1368 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1369 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1370 {
Jamie Madill437fa652016-05-03 15:13:24 -04001371 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001372 Error(GL_INVALID_OPERATION,
1373 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001374 return false;
1375 }
1376
1377 return true;
1378}
1379
Austin Kinross08332632015-05-05 13:35:47 -07001380bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
1381 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001382{
Austin Kinross08332632015-05-05 13:35:47 -07001383 if (context->getClientVersion() < 3)
1384 {
Jamie Madill437fa652016-05-03 15:13:24 -04001385 context->handleError(
1386 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001387 return false;
1388 }
1389
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001390 bool defaultFramebuffer = false;
1391
1392 switch (target)
1393 {
1394 case GL_DRAW_FRAMEBUFFER:
1395 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001396 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1397 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001398 case GL_READ_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001399 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1400 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001401 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001402 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001403 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001404 }
1405
Austin Kinross08332632015-05-05 13:35:47 -07001406 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001407}
1408
Jamie Madillc29968b2016-01-20 11:17:23 -05001409bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001410{
1411 if (context->getClientVersion() < 3)
1412 {
Jamie Madill437fa652016-05-03 15:13:24 -04001413 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001414 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001415 }
1416
Jamie Madill51f40ec2016-06-15 14:06:00 -04001417 if (context->getGLState().getDrawFramebuffer()->checkStatus(context->getContextState()) !=
1418 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001419 {
Jamie Madill437fa652016-05-03 15:13:24 -04001420 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001421 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001422 }
1423
1424 return true;
1425}
1426
Olli Etuaho71dfb362016-03-10 14:04:27 +02001427bool ValidateDrawRangeElements(Context *context,
1428 GLenum mode,
1429 GLuint start,
1430 GLuint end,
1431 GLsizei count,
1432 GLenum type,
1433 const GLvoid *indices,
1434 IndexRange *indexRange)
1435{
1436 if (context->getClientVersion() < 3)
1437 {
Jamie Madill437fa652016-05-03 15:13:24 -04001438 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001439 return false;
1440 }
1441
1442 if (end < start)
1443 {
Jamie Madill437fa652016-05-03 15:13:24 -04001444 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001445 return false;
1446 }
1447
1448 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1449 {
1450 return false;
1451 }
1452
1453 if (indexRange->end > end || indexRange->start < start)
1454 {
1455 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001456 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001457 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1458 return false;
1459 }
1460 return true;
1461}
1462
Geoff Langb1196682014-07-23 13:47:29 -04001463bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001464{
1465 if (context->getClientVersion() < 3)
1466 {
Jamie Madill437fa652016-05-03 15:13:24 -04001467 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001468 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001469 }
1470
Jamie Madill78f41802014-08-25 15:47:55 -04001471 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001472}
1473
Jamie Madillb885e572015-02-03 16:16:04 -05001474bool ValidateReadBuffer(Context *context, GLenum src)
1475{
1476 if (context->getClientVersion() < 3)
1477 {
Jamie Madill437fa652016-05-03 15:13:24 -04001478 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001479 return false;
1480 }
1481
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001482 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001483
1484 if (readFBO == nullptr)
1485 {
Jamie Madill437fa652016-05-03 15:13:24 -04001486 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001487 return false;
1488 }
1489
1490 if (src == GL_NONE)
1491 {
1492 return true;
1493 }
1494
Olli Etuaho84c9f592016-03-09 14:37:25 +02001495 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001496 {
Jamie Madill437fa652016-05-03 15:13:24 -04001497 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001498 return false;
1499 }
1500
1501 if (readFBO->id() == 0)
1502 {
1503 if (src != GL_BACK)
1504 {
1505 const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001506 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001507 return false;
1508 }
1509 }
1510 else
1511 {
1512 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1513
1514 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1515 {
1516 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001517 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001518 return false;
1519 }
1520 }
1521
1522 return true;
1523}
1524
Jamie Madill86af3d22015-07-21 15:14:07 -04001525bool ValidateCompressedTexImage3D(Context *context,
1526 GLenum target,
1527 GLint level,
1528 GLenum internalformat,
1529 GLsizei width,
1530 GLsizei height,
1531 GLsizei depth,
1532 GLint border,
1533 GLsizei imageSize,
1534 const GLvoid *data)
1535{
1536 if (context->getClientVersion() < 3)
1537 {
Jamie Madill437fa652016-05-03 15:13:24 -04001538 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001539 return false;
1540 }
1541
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001542 if (!ValidTextureTarget(context, target))
1543 {
1544 context->handleError(Error(GL_INVALID_ENUM));
1545 return false;
1546 }
1547
Jamie Madille2e406c2016-06-02 13:04:10 -04001548 // Validate image size
1549 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1550 {
1551 context->handleError(Error(GL_INVALID_VALUE));
1552 return false;
1553 }
1554
Jamie Madill86af3d22015-07-21 15:14:07 -04001555 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001556 if (!formatInfo.compressed)
1557 {
1558 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1559 return false;
1560 }
1561
Jamie Madill513558d2016-06-02 13:04:11 -04001562 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001563 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001564 if (blockSizeOrErr.isError())
1565 {
Jamie Madill513558d2016-06-02 13:04:11 -04001566 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001567 return false;
1568 }
1569 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001570 {
Jamie Madill437fa652016-05-03 15:13:24 -04001571 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001572 return false;
1573 }
1574
1575 // 3D texture target validation
1576 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1577 {
Jamie Madill437fa652016-05-03 15:13:24 -04001578 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001579 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1580 return false;
1581 }
1582
1583 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001584 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
1585 0, width, height, depth, border, GL_NONE, GL_NONE, data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001586 {
1587 return false;
1588 }
1589
1590 return true;
1591}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001592
1593bool ValidateBindVertexArray(Context *context, GLuint array)
1594{
1595 if (context->getClientVersion() < 3)
1596 {
Jamie Madill437fa652016-05-03 15:13:24 -04001597 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001598 return false;
1599 }
1600
1601 return ValidateBindVertexArrayBase(context, array);
1602}
1603
Austin Kinrossbc781f32015-10-26 09:27:38 -07001604bool ValidateIsVertexArray(Context *context)
1605{
1606 if (context->getClientVersion() < 3)
1607 {
Jamie Madill437fa652016-05-03 15:13:24 -04001608 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001609 return false;
1610 }
1611
1612 return true;
1613}
Geoff Langc5629752015-12-07 16:29:04 -05001614
1615bool ValidateProgramBinary(Context *context,
1616 GLuint program,
1617 GLenum binaryFormat,
1618 const void *binary,
1619 GLint length)
1620{
1621 if (context->getClientVersion() < 3)
1622 {
Jamie Madill437fa652016-05-03 15:13:24 -04001623 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001624 return false;
1625 }
1626
1627 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1628}
1629
1630bool ValidateGetProgramBinary(Context *context,
1631 GLuint program,
1632 GLsizei bufSize,
1633 GLsizei *length,
1634 GLenum *binaryFormat,
1635 void *binary)
1636{
1637 if (context->getClientVersion() < 3)
1638 {
Jamie Madill437fa652016-05-03 15:13:24 -04001639 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001640 return false;
1641 }
1642
1643 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1644}
1645
Olli Etuahof0fee072016-03-30 15:11:58 +03001646bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001647{
1648 if (context->getClientVersion() < 3)
1649 {
Jamie Madill437fa652016-05-03 15:13:24 -04001650 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001651 return false;
1652 }
1653
1654 if (GetValidProgram(context, program) == nullptr)
1655 {
1656 return false;
1657 }
1658
1659 switch (pname)
1660 {
1661 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001662 if (value != GL_FALSE && value != GL_TRUE)
1663 {
Jamie Madill437fa652016-05-03 15:13:24 -04001664 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001665 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1666 return false;
1667 }
Geoff Langc5629752015-12-07 16:29:04 -05001668 break;
1669
1670 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001671 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001672 return false;
1673 }
1674
1675 return true;
1676}
Jamie Madillc29968b2016-01-20 11:17:23 -05001677
1678bool ValidateBlitFramebuffer(Context *context,
1679 GLint srcX0,
1680 GLint srcY0,
1681 GLint srcX1,
1682 GLint srcY1,
1683 GLint dstX0,
1684 GLint dstY0,
1685 GLint dstX1,
1686 GLint dstY1,
1687 GLbitfield mask,
1688 GLenum filter)
1689{
1690 if (context->getClientVersion() < 3)
1691 {
Jamie Madill437fa652016-05-03 15:13:24 -04001692 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001693 return false;
1694 }
1695
1696 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1697 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001698}
Jamie Madillc29968b2016-01-20 11:17:23 -05001699
1700bool ValidateClearBufferiv(ValidationContext *context,
1701 GLenum buffer,
1702 GLint drawbuffer,
1703 const GLint *value)
1704{
1705 switch (buffer)
1706 {
1707 case GL_COLOR:
1708 if (drawbuffer < 0 ||
1709 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1710 {
Jamie Madill437fa652016-05-03 15:13:24 -04001711 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001712 return false;
1713 }
1714 break;
1715
1716 case GL_STENCIL:
1717 if (drawbuffer != 0)
1718 {
Jamie Madill437fa652016-05-03 15:13:24 -04001719 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001720 return false;
1721 }
1722 break;
1723
1724 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001725 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001726 return false;
1727 }
1728
1729 return ValidateClearBuffer(context);
1730}
1731
1732bool ValidateClearBufferuiv(ValidationContext *context,
1733 GLenum buffer,
1734 GLint drawbuffer,
1735 const GLuint *value)
1736{
1737 switch (buffer)
1738 {
1739 case GL_COLOR:
1740 if (drawbuffer < 0 ||
1741 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1742 {
Jamie Madill437fa652016-05-03 15:13:24 -04001743 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001744 return false;
1745 }
1746 break;
1747
1748 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001749 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001750 return false;
1751 }
1752
1753 return ValidateClearBuffer(context);
1754}
1755
1756bool ValidateClearBufferfv(ValidationContext *context,
1757 GLenum buffer,
1758 GLint drawbuffer,
1759 const GLfloat *value)
1760{
1761 switch (buffer)
1762 {
1763 case GL_COLOR:
1764 if (drawbuffer < 0 ||
1765 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1766 {
Jamie Madill437fa652016-05-03 15:13:24 -04001767 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001768 return false;
1769 }
1770 break;
1771
1772 case GL_DEPTH:
1773 if (drawbuffer != 0)
1774 {
Jamie Madill437fa652016-05-03 15:13:24 -04001775 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001776 return false;
1777 }
1778 break;
1779
1780 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001781 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001782 return false;
1783 }
1784
1785 return ValidateClearBuffer(context);
1786}
1787
1788bool ValidateClearBufferfi(ValidationContext *context,
1789 GLenum buffer,
1790 GLint drawbuffer,
1791 GLfloat depth,
1792 GLint stencil)
1793{
1794 switch (buffer)
1795 {
1796 case GL_DEPTH_STENCIL:
1797 if (drawbuffer != 0)
1798 {
Jamie Madill437fa652016-05-03 15:13:24 -04001799 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001800 return false;
1801 }
1802 break;
1803
1804 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001805 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001806 return false;
1807 }
1808
1809 return ValidateClearBuffer(context);
1810}
1811
1812bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1813{
1814 if (context->getClientVersion() < 3)
1815 {
Jamie Madill437fa652016-05-03 15:13:24 -04001816 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001817 return false;
1818 }
1819
1820 return ValidateDrawBuffersBase(context, n, bufs);
1821}
1822
1823bool ValidateCopyTexSubImage3D(Context *context,
1824 GLenum target,
1825 GLint level,
1826 GLint xoffset,
1827 GLint yoffset,
1828 GLint zoffset,
1829 GLint x,
1830 GLint y,
1831 GLsizei width,
1832 GLsizei height)
1833{
1834 if (context->getClientVersion() < 3)
1835 {
Jamie Madill437fa652016-05-03 15:13:24 -04001836 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001837 return false;
1838 }
1839
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001840 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1841 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001842}
1843
Jamie Madill73a84962016-02-12 09:27:23 -05001844bool ValidateTexImage3D(Context *context,
1845 GLenum target,
1846 GLint level,
1847 GLint internalformat,
1848 GLsizei width,
1849 GLsizei height,
1850 GLsizei depth,
1851 GLint border,
1852 GLenum format,
1853 GLenum type,
1854 const GLvoid *pixels)
1855{
1856 if (context->getClientVersion() < 3)
1857 {
Jamie Madill437fa652016-05-03 15:13:24 -04001858 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001859 return false;
1860 }
1861
1862 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1863 0, 0, width, height, depth, border, format, type,
1864 pixels);
1865}
1866
1867bool ValidateTexSubImage3D(Context *context,
1868 GLenum target,
1869 GLint level,
1870 GLint xoffset,
1871 GLint yoffset,
1872 GLint zoffset,
1873 GLsizei width,
1874 GLsizei height,
1875 GLsizei depth,
1876 GLenum format,
1877 GLenum type,
1878 const GLvoid *pixels)
1879{
1880 if (context->getClientVersion() < 3)
1881 {
Jamie Madill437fa652016-05-03 15:13:24 -04001882 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001883 return false;
1884 }
1885
1886 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1887 yoffset, zoffset, width, height, depth, 0, format, type,
1888 pixels);
1889}
1890
1891bool ValidateCompressedTexSubImage3D(Context *context,
1892 GLenum target,
1893 GLint level,
1894 GLint xoffset,
1895 GLint yoffset,
1896 GLint zoffset,
1897 GLsizei width,
1898 GLsizei height,
1899 GLsizei depth,
1900 GLenum format,
1901 GLsizei imageSize,
1902 const GLvoid *data)
1903{
1904 if (context->getClientVersion() < 3)
1905 {
Jamie Madill437fa652016-05-03 15:13:24 -04001906 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001907 return false;
1908 }
1909
1910 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001911 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001912 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001913 if (blockSizeOrErr.isError())
1914 {
1915 context->handleError(blockSizeOrErr.getError());
1916 return false;
1917 }
1918 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001919 {
Jamie Madill437fa652016-05-03 15:13:24 -04001920 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001921 return false;
1922 }
1923
1924 if (!data)
1925 {
Jamie Madill437fa652016-05-03 15:13:24 -04001926 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001927 return false;
1928 }
1929
1930 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
1931 width, height, depth, 0, GL_NONE, GL_NONE, data);
1932}
1933
Olli Etuaho41997e72016-03-10 13:38:39 +02001934bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1935{
1936 return ValidateGenOrDeleteES3(context, n);
1937}
1938
1939bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1940{
1941 return ValidateGenOrDeleteES3(context, n);
1942}
1943
1944bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1945{
1946 return ValidateGenOrDeleteCountES3(context, count);
1947}
1948
1949bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1950{
1951 return ValidateGenOrDeleteCountES3(context, count);
1952}
1953
1954bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1955{
1956 return ValidateGenOrDeleteES3(context, n);
1957}
1958
1959bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1960{
1961 if (!ValidateGenOrDeleteES3(context, n))
1962 {
1963 return false;
1964 }
1965 for (GLint i = 0; i < n; ++i)
1966 {
1967 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1968 if (transformFeedback != nullptr && transformFeedback->isActive())
1969 {
1970 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001971 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001972 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1973 return false;
1974 }
1975 }
1976 return true;
1977}
1978
1979bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1980{
1981 return ValidateGenOrDeleteES3(context, n);
1982}
1983
1984bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1985{
1986 return ValidateGenOrDeleteES3(context, n);
1987}
1988
1989bool ValidateGenOrDeleteES3(Context *context, GLint n)
1990{
1991 if (context->getClientVersion() < 3)
1992 {
Jamie Madill437fa652016-05-03 15:13:24 -04001993 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001994 return false;
1995 }
1996 return ValidateGenOrDelete(context, n);
1997}
1998
1999bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
2000{
2001 if (context->getClientVersion() < 3)
2002 {
Jamie Madill437fa652016-05-03 15:13:24 -04002003 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02002004 return false;
2005 }
2006 if (count < 0)
2007 {
Jamie Madill437fa652016-05-03 15:13:24 -04002008 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02002009 return false;
2010 }
2011 return true;
2012}
2013
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002014bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
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 Etuahoc3e55a42016-03-09 16:29:18 +02002019 return false;
2020 }
2021 switch (primitiveMode)
2022 {
2023 case GL_TRIANGLES:
2024 case GL_LINES:
2025 case GL_POINTS:
2026 break;
2027
2028 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002029 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002030 return false;
2031 }
2032
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002033 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002034 ASSERT(transformFeedback != nullptr);
2035
2036 if (transformFeedback->isActive())
2037 {
Jamie Madill437fa652016-05-03 15:13:24 -04002038 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002039 return false;
2040 }
2041 return true;
2042}
2043
Olli Etuaho37477912016-03-30 14:54:40 +03002044bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
2045{
2046 if (context->getClientVersion() < 3)
2047 {
Jamie Madill437fa652016-05-03 15:13:24 -04002048 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho37477912016-03-30 14:54:40 +03002049 return false;
2050 }
2051
2052 if (!context->isSampler(sampler))
2053 {
Jamie Madill437fa652016-05-03 15:13:24 -04002054 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho37477912016-03-30 14:54:40 +03002055 return false;
2056 }
2057
2058 if (!ValidateSamplerObjectParameter(context, pname))
2059 {
2060 return false;
2061 }
2062
Ian Ewellbda75592016-04-18 17:25:54 -04002063 if (!ValidateTexParamParameters(context, GL_TEXTURE_2D, pname, param))
Olli Etuaho37477912016-03-30 14:54:40 +03002064 {
2065 return false;
2066 }
2067 return true;
2068}
2069
2070bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
2071{
2072 // The only float parameters are MIN_LOD and MAX_LOD. For these any value is permissible, so
2073 // ValidateSamplerParameteri can be used for validation here.
2074 return ValidateSamplerParameteri(context, sampler, pname, static_cast<GLint>(param));
2075}
2076
Olli Etuaho4f667482016-03-30 15:56:35 +03002077bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
2078{
2079 if (context->getClientVersion() < 3)
2080 {
Jamie Madill437fa652016-05-03 15:13:24 -04002081 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002082 return false;
2083 }
2084
2085 return ValidateGetBufferPointervBase(context, target, pname, params);
2086}
2087
2088bool ValidateUnmapBuffer(Context *context, GLenum target)
2089{
2090 if (context->getClientVersion() < 3)
2091 {
Jamie Madill437fa652016-05-03 15:13:24 -04002092 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03002093 return false;
2094 }
2095
2096 return ValidateUnmapBufferBase(context, target);
2097}
2098
2099bool ValidateMapBufferRange(Context *context,
2100 GLenum target,
2101 GLintptr offset,
2102 GLsizeiptr length,
2103 GLbitfield access)
2104{
2105 if (context->getClientVersion() < 3)
2106 {
Jamie Madill437fa652016-05-03 15:13:24 -04002107 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002108 return false;
2109 }
2110
2111 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2112}
2113
2114bool ValidateFlushMappedBufferRange(Context *context,
2115 GLenum target,
2116 GLintptr offset,
2117 GLsizeiptr length)
2118{
2119 if (context->getClientVersion() < 3)
2120 {
Jamie Madill437fa652016-05-03 15:13:24 -04002121 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002122 return false;
2123 }
2124
2125 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2126}
2127
Jamie Madillc29968b2016-01-20 11:17:23 -05002128} // namespace gl