blob: a1e11cdb043f84c8cbe95742b99d80dde25e79b0 [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
Geoff Lang5d601382014-07-22 15:14:06 -0400773static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle)
774{
775 const InternalFormat &textureInternalFormatInfo = GetInternalFormatInfo(textureInternalFormat);
776 const InternalFormat &framebufferInternalFormatInfo = GetInternalFormatInfo(frameBufferInternalFormat);
777
778 static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
779 if (conversionSet.find(CopyConversion(textureInternalFormatInfo.format, framebufferInternalFormatInfo.format)) != conversionSet.end())
780 {
781 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
782 // must both be signed, unsigned, or fixed point and both source and destinations
783 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
784 // conversion between fixed and floating point.
785
786 if ((textureInternalFormatInfo.colorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.colorEncoding == GL_SRGB))
787 {
788 return false;
789 }
790
791 if (((textureInternalFormatInfo.componentType == GL_INT) != (framebufferInternalFormatInfo.componentType == GL_INT )) ||
792 ((textureInternalFormatInfo.componentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.componentType == GL_UNSIGNED_INT)))
793 {
794 return false;
795 }
796
797 if ((textureInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
798 textureInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
799 textureInternalFormatInfo.componentType == GL_FLOAT) &&
800 !(framebufferInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
801 framebufferInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
802 framebufferInternalFormatInfo.componentType == GL_FLOAT))
803 {
804 return false;
805 }
806
807 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
808 // The effective internal format of the source buffer is determined with the following rules applied in order:
809 // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
810 // effective internal format is the source buffer's sized internal format.
811 // * If the source buffer is a texture that was created with an unsized base internal format, then the
812 // effective internal format is the source image array's effective internal format, as specified by table
813 // 3.12, which is determined from the <format> and <type> that were used when the source image array was
814 // specified by TexImage*.
815 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
816 // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
817 // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
818 // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
819 // is SRGB.
820 const InternalFormat *sourceEffectiveFormat = NULL;
821 if (readBufferHandle != 0)
822 {
823 // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
824 if (framebufferInternalFormatInfo.pixelBytes > 0)
825 {
826 sourceEffectiveFormat = &framebufferInternalFormatInfo;
827 }
828 else
829 {
830 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
831 // texture. We can use the same table we use when creating textures to get its effective sized format.
Geoff Lang051dbc72015-01-05 15:48:58 -0500832 GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type);
833 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400834 }
835 }
836 else
837 {
838 // The effective internal format must be derived from the source framebuffer's channel sizes.
839 // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
840 if (framebufferInternalFormatInfo.colorEncoding == GL_LINEAR)
841 {
842 GLenum effectiveFormat;
843 if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat))
844 {
845 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
846 }
847 else
848 {
849 return false;
850 }
851 }
852 else if (framebufferInternalFormatInfo.colorEncoding == GL_SRGB)
853 {
854 // SRGB buffers can only be copied to sized format destinations according to table 3.18
855 if ((textureInternalFormatInfo.pixelBytes > 0) &&
856 (framebufferInternalFormatInfo.redBits >= 1 && framebufferInternalFormatInfo.redBits <= 8) &&
857 (framebufferInternalFormatInfo.greenBits >= 1 && framebufferInternalFormatInfo.greenBits <= 8) &&
858 (framebufferInternalFormatInfo.blueBits >= 1 && framebufferInternalFormatInfo.blueBits <= 8) &&
859 (framebufferInternalFormatInfo.alphaBits >= 1 && framebufferInternalFormatInfo.alphaBits <= 8))
860 {
861 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
862 }
863 else
864 {
865 return false;
866 }
867 }
868 else
869 {
870 UNREACHABLE();
871 return false;
872 }
873 }
874
875 if (textureInternalFormatInfo.pixelBytes > 0)
876 {
Corentin Wallez76287682016-04-25 09:23:38 -0400877 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination
878 // format is sized, component sizes of the source and destination formats must exactly
879 // match if the destination format exists.
880 if (!EqualOrFirstZero(textureInternalFormatInfo.redBits,
881 sourceEffectiveFormat->redBits) ||
882 !EqualOrFirstZero(textureInternalFormatInfo.greenBits,
883 sourceEffectiveFormat->greenBits) ||
884 !EqualOrFirstZero(textureInternalFormatInfo.blueBits,
885 sourceEffectiveFormat->blueBits) ||
886 !EqualOrFirstZero(textureInternalFormatInfo.alphaBits,
887 sourceEffectiveFormat->alphaBits))
Geoff Lang5d601382014-07-22 15:14:06 -0400888 {
889 return false;
890 }
891 }
892
893
894 return true; // A conversion function exists, and no rule in the specification has precluded conversion
895 // between these formats.
896 }
897
898 return false;
899}
900
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500901bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
902 GLenum target,
903 GLint level,
904 GLenum internalformat,
905 bool isSubImage,
906 GLint xoffset,
907 GLint yoffset,
908 GLint zoffset,
909 GLint x,
910 GLint y,
911 GLsizei width,
912 GLsizei height,
913 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400914{
Jamie Madilla3944d42016-07-22 22:13:26 -0400915 GLenum textureInternalFormat = GL_NONE;
Jamie Madill560a8d82014-05-21 13:06:20 -0400916 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill6f38f822014-06-06 17:12:20 -0400917 xoffset, yoffset, zoffset, x, y, width, height,
918 border, &textureInternalFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400919 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400920 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400921 }
Jamie Madilla3944d42016-07-22 22:13:26 -0400922 ASSERT(textureInternalFormat != GL_NONE || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400923
Jamie Madill51f40ec2016-06-15 14:06:00 -0400924 const auto &state = context->getGLState();
925 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
926 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400927
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700928 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400929 {
Jamie Madill437fa652016-05-03 15:13:24 -0400930 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400931 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400932 }
933
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700934 if (readFramebufferID != 0 && framebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400935 {
Jamie Madill437fa652016-05-03 15:13:24 -0400936 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400937 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400938 }
939
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400940 const gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Jamie Madilla3944d42016-07-22 22:13:26 -0400941 GLenum colorbufferInternalFormat = source->getFormat().asSized();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400942
943 if (isSubImage)
944 {
Geoff Lang5d601382014-07-22 15:14:06 -0400945 if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat,
Jamie Madillc29968b2016-01-20 11:17:23 -0500946 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400947 {
Jamie Madill437fa652016-05-03 15:13:24 -0400948 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400949 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400950 }
951 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400952 else
953 {
Geoff Lang5d601382014-07-22 15:14:06 -0400954 if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat,
Jamie Madillc29968b2016-01-20 11:17:23 -0500955 readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400956 {
Jamie Madill437fa652016-05-03 15:13:24 -0400957 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400958 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400959 }
960 }
961
Geoff Lang784a8fd2013-09-24 12:33:16 -0400962 // If width or height is zero, it is a no-op. Return false without setting an error.
963 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400964}
965
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500966bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
967 GLenum target,
968 GLint level,
969 GLenum internalformat,
970 bool isSubImage,
971 GLint xoffset,
972 GLint yoffset,
973 GLint zoffset,
974 GLint x,
975 GLint y,
976 GLsizei width,
977 GLsizei height,
978 GLint border)
979{
980 if (!ValidTexture2DDestinationTarget(context, target))
981 {
Jamie Madill437fa652016-05-03 15:13:24 -0400982 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500983 return false;
984 }
985
986 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
987 xoffset, yoffset, zoffset, x, y, width, height,
988 border);
989}
990
991bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
992 GLenum target,
993 GLint level,
994 GLenum internalformat,
995 bool isSubImage,
996 GLint xoffset,
997 GLint yoffset,
998 GLint zoffset,
999 GLint x,
1000 GLint y,
1001 GLsizei width,
1002 GLsizei height,
1003 GLint border)
1004{
1005 if (!ValidTexture3DDestinationTarget(context, target))
1006 {
Jamie Madill437fa652016-05-03 15:13:24 -04001007 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001008 return false;
1009 }
1010
1011 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
1012 xoffset, yoffset, zoffset, x, y, width, height,
1013 border);
1014}
1015
1016bool ValidateES3TexStorageParametersBase(Context *context,
1017 GLenum target,
1018 GLsizei levels,
1019 GLenum internalformat,
1020 GLsizei width,
1021 GLsizei height,
1022 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001023{
1024 if (width < 1 || height < 1 || depth < 1 || levels < 1)
1025 {
Jamie Madill437fa652016-05-03 15:13:24 -04001026 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001027 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001028 }
1029
Geoff Langb92c1332015-09-04 12:54:55 -04001030 GLsizei maxDim = std::max(width, height);
1031 if (target != GL_TEXTURE_2D_ARRAY)
1032 {
1033 maxDim = std::max(maxDim, depth);
1034 }
1035
1036 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001037 {
Jamie Madill437fa652016-05-03 15:13:24 -04001038 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001039 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001040 }
1041
Geoff Langaae65a42014-05-26 12:43:44 -04001042 const gl::Caps &caps = context->getCaps();
1043
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001044 switch (target)
1045 {
1046 case GL_TEXTURE_2D:
1047 {
Geoff Langaae65a42014-05-26 12:43:44 -04001048 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1049 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001050 {
Jamie Madill437fa652016-05-03 15:13:24 -04001051 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001052 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001053 }
1054 }
1055 break;
1056
Geoff Lang01c21d22013-09-24 11:52:16 -04001057 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001058 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001059 if (width != height)
1060 {
Jamie Madill437fa652016-05-03 15:13:24 -04001061 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001062 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001063 }
1064
Geoff Langaae65a42014-05-26 12:43:44 -04001065 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001066 {
Jamie Madill437fa652016-05-03 15:13:24 -04001067 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001068 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001069 }
1070 }
1071 break;
1072
1073 case GL_TEXTURE_3D:
1074 {
Geoff Langaae65a42014-05-26 12:43:44 -04001075 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
1076 static_cast<GLuint>(height) > caps.max3DTextureSize ||
1077 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001078 {
Jamie Madill437fa652016-05-03 15:13:24 -04001079 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001080 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001081 }
1082 }
1083 break;
1084
1085 case GL_TEXTURE_2D_ARRAY:
1086 {
Geoff Langaae65a42014-05-26 12:43:44 -04001087 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1088 static_cast<GLuint>(height) > caps.max2DTextureSize ||
1089 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001090 {
Jamie Madill437fa652016-05-03 15:13:24 -04001091 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001092 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001093 }
1094 }
1095 break;
1096
1097 default:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001098 UNREACHABLE();
Geoff Langb1196682014-07-23 13:47:29 -04001099 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001100 }
1101
Geoff Lang691e58c2014-12-19 17:03:25 -05001102 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001103 if (!texture || texture->id() == 0)
1104 {
Jamie Madill437fa652016-05-03 15:13:24 -04001105 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001106 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001107 }
1108
Geoff Lang69cce582015-09-17 13:20:36 -04001109 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001110 {
Jamie Madill437fa652016-05-03 15:13:24 -04001111 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001112 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001113 }
1114
Geoff Lang5d601382014-07-22 15:14:06 -04001115 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Martin Radev1be913c2016-07-11 17:59:16 +03001116 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001117 {
Jamie Madill437fa652016-05-03 15:13:24 -04001118 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001119 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001120 }
1121
Geoff Lang5d601382014-07-22 15:14:06 -04001122 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001123 {
Jamie Madill437fa652016-05-03 15:13:24 -04001124 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001125 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001126 }
1127
1128 return true;
1129}
1130
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001131bool ValidateES3TexStorage2DParameters(Context *context,
1132 GLenum target,
1133 GLsizei levels,
1134 GLenum internalformat,
1135 GLsizei width,
1136 GLsizei height,
1137 GLsizei depth)
1138{
1139 if (!ValidTexture2DTarget(context, target))
1140 {
Jamie Madill437fa652016-05-03 15:13:24 -04001141 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001142 return false;
1143 }
1144
1145 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1146 height, depth);
1147}
1148
1149bool ValidateES3TexStorage3DParameters(Context *context,
1150 GLenum target,
1151 GLsizei levels,
1152 GLenum internalformat,
1153 GLsizei width,
1154 GLsizei height,
1155 GLsizei depth)
1156{
1157 if (!ValidTexture3DTarget(context, target))
1158 {
Jamie Madill437fa652016-05-03 15:13:24 -04001159 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001160 return false;
1161 }
1162
1163 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1164 height, depth);
1165}
1166
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001167bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1168{
Martin Radev1be913c2016-07-11 17:59:16 +03001169 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001170 {
Jamie Madill437fa652016-05-03 15:13:24 -04001171 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001172 return false;
1173 }
1174
1175 return ValidateBeginQueryBase(context, target, id);
1176}
1177
1178bool ValidateEndQuery(gl::Context *context, GLenum target)
1179{
Martin Radev1be913c2016-07-11 17:59:16 +03001180 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001181 {
Jamie Madill437fa652016-05-03 15:13:24 -04001182 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001183 return false;
1184 }
1185
1186 return ValidateEndQueryBase(context, target);
1187}
1188
1189bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1190{
Martin Radev1be913c2016-07-11 17:59:16 +03001191 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001192 {
Jamie Madill437fa652016-05-03 15:13:24 -04001193 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001194 return false;
1195 }
1196
1197 return ValidateGetQueryivBase(context, target, pname);
1198}
1199
1200bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1201{
Martin Radev1be913c2016-07-11 17:59:16 +03001202 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001203 {
Jamie Madill437fa652016-05-03 15:13:24 -04001204 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001205 return false;
1206 }
1207
1208 return ValidateGetQueryObjectValueBase(context, id, pname);
1209}
1210
Geoff Langb1196682014-07-23 13:47:29 -04001211bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
Jamie Madill570f7c82014-07-03 10:38:54 -04001212 GLuint texture, GLint level, GLint layer)
1213{
Martin Radev1be913c2016-07-11 17:59:16 +03001214 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001215 {
Jamie Madill437fa652016-05-03 15:13:24 -04001216 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001217 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001218 }
1219
Jamie Madill55ec3b12014-07-03 10:38:57 -04001220 if (layer < 0)
1221 {
Jamie Madill437fa652016-05-03 15:13:24 -04001222 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001223 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001224 }
1225
1226 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1227 {
1228 return false;
1229 }
1230
1231 const gl::Caps &caps = context->getCaps();
1232 if (texture != 0)
1233 {
1234 gl::Texture *tex = context->getTexture(texture);
1235 ASSERT(tex);
1236
1237 switch (tex->getTarget())
1238 {
1239 case GL_TEXTURE_2D_ARRAY:
1240 {
1241 if (level > gl::log2(caps.max2DTextureSize))
1242 {
Jamie Madill437fa652016-05-03 15:13:24 -04001243 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001244 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001245 }
1246
1247 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1248 {
Jamie Madill437fa652016-05-03 15:13:24 -04001249 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001250 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001251 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001252 }
1253 break;
1254
1255 case GL_TEXTURE_3D:
1256 {
1257 if (level > gl::log2(caps.max3DTextureSize))
1258 {
Jamie Madill437fa652016-05-03 15:13:24 -04001259 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001260 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001261 }
1262
1263 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1264 {
Jamie Madill437fa652016-05-03 15:13:24 -04001265 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001266 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001267 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001268 }
1269 break;
1270
1271 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001272 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001273 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001274 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001275
Jamie Madilla3944d42016-07-22 22:13:26 -04001276 const auto &format = tex->getFormat(tex->getTarget(), level);
1277 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001278 {
Jamie Madill437fa652016-05-03 15:13:24 -04001279 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001280 return false;
1281 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001282 }
1283
1284 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001285}
1286
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001287bool ValidES3ReadFormatType(ValidationContext *context,
1288 GLenum internalFormat,
1289 GLenum format,
1290 GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001291{
Geoff Lang5d601382014-07-22 15:14:06 -04001292 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
1293
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001294 switch (format)
1295 {
1296 case GL_RGBA:
1297 switch (type)
1298 {
1299 case GL_UNSIGNED_BYTE:
1300 break;
Vincent Lang25ab4512016-05-13 18:13:59 +02001301 case GL_UNSIGNED_SHORT:
1302 if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
1303 internalFormatInfo.type != GL_UNSIGNED_SHORT)
1304 {
1305 return false;
1306 }
1307 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001308 case GL_UNSIGNED_INT_2_10_10_10_REV:
1309 if (internalFormat != GL_RGB10_A2)
1310 {
1311 return false;
1312 }
1313 break;
Geoff Lang1ec57f82013-10-16 11:43:23 -04001314 case GL_FLOAT:
Geoff Lang5d601382014-07-22 15:14:06 -04001315 if (internalFormatInfo.componentType != GL_FLOAT)
Geoff Lang1ec57f82013-10-16 11:43:23 -04001316 {
1317 return false;
1318 }
1319 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001320 default:
1321 return false;
1322 }
1323 break;
1324 case GL_RGBA_INTEGER:
1325 switch (type)
1326 {
1327 case GL_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001328 if (internalFormatInfo.componentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001329 {
1330 return false;
1331 }
1332 break;
1333 case GL_UNSIGNED_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001334 if (internalFormatInfo.componentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001335 {
1336 return false;
1337 }
1338 break;
1339 default:
1340 return false;
1341 }
1342 break;
1343 case GL_BGRA_EXT:
1344 switch (type)
1345 {
1346 case GL_UNSIGNED_BYTE:
1347 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1348 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1349 break;
1350 default:
1351 return false;
1352 }
1353 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001354 case GL_RG_EXT:
1355 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001356 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001357 {
1358 return false;
1359 }
1360 switch (type)
1361 {
1362 case GL_UNSIGNED_BYTE:
1363 break;
Vincent Lang25ab4512016-05-13 18:13:59 +02001364 case GL_UNSIGNED_SHORT:
1365 if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
1366 internalFormatInfo.type != GL_UNSIGNED_SHORT)
1367 {
1368 return false;
1369 }
1370 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001371 default:
1372 return false;
1373 }
1374 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001375 default:
1376 return false;
1377 }
1378 return true;
1379}
1380
Corentin Walleze0902642014-11-04 12:32:15 -08001381bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
1382 GLenum internalformat, GLsizei width, GLsizei height)
1383{
1384 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
1385 {
1386 return false;
1387 }
1388
1389 //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.
1390 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1391 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
1392 {
Jamie Madill437fa652016-05-03 15:13:24 -04001393 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -08001394 return false;
1395 }
1396
1397 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
1398 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1399 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1400 {
Jamie Madill437fa652016-05-03 15:13:24 -04001401 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001402 Error(GL_INVALID_OPERATION,
1403 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001404 return false;
1405 }
1406
1407 return true;
1408}
1409
Austin Kinross08332632015-05-05 13:35:47 -07001410bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
1411 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001412{
Martin Radev1be913c2016-07-11 17:59:16 +03001413 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001414 {
Jamie Madill437fa652016-05-03 15:13:24 -04001415 context->handleError(
1416 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001417 return false;
1418 }
1419
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001420 bool defaultFramebuffer = false;
1421
1422 switch (target)
1423 {
1424 case GL_DRAW_FRAMEBUFFER:
1425 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001426 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1427 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001428 case GL_READ_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001429 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1430 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001431 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001432 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001433 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001434 }
1435
Austin Kinross08332632015-05-05 13:35:47 -07001436 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001437}
1438
Jamie Madillc29968b2016-01-20 11:17:23 -05001439bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001440{
Martin Radev1be913c2016-07-11 17:59:16 +03001441 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001442 {
Jamie Madill437fa652016-05-03 15:13:24 -04001443 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001444 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001445 }
1446
Jamie Madill51f40ec2016-06-15 14:06:00 -04001447 if (context->getGLState().getDrawFramebuffer()->checkStatus(context->getContextState()) !=
1448 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001449 {
Jamie Madill437fa652016-05-03 15:13:24 -04001450 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001451 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001452 }
1453
1454 return true;
1455}
1456
Olli Etuaho71dfb362016-03-10 14:04:27 +02001457bool ValidateDrawRangeElements(Context *context,
1458 GLenum mode,
1459 GLuint start,
1460 GLuint end,
1461 GLsizei count,
1462 GLenum type,
1463 const GLvoid *indices,
1464 IndexRange *indexRange)
1465{
Martin Radev1be913c2016-07-11 17:59:16 +03001466 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001467 {
Jamie Madill437fa652016-05-03 15:13:24 -04001468 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001469 return false;
1470 }
1471
1472 if (end < start)
1473 {
Jamie Madill437fa652016-05-03 15:13:24 -04001474 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001475 return false;
1476 }
1477
1478 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1479 {
1480 return false;
1481 }
1482
1483 if (indexRange->end > end || indexRange->start < start)
1484 {
1485 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001486 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001487 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1488 return false;
1489 }
1490 return true;
1491}
1492
Geoff Langb1196682014-07-23 13:47:29 -04001493bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001494{
Martin Radev1be913c2016-07-11 17:59:16 +03001495 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001496 {
Jamie Madill437fa652016-05-03 15:13:24 -04001497 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001498 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001499 }
1500
Jamie Madill78f41802014-08-25 15:47:55 -04001501 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001502}
1503
Jamie Madillb885e572015-02-03 16:16:04 -05001504bool ValidateReadBuffer(Context *context, GLenum src)
1505{
Martin Radev1be913c2016-07-11 17:59:16 +03001506 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001507 {
Jamie Madill437fa652016-05-03 15:13:24 -04001508 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001509 return false;
1510 }
1511
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001512 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001513
1514 if (readFBO == nullptr)
1515 {
Jamie Madill437fa652016-05-03 15:13:24 -04001516 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001517 return false;
1518 }
1519
1520 if (src == GL_NONE)
1521 {
1522 return true;
1523 }
1524
Olli Etuaho84c9f592016-03-09 14:37:25 +02001525 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001526 {
Jamie Madill437fa652016-05-03 15:13:24 -04001527 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001528 return false;
1529 }
1530
1531 if (readFBO->id() == 0)
1532 {
1533 if (src != GL_BACK)
1534 {
1535 const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001536 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001537 return false;
1538 }
1539 }
1540 else
1541 {
1542 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1543
1544 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1545 {
1546 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001547 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001548 return false;
1549 }
1550 }
1551
1552 return true;
1553}
1554
Jamie Madill86af3d22015-07-21 15:14:07 -04001555bool ValidateCompressedTexImage3D(Context *context,
1556 GLenum target,
1557 GLint level,
1558 GLenum internalformat,
1559 GLsizei width,
1560 GLsizei height,
1561 GLsizei depth,
1562 GLint border,
1563 GLsizei imageSize,
1564 const GLvoid *data)
1565{
Martin Radev1be913c2016-07-11 17:59:16 +03001566 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001567 {
Jamie Madill437fa652016-05-03 15:13:24 -04001568 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001569 return false;
1570 }
1571
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001572 if (!ValidTextureTarget(context, target))
1573 {
1574 context->handleError(Error(GL_INVALID_ENUM));
1575 return false;
1576 }
1577
Jamie Madille2e406c2016-06-02 13:04:10 -04001578 // Validate image size
1579 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1580 {
1581 context->handleError(Error(GL_INVALID_VALUE));
1582 return false;
1583 }
1584
Jamie Madill86af3d22015-07-21 15:14:07 -04001585 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001586 if (!formatInfo.compressed)
1587 {
1588 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1589 return false;
1590 }
1591
Jamie Madill513558d2016-06-02 13:04:11 -04001592 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001593 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001594 if (blockSizeOrErr.isError())
1595 {
Jamie Madill513558d2016-06-02 13:04:11 -04001596 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001597 return false;
1598 }
1599 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001600 {
Jamie Madill437fa652016-05-03 15:13:24 -04001601 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001602 return false;
1603 }
1604
1605 // 3D texture target validation
1606 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1607 {
Jamie Madill437fa652016-05-03 15:13:24 -04001608 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001609 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1610 return false;
1611 }
1612
1613 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001614 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
1615 0, width, height, depth, border, GL_NONE, GL_NONE, data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001616 {
1617 return false;
1618 }
1619
1620 return true;
1621}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001622
1623bool ValidateBindVertexArray(Context *context, GLuint array)
1624{
Martin Radev1be913c2016-07-11 17:59:16 +03001625 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001626 {
Jamie Madill437fa652016-05-03 15:13:24 -04001627 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001628 return false;
1629 }
1630
1631 return ValidateBindVertexArrayBase(context, array);
1632}
1633
Austin Kinrossbc781f32015-10-26 09:27:38 -07001634bool ValidateIsVertexArray(Context *context)
1635{
Martin Radev1be913c2016-07-11 17:59:16 +03001636 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001637 {
Jamie Madill437fa652016-05-03 15:13:24 -04001638 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001639 return false;
1640 }
1641
1642 return true;
1643}
Geoff Langc5629752015-12-07 16:29:04 -05001644
1645bool ValidateProgramBinary(Context *context,
1646 GLuint program,
1647 GLenum binaryFormat,
1648 const void *binary,
1649 GLint length)
1650{
Martin Radev1be913c2016-07-11 17:59:16 +03001651 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001652 {
Jamie Madill437fa652016-05-03 15:13:24 -04001653 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001654 return false;
1655 }
1656
1657 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1658}
1659
1660bool ValidateGetProgramBinary(Context *context,
1661 GLuint program,
1662 GLsizei bufSize,
1663 GLsizei *length,
1664 GLenum *binaryFormat,
1665 void *binary)
1666{
Martin Radev1be913c2016-07-11 17:59:16 +03001667 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001668 {
Jamie Madill437fa652016-05-03 15:13:24 -04001669 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001670 return false;
1671 }
1672
1673 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1674}
1675
Olli Etuahof0fee072016-03-30 15:11:58 +03001676bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001677{
Martin Radev1be913c2016-07-11 17:59:16 +03001678 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001679 {
Jamie Madill437fa652016-05-03 15:13:24 -04001680 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001681 return false;
1682 }
1683
1684 if (GetValidProgram(context, program) == nullptr)
1685 {
1686 return false;
1687 }
1688
1689 switch (pname)
1690 {
1691 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001692 if (value != GL_FALSE && value != GL_TRUE)
1693 {
Jamie Madill437fa652016-05-03 15:13:24 -04001694 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001695 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1696 return false;
1697 }
Geoff Langc5629752015-12-07 16:29:04 -05001698 break;
1699
1700 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001701 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001702 return false;
1703 }
1704
1705 return true;
1706}
Jamie Madillc29968b2016-01-20 11:17:23 -05001707
1708bool ValidateBlitFramebuffer(Context *context,
1709 GLint srcX0,
1710 GLint srcY0,
1711 GLint srcX1,
1712 GLint srcY1,
1713 GLint dstX0,
1714 GLint dstY0,
1715 GLint dstX1,
1716 GLint dstY1,
1717 GLbitfield mask,
1718 GLenum filter)
1719{
Martin Radev1be913c2016-07-11 17:59:16 +03001720 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001721 {
Jamie Madill437fa652016-05-03 15:13:24 -04001722 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001723 return false;
1724 }
1725
1726 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1727 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001728}
Jamie Madillc29968b2016-01-20 11:17:23 -05001729
1730bool ValidateClearBufferiv(ValidationContext *context,
1731 GLenum buffer,
1732 GLint drawbuffer,
1733 const GLint *value)
1734{
1735 switch (buffer)
1736 {
1737 case GL_COLOR:
1738 if (drawbuffer < 0 ||
1739 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1740 {
Jamie Madill437fa652016-05-03 15:13:24 -04001741 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001742 return false;
1743 }
1744 break;
1745
1746 case GL_STENCIL:
1747 if (drawbuffer != 0)
1748 {
Jamie Madill437fa652016-05-03 15:13:24 -04001749 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001750 return false;
1751 }
1752 break;
1753
1754 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001755 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001756 return false;
1757 }
1758
1759 return ValidateClearBuffer(context);
1760}
1761
1762bool ValidateClearBufferuiv(ValidationContext *context,
1763 GLenum buffer,
1764 GLint drawbuffer,
1765 const GLuint *value)
1766{
1767 switch (buffer)
1768 {
1769 case GL_COLOR:
1770 if (drawbuffer < 0 ||
1771 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1772 {
Jamie Madill437fa652016-05-03 15:13:24 -04001773 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001774 return false;
1775 }
1776 break;
1777
1778 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001779 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001780 return false;
1781 }
1782
1783 return ValidateClearBuffer(context);
1784}
1785
1786bool ValidateClearBufferfv(ValidationContext *context,
1787 GLenum buffer,
1788 GLint drawbuffer,
1789 const GLfloat *value)
1790{
1791 switch (buffer)
1792 {
1793 case GL_COLOR:
1794 if (drawbuffer < 0 ||
1795 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1796 {
Jamie Madill437fa652016-05-03 15:13:24 -04001797 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001798 return false;
1799 }
1800 break;
1801
1802 case GL_DEPTH:
1803 if (drawbuffer != 0)
1804 {
Jamie Madill437fa652016-05-03 15:13:24 -04001805 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001806 return false;
1807 }
1808 break;
1809
1810 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001811 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001812 return false;
1813 }
1814
1815 return ValidateClearBuffer(context);
1816}
1817
1818bool ValidateClearBufferfi(ValidationContext *context,
1819 GLenum buffer,
1820 GLint drawbuffer,
1821 GLfloat depth,
1822 GLint stencil)
1823{
1824 switch (buffer)
1825 {
1826 case GL_DEPTH_STENCIL:
1827 if (drawbuffer != 0)
1828 {
Jamie Madill437fa652016-05-03 15:13:24 -04001829 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001830 return false;
1831 }
1832 break;
1833
1834 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001835 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001836 return false;
1837 }
1838
1839 return ValidateClearBuffer(context);
1840}
1841
1842bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1843{
Martin Radev1be913c2016-07-11 17:59:16 +03001844 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001845 {
Jamie Madill437fa652016-05-03 15:13:24 -04001846 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001847 return false;
1848 }
1849
1850 return ValidateDrawBuffersBase(context, n, bufs);
1851}
1852
1853bool ValidateCopyTexSubImage3D(Context *context,
1854 GLenum target,
1855 GLint level,
1856 GLint xoffset,
1857 GLint yoffset,
1858 GLint zoffset,
1859 GLint x,
1860 GLint y,
1861 GLsizei width,
1862 GLsizei height)
1863{
Martin Radev1be913c2016-07-11 17:59:16 +03001864 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001865 {
Jamie Madill437fa652016-05-03 15:13:24 -04001866 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001867 return false;
1868 }
1869
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001870 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1871 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001872}
1873
Jamie Madill73a84962016-02-12 09:27:23 -05001874bool ValidateTexImage3D(Context *context,
1875 GLenum target,
1876 GLint level,
1877 GLint internalformat,
1878 GLsizei width,
1879 GLsizei height,
1880 GLsizei depth,
1881 GLint border,
1882 GLenum format,
1883 GLenum type,
1884 const GLvoid *pixels)
1885{
Martin Radev1be913c2016-07-11 17:59:16 +03001886 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001887 {
Jamie Madill437fa652016-05-03 15:13:24 -04001888 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001889 return false;
1890 }
1891
1892 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1893 0, 0, width, height, depth, border, format, type,
1894 pixels);
1895}
1896
1897bool ValidateTexSubImage3D(Context *context,
1898 GLenum target,
1899 GLint level,
1900 GLint xoffset,
1901 GLint yoffset,
1902 GLint zoffset,
1903 GLsizei width,
1904 GLsizei height,
1905 GLsizei depth,
1906 GLenum format,
1907 GLenum type,
1908 const GLvoid *pixels)
1909{
Martin Radev1be913c2016-07-11 17:59:16 +03001910 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001911 {
Jamie Madill437fa652016-05-03 15:13:24 -04001912 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001913 return false;
1914 }
1915
1916 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1917 yoffset, zoffset, width, height, depth, 0, format, type,
1918 pixels);
1919}
1920
1921bool ValidateCompressedTexSubImage3D(Context *context,
1922 GLenum target,
1923 GLint level,
1924 GLint xoffset,
1925 GLint yoffset,
1926 GLint zoffset,
1927 GLsizei width,
1928 GLsizei height,
1929 GLsizei depth,
1930 GLenum format,
1931 GLsizei imageSize,
1932 const GLvoid *data)
1933{
Martin Radev1be913c2016-07-11 17:59:16 +03001934 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001935 {
Jamie Madill437fa652016-05-03 15:13:24 -04001936 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001937 return false;
1938 }
1939
1940 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001941 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001942 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001943 if (blockSizeOrErr.isError())
1944 {
1945 context->handleError(blockSizeOrErr.getError());
1946 return false;
1947 }
1948 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001949 {
Jamie Madill437fa652016-05-03 15:13:24 -04001950 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001951 return false;
1952 }
1953
1954 if (!data)
1955 {
Jamie Madill437fa652016-05-03 15:13:24 -04001956 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001957 return false;
1958 }
1959
1960 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
1961 width, height, depth, 0, GL_NONE, GL_NONE, data);
1962}
1963
Olli Etuaho41997e72016-03-10 13:38:39 +02001964bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1965{
1966 return ValidateGenOrDeleteES3(context, n);
1967}
1968
1969bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1970{
1971 return ValidateGenOrDeleteES3(context, n);
1972}
1973
1974bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1975{
1976 return ValidateGenOrDeleteCountES3(context, count);
1977}
1978
1979bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1980{
1981 return ValidateGenOrDeleteCountES3(context, count);
1982}
1983
1984bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1985{
1986 return ValidateGenOrDeleteES3(context, n);
1987}
1988
1989bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1990{
1991 if (!ValidateGenOrDeleteES3(context, n))
1992 {
1993 return false;
1994 }
1995 for (GLint i = 0; i < n; ++i)
1996 {
1997 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1998 if (transformFeedback != nullptr && transformFeedback->isActive())
1999 {
2000 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04002001 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02002002 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
2003 return false;
2004 }
2005 }
2006 return true;
2007}
2008
2009bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2010{
2011 return ValidateGenOrDeleteES3(context, n);
2012}
2013
2014bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2015{
2016 return ValidateGenOrDeleteES3(context, n);
2017}
2018
2019bool ValidateGenOrDeleteES3(Context *context, GLint n)
2020{
Martin Radev1be913c2016-07-11 17:59:16 +03002021 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02002022 {
Jamie Madill437fa652016-05-03 15:13:24 -04002023 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02002024 return false;
2025 }
2026 return ValidateGenOrDelete(context, n);
2027}
2028
2029bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
2030{
Martin Radev1be913c2016-07-11 17:59:16 +03002031 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02002032 {
Jamie Madill437fa652016-05-03 15:13:24 -04002033 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02002034 return false;
2035 }
2036 if (count < 0)
2037 {
Jamie Madill437fa652016-05-03 15:13:24 -04002038 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02002039 return false;
2040 }
2041 return true;
2042}
2043
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002044bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2045{
Martin Radev1be913c2016-07-11 17:59:16 +03002046 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002047 {
Jamie Madill437fa652016-05-03 15:13:24 -04002048 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002049 return false;
2050 }
2051 switch (primitiveMode)
2052 {
2053 case GL_TRIANGLES:
2054 case GL_LINES:
2055 case GL_POINTS:
2056 break;
2057
2058 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002059 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002060 return false;
2061 }
2062
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002063 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002064 ASSERT(transformFeedback != nullptr);
2065
2066 if (transformFeedback->isActive())
2067 {
Jamie Madill437fa652016-05-03 15:13:24 -04002068 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002069 return false;
2070 }
2071 return true;
2072}
2073
Olli Etuaho37477912016-03-30 14:54:40 +03002074bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
2075{
Martin Radev1be913c2016-07-11 17:59:16 +03002076 if (context->getClientMajorVersion() < 3)
Olli Etuaho37477912016-03-30 14:54:40 +03002077 {
Jamie Madill437fa652016-05-03 15:13:24 -04002078 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho37477912016-03-30 14:54:40 +03002079 return false;
2080 }
2081
2082 if (!context->isSampler(sampler))
2083 {
Jamie Madill437fa652016-05-03 15:13:24 -04002084 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho37477912016-03-30 14:54:40 +03002085 return false;
2086 }
2087
2088 if (!ValidateSamplerObjectParameter(context, pname))
2089 {
2090 return false;
2091 }
2092
Ian Ewellbda75592016-04-18 17:25:54 -04002093 if (!ValidateTexParamParameters(context, GL_TEXTURE_2D, pname, param))
Olli Etuaho37477912016-03-30 14:54:40 +03002094 {
2095 return false;
2096 }
2097 return true;
2098}
2099
2100bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
2101{
2102 // The only float parameters are MIN_LOD and MAX_LOD. For these any value is permissible, so
2103 // ValidateSamplerParameteri can be used for validation here.
2104 return ValidateSamplerParameteri(context, sampler, pname, static_cast<GLint>(param));
2105}
2106
Olli Etuaho4f667482016-03-30 15:56:35 +03002107bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
2108{
Martin Radev1be913c2016-07-11 17:59:16 +03002109 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002110 {
Jamie Madill437fa652016-05-03 15:13:24 -04002111 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002112 return false;
2113 }
2114
2115 return ValidateGetBufferPointervBase(context, target, pname, params);
2116}
2117
2118bool ValidateUnmapBuffer(Context *context, GLenum target)
2119{
Martin Radev1be913c2016-07-11 17:59:16 +03002120 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002121 {
Jamie Madill437fa652016-05-03 15:13:24 -04002122 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03002123 return false;
2124 }
2125
2126 return ValidateUnmapBufferBase(context, target);
2127}
2128
2129bool ValidateMapBufferRange(Context *context,
2130 GLenum target,
2131 GLintptr offset,
2132 GLsizeiptr length,
2133 GLbitfield access)
2134{
Martin Radev1be913c2016-07-11 17:59:16 +03002135 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002136 {
Jamie Madill437fa652016-05-03 15:13:24 -04002137 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002138 return false;
2139 }
2140
2141 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2142}
2143
2144bool ValidateFlushMappedBufferRange(Context *context,
2145 GLenum target,
2146 GLintptr offset,
2147 GLsizeiptr length)
2148{
Martin Radev1be913c2016-07-11 17:59:16 +03002149 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002150 {
Jamie Madill437fa652016-05-03 15:13:24 -04002151 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002152 return false;
2153 }
2154
2155 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2156}
2157
Jamie Madillc29968b2016-01-20 11:17:23 -05002158} // namespace gl