blob: 782646f7de4d352b3bcaa411818497c87bf53d15 [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 Langf607c602016-09-21 11:46:48 -0400207 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400208
Vincent Lang25ab4512016-05-13 18:13:59 +0200209 // From GL_EXT_texture_norm16
210 InsertES3FormatCombo(&set, GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT);
211 InsertES3FormatCombo(&set, GL_RG16_EXT, GL_RG, GL_UNSIGNED_SHORT);
212 InsertES3FormatCombo(&set, GL_RGB16_EXT, GL_RGB, GL_UNSIGNED_SHORT);
213 InsertES3FormatCombo(&set, GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT);
214 InsertES3FormatCombo(&set, GL_R16_SNORM_EXT, GL_RED, GL_SHORT);
215 InsertES3FormatCombo(&set, GL_RG16_SNORM_EXT, GL_RG, GL_SHORT);
216 InsertES3FormatCombo(&set, GL_RGB16_SNORM_EXT, GL_RGB, GL_SHORT);
217 InsertES3FormatCombo(&set, GL_RGBA16_SNORM_EXT, GL_RGBA, GL_SHORT);
218
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);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400480 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400481 {
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 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400516 context->handleError(
517 Error(GL_INVALID_OPERATION, "Reads would overflow the pixel unpack buffer."));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400518 return false;
519 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400520 }
521
Jamie Madill7a5f7382014-03-05 15:01:24 -0500522 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700523 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500524 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400525 context->handleError(Error(GL_INVALID_OPERATION, "Pixel unpack buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -0400526 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500527 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400528 }
529
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400530 return true;
531}
532
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500533bool ValidateES3TexImage2DParameters(Context *context,
534 GLenum target,
535 GLint level,
536 GLenum internalformat,
537 bool isCompressed,
538 bool isSubImage,
539 GLint xoffset,
540 GLint yoffset,
541 GLint zoffset,
542 GLsizei width,
543 GLsizei height,
544 GLsizei depth,
545 GLint border,
546 GLenum format,
547 GLenum type,
548 const GLvoid *pixels)
549{
550 if (!ValidTexture2DDestinationTarget(context, target))
551 {
Jamie Madill437fa652016-05-03 15:13:24 -0400552 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500553 return false;
554 }
555
556 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
557 isSubImage, xoffset, yoffset, zoffset, width, height,
558 depth, border, format, type, pixels);
559}
560
561bool ValidateES3TexImage3DParameters(Context *context,
562 GLenum target,
563 GLint level,
564 GLenum internalformat,
565 bool isCompressed,
566 bool isSubImage,
567 GLint xoffset,
568 GLint yoffset,
569 GLint zoffset,
570 GLsizei width,
571 GLsizei height,
572 GLsizei depth,
573 GLint border,
574 GLenum format,
575 GLenum type,
576 const GLvoid *pixels)
577{
578 if (!ValidTexture3DDestinationTarget(context, target))
579 {
Jamie Madill437fa652016-05-03 15:13:24 -0400580 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500581 return false;
582 }
583
584 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
585 isSubImage, xoffset, yoffset, zoffset, width, height,
586 depth, border, format, type, pixels);
587}
588
Geoff Lang5d601382014-07-22 15:14:06 -0400589struct EffectiveInternalFormatInfo
590{
591 GLenum mEffectiveFormat;
592 GLenum mDestFormat;
593 GLuint mMinRedBits;
594 GLuint mMaxRedBits;
595 GLuint mMinGreenBits;
596 GLuint mMaxGreenBits;
597 GLuint mMinBlueBits;
598 GLuint mMaxBlueBits;
599 GLuint mMinAlphaBits;
600 GLuint mMaxAlphaBits;
601
602 EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits,
603 GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits,
604 GLuint minAlphaBits, GLuint maxAlphaBits)
605 : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits),
606 mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits),
607 mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits),
608 mMaxAlphaBits(maxAlphaBits) {};
609};
610
611typedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
612
613static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList()
614{
615 EffectiveInternalFormatList list;
616
617 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
618 // linear source buffer component sizes.
619 // | Source channel min/max sizes |
620 // Effective Internal Format | N/A | R | G | B | A |
621 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8));
622 list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0));
623 list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0));
624 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0));
625 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0));
626 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4));
627 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1));
628 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8));
629 list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2));
630
631 return list;
632}
633
634static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList()
635{
636 EffectiveInternalFormatList list;
637
638 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
639 // linear source buffer component sizes.
640 // | Source channel min/max sizes |
641 // Effective Internal Format | Dest Format | R | G | B | A |
642 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
643 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX));
644 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
645 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX));
646 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX));
647 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4));
648 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1));
649 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8));
650
651 return list;
652}
653
654static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
655 GLenum *outEffectiveFormat)
656{
657 const EffectiveInternalFormatList *list = NULL;
658 GLenum targetFormat = GL_NONE;
659
660 if (destFormat.pixelBytes > 0)
661 {
662 static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList();
663 list = &sizedList;
664 }
665 else
666 {
667 static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList();
668 list = &unsizedList;
669 targetFormat = destFormat.format;
670 }
671
672 for (size_t curFormat = 0; curFormat < list->size(); ++curFormat)
673 {
674 const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat);
675 if ((formatInfo.mDestFormat == targetFormat) &&
676 (formatInfo.mMinRedBits <= srcFormat.redBits && formatInfo.mMaxRedBits >= srcFormat.redBits) &&
677 (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) &&
678 (formatInfo.mMinBlueBits <= srcFormat.blueBits && formatInfo.mMaxBlueBits >= srcFormat.blueBits) &&
679 (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits))
680 {
681 *outEffectiveFormat = formatInfo.mEffectiveFormat;
682 return true;
683 }
684 }
685
686 return false;
687}
688
689struct CopyConversion
690{
691 GLenum mTextureFormat;
692 GLenum mFramebufferFormat;
693
694 CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
695 : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
696
697 bool operator<(const CopyConversion& other) const
698 {
699 return memcmp(this, &other, sizeof(CopyConversion)) < 0;
700 }
701};
702
703typedef std::set<CopyConversion> CopyConversionSet;
704
705static CopyConversionSet BuildValidES3CopyTexImageCombinations()
706{
707 CopyConversionSet set;
708
709 // From ES 3.0.1 spec, table 3.15
710 set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
711 set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
712 set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
713 set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
714 set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
715 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
716 set.insert(CopyConversion(GL_RED, GL_RED));
717 set.insert(CopyConversion(GL_RED, GL_RG));
718 set.insert(CopyConversion(GL_RED, GL_RGB));
719 set.insert(CopyConversion(GL_RED, GL_RGBA));
720 set.insert(CopyConversion(GL_RG, GL_RG));
721 set.insert(CopyConversion(GL_RG, GL_RGB));
722 set.insert(CopyConversion(GL_RG, GL_RGBA));
723 set.insert(CopyConversion(GL_RGB, GL_RGB));
724 set.insert(CopyConversion(GL_RGB, GL_RGBA));
725 set.insert(CopyConversion(GL_RGBA, GL_RGBA));
726
727 // Necessary for ANGLE back-buffers
728 set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
729 set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
730 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
731 set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
732 set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
733 set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
734 set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
Geoff Lang4e58af62016-08-26 10:56:52 -0400735 set.insert(CopyConversion(GL_BGRA_EXT, GL_BGRA_EXT));
Geoff Lang5d601382014-07-22 15:14:06 -0400736
737 set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
738 set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
739 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
740 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
741 set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
742 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
743 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
744 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
745 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
746 set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
747
748 return set;
749}
750
Corentin Wallez76287682016-04-25 09:23:38 -0400751static bool EqualOrFirstZero(GLuint first, GLuint second)
752{
753 return first == 0 || first == second;
754}
755
Jamie Madill0c8abca2016-07-22 20:21:26 -0400756static bool IsValidES3CopyTexImageCombination(const Format &textureFormat,
757 const Format &framebufferFormat,
758 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400759{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400760 const auto &textureFormatInfo = *textureFormat.info;
761 const auto &framebufferFormatInfo = *framebufferFormat.info;
Geoff Lang5d601382014-07-22 15:14:06 -0400762
763 static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
Jamie Madill0c8abca2016-07-22 20:21:26 -0400764 if (conversionSet.find(CopyConversion(textureFormatInfo.format,
765 framebufferFormatInfo.format)) != conversionSet.end())
Geoff Lang5d601382014-07-22 15:14:06 -0400766 {
767 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
768 // must both be signed, unsigned, or fixed point and both source and destinations
769 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
770 // conversion between fixed and floating point.
771
Jamie Madill0c8abca2016-07-22 20:21:26 -0400772 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
773 (framebufferFormatInfo.colorEncoding == GL_SRGB))
Geoff Lang5d601382014-07-22 15:14:06 -0400774 {
775 return false;
776 }
777
Jamie Madill0c8abca2016-07-22 20:21:26 -0400778 if (((textureFormatInfo.componentType == GL_INT) !=
779 (framebufferFormatInfo.componentType == GL_INT)) ||
780 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
781 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
Geoff Lang5d601382014-07-22 15:14:06 -0400782 {
783 return false;
784 }
785
Jamie Madill0c8abca2016-07-22 20:21:26 -0400786 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
787 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
788 textureFormatInfo.componentType == GL_FLOAT) &&
789 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
790 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
791 framebufferFormatInfo.componentType == GL_FLOAT))
Geoff Lang5d601382014-07-22 15:14:06 -0400792 {
793 return false;
794 }
795
796 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
797 // The effective internal format of the source buffer is determined with the following rules applied in order:
798 // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
799 // effective internal format is the source buffer's sized internal format.
800 // * If the source buffer is a texture that was created with an unsized base internal format, then the
801 // effective internal format is the source image array's effective internal format, as specified by table
802 // 3.12, which is determined from the <format> and <type> that were used when the source image array was
803 // specified by TexImage*.
804 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
805 // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
806 // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
807 // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
808 // is SRGB.
809 const InternalFormat *sourceEffectiveFormat = NULL;
810 if (readBufferHandle != 0)
811 {
812 // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
Jamie Madill0c8abca2016-07-22 20:21:26 -0400813 if (framebufferFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400814 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400815 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400816 }
817 else
818 {
819 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
820 // 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 -0400821 GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferFormatInfo.format,
822 framebufferFormatInfo.type);
Geoff Lang051dbc72015-01-05 15:48:58 -0500823 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400824 }
825 }
826 else
827 {
828 // The effective internal format must be derived from the source framebuffer's channel sizes.
829 // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
Jamie Madill0c8abca2016-07-22 20:21:26 -0400830 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400831 {
832 GLenum effectiveFormat;
Jamie Madill0c8abca2016-07-22 20:21:26 -0400833 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
834 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400835 {
836 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
837 }
838 else
839 {
840 return false;
841 }
842 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400843 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
Geoff Lang5d601382014-07-22 15:14:06 -0400844 {
845 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Jamie Madill0c8abca2016-07-22 20:21:26 -0400846 if (textureFormat.sized &&
847 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
848 (framebufferFormatInfo.greenBits >= 1 &&
849 framebufferFormatInfo.greenBits <= 8) &&
850 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
851 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
Geoff Lang5d601382014-07-22 15:14:06 -0400852 {
853 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
854 }
855 else
856 {
857 return false;
858 }
859 }
860 else
861 {
862 UNREACHABLE();
863 return false;
864 }
865 }
866
Jamie Madill0c8abca2016-07-22 20:21:26 -0400867 if (textureFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400868 {
Corentin Wallez76287682016-04-25 09:23:38 -0400869 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination
870 // format is sized, component sizes of the source and destination formats must exactly
871 // match if the destination format exists.
Jamie Madill0c8abca2016-07-22 20:21:26 -0400872 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
873 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
874 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
875 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
Geoff Lang5d601382014-07-22 15:14:06 -0400876 {
877 return false;
878 }
879 }
880
Geoff Lang5d601382014-07-22 15:14:06 -0400881 return true; // A conversion function exists, and no rule in the specification has precluded conversion
882 // between these formats.
883 }
884
885 return false;
886}
887
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500888bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
889 GLenum target,
890 GLint level,
891 GLenum internalformat,
892 bool isSubImage,
893 GLint xoffset,
894 GLint yoffset,
895 GLint zoffset,
896 GLint x,
897 GLint y,
898 GLsizei width,
899 GLsizei height,
900 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400901{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400902 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400903 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400904 xoffset, yoffset, zoffset, x, y, width, height, border,
905 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400906 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400907 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400908 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400909 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400910
Jamie Madill51f40ec2016-06-15 14:06:00 -0400911 const auto &state = context->getGLState();
912 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
913 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400914
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700915 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400916 {
Jamie Madill437fa652016-05-03 15:13:24 -0400917 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400918 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400919 }
920
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700921 if (readFramebufferID != 0 && framebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400922 {
Jamie Madill437fa652016-05-03 15:13:24 -0400923 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400924 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400925 }
926
Jamie Madill0c8abca2016-07-22 20:21:26 -0400927 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400928
929 if (isSubImage)
930 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400931 if (!IsValidES3CopyTexImageCombination(textureFormat, source->getFormat(),
Jamie Madillc29968b2016-01-20 11:17:23 -0500932 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400933 {
Jamie Madill437fa652016-05-03 15:13:24 -0400934 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400935 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400936 }
937 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400938 else
939 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400940 // Use format/type from the source FBO. (Might not be perfect for all cases?)
941 const auto framebufferFormat = source->getFormat();
942 Format copyFormat(internalformat, framebufferFormat.format, framebufferFormat.type);
943 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400944 {
Jamie Madill437fa652016-05-03 15:13:24 -0400945 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400946 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400947 }
948 }
949
Geoff Lang784a8fd2013-09-24 12:33:16 -0400950 // If width or height is zero, it is a no-op. Return false without setting an error.
951 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400952}
953
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500954bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
955 GLenum target,
956 GLint level,
957 GLenum internalformat,
958 bool isSubImage,
959 GLint xoffset,
960 GLint yoffset,
961 GLint zoffset,
962 GLint x,
963 GLint y,
964 GLsizei width,
965 GLsizei height,
966 GLint border)
967{
968 if (!ValidTexture2DDestinationTarget(context, target))
969 {
Jamie Madill437fa652016-05-03 15:13:24 -0400970 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500971 return false;
972 }
973
974 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
975 xoffset, yoffset, zoffset, x, y, width, height,
976 border);
977}
978
979bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
980 GLenum target,
981 GLint level,
982 GLenum internalformat,
983 bool isSubImage,
984 GLint xoffset,
985 GLint yoffset,
986 GLint zoffset,
987 GLint x,
988 GLint y,
989 GLsizei width,
990 GLsizei height,
991 GLint border)
992{
993 if (!ValidTexture3DDestinationTarget(context, target))
994 {
Jamie Madill437fa652016-05-03 15:13:24 -0400995 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500996 return false;
997 }
998
999 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
1000 xoffset, yoffset, zoffset, x, y, width, height,
1001 border);
1002}
1003
1004bool ValidateES3TexStorageParametersBase(Context *context,
1005 GLenum target,
1006 GLsizei levels,
1007 GLenum internalformat,
1008 GLsizei width,
1009 GLsizei height,
1010 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001011{
1012 if (width < 1 || height < 1 || depth < 1 || levels < 1)
1013 {
Jamie Madill437fa652016-05-03 15:13:24 -04001014 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001015 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001016 }
1017
Geoff Langb92c1332015-09-04 12:54:55 -04001018 GLsizei maxDim = std::max(width, height);
1019 if (target != GL_TEXTURE_2D_ARRAY)
1020 {
1021 maxDim = std::max(maxDim, depth);
1022 }
1023
1024 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001025 {
Jamie Madill437fa652016-05-03 15:13:24 -04001026 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001027 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001028 }
1029
Geoff Langaae65a42014-05-26 12:43:44 -04001030 const gl::Caps &caps = context->getCaps();
1031
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001032 switch (target)
1033 {
1034 case GL_TEXTURE_2D:
1035 {
Geoff Langaae65a42014-05-26 12:43:44 -04001036 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1037 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001038 {
Jamie Madill437fa652016-05-03 15:13:24 -04001039 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001040 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001041 }
1042 }
1043 break;
1044
Geoff Lang01c21d22013-09-24 11:52:16 -04001045 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001046 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001047 if (width != height)
1048 {
Jamie Madill437fa652016-05-03 15:13:24 -04001049 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001050 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001051 }
1052
Geoff Langaae65a42014-05-26 12:43:44 -04001053 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001054 {
Jamie Madill437fa652016-05-03 15:13:24 -04001055 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001056 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001057 }
1058 }
1059 break;
1060
1061 case GL_TEXTURE_3D:
1062 {
Geoff Langaae65a42014-05-26 12:43:44 -04001063 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
1064 static_cast<GLuint>(height) > caps.max3DTextureSize ||
1065 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001066 {
Jamie Madill437fa652016-05-03 15:13:24 -04001067 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001068 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001069 }
1070 }
1071 break;
1072
1073 case GL_TEXTURE_2D_ARRAY:
1074 {
Geoff Langaae65a42014-05-26 12:43:44 -04001075 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1076 static_cast<GLuint>(height) > caps.max2DTextureSize ||
1077 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001078 {
Jamie Madill437fa652016-05-03 15:13:24 -04001079 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001080 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001081 }
1082 }
1083 break;
1084
1085 default:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001086 UNREACHABLE();
Geoff Langb1196682014-07-23 13:47:29 -04001087 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001088 }
1089
Geoff Lang691e58c2014-12-19 17:03:25 -05001090 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001091 if (!texture || texture->id() == 0)
1092 {
Jamie Madill437fa652016-05-03 15:13:24 -04001093 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001094 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001095 }
1096
Geoff Lang69cce582015-09-17 13:20:36 -04001097 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001098 {
Jamie Madill437fa652016-05-03 15:13:24 -04001099 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001100 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001101 }
1102
Geoff Lang5d601382014-07-22 15:14:06 -04001103 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Martin Radev1be913c2016-07-11 17:59:16 +03001104 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001105 {
Jamie Madill437fa652016-05-03 15:13:24 -04001106 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001107 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001108 }
1109
Geoff Lang5d601382014-07-22 15:14:06 -04001110 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001111 {
Jamie Madill437fa652016-05-03 15:13:24 -04001112 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001113 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001114 }
1115
1116 return true;
1117}
1118
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001119bool ValidateES3TexStorage2DParameters(Context *context,
1120 GLenum target,
1121 GLsizei levels,
1122 GLenum internalformat,
1123 GLsizei width,
1124 GLsizei height,
1125 GLsizei depth)
1126{
1127 if (!ValidTexture2DTarget(context, target))
1128 {
Jamie Madill437fa652016-05-03 15:13:24 -04001129 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001130 return false;
1131 }
1132
1133 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1134 height, depth);
1135}
1136
1137bool ValidateES3TexStorage3DParameters(Context *context,
1138 GLenum target,
1139 GLsizei levels,
1140 GLenum internalformat,
1141 GLsizei width,
1142 GLsizei height,
1143 GLsizei depth)
1144{
1145 if (!ValidTexture3DTarget(context, target))
1146 {
Jamie Madill437fa652016-05-03 15:13:24 -04001147 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001148 return false;
1149 }
1150
1151 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1152 height, depth);
1153}
1154
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001155bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1156{
Martin Radev1be913c2016-07-11 17:59:16 +03001157 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001158 {
Jamie Madill437fa652016-05-03 15:13:24 -04001159 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001160 return false;
1161 }
1162
1163 return ValidateBeginQueryBase(context, target, id);
1164}
1165
1166bool ValidateEndQuery(gl::Context *context, GLenum target)
1167{
Martin Radev1be913c2016-07-11 17:59:16 +03001168 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001169 {
Jamie Madill437fa652016-05-03 15:13:24 -04001170 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001171 return false;
1172 }
1173
1174 return ValidateEndQueryBase(context, target);
1175}
1176
1177bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1178{
Martin Radev1be913c2016-07-11 17:59:16 +03001179 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001180 {
Jamie Madill437fa652016-05-03 15:13:24 -04001181 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001182 return false;
1183 }
1184
1185 return ValidateGetQueryivBase(context, target, pname);
1186}
1187
1188bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1189{
Martin Radev1be913c2016-07-11 17:59:16 +03001190 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001191 {
Jamie Madill437fa652016-05-03 15:13:24 -04001192 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001193 return false;
1194 }
1195
1196 return ValidateGetQueryObjectValueBase(context, id, pname);
1197}
1198
Geoff Langb1196682014-07-23 13:47:29 -04001199bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
Jamie Madill570f7c82014-07-03 10:38:54 -04001200 GLuint texture, GLint level, GLint layer)
1201{
Martin Radev1be913c2016-07-11 17:59:16 +03001202 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001203 {
Jamie Madill437fa652016-05-03 15:13:24 -04001204 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001205 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001206 }
1207
Jamie Madill55ec3b12014-07-03 10:38:57 -04001208 if (layer < 0)
1209 {
Jamie Madill437fa652016-05-03 15:13:24 -04001210 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001211 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001212 }
1213
1214 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1215 {
1216 return false;
1217 }
1218
1219 const gl::Caps &caps = context->getCaps();
1220 if (texture != 0)
1221 {
1222 gl::Texture *tex = context->getTexture(texture);
1223 ASSERT(tex);
1224
1225 switch (tex->getTarget())
1226 {
1227 case GL_TEXTURE_2D_ARRAY:
1228 {
1229 if (level > gl::log2(caps.max2DTextureSize))
1230 {
Jamie Madill437fa652016-05-03 15:13:24 -04001231 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001232 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001233 }
1234
1235 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1236 {
Jamie Madill437fa652016-05-03 15:13:24 -04001237 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001238 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001239 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001240 }
1241 break;
1242
1243 case GL_TEXTURE_3D:
1244 {
1245 if (level > gl::log2(caps.max3DTextureSize))
1246 {
Jamie Madill437fa652016-05-03 15:13:24 -04001247 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001248 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001249 }
1250
1251 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1252 {
Jamie Madill437fa652016-05-03 15:13:24 -04001253 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001254 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001255 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001256 }
1257 break;
1258
1259 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001260 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001261 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001262 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001263
Jamie Madilla3944d42016-07-22 22:13:26 -04001264 const auto &format = tex->getFormat(tex->getTarget(), level);
1265 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001266 {
Jamie Madill437fa652016-05-03 15:13:24 -04001267 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001268 return false;
1269 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001270 }
1271
1272 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001273}
1274
Corentin Walleze0902642014-11-04 12:32:15 -08001275bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
1276 GLenum internalformat, GLsizei width, GLsizei height)
1277{
1278 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
1279 {
1280 return false;
1281 }
1282
1283 //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.
1284 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1285 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
1286 {
Jamie Madill437fa652016-05-03 15:13:24 -04001287 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -08001288 return false;
1289 }
1290
1291 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
1292 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1293 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1294 {
Jamie Madill437fa652016-05-03 15:13:24 -04001295 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001296 Error(GL_INVALID_OPERATION,
1297 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001298 return false;
1299 }
1300
1301 return true;
1302}
1303
Austin Kinross08332632015-05-05 13:35:47 -07001304bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
1305 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001306{
Martin Radev1be913c2016-07-11 17:59:16 +03001307 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001308 {
Jamie Madill437fa652016-05-03 15:13:24 -04001309 context->handleError(
1310 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001311 return false;
1312 }
1313
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001314 bool defaultFramebuffer = false;
1315
1316 switch (target)
1317 {
1318 case GL_DRAW_FRAMEBUFFER:
1319 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001320 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1321 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001322 case GL_READ_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001323 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1324 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001325 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001326 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001327 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001328 }
1329
Austin Kinross08332632015-05-05 13:35:47 -07001330 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001331}
1332
Jamie Madillc29968b2016-01-20 11:17:23 -05001333bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001334{
Martin Radev1be913c2016-07-11 17:59:16 +03001335 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001336 {
Jamie Madill437fa652016-05-03 15:13:24 -04001337 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001338 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001339 }
1340
Jamie Madill51f40ec2016-06-15 14:06:00 -04001341 if (context->getGLState().getDrawFramebuffer()->checkStatus(context->getContextState()) !=
1342 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001343 {
Jamie Madill437fa652016-05-03 15:13:24 -04001344 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001345 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001346 }
1347
1348 return true;
1349}
1350
Olli Etuaho71dfb362016-03-10 14:04:27 +02001351bool ValidateDrawRangeElements(Context *context,
1352 GLenum mode,
1353 GLuint start,
1354 GLuint end,
1355 GLsizei count,
1356 GLenum type,
1357 const GLvoid *indices,
1358 IndexRange *indexRange)
1359{
Martin Radev1be913c2016-07-11 17:59:16 +03001360 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001361 {
Jamie Madill437fa652016-05-03 15:13:24 -04001362 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001363 return false;
1364 }
1365
1366 if (end < start)
1367 {
Jamie Madill437fa652016-05-03 15:13:24 -04001368 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001369 return false;
1370 }
1371
1372 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1373 {
1374 return false;
1375 }
1376
1377 if (indexRange->end > end || indexRange->start < start)
1378 {
1379 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001380 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001381 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1382 return false;
1383 }
1384 return true;
1385}
1386
Geoff Langb1196682014-07-23 13:47:29 -04001387bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001388{
Martin Radev1be913c2016-07-11 17:59:16 +03001389 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001390 {
Jamie Madill437fa652016-05-03 15:13:24 -04001391 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001392 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001393 }
1394
Jamie Madill78f41802014-08-25 15:47:55 -04001395 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001396}
1397
Jamie Madillb885e572015-02-03 16:16:04 -05001398bool ValidateReadBuffer(Context *context, GLenum src)
1399{
Martin Radev1be913c2016-07-11 17:59:16 +03001400 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001401 {
Jamie Madill437fa652016-05-03 15:13:24 -04001402 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001403 return false;
1404 }
1405
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001406 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001407
1408 if (readFBO == nullptr)
1409 {
Jamie Madill437fa652016-05-03 15:13:24 -04001410 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001411 return false;
1412 }
1413
1414 if (src == GL_NONE)
1415 {
1416 return true;
1417 }
1418
Olli Etuaho84c9f592016-03-09 14:37:25 +02001419 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001420 {
Jamie Madill437fa652016-05-03 15:13:24 -04001421 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001422 return false;
1423 }
1424
1425 if (readFBO->id() == 0)
1426 {
1427 if (src != GL_BACK)
1428 {
1429 const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001430 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001431 return false;
1432 }
1433 }
1434 else
1435 {
1436 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1437
1438 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1439 {
1440 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001441 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001442 return false;
1443 }
1444 }
1445
1446 return true;
1447}
1448
Jamie Madill86af3d22015-07-21 15:14:07 -04001449bool ValidateCompressedTexImage3D(Context *context,
1450 GLenum target,
1451 GLint level,
1452 GLenum internalformat,
1453 GLsizei width,
1454 GLsizei height,
1455 GLsizei depth,
1456 GLint border,
1457 GLsizei imageSize,
1458 const GLvoid *data)
1459{
Martin Radev1be913c2016-07-11 17:59:16 +03001460 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001461 {
Jamie Madill437fa652016-05-03 15:13:24 -04001462 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001463 return false;
1464 }
1465
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001466 if (!ValidTextureTarget(context, target))
1467 {
1468 context->handleError(Error(GL_INVALID_ENUM));
1469 return false;
1470 }
1471
Jamie Madille2e406c2016-06-02 13:04:10 -04001472 // Validate image size
1473 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1474 {
1475 context->handleError(Error(GL_INVALID_VALUE));
1476 return false;
1477 }
1478
Jamie Madill86af3d22015-07-21 15:14:07 -04001479 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001480 if (!formatInfo.compressed)
1481 {
1482 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1483 return false;
1484 }
1485
Jamie Madill513558d2016-06-02 13:04:11 -04001486 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001487 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001488 if (blockSizeOrErr.isError())
1489 {
Jamie Madill513558d2016-06-02 13:04:11 -04001490 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001491 return false;
1492 }
1493 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001494 {
Jamie Madill437fa652016-05-03 15:13:24 -04001495 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001496 return false;
1497 }
1498
1499 // 3D texture target validation
1500 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1501 {
Jamie Madill437fa652016-05-03 15:13:24 -04001502 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001503 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1504 return false;
1505 }
1506
1507 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001508 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
1509 0, width, height, depth, border, GL_NONE, GL_NONE, data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001510 {
1511 return false;
1512 }
1513
1514 return true;
1515}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001516
1517bool ValidateBindVertexArray(Context *context, GLuint array)
1518{
Martin Radev1be913c2016-07-11 17:59:16 +03001519 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001520 {
Jamie Madill437fa652016-05-03 15:13:24 -04001521 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001522 return false;
1523 }
1524
1525 return ValidateBindVertexArrayBase(context, array);
1526}
1527
Austin Kinrossbc781f32015-10-26 09:27:38 -07001528bool ValidateIsVertexArray(Context *context)
1529{
Martin Radev1be913c2016-07-11 17:59:16 +03001530 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001531 {
Jamie Madill437fa652016-05-03 15:13:24 -04001532 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001533 return false;
1534 }
1535
1536 return true;
1537}
Geoff Langc5629752015-12-07 16:29:04 -05001538
1539bool ValidateProgramBinary(Context *context,
1540 GLuint program,
1541 GLenum binaryFormat,
1542 const void *binary,
1543 GLint length)
1544{
Martin Radev1be913c2016-07-11 17:59:16 +03001545 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001546 {
Jamie Madill437fa652016-05-03 15:13:24 -04001547 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001548 return false;
1549 }
1550
1551 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1552}
1553
1554bool ValidateGetProgramBinary(Context *context,
1555 GLuint program,
1556 GLsizei bufSize,
1557 GLsizei *length,
1558 GLenum *binaryFormat,
1559 void *binary)
1560{
Martin Radev1be913c2016-07-11 17:59:16 +03001561 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001562 {
Jamie Madill437fa652016-05-03 15:13:24 -04001563 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001564 return false;
1565 }
1566
1567 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1568}
1569
Olli Etuahof0fee072016-03-30 15:11:58 +03001570bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001571{
Martin Radev1be913c2016-07-11 17:59:16 +03001572 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001573 {
Jamie Madill437fa652016-05-03 15:13:24 -04001574 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001575 return false;
1576 }
1577
1578 if (GetValidProgram(context, program) == nullptr)
1579 {
1580 return false;
1581 }
1582
1583 switch (pname)
1584 {
1585 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001586 if (value != GL_FALSE && value != GL_TRUE)
1587 {
Jamie Madill437fa652016-05-03 15:13:24 -04001588 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001589 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1590 return false;
1591 }
Geoff Langc5629752015-12-07 16:29:04 -05001592 break;
1593
1594 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001595 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001596 return false;
1597 }
1598
1599 return true;
1600}
Jamie Madillc29968b2016-01-20 11:17:23 -05001601
1602bool ValidateBlitFramebuffer(Context *context,
1603 GLint srcX0,
1604 GLint srcY0,
1605 GLint srcX1,
1606 GLint srcY1,
1607 GLint dstX0,
1608 GLint dstY0,
1609 GLint dstX1,
1610 GLint dstY1,
1611 GLbitfield mask,
1612 GLenum filter)
1613{
Martin Radev1be913c2016-07-11 17:59:16 +03001614 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001615 {
Jamie Madill437fa652016-05-03 15:13:24 -04001616 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001617 return false;
1618 }
1619
1620 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1621 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001622}
Jamie Madillc29968b2016-01-20 11:17:23 -05001623
1624bool ValidateClearBufferiv(ValidationContext *context,
1625 GLenum buffer,
1626 GLint drawbuffer,
1627 const GLint *value)
1628{
1629 switch (buffer)
1630 {
1631 case GL_COLOR:
1632 if (drawbuffer < 0 ||
1633 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1634 {
Jamie Madill437fa652016-05-03 15:13:24 -04001635 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001636 return false;
1637 }
1638 break;
1639
1640 case GL_STENCIL:
1641 if (drawbuffer != 0)
1642 {
Jamie Madill437fa652016-05-03 15:13:24 -04001643 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001644 return false;
1645 }
1646 break;
1647
1648 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001649 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001650 return false;
1651 }
1652
1653 return ValidateClearBuffer(context);
1654}
1655
1656bool ValidateClearBufferuiv(ValidationContext *context,
1657 GLenum buffer,
1658 GLint drawbuffer,
1659 const GLuint *value)
1660{
1661 switch (buffer)
1662 {
1663 case GL_COLOR:
1664 if (drawbuffer < 0 ||
1665 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1666 {
Jamie Madill437fa652016-05-03 15:13:24 -04001667 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001668 return false;
1669 }
1670 break;
1671
1672 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001673 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001674 return false;
1675 }
1676
1677 return ValidateClearBuffer(context);
1678}
1679
1680bool ValidateClearBufferfv(ValidationContext *context,
1681 GLenum buffer,
1682 GLint drawbuffer,
1683 const GLfloat *value)
1684{
1685 switch (buffer)
1686 {
1687 case GL_COLOR:
1688 if (drawbuffer < 0 ||
1689 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1690 {
Jamie Madill437fa652016-05-03 15:13:24 -04001691 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001692 return false;
1693 }
1694 break;
1695
1696 case GL_DEPTH:
1697 if (drawbuffer != 0)
1698 {
Jamie Madill437fa652016-05-03 15:13:24 -04001699 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001700 return false;
1701 }
1702 break;
1703
1704 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001705 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001706 return false;
1707 }
1708
1709 return ValidateClearBuffer(context);
1710}
1711
1712bool ValidateClearBufferfi(ValidationContext *context,
1713 GLenum buffer,
1714 GLint drawbuffer,
1715 GLfloat depth,
1716 GLint stencil)
1717{
1718 switch (buffer)
1719 {
1720 case GL_DEPTH_STENCIL:
1721 if (drawbuffer != 0)
1722 {
Jamie Madill437fa652016-05-03 15:13:24 -04001723 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001724 return false;
1725 }
1726 break;
1727
1728 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001729 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001730 return false;
1731 }
1732
1733 return ValidateClearBuffer(context);
1734}
1735
1736bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1737{
Martin Radev1be913c2016-07-11 17:59:16 +03001738 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001739 {
Jamie Madill437fa652016-05-03 15:13:24 -04001740 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001741 return false;
1742 }
1743
1744 return ValidateDrawBuffersBase(context, n, bufs);
1745}
1746
1747bool ValidateCopyTexSubImage3D(Context *context,
1748 GLenum target,
1749 GLint level,
1750 GLint xoffset,
1751 GLint yoffset,
1752 GLint zoffset,
1753 GLint x,
1754 GLint y,
1755 GLsizei width,
1756 GLsizei height)
1757{
Martin Radev1be913c2016-07-11 17:59:16 +03001758 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001759 {
Jamie Madill437fa652016-05-03 15:13:24 -04001760 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001761 return false;
1762 }
1763
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001764 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1765 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001766}
1767
Jamie Madill73a84962016-02-12 09:27:23 -05001768bool ValidateTexImage3D(Context *context,
1769 GLenum target,
1770 GLint level,
1771 GLint internalformat,
1772 GLsizei width,
1773 GLsizei height,
1774 GLsizei depth,
1775 GLint border,
1776 GLenum format,
1777 GLenum type,
1778 const GLvoid *pixels)
1779{
Martin Radev1be913c2016-07-11 17:59:16 +03001780 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001781 {
Jamie Madill437fa652016-05-03 15:13:24 -04001782 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001783 return false;
1784 }
1785
1786 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1787 0, 0, width, height, depth, border, format, type,
1788 pixels);
1789}
1790
1791bool ValidateTexSubImage3D(Context *context,
1792 GLenum target,
1793 GLint level,
1794 GLint xoffset,
1795 GLint yoffset,
1796 GLint zoffset,
1797 GLsizei width,
1798 GLsizei height,
1799 GLsizei depth,
1800 GLenum format,
1801 GLenum type,
1802 const GLvoid *pixels)
1803{
Martin Radev1be913c2016-07-11 17:59:16 +03001804 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001805 {
Jamie Madill437fa652016-05-03 15:13:24 -04001806 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001807 return false;
1808 }
1809
1810 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1811 yoffset, zoffset, width, height, depth, 0, format, type,
1812 pixels);
1813}
1814
1815bool ValidateCompressedTexSubImage3D(Context *context,
1816 GLenum target,
1817 GLint level,
1818 GLint xoffset,
1819 GLint yoffset,
1820 GLint zoffset,
1821 GLsizei width,
1822 GLsizei height,
1823 GLsizei depth,
1824 GLenum format,
1825 GLsizei imageSize,
1826 const GLvoid *data)
1827{
Martin Radev1be913c2016-07-11 17:59:16 +03001828 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001829 {
Jamie Madill437fa652016-05-03 15:13:24 -04001830 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001831 return false;
1832 }
1833
1834 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001835 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001836 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001837 if (blockSizeOrErr.isError())
1838 {
1839 context->handleError(blockSizeOrErr.getError());
1840 return false;
1841 }
1842 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001843 {
Jamie Madill437fa652016-05-03 15:13:24 -04001844 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001845 return false;
1846 }
1847
1848 if (!data)
1849 {
Jamie Madill437fa652016-05-03 15:13:24 -04001850 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001851 return false;
1852 }
1853
1854 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
1855 width, height, depth, 0, GL_NONE, GL_NONE, data);
1856}
1857
Olli Etuaho41997e72016-03-10 13:38:39 +02001858bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1859{
1860 return ValidateGenOrDeleteES3(context, n);
1861}
1862
1863bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1864{
1865 return ValidateGenOrDeleteES3(context, n);
1866}
1867
1868bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1869{
1870 return ValidateGenOrDeleteCountES3(context, count);
1871}
1872
1873bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1874{
1875 return ValidateGenOrDeleteCountES3(context, count);
1876}
1877
1878bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1879{
1880 return ValidateGenOrDeleteES3(context, n);
1881}
1882
1883bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1884{
1885 if (!ValidateGenOrDeleteES3(context, n))
1886 {
1887 return false;
1888 }
1889 for (GLint i = 0; i < n; ++i)
1890 {
1891 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1892 if (transformFeedback != nullptr && transformFeedback->isActive())
1893 {
1894 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001895 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001896 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1897 return false;
1898 }
1899 }
1900 return true;
1901}
1902
1903bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1904{
1905 return ValidateGenOrDeleteES3(context, n);
1906}
1907
1908bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1909{
1910 return ValidateGenOrDeleteES3(context, n);
1911}
1912
1913bool ValidateGenOrDeleteES3(Context *context, GLint n)
1914{
Martin Radev1be913c2016-07-11 17:59:16 +03001915 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001916 {
Jamie Madill437fa652016-05-03 15:13:24 -04001917 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001918 return false;
1919 }
1920 return ValidateGenOrDelete(context, n);
1921}
1922
1923bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1924{
Martin Radev1be913c2016-07-11 17:59:16 +03001925 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001926 {
Jamie Madill437fa652016-05-03 15:13:24 -04001927 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001928 return false;
1929 }
1930 if (count < 0)
1931 {
Jamie Madill437fa652016-05-03 15:13:24 -04001932 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001933 return false;
1934 }
1935 return true;
1936}
1937
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001938bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1939{
Martin Radev1be913c2016-07-11 17:59:16 +03001940 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001941 {
Jamie Madill437fa652016-05-03 15:13:24 -04001942 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001943 return false;
1944 }
1945 switch (primitiveMode)
1946 {
1947 case GL_TRIANGLES:
1948 case GL_LINES:
1949 case GL_POINTS:
1950 break;
1951
1952 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001953 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001954 return false;
1955 }
1956
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001957 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001958 ASSERT(transformFeedback != nullptr);
1959
1960 if (transformFeedback->isActive())
1961 {
Jamie Madill437fa652016-05-03 15:13:24 -04001962 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001963 return false;
1964 }
1965 return true;
1966}
1967
Olli Etuaho37477912016-03-30 14:54:40 +03001968bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
1969{
Martin Radev1be913c2016-07-11 17:59:16 +03001970 if (context->getClientMajorVersion() < 3)
Olli Etuaho37477912016-03-30 14:54:40 +03001971 {
Jamie Madill437fa652016-05-03 15:13:24 -04001972 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho37477912016-03-30 14:54:40 +03001973 return false;
1974 }
1975
1976 if (!context->isSampler(sampler))
1977 {
Jamie Madill437fa652016-05-03 15:13:24 -04001978 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho37477912016-03-30 14:54:40 +03001979 return false;
1980 }
1981
1982 if (!ValidateSamplerObjectParameter(context, pname))
1983 {
1984 return false;
1985 }
1986
Ian Ewellbda75592016-04-18 17:25:54 -04001987 if (!ValidateTexParamParameters(context, GL_TEXTURE_2D, pname, param))
Olli Etuaho37477912016-03-30 14:54:40 +03001988 {
1989 return false;
1990 }
1991 return true;
1992}
1993
1994bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
1995{
1996 // The only float parameters are MIN_LOD and MAX_LOD. For these any value is permissible, so
1997 // ValidateSamplerParameteri can be used for validation here.
1998 return ValidateSamplerParameteri(context, sampler, pname, static_cast<GLint>(param));
1999}
2000
Olli Etuaho4f667482016-03-30 15:56:35 +03002001bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
2002{
Martin Radev1be913c2016-07-11 17:59:16 +03002003 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002004 {
Jamie Madill437fa652016-05-03 15:13:24 -04002005 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002006 return false;
2007 }
2008
2009 return ValidateGetBufferPointervBase(context, target, pname, params);
2010}
2011
2012bool ValidateUnmapBuffer(Context *context, GLenum target)
2013{
Martin Radev1be913c2016-07-11 17:59:16 +03002014 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002015 {
Jamie Madill437fa652016-05-03 15:13:24 -04002016 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03002017 return false;
2018 }
2019
2020 return ValidateUnmapBufferBase(context, target);
2021}
2022
2023bool ValidateMapBufferRange(Context *context,
2024 GLenum target,
2025 GLintptr offset,
2026 GLsizeiptr length,
2027 GLbitfield access)
2028{
Martin Radev1be913c2016-07-11 17:59:16 +03002029 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002030 {
Jamie Madill437fa652016-05-03 15:13:24 -04002031 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002032 return false;
2033 }
2034
2035 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2036}
2037
2038bool ValidateFlushMappedBufferRange(Context *context,
2039 GLenum target,
2040 GLintptr offset,
2041 GLsizeiptr length)
2042{
Martin Radev1be913c2016-07-11 17:59:16 +03002043 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002044 {
Jamie Madill437fa652016-05-03 15:13:24 -04002045 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002046 return false;
2047 }
2048
2049 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2050}
2051
Martin Radev66fb8202016-07-28 11:45:20 +03002052bool ValidateIndexedStateQuery(ValidationContext *context, GLenum pname, GLuint index)
2053{
2054 GLenum nativeType;
2055 unsigned int numParams;
2056 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2057 {
2058 context->handleError(Error(GL_INVALID_ENUM));
2059 return false;
2060 }
2061
2062 const Caps &caps = context->getCaps();
2063 switch (pname)
2064 {
2065 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2066 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2067 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2068 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2069 {
2070 context->handleError(Error(GL_INVALID_VALUE));
2071 return false;
2072 }
2073 break;
2074
2075 case GL_UNIFORM_BUFFER_START:
2076 case GL_UNIFORM_BUFFER_SIZE:
2077 case GL_UNIFORM_BUFFER_BINDING:
2078 if (index >= caps.maxUniformBufferBindings)
2079 {
2080 context->handleError(Error(GL_INVALID_VALUE));
2081 return false;
2082 }
2083 break;
2084 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2085 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2086 if (index >= 3u)
2087 {
2088 context->handleError(Error(GL_INVALID_VALUE));
2089 return false;
2090 }
2091 break;
2092 default:
2093 context->handleError(Error(GL_INVALID_ENUM));
2094 return false;
2095 }
2096
2097 // pname is valid, but there are no parameters to return
2098 if (numParams == 0)
2099 {
2100 return false;
2101 }
2102
2103 return true;
2104}
2105
2106bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2107{
2108 if (!context->getGLVersion().isES3OrGreater())
2109 {
2110 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2111 return false;
2112 }
2113 return ValidateIndexedStateQuery(context, target, index);
2114}
2115
2116bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2117{
2118 if (!context->getGLVersion().isES3OrGreater())
2119 {
2120 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2121 return false;
2122 }
2123 return ValidateIndexedStateQuery(context, target, index);
2124}
2125
Jamie Madillc29968b2016-01-20 11:17:23 -05002126} // namespace gl