blob: 120cc732200af1ec8abe10b017b67f03e35ecbda [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// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES2.h"
10#include "libANGLE/validationES.h"
Jamie Madill73a84962016-02-12 09:27:23 -050011#include "libANGLE/validationES3.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050012#include "libANGLE/Context.h"
13#include "libANGLE/Texture.h"
14#include "libANGLE/Framebuffer.h"
15#include "libANGLE/Renderbuffer.h"
16#include "libANGLE/formatutils.h"
17#include "libANGLE/FramebufferAttachment.h"
Geoff Langd8605522016-04-13 10:19:12 -040018#include "libANGLE/Uniform.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040019
20#include "common/mathutil.h"
21#include "common/utilities.h"
22
23namespace gl
24{
25
Jamie Madillc29968b2016-01-20 11:17:23 -050026namespace
27{
28
29bool IsPartialBlit(gl::Context *context,
30 const FramebufferAttachment *readBuffer,
31 const FramebufferAttachment *writeBuffer,
32 GLint srcX0,
33 GLint srcY0,
34 GLint srcX1,
35 GLint srcY1,
36 GLint dstX0,
37 GLint dstY0,
38 GLint dstX1,
39 GLint dstY1)
40{
41 const Extents &writeSize = writeBuffer->getSize();
42 const Extents &readSize = readBuffer->getSize();
43
44 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
45 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
46 {
47 return true;
48 }
49
50 if (context->getState().isScissorTestEnabled())
51 {
52 const Rectangle &scissor = context->getState().getScissor();
53 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
54 scissor.height < writeSize.height;
55 }
56
57 return false;
58}
59
60} // anonymous namespace
61
Geoff Langb1196682014-07-23 13:47:29 -040062bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
Geoff Lange8ebe7f2013-08-05 15:03:13 -040063 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
64 GLint border, GLenum format, GLenum type, const GLvoid *pixels)
65{
Jamie Madill6f38f822014-06-06 17:12:20 -040066 if (!ValidTexture2DDestinationTarget(context, target))
67 {
Geoff Langb1196682014-07-23 13:47:29 -040068 context->recordError(Error(GL_INVALID_ENUM));
69 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -040070 }
71
Austin Kinross08528e12015-10-07 16:24:40 -070072 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040073 {
Geoff Langb1196682014-07-23 13:47:29 -040074 context->recordError(Error(GL_INVALID_VALUE));
75 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040076 }
77
Geoff Lange8ebe7f2013-08-05 15:03:13 -040078 if (level < 0 || xoffset < 0 ||
79 std::numeric_limits<GLsizei>::max() - xoffset < width ||
80 std::numeric_limits<GLsizei>::max() - yoffset < height)
81 {
Geoff Langb1196682014-07-23 13:47:29 -040082 context->recordError(Error(GL_INVALID_VALUE));
83 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040084 }
85
Geoff Lang005df412013-10-16 14:12:50 -040086 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040087 {
Geoff Langb1196682014-07-23 13:47:29 -040088 context->recordError(Error(GL_INVALID_OPERATION));
89 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040090 }
91
Geoff Langaae65a42014-05-26 12:43:44 -040092 const gl::Caps &caps = context->getCaps();
93
Geoff Langa9be0dc2014-12-17 12:34:40 -050094 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040095 {
Geoff Langa9be0dc2014-12-17 12:34:40 -050096 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
97 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040098 {
Geoff Langa9be0dc2014-12-17 12:34:40 -050099 context->recordError(Error(GL_INVALID_VALUE));
100 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400101 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500102 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500103 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500104 {
105 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400106 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500107 context->recordError(Error(GL_INVALID_VALUE));
108 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400109 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400110
Geoff Langa9be0dc2014-12-17 12:34:40 -0500111 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
112 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
113 {
114 context->recordError(Error(GL_INVALID_VALUE));
115 return false;
116 }
117 }
118 else
119 {
Geoff Langb1196682014-07-23 13:47:29 -0400120 context->recordError(Error(GL_INVALID_ENUM));
121 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400122 }
123
Geoff Lang691e58c2014-12-19 17:03:25 -0500124 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400125 if (!texture)
126 {
Geoff Langb1196682014-07-23 13:47:29 -0400127 context->recordError(Error(GL_INVALID_OPERATION));
128 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400129 }
130
Geoff Langa9be0dc2014-12-17 12:34:40 -0500131 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400132 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500133 if (format != GL_NONE)
134 {
Geoff Lang051dbc72015-01-05 15:48:58 -0500135 if (gl::GetSizedInternalFormat(format, type) != texture->getInternalFormat(target, level))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500136 {
137 context->recordError(Error(GL_INVALID_OPERATION));
138 return false;
139 }
140 }
141
142 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
143 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
144 {
145 context->recordError(Error(GL_INVALID_VALUE));
146 return false;
147 }
148 }
149 else
150 {
Geoff Lang69cce582015-09-17 13:20:36 -0400151 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500152 {
153 context->recordError(Error(GL_INVALID_OPERATION));
154 return false;
155 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400156 }
157
158 // Verify zero border
159 if (border != 0)
160 {
Geoff Langb1196682014-07-23 13:47:29 -0400161 context->recordError(Error(GL_INVALID_VALUE));
162 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400163 }
164
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400165 if (isCompressed)
166 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400167 GLenum actualInternalFormat =
168 isSubImage ? texture->getInternalFormat(target, level) : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400169 switch (actualInternalFormat)
170 {
171 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
172 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400173 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400174 {
Geoff Langb1196682014-07-23 13:47:29 -0400175 context->recordError(Error(GL_INVALID_ENUM));
176 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400177 }
178 break;
179 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400180 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400181 {
Geoff Langb1196682014-07-23 13:47:29 -0400182 context->recordError(Error(GL_INVALID_ENUM));
183 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400184 }
185 break;
186 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langb1196682014-07-23 13:47:29 -0400187 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400188 {
Geoff Langb1196682014-07-23 13:47:29 -0400189 context->recordError(Error(GL_INVALID_ENUM));
190 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400191 }
192 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400193 case GL_ETC1_RGB8_OES:
194 if (!context->getExtensions().compressedETC1RGB8Texture)
195 {
196 context->recordError(Error(GL_INVALID_ENUM));
197 return false;
198 }
199 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800200 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
201 if (!context->getExtensions().lossyETCDecode)
202 {
203 context->recordError(
204 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
205 return false;
206 }
207 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400208 default:
tmartino0ccd5ae2015-10-01 14:33:14 -0400209 context->recordError(Error(
210 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format"));
211 return false;
212 }
213 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
214 {
215 context->recordError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400216 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400217 }
218 }
219 else
220 {
221 // validate <type> by itself (used as secondary key below)
222 switch (type)
223 {
224 case GL_UNSIGNED_BYTE:
225 case GL_UNSIGNED_SHORT_5_6_5:
226 case GL_UNSIGNED_SHORT_4_4_4_4:
227 case GL_UNSIGNED_SHORT_5_5_5_1:
228 case GL_UNSIGNED_SHORT:
229 case GL_UNSIGNED_INT:
230 case GL_UNSIGNED_INT_24_8_OES:
231 case GL_HALF_FLOAT_OES:
232 case GL_FLOAT:
233 break;
234 default:
Geoff Langb1196682014-07-23 13:47:29 -0400235 context->recordError(Error(GL_INVALID_ENUM));
236 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400237 }
238
239 // validate <format> + <type> combinations
240 // - invalid <format> -> sets INVALID_ENUM
241 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
242 switch (format)
243 {
244 case GL_ALPHA:
245 case GL_LUMINANCE:
246 case GL_LUMINANCE_ALPHA:
247 switch (type)
248 {
249 case GL_UNSIGNED_BYTE:
250 case GL_FLOAT:
251 case GL_HALF_FLOAT_OES:
252 break;
Geoff Langb1196682014-07-23 13:47:29 -0400253 default:
254 context->recordError(Error(GL_INVALID_OPERATION));
255 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400256 }
257 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400258 case GL_RED:
Geoff Langcec35902014-04-16 10:52:36 -0400259 case GL_RG:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400260 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400261 {
Geoff Langb1196682014-07-23 13:47:29 -0400262 context->recordError(Error(GL_INVALID_ENUM));
263 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400264 }
265 switch (type)
266 {
267 case GL_UNSIGNED_BYTE:
268 case GL_FLOAT:
269 case GL_HALF_FLOAT_OES:
270 break;
271 default:
Geoff Langb1196682014-07-23 13:47:29 -0400272 context->recordError(Error(GL_INVALID_OPERATION));
273 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400274 }
275 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400276 case GL_RGB:
277 switch (type)
278 {
279 case GL_UNSIGNED_BYTE:
280 case GL_UNSIGNED_SHORT_5_6_5:
281 case GL_FLOAT:
282 case GL_HALF_FLOAT_OES:
283 break;
284 default:
Geoff Langb1196682014-07-23 13:47:29 -0400285 context->recordError(Error(GL_INVALID_OPERATION));
286 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400287 }
288 break;
289 case GL_RGBA:
290 switch (type)
291 {
292 case GL_UNSIGNED_BYTE:
293 case GL_UNSIGNED_SHORT_4_4_4_4:
294 case GL_UNSIGNED_SHORT_5_5_5_1:
295 case GL_FLOAT:
296 case GL_HALF_FLOAT_OES:
297 break;
298 default:
Geoff Langb1196682014-07-23 13:47:29 -0400299 context->recordError(Error(GL_INVALID_OPERATION));
300 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400301 }
302 break;
303 case GL_BGRA_EXT:
304 switch (type)
305 {
306 case GL_UNSIGNED_BYTE:
307 break;
308 default:
Geoff Langb1196682014-07-23 13:47:29 -0400309 context->recordError(Error(GL_INVALID_OPERATION));
310 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400311 }
312 break;
Geoff Lang05b05022014-06-11 15:31:45 -0400313 case GL_SRGB_EXT:
314 case GL_SRGB_ALPHA_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400315 if (!context->getExtensions().sRGB)
Geoff Lang05b05022014-06-11 15:31:45 -0400316 {
Geoff Langb1196682014-07-23 13:47:29 -0400317 context->recordError(Error(GL_INVALID_ENUM));
318 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400319 }
320 switch (type)
321 {
322 case GL_UNSIGNED_BYTE:
323 break;
324 default:
Geoff Langb1196682014-07-23 13:47:29 -0400325 context->recordError(Error(GL_INVALID_OPERATION));
326 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400327 }
328 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400329 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
330 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
331 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
332 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
333 break;
334 case GL_DEPTH_COMPONENT:
335 switch (type)
336 {
337 case GL_UNSIGNED_SHORT:
338 case GL_UNSIGNED_INT:
339 break;
340 default:
Geoff Langb1196682014-07-23 13:47:29 -0400341 context->recordError(Error(GL_INVALID_OPERATION));
342 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400343 }
344 break;
345 case GL_DEPTH_STENCIL_OES:
346 switch (type)
347 {
348 case GL_UNSIGNED_INT_24_8_OES:
349 break;
350 default:
Geoff Langb1196682014-07-23 13:47:29 -0400351 context->recordError(Error(GL_INVALID_OPERATION));
352 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400353 }
354 break;
355 default:
Geoff Langb1196682014-07-23 13:47:29 -0400356 context->recordError(Error(GL_INVALID_ENUM));
357 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400358 }
359
360 switch (format)
361 {
362 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
363 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400364 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400365 {
Geoff Langb1196682014-07-23 13:47:29 -0400366 context->recordError(Error(GL_INVALID_OPERATION));
367 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400368 }
369 else
370 {
Geoff Langb1196682014-07-23 13:47:29 -0400371 context->recordError(Error(GL_INVALID_ENUM));
372 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400373 }
374 break;
375 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400376 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400377 {
Geoff Langb1196682014-07-23 13:47:29 -0400378 context->recordError(Error(GL_INVALID_OPERATION));
379 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400380 }
381 else
382 {
Geoff Langb1196682014-07-23 13:47:29 -0400383 context->recordError(Error(GL_INVALID_ENUM));
384 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400385 }
386 break;
387 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400388 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400389 {
Geoff Langb1196682014-07-23 13:47:29 -0400390 context->recordError(Error(GL_INVALID_OPERATION));
391 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400392 }
393 else
394 {
Geoff Langb1196682014-07-23 13:47:29 -0400395 context->recordError(Error(GL_INVALID_ENUM));
396 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400397 }
398 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400399 case GL_ETC1_RGB8_OES:
400 if (context->getExtensions().compressedETC1RGB8Texture)
401 {
402 context->recordError(Error(GL_INVALID_OPERATION));
403 return false;
404 }
405 else
406 {
407 context->recordError(Error(GL_INVALID_ENUM));
408 return false;
409 }
410 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800411 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
412 if (context->getExtensions().lossyETCDecode)
413 {
414 context->recordError(
415 Error(GL_INVALID_OPERATION,
416 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't work with this type."));
417 return false;
418 }
419 else
420 {
421 context->recordError(
422 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
423 return false;
424 }
425 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400426 case GL_DEPTH_COMPONENT:
427 case GL_DEPTH_STENCIL_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400428 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400429 {
Geoff Langb1196682014-07-23 13:47:29 -0400430 context->recordError(Error(GL_INVALID_VALUE));
431 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400432 }
433 if (target != GL_TEXTURE_2D)
434 {
Geoff Langb1196682014-07-23 13:47:29 -0400435 context->recordError(Error(GL_INVALID_OPERATION));
436 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400437 }
438 // OES_depth_texture supports loading depth data and multiple levels,
439 // but ANGLE_depth_texture does not
440 if (pixels != NULL || level != 0)
441 {
Geoff Langb1196682014-07-23 13:47:29 -0400442 context->recordError(Error(GL_INVALID_OPERATION));
443 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400444 }
445 break;
446 default:
447 break;
448 }
449
450 if (type == GL_FLOAT)
451 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400452 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400453 {
Geoff Langb1196682014-07-23 13:47:29 -0400454 context->recordError(Error(GL_INVALID_ENUM));
455 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400456 }
457 }
458 else if (type == GL_HALF_FLOAT_OES)
459 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400460 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400461 {
Geoff Langb1196682014-07-23 13:47:29 -0400462 context->recordError(Error(GL_INVALID_ENUM));
463 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400464 }
465 }
466 }
467
468 return true;
469}
470
Jamie Madillc29968b2016-01-20 11:17:23 -0500471bool ValidateES2CopyTexImageParameters(ValidationContext *context,
472 GLenum target,
473 GLint level,
474 GLenum internalformat,
475 bool isSubImage,
476 GLint xoffset,
477 GLint yoffset,
478 GLint x,
479 GLint y,
480 GLsizei width,
481 GLsizei height,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400482 GLint border)
483{
Jamie Madill560a8d82014-05-21 13:06:20 -0400484 GLenum textureInternalFormat = GL_NONE;
Shannon Woods4dfed832014-03-17 20:03:39 -0400485
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500486 if (!ValidTexture2DDestinationTarget(context, target))
487 {
488 context->recordError(Error(GL_INVALID_ENUM, "Invalid texture target"));
489 return false;
490 }
491
Jamie Madill560a8d82014-05-21 13:06:20 -0400492 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
493 xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400494 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400495 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400496 }
497
Jamie Madillc29968b2016-01-20 11:17:23 -0500498 const gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400499 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat();
Jamie Madillbc393df2015-01-29 13:46:07 -0500500 const auto &internalFormatInfo = gl::GetInternalFormatInfo(textureInternalFormat);
501 GLenum textureFormat = internalFormatInfo.format;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400502
503 // [OpenGL ES 2.0.24] table 3.9
504 if (isSubImage)
505 {
506 switch (textureFormat)
507 {
508 case GL_ALPHA:
509 if (colorbufferFormat != GL_ALPHA8_EXT &&
510 colorbufferFormat != GL_RGBA4 &&
511 colorbufferFormat != GL_RGB5_A1 &&
512 colorbufferFormat != GL_RGBA8_OES)
513 {
Geoff Langb1196682014-07-23 13:47:29 -0400514 context->recordError(Error(GL_INVALID_OPERATION));
515 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400516 }
517 break;
518 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400519 if (colorbufferFormat != GL_R8_EXT &&
520 colorbufferFormat != GL_RG8_EXT &&
521 colorbufferFormat != GL_RGB565 &&
522 colorbufferFormat != GL_RGB8_OES &&
523 colorbufferFormat != GL_RGBA4 &&
524 colorbufferFormat != GL_RGB5_A1 &&
525 colorbufferFormat != GL_RGBA8_OES)
526 {
Geoff Langb1196682014-07-23 13:47:29 -0400527 context->recordError(Error(GL_INVALID_OPERATION));
528 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400529 }
530 break;
531 case GL_RED_EXT:
532 if (colorbufferFormat != GL_R8_EXT &&
533 colorbufferFormat != GL_RG8_EXT &&
534 colorbufferFormat != GL_RGB565 &&
535 colorbufferFormat != GL_RGB8_OES &&
536 colorbufferFormat != GL_RGBA4 &&
537 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500538 colorbufferFormat != GL_RGBA8_OES &&
539 colorbufferFormat != GL_R32F &&
540 colorbufferFormat != GL_RG32F &&
541 colorbufferFormat != GL_RGB32F &&
542 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400543 {
Geoff Langb1196682014-07-23 13:47:29 -0400544 context->recordError(Error(GL_INVALID_OPERATION));
545 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400546 }
547 break;
548 case GL_RG_EXT:
549 if (colorbufferFormat != GL_RG8_EXT &&
550 colorbufferFormat != GL_RGB565 &&
551 colorbufferFormat != GL_RGB8_OES &&
552 colorbufferFormat != GL_RGBA4 &&
553 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500554 colorbufferFormat != GL_RGBA8_OES &&
555 colorbufferFormat != GL_RG32F &&
556 colorbufferFormat != GL_RGB32F &&
557 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400558 {
Geoff Langb1196682014-07-23 13:47:29 -0400559 context->recordError(Error(GL_INVALID_OPERATION));
560 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400561 }
562 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400563 case GL_RGB:
564 if (colorbufferFormat != GL_RGB565 &&
565 colorbufferFormat != GL_RGB8_OES &&
566 colorbufferFormat != GL_RGBA4 &&
567 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500568 colorbufferFormat != GL_RGBA8_OES &&
569 colorbufferFormat != GL_RGB32F &&
570 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400571 {
Geoff Langb1196682014-07-23 13:47:29 -0400572 context->recordError(Error(GL_INVALID_OPERATION));
573 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400574 }
575 break;
576 case GL_LUMINANCE_ALPHA:
577 case GL_RGBA:
578 if (colorbufferFormat != GL_RGBA4 &&
579 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500580 colorbufferFormat != GL_RGBA8_OES &&
581 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400582 {
Geoff Langb1196682014-07-23 13:47:29 -0400583 context->recordError(Error(GL_INVALID_OPERATION));
584 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400585 }
586 break;
587 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
588 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
589 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
590 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Lang6ea6f942015-09-11 13:11:22 -0400591 case GL_ETC1_RGB8_OES:
Minmin Gonge3939b92015-12-01 15:36:51 -0800592 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Langb1196682014-07-23 13:47:29 -0400593 context->recordError(Error(GL_INVALID_OPERATION));
594 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400595 case GL_DEPTH_COMPONENT:
596 case GL_DEPTH_STENCIL_OES:
Geoff Langb1196682014-07-23 13:47:29 -0400597 context->recordError(Error(GL_INVALID_OPERATION));
598 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400599 default:
Geoff Langb1196682014-07-23 13:47:29 -0400600 context->recordError(Error(GL_INVALID_OPERATION));
601 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400602 }
Jamie Madillbc393df2015-01-29 13:46:07 -0500603
604 if (internalFormatInfo.type == GL_FLOAT &&
605 !context->getExtensions().textureFloat)
606 {
607 context->recordError(Error(GL_INVALID_OPERATION));
608 return false;
609 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400610 }
611 else
612 {
613 switch (internalformat)
614 {
615 case GL_ALPHA:
616 if (colorbufferFormat != GL_ALPHA8_EXT &&
617 colorbufferFormat != GL_RGBA4 &&
618 colorbufferFormat != GL_RGB5_A1 &&
619 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500620 colorbufferFormat != GL_RGBA8_OES &&
621 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400622 {
Geoff Langb1196682014-07-23 13:47:29 -0400623 context->recordError(Error(GL_INVALID_OPERATION));
624 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400625 }
626 break;
627 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400628 if (colorbufferFormat != GL_R8_EXT &&
629 colorbufferFormat != GL_RG8_EXT &&
630 colorbufferFormat != GL_RGB565 &&
631 colorbufferFormat != GL_RGB8_OES &&
632 colorbufferFormat != GL_RGBA4 &&
633 colorbufferFormat != GL_RGB5_A1 &&
634 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500635 colorbufferFormat != GL_RGBA8_OES &&
636 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400637 {
Geoff Langb1196682014-07-23 13:47:29 -0400638 context->recordError(Error(GL_INVALID_OPERATION));
639 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400640 }
641 break;
642 case GL_RED_EXT:
643 if (colorbufferFormat != GL_R8_EXT &&
644 colorbufferFormat != GL_RG8_EXT &&
645 colorbufferFormat != GL_RGB565 &&
646 colorbufferFormat != GL_RGB8_OES &&
647 colorbufferFormat != GL_RGBA4 &&
648 colorbufferFormat != GL_RGB5_A1 &&
649 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500650 colorbufferFormat != GL_RGBA8_OES &&
651 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400652 {
Geoff Langb1196682014-07-23 13:47:29 -0400653 context->recordError(Error(GL_INVALID_OPERATION));
654 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400655 }
656 break;
657 case GL_RG_EXT:
658 if (colorbufferFormat != GL_RG8_EXT &&
659 colorbufferFormat != GL_RGB565 &&
660 colorbufferFormat != GL_RGB8_OES &&
661 colorbufferFormat != GL_RGBA4 &&
662 colorbufferFormat != GL_RGB5_A1 &&
663 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500664 colorbufferFormat != GL_RGBA8_OES &&
665 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400666 {
Geoff Langb1196682014-07-23 13:47:29 -0400667 context->recordError(Error(GL_INVALID_OPERATION));
668 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400669 }
670 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400671 case GL_RGB:
672 if (colorbufferFormat != GL_RGB565 &&
673 colorbufferFormat != GL_RGB8_OES &&
674 colorbufferFormat != GL_RGBA4 &&
675 colorbufferFormat != GL_RGB5_A1 &&
676 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500677 colorbufferFormat != GL_RGBA8_OES &&
678 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400679 {
Geoff Langb1196682014-07-23 13:47:29 -0400680 context->recordError(Error(GL_INVALID_OPERATION));
681 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400682 }
683 break;
684 case GL_LUMINANCE_ALPHA:
685 case GL_RGBA:
686 if (colorbufferFormat != GL_RGBA4 &&
687 colorbufferFormat != GL_RGB5_A1 &&
688 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500689 colorbufferFormat != GL_RGBA8_OES &&
690 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400691 {
Geoff Langb1196682014-07-23 13:47:29 -0400692 context->recordError(Error(GL_INVALID_OPERATION));
693 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400694 }
695 break;
696 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
697 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400698 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400699 {
Geoff Langb1196682014-07-23 13:47:29 -0400700 context->recordError(Error(GL_INVALID_OPERATION));
701 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400702 }
703 else
704 {
Geoff Langb1196682014-07-23 13:47:29 -0400705 context->recordError(Error(GL_INVALID_ENUM));
706 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400707 }
708 break;
709 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400710 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400711 {
Geoff Langb1196682014-07-23 13:47:29 -0400712 context->recordError(Error(GL_INVALID_OPERATION));
713 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400714 }
715 else
716 {
Geoff Langb1196682014-07-23 13:47:29 -0400717 context->recordError(Error(GL_INVALID_ENUM));
718 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400719 }
720 break;
721 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400722 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400723 {
Geoff Langb1196682014-07-23 13:47:29 -0400724 context->recordError(Error(GL_INVALID_OPERATION));
725 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400726 }
727 else
728 {
Geoff Langb1196682014-07-23 13:47:29 -0400729 context->recordError(Error(GL_INVALID_ENUM));
730 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400731 }
732 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400733 case GL_ETC1_RGB8_OES:
734 if (context->getExtensions().compressedETC1RGB8Texture)
735 {
736 context->recordError(Error(GL_INVALID_OPERATION));
737 return false;
738 }
739 else
740 {
741 context->recordError(Error(GL_INVALID_ENUM));
742 return false;
743 }
744 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800745 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
746 if (context->getExtensions().lossyETCDecode)
747 {
748 context->recordError(Error(GL_INVALID_OPERATION,
749 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't be copied to."));
750 return false;
751 }
752 else
753 {
754 context->recordError(
755 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
756 return false;
757 }
758 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400759 case GL_DEPTH_COMPONENT:
760 case GL_DEPTH_COMPONENT16:
761 case GL_DEPTH_COMPONENT32_OES:
762 case GL_DEPTH_STENCIL_OES:
763 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400764 if (context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400765 {
Geoff Langb1196682014-07-23 13:47:29 -0400766 context->recordError(Error(GL_INVALID_OPERATION));
767 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400768 }
769 else
770 {
Geoff Langb1196682014-07-23 13:47:29 -0400771 context->recordError(Error(GL_INVALID_ENUM));
772 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400773 }
774 default:
Geoff Langb1196682014-07-23 13:47:29 -0400775 context->recordError(Error(GL_INVALID_ENUM));
776 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400777 }
778 }
779
Geoff Lang784a8fd2013-09-24 12:33:16 -0400780 // If width or height is zero, it is a no-op. Return false without setting an error.
781 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400782}
783
Geoff Langb1196682014-07-23 13:47:29 -0400784bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400785 GLsizei width, GLsizei height)
786{
787 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
788 {
Geoff Langb1196682014-07-23 13:47:29 -0400789 context->recordError(Error(GL_INVALID_ENUM));
790 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400791 }
792
793 if (width < 1 || height < 1 || levels < 1)
794 {
Geoff Langb1196682014-07-23 13:47:29 -0400795 context->recordError(Error(GL_INVALID_VALUE));
796 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400797 }
798
799 if (target == GL_TEXTURE_CUBE_MAP && width != height)
800 {
Geoff Langb1196682014-07-23 13:47:29 -0400801 context->recordError(Error(GL_INVALID_VALUE));
802 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400803 }
804
805 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
806 {
Geoff Langb1196682014-07-23 13:47:29 -0400807 context->recordError(Error(GL_INVALID_OPERATION));
808 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400809 }
810
Geoff Lang5d601382014-07-22 15:14:06 -0400811 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
812 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400813 {
Geoff Langb1196682014-07-23 13:47:29 -0400814 context->recordError(Error(GL_INVALID_ENUM));
815 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400816 }
817
Geoff Langaae65a42014-05-26 12:43:44 -0400818 const gl::Caps &caps = context->getCaps();
819
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400820 switch (target)
821 {
822 case GL_TEXTURE_2D:
Geoff Langaae65a42014-05-26 12:43:44 -0400823 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
824 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400825 {
Geoff Langb1196682014-07-23 13:47:29 -0400826 context->recordError(Error(GL_INVALID_VALUE));
827 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400828 }
829 break;
830 case GL_TEXTURE_CUBE_MAP:
Geoff Langaae65a42014-05-26 12:43:44 -0400831 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
832 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400833 {
Geoff Langb1196682014-07-23 13:47:29 -0400834 context->recordError(Error(GL_INVALID_VALUE));
835 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400836 }
837 break;
838 default:
Geoff Langb1196682014-07-23 13:47:29 -0400839 context->recordError(Error(GL_INVALID_ENUM));
840 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400841 }
842
Geoff Langc0b9ef42014-07-02 10:02:37 -0400843 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400844 {
845 if (!gl::isPow2(width) || !gl::isPow2(height))
846 {
Geoff Langb1196682014-07-23 13:47:29 -0400847 context->recordError(Error(GL_INVALID_OPERATION));
848 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400849 }
850 }
851
852 switch (internalformat)
853 {
854 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
855 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400856 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400857 {
Geoff Langb1196682014-07-23 13:47:29 -0400858 context->recordError(Error(GL_INVALID_ENUM));
859 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400860 }
861 break;
862 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400863 if (!context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400864 {
Geoff Langb1196682014-07-23 13:47:29 -0400865 context->recordError(Error(GL_INVALID_ENUM));
866 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400867 }
868 break;
869 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400870 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400871 {
Geoff Langb1196682014-07-23 13:47:29 -0400872 context->recordError(Error(GL_INVALID_ENUM));
873 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400874 }
875 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400876 case GL_ETC1_RGB8_OES:
877 if (!context->getExtensions().compressedETC1RGB8Texture)
878 {
879 context->recordError(Error(GL_INVALID_ENUM));
880 return false;
881 }
882 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800883 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
884 if (!context->getExtensions().lossyETCDecode)
885 {
886 context->recordError(
887 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
888 return false;
889 }
890 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400891 case GL_RGBA32F_EXT:
892 case GL_RGB32F_EXT:
893 case GL_ALPHA32F_EXT:
894 case GL_LUMINANCE32F_EXT:
895 case GL_LUMINANCE_ALPHA32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400896 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400897 {
Geoff Langb1196682014-07-23 13:47:29 -0400898 context->recordError(Error(GL_INVALID_ENUM));
899 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400900 }
901 break;
902 case GL_RGBA16F_EXT:
903 case GL_RGB16F_EXT:
904 case GL_ALPHA16F_EXT:
905 case GL_LUMINANCE16F_EXT:
906 case GL_LUMINANCE_ALPHA16F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400907 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400908 {
Geoff Langb1196682014-07-23 13:47:29 -0400909 context->recordError(Error(GL_INVALID_ENUM));
910 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400911 }
912 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400913 case GL_R8_EXT:
914 case GL_RG8_EXT:
915 case GL_R16F_EXT:
916 case GL_RG16F_EXT:
917 case GL_R32F_EXT:
918 case GL_RG32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400919 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400920 {
Geoff Langb1196682014-07-23 13:47:29 -0400921 context->recordError(Error(GL_INVALID_ENUM));
922 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400923 }
924 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400925 case GL_DEPTH_COMPONENT16:
926 case GL_DEPTH_COMPONENT32_OES:
927 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400928 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400929 {
Geoff Langb1196682014-07-23 13:47:29 -0400930 context->recordError(Error(GL_INVALID_ENUM));
931 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400932 }
933 if (target != GL_TEXTURE_2D)
934 {
Geoff Langb1196682014-07-23 13:47:29 -0400935 context->recordError(Error(GL_INVALID_OPERATION));
936 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400937 }
938 // ANGLE_depth_texture only supports 1-level textures
939 if (levels != 1)
940 {
Geoff Langb1196682014-07-23 13:47:29 -0400941 context->recordError(Error(GL_INVALID_OPERATION));
942 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400943 }
944 break;
945 default:
946 break;
947 }
948
Geoff Lang691e58c2014-12-19 17:03:25 -0500949 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400950 if (!texture || texture->id() == 0)
951 {
Geoff Langb1196682014-07-23 13:47:29 -0400952 context->recordError(Error(GL_INVALID_OPERATION));
953 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400954 }
955
Geoff Lang69cce582015-09-17 13:20:36 -0400956 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400957 {
Geoff Langb1196682014-07-23 13:47:29 -0400958 context->recordError(Error(GL_INVALID_OPERATION));
959 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400960 }
961
962 return true;
963}
964
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400965// check for combinations of format and type that are valid for ReadPixels
Geoff Langb1196682014-07-23 13:47:29 -0400966bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400967{
968 switch (format)
969 {
970 case GL_RGBA:
971 switch (type)
972 {
973 case GL_UNSIGNED_BYTE:
974 break;
975 default:
976 return false;
977 }
978 break;
979 case GL_BGRA_EXT:
980 switch (type)
981 {
982 case GL_UNSIGNED_BYTE:
983 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
984 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
985 break;
986 default:
987 return false;
988 }
989 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400990 case GL_RG_EXT:
991 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400992 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400993 {
994 return false;
995 }
996 switch (type)
997 {
998 case GL_UNSIGNED_BYTE:
999 break;
1000 default:
1001 return false;
1002 }
1003 break;
1004
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001005 default:
1006 return false;
1007 }
1008 return true;
1009}
1010
Austin Kinross08332632015-05-05 13:35:47 -07001011bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
1012 const GLenum *attachments)
1013{
Jamie Madillc29968b2016-01-20 11:17:23 -05001014 if (!context->getExtensions().discardFramebuffer)
1015 {
1016 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1017 return false;
1018 }
1019
Austin Kinross08332632015-05-05 13:35:47 -07001020 bool defaultFramebuffer = false;
1021
1022 switch (target)
1023 {
1024 case GL_FRAMEBUFFER:
1025 defaultFramebuffer = (context->getState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1026 break;
1027 default:
1028 context->recordError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1029 return false;
1030 }
1031
1032 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
1033}
1034
Austin Kinrossbc781f32015-10-26 09:27:38 -07001035bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1036{
1037 if (!context->getExtensions().vertexArrayObject)
1038 {
1039 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1040 return false;
1041 }
1042
1043 return ValidateBindVertexArrayBase(context, array);
1044}
1045
1046bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1047{
1048 if (!context->getExtensions().vertexArrayObject)
1049 {
1050 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1051 return false;
1052 }
1053
Olli Etuaho41997e72016-03-10 13:38:39 +02001054 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001055}
1056
1057bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1058{
1059 if (!context->getExtensions().vertexArrayObject)
1060 {
1061 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1062 return false;
1063 }
1064
Olli Etuaho41997e72016-03-10 13:38:39 +02001065 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001066}
1067
1068bool ValidateIsVertexArrayOES(Context *context)
1069{
1070 if (!context->getExtensions().vertexArrayObject)
1071 {
1072 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1073 return false;
1074 }
1075
1076 return true;
1077}
Geoff Langc5629752015-12-07 16:29:04 -05001078
1079bool ValidateProgramBinaryOES(Context *context,
1080 GLuint program,
1081 GLenum binaryFormat,
1082 const void *binary,
1083 GLint length)
1084{
1085 if (!context->getExtensions().getProgramBinary)
1086 {
1087 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1088 return false;
1089 }
1090
1091 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1092}
1093
1094bool ValidateGetProgramBinaryOES(Context *context,
1095 GLuint program,
1096 GLsizei bufSize,
1097 GLsizei *length,
1098 GLenum *binaryFormat,
1099 void *binary)
1100{
1101 if (!context->getExtensions().getProgramBinary)
1102 {
1103 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1104 return false;
1105 }
1106
1107 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1108}
Geoff Lange102fee2015-12-10 11:23:30 -05001109
Geoff Lang70d0f492015-12-10 17:45:46 -05001110static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1111{
1112 switch (source)
1113 {
1114 case GL_DEBUG_SOURCE_API:
1115 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1116 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1117 case GL_DEBUG_SOURCE_OTHER:
1118 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1119 return !mustBeThirdPartyOrApplication;
1120
1121 case GL_DEBUG_SOURCE_THIRD_PARTY:
1122 case GL_DEBUG_SOURCE_APPLICATION:
1123 return true;
1124
1125 default:
1126 return false;
1127 }
1128}
1129
1130static bool ValidDebugType(GLenum type)
1131{
1132 switch (type)
1133 {
1134 case GL_DEBUG_TYPE_ERROR:
1135 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1136 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1137 case GL_DEBUG_TYPE_PERFORMANCE:
1138 case GL_DEBUG_TYPE_PORTABILITY:
1139 case GL_DEBUG_TYPE_OTHER:
1140 case GL_DEBUG_TYPE_MARKER:
1141 case GL_DEBUG_TYPE_PUSH_GROUP:
1142 case GL_DEBUG_TYPE_POP_GROUP:
1143 return true;
1144
1145 default:
1146 return false;
1147 }
1148}
1149
1150static bool ValidDebugSeverity(GLenum severity)
1151{
1152 switch (severity)
1153 {
1154 case GL_DEBUG_SEVERITY_HIGH:
1155 case GL_DEBUG_SEVERITY_MEDIUM:
1156 case GL_DEBUG_SEVERITY_LOW:
1157 case GL_DEBUG_SEVERITY_NOTIFICATION:
1158 return true;
1159
1160 default:
1161 return false;
1162 }
1163}
1164
Geoff Lange102fee2015-12-10 11:23:30 -05001165bool ValidateDebugMessageControlKHR(Context *context,
1166 GLenum source,
1167 GLenum type,
1168 GLenum severity,
1169 GLsizei count,
1170 const GLuint *ids,
1171 GLboolean enabled)
1172{
1173 if (!context->getExtensions().debug)
1174 {
1175 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1176 return false;
1177 }
1178
Geoff Lang70d0f492015-12-10 17:45:46 -05001179 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1180 {
1181 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
1182 return false;
1183 }
1184
1185 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1186 {
1187 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug type."));
1188 return false;
1189 }
1190
1191 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1192 {
1193 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
1194 return false;
1195 }
1196
1197 if (count > 0)
1198 {
1199 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1200 {
1201 context->recordError(Error(
1202 GL_INVALID_OPERATION,
1203 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1204 return false;
1205 }
1206
1207 if (severity != GL_DONT_CARE)
1208 {
1209 context->recordError(
1210 Error(GL_INVALID_OPERATION,
1211 "If count is greater than zero, severity must be GL_DONT_CARE."));
1212 return false;
1213 }
1214 }
1215
Geoff Lange102fee2015-12-10 11:23:30 -05001216 return true;
1217}
1218
1219bool ValidateDebugMessageInsertKHR(Context *context,
1220 GLenum source,
1221 GLenum type,
1222 GLuint id,
1223 GLenum severity,
1224 GLsizei length,
1225 const GLchar *buf)
1226{
1227 if (!context->getExtensions().debug)
1228 {
1229 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1230 return false;
1231 }
1232
Geoff Lang70d0f492015-12-10 17:45:46 -05001233 if (!context->getState().getDebug().isOutputEnabled())
1234 {
1235 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1236 // not generate an error.
1237 return false;
1238 }
1239
1240 if (!ValidDebugSeverity(severity))
1241 {
1242 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
1243 return false;
1244 }
1245
1246 if (!ValidDebugType(type))
1247 {
1248 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug type."));
1249 return false;
1250 }
1251
1252 if (!ValidDebugSource(source, true))
1253 {
1254 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
1255 return false;
1256 }
1257
1258 size_t messageLength = (length < 0) ? strlen(buf) : length;
1259 if (messageLength > context->getExtensions().maxDebugMessageLength)
1260 {
1261 context->recordError(
1262 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1263 return false;
1264 }
1265
Geoff Lange102fee2015-12-10 11:23:30 -05001266 return true;
1267}
1268
1269bool ValidateDebugMessageCallbackKHR(Context *context,
1270 GLDEBUGPROCKHR callback,
1271 const void *userParam)
1272{
1273 if (!context->getExtensions().debug)
1274 {
1275 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1276 return false;
1277 }
1278
Geoff Lange102fee2015-12-10 11:23:30 -05001279 return true;
1280}
1281
1282bool ValidateGetDebugMessageLogKHR(Context *context,
1283 GLuint count,
1284 GLsizei bufSize,
1285 GLenum *sources,
1286 GLenum *types,
1287 GLuint *ids,
1288 GLenum *severities,
1289 GLsizei *lengths,
1290 GLchar *messageLog)
1291{
1292 if (!context->getExtensions().debug)
1293 {
1294 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1295 return false;
1296 }
1297
Geoff Lang70d0f492015-12-10 17:45:46 -05001298 if (bufSize < 0 && messageLog != nullptr)
1299 {
1300 context->recordError(
1301 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1302 return false;
1303 }
1304
Geoff Lange102fee2015-12-10 11:23:30 -05001305 return true;
1306}
1307
1308bool ValidatePushDebugGroupKHR(Context *context,
1309 GLenum source,
1310 GLuint id,
1311 GLsizei length,
1312 const GLchar *message)
1313{
1314 if (!context->getExtensions().debug)
1315 {
1316 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1317 return false;
1318 }
1319
Geoff Lang70d0f492015-12-10 17:45:46 -05001320 if (!ValidDebugSource(source, true))
1321 {
1322 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
1323 return false;
1324 }
1325
1326 size_t messageLength = (length < 0) ? strlen(message) : length;
1327 if (messageLength > context->getExtensions().maxDebugMessageLength)
1328 {
1329 context->recordError(
1330 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1331 return false;
1332 }
1333
1334 size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
1335 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1336 {
1337 context->recordError(
1338 Error(GL_STACK_OVERFLOW,
1339 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1340 return false;
1341 }
1342
Geoff Lange102fee2015-12-10 11:23:30 -05001343 return true;
1344}
1345
1346bool ValidatePopDebugGroupKHR(Context *context)
1347{
1348 if (!context->getExtensions().debug)
1349 {
1350 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1351 return false;
1352 }
1353
Geoff Lang70d0f492015-12-10 17:45:46 -05001354 size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
1355 if (currentStackSize <= 1)
1356 {
1357 context->recordError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
1358 return false;
1359 }
1360
1361 return true;
1362}
1363
1364static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1365{
1366 switch (identifier)
1367 {
1368 case GL_BUFFER:
1369 if (context->getBuffer(name) == nullptr)
1370 {
1371 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
1372 return false;
1373 }
1374 return true;
1375
1376 case GL_SHADER:
1377 if (context->getShader(name) == nullptr)
1378 {
1379 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
1380 return false;
1381 }
1382 return true;
1383
1384 case GL_PROGRAM:
1385 if (context->getProgram(name) == nullptr)
1386 {
1387 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid program."));
1388 return false;
1389 }
1390 return true;
1391
1392 case GL_VERTEX_ARRAY:
1393 if (context->getVertexArray(name) == nullptr)
1394 {
1395 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
1396 return false;
1397 }
1398 return true;
1399
1400 case GL_QUERY:
1401 if (context->getQuery(name) == nullptr)
1402 {
1403 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid query."));
1404 return false;
1405 }
1406 return true;
1407
1408 case GL_TRANSFORM_FEEDBACK:
1409 if (context->getTransformFeedback(name) == nullptr)
1410 {
1411 context->recordError(
1412 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1413 return false;
1414 }
1415 return true;
1416
1417 case GL_SAMPLER:
1418 if (context->getSampler(name) == nullptr)
1419 {
1420 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
1421 return false;
1422 }
1423 return true;
1424
1425 case GL_TEXTURE:
1426 if (context->getTexture(name) == nullptr)
1427 {
1428 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
1429 return false;
1430 }
1431 return true;
1432
1433 case GL_RENDERBUFFER:
1434 if (context->getRenderbuffer(name) == nullptr)
1435 {
1436 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
1437 return false;
1438 }
1439 return true;
1440
1441 case GL_FRAMEBUFFER:
1442 if (context->getFramebuffer(name) == nullptr)
1443 {
1444 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
1445 return false;
1446 }
1447 return true;
1448
1449 default:
1450 context->recordError(Error(GL_INVALID_ENUM, "Invalid identifier."));
1451 return false;
1452 }
1453
Geoff Lange102fee2015-12-10 11:23:30 -05001454 return true;
1455}
1456
1457bool ValidateObjectLabelKHR(Context *context,
1458 GLenum identifier,
1459 GLuint name,
1460 GLsizei length,
1461 const GLchar *label)
1462{
1463 if (!context->getExtensions().debug)
1464 {
1465 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1466 return false;
1467 }
1468
Geoff Lang70d0f492015-12-10 17:45:46 -05001469 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1470 {
1471 return false;
1472 }
1473
1474 size_t labelLength = (length < 0) ? strlen(label) : length;
1475 if (labelLength > context->getExtensions().maxLabelLength)
1476 {
1477 context->recordError(
1478 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1479 return false;
1480 }
1481
Geoff Lange102fee2015-12-10 11:23:30 -05001482 return true;
1483}
1484
1485bool ValidateGetObjectLabelKHR(Context *context,
1486 GLenum identifier,
1487 GLuint name,
1488 GLsizei bufSize,
1489 GLsizei *length,
1490 GLchar *label)
1491{
1492 if (!context->getExtensions().debug)
1493 {
1494 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1495 return false;
1496 }
1497
Geoff Lang70d0f492015-12-10 17:45:46 -05001498 if (bufSize < 0)
1499 {
1500 context->recordError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1501 return false;
1502 }
1503
1504 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1505 {
1506 return false;
1507 }
1508
1509 // Can no-op if bufSize is zero.
1510 return bufSize > 0;
1511}
1512
1513static bool ValidateObjectPtrName(Context *context, const void *ptr)
1514{
1515 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1516 {
1517 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
1518 return false;
1519 }
1520
Geoff Lange102fee2015-12-10 11:23:30 -05001521 return true;
1522}
1523
1524bool ValidateObjectPtrLabelKHR(Context *context,
1525 const void *ptr,
1526 GLsizei length,
1527 const GLchar *label)
1528{
1529 if (!context->getExtensions().debug)
1530 {
1531 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1532 return false;
1533 }
1534
Geoff Lang70d0f492015-12-10 17:45:46 -05001535 if (!ValidateObjectPtrName(context, ptr))
1536 {
1537 return false;
1538 }
1539
1540 size_t labelLength = (length < 0) ? strlen(label) : length;
1541 if (labelLength > context->getExtensions().maxLabelLength)
1542 {
1543 context->recordError(
1544 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1545 return false;
1546 }
1547
Geoff Lange102fee2015-12-10 11:23:30 -05001548 return true;
1549}
1550
1551bool ValidateGetObjectPtrLabelKHR(Context *context,
1552 const void *ptr,
1553 GLsizei bufSize,
1554 GLsizei *length,
1555 GLchar *label)
1556{
1557 if (!context->getExtensions().debug)
1558 {
1559 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1560 return false;
1561 }
1562
Geoff Lang70d0f492015-12-10 17:45:46 -05001563 if (bufSize < 0)
1564 {
1565 context->recordError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1566 return false;
1567 }
1568
1569 if (!ValidateObjectPtrName(context, ptr))
1570 {
1571 return false;
1572 }
1573
1574 // Can no-op if bufSize is zero.
1575 return bufSize > 0;
Geoff Lange102fee2015-12-10 11:23:30 -05001576}
1577
1578bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1579{
1580 if (!context->getExtensions().debug)
1581 {
1582 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1583 return false;
1584 }
1585
Geoff Lang70d0f492015-12-10 17:45:46 -05001586 // TODO: represent this in Context::getQueryParameterInfo.
1587 switch (pname)
1588 {
1589 case GL_DEBUG_CALLBACK_FUNCTION:
1590 case GL_DEBUG_CALLBACK_USER_PARAM:
1591 break;
1592
1593 default:
1594 context->recordError(Error(GL_INVALID_ENUM, "Invalid pname."));
1595 return false;
1596 }
1597
Geoff Lange102fee2015-12-10 11:23:30 -05001598 return true;
1599}
Jamie Madillc29968b2016-01-20 11:17:23 -05001600
1601bool ValidateBlitFramebufferANGLE(Context *context,
1602 GLint srcX0,
1603 GLint srcY0,
1604 GLint srcX1,
1605 GLint srcY1,
1606 GLint dstX0,
1607 GLint dstY0,
1608 GLint dstX1,
1609 GLint dstY1,
1610 GLbitfield mask,
1611 GLenum filter)
1612{
1613 if (!context->getExtensions().framebufferBlit)
1614 {
1615 context->recordError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
1616 return false;
1617 }
1618
1619 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1620 {
1621 // TODO(jmadill): Determine if this should be available on other implementations.
1622 context->recordError(Error(
1623 GL_INVALID_OPERATION,
1624 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1625 return false;
1626 }
1627
1628 if (filter == GL_LINEAR)
1629 {
1630 context->recordError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
1631 return false;
1632 }
1633
1634 const Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
1635 const Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
1636
1637 if (mask & GL_COLOR_BUFFER_BIT)
1638 {
1639 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1640 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1641
1642 if (readColorAttachment && drawColorAttachment)
1643 {
1644 if (!(readColorAttachment->type() == GL_TEXTURE &&
1645 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1646 readColorAttachment->type() != GL_RENDERBUFFER &&
1647 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1648 {
1649 context->recordError(Error(GL_INVALID_OPERATION));
1650 return false;
1651 }
1652
Geoff Langa15472a2015-08-11 11:48:03 -04001653 for (size_t drawbufferIdx = 0;
1654 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001655 {
Geoff Langa15472a2015-08-11 11:48:03 -04001656 const FramebufferAttachment *attachment =
1657 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1658 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001659 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001660 if (!(attachment->type() == GL_TEXTURE &&
1661 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1662 attachment->type() != GL_RENDERBUFFER &&
1663 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1664 {
1665 context->recordError(Error(GL_INVALID_OPERATION));
1666 return false;
1667 }
1668
1669 // Return an error if the destination formats do not match
1670 if (attachment->getInternalFormat() != readColorAttachment->getInternalFormat())
1671 {
1672 context->recordError(Error(GL_INVALID_OPERATION));
1673 return false;
1674 }
1675 }
1676 }
1677
1678 int readSamples = readFramebuffer->getSamples(context->getData());
1679
1680 if (readSamples != 0 &&
1681 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1682 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1683 {
1684 context->recordError(Error(GL_INVALID_OPERATION));
1685 return false;
1686 }
1687 }
1688 }
1689
1690 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1691 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1692 for (size_t i = 0; i < 2; i++)
1693 {
1694 if (mask & masks[i])
1695 {
1696 const FramebufferAttachment *readBuffer =
1697 readFramebuffer->getAttachment(attachments[i]);
1698 const FramebufferAttachment *drawBuffer =
1699 drawFramebuffer->getAttachment(attachments[i]);
1700
1701 if (readBuffer && drawBuffer)
1702 {
1703 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1704 dstX0, dstY0, dstX1, dstY1))
1705 {
1706 // only whole-buffer copies are permitted
1707 ERR(
1708 "Only whole-buffer depth and stencil blits are supported by this "
1709 "implementation.");
1710 context->recordError(Error(GL_INVALID_OPERATION));
1711 return false;
1712 }
1713
1714 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1715 {
1716 context->recordError(Error(GL_INVALID_OPERATION));
1717 return false;
1718 }
1719 }
1720 }
1721 }
1722
1723 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1724 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001725}
Jamie Madillc29968b2016-01-20 11:17:23 -05001726
1727bool ValidateClear(ValidationContext *context, GLbitfield mask)
1728{
1729 const Framebuffer *framebufferObject = context->getState().getDrawFramebuffer();
1730 ASSERT(framebufferObject);
1731
1732 if (framebufferObject->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
1733 {
1734 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
1735 return false;
1736 }
1737
1738 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1739 {
1740 context->recordError(Error(GL_INVALID_VALUE));
1741 return false;
1742 }
1743
1744 return true;
1745}
1746
1747bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1748{
1749 if (!context->getExtensions().drawBuffers)
1750 {
1751 context->recordError(Error(GL_INVALID_OPERATION, "Extension not supported."));
1752 return false;
1753 }
1754
1755 return ValidateDrawBuffersBase(context, n, bufs);
1756}
1757
Jamie Madill73a84962016-02-12 09:27:23 -05001758bool ValidateTexImage2D(Context *context,
1759 GLenum target,
1760 GLint level,
1761 GLint internalformat,
1762 GLsizei width,
1763 GLsizei height,
1764 GLint border,
1765 GLenum format,
1766 GLenum type,
1767 const GLvoid *pixels)
1768{
1769 if (context->getClientVersion() < 3)
1770 {
1771 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
1772 0, 0, width, height, border, format, type, pixels);
1773 }
1774
1775 ASSERT(context->getClientVersion() >= 3);
1776 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
1777 0, 0, width, height, 1, border, format, type, pixels);
1778}
1779
1780bool ValidateTexSubImage2D(Context *context,
1781 GLenum target,
1782 GLint level,
1783 GLint xoffset,
1784 GLint yoffset,
1785 GLsizei width,
1786 GLsizei height,
1787 GLenum format,
1788 GLenum type,
1789 const GLvoid *pixels)
1790{
1791
1792 if (context->getClientVersion() < 3)
1793 {
1794 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
1795 yoffset, width, height, 0, format, type, pixels);
1796 }
1797
1798 ASSERT(context->getClientVersion() >= 3);
1799 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
1800 yoffset, 0, width, height, 1, 0, format, type, pixels);
1801}
1802
1803bool ValidateCompressedTexImage2D(Context *context,
1804 GLenum target,
1805 GLint level,
1806 GLenum internalformat,
1807 GLsizei width,
1808 GLsizei height,
1809 GLint border,
1810 GLsizei imageSize,
1811 const GLvoid *data)
1812{
1813 if (context->getClientVersion() < 3)
1814 {
1815 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
1816 0, width, height, border, GL_NONE, GL_NONE, data))
1817 {
1818 return false;
1819 }
1820 }
1821 else
1822 {
1823 ASSERT(context->getClientVersion() >= 3);
1824 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
1825 0, 0, width, height, 1, border, GL_NONE, GL_NONE,
1826 data))
1827 {
1828 return false;
1829 }
1830 }
1831
1832 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
1833 if (imageSize < 0 ||
1834 static_cast<GLuint>(imageSize) !=
1835 formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
1836 {
1837 context->recordError(Error(GL_INVALID_VALUE));
1838 return false;
1839 }
1840
1841 return true;
1842}
1843
1844bool ValidateCompressedTexSubImage2D(Context *context,
1845 GLenum target,
1846 GLint level,
1847 GLint xoffset,
1848 GLint yoffset,
1849 GLsizei width,
1850 GLsizei height,
1851 GLenum format,
1852 GLsizei imageSize,
1853 const GLvoid *data)
1854{
1855 if (context->getClientVersion() < 3)
1856 {
1857 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
1858 yoffset, width, height, 0, GL_NONE, GL_NONE, data))
1859 {
1860 return false;
1861 }
1862 }
1863 else
1864 {
1865 ASSERT(context->getClientVersion() >= 3);
1866 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
1867 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE,
1868 data))
1869 {
1870 return false;
1871 }
1872 }
1873
1874 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
1875 if (imageSize < 0 ||
1876 static_cast<GLuint>(imageSize) !=
1877 formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
1878 {
1879 context->recordError(Error(GL_INVALID_VALUE));
1880 return false;
1881 }
1882
1883 return true;
1884}
1885
Olli Etuaho4f667482016-03-30 15:56:35 +03001886bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
1887{
1888 if (!context->getExtensions().mapBuffer)
1889 {
1890 context->recordError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
1891 return false;
1892 }
1893
1894 return ValidateGetBufferPointervBase(context, target, pname, params);
1895}
1896
1897bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
1898{
1899 if (!context->getExtensions().mapBuffer)
1900 {
1901 context->recordError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
1902 return false;
1903 }
1904
1905 if (!ValidBufferTarget(context, target))
1906 {
1907 context->recordError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1908 return false;
1909 }
1910
1911 Buffer *buffer = context->getState().getTargetBuffer(target);
1912
1913 if (buffer == nullptr)
1914 {
1915 context->recordError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
1916 return false;
1917 }
1918
1919 if (access != GL_WRITE_ONLY_OES)
1920 {
1921 context->recordError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
1922 return false;
1923 }
1924
1925 if (buffer->isMapped())
1926 {
1927 context->recordError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
1928 return false;
1929 }
1930
1931 return true;
1932}
1933
1934bool ValidateUnmapBufferOES(Context *context, GLenum target)
1935{
1936 if (!context->getExtensions().mapBuffer)
1937 {
1938 context->recordError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
1939 return false;
1940 }
1941
1942 return ValidateUnmapBufferBase(context, target);
1943}
1944
1945bool ValidateMapBufferRangeEXT(Context *context,
1946 GLenum target,
1947 GLintptr offset,
1948 GLsizeiptr length,
1949 GLbitfield access)
1950{
1951 if (!context->getExtensions().mapBufferRange)
1952 {
1953 context->recordError(
1954 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
1955 return false;
1956 }
1957
1958 return ValidateMapBufferRangeBase(context, target, offset, length, access);
1959}
1960
1961bool ValidateFlushMappedBufferRangeEXT(Context *context,
1962 GLenum target,
1963 GLintptr offset,
1964 GLsizeiptr length)
1965{
1966 if (!context->getExtensions().mapBufferRange)
1967 {
1968 context->recordError(
1969 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
1970 return false;
1971 }
1972
1973 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
1974}
1975
Ian Ewell54f87462016-03-10 13:47:21 -05001976bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
1977{
1978 Texture *textureObject = context->getTexture(texture);
1979 if (textureObject && textureObject->getTarget() != target && texture != 0)
1980 {
1981 context->recordError(Error(GL_INVALID_OPERATION, "Invalid texture"));
1982 return false;
1983 }
1984
1985 switch (target)
1986 {
1987 case GL_TEXTURE_2D:
1988 case GL_TEXTURE_CUBE_MAP:
1989 break;
1990
1991 case GL_TEXTURE_3D:
1992 case GL_TEXTURE_2D_ARRAY:
1993 if (context->getClientVersion() < 3)
1994 {
1995 context->recordError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
1996 return false;
1997 }
1998 break;
1999 case GL_TEXTURE_EXTERNAL_OES:
2000 if (!context->getExtensions().eglStreamConsumerExternal)
2001 {
2002 context->recordError(
2003 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2004 return false;
2005 }
2006 break;
2007 default:
2008 context->recordError(Error(GL_INVALID_ENUM, "Invalid target"));
2009 return false;
2010 }
2011
2012 return true;
2013}
2014
Geoff Langd8605522016-04-13 10:19:12 -04002015bool ValidateBindUniformLocationCHROMIUM(Context *context,
2016 GLuint program,
2017 GLint location,
2018 const GLchar *name)
2019{
2020 if (!context->getExtensions().bindUniformLocation)
2021 {
2022 context->recordError(
2023 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2024 return false;
2025 }
2026
2027 Program *programObject = GetValidProgram(context, program);
2028 if (!programObject)
2029 {
2030 return false;
2031 }
2032
2033 if (location < 0)
2034 {
2035 context->recordError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
2036 return false;
2037 }
2038
2039 const Caps &caps = context->getCaps();
2040 if (static_cast<size_t>(location) >=
2041 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2042 {
2043 context->recordError(Error(GL_INVALID_VALUE,
2044 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2045 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2046 return false;
2047 }
2048
2049 if (strncmp(name, "gl_", 3) == 0)
2050 {
2051 context->recordError(
2052 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2053 return false;
2054 }
2055
2056 return true;
2057}
2058
Jamie Madillc29968b2016-01-20 11:17:23 -05002059} // namespace gl