blob: 6f3d8002a80cca69fd5a2ebc9beb4acf86e90878 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES3.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES.h"
12#include "libANGLE/Context.h"
13#include "libANGLE/Texture.h"
14#include "libANGLE/Framebuffer.h"
15#include "libANGLE/Renderbuffer.h"
16#include "libANGLE/formatutils.h"
17#include "libANGLE/FramebufferAttachment.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040018
19#include "common/mathutil.h"
Geoff Langa9be0dc2014-12-17 12:34:40 -050020#include "common/utilities.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040021
Jamie Madille2e406c2016-06-02 13:04:10 -040022using namespace angle;
23
Geoff Lange8ebe7f2013-08-05 15:03:13 -040024namespace gl
25{
26
Geoff Lang5d601382014-07-22 15:14:06 -040027struct ES3FormatCombination
28{
29 GLenum internalFormat;
30 GLenum format;
31 GLenum type;
32};
33
34bool operator<(const ES3FormatCombination& a, const ES3FormatCombination& b)
35{
36 return memcmp(&a, &b, sizeof(ES3FormatCombination)) < 0;
37}
38
39typedef std::set<ES3FormatCombination> ES3FormatCombinationSet;
40
41static inline void InsertES3FormatCombo(ES3FormatCombinationSet *set, GLenum internalFormat, GLenum format, GLenum type)
42{
43 ES3FormatCombination info;
44 info.internalFormat = internalFormat;
45 info.format = format;
46 info.type = type;
47 set->insert(info);
48}
49
50ES3FormatCombinationSet BuildES3FormatSet()
51{
52 ES3FormatCombinationSet set;
53
54 // Format combinations from ES 3.0.1 spec, table 3.2
55
Geoff Lang4e58af62016-08-26 10:56:52 -040056 // clang-format off
Geoff Lang5d601382014-07-22 15:14:06 -040057 // | Internal format | Format | Type |
58 // | | | |
59 InsertES3FormatCombo(&set, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE );
60 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE );
61 InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE );
62 InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE );
63 InsertES3FormatCombo(&set, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE );
64 InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 );
65 InsertES3FormatCombo(&set, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV );
66 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV );
67 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 );
68 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT );
69 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT_OES );
70 InsertES3FormatCombo(&set, GL_RGBA32F, GL_RGBA, GL_FLOAT );
71 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_FLOAT );
72 InsertES3FormatCombo(&set, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE );
73 InsertES3FormatCombo(&set, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE );
74 InsertES3FormatCombo(&set, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT );
75 InsertES3FormatCombo(&set, GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT );
76 InsertES3FormatCombo(&set, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT );
77 InsertES3FormatCombo(&set, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT );
78 InsertES3FormatCombo(&set, GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV );
79 InsertES3FormatCombo(&set, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE );
80 InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE );
81 InsertES3FormatCombo(&set, GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE );
82 InsertES3FormatCombo(&set, GL_RGB8_SNORM, GL_RGB, GL_BYTE );
83 InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 );
84 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV );
85 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV );
86 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT );
87 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT_OES );
88 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT );
89 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT_OES );
90 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT );
91 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT_OES );
92 InsertES3FormatCombo(&set, GL_RGB32F, GL_RGB, GL_FLOAT );
93 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_FLOAT );
94 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT );
95 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_FLOAT );
96 InsertES3FormatCombo(&set, GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE );
97 InsertES3FormatCombo(&set, GL_RGB8I, GL_RGB_INTEGER, GL_BYTE );
98 InsertES3FormatCombo(&set, GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT );
99 InsertES3FormatCombo(&set, GL_RGB16I, GL_RGB_INTEGER, GL_SHORT );
100 InsertES3FormatCombo(&set, GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT );
101 InsertES3FormatCombo(&set, GL_RGB32I, GL_RGB_INTEGER, GL_INT );
102 InsertES3FormatCombo(&set, GL_RG8, GL_RG, GL_UNSIGNED_BYTE );
103 InsertES3FormatCombo(&set, GL_RG8_SNORM, GL_RG, GL_BYTE );
104 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT );
105 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT_OES );
106 InsertES3FormatCombo(&set, GL_RG32F, GL_RG, GL_FLOAT );
107 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_FLOAT );
108 InsertES3FormatCombo(&set, GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE );
109 InsertES3FormatCombo(&set, GL_RG8I, GL_RG_INTEGER, GL_BYTE );
110 InsertES3FormatCombo(&set, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT );
111 InsertES3FormatCombo(&set, GL_RG16I, GL_RG_INTEGER, GL_SHORT );
112 InsertES3FormatCombo(&set, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT );
113 InsertES3FormatCombo(&set, GL_RG32I, GL_RG_INTEGER, GL_INT );
114 InsertES3FormatCombo(&set, GL_R8, GL_RED, GL_UNSIGNED_BYTE );
115 InsertES3FormatCombo(&set, GL_R8_SNORM, GL_RED, GL_BYTE );
116 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT );
117 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT_OES );
118 InsertES3FormatCombo(&set, GL_R32F, GL_RED, GL_FLOAT );
119 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_FLOAT );
120 InsertES3FormatCombo(&set, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE );
121 InsertES3FormatCombo(&set, GL_R8I, GL_RED_INTEGER, GL_BYTE );
122 InsertES3FormatCombo(&set, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT );
123 InsertES3FormatCombo(&set, GL_R16I, GL_RED_INTEGER, GL_SHORT );
124 InsertES3FormatCombo(&set, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT );
125 InsertES3FormatCombo(&set, GL_R32I, GL_RED_INTEGER, GL_INT );
126
127 // Unsized formats
128 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE );
129 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 );
130 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 );
131 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE );
132 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 );
133 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE );
134 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE );
135 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE );
136 InsertES3FormatCombo(&set, GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE );
137 InsertES3FormatCombo(&set, GL_SRGB_EXT, GL_SRGB_EXT, GL_UNSIGNED_BYTE );
Jamie Madill689325c2015-07-20 14:36:53 -0400138 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_UNSIGNED_BYTE );
139 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_FLOAT );
140 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_HALF_FLOAT );
141 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_HALF_FLOAT_OES );
142 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_UNSIGNED_BYTE );
143 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_FLOAT );
144 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_HALF_FLOAT );
145 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_HALF_FLOAT_OES );
146 InsertES3FormatCombo(&set, GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 );
Geoff Lang5d601382014-07-22 15:14:06 -0400147
148 // Depth stencil formats
149 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT );
150 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
151 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
152 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT );
153 InsertES3FormatCombo(&set, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 );
154 InsertES3FormatCombo(&set, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
155
156 // From GL_EXT_sRGB
157 InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE );
158 InsertES3FormatCombo(&set, GL_SRGB8, GL_SRGB_EXT, GL_UNSIGNED_BYTE );
159
160 // From GL_OES_texture_float
Jeff Muizelaarbb1a5be2015-12-02 12:03:46 -0500161 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_FLOAT );
162 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_FLOAT );
Geoff Lang5d601382014-07-22 15:14:06 -0400163 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT );
164 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT );
165 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_FLOAT );
166
167 // From GL_OES_texture_half_float
Geoff Lang4e58af62016-08-26 10:56:52 -0400168 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES );
169 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_HALF_FLOAT_OES );
Geoff Lang5d601382014-07-22 15:14:06 -0400170 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT );
171 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES );
172 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT );
173 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES );
174 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT );
175 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES );
176
177 // From GL_EXT_texture_format_BGRA8888
178 InsertES3FormatCombo(&set, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
179
180 // From GL_EXT_texture_storage
181 // | Internal format | Format | Type |
182 // | | | |
183 InsertES3FormatCombo(&set, GL_ALPHA8_EXT, GL_ALPHA, GL_UNSIGNED_BYTE );
184 InsertES3FormatCombo(&set, GL_LUMINANCE8_EXT, GL_LUMINANCE, GL_UNSIGNED_BYTE );
185 InsertES3FormatCombo(&set, GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE );
186 InsertES3FormatCombo(&set, GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT );
187 InsertES3FormatCombo(&set, GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT );
188 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT );
189 InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT );
190 InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT_OES );
191 InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT );
192 InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT_OES );
193 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT );
194 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES );
195
196 // From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888
197 InsertES3FormatCombo(&set, GL_BGRA8_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
198 InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT);
199 InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
200 InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT);
201 InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
202
Geoff Lang4e58af62016-08-26 10:56:52 -0400203 // From GL_ANGLE_depth_texture and OES_depth_texture
Geoff Lang5d601382014-07-22 15:14:06 -0400204 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8_OES );
Geoff Lang4e58af62016-08-26 10:56:52 -0400205 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT );
206 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
Geoff Lang5d601382014-07-22 15:14:06 -0400207
Vincent Lang25ab4512016-05-13 18:13:59 +0200208 // From GL_EXT_texture_norm16
209 InsertES3FormatCombo(&set, GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT);
210 InsertES3FormatCombo(&set, GL_RG16_EXT, GL_RG, GL_UNSIGNED_SHORT);
211 InsertES3FormatCombo(&set, GL_RGB16_EXT, GL_RGB, GL_UNSIGNED_SHORT);
212 InsertES3FormatCombo(&set, GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT);
213 InsertES3FormatCombo(&set, GL_R16_SNORM_EXT, GL_RED, GL_SHORT);
214 InsertES3FormatCombo(&set, GL_RG16_SNORM_EXT, GL_RG, GL_SHORT);
215 InsertES3FormatCombo(&set, GL_RGB16_SNORM_EXT, GL_RGB, GL_SHORT);
216 InsertES3FormatCombo(&set, GL_RGBA16_SNORM_EXT, GL_RGBA, GL_SHORT);
Geoff Lang4e58af62016-08-26 10:56:52 -0400217 // clang-format on
Vincent Lang25ab4512016-05-13 18:13:59 +0200218
Geoff Lang5d601382014-07-22 15:14:06 -0400219 return set;
220}
221
222static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
223{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500224 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
225 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
226 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
227 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
Geoff Langbaadf232014-08-04 13:58:02 -0400228 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
Martin Radev1be913c2016-07-11 17:59:16 +0300229 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Geoff Lang5d601382014-07-22 15:14:06 -0400230 {
Jamie Madill437fa652016-05-03 15:13:24 -0400231 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400232 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400233 }
234
235 // The type and format are valid if any supported internal format has that type and format
236 bool formatSupported = false;
237 bool typeSupported = false;
238
239 static const ES3FormatCombinationSet es3FormatSet = BuildES3FormatSet();
240 for (ES3FormatCombinationSet::const_iterator i = es3FormatSet.begin(); i != es3FormatSet.end(); i++)
241 {
242 if (i->format == format || i->type == type)
243 {
244 const gl::InternalFormat &info = gl::GetInternalFormatInfo(i->internalFormat);
Martin Radev1be913c2016-07-11 17:59:16 +0300245 bool supported =
246 info.textureSupport(context->getClientMajorVersion(), context->getExtensions());
Geoff Langbaadf232014-08-04 13:58:02 -0400247 if (supported && i->type == type)
Geoff Lang5d601382014-07-22 15:14:06 -0400248 {
249 typeSupported = true;
250 }
Geoff Langbaadf232014-08-04 13:58:02 -0400251 if (supported && i->format == format)
Geoff Lang5d601382014-07-22 15:14:06 -0400252 {
253 formatSupported = true;
254 }
Geoff Langbaadf232014-08-04 13:58:02 -0400255
256 // Early-out if both type and format are supported now
257 if (typeSupported && formatSupported)
258 {
259 break;
260 }
Geoff Lang5d601382014-07-22 15:14:06 -0400261 }
262 }
263
264 if (!typeSupported || !formatSupported)
265 {
Jamie Madill437fa652016-05-03 15:13:24 -0400266 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400267 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400268 }
269
270 // Check if this is a valid format combination to load texture data
271 ES3FormatCombination searchFormat;
272 searchFormat.internalFormat = internalFormat;
273 searchFormat.format = format;
274 searchFormat.type = type;
275
276 if (es3FormatSet.find(searchFormat) == es3FormatSet.end())
277 {
Jamie Madill437fa652016-05-03 15:13:24 -0400278 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400279 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400280 }
281
282 return true;
283}
284
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500285bool ValidateES3TexImageParametersBase(Context *context,
286 GLenum target,
287 GLint level,
288 GLenum internalformat,
289 bool isCompressed,
290 bool isSubImage,
291 GLint xoffset,
292 GLint yoffset,
293 GLint zoffset,
294 GLsizei width,
295 GLsizei height,
296 GLsizei depth,
297 GLint border,
298 GLenum format,
299 GLenum type,
300 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400301{
302 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -0700303 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400304 {
Jamie Madill437fa652016-05-03 15:13:24 -0400305 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400306 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400307 }
308
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400309 // Verify zero border
310 if (border != 0)
311 {
Jamie Madill437fa652016-05-03 15:13:24 -0400312 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400313 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400314 }
315
Jamie Madill6f38f822014-06-06 17:12:20 -0400316 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
317 std::numeric_limits<GLsizei>::max() - xoffset < width ||
318 std::numeric_limits<GLsizei>::max() - yoffset < height ||
319 std::numeric_limits<GLsizei>::max() - zoffset < depth)
320 {
Jamie Madill437fa652016-05-03 15:13:24 -0400321 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400322 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400323 }
324
Geoff Langaae65a42014-05-26 12:43:44 -0400325 const gl::Caps &caps = context->getCaps();
326
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400327 switch (target)
328 {
329 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500330 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
331 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400332 {
Jamie Madill437fa652016-05-03 15:13:24 -0400333 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500334 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400335 }
336 break;
337
338 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
339 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
340 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
341 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
342 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
343 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500344 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400345 {
Jamie Madill437fa652016-05-03 15:13:24 -0400346 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500347 return false;
348 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400349
Geoff Langa9be0dc2014-12-17 12:34:40 -0500350 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
351 {
Jamie Madill437fa652016-05-03 15:13:24 -0400352 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500353 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400354 }
355 break;
356
357 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500358 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
359 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
360 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400361 {
Jamie Madill437fa652016-05-03 15:13:24 -0400362 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500363 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400364 }
365 break;
366
Geoff Langa9be0dc2014-12-17 12:34:40 -0500367 case GL_TEXTURE_2D_ARRAY:
368 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
369 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
Geoff Langb92c1332015-09-04 12:54:55 -0400370 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500371 {
Jamie Madill437fa652016-05-03 15:13:24 -0400372 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500373 return false;
374 }
375 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400376
377 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400378 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400379 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400380 }
381
Geoff Lang691e58c2014-12-19 17:03:25 -0500382 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400383 if (!texture)
384 {
Jamie Madill437fa652016-05-03 15:13:24 -0400385 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400386 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400387 }
388
Geoff Lang69cce582015-09-17 13:20:36 -0400389 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400390 {
Jamie Madill437fa652016-05-03 15:13:24 -0400391 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400392 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400393 }
394
395 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400396 GLenum actualInternalFormat =
397 isSubImage ? texture->getFormat(target, level).asSized() : internalformat;
Geoff Lang5d601382014-07-22 15:14:06 -0400398 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400399 if (isCompressed)
400 {
tmartino7c102692015-10-02 16:43:40 -0400401 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400402 {
Jamie Madill437fa652016-05-03 15:13:24 -0400403 context->handleError(Error(
tmartino7c102692015-10-02 16:43:40 -0400404 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format."));
Geoff Langb1196682014-07-23 13:47:29 -0400405 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400406 }
407
tmartino7c102692015-10-02 16:43:40 -0400408 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400409 {
Jamie Madill437fa652016-05-03 15:13:24 -0400410 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400411 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400412 }
413
Martin Radev1be913c2016-07-11 17:59:16 +0300414 if (!actualFormatInfo.textureSupport(context->getClientMajorVersion(),
415 context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400416 {
Jamie Madill437fa652016-05-03 15:13:24 -0400417 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang839ce0b2015-10-23 13:13:12 -0400418 return false;
419 }
420
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400421 if (target == GL_TEXTURE_3D)
422 {
Jamie Madill437fa652016-05-03 15:13:24 -0400423 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400424 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400425 }
426 }
427 else
428 {
Geoff Langbaadf232014-08-04 13:58:02 -0400429 if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400430 {
Geoff Lang5d601382014-07-22 15:14:06 -0400431 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400432 }
433
434 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
435 {
Jamie Madill437fa652016-05-03 15:13:24 -0400436 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400437 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400438 }
439 }
440
441 // Validate sub image parameters
442 if (isSubImage)
443 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500444 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400445 {
Jamie Madill437fa652016-05-03 15:13:24 -0400446 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400447 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400448 }
449
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400450 if (width == 0 || height == 0 || depth == 0)
451 {
452 return false;
453 }
454
455 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
456 {
Jamie Madill437fa652016-05-03 15:13:24 -0400457 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400458 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400459 }
460
461 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
462 std::numeric_limits<GLsizei>::max() - yoffset < height ||
463 std::numeric_limits<GLsizei>::max() - zoffset < depth)
464 {
Jamie Madill437fa652016-05-03 15:13:24 -0400465 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400466 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400467 }
468
Geoff Langa9be0dc2014-12-17 12:34:40 -0500469 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
470 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
471 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400472 {
Jamie Madill437fa652016-05-03 15:13:24 -0400473 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400474 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400475 }
476 }
477
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400478 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700479 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400480 if (pixelUnpackBuffer != NULL)
481 {
482 // ...the data would be unpacked from the buffer object such that the memory reads required
483 // would exceed the data store size.
Geoff Lang5d601382014-07-22 15:14:06 -0400484 GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400485 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -0700486 const gl::Extents size(width, height, depth);
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700487 const auto &unpack = context->getGLState().getUnpackState();
Jamie Madill4b4cdff2016-06-06 13:53:38 -0700488
489 auto copyBytesOrErr = formatInfo.computeUnpackSize(type, size, unpack);
Jamie Madille2e406c2016-06-02 13:04:10 -0400490 if (copyBytesOrErr.isError())
491 {
492 context->handleError(copyBytesOrErr.getError());
493 return false;
494 }
495 CheckedNumeric<size_t> checkedCopyBytes(copyBytesOrErr.getResult());
496 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
497 checkedCopyBytes += checkedOffset;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400498
Olli Etuaho989cac32016-06-08 16:18:49 -0700499 auto rowPitchOrErr =
500 formatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength);
501 if (rowPitchOrErr.isError())
502 {
503 context->handleError(rowPitchOrErr.getError());
504 return false;
505 }
506 auto depthPitchOrErr = formatInfo.computeDepthPitch(type, width, height, unpack.alignment,
507 unpack.rowLength, unpack.imageHeight);
508 if (depthPitchOrErr.isError())
509 {
510 context->handleError(depthPitchOrErr.getError());
511 return false;
512 }
513
514 bool targetIs3D = target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY;
515 auto skipBytesOrErr = formatInfo.computeSkipBytes(
516 rowPitchOrErr.getResult(), depthPitchOrErr.getResult(), unpack.skipImages,
517 unpack.skipRows, unpack.skipPixels, targetIs3D);
518 if (skipBytesOrErr.isError())
519 {
520 context->handleError(skipBytesOrErr.getError());
521 return false;
522 }
523 checkedCopyBytes += skipBytesOrErr.getResult();
524
Jamie Madille2e406c2016-06-02 13:04:10 -0400525 if (!checkedCopyBytes.IsValid() ||
526 (checkedCopyBytes.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400527 {
528 // Overflow past the end of the buffer
Jamie Madill437fa652016-05-03 15:13:24 -0400529 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400530 return false;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400531 }
532
533 // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
534 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400535 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400536 {
Jamie Madillc751d1e2014-10-21 17:46:29 -0400537 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
538
Jamie Madille2e406c2016-06-02 13:04:10 -0400539 if ((checkedOffset.ValueOrDie() % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400540 {
Jamie Madill437fa652016-05-03 15:13:24 -0400541 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400542 return false;
543 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400544 }
545
Jamie Madill7a5f7382014-03-05 15:01:24 -0500546 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700547 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500548 {
Jamie Madill437fa652016-05-03 15:13:24 -0400549 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400550 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500551 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400552 }
553
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400554 return true;
555}
556
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500557bool ValidateES3TexImage2DParameters(Context *context,
558 GLenum target,
559 GLint level,
560 GLenum internalformat,
561 bool isCompressed,
562 bool isSubImage,
563 GLint xoffset,
564 GLint yoffset,
565 GLint zoffset,
566 GLsizei width,
567 GLsizei height,
568 GLsizei depth,
569 GLint border,
570 GLenum format,
571 GLenum type,
572 const GLvoid *pixels)
573{
574 if (!ValidTexture2DDestinationTarget(context, target))
575 {
Jamie Madill437fa652016-05-03 15:13:24 -0400576 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500577 return false;
578 }
579
580 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
581 isSubImage, xoffset, yoffset, zoffset, width, height,
582 depth, border, format, type, pixels);
583}
584
585bool ValidateES3TexImage3DParameters(Context *context,
586 GLenum target,
587 GLint level,
588 GLenum internalformat,
589 bool isCompressed,
590 bool isSubImage,
591 GLint xoffset,
592 GLint yoffset,
593 GLint zoffset,
594 GLsizei width,
595 GLsizei height,
596 GLsizei depth,
597 GLint border,
598 GLenum format,
599 GLenum type,
600 const GLvoid *pixels)
601{
602 if (!ValidTexture3DDestinationTarget(context, target))
603 {
Jamie Madill437fa652016-05-03 15:13:24 -0400604 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500605 return false;
606 }
607
608 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
609 isSubImage, xoffset, yoffset, zoffset, width, height,
610 depth, border, format, type, pixels);
611}
612
Geoff Lang5d601382014-07-22 15:14:06 -0400613struct EffectiveInternalFormatInfo
614{
615 GLenum mEffectiveFormat;
616 GLenum mDestFormat;
617 GLuint mMinRedBits;
618 GLuint mMaxRedBits;
619 GLuint mMinGreenBits;
620 GLuint mMaxGreenBits;
621 GLuint mMinBlueBits;
622 GLuint mMaxBlueBits;
623 GLuint mMinAlphaBits;
624 GLuint mMaxAlphaBits;
625
626 EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits,
627 GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits,
628 GLuint minAlphaBits, GLuint maxAlphaBits)
629 : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits),
630 mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits),
631 mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits),
632 mMaxAlphaBits(maxAlphaBits) {};
633};
634
635typedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
636
637static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList()
638{
639 EffectiveInternalFormatList list;
640
641 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
642 // linear source buffer component sizes.
643 // | Source channel min/max sizes |
644 // Effective Internal Format | N/A | R | G | B | A |
645 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8));
646 list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0));
647 list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0));
648 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0));
649 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0));
650 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4));
651 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1));
652 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8));
653 list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2));
654
655 return list;
656}
657
658static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList()
659{
660 EffectiveInternalFormatList list;
661
662 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
663 // linear source buffer component sizes.
664 // | Source channel min/max sizes |
665 // Effective Internal Format | Dest Format | R | G | B | A |
666 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
667 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX));
668 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
669 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX));
670 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX));
671 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4));
672 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1));
673 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8));
674
675 return list;
676}
677
678static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
679 GLenum *outEffectiveFormat)
680{
681 const EffectiveInternalFormatList *list = NULL;
682 GLenum targetFormat = GL_NONE;
683
684 if (destFormat.pixelBytes > 0)
685 {
686 static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList();
687 list = &sizedList;
688 }
689 else
690 {
691 static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList();
692 list = &unsizedList;
693 targetFormat = destFormat.format;
694 }
695
696 for (size_t curFormat = 0; curFormat < list->size(); ++curFormat)
697 {
698 const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat);
699 if ((formatInfo.mDestFormat == targetFormat) &&
700 (formatInfo.mMinRedBits <= srcFormat.redBits && formatInfo.mMaxRedBits >= srcFormat.redBits) &&
701 (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) &&
702 (formatInfo.mMinBlueBits <= srcFormat.blueBits && formatInfo.mMaxBlueBits >= srcFormat.blueBits) &&
703 (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits))
704 {
705 *outEffectiveFormat = formatInfo.mEffectiveFormat;
706 return true;
707 }
708 }
709
710 return false;
711}
712
713struct CopyConversion
714{
715 GLenum mTextureFormat;
716 GLenum mFramebufferFormat;
717
718 CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
719 : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
720
721 bool operator<(const CopyConversion& other) const
722 {
723 return memcmp(this, &other, sizeof(CopyConversion)) < 0;
724 }
725};
726
727typedef std::set<CopyConversion> CopyConversionSet;
728
729static CopyConversionSet BuildValidES3CopyTexImageCombinations()
730{
731 CopyConversionSet set;
732
733 // From ES 3.0.1 spec, table 3.15
734 set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
735 set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
736 set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
737 set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
738 set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
739 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
740 set.insert(CopyConversion(GL_RED, GL_RED));
741 set.insert(CopyConversion(GL_RED, GL_RG));
742 set.insert(CopyConversion(GL_RED, GL_RGB));
743 set.insert(CopyConversion(GL_RED, GL_RGBA));
744 set.insert(CopyConversion(GL_RG, GL_RG));
745 set.insert(CopyConversion(GL_RG, GL_RGB));
746 set.insert(CopyConversion(GL_RG, GL_RGBA));
747 set.insert(CopyConversion(GL_RGB, GL_RGB));
748 set.insert(CopyConversion(GL_RGB, GL_RGBA));
749 set.insert(CopyConversion(GL_RGBA, GL_RGBA));
750
751 // Necessary for ANGLE back-buffers
752 set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
753 set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
754 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
755 set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
756 set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
757 set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
758 set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
Geoff Lang4e58af62016-08-26 10:56:52 -0400759 set.insert(CopyConversion(GL_BGRA_EXT, GL_BGRA_EXT));
Geoff Lang5d601382014-07-22 15:14:06 -0400760
761 set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
762 set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
763 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
764 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
765 set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
766 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
767 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
768 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
769 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
770 set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
771
772 return set;
773}
774
Corentin Wallez76287682016-04-25 09:23:38 -0400775static bool EqualOrFirstZero(GLuint first, GLuint second)
776{
777 return first == 0 || first == second;
778}
779
Jamie Madill0c8abca2016-07-22 20:21:26 -0400780static bool IsValidES3CopyTexImageCombination(const Format &textureFormat,
781 const Format &framebufferFormat,
782 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400783{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400784 const auto &textureFormatInfo = *textureFormat.info;
785 const auto &framebufferFormatInfo = *framebufferFormat.info;
Geoff Lang5d601382014-07-22 15:14:06 -0400786
787 static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
Jamie Madill0c8abca2016-07-22 20:21:26 -0400788 if (conversionSet.find(CopyConversion(textureFormatInfo.format,
789 framebufferFormatInfo.format)) != conversionSet.end())
Geoff Lang5d601382014-07-22 15:14:06 -0400790 {
791 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
792 // must both be signed, unsigned, or fixed point and both source and destinations
793 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
794 // conversion between fixed and floating point.
795
Jamie Madill0c8abca2016-07-22 20:21:26 -0400796 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
797 (framebufferFormatInfo.colorEncoding == GL_SRGB))
Geoff Lang5d601382014-07-22 15:14:06 -0400798 {
799 return false;
800 }
801
Jamie Madill0c8abca2016-07-22 20:21:26 -0400802 if (((textureFormatInfo.componentType == GL_INT) !=
803 (framebufferFormatInfo.componentType == GL_INT)) ||
804 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
805 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
Geoff Lang5d601382014-07-22 15:14:06 -0400806 {
807 return false;
808 }
809
Jamie Madill0c8abca2016-07-22 20:21:26 -0400810 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
811 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
812 textureFormatInfo.componentType == GL_FLOAT) &&
813 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
814 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
815 framebufferFormatInfo.componentType == GL_FLOAT))
Geoff Lang5d601382014-07-22 15:14:06 -0400816 {
817 return false;
818 }
819
820 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
821 // The effective internal format of the source buffer is determined with the following rules applied in order:
822 // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
823 // effective internal format is the source buffer's sized internal format.
824 // * If the source buffer is a texture that was created with an unsized base internal format, then the
825 // effective internal format is the source image array's effective internal format, as specified by table
826 // 3.12, which is determined from the <format> and <type> that were used when the source image array was
827 // specified by TexImage*.
828 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
829 // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
830 // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
831 // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
832 // is SRGB.
833 const InternalFormat *sourceEffectiveFormat = NULL;
834 if (readBufferHandle != 0)
835 {
836 // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
Jamie Madill0c8abca2016-07-22 20:21:26 -0400837 if (framebufferFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400838 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400839 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400840 }
841 else
842 {
843 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
844 // 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 -0400845 GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferFormatInfo.format,
846 framebufferFormatInfo.type);
Geoff Lang051dbc72015-01-05 15:48:58 -0500847 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400848 }
849 }
850 else
851 {
852 // The effective internal format must be derived from the source framebuffer's channel sizes.
853 // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
Jamie Madill0c8abca2016-07-22 20:21:26 -0400854 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400855 {
856 GLenum effectiveFormat;
Jamie Madill0c8abca2016-07-22 20:21:26 -0400857 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
858 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400859 {
860 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
861 }
862 else
863 {
864 return false;
865 }
866 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400867 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
Geoff Lang5d601382014-07-22 15:14:06 -0400868 {
869 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Jamie Madill0c8abca2016-07-22 20:21:26 -0400870 if (textureFormat.sized &&
871 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
872 (framebufferFormatInfo.greenBits >= 1 &&
873 framebufferFormatInfo.greenBits <= 8) &&
874 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
875 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
Geoff Lang5d601382014-07-22 15:14:06 -0400876 {
877 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
878 }
879 else
880 {
881 return false;
882 }
883 }
884 else
885 {
886 UNREACHABLE();
887 return false;
888 }
889 }
890
Jamie Madill0c8abca2016-07-22 20:21:26 -0400891 if (textureFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400892 {
Corentin Wallez76287682016-04-25 09:23:38 -0400893 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination
894 // format is sized, component sizes of the source and destination formats must exactly
895 // match if the destination format exists.
Jamie Madill0c8abca2016-07-22 20:21:26 -0400896 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
897 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
898 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
899 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
Geoff Lang5d601382014-07-22 15:14:06 -0400900 {
901 return false;
902 }
903 }
904
Geoff Lang5d601382014-07-22 15:14:06 -0400905 return true; // A conversion function exists, and no rule in the specification has precluded conversion
906 // between these formats.
907 }
908
909 return false;
910}
911
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500912bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
913 GLenum target,
914 GLint level,
915 GLenum internalformat,
916 bool isSubImage,
917 GLint xoffset,
918 GLint yoffset,
919 GLint zoffset,
920 GLint x,
921 GLint y,
922 GLsizei width,
923 GLsizei height,
924 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400925{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400926 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400927 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400928 xoffset, yoffset, zoffset, x, y, width, height, border,
929 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400930 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400931 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400932 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400933 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400934
Jamie Madill51f40ec2016-06-15 14:06:00 -0400935 const auto &state = context->getGLState();
936 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
937 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400938
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700939 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400940 {
Jamie Madill437fa652016-05-03 15:13:24 -0400941 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400942 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400943 }
944
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700945 if (readFramebufferID != 0 && framebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400946 {
Jamie Madill437fa652016-05-03 15:13:24 -0400947 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400948 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400949 }
950
Jamie Madill0c8abca2016-07-22 20:21:26 -0400951 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400952
953 if (isSubImage)
954 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400955 if (!IsValidES3CopyTexImageCombination(textureFormat, source->getFormat(),
Jamie Madillc29968b2016-01-20 11:17:23 -0500956 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400957 {
Jamie Madill437fa652016-05-03 15:13:24 -0400958 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400959 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400960 }
961 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400962 else
963 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400964 // Use format/type from the source FBO. (Might not be perfect for all cases?)
965 const auto framebufferFormat = source->getFormat();
966 Format copyFormat(internalformat, framebufferFormat.format, framebufferFormat.type);
967 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400968 {
Jamie Madill437fa652016-05-03 15:13:24 -0400969 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400970 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400971 }
972 }
973
Geoff Lang784a8fd2013-09-24 12:33:16 -0400974 // If width or height is zero, it is a no-op. Return false without setting an error.
975 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400976}
977
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500978bool ValidateES3CopyTexImage2DParameters(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 (!ValidTexture2DDestinationTarget(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 ValidateES3CopyTexImage3DParameters(ValidationContext *context,
1004 GLenum target,
1005 GLint level,
1006 GLenum internalformat,
1007 bool isSubImage,
1008 GLint xoffset,
1009 GLint yoffset,
1010 GLint zoffset,
1011 GLint x,
1012 GLint y,
1013 GLsizei width,
1014 GLsizei height,
1015 GLint border)
1016{
1017 if (!ValidTexture3DDestinationTarget(context, target))
1018 {
Jamie Madill437fa652016-05-03 15:13:24 -04001019 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001020 return false;
1021 }
1022
1023 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
1024 xoffset, yoffset, zoffset, x, y, width, height,
1025 border);
1026}
1027
1028bool ValidateES3TexStorageParametersBase(Context *context,
1029 GLenum target,
1030 GLsizei levels,
1031 GLenum internalformat,
1032 GLsizei width,
1033 GLsizei height,
1034 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001035{
1036 if (width < 1 || height < 1 || depth < 1 || levels < 1)
1037 {
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
Geoff Langb92c1332015-09-04 12:54:55 -04001042 GLsizei maxDim = std::max(width, height);
1043 if (target != GL_TEXTURE_2D_ARRAY)
1044 {
1045 maxDim = std::max(maxDim, depth);
1046 }
1047
1048 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001049 {
Jamie Madill437fa652016-05-03 15:13:24 -04001050 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001051 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001052 }
1053
Geoff Langaae65a42014-05-26 12:43:44 -04001054 const gl::Caps &caps = context->getCaps();
1055
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001056 switch (target)
1057 {
1058 case GL_TEXTURE_2D:
1059 {
Geoff Langaae65a42014-05-26 12:43:44 -04001060 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1061 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001062 {
Jamie Madill437fa652016-05-03 15:13:24 -04001063 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001064 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001065 }
1066 }
1067 break;
1068
Geoff Lang01c21d22013-09-24 11:52:16 -04001069 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001070 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001071 if (width != height)
1072 {
Jamie Madill437fa652016-05-03 15:13:24 -04001073 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001074 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001075 }
1076
Geoff Langaae65a42014-05-26 12:43:44 -04001077 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001078 {
Jamie Madill437fa652016-05-03 15:13:24 -04001079 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001080 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001081 }
1082 }
1083 break;
1084
1085 case GL_TEXTURE_3D:
1086 {
Geoff Langaae65a42014-05-26 12:43:44 -04001087 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
1088 static_cast<GLuint>(height) > caps.max3DTextureSize ||
1089 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001090 {
Jamie Madill437fa652016-05-03 15:13:24 -04001091 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001092 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001093 }
1094 }
1095 break;
1096
1097 case GL_TEXTURE_2D_ARRAY:
1098 {
Geoff Langaae65a42014-05-26 12:43:44 -04001099 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1100 static_cast<GLuint>(height) > caps.max2DTextureSize ||
1101 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001102 {
Jamie Madill437fa652016-05-03 15:13:24 -04001103 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001104 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001105 }
1106 }
1107 break;
1108
1109 default:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001110 UNREACHABLE();
Geoff Langb1196682014-07-23 13:47:29 -04001111 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001112 }
1113
Geoff Lang691e58c2014-12-19 17:03:25 -05001114 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001115 if (!texture || texture->id() == 0)
1116 {
Jamie Madill437fa652016-05-03 15:13:24 -04001117 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001118 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001119 }
1120
Geoff Lang69cce582015-09-17 13:20:36 -04001121 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001122 {
Jamie Madill437fa652016-05-03 15:13:24 -04001123 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001124 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001125 }
1126
Geoff Lang5d601382014-07-22 15:14:06 -04001127 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Martin Radev1be913c2016-07-11 17:59:16 +03001128 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001129 {
Jamie Madill437fa652016-05-03 15:13:24 -04001130 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001131 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001132 }
1133
Geoff Lang5d601382014-07-22 15:14:06 -04001134 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001135 {
Jamie Madill437fa652016-05-03 15:13:24 -04001136 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001137 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001138 }
1139
1140 return true;
1141}
1142
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001143bool ValidateES3TexStorage2DParameters(Context *context,
1144 GLenum target,
1145 GLsizei levels,
1146 GLenum internalformat,
1147 GLsizei width,
1148 GLsizei height,
1149 GLsizei depth)
1150{
1151 if (!ValidTexture2DTarget(context, target))
1152 {
Jamie Madill437fa652016-05-03 15:13:24 -04001153 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001154 return false;
1155 }
1156
1157 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1158 height, depth);
1159}
1160
1161bool ValidateES3TexStorage3DParameters(Context *context,
1162 GLenum target,
1163 GLsizei levels,
1164 GLenum internalformat,
1165 GLsizei width,
1166 GLsizei height,
1167 GLsizei depth)
1168{
1169 if (!ValidTexture3DTarget(context, target))
1170 {
Jamie Madill437fa652016-05-03 15:13:24 -04001171 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001172 return false;
1173 }
1174
1175 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1176 height, depth);
1177}
1178
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001179bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1180{
Martin Radev1be913c2016-07-11 17:59:16 +03001181 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001182 {
Jamie Madill437fa652016-05-03 15:13:24 -04001183 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001184 return false;
1185 }
1186
1187 return ValidateBeginQueryBase(context, target, id);
1188}
1189
1190bool ValidateEndQuery(gl::Context *context, GLenum target)
1191{
Martin Radev1be913c2016-07-11 17:59:16 +03001192 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001193 {
Jamie Madill437fa652016-05-03 15:13:24 -04001194 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001195 return false;
1196 }
1197
1198 return ValidateEndQueryBase(context, target);
1199}
1200
1201bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1202{
Martin Radev1be913c2016-07-11 17:59:16 +03001203 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001204 {
Jamie Madill437fa652016-05-03 15:13:24 -04001205 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001206 return false;
1207 }
1208
1209 return ValidateGetQueryivBase(context, target, pname);
1210}
1211
1212bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1213{
Martin Radev1be913c2016-07-11 17:59:16 +03001214 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001215 {
Jamie Madill437fa652016-05-03 15:13:24 -04001216 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001217 return false;
1218 }
1219
1220 return ValidateGetQueryObjectValueBase(context, id, pname);
1221}
1222
Geoff Langb1196682014-07-23 13:47:29 -04001223bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
Jamie Madill570f7c82014-07-03 10:38:54 -04001224 GLuint texture, GLint level, GLint layer)
1225{
Martin Radev1be913c2016-07-11 17:59:16 +03001226 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001227 {
Jamie Madill437fa652016-05-03 15:13:24 -04001228 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001229 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001230 }
1231
Jamie Madill55ec3b12014-07-03 10:38:57 -04001232 if (layer < 0)
1233 {
Jamie Madill437fa652016-05-03 15:13:24 -04001234 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001235 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001236 }
1237
1238 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1239 {
1240 return false;
1241 }
1242
1243 const gl::Caps &caps = context->getCaps();
1244 if (texture != 0)
1245 {
1246 gl::Texture *tex = context->getTexture(texture);
1247 ASSERT(tex);
1248
1249 switch (tex->getTarget())
1250 {
1251 case GL_TEXTURE_2D_ARRAY:
1252 {
1253 if (level > gl::log2(caps.max2DTextureSize))
1254 {
Jamie Madill437fa652016-05-03 15:13:24 -04001255 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001256 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001257 }
1258
1259 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1260 {
Jamie Madill437fa652016-05-03 15:13:24 -04001261 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001262 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001263 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001264 }
1265 break;
1266
1267 case GL_TEXTURE_3D:
1268 {
1269 if (level > gl::log2(caps.max3DTextureSize))
1270 {
Jamie Madill437fa652016-05-03 15:13:24 -04001271 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001272 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001273 }
1274
1275 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1276 {
Jamie Madill437fa652016-05-03 15:13:24 -04001277 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001278 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001279 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001280 }
1281 break;
1282
1283 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001284 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001285 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001286 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001287
Jamie Madilla3944d42016-07-22 22:13:26 -04001288 const auto &format = tex->getFormat(tex->getTarget(), level);
1289 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001290 {
Jamie Madill437fa652016-05-03 15:13:24 -04001291 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001292 return false;
1293 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001294 }
1295
1296 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001297}
1298
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001299bool ValidES3ReadFormatType(ValidationContext *context,
1300 GLenum internalFormat,
1301 GLenum format,
1302 GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001303{
Geoff Lang5d601382014-07-22 15:14:06 -04001304 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
1305
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001306 switch (format)
1307 {
1308 case GL_RGBA:
1309 switch (type)
1310 {
1311 case GL_UNSIGNED_BYTE:
1312 break;
Vincent Lang25ab4512016-05-13 18:13:59 +02001313 case GL_UNSIGNED_SHORT:
1314 if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
1315 internalFormatInfo.type != GL_UNSIGNED_SHORT)
1316 {
1317 return false;
1318 }
1319 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001320 case GL_UNSIGNED_INT_2_10_10_10_REV:
1321 if (internalFormat != GL_RGB10_A2)
1322 {
1323 return false;
1324 }
1325 break;
Geoff Lang1ec57f82013-10-16 11:43:23 -04001326 case GL_FLOAT:
Geoff Lang5d601382014-07-22 15:14:06 -04001327 if (internalFormatInfo.componentType != GL_FLOAT)
Geoff Lang1ec57f82013-10-16 11:43:23 -04001328 {
1329 return false;
1330 }
1331 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001332 default:
1333 return false;
1334 }
1335 break;
1336 case GL_RGBA_INTEGER:
1337 switch (type)
1338 {
1339 case GL_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001340 if (internalFormatInfo.componentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001341 {
1342 return false;
1343 }
1344 break;
1345 case GL_UNSIGNED_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001346 if (internalFormatInfo.componentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001347 {
1348 return false;
1349 }
1350 break;
1351 default:
1352 return false;
1353 }
1354 break;
1355 case GL_BGRA_EXT:
1356 switch (type)
1357 {
1358 case GL_UNSIGNED_BYTE:
1359 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1360 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1361 break;
1362 default:
1363 return false;
1364 }
1365 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001366 case GL_RG_EXT:
1367 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001368 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001369 {
1370 return false;
1371 }
1372 switch (type)
1373 {
1374 case GL_UNSIGNED_BYTE:
1375 break;
Vincent Lang25ab4512016-05-13 18:13:59 +02001376 case GL_UNSIGNED_SHORT:
1377 if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
1378 internalFormatInfo.type != GL_UNSIGNED_SHORT)
1379 {
1380 return false;
1381 }
1382 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001383 default:
1384 return false;
1385 }
1386 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001387 default:
1388 return false;
1389 }
1390 return true;
1391}
1392
Corentin Walleze0902642014-11-04 12:32:15 -08001393bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
1394 GLenum internalformat, GLsizei width, GLsizei height)
1395{
1396 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
1397 {
1398 return false;
1399 }
1400
1401 //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.
1402 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1403 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
1404 {
Jamie Madill437fa652016-05-03 15:13:24 -04001405 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -08001406 return false;
1407 }
1408
1409 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
1410 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1411 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1412 {
Jamie Madill437fa652016-05-03 15:13:24 -04001413 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001414 Error(GL_INVALID_OPERATION,
1415 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001416 return false;
1417 }
1418
1419 return true;
1420}
1421
Austin Kinross08332632015-05-05 13:35:47 -07001422bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
1423 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001424{
Martin Radev1be913c2016-07-11 17:59:16 +03001425 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001426 {
Jamie Madill437fa652016-05-03 15:13:24 -04001427 context->handleError(
1428 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001429 return false;
1430 }
1431
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001432 bool defaultFramebuffer = false;
1433
1434 switch (target)
1435 {
1436 case GL_DRAW_FRAMEBUFFER:
1437 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001438 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1439 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001440 case GL_READ_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001441 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1442 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001443 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001444 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001445 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001446 }
1447
Austin Kinross08332632015-05-05 13:35:47 -07001448 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001449}
1450
Jamie Madillc29968b2016-01-20 11:17:23 -05001451bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001452{
Martin Radev1be913c2016-07-11 17:59:16 +03001453 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001454 {
Jamie Madill437fa652016-05-03 15:13:24 -04001455 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001456 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001457 }
1458
Jamie Madill51f40ec2016-06-15 14:06:00 -04001459 if (context->getGLState().getDrawFramebuffer()->checkStatus(context->getContextState()) !=
1460 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001461 {
Jamie Madill437fa652016-05-03 15:13:24 -04001462 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001463 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001464 }
1465
1466 return true;
1467}
1468
Olli Etuaho71dfb362016-03-10 14:04:27 +02001469bool ValidateDrawRangeElements(Context *context,
1470 GLenum mode,
1471 GLuint start,
1472 GLuint end,
1473 GLsizei count,
1474 GLenum type,
1475 const GLvoid *indices,
1476 IndexRange *indexRange)
1477{
Martin Radev1be913c2016-07-11 17:59:16 +03001478 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001479 {
Jamie Madill437fa652016-05-03 15:13:24 -04001480 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001481 return false;
1482 }
1483
1484 if (end < start)
1485 {
Jamie Madill437fa652016-05-03 15:13:24 -04001486 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001487 return false;
1488 }
1489
1490 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1491 {
1492 return false;
1493 }
1494
1495 if (indexRange->end > end || indexRange->start < start)
1496 {
1497 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001498 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001499 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1500 return false;
1501 }
1502 return true;
1503}
1504
Geoff Langb1196682014-07-23 13:47:29 -04001505bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001506{
Martin Radev1be913c2016-07-11 17:59:16 +03001507 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001508 {
Jamie Madill437fa652016-05-03 15:13:24 -04001509 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001510 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001511 }
1512
Jamie Madill78f41802014-08-25 15:47:55 -04001513 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001514}
1515
Jamie Madillb885e572015-02-03 16:16:04 -05001516bool ValidateReadBuffer(Context *context, GLenum src)
1517{
Martin Radev1be913c2016-07-11 17:59:16 +03001518 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001519 {
Jamie Madill437fa652016-05-03 15:13:24 -04001520 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001521 return false;
1522 }
1523
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001524 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001525
1526 if (readFBO == nullptr)
1527 {
Jamie Madill437fa652016-05-03 15:13:24 -04001528 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001529 return false;
1530 }
1531
1532 if (src == GL_NONE)
1533 {
1534 return true;
1535 }
1536
Olli Etuaho84c9f592016-03-09 14:37:25 +02001537 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001538 {
Jamie Madill437fa652016-05-03 15:13:24 -04001539 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001540 return false;
1541 }
1542
1543 if (readFBO->id() == 0)
1544 {
1545 if (src != GL_BACK)
1546 {
1547 const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001548 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001549 return false;
1550 }
1551 }
1552 else
1553 {
1554 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1555
1556 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1557 {
1558 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001559 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001560 return false;
1561 }
1562 }
1563
1564 return true;
1565}
1566
Jamie Madill86af3d22015-07-21 15:14:07 -04001567bool ValidateCompressedTexImage3D(Context *context,
1568 GLenum target,
1569 GLint level,
1570 GLenum internalformat,
1571 GLsizei width,
1572 GLsizei height,
1573 GLsizei depth,
1574 GLint border,
1575 GLsizei imageSize,
1576 const GLvoid *data)
1577{
Martin Radev1be913c2016-07-11 17:59:16 +03001578 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001579 {
Jamie Madill437fa652016-05-03 15:13:24 -04001580 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001581 return false;
1582 }
1583
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001584 if (!ValidTextureTarget(context, target))
1585 {
1586 context->handleError(Error(GL_INVALID_ENUM));
1587 return false;
1588 }
1589
Jamie Madille2e406c2016-06-02 13:04:10 -04001590 // Validate image size
1591 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1592 {
1593 context->handleError(Error(GL_INVALID_VALUE));
1594 return false;
1595 }
1596
Jamie Madill86af3d22015-07-21 15:14:07 -04001597 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001598 if (!formatInfo.compressed)
1599 {
1600 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1601 return false;
1602 }
1603
Jamie Madill513558d2016-06-02 13:04:11 -04001604 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001605 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001606 if (blockSizeOrErr.isError())
1607 {
Jamie Madill513558d2016-06-02 13:04:11 -04001608 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001609 return false;
1610 }
1611 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001612 {
Jamie Madill437fa652016-05-03 15:13:24 -04001613 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001614 return false;
1615 }
1616
1617 // 3D texture target validation
1618 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1619 {
Jamie Madill437fa652016-05-03 15:13:24 -04001620 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001621 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1622 return false;
1623 }
1624
1625 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001626 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
1627 0, width, height, depth, border, GL_NONE, GL_NONE, data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001628 {
1629 return false;
1630 }
1631
1632 return true;
1633}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001634
1635bool ValidateBindVertexArray(Context *context, GLuint array)
1636{
Martin Radev1be913c2016-07-11 17:59:16 +03001637 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001638 {
Jamie Madill437fa652016-05-03 15:13:24 -04001639 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001640 return false;
1641 }
1642
1643 return ValidateBindVertexArrayBase(context, array);
1644}
1645
Austin Kinrossbc781f32015-10-26 09:27:38 -07001646bool ValidateIsVertexArray(Context *context)
1647{
Martin Radev1be913c2016-07-11 17:59:16 +03001648 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001649 {
Jamie Madill437fa652016-05-03 15:13:24 -04001650 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001651 return false;
1652 }
1653
1654 return true;
1655}
Geoff Langc5629752015-12-07 16:29:04 -05001656
1657bool ValidateProgramBinary(Context *context,
1658 GLuint program,
1659 GLenum binaryFormat,
1660 const void *binary,
1661 GLint length)
1662{
Martin Radev1be913c2016-07-11 17:59:16 +03001663 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001664 {
Jamie Madill437fa652016-05-03 15:13:24 -04001665 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001666 return false;
1667 }
1668
1669 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1670}
1671
1672bool ValidateGetProgramBinary(Context *context,
1673 GLuint program,
1674 GLsizei bufSize,
1675 GLsizei *length,
1676 GLenum *binaryFormat,
1677 void *binary)
1678{
Martin Radev1be913c2016-07-11 17:59:16 +03001679 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001680 {
Jamie Madill437fa652016-05-03 15:13:24 -04001681 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001682 return false;
1683 }
1684
1685 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1686}
1687
Olli Etuahof0fee072016-03-30 15:11:58 +03001688bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001689{
Martin Radev1be913c2016-07-11 17:59:16 +03001690 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001691 {
Jamie Madill437fa652016-05-03 15:13:24 -04001692 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001693 return false;
1694 }
1695
1696 if (GetValidProgram(context, program) == nullptr)
1697 {
1698 return false;
1699 }
1700
1701 switch (pname)
1702 {
1703 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001704 if (value != GL_FALSE && value != GL_TRUE)
1705 {
Jamie Madill437fa652016-05-03 15:13:24 -04001706 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001707 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1708 return false;
1709 }
Geoff Langc5629752015-12-07 16:29:04 -05001710 break;
1711
1712 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001713 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001714 return false;
1715 }
1716
1717 return true;
1718}
Jamie Madillc29968b2016-01-20 11:17:23 -05001719
1720bool ValidateBlitFramebuffer(Context *context,
1721 GLint srcX0,
1722 GLint srcY0,
1723 GLint srcX1,
1724 GLint srcY1,
1725 GLint dstX0,
1726 GLint dstY0,
1727 GLint dstX1,
1728 GLint dstY1,
1729 GLbitfield mask,
1730 GLenum filter)
1731{
Martin Radev1be913c2016-07-11 17:59:16 +03001732 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001733 {
Jamie Madill437fa652016-05-03 15:13:24 -04001734 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001735 return false;
1736 }
1737
1738 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1739 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001740}
Jamie Madillc29968b2016-01-20 11:17:23 -05001741
1742bool ValidateClearBufferiv(ValidationContext *context,
1743 GLenum buffer,
1744 GLint drawbuffer,
1745 const GLint *value)
1746{
1747 switch (buffer)
1748 {
1749 case GL_COLOR:
1750 if (drawbuffer < 0 ||
1751 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1752 {
Jamie Madill437fa652016-05-03 15:13:24 -04001753 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001754 return false;
1755 }
1756 break;
1757
1758 case GL_STENCIL:
1759 if (drawbuffer != 0)
1760 {
Jamie Madill437fa652016-05-03 15:13:24 -04001761 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001762 return false;
1763 }
1764 break;
1765
1766 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001767 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001768 return false;
1769 }
1770
1771 return ValidateClearBuffer(context);
1772}
1773
1774bool ValidateClearBufferuiv(ValidationContext *context,
1775 GLenum buffer,
1776 GLint drawbuffer,
1777 const GLuint *value)
1778{
1779 switch (buffer)
1780 {
1781 case GL_COLOR:
1782 if (drawbuffer < 0 ||
1783 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1784 {
Jamie Madill437fa652016-05-03 15:13:24 -04001785 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001786 return false;
1787 }
1788 break;
1789
1790 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001791 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001792 return false;
1793 }
1794
1795 return ValidateClearBuffer(context);
1796}
1797
1798bool ValidateClearBufferfv(ValidationContext *context,
1799 GLenum buffer,
1800 GLint drawbuffer,
1801 const GLfloat *value)
1802{
1803 switch (buffer)
1804 {
1805 case GL_COLOR:
1806 if (drawbuffer < 0 ||
1807 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1808 {
Jamie Madill437fa652016-05-03 15:13:24 -04001809 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001810 return false;
1811 }
1812 break;
1813
1814 case GL_DEPTH:
1815 if (drawbuffer != 0)
1816 {
Jamie Madill437fa652016-05-03 15:13:24 -04001817 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001818 return false;
1819 }
1820 break;
1821
1822 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001823 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001824 return false;
1825 }
1826
1827 return ValidateClearBuffer(context);
1828}
1829
1830bool ValidateClearBufferfi(ValidationContext *context,
1831 GLenum buffer,
1832 GLint drawbuffer,
1833 GLfloat depth,
1834 GLint stencil)
1835{
1836 switch (buffer)
1837 {
1838 case GL_DEPTH_STENCIL:
1839 if (drawbuffer != 0)
1840 {
Jamie Madill437fa652016-05-03 15:13:24 -04001841 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001842 return false;
1843 }
1844 break;
1845
1846 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001847 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001848 return false;
1849 }
1850
1851 return ValidateClearBuffer(context);
1852}
1853
1854bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1855{
Martin Radev1be913c2016-07-11 17:59:16 +03001856 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001857 {
Jamie Madill437fa652016-05-03 15:13:24 -04001858 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001859 return false;
1860 }
1861
1862 return ValidateDrawBuffersBase(context, n, bufs);
1863}
1864
1865bool ValidateCopyTexSubImage3D(Context *context,
1866 GLenum target,
1867 GLint level,
1868 GLint xoffset,
1869 GLint yoffset,
1870 GLint zoffset,
1871 GLint x,
1872 GLint y,
1873 GLsizei width,
1874 GLsizei height)
1875{
Martin Radev1be913c2016-07-11 17:59:16 +03001876 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001877 {
Jamie Madill437fa652016-05-03 15:13:24 -04001878 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001879 return false;
1880 }
1881
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001882 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1883 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001884}
1885
Jamie Madill73a84962016-02-12 09:27:23 -05001886bool ValidateTexImage3D(Context *context,
1887 GLenum target,
1888 GLint level,
1889 GLint internalformat,
1890 GLsizei width,
1891 GLsizei height,
1892 GLsizei depth,
1893 GLint border,
1894 GLenum format,
1895 GLenum type,
1896 const GLvoid *pixels)
1897{
Martin Radev1be913c2016-07-11 17:59:16 +03001898 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001899 {
Jamie Madill437fa652016-05-03 15:13:24 -04001900 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001901 return false;
1902 }
1903
1904 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1905 0, 0, width, height, depth, border, format, type,
1906 pixels);
1907}
1908
1909bool ValidateTexSubImage3D(Context *context,
1910 GLenum target,
1911 GLint level,
1912 GLint xoffset,
1913 GLint yoffset,
1914 GLint zoffset,
1915 GLsizei width,
1916 GLsizei height,
1917 GLsizei depth,
1918 GLenum format,
1919 GLenum type,
1920 const GLvoid *pixels)
1921{
Martin Radev1be913c2016-07-11 17:59:16 +03001922 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001923 {
Jamie Madill437fa652016-05-03 15:13:24 -04001924 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001925 return false;
1926 }
1927
1928 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1929 yoffset, zoffset, width, height, depth, 0, format, type,
1930 pixels);
1931}
1932
1933bool ValidateCompressedTexSubImage3D(Context *context,
1934 GLenum target,
1935 GLint level,
1936 GLint xoffset,
1937 GLint yoffset,
1938 GLint zoffset,
1939 GLsizei width,
1940 GLsizei height,
1941 GLsizei depth,
1942 GLenum format,
1943 GLsizei imageSize,
1944 const GLvoid *data)
1945{
Martin Radev1be913c2016-07-11 17:59:16 +03001946 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001947 {
Jamie Madill437fa652016-05-03 15:13:24 -04001948 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001949 return false;
1950 }
1951
1952 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001953 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001954 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001955 if (blockSizeOrErr.isError())
1956 {
1957 context->handleError(blockSizeOrErr.getError());
1958 return false;
1959 }
1960 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001961 {
Jamie Madill437fa652016-05-03 15:13:24 -04001962 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001963 return false;
1964 }
1965
1966 if (!data)
1967 {
Jamie Madill437fa652016-05-03 15:13:24 -04001968 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001969 return false;
1970 }
1971
1972 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
1973 width, height, depth, 0, GL_NONE, GL_NONE, data);
1974}
1975
Olli Etuaho41997e72016-03-10 13:38:39 +02001976bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1977{
1978 return ValidateGenOrDeleteES3(context, n);
1979}
1980
1981bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1982{
1983 return ValidateGenOrDeleteES3(context, n);
1984}
1985
1986bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1987{
1988 return ValidateGenOrDeleteCountES3(context, count);
1989}
1990
1991bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1992{
1993 return ValidateGenOrDeleteCountES3(context, count);
1994}
1995
1996bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1997{
1998 return ValidateGenOrDeleteES3(context, n);
1999}
2000
2001bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2002{
2003 if (!ValidateGenOrDeleteES3(context, n))
2004 {
2005 return false;
2006 }
2007 for (GLint i = 0; i < n; ++i)
2008 {
2009 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2010 if (transformFeedback != nullptr && transformFeedback->isActive())
2011 {
2012 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04002013 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02002014 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
2015 return false;
2016 }
2017 }
2018 return true;
2019}
2020
2021bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2022{
2023 return ValidateGenOrDeleteES3(context, n);
2024}
2025
2026bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2027{
2028 return ValidateGenOrDeleteES3(context, n);
2029}
2030
2031bool ValidateGenOrDeleteES3(Context *context, GLint n)
2032{
Martin Radev1be913c2016-07-11 17:59:16 +03002033 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02002034 {
Jamie Madill437fa652016-05-03 15:13:24 -04002035 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02002036 return false;
2037 }
2038 return ValidateGenOrDelete(context, n);
2039}
2040
2041bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
2042{
Martin Radev1be913c2016-07-11 17:59:16 +03002043 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02002044 {
Jamie Madill437fa652016-05-03 15:13:24 -04002045 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02002046 return false;
2047 }
2048 if (count < 0)
2049 {
Jamie Madill437fa652016-05-03 15:13:24 -04002050 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02002051 return false;
2052 }
2053 return true;
2054}
2055
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002056bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2057{
Martin Radev1be913c2016-07-11 17:59:16 +03002058 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002059 {
Jamie Madill437fa652016-05-03 15:13:24 -04002060 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002061 return false;
2062 }
2063 switch (primitiveMode)
2064 {
2065 case GL_TRIANGLES:
2066 case GL_LINES:
2067 case GL_POINTS:
2068 break;
2069
2070 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002071 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002072 return false;
2073 }
2074
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002075 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002076 ASSERT(transformFeedback != nullptr);
2077
2078 if (transformFeedback->isActive())
2079 {
Jamie Madill437fa652016-05-03 15:13:24 -04002080 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002081 return false;
2082 }
2083 return true;
2084}
2085
Olli Etuaho37477912016-03-30 14:54:40 +03002086bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
2087{
Martin Radev1be913c2016-07-11 17:59:16 +03002088 if (context->getClientMajorVersion() < 3)
Olli Etuaho37477912016-03-30 14:54:40 +03002089 {
Jamie Madill437fa652016-05-03 15:13:24 -04002090 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho37477912016-03-30 14:54:40 +03002091 return false;
2092 }
2093
2094 if (!context->isSampler(sampler))
2095 {
Jamie Madill437fa652016-05-03 15:13:24 -04002096 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho37477912016-03-30 14:54:40 +03002097 return false;
2098 }
2099
2100 if (!ValidateSamplerObjectParameter(context, pname))
2101 {
2102 return false;
2103 }
2104
Ian Ewellbda75592016-04-18 17:25:54 -04002105 if (!ValidateTexParamParameters(context, GL_TEXTURE_2D, pname, param))
Olli Etuaho37477912016-03-30 14:54:40 +03002106 {
2107 return false;
2108 }
2109 return true;
2110}
2111
2112bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
2113{
2114 // The only float parameters are MIN_LOD and MAX_LOD. For these any value is permissible, so
2115 // ValidateSamplerParameteri can be used for validation here.
2116 return ValidateSamplerParameteri(context, sampler, pname, static_cast<GLint>(param));
2117}
2118
Olli Etuaho4f667482016-03-30 15:56:35 +03002119bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
2120{
Martin Radev1be913c2016-07-11 17:59:16 +03002121 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002122 {
Jamie Madill437fa652016-05-03 15:13:24 -04002123 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002124 return false;
2125 }
2126
2127 return ValidateGetBufferPointervBase(context, target, pname, params);
2128}
2129
2130bool ValidateUnmapBuffer(Context *context, GLenum target)
2131{
Martin Radev1be913c2016-07-11 17:59:16 +03002132 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002133 {
Jamie Madill437fa652016-05-03 15:13:24 -04002134 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03002135 return false;
2136 }
2137
2138 return ValidateUnmapBufferBase(context, target);
2139}
2140
2141bool ValidateMapBufferRange(Context *context,
2142 GLenum target,
2143 GLintptr offset,
2144 GLsizeiptr length,
2145 GLbitfield access)
2146{
Martin Radev1be913c2016-07-11 17:59:16 +03002147 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002148 {
Jamie Madill437fa652016-05-03 15:13:24 -04002149 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002150 return false;
2151 }
2152
2153 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2154}
2155
2156bool ValidateFlushMappedBufferRange(Context *context,
2157 GLenum target,
2158 GLintptr offset,
2159 GLsizeiptr length)
2160{
Martin Radev1be913c2016-07-11 17:59:16 +03002161 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002162 {
Jamie Madill437fa652016-05-03 15:13:24 -04002163 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002164 return false;
2165 }
2166
2167 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2168}
2169
Martin Radev66fb8202016-07-28 11:45:20 +03002170bool ValidateIndexedStateQuery(ValidationContext *context, GLenum pname, GLuint index)
2171{
2172 GLenum nativeType;
2173 unsigned int numParams;
2174 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2175 {
2176 context->handleError(Error(GL_INVALID_ENUM));
2177 return false;
2178 }
2179
2180 const Caps &caps = context->getCaps();
2181 switch (pname)
2182 {
2183 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2184 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2185 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2186 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2187 {
2188 context->handleError(Error(GL_INVALID_VALUE));
2189 return false;
2190 }
2191 break;
2192
2193 case GL_UNIFORM_BUFFER_START:
2194 case GL_UNIFORM_BUFFER_SIZE:
2195 case GL_UNIFORM_BUFFER_BINDING:
2196 if (index >= caps.maxUniformBufferBindings)
2197 {
2198 context->handleError(Error(GL_INVALID_VALUE));
2199 return false;
2200 }
2201 break;
2202 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2203 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2204 if (index >= 3u)
2205 {
2206 context->handleError(Error(GL_INVALID_VALUE));
2207 return false;
2208 }
2209 break;
2210 default:
2211 context->handleError(Error(GL_INVALID_ENUM));
2212 return false;
2213 }
2214
2215 // pname is valid, but there are no parameters to return
2216 if (numParams == 0)
2217 {
2218 return false;
2219 }
2220
2221 return true;
2222}
2223
2224bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2225{
2226 if (!context->getGLVersion().isES3OrGreater())
2227 {
2228 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2229 return false;
2230 }
2231 return ValidateIndexedStateQuery(context, target, index);
2232}
2233
2234bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2235{
2236 if (!context->getGLVersion().isES3OrGreater())
2237 {
2238 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2239 return false;
2240 }
2241 return ValidateIndexedStateQuery(context, target, index);
2242}
2243
Jamie Madillc29968b2016-01-20 11:17:23 -05002244} // namespace gl