blob: c6f645c808f96c7d03b44097e7fc4341a503ba7a [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
Geoff Lang4e58af62016-08-26 10:56:52 -040056 // clang-format off
Geoff Lang5d601382014-07-22 15:14:06 -040057 // | Internal format | Format | Type |
58 // | | | |
59 InsertES3FormatCombo(&set, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE );
60 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE );
61 InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE );
62 InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE );
63 InsertES3FormatCombo(&set, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE );
64 InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 );
65 InsertES3FormatCombo(&set, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV );
66 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV );
67 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 );
68 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT );
69 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT_OES );
70 InsertES3FormatCombo(&set, GL_RGBA32F, GL_RGBA, GL_FLOAT );
71 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_FLOAT );
72 InsertES3FormatCombo(&set, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE );
73 InsertES3FormatCombo(&set, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE );
74 InsertES3FormatCombo(&set, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT );
75 InsertES3FormatCombo(&set, GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT );
76 InsertES3FormatCombo(&set, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT );
77 InsertES3FormatCombo(&set, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT );
78 InsertES3FormatCombo(&set, GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV );
79 InsertES3FormatCombo(&set, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE );
80 InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE );
81 InsertES3FormatCombo(&set, GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE );
82 InsertES3FormatCombo(&set, GL_RGB8_SNORM, GL_RGB, GL_BYTE );
83 InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 );
84 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV );
85 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV );
86 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT );
87 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT_OES );
88 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT );
89 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT_OES );
90 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT );
91 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT_OES );
92 InsertES3FormatCombo(&set, GL_RGB32F, GL_RGB, GL_FLOAT );
93 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_FLOAT );
94 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT );
95 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_FLOAT );
96 InsertES3FormatCombo(&set, GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE );
97 InsertES3FormatCombo(&set, GL_RGB8I, GL_RGB_INTEGER, GL_BYTE );
98 InsertES3FormatCombo(&set, GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT );
99 InsertES3FormatCombo(&set, GL_RGB16I, GL_RGB_INTEGER, GL_SHORT );
100 InsertES3FormatCombo(&set, GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT );
101 InsertES3FormatCombo(&set, GL_RGB32I, GL_RGB_INTEGER, GL_INT );
102 InsertES3FormatCombo(&set, GL_RG8, GL_RG, GL_UNSIGNED_BYTE );
103 InsertES3FormatCombo(&set, GL_RG8_SNORM, GL_RG, GL_BYTE );
104 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT );
105 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT_OES );
106 InsertES3FormatCombo(&set, GL_RG32F, GL_RG, GL_FLOAT );
107 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_FLOAT );
108 InsertES3FormatCombo(&set, GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE );
109 InsertES3FormatCombo(&set, GL_RG8I, GL_RG_INTEGER, GL_BYTE );
110 InsertES3FormatCombo(&set, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT );
111 InsertES3FormatCombo(&set, GL_RG16I, GL_RG_INTEGER, GL_SHORT );
112 InsertES3FormatCombo(&set, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT );
113 InsertES3FormatCombo(&set, GL_RG32I, GL_RG_INTEGER, GL_INT );
114 InsertES3FormatCombo(&set, GL_R8, GL_RED, GL_UNSIGNED_BYTE );
115 InsertES3FormatCombo(&set, GL_R8_SNORM, GL_RED, GL_BYTE );
116 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT );
117 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT_OES );
118 InsertES3FormatCombo(&set, GL_R32F, GL_RED, GL_FLOAT );
119 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_FLOAT );
120 InsertES3FormatCombo(&set, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE );
121 InsertES3FormatCombo(&set, GL_R8I, GL_RED_INTEGER, GL_BYTE );
122 InsertES3FormatCombo(&set, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT );
123 InsertES3FormatCombo(&set, GL_R16I, GL_RED_INTEGER, GL_SHORT );
124 InsertES3FormatCombo(&set, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT );
125 InsertES3FormatCombo(&set, GL_R32I, GL_RED_INTEGER, GL_INT );
126
127 // Unsized formats
128 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE );
129 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 );
130 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 );
131 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE );
132 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 );
133 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE );
134 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE );
135 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE );
136 InsertES3FormatCombo(&set, GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE );
137 InsertES3FormatCombo(&set, GL_SRGB_EXT, GL_SRGB_EXT, GL_UNSIGNED_BYTE );
Jamie Madill689325c2015-07-20 14:36:53 -0400138 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_UNSIGNED_BYTE );
139 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_FLOAT );
140 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_HALF_FLOAT );
141 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_HALF_FLOAT_OES );
142 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_UNSIGNED_BYTE );
143 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_FLOAT );
144 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_HALF_FLOAT );
145 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_HALF_FLOAT_OES );
146 InsertES3FormatCombo(&set, GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 );
Geoff Lang5d601382014-07-22 15:14:06 -0400147
148 // Depth stencil formats
149 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT );
150 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
151 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
152 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT );
153 InsertES3FormatCombo(&set, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 );
154 InsertES3FormatCombo(&set, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
155
156 // From GL_EXT_sRGB
157 InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE );
158 InsertES3FormatCombo(&set, GL_SRGB8, GL_SRGB_EXT, GL_UNSIGNED_BYTE );
159
160 // From GL_OES_texture_float
Jeff Muizelaarbb1a5be2015-12-02 12:03:46 -0500161 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_FLOAT );
162 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_FLOAT );
Geoff Lang5d601382014-07-22 15:14:06 -0400163 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT );
164 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT );
165 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_FLOAT );
166
167 // From GL_OES_texture_half_float
Geoff Lang4e58af62016-08-26 10:56:52 -0400168 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES );
169 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_HALF_FLOAT_OES );
Geoff Lang5d601382014-07-22 15:14:06 -0400170 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT );
171 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES );
172 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT );
173 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES );
174 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT );
175 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES );
176
177 // From GL_EXT_texture_format_BGRA8888
178 InsertES3FormatCombo(&set, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
179
180 // From GL_EXT_texture_storage
181 // | Internal format | Format | Type |
182 // | | | |
183 InsertES3FormatCombo(&set, GL_ALPHA8_EXT, GL_ALPHA, GL_UNSIGNED_BYTE );
184 InsertES3FormatCombo(&set, GL_LUMINANCE8_EXT, GL_LUMINANCE, GL_UNSIGNED_BYTE );
185 InsertES3FormatCombo(&set, GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE );
186 InsertES3FormatCombo(&set, GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT );
187 InsertES3FormatCombo(&set, GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT );
188 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT );
189 InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT );
190 InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT_OES );
191 InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT );
192 InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT_OES );
193 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT );
194 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES );
195
196 // From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888
197 InsertES3FormatCombo(&set, GL_BGRA8_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
198 InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT);
199 InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
200 InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT);
201 InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
202
Geoff Lang4e58af62016-08-26 10:56:52 -0400203 // From GL_ANGLE_depth_texture and OES_depth_texture
Geoff Lang5d601382014-07-22 15:14:06 -0400204 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8_OES );
Geoff Lang4e58af62016-08-26 10:56:52 -0400205 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT );
206 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
Geoff Lang5d601382014-07-22 15:14:06 -0400207
Vincent Lang25ab4512016-05-13 18:13:59 +0200208 // From GL_EXT_texture_norm16
209 InsertES3FormatCombo(&set, GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT);
210 InsertES3FormatCombo(&set, GL_RG16_EXT, GL_RG, GL_UNSIGNED_SHORT);
211 InsertES3FormatCombo(&set, GL_RGB16_EXT, GL_RGB, GL_UNSIGNED_SHORT);
212 InsertES3FormatCombo(&set, GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT);
213 InsertES3FormatCombo(&set, GL_R16_SNORM_EXT, GL_RED, GL_SHORT);
214 InsertES3FormatCombo(&set, GL_RG16_SNORM_EXT, GL_RG, GL_SHORT);
215 InsertES3FormatCombo(&set, GL_RGB16_SNORM_EXT, GL_RGB, GL_SHORT);
216 InsertES3FormatCombo(&set, GL_RGBA16_SNORM_EXT, GL_RGBA, GL_SHORT);
Geoff Lang4e58af62016-08-26 10:56:52 -0400217 // clang-format on
Vincent Lang25ab4512016-05-13 18:13:59 +0200218
Geoff Lang5d601382014-07-22 15:14:06 -0400219 return set;
220}
221
222static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
223{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500224 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
225 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
226 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
227 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
Geoff Langbaadf232014-08-04 13:58:02 -0400228 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
Martin Radev1be913c2016-07-11 17:59:16 +0300229 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Geoff Lang5d601382014-07-22 15:14:06 -0400230 {
Jamie Madill437fa652016-05-03 15:13:24 -0400231 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400232 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400233 }
234
235 // The type and format are valid if any supported internal format has that type and format
236 bool formatSupported = false;
237 bool typeSupported = false;
238
239 static const ES3FormatCombinationSet es3FormatSet = BuildES3FormatSet();
240 for (ES3FormatCombinationSet::const_iterator i = es3FormatSet.begin(); i != es3FormatSet.end(); i++)
241 {
242 if (i->format == format || i->type == type)
243 {
244 const gl::InternalFormat &info = gl::GetInternalFormatInfo(i->internalFormat);
Martin Radev1be913c2016-07-11 17:59:16 +0300245 bool supported =
246 info.textureSupport(context->getClientMajorVersion(), context->getExtensions());
Geoff Langbaadf232014-08-04 13:58:02 -0400247 if (supported && i->type == type)
Geoff Lang5d601382014-07-22 15:14:06 -0400248 {
249 typeSupported = true;
250 }
Geoff Langbaadf232014-08-04 13:58:02 -0400251 if (supported && i->format == format)
Geoff Lang5d601382014-07-22 15:14:06 -0400252 {
253 formatSupported = true;
254 }
Geoff Langbaadf232014-08-04 13:58:02 -0400255
256 // Early-out if both type and format are supported now
257 if (typeSupported && formatSupported)
258 {
259 break;
260 }
Geoff Lang5d601382014-07-22 15:14:06 -0400261 }
262 }
263
264 if (!typeSupported || !formatSupported)
265 {
Jamie Madill437fa652016-05-03 15:13:24 -0400266 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400267 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400268 }
269
270 // Check if this is a valid format combination to load texture data
271 ES3FormatCombination searchFormat;
272 searchFormat.internalFormat = internalFormat;
273 searchFormat.format = format;
274 searchFormat.type = type;
275
276 if (es3FormatSet.find(searchFormat) == es3FormatSet.end())
277 {
Jamie Madill437fa652016-05-03 15:13:24 -0400278 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400279 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400280 }
281
282 return true;
283}
284
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500285bool ValidateES3TexImageParametersBase(Context *context,
286 GLenum target,
287 GLint level,
288 GLenum internalformat,
289 bool isCompressed,
290 bool isSubImage,
291 GLint xoffset,
292 GLint yoffset,
293 GLint zoffset,
294 GLsizei width,
295 GLsizei height,
296 GLsizei depth,
297 GLint border,
298 GLenum format,
299 GLenum type,
300 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400301{
302 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -0700303 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400304 {
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
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400309 // Verify zero border
310 if (border != 0)
311 {
Jamie Madill437fa652016-05-03 15:13:24 -0400312 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400313 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400314 }
315
Jamie Madill6f38f822014-06-06 17:12:20 -0400316 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
317 std::numeric_limits<GLsizei>::max() - xoffset < width ||
318 std::numeric_limits<GLsizei>::max() - yoffset < height ||
319 std::numeric_limits<GLsizei>::max() - zoffset < depth)
320 {
Jamie Madill437fa652016-05-03 15:13:24 -0400321 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400322 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400323 }
324
Geoff Langaae65a42014-05-26 12:43:44 -0400325 const gl::Caps &caps = context->getCaps();
326
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400327 switch (target)
328 {
329 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500330 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
331 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400332 {
Jamie Madill437fa652016-05-03 15:13:24 -0400333 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500334 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400335 }
336 break;
337
338 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
339 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
340 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
341 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
342 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
343 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500344 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400345 {
Jamie Madill437fa652016-05-03 15:13:24 -0400346 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500347 return false;
348 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400349
Geoff Langa9be0dc2014-12-17 12:34:40 -0500350 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
351 {
Jamie Madill437fa652016-05-03 15:13:24 -0400352 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500353 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400354 }
355 break;
356
357 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500358 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
359 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
360 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400361 {
Jamie Madill437fa652016-05-03 15:13:24 -0400362 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500363 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400364 }
365 break;
366
Geoff Langa9be0dc2014-12-17 12:34:40 -0500367 case GL_TEXTURE_2D_ARRAY:
368 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
369 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
Geoff Langb92c1332015-09-04 12:54:55 -0400370 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500371 {
Jamie Madill437fa652016-05-03 15:13:24 -0400372 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500373 return false;
374 }
375 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400376
377 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400378 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400379 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400380 }
381
Geoff Lang691e58c2014-12-19 17:03:25 -0500382 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400383 if (!texture)
384 {
Jamie Madill437fa652016-05-03 15:13:24 -0400385 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400386 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400387 }
388
Geoff Lang69cce582015-09-17 13:20:36 -0400389 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400390 {
Jamie Madill437fa652016-05-03 15:13:24 -0400391 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400392 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400393 }
394
395 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400396 GLenum actualInternalFormat =
397 isSubImage ? texture->getFormat(target, level).asSized() : internalformat;
Geoff Lang5d601382014-07-22 15:14:06 -0400398 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400399 if (isCompressed)
400 {
tmartino7c102692015-10-02 16:43:40 -0400401 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400402 {
Jamie Madill437fa652016-05-03 15:13:24 -0400403 context->handleError(Error(
tmartino7c102692015-10-02 16:43:40 -0400404 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format."));
Geoff Langb1196682014-07-23 13:47:29 -0400405 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400406 }
407
tmartino7c102692015-10-02 16:43:40 -0400408 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400409 {
Jamie Madill437fa652016-05-03 15:13:24 -0400410 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400411 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400412 }
413
Martin Radev1be913c2016-07-11 17:59:16 +0300414 if (!actualFormatInfo.textureSupport(context->getClientMajorVersion(),
415 context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400416 {
Jamie Madill437fa652016-05-03 15:13:24 -0400417 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang839ce0b2015-10-23 13:13:12 -0400418 return false;
419 }
420
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400421 if (target == GL_TEXTURE_3D)
422 {
Jamie Madill437fa652016-05-03 15:13:24 -0400423 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400424 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400425 }
426 }
427 else
428 {
Geoff Langbaadf232014-08-04 13:58:02 -0400429 if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400430 {
Geoff Lang5d601382014-07-22 15:14:06 -0400431 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400432 }
433
434 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
435 {
Jamie Madill437fa652016-05-03 15:13:24 -0400436 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400437 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400438 }
439 }
440
441 // Validate sub image parameters
442 if (isSubImage)
443 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500444 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400445 {
Jamie Madill437fa652016-05-03 15:13:24 -0400446 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400447 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400448 }
449
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400450 if (width == 0 || height == 0 || depth == 0)
451 {
452 return false;
453 }
454
455 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
456 {
Jamie Madill437fa652016-05-03 15:13:24 -0400457 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400458 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400459 }
460
461 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
462 std::numeric_limits<GLsizei>::max() - yoffset < height ||
463 std::numeric_limits<GLsizei>::max() - zoffset < depth)
464 {
Jamie Madill437fa652016-05-03 15:13:24 -0400465 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400466 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400467 }
468
Geoff Langa9be0dc2014-12-17 12:34:40 -0500469 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
470 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
471 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400472 {
Jamie Madill437fa652016-05-03 15:13:24 -0400473 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400474 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400475 }
476 }
477
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400478 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700479 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400480 if (pixelUnpackBuffer != NULL)
481 {
482 // ...the data would be unpacked from the buffer object such that the memory reads required
483 // would exceed the data store size.
Geoff Lang5d601382014-07-22 15:14:06 -0400484 GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400485 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -0700486 const gl::Extents size(width, height, depth);
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700487 const auto &unpack = context->getGLState().getUnpackState();
Jamie Madill4b4cdff2016-06-06 13:53:38 -0700488
Olli Etuaho989cac32016-06-08 16:18:49 -0700489 bool targetIs3D = target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY;
Corentin Wallezc5cacd62016-09-14 14:50:24 -0400490 auto endByteOrErr = formatInfo.computeUnpackEndByte(type, size, unpack, targetIs3D);
491 if (endByteOrErr.isError())
Olli Etuaho989cac32016-06-08 16:18:49 -0700492 {
Corentin Wallezc5cacd62016-09-14 14:50:24 -0400493 context->handleError(endByteOrErr.getError());
Olli Etuaho989cac32016-06-08 16:18:49 -0700494 return false;
495 }
Corentin Wallezc5cacd62016-09-14 14:50:24 -0400496 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
497 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
498 checkedEndByte += checkedOffset;
Olli Etuaho989cac32016-06-08 16:18:49 -0700499
Corentin Wallezc5cacd62016-09-14 14:50:24 -0400500 if (!checkedEndByte.IsValid() ||
501 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400502 {
503 // Overflow past the end of the buffer
Jamie Madill437fa652016-05-03 15:13:24 -0400504 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400505 return false;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400506 }
507
508 // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
509 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400510 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400511 {
Jamie Madillc751d1e2014-10-21 17:46:29 -0400512 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
513
Jamie Madille2e406c2016-06-02 13:04:10 -0400514 if ((checkedOffset.ValueOrDie() % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400515 {
Jamie Madill437fa652016-05-03 15:13:24 -0400516 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400517 return false;
518 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400519 }
520
Jamie Madill7a5f7382014-03-05 15:01:24 -0500521 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700522 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500523 {
Jamie Madill437fa652016-05-03 15:13:24 -0400524 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400525 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500526 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400527 }
528
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400529 return true;
530}
531
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500532bool ValidateES3TexImage2DParameters(Context *context,
533 GLenum target,
534 GLint level,
535 GLenum internalformat,
536 bool isCompressed,
537 bool isSubImage,
538 GLint xoffset,
539 GLint yoffset,
540 GLint zoffset,
541 GLsizei width,
542 GLsizei height,
543 GLsizei depth,
544 GLint border,
545 GLenum format,
546 GLenum type,
547 const GLvoid *pixels)
548{
549 if (!ValidTexture2DDestinationTarget(context, target))
550 {
Jamie Madill437fa652016-05-03 15:13:24 -0400551 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500552 return false;
553 }
554
555 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
556 isSubImage, xoffset, yoffset, zoffset, width, height,
557 depth, border, format, type, pixels);
558}
559
560bool ValidateES3TexImage3DParameters(Context *context,
561 GLenum target,
562 GLint level,
563 GLenum internalformat,
564 bool isCompressed,
565 bool isSubImage,
566 GLint xoffset,
567 GLint yoffset,
568 GLint zoffset,
569 GLsizei width,
570 GLsizei height,
571 GLsizei depth,
572 GLint border,
573 GLenum format,
574 GLenum type,
575 const GLvoid *pixels)
576{
577 if (!ValidTexture3DDestinationTarget(context, target))
578 {
Jamie Madill437fa652016-05-03 15:13:24 -0400579 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500580 return false;
581 }
582
583 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
584 isSubImage, xoffset, yoffset, zoffset, width, height,
585 depth, border, format, type, pixels);
586}
587
Geoff Lang5d601382014-07-22 15:14:06 -0400588struct EffectiveInternalFormatInfo
589{
590 GLenum mEffectiveFormat;
591 GLenum mDestFormat;
592 GLuint mMinRedBits;
593 GLuint mMaxRedBits;
594 GLuint mMinGreenBits;
595 GLuint mMaxGreenBits;
596 GLuint mMinBlueBits;
597 GLuint mMaxBlueBits;
598 GLuint mMinAlphaBits;
599 GLuint mMaxAlphaBits;
600
601 EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits,
602 GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits,
603 GLuint minAlphaBits, GLuint maxAlphaBits)
604 : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits),
605 mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits),
606 mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits),
607 mMaxAlphaBits(maxAlphaBits) {};
608};
609
610typedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
611
612static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList()
613{
614 EffectiveInternalFormatList list;
615
616 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
617 // linear source buffer component sizes.
618 // | Source channel min/max sizes |
619 // Effective Internal Format | N/A | R | G | B | A |
620 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8));
621 list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0));
622 list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0));
623 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0));
624 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0));
625 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4));
626 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1));
627 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8));
628 list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2));
629
630 return list;
631}
632
633static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList()
634{
635 EffectiveInternalFormatList list;
636
637 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
638 // linear source buffer component sizes.
639 // | Source channel min/max sizes |
640 // Effective Internal Format | Dest Format | R | G | B | A |
641 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
642 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX));
643 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
644 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX));
645 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX));
646 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4));
647 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1));
648 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8));
649
650 return list;
651}
652
653static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
654 GLenum *outEffectiveFormat)
655{
656 const EffectiveInternalFormatList *list = NULL;
657 GLenum targetFormat = GL_NONE;
658
659 if (destFormat.pixelBytes > 0)
660 {
661 static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList();
662 list = &sizedList;
663 }
664 else
665 {
666 static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList();
667 list = &unsizedList;
668 targetFormat = destFormat.format;
669 }
670
671 for (size_t curFormat = 0; curFormat < list->size(); ++curFormat)
672 {
673 const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat);
674 if ((formatInfo.mDestFormat == targetFormat) &&
675 (formatInfo.mMinRedBits <= srcFormat.redBits && formatInfo.mMaxRedBits >= srcFormat.redBits) &&
676 (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) &&
677 (formatInfo.mMinBlueBits <= srcFormat.blueBits && formatInfo.mMaxBlueBits >= srcFormat.blueBits) &&
678 (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits))
679 {
680 *outEffectiveFormat = formatInfo.mEffectiveFormat;
681 return true;
682 }
683 }
684
685 return false;
686}
687
688struct CopyConversion
689{
690 GLenum mTextureFormat;
691 GLenum mFramebufferFormat;
692
693 CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
694 : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
695
696 bool operator<(const CopyConversion& other) const
697 {
698 return memcmp(this, &other, sizeof(CopyConversion)) < 0;
699 }
700};
701
702typedef std::set<CopyConversion> CopyConversionSet;
703
704static CopyConversionSet BuildValidES3CopyTexImageCombinations()
705{
706 CopyConversionSet set;
707
708 // From ES 3.0.1 spec, table 3.15
709 set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
710 set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
711 set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
712 set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
713 set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
714 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
715 set.insert(CopyConversion(GL_RED, GL_RED));
716 set.insert(CopyConversion(GL_RED, GL_RG));
717 set.insert(CopyConversion(GL_RED, GL_RGB));
718 set.insert(CopyConversion(GL_RED, GL_RGBA));
719 set.insert(CopyConversion(GL_RG, GL_RG));
720 set.insert(CopyConversion(GL_RG, GL_RGB));
721 set.insert(CopyConversion(GL_RG, GL_RGBA));
722 set.insert(CopyConversion(GL_RGB, GL_RGB));
723 set.insert(CopyConversion(GL_RGB, GL_RGBA));
724 set.insert(CopyConversion(GL_RGBA, GL_RGBA));
725
726 // Necessary for ANGLE back-buffers
727 set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
728 set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
729 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
730 set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
731 set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
732 set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
733 set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
Geoff Lang4e58af62016-08-26 10:56:52 -0400734 set.insert(CopyConversion(GL_BGRA_EXT, GL_BGRA_EXT));
Geoff Lang5d601382014-07-22 15:14:06 -0400735
736 set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
737 set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
738 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
739 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
740 set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
741 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
742 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
743 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
744 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
745 set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
746
747 return set;
748}
749
Corentin Wallez76287682016-04-25 09:23:38 -0400750static bool EqualOrFirstZero(GLuint first, GLuint second)
751{
752 return first == 0 || first == second;
753}
754
Jamie Madill0c8abca2016-07-22 20:21:26 -0400755static bool IsValidES3CopyTexImageCombination(const Format &textureFormat,
756 const Format &framebufferFormat,
757 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400758{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400759 const auto &textureFormatInfo = *textureFormat.info;
760 const auto &framebufferFormatInfo = *framebufferFormat.info;
Geoff Lang5d601382014-07-22 15:14:06 -0400761
762 static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
Jamie Madill0c8abca2016-07-22 20:21:26 -0400763 if (conversionSet.find(CopyConversion(textureFormatInfo.format,
764 framebufferFormatInfo.format)) != conversionSet.end())
Geoff Lang5d601382014-07-22 15:14:06 -0400765 {
766 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
767 // must both be signed, unsigned, or fixed point and both source and destinations
768 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
769 // conversion between fixed and floating point.
770
Jamie Madill0c8abca2016-07-22 20:21:26 -0400771 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
772 (framebufferFormatInfo.colorEncoding == GL_SRGB))
Geoff Lang5d601382014-07-22 15:14:06 -0400773 {
774 return false;
775 }
776
Jamie Madill0c8abca2016-07-22 20:21:26 -0400777 if (((textureFormatInfo.componentType == GL_INT) !=
778 (framebufferFormatInfo.componentType == GL_INT)) ||
779 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
780 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
Geoff Lang5d601382014-07-22 15:14:06 -0400781 {
782 return false;
783 }
784
Jamie Madill0c8abca2016-07-22 20:21:26 -0400785 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
786 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
787 textureFormatInfo.componentType == GL_FLOAT) &&
788 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
789 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
790 framebufferFormatInfo.componentType == GL_FLOAT))
Geoff Lang5d601382014-07-22 15:14:06 -0400791 {
792 return false;
793 }
794
795 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
796 // The effective internal format of the source buffer is determined with the following rules applied in order:
797 // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
798 // effective internal format is the source buffer's sized internal format.
799 // * If the source buffer is a texture that was created with an unsized base internal format, then the
800 // effective internal format is the source image array's effective internal format, as specified by table
801 // 3.12, which is determined from the <format> and <type> that were used when the source image array was
802 // specified by TexImage*.
803 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
804 // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
805 // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
806 // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
807 // is SRGB.
808 const InternalFormat *sourceEffectiveFormat = NULL;
809 if (readBufferHandle != 0)
810 {
811 // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
Jamie Madill0c8abca2016-07-22 20:21:26 -0400812 if (framebufferFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400813 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400814 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400815 }
816 else
817 {
818 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
819 // texture. We can use the same table we use when creating textures to get its effective sized format.
Jamie Madill0c8abca2016-07-22 20:21:26 -0400820 GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferFormatInfo.format,
821 framebufferFormatInfo.type);
Geoff Lang051dbc72015-01-05 15:48:58 -0500822 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400823 }
824 }
825 else
826 {
827 // The effective internal format must be derived from the source framebuffer's channel sizes.
828 // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
Jamie Madill0c8abca2016-07-22 20:21:26 -0400829 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400830 {
831 GLenum effectiveFormat;
Jamie Madill0c8abca2016-07-22 20:21:26 -0400832 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
833 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400834 {
835 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
836 }
837 else
838 {
839 return false;
840 }
841 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400842 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
Geoff Lang5d601382014-07-22 15:14:06 -0400843 {
844 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Jamie Madill0c8abca2016-07-22 20:21:26 -0400845 if (textureFormat.sized &&
846 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
847 (framebufferFormatInfo.greenBits >= 1 &&
848 framebufferFormatInfo.greenBits <= 8) &&
849 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
850 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
Geoff Lang5d601382014-07-22 15:14:06 -0400851 {
852 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
853 }
854 else
855 {
856 return false;
857 }
858 }
859 else
860 {
861 UNREACHABLE();
862 return false;
863 }
864 }
865
Jamie Madill0c8abca2016-07-22 20:21:26 -0400866 if (textureFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400867 {
Corentin Wallez76287682016-04-25 09:23:38 -0400868 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination
869 // format is sized, component sizes of the source and destination formats must exactly
870 // match if the destination format exists.
Jamie Madill0c8abca2016-07-22 20:21:26 -0400871 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
872 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
873 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
874 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
Geoff Lang5d601382014-07-22 15:14:06 -0400875 {
876 return false;
877 }
878 }
879
Geoff Lang5d601382014-07-22 15:14:06 -0400880 return true; // A conversion function exists, and no rule in the specification has precluded conversion
881 // between these formats.
882 }
883
884 return false;
885}
886
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500887bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
888 GLenum target,
889 GLint level,
890 GLenum internalformat,
891 bool isSubImage,
892 GLint xoffset,
893 GLint yoffset,
894 GLint zoffset,
895 GLint x,
896 GLint y,
897 GLsizei width,
898 GLsizei height,
899 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400900{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400901 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400902 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400903 xoffset, yoffset, zoffset, x, y, width, height, border,
904 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400905 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400906 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400907 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400908 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400909
Jamie Madill51f40ec2016-06-15 14:06:00 -0400910 const auto &state = context->getGLState();
911 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
912 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400913
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700914 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400915 {
Jamie Madill437fa652016-05-03 15:13:24 -0400916 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400917 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400918 }
919
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700920 if (readFramebufferID != 0 && framebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400921 {
Jamie Madill437fa652016-05-03 15:13:24 -0400922 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400923 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400924 }
925
Jamie Madill0c8abca2016-07-22 20:21:26 -0400926 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400927
928 if (isSubImage)
929 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400930 if (!IsValidES3CopyTexImageCombination(textureFormat, source->getFormat(),
Jamie Madillc29968b2016-01-20 11:17:23 -0500931 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400932 {
Jamie Madill437fa652016-05-03 15:13:24 -0400933 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400934 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400935 }
936 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400937 else
938 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400939 // Use format/type from the source FBO. (Might not be perfect for all cases?)
940 const auto framebufferFormat = source->getFormat();
941 Format copyFormat(internalformat, framebufferFormat.format, framebufferFormat.type);
942 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400943 {
Jamie Madill437fa652016-05-03 15:13:24 -0400944 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400945 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400946 }
947 }
948
Geoff Lang784a8fd2013-09-24 12:33:16 -0400949 // If width or height is zero, it is a no-op. Return false without setting an error.
950 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400951}
952
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500953bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
954 GLenum target,
955 GLint level,
956 GLenum internalformat,
957 bool isSubImage,
958 GLint xoffset,
959 GLint yoffset,
960 GLint zoffset,
961 GLint x,
962 GLint y,
963 GLsizei width,
964 GLsizei height,
965 GLint border)
966{
967 if (!ValidTexture2DDestinationTarget(context, target))
968 {
Jamie Madill437fa652016-05-03 15:13:24 -0400969 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500970 return false;
971 }
972
973 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
974 xoffset, yoffset, zoffset, x, y, width, height,
975 border);
976}
977
978bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
979 GLenum target,
980 GLint level,
981 GLenum internalformat,
982 bool isSubImage,
983 GLint xoffset,
984 GLint yoffset,
985 GLint zoffset,
986 GLint x,
987 GLint y,
988 GLsizei width,
989 GLsizei height,
990 GLint border)
991{
992 if (!ValidTexture3DDestinationTarget(context, target))
993 {
Jamie Madill437fa652016-05-03 15:13:24 -0400994 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500995 return false;
996 }
997
998 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
999 xoffset, yoffset, zoffset, x, y, width, height,
1000 border);
1001}
1002
1003bool ValidateES3TexStorageParametersBase(Context *context,
1004 GLenum target,
1005 GLsizei levels,
1006 GLenum internalformat,
1007 GLsizei width,
1008 GLsizei height,
1009 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001010{
1011 if (width < 1 || height < 1 || depth < 1 || levels < 1)
1012 {
Jamie Madill437fa652016-05-03 15:13:24 -04001013 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001014 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001015 }
1016
Geoff Langb92c1332015-09-04 12:54:55 -04001017 GLsizei maxDim = std::max(width, height);
1018 if (target != GL_TEXTURE_2D_ARRAY)
1019 {
1020 maxDim = std::max(maxDim, depth);
1021 }
1022
1023 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001024 {
Jamie Madill437fa652016-05-03 15:13:24 -04001025 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001026 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001027 }
1028
Geoff Langaae65a42014-05-26 12:43:44 -04001029 const gl::Caps &caps = context->getCaps();
1030
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001031 switch (target)
1032 {
1033 case GL_TEXTURE_2D:
1034 {
Geoff Langaae65a42014-05-26 12:43:44 -04001035 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1036 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001037 {
Jamie Madill437fa652016-05-03 15:13:24 -04001038 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001039 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001040 }
1041 }
1042 break;
1043
Geoff Lang01c21d22013-09-24 11:52:16 -04001044 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001045 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001046 if (width != height)
1047 {
Jamie Madill437fa652016-05-03 15:13:24 -04001048 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001049 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001050 }
1051
Geoff Langaae65a42014-05-26 12:43:44 -04001052 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001053 {
Jamie Madill437fa652016-05-03 15:13:24 -04001054 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001055 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001056 }
1057 }
1058 break;
1059
1060 case GL_TEXTURE_3D:
1061 {
Geoff Langaae65a42014-05-26 12:43:44 -04001062 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
1063 static_cast<GLuint>(height) > caps.max3DTextureSize ||
1064 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001065 {
Jamie Madill437fa652016-05-03 15:13:24 -04001066 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001067 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001068 }
1069 }
1070 break;
1071
1072 case GL_TEXTURE_2D_ARRAY:
1073 {
Geoff Langaae65a42014-05-26 12:43:44 -04001074 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1075 static_cast<GLuint>(height) > caps.max2DTextureSize ||
1076 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001077 {
Jamie Madill437fa652016-05-03 15:13:24 -04001078 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001079 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001080 }
1081 }
1082 break;
1083
1084 default:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001085 UNREACHABLE();
Geoff Langb1196682014-07-23 13:47:29 -04001086 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001087 }
1088
Geoff Lang691e58c2014-12-19 17:03:25 -05001089 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001090 if (!texture || texture->id() == 0)
1091 {
Jamie Madill437fa652016-05-03 15:13:24 -04001092 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001093 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001094 }
1095
Geoff Lang69cce582015-09-17 13:20:36 -04001096 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001097 {
Jamie Madill437fa652016-05-03 15:13:24 -04001098 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001099 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001100 }
1101
Geoff Lang5d601382014-07-22 15:14:06 -04001102 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Martin Radev1be913c2016-07-11 17:59:16 +03001103 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001104 {
Jamie Madill437fa652016-05-03 15:13:24 -04001105 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001106 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001107 }
1108
Geoff Lang5d601382014-07-22 15:14:06 -04001109 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001110 {
Jamie Madill437fa652016-05-03 15:13:24 -04001111 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001112 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001113 }
1114
1115 return true;
1116}
1117
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001118bool ValidateES3TexStorage2DParameters(Context *context,
1119 GLenum target,
1120 GLsizei levels,
1121 GLenum internalformat,
1122 GLsizei width,
1123 GLsizei height,
1124 GLsizei depth)
1125{
1126 if (!ValidTexture2DTarget(context, target))
1127 {
Jamie Madill437fa652016-05-03 15:13:24 -04001128 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001129 return false;
1130 }
1131
1132 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1133 height, depth);
1134}
1135
1136bool ValidateES3TexStorage3DParameters(Context *context,
1137 GLenum target,
1138 GLsizei levels,
1139 GLenum internalformat,
1140 GLsizei width,
1141 GLsizei height,
1142 GLsizei depth)
1143{
1144 if (!ValidTexture3DTarget(context, target))
1145 {
Jamie Madill437fa652016-05-03 15:13:24 -04001146 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001147 return false;
1148 }
1149
1150 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1151 height, depth);
1152}
1153
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001154bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1155{
Martin Radev1be913c2016-07-11 17:59:16 +03001156 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001157 {
Jamie Madill437fa652016-05-03 15:13:24 -04001158 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001159 return false;
1160 }
1161
1162 return ValidateBeginQueryBase(context, target, id);
1163}
1164
1165bool ValidateEndQuery(gl::Context *context, GLenum target)
1166{
Martin Radev1be913c2016-07-11 17:59:16 +03001167 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001168 {
Jamie Madill437fa652016-05-03 15:13:24 -04001169 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001170 return false;
1171 }
1172
1173 return ValidateEndQueryBase(context, target);
1174}
1175
1176bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1177{
Martin Radev1be913c2016-07-11 17:59:16 +03001178 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001179 {
Jamie Madill437fa652016-05-03 15:13:24 -04001180 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001181 return false;
1182 }
1183
1184 return ValidateGetQueryivBase(context, target, pname);
1185}
1186
1187bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1188{
Martin Radev1be913c2016-07-11 17:59:16 +03001189 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001190 {
Jamie Madill437fa652016-05-03 15:13:24 -04001191 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001192 return false;
1193 }
1194
1195 return ValidateGetQueryObjectValueBase(context, id, pname);
1196}
1197
Geoff Langb1196682014-07-23 13:47:29 -04001198bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
Jamie Madill570f7c82014-07-03 10:38:54 -04001199 GLuint texture, GLint level, GLint layer)
1200{
Martin Radev1be913c2016-07-11 17:59:16 +03001201 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001202 {
Jamie Madill437fa652016-05-03 15:13:24 -04001203 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001204 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001205 }
1206
Jamie Madill55ec3b12014-07-03 10:38:57 -04001207 if (layer < 0)
1208 {
Jamie Madill437fa652016-05-03 15:13:24 -04001209 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001210 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001211 }
1212
1213 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1214 {
1215 return false;
1216 }
1217
1218 const gl::Caps &caps = context->getCaps();
1219 if (texture != 0)
1220 {
1221 gl::Texture *tex = context->getTexture(texture);
1222 ASSERT(tex);
1223
1224 switch (tex->getTarget())
1225 {
1226 case GL_TEXTURE_2D_ARRAY:
1227 {
1228 if (level > gl::log2(caps.max2DTextureSize))
1229 {
Jamie Madill437fa652016-05-03 15:13:24 -04001230 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001231 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001232 }
1233
1234 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1235 {
Jamie Madill437fa652016-05-03 15:13:24 -04001236 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001237 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001238 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001239 }
1240 break;
1241
1242 case GL_TEXTURE_3D:
1243 {
1244 if (level > gl::log2(caps.max3DTextureSize))
1245 {
Jamie Madill437fa652016-05-03 15:13:24 -04001246 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001247 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001248 }
1249
1250 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1251 {
Jamie Madill437fa652016-05-03 15:13:24 -04001252 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001253 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001254 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001255 }
1256 break;
1257
1258 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001259 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001260 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001261 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001262
Jamie Madilla3944d42016-07-22 22:13:26 -04001263 const auto &format = tex->getFormat(tex->getTarget(), level);
1264 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001265 {
Jamie Madill437fa652016-05-03 15:13:24 -04001266 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001267 return false;
1268 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001269 }
1270
1271 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001272}
1273
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001274bool ValidES3ReadFormatType(ValidationContext *context,
1275 GLenum internalFormat,
1276 GLenum format,
1277 GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001278{
Geoff Lang5d601382014-07-22 15:14:06 -04001279 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
1280
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001281 switch (format)
1282 {
1283 case GL_RGBA:
1284 switch (type)
1285 {
1286 case GL_UNSIGNED_BYTE:
1287 break;
Vincent Lang25ab4512016-05-13 18:13:59 +02001288 case GL_UNSIGNED_SHORT:
1289 if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
1290 internalFormatInfo.type != GL_UNSIGNED_SHORT)
1291 {
1292 return false;
1293 }
1294 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001295 case GL_UNSIGNED_INT_2_10_10_10_REV:
1296 if (internalFormat != GL_RGB10_A2)
1297 {
1298 return false;
1299 }
1300 break;
Geoff Lang1ec57f82013-10-16 11:43:23 -04001301 case GL_FLOAT:
Geoff Lang5d601382014-07-22 15:14:06 -04001302 if (internalFormatInfo.componentType != GL_FLOAT)
Geoff Lang1ec57f82013-10-16 11:43:23 -04001303 {
1304 return false;
1305 }
1306 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001307 default:
1308 return false;
1309 }
1310 break;
1311 case GL_RGBA_INTEGER:
1312 switch (type)
1313 {
1314 case GL_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001315 if (internalFormatInfo.componentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001316 {
1317 return false;
1318 }
1319 break;
1320 case GL_UNSIGNED_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001321 if (internalFormatInfo.componentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001322 {
1323 return false;
1324 }
1325 break;
1326 default:
1327 return false;
1328 }
1329 break;
1330 case GL_BGRA_EXT:
1331 switch (type)
1332 {
1333 case GL_UNSIGNED_BYTE:
1334 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1335 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1336 break;
1337 default:
1338 return false;
1339 }
1340 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001341 case GL_RG_EXT:
1342 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001343 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001344 {
1345 return false;
1346 }
1347 switch (type)
1348 {
1349 case GL_UNSIGNED_BYTE:
1350 break;
Vincent Lang25ab4512016-05-13 18:13:59 +02001351 case GL_UNSIGNED_SHORT:
1352 if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
1353 internalFormatInfo.type != GL_UNSIGNED_SHORT)
1354 {
1355 return false;
1356 }
1357 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001358 default:
1359 return false;
1360 }
1361 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001362 default:
1363 return false;
1364 }
1365 return true;
1366}
1367
Corentin Walleze0902642014-11-04 12:32:15 -08001368bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
1369 GLenum internalformat, GLsizei width, GLsizei height)
1370{
1371 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
1372 {
1373 return false;
1374 }
1375
1376 //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.
1377 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1378 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
1379 {
Jamie Madill437fa652016-05-03 15:13:24 -04001380 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -08001381 return false;
1382 }
1383
1384 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
1385 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1386 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1387 {
Jamie Madill437fa652016-05-03 15:13:24 -04001388 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001389 Error(GL_INVALID_OPERATION,
1390 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001391 return false;
1392 }
1393
1394 return true;
1395}
1396
Austin Kinross08332632015-05-05 13:35:47 -07001397bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
1398 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399{
Martin Radev1be913c2016-07-11 17:59:16 +03001400 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001401 {
Jamie Madill437fa652016-05-03 15:13:24 -04001402 context->handleError(
1403 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001404 return false;
1405 }
1406
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001407 bool defaultFramebuffer = false;
1408
1409 switch (target)
1410 {
1411 case GL_DRAW_FRAMEBUFFER:
1412 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001413 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1414 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001415 case GL_READ_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001416 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1417 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001418 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001419 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001420 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001421 }
1422
Austin Kinross08332632015-05-05 13:35:47 -07001423 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001424}
1425
Jamie Madillc29968b2016-01-20 11:17:23 -05001426bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001427{
Martin Radev1be913c2016-07-11 17:59:16 +03001428 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001429 {
Jamie Madill437fa652016-05-03 15:13:24 -04001430 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001431 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001432 }
1433
Jamie Madill51f40ec2016-06-15 14:06:00 -04001434 if (context->getGLState().getDrawFramebuffer()->checkStatus(context->getContextState()) !=
1435 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001436 {
Jamie Madill437fa652016-05-03 15:13:24 -04001437 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001438 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001439 }
1440
1441 return true;
1442}
1443
Olli Etuaho71dfb362016-03-10 14:04:27 +02001444bool ValidateDrawRangeElements(Context *context,
1445 GLenum mode,
1446 GLuint start,
1447 GLuint end,
1448 GLsizei count,
1449 GLenum type,
1450 const GLvoid *indices,
1451 IndexRange *indexRange)
1452{
Martin Radev1be913c2016-07-11 17:59:16 +03001453 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001454 {
Jamie Madill437fa652016-05-03 15:13:24 -04001455 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001456 return false;
1457 }
1458
1459 if (end < start)
1460 {
Jamie Madill437fa652016-05-03 15:13:24 -04001461 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001462 return false;
1463 }
1464
1465 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1466 {
1467 return false;
1468 }
1469
1470 if (indexRange->end > end || indexRange->start < start)
1471 {
1472 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001473 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001474 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1475 return false;
1476 }
1477 return true;
1478}
1479
Geoff Langb1196682014-07-23 13:47:29 -04001480bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001481{
Martin Radev1be913c2016-07-11 17:59:16 +03001482 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001483 {
Jamie Madill437fa652016-05-03 15:13:24 -04001484 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001485 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001486 }
1487
Jamie Madill78f41802014-08-25 15:47:55 -04001488 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001489}
1490
Jamie Madillb885e572015-02-03 16:16:04 -05001491bool ValidateReadBuffer(Context *context, GLenum src)
1492{
Martin Radev1be913c2016-07-11 17:59:16 +03001493 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001494 {
Jamie Madill437fa652016-05-03 15:13:24 -04001495 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001496 return false;
1497 }
1498
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001499 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001500
1501 if (readFBO == nullptr)
1502 {
Jamie Madill437fa652016-05-03 15:13:24 -04001503 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001504 return false;
1505 }
1506
1507 if (src == GL_NONE)
1508 {
1509 return true;
1510 }
1511
Olli Etuaho84c9f592016-03-09 14:37:25 +02001512 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001513 {
Jamie Madill437fa652016-05-03 15:13:24 -04001514 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001515 return false;
1516 }
1517
1518 if (readFBO->id() == 0)
1519 {
1520 if (src != GL_BACK)
1521 {
1522 const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001523 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001524 return false;
1525 }
1526 }
1527 else
1528 {
1529 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1530
1531 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1532 {
1533 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001534 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001535 return false;
1536 }
1537 }
1538
1539 return true;
1540}
1541
Jamie Madill86af3d22015-07-21 15:14:07 -04001542bool ValidateCompressedTexImage3D(Context *context,
1543 GLenum target,
1544 GLint level,
1545 GLenum internalformat,
1546 GLsizei width,
1547 GLsizei height,
1548 GLsizei depth,
1549 GLint border,
1550 GLsizei imageSize,
1551 const GLvoid *data)
1552{
Martin Radev1be913c2016-07-11 17:59:16 +03001553 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001554 {
Jamie Madill437fa652016-05-03 15:13:24 -04001555 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001556 return false;
1557 }
1558
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001559 if (!ValidTextureTarget(context, target))
1560 {
1561 context->handleError(Error(GL_INVALID_ENUM));
1562 return false;
1563 }
1564
Jamie Madille2e406c2016-06-02 13:04:10 -04001565 // Validate image size
1566 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1567 {
1568 context->handleError(Error(GL_INVALID_VALUE));
1569 return false;
1570 }
1571
Jamie Madill86af3d22015-07-21 15:14:07 -04001572 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001573 if (!formatInfo.compressed)
1574 {
1575 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1576 return false;
1577 }
1578
Jamie Madill513558d2016-06-02 13:04:11 -04001579 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001580 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001581 if (blockSizeOrErr.isError())
1582 {
Jamie Madill513558d2016-06-02 13:04:11 -04001583 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001584 return false;
1585 }
1586 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001587 {
Jamie Madill437fa652016-05-03 15:13:24 -04001588 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001589 return false;
1590 }
1591
1592 // 3D texture target validation
1593 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1594 {
Jamie Madill437fa652016-05-03 15:13:24 -04001595 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001596 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1597 return false;
1598 }
1599
1600 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001601 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
1602 0, width, height, depth, border, GL_NONE, GL_NONE, data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001603 {
1604 return false;
1605 }
1606
1607 return true;
1608}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001609
1610bool ValidateBindVertexArray(Context *context, GLuint array)
1611{
Martin Radev1be913c2016-07-11 17:59:16 +03001612 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001613 {
Jamie Madill437fa652016-05-03 15:13:24 -04001614 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001615 return false;
1616 }
1617
1618 return ValidateBindVertexArrayBase(context, array);
1619}
1620
Austin Kinrossbc781f32015-10-26 09:27:38 -07001621bool ValidateIsVertexArray(Context *context)
1622{
Martin Radev1be913c2016-07-11 17:59:16 +03001623 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001624 {
Jamie Madill437fa652016-05-03 15:13:24 -04001625 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001626 return false;
1627 }
1628
1629 return true;
1630}
Geoff Langc5629752015-12-07 16:29:04 -05001631
1632bool ValidateProgramBinary(Context *context,
1633 GLuint program,
1634 GLenum binaryFormat,
1635 const void *binary,
1636 GLint length)
1637{
Martin Radev1be913c2016-07-11 17:59:16 +03001638 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001639 {
Jamie Madill437fa652016-05-03 15:13:24 -04001640 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001641 return false;
1642 }
1643
1644 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1645}
1646
1647bool ValidateGetProgramBinary(Context *context,
1648 GLuint program,
1649 GLsizei bufSize,
1650 GLsizei *length,
1651 GLenum *binaryFormat,
1652 void *binary)
1653{
Martin Radev1be913c2016-07-11 17:59:16 +03001654 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001655 {
Jamie Madill437fa652016-05-03 15:13:24 -04001656 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001657 return false;
1658 }
1659
1660 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1661}
1662
Olli Etuahof0fee072016-03-30 15:11:58 +03001663bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001664{
Martin Radev1be913c2016-07-11 17:59:16 +03001665 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001666 {
Jamie Madill437fa652016-05-03 15:13:24 -04001667 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001668 return false;
1669 }
1670
1671 if (GetValidProgram(context, program) == nullptr)
1672 {
1673 return false;
1674 }
1675
1676 switch (pname)
1677 {
1678 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001679 if (value != GL_FALSE && value != GL_TRUE)
1680 {
Jamie Madill437fa652016-05-03 15:13:24 -04001681 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001682 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1683 return false;
1684 }
Geoff Langc5629752015-12-07 16:29:04 -05001685 break;
1686
1687 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001688 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001689 return false;
1690 }
1691
1692 return true;
1693}
Jamie Madillc29968b2016-01-20 11:17:23 -05001694
1695bool ValidateBlitFramebuffer(Context *context,
1696 GLint srcX0,
1697 GLint srcY0,
1698 GLint srcX1,
1699 GLint srcY1,
1700 GLint dstX0,
1701 GLint dstY0,
1702 GLint dstX1,
1703 GLint dstY1,
1704 GLbitfield mask,
1705 GLenum filter)
1706{
Martin Radev1be913c2016-07-11 17:59:16 +03001707 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001708 {
Jamie Madill437fa652016-05-03 15:13:24 -04001709 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001710 return false;
1711 }
1712
1713 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1714 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001715}
Jamie Madillc29968b2016-01-20 11:17:23 -05001716
1717bool ValidateClearBufferiv(ValidationContext *context,
1718 GLenum buffer,
1719 GLint drawbuffer,
1720 const GLint *value)
1721{
1722 switch (buffer)
1723 {
1724 case GL_COLOR:
1725 if (drawbuffer < 0 ||
1726 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1727 {
Jamie Madill437fa652016-05-03 15:13:24 -04001728 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001729 return false;
1730 }
1731 break;
1732
1733 case GL_STENCIL:
1734 if (drawbuffer != 0)
1735 {
Jamie Madill437fa652016-05-03 15:13:24 -04001736 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001737 return false;
1738 }
1739 break;
1740
1741 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001742 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001743 return false;
1744 }
1745
1746 return ValidateClearBuffer(context);
1747}
1748
1749bool ValidateClearBufferuiv(ValidationContext *context,
1750 GLenum buffer,
1751 GLint drawbuffer,
1752 const GLuint *value)
1753{
1754 switch (buffer)
1755 {
1756 case GL_COLOR:
1757 if (drawbuffer < 0 ||
1758 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1759 {
Jamie Madill437fa652016-05-03 15:13:24 -04001760 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001761 return false;
1762 }
1763 break;
1764
1765 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001766 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001767 return false;
1768 }
1769
1770 return ValidateClearBuffer(context);
1771}
1772
1773bool ValidateClearBufferfv(ValidationContext *context,
1774 GLenum buffer,
1775 GLint drawbuffer,
1776 const GLfloat *value)
1777{
1778 switch (buffer)
1779 {
1780 case GL_COLOR:
1781 if (drawbuffer < 0 ||
1782 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1783 {
Jamie Madill437fa652016-05-03 15:13:24 -04001784 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001785 return false;
1786 }
1787 break;
1788
1789 case GL_DEPTH:
1790 if (drawbuffer != 0)
1791 {
Jamie Madill437fa652016-05-03 15:13:24 -04001792 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001793 return false;
1794 }
1795 break;
1796
1797 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001798 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001799 return false;
1800 }
1801
1802 return ValidateClearBuffer(context);
1803}
1804
1805bool ValidateClearBufferfi(ValidationContext *context,
1806 GLenum buffer,
1807 GLint drawbuffer,
1808 GLfloat depth,
1809 GLint stencil)
1810{
1811 switch (buffer)
1812 {
1813 case GL_DEPTH_STENCIL:
1814 if (drawbuffer != 0)
1815 {
Jamie Madill437fa652016-05-03 15:13:24 -04001816 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001817 return false;
1818 }
1819 break;
1820
1821 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001822 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001823 return false;
1824 }
1825
1826 return ValidateClearBuffer(context);
1827}
1828
1829bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1830{
Martin Radev1be913c2016-07-11 17:59:16 +03001831 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001832 {
Jamie Madill437fa652016-05-03 15:13:24 -04001833 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001834 return false;
1835 }
1836
1837 return ValidateDrawBuffersBase(context, n, bufs);
1838}
1839
1840bool ValidateCopyTexSubImage3D(Context *context,
1841 GLenum target,
1842 GLint level,
1843 GLint xoffset,
1844 GLint yoffset,
1845 GLint zoffset,
1846 GLint x,
1847 GLint y,
1848 GLsizei width,
1849 GLsizei height)
1850{
Martin Radev1be913c2016-07-11 17:59:16 +03001851 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001852 {
Jamie Madill437fa652016-05-03 15:13:24 -04001853 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001854 return false;
1855 }
1856
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001857 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1858 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001859}
1860
Jamie Madill73a84962016-02-12 09:27:23 -05001861bool ValidateTexImage3D(Context *context,
1862 GLenum target,
1863 GLint level,
1864 GLint internalformat,
1865 GLsizei width,
1866 GLsizei height,
1867 GLsizei depth,
1868 GLint border,
1869 GLenum format,
1870 GLenum type,
1871 const GLvoid *pixels)
1872{
Martin Radev1be913c2016-07-11 17:59:16 +03001873 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001874 {
Jamie Madill437fa652016-05-03 15:13:24 -04001875 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001876 return false;
1877 }
1878
1879 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1880 0, 0, width, height, depth, border, format, type,
1881 pixels);
1882}
1883
1884bool ValidateTexSubImage3D(Context *context,
1885 GLenum target,
1886 GLint level,
1887 GLint xoffset,
1888 GLint yoffset,
1889 GLint zoffset,
1890 GLsizei width,
1891 GLsizei height,
1892 GLsizei depth,
1893 GLenum format,
1894 GLenum type,
1895 const GLvoid *pixels)
1896{
Martin Radev1be913c2016-07-11 17:59:16 +03001897 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001898 {
Jamie Madill437fa652016-05-03 15:13:24 -04001899 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001900 return false;
1901 }
1902
1903 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1904 yoffset, zoffset, width, height, depth, 0, format, type,
1905 pixels);
1906}
1907
1908bool ValidateCompressedTexSubImage3D(Context *context,
1909 GLenum target,
1910 GLint level,
1911 GLint xoffset,
1912 GLint yoffset,
1913 GLint zoffset,
1914 GLsizei width,
1915 GLsizei height,
1916 GLsizei depth,
1917 GLenum format,
1918 GLsizei imageSize,
1919 const GLvoid *data)
1920{
Martin Radev1be913c2016-07-11 17:59:16 +03001921 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001922 {
Jamie Madill437fa652016-05-03 15:13:24 -04001923 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001924 return false;
1925 }
1926
1927 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001928 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001929 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001930 if (blockSizeOrErr.isError())
1931 {
1932 context->handleError(blockSizeOrErr.getError());
1933 return false;
1934 }
1935 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001936 {
Jamie Madill437fa652016-05-03 15:13:24 -04001937 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001938 return false;
1939 }
1940
1941 if (!data)
1942 {
Jamie Madill437fa652016-05-03 15:13:24 -04001943 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001944 return false;
1945 }
1946
1947 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
1948 width, height, depth, 0, GL_NONE, GL_NONE, data);
1949}
1950
Olli Etuaho41997e72016-03-10 13:38:39 +02001951bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1952{
1953 return ValidateGenOrDeleteES3(context, n);
1954}
1955
1956bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1957{
1958 return ValidateGenOrDeleteES3(context, n);
1959}
1960
1961bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1962{
1963 return ValidateGenOrDeleteCountES3(context, count);
1964}
1965
1966bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1967{
1968 return ValidateGenOrDeleteCountES3(context, count);
1969}
1970
1971bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1972{
1973 return ValidateGenOrDeleteES3(context, n);
1974}
1975
1976bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1977{
1978 if (!ValidateGenOrDeleteES3(context, n))
1979 {
1980 return false;
1981 }
1982 for (GLint i = 0; i < n; ++i)
1983 {
1984 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1985 if (transformFeedback != nullptr && transformFeedback->isActive())
1986 {
1987 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001988 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001989 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1990 return false;
1991 }
1992 }
1993 return true;
1994}
1995
1996bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1997{
1998 return ValidateGenOrDeleteES3(context, n);
1999}
2000
2001bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2002{
2003 return ValidateGenOrDeleteES3(context, n);
2004}
2005
2006bool ValidateGenOrDeleteES3(Context *context, GLint n)
2007{
Martin Radev1be913c2016-07-11 17:59:16 +03002008 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02002009 {
Jamie Madill437fa652016-05-03 15:13:24 -04002010 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02002011 return false;
2012 }
2013 return ValidateGenOrDelete(context, n);
2014}
2015
2016bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
2017{
Martin Radev1be913c2016-07-11 17:59:16 +03002018 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02002019 {
Jamie Madill437fa652016-05-03 15:13:24 -04002020 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02002021 return false;
2022 }
2023 if (count < 0)
2024 {
Jamie Madill437fa652016-05-03 15:13:24 -04002025 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02002026 return false;
2027 }
2028 return true;
2029}
2030
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002031bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2032{
Martin Radev1be913c2016-07-11 17:59:16 +03002033 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002034 {
Jamie Madill437fa652016-05-03 15:13:24 -04002035 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002036 return false;
2037 }
2038 switch (primitiveMode)
2039 {
2040 case GL_TRIANGLES:
2041 case GL_LINES:
2042 case GL_POINTS:
2043 break;
2044
2045 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002046 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002047 return false;
2048 }
2049
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002050 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002051 ASSERT(transformFeedback != nullptr);
2052
2053 if (transformFeedback->isActive())
2054 {
Jamie Madill437fa652016-05-03 15:13:24 -04002055 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002056 return false;
2057 }
2058 return true;
2059}
2060
Olli Etuaho37477912016-03-30 14:54:40 +03002061bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
2062{
Martin Radev1be913c2016-07-11 17:59:16 +03002063 if (context->getClientMajorVersion() < 3)
Olli Etuaho37477912016-03-30 14:54:40 +03002064 {
Jamie Madill437fa652016-05-03 15:13:24 -04002065 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho37477912016-03-30 14:54:40 +03002066 return false;
2067 }
2068
2069 if (!context->isSampler(sampler))
2070 {
Jamie Madill437fa652016-05-03 15:13:24 -04002071 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho37477912016-03-30 14:54:40 +03002072 return false;
2073 }
2074
2075 if (!ValidateSamplerObjectParameter(context, pname))
2076 {
2077 return false;
2078 }
2079
Ian Ewellbda75592016-04-18 17:25:54 -04002080 if (!ValidateTexParamParameters(context, GL_TEXTURE_2D, pname, param))
Olli Etuaho37477912016-03-30 14:54:40 +03002081 {
2082 return false;
2083 }
2084 return true;
2085}
2086
2087bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
2088{
2089 // The only float parameters are MIN_LOD and MAX_LOD. For these any value is permissible, so
2090 // ValidateSamplerParameteri can be used for validation here.
2091 return ValidateSamplerParameteri(context, sampler, pname, static_cast<GLint>(param));
2092}
2093
Olli Etuaho4f667482016-03-30 15:56:35 +03002094bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
2095{
Martin Radev1be913c2016-07-11 17:59:16 +03002096 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002097 {
Jamie Madill437fa652016-05-03 15:13:24 -04002098 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002099 return false;
2100 }
2101
2102 return ValidateGetBufferPointervBase(context, target, pname, params);
2103}
2104
2105bool ValidateUnmapBuffer(Context *context, GLenum target)
2106{
Martin Radev1be913c2016-07-11 17:59:16 +03002107 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002108 {
Jamie Madill437fa652016-05-03 15:13:24 -04002109 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03002110 return false;
2111 }
2112
2113 return ValidateUnmapBufferBase(context, target);
2114}
2115
2116bool ValidateMapBufferRange(Context *context,
2117 GLenum target,
2118 GLintptr offset,
2119 GLsizeiptr length,
2120 GLbitfield access)
2121{
Martin Radev1be913c2016-07-11 17:59:16 +03002122 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002123 {
Jamie Madill437fa652016-05-03 15:13:24 -04002124 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002125 return false;
2126 }
2127
2128 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2129}
2130
2131bool ValidateFlushMappedBufferRange(Context *context,
2132 GLenum target,
2133 GLintptr offset,
2134 GLsizeiptr length)
2135{
Martin Radev1be913c2016-07-11 17:59:16 +03002136 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002137 {
Jamie Madill437fa652016-05-03 15:13:24 -04002138 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002139 return false;
2140 }
2141
2142 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2143}
2144
Martin Radev66fb8202016-07-28 11:45:20 +03002145bool ValidateIndexedStateQuery(ValidationContext *context, GLenum pname, GLuint index)
2146{
2147 GLenum nativeType;
2148 unsigned int numParams;
2149 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2150 {
2151 context->handleError(Error(GL_INVALID_ENUM));
2152 return false;
2153 }
2154
2155 const Caps &caps = context->getCaps();
2156 switch (pname)
2157 {
2158 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2159 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2160 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2161 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2162 {
2163 context->handleError(Error(GL_INVALID_VALUE));
2164 return false;
2165 }
2166 break;
2167
2168 case GL_UNIFORM_BUFFER_START:
2169 case GL_UNIFORM_BUFFER_SIZE:
2170 case GL_UNIFORM_BUFFER_BINDING:
2171 if (index >= caps.maxUniformBufferBindings)
2172 {
2173 context->handleError(Error(GL_INVALID_VALUE));
2174 return false;
2175 }
2176 break;
2177 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2178 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2179 if (index >= 3u)
2180 {
2181 context->handleError(Error(GL_INVALID_VALUE));
2182 return false;
2183 }
2184 break;
2185 default:
2186 context->handleError(Error(GL_INVALID_ENUM));
2187 return false;
2188 }
2189
2190 // pname is valid, but there are no parameters to return
2191 if (numParams == 0)
2192 {
2193 return false;
2194 }
2195
2196 return true;
2197}
2198
2199bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2200{
2201 if (!context->getGLVersion().isES3OrGreater())
2202 {
2203 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2204 return false;
2205 }
2206 return ValidateIndexedStateQuery(context, target, index);
2207}
2208
2209bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2210{
2211 if (!context->getGLVersion().isES3OrGreater())
2212 {
2213 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2214 return false;
2215 }
2216 return ValidateIndexedStateQuery(context, target, index);
2217}
2218
Jamie Madillc29968b2016-01-20 11:17:23 -05002219} // namespace gl