blob: c097059daeeb95cfbea88e38503bde3e9756a2a9 [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"
10#include "libANGLE/validationES.h"
11#include "libANGLE/Context.h"
12#include "libANGLE/Texture.h"
13#include "libANGLE/Framebuffer.h"
14#include "libANGLE/Renderbuffer.h"
15#include "libANGLE/formatutils.h"
16#include "libANGLE/FramebufferAttachment.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040017
18#include "common/mathutil.h"
Geoff Langa9be0dc2014-12-17 12:34:40 -050019#include "common/utilities.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040020
21namespace gl
22{
23
Geoff Lang5d601382014-07-22 15:14:06 -040024struct ES3FormatCombination
25{
26 GLenum internalFormat;
27 GLenum format;
28 GLenum type;
29};
30
31bool operator<(const ES3FormatCombination& a, const ES3FormatCombination& b)
32{
33 return memcmp(&a, &b, sizeof(ES3FormatCombination)) < 0;
34}
35
36typedef std::set<ES3FormatCombination> ES3FormatCombinationSet;
37
38static inline void InsertES3FormatCombo(ES3FormatCombinationSet *set, GLenum internalFormat, GLenum format, GLenum type)
39{
40 ES3FormatCombination info;
41 info.internalFormat = internalFormat;
42 info.format = format;
43 info.type = type;
44 set->insert(info);
45}
46
47ES3FormatCombinationSet BuildES3FormatSet()
48{
49 ES3FormatCombinationSet set;
50
51 // Format combinations from ES 3.0.1 spec, table 3.2
52
53 // | Internal format | Format | Type |
54 // | | | |
55 InsertES3FormatCombo(&set, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE );
56 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE );
57 InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE );
58 InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE );
59 InsertES3FormatCombo(&set, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE );
60 InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 );
61 InsertES3FormatCombo(&set, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV );
62 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV );
63 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 );
64 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT );
65 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT_OES );
66 InsertES3FormatCombo(&set, GL_RGBA32F, GL_RGBA, GL_FLOAT );
67 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_FLOAT );
68 InsertES3FormatCombo(&set, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE );
69 InsertES3FormatCombo(&set, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE );
70 InsertES3FormatCombo(&set, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT );
71 InsertES3FormatCombo(&set, GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT );
72 InsertES3FormatCombo(&set, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT );
73 InsertES3FormatCombo(&set, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT );
74 InsertES3FormatCombo(&set, GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV );
75 InsertES3FormatCombo(&set, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE );
76 InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE );
77 InsertES3FormatCombo(&set, GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE );
78 InsertES3FormatCombo(&set, GL_RGB8_SNORM, GL_RGB, GL_BYTE );
79 InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 );
80 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV );
81 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV );
82 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT );
83 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT_OES );
84 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT );
85 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT_OES );
86 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT );
87 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT_OES );
88 InsertES3FormatCombo(&set, GL_RGB32F, GL_RGB, GL_FLOAT );
89 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_FLOAT );
90 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT );
91 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_FLOAT );
92 InsertES3FormatCombo(&set, GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE );
93 InsertES3FormatCombo(&set, GL_RGB8I, GL_RGB_INTEGER, GL_BYTE );
94 InsertES3FormatCombo(&set, GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT );
95 InsertES3FormatCombo(&set, GL_RGB16I, GL_RGB_INTEGER, GL_SHORT );
96 InsertES3FormatCombo(&set, GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT );
97 InsertES3FormatCombo(&set, GL_RGB32I, GL_RGB_INTEGER, GL_INT );
98 InsertES3FormatCombo(&set, GL_RG8, GL_RG, GL_UNSIGNED_BYTE );
99 InsertES3FormatCombo(&set, GL_RG8_SNORM, GL_RG, GL_BYTE );
100 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT );
101 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT_OES );
102 InsertES3FormatCombo(&set, GL_RG32F, GL_RG, GL_FLOAT );
103 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_FLOAT );
104 InsertES3FormatCombo(&set, GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE );
105 InsertES3FormatCombo(&set, GL_RG8I, GL_RG_INTEGER, GL_BYTE );
106 InsertES3FormatCombo(&set, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT );
107 InsertES3FormatCombo(&set, GL_RG16I, GL_RG_INTEGER, GL_SHORT );
108 InsertES3FormatCombo(&set, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT );
109 InsertES3FormatCombo(&set, GL_RG32I, GL_RG_INTEGER, GL_INT );
110 InsertES3FormatCombo(&set, GL_R8, GL_RED, GL_UNSIGNED_BYTE );
111 InsertES3FormatCombo(&set, GL_R8_SNORM, GL_RED, GL_BYTE );
112 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT );
113 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT_OES );
114 InsertES3FormatCombo(&set, GL_R32F, GL_RED, GL_FLOAT );
115 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_FLOAT );
116 InsertES3FormatCombo(&set, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE );
117 InsertES3FormatCombo(&set, GL_R8I, GL_RED_INTEGER, GL_BYTE );
118 InsertES3FormatCombo(&set, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT );
119 InsertES3FormatCombo(&set, GL_R16I, GL_RED_INTEGER, GL_SHORT );
120 InsertES3FormatCombo(&set, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT );
121 InsertES3FormatCombo(&set, GL_R32I, GL_RED_INTEGER, GL_INT );
122
123 // Unsized formats
124 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE );
125 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 );
126 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 );
127 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE );
128 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 );
129 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE );
130 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE );
131 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE );
132 InsertES3FormatCombo(&set, GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE );
133 InsertES3FormatCombo(&set, GL_SRGB_EXT, GL_SRGB_EXT, GL_UNSIGNED_BYTE );
Jamie Madill689325c2015-07-20 14:36:53 -0400134 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_UNSIGNED_BYTE );
135 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_FLOAT );
136 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_HALF_FLOAT );
137 InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_HALF_FLOAT_OES );
138 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_UNSIGNED_BYTE );
139 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_FLOAT );
140 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_HALF_FLOAT );
141 InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_HALF_FLOAT_OES );
142 InsertES3FormatCombo(&set, GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 );
Geoff Lang5d601382014-07-22 15:14:06 -0400143
144 // Depth stencil formats
145 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT );
146 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
147 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
148 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT );
149 InsertES3FormatCombo(&set, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 );
150 InsertES3FormatCombo(&set, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
151
152 // From GL_EXT_sRGB
153 InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE );
154 InsertES3FormatCombo(&set, GL_SRGB8, GL_SRGB_EXT, GL_UNSIGNED_BYTE );
155
156 // From GL_OES_texture_float
Jeff Muizelaarbb1a5be2015-12-02 12:03:46 -0500157 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_FLOAT );
158 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_FLOAT );
Geoff Lang5d601382014-07-22 15:14:06 -0400159 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT );
160 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT );
161 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_FLOAT );
162
163 // From GL_OES_texture_half_float
164 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT );
165 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES );
166 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT );
167 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES );
168 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT );
169 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES );
170
171 // From GL_EXT_texture_format_BGRA8888
172 InsertES3FormatCombo(&set, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
173
174 // From GL_EXT_texture_storage
175 // | Internal format | Format | Type |
176 // | | | |
177 InsertES3FormatCombo(&set, GL_ALPHA8_EXT, GL_ALPHA, GL_UNSIGNED_BYTE );
178 InsertES3FormatCombo(&set, GL_LUMINANCE8_EXT, GL_LUMINANCE, GL_UNSIGNED_BYTE );
179 InsertES3FormatCombo(&set, GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE );
180 InsertES3FormatCombo(&set, GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT );
181 InsertES3FormatCombo(&set, GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT );
182 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT );
183 InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT );
184 InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT_OES );
185 InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT );
186 InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT_OES );
187 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT );
188 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES );
189
190 // From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888
191 InsertES3FormatCombo(&set, GL_BGRA8_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
192 InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT);
193 InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
194 InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT);
195 InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
196
197 // From GL_ANGLE_depth_texture
198 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8_OES );
199
Geoff Lang5d601382014-07-22 15:14:06 -0400200 return set;
201}
202
203static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
204{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500205 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
206 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
207 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
208 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
Geoff Langbaadf232014-08-04 13:58:02 -0400209 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400210 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
211 {
Jamie Madill437fa652016-05-03 15:13:24 -0400212 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400213 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400214 }
215
216 // The type and format are valid if any supported internal format has that type and format
217 bool formatSupported = false;
218 bool typeSupported = false;
219
220 static const ES3FormatCombinationSet es3FormatSet = BuildES3FormatSet();
221 for (ES3FormatCombinationSet::const_iterator i = es3FormatSet.begin(); i != es3FormatSet.end(); i++)
222 {
223 if (i->format == format || i->type == type)
224 {
225 const gl::InternalFormat &info = gl::GetInternalFormatInfo(i->internalFormat);
226 bool supported = info.textureSupport(context->getClientVersion(), context->getExtensions());
Geoff Langbaadf232014-08-04 13:58:02 -0400227 if (supported && i->type == type)
Geoff Lang5d601382014-07-22 15:14:06 -0400228 {
229 typeSupported = true;
230 }
Geoff Langbaadf232014-08-04 13:58:02 -0400231 if (supported && i->format == format)
Geoff Lang5d601382014-07-22 15:14:06 -0400232 {
233 formatSupported = true;
234 }
Geoff Langbaadf232014-08-04 13:58:02 -0400235
236 // Early-out if both type and format are supported now
237 if (typeSupported && formatSupported)
238 {
239 break;
240 }
Geoff Lang5d601382014-07-22 15:14:06 -0400241 }
242 }
243
244 if (!typeSupported || !formatSupported)
245 {
Jamie Madill437fa652016-05-03 15:13:24 -0400246 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400247 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400248 }
249
250 // Check if this is a valid format combination to load texture data
251 ES3FormatCombination searchFormat;
252 searchFormat.internalFormat = internalFormat;
253 searchFormat.format = format;
254 searchFormat.type = type;
255
256 if (es3FormatSet.find(searchFormat) == es3FormatSet.end())
257 {
Jamie Madill437fa652016-05-03 15:13:24 -0400258 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400259 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400260 }
261
262 return true;
263}
264
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500265bool ValidateES3TexImageParametersBase(Context *context,
266 GLenum target,
267 GLint level,
268 GLenum internalformat,
269 bool isCompressed,
270 bool isSubImage,
271 GLint xoffset,
272 GLint yoffset,
273 GLint zoffset,
274 GLsizei width,
275 GLsizei height,
276 GLsizei depth,
277 GLint border,
278 GLenum format,
279 GLenum type,
280 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400281{
282 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -0700283 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400284 {
Jamie Madill437fa652016-05-03 15:13:24 -0400285 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400286 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400287 }
288
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400289 // Verify zero border
290 if (border != 0)
291 {
Jamie Madill437fa652016-05-03 15:13:24 -0400292 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400293 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400294 }
295
Jamie Madill6f38f822014-06-06 17:12:20 -0400296 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
297 std::numeric_limits<GLsizei>::max() - xoffset < width ||
298 std::numeric_limits<GLsizei>::max() - yoffset < height ||
299 std::numeric_limits<GLsizei>::max() - zoffset < depth)
300 {
Jamie Madill437fa652016-05-03 15:13:24 -0400301 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400302 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400303 }
304
Geoff Langaae65a42014-05-26 12:43:44 -0400305 const gl::Caps &caps = context->getCaps();
306
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400307 switch (target)
308 {
309 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500310 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
311 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400312 {
Jamie Madill437fa652016-05-03 15:13:24 -0400313 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500314 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400315 }
316 break;
317
318 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
319 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
320 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
321 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
322 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
323 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500324 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400325 {
Jamie Madill437fa652016-05-03 15:13:24 -0400326 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500327 return false;
328 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400329
Geoff Langa9be0dc2014-12-17 12:34:40 -0500330 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
331 {
Jamie Madill437fa652016-05-03 15:13:24 -0400332 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500333 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400334 }
335 break;
336
337 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500338 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
339 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
340 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400341 {
Jamie Madill437fa652016-05-03 15:13:24 -0400342 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500343 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400344 }
345 break;
346
Geoff Langa9be0dc2014-12-17 12:34:40 -0500347 case GL_TEXTURE_2D_ARRAY:
348 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
349 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
Geoff Langb92c1332015-09-04 12:54:55 -0400350 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500351 {
Jamie Madill437fa652016-05-03 15:13:24 -0400352 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500353 return false;
354 }
355 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400356
357 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400358 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400359 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400360 }
361
Geoff Lang691e58c2014-12-19 17:03:25 -0500362 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400363 if (!texture)
364 {
Jamie Madill437fa652016-05-03 15:13:24 -0400365 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400366 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400367 }
368
Geoff Lang69cce582015-09-17 13:20:36 -0400369 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400370 {
Jamie Madill437fa652016-05-03 15:13:24 -0400371 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400372 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400373 }
374
375 // Validate texture formats
Geoff Langa9be0dc2014-12-17 12:34:40 -0500376 GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat;
Geoff Lang5d601382014-07-22 15:14:06 -0400377 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400378 if (isCompressed)
379 {
tmartino7c102692015-10-02 16:43:40 -0400380 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400381 {
Jamie Madill437fa652016-05-03 15:13:24 -0400382 context->handleError(Error(
tmartino7c102692015-10-02 16:43:40 -0400383 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format."));
Geoff Langb1196682014-07-23 13:47:29 -0400384 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400385 }
386
tmartino7c102692015-10-02 16:43:40 -0400387 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400388 {
Jamie Madill437fa652016-05-03 15:13:24 -0400389 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400390 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400391 }
392
Geoff Lang839ce0b2015-10-23 13:13:12 -0400393 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
394 {
Jamie Madill437fa652016-05-03 15:13:24 -0400395 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang839ce0b2015-10-23 13:13:12 -0400396 return false;
397 }
398
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400399 if (target == GL_TEXTURE_3D)
400 {
Jamie Madill437fa652016-05-03 15:13:24 -0400401 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400402 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400403 }
404 }
405 else
406 {
Geoff Langbaadf232014-08-04 13:58:02 -0400407 if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400408 {
Geoff Lang5d601382014-07-22 15:14:06 -0400409 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400410 }
411
412 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
413 {
Jamie Madill437fa652016-05-03 15:13:24 -0400414 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400415 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400416 }
417 }
418
419 // Validate sub image parameters
420 if (isSubImage)
421 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500422 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400423 {
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
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400428 if (width == 0 || height == 0 || depth == 0)
429 {
430 return false;
431 }
432
433 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
434 {
Jamie Madill437fa652016-05-03 15:13:24 -0400435 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400436 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400437 }
438
439 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
440 std::numeric_limits<GLsizei>::max() - yoffset < height ||
441 std::numeric_limits<GLsizei>::max() - zoffset < depth)
442 {
Jamie Madill437fa652016-05-03 15:13:24 -0400443 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400444 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400445 }
446
Geoff Langa9be0dc2014-12-17 12:34:40 -0500447 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
448 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
449 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400450 {
Jamie Madill437fa652016-05-03 15:13:24 -0400451 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400452 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400453 }
454 }
455
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400456 // Check for pixel unpack buffer related API errors
Shannon Woods53a94a82014-06-24 15:20:36 -0400457 gl::Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400458 if (pixelUnpackBuffer != NULL)
459 {
460 // ...the data would be unpacked from the buffer object such that the memory reads required
461 // would exceed the data store size.
462 size_t widthSize = static_cast<size_t>(width);
463 size_t heightSize = static_cast<size_t>(height);
464 size_t depthSize = static_cast<size_t>(depth);
Geoff Lang5d601382014-07-22 15:14:06 -0400465 GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type);
Jamie Madill6f38f822014-06-06 17:12:20 -0400466
Geoff Lang5d601382014-07-22 15:14:06 -0400467 size_t pixelBytes = static_cast<size_t>(gl::GetInternalFormatInfo(sizedFormat).pixelBytes);
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400468
469 if (!rx::IsUnsignedMultiplicationSafe(widthSize, heightSize) ||
470 !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize, depthSize) ||
471 !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize * depthSize, pixelBytes))
472 {
473 // Overflow past the end of the buffer
Jamie Madill437fa652016-05-03 15:13:24 -0400474 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400475 return false;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400476 }
477
Jamie Madillc751d1e2014-10-21 17:46:29 -0400478 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
479 size_t copyBytes = formatInfo.computeBlockSize(type, width, height);
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400480 size_t offset = reinterpret_cast<size_t>(pixels);
481
Jamie Madill6f38f822014-06-06 17:12:20 -0400482 if (!rx::IsUnsignedAdditionSafe(offset, copyBytes) ||
Brandon Jonesd38f9262014-06-18 16:26:45 -0700483 ((offset + copyBytes) > static_cast<size_t>(pixelUnpackBuffer->getSize())))
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400484 {
485 // Overflow past the end of the buffer
Jamie Madill437fa652016-05-03 15:13:24 -0400486 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400487 return false;
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400488 }
489
490 // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
491 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400492 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400493 {
Jamie Madillc751d1e2014-10-21 17:46:29 -0400494 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
495
496 if ((offset % dataBytesPerPixel) != 0)
497 {
Jamie Madill437fa652016-05-03 15:13:24 -0400498 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400499 return false;
500 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400501 }
502
Jamie Madill7a5f7382014-03-05 15:01:24 -0500503 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700504 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500505 {
Jamie Madill437fa652016-05-03 15:13:24 -0400506 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400507 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500508 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400509 }
510
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400511 return true;
512}
513
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500514bool ValidateES3TexImage2DParameters(Context *context,
515 GLenum target,
516 GLint level,
517 GLenum internalformat,
518 bool isCompressed,
519 bool isSubImage,
520 GLint xoffset,
521 GLint yoffset,
522 GLint zoffset,
523 GLsizei width,
524 GLsizei height,
525 GLsizei depth,
526 GLint border,
527 GLenum format,
528 GLenum type,
529 const GLvoid *pixels)
530{
531 if (!ValidTexture2DDestinationTarget(context, target))
532 {
Jamie Madill437fa652016-05-03 15:13:24 -0400533 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500534 return false;
535 }
536
537 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
538 isSubImage, xoffset, yoffset, zoffset, width, height,
539 depth, border, format, type, pixels);
540}
541
542bool ValidateES3TexImage3DParameters(Context *context,
543 GLenum target,
544 GLint level,
545 GLenum internalformat,
546 bool isCompressed,
547 bool isSubImage,
548 GLint xoffset,
549 GLint yoffset,
550 GLint zoffset,
551 GLsizei width,
552 GLsizei height,
553 GLsizei depth,
554 GLint border,
555 GLenum format,
556 GLenum type,
557 const GLvoid *pixels)
558{
559 if (!ValidTexture3DDestinationTarget(context, target))
560 {
Jamie Madill437fa652016-05-03 15:13:24 -0400561 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500562 return false;
563 }
564
565 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
566 isSubImage, xoffset, yoffset, zoffset, width, height,
567 depth, border, format, type, pixels);
568}
569
Geoff Lang5d601382014-07-22 15:14:06 -0400570struct EffectiveInternalFormatInfo
571{
572 GLenum mEffectiveFormat;
573 GLenum mDestFormat;
574 GLuint mMinRedBits;
575 GLuint mMaxRedBits;
576 GLuint mMinGreenBits;
577 GLuint mMaxGreenBits;
578 GLuint mMinBlueBits;
579 GLuint mMaxBlueBits;
580 GLuint mMinAlphaBits;
581 GLuint mMaxAlphaBits;
582
583 EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits,
584 GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits,
585 GLuint minAlphaBits, GLuint maxAlphaBits)
586 : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits),
587 mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits),
588 mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits),
589 mMaxAlphaBits(maxAlphaBits) {};
590};
591
592typedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
593
594static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList()
595{
596 EffectiveInternalFormatList list;
597
598 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
599 // linear source buffer component sizes.
600 // | Source channel min/max sizes |
601 // Effective Internal Format | N/A | R | G | B | A |
602 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8));
603 list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0));
604 list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0));
605 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0));
606 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0));
607 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4));
608 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1));
609 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8));
610 list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2));
611
612 return list;
613}
614
615static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList()
616{
617 EffectiveInternalFormatList list;
618
619 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
620 // linear source buffer component sizes.
621 // | Source channel min/max sizes |
622 // Effective Internal Format | Dest Format | R | G | B | A |
623 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
624 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX));
625 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
626 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX));
627 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX));
628 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4));
629 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1));
630 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8));
631
632 return list;
633}
634
635static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
636 GLenum *outEffectiveFormat)
637{
638 const EffectiveInternalFormatList *list = NULL;
639 GLenum targetFormat = GL_NONE;
640
641 if (destFormat.pixelBytes > 0)
642 {
643 static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList();
644 list = &sizedList;
645 }
646 else
647 {
648 static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList();
649 list = &unsizedList;
650 targetFormat = destFormat.format;
651 }
652
653 for (size_t curFormat = 0; curFormat < list->size(); ++curFormat)
654 {
655 const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat);
656 if ((formatInfo.mDestFormat == targetFormat) &&
657 (formatInfo.mMinRedBits <= srcFormat.redBits && formatInfo.mMaxRedBits >= srcFormat.redBits) &&
658 (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) &&
659 (formatInfo.mMinBlueBits <= srcFormat.blueBits && formatInfo.mMaxBlueBits >= srcFormat.blueBits) &&
660 (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits))
661 {
662 *outEffectiveFormat = formatInfo.mEffectiveFormat;
663 return true;
664 }
665 }
666
667 return false;
668}
669
670struct CopyConversion
671{
672 GLenum mTextureFormat;
673 GLenum mFramebufferFormat;
674
675 CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
676 : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
677
678 bool operator<(const CopyConversion& other) const
679 {
680 return memcmp(this, &other, sizeof(CopyConversion)) < 0;
681 }
682};
683
684typedef std::set<CopyConversion> CopyConversionSet;
685
686static CopyConversionSet BuildValidES3CopyTexImageCombinations()
687{
688 CopyConversionSet set;
689
690 // From ES 3.0.1 spec, table 3.15
691 set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
692 set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
693 set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
694 set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
695 set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
696 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
697 set.insert(CopyConversion(GL_RED, GL_RED));
698 set.insert(CopyConversion(GL_RED, GL_RG));
699 set.insert(CopyConversion(GL_RED, GL_RGB));
700 set.insert(CopyConversion(GL_RED, GL_RGBA));
701 set.insert(CopyConversion(GL_RG, GL_RG));
702 set.insert(CopyConversion(GL_RG, GL_RGB));
703 set.insert(CopyConversion(GL_RG, GL_RGBA));
704 set.insert(CopyConversion(GL_RGB, GL_RGB));
705 set.insert(CopyConversion(GL_RGB, GL_RGBA));
706 set.insert(CopyConversion(GL_RGBA, GL_RGBA));
707
708 // Necessary for ANGLE back-buffers
709 set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
710 set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
711 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
712 set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
713 set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
714 set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
715 set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
716
717 set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
718 set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
719 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
720 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
721 set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
722 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
723 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
724 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
725 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
726 set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
727
728 return set;
729}
730
Corentin Wallez76287682016-04-25 09:23:38 -0400731static bool EqualOrFirstZero(GLuint first, GLuint second)
732{
733 return first == 0 || first == second;
734}
735
Geoff Lang5d601382014-07-22 15:14:06 -0400736static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle)
737{
738 const InternalFormat &textureInternalFormatInfo = GetInternalFormatInfo(textureInternalFormat);
739 const InternalFormat &framebufferInternalFormatInfo = GetInternalFormatInfo(frameBufferInternalFormat);
740
741 static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
742 if (conversionSet.find(CopyConversion(textureInternalFormatInfo.format, framebufferInternalFormatInfo.format)) != conversionSet.end())
743 {
744 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
745 // must both be signed, unsigned, or fixed point and both source and destinations
746 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
747 // conversion between fixed and floating point.
748
749 if ((textureInternalFormatInfo.colorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.colorEncoding == GL_SRGB))
750 {
751 return false;
752 }
753
754 if (((textureInternalFormatInfo.componentType == GL_INT) != (framebufferInternalFormatInfo.componentType == GL_INT )) ||
755 ((textureInternalFormatInfo.componentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.componentType == GL_UNSIGNED_INT)))
756 {
757 return false;
758 }
759
760 if ((textureInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
761 textureInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
762 textureInternalFormatInfo.componentType == GL_FLOAT) &&
763 !(framebufferInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
764 framebufferInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
765 framebufferInternalFormatInfo.componentType == GL_FLOAT))
766 {
767 return false;
768 }
769
770 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
771 // The effective internal format of the source buffer is determined with the following rules applied in order:
772 // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
773 // effective internal format is the source buffer's sized internal format.
774 // * If the source buffer is a texture that was created with an unsized base internal format, then the
775 // effective internal format is the source image array's effective internal format, as specified by table
776 // 3.12, which is determined from the <format> and <type> that were used when the source image array was
777 // specified by TexImage*.
778 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
779 // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
780 // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
781 // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
782 // is SRGB.
783 const InternalFormat *sourceEffectiveFormat = NULL;
784 if (readBufferHandle != 0)
785 {
786 // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
787 if (framebufferInternalFormatInfo.pixelBytes > 0)
788 {
789 sourceEffectiveFormat = &framebufferInternalFormatInfo;
790 }
791 else
792 {
793 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
794 // texture. We can use the same table we use when creating textures to get its effective sized format.
Geoff Lang051dbc72015-01-05 15:48:58 -0500795 GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type);
796 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400797 }
798 }
799 else
800 {
801 // The effective internal format must be derived from the source framebuffer's channel sizes.
802 // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
803 if (framebufferInternalFormatInfo.colorEncoding == GL_LINEAR)
804 {
805 GLenum effectiveFormat;
806 if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat))
807 {
808 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
809 }
810 else
811 {
812 return false;
813 }
814 }
815 else if (framebufferInternalFormatInfo.colorEncoding == GL_SRGB)
816 {
817 // SRGB buffers can only be copied to sized format destinations according to table 3.18
818 if ((textureInternalFormatInfo.pixelBytes > 0) &&
819 (framebufferInternalFormatInfo.redBits >= 1 && framebufferInternalFormatInfo.redBits <= 8) &&
820 (framebufferInternalFormatInfo.greenBits >= 1 && framebufferInternalFormatInfo.greenBits <= 8) &&
821 (framebufferInternalFormatInfo.blueBits >= 1 && framebufferInternalFormatInfo.blueBits <= 8) &&
822 (framebufferInternalFormatInfo.alphaBits >= 1 && framebufferInternalFormatInfo.alphaBits <= 8))
823 {
824 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
825 }
826 else
827 {
828 return false;
829 }
830 }
831 else
832 {
833 UNREACHABLE();
834 return false;
835 }
836 }
837
838 if (textureInternalFormatInfo.pixelBytes > 0)
839 {
Corentin Wallez76287682016-04-25 09:23:38 -0400840 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination
841 // format is sized, component sizes of the source and destination formats must exactly
842 // match if the destination format exists.
843 if (!EqualOrFirstZero(textureInternalFormatInfo.redBits,
844 sourceEffectiveFormat->redBits) ||
845 !EqualOrFirstZero(textureInternalFormatInfo.greenBits,
846 sourceEffectiveFormat->greenBits) ||
847 !EqualOrFirstZero(textureInternalFormatInfo.blueBits,
848 sourceEffectiveFormat->blueBits) ||
849 !EqualOrFirstZero(textureInternalFormatInfo.alphaBits,
850 sourceEffectiveFormat->alphaBits))
Geoff Lang5d601382014-07-22 15:14:06 -0400851 {
852 return false;
853 }
854 }
855
856
857 return true; // A conversion function exists, and no rule in the specification has precluded conversion
858 // between these formats.
859 }
860
861 return false;
862}
863
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500864bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
865 GLenum target,
866 GLint level,
867 GLenum internalformat,
868 bool isSubImage,
869 GLint xoffset,
870 GLint yoffset,
871 GLint zoffset,
872 GLint x,
873 GLint y,
874 GLsizei width,
875 GLsizei height,
876 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400877{
Jamie Madill560a8d82014-05-21 13:06:20 -0400878 GLenum textureInternalFormat;
879 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill6f38f822014-06-06 17:12:20 -0400880 xoffset, yoffset, zoffset, x, y, width, height,
881 border, &textureInternalFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400882 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400883 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400884 }
885
Jamie Madillc29968b2016-01-20 11:17:23 -0500886 const auto &state = context->getState();
887 const gl::Framebuffer *framebuffer = state.getReadFramebuffer();
888 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400889
Geoff Lang748f74e2014-12-01 11:25:34 -0500890 if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400891 {
Jamie Madill437fa652016-05-03 15:13:24 -0400892 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400893 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400894 }
895
Jamie Madillc29968b2016-01-20 11:17:23 -0500896 if (readFramebufferID != 0 && framebuffer->getSamples(context->getData()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400897 {
Jamie Madill437fa652016-05-03 15:13:24 -0400898 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400899 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400900 }
901
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400902 const gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400903 GLenum colorbufferInternalFormat = source->getInternalFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400904
905 if (isSubImage)
906 {
Geoff Lang5d601382014-07-22 15:14:06 -0400907 if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat,
Jamie Madillc29968b2016-01-20 11:17:23 -0500908 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400909 {
Jamie Madill437fa652016-05-03 15:13:24 -0400910 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400911 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400912 }
913 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400914 else
915 {
Geoff Lang5d601382014-07-22 15:14:06 -0400916 if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat,
Jamie Madillc29968b2016-01-20 11:17:23 -0500917 readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400918 {
Jamie Madill437fa652016-05-03 15:13:24 -0400919 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400920 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400921 }
922 }
923
Geoff Lang784a8fd2013-09-24 12:33:16 -0400924 // If width or height is zero, it is a no-op. Return false without setting an error.
925 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400926}
927
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500928bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
929 GLenum target,
930 GLint level,
931 GLenum internalformat,
932 bool isSubImage,
933 GLint xoffset,
934 GLint yoffset,
935 GLint zoffset,
936 GLint x,
937 GLint y,
938 GLsizei width,
939 GLsizei height,
940 GLint border)
941{
942 if (!ValidTexture2DDestinationTarget(context, target))
943 {
Jamie Madill437fa652016-05-03 15:13:24 -0400944 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500945 return false;
946 }
947
948 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
949 xoffset, yoffset, zoffset, x, y, width, height,
950 border);
951}
952
953bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
954 GLenum target,
955 GLint level,
956 GLenum internalformat,
957 bool isSubImage,
958 GLint xoffset,
959 GLint yoffset,
960 GLint zoffset,
961 GLint x,
962 GLint y,
963 GLsizei width,
964 GLsizei height,
965 GLint border)
966{
967 if (!ValidTexture3DDestinationTarget(context, target))
968 {
Jamie Madill437fa652016-05-03 15:13:24 -0400969 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500970 return false;
971 }
972
973 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
974 xoffset, yoffset, zoffset, x, y, width, height,
975 border);
976}
977
978bool ValidateES3TexStorageParametersBase(Context *context,
979 GLenum target,
980 GLsizei levels,
981 GLenum internalformat,
982 GLsizei width,
983 GLsizei height,
984 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400985{
986 if (width < 1 || height < 1 || depth < 1 || levels < 1)
987 {
Jamie Madill437fa652016-05-03 15:13:24 -0400988 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400989 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400990 }
991
Geoff Langb92c1332015-09-04 12:54:55 -0400992 GLsizei maxDim = std::max(width, height);
993 if (target != GL_TEXTURE_2D_ARRAY)
994 {
995 maxDim = std::max(maxDim, depth);
996 }
997
998 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400999 {
Jamie Madill437fa652016-05-03 15:13:24 -04001000 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001001 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001002 }
1003
Geoff Langaae65a42014-05-26 12:43:44 -04001004 const gl::Caps &caps = context->getCaps();
1005
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001006 switch (target)
1007 {
1008 case GL_TEXTURE_2D:
1009 {
Geoff Langaae65a42014-05-26 12:43:44 -04001010 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1011 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001012 {
Jamie Madill437fa652016-05-03 15:13:24 -04001013 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001014 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001015 }
1016 }
1017 break;
1018
Geoff Lang01c21d22013-09-24 11:52:16 -04001019 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001020 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001021 if (width != height)
1022 {
Jamie Madill437fa652016-05-03 15:13:24 -04001023 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001024 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001025 }
1026
Geoff Langaae65a42014-05-26 12:43:44 -04001027 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001028 {
Jamie Madill437fa652016-05-03 15:13:24 -04001029 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001030 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001031 }
1032 }
1033 break;
1034
1035 case GL_TEXTURE_3D:
1036 {
Geoff Langaae65a42014-05-26 12:43:44 -04001037 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
1038 static_cast<GLuint>(height) > caps.max3DTextureSize ||
1039 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001040 {
Jamie Madill437fa652016-05-03 15:13:24 -04001041 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001042 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001043 }
1044 }
1045 break;
1046
1047 case GL_TEXTURE_2D_ARRAY:
1048 {
Geoff Langaae65a42014-05-26 12:43:44 -04001049 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1050 static_cast<GLuint>(height) > caps.max2DTextureSize ||
1051 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001052 {
Jamie Madill437fa652016-05-03 15:13:24 -04001053 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001054 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001055 }
1056 }
1057 break;
1058
1059 default:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001060 UNREACHABLE();
Geoff Langb1196682014-07-23 13:47:29 -04001061 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001062 }
1063
Geoff Lang691e58c2014-12-19 17:03:25 -05001064 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001065 if (!texture || texture->id() == 0)
1066 {
Jamie Madill437fa652016-05-03 15:13:24 -04001067 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001068 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001069 }
1070
Geoff Lang69cce582015-09-17 13:20:36 -04001071 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001072 {
Jamie Madill437fa652016-05-03 15:13:24 -04001073 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001074 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001075 }
1076
Geoff Lang5d601382014-07-22 15:14:06 -04001077 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1078 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001079 {
Jamie Madill437fa652016-05-03 15:13:24 -04001080 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001081 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001082 }
1083
Geoff Lang5d601382014-07-22 15:14:06 -04001084 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001085 {
Jamie Madill437fa652016-05-03 15:13:24 -04001086 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001087 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001088 }
1089
1090 return true;
1091}
1092
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001093bool ValidateES3TexStorage2DParameters(Context *context,
1094 GLenum target,
1095 GLsizei levels,
1096 GLenum internalformat,
1097 GLsizei width,
1098 GLsizei height,
1099 GLsizei depth)
1100{
1101 if (!ValidTexture2DTarget(context, target))
1102 {
Jamie Madill437fa652016-05-03 15:13:24 -04001103 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001104 return false;
1105 }
1106
1107 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1108 height, depth);
1109}
1110
1111bool ValidateES3TexStorage3DParameters(Context *context,
1112 GLenum target,
1113 GLsizei levels,
1114 GLenum internalformat,
1115 GLsizei width,
1116 GLsizei height,
1117 GLsizei depth)
1118{
1119 if (!ValidTexture3DTarget(context, target))
1120 {
Jamie Madill437fa652016-05-03 15:13:24 -04001121 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001122 return false;
1123 }
1124
1125 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1126 height, depth);
1127}
1128
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001129bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1130{
1131 if (context->getClientVersion() < 3)
1132 {
Jamie Madill437fa652016-05-03 15:13:24 -04001133 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001134 return false;
1135 }
1136
1137 return ValidateBeginQueryBase(context, target, id);
1138}
1139
1140bool ValidateEndQuery(gl::Context *context, GLenum target)
1141{
1142 if (context->getClientVersion() < 3)
1143 {
Jamie Madill437fa652016-05-03 15:13:24 -04001144 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001145 return false;
1146 }
1147
1148 return ValidateEndQueryBase(context, target);
1149}
1150
1151bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1152{
1153 if (context->getClientVersion() < 3)
1154 {
Jamie Madill437fa652016-05-03 15:13:24 -04001155 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001156 return false;
1157 }
1158
1159 return ValidateGetQueryivBase(context, target, pname);
1160}
1161
1162bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1163{
1164 if (context->getClientVersion() < 3)
1165 {
Jamie Madill437fa652016-05-03 15:13:24 -04001166 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001167 return false;
1168 }
1169
1170 return ValidateGetQueryObjectValueBase(context, id, pname);
1171}
1172
Geoff Langb1196682014-07-23 13:47:29 -04001173bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
Jamie Madill570f7c82014-07-03 10:38:54 -04001174 GLuint texture, GLint level, GLint layer)
1175{
1176 if (context->getClientVersion() < 3)
1177 {
Jamie Madill437fa652016-05-03 15:13:24 -04001178 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001179 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001180 }
1181
Jamie Madill55ec3b12014-07-03 10:38:57 -04001182 if (layer < 0)
1183 {
Jamie Madill437fa652016-05-03 15:13:24 -04001184 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001185 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001186 }
1187
1188 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1189 {
1190 return false;
1191 }
1192
1193 const gl::Caps &caps = context->getCaps();
1194 if (texture != 0)
1195 {
1196 gl::Texture *tex = context->getTexture(texture);
1197 ASSERT(tex);
1198
1199 switch (tex->getTarget())
1200 {
1201 case GL_TEXTURE_2D_ARRAY:
1202 {
1203 if (level > gl::log2(caps.max2DTextureSize))
1204 {
Jamie Madill437fa652016-05-03 15:13:24 -04001205 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001206 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001207 }
1208
1209 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1210 {
Jamie Madill437fa652016-05-03 15:13:24 -04001211 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001212 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001213 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001214 }
1215 break;
1216
1217 case GL_TEXTURE_3D:
1218 {
1219 if (level > gl::log2(caps.max3DTextureSize))
1220 {
Jamie Madill437fa652016-05-03 15:13:24 -04001221 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001222 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001223 }
1224
1225 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1226 {
Jamie Madill437fa652016-05-03 15:13:24 -04001227 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001228 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001229 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001230 }
1231 break;
1232
1233 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001234 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001235 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001236 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001237
1238 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(tex->getTarget(), level));
1239 if (internalFormatInfo.compressed)
1240 {
Jamie Madill437fa652016-05-03 15:13:24 -04001241 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001242 return false;
1243 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001244 }
1245
1246 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001247}
1248
Geoff Langb1196682014-07-23 13:47:29 -04001249bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001250{
Geoff Lang5d601382014-07-22 15:14:06 -04001251 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
1252
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001253 switch (format)
1254 {
1255 case GL_RGBA:
1256 switch (type)
1257 {
1258 case GL_UNSIGNED_BYTE:
1259 break;
1260 case GL_UNSIGNED_INT_2_10_10_10_REV:
1261 if (internalFormat != GL_RGB10_A2)
1262 {
1263 return false;
1264 }
1265 break;
Geoff Lang1ec57f82013-10-16 11:43:23 -04001266 case GL_FLOAT:
Geoff Lang5d601382014-07-22 15:14:06 -04001267 if (internalFormatInfo.componentType != GL_FLOAT)
Geoff Lang1ec57f82013-10-16 11:43:23 -04001268 {
1269 return false;
1270 }
1271 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001272 default:
1273 return false;
1274 }
1275 break;
1276 case GL_RGBA_INTEGER:
1277 switch (type)
1278 {
1279 case GL_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001280 if (internalFormatInfo.componentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001281 {
1282 return false;
1283 }
1284 break;
1285 case GL_UNSIGNED_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001286 if (internalFormatInfo.componentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001287 {
1288 return false;
1289 }
1290 break;
1291 default:
1292 return false;
1293 }
1294 break;
1295 case GL_BGRA_EXT:
1296 switch (type)
1297 {
1298 case GL_UNSIGNED_BYTE:
1299 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1300 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1301 break;
1302 default:
1303 return false;
1304 }
1305 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001306 case GL_RG_EXT:
1307 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001308 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001309 {
1310 return false;
1311 }
1312 switch (type)
1313 {
1314 case GL_UNSIGNED_BYTE:
1315 break;
1316 default:
1317 return false;
1318 }
1319 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001320 default:
1321 return false;
1322 }
1323 return true;
1324}
1325
Corentin Walleze0902642014-11-04 12:32:15 -08001326bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
1327 GLenum internalformat, GLsizei width, GLsizei height)
1328{
1329 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
1330 {
1331 return false;
1332 }
1333
1334 //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.
1335 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1336 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
1337 {
Jamie Madill437fa652016-05-03 15:13:24 -04001338 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -08001339 return false;
1340 }
1341
1342 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
1343 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1344 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1345 {
Jamie Madill437fa652016-05-03 15:13:24 -04001346 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001347 Error(GL_INVALID_OPERATION,
1348 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001349 return false;
1350 }
1351
1352 return true;
1353}
1354
Austin Kinross08332632015-05-05 13:35:47 -07001355bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
1356 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001357{
Austin Kinross08332632015-05-05 13:35:47 -07001358 if (context->getClientVersion() < 3)
1359 {
Jamie Madill437fa652016-05-03 15:13:24 -04001360 context->handleError(
1361 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001362 return false;
1363 }
1364
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001365 bool defaultFramebuffer = false;
1366
1367 switch (target)
1368 {
1369 case GL_DRAW_FRAMEBUFFER:
1370 case GL_FRAMEBUFFER:
Shannon Woods53a94a82014-06-24 15:20:36 -04001371 defaultFramebuffer = context->getState().getDrawFramebuffer()->id() == 0;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001372 break;
1373 case GL_READ_FRAMEBUFFER:
Shannon Woods53a94a82014-06-24 15:20:36 -04001374 defaultFramebuffer = context->getState().getReadFramebuffer()->id() == 0;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001375 break;
1376 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001377 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001378 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001379 }
1380
Austin Kinross08332632015-05-05 13:35:47 -07001381 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001382}
1383
Jamie Madillc29968b2016-01-20 11:17:23 -05001384bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001385{
1386 if (context->getClientVersion() < 3)
1387 {
Jamie Madill437fa652016-05-03 15:13:24 -04001388 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001389 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001390 }
1391
Shannon Woods53a94a82014-06-24 15:20:36 -04001392 const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer();
Geoff Lang748f74e2014-12-01 11:25:34 -05001393 if (!fbo || fbo->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001394 {
Jamie Madill437fa652016-05-03 15:13:24 -04001395 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001396 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001397 }
1398
1399 return true;
1400}
1401
Olli Etuaho71dfb362016-03-10 14:04:27 +02001402bool ValidateDrawRangeElements(Context *context,
1403 GLenum mode,
1404 GLuint start,
1405 GLuint end,
1406 GLsizei count,
1407 GLenum type,
1408 const GLvoid *indices,
1409 IndexRange *indexRange)
1410{
1411 if (context->getClientVersion() < 3)
1412 {
Jamie Madill437fa652016-05-03 15:13:24 -04001413 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001414 return false;
1415 }
1416
1417 if (end < start)
1418 {
Jamie Madill437fa652016-05-03 15:13:24 -04001419 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001420 return false;
1421 }
1422
1423 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1424 {
1425 return false;
1426 }
1427
1428 if (indexRange->end > end || indexRange->start < start)
1429 {
1430 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001431 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001432 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1433 return false;
1434 }
1435 return true;
1436}
1437
Geoff Langb1196682014-07-23 13:47:29 -04001438bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001439{
1440 if (context->getClientVersion() < 3)
1441 {
Jamie Madill437fa652016-05-03 15:13:24 -04001442 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001443 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001444 }
1445
Jamie Madill78f41802014-08-25 15:47:55 -04001446 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001447}
1448
Jamie Madillb885e572015-02-03 16:16:04 -05001449bool ValidateReadBuffer(Context *context, GLenum src)
1450{
1451 if (context->getClientVersion() < 3)
1452 {
Jamie Madill437fa652016-05-03 15:13:24 -04001453 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001454 return false;
1455 }
1456
1457 Framebuffer *readFBO = context->getState().getReadFramebuffer();
1458
1459 if (readFBO == nullptr)
1460 {
Jamie Madill437fa652016-05-03 15:13:24 -04001461 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001462 return false;
1463 }
1464
1465 if (src == GL_NONE)
1466 {
1467 return true;
1468 }
1469
Olli Etuaho84c9f592016-03-09 14:37:25 +02001470 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001471 {
Jamie Madill437fa652016-05-03 15:13:24 -04001472 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001473 return false;
1474 }
1475
1476 if (readFBO->id() == 0)
1477 {
1478 if (src != GL_BACK)
1479 {
1480 const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001481 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001482 return false;
1483 }
1484 }
1485 else
1486 {
1487 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1488
1489 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1490 {
1491 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001492 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001493 return false;
1494 }
1495 }
1496
1497 return true;
1498}
1499
Jamie Madill86af3d22015-07-21 15:14:07 -04001500bool ValidateCompressedTexImage3D(Context *context,
1501 GLenum target,
1502 GLint level,
1503 GLenum internalformat,
1504 GLsizei width,
1505 GLsizei height,
1506 GLsizei depth,
1507 GLint border,
1508 GLsizei imageSize,
1509 const GLvoid *data)
1510{
1511 if (context->getClientVersion() < 3)
1512 {
Jamie Madill437fa652016-05-03 15:13:24 -04001513 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001514 return false;
1515 }
1516
1517 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
1518 if (imageSize < 0 ||
1519 static_cast<GLuint>(imageSize) !=
1520 formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
1521 {
Jamie Madill437fa652016-05-03 15:13:24 -04001522 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001523 return false;
1524 }
1525
1526 // 3D texture target validation
1527 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1528 {
Jamie Madill437fa652016-05-03 15:13:24 -04001529 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001530 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1531 return false;
1532 }
1533
1534 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001535 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
1536 0, width, height, depth, border, GL_NONE, GL_NONE, data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001537 {
1538 return false;
1539 }
1540
1541 return true;
1542}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001543
1544bool ValidateBindVertexArray(Context *context, GLuint array)
1545{
1546 if (context->getClientVersion() < 3)
1547 {
Jamie Madill437fa652016-05-03 15:13:24 -04001548 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001549 return false;
1550 }
1551
1552 return ValidateBindVertexArrayBase(context, array);
1553}
1554
Austin Kinrossbc781f32015-10-26 09:27:38 -07001555bool ValidateIsVertexArray(Context *context)
1556{
1557 if (context->getClientVersion() < 3)
1558 {
Jamie Madill437fa652016-05-03 15:13:24 -04001559 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001560 return false;
1561 }
1562
1563 return true;
1564}
Geoff Langc5629752015-12-07 16:29:04 -05001565
1566bool ValidateProgramBinary(Context *context,
1567 GLuint program,
1568 GLenum binaryFormat,
1569 const void *binary,
1570 GLint length)
1571{
1572 if (context->getClientVersion() < 3)
1573 {
Jamie Madill437fa652016-05-03 15:13:24 -04001574 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001575 return false;
1576 }
1577
1578 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1579}
1580
1581bool ValidateGetProgramBinary(Context *context,
1582 GLuint program,
1583 GLsizei bufSize,
1584 GLsizei *length,
1585 GLenum *binaryFormat,
1586 void *binary)
1587{
1588 if (context->getClientVersion() < 3)
1589 {
Jamie Madill437fa652016-05-03 15:13:24 -04001590 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001591 return false;
1592 }
1593
1594 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1595}
1596
Olli Etuahof0fee072016-03-30 15:11:58 +03001597bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001598{
1599 if (context->getClientVersion() < 3)
1600 {
Jamie Madill437fa652016-05-03 15:13:24 -04001601 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001602 return false;
1603 }
1604
1605 if (GetValidProgram(context, program) == nullptr)
1606 {
1607 return false;
1608 }
1609
1610 switch (pname)
1611 {
1612 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001613 if (value != GL_FALSE && value != GL_TRUE)
1614 {
Jamie Madill437fa652016-05-03 15:13:24 -04001615 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001616 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1617 return false;
1618 }
Geoff Langc5629752015-12-07 16:29:04 -05001619 break;
1620
1621 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001622 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001623 return false;
1624 }
1625
1626 return true;
1627}
Jamie Madillc29968b2016-01-20 11:17:23 -05001628
1629bool ValidateBlitFramebuffer(Context *context,
1630 GLint srcX0,
1631 GLint srcY0,
1632 GLint srcX1,
1633 GLint srcY1,
1634 GLint dstX0,
1635 GLint dstY0,
1636 GLint dstX1,
1637 GLint dstY1,
1638 GLbitfield mask,
1639 GLenum filter)
1640{
1641 if (context->getClientVersion() < 3)
1642 {
Jamie Madill437fa652016-05-03 15:13:24 -04001643 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001644 return false;
1645 }
1646
1647 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1648 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001649}
Jamie Madillc29968b2016-01-20 11:17:23 -05001650
1651bool ValidateClearBufferiv(ValidationContext *context,
1652 GLenum buffer,
1653 GLint drawbuffer,
1654 const GLint *value)
1655{
1656 switch (buffer)
1657 {
1658 case GL_COLOR:
1659 if (drawbuffer < 0 ||
1660 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1661 {
Jamie Madill437fa652016-05-03 15:13:24 -04001662 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001663 return false;
1664 }
1665 break;
1666
1667 case GL_STENCIL:
1668 if (drawbuffer != 0)
1669 {
Jamie Madill437fa652016-05-03 15:13:24 -04001670 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001671 return false;
1672 }
1673 break;
1674
1675 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001676 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001677 return false;
1678 }
1679
1680 return ValidateClearBuffer(context);
1681}
1682
1683bool ValidateClearBufferuiv(ValidationContext *context,
1684 GLenum buffer,
1685 GLint drawbuffer,
1686 const GLuint *value)
1687{
1688 switch (buffer)
1689 {
1690 case GL_COLOR:
1691 if (drawbuffer < 0 ||
1692 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1693 {
Jamie Madill437fa652016-05-03 15:13:24 -04001694 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001695 return false;
1696 }
1697 break;
1698
1699 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001700 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001701 return false;
1702 }
1703
1704 return ValidateClearBuffer(context);
1705}
1706
1707bool ValidateClearBufferfv(ValidationContext *context,
1708 GLenum buffer,
1709 GLint drawbuffer,
1710 const GLfloat *value)
1711{
1712 switch (buffer)
1713 {
1714 case GL_COLOR:
1715 if (drawbuffer < 0 ||
1716 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1717 {
Jamie Madill437fa652016-05-03 15:13:24 -04001718 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001719 return false;
1720 }
1721 break;
1722
1723 case GL_DEPTH:
1724 if (drawbuffer != 0)
1725 {
Jamie Madill437fa652016-05-03 15:13:24 -04001726 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001727 return false;
1728 }
1729 break;
1730
1731 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001732 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001733 return false;
1734 }
1735
1736 return ValidateClearBuffer(context);
1737}
1738
1739bool ValidateClearBufferfi(ValidationContext *context,
1740 GLenum buffer,
1741 GLint drawbuffer,
1742 GLfloat depth,
1743 GLint stencil)
1744{
1745 switch (buffer)
1746 {
1747 case GL_DEPTH_STENCIL:
1748 if (drawbuffer != 0)
1749 {
Jamie Madill437fa652016-05-03 15:13:24 -04001750 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001751 return false;
1752 }
1753 break;
1754
1755 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001756 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001757 return false;
1758 }
1759
1760 return ValidateClearBuffer(context);
1761}
1762
1763bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1764{
1765 if (context->getClientVersion() < 3)
1766 {
Jamie Madill437fa652016-05-03 15:13:24 -04001767 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001768 return false;
1769 }
1770
1771 return ValidateDrawBuffersBase(context, n, bufs);
1772}
1773
1774bool ValidateCopyTexSubImage3D(Context *context,
1775 GLenum target,
1776 GLint level,
1777 GLint xoffset,
1778 GLint yoffset,
1779 GLint zoffset,
1780 GLint x,
1781 GLint y,
1782 GLsizei width,
1783 GLsizei height)
1784{
1785 if (context->getClientVersion() < 3)
1786 {
Jamie Madill437fa652016-05-03 15:13:24 -04001787 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001788 return false;
1789 }
1790
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001791 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1792 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001793}
1794
Jamie Madill73a84962016-02-12 09:27:23 -05001795bool ValidateTexImage3D(Context *context,
1796 GLenum target,
1797 GLint level,
1798 GLint internalformat,
1799 GLsizei width,
1800 GLsizei height,
1801 GLsizei depth,
1802 GLint border,
1803 GLenum format,
1804 GLenum type,
1805 const GLvoid *pixels)
1806{
1807 if (context->getClientVersion() < 3)
1808 {
Jamie Madill437fa652016-05-03 15:13:24 -04001809 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001810 return false;
1811 }
1812
1813 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1814 0, 0, width, height, depth, border, format, type,
1815 pixels);
1816}
1817
1818bool ValidateTexSubImage3D(Context *context,
1819 GLenum target,
1820 GLint level,
1821 GLint xoffset,
1822 GLint yoffset,
1823 GLint zoffset,
1824 GLsizei width,
1825 GLsizei height,
1826 GLsizei depth,
1827 GLenum format,
1828 GLenum type,
1829 const GLvoid *pixels)
1830{
1831 if (context->getClientVersion() < 3)
1832 {
Jamie Madill437fa652016-05-03 15:13:24 -04001833 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001834 return false;
1835 }
1836
1837 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1838 yoffset, zoffset, width, height, depth, 0, format, type,
1839 pixels);
1840}
1841
1842bool ValidateCompressedTexSubImage3D(Context *context,
1843 GLenum target,
1844 GLint level,
1845 GLint xoffset,
1846 GLint yoffset,
1847 GLint zoffset,
1848 GLsizei width,
1849 GLsizei height,
1850 GLsizei depth,
1851 GLenum format,
1852 GLsizei imageSize,
1853 const GLvoid *data)
1854{
1855 if (context->getClientVersion() < 3)
1856 {
Jamie Madill437fa652016-05-03 15:13:24 -04001857 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001858 return false;
1859 }
1860
1861 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
1862 if (imageSize < 0 ||
1863 static_cast<GLuint>(imageSize) !=
1864 formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
1865 {
Jamie Madill437fa652016-05-03 15:13:24 -04001866 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001867 return false;
1868 }
1869
1870 if (!data)
1871 {
Jamie Madill437fa652016-05-03 15:13:24 -04001872 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001873 return false;
1874 }
1875
1876 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
1877 width, height, depth, 0, GL_NONE, GL_NONE, data);
1878}
1879
Olli Etuaho41997e72016-03-10 13:38:39 +02001880bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1881{
1882 return ValidateGenOrDeleteES3(context, n);
1883}
1884
1885bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1886{
1887 return ValidateGenOrDeleteES3(context, n);
1888}
1889
1890bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1891{
1892 return ValidateGenOrDeleteCountES3(context, count);
1893}
1894
1895bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1896{
1897 return ValidateGenOrDeleteCountES3(context, count);
1898}
1899
1900bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1901{
1902 return ValidateGenOrDeleteES3(context, n);
1903}
1904
1905bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1906{
1907 if (!ValidateGenOrDeleteES3(context, n))
1908 {
1909 return false;
1910 }
1911 for (GLint i = 0; i < n; ++i)
1912 {
1913 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1914 if (transformFeedback != nullptr && transformFeedback->isActive())
1915 {
1916 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001917 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001918 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1919 return false;
1920 }
1921 }
1922 return true;
1923}
1924
1925bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1926{
1927 return ValidateGenOrDeleteES3(context, n);
1928}
1929
1930bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1931{
1932 return ValidateGenOrDeleteES3(context, n);
1933}
1934
1935bool ValidateGenOrDeleteES3(Context *context, GLint n)
1936{
1937 if (context->getClientVersion() < 3)
1938 {
Jamie Madill437fa652016-05-03 15:13:24 -04001939 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001940 return false;
1941 }
1942 return ValidateGenOrDelete(context, n);
1943}
1944
1945bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1946{
1947 if (context->getClientVersion() < 3)
1948 {
Jamie Madill437fa652016-05-03 15:13:24 -04001949 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001950 return false;
1951 }
1952 if (count < 0)
1953 {
Jamie Madill437fa652016-05-03 15:13:24 -04001954 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001955 return false;
1956 }
1957 return true;
1958}
1959
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001960bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1961{
1962 if (context->getClientVersion() < 3)
1963 {
Jamie Madill437fa652016-05-03 15:13:24 -04001964 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001965 return false;
1966 }
1967 switch (primitiveMode)
1968 {
1969 case GL_TRIANGLES:
1970 case GL_LINES:
1971 case GL_POINTS:
1972 break;
1973
1974 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001975 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001976 return false;
1977 }
1978
1979 TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
1980 ASSERT(transformFeedback != nullptr);
1981
1982 if (transformFeedback->isActive())
1983 {
Jamie Madill437fa652016-05-03 15:13:24 -04001984 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001985 return false;
1986 }
1987 return true;
1988}
1989
Olli Etuaho37477912016-03-30 14:54:40 +03001990bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
1991{
1992 if (context->getClientVersion() < 3)
1993 {
Jamie Madill437fa652016-05-03 15:13:24 -04001994 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho37477912016-03-30 14:54:40 +03001995 return false;
1996 }
1997
1998 if (!context->isSampler(sampler))
1999 {
Jamie Madill437fa652016-05-03 15:13:24 -04002000 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho37477912016-03-30 14:54:40 +03002001 return false;
2002 }
2003
2004 if (!ValidateSamplerObjectParameter(context, pname))
2005 {
2006 return false;
2007 }
2008
Ian Ewellbda75592016-04-18 17:25:54 -04002009 if (!ValidateTexParamParameters(context, GL_TEXTURE_2D, pname, param))
Olli Etuaho37477912016-03-30 14:54:40 +03002010 {
2011 return false;
2012 }
2013 return true;
2014}
2015
2016bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
2017{
2018 // The only float parameters are MIN_LOD and MAX_LOD. For these any value is permissible, so
2019 // ValidateSamplerParameteri can be used for validation here.
2020 return ValidateSamplerParameteri(context, sampler, pname, static_cast<GLint>(param));
2021}
2022
Olli Etuaho4f667482016-03-30 15:56:35 +03002023bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
2024{
2025 if (context->getClientVersion() < 3)
2026 {
Jamie Madill437fa652016-05-03 15:13:24 -04002027 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002028 return false;
2029 }
2030
2031 return ValidateGetBufferPointervBase(context, target, pname, params);
2032}
2033
2034bool ValidateUnmapBuffer(Context *context, GLenum target)
2035{
2036 if (context->getClientVersion() < 3)
2037 {
Jamie Madill437fa652016-05-03 15:13:24 -04002038 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03002039 return false;
2040 }
2041
2042 return ValidateUnmapBufferBase(context, target);
2043}
2044
2045bool ValidateMapBufferRange(Context *context,
2046 GLenum target,
2047 GLintptr offset,
2048 GLsizeiptr length,
2049 GLbitfield access)
2050{
2051 if (context->getClientVersion() < 3)
2052 {
Jamie Madill437fa652016-05-03 15:13:24 -04002053 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002054 return false;
2055 }
2056
2057 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2058}
2059
2060bool ValidateFlushMappedBufferRange(Context *context,
2061 GLenum target,
2062 GLintptr offset,
2063 GLsizeiptr length)
2064{
2065 if (context->getClientVersion() < 3)
2066 {
Jamie Madill437fa652016-05-03 15:13:24 -04002067 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002068 return false;
2069 }
2070
2071 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2072}
2073
Jamie Madillc29968b2016-01-20 11:17:23 -05002074} // namespace gl