blob: acdffca7844bca089d970d2d70bbbe9b307ee2e8 [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
Shannon Woods53a94a82014-06-24 15:20:36 -0400470 gl::Buffer *pixelUnpackBuffer = context->getState().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.
475 size_t widthSize = static_cast<size_t>(width);
476 size_t heightSize = static_cast<size_t>(height);
477 size_t depthSize = static_cast<size_t>(depth);
Geoff Lang5d601382014-07-22 15:14:06 -0400478 GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type);
Jamie Madill6f38f822014-06-06 17:12:20 -0400479
Jamie Madille2e406c2016-06-02 13:04:10 -0400480 CheckedNumeric<size_t> checkedBytes(gl::GetInternalFormatInfo(sizedFormat).pixelBytes);
481 checkedBytes *= widthSize;
482 checkedBytes *= heightSize;
483 checkedBytes *= depthSize;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400484
Jamie Madille2e406c2016-06-02 13:04:10 -0400485 if (!checkedBytes.IsValid())
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400486 {
487 // Overflow past the end of the buffer
Jamie Madille2e406c2016-06-02 13:04:10 -0400488 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow"));
Geoff Langb1196682014-07-23 13:47:29 -0400489 return false;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400490 }
491
Jamie Madillc751d1e2014-10-21 17:46:29 -0400492 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
Jamie Madill513558d2016-06-02 13:04:11 -0400493 auto copyBytesOrErr = formatInfo.computeBlockSize(type, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -0400494 if (copyBytesOrErr.isError())
495 {
496 context->handleError(copyBytesOrErr.getError());
497 return false;
498 }
499 CheckedNumeric<size_t> checkedCopyBytes(copyBytesOrErr.getResult());
500 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
501 checkedCopyBytes += checkedOffset;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400502
Jamie Madille2e406c2016-06-02 13:04:10 -0400503 if (!checkedCopyBytes.IsValid() ||
504 (checkedCopyBytes.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400505 {
506 // Overflow past the end of the buffer
Jamie Madill437fa652016-05-03 15:13:24 -0400507 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400508 return false;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400509 }
510
511 // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
512 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400513 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400514 {
Jamie Madillc751d1e2014-10-21 17:46:29 -0400515 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
516
Jamie Madille2e406c2016-06-02 13:04:10 -0400517 if ((checkedOffset.ValueOrDie() % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400518 {
Jamie Madill437fa652016-05-03 15:13:24 -0400519 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400520 return false;
521 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400522 }
523
Jamie Madill7a5f7382014-03-05 15:01:24 -0500524 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700525 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500526 {
Jamie Madill437fa652016-05-03 15:13:24 -0400527 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400528 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500529 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400530 }
531
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400532 return true;
533}
534
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500535bool ValidateES3TexImage2DParameters(Context *context,
536 GLenum target,
537 GLint level,
538 GLenum internalformat,
539 bool isCompressed,
540 bool isSubImage,
541 GLint xoffset,
542 GLint yoffset,
543 GLint zoffset,
544 GLsizei width,
545 GLsizei height,
546 GLsizei depth,
547 GLint border,
548 GLenum format,
549 GLenum type,
550 const GLvoid *pixels)
551{
552 if (!ValidTexture2DDestinationTarget(context, target))
553 {
Jamie Madill437fa652016-05-03 15:13:24 -0400554 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500555 return false;
556 }
557
558 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
559 isSubImage, xoffset, yoffset, zoffset, width, height,
560 depth, border, format, type, pixels);
561}
562
563bool ValidateES3TexImage3DParameters(Context *context,
564 GLenum target,
565 GLint level,
566 GLenum internalformat,
567 bool isCompressed,
568 bool isSubImage,
569 GLint xoffset,
570 GLint yoffset,
571 GLint zoffset,
572 GLsizei width,
573 GLsizei height,
574 GLsizei depth,
575 GLint border,
576 GLenum format,
577 GLenum type,
578 const GLvoid *pixels)
579{
580 if (!ValidTexture3DDestinationTarget(context, target))
581 {
Jamie Madill437fa652016-05-03 15:13:24 -0400582 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500583 return false;
584 }
585
586 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
587 isSubImage, xoffset, yoffset, zoffset, width, height,
588 depth, border, format, type, pixels);
589}
590
Geoff Lang5d601382014-07-22 15:14:06 -0400591struct EffectiveInternalFormatInfo
592{
593 GLenum mEffectiveFormat;
594 GLenum mDestFormat;
595 GLuint mMinRedBits;
596 GLuint mMaxRedBits;
597 GLuint mMinGreenBits;
598 GLuint mMaxGreenBits;
599 GLuint mMinBlueBits;
600 GLuint mMaxBlueBits;
601 GLuint mMinAlphaBits;
602 GLuint mMaxAlphaBits;
603
604 EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits,
605 GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits,
606 GLuint minAlphaBits, GLuint maxAlphaBits)
607 : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits),
608 mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits),
609 mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits),
610 mMaxAlphaBits(maxAlphaBits) {};
611};
612
613typedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
614
615static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList()
616{
617 EffectiveInternalFormatList list;
618
619 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
620 // linear source buffer component sizes.
621 // | Source channel min/max sizes |
622 // Effective Internal Format | N/A | R | G | B | A |
623 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8));
624 list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0));
625 list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0));
626 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0));
627 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0));
628 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4));
629 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1));
630 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8));
631 list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2));
632
633 return list;
634}
635
636static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList()
637{
638 EffectiveInternalFormatList list;
639
640 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
641 // linear source buffer component sizes.
642 // | Source channel min/max sizes |
643 // Effective Internal Format | Dest Format | R | G | B | A |
644 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
645 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX));
646 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
647 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX));
648 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX));
649 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4));
650 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1));
651 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8));
652
653 return list;
654}
655
656static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
657 GLenum *outEffectiveFormat)
658{
659 const EffectiveInternalFormatList *list = NULL;
660 GLenum targetFormat = GL_NONE;
661
662 if (destFormat.pixelBytes > 0)
663 {
664 static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList();
665 list = &sizedList;
666 }
667 else
668 {
669 static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList();
670 list = &unsizedList;
671 targetFormat = destFormat.format;
672 }
673
674 for (size_t curFormat = 0; curFormat < list->size(); ++curFormat)
675 {
676 const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat);
677 if ((formatInfo.mDestFormat == targetFormat) &&
678 (formatInfo.mMinRedBits <= srcFormat.redBits && formatInfo.mMaxRedBits >= srcFormat.redBits) &&
679 (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) &&
680 (formatInfo.mMinBlueBits <= srcFormat.blueBits && formatInfo.mMaxBlueBits >= srcFormat.blueBits) &&
681 (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits))
682 {
683 *outEffectiveFormat = formatInfo.mEffectiveFormat;
684 return true;
685 }
686 }
687
688 return false;
689}
690
691struct CopyConversion
692{
693 GLenum mTextureFormat;
694 GLenum mFramebufferFormat;
695
696 CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
697 : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
698
699 bool operator<(const CopyConversion& other) const
700 {
701 return memcmp(this, &other, sizeof(CopyConversion)) < 0;
702 }
703};
704
705typedef std::set<CopyConversion> CopyConversionSet;
706
707static CopyConversionSet BuildValidES3CopyTexImageCombinations()
708{
709 CopyConversionSet set;
710
711 // From ES 3.0.1 spec, table 3.15
712 set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
713 set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
714 set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
715 set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
716 set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
717 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
718 set.insert(CopyConversion(GL_RED, GL_RED));
719 set.insert(CopyConversion(GL_RED, GL_RG));
720 set.insert(CopyConversion(GL_RED, GL_RGB));
721 set.insert(CopyConversion(GL_RED, GL_RGBA));
722 set.insert(CopyConversion(GL_RG, GL_RG));
723 set.insert(CopyConversion(GL_RG, GL_RGB));
724 set.insert(CopyConversion(GL_RG, GL_RGBA));
725 set.insert(CopyConversion(GL_RGB, GL_RGB));
726 set.insert(CopyConversion(GL_RGB, GL_RGBA));
727 set.insert(CopyConversion(GL_RGBA, GL_RGBA));
728
729 // Necessary for ANGLE back-buffers
730 set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
731 set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
732 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
733 set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
734 set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
735 set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
736 set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
737
738 set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
739 set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
740 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
741 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
742 set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
743 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
744 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
745 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
746 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
747 set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
748
749 return set;
750}
751
Corentin Wallez76287682016-04-25 09:23:38 -0400752static bool EqualOrFirstZero(GLuint first, GLuint second)
753{
754 return first == 0 || first == second;
755}
756
Geoff Lang5d601382014-07-22 15:14:06 -0400757static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle)
758{
759 const InternalFormat &textureInternalFormatInfo = GetInternalFormatInfo(textureInternalFormat);
760 const InternalFormat &framebufferInternalFormatInfo = GetInternalFormatInfo(frameBufferInternalFormat);
761
762 static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
763 if (conversionSet.find(CopyConversion(textureInternalFormatInfo.format, framebufferInternalFormatInfo.format)) != conversionSet.end())
764 {
765 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
766 // must both be signed, unsigned, or fixed point and both source and destinations
767 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
768 // conversion between fixed and floating point.
769
770 if ((textureInternalFormatInfo.colorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.colorEncoding == GL_SRGB))
771 {
772 return false;
773 }
774
775 if (((textureInternalFormatInfo.componentType == GL_INT) != (framebufferInternalFormatInfo.componentType == GL_INT )) ||
776 ((textureInternalFormatInfo.componentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.componentType == GL_UNSIGNED_INT)))
777 {
778 return false;
779 }
780
781 if ((textureInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
782 textureInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
783 textureInternalFormatInfo.componentType == GL_FLOAT) &&
784 !(framebufferInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
785 framebufferInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
786 framebufferInternalFormatInfo.componentType == GL_FLOAT))
787 {
788 return false;
789 }
790
791 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
792 // The effective internal format of the source buffer is determined with the following rules applied in order:
793 // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
794 // effective internal format is the source buffer's sized internal format.
795 // * If the source buffer is a texture that was created with an unsized base internal format, then the
796 // effective internal format is the source image array's effective internal format, as specified by table
797 // 3.12, which is determined from the <format> and <type> that were used when the source image array was
798 // specified by TexImage*.
799 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
800 // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
801 // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
802 // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
803 // is SRGB.
804 const InternalFormat *sourceEffectiveFormat = NULL;
805 if (readBufferHandle != 0)
806 {
807 // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
808 if (framebufferInternalFormatInfo.pixelBytes > 0)
809 {
810 sourceEffectiveFormat = &framebufferInternalFormatInfo;
811 }
812 else
813 {
814 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
815 // 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 -0500816 GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type);
817 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400818 }
819 }
820 else
821 {
822 // The effective internal format must be derived from the source framebuffer's channel sizes.
823 // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
824 if (framebufferInternalFormatInfo.colorEncoding == GL_LINEAR)
825 {
826 GLenum effectiveFormat;
827 if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat))
828 {
829 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
830 }
831 else
832 {
833 return false;
834 }
835 }
836 else if (framebufferInternalFormatInfo.colorEncoding == GL_SRGB)
837 {
838 // SRGB buffers can only be copied to sized format destinations according to table 3.18
839 if ((textureInternalFormatInfo.pixelBytes > 0) &&
840 (framebufferInternalFormatInfo.redBits >= 1 && framebufferInternalFormatInfo.redBits <= 8) &&
841 (framebufferInternalFormatInfo.greenBits >= 1 && framebufferInternalFormatInfo.greenBits <= 8) &&
842 (framebufferInternalFormatInfo.blueBits >= 1 && framebufferInternalFormatInfo.blueBits <= 8) &&
843 (framebufferInternalFormatInfo.alphaBits >= 1 && framebufferInternalFormatInfo.alphaBits <= 8))
844 {
845 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
846 }
847 else
848 {
849 return false;
850 }
851 }
852 else
853 {
854 UNREACHABLE();
855 return false;
856 }
857 }
858
859 if (textureInternalFormatInfo.pixelBytes > 0)
860 {
Corentin Wallez76287682016-04-25 09:23:38 -0400861 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination
862 // format is sized, component sizes of the source and destination formats must exactly
863 // match if the destination format exists.
864 if (!EqualOrFirstZero(textureInternalFormatInfo.redBits,
865 sourceEffectiveFormat->redBits) ||
866 !EqualOrFirstZero(textureInternalFormatInfo.greenBits,
867 sourceEffectiveFormat->greenBits) ||
868 !EqualOrFirstZero(textureInternalFormatInfo.blueBits,
869 sourceEffectiveFormat->blueBits) ||
870 !EqualOrFirstZero(textureInternalFormatInfo.alphaBits,
871 sourceEffectiveFormat->alphaBits))
Geoff Lang5d601382014-07-22 15:14:06 -0400872 {
873 return false;
874 }
875 }
876
877
878 return true; // A conversion function exists, and no rule in the specification has precluded conversion
879 // between these formats.
880 }
881
882 return false;
883}
884
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500885bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
886 GLenum target,
887 GLint level,
888 GLenum internalformat,
889 bool isSubImage,
890 GLint xoffset,
891 GLint yoffset,
892 GLint zoffset,
893 GLint x,
894 GLint y,
895 GLsizei width,
896 GLsizei height,
897 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400898{
Jamie Madill560a8d82014-05-21 13:06:20 -0400899 GLenum textureInternalFormat;
900 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill6f38f822014-06-06 17:12:20 -0400901 xoffset, yoffset, zoffset, x, y, width, height,
902 border, &textureInternalFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400903 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400904 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400905 }
906
Jamie Madillc29968b2016-01-20 11:17:23 -0500907 const auto &state = context->getState();
908 const gl::Framebuffer *framebuffer = state.getReadFramebuffer();
909 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400910
Geoff Lang748f74e2014-12-01 11:25:34 -0500911 if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400912 {
Jamie Madill437fa652016-05-03 15:13:24 -0400913 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400914 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400915 }
916
Jamie Madillc29968b2016-01-20 11:17:23 -0500917 if (readFramebufferID != 0 && framebuffer->getSamples(context->getData()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400918 {
Jamie Madill437fa652016-05-03 15:13:24 -0400919 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400920 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400921 }
922
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400923 const gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400924 GLenum colorbufferInternalFormat = source->getInternalFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400925
926 if (isSubImage)
927 {
Geoff Lang5d601382014-07-22 15:14:06 -0400928 if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat,
Jamie Madillc29968b2016-01-20 11:17:23 -0500929 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400930 {
Jamie Madill437fa652016-05-03 15:13:24 -0400931 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400932 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400933 }
934 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400935 else
936 {
Geoff Lang5d601382014-07-22 15:14:06 -0400937 if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat,
Jamie Madillc29968b2016-01-20 11:17:23 -0500938 readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400939 {
Jamie Madill437fa652016-05-03 15:13:24 -0400940 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400941 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400942 }
943 }
944
Geoff Lang784a8fd2013-09-24 12:33:16 -0400945 // If width or height is zero, it is a no-op. Return false without setting an error.
946 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400947}
948
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500949bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
950 GLenum target,
951 GLint level,
952 GLenum internalformat,
953 bool isSubImage,
954 GLint xoffset,
955 GLint yoffset,
956 GLint zoffset,
957 GLint x,
958 GLint y,
959 GLsizei width,
960 GLsizei height,
961 GLint border)
962{
963 if (!ValidTexture2DDestinationTarget(context, target))
964 {
Jamie Madill437fa652016-05-03 15:13:24 -0400965 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500966 return false;
967 }
968
969 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
970 xoffset, yoffset, zoffset, x, y, width, height,
971 border);
972}
973
974bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
975 GLenum target,
976 GLint level,
977 GLenum internalformat,
978 bool isSubImage,
979 GLint xoffset,
980 GLint yoffset,
981 GLint zoffset,
982 GLint x,
983 GLint y,
984 GLsizei width,
985 GLsizei height,
986 GLint border)
987{
988 if (!ValidTexture3DDestinationTarget(context, target))
989 {
Jamie Madill437fa652016-05-03 15:13:24 -0400990 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500991 return false;
992 }
993
994 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
995 xoffset, yoffset, zoffset, x, y, width, height,
996 border);
997}
998
999bool ValidateES3TexStorageParametersBase(Context *context,
1000 GLenum target,
1001 GLsizei levels,
1002 GLenum internalformat,
1003 GLsizei width,
1004 GLsizei height,
1005 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001006{
1007 if (width < 1 || height < 1 || depth < 1 || levels < 1)
1008 {
Jamie Madill437fa652016-05-03 15:13:24 -04001009 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001010 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001011 }
1012
Geoff Langb92c1332015-09-04 12:54:55 -04001013 GLsizei maxDim = std::max(width, height);
1014 if (target != GL_TEXTURE_2D_ARRAY)
1015 {
1016 maxDim = std::max(maxDim, depth);
1017 }
1018
1019 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001020 {
Jamie Madill437fa652016-05-03 15:13:24 -04001021 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001022 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001023 }
1024
Geoff Langaae65a42014-05-26 12:43:44 -04001025 const gl::Caps &caps = context->getCaps();
1026
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001027 switch (target)
1028 {
1029 case GL_TEXTURE_2D:
1030 {
Geoff Langaae65a42014-05-26 12:43:44 -04001031 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1032 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001033 {
Jamie Madill437fa652016-05-03 15:13:24 -04001034 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001035 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001036 }
1037 }
1038 break;
1039
Geoff Lang01c21d22013-09-24 11:52:16 -04001040 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001041 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001042 if (width != height)
1043 {
Jamie Madill437fa652016-05-03 15:13:24 -04001044 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001045 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001046 }
1047
Geoff Langaae65a42014-05-26 12:43:44 -04001048 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001049 {
Jamie Madill437fa652016-05-03 15:13:24 -04001050 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001051 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001052 }
1053 }
1054 break;
1055
1056 case GL_TEXTURE_3D:
1057 {
Geoff Langaae65a42014-05-26 12:43:44 -04001058 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
1059 static_cast<GLuint>(height) > caps.max3DTextureSize ||
1060 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001061 {
Jamie Madill437fa652016-05-03 15:13:24 -04001062 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001063 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001064 }
1065 }
1066 break;
1067
1068 case GL_TEXTURE_2D_ARRAY:
1069 {
Geoff Langaae65a42014-05-26 12:43:44 -04001070 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1071 static_cast<GLuint>(height) > caps.max2DTextureSize ||
1072 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001073 {
Jamie Madill437fa652016-05-03 15:13:24 -04001074 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001075 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001076 }
1077 }
1078 break;
1079
1080 default:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001081 UNREACHABLE();
Geoff Langb1196682014-07-23 13:47:29 -04001082 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001083 }
1084
Geoff Lang691e58c2014-12-19 17:03:25 -05001085 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001086 if (!texture || texture->id() == 0)
1087 {
Jamie Madill437fa652016-05-03 15:13:24 -04001088 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001089 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001090 }
1091
Geoff Lang69cce582015-09-17 13:20:36 -04001092 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001093 {
Jamie Madill437fa652016-05-03 15:13:24 -04001094 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001095 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001096 }
1097
Geoff Lang5d601382014-07-22 15:14:06 -04001098 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1099 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001100 {
Jamie Madill437fa652016-05-03 15:13:24 -04001101 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001102 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001103 }
1104
Geoff Lang5d601382014-07-22 15:14:06 -04001105 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001106 {
Jamie Madill437fa652016-05-03 15:13:24 -04001107 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001108 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001109 }
1110
1111 return true;
1112}
1113
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001114bool ValidateES3TexStorage2DParameters(Context *context,
1115 GLenum target,
1116 GLsizei levels,
1117 GLenum internalformat,
1118 GLsizei width,
1119 GLsizei height,
1120 GLsizei depth)
1121{
1122 if (!ValidTexture2DTarget(context, target))
1123 {
Jamie Madill437fa652016-05-03 15:13:24 -04001124 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001125 return false;
1126 }
1127
1128 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1129 height, depth);
1130}
1131
1132bool ValidateES3TexStorage3DParameters(Context *context,
1133 GLenum target,
1134 GLsizei levels,
1135 GLenum internalformat,
1136 GLsizei width,
1137 GLsizei height,
1138 GLsizei depth)
1139{
1140 if (!ValidTexture3DTarget(context, target))
1141 {
Jamie Madill437fa652016-05-03 15:13:24 -04001142 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001143 return false;
1144 }
1145
1146 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1147 height, depth);
1148}
1149
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001150bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1151{
1152 if (context->getClientVersion() < 3)
1153 {
Jamie Madill437fa652016-05-03 15:13:24 -04001154 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001155 return false;
1156 }
1157
1158 return ValidateBeginQueryBase(context, target, id);
1159}
1160
1161bool ValidateEndQuery(gl::Context *context, GLenum target)
1162{
1163 if (context->getClientVersion() < 3)
1164 {
Jamie Madill437fa652016-05-03 15:13:24 -04001165 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001166 return false;
1167 }
1168
1169 return ValidateEndQueryBase(context, target);
1170}
1171
1172bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1173{
1174 if (context->getClientVersion() < 3)
1175 {
Jamie Madill437fa652016-05-03 15:13:24 -04001176 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001177 return false;
1178 }
1179
1180 return ValidateGetQueryivBase(context, target, pname);
1181}
1182
1183bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1184{
1185 if (context->getClientVersion() < 3)
1186 {
Jamie Madill437fa652016-05-03 15:13:24 -04001187 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001188 return false;
1189 }
1190
1191 return ValidateGetQueryObjectValueBase(context, id, pname);
1192}
1193
Geoff Langb1196682014-07-23 13:47:29 -04001194bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
Jamie Madill570f7c82014-07-03 10:38:54 -04001195 GLuint texture, GLint level, GLint layer)
1196{
1197 if (context->getClientVersion() < 3)
1198 {
Jamie Madill437fa652016-05-03 15:13:24 -04001199 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001200 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001201 }
1202
Jamie Madill55ec3b12014-07-03 10:38:57 -04001203 if (layer < 0)
1204 {
Jamie Madill437fa652016-05-03 15:13:24 -04001205 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001206 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001207 }
1208
1209 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1210 {
1211 return false;
1212 }
1213
1214 const gl::Caps &caps = context->getCaps();
1215 if (texture != 0)
1216 {
1217 gl::Texture *tex = context->getTexture(texture);
1218 ASSERT(tex);
1219
1220 switch (tex->getTarget())
1221 {
1222 case GL_TEXTURE_2D_ARRAY:
1223 {
1224 if (level > gl::log2(caps.max2DTextureSize))
1225 {
Jamie Madill437fa652016-05-03 15:13:24 -04001226 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001227 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001228 }
1229
1230 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1231 {
Jamie Madill437fa652016-05-03 15:13:24 -04001232 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001233 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001234 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001235 }
1236 break;
1237
1238 case GL_TEXTURE_3D:
1239 {
1240 if (level > gl::log2(caps.max3DTextureSize))
1241 {
Jamie Madill437fa652016-05-03 15:13:24 -04001242 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001243 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001244 }
1245
1246 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1247 {
Jamie Madill437fa652016-05-03 15:13:24 -04001248 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001249 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001250 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001251 }
1252 break;
1253
1254 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001255 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001256 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001257 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001258
1259 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(tex->getTarget(), level));
1260 if (internalFormatInfo.compressed)
1261 {
Jamie Madill437fa652016-05-03 15:13:24 -04001262 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001263 return false;
1264 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001265 }
1266
1267 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001268}
1269
Geoff Langb1196682014-07-23 13:47:29 -04001270bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001271{
Geoff Lang5d601382014-07-22 15:14:06 -04001272 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
1273
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001274 switch (format)
1275 {
1276 case GL_RGBA:
1277 switch (type)
1278 {
1279 case GL_UNSIGNED_BYTE:
1280 break;
Vincent Lang25ab4512016-05-13 18:13:59 +02001281 case GL_UNSIGNED_SHORT:
1282 if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
1283 internalFormatInfo.type != GL_UNSIGNED_SHORT)
1284 {
1285 return false;
1286 }
1287 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001288 case GL_UNSIGNED_INT_2_10_10_10_REV:
1289 if (internalFormat != GL_RGB10_A2)
1290 {
1291 return false;
1292 }
1293 break;
Geoff Lang1ec57f82013-10-16 11:43:23 -04001294 case GL_FLOAT:
Geoff Lang5d601382014-07-22 15:14:06 -04001295 if (internalFormatInfo.componentType != GL_FLOAT)
Geoff Lang1ec57f82013-10-16 11:43:23 -04001296 {
1297 return false;
1298 }
1299 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001300 default:
1301 return false;
1302 }
1303 break;
1304 case GL_RGBA_INTEGER:
1305 switch (type)
1306 {
1307 case GL_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001308 if (internalFormatInfo.componentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001309 {
1310 return false;
1311 }
1312 break;
1313 case GL_UNSIGNED_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001314 if (internalFormatInfo.componentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001315 {
1316 return false;
1317 }
1318 break;
1319 default:
1320 return false;
1321 }
1322 break;
1323 case GL_BGRA_EXT:
1324 switch (type)
1325 {
1326 case GL_UNSIGNED_BYTE:
1327 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1328 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1329 break;
1330 default:
1331 return false;
1332 }
1333 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001334 case GL_RG_EXT:
1335 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001336 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001337 {
1338 return false;
1339 }
1340 switch (type)
1341 {
1342 case GL_UNSIGNED_BYTE:
1343 break;
Vincent Lang25ab4512016-05-13 18:13:59 +02001344 case GL_UNSIGNED_SHORT:
1345 if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
1346 internalFormatInfo.type != GL_UNSIGNED_SHORT)
1347 {
1348 return false;
1349 }
1350 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001351 default:
1352 return false;
1353 }
1354 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001355 default:
1356 return false;
1357 }
1358 return true;
1359}
1360
Corentin Walleze0902642014-11-04 12:32:15 -08001361bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
1362 GLenum internalformat, GLsizei width, GLsizei height)
1363{
1364 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
1365 {
1366 return false;
1367 }
1368
1369 //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.
1370 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1371 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
1372 {
Jamie Madill437fa652016-05-03 15:13:24 -04001373 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -08001374 return false;
1375 }
1376
1377 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
1378 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1379 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1380 {
Jamie Madill437fa652016-05-03 15:13:24 -04001381 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001382 Error(GL_INVALID_OPERATION,
1383 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001384 return false;
1385 }
1386
1387 return true;
1388}
1389
Austin Kinross08332632015-05-05 13:35:47 -07001390bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
1391 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001392{
Austin Kinross08332632015-05-05 13:35:47 -07001393 if (context->getClientVersion() < 3)
1394 {
Jamie Madill437fa652016-05-03 15:13:24 -04001395 context->handleError(
1396 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001397 return false;
1398 }
1399
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001400 bool defaultFramebuffer = false;
1401
1402 switch (target)
1403 {
1404 case GL_DRAW_FRAMEBUFFER:
1405 case GL_FRAMEBUFFER:
Shannon Woods53a94a82014-06-24 15:20:36 -04001406 defaultFramebuffer = context->getState().getDrawFramebuffer()->id() == 0;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001407 break;
1408 case GL_READ_FRAMEBUFFER:
Shannon Woods53a94a82014-06-24 15:20:36 -04001409 defaultFramebuffer = context->getState().getReadFramebuffer()->id() == 0;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001410 break;
1411 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001412 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001413 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001414 }
1415
Austin Kinross08332632015-05-05 13:35:47 -07001416 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001417}
1418
Jamie Madillc29968b2016-01-20 11:17:23 -05001419bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001420{
1421 if (context->getClientVersion() < 3)
1422 {
Jamie Madill437fa652016-05-03 15:13:24 -04001423 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001424 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001425 }
1426
Shannon Woods53a94a82014-06-24 15:20:36 -04001427 const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer();
Geoff Lang748f74e2014-12-01 11:25:34 -05001428 if (!fbo || fbo->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001429 {
Jamie Madill437fa652016-05-03 15:13:24 -04001430 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001431 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001432 }
1433
1434 return true;
1435}
1436
Olli Etuaho71dfb362016-03-10 14:04:27 +02001437bool ValidateDrawRangeElements(Context *context,
1438 GLenum mode,
1439 GLuint start,
1440 GLuint end,
1441 GLsizei count,
1442 GLenum type,
1443 const GLvoid *indices,
1444 IndexRange *indexRange)
1445{
1446 if (context->getClientVersion() < 3)
1447 {
Jamie Madill437fa652016-05-03 15:13:24 -04001448 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001449 return false;
1450 }
1451
1452 if (end < start)
1453 {
Jamie Madill437fa652016-05-03 15:13:24 -04001454 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001455 return false;
1456 }
1457
1458 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1459 {
1460 return false;
1461 }
1462
1463 if (indexRange->end > end || indexRange->start < start)
1464 {
1465 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001466 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001467 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1468 return false;
1469 }
1470 return true;
1471}
1472
Geoff Langb1196682014-07-23 13:47:29 -04001473bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001474{
1475 if (context->getClientVersion() < 3)
1476 {
Jamie Madill437fa652016-05-03 15:13:24 -04001477 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001478 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001479 }
1480
Jamie Madill78f41802014-08-25 15:47:55 -04001481 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001482}
1483
Jamie Madillb885e572015-02-03 16:16:04 -05001484bool ValidateReadBuffer(Context *context, GLenum src)
1485{
1486 if (context->getClientVersion() < 3)
1487 {
Jamie Madill437fa652016-05-03 15:13:24 -04001488 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001489 return false;
1490 }
1491
1492 Framebuffer *readFBO = context->getState().getReadFramebuffer();
1493
1494 if (readFBO == nullptr)
1495 {
Jamie Madill437fa652016-05-03 15:13:24 -04001496 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001497 return false;
1498 }
1499
1500 if (src == GL_NONE)
1501 {
1502 return true;
1503 }
1504
Olli Etuaho84c9f592016-03-09 14:37:25 +02001505 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001506 {
Jamie Madill437fa652016-05-03 15:13:24 -04001507 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001508 return false;
1509 }
1510
1511 if (readFBO->id() == 0)
1512 {
1513 if (src != GL_BACK)
1514 {
1515 const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001516 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001517 return false;
1518 }
1519 }
1520 else
1521 {
1522 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1523
1524 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1525 {
1526 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001527 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001528 return false;
1529 }
1530 }
1531
1532 return true;
1533}
1534
Jamie Madill86af3d22015-07-21 15:14:07 -04001535bool ValidateCompressedTexImage3D(Context *context,
1536 GLenum target,
1537 GLint level,
1538 GLenum internalformat,
1539 GLsizei width,
1540 GLsizei height,
1541 GLsizei depth,
1542 GLint border,
1543 GLsizei imageSize,
1544 const GLvoid *data)
1545{
1546 if (context->getClientVersion() < 3)
1547 {
Jamie Madill437fa652016-05-03 15:13:24 -04001548 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001549 return false;
1550 }
1551
Jamie Madille2e406c2016-06-02 13:04:10 -04001552 // Validate image size
1553 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1554 {
1555 context->handleError(Error(GL_INVALID_VALUE));
1556 return false;
1557 }
1558
Jamie Madill86af3d22015-07-21 15:14:07 -04001559 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04001560 auto blockSizeOrErr =
1561 formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001562 if (blockSizeOrErr.isError())
1563 {
Jamie Madill513558d2016-06-02 13:04:11 -04001564 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001565 return false;
1566 }
1567 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001568 {
Jamie Madill437fa652016-05-03 15:13:24 -04001569 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001570 return false;
1571 }
1572
1573 // 3D texture target validation
1574 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1575 {
Jamie Madill437fa652016-05-03 15:13:24 -04001576 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001577 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1578 return false;
1579 }
1580
1581 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001582 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
1583 0, width, height, depth, border, GL_NONE, GL_NONE, data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001584 {
1585 return false;
1586 }
1587
1588 return true;
1589}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001590
1591bool ValidateBindVertexArray(Context *context, GLuint array)
1592{
1593 if (context->getClientVersion() < 3)
1594 {
Jamie Madill437fa652016-05-03 15:13:24 -04001595 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001596 return false;
1597 }
1598
1599 return ValidateBindVertexArrayBase(context, array);
1600}
1601
Austin Kinrossbc781f32015-10-26 09:27:38 -07001602bool ValidateIsVertexArray(Context *context)
1603{
1604 if (context->getClientVersion() < 3)
1605 {
Jamie Madill437fa652016-05-03 15:13:24 -04001606 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001607 return false;
1608 }
1609
1610 return true;
1611}
Geoff Langc5629752015-12-07 16:29:04 -05001612
1613bool ValidateProgramBinary(Context *context,
1614 GLuint program,
1615 GLenum binaryFormat,
1616 const void *binary,
1617 GLint length)
1618{
1619 if (context->getClientVersion() < 3)
1620 {
Jamie Madill437fa652016-05-03 15:13:24 -04001621 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001622 return false;
1623 }
1624
1625 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1626}
1627
1628bool ValidateGetProgramBinary(Context *context,
1629 GLuint program,
1630 GLsizei bufSize,
1631 GLsizei *length,
1632 GLenum *binaryFormat,
1633 void *binary)
1634{
1635 if (context->getClientVersion() < 3)
1636 {
Jamie Madill437fa652016-05-03 15:13:24 -04001637 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001638 return false;
1639 }
1640
1641 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1642}
1643
Olli Etuahof0fee072016-03-30 15:11:58 +03001644bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001645{
1646 if (context->getClientVersion() < 3)
1647 {
Jamie Madill437fa652016-05-03 15:13:24 -04001648 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001649 return false;
1650 }
1651
1652 if (GetValidProgram(context, program) == nullptr)
1653 {
1654 return false;
1655 }
1656
1657 switch (pname)
1658 {
1659 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001660 if (value != GL_FALSE && value != GL_TRUE)
1661 {
Jamie Madill437fa652016-05-03 15:13:24 -04001662 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001663 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1664 return false;
1665 }
Geoff Langc5629752015-12-07 16:29:04 -05001666 break;
1667
1668 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001669 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001670 return false;
1671 }
1672
1673 return true;
1674}
Jamie Madillc29968b2016-01-20 11:17:23 -05001675
1676bool ValidateBlitFramebuffer(Context *context,
1677 GLint srcX0,
1678 GLint srcY0,
1679 GLint srcX1,
1680 GLint srcY1,
1681 GLint dstX0,
1682 GLint dstY0,
1683 GLint dstX1,
1684 GLint dstY1,
1685 GLbitfield mask,
1686 GLenum filter)
1687{
1688 if (context->getClientVersion() < 3)
1689 {
Jamie Madill437fa652016-05-03 15:13:24 -04001690 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001691 return false;
1692 }
1693
1694 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1695 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001696}
Jamie Madillc29968b2016-01-20 11:17:23 -05001697
1698bool ValidateClearBufferiv(ValidationContext *context,
1699 GLenum buffer,
1700 GLint drawbuffer,
1701 const GLint *value)
1702{
1703 switch (buffer)
1704 {
1705 case GL_COLOR:
1706 if (drawbuffer < 0 ||
1707 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1708 {
Jamie Madill437fa652016-05-03 15:13:24 -04001709 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001710 return false;
1711 }
1712 break;
1713
1714 case GL_STENCIL:
1715 if (drawbuffer != 0)
1716 {
Jamie Madill437fa652016-05-03 15:13:24 -04001717 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001718 return false;
1719 }
1720 break;
1721
1722 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001723 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001724 return false;
1725 }
1726
1727 return ValidateClearBuffer(context);
1728}
1729
1730bool ValidateClearBufferuiv(ValidationContext *context,
1731 GLenum buffer,
1732 GLint drawbuffer,
1733 const GLuint *value)
1734{
1735 switch (buffer)
1736 {
1737 case GL_COLOR:
1738 if (drawbuffer < 0 ||
1739 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1740 {
Jamie Madill437fa652016-05-03 15:13:24 -04001741 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001742 return false;
1743 }
1744 break;
1745
1746 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001747 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001748 return false;
1749 }
1750
1751 return ValidateClearBuffer(context);
1752}
1753
1754bool ValidateClearBufferfv(ValidationContext *context,
1755 GLenum buffer,
1756 GLint drawbuffer,
1757 const GLfloat *value)
1758{
1759 switch (buffer)
1760 {
1761 case GL_COLOR:
1762 if (drawbuffer < 0 ||
1763 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1764 {
Jamie Madill437fa652016-05-03 15:13:24 -04001765 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001766 return false;
1767 }
1768 break;
1769
1770 case GL_DEPTH:
1771 if (drawbuffer != 0)
1772 {
Jamie Madill437fa652016-05-03 15:13:24 -04001773 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001774 return false;
1775 }
1776 break;
1777
1778 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001779 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001780 return false;
1781 }
1782
1783 return ValidateClearBuffer(context);
1784}
1785
1786bool ValidateClearBufferfi(ValidationContext *context,
1787 GLenum buffer,
1788 GLint drawbuffer,
1789 GLfloat depth,
1790 GLint stencil)
1791{
1792 switch (buffer)
1793 {
1794 case GL_DEPTH_STENCIL:
1795 if (drawbuffer != 0)
1796 {
Jamie Madill437fa652016-05-03 15:13:24 -04001797 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001798 return false;
1799 }
1800 break;
1801
1802 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001803 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001804 return false;
1805 }
1806
1807 return ValidateClearBuffer(context);
1808}
1809
1810bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1811{
1812 if (context->getClientVersion() < 3)
1813 {
Jamie Madill437fa652016-05-03 15:13:24 -04001814 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001815 return false;
1816 }
1817
1818 return ValidateDrawBuffersBase(context, n, bufs);
1819}
1820
1821bool ValidateCopyTexSubImage3D(Context *context,
1822 GLenum target,
1823 GLint level,
1824 GLint xoffset,
1825 GLint yoffset,
1826 GLint zoffset,
1827 GLint x,
1828 GLint y,
1829 GLsizei width,
1830 GLsizei height)
1831{
1832 if (context->getClientVersion() < 3)
1833 {
Jamie Madill437fa652016-05-03 15:13:24 -04001834 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001835 return false;
1836 }
1837
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001838 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1839 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001840}
1841
Jamie Madill73a84962016-02-12 09:27:23 -05001842bool ValidateTexImage3D(Context *context,
1843 GLenum target,
1844 GLint level,
1845 GLint internalformat,
1846 GLsizei width,
1847 GLsizei height,
1848 GLsizei depth,
1849 GLint border,
1850 GLenum format,
1851 GLenum type,
1852 const GLvoid *pixels)
1853{
1854 if (context->getClientVersion() < 3)
1855 {
Jamie Madill437fa652016-05-03 15:13:24 -04001856 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001857 return false;
1858 }
1859
1860 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1861 0, 0, width, height, depth, border, format, type,
1862 pixels);
1863}
1864
1865bool ValidateTexSubImage3D(Context *context,
1866 GLenum target,
1867 GLint level,
1868 GLint xoffset,
1869 GLint yoffset,
1870 GLint zoffset,
1871 GLsizei width,
1872 GLsizei height,
1873 GLsizei depth,
1874 GLenum format,
1875 GLenum type,
1876 const GLvoid *pixels)
1877{
1878 if (context->getClientVersion() < 3)
1879 {
Jamie Madill437fa652016-05-03 15:13:24 -04001880 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001881 return false;
1882 }
1883
1884 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1885 yoffset, zoffset, width, height, depth, 0, format, type,
1886 pixels);
1887}
1888
1889bool ValidateCompressedTexSubImage3D(Context *context,
1890 GLenum target,
1891 GLint level,
1892 GLint xoffset,
1893 GLint yoffset,
1894 GLint zoffset,
1895 GLsizei width,
1896 GLsizei height,
1897 GLsizei depth,
1898 GLenum format,
1899 GLsizei imageSize,
1900 const GLvoid *data)
1901{
1902 if (context->getClientVersion() < 3)
1903 {
Jamie Madill437fa652016-05-03 15:13:24 -04001904 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001905 return false;
1906 }
1907
1908 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001909 auto blockSizeOrErr =
1910 formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001911 if (blockSizeOrErr.isError())
1912 {
1913 context->handleError(blockSizeOrErr.getError());
1914 return false;
1915 }
1916 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001917 {
Jamie Madill437fa652016-05-03 15:13:24 -04001918 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001919 return false;
1920 }
1921
1922 if (!data)
1923 {
Jamie Madill437fa652016-05-03 15:13:24 -04001924 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001925 return false;
1926 }
1927
1928 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
1929 width, height, depth, 0, GL_NONE, GL_NONE, data);
1930}
1931
Olli Etuaho41997e72016-03-10 13:38:39 +02001932bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1933{
1934 return ValidateGenOrDeleteES3(context, n);
1935}
1936
1937bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1938{
1939 return ValidateGenOrDeleteES3(context, n);
1940}
1941
1942bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1943{
1944 return ValidateGenOrDeleteCountES3(context, count);
1945}
1946
1947bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1948{
1949 return ValidateGenOrDeleteCountES3(context, count);
1950}
1951
1952bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1953{
1954 return ValidateGenOrDeleteES3(context, n);
1955}
1956
1957bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1958{
1959 if (!ValidateGenOrDeleteES3(context, n))
1960 {
1961 return false;
1962 }
1963 for (GLint i = 0; i < n; ++i)
1964 {
1965 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1966 if (transformFeedback != nullptr && transformFeedback->isActive())
1967 {
1968 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001969 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001970 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1971 return false;
1972 }
1973 }
1974 return true;
1975}
1976
1977bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1978{
1979 return ValidateGenOrDeleteES3(context, n);
1980}
1981
1982bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1983{
1984 return ValidateGenOrDeleteES3(context, n);
1985}
1986
1987bool ValidateGenOrDeleteES3(Context *context, GLint n)
1988{
1989 if (context->getClientVersion() < 3)
1990 {
Jamie Madill437fa652016-05-03 15:13:24 -04001991 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001992 return false;
1993 }
1994 return ValidateGenOrDelete(context, n);
1995}
1996
1997bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1998{
1999 if (context->getClientVersion() < 3)
2000 {
Jamie Madill437fa652016-05-03 15:13:24 -04002001 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02002002 return false;
2003 }
2004 if (count < 0)
2005 {
Jamie Madill437fa652016-05-03 15:13:24 -04002006 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02002007 return false;
2008 }
2009 return true;
2010}
2011
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002012bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2013{
2014 if (context->getClientVersion() < 3)
2015 {
Jamie Madill437fa652016-05-03 15:13:24 -04002016 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002017 return false;
2018 }
2019 switch (primitiveMode)
2020 {
2021 case GL_TRIANGLES:
2022 case GL_LINES:
2023 case GL_POINTS:
2024 break;
2025
2026 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002027 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002028 return false;
2029 }
2030
2031 TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
2032 ASSERT(transformFeedback != nullptr);
2033
2034 if (transformFeedback->isActive())
2035 {
Jamie Madill437fa652016-05-03 15:13:24 -04002036 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002037 return false;
2038 }
2039 return true;
2040}
2041
Olli Etuaho37477912016-03-30 14:54:40 +03002042bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
2043{
2044 if (context->getClientVersion() < 3)
2045 {
Jamie Madill437fa652016-05-03 15:13:24 -04002046 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho37477912016-03-30 14:54:40 +03002047 return false;
2048 }
2049
2050 if (!context->isSampler(sampler))
2051 {
Jamie Madill437fa652016-05-03 15:13:24 -04002052 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho37477912016-03-30 14:54:40 +03002053 return false;
2054 }
2055
2056 if (!ValidateSamplerObjectParameter(context, pname))
2057 {
2058 return false;
2059 }
2060
Ian Ewellbda75592016-04-18 17:25:54 -04002061 if (!ValidateTexParamParameters(context, GL_TEXTURE_2D, pname, param))
Olli Etuaho37477912016-03-30 14:54:40 +03002062 {
2063 return false;
2064 }
2065 return true;
2066}
2067
2068bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
2069{
2070 // The only float parameters are MIN_LOD and MAX_LOD. For these any value is permissible, so
2071 // ValidateSamplerParameteri can be used for validation here.
2072 return ValidateSamplerParameteri(context, sampler, pname, static_cast<GLint>(param));
2073}
2074
Olli Etuaho4f667482016-03-30 15:56:35 +03002075bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
2076{
2077 if (context->getClientVersion() < 3)
2078 {
Jamie Madill437fa652016-05-03 15:13:24 -04002079 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002080 return false;
2081 }
2082
2083 return ValidateGetBufferPointervBase(context, target, pname, params);
2084}
2085
2086bool ValidateUnmapBuffer(Context *context, GLenum target)
2087{
2088 if (context->getClientVersion() < 3)
2089 {
Jamie Madill437fa652016-05-03 15:13:24 -04002090 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03002091 return false;
2092 }
2093
2094 return ValidateUnmapBufferBase(context, target);
2095}
2096
2097bool ValidateMapBufferRange(Context *context,
2098 GLenum target,
2099 GLintptr offset,
2100 GLsizeiptr length,
2101 GLbitfield access)
2102{
2103 if (context->getClientVersion() < 3)
2104 {
Jamie Madill437fa652016-05-03 15:13:24 -04002105 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002106 return false;
2107 }
2108
2109 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2110}
2111
2112bool ValidateFlushMappedBufferRange(Context *context,
2113 GLenum target,
2114 GLintptr offset,
2115 GLsizeiptr length)
2116{
2117 if (context->getClientVersion() < 3)
2118 {
Jamie Madill437fa652016-05-03 15:13:24 -04002119 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002120 return false;
2121 }
2122
2123 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2124}
2125
Jamie Madillc29968b2016-01-20 11:17:23 -05002126} // namespace gl