blob: 690672d0798c9f0cb8f16d88248aa531ba3da2a8 [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
731static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle)
732{
733 const InternalFormat &textureInternalFormatInfo = GetInternalFormatInfo(textureInternalFormat);
734 const InternalFormat &framebufferInternalFormatInfo = GetInternalFormatInfo(frameBufferInternalFormat);
735
736 static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
737 if (conversionSet.find(CopyConversion(textureInternalFormatInfo.format, framebufferInternalFormatInfo.format)) != conversionSet.end())
738 {
739 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
740 // must both be signed, unsigned, or fixed point and both source and destinations
741 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
742 // conversion between fixed and floating point.
743
744 if ((textureInternalFormatInfo.colorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.colorEncoding == GL_SRGB))
745 {
746 return false;
747 }
748
749 if (((textureInternalFormatInfo.componentType == GL_INT) != (framebufferInternalFormatInfo.componentType == GL_INT )) ||
750 ((textureInternalFormatInfo.componentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.componentType == GL_UNSIGNED_INT)))
751 {
752 return false;
753 }
754
755 if ((textureInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
756 textureInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
757 textureInternalFormatInfo.componentType == GL_FLOAT) &&
758 !(framebufferInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
759 framebufferInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
760 framebufferInternalFormatInfo.componentType == GL_FLOAT))
761 {
762 return false;
763 }
764
765 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
766 // The effective internal format of the source buffer is determined with the following rules applied in order:
767 // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
768 // effective internal format is the source buffer's sized internal format.
769 // * If the source buffer is a texture that was created with an unsized base internal format, then the
770 // effective internal format is the source image array's effective internal format, as specified by table
771 // 3.12, which is determined from the <format> and <type> that were used when the source image array was
772 // specified by TexImage*.
773 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
774 // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
775 // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
776 // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
777 // is SRGB.
778 const InternalFormat *sourceEffectiveFormat = NULL;
779 if (readBufferHandle != 0)
780 {
781 // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
782 if (framebufferInternalFormatInfo.pixelBytes > 0)
783 {
784 sourceEffectiveFormat = &framebufferInternalFormatInfo;
785 }
786 else
787 {
788 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
789 // 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 -0500790 GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type);
791 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400792 }
793 }
794 else
795 {
796 // The effective internal format must be derived from the source framebuffer's channel sizes.
797 // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
798 if (framebufferInternalFormatInfo.colorEncoding == GL_LINEAR)
799 {
800 GLenum effectiveFormat;
801 if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat))
802 {
803 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
804 }
805 else
806 {
807 return false;
808 }
809 }
810 else if (framebufferInternalFormatInfo.colorEncoding == GL_SRGB)
811 {
812 // SRGB buffers can only be copied to sized format destinations according to table 3.18
813 if ((textureInternalFormatInfo.pixelBytes > 0) &&
814 (framebufferInternalFormatInfo.redBits >= 1 && framebufferInternalFormatInfo.redBits <= 8) &&
815 (framebufferInternalFormatInfo.greenBits >= 1 && framebufferInternalFormatInfo.greenBits <= 8) &&
816 (framebufferInternalFormatInfo.blueBits >= 1 && framebufferInternalFormatInfo.blueBits <= 8) &&
817 (framebufferInternalFormatInfo.alphaBits >= 1 && framebufferInternalFormatInfo.alphaBits <= 8))
818 {
819 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
820 }
821 else
822 {
823 return false;
824 }
825 }
826 else
827 {
828 UNREACHABLE();
829 return false;
830 }
831 }
832
833 if (textureInternalFormatInfo.pixelBytes > 0)
834 {
835 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is sized,
836 // component sizes of the source and destination formats must exactly match
837 if (textureInternalFormatInfo.redBits != sourceEffectiveFormat->redBits ||
838 textureInternalFormatInfo.greenBits != sourceEffectiveFormat->greenBits ||
839 textureInternalFormatInfo.blueBits != sourceEffectiveFormat->blueBits ||
840 textureInternalFormatInfo.alphaBits != sourceEffectiveFormat->alphaBits)
841 {
842 return false;
843 }
844 }
845
846
847 return true; // A conversion function exists, and no rule in the specification has precluded conversion
848 // between these formats.
849 }
850
851 return false;
852}
853
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500854bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
855 GLenum target,
856 GLint level,
857 GLenum internalformat,
858 bool isSubImage,
859 GLint xoffset,
860 GLint yoffset,
861 GLint zoffset,
862 GLint x,
863 GLint y,
864 GLsizei width,
865 GLsizei height,
866 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400867{
Jamie Madill560a8d82014-05-21 13:06:20 -0400868 GLenum textureInternalFormat;
869 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill6f38f822014-06-06 17:12:20 -0400870 xoffset, yoffset, zoffset, x, y, width, height,
871 border, &textureInternalFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400872 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400873 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400874 }
875
Jamie Madillc29968b2016-01-20 11:17:23 -0500876 const auto &state = context->getState();
877 const gl::Framebuffer *framebuffer = state.getReadFramebuffer();
878 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400879
Geoff Lang748f74e2014-12-01 11:25:34 -0500880 if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400881 {
Jamie Madill437fa652016-05-03 15:13:24 -0400882 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400883 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400884 }
885
Jamie Madillc29968b2016-01-20 11:17:23 -0500886 if (readFramebufferID != 0 && framebuffer->getSamples(context->getData()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400887 {
Jamie Madill437fa652016-05-03 15:13:24 -0400888 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400889 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400890 }
891
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400892 const gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400893 GLenum colorbufferInternalFormat = source->getInternalFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400894
895 if (isSubImage)
896 {
Geoff Lang5d601382014-07-22 15:14:06 -0400897 if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat,
Jamie Madillc29968b2016-01-20 11:17:23 -0500898 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400899 {
Jamie Madill437fa652016-05-03 15:13:24 -0400900 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400901 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400902 }
903 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400904 else
905 {
Geoff Lang5d601382014-07-22 15:14:06 -0400906 if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat,
Jamie Madillc29968b2016-01-20 11:17:23 -0500907 readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400908 {
Jamie Madill437fa652016-05-03 15:13:24 -0400909 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400910 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400911 }
912 }
913
Geoff Lang784a8fd2013-09-24 12:33:16 -0400914 // If width or height is zero, it is a no-op. Return false without setting an error.
915 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400916}
917
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500918bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
919 GLenum target,
920 GLint level,
921 GLenum internalformat,
922 bool isSubImage,
923 GLint xoffset,
924 GLint yoffset,
925 GLint zoffset,
926 GLint x,
927 GLint y,
928 GLsizei width,
929 GLsizei height,
930 GLint border)
931{
932 if (!ValidTexture2DDestinationTarget(context, target))
933 {
Jamie Madill437fa652016-05-03 15:13:24 -0400934 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500935 return false;
936 }
937
938 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
939 xoffset, yoffset, zoffset, x, y, width, height,
940 border);
941}
942
943bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
944 GLenum target,
945 GLint level,
946 GLenum internalformat,
947 bool isSubImage,
948 GLint xoffset,
949 GLint yoffset,
950 GLint zoffset,
951 GLint x,
952 GLint y,
953 GLsizei width,
954 GLsizei height,
955 GLint border)
956{
957 if (!ValidTexture3DDestinationTarget(context, target))
958 {
Jamie Madill437fa652016-05-03 15:13:24 -0400959 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500960 return false;
961 }
962
963 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
964 xoffset, yoffset, zoffset, x, y, width, height,
965 border);
966}
967
968bool ValidateES3TexStorageParametersBase(Context *context,
969 GLenum target,
970 GLsizei levels,
971 GLenum internalformat,
972 GLsizei width,
973 GLsizei height,
974 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400975{
976 if (width < 1 || height < 1 || depth < 1 || levels < 1)
977 {
Jamie Madill437fa652016-05-03 15:13:24 -0400978 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400979 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400980 }
981
Geoff Langb92c1332015-09-04 12:54:55 -0400982 GLsizei maxDim = std::max(width, height);
983 if (target != GL_TEXTURE_2D_ARRAY)
984 {
985 maxDim = std::max(maxDim, depth);
986 }
987
988 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400989 {
Jamie Madill437fa652016-05-03 15:13:24 -0400990 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400991 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400992 }
993
Geoff Langaae65a42014-05-26 12:43:44 -0400994 const gl::Caps &caps = context->getCaps();
995
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400996 switch (target)
997 {
998 case GL_TEXTURE_2D:
999 {
Geoff Langaae65a42014-05-26 12:43:44 -04001000 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1001 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001002 {
Jamie Madill437fa652016-05-03 15:13:24 -04001003 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001004 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001005 }
1006 }
1007 break;
1008
Geoff Lang01c21d22013-09-24 11:52:16 -04001009 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001010 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001011 if (width != height)
1012 {
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
Geoff Langaae65a42014-05-26 12:43:44 -04001017 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001018 {
Jamie Madill437fa652016-05-03 15:13:24 -04001019 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001020 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001021 }
1022 }
1023 break;
1024
1025 case GL_TEXTURE_3D:
1026 {
Geoff Langaae65a42014-05-26 12:43:44 -04001027 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
1028 static_cast<GLuint>(height) > caps.max3DTextureSize ||
1029 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001030 {
Jamie Madill437fa652016-05-03 15:13:24 -04001031 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001032 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001033 }
1034 }
1035 break;
1036
1037 case GL_TEXTURE_2D_ARRAY:
1038 {
Geoff Langaae65a42014-05-26 12:43:44 -04001039 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1040 static_cast<GLuint>(height) > caps.max2DTextureSize ||
1041 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001042 {
Jamie Madill437fa652016-05-03 15:13:24 -04001043 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001044 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001045 }
1046 }
1047 break;
1048
1049 default:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001050 UNREACHABLE();
Geoff Langb1196682014-07-23 13:47:29 -04001051 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001052 }
1053
Geoff Lang691e58c2014-12-19 17:03:25 -05001054 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001055 if (!texture || texture->id() == 0)
1056 {
Jamie Madill437fa652016-05-03 15:13:24 -04001057 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001058 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001059 }
1060
Geoff Lang69cce582015-09-17 13:20:36 -04001061 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001062 {
Jamie Madill437fa652016-05-03 15:13:24 -04001063 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001064 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001065 }
1066
Geoff Lang5d601382014-07-22 15:14:06 -04001067 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1068 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001069 {
Jamie Madill437fa652016-05-03 15:13:24 -04001070 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001071 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001072 }
1073
Geoff Lang5d601382014-07-22 15:14:06 -04001074 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001075 {
Jamie Madill437fa652016-05-03 15:13:24 -04001076 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001077 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001078 }
1079
1080 return true;
1081}
1082
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001083bool ValidateES3TexStorage2DParameters(Context *context,
1084 GLenum target,
1085 GLsizei levels,
1086 GLenum internalformat,
1087 GLsizei width,
1088 GLsizei height,
1089 GLsizei depth)
1090{
1091 if (!ValidTexture2DTarget(context, target))
1092 {
Jamie Madill437fa652016-05-03 15:13:24 -04001093 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001094 return false;
1095 }
1096
1097 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1098 height, depth);
1099}
1100
1101bool ValidateES3TexStorage3DParameters(Context *context,
1102 GLenum target,
1103 GLsizei levels,
1104 GLenum internalformat,
1105 GLsizei width,
1106 GLsizei height,
1107 GLsizei depth)
1108{
1109 if (!ValidTexture3DTarget(context, target))
1110 {
Jamie Madill437fa652016-05-03 15:13:24 -04001111 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001112 return false;
1113 }
1114
1115 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1116 height, depth);
1117}
1118
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001119bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1120{
1121 if (context->getClientVersion() < 3)
1122 {
Jamie Madill437fa652016-05-03 15:13:24 -04001123 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001124 return false;
1125 }
1126
1127 return ValidateBeginQueryBase(context, target, id);
1128}
1129
1130bool ValidateEndQuery(gl::Context *context, GLenum target)
1131{
1132 if (context->getClientVersion() < 3)
1133 {
Jamie Madill437fa652016-05-03 15:13:24 -04001134 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001135 return false;
1136 }
1137
1138 return ValidateEndQueryBase(context, target);
1139}
1140
1141bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1142{
1143 if (context->getClientVersion() < 3)
1144 {
Jamie Madill437fa652016-05-03 15:13:24 -04001145 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001146 return false;
1147 }
1148
1149 return ValidateGetQueryivBase(context, target, pname);
1150}
1151
1152bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1153{
1154 if (context->getClientVersion() < 3)
1155 {
Jamie Madill437fa652016-05-03 15:13:24 -04001156 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001157 return false;
1158 }
1159
1160 return ValidateGetQueryObjectValueBase(context, id, pname);
1161}
1162
Geoff Langb1196682014-07-23 13:47:29 -04001163bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
Jamie Madill570f7c82014-07-03 10:38:54 -04001164 GLuint texture, GLint level, GLint layer)
1165{
1166 if (context->getClientVersion() < 3)
1167 {
Jamie Madill437fa652016-05-03 15:13:24 -04001168 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001169 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001170 }
1171
Jamie Madill55ec3b12014-07-03 10:38:57 -04001172 if (layer < 0)
1173 {
Jamie Madill437fa652016-05-03 15:13:24 -04001174 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001175 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001176 }
1177
1178 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1179 {
1180 return false;
1181 }
1182
1183 const gl::Caps &caps = context->getCaps();
1184 if (texture != 0)
1185 {
1186 gl::Texture *tex = context->getTexture(texture);
1187 ASSERT(tex);
1188
1189 switch (tex->getTarget())
1190 {
1191 case GL_TEXTURE_2D_ARRAY:
1192 {
1193 if (level > gl::log2(caps.max2DTextureSize))
1194 {
Jamie Madill437fa652016-05-03 15:13:24 -04001195 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001196 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001197 }
1198
1199 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1200 {
Jamie Madill437fa652016-05-03 15:13:24 -04001201 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001202 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001203 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001204 }
1205 break;
1206
1207 case GL_TEXTURE_3D:
1208 {
1209 if (level > gl::log2(caps.max3DTextureSize))
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 }
1214
1215 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1216 {
Jamie Madill437fa652016-05-03 15:13:24 -04001217 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001218 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001219 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001220 }
1221 break;
1222
1223 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001224 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001225 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001226 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001227
1228 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(tex->getTarget(), level));
1229 if (internalFormatInfo.compressed)
1230 {
Jamie Madill437fa652016-05-03 15:13:24 -04001231 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001232 return false;
1233 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001234 }
1235
1236 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001237}
1238
Geoff Langb1196682014-07-23 13:47:29 -04001239bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001240{
Geoff Lang5d601382014-07-22 15:14:06 -04001241 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
1242
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001243 switch (format)
1244 {
1245 case GL_RGBA:
1246 switch (type)
1247 {
1248 case GL_UNSIGNED_BYTE:
1249 break;
1250 case GL_UNSIGNED_INT_2_10_10_10_REV:
1251 if (internalFormat != GL_RGB10_A2)
1252 {
1253 return false;
1254 }
1255 break;
Geoff Lang1ec57f82013-10-16 11:43:23 -04001256 case GL_FLOAT:
Geoff Lang5d601382014-07-22 15:14:06 -04001257 if (internalFormatInfo.componentType != GL_FLOAT)
Geoff Lang1ec57f82013-10-16 11:43:23 -04001258 {
1259 return false;
1260 }
1261 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001262 default:
1263 return false;
1264 }
1265 break;
1266 case GL_RGBA_INTEGER:
1267 switch (type)
1268 {
1269 case GL_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001270 if (internalFormatInfo.componentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001271 {
1272 return false;
1273 }
1274 break;
1275 case GL_UNSIGNED_INT:
Geoff Lang5d601382014-07-22 15:14:06 -04001276 if (internalFormatInfo.componentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001277 {
1278 return false;
1279 }
1280 break;
1281 default:
1282 return false;
1283 }
1284 break;
1285 case GL_BGRA_EXT:
1286 switch (type)
1287 {
1288 case GL_UNSIGNED_BYTE:
1289 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1290 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1291 break;
1292 default:
1293 return false;
1294 }
1295 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001296 case GL_RG_EXT:
1297 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001298 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001299 {
1300 return false;
1301 }
1302 switch (type)
1303 {
1304 case GL_UNSIGNED_BYTE:
1305 break;
1306 default:
1307 return false;
1308 }
1309 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001310 default:
1311 return false;
1312 }
1313 return true;
1314}
1315
Corentin Walleze0902642014-11-04 12:32:15 -08001316bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
1317 GLenum internalformat, GLsizei width, GLsizei height)
1318{
1319 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
1320 {
1321 return false;
1322 }
1323
1324 //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.
1325 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1326 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
1327 {
Jamie Madill437fa652016-05-03 15:13:24 -04001328 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -08001329 return false;
1330 }
1331
1332 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
1333 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1334 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1335 {
Jamie Madill437fa652016-05-03 15:13:24 -04001336 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001337 Error(GL_INVALID_OPERATION,
1338 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001339 return false;
1340 }
1341
1342 return true;
1343}
1344
Austin Kinross08332632015-05-05 13:35:47 -07001345bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
1346 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001347{
Austin Kinross08332632015-05-05 13:35:47 -07001348 if (context->getClientVersion() < 3)
1349 {
Jamie Madill437fa652016-05-03 15:13:24 -04001350 context->handleError(
1351 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001352 return false;
1353 }
1354
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001355 bool defaultFramebuffer = false;
1356
1357 switch (target)
1358 {
1359 case GL_DRAW_FRAMEBUFFER:
1360 case GL_FRAMEBUFFER:
Shannon Woods53a94a82014-06-24 15:20:36 -04001361 defaultFramebuffer = context->getState().getDrawFramebuffer()->id() == 0;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001362 break;
1363 case GL_READ_FRAMEBUFFER:
Shannon Woods53a94a82014-06-24 15:20:36 -04001364 defaultFramebuffer = context->getState().getReadFramebuffer()->id() == 0;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001365 break;
1366 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001367 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001368 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001369 }
1370
Austin Kinross08332632015-05-05 13:35:47 -07001371 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001372}
1373
Jamie Madillc29968b2016-01-20 11:17:23 -05001374bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001375{
1376 if (context->getClientVersion() < 3)
1377 {
Jamie Madill437fa652016-05-03 15:13:24 -04001378 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001379 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001380 }
1381
Shannon Woods53a94a82014-06-24 15:20:36 -04001382 const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer();
Geoff Lang748f74e2014-12-01 11:25:34 -05001383 if (!fbo || fbo->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001384 {
Jamie Madill437fa652016-05-03 15:13:24 -04001385 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001386 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001387 }
1388
1389 return true;
1390}
1391
Olli Etuaho71dfb362016-03-10 14:04:27 +02001392bool ValidateDrawRangeElements(Context *context,
1393 GLenum mode,
1394 GLuint start,
1395 GLuint end,
1396 GLsizei count,
1397 GLenum type,
1398 const GLvoid *indices,
1399 IndexRange *indexRange)
1400{
1401 if (context->getClientVersion() < 3)
1402 {
Jamie Madill437fa652016-05-03 15:13:24 -04001403 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001404 return false;
1405 }
1406
1407 if (end < start)
1408 {
Jamie Madill437fa652016-05-03 15:13:24 -04001409 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001410 return false;
1411 }
1412
1413 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1414 {
1415 return false;
1416 }
1417
1418 if (indexRange->end > end || indexRange->start < start)
1419 {
1420 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001421 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001422 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1423 return false;
1424 }
1425 return true;
1426}
1427
Geoff Langb1196682014-07-23 13:47:29 -04001428bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001429{
1430 if (context->getClientVersion() < 3)
1431 {
Jamie Madill437fa652016-05-03 15:13:24 -04001432 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001433 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001434 }
1435
Jamie Madill78f41802014-08-25 15:47:55 -04001436 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001437}
1438
Jamie Madillb885e572015-02-03 16:16:04 -05001439bool ValidateReadBuffer(Context *context, GLenum src)
1440{
1441 if (context->getClientVersion() < 3)
1442 {
Jamie Madill437fa652016-05-03 15:13:24 -04001443 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001444 return false;
1445 }
1446
1447 Framebuffer *readFBO = context->getState().getReadFramebuffer();
1448
1449 if (readFBO == nullptr)
1450 {
Jamie Madill437fa652016-05-03 15:13:24 -04001451 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001452 return false;
1453 }
1454
1455 if (src == GL_NONE)
1456 {
1457 return true;
1458 }
1459
Olli Etuaho84c9f592016-03-09 14:37:25 +02001460 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001461 {
Jamie Madill437fa652016-05-03 15:13:24 -04001462 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001463 return false;
1464 }
1465
1466 if (readFBO->id() == 0)
1467 {
1468 if (src != GL_BACK)
1469 {
1470 const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001471 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001472 return false;
1473 }
1474 }
1475 else
1476 {
1477 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1478
1479 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1480 {
1481 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001482 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001483 return false;
1484 }
1485 }
1486
1487 return true;
1488}
1489
Jamie Madill86af3d22015-07-21 15:14:07 -04001490bool ValidateCompressedTexImage3D(Context *context,
1491 GLenum target,
1492 GLint level,
1493 GLenum internalformat,
1494 GLsizei width,
1495 GLsizei height,
1496 GLsizei depth,
1497 GLint border,
1498 GLsizei imageSize,
1499 const GLvoid *data)
1500{
1501 if (context->getClientVersion() < 3)
1502 {
Jamie Madill437fa652016-05-03 15:13:24 -04001503 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001504 return false;
1505 }
1506
1507 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
1508 if (imageSize < 0 ||
1509 static_cast<GLuint>(imageSize) !=
1510 formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
1511 {
Jamie Madill437fa652016-05-03 15:13:24 -04001512 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001513 return false;
1514 }
1515
1516 // 3D texture target validation
1517 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1518 {
Jamie Madill437fa652016-05-03 15:13:24 -04001519 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001520 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1521 return false;
1522 }
1523
1524 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001525 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
1526 0, width, height, depth, border, GL_NONE, GL_NONE, data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001527 {
1528 return false;
1529 }
1530
1531 return true;
1532}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001533
1534bool ValidateBindVertexArray(Context *context, GLuint array)
1535{
1536 if (context->getClientVersion() < 3)
1537 {
Jamie Madill437fa652016-05-03 15:13:24 -04001538 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001539 return false;
1540 }
1541
1542 return ValidateBindVertexArrayBase(context, array);
1543}
1544
Austin Kinrossbc781f32015-10-26 09:27:38 -07001545bool ValidateIsVertexArray(Context *context)
1546{
1547 if (context->getClientVersion() < 3)
1548 {
Jamie Madill437fa652016-05-03 15:13:24 -04001549 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001550 return false;
1551 }
1552
1553 return true;
1554}
Geoff Langc5629752015-12-07 16:29:04 -05001555
1556bool ValidateProgramBinary(Context *context,
1557 GLuint program,
1558 GLenum binaryFormat,
1559 const void *binary,
1560 GLint length)
1561{
1562 if (context->getClientVersion() < 3)
1563 {
Jamie Madill437fa652016-05-03 15:13:24 -04001564 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001565 return false;
1566 }
1567
1568 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1569}
1570
1571bool ValidateGetProgramBinary(Context *context,
1572 GLuint program,
1573 GLsizei bufSize,
1574 GLsizei *length,
1575 GLenum *binaryFormat,
1576 void *binary)
1577{
1578 if (context->getClientVersion() < 3)
1579 {
Jamie Madill437fa652016-05-03 15:13:24 -04001580 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001581 return false;
1582 }
1583
1584 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1585}
1586
Olli Etuahof0fee072016-03-30 15:11:58 +03001587bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001588{
1589 if (context->getClientVersion() < 3)
1590 {
Jamie Madill437fa652016-05-03 15:13:24 -04001591 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001592 return false;
1593 }
1594
1595 if (GetValidProgram(context, program) == nullptr)
1596 {
1597 return false;
1598 }
1599
1600 switch (pname)
1601 {
1602 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001603 if (value != GL_FALSE && value != GL_TRUE)
1604 {
Jamie Madill437fa652016-05-03 15:13:24 -04001605 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001606 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1607 return false;
1608 }
Geoff Langc5629752015-12-07 16:29:04 -05001609 break;
1610
1611 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001612 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001613 return false;
1614 }
1615
1616 return true;
1617}
Jamie Madillc29968b2016-01-20 11:17:23 -05001618
1619bool ValidateBlitFramebuffer(Context *context,
1620 GLint srcX0,
1621 GLint srcY0,
1622 GLint srcX1,
1623 GLint srcY1,
1624 GLint dstX0,
1625 GLint dstY0,
1626 GLint dstX1,
1627 GLint dstY1,
1628 GLbitfield mask,
1629 GLenum filter)
1630{
1631 if (context->getClientVersion() < 3)
1632 {
Jamie Madill437fa652016-05-03 15:13:24 -04001633 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001634 return false;
1635 }
1636
1637 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1638 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001639}
Jamie Madillc29968b2016-01-20 11:17:23 -05001640
1641bool ValidateClearBufferiv(ValidationContext *context,
1642 GLenum buffer,
1643 GLint drawbuffer,
1644 const GLint *value)
1645{
1646 switch (buffer)
1647 {
1648 case GL_COLOR:
1649 if (drawbuffer < 0 ||
1650 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1651 {
Jamie Madill437fa652016-05-03 15:13:24 -04001652 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001653 return false;
1654 }
1655 break;
1656
1657 case GL_STENCIL:
1658 if (drawbuffer != 0)
1659 {
Jamie Madill437fa652016-05-03 15:13:24 -04001660 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001661 return false;
1662 }
1663 break;
1664
1665 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001666 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001667 return false;
1668 }
1669
1670 return ValidateClearBuffer(context);
1671}
1672
1673bool ValidateClearBufferuiv(ValidationContext *context,
1674 GLenum buffer,
1675 GLint drawbuffer,
1676 const GLuint *value)
1677{
1678 switch (buffer)
1679 {
1680 case GL_COLOR:
1681 if (drawbuffer < 0 ||
1682 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1683 {
Jamie Madill437fa652016-05-03 15:13:24 -04001684 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001685 return false;
1686 }
1687 break;
1688
1689 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001690 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001691 return false;
1692 }
1693
1694 return ValidateClearBuffer(context);
1695}
1696
1697bool ValidateClearBufferfv(ValidationContext *context,
1698 GLenum buffer,
1699 GLint drawbuffer,
1700 const GLfloat *value)
1701{
1702 switch (buffer)
1703 {
1704 case GL_COLOR:
1705 if (drawbuffer < 0 ||
1706 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1707 {
Jamie Madill437fa652016-05-03 15:13:24 -04001708 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001709 return false;
1710 }
1711 break;
1712
1713 case GL_DEPTH:
1714 if (drawbuffer != 0)
1715 {
Jamie Madill437fa652016-05-03 15:13:24 -04001716 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001717 return false;
1718 }
1719 break;
1720
1721 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001722 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001723 return false;
1724 }
1725
1726 return ValidateClearBuffer(context);
1727}
1728
1729bool ValidateClearBufferfi(ValidationContext *context,
1730 GLenum buffer,
1731 GLint drawbuffer,
1732 GLfloat depth,
1733 GLint stencil)
1734{
1735 switch (buffer)
1736 {
1737 case GL_DEPTH_STENCIL:
1738 if (drawbuffer != 0)
1739 {
Jamie Madill437fa652016-05-03 15:13:24 -04001740 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001741 return false;
1742 }
1743 break;
1744
1745 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001746 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001747 return false;
1748 }
1749
1750 return ValidateClearBuffer(context);
1751}
1752
1753bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1754{
1755 if (context->getClientVersion() < 3)
1756 {
Jamie Madill437fa652016-05-03 15:13:24 -04001757 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001758 return false;
1759 }
1760
1761 return ValidateDrawBuffersBase(context, n, bufs);
1762}
1763
1764bool ValidateCopyTexSubImage3D(Context *context,
1765 GLenum target,
1766 GLint level,
1767 GLint xoffset,
1768 GLint yoffset,
1769 GLint zoffset,
1770 GLint x,
1771 GLint y,
1772 GLsizei width,
1773 GLsizei height)
1774{
1775 if (context->getClientVersion() < 3)
1776 {
Jamie Madill437fa652016-05-03 15:13:24 -04001777 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001778 return false;
1779 }
1780
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001781 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1782 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001783}
1784
Jamie Madill73a84962016-02-12 09:27:23 -05001785bool ValidateTexImage3D(Context *context,
1786 GLenum target,
1787 GLint level,
1788 GLint internalformat,
1789 GLsizei width,
1790 GLsizei height,
1791 GLsizei depth,
1792 GLint border,
1793 GLenum format,
1794 GLenum type,
1795 const GLvoid *pixels)
1796{
1797 if (context->getClientVersion() < 3)
1798 {
Jamie Madill437fa652016-05-03 15:13:24 -04001799 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001800 return false;
1801 }
1802
1803 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1804 0, 0, width, height, depth, border, format, type,
1805 pixels);
1806}
1807
1808bool ValidateTexSubImage3D(Context *context,
1809 GLenum target,
1810 GLint level,
1811 GLint xoffset,
1812 GLint yoffset,
1813 GLint zoffset,
1814 GLsizei width,
1815 GLsizei height,
1816 GLsizei depth,
1817 GLenum format,
1818 GLenum type,
1819 const GLvoid *pixels)
1820{
1821 if (context->getClientVersion() < 3)
1822 {
Jamie Madill437fa652016-05-03 15:13:24 -04001823 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001824 return false;
1825 }
1826
1827 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1828 yoffset, zoffset, width, height, depth, 0, format, type,
1829 pixels);
1830}
1831
1832bool ValidateCompressedTexSubImage3D(Context *context,
1833 GLenum target,
1834 GLint level,
1835 GLint xoffset,
1836 GLint yoffset,
1837 GLint zoffset,
1838 GLsizei width,
1839 GLsizei height,
1840 GLsizei depth,
1841 GLenum format,
1842 GLsizei imageSize,
1843 const GLvoid *data)
1844{
1845 if (context->getClientVersion() < 3)
1846 {
Jamie Madill437fa652016-05-03 15:13:24 -04001847 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001848 return false;
1849 }
1850
1851 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
1852 if (imageSize < 0 ||
1853 static_cast<GLuint>(imageSize) !=
1854 formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
1855 {
Jamie Madill437fa652016-05-03 15:13:24 -04001856 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001857 return false;
1858 }
1859
1860 if (!data)
1861 {
Jamie Madill437fa652016-05-03 15:13:24 -04001862 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001863 return false;
1864 }
1865
1866 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
1867 width, height, depth, 0, GL_NONE, GL_NONE, data);
1868}
1869
Olli Etuaho41997e72016-03-10 13:38:39 +02001870bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1871{
1872 return ValidateGenOrDeleteES3(context, n);
1873}
1874
1875bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1876{
1877 return ValidateGenOrDeleteES3(context, n);
1878}
1879
1880bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1881{
1882 return ValidateGenOrDeleteCountES3(context, count);
1883}
1884
1885bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1886{
1887 return ValidateGenOrDeleteCountES3(context, count);
1888}
1889
1890bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1891{
1892 return ValidateGenOrDeleteES3(context, n);
1893}
1894
1895bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1896{
1897 if (!ValidateGenOrDeleteES3(context, n))
1898 {
1899 return false;
1900 }
1901 for (GLint i = 0; i < n; ++i)
1902 {
1903 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1904 if (transformFeedback != nullptr && transformFeedback->isActive())
1905 {
1906 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001907 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001908 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1909 return false;
1910 }
1911 }
1912 return true;
1913}
1914
1915bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1916{
1917 return ValidateGenOrDeleteES3(context, n);
1918}
1919
1920bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1921{
1922 return ValidateGenOrDeleteES3(context, n);
1923}
1924
1925bool ValidateGenOrDeleteES3(Context *context, GLint n)
1926{
1927 if (context->getClientVersion() < 3)
1928 {
Jamie Madill437fa652016-05-03 15:13:24 -04001929 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001930 return false;
1931 }
1932 return ValidateGenOrDelete(context, n);
1933}
1934
1935bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
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 if (count < 0)
1943 {
Jamie Madill437fa652016-05-03 15:13:24 -04001944 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001945 return false;
1946 }
1947 return true;
1948}
1949
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001950bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1951{
1952 if (context->getClientVersion() < 3)
1953 {
Jamie Madill437fa652016-05-03 15:13:24 -04001954 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001955 return false;
1956 }
1957 switch (primitiveMode)
1958 {
1959 case GL_TRIANGLES:
1960 case GL_LINES:
1961 case GL_POINTS:
1962 break;
1963
1964 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001965 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001966 return false;
1967 }
1968
1969 TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
1970 ASSERT(transformFeedback != nullptr);
1971
1972 if (transformFeedback->isActive())
1973 {
Jamie Madill437fa652016-05-03 15:13:24 -04001974 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001975 return false;
1976 }
1977 return true;
1978}
1979
Olli Etuaho37477912016-03-30 14:54:40 +03001980bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
1981{
1982 if (context->getClientVersion() < 3)
1983 {
Jamie Madill437fa652016-05-03 15:13:24 -04001984 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho37477912016-03-30 14:54:40 +03001985 return false;
1986 }
1987
1988 if (!context->isSampler(sampler))
1989 {
Jamie Madill437fa652016-05-03 15:13:24 -04001990 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho37477912016-03-30 14:54:40 +03001991 return false;
1992 }
1993
1994 if (!ValidateSamplerObjectParameter(context, pname))
1995 {
1996 return false;
1997 }
1998
Ian Ewellbda75592016-04-18 17:25:54 -04001999 if (!ValidateTexParamParameters(context, GL_TEXTURE_2D, pname, param))
Olli Etuaho37477912016-03-30 14:54:40 +03002000 {
2001 return false;
2002 }
2003 return true;
2004}
2005
2006bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
2007{
2008 // The only float parameters are MIN_LOD and MAX_LOD. For these any value is permissible, so
2009 // ValidateSamplerParameteri can be used for validation here.
2010 return ValidateSamplerParameteri(context, sampler, pname, static_cast<GLint>(param));
2011}
2012
Olli Etuaho4f667482016-03-30 15:56:35 +03002013bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
2014{
2015 if (context->getClientVersion() < 3)
2016 {
Jamie Madill437fa652016-05-03 15:13:24 -04002017 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002018 return false;
2019 }
2020
2021 return ValidateGetBufferPointervBase(context, target, pname, params);
2022}
2023
2024bool ValidateUnmapBuffer(Context *context, GLenum target)
2025{
2026 if (context->getClientVersion() < 3)
2027 {
Jamie Madill437fa652016-05-03 15:13:24 -04002028 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03002029 return false;
2030 }
2031
2032 return ValidateUnmapBufferBase(context, target);
2033}
2034
2035bool ValidateMapBufferRange(Context *context,
2036 GLenum target,
2037 GLintptr offset,
2038 GLsizeiptr length,
2039 GLbitfield access)
2040{
2041 if (context->getClientVersion() < 3)
2042 {
Jamie Madill437fa652016-05-03 15:13:24 -04002043 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002044 return false;
2045 }
2046
2047 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2048}
2049
2050bool ValidateFlushMappedBufferRange(Context *context,
2051 GLenum target,
2052 GLintptr offset,
2053 GLsizeiptr length)
2054{
2055 if (context->getClientVersion() < 3)
2056 {
Jamie Madill437fa652016-05-03 15:13:24 -04002057 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002058 return false;
2059 }
2060
2061 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2062}
2063
Jamie Madillc29968b2016-01-20 11:17:23 -05002064} // namespace gl