blob: aab10df26e3bae2b5185d09aec29215c1dd5e449 [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
Geoff Langa9be0dc2014-12-17 12:34:40 -0500390 GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat;
Geoff Lang5d601382014-07-22 15:14:06 -0400391 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400392 if (isCompressed)
393 {
tmartino7c102692015-10-02 16:43:40 -0400394 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400395 {
Jamie Madill437fa652016-05-03 15:13:24 -0400396 context->handleError(Error(
tmartino7c102692015-10-02 16:43:40 -0400397 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format."));
Geoff Langb1196682014-07-23 13:47:29 -0400398 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400399 }
400
tmartino7c102692015-10-02 16:43:40 -0400401 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400402 {
Jamie Madill437fa652016-05-03 15:13:24 -0400403 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400404 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400405 }
406
Martin Radev1be913c2016-07-11 17:59:16 +0300407 if (!actualFormatInfo.textureSupport(context->getClientMajorVersion(),
408 context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400409 {
Jamie Madill437fa652016-05-03 15:13:24 -0400410 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang839ce0b2015-10-23 13:13:12 -0400411 return false;
412 }
413
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400414 if (target == GL_TEXTURE_3D)
415 {
Jamie Madill437fa652016-05-03 15:13:24 -0400416 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400417 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400418 }
419 }
420 else
421 {
Geoff Langbaadf232014-08-04 13:58:02 -0400422 if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400423 {
Geoff Lang5d601382014-07-22 15:14:06 -0400424 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400425 }
426
427 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
428 {
Jamie Madill437fa652016-05-03 15:13:24 -0400429 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400430 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400431 }
432 }
433
434 // Validate sub image parameters
435 if (isSubImage)
436 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500437 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400438 {
Jamie Madill437fa652016-05-03 15:13:24 -0400439 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400440 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400441 }
442
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400443 if (width == 0 || height == 0 || depth == 0)
444 {
445 return false;
446 }
447
448 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
449 {
Jamie Madill437fa652016-05-03 15:13:24 -0400450 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400451 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400452 }
453
454 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
455 std::numeric_limits<GLsizei>::max() - yoffset < height ||
456 std::numeric_limits<GLsizei>::max() - zoffset < depth)
457 {
Jamie Madill437fa652016-05-03 15:13:24 -0400458 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400459 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400460 }
461
Geoff Langa9be0dc2014-12-17 12:34:40 -0500462 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
463 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
464 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400465 {
Jamie Madill437fa652016-05-03 15:13:24 -0400466 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400467 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400468 }
469 }
470
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400471 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700472 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400473 if (pixelUnpackBuffer != NULL)
474 {
475 // ...the data would be unpacked from the buffer object such that the memory reads required
476 // would exceed the data store size.
Geoff Lang5d601382014-07-22 15:14:06 -0400477 GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400478 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -0700479 const gl::Extents size(width, height, depth);
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700480 const auto &unpack = context->getGLState().getUnpackState();
Jamie Madill4b4cdff2016-06-06 13:53:38 -0700481
482 auto copyBytesOrErr = formatInfo.computeUnpackSize(type, size, unpack);
Jamie Madille2e406c2016-06-02 13:04:10 -0400483 if (copyBytesOrErr.isError())
484 {
485 context->handleError(copyBytesOrErr.getError());
486 return false;
487 }
488 CheckedNumeric<size_t> checkedCopyBytes(copyBytesOrErr.getResult());
489 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
490 checkedCopyBytes += checkedOffset;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400491
Olli Etuaho989cac32016-06-08 16:18:49 -0700492 auto rowPitchOrErr =
493 formatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength);
494 if (rowPitchOrErr.isError())
495 {
496 context->handleError(rowPitchOrErr.getError());
497 return false;
498 }
499 auto depthPitchOrErr = formatInfo.computeDepthPitch(type, width, height, unpack.alignment,
500 unpack.rowLength, unpack.imageHeight);
501 if (depthPitchOrErr.isError())
502 {
503 context->handleError(depthPitchOrErr.getError());
504 return false;
505 }
506
507 bool targetIs3D = target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY;
508 auto skipBytesOrErr = formatInfo.computeSkipBytes(
509 rowPitchOrErr.getResult(), depthPitchOrErr.getResult(), unpack.skipImages,
510 unpack.skipRows, unpack.skipPixels, targetIs3D);
511 if (skipBytesOrErr.isError())
512 {
513 context->handleError(skipBytesOrErr.getError());
514 return false;
515 }
516 checkedCopyBytes += skipBytesOrErr.getResult();
517
Jamie Madille2e406c2016-06-02 13:04:10 -0400518 if (!checkedCopyBytes.IsValid() ||
519 (checkedCopyBytes.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400520 {
521 // Overflow past the end of the buffer
Jamie Madill437fa652016-05-03 15:13:24 -0400522 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400523 return false;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400524 }
525
526 // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
527 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400528 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400529 {
Jamie Madillc751d1e2014-10-21 17:46:29 -0400530 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
531
Jamie Madille2e406c2016-06-02 13:04:10 -0400532 if ((checkedOffset.ValueOrDie() % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400533 {
Jamie Madill437fa652016-05-03 15:13:24 -0400534 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400535 return false;
536 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400537 }
538
Jamie Madill7a5f7382014-03-05 15:01:24 -0500539 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700540 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500541 {
Jamie Madill437fa652016-05-03 15:13:24 -0400542 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400543 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500544 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400545 }
546
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400547 return true;
548}
549
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500550bool ValidateES3TexImage2DParameters(Context *context,
551 GLenum target,
552 GLint level,
553 GLenum internalformat,
554 bool isCompressed,
555 bool isSubImage,
556 GLint xoffset,
557 GLint yoffset,
558 GLint zoffset,
559 GLsizei width,
560 GLsizei height,
561 GLsizei depth,
562 GLint border,
563 GLenum format,
564 GLenum type,
565 const GLvoid *pixels)
566{
567 if (!ValidTexture2DDestinationTarget(context, target))
568 {
Jamie Madill437fa652016-05-03 15:13:24 -0400569 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500570 return false;
571 }
572
573 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
574 isSubImage, xoffset, yoffset, zoffset, width, height,
575 depth, border, format, type, pixels);
576}
577
578bool ValidateES3TexImage3DParameters(Context *context,
579 GLenum target,
580 GLint level,
581 GLenum internalformat,
582 bool isCompressed,
583 bool isSubImage,
584 GLint xoffset,
585 GLint yoffset,
586 GLint zoffset,
587 GLsizei width,
588 GLsizei height,
589 GLsizei depth,
590 GLint border,
591 GLenum format,
592 GLenum type,
593 const GLvoid *pixels)
594{
595 if (!ValidTexture3DDestinationTarget(context, target))
596 {
Jamie Madill437fa652016-05-03 15:13:24 -0400597 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500598 return false;
599 }
600
601 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
602 isSubImage, xoffset, yoffset, zoffset, width, height,
603 depth, border, format, type, pixels);
604}
605
Geoff Lang5d601382014-07-22 15:14:06 -0400606struct EffectiveInternalFormatInfo
607{
608 GLenum mEffectiveFormat;
609 GLenum mDestFormat;
610 GLuint mMinRedBits;
611 GLuint mMaxRedBits;
612 GLuint mMinGreenBits;
613 GLuint mMaxGreenBits;
614 GLuint mMinBlueBits;
615 GLuint mMaxBlueBits;
616 GLuint mMinAlphaBits;
617 GLuint mMaxAlphaBits;
618
619 EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits,
620 GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits,
621 GLuint minAlphaBits, GLuint maxAlphaBits)
622 : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits),
623 mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits),
624 mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits),
625 mMaxAlphaBits(maxAlphaBits) {};
626};
627
628typedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
629
630static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList()
631{
632 EffectiveInternalFormatList list;
633
634 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
635 // linear source buffer component sizes.
636 // | Source channel min/max sizes |
637 // Effective Internal Format | N/A | R | G | B | A |
638 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8));
639 list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0));
640 list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0));
641 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0));
642 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0));
643 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4));
644 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1));
645 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8));
646 list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2));
647
648 return list;
649}
650
651static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList()
652{
653 EffectiveInternalFormatList list;
654
655 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
656 // linear source buffer component sizes.
657 // | Source channel min/max sizes |
658 // Effective Internal Format | Dest Format | R | G | B | A |
659 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
660 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX));
661 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
662 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX));
663 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX));
664 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4));
665 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1));
666 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8));
667
668 return list;
669}
670
671static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
672 GLenum *outEffectiveFormat)
673{
674 const EffectiveInternalFormatList *list = NULL;
675 GLenum targetFormat = GL_NONE;
676
677 if (destFormat.pixelBytes > 0)
678 {
679 static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList();
680 list = &sizedList;
681 }
682 else
683 {
684 static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList();
685 list = &unsizedList;
686 targetFormat = destFormat.format;
687 }
688
689 for (size_t curFormat = 0; curFormat < list->size(); ++curFormat)
690 {
691 const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat);
692 if ((formatInfo.mDestFormat == targetFormat) &&
693 (formatInfo.mMinRedBits <= srcFormat.redBits && formatInfo.mMaxRedBits >= srcFormat.redBits) &&
694 (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) &&
695 (formatInfo.mMinBlueBits <= srcFormat.blueBits && formatInfo.mMaxBlueBits >= srcFormat.blueBits) &&
696 (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits))
697 {
698 *outEffectiveFormat = formatInfo.mEffectiveFormat;
699 return true;
700 }
701 }
702
703 return false;
704}
705
706struct CopyConversion
707{
708 GLenum mTextureFormat;
709 GLenum mFramebufferFormat;
710
711 CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
712 : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
713
714 bool operator<(const CopyConversion& other) const
715 {
716 return memcmp(this, &other, sizeof(CopyConversion)) < 0;
717 }
718};
719
720typedef std::set<CopyConversion> CopyConversionSet;
721
722static CopyConversionSet BuildValidES3CopyTexImageCombinations()
723{
724 CopyConversionSet set;
725
726 // From ES 3.0.1 spec, table 3.15
727 set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
728 set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
729 set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
730 set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
731 set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
732 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
733 set.insert(CopyConversion(GL_RED, GL_RED));
734 set.insert(CopyConversion(GL_RED, GL_RG));
735 set.insert(CopyConversion(GL_RED, GL_RGB));
736 set.insert(CopyConversion(GL_RED, GL_RGBA));
737 set.insert(CopyConversion(GL_RG, GL_RG));
738 set.insert(CopyConversion(GL_RG, GL_RGB));
739 set.insert(CopyConversion(GL_RG, GL_RGBA));
740 set.insert(CopyConversion(GL_RGB, GL_RGB));
741 set.insert(CopyConversion(GL_RGB, GL_RGBA));
742 set.insert(CopyConversion(GL_RGBA, GL_RGBA));
743
744 // Necessary for ANGLE back-buffers
745 set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
746 set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
747 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
748 set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
749 set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
750 set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
751 set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
752
753 set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
754 set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
755 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
756 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
757 set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
758 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
759 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
760 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
761 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
762 set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
763
764 return set;
765}
766
Corentin Wallez76287682016-04-25 09:23:38 -0400767static bool EqualOrFirstZero(GLuint first, GLuint second)
768{
769 return first == 0 || first == second;
770}
771
Geoff Lang5d601382014-07-22 15:14:06 -0400772static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle)
773{
774 const InternalFormat &textureInternalFormatInfo = GetInternalFormatInfo(textureInternalFormat);
775 const InternalFormat &framebufferInternalFormatInfo = GetInternalFormatInfo(frameBufferInternalFormat);
776
777 static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
778 if (conversionSet.find(CopyConversion(textureInternalFormatInfo.format, framebufferInternalFormatInfo.format)) != conversionSet.end())
779 {
780 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
781 // must both be signed, unsigned, or fixed point and both source and destinations
782 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
783 // conversion between fixed and floating point.
784
785 if ((textureInternalFormatInfo.colorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.colorEncoding == GL_SRGB))
786 {
787 return false;
788 }
789
790 if (((textureInternalFormatInfo.componentType == GL_INT) != (framebufferInternalFormatInfo.componentType == GL_INT )) ||
791 ((textureInternalFormatInfo.componentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.componentType == GL_UNSIGNED_INT)))
792 {
793 return false;
794 }
795
796 if ((textureInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
797 textureInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
798 textureInternalFormatInfo.componentType == GL_FLOAT) &&
799 !(framebufferInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
800 framebufferInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
801 framebufferInternalFormatInfo.componentType == GL_FLOAT))
802 {
803 return false;
804 }
805
806 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
807 // The effective internal format of the source buffer is determined with the following rules applied in order:
808 // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
809 // effective internal format is the source buffer's sized internal format.
810 // * If the source buffer is a texture that was created with an unsized base internal format, then the
811 // effective internal format is the source image array's effective internal format, as specified by table
812 // 3.12, which is determined from the <format> and <type> that were used when the source image array was
813 // specified by TexImage*.
814 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
815 // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
816 // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
817 // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
818 // is SRGB.
819 const InternalFormat *sourceEffectiveFormat = NULL;
820 if (readBufferHandle != 0)
821 {
822 // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
823 if (framebufferInternalFormatInfo.pixelBytes > 0)
824 {
825 sourceEffectiveFormat = &framebufferInternalFormatInfo;
826 }
827 else
828 {
829 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
830 // 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 -0500831 GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type);
832 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400833 }
834 }
835 else
836 {
837 // The effective internal format must be derived from the source framebuffer's channel sizes.
838 // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
839 if (framebufferInternalFormatInfo.colorEncoding == GL_LINEAR)
840 {
841 GLenum effectiveFormat;
842 if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat))
843 {
844 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
845 }
846 else
847 {
848 return false;
849 }
850 }
851 else if (framebufferInternalFormatInfo.colorEncoding == GL_SRGB)
852 {
853 // SRGB buffers can only be copied to sized format destinations according to table 3.18
854 if ((textureInternalFormatInfo.pixelBytes > 0) &&
855 (framebufferInternalFormatInfo.redBits >= 1 && framebufferInternalFormatInfo.redBits <= 8) &&
856 (framebufferInternalFormatInfo.greenBits >= 1 && framebufferInternalFormatInfo.greenBits <= 8) &&
857 (framebufferInternalFormatInfo.blueBits >= 1 && framebufferInternalFormatInfo.blueBits <= 8) &&
858 (framebufferInternalFormatInfo.alphaBits >= 1 && framebufferInternalFormatInfo.alphaBits <= 8))
859 {
860 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
861 }
862 else
863 {
864 return false;
865 }
866 }
867 else
868 {
869 UNREACHABLE();
870 return false;
871 }
872 }
873
874 if (textureInternalFormatInfo.pixelBytes > 0)
875 {
Corentin Wallez76287682016-04-25 09:23:38 -0400876 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination
877 // format is sized, component sizes of the source and destination formats must exactly
878 // match if the destination format exists.
879 if (!EqualOrFirstZero(textureInternalFormatInfo.redBits,
880 sourceEffectiveFormat->redBits) ||
881 !EqualOrFirstZero(textureInternalFormatInfo.greenBits,
882 sourceEffectiveFormat->greenBits) ||
883 !EqualOrFirstZero(textureInternalFormatInfo.blueBits,
884 sourceEffectiveFormat->blueBits) ||
885 !EqualOrFirstZero(textureInternalFormatInfo.alphaBits,
886 sourceEffectiveFormat->alphaBits))
Geoff Lang5d601382014-07-22 15:14:06 -0400887 {
888 return false;
889 }
890 }
891
892
893 return true; // A conversion function exists, and no rule in the specification has precluded conversion
894 // between these formats.
895 }
896
897 return false;
898}
899
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500900bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
901 GLenum target,
902 GLint level,
903 GLenum internalformat,
904 bool isSubImage,
905 GLint xoffset,
906 GLint yoffset,
907 GLint zoffset,
908 GLint x,
909 GLint y,
910 GLsizei width,
911 GLsizei height,
912 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400913{
Jamie Madill560a8d82014-05-21 13:06:20 -0400914 GLenum textureInternalFormat;
915 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill6f38f822014-06-06 17:12:20 -0400916 xoffset, yoffset, zoffset, x, y, width, height,
917 border, &textureInternalFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400918 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400919 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400920 }
921
Jamie Madill51f40ec2016-06-15 14:06:00 -0400922 const auto &state = context->getGLState();
923 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
924 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400925
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700926 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400927 {
Jamie Madill437fa652016-05-03 15:13:24 -0400928 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400929 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400930 }
931
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700932 if (readFramebufferID != 0 && framebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400933 {
Jamie Madill437fa652016-05-03 15:13:24 -0400934 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400935 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400936 }
937
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400938 const gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400939 GLenum colorbufferInternalFormat = source->getInternalFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400940
941 if (isSubImage)
942 {
Geoff Lang5d601382014-07-22 15:14:06 -0400943 if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat,
Jamie Madillc29968b2016-01-20 11:17:23 -0500944 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400945 {
Jamie Madill437fa652016-05-03 15:13:24 -0400946 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400947 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400948 }
949 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400950 else
951 {
Geoff Lang5d601382014-07-22 15:14:06 -0400952 if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat,
Jamie Madillc29968b2016-01-20 11:17:23 -0500953 readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400954 {
Jamie Madill437fa652016-05-03 15:13:24 -0400955 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400956 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400957 }
958 }
959
Geoff Lang784a8fd2013-09-24 12:33:16 -0400960 // If width or height is zero, it is a no-op. Return false without setting an error.
961 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400962}
963
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500964bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
965 GLenum target,
966 GLint level,
967 GLenum internalformat,
968 bool isSubImage,
969 GLint xoffset,
970 GLint yoffset,
971 GLint zoffset,
972 GLint x,
973 GLint y,
974 GLsizei width,
975 GLsizei height,
976 GLint border)
977{
978 if (!ValidTexture2DDestinationTarget(context, target))
979 {
Jamie Madill437fa652016-05-03 15:13:24 -0400980 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500981 return false;
982 }
983
984 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
985 xoffset, yoffset, zoffset, x, y, width, height,
986 border);
987}
988
989bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
990 GLenum target,
991 GLint level,
992 GLenum internalformat,
993 bool isSubImage,
994 GLint xoffset,
995 GLint yoffset,
996 GLint zoffset,
997 GLint x,
998 GLint y,
999 GLsizei width,
1000 GLsizei height,
1001 GLint border)
1002{
1003 if (!ValidTexture3DDestinationTarget(context, target))
1004 {
Jamie Madill437fa652016-05-03 15:13:24 -04001005 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001006 return false;
1007 }
1008
1009 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
1010 xoffset, yoffset, zoffset, x, y, width, height,
1011 border);
1012}
1013
1014bool ValidateES3TexStorageParametersBase(Context *context,
1015 GLenum target,
1016 GLsizei levels,
1017 GLenum internalformat,
1018 GLsizei width,
1019 GLsizei height,
1020 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001021{
1022 if (width < 1 || height < 1 || depth < 1 || levels < 1)
1023 {
Jamie Madill437fa652016-05-03 15:13:24 -04001024 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001025 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001026 }
1027
Geoff Langb92c1332015-09-04 12:54:55 -04001028 GLsizei maxDim = std::max(width, height);
1029 if (target != GL_TEXTURE_2D_ARRAY)
1030 {
1031 maxDim = std::max(maxDim, depth);
1032 }
1033
1034 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001035 {
Jamie Madill437fa652016-05-03 15:13:24 -04001036 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001037 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001038 }
1039
Geoff Langaae65a42014-05-26 12:43:44 -04001040 const gl::Caps &caps = context->getCaps();
1041
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001042 switch (target)
1043 {
1044 case GL_TEXTURE_2D:
1045 {
Geoff Langaae65a42014-05-26 12:43:44 -04001046 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1047 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001048 {
Jamie Madill437fa652016-05-03 15:13:24 -04001049 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001050 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001051 }
1052 }
1053 break;
1054
Geoff Lang01c21d22013-09-24 11:52:16 -04001055 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001056 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001057 if (width != height)
1058 {
Jamie Madill437fa652016-05-03 15:13:24 -04001059 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001060 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001061 }
1062
Geoff Langaae65a42014-05-26 12:43:44 -04001063 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001064 {
Jamie Madill437fa652016-05-03 15:13:24 -04001065 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001066 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001067 }
1068 }
1069 break;
1070
1071 case GL_TEXTURE_3D:
1072 {
Geoff Langaae65a42014-05-26 12:43:44 -04001073 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
1074 static_cast<GLuint>(height) > caps.max3DTextureSize ||
1075 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001076 {
Jamie Madill437fa652016-05-03 15:13:24 -04001077 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001078 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001079 }
1080 }
1081 break;
1082
1083 case GL_TEXTURE_2D_ARRAY:
1084 {
Geoff Langaae65a42014-05-26 12:43:44 -04001085 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1086 static_cast<GLuint>(height) > caps.max2DTextureSize ||
1087 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001088 {
Jamie Madill437fa652016-05-03 15:13:24 -04001089 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001090 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001091 }
1092 }
1093 break;
1094
1095 default:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001096 UNREACHABLE();
Geoff Langb1196682014-07-23 13:47:29 -04001097 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001098 }
1099
Geoff Lang691e58c2014-12-19 17:03:25 -05001100 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001101 if (!texture || texture->id() == 0)
1102 {
Jamie Madill437fa652016-05-03 15:13:24 -04001103 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001104 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001105 }
1106
Geoff Lang69cce582015-09-17 13:20:36 -04001107 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001108 {
Jamie Madill437fa652016-05-03 15:13:24 -04001109 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001110 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001111 }
1112
Geoff Lang5d601382014-07-22 15:14:06 -04001113 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Martin Radev1be913c2016-07-11 17:59:16 +03001114 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001115 {
Jamie Madill437fa652016-05-03 15:13:24 -04001116 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001117 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001118 }
1119
Geoff Lang5d601382014-07-22 15:14:06 -04001120 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001121 {
Jamie Madill437fa652016-05-03 15:13:24 -04001122 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001123 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001124 }
1125
1126 return true;
1127}
1128
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001129bool ValidateES3TexStorage2DParameters(Context *context,
1130 GLenum target,
1131 GLsizei levels,
1132 GLenum internalformat,
1133 GLsizei width,
1134 GLsizei height,
1135 GLsizei depth)
1136{
1137 if (!ValidTexture2DTarget(context, target))
1138 {
Jamie Madill437fa652016-05-03 15:13:24 -04001139 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001140 return false;
1141 }
1142
1143 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1144 height, depth);
1145}
1146
1147bool ValidateES3TexStorage3DParameters(Context *context,
1148 GLenum target,
1149 GLsizei levels,
1150 GLenum internalformat,
1151 GLsizei width,
1152 GLsizei height,
1153 GLsizei depth)
1154{
1155 if (!ValidTexture3DTarget(context, target))
1156 {
Jamie Madill437fa652016-05-03 15:13:24 -04001157 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001158 return false;
1159 }
1160
1161 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1162 height, depth);
1163}
1164
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001165bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1166{
Martin Radev1be913c2016-07-11 17:59:16 +03001167 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001168 {
Jamie Madill437fa652016-05-03 15:13:24 -04001169 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001170 return false;
1171 }
1172
1173 return ValidateBeginQueryBase(context, target, id);
1174}
1175
1176bool ValidateEndQuery(gl::Context *context, GLenum target)
1177{
Martin Radev1be913c2016-07-11 17:59:16 +03001178 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001179 {
Jamie Madill437fa652016-05-03 15:13:24 -04001180 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001181 return false;
1182 }
1183
1184 return ValidateEndQueryBase(context, target);
1185}
1186
1187bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1188{
Martin Radev1be913c2016-07-11 17:59:16 +03001189 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001190 {
Jamie Madill437fa652016-05-03 15:13:24 -04001191 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001192 return false;
1193 }
1194
1195 return ValidateGetQueryivBase(context, target, pname);
1196}
1197
1198bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1199{
Martin Radev1be913c2016-07-11 17:59:16 +03001200 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001201 {
Jamie Madill437fa652016-05-03 15:13:24 -04001202 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001203 return false;
1204 }
1205
1206 return ValidateGetQueryObjectValueBase(context, id, pname);
1207}
1208
Geoff Langb1196682014-07-23 13:47:29 -04001209bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
Jamie Madill570f7c82014-07-03 10:38:54 -04001210 GLuint texture, GLint level, GLint layer)
1211{
Martin Radev1be913c2016-07-11 17:59:16 +03001212 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001213 {
Jamie Madill437fa652016-05-03 15:13:24 -04001214 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001215 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001216 }
1217
Jamie Madill55ec3b12014-07-03 10:38:57 -04001218 if (layer < 0)
1219 {
Jamie Madill437fa652016-05-03 15:13:24 -04001220 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001221 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001222 }
1223
1224 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1225 {
1226 return false;
1227 }
1228
1229 const gl::Caps &caps = context->getCaps();
1230 if (texture != 0)
1231 {
1232 gl::Texture *tex = context->getTexture(texture);
1233 ASSERT(tex);
1234
1235 switch (tex->getTarget())
1236 {
1237 case GL_TEXTURE_2D_ARRAY:
1238 {
1239 if (level > gl::log2(caps.max2DTextureSize))
1240 {
Jamie Madill437fa652016-05-03 15:13:24 -04001241 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001242 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001243 }
1244
1245 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1246 {
Jamie Madill437fa652016-05-03 15:13:24 -04001247 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001248 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001249 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001250 }
1251 break;
1252
1253 case GL_TEXTURE_3D:
1254 {
1255 if (level > gl::log2(caps.max3DTextureSize))
1256 {
Jamie Madill437fa652016-05-03 15:13:24 -04001257 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001258 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001259 }
1260
1261 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1262 {
Jamie Madill437fa652016-05-03 15:13:24 -04001263 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001264 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001265 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001266 }
1267 break;
1268
1269 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001270 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001271 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001272 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001273
1274 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(tex->getTarget(), level));
1275 if (internalFormatInfo.compressed)
1276 {
Jamie Madill437fa652016-05-03 15:13:24 -04001277 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001278 return false;
1279 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001280 }
1281
1282 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001283}
1284
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001285bool ValidES3ReadFormatType(ValidationContext *context,
1286 GLenum internalFormat,
1287 GLenum format,
1288 GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001289{
Geoff Lang5d601382014-07-22 15:14:06 -04001290 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
1291
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001292 switch (format)
1293 {
1294 case GL_RGBA:
1295 switch (type)
1296 {
1297 case GL_UNSIGNED_BYTE:
1298 break;
Vincent Lang25ab4512016-05-13 18:13:59 +02001299 case GL_UNSIGNED_SHORT:
1300 if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
1301 internalFormatInfo.type != GL_UNSIGNED_SHORT)
1302 {
1303 return false;
1304 }
1305 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001306 case GL_UNSIGNED_INT_2_10_10_10_REV:
1307 if (internalFormat != GL_RGB10_A2)
1308 {
1309 return false;
1310 }
1311 break;
Geoff Lang1ec57f82013-10-16 11:43:23 -04001312 case GL_FLOAT:
Geoff Lang5d601382014-07-22 15:14:06 -04001313 if (internalFormatInfo.componentType != GL_FLOAT)
Geoff Lang1ec57f82013-10-16 11:43:23 -04001314 {
1315 return false;
1316 }
1317 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001318 default:
1319 return false;
1320 }
1321 break;
1322 case GL_RGBA_INTEGER:
1323 switch (type)
1324 {
1325 case GL_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001326 if (internalFormatInfo.componentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001327 {
1328 return false;
1329 }
1330 break;
1331 case GL_UNSIGNED_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001332 if (internalFormatInfo.componentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001333 {
1334 return false;
1335 }
1336 break;
1337 default:
1338 return false;
1339 }
1340 break;
1341 case GL_BGRA_EXT:
1342 switch (type)
1343 {
1344 case GL_UNSIGNED_BYTE:
1345 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1346 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1347 break;
1348 default:
1349 return false;
1350 }
1351 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001352 case GL_RG_EXT:
1353 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001354 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001355 {
1356 return false;
1357 }
1358 switch (type)
1359 {
1360 case GL_UNSIGNED_BYTE:
1361 break;
Vincent Lang25ab4512016-05-13 18:13:59 +02001362 case GL_UNSIGNED_SHORT:
1363 if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
1364 internalFormatInfo.type != GL_UNSIGNED_SHORT)
1365 {
1366 return false;
1367 }
1368 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001369 default:
1370 return false;
1371 }
1372 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001373 default:
1374 return false;
1375 }
1376 return true;
1377}
1378
Corentin Walleze0902642014-11-04 12:32:15 -08001379bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
1380 GLenum internalformat, GLsizei width, GLsizei height)
1381{
1382 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
1383 {
1384 return false;
1385 }
1386
1387 //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.
1388 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1389 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
1390 {
Jamie Madill437fa652016-05-03 15:13:24 -04001391 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -08001392 return false;
1393 }
1394
1395 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
1396 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1397 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1398 {
Jamie Madill437fa652016-05-03 15:13:24 -04001399 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001400 Error(GL_INVALID_OPERATION,
1401 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001402 return false;
1403 }
1404
1405 return true;
1406}
1407
Austin Kinross08332632015-05-05 13:35:47 -07001408bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
1409 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001410{
Martin Radev1be913c2016-07-11 17:59:16 +03001411 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001412 {
Jamie Madill437fa652016-05-03 15:13:24 -04001413 context->handleError(
1414 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001415 return false;
1416 }
1417
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001418 bool defaultFramebuffer = false;
1419
1420 switch (target)
1421 {
1422 case GL_DRAW_FRAMEBUFFER:
1423 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001424 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1425 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001426 case GL_READ_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001427 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1428 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001429 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001430 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001431 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001432 }
1433
Austin Kinross08332632015-05-05 13:35:47 -07001434 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001435}
1436
Jamie Madillc29968b2016-01-20 11:17:23 -05001437bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001438{
Martin Radev1be913c2016-07-11 17:59:16 +03001439 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001440 {
Jamie Madill437fa652016-05-03 15:13:24 -04001441 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001442 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001443 }
1444
Jamie Madill51f40ec2016-06-15 14:06:00 -04001445 if (context->getGLState().getDrawFramebuffer()->checkStatus(context->getContextState()) !=
1446 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001447 {
Jamie Madill437fa652016-05-03 15:13:24 -04001448 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001449 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001450 }
1451
1452 return true;
1453}
1454
Olli Etuaho71dfb362016-03-10 14:04:27 +02001455bool ValidateDrawRangeElements(Context *context,
1456 GLenum mode,
1457 GLuint start,
1458 GLuint end,
1459 GLsizei count,
1460 GLenum type,
1461 const GLvoid *indices,
1462 IndexRange *indexRange)
1463{
Martin Radev1be913c2016-07-11 17:59:16 +03001464 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001465 {
Jamie Madill437fa652016-05-03 15:13:24 -04001466 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001467 return false;
1468 }
1469
1470 if (end < start)
1471 {
Jamie Madill437fa652016-05-03 15:13:24 -04001472 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001473 return false;
1474 }
1475
1476 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1477 {
1478 return false;
1479 }
1480
1481 if (indexRange->end > end || indexRange->start < start)
1482 {
1483 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001484 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001485 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1486 return false;
1487 }
1488 return true;
1489}
1490
Geoff Langb1196682014-07-23 13:47:29 -04001491bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001492{
Martin Radev1be913c2016-07-11 17:59:16 +03001493 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001494 {
Jamie Madill437fa652016-05-03 15:13:24 -04001495 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001496 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001497 }
1498
Jamie Madill78f41802014-08-25 15:47:55 -04001499 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001500}
1501
Jamie Madillb885e572015-02-03 16:16:04 -05001502bool ValidateReadBuffer(Context *context, GLenum src)
1503{
Martin Radev1be913c2016-07-11 17:59:16 +03001504 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001505 {
Jamie Madill437fa652016-05-03 15:13:24 -04001506 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001507 return false;
1508 }
1509
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001510 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001511
1512 if (readFBO == nullptr)
1513 {
Jamie Madill437fa652016-05-03 15:13:24 -04001514 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001515 return false;
1516 }
1517
1518 if (src == GL_NONE)
1519 {
1520 return true;
1521 }
1522
Olli Etuaho84c9f592016-03-09 14:37:25 +02001523 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001524 {
Jamie Madill437fa652016-05-03 15:13:24 -04001525 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001526 return false;
1527 }
1528
1529 if (readFBO->id() == 0)
1530 {
1531 if (src != GL_BACK)
1532 {
1533 const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001534 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001535 return false;
1536 }
1537 }
1538 else
1539 {
1540 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1541
1542 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1543 {
1544 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001545 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001546 return false;
1547 }
1548 }
1549
1550 return true;
1551}
1552
Jamie Madill86af3d22015-07-21 15:14:07 -04001553bool ValidateCompressedTexImage3D(Context *context,
1554 GLenum target,
1555 GLint level,
1556 GLenum internalformat,
1557 GLsizei width,
1558 GLsizei height,
1559 GLsizei depth,
1560 GLint border,
1561 GLsizei imageSize,
1562 const GLvoid *data)
1563{
Martin Radev1be913c2016-07-11 17:59:16 +03001564 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001565 {
Jamie Madill437fa652016-05-03 15:13:24 -04001566 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001567 return false;
1568 }
1569
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001570 if (!ValidTextureTarget(context, target))
1571 {
1572 context->handleError(Error(GL_INVALID_ENUM));
1573 return false;
1574 }
1575
Jamie Madille2e406c2016-06-02 13:04:10 -04001576 // Validate image size
1577 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1578 {
1579 context->handleError(Error(GL_INVALID_VALUE));
1580 return false;
1581 }
1582
Jamie Madill86af3d22015-07-21 15:14:07 -04001583 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001584 if (!formatInfo.compressed)
1585 {
1586 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1587 return false;
1588 }
1589
Jamie Madill513558d2016-06-02 13:04:11 -04001590 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001591 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001592 if (blockSizeOrErr.isError())
1593 {
Jamie Madill513558d2016-06-02 13:04:11 -04001594 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001595 return false;
1596 }
1597 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001598 {
Jamie Madill437fa652016-05-03 15:13:24 -04001599 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001600 return false;
1601 }
1602
1603 // 3D texture target validation
1604 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1605 {
Jamie Madill437fa652016-05-03 15:13:24 -04001606 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001607 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1608 return false;
1609 }
1610
1611 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001612 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
1613 0, width, height, depth, border, GL_NONE, GL_NONE, data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001614 {
1615 return false;
1616 }
1617
1618 return true;
1619}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001620
1621bool ValidateBindVertexArray(Context *context, GLuint array)
1622{
Martin Radev1be913c2016-07-11 17:59:16 +03001623 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001624 {
Jamie Madill437fa652016-05-03 15:13:24 -04001625 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001626 return false;
1627 }
1628
1629 return ValidateBindVertexArrayBase(context, array);
1630}
1631
Austin Kinrossbc781f32015-10-26 09:27:38 -07001632bool ValidateIsVertexArray(Context *context)
1633{
Martin Radev1be913c2016-07-11 17:59:16 +03001634 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001635 {
Jamie Madill437fa652016-05-03 15:13:24 -04001636 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001637 return false;
1638 }
1639
1640 return true;
1641}
Geoff Langc5629752015-12-07 16:29:04 -05001642
1643bool ValidateProgramBinary(Context *context,
1644 GLuint program,
1645 GLenum binaryFormat,
1646 const void *binary,
1647 GLint length)
1648{
Martin Radev1be913c2016-07-11 17:59:16 +03001649 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001650 {
Jamie Madill437fa652016-05-03 15:13:24 -04001651 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001652 return false;
1653 }
1654
1655 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1656}
1657
1658bool ValidateGetProgramBinary(Context *context,
1659 GLuint program,
1660 GLsizei bufSize,
1661 GLsizei *length,
1662 GLenum *binaryFormat,
1663 void *binary)
1664{
Martin Radev1be913c2016-07-11 17:59:16 +03001665 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001666 {
Jamie Madill437fa652016-05-03 15:13:24 -04001667 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001668 return false;
1669 }
1670
1671 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1672}
1673
Olli Etuahof0fee072016-03-30 15:11:58 +03001674bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001675{
Martin Radev1be913c2016-07-11 17:59:16 +03001676 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001677 {
Jamie Madill437fa652016-05-03 15:13:24 -04001678 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001679 return false;
1680 }
1681
1682 if (GetValidProgram(context, program) == nullptr)
1683 {
1684 return false;
1685 }
1686
1687 switch (pname)
1688 {
1689 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001690 if (value != GL_FALSE && value != GL_TRUE)
1691 {
Jamie Madill437fa652016-05-03 15:13:24 -04001692 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001693 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1694 return false;
1695 }
Geoff Langc5629752015-12-07 16:29:04 -05001696 break;
1697
1698 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001699 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001700 return false;
1701 }
1702
1703 return true;
1704}
Jamie Madillc29968b2016-01-20 11:17:23 -05001705
1706bool ValidateBlitFramebuffer(Context *context,
1707 GLint srcX0,
1708 GLint srcY0,
1709 GLint srcX1,
1710 GLint srcY1,
1711 GLint dstX0,
1712 GLint dstY0,
1713 GLint dstX1,
1714 GLint dstY1,
1715 GLbitfield mask,
1716 GLenum filter)
1717{
Martin Radev1be913c2016-07-11 17:59:16 +03001718 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001719 {
Jamie Madill437fa652016-05-03 15:13:24 -04001720 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001721 return false;
1722 }
1723
1724 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1725 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001726}
Jamie Madillc29968b2016-01-20 11:17:23 -05001727
1728bool ValidateClearBufferiv(ValidationContext *context,
1729 GLenum buffer,
1730 GLint drawbuffer,
1731 const GLint *value)
1732{
1733 switch (buffer)
1734 {
1735 case GL_COLOR:
1736 if (drawbuffer < 0 ||
1737 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1738 {
Jamie Madill437fa652016-05-03 15:13:24 -04001739 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001740 return false;
1741 }
1742 break;
1743
1744 case GL_STENCIL:
1745 if (drawbuffer != 0)
1746 {
Jamie Madill437fa652016-05-03 15:13:24 -04001747 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001748 return false;
1749 }
1750 break;
1751
1752 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001753 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001754 return false;
1755 }
1756
1757 return ValidateClearBuffer(context);
1758}
1759
1760bool ValidateClearBufferuiv(ValidationContext *context,
1761 GLenum buffer,
1762 GLint drawbuffer,
1763 const GLuint *value)
1764{
1765 switch (buffer)
1766 {
1767 case GL_COLOR:
1768 if (drawbuffer < 0 ||
1769 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1770 {
Jamie Madill437fa652016-05-03 15:13:24 -04001771 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001772 return false;
1773 }
1774 break;
1775
1776 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001777 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001778 return false;
1779 }
1780
1781 return ValidateClearBuffer(context);
1782}
1783
1784bool ValidateClearBufferfv(ValidationContext *context,
1785 GLenum buffer,
1786 GLint drawbuffer,
1787 const GLfloat *value)
1788{
1789 switch (buffer)
1790 {
1791 case GL_COLOR:
1792 if (drawbuffer < 0 ||
1793 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1794 {
Jamie Madill437fa652016-05-03 15:13:24 -04001795 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001796 return false;
1797 }
1798 break;
1799
1800 case GL_DEPTH:
1801 if (drawbuffer != 0)
1802 {
Jamie Madill437fa652016-05-03 15:13:24 -04001803 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001804 return false;
1805 }
1806 break;
1807
1808 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001809 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001810 return false;
1811 }
1812
1813 return ValidateClearBuffer(context);
1814}
1815
1816bool ValidateClearBufferfi(ValidationContext *context,
1817 GLenum buffer,
1818 GLint drawbuffer,
1819 GLfloat depth,
1820 GLint stencil)
1821{
1822 switch (buffer)
1823 {
1824 case GL_DEPTH_STENCIL:
1825 if (drawbuffer != 0)
1826 {
Jamie Madill437fa652016-05-03 15:13:24 -04001827 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001828 return false;
1829 }
1830 break;
1831
1832 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001833 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001834 return false;
1835 }
1836
1837 return ValidateClearBuffer(context);
1838}
1839
1840bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1841{
Martin Radev1be913c2016-07-11 17:59:16 +03001842 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001843 {
Jamie Madill437fa652016-05-03 15:13:24 -04001844 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001845 return false;
1846 }
1847
1848 return ValidateDrawBuffersBase(context, n, bufs);
1849}
1850
1851bool ValidateCopyTexSubImage3D(Context *context,
1852 GLenum target,
1853 GLint level,
1854 GLint xoffset,
1855 GLint yoffset,
1856 GLint zoffset,
1857 GLint x,
1858 GLint y,
1859 GLsizei width,
1860 GLsizei height)
1861{
Martin Radev1be913c2016-07-11 17:59:16 +03001862 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001863 {
Jamie Madill437fa652016-05-03 15:13:24 -04001864 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001865 return false;
1866 }
1867
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001868 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1869 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001870}
1871
Jamie Madill73a84962016-02-12 09:27:23 -05001872bool ValidateTexImage3D(Context *context,
1873 GLenum target,
1874 GLint level,
1875 GLint internalformat,
1876 GLsizei width,
1877 GLsizei height,
1878 GLsizei depth,
1879 GLint border,
1880 GLenum format,
1881 GLenum type,
1882 const GLvoid *pixels)
1883{
Martin Radev1be913c2016-07-11 17:59:16 +03001884 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001885 {
Jamie Madill437fa652016-05-03 15:13:24 -04001886 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001887 return false;
1888 }
1889
1890 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1891 0, 0, width, height, depth, border, format, type,
1892 pixels);
1893}
1894
1895bool ValidateTexSubImage3D(Context *context,
1896 GLenum target,
1897 GLint level,
1898 GLint xoffset,
1899 GLint yoffset,
1900 GLint zoffset,
1901 GLsizei width,
1902 GLsizei height,
1903 GLsizei depth,
1904 GLenum format,
1905 GLenum type,
1906 const GLvoid *pixels)
1907{
Martin Radev1be913c2016-07-11 17:59:16 +03001908 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001909 {
Jamie Madill437fa652016-05-03 15:13:24 -04001910 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001911 return false;
1912 }
1913
1914 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1915 yoffset, zoffset, width, height, depth, 0, format, type,
1916 pixels);
1917}
1918
1919bool ValidateCompressedTexSubImage3D(Context *context,
1920 GLenum target,
1921 GLint level,
1922 GLint xoffset,
1923 GLint yoffset,
1924 GLint zoffset,
1925 GLsizei width,
1926 GLsizei height,
1927 GLsizei depth,
1928 GLenum format,
1929 GLsizei imageSize,
1930 const GLvoid *data)
1931{
Martin Radev1be913c2016-07-11 17:59:16 +03001932 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001933 {
Jamie Madill437fa652016-05-03 15:13:24 -04001934 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001935 return false;
1936 }
1937
1938 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001939 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001940 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001941 if (blockSizeOrErr.isError())
1942 {
1943 context->handleError(blockSizeOrErr.getError());
1944 return false;
1945 }
1946 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001947 {
Jamie Madill437fa652016-05-03 15:13:24 -04001948 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001949 return false;
1950 }
1951
1952 if (!data)
1953 {
Jamie Madill437fa652016-05-03 15:13:24 -04001954 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001955 return false;
1956 }
1957
1958 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
1959 width, height, depth, 0, GL_NONE, GL_NONE, data);
1960}
1961
Olli Etuaho41997e72016-03-10 13:38:39 +02001962bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1963{
1964 return ValidateGenOrDeleteES3(context, n);
1965}
1966
1967bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1968{
1969 return ValidateGenOrDeleteES3(context, n);
1970}
1971
1972bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1973{
1974 return ValidateGenOrDeleteCountES3(context, count);
1975}
1976
1977bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1978{
1979 return ValidateGenOrDeleteCountES3(context, count);
1980}
1981
1982bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1983{
1984 return ValidateGenOrDeleteES3(context, n);
1985}
1986
1987bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1988{
1989 if (!ValidateGenOrDeleteES3(context, n))
1990 {
1991 return false;
1992 }
1993 for (GLint i = 0; i < n; ++i)
1994 {
1995 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1996 if (transformFeedback != nullptr && transformFeedback->isActive())
1997 {
1998 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001999 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02002000 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
2001 return false;
2002 }
2003 }
2004 return true;
2005}
2006
2007bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2008{
2009 return ValidateGenOrDeleteES3(context, n);
2010}
2011
2012bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2013{
2014 return ValidateGenOrDeleteES3(context, n);
2015}
2016
2017bool ValidateGenOrDeleteES3(Context *context, GLint n)
2018{
Martin Radev1be913c2016-07-11 17:59:16 +03002019 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02002020 {
Jamie Madill437fa652016-05-03 15:13:24 -04002021 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02002022 return false;
2023 }
2024 return ValidateGenOrDelete(context, n);
2025}
2026
2027bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
2028{
Martin Radev1be913c2016-07-11 17:59:16 +03002029 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02002030 {
Jamie Madill437fa652016-05-03 15:13:24 -04002031 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02002032 return false;
2033 }
2034 if (count < 0)
2035 {
Jamie Madill437fa652016-05-03 15:13:24 -04002036 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02002037 return false;
2038 }
2039 return true;
2040}
2041
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002042bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2043{
Martin Radev1be913c2016-07-11 17:59:16 +03002044 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002045 {
Jamie Madill437fa652016-05-03 15:13:24 -04002046 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002047 return false;
2048 }
2049 switch (primitiveMode)
2050 {
2051 case GL_TRIANGLES:
2052 case GL_LINES:
2053 case GL_POINTS:
2054 break;
2055
2056 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002057 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002058 return false;
2059 }
2060
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002061 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002062 ASSERT(transformFeedback != nullptr);
2063
2064 if (transformFeedback->isActive())
2065 {
Jamie Madill437fa652016-05-03 15:13:24 -04002066 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002067 return false;
2068 }
2069 return true;
2070}
2071
Olli Etuaho37477912016-03-30 14:54:40 +03002072bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
2073{
Martin Radev1be913c2016-07-11 17:59:16 +03002074 if (context->getClientMajorVersion() < 3)
Olli Etuaho37477912016-03-30 14:54:40 +03002075 {
Jamie Madill437fa652016-05-03 15:13:24 -04002076 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho37477912016-03-30 14:54:40 +03002077 return false;
2078 }
2079
2080 if (!context->isSampler(sampler))
2081 {
Jamie Madill437fa652016-05-03 15:13:24 -04002082 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho37477912016-03-30 14:54:40 +03002083 return false;
2084 }
2085
2086 if (!ValidateSamplerObjectParameter(context, pname))
2087 {
2088 return false;
2089 }
2090
Ian Ewellbda75592016-04-18 17:25:54 -04002091 if (!ValidateTexParamParameters(context, GL_TEXTURE_2D, pname, param))
Olli Etuaho37477912016-03-30 14:54:40 +03002092 {
2093 return false;
2094 }
2095 return true;
2096}
2097
2098bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
2099{
2100 // The only float parameters are MIN_LOD and MAX_LOD. For these any value is permissible, so
2101 // ValidateSamplerParameteri can be used for validation here.
2102 return ValidateSamplerParameteri(context, sampler, pname, static_cast<GLint>(param));
2103}
2104
Olli Etuaho4f667482016-03-30 15:56:35 +03002105bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
2106{
Martin Radev1be913c2016-07-11 17:59:16 +03002107 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002108 {
Jamie Madill437fa652016-05-03 15:13:24 -04002109 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002110 return false;
2111 }
2112
2113 return ValidateGetBufferPointervBase(context, target, pname, params);
2114}
2115
2116bool ValidateUnmapBuffer(Context *context, GLenum target)
2117{
Martin Radev1be913c2016-07-11 17:59:16 +03002118 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002119 {
Jamie Madill437fa652016-05-03 15:13:24 -04002120 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03002121 return false;
2122 }
2123
2124 return ValidateUnmapBufferBase(context, target);
2125}
2126
2127bool ValidateMapBufferRange(Context *context,
2128 GLenum target,
2129 GLintptr offset,
2130 GLsizeiptr length,
2131 GLbitfield access)
2132{
Martin Radev1be913c2016-07-11 17:59:16 +03002133 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002134 {
Jamie Madill437fa652016-05-03 15:13:24 -04002135 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002136 return false;
2137 }
2138
2139 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2140}
2141
2142bool ValidateFlushMappedBufferRange(Context *context,
2143 GLenum target,
2144 GLintptr offset,
2145 GLsizeiptr length)
2146{
Martin Radev1be913c2016-07-11 17:59:16 +03002147 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002148 {
Jamie Madill437fa652016-05-03 15:13:24 -04002149 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002150 return false;
2151 }
2152
2153 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2154}
2155
Jamie Madillc29968b2016-01-20 11:17:23 -05002156} // namespace gl