blob: b635c50bf1960bbc448590d82231dca7ed6b5d89 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES3.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES.h"
12#include "libANGLE/Context.h"
13#include "libANGLE/Texture.h"
14#include "libANGLE/Framebuffer.h"
15#include "libANGLE/Renderbuffer.h"
16#include "libANGLE/formatutils.h"
17#include "libANGLE/FramebufferAttachment.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040018
19#include "common/mathutil.h"
Geoff Langa9be0dc2014-12-17 12:34:40 -050020#include "common/utilities.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040021
Jamie Madille2e406c2016-06-02 13:04:10 -040022using namespace angle;
23
Geoff Lange8ebe7f2013-08-05 15:03:13 -040024namespace gl
25{
26
Geoff Lang5d601382014-07-22 15:14:06 -040027struct ES3FormatCombination
28{
29 GLenum internalFormat;
30 GLenum format;
31 GLenum type;
32};
33
34bool operator<(const ES3FormatCombination& a, const ES3FormatCombination& b)
35{
36 return memcmp(&a, &b, sizeof(ES3FormatCombination)) < 0;
37}
38
39typedef std::set<ES3FormatCombination> ES3FormatCombinationSet;
40
41static inline void InsertES3FormatCombo(ES3FormatCombinationSet *set, GLenum internalFormat, GLenum format, GLenum type)
42{
43 ES3FormatCombination info;
44 info.internalFormat = internalFormat;
45 info.format = format;
46 info.type = type;
47 set->insert(info);
48}
49
50ES3FormatCombinationSet BuildES3FormatSet()
51{
52 ES3FormatCombinationSet set;
53
54 // Format combinations from ES 3.0.1 spec, table 3.2
55
Geoff Lang4e58af62016-08-26 10:56:52 -040056 // clang-format off
Geoff Lang5d601382014-07-22 15:14:06 -040057 // | Internal format | Format | Type |
58 // | | | |
59 InsertES3FormatCombo(&set, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE );
60 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE );
61 InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE );
62 InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE );
63 InsertES3FormatCombo(&set, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE );
64 InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 );
65 InsertES3FormatCombo(&set, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV );
66 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV );
67 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 );
68 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT );
69 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT_OES );
70 InsertES3FormatCombo(&set, GL_RGBA32F, GL_RGBA, GL_FLOAT );
71 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_FLOAT );
72 InsertES3FormatCombo(&set, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE );
73 InsertES3FormatCombo(&set, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE );
74 InsertES3FormatCombo(&set, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT );
75 InsertES3FormatCombo(&set, GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT );
76 InsertES3FormatCombo(&set, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT );
77 InsertES3FormatCombo(&set, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT );
78 InsertES3FormatCombo(&set, GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV );
79 InsertES3FormatCombo(&set, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE );
80 InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE );
81 InsertES3FormatCombo(&set, GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE );
82 InsertES3FormatCombo(&set, GL_RGB8_SNORM, GL_RGB, GL_BYTE );
83 InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 );
84 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV );
85 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV );
86 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT );
87 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT_OES );
88 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT );
89 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT_OES );
90 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT );
91 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT_OES );
92 InsertES3FormatCombo(&set, GL_RGB32F, GL_RGB, GL_FLOAT );
93 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_FLOAT );
94 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT );
95 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_FLOAT );
96 InsertES3FormatCombo(&set, GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE );
97 InsertES3FormatCombo(&set, GL_RGB8I, GL_RGB_INTEGER, GL_BYTE );
98 InsertES3FormatCombo(&set, GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT );
99 InsertES3FormatCombo(&set, GL_RGB16I, GL_RGB_INTEGER, GL_SHORT );
100 InsertES3FormatCombo(&set, GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT );
101 InsertES3FormatCombo(&set, GL_RGB32I, GL_RGB_INTEGER, GL_INT );
102 InsertES3FormatCombo(&set, GL_RG8, GL_RG, GL_UNSIGNED_BYTE );
103 InsertES3FormatCombo(&set, GL_RG8_SNORM, GL_RG, GL_BYTE );
104 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT );
105 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT_OES );
106 InsertES3FormatCombo(&set, GL_RG32F, GL_RG, GL_FLOAT );
107 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_FLOAT );
108 InsertES3FormatCombo(&set, GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE );
109 InsertES3FormatCombo(&set, GL_RG8I, GL_RG_INTEGER, GL_BYTE );
110 InsertES3FormatCombo(&set, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT );
111 InsertES3FormatCombo(&set, GL_RG16I, GL_RG_INTEGER, GL_SHORT );
112 InsertES3FormatCombo(&set, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT );
113 InsertES3FormatCombo(&set, GL_RG32I, GL_RG_INTEGER, GL_INT );
114 InsertES3FormatCombo(&set, GL_R8, GL_RED, GL_UNSIGNED_BYTE );
115 InsertES3FormatCombo(&set, GL_R8_SNORM, GL_RED, GL_BYTE );
116 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT );
117 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT_OES );
118 InsertES3FormatCombo(&set, GL_R32F, GL_RED, GL_FLOAT );
119 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_FLOAT );
120 InsertES3FormatCombo(&set, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE );
121 InsertES3FormatCombo(&set, GL_R8I, GL_RED_INTEGER, GL_BYTE );
122 InsertES3FormatCombo(&set, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT );
123 InsertES3FormatCombo(&set, GL_R16I, GL_RED_INTEGER, GL_SHORT );
124 InsertES3FormatCombo(&set, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT );
125 InsertES3FormatCombo(&set, GL_R32I, GL_RED_INTEGER, GL_INT );
126
127 // Unsized formats
128 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE );
129 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 );
130 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 );
131 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE );
132 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 );
133 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE );
134 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE );
135 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE );
136 InsertES3FormatCombo(&set, GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE );
137 InsertES3FormatCombo(&set, GL_SRGB_EXT, GL_SRGB_EXT, GL_UNSIGNED_BYTE );
Jamie Madill689325c2015-07-20 14:36:53 -0400138 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_UNSIGNED_BYTE );
139 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_FLOAT );
140 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_HALF_FLOAT );
141 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_HALF_FLOAT_OES );
142 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_UNSIGNED_BYTE );
143 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_FLOAT );
144 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_HALF_FLOAT );
145 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_HALF_FLOAT_OES );
146 InsertES3FormatCombo(&set, GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 );
Geoff Lang5d601382014-07-22 15:14:06 -0400147
148 // Depth stencil formats
149 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT );
150 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
151 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
152 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT );
153 InsertES3FormatCombo(&set, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 );
154 InsertES3FormatCombo(&set, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
155
156 // From GL_EXT_sRGB
157 InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE );
158 InsertES3FormatCombo(&set, GL_SRGB8, GL_SRGB_EXT, GL_UNSIGNED_BYTE );
159
160 // From GL_OES_texture_float
Jeff Muizelaarbb1a5be2015-12-02 12:03:46 -0500161 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_FLOAT );
162 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_FLOAT );
Geoff Lang5d601382014-07-22 15:14:06 -0400163 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT );
164 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT );
165 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_FLOAT );
166
167 // From GL_OES_texture_half_float
Geoff Lang4e58af62016-08-26 10:56:52 -0400168 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES );
169 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_HALF_FLOAT_OES );
Geoff Lang5d601382014-07-22 15:14:06 -0400170 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT );
171 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES );
172 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT );
173 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES );
174 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT );
175 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES );
176
177 // From GL_EXT_texture_format_BGRA8888
178 InsertES3FormatCombo(&set, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
179
180 // From GL_EXT_texture_storage
181 // | Internal format | Format | Type |
182 // | | | |
183 InsertES3FormatCombo(&set, GL_ALPHA8_EXT, GL_ALPHA, GL_UNSIGNED_BYTE );
184 InsertES3FormatCombo(&set, GL_LUMINANCE8_EXT, GL_LUMINANCE, GL_UNSIGNED_BYTE );
185 InsertES3FormatCombo(&set, GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE );
186 InsertES3FormatCombo(&set, GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT );
187 InsertES3FormatCombo(&set, GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT );
188 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT );
189 InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT );
190 InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT_OES );
191 InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT );
192 InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT_OES );
193 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT );
194 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES );
195
196 // From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888
197 InsertES3FormatCombo(&set, GL_BGRA8_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
198 InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT);
199 InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
200 InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT);
201 InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
202
Geoff Lang4e58af62016-08-26 10:56:52 -0400203 // From GL_ANGLE_depth_texture and OES_depth_texture
Geoff Lang5d601382014-07-22 15:14:06 -0400204 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8_OES );
Geoff Lang4e58af62016-08-26 10:56:52 -0400205 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT );
206 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
Geoff Langf607c602016-09-21 11:46:48 -0400207 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400208
Vincent Lang25ab4512016-05-13 18:13:59 +0200209 // From GL_EXT_texture_norm16
210 InsertES3FormatCombo(&set, GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT);
211 InsertES3FormatCombo(&set, GL_RG16_EXT, GL_RG, GL_UNSIGNED_SHORT);
212 InsertES3FormatCombo(&set, GL_RGB16_EXT, GL_RGB, GL_UNSIGNED_SHORT);
213 InsertES3FormatCombo(&set, GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT);
214 InsertES3FormatCombo(&set, GL_R16_SNORM_EXT, GL_RED, GL_SHORT);
215 InsertES3FormatCombo(&set, GL_RG16_SNORM_EXT, GL_RG, GL_SHORT);
216 InsertES3FormatCombo(&set, GL_RGB16_SNORM_EXT, GL_RGB, GL_SHORT);
217 InsertES3FormatCombo(&set, GL_RGBA16_SNORM_EXT, GL_RGBA, GL_SHORT);
218
Geoff Lang5d601382014-07-22 15:14:06 -0400219 return set;
220}
221
222static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
223{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500224 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
225 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
226 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
227 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
Geoff Langbaadf232014-08-04 13:58:02 -0400228 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
Martin Radev1be913c2016-07-11 17:59:16 +0300229 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Geoff Lang5d601382014-07-22 15:14:06 -0400230 {
Jamie Madill437fa652016-05-03 15:13:24 -0400231 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400232 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400233 }
234
235 // The type and format are valid if any supported internal format has that type and format
236 bool formatSupported = false;
237 bool typeSupported = false;
238
239 static const ES3FormatCombinationSet es3FormatSet = BuildES3FormatSet();
240 for (ES3FormatCombinationSet::const_iterator i = es3FormatSet.begin(); i != es3FormatSet.end(); i++)
241 {
242 if (i->format == format || i->type == type)
243 {
244 const gl::InternalFormat &info = gl::GetInternalFormatInfo(i->internalFormat);
Martin Radev1be913c2016-07-11 17:59:16 +0300245 bool supported =
246 info.textureSupport(context->getClientMajorVersion(), context->getExtensions());
Geoff Langbaadf232014-08-04 13:58:02 -0400247 if (supported && i->type == type)
Geoff Lang5d601382014-07-22 15:14:06 -0400248 {
249 typeSupported = true;
250 }
Geoff Langbaadf232014-08-04 13:58:02 -0400251 if (supported && i->format == format)
Geoff Lang5d601382014-07-22 15:14:06 -0400252 {
253 formatSupported = true;
254 }
Geoff Langbaadf232014-08-04 13:58:02 -0400255
256 // Early-out if both type and format are supported now
257 if (typeSupported && formatSupported)
258 {
259 break;
260 }
Geoff Lang5d601382014-07-22 15:14:06 -0400261 }
262 }
263
264 if (!typeSupported || !formatSupported)
265 {
Jamie Madill437fa652016-05-03 15:13:24 -0400266 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400267 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400268 }
269
270 // Check if this is a valid format combination to load texture data
271 ES3FormatCombination searchFormat;
272 searchFormat.internalFormat = internalFormat;
273 searchFormat.format = format;
274 searchFormat.type = type;
275
276 if (es3FormatSet.find(searchFormat) == es3FormatSet.end())
277 {
Jamie Madill437fa652016-05-03 15:13:24 -0400278 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400279 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400280 }
281
282 return true;
283}
284
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500285bool ValidateES3TexImageParametersBase(Context *context,
286 GLenum target,
287 GLint level,
288 GLenum internalformat,
289 bool isCompressed,
290 bool isSubImage,
291 GLint xoffset,
292 GLint yoffset,
293 GLint zoffset,
294 GLsizei width,
295 GLsizei height,
296 GLsizei depth,
297 GLint border,
298 GLenum format,
299 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400300 GLsizei imageSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500301 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400302{
303 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -0700304 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400305 {
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
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400310 // Verify zero border
311 if (border != 0)
312 {
Jamie Madill437fa652016-05-03 15:13:24 -0400313 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400314 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400315 }
316
Jamie Madill6f38f822014-06-06 17:12:20 -0400317 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
318 std::numeric_limits<GLsizei>::max() - xoffset < width ||
319 std::numeric_limits<GLsizei>::max() - yoffset < height ||
320 std::numeric_limits<GLsizei>::max() - zoffset < depth)
321 {
Jamie Madill437fa652016-05-03 15:13:24 -0400322 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400323 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400324 }
325
Geoff Langaae65a42014-05-26 12:43:44 -0400326 const gl::Caps &caps = context->getCaps();
327
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400328 switch (target)
329 {
330 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500331 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
332 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400333 {
Jamie Madill437fa652016-05-03 15:13:24 -0400334 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500335 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400336 }
337 break;
338
339 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
340 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
341 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
342 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
343 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
344 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500345 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400346 {
Jamie Madill437fa652016-05-03 15:13:24 -0400347 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500348 return false;
349 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400350
Geoff Langa9be0dc2014-12-17 12:34:40 -0500351 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
352 {
Jamie Madill437fa652016-05-03 15:13:24 -0400353 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500354 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400355 }
356 break;
357
358 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500359 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
360 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
361 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400362 {
Jamie Madill437fa652016-05-03 15:13:24 -0400363 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500364 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400365 }
366 break;
367
Geoff Langa9be0dc2014-12-17 12:34:40 -0500368 case GL_TEXTURE_2D_ARRAY:
369 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
370 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
Geoff Langb92c1332015-09-04 12:54:55 -0400371 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500372 {
Jamie Madill437fa652016-05-03 15:13:24 -0400373 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500374 return false;
375 }
376 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400377
378 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400379 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400380 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400381 }
382
Geoff Lang691e58c2014-12-19 17:03:25 -0500383 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400384 if (!texture)
385 {
Jamie Madill437fa652016-05-03 15:13:24 -0400386 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400387 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400388 }
389
Geoff Lang69cce582015-09-17 13:20:36 -0400390 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400391 {
Jamie Madill437fa652016-05-03 15:13:24 -0400392 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400393 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400394 }
395
396 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400397 GLenum actualInternalFormat =
398 isSubImage ? texture->getFormat(target, level).asSized() : internalformat;
Geoff Lang5d601382014-07-22 15:14:06 -0400399 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400400 if (isCompressed)
401 {
tmartino7c102692015-10-02 16:43:40 -0400402 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400403 {
Jamie Madill437fa652016-05-03 15:13:24 -0400404 context->handleError(Error(
tmartino7c102692015-10-02 16:43:40 -0400405 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format."));
Geoff Langb1196682014-07-23 13:47:29 -0400406 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400407 }
408
tmartino7c102692015-10-02 16:43:40 -0400409 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400410 {
Jamie Madill437fa652016-05-03 15:13:24 -0400411 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400412 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400413 }
414
Martin Radev1be913c2016-07-11 17:59:16 +0300415 if (!actualFormatInfo.textureSupport(context->getClientMajorVersion(),
416 context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400417 {
Jamie Madill437fa652016-05-03 15:13:24 -0400418 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang839ce0b2015-10-23 13:13:12 -0400419 return false;
420 }
421
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400422 if (target == GL_TEXTURE_3D)
423 {
Jamie Madill437fa652016-05-03 15:13:24 -0400424 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400425 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400426 }
427 }
428 else
429 {
Geoff Langbaadf232014-08-04 13:58:02 -0400430 if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400431 {
Geoff Lang5d601382014-07-22 15:14:06 -0400432 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400433 }
434
435 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
436 {
Jamie Madill437fa652016-05-03 15:13:24 -0400437 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400438 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400439 }
440 }
441
442 // Validate sub image parameters
443 if (isSubImage)
444 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500445 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400446 {
Jamie Madill437fa652016-05-03 15:13:24 -0400447 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400448 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400449 }
450
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400451 if (width == 0 || height == 0 || depth == 0)
452 {
453 return false;
454 }
455
456 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
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
462 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
463 std::numeric_limits<GLsizei>::max() - yoffset < height ||
464 std::numeric_limits<GLsizei>::max() - zoffset < depth)
465 {
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
Geoff Langa9be0dc2014-12-17 12:34:40 -0500470 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
471 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
472 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400473 {
Jamie Madill437fa652016-05-03 15:13:24 -0400474 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400475 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400476 }
477 }
478
Geoff Langff5b2d52016-09-07 11:32:23 -0400479 if (!ValidImageDataSize(context, target, width, height, 1, actualInternalFormat, type, pixels,
480 imageSize))
481 {
482 return false;
483 }
484
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400485 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700486 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400487 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400488 {
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400489 // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
490 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400491 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400492 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400493 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400494 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
495
Geoff Langff5b2d52016-09-07 11:32:23 -0400496 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400497 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400498 context->handleError(
499 Error(GL_INVALID_OPERATION, "Reads would overflow the pixel unpack buffer."));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400500 return false;
501 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400502 }
503
Jamie Madill7a5f7382014-03-05 15:01:24 -0500504 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700505 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500506 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400507 context->handleError(Error(GL_INVALID_OPERATION, "Pixel unpack buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -0400508 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500509 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400510 }
511
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400512 return true;
513}
514
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500515bool ValidateES3TexImage2DParameters(Context *context,
516 GLenum target,
517 GLint level,
518 GLenum internalformat,
519 bool isCompressed,
520 bool isSubImage,
521 GLint xoffset,
522 GLint yoffset,
523 GLint zoffset,
524 GLsizei width,
525 GLsizei height,
526 GLsizei depth,
527 GLint border,
528 GLenum format,
529 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400530 GLsizei imageSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500531 const GLvoid *pixels)
532{
533 if (!ValidTexture2DDestinationTarget(context, target))
534 {
Jamie Madill437fa652016-05-03 15:13:24 -0400535 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500536 return false;
537 }
538
539 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
540 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400541 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500542}
543
544bool ValidateES3TexImage3DParameters(Context *context,
545 GLenum target,
546 GLint level,
547 GLenum internalformat,
548 bool isCompressed,
549 bool isSubImage,
550 GLint xoffset,
551 GLint yoffset,
552 GLint zoffset,
553 GLsizei width,
554 GLsizei height,
555 GLsizei depth,
556 GLint border,
557 GLenum format,
558 GLenum type,
559 const GLvoid *pixels)
560{
561 if (!ValidTexture3DDestinationTarget(context, target))
562 {
Jamie Madill437fa652016-05-03 15:13:24 -0400563 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500564 return false;
565 }
566
567 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
568 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400569 depth, border, format, type, -1, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500570}
571
Geoff Lang5d601382014-07-22 15:14:06 -0400572struct EffectiveInternalFormatInfo
573{
574 GLenum mEffectiveFormat;
575 GLenum mDestFormat;
576 GLuint mMinRedBits;
577 GLuint mMaxRedBits;
578 GLuint mMinGreenBits;
579 GLuint mMaxGreenBits;
580 GLuint mMinBlueBits;
581 GLuint mMaxBlueBits;
582 GLuint mMinAlphaBits;
583 GLuint mMaxAlphaBits;
584
585 EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits,
586 GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits,
587 GLuint minAlphaBits, GLuint maxAlphaBits)
588 : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits),
589 mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits),
590 mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits),
591 mMaxAlphaBits(maxAlphaBits) {};
592};
593
594typedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
595
596static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList()
597{
598 EffectiveInternalFormatList list;
599
600 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
601 // linear source buffer component sizes.
602 // | Source channel min/max sizes |
603 // Effective Internal Format | N/A | R | G | B | A |
604 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8));
605 list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0));
606 list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0));
607 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0));
608 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0));
609 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4));
610 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1));
611 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8));
612 list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2));
613
614 return list;
615}
616
617static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList()
618{
619 EffectiveInternalFormatList list;
620
621 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
622 // linear source buffer component sizes.
623 // | Source channel min/max sizes |
624 // Effective Internal Format | Dest Format | R | G | B | A |
625 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
626 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX));
627 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
628 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX));
629 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX));
630 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4));
631 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1));
632 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8));
633
634 return list;
635}
636
637static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
638 GLenum *outEffectiveFormat)
639{
640 const EffectiveInternalFormatList *list = NULL;
641 GLenum targetFormat = GL_NONE;
642
643 if (destFormat.pixelBytes > 0)
644 {
645 static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList();
646 list = &sizedList;
647 }
648 else
649 {
650 static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList();
651 list = &unsizedList;
652 targetFormat = destFormat.format;
653 }
654
655 for (size_t curFormat = 0; curFormat < list->size(); ++curFormat)
656 {
657 const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat);
658 if ((formatInfo.mDestFormat == targetFormat) &&
659 (formatInfo.mMinRedBits <= srcFormat.redBits && formatInfo.mMaxRedBits >= srcFormat.redBits) &&
660 (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) &&
661 (formatInfo.mMinBlueBits <= srcFormat.blueBits && formatInfo.mMaxBlueBits >= srcFormat.blueBits) &&
662 (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits))
663 {
664 *outEffectiveFormat = formatInfo.mEffectiveFormat;
665 return true;
666 }
667 }
668
669 return false;
670}
671
672struct CopyConversion
673{
674 GLenum mTextureFormat;
675 GLenum mFramebufferFormat;
676
677 CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
678 : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
679
680 bool operator<(const CopyConversion& other) const
681 {
682 return memcmp(this, &other, sizeof(CopyConversion)) < 0;
683 }
684};
685
686typedef std::set<CopyConversion> CopyConversionSet;
687
688static CopyConversionSet BuildValidES3CopyTexImageCombinations()
689{
690 CopyConversionSet set;
691
692 // From ES 3.0.1 spec, table 3.15
693 set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
694 set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
695 set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
696 set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
697 set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
698 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
699 set.insert(CopyConversion(GL_RED, GL_RED));
700 set.insert(CopyConversion(GL_RED, GL_RG));
701 set.insert(CopyConversion(GL_RED, GL_RGB));
702 set.insert(CopyConversion(GL_RED, GL_RGBA));
703 set.insert(CopyConversion(GL_RG, GL_RG));
704 set.insert(CopyConversion(GL_RG, GL_RGB));
705 set.insert(CopyConversion(GL_RG, GL_RGBA));
706 set.insert(CopyConversion(GL_RGB, GL_RGB));
707 set.insert(CopyConversion(GL_RGB, GL_RGBA));
708 set.insert(CopyConversion(GL_RGBA, GL_RGBA));
709
710 // Necessary for ANGLE back-buffers
711 set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
712 set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
713 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
714 set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
715 set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
716 set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
717 set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
Geoff Lang4e58af62016-08-26 10:56:52 -0400718 set.insert(CopyConversion(GL_BGRA_EXT, GL_BGRA_EXT));
Geoff Lang5d601382014-07-22 15:14:06 -0400719
720 set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
721 set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
722 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
723 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
724 set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
725 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
726 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
727 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
728 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
729 set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
730
731 return set;
732}
733
Corentin Wallez76287682016-04-25 09:23:38 -0400734static bool EqualOrFirstZero(GLuint first, GLuint second)
735{
736 return first == 0 || first == second;
737}
738
Jamie Madill0c8abca2016-07-22 20:21:26 -0400739static bool IsValidES3CopyTexImageCombination(const Format &textureFormat,
740 const Format &framebufferFormat,
741 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400742{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400743 const auto &textureFormatInfo = *textureFormat.info;
744 const auto &framebufferFormatInfo = *framebufferFormat.info;
Geoff Lang5d601382014-07-22 15:14:06 -0400745
746 static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
Jamie Madill0c8abca2016-07-22 20:21:26 -0400747 if (conversionSet.find(CopyConversion(textureFormatInfo.format,
748 framebufferFormatInfo.format)) != conversionSet.end())
Geoff Lang5d601382014-07-22 15:14:06 -0400749 {
750 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
751 // must both be signed, unsigned, or fixed point and both source and destinations
752 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
753 // conversion between fixed and floating point.
754
Jamie Madill0c8abca2016-07-22 20:21:26 -0400755 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
756 (framebufferFormatInfo.colorEncoding == GL_SRGB))
Geoff Lang5d601382014-07-22 15:14:06 -0400757 {
758 return false;
759 }
760
Jamie Madill0c8abca2016-07-22 20:21:26 -0400761 if (((textureFormatInfo.componentType == GL_INT) !=
762 (framebufferFormatInfo.componentType == GL_INT)) ||
763 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
764 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
Geoff Lang5d601382014-07-22 15:14:06 -0400765 {
766 return false;
767 }
768
Jamie Madill0c8abca2016-07-22 20:21:26 -0400769 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
770 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
771 textureFormatInfo.componentType == GL_FLOAT) &&
772 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
773 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
774 framebufferFormatInfo.componentType == GL_FLOAT))
Geoff Lang5d601382014-07-22 15:14:06 -0400775 {
776 return false;
777 }
778
779 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
780 // The effective internal format of the source buffer is determined with the following rules applied in order:
781 // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
782 // effective internal format is the source buffer's sized internal format.
783 // * If the source buffer is a texture that was created with an unsized base internal format, then the
784 // effective internal format is the source image array's effective internal format, as specified by table
785 // 3.12, which is determined from the <format> and <type> that were used when the source image array was
786 // specified by TexImage*.
787 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
788 // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
789 // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
790 // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
791 // is SRGB.
792 const InternalFormat *sourceEffectiveFormat = NULL;
793 if (readBufferHandle != 0)
794 {
795 // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
Jamie Madill0c8abca2016-07-22 20:21:26 -0400796 if (framebufferFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400797 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400798 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400799 }
800 else
801 {
802 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
803 // texture. We can use the same table we use when creating textures to get its effective sized format.
Jamie Madill0c8abca2016-07-22 20:21:26 -0400804 GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferFormatInfo.format,
805 framebufferFormatInfo.type);
Geoff Lang051dbc72015-01-05 15:48:58 -0500806 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400807 }
808 }
809 else
810 {
811 // The effective internal format must be derived from the source framebuffer's channel sizes.
812 // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
Jamie Madill0c8abca2016-07-22 20:21:26 -0400813 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400814 {
815 GLenum effectiveFormat;
Jamie Madill0c8abca2016-07-22 20:21:26 -0400816 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
817 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400818 {
819 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
820 }
821 else
822 {
823 return false;
824 }
825 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400826 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
Geoff Lang5d601382014-07-22 15:14:06 -0400827 {
828 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Jamie Madill0c8abca2016-07-22 20:21:26 -0400829 if (textureFormat.sized &&
830 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
831 (framebufferFormatInfo.greenBits >= 1 &&
832 framebufferFormatInfo.greenBits <= 8) &&
833 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
834 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
Geoff Lang5d601382014-07-22 15:14:06 -0400835 {
836 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
837 }
838 else
839 {
840 return false;
841 }
842 }
843 else
844 {
845 UNREACHABLE();
846 return false;
847 }
848 }
849
Jamie Madill0c8abca2016-07-22 20:21:26 -0400850 if (textureFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400851 {
Corentin Wallez76287682016-04-25 09:23:38 -0400852 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination
853 // format is sized, component sizes of the source and destination formats must exactly
854 // match if the destination format exists.
Jamie Madill0c8abca2016-07-22 20:21:26 -0400855 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
856 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
857 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
858 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
Geoff Lang5d601382014-07-22 15:14:06 -0400859 {
860 return false;
861 }
862 }
863
Geoff Lang5d601382014-07-22 15:14:06 -0400864 return true; // A conversion function exists, and no rule in the specification has precluded conversion
865 // between these formats.
866 }
867
868 return false;
869}
870
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500871bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
872 GLenum target,
873 GLint level,
874 GLenum internalformat,
875 bool isSubImage,
876 GLint xoffset,
877 GLint yoffset,
878 GLint zoffset,
879 GLint x,
880 GLint y,
881 GLsizei width,
882 GLsizei height,
883 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400884{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400885 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400886 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400887 xoffset, yoffset, zoffset, x, y, width, height, border,
888 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400889 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400890 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400891 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400892 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400893
Jamie Madill51f40ec2016-06-15 14:06:00 -0400894 const auto &state = context->getGLState();
895 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
896 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400897
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700898 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400899 {
Jamie Madill437fa652016-05-03 15:13:24 -0400900 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400901 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400902 }
903
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700904 if (readFramebufferID != 0 && framebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400905 {
Jamie Madill437fa652016-05-03 15:13:24 -0400906 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400907 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400908 }
909
Jamie Madill0c8abca2016-07-22 20:21:26 -0400910 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400911
912 if (isSubImage)
913 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400914 if (!IsValidES3CopyTexImageCombination(textureFormat, source->getFormat(),
Jamie Madillc29968b2016-01-20 11:17:23 -0500915 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400916 {
Jamie Madill437fa652016-05-03 15:13:24 -0400917 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400918 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400919 }
920 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400921 else
922 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400923 // Use format/type from the source FBO. (Might not be perfect for all cases?)
924 const auto framebufferFormat = source->getFormat();
925 Format copyFormat(internalformat, framebufferFormat.format, framebufferFormat.type);
926 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400927 {
Jamie Madill437fa652016-05-03 15:13:24 -0400928 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400929 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400930 }
931 }
932
Geoff Lang784a8fd2013-09-24 12:33:16 -0400933 // If width or height is zero, it is a no-op. Return false without setting an error.
934 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400935}
936
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500937bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
938 GLenum target,
939 GLint level,
940 GLenum internalformat,
941 bool isSubImage,
942 GLint xoffset,
943 GLint yoffset,
944 GLint zoffset,
945 GLint x,
946 GLint y,
947 GLsizei width,
948 GLsizei height,
949 GLint border)
950{
951 if (!ValidTexture2DDestinationTarget(context, target))
952 {
Jamie Madill437fa652016-05-03 15:13:24 -0400953 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500954 return false;
955 }
956
957 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
958 xoffset, yoffset, zoffset, x, y, width, height,
959 border);
960}
961
962bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
963 GLenum target,
964 GLint level,
965 GLenum internalformat,
966 bool isSubImage,
967 GLint xoffset,
968 GLint yoffset,
969 GLint zoffset,
970 GLint x,
971 GLint y,
972 GLsizei width,
973 GLsizei height,
974 GLint border)
975{
976 if (!ValidTexture3DDestinationTarget(context, target))
977 {
Jamie Madill437fa652016-05-03 15:13:24 -0400978 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500979 return false;
980 }
981
982 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
983 xoffset, yoffset, zoffset, x, y, width, height,
984 border);
985}
986
987bool ValidateES3TexStorageParametersBase(Context *context,
988 GLenum target,
989 GLsizei levels,
990 GLenum internalformat,
991 GLsizei width,
992 GLsizei height,
993 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400994{
995 if (width < 1 || height < 1 || depth < 1 || levels < 1)
996 {
Jamie Madill437fa652016-05-03 15:13:24 -0400997 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400998 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400999 }
1000
Geoff Langb92c1332015-09-04 12:54:55 -04001001 GLsizei maxDim = std::max(width, height);
1002 if (target != GL_TEXTURE_2D_ARRAY)
1003 {
1004 maxDim = std::max(maxDim, depth);
1005 }
1006
1007 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001008 {
Jamie Madill437fa652016-05-03 15:13:24 -04001009 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001010 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001011 }
1012
Geoff Langaae65a42014-05-26 12:43:44 -04001013 const gl::Caps &caps = context->getCaps();
1014
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001015 switch (target)
1016 {
1017 case GL_TEXTURE_2D:
1018 {
Geoff Langaae65a42014-05-26 12:43:44 -04001019 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1020 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001021 {
Jamie Madill437fa652016-05-03 15:13:24 -04001022 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001023 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001024 }
1025 }
1026 break;
1027
Geoff Lang01c21d22013-09-24 11:52:16 -04001028 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001029 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001030 if (width != height)
1031 {
Jamie Madill437fa652016-05-03 15:13:24 -04001032 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001033 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001034 }
1035
Geoff Langaae65a42014-05-26 12:43:44 -04001036 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001037 {
Jamie Madill437fa652016-05-03 15:13:24 -04001038 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001039 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001040 }
1041 }
1042 break;
1043
1044 case GL_TEXTURE_3D:
1045 {
Geoff Langaae65a42014-05-26 12:43:44 -04001046 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
1047 static_cast<GLuint>(height) > caps.max3DTextureSize ||
1048 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001049 {
Jamie Madill437fa652016-05-03 15:13:24 -04001050 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001051 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001052 }
1053 }
1054 break;
1055
1056 case GL_TEXTURE_2D_ARRAY:
1057 {
Geoff Langaae65a42014-05-26 12:43:44 -04001058 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1059 static_cast<GLuint>(height) > caps.max2DTextureSize ||
1060 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001061 {
Jamie Madill437fa652016-05-03 15:13:24 -04001062 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001063 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001064 }
1065 }
1066 break;
1067
1068 default:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001069 UNREACHABLE();
Geoff Langb1196682014-07-23 13:47:29 -04001070 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001071 }
1072
Geoff Lang691e58c2014-12-19 17:03:25 -05001073 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001074 if (!texture || texture->id() == 0)
1075 {
Jamie Madill437fa652016-05-03 15:13:24 -04001076 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001077 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001078 }
1079
Geoff Lang69cce582015-09-17 13:20:36 -04001080 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001081 {
Jamie Madill437fa652016-05-03 15:13:24 -04001082 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001083 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001084 }
1085
Geoff Lang5d601382014-07-22 15:14:06 -04001086 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Martin Radev1be913c2016-07-11 17:59:16 +03001087 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001088 {
Jamie Madill437fa652016-05-03 15:13:24 -04001089 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001090 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001091 }
1092
Geoff Lang5d601382014-07-22 15:14:06 -04001093 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001094 {
Jamie Madill437fa652016-05-03 15:13:24 -04001095 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001096 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001097 }
1098
1099 return true;
1100}
1101
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001102bool ValidateES3TexStorage2DParameters(Context *context,
1103 GLenum target,
1104 GLsizei levels,
1105 GLenum internalformat,
1106 GLsizei width,
1107 GLsizei height,
1108 GLsizei depth)
1109{
1110 if (!ValidTexture2DTarget(context, target))
1111 {
Jamie Madill437fa652016-05-03 15:13:24 -04001112 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001113 return false;
1114 }
1115
1116 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1117 height, depth);
1118}
1119
1120bool ValidateES3TexStorage3DParameters(Context *context,
1121 GLenum target,
1122 GLsizei levels,
1123 GLenum internalformat,
1124 GLsizei width,
1125 GLsizei height,
1126 GLsizei depth)
1127{
1128 if (!ValidTexture3DTarget(context, target))
1129 {
Jamie Madill437fa652016-05-03 15:13:24 -04001130 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001131 return false;
1132 }
1133
1134 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1135 height, depth);
1136}
1137
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001138bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1139{
Martin Radev1be913c2016-07-11 17:59:16 +03001140 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001141 {
Jamie Madill437fa652016-05-03 15:13:24 -04001142 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001143 return false;
1144 }
1145
1146 return ValidateBeginQueryBase(context, target, id);
1147}
1148
1149bool ValidateEndQuery(gl::Context *context, GLenum target)
1150{
Martin Radev1be913c2016-07-11 17:59:16 +03001151 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001152 {
Jamie Madill437fa652016-05-03 15:13:24 -04001153 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001154 return false;
1155 }
1156
1157 return ValidateEndQueryBase(context, target);
1158}
1159
1160bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1161{
Martin Radev1be913c2016-07-11 17:59:16 +03001162 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001163 {
Jamie Madill437fa652016-05-03 15:13:24 -04001164 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001165 return false;
1166 }
1167
1168 return ValidateGetQueryivBase(context, target, pname);
1169}
1170
1171bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1172{
Martin Radev1be913c2016-07-11 17:59:16 +03001173 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001174 {
Jamie Madill437fa652016-05-03 15:13:24 -04001175 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001176 return false;
1177 }
1178
1179 return ValidateGetQueryObjectValueBase(context, id, pname);
1180}
1181
Geoff Langb1196682014-07-23 13:47:29 -04001182bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
Jamie Madill570f7c82014-07-03 10:38:54 -04001183 GLuint texture, GLint level, GLint layer)
1184{
Martin Radev1be913c2016-07-11 17:59:16 +03001185 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001186 {
Jamie Madill437fa652016-05-03 15:13:24 -04001187 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001188 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001189 }
1190
Jamie Madill55ec3b12014-07-03 10:38:57 -04001191 if (layer < 0)
1192 {
Jamie Madill437fa652016-05-03 15:13:24 -04001193 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001194 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001195 }
1196
1197 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1198 {
1199 return false;
1200 }
1201
1202 const gl::Caps &caps = context->getCaps();
1203 if (texture != 0)
1204 {
1205 gl::Texture *tex = context->getTexture(texture);
1206 ASSERT(tex);
1207
1208 switch (tex->getTarget())
1209 {
1210 case GL_TEXTURE_2D_ARRAY:
1211 {
1212 if (level > gl::log2(caps.max2DTextureSize))
1213 {
Jamie Madill437fa652016-05-03 15:13:24 -04001214 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001215 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001216 }
1217
1218 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
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 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001223 }
1224 break;
1225
1226 case GL_TEXTURE_3D:
1227 {
1228 if (level > gl::log2(caps.max3DTextureSize))
1229 {
Jamie Madill437fa652016-05-03 15:13:24 -04001230 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001231 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001232 }
1233
1234 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1235 {
Jamie Madill437fa652016-05-03 15:13:24 -04001236 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001237 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001238 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001239 }
1240 break;
1241
1242 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001243 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001244 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001245 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001246
Jamie Madilla3944d42016-07-22 22:13:26 -04001247 const auto &format = tex->getFormat(tex->getTarget(), level);
1248 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001249 {
Jamie Madill437fa652016-05-03 15:13:24 -04001250 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001251 return false;
1252 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001253 }
1254
1255 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001256}
1257
Corentin Walleze0902642014-11-04 12:32:15 -08001258bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
1259 GLenum internalformat, GLsizei width, GLsizei height)
1260{
1261 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
1262 {
1263 return false;
1264 }
1265
1266 //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.
1267 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1268 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
1269 {
Jamie Madill437fa652016-05-03 15:13:24 -04001270 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -08001271 return false;
1272 }
1273
1274 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
1275 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1276 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1277 {
Jamie Madill437fa652016-05-03 15:13:24 -04001278 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001279 Error(GL_INVALID_OPERATION,
1280 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001281 return false;
1282 }
1283
1284 return true;
1285}
1286
Austin Kinross08332632015-05-05 13:35:47 -07001287bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
1288 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001289{
Martin Radev1be913c2016-07-11 17:59:16 +03001290 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001291 {
Jamie Madill437fa652016-05-03 15:13:24 -04001292 context->handleError(
1293 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001294 return false;
1295 }
1296
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001297 bool defaultFramebuffer = false;
1298
1299 switch (target)
1300 {
1301 case GL_DRAW_FRAMEBUFFER:
1302 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001303 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1304 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001305 case GL_READ_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001306 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1307 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001308 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001309 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001310 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001311 }
1312
Austin Kinross08332632015-05-05 13:35:47 -07001313 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001314}
1315
Jamie Madillc29968b2016-01-20 11:17:23 -05001316bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001317{
Martin Radev1be913c2016-07-11 17:59:16 +03001318 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001319 {
Jamie Madill437fa652016-05-03 15:13:24 -04001320 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001321 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001322 }
1323
Jamie Madill51f40ec2016-06-15 14:06:00 -04001324 if (context->getGLState().getDrawFramebuffer()->checkStatus(context->getContextState()) !=
1325 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001326 {
Jamie Madill437fa652016-05-03 15:13:24 -04001327 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001328 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001329 }
1330
1331 return true;
1332}
1333
Olli Etuaho71dfb362016-03-10 14:04:27 +02001334bool ValidateDrawRangeElements(Context *context,
1335 GLenum mode,
1336 GLuint start,
1337 GLuint end,
1338 GLsizei count,
1339 GLenum type,
1340 const GLvoid *indices,
1341 IndexRange *indexRange)
1342{
Martin Radev1be913c2016-07-11 17:59:16 +03001343 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001344 {
Jamie Madill437fa652016-05-03 15:13:24 -04001345 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001346 return false;
1347 }
1348
1349 if (end < start)
1350 {
Jamie Madill437fa652016-05-03 15:13:24 -04001351 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001352 return false;
1353 }
1354
1355 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1356 {
1357 return false;
1358 }
1359
1360 if (indexRange->end > end || indexRange->start < start)
1361 {
1362 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001363 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001364 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1365 return false;
1366 }
1367 return true;
1368}
1369
Geoff Langb1196682014-07-23 13:47:29 -04001370bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001371{
Martin Radev1be913c2016-07-11 17:59:16 +03001372 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001373 {
Jamie Madill437fa652016-05-03 15:13:24 -04001374 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001375 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001376 }
1377
Jamie Madill78f41802014-08-25 15:47:55 -04001378 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001379}
1380
Jamie Madillb885e572015-02-03 16:16:04 -05001381bool ValidateReadBuffer(Context *context, GLenum src)
1382{
Martin Radev1be913c2016-07-11 17:59:16 +03001383 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001384 {
Jamie Madill437fa652016-05-03 15:13:24 -04001385 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001386 return false;
1387 }
1388
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001389 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001390
1391 if (readFBO == nullptr)
1392 {
Jamie Madill437fa652016-05-03 15:13:24 -04001393 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001394 return false;
1395 }
1396
1397 if (src == GL_NONE)
1398 {
1399 return true;
1400 }
1401
Olli Etuaho84c9f592016-03-09 14:37:25 +02001402 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001403 {
Jamie Madill437fa652016-05-03 15:13:24 -04001404 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001405 return false;
1406 }
1407
1408 if (readFBO->id() == 0)
1409 {
1410 if (src != GL_BACK)
1411 {
1412 const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001413 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001414 return false;
1415 }
1416 }
1417 else
1418 {
1419 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1420
1421 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1422 {
1423 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001424 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001425 return false;
1426 }
1427 }
1428
1429 return true;
1430}
1431
Jamie Madill86af3d22015-07-21 15:14:07 -04001432bool ValidateCompressedTexImage3D(Context *context,
1433 GLenum target,
1434 GLint level,
1435 GLenum internalformat,
1436 GLsizei width,
1437 GLsizei height,
1438 GLsizei depth,
1439 GLint border,
1440 GLsizei imageSize,
1441 const GLvoid *data)
1442{
Martin Radev1be913c2016-07-11 17:59:16 +03001443 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001444 {
Jamie Madill437fa652016-05-03 15:13:24 -04001445 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001446 return false;
1447 }
1448
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001449 if (!ValidTextureTarget(context, target))
1450 {
1451 context->handleError(Error(GL_INVALID_ENUM));
1452 return false;
1453 }
1454
Jamie Madille2e406c2016-06-02 13:04:10 -04001455 // Validate image size
1456 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1457 {
1458 context->handleError(Error(GL_INVALID_VALUE));
1459 return false;
1460 }
1461
Jamie Madill86af3d22015-07-21 15:14:07 -04001462 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001463 if (!formatInfo.compressed)
1464 {
1465 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1466 return false;
1467 }
1468
Jamie Madill513558d2016-06-02 13:04:11 -04001469 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001470 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001471 if (blockSizeOrErr.isError())
1472 {
Jamie Madill513558d2016-06-02 13:04:11 -04001473 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001474 return false;
1475 }
1476 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001477 {
Jamie Madill437fa652016-05-03 15:13:24 -04001478 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001479 return false;
1480 }
1481
1482 // 3D texture target validation
1483 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1484 {
Jamie Madill437fa652016-05-03 15:13:24 -04001485 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001486 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1487 return false;
1488 }
1489
1490 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001491 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
1492 0, width, height, depth, border, GL_NONE, GL_NONE, data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001493 {
1494 return false;
1495 }
1496
1497 return true;
1498}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001499
1500bool ValidateBindVertexArray(Context *context, GLuint array)
1501{
Martin Radev1be913c2016-07-11 17:59:16 +03001502 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001503 {
Jamie Madill437fa652016-05-03 15:13:24 -04001504 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001505 return false;
1506 }
1507
1508 return ValidateBindVertexArrayBase(context, array);
1509}
1510
Austin Kinrossbc781f32015-10-26 09:27:38 -07001511bool ValidateIsVertexArray(Context *context)
1512{
Martin Radev1be913c2016-07-11 17:59:16 +03001513 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001514 {
Jamie Madill437fa652016-05-03 15:13:24 -04001515 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001516 return false;
1517 }
1518
1519 return true;
1520}
Geoff Langc5629752015-12-07 16:29:04 -05001521
1522bool ValidateProgramBinary(Context *context,
1523 GLuint program,
1524 GLenum binaryFormat,
1525 const void *binary,
1526 GLint length)
1527{
Martin Radev1be913c2016-07-11 17:59:16 +03001528 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001529 {
Jamie Madill437fa652016-05-03 15:13:24 -04001530 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001531 return false;
1532 }
1533
1534 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1535}
1536
1537bool ValidateGetProgramBinary(Context *context,
1538 GLuint program,
1539 GLsizei bufSize,
1540 GLsizei *length,
1541 GLenum *binaryFormat,
1542 void *binary)
1543{
Martin Radev1be913c2016-07-11 17:59:16 +03001544 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001545 {
Jamie Madill437fa652016-05-03 15:13:24 -04001546 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001547 return false;
1548 }
1549
1550 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1551}
1552
Olli Etuahof0fee072016-03-30 15:11:58 +03001553bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001554{
Martin Radev1be913c2016-07-11 17:59:16 +03001555 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001556 {
Jamie Madill437fa652016-05-03 15:13:24 -04001557 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001558 return false;
1559 }
1560
1561 if (GetValidProgram(context, program) == nullptr)
1562 {
1563 return false;
1564 }
1565
1566 switch (pname)
1567 {
1568 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001569 if (value != GL_FALSE && value != GL_TRUE)
1570 {
Jamie Madill437fa652016-05-03 15:13:24 -04001571 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001572 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1573 return false;
1574 }
Geoff Langc5629752015-12-07 16:29:04 -05001575 break;
1576
1577 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001578 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001579 return false;
1580 }
1581
1582 return true;
1583}
Jamie Madillc29968b2016-01-20 11:17:23 -05001584
1585bool ValidateBlitFramebuffer(Context *context,
1586 GLint srcX0,
1587 GLint srcY0,
1588 GLint srcX1,
1589 GLint srcY1,
1590 GLint dstX0,
1591 GLint dstY0,
1592 GLint dstX1,
1593 GLint dstY1,
1594 GLbitfield mask,
1595 GLenum filter)
1596{
Martin Radev1be913c2016-07-11 17:59:16 +03001597 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001598 {
Jamie Madill437fa652016-05-03 15:13:24 -04001599 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001600 return false;
1601 }
1602
1603 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1604 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001605}
Jamie Madillc29968b2016-01-20 11:17:23 -05001606
1607bool ValidateClearBufferiv(ValidationContext *context,
1608 GLenum buffer,
1609 GLint drawbuffer,
1610 const GLint *value)
1611{
1612 switch (buffer)
1613 {
1614 case GL_COLOR:
1615 if (drawbuffer < 0 ||
1616 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1617 {
Jamie Madill437fa652016-05-03 15:13:24 -04001618 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001619 return false;
1620 }
1621 break;
1622
1623 case GL_STENCIL:
1624 if (drawbuffer != 0)
1625 {
Jamie Madill437fa652016-05-03 15:13:24 -04001626 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001627 return false;
1628 }
1629 break;
1630
1631 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001632 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001633 return false;
1634 }
1635
1636 return ValidateClearBuffer(context);
1637}
1638
1639bool ValidateClearBufferuiv(ValidationContext *context,
1640 GLenum buffer,
1641 GLint drawbuffer,
1642 const GLuint *value)
1643{
1644 switch (buffer)
1645 {
1646 case GL_COLOR:
1647 if (drawbuffer < 0 ||
1648 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1649 {
Jamie Madill437fa652016-05-03 15:13:24 -04001650 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001651 return false;
1652 }
1653 break;
1654
1655 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001656 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001657 return false;
1658 }
1659
1660 return ValidateClearBuffer(context);
1661}
1662
1663bool ValidateClearBufferfv(ValidationContext *context,
1664 GLenum buffer,
1665 GLint drawbuffer,
1666 const GLfloat *value)
1667{
1668 switch (buffer)
1669 {
1670 case GL_COLOR:
1671 if (drawbuffer < 0 ||
1672 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1673 {
Jamie Madill437fa652016-05-03 15:13:24 -04001674 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001675 return false;
1676 }
1677 break;
1678
1679 case GL_DEPTH:
1680 if (drawbuffer != 0)
1681 {
Jamie Madill437fa652016-05-03 15:13:24 -04001682 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001683 return false;
1684 }
1685 break;
1686
1687 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001688 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001689 return false;
1690 }
1691
1692 return ValidateClearBuffer(context);
1693}
1694
1695bool ValidateClearBufferfi(ValidationContext *context,
1696 GLenum buffer,
1697 GLint drawbuffer,
1698 GLfloat depth,
1699 GLint stencil)
1700{
1701 switch (buffer)
1702 {
1703 case GL_DEPTH_STENCIL:
1704 if (drawbuffer != 0)
1705 {
Jamie Madill437fa652016-05-03 15:13:24 -04001706 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001707 return false;
1708 }
1709 break;
1710
1711 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001712 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001713 return false;
1714 }
1715
1716 return ValidateClearBuffer(context);
1717}
1718
1719bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1720{
Martin Radev1be913c2016-07-11 17:59:16 +03001721 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001722 {
Jamie Madill437fa652016-05-03 15:13:24 -04001723 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001724 return false;
1725 }
1726
1727 return ValidateDrawBuffersBase(context, n, bufs);
1728}
1729
1730bool ValidateCopyTexSubImage3D(Context *context,
1731 GLenum target,
1732 GLint level,
1733 GLint xoffset,
1734 GLint yoffset,
1735 GLint zoffset,
1736 GLint x,
1737 GLint y,
1738 GLsizei width,
1739 GLsizei height)
1740{
Martin Radev1be913c2016-07-11 17:59:16 +03001741 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001742 {
Jamie Madill437fa652016-05-03 15:13:24 -04001743 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001744 return false;
1745 }
1746
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001747 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1748 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001749}
1750
Jamie Madill73a84962016-02-12 09:27:23 -05001751bool ValidateTexImage3D(Context *context,
1752 GLenum target,
1753 GLint level,
1754 GLint internalformat,
1755 GLsizei width,
1756 GLsizei height,
1757 GLsizei depth,
1758 GLint border,
1759 GLenum format,
1760 GLenum type,
1761 const GLvoid *pixels)
1762{
Martin Radev1be913c2016-07-11 17:59:16 +03001763 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001764 {
Jamie Madill437fa652016-05-03 15:13:24 -04001765 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001766 return false;
1767 }
1768
1769 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1770 0, 0, width, height, depth, border, format, type,
1771 pixels);
1772}
1773
1774bool ValidateTexSubImage3D(Context *context,
1775 GLenum target,
1776 GLint level,
1777 GLint xoffset,
1778 GLint yoffset,
1779 GLint zoffset,
1780 GLsizei width,
1781 GLsizei height,
1782 GLsizei depth,
1783 GLenum format,
1784 GLenum type,
1785 const GLvoid *pixels)
1786{
Martin Radev1be913c2016-07-11 17:59:16 +03001787 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001788 {
Jamie Madill437fa652016-05-03 15:13:24 -04001789 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001790 return false;
1791 }
1792
1793 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1794 yoffset, zoffset, width, height, depth, 0, format, type,
1795 pixels);
1796}
1797
1798bool ValidateCompressedTexSubImage3D(Context *context,
1799 GLenum target,
1800 GLint level,
1801 GLint xoffset,
1802 GLint yoffset,
1803 GLint zoffset,
1804 GLsizei width,
1805 GLsizei height,
1806 GLsizei depth,
1807 GLenum format,
1808 GLsizei imageSize,
1809 const GLvoid *data)
1810{
Martin Radev1be913c2016-07-11 17:59:16 +03001811 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001812 {
Jamie Madill437fa652016-05-03 15:13:24 -04001813 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001814 return false;
1815 }
1816
1817 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001818 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001819 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001820 if (blockSizeOrErr.isError())
1821 {
1822 context->handleError(blockSizeOrErr.getError());
1823 return false;
1824 }
1825 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001826 {
Jamie Madill437fa652016-05-03 15:13:24 -04001827 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001828 return false;
1829 }
1830
1831 if (!data)
1832 {
Jamie Madill437fa652016-05-03 15:13:24 -04001833 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001834 return false;
1835 }
1836
1837 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
1838 width, height, depth, 0, GL_NONE, GL_NONE, data);
1839}
1840
Olli Etuaho41997e72016-03-10 13:38:39 +02001841bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1842{
1843 return ValidateGenOrDeleteES3(context, n);
1844}
1845
1846bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1847{
1848 return ValidateGenOrDeleteES3(context, n);
1849}
1850
1851bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1852{
1853 return ValidateGenOrDeleteCountES3(context, count);
1854}
1855
1856bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1857{
1858 return ValidateGenOrDeleteCountES3(context, count);
1859}
1860
1861bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1862{
1863 return ValidateGenOrDeleteES3(context, n);
1864}
1865
1866bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1867{
1868 if (!ValidateGenOrDeleteES3(context, n))
1869 {
1870 return false;
1871 }
1872 for (GLint i = 0; i < n; ++i)
1873 {
1874 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1875 if (transformFeedback != nullptr && transformFeedback->isActive())
1876 {
1877 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001878 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001879 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1880 return false;
1881 }
1882 }
1883 return true;
1884}
1885
1886bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1887{
1888 return ValidateGenOrDeleteES3(context, n);
1889}
1890
1891bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1892{
1893 return ValidateGenOrDeleteES3(context, n);
1894}
1895
1896bool ValidateGenOrDeleteES3(Context *context, GLint n)
1897{
Martin Radev1be913c2016-07-11 17:59:16 +03001898 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001899 {
Jamie Madill437fa652016-05-03 15:13:24 -04001900 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001901 return false;
1902 }
1903 return ValidateGenOrDelete(context, n);
1904}
1905
1906bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1907{
Martin Radev1be913c2016-07-11 17:59:16 +03001908 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001909 {
Jamie Madill437fa652016-05-03 15:13:24 -04001910 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001911 return false;
1912 }
1913 if (count < 0)
1914 {
Jamie Madill437fa652016-05-03 15:13:24 -04001915 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001916 return false;
1917 }
1918 return true;
1919}
1920
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001921bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1922{
Martin Radev1be913c2016-07-11 17:59:16 +03001923 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001924 {
Jamie Madill437fa652016-05-03 15:13:24 -04001925 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001926 return false;
1927 }
1928 switch (primitiveMode)
1929 {
1930 case GL_TRIANGLES:
1931 case GL_LINES:
1932 case GL_POINTS:
1933 break;
1934
1935 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001936 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001937 return false;
1938 }
1939
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001940 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001941 ASSERT(transformFeedback != nullptr);
1942
1943 if (transformFeedback->isActive())
1944 {
Jamie Madill437fa652016-05-03 15:13:24 -04001945 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001946 return false;
1947 }
1948 return true;
1949}
1950
Olli Etuaho37477912016-03-30 14:54:40 +03001951bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
1952{
Martin Radev1be913c2016-07-11 17:59:16 +03001953 if (context->getClientMajorVersion() < 3)
Olli Etuaho37477912016-03-30 14:54:40 +03001954 {
Jamie Madill437fa652016-05-03 15:13:24 -04001955 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho37477912016-03-30 14:54:40 +03001956 return false;
1957 }
1958
1959 if (!context->isSampler(sampler))
1960 {
Jamie Madill437fa652016-05-03 15:13:24 -04001961 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho37477912016-03-30 14:54:40 +03001962 return false;
1963 }
1964
1965 if (!ValidateSamplerObjectParameter(context, pname))
1966 {
1967 return false;
1968 }
1969
Ian Ewellbda75592016-04-18 17:25:54 -04001970 if (!ValidateTexParamParameters(context, GL_TEXTURE_2D, pname, param))
Olli Etuaho37477912016-03-30 14:54:40 +03001971 {
1972 return false;
1973 }
1974 return true;
1975}
1976
1977bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
1978{
1979 // The only float parameters are MIN_LOD and MAX_LOD. For these any value is permissible, so
1980 // ValidateSamplerParameteri can be used for validation here.
1981 return ValidateSamplerParameteri(context, sampler, pname, static_cast<GLint>(param));
1982}
1983
Olli Etuaho4f667482016-03-30 15:56:35 +03001984bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
1985{
Martin Radev1be913c2016-07-11 17:59:16 +03001986 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001987 {
Jamie Madill437fa652016-05-03 15:13:24 -04001988 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001989 return false;
1990 }
1991
1992 return ValidateGetBufferPointervBase(context, target, pname, params);
1993}
1994
1995bool ValidateUnmapBuffer(Context *context, GLenum target)
1996{
Martin Radev1be913c2016-07-11 17:59:16 +03001997 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001998 {
Jamie Madill437fa652016-05-03 15:13:24 -04001999 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03002000 return false;
2001 }
2002
2003 return ValidateUnmapBufferBase(context, target);
2004}
2005
2006bool ValidateMapBufferRange(Context *context,
2007 GLenum target,
2008 GLintptr offset,
2009 GLsizeiptr length,
2010 GLbitfield access)
2011{
Martin Radev1be913c2016-07-11 17:59:16 +03002012 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002013 {
Jamie Madill437fa652016-05-03 15:13:24 -04002014 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002015 return false;
2016 }
2017
2018 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2019}
2020
2021bool ValidateFlushMappedBufferRange(Context *context,
2022 GLenum target,
2023 GLintptr offset,
2024 GLsizeiptr length)
2025{
Martin Radev1be913c2016-07-11 17:59:16 +03002026 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002027 {
Jamie Madill437fa652016-05-03 15:13:24 -04002028 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002029 return false;
2030 }
2031
2032 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2033}
2034
Martin Radev66fb8202016-07-28 11:45:20 +03002035bool ValidateIndexedStateQuery(ValidationContext *context, GLenum pname, GLuint index)
2036{
2037 GLenum nativeType;
2038 unsigned int numParams;
2039 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2040 {
2041 context->handleError(Error(GL_INVALID_ENUM));
2042 return false;
2043 }
2044
2045 const Caps &caps = context->getCaps();
2046 switch (pname)
2047 {
2048 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2049 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2050 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2051 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2052 {
2053 context->handleError(Error(GL_INVALID_VALUE));
2054 return false;
2055 }
2056 break;
2057
2058 case GL_UNIFORM_BUFFER_START:
2059 case GL_UNIFORM_BUFFER_SIZE:
2060 case GL_UNIFORM_BUFFER_BINDING:
2061 if (index >= caps.maxUniformBufferBindings)
2062 {
2063 context->handleError(Error(GL_INVALID_VALUE));
2064 return false;
2065 }
2066 break;
2067 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2068 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2069 if (index >= 3u)
2070 {
2071 context->handleError(Error(GL_INVALID_VALUE));
2072 return false;
2073 }
2074 break;
2075 default:
2076 context->handleError(Error(GL_INVALID_ENUM));
2077 return false;
2078 }
2079
2080 // pname is valid, but there are no parameters to return
2081 if (numParams == 0)
2082 {
2083 return false;
2084 }
2085
2086 return true;
2087}
2088
2089bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2090{
2091 if (!context->getGLVersion().isES3OrGreater())
2092 {
2093 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2094 return false;
2095 }
2096 return ValidateIndexedStateQuery(context, target, index);
2097}
2098
2099bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2100{
2101 if (!context->getGLVersion().isES3OrGreater())
2102 {
2103 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2104 return false;
2105 }
2106 return ValidateIndexedStateQuery(context, target, index);
2107}
2108
Jamie Madillc29968b2016-01-20 11:17:23 -05002109} // namespace gl