blob: 21c20f15e6be6645c5fc0cbb75e8f512b9932d30 [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
Olli Etuaho989cac32016-06-08 16:18:49 -0700490 auto rowPitchOrErr =
491 formatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength);
492 if (rowPitchOrErr.isError())
493 {
494 context->handleError(rowPitchOrErr.getError());
495 return false;
496 }
497 auto depthPitchOrErr = formatInfo.computeDepthPitch(type, width, height, unpack.alignment,
498 unpack.rowLength, unpack.imageHeight);
499 if (depthPitchOrErr.isError())
500 {
501 context->handleError(depthPitchOrErr.getError());
502 return false;
503 }
504
505 bool targetIs3D = target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY;
506 auto skipBytesOrErr = formatInfo.computeSkipBytes(
507 rowPitchOrErr.getResult(), depthPitchOrErr.getResult(), unpack.skipImages,
508 unpack.skipRows, unpack.skipPixels, targetIs3D);
509 if (skipBytesOrErr.isError())
510 {
511 context->handleError(skipBytesOrErr.getError());
512 return false;
513 }
514 checkedCopyBytes += skipBytesOrErr.getResult();
515
Jamie Madille2e406c2016-06-02 13:04:10 -0400516 if (!checkedCopyBytes.IsValid() ||
517 (checkedCopyBytes.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400518 {
519 // Overflow past the end of the buffer
Jamie Madill437fa652016-05-03 15:13:24 -0400520 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400521 return false;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400522 }
523
524 // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
525 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400526 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400527 {
Jamie Madillc751d1e2014-10-21 17:46:29 -0400528 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
529
Jamie Madille2e406c2016-06-02 13:04:10 -0400530 if ((checkedOffset.ValueOrDie() % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400531 {
Jamie Madill437fa652016-05-03 15:13:24 -0400532 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400533 return false;
534 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400535 }
536
Jamie Madill7a5f7382014-03-05 15:01:24 -0500537 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700538 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500539 {
Jamie Madill437fa652016-05-03 15:13:24 -0400540 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400541 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500542 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400543 }
544
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400545 return true;
546}
547
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500548bool ValidateES3TexImage2DParameters(Context *context,
549 GLenum target,
550 GLint level,
551 GLenum internalformat,
552 bool isCompressed,
553 bool isSubImage,
554 GLint xoffset,
555 GLint yoffset,
556 GLint zoffset,
557 GLsizei width,
558 GLsizei height,
559 GLsizei depth,
560 GLint border,
561 GLenum format,
562 GLenum type,
563 const GLvoid *pixels)
564{
565 if (!ValidTexture2DDestinationTarget(context, target))
566 {
Jamie Madill437fa652016-05-03 15:13:24 -0400567 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500568 return false;
569 }
570
571 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
572 isSubImage, xoffset, yoffset, zoffset, width, height,
573 depth, border, format, type, pixels);
574}
575
576bool ValidateES3TexImage3DParameters(Context *context,
577 GLenum target,
578 GLint level,
579 GLenum internalformat,
580 bool isCompressed,
581 bool isSubImage,
582 GLint xoffset,
583 GLint yoffset,
584 GLint zoffset,
585 GLsizei width,
586 GLsizei height,
587 GLsizei depth,
588 GLint border,
589 GLenum format,
590 GLenum type,
591 const GLvoid *pixels)
592{
593 if (!ValidTexture3DDestinationTarget(context, target))
594 {
Jamie Madill437fa652016-05-03 15:13:24 -0400595 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500596 return false;
597 }
598
599 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
600 isSubImage, xoffset, yoffset, zoffset, width, height,
601 depth, border, format, type, pixels);
602}
603
Geoff Lang5d601382014-07-22 15:14:06 -0400604struct EffectiveInternalFormatInfo
605{
606 GLenum mEffectiveFormat;
607 GLenum mDestFormat;
608 GLuint mMinRedBits;
609 GLuint mMaxRedBits;
610 GLuint mMinGreenBits;
611 GLuint mMaxGreenBits;
612 GLuint mMinBlueBits;
613 GLuint mMaxBlueBits;
614 GLuint mMinAlphaBits;
615 GLuint mMaxAlphaBits;
616
617 EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits,
618 GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits,
619 GLuint minAlphaBits, GLuint maxAlphaBits)
620 : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits),
621 mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits),
622 mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits),
623 mMaxAlphaBits(maxAlphaBits) {};
624};
625
626typedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
627
628static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList()
629{
630 EffectiveInternalFormatList list;
631
632 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
633 // linear source buffer component sizes.
634 // | Source channel min/max sizes |
635 // Effective Internal Format | N/A | R | G | B | A |
636 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8));
637 list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0));
638 list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0));
639 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0));
640 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0));
641 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4));
642 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1));
643 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8));
644 list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2));
645
646 return list;
647}
648
649static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList()
650{
651 EffectiveInternalFormatList list;
652
653 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
654 // linear source buffer component sizes.
655 // | Source channel min/max sizes |
656 // Effective Internal Format | Dest Format | R | G | B | A |
657 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
658 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX));
659 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
660 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX));
661 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX));
662 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4));
663 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1));
664 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8));
665
666 return list;
667}
668
669static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
670 GLenum *outEffectiveFormat)
671{
672 const EffectiveInternalFormatList *list = NULL;
673 GLenum targetFormat = GL_NONE;
674
675 if (destFormat.pixelBytes > 0)
676 {
677 static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList();
678 list = &sizedList;
679 }
680 else
681 {
682 static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList();
683 list = &unsizedList;
684 targetFormat = destFormat.format;
685 }
686
687 for (size_t curFormat = 0; curFormat < list->size(); ++curFormat)
688 {
689 const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat);
690 if ((formatInfo.mDestFormat == targetFormat) &&
691 (formatInfo.mMinRedBits <= srcFormat.redBits && formatInfo.mMaxRedBits >= srcFormat.redBits) &&
692 (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) &&
693 (formatInfo.mMinBlueBits <= srcFormat.blueBits && formatInfo.mMaxBlueBits >= srcFormat.blueBits) &&
694 (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits))
695 {
696 *outEffectiveFormat = formatInfo.mEffectiveFormat;
697 return true;
698 }
699 }
700
701 return false;
702}
703
704struct CopyConversion
705{
706 GLenum mTextureFormat;
707 GLenum mFramebufferFormat;
708
709 CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
710 : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
711
712 bool operator<(const CopyConversion& other) const
713 {
714 return memcmp(this, &other, sizeof(CopyConversion)) < 0;
715 }
716};
717
718typedef std::set<CopyConversion> CopyConversionSet;
719
720static CopyConversionSet BuildValidES3CopyTexImageCombinations()
721{
722 CopyConversionSet set;
723
724 // From ES 3.0.1 spec, table 3.15
725 set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
726 set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
727 set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
728 set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
729 set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
730 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
731 set.insert(CopyConversion(GL_RED, GL_RED));
732 set.insert(CopyConversion(GL_RED, GL_RG));
733 set.insert(CopyConversion(GL_RED, GL_RGB));
734 set.insert(CopyConversion(GL_RED, GL_RGBA));
735 set.insert(CopyConversion(GL_RG, GL_RG));
736 set.insert(CopyConversion(GL_RG, GL_RGB));
737 set.insert(CopyConversion(GL_RG, GL_RGBA));
738 set.insert(CopyConversion(GL_RGB, GL_RGB));
739 set.insert(CopyConversion(GL_RGB, GL_RGBA));
740 set.insert(CopyConversion(GL_RGBA, GL_RGBA));
741
742 // Necessary for ANGLE back-buffers
743 set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
744 set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
745 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
746 set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
747 set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
748 set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
749 set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
750
751 set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
752 set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
753 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
754 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
755 set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
756 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
757 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
758 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
759 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
760 set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
761
762 return set;
763}
764
Corentin Wallez76287682016-04-25 09:23:38 -0400765static bool EqualOrFirstZero(GLuint first, GLuint second)
766{
767 return first == 0 || first == second;
768}
769
Geoff Lang5d601382014-07-22 15:14:06 -0400770static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle)
771{
772 const InternalFormat &textureInternalFormatInfo = GetInternalFormatInfo(textureInternalFormat);
773 const InternalFormat &framebufferInternalFormatInfo = GetInternalFormatInfo(frameBufferInternalFormat);
774
775 static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
776 if (conversionSet.find(CopyConversion(textureInternalFormatInfo.format, framebufferInternalFormatInfo.format)) != conversionSet.end())
777 {
778 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
779 // must both be signed, unsigned, or fixed point and both source and destinations
780 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
781 // conversion between fixed and floating point.
782
783 if ((textureInternalFormatInfo.colorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.colorEncoding == GL_SRGB))
784 {
785 return false;
786 }
787
788 if (((textureInternalFormatInfo.componentType == GL_INT) != (framebufferInternalFormatInfo.componentType == GL_INT )) ||
789 ((textureInternalFormatInfo.componentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.componentType == GL_UNSIGNED_INT)))
790 {
791 return false;
792 }
793
794 if ((textureInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
795 textureInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
796 textureInternalFormatInfo.componentType == GL_FLOAT) &&
797 !(framebufferInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
798 framebufferInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
799 framebufferInternalFormatInfo.componentType == GL_FLOAT))
800 {
801 return false;
802 }
803
804 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
805 // The effective internal format of the source buffer is determined with the following rules applied in order:
806 // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
807 // effective internal format is the source buffer's sized internal format.
808 // * If the source buffer is a texture that was created with an unsized base internal format, then the
809 // effective internal format is the source image array's effective internal format, as specified by table
810 // 3.12, which is determined from the <format> and <type> that were used when the source image array was
811 // specified by TexImage*.
812 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
813 // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
814 // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
815 // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
816 // is SRGB.
817 const InternalFormat *sourceEffectiveFormat = NULL;
818 if (readBufferHandle != 0)
819 {
820 // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
821 if (framebufferInternalFormatInfo.pixelBytes > 0)
822 {
823 sourceEffectiveFormat = &framebufferInternalFormatInfo;
824 }
825 else
826 {
827 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
828 // 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 -0500829 GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type);
830 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400831 }
832 }
833 else
834 {
835 // The effective internal format must be derived from the source framebuffer's channel sizes.
836 // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
837 if (framebufferInternalFormatInfo.colorEncoding == GL_LINEAR)
838 {
839 GLenum effectiveFormat;
840 if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat))
841 {
842 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
843 }
844 else
845 {
846 return false;
847 }
848 }
849 else if (framebufferInternalFormatInfo.colorEncoding == GL_SRGB)
850 {
851 // SRGB buffers can only be copied to sized format destinations according to table 3.18
852 if ((textureInternalFormatInfo.pixelBytes > 0) &&
853 (framebufferInternalFormatInfo.redBits >= 1 && framebufferInternalFormatInfo.redBits <= 8) &&
854 (framebufferInternalFormatInfo.greenBits >= 1 && framebufferInternalFormatInfo.greenBits <= 8) &&
855 (framebufferInternalFormatInfo.blueBits >= 1 && framebufferInternalFormatInfo.blueBits <= 8) &&
856 (framebufferInternalFormatInfo.alphaBits >= 1 && framebufferInternalFormatInfo.alphaBits <= 8))
857 {
858 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
859 }
860 else
861 {
862 return false;
863 }
864 }
865 else
866 {
867 UNREACHABLE();
868 return false;
869 }
870 }
871
872 if (textureInternalFormatInfo.pixelBytes > 0)
873 {
Corentin Wallez76287682016-04-25 09:23:38 -0400874 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination
875 // format is sized, component sizes of the source and destination formats must exactly
876 // match if the destination format exists.
877 if (!EqualOrFirstZero(textureInternalFormatInfo.redBits,
878 sourceEffectiveFormat->redBits) ||
879 !EqualOrFirstZero(textureInternalFormatInfo.greenBits,
880 sourceEffectiveFormat->greenBits) ||
881 !EqualOrFirstZero(textureInternalFormatInfo.blueBits,
882 sourceEffectiveFormat->blueBits) ||
883 !EqualOrFirstZero(textureInternalFormatInfo.alphaBits,
884 sourceEffectiveFormat->alphaBits))
Geoff Lang5d601382014-07-22 15:14:06 -0400885 {
886 return false;
887 }
888 }
889
890
891 return true; // A conversion function exists, and no rule in the specification has precluded conversion
892 // between these formats.
893 }
894
895 return false;
896}
897
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500898bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
899 GLenum target,
900 GLint level,
901 GLenum internalformat,
902 bool isSubImage,
903 GLint xoffset,
904 GLint yoffset,
905 GLint zoffset,
906 GLint x,
907 GLint y,
908 GLsizei width,
909 GLsizei height,
910 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400911{
Jamie Madill560a8d82014-05-21 13:06:20 -0400912 GLenum textureInternalFormat;
913 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill6f38f822014-06-06 17:12:20 -0400914 xoffset, yoffset, zoffset, x, y, width, height,
915 border, &textureInternalFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400916 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400917 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400918 }
919
Jamie Madill51f40ec2016-06-15 14:06:00 -0400920 const auto &state = context->getGLState();
921 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
922 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400923
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700924 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400925 {
Jamie Madill437fa652016-05-03 15:13:24 -0400926 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400927 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400928 }
929
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700930 if (readFramebufferID != 0 && framebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400931 {
Jamie Madill437fa652016-05-03 15:13:24 -0400932 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400933 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400934 }
935
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400936 const gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400937 GLenum colorbufferInternalFormat = source->getInternalFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400938
939 if (isSubImage)
940 {
Geoff Lang5d601382014-07-22 15:14:06 -0400941 if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat,
Jamie Madillc29968b2016-01-20 11:17:23 -0500942 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400943 {
Jamie Madill437fa652016-05-03 15:13:24 -0400944 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400945 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400946 }
947 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400948 else
949 {
Geoff Lang5d601382014-07-22 15:14:06 -0400950 if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat,
Jamie Madillc29968b2016-01-20 11:17:23 -0500951 readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400952 {
Jamie Madill437fa652016-05-03 15:13:24 -0400953 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400954 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400955 }
956 }
957
Geoff Lang784a8fd2013-09-24 12:33:16 -0400958 // If width or height is zero, it is a no-op. Return false without setting an error.
959 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400960}
961
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500962bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
963 GLenum target,
964 GLint level,
965 GLenum internalformat,
966 bool isSubImage,
967 GLint xoffset,
968 GLint yoffset,
969 GLint zoffset,
970 GLint x,
971 GLint y,
972 GLsizei width,
973 GLsizei height,
974 GLint border)
975{
976 if (!ValidTexture2DDestinationTarget(context, target))
977 {
Jamie Madill437fa652016-05-03 15:13:24 -0400978 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500979 return false;
980 }
981
982 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
983 xoffset, yoffset, zoffset, x, y, width, height,
984 border);
985}
986
987bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
988 GLenum target,
989 GLint level,
990 GLenum internalformat,
991 bool isSubImage,
992 GLint xoffset,
993 GLint yoffset,
994 GLint zoffset,
995 GLint x,
996 GLint y,
997 GLsizei width,
998 GLsizei height,
999 GLint border)
1000{
1001 if (!ValidTexture3DDestinationTarget(context, target))
1002 {
Jamie Madill437fa652016-05-03 15:13:24 -04001003 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001004 return false;
1005 }
1006
1007 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
1008 xoffset, yoffset, zoffset, x, y, width, height,
1009 border);
1010}
1011
1012bool ValidateES3TexStorageParametersBase(Context *context,
1013 GLenum target,
1014 GLsizei levels,
1015 GLenum internalformat,
1016 GLsizei width,
1017 GLsizei height,
1018 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001019{
1020 if (width < 1 || height < 1 || depth < 1 || levels < 1)
1021 {
Jamie Madill437fa652016-05-03 15:13:24 -04001022 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001023 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001024 }
1025
Geoff Langb92c1332015-09-04 12:54:55 -04001026 GLsizei maxDim = std::max(width, height);
1027 if (target != GL_TEXTURE_2D_ARRAY)
1028 {
1029 maxDim = std::max(maxDim, depth);
1030 }
1031
1032 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001033 {
Jamie Madill437fa652016-05-03 15:13:24 -04001034 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001035 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001036 }
1037
Geoff Langaae65a42014-05-26 12:43:44 -04001038 const gl::Caps &caps = context->getCaps();
1039
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001040 switch (target)
1041 {
1042 case GL_TEXTURE_2D:
1043 {
Geoff Langaae65a42014-05-26 12:43:44 -04001044 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1045 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001046 {
Jamie Madill437fa652016-05-03 15:13:24 -04001047 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001048 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001049 }
1050 }
1051 break;
1052
Geoff Lang01c21d22013-09-24 11:52:16 -04001053 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001054 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001055 if (width != height)
1056 {
Jamie Madill437fa652016-05-03 15:13:24 -04001057 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001058 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001059 }
1060
Geoff Langaae65a42014-05-26 12:43:44 -04001061 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
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 case GL_TEXTURE_3D:
1070 {
Geoff Langaae65a42014-05-26 12:43:44 -04001071 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
1072 static_cast<GLuint>(height) > caps.max3DTextureSize ||
1073 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001074 {
Jamie Madill437fa652016-05-03 15:13:24 -04001075 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001076 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001077 }
1078 }
1079 break;
1080
1081 case GL_TEXTURE_2D_ARRAY:
1082 {
Geoff Langaae65a42014-05-26 12:43:44 -04001083 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1084 static_cast<GLuint>(height) > caps.max2DTextureSize ||
1085 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001086 {
Jamie Madill437fa652016-05-03 15:13:24 -04001087 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001088 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001089 }
1090 }
1091 break;
1092
1093 default:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001094 UNREACHABLE();
Geoff Langb1196682014-07-23 13:47:29 -04001095 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001096 }
1097
Geoff Lang691e58c2014-12-19 17:03:25 -05001098 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001099 if (!texture || texture->id() == 0)
1100 {
Jamie Madill437fa652016-05-03 15:13:24 -04001101 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001102 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001103 }
1104
Geoff Lang69cce582015-09-17 13:20:36 -04001105 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001106 {
Jamie Madill437fa652016-05-03 15:13:24 -04001107 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001108 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001109 }
1110
Geoff Lang5d601382014-07-22 15:14:06 -04001111 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1112 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001113 {
Jamie Madill437fa652016-05-03 15:13:24 -04001114 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001115 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001116 }
1117
Geoff Lang5d601382014-07-22 15:14:06 -04001118 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001119 {
Jamie Madill437fa652016-05-03 15:13:24 -04001120 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001121 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001122 }
1123
1124 return true;
1125}
1126
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001127bool ValidateES3TexStorage2DParameters(Context *context,
1128 GLenum target,
1129 GLsizei levels,
1130 GLenum internalformat,
1131 GLsizei width,
1132 GLsizei height,
1133 GLsizei depth)
1134{
1135 if (!ValidTexture2DTarget(context, target))
1136 {
Jamie Madill437fa652016-05-03 15:13:24 -04001137 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001138 return false;
1139 }
1140
1141 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1142 height, depth);
1143}
1144
1145bool ValidateES3TexStorage3DParameters(Context *context,
1146 GLenum target,
1147 GLsizei levels,
1148 GLenum internalformat,
1149 GLsizei width,
1150 GLsizei height,
1151 GLsizei depth)
1152{
1153 if (!ValidTexture3DTarget(context, target))
1154 {
Jamie Madill437fa652016-05-03 15:13:24 -04001155 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001156 return false;
1157 }
1158
1159 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1160 height, depth);
1161}
1162
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001163bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1164{
1165 if (context->getClientVersion() < 3)
1166 {
Jamie Madill437fa652016-05-03 15:13:24 -04001167 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001168 return false;
1169 }
1170
1171 return ValidateBeginQueryBase(context, target, id);
1172}
1173
1174bool ValidateEndQuery(gl::Context *context, GLenum target)
1175{
1176 if (context->getClientVersion() < 3)
1177 {
Jamie Madill437fa652016-05-03 15:13:24 -04001178 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001179 return false;
1180 }
1181
1182 return ValidateEndQueryBase(context, target);
1183}
1184
1185bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1186{
1187 if (context->getClientVersion() < 3)
1188 {
Jamie Madill437fa652016-05-03 15:13:24 -04001189 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001190 return false;
1191 }
1192
1193 return ValidateGetQueryivBase(context, target, pname);
1194}
1195
1196bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1197{
1198 if (context->getClientVersion() < 3)
1199 {
Jamie Madill437fa652016-05-03 15:13:24 -04001200 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001201 return false;
1202 }
1203
1204 return ValidateGetQueryObjectValueBase(context, id, pname);
1205}
1206
Geoff Langb1196682014-07-23 13:47:29 -04001207bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
Jamie Madill570f7c82014-07-03 10:38:54 -04001208 GLuint texture, GLint level, GLint layer)
1209{
1210 if (context->getClientVersion() < 3)
1211 {
Jamie Madill437fa652016-05-03 15:13:24 -04001212 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001213 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001214 }
1215
Jamie Madill55ec3b12014-07-03 10:38:57 -04001216 if (layer < 0)
1217 {
Jamie Madill437fa652016-05-03 15:13:24 -04001218 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001219 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001220 }
1221
1222 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1223 {
1224 return false;
1225 }
1226
1227 const gl::Caps &caps = context->getCaps();
1228 if (texture != 0)
1229 {
1230 gl::Texture *tex = context->getTexture(texture);
1231 ASSERT(tex);
1232
1233 switch (tex->getTarget())
1234 {
1235 case GL_TEXTURE_2D_ARRAY:
1236 {
1237 if (level > gl::log2(caps.max2DTextureSize))
1238 {
Jamie Madill437fa652016-05-03 15:13:24 -04001239 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001240 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001241 }
1242
1243 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1244 {
Jamie Madill437fa652016-05-03 15:13:24 -04001245 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001246 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001247 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001248 }
1249 break;
1250
1251 case GL_TEXTURE_3D:
1252 {
1253 if (level > gl::log2(caps.max3DTextureSize))
1254 {
Jamie Madill437fa652016-05-03 15:13:24 -04001255 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001256 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001257 }
1258
1259 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1260 {
Jamie Madill437fa652016-05-03 15:13:24 -04001261 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001262 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001263 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001264 }
1265 break;
1266
1267 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001268 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001269 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001270 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001271
1272 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(tex->getTarget(), level));
1273 if (internalFormatInfo.compressed)
1274 {
Jamie Madill437fa652016-05-03 15:13:24 -04001275 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001276 return false;
1277 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001278 }
1279
1280 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001281}
1282
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001283bool ValidES3ReadFormatType(ValidationContext *context,
1284 GLenum internalFormat,
1285 GLenum format,
1286 GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001287{
Geoff Lang5d601382014-07-22 15:14:06 -04001288 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
1289
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001290 switch (format)
1291 {
1292 case GL_RGBA:
1293 switch (type)
1294 {
1295 case GL_UNSIGNED_BYTE:
1296 break;
Vincent Lang25ab4512016-05-13 18:13:59 +02001297 case GL_UNSIGNED_SHORT:
1298 if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
1299 internalFormatInfo.type != GL_UNSIGNED_SHORT)
1300 {
1301 return false;
1302 }
1303 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001304 case GL_UNSIGNED_INT_2_10_10_10_REV:
1305 if (internalFormat != GL_RGB10_A2)
1306 {
1307 return false;
1308 }
1309 break;
Geoff Lang1ec57f82013-10-16 11:43:23 -04001310 case GL_FLOAT:
Geoff Lang5d601382014-07-22 15:14:06 -04001311 if (internalFormatInfo.componentType != GL_FLOAT)
Geoff Lang1ec57f82013-10-16 11:43:23 -04001312 {
1313 return false;
1314 }
1315 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001316 default:
1317 return false;
1318 }
1319 break;
1320 case GL_RGBA_INTEGER:
1321 switch (type)
1322 {
1323 case GL_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001324 if (internalFormatInfo.componentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001325 {
1326 return false;
1327 }
1328 break;
1329 case GL_UNSIGNED_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001330 if (internalFormatInfo.componentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001331 {
1332 return false;
1333 }
1334 break;
1335 default:
1336 return false;
1337 }
1338 break;
1339 case GL_BGRA_EXT:
1340 switch (type)
1341 {
1342 case GL_UNSIGNED_BYTE:
1343 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1344 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1345 break;
1346 default:
1347 return false;
1348 }
1349 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001350 case GL_RG_EXT:
1351 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001352 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001353 {
1354 return false;
1355 }
1356 switch (type)
1357 {
1358 case GL_UNSIGNED_BYTE:
1359 break;
Vincent Lang25ab4512016-05-13 18:13:59 +02001360 case GL_UNSIGNED_SHORT:
1361 if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
1362 internalFormatInfo.type != GL_UNSIGNED_SHORT)
1363 {
1364 return false;
1365 }
1366 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001367 default:
1368 return false;
1369 }
1370 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001371 default:
1372 return false;
1373 }
1374 return true;
1375}
1376
Corentin Walleze0902642014-11-04 12:32:15 -08001377bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
1378 GLenum internalformat, GLsizei width, GLsizei height)
1379{
1380 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
1381 {
1382 return false;
1383 }
1384
1385 //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.
1386 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1387 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
1388 {
Jamie Madill437fa652016-05-03 15:13:24 -04001389 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -08001390 return false;
1391 }
1392
1393 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
1394 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1395 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1396 {
Jamie Madill437fa652016-05-03 15:13:24 -04001397 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001398 Error(GL_INVALID_OPERATION,
1399 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001400 return false;
1401 }
1402
1403 return true;
1404}
1405
Austin Kinross08332632015-05-05 13:35:47 -07001406bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
1407 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001408{
Austin Kinross08332632015-05-05 13:35:47 -07001409 if (context->getClientVersion() < 3)
1410 {
Jamie Madill437fa652016-05-03 15:13:24 -04001411 context->handleError(
1412 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001413 return false;
1414 }
1415
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001416 bool defaultFramebuffer = false;
1417
1418 switch (target)
1419 {
1420 case GL_DRAW_FRAMEBUFFER:
1421 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001422 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1423 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001424 case GL_READ_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001425 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1426 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001427 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001428 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001429 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001430 }
1431
Austin Kinross08332632015-05-05 13:35:47 -07001432 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001433}
1434
Jamie Madillc29968b2016-01-20 11:17:23 -05001435bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001436{
1437 if (context->getClientVersion() < 3)
1438 {
Jamie Madill437fa652016-05-03 15:13:24 -04001439 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001440 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001441 }
1442
Jamie Madill51f40ec2016-06-15 14:06:00 -04001443 if (context->getGLState().getDrawFramebuffer()->checkStatus(context->getContextState()) !=
1444 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001445 {
Jamie Madill437fa652016-05-03 15:13:24 -04001446 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001447 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001448 }
1449
1450 return true;
1451}
1452
Olli Etuaho71dfb362016-03-10 14:04:27 +02001453bool ValidateDrawRangeElements(Context *context,
1454 GLenum mode,
1455 GLuint start,
1456 GLuint end,
1457 GLsizei count,
1458 GLenum type,
1459 const GLvoid *indices,
1460 IndexRange *indexRange)
1461{
1462 if (context->getClientVersion() < 3)
1463 {
Jamie Madill437fa652016-05-03 15:13:24 -04001464 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001465 return false;
1466 }
1467
1468 if (end < start)
1469 {
Jamie Madill437fa652016-05-03 15:13:24 -04001470 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001471 return false;
1472 }
1473
1474 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1475 {
1476 return false;
1477 }
1478
1479 if (indexRange->end > end || indexRange->start < start)
1480 {
1481 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001482 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001483 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1484 return false;
1485 }
1486 return true;
1487}
1488
Geoff Langb1196682014-07-23 13:47:29 -04001489bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001490{
1491 if (context->getClientVersion() < 3)
1492 {
Jamie Madill437fa652016-05-03 15:13:24 -04001493 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001494 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001495 }
1496
Jamie Madill78f41802014-08-25 15:47:55 -04001497 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001498}
1499
Jamie Madillb885e572015-02-03 16:16:04 -05001500bool ValidateReadBuffer(Context *context, GLenum src)
1501{
1502 if (context->getClientVersion() < 3)
1503 {
Jamie Madill437fa652016-05-03 15:13:24 -04001504 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001505 return false;
1506 }
1507
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001508 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001509
1510 if (readFBO == nullptr)
1511 {
Jamie Madill437fa652016-05-03 15:13:24 -04001512 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001513 return false;
1514 }
1515
1516 if (src == GL_NONE)
1517 {
1518 return true;
1519 }
1520
Olli Etuaho84c9f592016-03-09 14:37:25 +02001521 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001522 {
Jamie Madill437fa652016-05-03 15:13:24 -04001523 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001524 return false;
1525 }
1526
1527 if (readFBO->id() == 0)
1528 {
1529 if (src != GL_BACK)
1530 {
1531 const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001532 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001533 return false;
1534 }
1535 }
1536 else
1537 {
1538 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1539
1540 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1541 {
1542 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001543 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001544 return false;
1545 }
1546 }
1547
1548 return true;
1549}
1550
Jamie Madill86af3d22015-07-21 15:14:07 -04001551bool ValidateCompressedTexImage3D(Context *context,
1552 GLenum target,
1553 GLint level,
1554 GLenum internalformat,
1555 GLsizei width,
1556 GLsizei height,
1557 GLsizei depth,
1558 GLint border,
1559 GLsizei imageSize,
1560 const GLvoid *data)
1561{
1562 if (context->getClientVersion() < 3)
1563 {
Jamie Madill437fa652016-05-03 15:13:24 -04001564 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001565 return false;
1566 }
1567
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001568 if (!ValidTextureTarget(context, target))
1569 {
1570 context->handleError(Error(GL_INVALID_ENUM));
1571 return false;
1572 }
1573
Jamie Madille2e406c2016-06-02 13:04:10 -04001574 // Validate image size
1575 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1576 {
1577 context->handleError(Error(GL_INVALID_VALUE));
1578 return false;
1579 }
1580
Jamie Madill86af3d22015-07-21 15:14:07 -04001581 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001582 if (!formatInfo.compressed)
1583 {
1584 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1585 return false;
1586 }
1587
Jamie Madill513558d2016-06-02 13:04:11 -04001588 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001589 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001590 if (blockSizeOrErr.isError())
1591 {
Jamie Madill513558d2016-06-02 13:04:11 -04001592 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001593 return false;
1594 }
1595 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001596 {
Jamie Madill437fa652016-05-03 15:13:24 -04001597 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001598 return false;
1599 }
1600
1601 // 3D texture target validation
1602 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1603 {
Jamie Madill437fa652016-05-03 15:13:24 -04001604 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001605 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1606 return false;
1607 }
1608
1609 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001610 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
1611 0, width, height, depth, border, GL_NONE, GL_NONE, data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001612 {
1613 return false;
1614 }
1615
1616 return true;
1617}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001618
1619bool ValidateBindVertexArray(Context *context, GLuint array)
1620{
1621 if (context->getClientVersion() < 3)
1622 {
Jamie Madill437fa652016-05-03 15:13:24 -04001623 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001624 return false;
1625 }
1626
1627 return ValidateBindVertexArrayBase(context, array);
1628}
1629
Austin Kinrossbc781f32015-10-26 09:27:38 -07001630bool ValidateIsVertexArray(Context *context)
1631{
1632 if (context->getClientVersion() < 3)
1633 {
Jamie Madill437fa652016-05-03 15:13:24 -04001634 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001635 return false;
1636 }
1637
1638 return true;
1639}
Geoff Langc5629752015-12-07 16:29:04 -05001640
1641bool ValidateProgramBinary(Context *context,
1642 GLuint program,
1643 GLenum binaryFormat,
1644 const void *binary,
1645 GLint length)
1646{
1647 if (context->getClientVersion() < 3)
1648 {
Jamie Madill437fa652016-05-03 15:13:24 -04001649 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001650 return false;
1651 }
1652
1653 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1654}
1655
1656bool ValidateGetProgramBinary(Context *context,
1657 GLuint program,
1658 GLsizei bufSize,
1659 GLsizei *length,
1660 GLenum *binaryFormat,
1661 void *binary)
1662{
1663 if (context->getClientVersion() < 3)
1664 {
Jamie Madill437fa652016-05-03 15:13:24 -04001665 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001666 return false;
1667 }
1668
1669 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1670}
1671
Olli Etuahof0fee072016-03-30 15:11:58 +03001672bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001673{
1674 if (context->getClientVersion() < 3)
1675 {
Jamie Madill437fa652016-05-03 15:13:24 -04001676 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001677 return false;
1678 }
1679
1680 if (GetValidProgram(context, program) == nullptr)
1681 {
1682 return false;
1683 }
1684
1685 switch (pname)
1686 {
1687 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001688 if (value != GL_FALSE && value != GL_TRUE)
1689 {
Jamie Madill437fa652016-05-03 15:13:24 -04001690 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001691 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1692 return false;
1693 }
Geoff Langc5629752015-12-07 16:29:04 -05001694 break;
1695
1696 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001697 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001698 return false;
1699 }
1700
1701 return true;
1702}
Jamie Madillc29968b2016-01-20 11:17:23 -05001703
1704bool ValidateBlitFramebuffer(Context *context,
1705 GLint srcX0,
1706 GLint srcY0,
1707 GLint srcX1,
1708 GLint srcY1,
1709 GLint dstX0,
1710 GLint dstY0,
1711 GLint dstX1,
1712 GLint dstY1,
1713 GLbitfield mask,
1714 GLenum filter)
1715{
1716 if (context->getClientVersion() < 3)
1717 {
Jamie Madill437fa652016-05-03 15:13:24 -04001718 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001719 return false;
1720 }
1721
1722 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1723 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001724}
Jamie Madillc29968b2016-01-20 11:17:23 -05001725
1726bool ValidateClearBufferiv(ValidationContext *context,
1727 GLenum buffer,
1728 GLint drawbuffer,
1729 const GLint *value)
1730{
1731 switch (buffer)
1732 {
1733 case GL_COLOR:
1734 if (drawbuffer < 0 ||
1735 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1736 {
Jamie Madill437fa652016-05-03 15:13:24 -04001737 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001738 return false;
1739 }
1740 break;
1741
1742 case GL_STENCIL:
1743 if (drawbuffer != 0)
1744 {
Jamie Madill437fa652016-05-03 15:13:24 -04001745 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001746 return false;
1747 }
1748 break;
1749
1750 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001751 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001752 return false;
1753 }
1754
1755 return ValidateClearBuffer(context);
1756}
1757
1758bool ValidateClearBufferuiv(ValidationContext *context,
1759 GLenum buffer,
1760 GLint drawbuffer,
1761 const GLuint *value)
1762{
1763 switch (buffer)
1764 {
1765 case GL_COLOR:
1766 if (drawbuffer < 0 ||
1767 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1768 {
Jamie Madill437fa652016-05-03 15:13:24 -04001769 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001770 return false;
1771 }
1772 break;
1773
1774 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001775 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001776 return false;
1777 }
1778
1779 return ValidateClearBuffer(context);
1780}
1781
1782bool ValidateClearBufferfv(ValidationContext *context,
1783 GLenum buffer,
1784 GLint drawbuffer,
1785 const GLfloat *value)
1786{
1787 switch (buffer)
1788 {
1789 case GL_COLOR:
1790 if (drawbuffer < 0 ||
1791 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1792 {
Jamie Madill437fa652016-05-03 15:13:24 -04001793 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001794 return false;
1795 }
1796 break;
1797
1798 case GL_DEPTH:
1799 if (drawbuffer != 0)
1800 {
Jamie Madill437fa652016-05-03 15:13:24 -04001801 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001802 return false;
1803 }
1804 break;
1805
1806 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001807 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001808 return false;
1809 }
1810
1811 return ValidateClearBuffer(context);
1812}
1813
1814bool ValidateClearBufferfi(ValidationContext *context,
1815 GLenum buffer,
1816 GLint drawbuffer,
1817 GLfloat depth,
1818 GLint stencil)
1819{
1820 switch (buffer)
1821 {
1822 case GL_DEPTH_STENCIL:
1823 if (drawbuffer != 0)
1824 {
Jamie Madill437fa652016-05-03 15:13:24 -04001825 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001826 return false;
1827 }
1828 break;
1829
1830 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001831 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001832 return false;
1833 }
1834
1835 return ValidateClearBuffer(context);
1836}
1837
1838bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1839{
1840 if (context->getClientVersion() < 3)
1841 {
Jamie Madill437fa652016-05-03 15:13:24 -04001842 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001843 return false;
1844 }
1845
1846 return ValidateDrawBuffersBase(context, n, bufs);
1847}
1848
1849bool ValidateCopyTexSubImage3D(Context *context,
1850 GLenum target,
1851 GLint level,
1852 GLint xoffset,
1853 GLint yoffset,
1854 GLint zoffset,
1855 GLint x,
1856 GLint y,
1857 GLsizei width,
1858 GLsizei height)
1859{
1860 if (context->getClientVersion() < 3)
1861 {
Jamie Madill437fa652016-05-03 15:13:24 -04001862 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001863 return false;
1864 }
1865
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001866 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1867 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001868}
1869
Jamie Madill73a84962016-02-12 09:27:23 -05001870bool ValidateTexImage3D(Context *context,
1871 GLenum target,
1872 GLint level,
1873 GLint internalformat,
1874 GLsizei width,
1875 GLsizei height,
1876 GLsizei depth,
1877 GLint border,
1878 GLenum format,
1879 GLenum type,
1880 const GLvoid *pixels)
1881{
1882 if (context->getClientVersion() < 3)
1883 {
Jamie Madill437fa652016-05-03 15:13:24 -04001884 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001885 return false;
1886 }
1887
1888 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1889 0, 0, width, height, depth, border, format, type,
1890 pixels);
1891}
1892
1893bool ValidateTexSubImage3D(Context *context,
1894 GLenum target,
1895 GLint level,
1896 GLint xoffset,
1897 GLint yoffset,
1898 GLint zoffset,
1899 GLsizei width,
1900 GLsizei height,
1901 GLsizei depth,
1902 GLenum format,
1903 GLenum type,
1904 const GLvoid *pixels)
1905{
1906 if (context->getClientVersion() < 3)
1907 {
Jamie Madill437fa652016-05-03 15:13:24 -04001908 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001909 return false;
1910 }
1911
1912 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1913 yoffset, zoffset, width, height, depth, 0, format, type,
1914 pixels);
1915}
1916
1917bool ValidateCompressedTexSubImage3D(Context *context,
1918 GLenum target,
1919 GLint level,
1920 GLint xoffset,
1921 GLint yoffset,
1922 GLint zoffset,
1923 GLsizei width,
1924 GLsizei height,
1925 GLsizei depth,
1926 GLenum format,
1927 GLsizei imageSize,
1928 const GLvoid *data)
1929{
1930 if (context->getClientVersion() < 3)
1931 {
Jamie Madill437fa652016-05-03 15:13:24 -04001932 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001933 return false;
1934 }
1935
1936 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001937 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001938 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001939 if (blockSizeOrErr.isError())
1940 {
1941 context->handleError(blockSizeOrErr.getError());
1942 return false;
1943 }
1944 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001945 {
Jamie Madill437fa652016-05-03 15:13:24 -04001946 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001947 return false;
1948 }
1949
1950 if (!data)
1951 {
Jamie Madill437fa652016-05-03 15:13:24 -04001952 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001953 return false;
1954 }
1955
1956 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
1957 width, height, depth, 0, GL_NONE, GL_NONE, data);
1958}
1959
Olli Etuaho41997e72016-03-10 13:38:39 +02001960bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1961{
1962 return ValidateGenOrDeleteES3(context, n);
1963}
1964
1965bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1966{
1967 return ValidateGenOrDeleteES3(context, n);
1968}
1969
1970bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1971{
1972 return ValidateGenOrDeleteCountES3(context, count);
1973}
1974
1975bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1976{
1977 return ValidateGenOrDeleteCountES3(context, count);
1978}
1979
1980bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1981{
1982 return ValidateGenOrDeleteES3(context, n);
1983}
1984
1985bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1986{
1987 if (!ValidateGenOrDeleteES3(context, n))
1988 {
1989 return false;
1990 }
1991 for (GLint i = 0; i < n; ++i)
1992 {
1993 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1994 if (transformFeedback != nullptr && transformFeedback->isActive())
1995 {
1996 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001997 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001998 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1999 return false;
2000 }
2001 }
2002 return true;
2003}
2004
2005bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2006{
2007 return ValidateGenOrDeleteES3(context, n);
2008}
2009
2010bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2011{
2012 return ValidateGenOrDeleteES3(context, n);
2013}
2014
2015bool ValidateGenOrDeleteES3(Context *context, GLint n)
2016{
2017 if (context->getClientVersion() < 3)
2018 {
Jamie Madill437fa652016-05-03 15:13:24 -04002019 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02002020 return false;
2021 }
2022 return ValidateGenOrDelete(context, n);
2023}
2024
2025bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
2026{
2027 if (context->getClientVersion() < 3)
2028 {
Jamie Madill437fa652016-05-03 15:13:24 -04002029 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02002030 return false;
2031 }
2032 if (count < 0)
2033 {
Jamie Madill437fa652016-05-03 15:13:24 -04002034 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02002035 return false;
2036 }
2037 return true;
2038}
2039
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002040bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2041{
2042 if (context->getClientVersion() < 3)
2043 {
Jamie Madill437fa652016-05-03 15:13:24 -04002044 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002045 return false;
2046 }
2047 switch (primitiveMode)
2048 {
2049 case GL_TRIANGLES:
2050 case GL_LINES:
2051 case GL_POINTS:
2052 break;
2053
2054 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002055 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002056 return false;
2057 }
2058
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002059 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002060 ASSERT(transformFeedback != nullptr);
2061
2062 if (transformFeedback->isActive())
2063 {
Jamie Madill437fa652016-05-03 15:13:24 -04002064 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002065 return false;
2066 }
2067 return true;
2068}
2069
Olli Etuaho37477912016-03-30 14:54:40 +03002070bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
2071{
2072 if (context->getClientVersion() < 3)
2073 {
Jamie Madill437fa652016-05-03 15:13:24 -04002074 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho37477912016-03-30 14:54:40 +03002075 return false;
2076 }
2077
2078 if (!context->isSampler(sampler))
2079 {
Jamie Madill437fa652016-05-03 15:13:24 -04002080 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho37477912016-03-30 14:54:40 +03002081 return false;
2082 }
2083
2084 if (!ValidateSamplerObjectParameter(context, pname))
2085 {
2086 return false;
2087 }
2088
Ian Ewellbda75592016-04-18 17:25:54 -04002089 if (!ValidateTexParamParameters(context, GL_TEXTURE_2D, pname, param))
Olli Etuaho37477912016-03-30 14:54:40 +03002090 {
2091 return false;
2092 }
2093 return true;
2094}
2095
2096bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
2097{
2098 // The only float parameters are MIN_LOD and MAX_LOD. For these any value is permissible, so
2099 // ValidateSamplerParameteri can be used for validation here.
2100 return ValidateSamplerParameteri(context, sampler, pname, static_cast<GLint>(param));
2101}
2102
Olli Etuaho4f667482016-03-30 15:56:35 +03002103bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
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 ValidateGetBufferPointervBase(context, target, pname, params);
2112}
2113
2114bool ValidateUnmapBuffer(Context *context, GLenum target)
2115{
2116 if (context->getClientVersion() < 3)
2117 {
Jamie Madill437fa652016-05-03 15:13:24 -04002118 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03002119 return false;
2120 }
2121
2122 return ValidateUnmapBufferBase(context, target);
2123}
2124
2125bool ValidateMapBufferRange(Context *context,
2126 GLenum target,
2127 GLintptr offset,
2128 GLsizeiptr length,
2129 GLbitfield access)
2130{
2131 if (context->getClientVersion() < 3)
2132 {
Jamie Madill437fa652016-05-03 15:13:24 -04002133 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002134 return false;
2135 }
2136
2137 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2138}
2139
2140bool ValidateFlushMappedBufferRange(Context *context,
2141 GLenum target,
2142 GLintptr offset,
2143 GLsizeiptr length)
2144{
2145 if (context->getClientVersion() < 3)
2146 {
Jamie Madill437fa652016-05-03 15:13:24 -04002147 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002148 return false;
2149 }
2150
2151 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2152}
2153
Jamie Madillc29968b2016-01-20 11:17:23 -05002154} // namespace gl