blob: c891563639bc054454c58bffc3497c20fca57bb5 [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);
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400480 if (pixelUnpackBuffer != NULL)
481 {
482 // ...the data would be unpacked from the buffer object such that the memory reads required
483 // would exceed the data store size.
Geoff Lang5d601382014-07-22 15:14:06 -0400484 GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400485 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -0700486 const gl::Extents size(width, height, depth);
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700487 const auto &unpack = context->getGLState().getUnpackState();
Jamie Madill4b4cdff2016-06-06 13:53:38 -0700488
Olli Etuaho989cac32016-06-08 16:18:49 -0700489 bool targetIs3D = target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY;
Corentin Wallezc5cacd62016-09-14 14:50:24 -0400490 auto endByteOrErr = formatInfo.computeUnpackEndByte(type, size, unpack, targetIs3D);
491 if (endByteOrErr.isError())
Olli Etuaho989cac32016-06-08 16:18:49 -0700492 {
Corentin Wallezc5cacd62016-09-14 14:50:24 -0400493 context->handleError(endByteOrErr.getError());
Olli Etuaho989cac32016-06-08 16:18:49 -0700494 return false;
495 }
Corentin Wallezc5cacd62016-09-14 14:50:24 -0400496 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
497 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
498 checkedEndByte += checkedOffset;
Olli Etuaho989cac32016-06-08 16:18:49 -0700499
Corentin Wallezc5cacd62016-09-14 14:50:24 -0400500 if (!checkedEndByte.IsValid() ||
501 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400502 {
503 // Overflow past the end of the buffer
Jamie Madill437fa652016-05-03 15:13:24 -0400504 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400505 return false;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400506 }
507
508 // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
509 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400510 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400511 {
Jamie Madillc751d1e2014-10-21 17:46:29 -0400512 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
513
Jamie Madille2e406c2016-06-02 13:04:10 -0400514 if ((checkedOffset.ValueOrDie() % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400515 {
Jamie Madill437fa652016-05-03 15:13:24 -0400516 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400517 return false;
518 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400519 }
520
Jamie Madill7a5f7382014-03-05 15:01:24 -0500521 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700522 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500523 {
Jamie Madill437fa652016-05-03 15:13:24 -0400524 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400525 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500526 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400527 }
528
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400529 return true;
530}
531
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500532bool ValidateES3TexImage2DParameters(Context *context,
533 GLenum target,
534 GLint level,
535 GLenum internalformat,
536 bool isCompressed,
537 bool isSubImage,
538 GLint xoffset,
539 GLint yoffset,
540 GLint zoffset,
541 GLsizei width,
542 GLsizei height,
543 GLsizei depth,
544 GLint border,
545 GLenum format,
546 GLenum type,
547 const GLvoid *pixels)
548{
549 if (!ValidTexture2DDestinationTarget(context, target))
550 {
Jamie Madill437fa652016-05-03 15:13:24 -0400551 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500552 return false;
553 }
554
555 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
556 isSubImage, xoffset, yoffset, zoffset, width, height,
557 depth, border, format, type, pixels);
558}
559
560bool ValidateES3TexImage3DParameters(Context *context,
561 GLenum target,
562 GLint level,
563 GLenum internalformat,
564 bool isCompressed,
565 bool isSubImage,
566 GLint xoffset,
567 GLint yoffset,
568 GLint zoffset,
569 GLsizei width,
570 GLsizei height,
571 GLsizei depth,
572 GLint border,
573 GLenum format,
574 GLenum type,
575 const GLvoid *pixels)
576{
577 if (!ValidTexture3DDestinationTarget(context, target))
578 {
Jamie Madill437fa652016-05-03 15:13:24 -0400579 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500580 return false;
581 }
582
583 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
584 isSubImage, xoffset, yoffset, zoffset, width, height,
585 depth, border, format, type, pixels);
586}
587
Geoff Lang5d601382014-07-22 15:14:06 -0400588struct EffectiveInternalFormatInfo
589{
590 GLenum mEffectiveFormat;
591 GLenum mDestFormat;
592 GLuint mMinRedBits;
593 GLuint mMaxRedBits;
594 GLuint mMinGreenBits;
595 GLuint mMaxGreenBits;
596 GLuint mMinBlueBits;
597 GLuint mMaxBlueBits;
598 GLuint mMinAlphaBits;
599 GLuint mMaxAlphaBits;
600
601 EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits,
602 GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits,
603 GLuint minAlphaBits, GLuint maxAlphaBits)
604 : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits),
605 mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits),
606 mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits),
607 mMaxAlphaBits(maxAlphaBits) {};
608};
609
610typedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
611
612static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList()
613{
614 EffectiveInternalFormatList list;
615
616 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
617 // linear source buffer component sizes.
618 // | Source channel min/max sizes |
619 // Effective Internal Format | N/A | R | G | B | A |
620 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8));
621 list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0));
622 list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0));
623 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0));
624 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0));
625 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4));
626 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1));
627 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8));
628 list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2));
629
630 return list;
631}
632
633static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList()
634{
635 EffectiveInternalFormatList list;
636
637 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
638 // linear source buffer component sizes.
639 // | Source channel min/max sizes |
640 // Effective Internal Format | Dest Format | R | G | B | A |
641 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
642 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX));
643 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
644 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX));
645 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX));
646 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4));
647 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1));
648 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8));
649
650 return list;
651}
652
653static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
654 GLenum *outEffectiveFormat)
655{
656 const EffectiveInternalFormatList *list = NULL;
657 GLenum targetFormat = GL_NONE;
658
659 if (destFormat.pixelBytes > 0)
660 {
661 static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList();
662 list = &sizedList;
663 }
664 else
665 {
666 static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList();
667 list = &unsizedList;
668 targetFormat = destFormat.format;
669 }
670
671 for (size_t curFormat = 0; curFormat < list->size(); ++curFormat)
672 {
673 const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat);
674 if ((formatInfo.mDestFormat == targetFormat) &&
675 (formatInfo.mMinRedBits <= srcFormat.redBits && formatInfo.mMaxRedBits >= srcFormat.redBits) &&
676 (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) &&
677 (formatInfo.mMinBlueBits <= srcFormat.blueBits && formatInfo.mMaxBlueBits >= srcFormat.blueBits) &&
678 (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits))
679 {
680 *outEffectiveFormat = formatInfo.mEffectiveFormat;
681 return true;
682 }
683 }
684
685 return false;
686}
687
688struct CopyConversion
689{
690 GLenum mTextureFormat;
691 GLenum mFramebufferFormat;
692
693 CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
694 : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
695
696 bool operator<(const CopyConversion& other) const
697 {
698 return memcmp(this, &other, sizeof(CopyConversion)) < 0;
699 }
700};
701
702typedef std::set<CopyConversion> CopyConversionSet;
703
704static CopyConversionSet BuildValidES3CopyTexImageCombinations()
705{
706 CopyConversionSet set;
707
708 // From ES 3.0.1 spec, table 3.15
709 set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
710 set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
711 set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
712 set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
713 set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
714 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
715 set.insert(CopyConversion(GL_RED, GL_RED));
716 set.insert(CopyConversion(GL_RED, GL_RG));
717 set.insert(CopyConversion(GL_RED, GL_RGB));
718 set.insert(CopyConversion(GL_RED, GL_RGBA));
719 set.insert(CopyConversion(GL_RG, GL_RG));
720 set.insert(CopyConversion(GL_RG, GL_RGB));
721 set.insert(CopyConversion(GL_RG, GL_RGBA));
722 set.insert(CopyConversion(GL_RGB, GL_RGB));
723 set.insert(CopyConversion(GL_RGB, GL_RGBA));
724 set.insert(CopyConversion(GL_RGBA, GL_RGBA));
725
726 // Necessary for ANGLE back-buffers
727 set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
728 set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
729 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
730 set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
731 set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
732 set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
733 set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
Geoff Lang4e58af62016-08-26 10:56:52 -0400734 set.insert(CopyConversion(GL_BGRA_EXT, GL_BGRA_EXT));
Geoff Lang5d601382014-07-22 15:14:06 -0400735
736 set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
737 set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
738 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
739 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
740 set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
741 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
742 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
743 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
744 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
745 set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
746
747 return set;
748}
749
Corentin Wallez76287682016-04-25 09:23:38 -0400750static bool EqualOrFirstZero(GLuint first, GLuint second)
751{
752 return first == 0 || first == second;
753}
754
Jamie Madill0c8abca2016-07-22 20:21:26 -0400755static bool IsValidES3CopyTexImageCombination(const Format &textureFormat,
756 const Format &framebufferFormat,
757 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400758{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400759 const auto &textureFormatInfo = *textureFormat.info;
760 const auto &framebufferFormatInfo = *framebufferFormat.info;
Geoff Lang5d601382014-07-22 15:14:06 -0400761
762 static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
Jamie Madill0c8abca2016-07-22 20:21:26 -0400763 if (conversionSet.find(CopyConversion(textureFormatInfo.format,
764 framebufferFormatInfo.format)) != conversionSet.end())
Geoff Lang5d601382014-07-22 15:14:06 -0400765 {
766 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
767 // must both be signed, unsigned, or fixed point and both source and destinations
768 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
769 // conversion between fixed and floating point.
770
Jamie Madill0c8abca2016-07-22 20:21:26 -0400771 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
772 (framebufferFormatInfo.colorEncoding == GL_SRGB))
Geoff Lang5d601382014-07-22 15:14:06 -0400773 {
774 return false;
775 }
776
Jamie Madill0c8abca2016-07-22 20:21:26 -0400777 if (((textureFormatInfo.componentType == GL_INT) !=
778 (framebufferFormatInfo.componentType == GL_INT)) ||
779 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
780 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
Geoff Lang5d601382014-07-22 15:14:06 -0400781 {
782 return false;
783 }
784
Jamie Madill0c8abca2016-07-22 20:21:26 -0400785 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
786 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
787 textureFormatInfo.componentType == GL_FLOAT) &&
788 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
789 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
790 framebufferFormatInfo.componentType == GL_FLOAT))
Geoff Lang5d601382014-07-22 15:14:06 -0400791 {
792 return false;
793 }
794
795 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
796 // The effective internal format of the source buffer is determined with the following rules applied in order:
797 // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
798 // effective internal format is the source buffer's sized internal format.
799 // * If the source buffer is a texture that was created with an unsized base internal format, then the
800 // effective internal format is the source image array's effective internal format, as specified by table
801 // 3.12, which is determined from the <format> and <type> that were used when the source image array was
802 // specified by TexImage*.
803 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
804 // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
805 // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
806 // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
807 // is SRGB.
808 const InternalFormat *sourceEffectiveFormat = NULL;
809 if (readBufferHandle != 0)
810 {
811 // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
Jamie Madill0c8abca2016-07-22 20:21:26 -0400812 if (framebufferFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400813 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400814 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400815 }
816 else
817 {
818 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
819 // texture. We can use the same table we use when creating textures to get its effective sized format.
Jamie Madill0c8abca2016-07-22 20:21:26 -0400820 GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferFormatInfo.format,
821 framebufferFormatInfo.type);
Geoff Lang051dbc72015-01-05 15:48:58 -0500822 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400823 }
824 }
825 else
826 {
827 // The effective internal format must be derived from the source framebuffer's channel sizes.
828 // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
Jamie Madill0c8abca2016-07-22 20:21:26 -0400829 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400830 {
831 GLenum effectiveFormat;
Jamie Madill0c8abca2016-07-22 20:21:26 -0400832 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
833 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400834 {
835 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
836 }
837 else
838 {
839 return false;
840 }
841 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400842 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
Geoff Lang5d601382014-07-22 15:14:06 -0400843 {
844 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Jamie Madill0c8abca2016-07-22 20:21:26 -0400845 if (textureFormat.sized &&
846 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
847 (framebufferFormatInfo.greenBits >= 1 &&
848 framebufferFormatInfo.greenBits <= 8) &&
849 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
850 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
Geoff Lang5d601382014-07-22 15:14:06 -0400851 {
852 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
853 }
854 else
855 {
856 return false;
857 }
858 }
859 else
860 {
861 UNREACHABLE();
862 return false;
863 }
864 }
865
Jamie Madill0c8abca2016-07-22 20:21:26 -0400866 if (textureFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400867 {
Corentin Wallez76287682016-04-25 09:23:38 -0400868 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination
869 // format is sized, component sizes of the source and destination formats must exactly
870 // match if the destination format exists.
Jamie Madill0c8abca2016-07-22 20:21:26 -0400871 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
872 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
873 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
874 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
Geoff Lang5d601382014-07-22 15:14:06 -0400875 {
876 return false;
877 }
878 }
879
Geoff Lang5d601382014-07-22 15:14:06 -0400880 return true; // A conversion function exists, and no rule in the specification has precluded conversion
881 // between these formats.
882 }
883
884 return false;
885}
886
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500887bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
888 GLenum target,
889 GLint level,
890 GLenum internalformat,
891 bool isSubImage,
892 GLint xoffset,
893 GLint yoffset,
894 GLint zoffset,
895 GLint x,
896 GLint y,
897 GLsizei width,
898 GLsizei height,
899 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400900{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400901 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400902 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400903 xoffset, yoffset, zoffset, x, y, width, height, border,
904 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400905 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400906 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400907 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400908 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400909
Jamie Madill51f40ec2016-06-15 14:06:00 -0400910 const auto &state = context->getGLState();
911 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
912 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400913
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700914 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400915 {
Jamie Madill437fa652016-05-03 15:13:24 -0400916 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400917 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400918 }
919
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700920 if (readFramebufferID != 0 && framebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400921 {
Jamie Madill437fa652016-05-03 15:13:24 -0400922 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400923 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400924 }
925
Jamie Madill0c8abca2016-07-22 20:21:26 -0400926 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400927
928 if (isSubImage)
929 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400930 if (!IsValidES3CopyTexImageCombination(textureFormat, source->getFormat(),
Jamie Madillc29968b2016-01-20 11:17:23 -0500931 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400932 {
Jamie Madill437fa652016-05-03 15:13:24 -0400933 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400934 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400935 }
936 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400937 else
938 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400939 // Use format/type from the source FBO. (Might not be perfect for all cases?)
940 const auto framebufferFormat = source->getFormat();
941 Format copyFormat(internalformat, framebufferFormat.format, framebufferFormat.type);
942 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400943 {
Jamie Madill437fa652016-05-03 15:13:24 -0400944 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400945 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400946 }
947 }
948
Geoff Lang784a8fd2013-09-24 12:33:16 -0400949 // If width or height is zero, it is a no-op. Return false without setting an error.
950 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400951}
952
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500953bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
954 GLenum target,
955 GLint level,
956 GLenum internalformat,
957 bool isSubImage,
958 GLint xoffset,
959 GLint yoffset,
960 GLint zoffset,
961 GLint x,
962 GLint y,
963 GLsizei width,
964 GLsizei height,
965 GLint border)
966{
967 if (!ValidTexture2DDestinationTarget(context, target))
968 {
Jamie Madill437fa652016-05-03 15:13:24 -0400969 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500970 return false;
971 }
972
973 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
974 xoffset, yoffset, zoffset, x, y, width, height,
975 border);
976}
977
978bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
979 GLenum target,
980 GLint level,
981 GLenum internalformat,
982 bool isSubImage,
983 GLint xoffset,
984 GLint yoffset,
985 GLint zoffset,
986 GLint x,
987 GLint y,
988 GLsizei width,
989 GLsizei height,
990 GLint border)
991{
992 if (!ValidTexture3DDestinationTarget(context, target))
993 {
Jamie Madill437fa652016-05-03 15:13:24 -0400994 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500995 return false;
996 }
997
998 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
999 xoffset, yoffset, zoffset, x, y, width, height,
1000 border);
1001}
1002
1003bool ValidateES3TexStorageParametersBase(Context *context,
1004 GLenum target,
1005 GLsizei levels,
1006 GLenum internalformat,
1007 GLsizei width,
1008 GLsizei height,
1009 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001010{
1011 if (width < 1 || height < 1 || depth < 1 || levels < 1)
1012 {
Jamie Madill437fa652016-05-03 15:13:24 -04001013 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001014 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001015 }
1016
Geoff Langb92c1332015-09-04 12:54:55 -04001017 GLsizei maxDim = std::max(width, height);
1018 if (target != GL_TEXTURE_2D_ARRAY)
1019 {
1020 maxDim = std::max(maxDim, depth);
1021 }
1022
1023 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001024 {
Jamie Madill437fa652016-05-03 15:13:24 -04001025 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001026 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001027 }
1028
Geoff Langaae65a42014-05-26 12:43:44 -04001029 const gl::Caps &caps = context->getCaps();
1030
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001031 switch (target)
1032 {
1033 case GL_TEXTURE_2D:
1034 {
Geoff Langaae65a42014-05-26 12:43:44 -04001035 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1036 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001037 {
Jamie Madill437fa652016-05-03 15:13:24 -04001038 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001039 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001040 }
1041 }
1042 break;
1043
Geoff Lang01c21d22013-09-24 11:52:16 -04001044 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001045 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001046 if (width != height)
1047 {
Jamie Madill437fa652016-05-03 15:13:24 -04001048 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001049 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001050 }
1051
Geoff Langaae65a42014-05-26 12:43:44 -04001052 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001053 {
Jamie Madill437fa652016-05-03 15:13:24 -04001054 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001055 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001056 }
1057 }
1058 break;
1059
1060 case GL_TEXTURE_3D:
1061 {
Geoff Langaae65a42014-05-26 12:43:44 -04001062 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
1063 static_cast<GLuint>(height) > caps.max3DTextureSize ||
1064 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001065 {
Jamie Madill437fa652016-05-03 15:13:24 -04001066 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001067 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001068 }
1069 }
1070 break;
1071
1072 case GL_TEXTURE_2D_ARRAY:
1073 {
Geoff Langaae65a42014-05-26 12:43:44 -04001074 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1075 static_cast<GLuint>(height) > caps.max2DTextureSize ||
1076 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001077 {
Jamie Madill437fa652016-05-03 15:13:24 -04001078 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001079 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001080 }
1081 }
1082 break;
1083
1084 default:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001085 UNREACHABLE();
Geoff Langb1196682014-07-23 13:47:29 -04001086 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001087 }
1088
Geoff Lang691e58c2014-12-19 17:03:25 -05001089 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001090 if (!texture || texture->id() == 0)
1091 {
Jamie Madill437fa652016-05-03 15:13:24 -04001092 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001093 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001094 }
1095
Geoff Lang69cce582015-09-17 13:20:36 -04001096 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001097 {
Jamie Madill437fa652016-05-03 15:13:24 -04001098 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001099 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001100 }
1101
Geoff Lang5d601382014-07-22 15:14:06 -04001102 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Martin Radev1be913c2016-07-11 17:59:16 +03001103 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001104 {
Jamie Madill437fa652016-05-03 15:13:24 -04001105 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001106 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001107 }
1108
Geoff Lang5d601382014-07-22 15:14:06 -04001109 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001110 {
Jamie Madill437fa652016-05-03 15:13:24 -04001111 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001112 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001113 }
1114
1115 return true;
1116}
1117
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001118bool ValidateES3TexStorage2DParameters(Context *context,
1119 GLenum target,
1120 GLsizei levels,
1121 GLenum internalformat,
1122 GLsizei width,
1123 GLsizei height,
1124 GLsizei depth)
1125{
1126 if (!ValidTexture2DTarget(context, target))
1127 {
Jamie Madill437fa652016-05-03 15:13:24 -04001128 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001129 return false;
1130 }
1131
1132 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1133 height, depth);
1134}
1135
1136bool ValidateES3TexStorage3DParameters(Context *context,
1137 GLenum target,
1138 GLsizei levels,
1139 GLenum internalformat,
1140 GLsizei width,
1141 GLsizei height,
1142 GLsizei depth)
1143{
1144 if (!ValidTexture3DTarget(context, target))
1145 {
Jamie Madill437fa652016-05-03 15:13:24 -04001146 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001147 return false;
1148 }
1149
1150 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1151 height, depth);
1152}
1153
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001154bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1155{
Martin Radev1be913c2016-07-11 17:59:16 +03001156 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001157 {
Jamie Madill437fa652016-05-03 15:13:24 -04001158 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001159 return false;
1160 }
1161
1162 return ValidateBeginQueryBase(context, target, id);
1163}
1164
1165bool ValidateEndQuery(gl::Context *context, GLenum target)
1166{
Martin Radev1be913c2016-07-11 17:59:16 +03001167 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001168 {
Jamie Madill437fa652016-05-03 15:13:24 -04001169 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001170 return false;
1171 }
1172
1173 return ValidateEndQueryBase(context, target);
1174}
1175
1176bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1177{
Martin Radev1be913c2016-07-11 17:59:16 +03001178 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001179 {
Jamie Madill437fa652016-05-03 15:13:24 -04001180 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001181 return false;
1182 }
1183
1184 return ValidateGetQueryivBase(context, target, pname);
1185}
1186
1187bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1188{
Martin Radev1be913c2016-07-11 17:59:16 +03001189 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001190 {
Jamie Madill437fa652016-05-03 15:13:24 -04001191 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001192 return false;
1193 }
1194
1195 return ValidateGetQueryObjectValueBase(context, id, pname);
1196}
1197
Geoff Langb1196682014-07-23 13:47:29 -04001198bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
Jamie Madill570f7c82014-07-03 10:38:54 -04001199 GLuint texture, GLint level, GLint layer)
1200{
Martin Radev1be913c2016-07-11 17:59:16 +03001201 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001202 {
Jamie Madill437fa652016-05-03 15:13:24 -04001203 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001204 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001205 }
1206
Jamie Madill55ec3b12014-07-03 10:38:57 -04001207 if (layer < 0)
1208 {
Jamie Madill437fa652016-05-03 15:13:24 -04001209 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001210 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001211 }
1212
1213 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1214 {
1215 return false;
1216 }
1217
1218 const gl::Caps &caps = context->getCaps();
1219 if (texture != 0)
1220 {
1221 gl::Texture *tex = context->getTexture(texture);
1222 ASSERT(tex);
1223
1224 switch (tex->getTarget())
1225 {
1226 case GL_TEXTURE_2D_ARRAY:
1227 {
1228 if (level > gl::log2(caps.max2DTextureSize))
1229 {
Jamie Madill437fa652016-05-03 15:13:24 -04001230 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001231 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001232 }
1233
1234 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1235 {
Jamie Madill437fa652016-05-03 15:13:24 -04001236 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001237 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001238 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001239 }
1240 break;
1241
1242 case GL_TEXTURE_3D:
1243 {
1244 if (level > gl::log2(caps.max3DTextureSize))
1245 {
Jamie Madill437fa652016-05-03 15:13:24 -04001246 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001247 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001248 }
1249
1250 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1251 {
Jamie Madill437fa652016-05-03 15:13:24 -04001252 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001253 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001254 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001255 }
1256 break;
1257
1258 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001259 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001260 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001261 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001262
Jamie Madilla3944d42016-07-22 22:13:26 -04001263 const auto &format = tex->getFormat(tex->getTarget(), level);
1264 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001265 {
Jamie Madill437fa652016-05-03 15:13:24 -04001266 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001267 return false;
1268 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001269 }
1270
1271 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001272}
1273
Corentin Walleze0902642014-11-04 12:32:15 -08001274bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
1275 GLenum internalformat, GLsizei width, GLsizei height)
1276{
1277 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
1278 {
1279 return false;
1280 }
1281
1282 //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.
1283 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1284 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
1285 {
Jamie Madill437fa652016-05-03 15:13:24 -04001286 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -08001287 return false;
1288 }
1289
1290 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
1291 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1292 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1293 {
Jamie Madill437fa652016-05-03 15:13:24 -04001294 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001295 Error(GL_INVALID_OPERATION,
1296 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001297 return false;
1298 }
1299
1300 return true;
1301}
1302
Austin Kinross08332632015-05-05 13:35:47 -07001303bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
1304 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001305{
Martin Radev1be913c2016-07-11 17:59:16 +03001306 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001307 {
Jamie Madill437fa652016-05-03 15:13:24 -04001308 context->handleError(
1309 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001310 return false;
1311 }
1312
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001313 bool defaultFramebuffer = false;
1314
1315 switch (target)
1316 {
1317 case GL_DRAW_FRAMEBUFFER:
1318 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001319 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1320 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001321 case GL_READ_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001322 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1323 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001324 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001325 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001326 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001327 }
1328
Austin Kinross08332632015-05-05 13:35:47 -07001329 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001330}
1331
Jamie Madillc29968b2016-01-20 11:17:23 -05001332bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001333{
Martin Radev1be913c2016-07-11 17:59:16 +03001334 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001335 {
Jamie Madill437fa652016-05-03 15:13:24 -04001336 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001337 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001338 }
1339
Jamie Madill51f40ec2016-06-15 14:06:00 -04001340 if (context->getGLState().getDrawFramebuffer()->checkStatus(context->getContextState()) !=
1341 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001342 {
Jamie Madill437fa652016-05-03 15:13:24 -04001343 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001344 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001345 }
1346
1347 return true;
1348}
1349
Olli Etuaho71dfb362016-03-10 14:04:27 +02001350bool ValidateDrawRangeElements(Context *context,
1351 GLenum mode,
1352 GLuint start,
1353 GLuint end,
1354 GLsizei count,
1355 GLenum type,
1356 const GLvoid *indices,
1357 IndexRange *indexRange)
1358{
Martin Radev1be913c2016-07-11 17:59:16 +03001359 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001360 {
Jamie Madill437fa652016-05-03 15:13:24 -04001361 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001362 return false;
1363 }
1364
1365 if (end < start)
1366 {
Jamie Madill437fa652016-05-03 15:13:24 -04001367 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001368 return false;
1369 }
1370
1371 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1372 {
1373 return false;
1374 }
1375
1376 if (indexRange->end > end || indexRange->start < start)
1377 {
1378 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001379 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001380 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1381 return false;
1382 }
1383 return true;
1384}
1385
Geoff Langb1196682014-07-23 13:47:29 -04001386bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001387{
Martin Radev1be913c2016-07-11 17:59:16 +03001388 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001389 {
Jamie Madill437fa652016-05-03 15:13:24 -04001390 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001391 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001392 }
1393
Jamie Madill78f41802014-08-25 15:47:55 -04001394 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001395}
1396
Jamie Madillb885e572015-02-03 16:16:04 -05001397bool ValidateReadBuffer(Context *context, GLenum src)
1398{
Martin Radev1be913c2016-07-11 17:59:16 +03001399 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001400 {
Jamie Madill437fa652016-05-03 15:13:24 -04001401 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001402 return false;
1403 }
1404
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001405 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001406
1407 if (readFBO == nullptr)
1408 {
Jamie Madill437fa652016-05-03 15:13:24 -04001409 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001410 return false;
1411 }
1412
1413 if (src == GL_NONE)
1414 {
1415 return true;
1416 }
1417
Olli Etuaho84c9f592016-03-09 14:37:25 +02001418 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001419 {
Jamie Madill437fa652016-05-03 15:13:24 -04001420 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001421 return false;
1422 }
1423
1424 if (readFBO->id() == 0)
1425 {
1426 if (src != GL_BACK)
1427 {
1428 const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001429 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001430 return false;
1431 }
1432 }
1433 else
1434 {
1435 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1436
1437 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1438 {
1439 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001440 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001441 return false;
1442 }
1443 }
1444
1445 return true;
1446}
1447
Jamie Madill86af3d22015-07-21 15:14:07 -04001448bool ValidateCompressedTexImage3D(Context *context,
1449 GLenum target,
1450 GLint level,
1451 GLenum internalformat,
1452 GLsizei width,
1453 GLsizei height,
1454 GLsizei depth,
1455 GLint border,
1456 GLsizei imageSize,
1457 const GLvoid *data)
1458{
Martin Radev1be913c2016-07-11 17:59:16 +03001459 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001460 {
Jamie Madill437fa652016-05-03 15:13:24 -04001461 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001462 return false;
1463 }
1464
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001465 if (!ValidTextureTarget(context, target))
1466 {
1467 context->handleError(Error(GL_INVALID_ENUM));
1468 return false;
1469 }
1470
Jamie Madille2e406c2016-06-02 13:04:10 -04001471 // Validate image size
1472 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1473 {
1474 context->handleError(Error(GL_INVALID_VALUE));
1475 return false;
1476 }
1477
Jamie Madill86af3d22015-07-21 15:14:07 -04001478 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001479 if (!formatInfo.compressed)
1480 {
1481 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1482 return false;
1483 }
1484
Jamie Madill513558d2016-06-02 13:04:11 -04001485 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001486 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001487 if (blockSizeOrErr.isError())
1488 {
Jamie Madill513558d2016-06-02 13:04:11 -04001489 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001490 return false;
1491 }
1492 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001493 {
Jamie Madill437fa652016-05-03 15:13:24 -04001494 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001495 return false;
1496 }
1497
1498 // 3D texture target validation
1499 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1500 {
Jamie Madill437fa652016-05-03 15:13:24 -04001501 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001502 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1503 return false;
1504 }
1505
1506 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001507 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
1508 0, width, height, depth, border, GL_NONE, GL_NONE, data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001509 {
1510 return false;
1511 }
1512
1513 return true;
1514}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001515
1516bool ValidateBindVertexArray(Context *context, GLuint array)
1517{
Martin Radev1be913c2016-07-11 17:59:16 +03001518 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001519 {
Jamie Madill437fa652016-05-03 15:13:24 -04001520 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001521 return false;
1522 }
1523
1524 return ValidateBindVertexArrayBase(context, array);
1525}
1526
Austin Kinrossbc781f32015-10-26 09:27:38 -07001527bool ValidateIsVertexArray(Context *context)
1528{
Martin Radev1be913c2016-07-11 17:59:16 +03001529 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001530 {
Jamie Madill437fa652016-05-03 15:13:24 -04001531 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001532 return false;
1533 }
1534
1535 return true;
1536}
Geoff Langc5629752015-12-07 16:29:04 -05001537
1538bool ValidateProgramBinary(Context *context,
1539 GLuint program,
1540 GLenum binaryFormat,
1541 const void *binary,
1542 GLint length)
1543{
Martin Radev1be913c2016-07-11 17:59:16 +03001544 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001545 {
Jamie Madill437fa652016-05-03 15:13:24 -04001546 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001547 return false;
1548 }
1549
1550 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1551}
1552
1553bool ValidateGetProgramBinary(Context *context,
1554 GLuint program,
1555 GLsizei bufSize,
1556 GLsizei *length,
1557 GLenum *binaryFormat,
1558 void *binary)
1559{
Martin Radev1be913c2016-07-11 17:59:16 +03001560 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001561 {
Jamie Madill437fa652016-05-03 15:13:24 -04001562 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001563 return false;
1564 }
1565
1566 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1567}
1568
Olli Etuahof0fee072016-03-30 15:11:58 +03001569bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001570{
Martin Radev1be913c2016-07-11 17:59:16 +03001571 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001572 {
Jamie Madill437fa652016-05-03 15:13:24 -04001573 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001574 return false;
1575 }
1576
1577 if (GetValidProgram(context, program) == nullptr)
1578 {
1579 return false;
1580 }
1581
1582 switch (pname)
1583 {
1584 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001585 if (value != GL_FALSE && value != GL_TRUE)
1586 {
Jamie Madill437fa652016-05-03 15:13:24 -04001587 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001588 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1589 return false;
1590 }
Geoff Langc5629752015-12-07 16:29:04 -05001591 break;
1592
1593 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001594 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001595 return false;
1596 }
1597
1598 return true;
1599}
Jamie Madillc29968b2016-01-20 11:17:23 -05001600
1601bool ValidateBlitFramebuffer(Context *context,
1602 GLint srcX0,
1603 GLint srcY0,
1604 GLint srcX1,
1605 GLint srcY1,
1606 GLint dstX0,
1607 GLint dstY0,
1608 GLint dstX1,
1609 GLint dstY1,
1610 GLbitfield mask,
1611 GLenum filter)
1612{
Martin Radev1be913c2016-07-11 17:59:16 +03001613 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001614 {
Jamie Madill437fa652016-05-03 15:13:24 -04001615 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001616 return false;
1617 }
1618
1619 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1620 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001621}
Jamie Madillc29968b2016-01-20 11:17:23 -05001622
1623bool ValidateClearBufferiv(ValidationContext *context,
1624 GLenum buffer,
1625 GLint drawbuffer,
1626 const GLint *value)
1627{
1628 switch (buffer)
1629 {
1630 case GL_COLOR:
1631 if (drawbuffer < 0 ||
1632 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1633 {
Jamie Madill437fa652016-05-03 15:13:24 -04001634 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001635 return false;
1636 }
1637 break;
1638
1639 case GL_STENCIL:
1640 if (drawbuffer != 0)
1641 {
Jamie Madill437fa652016-05-03 15:13:24 -04001642 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001643 return false;
1644 }
1645 break;
1646
1647 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001648 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001649 return false;
1650 }
1651
1652 return ValidateClearBuffer(context);
1653}
1654
1655bool ValidateClearBufferuiv(ValidationContext *context,
1656 GLenum buffer,
1657 GLint drawbuffer,
1658 const GLuint *value)
1659{
1660 switch (buffer)
1661 {
1662 case GL_COLOR:
1663 if (drawbuffer < 0 ||
1664 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1665 {
Jamie Madill437fa652016-05-03 15:13:24 -04001666 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001667 return false;
1668 }
1669 break;
1670
1671 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001672 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001673 return false;
1674 }
1675
1676 return ValidateClearBuffer(context);
1677}
1678
1679bool ValidateClearBufferfv(ValidationContext *context,
1680 GLenum buffer,
1681 GLint drawbuffer,
1682 const GLfloat *value)
1683{
1684 switch (buffer)
1685 {
1686 case GL_COLOR:
1687 if (drawbuffer < 0 ||
1688 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1689 {
Jamie Madill437fa652016-05-03 15:13:24 -04001690 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001691 return false;
1692 }
1693 break;
1694
1695 case GL_DEPTH:
1696 if (drawbuffer != 0)
1697 {
Jamie Madill437fa652016-05-03 15:13:24 -04001698 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001699 return false;
1700 }
1701 break;
1702
1703 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001704 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001705 return false;
1706 }
1707
1708 return ValidateClearBuffer(context);
1709}
1710
1711bool ValidateClearBufferfi(ValidationContext *context,
1712 GLenum buffer,
1713 GLint drawbuffer,
1714 GLfloat depth,
1715 GLint stencil)
1716{
1717 switch (buffer)
1718 {
1719 case GL_DEPTH_STENCIL:
1720 if (drawbuffer != 0)
1721 {
Jamie Madill437fa652016-05-03 15:13:24 -04001722 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001723 return false;
1724 }
1725 break;
1726
1727 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001728 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001729 return false;
1730 }
1731
1732 return ValidateClearBuffer(context);
1733}
1734
1735bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1736{
Martin Radev1be913c2016-07-11 17:59:16 +03001737 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001738 {
Jamie Madill437fa652016-05-03 15:13:24 -04001739 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001740 return false;
1741 }
1742
1743 return ValidateDrawBuffersBase(context, n, bufs);
1744}
1745
1746bool ValidateCopyTexSubImage3D(Context *context,
1747 GLenum target,
1748 GLint level,
1749 GLint xoffset,
1750 GLint yoffset,
1751 GLint zoffset,
1752 GLint x,
1753 GLint y,
1754 GLsizei width,
1755 GLsizei height)
1756{
Martin Radev1be913c2016-07-11 17:59:16 +03001757 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001758 {
Jamie Madill437fa652016-05-03 15:13:24 -04001759 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001760 return false;
1761 }
1762
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001763 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1764 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001765}
1766
Jamie Madill73a84962016-02-12 09:27:23 -05001767bool ValidateTexImage3D(Context *context,
1768 GLenum target,
1769 GLint level,
1770 GLint internalformat,
1771 GLsizei width,
1772 GLsizei height,
1773 GLsizei depth,
1774 GLint border,
1775 GLenum format,
1776 GLenum type,
1777 const GLvoid *pixels)
1778{
Martin Radev1be913c2016-07-11 17:59:16 +03001779 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001780 {
Jamie Madill437fa652016-05-03 15:13:24 -04001781 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001782 return false;
1783 }
1784
1785 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1786 0, 0, width, height, depth, border, format, type,
1787 pixels);
1788}
1789
1790bool ValidateTexSubImage3D(Context *context,
1791 GLenum target,
1792 GLint level,
1793 GLint xoffset,
1794 GLint yoffset,
1795 GLint zoffset,
1796 GLsizei width,
1797 GLsizei height,
1798 GLsizei depth,
1799 GLenum format,
1800 GLenum type,
1801 const GLvoid *pixels)
1802{
Martin Radev1be913c2016-07-11 17:59:16 +03001803 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001804 {
Jamie Madill437fa652016-05-03 15:13:24 -04001805 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001806 return false;
1807 }
1808
1809 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1810 yoffset, zoffset, width, height, depth, 0, format, type,
1811 pixels);
1812}
1813
1814bool ValidateCompressedTexSubImage3D(Context *context,
1815 GLenum target,
1816 GLint level,
1817 GLint xoffset,
1818 GLint yoffset,
1819 GLint zoffset,
1820 GLsizei width,
1821 GLsizei height,
1822 GLsizei depth,
1823 GLenum format,
1824 GLsizei imageSize,
1825 const GLvoid *data)
1826{
Martin Radev1be913c2016-07-11 17:59:16 +03001827 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001828 {
Jamie Madill437fa652016-05-03 15:13:24 -04001829 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001830 return false;
1831 }
1832
1833 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001834 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001835 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001836 if (blockSizeOrErr.isError())
1837 {
1838 context->handleError(blockSizeOrErr.getError());
1839 return false;
1840 }
1841 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001842 {
Jamie Madill437fa652016-05-03 15:13:24 -04001843 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001844 return false;
1845 }
1846
1847 if (!data)
1848 {
Jamie Madill437fa652016-05-03 15:13:24 -04001849 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001850 return false;
1851 }
1852
1853 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
1854 width, height, depth, 0, GL_NONE, GL_NONE, data);
1855}
1856
Olli Etuaho41997e72016-03-10 13:38:39 +02001857bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1858{
1859 return ValidateGenOrDeleteES3(context, n);
1860}
1861
1862bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1863{
1864 return ValidateGenOrDeleteES3(context, n);
1865}
1866
1867bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1868{
1869 return ValidateGenOrDeleteCountES3(context, count);
1870}
1871
1872bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1873{
1874 return ValidateGenOrDeleteCountES3(context, count);
1875}
1876
1877bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1878{
1879 return ValidateGenOrDeleteES3(context, n);
1880}
1881
1882bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1883{
1884 if (!ValidateGenOrDeleteES3(context, n))
1885 {
1886 return false;
1887 }
1888 for (GLint i = 0; i < n; ++i)
1889 {
1890 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1891 if (transformFeedback != nullptr && transformFeedback->isActive())
1892 {
1893 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001894 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001895 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1896 return false;
1897 }
1898 }
1899 return true;
1900}
1901
1902bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1903{
1904 return ValidateGenOrDeleteES3(context, n);
1905}
1906
1907bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1908{
1909 return ValidateGenOrDeleteES3(context, n);
1910}
1911
1912bool ValidateGenOrDeleteES3(Context *context, GLint n)
1913{
Martin Radev1be913c2016-07-11 17:59:16 +03001914 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001915 {
Jamie Madill437fa652016-05-03 15:13:24 -04001916 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001917 return false;
1918 }
1919 return ValidateGenOrDelete(context, n);
1920}
1921
1922bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1923{
Martin Radev1be913c2016-07-11 17:59:16 +03001924 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001925 {
Jamie Madill437fa652016-05-03 15:13:24 -04001926 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001927 return false;
1928 }
1929 if (count < 0)
1930 {
Jamie Madill437fa652016-05-03 15:13:24 -04001931 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001932 return false;
1933 }
1934 return true;
1935}
1936
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001937bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1938{
Martin Radev1be913c2016-07-11 17:59:16 +03001939 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001940 {
Jamie Madill437fa652016-05-03 15:13:24 -04001941 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001942 return false;
1943 }
1944 switch (primitiveMode)
1945 {
1946 case GL_TRIANGLES:
1947 case GL_LINES:
1948 case GL_POINTS:
1949 break;
1950
1951 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001952 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001953 return false;
1954 }
1955
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001956 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001957 ASSERT(transformFeedback != nullptr);
1958
1959 if (transformFeedback->isActive())
1960 {
Jamie Madill437fa652016-05-03 15:13:24 -04001961 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001962 return false;
1963 }
1964 return true;
1965}
1966
Olli Etuaho37477912016-03-30 14:54:40 +03001967bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
1968{
Martin Radev1be913c2016-07-11 17:59:16 +03001969 if (context->getClientMajorVersion() < 3)
Olli Etuaho37477912016-03-30 14:54:40 +03001970 {
Jamie Madill437fa652016-05-03 15:13:24 -04001971 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho37477912016-03-30 14:54:40 +03001972 return false;
1973 }
1974
1975 if (!context->isSampler(sampler))
1976 {
Jamie Madill437fa652016-05-03 15:13:24 -04001977 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho37477912016-03-30 14:54:40 +03001978 return false;
1979 }
1980
1981 if (!ValidateSamplerObjectParameter(context, pname))
1982 {
1983 return false;
1984 }
1985
Ian Ewellbda75592016-04-18 17:25:54 -04001986 if (!ValidateTexParamParameters(context, GL_TEXTURE_2D, pname, param))
Olli Etuaho37477912016-03-30 14:54:40 +03001987 {
1988 return false;
1989 }
1990 return true;
1991}
1992
1993bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
1994{
1995 // The only float parameters are MIN_LOD and MAX_LOD. For these any value is permissible, so
1996 // ValidateSamplerParameteri can be used for validation here.
1997 return ValidateSamplerParameteri(context, sampler, pname, static_cast<GLint>(param));
1998}
1999
Olli Etuaho4f667482016-03-30 15:56:35 +03002000bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
2001{
Martin Radev1be913c2016-07-11 17:59:16 +03002002 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002003 {
Jamie Madill437fa652016-05-03 15:13:24 -04002004 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002005 return false;
2006 }
2007
2008 return ValidateGetBufferPointervBase(context, target, pname, params);
2009}
2010
2011bool ValidateUnmapBuffer(Context *context, GLenum target)
2012{
Martin Radev1be913c2016-07-11 17:59:16 +03002013 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002014 {
Jamie Madill437fa652016-05-03 15:13:24 -04002015 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03002016 return false;
2017 }
2018
2019 return ValidateUnmapBufferBase(context, target);
2020}
2021
2022bool ValidateMapBufferRange(Context *context,
2023 GLenum target,
2024 GLintptr offset,
2025 GLsizeiptr length,
2026 GLbitfield access)
2027{
Martin Radev1be913c2016-07-11 17:59:16 +03002028 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002029 {
Jamie Madill437fa652016-05-03 15:13:24 -04002030 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002031 return false;
2032 }
2033
2034 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2035}
2036
2037bool ValidateFlushMappedBufferRange(Context *context,
2038 GLenum target,
2039 GLintptr offset,
2040 GLsizeiptr length)
2041{
Martin Radev1be913c2016-07-11 17:59:16 +03002042 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002043 {
Jamie Madill437fa652016-05-03 15:13:24 -04002044 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002045 return false;
2046 }
2047
2048 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2049}
2050
Martin Radev66fb8202016-07-28 11:45:20 +03002051bool ValidateIndexedStateQuery(ValidationContext *context, GLenum pname, GLuint index)
2052{
2053 GLenum nativeType;
2054 unsigned int numParams;
2055 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2056 {
2057 context->handleError(Error(GL_INVALID_ENUM));
2058 return false;
2059 }
2060
2061 const Caps &caps = context->getCaps();
2062 switch (pname)
2063 {
2064 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2065 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2066 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2067 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2068 {
2069 context->handleError(Error(GL_INVALID_VALUE));
2070 return false;
2071 }
2072 break;
2073
2074 case GL_UNIFORM_BUFFER_START:
2075 case GL_UNIFORM_BUFFER_SIZE:
2076 case GL_UNIFORM_BUFFER_BINDING:
2077 if (index >= caps.maxUniformBufferBindings)
2078 {
2079 context->handleError(Error(GL_INVALID_VALUE));
2080 return false;
2081 }
2082 break;
2083 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2084 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2085 if (index >= 3u)
2086 {
2087 context->handleError(Error(GL_INVALID_VALUE));
2088 return false;
2089 }
2090 break;
2091 default:
2092 context->handleError(Error(GL_INVALID_ENUM));
2093 return false;
2094 }
2095
2096 // pname is valid, but there are no parameters to return
2097 if (numParams == 0)
2098 {
2099 return false;
2100 }
2101
2102 return true;
2103}
2104
2105bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2106{
2107 if (!context->getGLVersion().isES3OrGreater())
2108 {
2109 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2110 return false;
2111 }
2112 return ValidateIndexedStateQuery(context, target, index);
2113}
2114
2115bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2116{
2117 if (!context->getGLVersion().isES3OrGreater())
2118 {
2119 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2120 return false;
2121 }
2122 return ValidateIndexedStateQuery(context, target, index);
2123}
2124
Jamie Madillc29968b2016-01-20 11:17:23 -05002125} // namespace gl