blob: d4f706bf4c06a51f0c3b18a805b4886142a6253a [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES3.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES.h"
12#include "libANGLE/Context.h"
13#include "libANGLE/Texture.h"
14#include "libANGLE/Framebuffer.h"
15#include "libANGLE/Renderbuffer.h"
16#include "libANGLE/formatutils.h"
17#include "libANGLE/FramebufferAttachment.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040018
19#include "common/mathutil.h"
Geoff Langa9be0dc2014-12-17 12:34:40 -050020#include "common/utilities.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040021
Jamie Madille2e406c2016-06-02 13:04:10 -040022using namespace angle;
23
Geoff Lange8ebe7f2013-08-05 15:03:13 -040024namespace gl
25{
26
Geoff Lang5d601382014-07-22 15:14:06 -040027struct ES3FormatCombination
28{
29 GLenum internalFormat;
30 GLenum format;
31 GLenum type;
32};
33
34bool operator<(const ES3FormatCombination& a, const ES3FormatCombination& b)
35{
36 return memcmp(&a, &b, sizeof(ES3FormatCombination)) < 0;
37}
38
39typedef std::set<ES3FormatCombination> ES3FormatCombinationSet;
40
41static inline void InsertES3FormatCombo(ES3FormatCombinationSet *set, GLenum internalFormat, GLenum format, GLenum type)
42{
43 ES3FormatCombination info;
44 info.internalFormat = internalFormat;
45 info.format = format;
46 info.type = type;
47 set->insert(info);
48}
49
50ES3FormatCombinationSet BuildES3FormatSet()
51{
52 ES3FormatCombinationSet set;
53
54 // Format combinations from ES 3.0.1 spec, table 3.2
55
56 // | Internal format | Format | Type |
57 // | | | |
58 InsertES3FormatCombo(&set, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE );
59 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE );
60 InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE );
61 InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE );
62 InsertES3FormatCombo(&set, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE );
63 InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 );
64 InsertES3FormatCombo(&set, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV );
65 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV );
66 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 );
67 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT );
68 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT_OES );
69 InsertES3FormatCombo(&set, GL_RGBA32F, GL_RGBA, GL_FLOAT );
70 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_FLOAT );
71 InsertES3FormatCombo(&set, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE );
72 InsertES3FormatCombo(&set, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE );
73 InsertES3FormatCombo(&set, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT );
74 InsertES3FormatCombo(&set, GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT );
75 InsertES3FormatCombo(&set, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT );
76 InsertES3FormatCombo(&set, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT );
77 InsertES3FormatCombo(&set, GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV );
78 InsertES3FormatCombo(&set, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE );
79 InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE );
80 InsertES3FormatCombo(&set, GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE );
81 InsertES3FormatCombo(&set, GL_RGB8_SNORM, GL_RGB, GL_BYTE );
82 InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 );
83 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV );
84 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV );
85 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT );
86 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT_OES );
87 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT );
88 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT_OES );
89 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT );
90 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT_OES );
91 InsertES3FormatCombo(&set, GL_RGB32F, GL_RGB, GL_FLOAT );
92 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_FLOAT );
93 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT );
94 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_FLOAT );
95 InsertES3FormatCombo(&set, GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE );
96 InsertES3FormatCombo(&set, GL_RGB8I, GL_RGB_INTEGER, GL_BYTE );
97 InsertES3FormatCombo(&set, GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT );
98 InsertES3FormatCombo(&set, GL_RGB16I, GL_RGB_INTEGER, GL_SHORT );
99 InsertES3FormatCombo(&set, GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT );
100 InsertES3FormatCombo(&set, GL_RGB32I, GL_RGB_INTEGER, GL_INT );
101 InsertES3FormatCombo(&set, GL_RG8, GL_RG, GL_UNSIGNED_BYTE );
102 InsertES3FormatCombo(&set, GL_RG8_SNORM, GL_RG, GL_BYTE );
103 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT );
104 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT_OES );
105 InsertES3FormatCombo(&set, GL_RG32F, GL_RG, GL_FLOAT );
106 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_FLOAT );
107 InsertES3FormatCombo(&set, GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE );
108 InsertES3FormatCombo(&set, GL_RG8I, GL_RG_INTEGER, GL_BYTE );
109 InsertES3FormatCombo(&set, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT );
110 InsertES3FormatCombo(&set, GL_RG16I, GL_RG_INTEGER, GL_SHORT );
111 InsertES3FormatCombo(&set, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT );
112 InsertES3FormatCombo(&set, GL_RG32I, GL_RG_INTEGER, GL_INT );
113 InsertES3FormatCombo(&set, GL_R8, GL_RED, GL_UNSIGNED_BYTE );
114 InsertES3FormatCombo(&set, GL_R8_SNORM, GL_RED, GL_BYTE );
115 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT );
116 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT_OES );
117 InsertES3FormatCombo(&set, GL_R32F, GL_RED, GL_FLOAT );
118 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_FLOAT );
119 InsertES3FormatCombo(&set, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE );
120 InsertES3FormatCombo(&set, GL_R8I, GL_RED_INTEGER, GL_BYTE );
121 InsertES3FormatCombo(&set, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT );
122 InsertES3FormatCombo(&set, GL_R16I, GL_RED_INTEGER, GL_SHORT );
123 InsertES3FormatCombo(&set, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT );
124 InsertES3FormatCombo(&set, GL_R32I, GL_RED_INTEGER, GL_INT );
125
126 // Unsized formats
127 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE );
128 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 );
129 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 );
130 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE );
131 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 );
132 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE );
133 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE );
134 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE );
135 InsertES3FormatCombo(&set, GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE );
136 InsertES3FormatCombo(&set, GL_SRGB_EXT, GL_SRGB_EXT, GL_UNSIGNED_BYTE );
Jamie Madill689325c2015-07-20 14:36:53 -0400137 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_UNSIGNED_BYTE );
138 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_FLOAT );
139 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_HALF_FLOAT );
140 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_HALF_FLOAT_OES );
141 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_UNSIGNED_BYTE );
142 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_FLOAT );
143 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_HALF_FLOAT );
144 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_HALF_FLOAT_OES );
145 InsertES3FormatCombo(&set, GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 );
Geoff Lang5d601382014-07-22 15:14:06 -0400146
147 // Depth stencil formats
148 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT );
149 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
150 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
151 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT );
152 InsertES3FormatCombo(&set, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 );
153 InsertES3FormatCombo(&set, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
154
155 // From GL_EXT_sRGB
156 InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE );
157 InsertES3FormatCombo(&set, GL_SRGB8, GL_SRGB_EXT, GL_UNSIGNED_BYTE );
158
159 // From GL_OES_texture_float
Jeff Muizelaarbb1a5be2015-12-02 12:03:46 -0500160 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_FLOAT );
161 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_FLOAT );
Geoff Lang5d601382014-07-22 15:14:06 -0400162 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT );
163 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT );
164 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_FLOAT );
165
166 // From GL_OES_texture_half_float
167 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT );
168 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES );
169 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT );
170 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES );
171 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT );
172 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES );
173
174 // From GL_EXT_texture_format_BGRA8888
175 InsertES3FormatCombo(&set, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
176
177 // From GL_EXT_texture_storage
178 // | Internal format | Format | Type |
179 // | | | |
180 InsertES3FormatCombo(&set, GL_ALPHA8_EXT, GL_ALPHA, GL_UNSIGNED_BYTE );
181 InsertES3FormatCombo(&set, GL_LUMINANCE8_EXT, GL_LUMINANCE, GL_UNSIGNED_BYTE );
182 InsertES3FormatCombo(&set, GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE );
183 InsertES3FormatCombo(&set, GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT );
184 InsertES3FormatCombo(&set, GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT );
185 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT );
186 InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT );
187 InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT_OES );
188 InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT );
189 InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT_OES );
190 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT );
191 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES );
192
193 // From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888
194 InsertES3FormatCombo(&set, GL_BGRA8_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
195 InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT);
196 InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
197 InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT);
198 InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
199
200 // From GL_ANGLE_depth_texture
201 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8_OES );
202
Vincent Lang25ab4512016-05-13 18:13:59 +0200203 // From GL_EXT_texture_norm16
204 InsertES3FormatCombo(&set, GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT);
205 InsertES3FormatCombo(&set, GL_RG16_EXT, GL_RG, GL_UNSIGNED_SHORT);
206 InsertES3FormatCombo(&set, GL_RGB16_EXT, GL_RGB, GL_UNSIGNED_SHORT);
207 InsertES3FormatCombo(&set, GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT);
208 InsertES3FormatCombo(&set, GL_R16_SNORM_EXT, GL_RED, GL_SHORT);
209 InsertES3FormatCombo(&set, GL_RG16_SNORM_EXT, GL_RG, GL_SHORT);
210 InsertES3FormatCombo(&set, GL_RGB16_SNORM_EXT, GL_RGB, GL_SHORT);
211 InsertES3FormatCombo(&set, GL_RGBA16_SNORM_EXT, GL_RGBA, GL_SHORT);
212
Geoff Lang5d601382014-07-22 15:14:06 -0400213 return set;
214}
215
216static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
217{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500218 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
219 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
220 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
221 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
Geoff Langbaadf232014-08-04 13:58:02 -0400222 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
Martin Radev1be913c2016-07-11 17:59:16 +0300223 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Geoff Lang5d601382014-07-22 15:14:06 -0400224 {
Jamie Madill437fa652016-05-03 15:13:24 -0400225 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400226 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400227 }
228
229 // The type and format are valid if any supported internal format has that type and format
230 bool formatSupported = false;
231 bool typeSupported = false;
232
233 static const ES3FormatCombinationSet es3FormatSet = BuildES3FormatSet();
234 for (ES3FormatCombinationSet::const_iterator i = es3FormatSet.begin(); i != es3FormatSet.end(); i++)
235 {
236 if (i->format == format || i->type == type)
237 {
238 const gl::InternalFormat &info = gl::GetInternalFormatInfo(i->internalFormat);
Martin Radev1be913c2016-07-11 17:59:16 +0300239 bool supported =
240 info.textureSupport(context->getClientMajorVersion(), context->getExtensions());
Geoff Langbaadf232014-08-04 13:58:02 -0400241 if (supported && i->type == type)
Geoff Lang5d601382014-07-22 15:14:06 -0400242 {
243 typeSupported = true;
244 }
Geoff Langbaadf232014-08-04 13:58:02 -0400245 if (supported && i->format == format)
Geoff Lang5d601382014-07-22 15:14:06 -0400246 {
247 formatSupported = true;
248 }
Geoff Langbaadf232014-08-04 13:58:02 -0400249
250 // Early-out if both type and format are supported now
251 if (typeSupported && formatSupported)
252 {
253 break;
254 }
Geoff Lang5d601382014-07-22 15:14:06 -0400255 }
256 }
257
258 if (!typeSupported || !formatSupported)
259 {
Jamie Madill437fa652016-05-03 15:13:24 -0400260 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400261 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400262 }
263
264 // Check if this is a valid format combination to load texture data
265 ES3FormatCombination searchFormat;
266 searchFormat.internalFormat = internalFormat;
267 searchFormat.format = format;
268 searchFormat.type = type;
269
270 if (es3FormatSet.find(searchFormat) == es3FormatSet.end())
271 {
Jamie Madill437fa652016-05-03 15:13:24 -0400272 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400273 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400274 }
275
276 return true;
277}
278
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500279bool ValidateES3TexImageParametersBase(Context *context,
280 GLenum target,
281 GLint level,
282 GLenum internalformat,
283 bool isCompressed,
284 bool isSubImage,
285 GLint xoffset,
286 GLint yoffset,
287 GLint zoffset,
288 GLsizei width,
289 GLsizei height,
290 GLsizei depth,
291 GLint border,
292 GLenum format,
293 GLenum type,
294 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400295{
296 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -0700297 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400298 {
Jamie Madill437fa652016-05-03 15:13:24 -0400299 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400300 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400301 }
302
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400303 // Verify zero border
304 if (border != 0)
305 {
Jamie Madill437fa652016-05-03 15:13:24 -0400306 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400307 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400308 }
309
Jamie Madill6f38f822014-06-06 17:12:20 -0400310 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
311 std::numeric_limits<GLsizei>::max() - xoffset < width ||
312 std::numeric_limits<GLsizei>::max() - yoffset < height ||
313 std::numeric_limits<GLsizei>::max() - zoffset < depth)
314 {
Jamie Madill437fa652016-05-03 15:13:24 -0400315 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400316 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400317 }
318
Geoff Langaae65a42014-05-26 12:43:44 -0400319 const gl::Caps &caps = context->getCaps();
320
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400321 switch (target)
322 {
323 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500324 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
325 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400326 {
Jamie Madill437fa652016-05-03 15:13:24 -0400327 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500328 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400329 }
330 break;
331
332 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
333 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
334 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
335 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
336 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
337 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500338 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400339 {
Jamie Madill437fa652016-05-03 15:13:24 -0400340 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500341 return false;
342 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400343
Geoff Langa9be0dc2014-12-17 12:34:40 -0500344 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
345 {
Jamie Madill437fa652016-05-03 15:13:24 -0400346 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500347 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400348 }
349 break;
350
351 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500352 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
353 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
354 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400355 {
Jamie Madill437fa652016-05-03 15:13:24 -0400356 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500357 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400358 }
359 break;
360
Geoff Langa9be0dc2014-12-17 12:34:40 -0500361 case GL_TEXTURE_2D_ARRAY:
362 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
363 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
Geoff Langb92c1332015-09-04 12:54:55 -0400364 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500365 {
Jamie Madill437fa652016-05-03 15:13:24 -0400366 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500367 return false;
368 }
369 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400370
371 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400372 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400373 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400374 }
375
Geoff Lang691e58c2014-12-19 17:03:25 -0500376 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400377 if (!texture)
378 {
Jamie Madill437fa652016-05-03 15:13:24 -0400379 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400380 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400381 }
382
Geoff Lang69cce582015-09-17 13:20:36 -0400383 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400384 {
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
389 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400390 GLenum actualInternalFormat =
391 isSubImage ? texture->getFormat(target, level).asSized() : internalformat;
Geoff Lang5d601382014-07-22 15:14:06 -0400392 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400393 if (isCompressed)
394 {
tmartino7c102692015-10-02 16:43:40 -0400395 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400396 {
Jamie Madill437fa652016-05-03 15:13:24 -0400397 context->handleError(Error(
tmartino7c102692015-10-02 16:43:40 -0400398 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format."));
Geoff Langb1196682014-07-23 13:47:29 -0400399 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400400 }
401
tmartino7c102692015-10-02 16:43:40 -0400402 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400403 {
Jamie Madill437fa652016-05-03 15:13:24 -0400404 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400405 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400406 }
407
Martin Radev1be913c2016-07-11 17:59:16 +0300408 if (!actualFormatInfo.textureSupport(context->getClientMajorVersion(),
409 context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400410 {
Jamie Madill437fa652016-05-03 15:13:24 -0400411 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang839ce0b2015-10-23 13:13:12 -0400412 return false;
413 }
414
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400415 if (target == GL_TEXTURE_3D)
416 {
Jamie Madill437fa652016-05-03 15:13:24 -0400417 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400418 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400419 }
420 }
421 else
422 {
Geoff Langbaadf232014-08-04 13:58:02 -0400423 if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400424 {
Geoff Lang5d601382014-07-22 15:14:06 -0400425 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400426 }
427
428 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
429 {
Jamie Madill437fa652016-05-03 15:13:24 -0400430 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400431 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400432 }
433 }
434
435 // Validate sub image parameters
436 if (isSubImage)
437 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500438 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400439 {
Jamie Madill437fa652016-05-03 15:13:24 -0400440 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400441 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400442 }
443
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400444 if (width == 0 || height == 0 || depth == 0)
445 {
446 return false;
447 }
448
449 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
450 {
Jamie Madill437fa652016-05-03 15:13:24 -0400451 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400452 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400453 }
454
455 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
456 std::numeric_limits<GLsizei>::max() - yoffset < height ||
457 std::numeric_limits<GLsizei>::max() - zoffset < depth)
458 {
Jamie Madill437fa652016-05-03 15:13:24 -0400459 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400460 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400461 }
462
Geoff Langa9be0dc2014-12-17 12:34:40 -0500463 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
464 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
465 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400466 {
Jamie Madill437fa652016-05-03 15:13:24 -0400467 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400468 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400469 }
470 }
471
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400472 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700473 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400474 if (pixelUnpackBuffer != NULL)
475 {
476 // ...the data would be unpacked from the buffer object such that the memory reads required
477 // would exceed the data store size.
Geoff Lang5d601382014-07-22 15:14:06 -0400478 GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400479 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -0700480 const gl::Extents size(width, height, depth);
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700481 const auto &unpack = context->getGLState().getUnpackState();
Jamie Madill4b4cdff2016-06-06 13:53:38 -0700482
483 auto copyBytesOrErr = formatInfo.computeUnpackSize(type, size, unpack);
Jamie Madille2e406c2016-06-02 13:04:10 -0400484 if (copyBytesOrErr.isError())
485 {
486 context->handleError(copyBytesOrErr.getError());
487 return false;
488 }
489 CheckedNumeric<size_t> checkedCopyBytes(copyBytesOrErr.getResult());
490 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
491 checkedCopyBytes += checkedOffset;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400492
Olli Etuaho989cac32016-06-08 16:18:49 -0700493 auto rowPitchOrErr =
494 formatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength);
495 if (rowPitchOrErr.isError())
496 {
497 context->handleError(rowPitchOrErr.getError());
498 return false;
499 }
500 auto depthPitchOrErr = formatInfo.computeDepthPitch(type, width, height, unpack.alignment,
501 unpack.rowLength, unpack.imageHeight);
502 if (depthPitchOrErr.isError())
503 {
504 context->handleError(depthPitchOrErr.getError());
505 return false;
506 }
507
508 bool targetIs3D = target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY;
509 auto skipBytesOrErr = formatInfo.computeSkipBytes(
510 rowPitchOrErr.getResult(), depthPitchOrErr.getResult(), unpack.skipImages,
511 unpack.skipRows, unpack.skipPixels, targetIs3D);
512 if (skipBytesOrErr.isError())
513 {
514 context->handleError(skipBytesOrErr.getError());
515 return false;
516 }
517 checkedCopyBytes += skipBytesOrErr.getResult();
518
Jamie Madille2e406c2016-06-02 13:04:10 -0400519 if (!checkedCopyBytes.IsValid() ||
520 (checkedCopyBytes.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400521 {
522 // Overflow past the end of the buffer
Jamie Madill437fa652016-05-03 15:13:24 -0400523 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400524 return false;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400525 }
526
527 // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
528 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400529 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400530 {
Jamie Madillc751d1e2014-10-21 17:46:29 -0400531 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
532
Jamie Madille2e406c2016-06-02 13:04:10 -0400533 if ((checkedOffset.ValueOrDie() % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400534 {
Jamie Madill437fa652016-05-03 15:13:24 -0400535 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400536 return false;
537 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400538 }
539
Jamie Madill7a5f7382014-03-05 15:01:24 -0500540 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700541 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500542 {
Jamie Madill437fa652016-05-03 15:13:24 -0400543 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400544 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500545 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400546 }
547
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400548 return true;
549}
550
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500551bool ValidateES3TexImage2DParameters(Context *context,
552 GLenum target,
553 GLint level,
554 GLenum internalformat,
555 bool isCompressed,
556 bool isSubImage,
557 GLint xoffset,
558 GLint yoffset,
559 GLint zoffset,
560 GLsizei width,
561 GLsizei height,
562 GLsizei depth,
563 GLint border,
564 GLenum format,
565 GLenum type,
566 const GLvoid *pixels)
567{
568 if (!ValidTexture2DDestinationTarget(context, target))
569 {
Jamie Madill437fa652016-05-03 15:13:24 -0400570 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500571 return false;
572 }
573
574 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
575 isSubImage, xoffset, yoffset, zoffset, width, height,
576 depth, border, format, type, pixels);
577}
578
579bool ValidateES3TexImage3DParameters(Context *context,
580 GLenum target,
581 GLint level,
582 GLenum internalformat,
583 bool isCompressed,
584 bool isSubImage,
585 GLint xoffset,
586 GLint yoffset,
587 GLint zoffset,
588 GLsizei width,
589 GLsizei height,
590 GLsizei depth,
591 GLint border,
592 GLenum format,
593 GLenum type,
594 const GLvoid *pixels)
595{
596 if (!ValidTexture3DDestinationTarget(context, target))
597 {
Jamie Madill437fa652016-05-03 15:13:24 -0400598 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500599 return false;
600 }
601
602 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
603 isSubImage, xoffset, yoffset, zoffset, width, height,
604 depth, border, format, type, pixels);
605}
606
Geoff Lang5d601382014-07-22 15:14:06 -0400607struct EffectiveInternalFormatInfo
608{
609 GLenum mEffectiveFormat;
610 GLenum mDestFormat;
611 GLuint mMinRedBits;
612 GLuint mMaxRedBits;
613 GLuint mMinGreenBits;
614 GLuint mMaxGreenBits;
615 GLuint mMinBlueBits;
616 GLuint mMaxBlueBits;
617 GLuint mMinAlphaBits;
618 GLuint mMaxAlphaBits;
619
620 EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits,
621 GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits,
622 GLuint minAlphaBits, GLuint maxAlphaBits)
623 : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits),
624 mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits),
625 mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits),
626 mMaxAlphaBits(maxAlphaBits) {};
627};
628
629typedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
630
631static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList()
632{
633 EffectiveInternalFormatList list;
634
635 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
636 // linear source buffer component sizes.
637 // | Source channel min/max sizes |
638 // Effective Internal Format | N/A | R | G | B | A |
639 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8));
640 list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0));
641 list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0));
642 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0));
643 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0));
644 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4));
645 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1));
646 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8));
647 list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2));
648
649 return list;
650}
651
652static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList()
653{
654 EffectiveInternalFormatList list;
655
656 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
657 // linear source buffer component sizes.
658 // | Source channel min/max sizes |
659 // Effective Internal Format | Dest Format | R | G | B | A |
660 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
661 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX));
662 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
663 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX));
664 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX));
665 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4));
666 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1));
667 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8));
668
669 return list;
670}
671
672static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
673 GLenum *outEffectiveFormat)
674{
675 const EffectiveInternalFormatList *list = NULL;
676 GLenum targetFormat = GL_NONE;
677
678 if (destFormat.pixelBytes > 0)
679 {
680 static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList();
681 list = &sizedList;
682 }
683 else
684 {
685 static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList();
686 list = &unsizedList;
687 targetFormat = destFormat.format;
688 }
689
690 for (size_t curFormat = 0; curFormat < list->size(); ++curFormat)
691 {
692 const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat);
693 if ((formatInfo.mDestFormat == targetFormat) &&
694 (formatInfo.mMinRedBits <= srcFormat.redBits && formatInfo.mMaxRedBits >= srcFormat.redBits) &&
695 (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) &&
696 (formatInfo.mMinBlueBits <= srcFormat.blueBits && formatInfo.mMaxBlueBits >= srcFormat.blueBits) &&
697 (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits))
698 {
699 *outEffectiveFormat = formatInfo.mEffectiveFormat;
700 return true;
701 }
702 }
703
704 return false;
705}
706
707struct CopyConversion
708{
709 GLenum mTextureFormat;
710 GLenum mFramebufferFormat;
711
712 CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
713 : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
714
715 bool operator<(const CopyConversion& other) const
716 {
717 return memcmp(this, &other, sizeof(CopyConversion)) < 0;
718 }
719};
720
721typedef std::set<CopyConversion> CopyConversionSet;
722
723static CopyConversionSet BuildValidES3CopyTexImageCombinations()
724{
725 CopyConversionSet set;
726
727 // From ES 3.0.1 spec, table 3.15
728 set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
729 set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
730 set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
731 set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
732 set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
733 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
734 set.insert(CopyConversion(GL_RED, GL_RED));
735 set.insert(CopyConversion(GL_RED, GL_RG));
736 set.insert(CopyConversion(GL_RED, GL_RGB));
737 set.insert(CopyConversion(GL_RED, GL_RGBA));
738 set.insert(CopyConversion(GL_RG, GL_RG));
739 set.insert(CopyConversion(GL_RG, GL_RGB));
740 set.insert(CopyConversion(GL_RG, GL_RGBA));
741 set.insert(CopyConversion(GL_RGB, GL_RGB));
742 set.insert(CopyConversion(GL_RGB, GL_RGBA));
743 set.insert(CopyConversion(GL_RGBA, GL_RGBA));
744
745 // Necessary for ANGLE back-buffers
746 set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
747 set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
748 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
749 set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
750 set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
751 set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
752 set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
753
754 set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
755 set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
756 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
757 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
758 set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
759 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
760 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
761 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
762 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
763 set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
764
765 return set;
766}
767
Corentin Wallez76287682016-04-25 09:23:38 -0400768static bool EqualOrFirstZero(GLuint first, GLuint second)
769{
770 return first == 0 || first == second;
771}
772
Jamie Madill0c8abca2016-07-22 20:21:26 -0400773static bool IsValidES3CopyTexImageCombination(const Format &textureFormat,
774 const Format &framebufferFormat,
775 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400776{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400777 const auto &textureFormatInfo = *textureFormat.info;
778 const auto &framebufferFormatInfo = *framebufferFormat.info;
Geoff Lang5d601382014-07-22 15:14:06 -0400779
780 static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
Jamie Madill0c8abca2016-07-22 20:21:26 -0400781 if (conversionSet.find(CopyConversion(textureFormatInfo.format,
782 framebufferFormatInfo.format)) != conversionSet.end())
Geoff Lang5d601382014-07-22 15:14:06 -0400783 {
784 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
785 // must both be signed, unsigned, or fixed point and both source and destinations
786 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
787 // conversion between fixed and floating point.
788
Jamie Madill0c8abca2016-07-22 20:21:26 -0400789 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
790 (framebufferFormatInfo.colorEncoding == GL_SRGB))
Geoff Lang5d601382014-07-22 15:14:06 -0400791 {
792 return false;
793 }
794
Jamie Madill0c8abca2016-07-22 20:21:26 -0400795 if (((textureFormatInfo.componentType == GL_INT) !=
796 (framebufferFormatInfo.componentType == GL_INT)) ||
797 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
798 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
Geoff Lang5d601382014-07-22 15:14:06 -0400799 {
800 return false;
801 }
802
Jamie Madill0c8abca2016-07-22 20:21:26 -0400803 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
804 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
805 textureFormatInfo.componentType == GL_FLOAT) &&
806 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
807 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
808 framebufferFormatInfo.componentType == GL_FLOAT))
Geoff Lang5d601382014-07-22 15:14:06 -0400809 {
810 return false;
811 }
812
813 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
814 // The effective internal format of the source buffer is determined with the following rules applied in order:
815 // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
816 // effective internal format is the source buffer's sized internal format.
817 // * If the source buffer is a texture that was created with an unsized base internal format, then the
818 // effective internal format is the source image array's effective internal format, as specified by table
819 // 3.12, which is determined from the <format> and <type> that were used when the source image array was
820 // specified by TexImage*.
821 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
822 // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
823 // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
824 // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
825 // is SRGB.
826 const InternalFormat *sourceEffectiveFormat = NULL;
827 if (readBufferHandle != 0)
828 {
829 // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
Jamie Madill0c8abca2016-07-22 20:21:26 -0400830 if (framebufferFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400831 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400832 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400833 }
834 else
835 {
836 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
837 // 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 -0400838 GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferFormatInfo.format,
839 framebufferFormatInfo.type);
Geoff Lang051dbc72015-01-05 15:48:58 -0500840 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400841 }
842 }
843 else
844 {
845 // The effective internal format must be derived from the source framebuffer's channel sizes.
846 // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
Jamie Madill0c8abca2016-07-22 20:21:26 -0400847 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400848 {
849 GLenum effectiveFormat;
Jamie Madill0c8abca2016-07-22 20:21:26 -0400850 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
851 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400852 {
853 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
854 }
855 else
856 {
857 return false;
858 }
859 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400860 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
Geoff Lang5d601382014-07-22 15:14:06 -0400861 {
862 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Jamie Madill0c8abca2016-07-22 20:21:26 -0400863 if (textureFormat.sized &&
864 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
865 (framebufferFormatInfo.greenBits >= 1 &&
866 framebufferFormatInfo.greenBits <= 8) &&
867 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
868 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
Geoff Lang5d601382014-07-22 15:14:06 -0400869 {
870 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
871 }
872 else
873 {
874 return false;
875 }
876 }
877 else
878 {
879 UNREACHABLE();
880 return false;
881 }
882 }
883
Jamie Madill0c8abca2016-07-22 20:21:26 -0400884 if (textureFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400885 {
Corentin Wallez76287682016-04-25 09:23:38 -0400886 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination
887 // format is sized, component sizes of the source and destination formats must exactly
888 // match if the destination format exists.
Jamie Madill0c8abca2016-07-22 20:21:26 -0400889 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
890 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
891 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
892 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
Geoff Lang5d601382014-07-22 15:14:06 -0400893 {
894 return false;
895 }
896 }
897
Geoff Lang5d601382014-07-22 15:14:06 -0400898 return true; // A conversion function exists, and no rule in the specification has precluded conversion
899 // between these formats.
900 }
901
902 return false;
903}
904
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500905bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
906 GLenum target,
907 GLint level,
908 GLenum internalformat,
909 bool isSubImage,
910 GLint xoffset,
911 GLint yoffset,
912 GLint zoffset,
913 GLint x,
914 GLint y,
915 GLsizei width,
916 GLsizei height,
917 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400918{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400919 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400920 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400921 xoffset, yoffset, zoffset, x, y, width, height, border,
922 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400923 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400924 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400925 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400926 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400927
Jamie Madill51f40ec2016-06-15 14:06:00 -0400928 const auto &state = context->getGLState();
929 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
930 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400931
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700932 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400933 {
Jamie Madill437fa652016-05-03 15:13:24 -0400934 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400935 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400936 }
937
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700938 if (readFramebufferID != 0 && framebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400939 {
Jamie Madill437fa652016-05-03 15:13:24 -0400940 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400941 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400942 }
943
Jamie Madill0c8abca2016-07-22 20:21:26 -0400944 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400945
946 if (isSubImage)
947 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400948 if (!IsValidES3CopyTexImageCombination(textureFormat, source->getFormat(),
Jamie Madillc29968b2016-01-20 11:17:23 -0500949 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400950 {
Jamie Madill437fa652016-05-03 15:13:24 -0400951 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400952 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400953 }
954 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400955 else
956 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400957 // Use format/type from the source FBO. (Might not be perfect for all cases?)
958 const auto framebufferFormat = source->getFormat();
959 Format copyFormat(internalformat, framebufferFormat.format, framebufferFormat.type);
960 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400961 {
Jamie Madill437fa652016-05-03 15:13:24 -0400962 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400963 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400964 }
965 }
966
Geoff Lang784a8fd2013-09-24 12:33:16 -0400967 // If width or height is zero, it is a no-op. Return false without setting an error.
968 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400969}
970
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500971bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
972 GLenum target,
973 GLint level,
974 GLenum internalformat,
975 bool isSubImage,
976 GLint xoffset,
977 GLint yoffset,
978 GLint zoffset,
979 GLint x,
980 GLint y,
981 GLsizei width,
982 GLsizei height,
983 GLint border)
984{
985 if (!ValidTexture2DDestinationTarget(context, target))
986 {
Jamie Madill437fa652016-05-03 15:13:24 -0400987 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500988 return false;
989 }
990
991 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
992 xoffset, yoffset, zoffset, x, y, width, height,
993 border);
994}
995
996bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
997 GLenum target,
998 GLint level,
999 GLenum internalformat,
1000 bool isSubImage,
1001 GLint xoffset,
1002 GLint yoffset,
1003 GLint zoffset,
1004 GLint x,
1005 GLint y,
1006 GLsizei width,
1007 GLsizei height,
1008 GLint border)
1009{
1010 if (!ValidTexture3DDestinationTarget(context, target))
1011 {
Jamie Madill437fa652016-05-03 15:13:24 -04001012 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001013 return false;
1014 }
1015
1016 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
1017 xoffset, yoffset, zoffset, x, y, width, height,
1018 border);
1019}
1020
1021bool ValidateES3TexStorageParametersBase(Context *context,
1022 GLenum target,
1023 GLsizei levels,
1024 GLenum internalformat,
1025 GLsizei width,
1026 GLsizei height,
1027 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001028{
1029 if (width < 1 || height < 1 || depth < 1 || levels < 1)
1030 {
Jamie Madill437fa652016-05-03 15:13:24 -04001031 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001032 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001033 }
1034
Geoff Langb92c1332015-09-04 12:54:55 -04001035 GLsizei maxDim = std::max(width, height);
1036 if (target != GL_TEXTURE_2D_ARRAY)
1037 {
1038 maxDim = std::max(maxDim, depth);
1039 }
1040
1041 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001042 {
Jamie Madill437fa652016-05-03 15:13:24 -04001043 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001044 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001045 }
1046
Geoff Langaae65a42014-05-26 12:43:44 -04001047 const gl::Caps &caps = context->getCaps();
1048
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001049 switch (target)
1050 {
1051 case GL_TEXTURE_2D:
1052 {
Geoff Langaae65a42014-05-26 12:43:44 -04001053 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1054 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001055 {
Jamie Madill437fa652016-05-03 15:13:24 -04001056 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001057 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001058 }
1059 }
1060 break;
1061
Geoff Lang01c21d22013-09-24 11:52:16 -04001062 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001063 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001064 if (width != height)
1065 {
Jamie Madill437fa652016-05-03 15:13:24 -04001066 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001067 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001068 }
1069
Geoff Langaae65a42014-05-26 12:43:44 -04001070 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001071 {
Jamie Madill437fa652016-05-03 15:13:24 -04001072 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001073 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001074 }
1075 }
1076 break;
1077
1078 case GL_TEXTURE_3D:
1079 {
Geoff Langaae65a42014-05-26 12:43:44 -04001080 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
1081 static_cast<GLuint>(height) > caps.max3DTextureSize ||
1082 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001083 {
Jamie Madill437fa652016-05-03 15:13:24 -04001084 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001085 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001086 }
1087 }
1088 break;
1089
1090 case GL_TEXTURE_2D_ARRAY:
1091 {
Geoff Langaae65a42014-05-26 12:43:44 -04001092 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1093 static_cast<GLuint>(height) > caps.max2DTextureSize ||
1094 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001095 {
Jamie Madill437fa652016-05-03 15:13:24 -04001096 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001097 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001098 }
1099 }
1100 break;
1101
1102 default:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001103 UNREACHABLE();
Geoff Langb1196682014-07-23 13:47:29 -04001104 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001105 }
1106
Geoff Lang691e58c2014-12-19 17:03:25 -05001107 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001108 if (!texture || texture->id() == 0)
1109 {
Jamie Madill437fa652016-05-03 15:13:24 -04001110 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001111 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001112 }
1113
Geoff Lang69cce582015-09-17 13:20:36 -04001114 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001115 {
Jamie Madill437fa652016-05-03 15:13:24 -04001116 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001117 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001118 }
1119
Geoff Lang5d601382014-07-22 15:14:06 -04001120 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Martin Radev1be913c2016-07-11 17:59:16 +03001121 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001122 {
Jamie Madill437fa652016-05-03 15:13:24 -04001123 context->handleError(Error(GL_INVALID_ENUM));
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 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001128 {
Jamie Madill437fa652016-05-03 15:13:24 -04001129 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001130 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001131 }
1132
1133 return true;
1134}
1135
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001136bool ValidateES3TexStorage2DParameters(Context *context,
1137 GLenum target,
1138 GLsizei levels,
1139 GLenum internalformat,
1140 GLsizei width,
1141 GLsizei height,
1142 GLsizei depth)
1143{
1144 if (!ValidTexture2DTarget(context, target))
1145 {
Jamie Madill437fa652016-05-03 15:13:24 -04001146 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001147 return false;
1148 }
1149
1150 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1151 height, depth);
1152}
1153
1154bool ValidateES3TexStorage3DParameters(Context *context,
1155 GLenum target,
1156 GLsizei levels,
1157 GLenum internalformat,
1158 GLsizei width,
1159 GLsizei height,
1160 GLsizei depth)
1161{
1162 if (!ValidTexture3DTarget(context, target))
1163 {
Jamie Madill437fa652016-05-03 15:13:24 -04001164 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001165 return false;
1166 }
1167
1168 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1169 height, depth);
1170}
1171
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001172bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1173{
Martin Radev1be913c2016-07-11 17:59:16 +03001174 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001175 {
Jamie Madill437fa652016-05-03 15:13:24 -04001176 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001177 return false;
1178 }
1179
1180 return ValidateBeginQueryBase(context, target, id);
1181}
1182
1183bool ValidateEndQuery(gl::Context *context, GLenum target)
1184{
Martin Radev1be913c2016-07-11 17:59:16 +03001185 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001186 {
Jamie Madill437fa652016-05-03 15:13:24 -04001187 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001188 return false;
1189 }
1190
1191 return ValidateEndQueryBase(context, target);
1192}
1193
1194bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1195{
Martin Radev1be913c2016-07-11 17:59:16 +03001196 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001197 {
Jamie Madill437fa652016-05-03 15:13:24 -04001198 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001199 return false;
1200 }
1201
1202 return ValidateGetQueryivBase(context, target, pname);
1203}
1204
1205bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1206{
Martin Radev1be913c2016-07-11 17:59:16 +03001207 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001208 {
Jamie Madill437fa652016-05-03 15:13:24 -04001209 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001210 return false;
1211 }
1212
1213 return ValidateGetQueryObjectValueBase(context, id, pname);
1214}
1215
Geoff Langb1196682014-07-23 13:47:29 -04001216bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
Jamie Madill570f7c82014-07-03 10:38:54 -04001217 GLuint texture, GLint level, GLint layer)
1218{
Martin Radev1be913c2016-07-11 17:59:16 +03001219 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001220 {
Jamie Madill437fa652016-05-03 15:13:24 -04001221 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001222 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001223 }
1224
Jamie Madill55ec3b12014-07-03 10:38:57 -04001225 if (layer < 0)
1226 {
Jamie Madill437fa652016-05-03 15:13:24 -04001227 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001228 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001229 }
1230
1231 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1232 {
1233 return false;
1234 }
1235
1236 const gl::Caps &caps = context->getCaps();
1237 if (texture != 0)
1238 {
1239 gl::Texture *tex = context->getTexture(texture);
1240 ASSERT(tex);
1241
1242 switch (tex->getTarget())
1243 {
1244 case GL_TEXTURE_2D_ARRAY:
1245 {
1246 if (level > gl::log2(caps.max2DTextureSize))
1247 {
Jamie Madill437fa652016-05-03 15:13:24 -04001248 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001249 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001250 }
1251
1252 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1253 {
Jamie Madill437fa652016-05-03 15:13:24 -04001254 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001255 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001256 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001257 }
1258 break;
1259
1260 case GL_TEXTURE_3D:
1261 {
1262 if (level > gl::log2(caps.max3DTextureSize))
1263 {
Jamie Madill437fa652016-05-03 15:13:24 -04001264 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001265 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001266 }
1267
1268 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1269 {
Jamie Madill437fa652016-05-03 15:13:24 -04001270 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001271 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001272 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001273 }
1274 break;
1275
1276 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001277 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001278 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001279 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001280
Jamie Madilla3944d42016-07-22 22:13:26 -04001281 const auto &format = tex->getFormat(tex->getTarget(), level);
1282 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001283 {
Jamie Madill437fa652016-05-03 15:13:24 -04001284 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001285 return false;
1286 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001287 }
1288
1289 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001290}
1291
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001292bool ValidES3ReadFormatType(ValidationContext *context,
1293 GLenum internalFormat,
1294 GLenum format,
1295 GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001296{
Geoff Lang5d601382014-07-22 15:14:06 -04001297 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
1298
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001299 switch (format)
1300 {
1301 case GL_RGBA:
1302 switch (type)
1303 {
1304 case GL_UNSIGNED_BYTE:
1305 break;
Vincent Lang25ab4512016-05-13 18:13:59 +02001306 case GL_UNSIGNED_SHORT:
1307 if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
1308 internalFormatInfo.type != GL_UNSIGNED_SHORT)
1309 {
1310 return false;
1311 }
1312 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001313 case GL_UNSIGNED_INT_2_10_10_10_REV:
1314 if (internalFormat != GL_RGB10_A2)
1315 {
1316 return false;
1317 }
1318 break;
Geoff Lang1ec57f82013-10-16 11:43:23 -04001319 case GL_FLOAT:
Geoff Lang5d601382014-07-22 15:14:06 -04001320 if (internalFormatInfo.componentType != GL_FLOAT)
Geoff Lang1ec57f82013-10-16 11:43:23 -04001321 {
1322 return false;
1323 }
1324 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001325 default:
1326 return false;
1327 }
1328 break;
1329 case GL_RGBA_INTEGER:
1330 switch (type)
1331 {
1332 case GL_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001333 if (internalFormatInfo.componentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001334 {
1335 return false;
1336 }
1337 break;
1338 case GL_UNSIGNED_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001339 if (internalFormatInfo.componentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001340 {
1341 return false;
1342 }
1343 break;
1344 default:
1345 return false;
1346 }
1347 break;
1348 case GL_BGRA_EXT:
1349 switch (type)
1350 {
1351 case GL_UNSIGNED_BYTE:
1352 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1353 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1354 break;
1355 default:
1356 return false;
1357 }
1358 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001359 case GL_RG_EXT:
1360 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001361 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001362 {
1363 return false;
1364 }
1365 switch (type)
1366 {
1367 case GL_UNSIGNED_BYTE:
1368 break;
Vincent Lang25ab4512016-05-13 18:13:59 +02001369 case GL_UNSIGNED_SHORT:
1370 if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
1371 internalFormatInfo.type != GL_UNSIGNED_SHORT)
1372 {
1373 return false;
1374 }
1375 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001376 default:
1377 return false;
1378 }
1379 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001380 default:
1381 return false;
1382 }
1383 return true;
1384}
1385
Corentin Walleze0902642014-11-04 12:32:15 -08001386bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
1387 GLenum internalformat, GLsizei width, GLsizei height)
1388{
1389 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
1390 {
1391 return false;
1392 }
1393
1394 //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.
1395 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1396 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
1397 {
Jamie Madill437fa652016-05-03 15:13:24 -04001398 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -08001399 return false;
1400 }
1401
1402 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
1403 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1404 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1405 {
Jamie Madill437fa652016-05-03 15:13:24 -04001406 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001407 Error(GL_INVALID_OPERATION,
1408 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001409 return false;
1410 }
1411
1412 return true;
1413}
1414
Austin Kinross08332632015-05-05 13:35:47 -07001415bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
1416 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001417{
Martin Radev1be913c2016-07-11 17:59:16 +03001418 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001419 {
Jamie Madill437fa652016-05-03 15:13:24 -04001420 context->handleError(
1421 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001422 return false;
1423 }
1424
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001425 bool defaultFramebuffer = false;
1426
1427 switch (target)
1428 {
1429 case GL_DRAW_FRAMEBUFFER:
1430 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001431 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1432 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001433 case GL_READ_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001434 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1435 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001436 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001437 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001438 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001439 }
1440
Austin Kinross08332632015-05-05 13:35:47 -07001441 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001442}
1443
Jamie Madillc29968b2016-01-20 11:17:23 -05001444bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001445{
Martin Radev1be913c2016-07-11 17:59:16 +03001446 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001447 {
Jamie Madill437fa652016-05-03 15:13:24 -04001448 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001449 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001450 }
1451
Jamie Madill51f40ec2016-06-15 14:06:00 -04001452 if (context->getGLState().getDrawFramebuffer()->checkStatus(context->getContextState()) !=
1453 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001454 {
Jamie Madill437fa652016-05-03 15:13:24 -04001455 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001456 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001457 }
1458
1459 return true;
1460}
1461
Olli Etuaho71dfb362016-03-10 14:04:27 +02001462bool ValidateDrawRangeElements(Context *context,
1463 GLenum mode,
1464 GLuint start,
1465 GLuint end,
1466 GLsizei count,
1467 GLenum type,
1468 const GLvoid *indices,
1469 IndexRange *indexRange)
1470{
Martin Radev1be913c2016-07-11 17:59:16 +03001471 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001472 {
Jamie Madill437fa652016-05-03 15:13:24 -04001473 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001474 return false;
1475 }
1476
1477 if (end < start)
1478 {
Jamie Madill437fa652016-05-03 15:13:24 -04001479 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001480 return false;
1481 }
1482
1483 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1484 {
1485 return false;
1486 }
1487
1488 if (indexRange->end > end || indexRange->start < start)
1489 {
1490 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001491 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001492 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1493 return false;
1494 }
1495 return true;
1496}
1497
Geoff Langb1196682014-07-23 13:47:29 -04001498bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001499{
Martin Radev1be913c2016-07-11 17:59:16 +03001500 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001501 {
Jamie Madill437fa652016-05-03 15:13:24 -04001502 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001503 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001504 }
1505
Jamie Madill78f41802014-08-25 15:47:55 -04001506 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001507}
1508
Jamie Madillb885e572015-02-03 16:16:04 -05001509bool ValidateReadBuffer(Context *context, GLenum src)
1510{
Martin Radev1be913c2016-07-11 17:59:16 +03001511 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001512 {
Jamie Madill437fa652016-05-03 15:13:24 -04001513 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001514 return false;
1515 }
1516
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001517 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001518
1519 if (readFBO == nullptr)
1520 {
Jamie Madill437fa652016-05-03 15:13:24 -04001521 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001522 return false;
1523 }
1524
1525 if (src == GL_NONE)
1526 {
1527 return true;
1528 }
1529
Olli Etuaho84c9f592016-03-09 14:37:25 +02001530 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001531 {
Jamie Madill437fa652016-05-03 15:13:24 -04001532 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001533 return false;
1534 }
1535
1536 if (readFBO->id() == 0)
1537 {
1538 if (src != GL_BACK)
1539 {
1540 const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001541 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001542 return false;
1543 }
1544 }
1545 else
1546 {
1547 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1548
1549 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1550 {
1551 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001552 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001553 return false;
1554 }
1555 }
1556
1557 return true;
1558}
1559
Jamie Madill86af3d22015-07-21 15:14:07 -04001560bool ValidateCompressedTexImage3D(Context *context,
1561 GLenum target,
1562 GLint level,
1563 GLenum internalformat,
1564 GLsizei width,
1565 GLsizei height,
1566 GLsizei depth,
1567 GLint border,
1568 GLsizei imageSize,
1569 const GLvoid *data)
1570{
Martin Radev1be913c2016-07-11 17:59:16 +03001571 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001572 {
Jamie Madill437fa652016-05-03 15:13:24 -04001573 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001574 return false;
1575 }
1576
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001577 if (!ValidTextureTarget(context, target))
1578 {
1579 context->handleError(Error(GL_INVALID_ENUM));
1580 return false;
1581 }
1582
Jamie Madille2e406c2016-06-02 13:04:10 -04001583 // Validate image size
1584 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1585 {
1586 context->handleError(Error(GL_INVALID_VALUE));
1587 return false;
1588 }
1589
Jamie Madill86af3d22015-07-21 15:14:07 -04001590 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001591 if (!formatInfo.compressed)
1592 {
1593 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1594 return false;
1595 }
1596
Jamie Madill513558d2016-06-02 13:04:11 -04001597 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001598 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001599 if (blockSizeOrErr.isError())
1600 {
Jamie Madill513558d2016-06-02 13:04:11 -04001601 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001602 return false;
1603 }
1604 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001605 {
Jamie Madill437fa652016-05-03 15:13:24 -04001606 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001607 return false;
1608 }
1609
1610 // 3D texture target validation
1611 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1612 {
Jamie Madill437fa652016-05-03 15:13:24 -04001613 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001614 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1615 return false;
1616 }
1617
1618 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001619 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
1620 0, width, height, depth, border, GL_NONE, GL_NONE, data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001621 {
1622 return false;
1623 }
1624
1625 return true;
1626}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001627
1628bool ValidateBindVertexArray(Context *context, GLuint array)
1629{
Martin Radev1be913c2016-07-11 17:59:16 +03001630 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001631 {
Jamie Madill437fa652016-05-03 15:13:24 -04001632 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001633 return false;
1634 }
1635
1636 return ValidateBindVertexArrayBase(context, array);
1637}
1638
Austin Kinrossbc781f32015-10-26 09:27:38 -07001639bool ValidateIsVertexArray(Context *context)
1640{
Martin Radev1be913c2016-07-11 17:59:16 +03001641 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001642 {
Jamie Madill437fa652016-05-03 15:13:24 -04001643 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001644 return false;
1645 }
1646
1647 return true;
1648}
Geoff Langc5629752015-12-07 16:29:04 -05001649
1650bool ValidateProgramBinary(Context *context,
1651 GLuint program,
1652 GLenum binaryFormat,
1653 const void *binary,
1654 GLint length)
1655{
Martin Radev1be913c2016-07-11 17:59:16 +03001656 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001657 {
Jamie Madill437fa652016-05-03 15:13:24 -04001658 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001659 return false;
1660 }
1661
1662 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1663}
1664
1665bool ValidateGetProgramBinary(Context *context,
1666 GLuint program,
1667 GLsizei bufSize,
1668 GLsizei *length,
1669 GLenum *binaryFormat,
1670 void *binary)
1671{
Martin Radev1be913c2016-07-11 17:59:16 +03001672 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001673 {
Jamie Madill437fa652016-05-03 15:13:24 -04001674 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001675 return false;
1676 }
1677
1678 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1679}
1680
Olli Etuahof0fee072016-03-30 15:11:58 +03001681bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001682{
Martin Radev1be913c2016-07-11 17:59:16 +03001683 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001684 {
Jamie Madill437fa652016-05-03 15:13:24 -04001685 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001686 return false;
1687 }
1688
1689 if (GetValidProgram(context, program) == nullptr)
1690 {
1691 return false;
1692 }
1693
1694 switch (pname)
1695 {
1696 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001697 if (value != GL_FALSE && value != GL_TRUE)
1698 {
Jamie Madill437fa652016-05-03 15:13:24 -04001699 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001700 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1701 return false;
1702 }
Geoff Langc5629752015-12-07 16:29:04 -05001703 break;
1704
1705 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001706 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001707 return false;
1708 }
1709
1710 return true;
1711}
Jamie Madillc29968b2016-01-20 11:17:23 -05001712
1713bool ValidateBlitFramebuffer(Context *context,
1714 GLint srcX0,
1715 GLint srcY0,
1716 GLint srcX1,
1717 GLint srcY1,
1718 GLint dstX0,
1719 GLint dstY0,
1720 GLint dstX1,
1721 GLint dstY1,
1722 GLbitfield mask,
1723 GLenum filter)
1724{
Martin Radev1be913c2016-07-11 17:59:16 +03001725 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001726 {
Jamie Madill437fa652016-05-03 15:13:24 -04001727 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001728 return false;
1729 }
1730
1731 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1732 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001733}
Jamie Madillc29968b2016-01-20 11:17:23 -05001734
1735bool ValidateClearBufferiv(ValidationContext *context,
1736 GLenum buffer,
1737 GLint drawbuffer,
1738 const GLint *value)
1739{
1740 switch (buffer)
1741 {
1742 case GL_COLOR:
1743 if (drawbuffer < 0 ||
1744 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1745 {
Jamie Madill437fa652016-05-03 15:13:24 -04001746 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001747 return false;
1748 }
1749 break;
1750
1751 case GL_STENCIL:
1752 if (drawbuffer != 0)
1753 {
Jamie Madill437fa652016-05-03 15:13:24 -04001754 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001755 return false;
1756 }
1757 break;
1758
1759 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001760 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001761 return false;
1762 }
1763
1764 return ValidateClearBuffer(context);
1765}
1766
1767bool ValidateClearBufferuiv(ValidationContext *context,
1768 GLenum buffer,
1769 GLint drawbuffer,
1770 const GLuint *value)
1771{
1772 switch (buffer)
1773 {
1774 case GL_COLOR:
1775 if (drawbuffer < 0 ||
1776 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1777 {
Jamie Madill437fa652016-05-03 15:13:24 -04001778 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001779 return false;
1780 }
1781 break;
1782
1783 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001784 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001785 return false;
1786 }
1787
1788 return ValidateClearBuffer(context);
1789}
1790
1791bool ValidateClearBufferfv(ValidationContext *context,
1792 GLenum buffer,
1793 GLint drawbuffer,
1794 const GLfloat *value)
1795{
1796 switch (buffer)
1797 {
1798 case GL_COLOR:
1799 if (drawbuffer < 0 ||
1800 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1801 {
Jamie Madill437fa652016-05-03 15:13:24 -04001802 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001803 return false;
1804 }
1805 break;
1806
1807 case GL_DEPTH:
1808 if (drawbuffer != 0)
1809 {
Jamie Madill437fa652016-05-03 15:13:24 -04001810 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001811 return false;
1812 }
1813 break;
1814
1815 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001816 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001817 return false;
1818 }
1819
1820 return ValidateClearBuffer(context);
1821}
1822
1823bool ValidateClearBufferfi(ValidationContext *context,
1824 GLenum buffer,
1825 GLint drawbuffer,
1826 GLfloat depth,
1827 GLint stencil)
1828{
1829 switch (buffer)
1830 {
1831 case GL_DEPTH_STENCIL:
1832 if (drawbuffer != 0)
1833 {
Jamie Madill437fa652016-05-03 15:13:24 -04001834 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001835 return false;
1836 }
1837 break;
1838
1839 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001840 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001841 return false;
1842 }
1843
1844 return ValidateClearBuffer(context);
1845}
1846
1847bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1848{
Martin Radev1be913c2016-07-11 17:59:16 +03001849 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001850 {
Jamie Madill437fa652016-05-03 15:13:24 -04001851 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001852 return false;
1853 }
1854
1855 return ValidateDrawBuffersBase(context, n, bufs);
1856}
1857
1858bool ValidateCopyTexSubImage3D(Context *context,
1859 GLenum target,
1860 GLint level,
1861 GLint xoffset,
1862 GLint yoffset,
1863 GLint zoffset,
1864 GLint x,
1865 GLint y,
1866 GLsizei width,
1867 GLsizei height)
1868{
Martin Radev1be913c2016-07-11 17:59:16 +03001869 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001870 {
Jamie Madill437fa652016-05-03 15:13:24 -04001871 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001872 return false;
1873 }
1874
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001875 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1876 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001877}
1878
Jamie Madill73a84962016-02-12 09:27:23 -05001879bool ValidateTexImage3D(Context *context,
1880 GLenum target,
1881 GLint level,
1882 GLint internalformat,
1883 GLsizei width,
1884 GLsizei height,
1885 GLsizei depth,
1886 GLint border,
1887 GLenum format,
1888 GLenum type,
1889 const GLvoid *pixels)
1890{
Martin Radev1be913c2016-07-11 17:59:16 +03001891 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001892 {
Jamie Madill437fa652016-05-03 15:13:24 -04001893 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001894 return false;
1895 }
1896
1897 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1898 0, 0, width, height, depth, border, format, type,
1899 pixels);
1900}
1901
1902bool ValidateTexSubImage3D(Context *context,
1903 GLenum target,
1904 GLint level,
1905 GLint xoffset,
1906 GLint yoffset,
1907 GLint zoffset,
1908 GLsizei width,
1909 GLsizei height,
1910 GLsizei depth,
1911 GLenum format,
1912 GLenum type,
1913 const GLvoid *pixels)
1914{
Martin Radev1be913c2016-07-11 17:59:16 +03001915 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001916 {
Jamie Madill437fa652016-05-03 15:13:24 -04001917 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001918 return false;
1919 }
1920
1921 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1922 yoffset, zoffset, width, height, depth, 0, format, type,
1923 pixels);
1924}
1925
1926bool ValidateCompressedTexSubImage3D(Context *context,
1927 GLenum target,
1928 GLint level,
1929 GLint xoffset,
1930 GLint yoffset,
1931 GLint zoffset,
1932 GLsizei width,
1933 GLsizei height,
1934 GLsizei depth,
1935 GLenum format,
1936 GLsizei imageSize,
1937 const GLvoid *data)
1938{
Martin Radev1be913c2016-07-11 17:59:16 +03001939 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001940 {
Jamie Madill437fa652016-05-03 15:13:24 -04001941 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001942 return false;
1943 }
1944
1945 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001946 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001947 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001948 if (blockSizeOrErr.isError())
1949 {
1950 context->handleError(blockSizeOrErr.getError());
1951 return false;
1952 }
1953 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001954 {
Jamie Madill437fa652016-05-03 15:13:24 -04001955 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001956 return false;
1957 }
1958
1959 if (!data)
1960 {
Jamie Madill437fa652016-05-03 15:13:24 -04001961 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001962 return false;
1963 }
1964
1965 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
1966 width, height, depth, 0, GL_NONE, GL_NONE, data);
1967}
1968
Olli Etuaho41997e72016-03-10 13:38:39 +02001969bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1970{
1971 return ValidateGenOrDeleteES3(context, n);
1972}
1973
1974bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1975{
1976 return ValidateGenOrDeleteES3(context, n);
1977}
1978
1979bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1980{
1981 return ValidateGenOrDeleteCountES3(context, count);
1982}
1983
1984bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1985{
1986 return ValidateGenOrDeleteCountES3(context, count);
1987}
1988
1989bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1990{
1991 return ValidateGenOrDeleteES3(context, n);
1992}
1993
1994bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1995{
1996 if (!ValidateGenOrDeleteES3(context, n))
1997 {
1998 return false;
1999 }
2000 for (GLint i = 0; i < n; ++i)
2001 {
2002 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2003 if (transformFeedback != nullptr && transformFeedback->isActive())
2004 {
2005 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04002006 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02002007 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
2008 return false;
2009 }
2010 }
2011 return true;
2012}
2013
2014bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2015{
2016 return ValidateGenOrDeleteES3(context, n);
2017}
2018
2019bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2020{
2021 return ValidateGenOrDeleteES3(context, n);
2022}
2023
2024bool ValidateGenOrDeleteES3(Context *context, GLint n)
2025{
Martin Radev1be913c2016-07-11 17:59:16 +03002026 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02002027 {
Jamie Madill437fa652016-05-03 15:13:24 -04002028 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02002029 return false;
2030 }
2031 return ValidateGenOrDelete(context, n);
2032}
2033
2034bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
2035{
Martin Radev1be913c2016-07-11 17:59:16 +03002036 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02002037 {
Jamie Madill437fa652016-05-03 15:13:24 -04002038 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02002039 return false;
2040 }
2041 if (count < 0)
2042 {
Jamie Madill437fa652016-05-03 15:13:24 -04002043 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02002044 return false;
2045 }
2046 return true;
2047}
2048
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002049bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2050{
Martin Radev1be913c2016-07-11 17:59:16 +03002051 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002052 {
Jamie Madill437fa652016-05-03 15:13:24 -04002053 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002054 return false;
2055 }
2056 switch (primitiveMode)
2057 {
2058 case GL_TRIANGLES:
2059 case GL_LINES:
2060 case GL_POINTS:
2061 break;
2062
2063 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002064 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002065 return false;
2066 }
2067
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002068 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002069 ASSERT(transformFeedback != nullptr);
2070
2071 if (transformFeedback->isActive())
2072 {
Jamie Madill437fa652016-05-03 15:13:24 -04002073 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002074 return false;
2075 }
2076 return true;
2077}
2078
Olli Etuaho37477912016-03-30 14:54:40 +03002079bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
2080{
Martin Radev1be913c2016-07-11 17:59:16 +03002081 if (context->getClientMajorVersion() < 3)
Olli Etuaho37477912016-03-30 14:54:40 +03002082 {
Jamie Madill437fa652016-05-03 15:13:24 -04002083 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho37477912016-03-30 14:54:40 +03002084 return false;
2085 }
2086
2087 if (!context->isSampler(sampler))
2088 {
Jamie Madill437fa652016-05-03 15:13:24 -04002089 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho37477912016-03-30 14:54:40 +03002090 return false;
2091 }
2092
2093 if (!ValidateSamplerObjectParameter(context, pname))
2094 {
2095 return false;
2096 }
2097
Ian Ewellbda75592016-04-18 17:25:54 -04002098 if (!ValidateTexParamParameters(context, GL_TEXTURE_2D, pname, param))
Olli Etuaho37477912016-03-30 14:54:40 +03002099 {
2100 return false;
2101 }
2102 return true;
2103}
2104
2105bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
2106{
2107 // The only float parameters are MIN_LOD and MAX_LOD. For these any value is permissible, so
2108 // ValidateSamplerParameteri can be used for validation here.
2109 return ValidateSamplerParameteri(context, sampler, pname, static_cast<GLint>(param));
2110}
2111
Olli Etuaho4f667482016-03-30 15:56:35 +03002112bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
2113{
Martin Radev1be913c2016-07-11 17:59:16 +03002114 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002115 {
Jamie Madill437fa652016-05-03 15:13:24 -04002116 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002117 return false;
2118 }
2119
2120 return ValidateGetBufferPointervBase(context, target, pname, params);
2121}
2122
2123bool ValidateUnmapBuffer(Context *context, GLenum target)
2124{
Martin Radev1be913c2016-07-11 17:59:16 +03002125 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002126 {
Jamie Madill437fa652016-05-03 15:13:24 -04002127 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03002128 return false;
2129 }
2130
2131 return ValidateUnmapBufferBase(context, target);
2132}
2133
2134bool ValidateMapBufferRange(Context *context,
2135 GLenum target,
2136 GLintptr offset,
2137 GLsizeiptr length,
2138 GLbitfield access)
2139{
Martin Radev1be913c2016-07-11 17:59:16 +03002140 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002141 {
Jamie Madill437fa652016-05-03 15:13:24 -04002142 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002143 return false;
2144 }
2145
2146 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2147}
2148
2149bool ValidateFlushMappedBufferRange(Context *context,
2150 GLenum target,
2151 GLintptr offset,
2152 GLsizeiptr length)
2153{
Martin Radev1be913c2016-07-11 17:59:16 +03002154 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002155 {
Jamie Madill437fa652016-05-03 15:13:24 -04002156 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002157 return false;
2158 }
2159
2160 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2161}
2162
Martin Radev66fb8202016-07-28 11:45:20 +03002163bool ValidateIndexedStateQuery(ValidationContext *context, GLenum pname, GLuint index)
2164{
2165 GLenum nativeType;
2166 unsigned int numParams;
2167 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2168 {
2169 context->handleError(Error(GL_INVALID_ENUM));
2170 return false;
2171 }
2172
2173 const Caps &caps = context->getCaps();
2174 switch (pname)
2175 {
2176 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2177 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2178 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2179 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2180 {
2181 context->handleError(Error(GL_INVALID_VALUE));
2182 return false;
2183 }
2184 break;
2185
2186 case GL_UNIFORM_BUFFER_START:
2187 case GL_UNIFORM_BUFFER_SIZE:
2188 case GL_UNIFORM_BUFFER_BINDING:
2189 if (index >= caps.maxUniformBufferBindings)
2190 {
2191 context->handleError(Error(GL_INVALID_VALUE));
2192 return false;
2193 }
2194 break;
2195 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2196 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2197 if (index >= 3u)
2198 {
2199 context->handleError(Error(GL_INVALID_VALUE));
2200 return false;
2201 }
2202 break;
2203 default:
2204 context->handleError(Error(GL_INVALID_ENUM));
2205 return false;
2206 }
2207
2208 // pname is valid, but there are no parameters to return
2209 if (numParams == 0)
2210 {
2211 return false;
2212 }
2213
2214 return true;
2215}
2216
2217bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2218{
2219 if (!context->getGLVersion().isES3OrGreater())
2220 {
2221 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2222 return false;
2223 }
2224 return ValidateIndexedStateQuery(context, target, index);
2225}
2226
2227bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2228{
2229 if (!context->getGLVersion().isES3OrGreater())
2230 {
2231 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2232 return false;
2233 }
2234 return ValidateIndexedStateQuery(context, target, index);
2235}
2236
Jamie Madillc29968b2016-01-20 11:17:23 -05002237} // namespace gl