blob: 2e5b955e996eaff9a69ae88b727994735cf13f26 [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"
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"
19#include "common/utilities.h"
20
21namespace gl
22{
23
Jamie Madillc29968b2016-01-20 11:17:23 -050024namespace
25{
26
27bool IsPartialBlit(gl::Context *context,
28 const FramebufferAttachment *readBuffer,
29 const FramebufferAttachment *writeBuffer,
30 GLint srcX0,
31 GLint srcY0,
32 GLint srcX1,
33 GLint srcY1,
34 GLint dstX0,
35 GLint dstY0,
36 GLint dstX1,
37 GLint dstY1)
38{
39 const Extents &writeSize = writeBuffer->getSize();
40 const Extents &readSize = readBuffer->getSize();
41
42 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
43 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
44 {
45 return true;
46 }
47
48 if (context->getState().isScissorTestEnabled())
49 {
50 const Rectangle &scissor = context->getState().getScissor();
51 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
52 scissor.height < writeSize.height;
53 }
54
55 return false;
56}
57
58} // anonymous namespace
59
Geoff Langb1196682014-07-23 13:47:29 -040060bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
Geoff Lange8ebe7f2013-08-05 15:03:13 -040061 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
62 GLint border, GLenum format, GLenum type, const GLvoid *pixels)
63{
Jamie Madill6f38f822014-06-06 17:12:20 -040064 if (!ValidTexture2DDestinationTarget(context, target))
65 {
Geoff Langb1196682014-07-23 13:47:29 -040066 context->recordError(Error(GL_INVALID_ENUM));
67 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -040068 }
69
Austin Kinross08528e12015-10-07 16:24:40 -070070 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040071 {
Geoff Langb1196682014-07-23 13:47:29 -040072 context->recordError(Error(GL_INVALID_VALUE));
73 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040074 }
75
Geoff Lange8ebe7f2013-08-05 15:03:13 -040076 if (level < 0 || xoffset < 0 ||
77 std::numeric_limits<GLsizei>::max() - xoffset < width ||
78 std::numeric_limits<GLsizei>::max() - yoffset < height)
79 {
Geoff Langb1196682014-07-23 13:47:29 -040080 context->recordError(Error(GL_INVALID_VALUE));
81 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040082 }
83
Geoff Lang005df412013-10-16 14:12:50 -040084 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040085 {
Geoff Langb1196682014-07-23 13:47:29 -040086 context->recordError(Error(GL_INVALID_OPERATION));
87 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040088 }
89
Geoff Langaae65a42014-05-26 12:43:44 -040090 const gl::Caps &caps = context->getCaps();
91
Geoff Langa9be0dc2014-12-17 12:34:40 -050092 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040093 {
Geoff Langa9be0dc2014-12-17 12:34:40 -050094 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
95 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040096 {
Geoff Langa9be0dc2014-12-17 12:34:40 -050097 context->recordError(Error(GL_INVALID_VALUE));
98 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040099 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500100 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500101 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500102 {
103 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400104 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500105 context->recordError(Error(GL_INVALID_VALUE));
106 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400107 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400108
Geoff Langa9be0dc2014-12-17 12:34:40 -0500109 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
110 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
111 {
112 context->recordError(Error(GL_INVALID_VALUE));
113 return false;
114 }
115 }
116 else
117 {
Geoff Langb1196682014-07-23 13:47:29 -0400118 context->recordError(Error(GL_INVALID_ENUM));
119 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400120 }
121
Geoff Lang691e58c2014-12-19 17:03:25 -0500122 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400123 if (!texture)
124 {
Geoff Langb1196682014-07-23 13:47:29 -0400125 context->recordError(Error(GL_INVALID_OPERATION));
126 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400127 }
128
Geoff Langa9be0dc2014-12-17 12:34:40 -0500129 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400130 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500131 if (format != GL_NONE)
132 {
Geoff Lang051dbc72015-01-05 15:48:58 -0500133 if (gl::GetSizedInternalFormat(format, type) != texture->getInternalFormat(target, level))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500134 {
135 context->recordError(Error(GL_INVALID_OPERATION));
136 return false;
137 }
138 }
139
140 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
141 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
142 {
143 context->recordError(Error(GL_INVALID_VALUE));
144 return false;
145 }
146 }
147 else
148 {
Geoff Lang69cce582015-09-17 13:20:36 -0400149 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500150 {
151 context->recordError(Error(GL_INVALID_OPERATION));
152 return false;
153 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400154 }
155
156 // Verify zero border
157 if (border != 0)
158 {
Geoff Langb1196682014-07-23 13:47:29 -0400159 context->recordError(Error(GL_INVALID_VALUE));
160 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400161 }
162
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400163 if (isCompressed)
164 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400165 GLenum actualInternalFormat =
166 isSubImage ? texture->getInternalFormat(target, level) : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400167 switch (actualInternalFormat)
168 {
169 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
170 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400171 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400172 {
Geoff Langb1196682014-07-23 13:47:29 -0400173 context->recordError(Error(GL_INVALID_ENUM));
174 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400175 }
176 break;
177 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400178 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400179 {
Geoff Langb1196682014-07-23 13:47:29 -0400180 context->recordError(Error(GL_INVALID_ENUM));
181 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400182 }
183 break;
184 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langb1196682014-07-23 13:47:29 -0400185 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400186 {
Geoff Langb1196682014-07-23 13:47:29 -0400187 context->recordError(Error(GL_INVALID_ENUM));
188 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400189 }
190 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400191 case GL_ETC1_RGB8_OES:
192 if (!context->getExtensions().compressedETC1RGB8Texture)
193 {
194 context->recordError(Error(GL_INVALID_ENUM));
195 return false;
196 }
197 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800198 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
199 if (!context->getExtensions().lossyETCDecode)
200 {
201 context->recordError(
202 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
203 return false;
204 }
205 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400206 default:
tmartino0ccd5ae2015-10-01 14:33:14 -0400207 context->recordError(Error(
208 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format"));
209 return false;
210 }
211 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
212 {
213 context->recordError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400214 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400215 }
216 }
217 else
218 {
219 // validate <type> by itself (used as secondary key below)
220 switch (type)
221 {
222 case GL_UNSIGNED_BYTE:
223 case GL_UNSIGNED_SHORT_5_6_5:
224 case GL_UNSIGNED_SHORT_4_4_4_4:
225 case GL_UNSIGNED_SHORT_5_5_5_1:
226 case GL_UNSIGNED_SHORT:
227 case GL_UNSIGNED_INT:
228 case GL_UNSIGNED_INT_24_8_OES:
229 case GL_HALF_FLOAT_OES:
230 case GL_FLOAT:
231 break;
232 default:
Geoff Langb1196682014-07-23 13:47:29 -0400233 context->recordError(Error(GL_INVALID_ENUM));
234 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400235 }
236
237 // validate <format> + <type> combinations
238 // - invalid <format> -> sets INVALID_ENUM
239 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
240 switch (format)
241 {
242 case GL_ALPHA:
243 case GL_LUMINANCE:
244 case GL_LUMINANCE_ALPHA:
245 switch (type)
246 {
247 case GL_UNSIGNED_BYTE:
248 case GL_FLOAT:
249 case GL_HALF_FLOAT_OES:
250 break;
Geoff Langb1196682014-07-23 13:47:29 -0400251 default:
252 context->recordError(Error(GL_INVALID_OPERATION));
253 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400254 }
255 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400256 case GL_RED:
Geoff Langcec35902014-04-16 10:52:36 -0400257 case GL_RG:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400258 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400259 {
Geoff Langb1196682014-07-23 13:47:29 -0400260 context->recordError(Error(GL_INVALID_ENUM));
261 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400262 }
263 switch (type)
264 {
265 case GL_UNSIGNED_BYTE:
266 case GL_FLOAT:
267 case GL_HALF_FLOAT_OES:
268 break;
269 default:
Geoff Langb1196682014-07-23 13:47:29 -0400270 context->recordError(Error(GL_INVALID_OPERATION));
271 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400272 }
273 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400274 case GL_RGB:
275 switch (type)
276 {
277 case GL_UNSIGNED_BYTE:
278 case GL_UNSIGNED_SHORT_5_6_5:
279 case GL_FLOAT:
280 case GL_HALF_FLOAT_OES:
281 break;
282 default:
Geoff Langb1196682014-07-23 13:47:29 -0400283 context->recordError(Error(GL_INVALID_OPERATION));
284 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400285 }
286 break;
287 case GL_RGBA:
288 switch (type)
289 {
290 case GL_UNSIGNED_BYTE:
291 case GL_UNSIGNED_SHORT_4_4_4_4:
292 case GL_UNSIGNED_SHORT_5_5_5_1:
293 case GL_FLOAT:
294 case GL_HALF_FLOAT_OES:
295 break;
296 default:
Geoff Langb1196682014-07-23 13:47:29 -0400297 context->recordError(Error(GL_INVALID_OPERATION));
298 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400299 }
300 break;
301 case GL_BGRA_EXT:
302 switch (type)
303 {
304 case GL_UNSIGNED_BYTE:
305 break;
306 default:
Geoff Langb1196682014-07-23 13:47:29 -0400307 context->recordError(Error(GL_INVALID_OPERATION));
308 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400309 }
310 break;
Geoff Lang05b05022014-06-11 15:31:45 -0400311 case GL_SRGB_EXT:
312 case GL_SRGB_ALPHA_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400313 if (!context->getExtensions().sRGB)
Geoff Lang05b05022014-06-11 15:31:45 -0400314 {
Geoff Langb1196682014-07-23 13:47:29 -0400315 context->recordError(Error(GL_INVALID_ENUM));
316 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400317 }
318 switch (type)
319 {
320 case GL_UNSIGNED_BYTE:
321 break;
322 default:
Geoff Langb1196682014-07-23 13:47:29 -0400323 context->recordError(Error(GL_INVALID_OPERATION));
324 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400325 }
326 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400327 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
328 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
329 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
330 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
331 break;
332 case GL_DEPTH_COMPONENT:
333 switch (type)
334 {
335 case GL_UNSIGNED_SHORT:
336 case GL_UNSIGNED_INT:
337 break;
338 default:
Geoff Langb1196682014-07-23 13:47:29 -0400339 context->recordError(Error(GL_INVALID_OPERATION));
340 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400341 }
342 break;
343 case GL_DEPTH_STENCIL_OES:
344 switch (type)
345 {
346 case GL_UNSIGNED_INT_24_8_OES:
347 break;
348 default:
Geoff Langb1196682014-07-23 13:47:29 -0400349 context->recordError(Error(GL_INVALID_OPERATION));
350 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400351 }
352 break;
353 default:
Geoff Langb1196682014-07-23 13:47:29 -0400354 context->recordError(Error(GL_INVALID_ENUM));
355 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400356 }
357
358 switch (format)
359 {
360 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
361 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400362 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400363 {
Geoff Langb1196682014-07-23 13:47:29 -0400364 context->recordError(Error(GL_INVALID_OPERATION));
365 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400366 }
367 else
368 {
Geoff Langb1196682014-07-23 13:47:29 -0400369 context->recordError(Error(GL_INVALID_ENUM));
370 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400371 }
372 break;
373 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400374 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400375 {
Geoff Langb1196682014-07-23 13:47:29 -0400376 context->recordError(Error(GL_INVALID_OPERATION));
377 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400378 }
379 else
380 {
Geoff Langb1196682014-07-23 13:47:29 -0400381 context->recordError(Error(GL_INVALID_ENUM));
382 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400383 }
384 break;
385 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400386 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400387 {
Geoff Langb1196682014-07-23 13:47:29 -0400388 context->recordError(Error(GL_INVALID_OPERATION));
389 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400390 }
391 else
392 {
Geoff Langb1196682014-07-23 13:47:29 -0400393 context->recordError(Error(GL_INVALID_ENUM));
394 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400395 }
396 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400397 case GL_ETC1_RGB8_OES:
398 if (context->getExtensions().compressedETC1RGB8Texture)
399 {
400 context->recordError(Error(GL_INVALID_OPERATION));
401 return false;
402 }
403 else
404 {
405 context->recordError(Error(GL_INVALID_ENUM));
406 return false;
407 }
408 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800409 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
410 if (context->getExtensions().lossyETCDecode)
411 {
412 context->recordError(
413 Error(GL_INVALID_OPERATION,
414 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't work with this type."));
415 return false;
416 }
417 else
418 {
419 context->recordError(
420 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
421 return false;
422 }
423 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400424 case GL_DEPTH_COMPONENT:
425 case GL_DEPTH_STENCIL_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400426 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400427 {
Geoff Langb1196682014-07-23 13:47:29 -0400428 context->recordError(Error(GL_INVALID_VALUE));
429 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400430 }
431 if (target != GL_TEXTURE_2D)
432 {
Geoff Langb1196682014-07-23 13:47:29 -0400433 context->recordError(Error(GL_INVALID_OPERATION));
434 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400435 }
436 // OES_depth_texture supports loading depth data and multiple levels,
437 // but ANGLE_depth_texture does not
438 if (pixels != NULL || level != 0)
439 {
Geoff Langb1196682014-07-23 13:47:29 -0400440 context->recordError(Error(GL_INVALID_OPERATION));
441 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400442 }
443 break;
444 default:
445 break;
446 }
447
448 if (type == GL_FLOAT)
449 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400450 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400451 {
Geoff Langb1196682014-07-23 13:47:29 -0400452 context->recordError(Error(GL_INVALID_ENUM));
453 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400454 }
455 }
456 else if (type == GL_HALF_FLOAT_OES)
457 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400458 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400459 {
Geoff Langb1196682014-07-23 13:47:29 -0400460 context->recordError(Error(GL_INVALID_ENUM));
461 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400462 }
463 }
464 }
465
466 return true;
467}
468
Jamie Madillc29968b2016-01-20 11:17:23 -0500469bool ValidateES2CopyTexImageParameters(ValidationContext *context,
470 GLenum target,
471 GLint level,
472 GLenum internalformat,
473 bool isSubImage,
474 GLint xoffset,
475 GLint yoffset,
476 GLint x,
477 GLint y,
478 GLsizei width,
479 GLsizei height,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400480 GLint border)
481{
Jamie Madill560a8d82014-05-21 13:06:20 -0400482 GLenum textureInternalFormat = GL_NONE;
Shannon Woods4dfed832014-03-17 20:03:39 -0400483
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500484 if (!ValidTexture2DDestinationTarget(context, target))
485 {
486 context->recordError(Error(GL_INVALID_ENUM, "Invalid texture target"));
487 return false;
488 }
489
Jamie Madill560a8d82014-05-21 13:06:20 -0400490 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
491 xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400492 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400493 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400494 }
495
Jamie Madillc29968b2016-01-20 11:17:23 -0500496 const gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400497 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat();
Jamie Madillbc393df2015-01-29 13:46:07 -0500498 const auto &internalFormatInfo = gl::GetInternalFormatInfo(textureInternalFormat);
499 GLenum textureFormat = internalFormatInfo.format;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400500
501 // [OpenGL ES 2.0.24] table 3.9
502 if (isSubImage)
503 {
504 switch (textureFormat)
505 {
506 case GL_ALPHA:
507 if (colorbufferFormat != GL_ALPHA8_EXT &&
508 colorbufferFormat != GL_RGBA4 &&
509 colorbufferFormat != GL_RGB5_A1 &&
510 colorbufferFormat != GL_RGBA8_OES)
511 {
Geoff Langb1196682014-07-23 13:47:29 -0400512 context->recordError(Error(GL_INVALID_OPERATION));
513 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400514 }
515 break;
516 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400517 if (colorbufferFormat != GL_R8_EXT &&
518 colorbufferFormat != GL_RG8_EXT &&
519 colorbufferFormat != GL_RGB565 &&
520 colorbufferFormat != GL_RGB8_OES &&
521 colorbufferFormat != GL_RGBA4 &&
522 colorbufferFormat != GL_RGB5_A1 &&
523 colorbufferFormat != GL_RGBA8_OES)
524 {
Geoff Langb1196682014-07-23 13:47:29 -0400525 context->recordError(Error(GL_INVALID_OPERATION));
526 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400527 }
528 break;
529 case GL_RED_EXT:
530 if (colorbufferFormat != GL_R8_EXT &&
531 colorbufferFormat != GL_RG8_EXT &&
532 colorbufferFormat != GL_RGB565 &&
533 colorbufferFormat != GL_RGB8_OES &&
534 colorbufferFormat != GL_RGBA4 &&
535 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500536 colorbufferFormat != GL_RGBA8_OES &&
537 colorbufferFormat != GL_R32F &&
538 colorbufferFormat != GL_RG32F &&
539 colorbufferFormat != GL_RGB32F &&
540 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400541 {
Geoff Langb1196682014-07-23 13:47:29 -0400542 context->recordError(Error(GL_INVALID_OPERATION));
543 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400544 }
545 break;
546 case GL_RG_EXT:
547 if (colorbufferFormat != GL_RG8_EXT &&
548 colorbufferFormat != GL_RGB565 &&
549 colorbufferFormat != GL_RGB8_OES &&
550 colorbufferFormat != GL_RGBA4 &&
551 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500552 colorbufferFormat != GL_RGBA8_OES &&
553 colorbufferFormat != GL_RG32F &&
554 colorbufferFormat != GL_RGB32F &&
555 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400556 {
Geoff Langb1196682014-07-23 13:47:29 -0400557 context->recordError(Error(GL_INVALID_OPERATION));
558 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400559 }
560 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400561 case GL_RGB:
562 if (colorbufferFormat != GL_RGB565 &&
563 colorbufferFormat != GL_RGB8_OES &&
564 colorbufferFormat != GL_RGBA4 &&
565 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500566 colorbufferFormat != GL_RGBA8_OES &&
567 colorbufferFormat != GL_RGB32F &&
568 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400569 {
Geoff Langb1196682014-07-23 13:47:29 -0400570 context->recordError(Error(GL_INVALID_OPERATION));
571 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400572 }
573 break;
574 case GL_LUMINANCE_ALPHA:
575 case GL_RGBA:
576 if (colorbufferFormat != GL_RGBA4 &&
577 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500578 colorbufferFormat != GL_RGBA8_OES &&
579 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400580 {
Geoff Langb1196682014-07-23 13:47:29 -0400581 context->recordError(Error(GL_INVALID_OPERATION));
582 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400583 }
584 break;
585 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
586 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
587 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
588 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Lang6ea6f942015-09-11 13:11:22 -0400589 case GL_ETC1_RGB8_OES:
Minmin Gonge3939b92015-12-01 15:36:51 -0800590 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Langb1196682014-07-23 13:47:29 -0400591 context->recordError(Error(GL_INVALID_OPERATION));
592 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400593 case GL_DEPTH_COMPONENT:
594 case GL_DEPTH_STENCIL_OES:
Geoff Langb1196682014-07-23 13:47:29 -0400595 context->recordError(Error(GL_INVALID_OPERATION));
596 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400597 default:
Geoff Langb1196682014-07-23 13:47:29 -0400598 context->recordError(Error(GL_INVALID_OPERATION));
599 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400600 }
Jamie Madillbc393df2015-01-29 13:46:07 -0500601
602 if (internalFormatInfo.type == GL_FLOAT &&
603 !context->getExtensions().textureFloat)
604 {
605 context->recordError(Error(GL_INVALID_OPERATION));
606 return false;
607 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400608 }
609 else
610 {
611 switch (internalformat)
612 {
613 case GL_ALPHA:
614 if (colorbufferFormat != GL_ALPHA8_EXT &&
615 colorbufferFormat != GL_RGBA4 &&
616 colorbufferFormat != GL_RGB5_A1 &&
617 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500618 colorbufferFormat != GL_RGBA8_OES &&
619 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400620 {
Geoff Langb1196682014-07-23 13:47:29 -0400621 context->recordError(Error(GL_INVALID_OPERATION));
622 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400623 }
624 break;
625 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400626 if (colorbufferFormat != GL_R8_EXT &&
627 colorbufferFormat != GL_RG8_EXT &&
628 colorbufferFormat != GL_RGB565 &&
629 colorbufferFormat != GL_RGB8_OES &&
630 colorbufferFormat != GL_RGBA4 &&
631 colorbufferFormat != GL_RGB5_A1 &&
632 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500633 colorbufferFormat != GL_RGBA8_OES &&
634 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400635 {
Geoff Langb1196682014-07-23 13:47:29 -0400636 context->recordError(Error(GL_INVALID_OPERATION));
637 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400638 }
639 break;
640 case GL_RED_EXT:
641 if (colorbufferFormat != GL_R8_EXT &&
642 colorbufferFormat != GL_RG8_EXT &&
643 colorbufferFormat != GL_RGB565 &&
644 colorbufferFormat != GL_RGB8_OES &&
645 colorbufferFormat != GL_RGBA4 &&
646 colorbufferFormat != GL_RGB5_A1 &&
647 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500648 colorbufferFormat != GL_RGBA8_OES &&
649 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400650 {
Geoff Langb1196682014-07-23 13:47:29 -0400651 context->recordError(Error(GL_INVALID_OPERATION));
652 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400653 }
654 break;
655 case GL_RG_EXT:
656 if (colorbufferFormat != GL_RG8_EXT &&
657 colorbufferFormat != GL_RGB565 &&
658 colorbufferFormat != GL_RGB8_OES &&
659 colorbufferFormat != GL_RGBA4 &&
660 colorbufferFormat != GL_RGB5_A1 &&
661 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500662 colorbufferFormat != GL_RGBA8_OES &&
663 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400664 {
Geoff Langb1196682014-07-23 13:47:29 -0400665 context->recordError(Error(GL_INVALID_OPERATION));
666 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400667 }
668 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400669 case GL_RGB:
670 if (colorbufferFormat != GL_RGB565 &&
671 colorbufferFormat != GL_RGB8_OES &&
672 colorbufferFormat != GL_RGBA4 &&
673 colorbufferFormat != GL_RGB5_A1 &&
674 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500675 colorbufferFormat != GL_RGBA8_OES &&
676 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400677 {
Geoff Langb1196682014-07-23 13:47:29 -0400678 context->recordError(Error(GL_INVALID_OPERATION));
679 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400680 }
681 break;
682 case GL_LUMINANCE_ALPHA:
683 case GL_RGBA:
684 if (colorbufferFormat != GL_RGBA4 &&
685 colorbufferFormat != GL_RGB5_A1 &&
686 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500687 colorbufferFormat != GL_RGBA8_OES &&
688 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400689 {
Geoff Langb1196682014-07-23 13:47:29 -0400690 context->recordError(Error(GL_INVALID_OPERATION));
691 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400692 }
693 break;
694 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
695 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400696 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400697 {
Geoff Langb1196682014-07-23 13:47:29 -0400698 context->recordError(Error(GL_INVALID_OPERATION));
699 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400700 }
701 else
702 {
Geoff Langb1196682014-07-23 13:47:29 -0400703 context->recordError(Error(GL_INVALID_ENUM));
704 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400705 }
706 break;
707 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400708 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400709 {
Geoff Langb1196682014-07-23 13:47:29 -0400710 context->recordError(Error(GL_INVALID_OPERATION));
711 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400712 }
713 else
714 {
Geoff Langb1196682014-07-23 13:47:29 -0400715 context->recordError(Error(GL_INVALID_ENUM));
716 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400717 }
718 break;
719 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400720 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400721 {
Geoff Langb1196682014-07-23 13:47:29 -0400722 context->recordError(Error(GL_INVALID_OPERATION));
723 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400724 }
725 else
726 {
Geoff Langb1196682014-07-23 13:47:29 -0400727 context->recordError(Error(GL_INVALID_ENUM));
728 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400729 }
730 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400731 case GL_ETC1_RGB8_OES:
732 if (context->getExtensions().compressedETC1RGB8Texture)
733 {
734 context->recordError(Error(GL_INVALID_OPERATION));
735 return false;
736 }
737 else
738 {
739 context->recordError(Error(GL_INVALID_ENUM));
740 return false;
741 }
742 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800743 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
744 if (context->getExtensions().lossyETCDecode)
745 {
746 context->recordError(Error(GL_INVALID_OPERATION,
747 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't be copied to."));
748 return false;
749 }
750 else
751 {
752 context->recordError(
753 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
754 return false;
755 }
756 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400757 case GL_DEPTH_COMPONENT:
758 case GL_DEPTH_COMPONENT16:
759 case GL_DEPTH_COMPONENT32_OES:
760 case GL_DEPTH_STENCIL_OES:
761 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400762 if (context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400763 {
Geoff Langb1196682014-07-23 13:47:29 -0400764 context->recordError(Error(GL_INVALID_OPERATION));
765 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400766 }
767 else
768 {
Geoff Langb1196682014-07-23 13:47:29 -0400769 context->recordError(Error(GL_INVALID_ENUM));
770 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400771 }
772 default:
Geoff Langb1196682014-07-23 13:47:29 -0400773 context->recordError(Error(GL_INVALID_ENUM));
774 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400775 }
776 }
777
Geoff Lang784a8fd2013-09-24 12:33:16 -0400778 // If width or height is zero, it is a no-op. Return false without setting an error.
779 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400780}
781
Geoff Langb1196682014-07-23 13:47:29 -0400782bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400783 GLsizei width, GLsizei height)
784{
785 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
786 {
Geoff Langb1196682014-07-23 13:47:29 -0400787 context->recordError(Error(GL_INVALID_ENUM));
788 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400789 }
790
791 if (width < 1 || height < 1 || levels < 1)
792 {
Geoff Langb1196682014-07-23 13:47:29 -0400793 context->recordError(Error(GL_INVALID_VALUE));
794 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400795 }
796
797 if (target == GL_TEXTURE_CUBE_MAP && width != height)
798 {
Geoff Langb1196682014-07-23 13:47:29 -0400799 context->recordError(Error(GL_INVALID_VALUE));
800 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400801 }
802
803 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
804 {
Geoff Langb1196682014-07-23 13:47:29 -0400805 context->recordError(Error(GL_INVALID_OPERATION));
806 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400807 }
808
Geoff Lang5d601382014-07-22 15:14:06 -0400809 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
810 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400811 {
Geoff Langb1196682014-07-23 13:47:29 -0400812 context->recordError(Error(GL_INVALID_ENUM));
813 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400814 }
815
Geoff Langaae65a42014-05-26 12:43:44 -0400816 const gl::Caps &caps = context->getCaps();
817
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400818 switch (target)
819 {
820 case GL_TEXTURE_2D:
Geoff Langaae65a42014-05-26 12:43:44 -0400821 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
822 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400823 {
Geoff Langb1196682014-07-23 13:47:29 -0400824 context->recordError(Error(GL_INVALID_VALUE));
825 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400826 }
827 break;
828 case GL_TEXTURE_CUBE_MAP:
Geoff Langaae65a42014-05-26 12:43:44 -0400829 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
830 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400831 {
Geoff Langb1196682014-07-23 13:47:29 -0400832 context->recordError(Error(GL_INVALID_VALUE));
833 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400834 }
835 break;
836 default:
Geoff Langb1196682014-07-23 13:47:29 -0400837 context->recordError(Error(GL_INVALID_ENUM));
838 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400839 }
840
Geoff Langc0b9ef42014-07-02 10:02:37 -0400841 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400842 {
843 if (!gl::isPow2(width) || !gl::isPow2(height))
844 {
Geoff Langb1196682014-07-23 13:47:29 -0400845 context->recordError(Error(GL_INVALID_OPERATION));
846 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400847 }
848 }
849
850 switch (internalformat)
851 {
852 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
853 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400854 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400855 {
Geoff Langb1196682014-07-23 13:47:29 -0400856 context->recordError(Error(GL_INVALID_ENUM));
857 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400858 }
859 break;
860 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400861 if (!context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400862 {
Geoff Langb1196682014-07-23 13:47:29 -0400863 context->recordError(Error(GL_INVALID_ENUM));
864 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400865 }
866 break;
867 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400868 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400869 {
Geoff Langb1196682014-07-23 13:47:29 -0400870 context->recordError(Error(GL_INVALID_ENUM));
871 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400872 }
873 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400874 case GL_ETC1_RGB8_OES:
875 if (!context->getExtensions().compressedETC1RGB8Texture)
876 {
877 context->recordError(Error(GL_INVALID_ENUM));
878 return false;
879 }
880 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800881 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
882 if (!context->getExtensions().lossyETCDecode)
883 {
884 context->recordError(
885 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
886 return false;
887 }
888 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400889 case GL_RGBA32F_EXT:
890 case GL_RGB32F_EXT:
891 case GL_ALPHA32F_EXT:
892 case GL_LUMINANCE32F_EXT:
893 case GL_LUMINANCE_ALPHA32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400894 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400895 {
Geoff Langb1196682014-07-23 13:47:29 -0400896 context->recordError(Error(GL_INVALID_ENUM));
897 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400898 }
899 break;
900 case GL_RGBA16F_EXT:
901 case GL_RGB16F_EXT:
902 case GL_ALPHA16F_EXT:
903 case GL_LUMINANCE16F_EXT:
904 case GL_LUMINANCE_ALPHA16F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400905 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400906 {
Geoff Langb1196682014-07-23 13:47:29 -0400907 context->recordError(Error(GL_INVALID_ENUM));
908 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400909 }
910 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400911 case GL_R8_EXT:
912 case GL_RG8_EXT:
913 case GL_R16F_EXT:
914 case GL_RG16F_EXT:
915 case GL_R32F_EXT:
916 case GL_RG32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400917 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400918 {
Geoff Langb1196682014-07-23 13:47:29 -0400919 context->recordError(Error(GL_INVALID_ENUM));
920 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400921 }
922 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400923 case GL_DEPTH_COMPONENT16:
924 case GL_DEPTH_COMPONENT32_OES:
925 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400926 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400927 {
Geoff Langb1196682014-07-23 13:47:29 -0400928 context->recordError(Error(GL_INVALID_ENUM));
929 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400930 }
931 if (target != GL_TEXTURE_2D)
932 {
Geoff Langb1196682014-07-23 13:47:29 -0400933 context->recordError(Error(GL_INVALID_OPERATION));
934 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400935 }
936 // ANGLE_depth_texture only supports 1-level textures
937 if (levels != 1)
938 {
Geoff Langb1196682014-07-23 13:47:29 -0400939 context->recordError(Error(GL_INVALID_OPERATION));
940 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400941 }
942 break;
943 default:
944 break;
945 }
946
Geoff Lang691e58c2014-12-19 17:03:25 -0500947 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400948 if (!texture || texture->id() == 0)
949 {
Geoff Langb1196682014-07-23 13:47:29 -0400950 context->recordError(Error(GL_INVALID_OPERATION));
951 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400952 }
953
Geoff Lang69cce582015-09-17 13:20:36 -0400954 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400955 {
Geoff Langb1196682014-07-23 13:47:29 -0400956 context->recordError(Error(GL_INVALID_OPERATION));
957 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400958 }
959
960 return true;
961}
962
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400963// check for combinations of format and type that are valid for ReadPixels
Geoff Langb1196682014-07-23 13:47:29 -0400964bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400965{
966 switch (format)
967 {
968 case GL_RGBA:
969 switch (type)
970 {
971 case GL_UNSIGNED_BYTE:
972 break;
973 default:
974 return false;
975 }
976 break;
977 case GL_BGRA_EXT:
978 switch (type)
979 {
980 case GL_UNSIGNED_BYTE:
981 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
982 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
983 break;
984 default:
985 return false;
986 }
987 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400988 case GL_RG_EXT:
989 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400990 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400991 {
992 return false;
993 }
994 switch (type)
995 {
996 case GL_UNSIGNED_BYTE:
997 break;
998 default:
999 return false;
1000 }
1001 break;
1002
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001003 default:
1004 return false;
1005 }
1006 return true;
1007}
1008
Austin Kinross08332632015-05-05 13:35:47 -07001009bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
1010 const GLenum *attachments)
1011{
Jamie Madillc29968b2016-01-20 11:17:23 -05001012 if (!context->getExtensions().discardFramebuffer)
1013 {
1014 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1015 return false;
1016 }
1017
Austin Kinross08332632015-05-05 13:35:47 -07001018 bool defaultFramebuffer = false;
1019
1020 switch (target)
1021 {
1022 case GL_FRAMEBUFFER:
1023 defaultFramebuffer = (context->getState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1024 break;
1025 default:
1026 context->recordError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1027 return false;
1028 }
1029
1030 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
1031}
1032
Austin Kinrossbc781f32015-10-26 09:27:38 -07001033bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1034{
1035 if (!context->getExtensions().vertexArrayObject)
1036 {
1037 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1038 return false;
1039 }
1040
1041 return ValidateBindVertexArrayBase(context, array);
1042}
1043
1044bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1045{
1046 if (!context->getExtensions().vertexArrayObject)
1047 {
1048 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1049 return false;
1050 }
1051
1052 return ValidateDeleteVertexArraysBase(context, n);
1053}
1054
1055bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1056{
1057 if (!context->getExtensions().vertexArrayObject)
1058 {
1059 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1060 return false;
1061 }
1062
1063 return ValidateGenVertexArraysBase(context, n);
1064}
1065
1066bool ValidateIsVertexArrayOES(Context *context)
1067{
1068 if (!context->getExtensions().vertexArrayObject)
1069 {
1070 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1071 return false;
1072 }
1073
1074 return true;
1075}
Geoff Langc5629752015-12-07 16:29:04 -05001076
1077bool ValidateProgramBinaryOES(Context *context,
1078 GLuint program,
1079 GLenum binaryFormat,
1080 const void *binary,
1081 GLint length)
1082{
1083 if (!context->getExtensions().getProgramBinary)
1084 {
1085 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1086 return false;
1087 }
1088
1089 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1090}
1091
1092bool ValidateGetProgramBinaryOES(Context *context,
1093 GLuint program,
1094 GLsizei bufSize,
1095 GLsizei *length,
1096 GLenum *binaryFormat,
1097 void *binary)
1098{
1099 if (!context->getExtensions().getProgramBinary)
1100 {
1101 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1102 return false;
1103 }
1104
1105 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1106}
Geoff Lange102fee2015-12-10 11:23:30 -05001107
Geoff Lang70d0f492015-12-10 17:45:46 -05001108static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1109{
1110 switch (source)
1111 {
1112 case GL_DEBUG_SOURCE_API:
1113 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1114 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1115 case GL_DEBUG_SOURCE_OTHER:
1116 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1117 return !mustBeThirdPartyOrApplication;
1118
1119 case GL_DEBUG_SOURCE_THIRD_PARTY:
1120 case GL_DEBUG_SOURCE_APPLICATION:
1121 return true;
1122
1123 default:
1124 return false;
1125 }
1126}
1127
1128static bool ValidDebugType(GLenum type)
1129{
1130 switch (type)
1131 {
1132 case GL_DEBUG_TYPE_ERROR:
1133 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1134 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1135 case GL_DEBUG_TYPE_PERFORMANCE:
1136 case GL_DEBUG_TYPE_PORTABILITY:
1137 case GL_DEBUG_TYPE_OTHER:
1138 case GL_DEBUG_TYPE_MARKER:
1139 case GL_DEBUG_TYPE_PUSH_GROUP:
1140 case GL_DEBUG_TYPE_POP_GROUP:
1141 return true;
1142
1143 default:
1144 return false;
1145 }
1146}
1147
1148static bool ValidDebugSeverity(GLenum severity)
1149{
1150 switch (severity)
1151 {
1152 case GL_DEBUG_SEVERITY_HIGH:
1153 case GL_DEBUG_SEVERITY_MEDIUM:
1154 case GL_DEBUG_SEVERITY_LOW:
1155 case GL_DEBUG_SEVERITY_NOTIFICATION:
1156 return true;
1157
1158 default:
1159 return false;
1160 }
1161}
1162
Geoff Lange102fee2015-12-10 11:23:30 -05001163bool ValidateDebugMessageControlKHR(Context *context,
1164 GLenum source,
1165 GLenum type,
1166 GLenum severity,
1167 GLsizei count,
1168 const GLuint *ids,
1169 GLboolean enabled)
1170{
1171 if (!context->getExtensions().debug)
1172 {
1173 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1174 return false;
1175 }
1176
Geoff Lang70d0f492015-12-10 17:45:46 -05001177 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1178 {
1179 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
1180 return false;
1181 }
1182
1183 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1184 {
1185 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug type."));
1186 return false;
1187 }
1188
1189 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1190 {
1191 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
1192 return false;
1193 }
1194
1195 if (count > 0)
1196 {
1197 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1198 {
1199 context->recordError(Error(
1200 GL_INVALID_OPERATION,
1201 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1202 return false;
1203 }
1204
1205 if (severity != GL_DONT_CARE)
1206 {
1207 context->recordError(
1208 Error(GL_INVALID_OPERATION,
1209 "If count is greater than zero, severity must be GL_DONT_CARE."));
1210 return false;
1211 }
1212 }
1213
Geoff Lange102fee2015-12-10 11:23:30 -05001214 return true;
1215}
1216
1217bool ValidateDebugMessageInsertKHR(Context *context,
1218 GLenum source,
1219 GLenum type,
1220 GLuint id,
1221 GLenum severity,
1222 GLsizei length,
1223 const GLchar *buf)
1224{
1225 if (!context->getExtensions().debug)
1226 {
1227 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1228 return false;
1229 }
1230
Geoff Lang70d0f492015-12-10 17:45:46 -05001231 if (!context->getState().getDebug().isOutputEnabled())
1232 {
1233 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1234 // not generate an error.
1235 return false;
1236 }
1237
1238 if (!ValidDebugSeverity(severity))
1239 {
1240 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
1241 return false;
1242 }
1243
1244 if (!ValidDebugType(type))
1245 {
1246 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug type."));
1247 return false;
1248 }
1249
1250 if (!ValidDebugSource(source, true))
1251 {
1252 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
1253 return false;
1254 }
1255
1256 size_t messageLength = (length < 0) ? strlen(buf) : length;
1257 if (messageLength > context->getExtensions().maxDebugMessageLength)
1258 {
1259 context->recordError(
1260 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1261 return false;
1262 }
1263
Geoff Lange102fee2015-12-10 11:23:30 -05001264 return true;
1265}
1266
1267bool ValidateDebugMessageCallbackKHR(Context *context,
1268 GLDEBUGPROCKHR callback,
1269 const void *userParam)
1270{
1271 if (!context->getExtensions().debug)
1272 {
1273 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1274 return false;
1275 }
1276
Geoff Lange102fee2015-12-10 11:23:30 -05001277 return true;
1278}
1279
1280bool ValidateGetDebugMessageLogKHR(Context *context,
1281 GLuint count,
1282 GLsizei bufSize,
1283 GLenum *sources,
1284 GLenum *types,
1285 GLuint *ids,
1286 GLenum *severities,
1287 GLsizei *lengths,
1288 GLchar *messageLog)
1289{
1290 if (!context->getExtensions().debug)
1291 {
1292 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1293 return false;
1294 }
1295
Geoff Lang70d0f492015-12-10 17:45:46 -05001296 if (bufSize < 0 && messageLog != nullptr)
1297 {
1298 context->recordError(
1299 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1300 return false;
1301 }
1302
Geoff Lange102fee2015-12-10 11:23:30 -05001303 return true;
1304}
1305
1306bool ValidatePushDebugGroupKHR(Context *context,
1307 GLenum source,
1308 GLuint id,
1309 GLsizei length,
1310 const GLchar *message)
1311{
1312 if (!context->getExtensions().debug)
1313 {
1314 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1315 return false;
1316 }
1317
Geoff Lang70d0f492015-12-10 17:45:46 -05001318 if (!ValidDebugSource(source, true))
1319 {
1320 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
1321 return false;
1322 }
1323
1324 size_t messageLength = (length < 0) ? strlen(message) : length;
1325 if (messageLength > context->getExtensions().maxDebugMessageLength)
1326 {
1327 context->recordError(
1328 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1329 return false;
1330 }
1331
1332 size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
1333 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1334 {
1335 context->recordError(
1336 Error(GL_STACK_OVERFLOW,
1337 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1338 return false;
1339 }
1340
Geoff Lange102fee2015-12-10 11:23:30 -05001341 return true;
1342}
1343
1344bool ValidatePopDebugGroupKHR(Context *context)
1345{
1346 if (!context->getExtensions().debug)
1347 {
1348 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1349 return false;
1350 }
1351
Geoff Lang70d0f492015-12-10 17:45:46 -05001352 size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
1353 if (currentStackSize <= 1)
1354 {
1355 context->recordError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
1356 return false;
1357 }
1358
1359 return true;
1360}
1361
1362static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1363{
1364 switch (identifier)
1365 {
1366 case GL_BUFFER:
1367 if (context->getBuffer(name) == nullptr)
1368 {
1369 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
1370 return false;
1371 }
1372 return true;
1373
1374 case GL_SHADER:
1375 if (context->getShader(name) == nullptr)
1376 {
1377 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
1378 return false;
1379 }
1380 return true;
1381
1382 case GL_PROGRAM:
1383 if (context->getProgram(name) == nullptr)
1384 {
1385 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid program."));
1386 return false;
1387 }
1388 return true;
1389
1390 case GL_VERTEX_ARRAY:
1391 if (context->getVertexArray(name) == nullptr)
1392 {
1393 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
1394 return false;
1395 }
1396 return true;
1397
1398 case GL_QUERY:
1399 if (context->getQuery(name) == nullptr)
1400 {
1401 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid query."));
1402 return false;
1403 }
1404 return true;
1405
1406 case GL_TRANSFORM_FEEDBACK:
1407 if (context->getTransformFeedback(name) == nullptr)
1408 {
1409 context->recordError(
1410 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1411 return false;
1412 }
1413 return true;
1414
1415 case GL_SAMPLER:
1416 if (context->getSampler(name) == nullptr)
1417 {
1418 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
1419 return false;
1420 }
1421 return true;
1422
1423 case GL_TEXTURE:
1424 if (context->getTexture(name) == nullptr)
1425 {
1426 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
1427 return false;
1428 }
1429 return true;
1430
1431 case GL_RENDERBUFFER:
1432 if (context->getRenderbuffer(name) == nullptr)
1433 {
1434 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
1435 return false;
1436 }
1437 return true;
1438
1439 case GL_FRAMEBUFFER:
1440 if (context->getFramebuffer(name) == nullptr)
1441 {
1442 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
1443 return false;
1444 }
1445 return true;
1446
1447 default:
1448 context->recordError(Error(GL_INVALID_ENUM, "Invalid identifier."));
1449 return false;
1450 }
1451
Geoff Lange102fee2015-12-10 11:23:30 -05001452 return true;
1453}
1454
1455bool ValidateObjectLabelKHR(Context *context,
1456 GLenum identifier,
1457 GLuint name,
1458 GLsizei length,
1459 const GLchar *label)
1460{
1461 if (!context->getExtensions().debug)
1462 {
1463 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1464 return false;
1465 }
1466
Geoff Lang70d0f492015-12-10 17:45:46 -05001467 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1468 {
1469 return false;
1470 }
1471
1472 size_t labelLength = (length < 0) ? strlen(label) : length;
1473 if (labelLength > context->getExtensions().maxLabelLength)
1474 {
1475 context->recordError(
1476 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1477 return false;
1478 }
1479
Geoff Lange102fee2015-12-10 11:23:30 -05001480 return true;
1481}
1482
1483bool ValidateGetObjectLabelKHR(Context *context,
1484 GLenum identifier,
1485 GLuint name,
1486 GLsizei bufSize,
1487 GLsizei *length,
1488 GLchar *label)
1489{
1490 if (!context->getExtensions().debug)
1491 {
1492 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1493 return false;
1494 }
1495
Geoff Lang70d0f492015-12-10 17:45:46 -05001496 if (bufSize < 0)
1497 {
1498 context->recordError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1499 return false;
1500 }
1501
1502 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1503 {
1504 return false;
1505 }
1506
1507 // Can no-op if bufSize is zero.
1508 return bufSize > 0;
1509}
1510
1511static bool ValidateObjectPtrName(Context *context, const void *ptr)
1512{
1513 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1514 {
1515 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
1516 return false;
1517 }
1518
Geoff Lange102fee2015-12-10 11:23:30 -05001519 return true;
1520}
1521
1522bool ValidateObjectPtrLabelKHR(Context *context,
1523 const void *ptr,
1524 GLsizei length,
1525 const GLchar *label)
1526{
1527 if (!context->getExtensions().debug)
1528 {
1529 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1530 return false;
1531 }
1532
Geoff Lang70d0f492015-12-10 17:45:46 -05001533 if (!ValidateObjectPtrName(context, ptr))
1534 {
1535 return false;
1536 }
1537
1538 size_t labelLength = (length < 0) ? strlen(label) : length;
1539 if (labelLength > context->getExtensions().maxLabelLength)
1540 {
1541 context->recordError(
1542 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1543 return false;
1544 }
1545
Geoff Lange102fee2015-12-10 11:23:30 -05001546 return true;
1547}
1548
1549bool ValidateGetObjectPtrLabelKHR(Context *context,
1550 const void *ptr,
1551 GLsizei bufSize,
1552 GLsizei *length,
1553 GLchar *label)
1554{
1555 if (!context->getExtensions().debug)
1556 {
1557 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1558 return false;
1559 }
1560
Geoff Lang70d0f492015-12-10 17:45:46 -05001561 if (bufSize < 0)
1562 {
1563 context->recordError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1564 return false;
1565 }
1566
1567 if (!ValidateObjectPtrName(context, ptr))
1568 {
1569 return false;
1570 }
1571
1572 // Can no-op if bufSize is zero.
1573 return bufSize > 0;
Geoff Lange102fee2015-12-10 11:23:30 -05001574}
1575
1576bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1577{
1578 if (!context->getExtensions().debug)
1579 {
1580 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1581 return false;
1582 }
1583
Geoff Lang70d0f492015-12-10 17:45:46 -05001584 // TODO: represent this in Context::getQueryParameterInfo.
1585 switch (pname)
1586 {
1587 case GL_DEBUG_CALLBACK_FUNCTION:
1588 case GL_DEBUG_CALLBACK_USER_PARAM:
1589 break;
1590
1591 default:
1592 context->recordError(Error(GL_INVALID_ENUM, "Invalid pname."));
1593 return false;
1594 }
1595
Geoff Lange102fee2015-12-10 11:23:30 -05001596 return true;
1597}
Jamie Madillc29968b2016-01-20 11:17:23 -05001598
1599bool ValidateBlitFramebufferANGLE(Context *context,
1600 GLint srcX0,
1601 GLint srcY0,
1602 GLint srcX1,
1603 GLint srcY1,
1604 GLint dstX0,
1605 GLint dstY0,
1606 GLint dstX1,
1607 GLint dstY1,
1608 GLbitfield mask,
1609 GLenum filter)
1610{
1611 if (!context->getExtensions().framebufferBlit)
1612 {
1613 context->recordError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
1614 return false;
1615 }
1616
1617 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1618 {
1619 // TODO(jmadill): Determine if this should be available on other implementations.
1620 context->recordError(Error(
1621 GL_INVALID_OPERATION,
1622 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1623 return false;
1624 }
1625
1626 if (filter == GL_LINEAR)
1627 {
1628 context->recordError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
1629 return false;
1630 }
1631
1632 const Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
1633 const Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
1634
1635 if (mask & GL_COLOR_BUFFER_BIT)
1636 {
1637 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1638 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1639
1640 if (readColorAttachment && drawColorAttachment)
1641 {
1642 if (!(readColorAttachment->type() == GL_TEXTURE &&
1643 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1644 readColorAttachment->type() != GL_RENDERBUFFER &&
1645 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1646 {
1647 context->recordError(Error(GL_INVALID_OPERATION));
1648 return false;
1649 }
1650
Geoff Langa15472a2015-08-11 11:48:03 -04001651 for (size_t drawbufferIdx = 0;
1652 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001653 {
Geoff Langa15472a2015-08-11 11:48:03 -04001654 const FramebufferAttachment *attachment =
1655 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1656 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001657 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001658 if (!(attachment->type() == GL_TEXTURE &&
1659 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1660 attachment->type() != GL_RENDERBUFFER &&
1661 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1662 {
1663 context->recordError(Error(GL_INVALID_OPERATION));
1664 return false;
1665 }
1666
1667 // Return an error if the destination formats do not match
1668 if (attachment->getInternalFormat() != readColorAttachment->getInternalFormat())
1669 {
1670 context->recordError(Error(GL_INVALID_OPERATION));
1671 return false;
1672 }
1673 }
1674 }
1675
1676 int readSamples = readFramebuffer->getSamples(context->getData());
1677
1678 if (readSamples != 0 &&
1679 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1680 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1681 {
1682 context->recordError(Error(GL_INVALID_OPERATION));
1683 return false;
1684 }
1685 }
1686 }
1687
1688 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1689 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1690 for (size_t i = 0; i < 2; i++)
1691 {
1692 if (mask & masks[i])
1693 {
1694 const FramebufferAttachment *readBuffer =
1695 readFramebuffer->getAttachment(attachments[i]);
1696 const FramebufferAttachment *drawBuffer =
1697 drawFramebuffer->getAttachment(attachments[i]);
1698
1699 if (readBuffer && drawBuffer)
1700 {
1701 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1702 dstX0, dstY0, dstX1, dstY1))
1703 {
1704 // only whole-buffer copies are permitted
1705 ERR(
1706 "Only whole-buffer depth and stencil blits are supported by this "
1707 "implementation.");
1708 context->recordError(Error(GL_INVALID_OPERATION));
1709 return false;
1710 }
1711
1712 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1713 {
1714 context->recordError(Error(GL_INVALID_OPERATION));
1715 return false;
1716 }
1717 }
1718 }
1719 }
1720
1721 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1722 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001723}
Jamie Madillc29968b2016-01-20 11:17:23 -05001724
1725bool ValidateClear(ValidationContext *context, GLbitfield mask)
1726{
1727 const Framebuffer *framebufferObject = context->getState().getDrawFramebuffer();
1728 ASSERT(framebufferObject);
1729
1730 if (framebufferObject->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
1731 {
1732 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
1733 return false;
1734 }
1735
1736 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1737 {
1738 context->recordError(Error(GL_INVALID_VALUE));
1739 return false;
1740 }
1741
1742 return true;
1743}
1744
1745bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1746{
1747 if (!context->getExtensions().drawBuffers)
1748 {
1749 context->recordError(Error(GL_INVALID_OPERATION, "Extension not supported."));
1750 return false;
1751 }
1752
1753 return ValidateDrawBuffersBase(context, n, bufs);
1754}
1755
1756} // namespace gl