blob: 39bd20e90551c40ec0b68f61395100997c009848 [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.
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);
478 const auto &unpack = context->getState().getUnpackState();
479
480 auto copyBytesOrErr = formatInfo.computeUnpackSize(type, size, unpack);
Jamie Madille2e406c2016-06-02 13:04:10 -0400481 if (copyBytesOrErr.isError())
482 {
483 context->handleError(copyBytesOrErr.getError());
484 return false;
485 }
486 CheckedNumeric<size_t> checkedCopyBytes(copyBytesOrErr.getResult());
487 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
488 checkedCopyBytes += checkedOffset;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400489
Jamie Madille2e406c2016-06-02 13:04:10 -0400490 if (!checkedCopyBytes.IsValid() ||
491 (checkedCopyBytes.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400492 {
493 // Overflow past the end of the buffer
Jamie Madill437fa652016-05-03 15:13:24 -0400494 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400495 return false;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400496 }
497
498 // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
499 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400500 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400501 {
Jamie Madillc751d1e2014-10-21 17:46:29 -0400502 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
503
Jamie Madille2e406c2016-06-02 13:04:10 -0400504 if ((checkedOffset.ValueOrDie() % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400505 {
Jamie Madill437fa652016-05-03 15:13:24 -0400506 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400507 return false;
508 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400509 }
510
Jamie Madill7a5f7382014-03-05 15:01:24 -0500511 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700512 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500513 {
Jamie Madill437fa652016-05-03 15:13:24 -0400514 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400515 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500516 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400517 }
518
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400519 return true;
520}
521
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500522bool ValidateES3TexImage2DParameters(Context *context,
523 GLenum target,
524 GLint level,
525 GLenum internalformat,
526 bool isCompressed,
527 bool isSubImage,
528 GLint xoffset,
529 GLint yoffset,
530 GLint zoffset,
531 GLsizei width,
532 GLsizei height,
533 GLsizei depth,
534 GLint border,
535 GLenum format,
536 GLenum type,
537 const GLvoid *pixels)
538{
539 if (!ValidTexture2DDestinationTarget(context, target))
540 {
Jamie Madill437fa652016-05-03 15:13:24 -0400541 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500542 return false;
543 }
544
545 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
546 isSubImage, xoffset, yoffset, zoffset, width, height,
547 depth, border, format, type, pixels);
548}
549
550bool ValidateES3TexImage3DParameters(Context *context,
551 GLenum target,
552 GLint level,
553 GLenum internalformat,
554 bool isCompressed,
555 bool isSubImage,
556 GLint xoffset,
557 GLint yoffset,
558 GLint zoffset,
559 GLsizei width,
560 GLsizei height,
561 GLsizei depth,
562 GLint border,
563 GLenum format,
564 GLenum type,
565 const GLvoid *pixels)
566{
567 if (!ValidTexture3DDestinationTarget(context, target))
568 {
Jamie Madill437fa652016-05-03 15:13:24 -0400569 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500570 return false;
571 }
572
573 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
574 isSubImage, xoffset, yoffset, zoffset, width, height,
575 depth, border, format, type, pixels);
576}
577
Geoff Lang5d601382014-07-22 15:14:06 -0400578struct EffectiveInternalFormatInfo
579{
580 GLenum mEffectiveFormat;
581 GLenum mDestFormat;
582 GLuint mMinRedBits;
583 GLuint mMaxRedBits;
584 GLuint mMinGreenBits;
585 GLuint mMaxGreenBits;
586 GLuint mMinBlueBits;
587 GLuint mMaxBlueBits;
588 GLuint mMinAlphaBits;
589 GLuint mMaxAlphaBits;
590
591 EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits,
592 GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits,
593 GLuint minAlphaBits, GLuint maxAlphaBits)
594 : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits),
595 mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits),
596 mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits),
597 mMaxAlphaBits(maxAlphaBits) {};
598};
599
600typedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
601
602static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList()
603{
604 EffectiveInternalFormatList list;
605
606 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
607 // linear source buffer component sizes.
608 // | Source channel min/max sizes |
609 // Effective Internal Format | N/A | R | G | B | A |
610 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8));
611 list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0));
612 list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0));
613 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0));
614 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0));
615 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4));
616 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1));
617 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8));
618 list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2));
619
620 return list;
621}
622
623static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList()
624{
625 EffectiveInternalFormatList list;
626
627 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
628 // linear source buffer component sizes.
629 // | Source channel min/max sizes |
630 // Effective Internal Format | Dest Format | R | G | B | A |
631 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
632 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX));
633 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
634 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX));
635 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX));
636 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4));
637 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1));
638 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8));
639
640 return list;
641}
642
643static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
644 GLenum *outEffectiveFormat)
645{
646 const EffectiveInternalFormatList *list = NULL;
647 GLenum targetFormat = GL_NONE;
648
649 if (destFormat.pixelBytes > 0)
650 {
651 static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList();
652 list = &sizedList;
653 }
654 else
655 {
656 static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList();
657 list = &unsizedList;
658 targetFormat = destFormat.format;
659 }
660
661 for (size_t curFormat = 0; curFormat < list->size(); ++curFormat)
662 {
663 const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat);
664 if ((formatInfo.mDestFormat == targetFormat) &&
665 (formatInfo.mMinRedBits <= srcFormat.redBits && formatInfo.mMaxRedBits >= srcFormat.redBits) &&
666 (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) &&
667 (formatInfo.mMinBlueBits <= srcFormat.blueBits && formatInfo.mMaxBlueBits >= srcFormat.blueBits) &&
668 (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits))
669 {
670 *outEffectiveFormat = formatInfo.mEffectiveFormat;
671 return true;
672 }
673 }
674
675 return false;
676}
677
678struct CopyConversion
679{
680 GLenum mTextureFormat;
681 GLenum mFramebufferFormat;
682
683 CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
684 : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
685
686 bool operator<(const CopyConversion& other) const
687 {
688 return memcmp(this, &other, sizeof(CopyConversion)) < 0;
689 }
690};
691
692typedef std::set<CopyConversion> CopyConversionSet;
693
694static CopyConversionSet BuildValidES3CopyTexImageCombinations()
695{
696 CopyConversionSet set;
697
698 // From ES 3.0.1 spec, table 3.15
699 set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
700 set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
701 set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
702 set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
703 set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
704 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
705 set.insert(CopyConversion(GL_RED, GL_RED));
706 set.insert(CopyConversion(GL_RED, GL_RG));
707 set.insert(CopyConversion(GL_RED, GL_RGB));
708 set.insert(CopyConversion(GL_RED, GL_RGBA));
709 set.insert(CopyConversion(GL_RG, GL_RG));
710 set.insert(CopyConversion(GL_RG, GL_RGB));
711 set.insert(CopyConversion(GL_RG, GL_RGBA));
712 set.insert(CopyConversion(GL_RGB, GL_RGB));
713 set.insert(CopyConversion(GL_RGB, GL_RGBA));
714 set.insert(CopyConversion(GL_RGBA, GL_RGBA));
715
716 // Necessary for ANGLE back-buffers
717 set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
718 set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
719 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
720 set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
721 set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
722 set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
723 set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
724
725 set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
726 set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
727 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
728 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
729 set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
730 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
731 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
732 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
733 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
734 set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
735
736 return set;
737}
738
Corentin Wallez76287682016-04-25 09:23:38 -0400739static bool EqualOrFirstZero(GLuint first, GLuint second)
740{
741 return first == 0 || first == second;
742}
743
Geoff Lang5d601382014-07-22 15:14:06 -0400744static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle)
745{
746 const InternalFormat &textureInternalFormatInfo = GetInternalFormatInfo(textureInternalFormat);
747 const InternalFormat &framebufferInternalFormatInfo = GetInternalFormatInfo(frameBufferInternalFormat);
748
749 static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
750 if (conversionSet.find(CopyConversion(textureInternalFormatInfo.format, framebufferInternalFormatInfo.format)) != conversionSet.end())
751 {
752 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
753 // must both be signed, unsigned, or fixed point and both source and destinations
754 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
755 // conversion between fixed and floating point.
756
757 if ((textureInternalFormatInfo.colorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.colorEncoding == GL_SRGB))
758 {
759 return false;
760 }
761
762 if (((textureInternalFormatInfo.componentType == GL_INT) != (framebufferInternalFormatInfo.componentType == GL_INT )) ||
763 ((textureInternalFormatInfo.componentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.componentType == GL_UNSIGNED_INT)))
764 {
765 return false;
766 }
767
768 if ((textureInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
769 textureInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
770 textureInternalFormatInfo.componentType == GL_FLOAT) &&
771 !(framebufferInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
772 framebufferInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
773 framebufferInternalFormatInfo.componentType == GL_FLOAT))
774 {
775 return false;
776 }
777
778 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
779 // The effective internal format of the source buffer is determined with the following rules applied in order:
780 // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
781 // effective internal format is the source buffer's sized internal format.
782 // * If the source buffer is a texture that was created with an unsized base internal format, then the
783 // effective internal format is the source image array's effective internal format, as specified by table
784 // 3.12, which is determined from the <format> and <type> that were used when the source image array was
785 // specified by TexImage*.
786 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
787 // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
788 // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
789 // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
790 // is SRGB.
791 const InternalFormat *sourceEffectiveFormat = NULL;
792 if (readBufferHandle != 0)
793 {
794 // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
795 if (framebufferInternalFormatInfo.pixelBytes > 0)
796 {
797 sourceEffectiveFormat = &framebufferInternalFormatInfo;
798 }
799 else
800 {
801 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
802 // texture. We can use the same table we use when creating textures to get its effective sized format.
Geoff Lang051dbc72015-01-05 15:48:58 -0500803 GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type);
804 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400805 }
806 }
807 else
808 {
809 // The effective internal format must be derived from the source framebuffer's channel sizes.
810 // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
811 if (framebufferInternalFormatInfo.colorEncoding == GL_LINEAR)
812 {
813 GLenum effectiveFormat;
814 if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat))
815 {
816 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
817 }
818 else
819 {
820 return false;
821 }
822 }
823 else if (framebufferInternalFormatInfo.colorEncoding == GL_SRGB)
824 {
825 // SRGB buffers can only be copied to sized format destinations according to table 3.18
826 if ((textureInternalFormatInfo.pixelBytes > 0) &&
827 (framebufferInternalFormatInfo.redBits >= 1 && framebufferInternalFormatInfo.redBits <= 8) &&
828 (framebufferInternalFormatInfo.greenBits >= 1 && framebufferInternalFormatInfo.greenBits <= 8) &&
829 (framebufferInternalFormatInfo.blueBits >= 1 && framebufferInternalFormatInfo.blueBits <= 8) &&
830 (framebufferInternalFormatInfo.alphaBits >= 1 && framebufferInternalFormatInfo.alphaBits <= 8))
831 {
832 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
833 }
834 else
835 {
836 return false;
837 }
838 }
839 else
840 {
841 UNREACHABLE();
842 return false;
843 }
844 }
845
846 if (textureInternalFormatInfo.pixelBytes > 0)
847 {
Corentin Wallez76287682016-04-25 09:23:38 -0400848 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination
849 // format is sized, component sizes of the source and destination formats must exactly
850 // match if the destination format exists.
851 if (!EqualOrFirstZero(textureInternalFormatInfo.redBits,
852 sourceEffectiveFormat->redBits) ||
853 !EqualOrFirstZero(textureInternalFormatInfo.greenBits,
854 sourceEffectiveFormat->greenBits) ||
855 !EqualOrFirstZero(textureInternalFormatInfo.blueBits,
856 sourceEffectiveFormat->blueBits) ||
857 !EqualOrFirstZero(textureInternalFormatInfo.alphaBits,
858 sourceEffectiveFormat->alphaBits))
Geoff Lang5d601382014-07-22 15:14:06 -0400859 {
860 return false;
861 }
862 }
863
864
865 return true; // A conversion function exists, and no rule in the specification has precluded conversion
866 // between these formats.
867 }
868
869 return false;
870}
871
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500872bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
873 GLenum target,
874 GLint level,
875 GLenum internalformat,
876 bool isSubImage,
877 GLint xoffset,
878 GLint yoffset,
879 GLint zoffset,
880 GLint x,
881 GLint y,
882 GLsizei width,
883 GLsizei height,
884 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400885{
Jamie Madill560a8d82014-05-21 13:06:20 -0400886 GLenum textureInternalFormat;
887 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill6f38f822014-06-06 17:12:20 -0400888 xoffset, yoffset, zoffset, x, y, width, height,
889 border, &textureInternalFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400890 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400891 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400892 }
893
Jamie Madillc29968b2016-01-20 11:17:23 -0500894 const auto &state = context->getState();
895 const gl::Framebuffer *framebuffer = state.getReadFramebuffer();
896 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400897
Geoff Lang748f74e2014-12-01 11:25:34 -0500898 if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400899 {
Jamie Madill437fa652016-05-03 15:13:24 -0400900 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400901 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400902 }
903
Jamie Madillc29968b2016-01-20 11:17:23 -0500904 if (readFramebufferID != 0 && framebuffer->getSamples(context->getData()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400905 {
Jamie Madill437fa652016-05-03 15:13:24 -0400906 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400907 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400908 }
909
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400910 const gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400911 GLenum colorbufferInternalFormat = source->getInternalFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400912
913 if (isSubImage)
914 {
Geoff Lang5d601382014-07-22 15:14:06 -0400915 if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat,
Jamie Madillc29968b2016-01-20 11:17:23 -0500916 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400917 {
Jamie Madill437fa652016-05-03 15:13:24 -0400918 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400919 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400920 }
921 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400922 else
923 {
Geoff Lang5d601382014-07-22 15:14:06 -0400924 if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat,
Jamie Madillc29968b2016-01-20 11:17:23 -0500925 readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400926 {
Jamie Madill437fa652016-05-03 15:13:24 -0400927 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400928 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400929 }
930 }
931
Geoff Lang784a8fd2013-09-24 12:33:16 -0400932 // If width or height is zero, it is a no-op. Return false without setting an error.
933 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400934}
935
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500936bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
937 GLenum target,
938 GLint level,
939 GLenum internalformat,
940 bool isSubImage,
941 GLint xoffset,
942 GLint yoffset,
943 GLint zoffset,
944 GLint x,
945 GLint y,
946 GLsizei width,
947 GLsizei height,
948 GLint border)
949{
950 if (!ValidTexture2DDestinationTarget(context, target))
951 {
Jamie Madill437fa652016-05-03 15:13:24 -0400952 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500953 return false;
954 }
955
956 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
957 xoffset, yoffset, zoffset, x, y, width, height,
958 border);
959}
960
961bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
962 GLenum target,
963 GLint level,
964 GLenum internalformat,
965 bool isSubImage,
966 GLint xoffset,
967 GLint yoffset,
968 GLint zoffset,
969 GLint x,
970 GLint y,
971 GLsizei width,
972 GLsizei height,
973 GLint border)
974{
975 if (!ValidTexture3DDestinationTarget(context, target))
976 {
Jamie Madill437fa652016-05-03 15:13:24 -0400977 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500978 return false;
979 }
980
981 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
982 xoffset, yoffset, zoffset, x, y, width, height,
983 border);
984}
985
986bool ValidateES3TexStorageParametersBase(Context *context,
987 GLenum target,
988 GLsizei levels,
989 GLenum internalformat,
990 GLsizei width,
991 GLsizei height,
992 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400993{
994 if (width < 1 || height < 1 || depth < 1 || levels < 1)
995 {
Jamie Madill437fa652016-05-03 15:13:24 -0400996 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400997 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400998 }
999
Geoff Langb92c1332015-09-04 12:54:55 -04001000 GLsizei maxDim = std::max(width, height);
1001 if (target != GL_TEXTURE_2D_ARRAY)
1002 {
1003 maxDim = std::max(maxDim, depth);
1004 }
1005
1006 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001007 {
Jamie Madill437fa652016-05-03 15:13:24 -04001008 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001009 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001010 }
1011
Geoff Langaae65a42014-05-26 12:43:44 -04001012 const gl::Caps &caps = context->getCaps();
1013
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001014 switch (target)
1015 {
1016 case GL_TEXTURE_2D:
1017 {
Geoff Langaae65a42014-05-26 12:43:44 -04001018 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1019 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001020 {
Jamie Madill437fa652016-05-03 15:13:24 -04001021 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001022 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001023 }
1024 }
1025 break;
1026
Geoff Lang01c21d22013-09-24 11:52:16 -04001027 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001028 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001029 if (width != height)
1030 {
Jamie Madill437fa652016-05-03 15:13:24 -04001031 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001032 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001033 }
1034
Geoff Langaae65a42014-05-26 12:43:44 -04001035 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001036 {
Jamie Madill437fa652016-05-03 15:13:24 -04001037 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001038 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001039 }
1040 }
1041 break;
1042
1043 case GL_TEXTURE_3D:
1044 {
Geoff Langaae65a42014-05-26 12:43:44 -04001045 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
1046 static_cast<GLuint>(height) > caps.max3DTextureSize ||
1047 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001048 {
Jamie Madill437fa652016-05-03 15:13:24 -04001049 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001050 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001051 }
1052 }
1053 break;
1054
1055 case GL_TEXTURE_2D_ARRAY:
1056 {
Geoff Langaae65a42014-05-26 12:43:44 -04001057 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1058 static_cast<GLuint>(height) > caps.max2DTextureSize ||
1059 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001060 {
Jamie Madill437fa652016-05-03 15:13:24 -04001061 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001062 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001063 }
1064 }
1065 break;
1066
1067 default:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001068 UNREACHABLE();
Geoff Langb1196682014-07-23 13:47:29 -04001069 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001070 }
1071
Geoff Lang691e58c2014-12-19 17:03:25 -05001072 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001073 if (!texture || texture->id() == 0)
1074 {
Jamie Madill437fa652016-05-03 15:13:24 -04001075 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001076 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001077 }
1078
Geoff Lang69cce582015-09-17 13:20:36 -04001079 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001080 {
Jamie Madill437fa652016-05-03 15:13:24 -04001081 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001082 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001083 }
1084
Geoff Lang5d601382014-07-22 15:14:06 -04001085 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1086 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001087 {
Jamie Madill437fa652016-05-03 15:13:24 -04001088 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001089 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001090 }
1091
Geoff Lang5d601382014-07-22 15:14:06 -04001092 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001093 {
Jamie Madill437fa652016-05-03 15:13:24 -04001094 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001095 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001096 }
1097
1098 return true;
1099}
1100
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001101bool ValidateES3TexStorage2DParameters(Context *context,
1102 GLenum target,
1103 GLsizei levels,
1104 GLenum internalformat,
1105 GLsizei width,
1106 GLsizei height,
1107 GLsizei depth)
1108{
1109 if (!ValidTexture2DTarget(context, target))
1110 {
Jamie Madill437fa652016-05-03 15:13:24 -04001111 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001112 return false;
1113 }
1114
1115 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1116 height, depth);
1117}
1118
1119bool ValidateES3TexStorage3DParameters(Context *context,
1120 GLenum target,
1121 GLsizei levels,
1122 GLenum internalformat,
1123 GLsizei width,
1124 GLsizei height,
1125 GLsizei depth)
1126{
1127 if (!ValidTexture3DTarget(context, target))
1128 {
Jamie Madill437fa652016-05-03 15:13:24 -04001129 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001130 return false;
1131 }
1132
1133 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1134 height, depth);
1135}
1136
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001137bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1138{
1139 if (context->getClientVersion() < 3)
1140 {
Jamie Madill437fa652016-05-03 15:13:24 -04001141 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001142 return false;
1143 }
1144
1145 return ValidateBeginQueryBase(context, target, id);
1146}
1147
1148bool ValidateEndQuery(gl::Context *context, GLenum target)
1149{
1150 if (context->getClientVersion() < 3)
1151 {
Jamie Madill437fa652016-05-03 15:13:24 -04001152 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001153 return false;
1154 }
1155
1156 return ValidateEndQueryBase(context, target);
1157}
1158
1159bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1160{
1161 if (context->getClientVersion() < 3)
1162 {
Jamie Madill437fa652016-05-03 15:13:24 -04001163 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001164 return false;
1165 }
1166
1167 return ValidateGetQueryivBase(context, target, pname);
1168}
1169
1170bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1171{
1172 if (context->getClientVersion() < 3)
1173 {
Jamie Madill437fa652016-05-03 15:13:24 -04001174 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001175 return false;
1176 }
1177
1178 return ValidateGetQueryObjectValueBase(context, id, pname);
1179}
1180
Geoff Langb1196682014-07-23 13:47:29 -04001181bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
Jamie Madill570f7c82014-07-03 10:38:54 -04001182 GLuint texture, GLint level, GLint layer)
1183{
1184 if (context->getClientVersion() < 3)
1185 {
Jamie Madill437fa652016-05-03 15:13:24 -04001186 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001187 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001188 }
1189
Jamie Madill55ec3b12014-07-03 10:38:57 -04001190 if (layer < 0)
1191 {
Jamie Madill437fa652016-05-03 15:13:24 -04001192 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001193 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001194 }
1195
1196 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1197 {
1198 return false;
1199 }
1200
1201 const gl::Caps &caps = context->getCaps();
1202 if (texture != 0)
1203 {
1204 gl::Texture *tex = context->getTexture(texture);
1205 ASSERT(tex);
1206
1207 switch (tex->getTarget())
1208 {
1209 case GL_TEXTURE_2D_ARRAY:
1210 {
1211 if (level > gl::log2(caps.max2DTextureSize))
1212 {
Jamie Madill437fa652016-05-03 15:13:24 -04001213 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001214 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001215 }
1216
1217 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1218 {
Jamie Madill437fa652016-05-03 15:13:24 -04001219 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001220 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001221 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001222 }
1223 break;
1224
1225 case GL_TEXTURE_3D:
1226 {
1227 if (level > gl::log2(caps.max3DTextureSize))
1228 {
Jamie Madill437fa652016-05-03 15:13:24 -04001229 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001230 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001231 }
1232
1233 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1234 {
Jamie Madill437fa652016-05-03 15:13:24 -04001235 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001236 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001237 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001238 }
1239 break;
1240
1241 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001242 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001243 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001244 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001245
1246 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(tex->getTarget(), level));
1247 if (internalFormatInfo.compressed)
1248 {
Jamie Madill437fa652016-05-03 15:13:24 -04001249 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001250 return false;
1251 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001252 }
1253
1254 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001255}
1256
Geoff Langb1196682014-07-23 13:47:29 -04001257bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001258{
Geoff Lang5d601382014-07-22 15:14:06 -04001259 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
1260
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001261 switch (format)
1262 {
1263 case GL_RGBA:
1264 switch (type)
1265 {
1266 case GL_UNSIGNED_BYTE:
1267 break;
Vincent Lang25ab4512016-05-13 18:13:59 +02001268 case GL_UNSIGNED_SHORT:
1269 if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
1270 internalFormatInfo.type != GL_UNSIGNED_SHORT)
1271 {
1272 return false;
1273 }
1274 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001275 case GL_UNSIGNED_INT_2_10_10_10_REV:
1276 if (internalFormat != GL_RGB10_A2)
1277 {
1278 return false;
1279 }
1280 break;
Geoff Lang1ec57f82013-10-16 11:43:23 -04001281 case GL_FLOAT:
Geoff Lang5d601382014-07-22 15:14:06 -04001282 if (internalFormatInfo.componentType != GL_FLOAT)
Geoff Lang1ec57f82013-10-16 11:43:23 -04001283 {
1284 return false;
1285 }
1286 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001287 default:
1288 return false;
1289 }
1290 break;
1291 case GL_RGBA_INTEGER:
1292 switch (type)
1293 {
1294 case GL_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001295 if (internalFormatInfo.componentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001296 {
1297 return false;
1298 }
1299 break;
1300 case GL_UNSIGNED_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001301 if (internalFormatInfo.componentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001302 {
1303 return false;
1304 }
1305 break;
1306 default:
1307 return false;
1308 }
1309 break;
1310 case GL_BGRA_EXT:
1311 switch (type)
1312 {
1313 case GL_UNSIGNED_BYTE:
1314 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1315 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1316 break;
1317 default:
1318 return false;
1319 }
1320 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001321 case GL_RG_EXT:
1322 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001323 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001324 {
1325 return false;
1326 }
1327 switch (type)
1328 {
1329 case GL_UNSIGNED_BYTE:
1330 break;
Vincent Lang25ab4512016-05-13 18:13:59 +02001331 case GL_UNSIGNED_SHORT:
1332 if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
1333 internalFormatInfo.type != GL_UNSIGNED_SHORT)
1334 {
1335 return false;
1336 }
1337 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001338 default:
1339 return false;
1340 }
1341 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001342 default:
1343 return false;
1344 }
1345 return true;
1346}
1347
Corentin Walleze0902642014-11-04 12:32:15 -08001348bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
1349 GLenum internalformat, GLsizei width, GLsizei height)
1350{
1351 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
1352 {
1353 return false;
1354 }
1355
1356 //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.
1357 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1358 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
1359 {
Jamie Madill437fa652016-05-03 15:13:24 -04001360 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -08001361 return false;
1362 }
1363
1364 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
1365 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1366 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1367 {
Jamie Madill437fa652016-05-03 15:13:24 -04001368 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001369 Error(GL_INVALID_OPERATION,
1370 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001371 return false;
1372 }
1373
1374 return true;
1375}
1376
Austin Kinross08332632015-05-05 13:35:47 -07001377bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
1378 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001379{
Austin Kinross08332632015-05-05 13:35:47 -07001380 if (context->getClientVersion() < 3)
1381 {
Jamie Madill437fa652016-05-03 15:13:24 -04001382 context->handleError(
1383 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001384 return false;
1385 }
1386
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001387 bool defaultFramebuffer = false;
1388
1389 switch (target)
1390 {
1391 case GL_DRAW_FRAMEBUFFER:
1392 case GL_FRAMEBUFFER:
Shannon Woods53a94a82014-06-24 15:20:36 -04001393 defaultFramebuffer = context->getState().getDrawFramebuffer()->id() == 0;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001394 break;
1395 case GL_READ_FRAMEBUFFER:
Shannon Woods53a94a82014-06-24 15:20:36 -04001396 defaultFramebuffer = context->getState().getReadFramebuffer()->id() == 0;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001397 break;
1398 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001399 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001400 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001401 }
1402
Austin Kinross08332632015-05-05 13:35:47 -07001403 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001404}
1405
Jamie Madillc29968b2016-01-20 11:17:23 -05001406bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001407{
1408 if (context->getClientVersion() < 3)
1409 {
Jamie Madill437fa652016-05-03 15:13:24 -04001410 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001411 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001412 }
1413
Shannon Woods53a94a82014-06-24 15:20:36 -04001414 const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer();
Geoff Lang748f74e2014-12-01 11:25:34 -05001415 if (!fbo || fbo->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001416 {
Jamie Madill437fa652016-05-03 15:13:24 -04001417 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001418 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001419 }
1420
1421 return true;
1422}
1423
Olli Etuaho71dfb362016-03-10 14:04:27 +02001424bool ValidateDrawRangeElements(Context *context,
1425 GLenum mode,
1426 GLuint start,
1427 GLuint end,
1428 GLsizei count,
1429 GLenum type,
1430 const GLvoid *indices,
1431 IndexRange *indexRange)
1432{
1433 if (context->getClientVersion() < 3)
1434 {
Jamie Madill437fa652016-05-03 15:13:24 -04001435 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001436 return false;
1437 }
1438
1439 if (end < start)
1440 {
Jamie Madill437fa652016-05-03 15:13:24 -04001441 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001442 return false;
1443 }
1444
1445 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1446 {
1447 return false;
1448 }
1449
1450 if (indexRange->end > end || indexRange->start < start)
1451 {
1452 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001453 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001454 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1455 return false;
1456 }
1457 return true;
1458}
1459
Geoff Langb1196682014-07-23 13:47:29 -04001460bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001461{
1462 if (context->getClientVersion() < 3)
1463 {
Jamie Madill437fa652016-05-03 15:13:24 -04001464 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001465 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001466 }
1467
Jamie Madill78f41802014-08-25 15:47:55 -04001468 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001469}
1470
Jamie Madillb885e572015-02-03 16:16:04 -05001471bool ValidateReadBuffer(Context *context, GLenum src)
1472{
1473 if (context->getClientVersion() < 3)
1474 {
Jamie Madill437fa652016-05-03 15:13:24 -04001475 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001476 return false;
1477 }
1478
1479 Framebuffer *readFBO = context->getState().getReadFramebuffer();
1480
1481 if (readFBO == nullptr)
1482 {
Jamie Madill437fa652016-05-03 15:13:24 -04001483 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001484 return false;
1485 }
1486
1487 if (src == GL_NONE)
1488 {
1489 return true;
1490 }
1491
Olli Etuaho84c9f592016-03-09 14:37:25 +02001492 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001493 {
Jamie Madill437fa652016-05-03 15:13:24 -04001494 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001495 return false;
1496 }
1497
1498 if (readFBO->id() == 0)
1499 {
1500 if (src != GL_BACK)
1501 {
1502 const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001503 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001504 return false;
1505 }
1506 }
1507 else
1508 {
1509 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1510
1511 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1512 {
1513 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001514 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001515 return false;
1516 }
1517 }
1518
1519 return true;
1520}
1521
Jamie Madill86af3d22015-07-21 15:14:07 -04001522bool ValidateCompressedTexImage3D(Context *context,
1523 GLenum target,
1524 GLint level,
1525 GLenum internalformat,
1526 GLsizei width,
1527 GLsizei height,
1528 GLsizei depth,
1529 GLint border,
1530 GLsizei imageSize,
1531 const GLvoid *data)
1532{
1533 if (context->getClientVersion() < 3)
1534 {
Jamie Madill437fa652016-05-03 15:13:24 -04001535 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001536 return false;
1537 }
1538
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001539 if (!ValidTextureTarget(context, target))
1540 {
1541 context->handleError(Error(GL_INVALID_ENUM));
1542 return false;
1543 }
1544
Jamie Madille2e406c2016-06-02 13:04:10 -04001545 // Validate image size
1546 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1547 {
1548 context->handleError(Error(GL_INVALID_VALUE));
1549 return false;
1550 }
1551
Jamie Madill86af3d22015-07-21 15:14:07 -04001552 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001553 if (!formatInfo.compressed)
1554 {
1555 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1556 return false;
1557 }
1558
Jamie Madill513558d2016-06-02 13:04:11 -04001559 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001560 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001561 if (blockSizeOrErr.isError())
1562 {
Jamie Madill513558d2016-06-02 13:04:11 -04001563 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001564 return false;
1565 }
1566 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001567 {
Jamie Madill437fa652016-05-03 15:13:24 -04001568 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001569 return false;
1570 }
1571
1572 // 3D texture target validation
1573 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1574 {
Jamie Madill437fa652016-05-03 15:13:24 -04001575 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001576 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1577 return false;
1578 }
1579
1580 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001581 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
1582 0, width, height, depth, border, GL_NONE, GL_NONE, data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001583 {
1584 return false;
1585 }
1586
1587 return true;
1588}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001589
1590bool ValidateBindVertexArray(Context *context, GLuint array)
1591{
1592 if (context->getClientVersion() < 3)
1593 {
Jamie Madill437fa652016-05-03 15:13:24 -04001594 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001595 return false;
1596 }
1597
1598 return ValidateBindVertexArrayBase(context, array);
1599}
1600
Austin Kinrossbc781f32015-10-26 09:27:38 -07001601bool ValidateIsVertexArray(Context *context)
1602{
1603 if (context->getClientVersion() < 3)
1604 {
Jamie Madill437fa652016-05-03 15:13:24 -04001605 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001606 return false;
1607 }
1608
1609 return true;
1610}
Geoff Langc5629752015-12-07 16:29:04 -05001611
1612bool ValidateProgramBinary(Context *context,
1613 GLuint program,
1614 GLenum binaryFormat,
1615 const void *binary,
1616 GLint length)
1617{
1618 if (context->getClientVersion() < 3)
1619 {
Jamie Madill437fa652016-05-03 15:13:24 -04001620 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001621 return false;
1622 }
1623
1624 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1625}
1626
1627bool ValidateGetProgramBinary(Context *context,
1628 GLuint program,
1629 GLsizei bufSize,
1630 GLsizei *length,
1631 GLenum *binaryFormat,
1632 void *binary)
1633{
1634 if (context->getClientVersion() < 3)
1635 {
Jamie Madill437fa652016-05-03 15:13:24 -04001636 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001637 return false;
1638 }
1639
1640 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1641}
1642
Olli Etuahof0fee072016-03-30 15:11:58 +03001643bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001644{
1645 if (context->getClientVersion() < 3)
1646 {
Jamie Madill437fa652016-05-03 15:13:24 -04001647 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001648 return false;
1649 }
1650
1651 if (GetValidProgram(context, program) == nullptr)
1652 {
1653 return false;
1654 }
1655
1656 switch (pname)
1657 {
1658 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001659 if (value != GL_FALSE && value != GL_TRUE)
1660 {
Jamie Madill437fa652016-05-03 15:13:24 -04001661 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001662 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1663 return false;
1664 }
Geoff Langc5629752015-12-07 16:29:04 -05001665 break;
1666
1667 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001668 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001669 return false;
1670 }
1671
1672 return true;
1673}
Jamie Madillc29968b2016-01-20 11:17:23 -05001674
1675bool ValidateBlitFramebuffer(Context *context,
1676 GLint srcX0,
1677 GLint srcY0,
1678 GLint srcX1,
1679 GLint srcY1,
1680 GLint dstX0,
1681 GLint dstY0,
1682 GLint dstX1,
1683 GLint dstY1,
1684 GLbitfield mask,
1685 GLenum filter)
1686{
1687 if (context->getClientVersion() < 3)
1688 {
Jamie Madill437fa652016-05-03 15:13:24 -04001689 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001690 return false;
1691 }
1692
1693 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1694 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001695}
Jamie Madillc29968b2016-01-20 11:17:23 -05001696
1697bool ValidateClearBufferiv(ValidationContext *context,
1698 GLenum buffer,
1699 GLint drawbuffer,
1700 const GLint *value)
1701{
1702 switch (buffer)
1703 {
1704 case GL_COLOR:
1705 if (drawbuffer < 0 ||
1706 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1707 {
Jamie Madill437fa652016-05-03 15:13:24 -04001708 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001709 return false;
1710 }
1711 break;
1712
1713 case GL_STENCIL:
1714 if (drawbuffer != 0)
1715 {
Jamie Madill437fa652016-05-03 15:13:24 -04001716 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001717 return false;
1718 }
1719 break;
1720
1721 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001722 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001723 return false;
1724 }
1725
1726 return ValidateClearBuffer(context);
1727}
1728
1729bool ValidateClearBufferuiv(ValidationContext *context,
1730 GLenum buffer,
1731 GLint drawbuffer,
1732 const GLuint *value)
1733{
1734 switch (buffer)
1735 {
1736 case GL_COLOR:
1737 if (drawbuffer < 0 ||
1738 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1739 {
Jamie Madill437fa652016-05-03 15:13:24 -04001740 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001741 return false;
1742 }
1743 break;
1744
1745 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001746 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001747 return false;
1748 }
1749
1750 return ValidateClearBuffer(context);
1751}
1752
1753bool ValidateClearBufferfv(ValidationContext *context,
1754 GLenum buffer,
1755 GLint drawbuffer,
1756 const GLfloat *value)
1757{
1758 switch (buffer)
1759 {
1760 case GL_COLOR:
1761 if (drawbuffer < 0 ||
1762 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1763 {
Jamie Madill437fa652016-05-03 15:13:24 -04001764 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001765 return false;
1766 }
1767 break;
1768
1769 case GL_DEPTH:
1770 if (drawbuffer != 0)
1771 {
Jamie Madill437fa652016-05-03 15:13:24 -04001772 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001773 return false;
1774 }
1775 break;
1776
1777 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001778 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001779 return false;
1780 }
1781
1782 return ValidateClearBuffer(context);
1783}
1784
1785bool ValidateClearBufferfi(ValidationContext *context,
1786 GLenum buffer,
1787 GLint drawbuffer,
1788 GLfloat depth,
1789 GLint stencil)
1790{
1791 switch (buffer)
1792 {
1793 case GL_DEPTH_STENCIL:
1794 if (drawbuffer != 0)
1795 {
Jamie Madill437fa652016-05-03 15:13:24 -04001796 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001797 return false;
1798 }
1799 break;
1800
1801 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001802 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001803 return false;
1804 }
1805
1806 return ValidateClearBuffer(context);
1807}
1808
1809bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1810{
1811 if (context->getClientVersion() < 3)
1812 {
Jamie Madill437fa652016-05-03 15:13:24 -04001813 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001814 return false;
1815 }
1816
1817 return ValidateDrawBuffersBase(context, n, bufs);
1818}
1819
1820bool ValidateCopyTexSubImage3D(Context *context,
1821 GLenum target,
1822 GLint level,
1823 GLint xoffset,
1824 GLint yoffset,
1825 GLint zoffset,
1826 GLint x,
1827 GLint y,
1828 GLsizei width,
1829 GLsizei height)
1830{
1831 if (context->getClientVersion() < 3)
1832 {
Jamie Madill437fa652016-05-03 15:13:24 -04001833 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001834 return false;
1835 }
1836
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001837 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1838 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001839}
1840
Jamie Madill73a84962016-02-12 09:27:23 -05001841bool ValidateTexImage3D(Context *context,
1842 GLenum target,
1843 GLint level,
1844 GLint internalformat,
1845 GLsizei width,
1846 GLsizei height,
1847 GLsizei depth,
1848 GLint border,
1849 GLenum format,
1850 GLenum type,
1851 const GLvoid *pixels)
1852{
1853 if (context->getClientVersion() < 3)
1854 {
Jamie Madill437fa652016-05-03 15:13:24 -04001855 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001856 return false;
1857 }
1858
1859 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1860 0, 0, width, height, depth, border, format, type,
1861 pixels);
1862}
1863
1864bool ValidateTexSubImage3D(Context *context,
1865 GLenum target,
1866 GLint level,
1867 GLint xoffset,
1868 GLint yoffset,
1869 GLint zoffset,
1870 GLsizei width,
1871 GLsizei height,
1872 GLsizei depth,
1873 GLenum format,
1874 GLenum type,
1875 const GLvoid *pixels)
1876{
1877 if (context->getClientVersion() < 3)
1878 {
Jamie Madill437fa652016-05-03 15:13:24 -04001879 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001880 return false;
1881 }
1882
1883 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1884 yoffset, zoffset, width, height, depth, 0, format, type,
1885 pixels);
1886}
1887
1888bool ValidateCompressedTexSubImage3D(Context *context,
1889 GLenum target,
1890 GLint level,
1891 GLint xoffset,
1892 GLint yoffset,
1893 GLint zoffset,
1894 GLsizei width,
1895 GLsizei height,
1896 GLsizei depth,
1897 GLenum format,
1898 GLsizei imageSize,
1899 const GLvoid *data)
1900{
1901 if (context->getClientVersion() < 3)
1902 {
Jamie Madill437fa652016-05-03 15:13:24 -04001903 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001904 return false;
1905 }
1906
1907 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001908 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001909 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001910 if (blockSizeOrErr.isError())
1911 {
1912 context->handleError(blockSizeOrErr.getError());
1913 return false;
1914 }
1915 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001916 {
Jamie Madill437fa652016-05-03 15:13:24 -04001917 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001918 return false;
1919 }
1920
1921 if (!data)
1922 {
Jamie Madill437fa652016-05-03 15:13:24 -04001923 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001924 return false;
1925 }
1926
1927 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
1928 width, height, depth, 0, GL_NONE, GL_NONE, data);
1929}
1930
Olli Etuaho41997e72016-03-10 13:38:39 +02001931bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1932{
1933 return ValidateGenOrDeleteES3(context, n);
1934}
1935
1936bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1937{
1938 return ValidateGenOrDeleteES3(context, n);
1939}
1940
1941bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1942{
1943 return ValidateGenOrDeleteCountES3(context, count);
1944}
1945
1946bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1947{
1948 return ValidateGenOrDeleteCountES3(context, count);
1949}
1950
1951bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1952{
1953 return ValidateGenOrDeleteES3(context, n);
1954}
1955
1956bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1957{
1958 if (!ValidateGenOrDeleteES3(context, n))
1959 {
1960 return false;
1961 }
1962 for (GLint i = 0; i < n; ++i)
1963 {
1964 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1965 if (transformFeedback != nullptr && transformFeedback->isActive())
1966 {
1967 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001968 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001969 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1970 return false;
1971 }
1972 }
1973 return true;
1974}
1975
1976bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1977{
1978 return ValidateGenOrDeleteES3(context, n);
1979}
1980
1981bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1982{
1983 return ValidateGenOrDeleteES3(context, n);
1984}
1985
1986bool ValidateGenOrDeleteES3(Context *context, GLint n)
1987{
1988 if (context->getClientVersion() < 3)
1989 {
Jamie Madill437fa652016-05-03 15:13:24 -04001990 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001991 return false;
1992 }
1993 return ValidateGenOrDelete(context, n);
1994}
1995
1996bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1997{
1998 if (context->getClientVersion() < 3)
1999 {
Jamie Madill437fa652016-05-03 15:13:24 -04002000 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02002001 return false;
2002 }
2003 if (count < 0)
2004 {
Jamie Madill437fa652016-05-03 15:13:24 -04002005 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02002006 return false;
2007 }
2008 return true;
2009}
2010
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002011bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2012{
2013 if (context->getClientVersion() < 3)
2014 {
Jamie Madill437fa652016-05-03 15:13:24 -04002015 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002016 return false;
2017 }
2018 switch (primitiveMode)
2019 {
2020 case GL_TRIANGLES:
2021 case GL_LINES:
2022 case GL_POINTS:
2023 break;
2024
2025 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002026 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002027 return false;
2028 }
2029
2030 TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
2031 ASSERT(transformFeedback != nullptr);
2032
2033 if (transformFeedback->isActive())
2034 {
Jamie Madill437fa652016-05-03 15:13:24 -04002035 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002036 return false;
2037 }
2038 return true;
2039}
2040
Olli Etuaho37477912016-03-30 14:54:40 +03002041bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
2042{
2043 if (context->getClientVersion() < 3)
2044 {
Jamie Madill437fa652016-05-03 15:13:24 -04002045 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho37477912016-03-30 14:54:40 +03002046 return false;
2047 }
2048
2049 if (!context->isSampler(sampler))
2050 {
Jamie Madill437fa652016-05-03 15:13:24 -04002051 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho37477912016-03-30 14:54:40 +03002052 return false;
2053 }
2054
2055 if (!ValidateSamplerObjectParameter(context, pname))
2056 {
2057 return false;
2058 }
2059
Ian Ewellbda75592016-04-18 17:25:54 -04002060 if (!ValidateTexParamParameters(context, GL_TEXTURE_2D, pname, param))
Olli Etuaho37477912016-03-30 14:54:40 +03002061 {
2062 return false;
2063 }
2064 return true;
2065}
2066
2067bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
2068{
2069 // The only float parameters are MIN_LOD and MAX_LOD. For these any value is permissible, so
2070 // ValidateSamplerParameteri can be used for validation here.
2071 return ValidateSamplerParameteri(context, sampler, pname, static_cast<GLint>(param));
2072}
2073
Olli Etuaho4f667482016-03-30 15:56:35 +03002074bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
2075{
2076 if (context->getClientVersion() < 3)
2077 {
Jamie Madill437fa652016-05-03 15:13:24 -04002078 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002079 return false;
2080 }
2081
2082 return ValidateGetBufferPointervBase(context, target, pname, params);
2083}
2084
2085bool ValidateUnmapBuffer(Context *context, GLenum target)
2086{
2087 if (context->getClientVersion() < 3)
2088 {
Jamie Madill437fa652016-05-03 15:13:24 -04002089 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03002090 return false;
2091 }
2092
2093 return ValidateUnmapBufferBase(context, target);
2094}
2095
2096bool ValidateMapBufferRange(Context *context,
2097 GLenum target,
2098 GLintptr offset,
2099 GLsizeiptr length,
2100 GLbitfield access)
2101{
2102 if (context->getClientVersion() < 3)
2103 {
Jamie Madill437fa652016-05-03 15:13:24 -04002104 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002105 return false;
2106 }
2107
2108 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2109}
2110
2111bool ValidateFlushMappedBufferRange(Context *context,
2112 GLenum target,
2113 GLintptr offset,
2114 GLsizeiptr length)
2115{
2116 if (context->getClientVersion() < 3)
2117 {
Jamie Madill437fa652016-05-03 15:13:24 -04002118 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002119 return false;
2120 }
2121
2122 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2123}
2124
Jamie Madillc29968b2016-01-20 11:17:23 -05002125} // namespace gl