blob: cfceef6bbdd30182e4de90f9365e4633c142324b [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
9#include "libGLESv2/validationES2.h"
Geoff Langce635692013-09-24 13:56:32 -040010#include "libGLESv2/validationES.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040011#include "libGLESv2/Context.h"
12#include "libGLESv2/Texture.h"
13#include "libGLESv2/Framebuffer.h"
14#include "libGLESv2/Renderbuffer.h"
15#include "libGLESv2/formatutils.h"
16#include "libGLESv2/main.h"
Jamie Madille261b442014-06-25 12:42:21 -040017#include "libGLESv2/FramebufferAttachment.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040018
19#include "common/mathutil.h"
20#include "common/utilities.h"
21
22namespace gl
23{
24
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025static bool validateSubImageParams2D(bool compressed, GLsizei width, GLsizei height,
26 GLint xoffset, GLint yoffset, GLint level, GLenum format, GLenum type,
27 gl::Texture2D *texture)
28{
29 if (!texture)
30 {
31 return gl::error(GL_INVALID_OPERATION, false);
32 }
33
34 if (compressed != texture->isCompressed(level))
35 {
36 return gl::error(GL_INVALID_OPERATION, false);
37 }
38
39 if (format != GL_NONE)
40 {
Geoff Lang5d601382014-07-22 15:14:06 -040041 if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040042 {
43 return gl::error(GL_INVALID_OPERATION, false);
44 }
45 }
46
47 if (compressed)
48 {
Geoff Langa836e482014-04-28 10:08:27 -040049 if ((width % 4 != 0 && width != texture->getWidth(level)) ||
50 (height % 4 != 0 && height != texture->getHeight(level)))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040051 {
52 return gl::error(GL_INVALID_OPERATION, false);
53 }
54 }
55
56 if (xoffset + width > texture->getWidth(level) ||
57 yoffset + height > texture->getHeight(level))
58 {
59 return gl::error(GL_INVALID_VALUE, false);
60 }
61
62 return true;
63}
64
65static bool validateSubImageParamsCube(bool compressed, GLsizei width, GLsizei height,
66 GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, GLenum type,
67 gl::TextureCubeMap *texture)
68{
69 if (!texture)
70 {
71 return gl::error(GL_INVALID_OPERATION, false);
72 }
73
74 if (compressed != texture->isCompressed(target, level))
75 {
76 return gl::error(GL_INVALID_OPERATION, false);
77 }
78
79 if (format != GL_NONE)
80 {
Geoff Lang5d601382014-07-22 15:14:06 -040081 if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040082 {
83 return gl::error(GL_INVALID_OPERATION, false);
84 }
85 }
86
87 if (compressed)
88 {
89 if ((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
90 (height % 4 != 0 && height != texture->getHeight(target, 0)))
91 {
92 return gl::error(GL_INVALID_OPERATION, false);
93 }
94 }
95
96 if (xoffset + width > texture->getWidth(target, level) ||
97 yoffset + height > texture->getHeight(target, level))
98 {
99 return gl::error(GL_INVALID_VALUE, false);
100 }
101
102 return true;
103}
104
Geoff Lang005df412013-10-16 14:12:50 -0400105bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400106 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
107 GLint border, GLenum format, GLenum type, const GLvoid *pixels)
108{
Jamie Madill6f38f822014-06-06 17:12:20 -0400109 if (!ValidTexture2DDestinationTarget(context, target))
110 {
111 return gl::error(GL_INVALID_ENUM, false);
112 }
113
Geoff Langce635692013-09-24 13:56:32 -0400114 if (!ValidImageSize(context, target, level, width, height, 1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400115 {
116 return gl::error(GL_INVALID_VALUE, false);
117 }
118
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400119 if (level < 0 || xoffset < 0 ||
120 std::numeric_limits<GLsizei>::max() - xoffset < width ||
121 std::numeric_limits<GLsizei>::max() - yoffset < height)
122 {
123 return gl::error(GL_INVALID_VALUE, false);
124 }
125
Geoff Lang005df412013-10-16 14:12:50 -0400126 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400127 {
128 return gl::error(GL_INVALID_OPERATION, false);
129 }
130
Geoff Langaae65a42014-05-26 12:43:44 -0400131 const gl::Caps &caps = context->getCaps();
132
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400133 gl::Texture *texture = NULL;
134 bool textureCompressed = false;
135 GLenum textureInternalFormat = GL_NONE;
136 GLint textureLevelWidth = 0;
137 GLint textureLevelHeight = 0;
138 switch (target)
139 {
140 case GL_TEXTURE_2D:
141 {
Geoff Langaae65a42014-05-26 12:43:44 -0400142 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
143 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400144 {
145 return gl::error(GL_INVALID_VALUE, false);
146 }
147
148 gl::Texture2D *tex2d = context->getTexture2D();
149 if (tex2d)
150 {
151 textureCompressed = tex2d->isCompressed(level);
152 textureInternalFormat = tex2d->getInternalFormat(level);
153 textureLevelWidth = tex2d->getWidth(level);
154 textureLevelHeight = tex2d->getHeight(level);
155 texture = tex2d;
156 }
157
158 if (isSubImage && !validateSubImageParams2D(isCompressed, width, height, xoffset, yoffset,
159 level, format, type, tex2d))
160 {
161 return false;
162 }
163
164 texture = tex2d;
165 }
166 break;
167
168 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
169 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
170 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
171 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
172 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
173 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
174 {
175 if (!isSubImage && width != height)
176 {
177 return gl::error(GL_INVALID_VALUE, false);
178 }
179
Geoff Langaae65a42014-05-26 12:43:44 -0400180 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
181 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400182 {
183 return gl::error(GL_INVALID_VALUE, false);
184 }
185
186 gl::TextureCubeMap *texCube = context->getTextureCubeMap();
187 if (texCube)
188 {
189 textureCompressed = texCube->isCompressed(target, level);
190 textureInternalFormat = texCube->getInternalFormat(target, level);
191 textureLevelWidth = texCube->getWidth(target, level);
192 textureLevelHeight = texCube->getHeight(target, level);
193 texture = texCube;
194 }
195
196 if (isSubImage && !validateSubImageParamsCube(isCompressed, width, height, xoffset, yoffset,
197 target, level, format, type, texCube))
198 {
199 return false;
200 }
201 }
202 break;
203
204 default:
205 return gl::error(GL_INVALID_ENUM, false);
206 }
207
208 if (!texture)
209 {
210 return gl::error(GL_INVALID_OPERATION, false);
211 }
212
213 if (!isSubImage && texture->isImmutable())
214 {
215 return gl::error(GL_INVALID_OPERATION, false);
216 }
217
218 // Verify zero border
219 if (border != 0)
220 {
221 return gl::error(GL_INVALID_VALUE, false);
222 }
223
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400224 GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
225 if (isCompressed)
226 {
Geoff Langd4f180b2013-09-24 13:57:44 -0400227 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
228 {
229 return gl::error(GL_INVALID_OPERATION, false);
230 }
231
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400232 switch (actualInternalFormat)
233 {
234 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
235 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400236 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400237 {
238 return gl::error(GL_INVALID_ENUM, false);
239 }
240 break;
241 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400242 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400243 {
244 return gl::error(GL_INVALID_ENUM, false);
245 }
246 break;
247 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400248 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400249 {
250 return gl::error(GL_INVALID_ENUM, false);
251 }
252 break;
253 default:
254 return gl::error(GL_INVALID_ENUM, false);
255 }
256 }
257 else
258 {
259 // validate <type> by itself (used as secondary key below)
260 switch (type)
261 {
262 case GL_UNSIGNED_BYTE:
263 case GL_UNSIGNED_SHORT_5_6_5:
264 case GL_UNSIGNED_SHORT_4_4_4_4:
265 case GL_UNSIGNED_SHORT_5_5_5_1:
266 case GL_UNSIGNED_SHORT:
267 case GL_UNSIGNED_INT:
268 case GL_UNSIGNED_INT_24_8_OES:
269 case GL_HALF_FLOAT_OES:
270 case GL_FLOAT:
271 break;
272 default:
273 return gl::error(GL_INVALID_ENUM, false);
274 }
275
276 // validate <format> + <type> combinations
277 // - invalid <format> -> sets INVALID_ENUM
278 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
279 switch (format)
280 {
281 case GL_ALPHA:
282 case GL_LUMINANCE:
283 case GL_LUMINANCE_ALPHA:
284 switch (type)
285 {
286 case GL_UNSIGNED_BYTE:
287 case GL_FLOAT:
288 case GL_HALF_FLOAT_OES:
289 break;
290 default:
291 return gl::error(GL_INVALID_OPERATION, false);
292 }
293 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400294 case GL_RED:
Geoff Langcec35902014-04-16 10:52:36 -0400295 case GL_RG:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400296 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400297 {
298 return gl::error(GL_INVALID_ENUM, false);
299 }
300 switch (type)
301 {
302 case GL_UNSIGNED_BYTE:
303 case GL_FLOAT:
304 case GL_HALF_FLOAT_OES:
305 break;
306 default:
307 return gl::error(GL_INVALID_OPERATION, false);
308 }
309 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400310 case GL_RGB:
311 switch (type)
312 {
313 case GL_UNSIGNED_BYTE:
314 case GL_UNSIGNED_SHORT_5_6_5:
315 case GL_FLOAT:
316 case GL_HALF_FLOAT_OES:
317 break;
318 default:
319 return gl::error(GL_INVALID_OPERATION, false);
320 }
321 break;
322 case GL_RGBA:
323 switch (type)
324 {
325 case GL_UNSIGNED_BYTE:
326 case GL_UNSIGNED_SHORT_4_4_4_4:
327 case GL_UNSIGNED_SHORT_5_5_5_1:
328 case GL_FLOAT:
329 case GL_HALF_FLOAT_OES:
330 break;
331 default:
332 return gl::error(GL_INVALID_OPERATION, false);
333 }
334 break;
335 case GL_BGRA_EXT:
336 switch (type)
337 {
338 case GL_UNSIGNED_BYTE:
339 break;
340 default:
341 return gl::error(GL_INVALID_OPERATION, false);
342 }
343 break;
Geoff Lang05b05022014-06-11 15:31:45 -0400344 case GL_SRGB_EXT:
345 case GL_SRGB_ALPHA_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400346 if (!context->getExtensions().sRGB)
Geoff Lang05b05022014-06-11 15:31:45 -0400347 {
348 return gl::error(GL_INVALID_ENUM, false);
349 }
350 switch (type)
351 {
352 case GL_UNSIGNED_BYTE:
353 break;
354 default:
355 return gl::error(GL_INVALID_OPERATION, false);
356 }
357 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400358 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
359 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
360 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
361 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
362 break;
363 case GL_DEPTH_COMPONENT:
364 switch (type)
365 {
366 case GL_UNSIGNED_SHORT:
367 case GL_UNSIGNED_INT:
368 break;
369 default:
370 return gl::error(GL_INVALID_OPERATION, false);
371 }
372 break;
373 case GL_DEPTH_STENCIL_OES:
374 switch (type)
375 {
376 case GL_UNSIGNED_INT_24_8_OES:
377 break;
378 default:
379 return gl::error(GL_INVALID_OPERATION, false);
380 }
381 break;
382 default:
383 return gl::error(GL_INVALID_ENUM, false);
384 }
385
386 switch (format)
387 {
388 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
389 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400390 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400391 {
392 return gl::error(GL_INVALID_OPERATION, false);
393 }
394 else
395 {
396 return gl::error(GL_INVALID_ENUM, false);
397 }
398 break;
399 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400400 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400401 {
402 return gl::error(GL_INVALID_OPERATION, false);
403 }
404 else
405 {
406 return gl::error(GL_INVALID_ENUM, false);
407 }
408 break;
409 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400410 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400411 {
412 return gl::error(GL_INVALID_OPERATION, false);
413 }
414 else
415 {
416 return gl::error(GL_INVALID_ENUM, false);
417 }
418 break;
419 case GL_DEPTH_COMPONENT:
420 case GL_DEPTH_STENCIL_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400421 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400422 {
423 return gl::error(GL_INVALID_VALUE, false);
424 }
425 if (target != GL_TEXTURE_2D)
426 {
427 return gl::error(GL_INVALID_OPERATION, false);
428 }
429 // OES_depth_texture supports loading depth data and multiple levels,
430 // but ANGLE_depth_texture does not
431 if (pixels != NULL || level != 0)
432 {
433 return gl::error(GL_INVALID_OPERATION, false);
434 }
435 break;
436 default:
437 break;
438 }
439
440 if (type == GL_FLOAT)
441 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400442 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400443 {
444 return gl::error(GL_INVALID_ENUM, false);
445 }
446 }
447 else if (type == GL_HALF_FLOAT_OES)
448 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400449 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400450 {
451 return gl::error(GL_INVALID_ENUM, false);
452 }
453 }
454 }
455
456 return true;
457}
458
459
460
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400461bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400462 GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height,
463 GLint border)
464{
Jamie Madill560a8d82014-05-21 13:06:20 -0400465 GLenum textureInternalFormat = GL_NONE;
Shannon Woods4dfed832014-03-17 20:03:39 -0400466
Jamie Madill560a8d82014-05-21 13:06:20 -0400467 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
468 xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400469 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400470 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400471 }
472
Shannon Woods53a94a82014-06-24 15:20:36 -0400473 gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400474 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat();
Geoff Lang5d601382014-07-22 15:14:06 -0400475 GLenum textureFormat = gl::GetInternalFormatInfo(textureInternalFormat).format;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400476
477 // [OpenGL ES 2.0.24] table 3.9
478 if (isSubImage)
479 {
480 switch (textureFormat)
481 {
482 case GL_ALPHA:
483 if (colorbufferFormat != GL_ALPHA8_EXT &&
484 colorbufferFormat != GL_RGBA4 &&
485 colorbufferFormat != GL_RGB5_A1 &&
486 colorbufferFormat != GL_RGBA8_OES)
487 {
488 return gl::error(GL_INVALID_OPERATION, false);
489 }
490 break;
491 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400492 if (colorbufferFormat != GL_R8_EXT &&
493 colorbufferFormat != GL_RG8_EXT &&
494 colorbufferFormat != GL_RGB565 &&
495 colorbufferFormat != GL_RGB8_OES &&
496 colorbufferFormat != GL_RGBA4 &&
497 colorbufferFormat != GL_RGB5_A1 &&
498 colorbufferFormat != GL_RGBA8_OES)
499 {
500 return gl::error(GL_INVALID_OPERATION, false);
501 }
502 break;
503 case GL_RED_EXT:
504 if (colorbufferFormat != GL_R8_EXT &&
505 colorbufferFormat != GL_RG8_EXT &&
506 colorbufferFormat != GL_RGB565 &&
507 colorbufferFormat != GL_RGB8_OES &&
508 colorbufferFormat != GL_RGBA4 &&
509 colorbufferFormat != GL_RGB5_A1 &&
510 colorbufferFormat != GL_RGBA8_OES)
511 {
512 return gl::error(GL_INVALID_OPERATION, false);
513 }
514 break;
515 case GL_RG_EXT:
516 if (colorbufferFormat != GL_RG8_EXT &&
517 colorbufferFormat != GL_RGB565 &&
518 colorbufferFormat != GL_RGB8_OES &&
519 colorbufferFormat != GL_RGBA4 &&
520 colorbufferFormat != GL_RGB5_A1 &&
521 colorbufferFormat != GL_RGBA8_OES)
522 {
523 return gl::error(GL_INVALID_OPERATION, false);
524 }
525 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400526 case GL_RGB:
527 if (colorbufferFormat != GL_RGB565 &&
528 colorbufferFormat != GL_RGB8_OES &&
529 colorbufferFormat != GL_RGBA4 &&
530 colorbufferFormat != GL_RGB5_A1 &&
531 colorbufferFormat != GL_RGBA8_OES)
532 {
533 return gl::error(GL_INVALID_OPERATION, false);
534 }
535 break;
536 case GL_LUMINANCE_ALPHA:
537 case GL_RGBA:
538 if (colorbufferFormat != GL_RGBA4 &&
539 colorbufferFormat != GL_RGB5_A1 &&
540 colorbufferFormat != GL_RGBA8_OES)
541 {
542 return gl::error(GL_INVALID_OPERATION, false);
543 }
544 break;
545 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
546 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
547 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
548 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
549 return gl::error(GL_INVALID_OPERATION, false);
550 case GL_DEPTH_COMPONENT:
551 case GL_DEPTH_STENCIL_OES:
552 return gl::error(GL_INVALID_OPERATION, false);
553 default:
554 return gl::error(GL_INVALID_OPERATION, false);
555 }
556 }
557 else
558 {
559 switch (internalformat)
560 {
561 case GL_ALPHA:
562 if (colorbufferFormat != GL_ALPHA8_EXT &&
563 colorbufferFormat != GL_RGBA4 &&
564 colorbufferFormat != GL_RGB5_A1 &&
565 colorbufferFormat != GL_BGRA8_EXT &&
566 colorbufferFormat != GL_RGBA8_OES)
567 {
568 return gl::error(GL_INVALID_OPERATION, false);
569 }
570 break;
571 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400572 if (colorbufferFormat != GL_R8_EXT &&
573 colorbufferFormat != GL_RG8_EXT &&
574 colorbufferFormat != GL_RGB565 &&
575 colorbufferFormat != GL_RGB8_OES &&
576 colorbufferFormat != GL_RGBA4 &&
577 colorbufferFormat != GL_RGB5_A1 &&
578 colorbufferFormat != GL_BGRA8_EXT &&
579 colorbufferFormat != GL_RGBA8_OES)
580 {
581 return gl::error(GL_INVALID_OPERATION, false);
582 }
583 break;
584 case GL_RED_EXT:
585 if (colorbufferFormat != GL_R8_EXT &&
586 colorbufferFormat != GL_RG8_EXT &&
587 colorbufferFormat != GL_RGB565 &&
588 colorbufferFormat != GL_RGB8_OES &&
589 colorbufferFormat != GL_RGBA4 &&
590 colorbufferFormat != GL_RGB5_A1 &&
591 colorbufferFormat != GL_BGRA8_EXT &&
592 colorbufferFormat != GL_RGBA8_OES)
593 {
594 return gl::error(GL_INVALID_OPERATION, false);
595 }
596 break;
597 case GL_RG_EXT:
598 if (colorbufferFormat != GL_RG8_EXT &&
599 colorbufferFormat != GL_RGB565 &&
600 colorbufferFormat != GL_RGB8_OES &&
601 colorbufferFormat != GL_RGBA4 &&
602 colorbufferFormat != GL_RGB5_A1 &&
603 colorbufferFormat != GL_BGRA8_EXT &&
604 colorbufferFormat != GL_RGBA8_OES)
605 {
606 return gl::error(GL_INVALID_OPERATION, false);
607 }
608 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400609 case GL_RGB:
610 if (colorbufferFormat != GL_RGB565 &&
611 colorbufferFormat != GL_RGB8_OES &&
612 colorbufferFormat != GL_RGBA4 &&
613 colorbufferFormat != GL_RGB5_A1 &&
614 colorbufferFormat != GL_BGRA8_EXT &&
615 colorbufferFormat != GL_RGBA8_OES)
616 {
617 return gl::error(GL_INVALID_OPERATION, false);
618 }
619 break;
620 case GL_LUMINANCE_ALPHA:
621 case GL_RGBA:
622 if (colorbufferFormat != GL_RGBA4 &&
623 colorbufferFormat != GL_RGB5_A1 &&
624 colorbufferFormat != GL_BGRA8_EXT &&
625 colorbufferFormat != GL_RGBA8_OES)
626 {
627 return gl::error(GL_INVALID_OPERATION, false);
628 }
629 break;
630 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
631 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400632 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400633 {
634 return gl::error(GL_INVALID_OPERATION, false);
635 }
636 else
637 {
638 return gl::error(GL_INVALID_ENUM, false);
639 }
640 break;
641 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400642 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400643 {
644 return gl::error(GL_INVALID_OPERATION, false);
645 }
646 else
647 {
648 return gl::error(GL_INVALID_ENUM, false);
649 }
650 break;
651 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400652 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400653 {
654 return gl::error(GL_INVALID_OPERATION, false);
655 }
656 else
657 {
658 return gl::error(GL_INVALID_ENUM, false);
659 }
660 break;
661 case GL_DEPTH_COMPONENT:
662 case GL_DEPTH_COMPONENT16:
663 case GL_DEPTH_COMPONENT32_OES:
664 case GL_DEPTH_STENCIL_OES:
665 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400666 if (context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400667 {
668 return gl::error(GL_INVALID_OPERATION, false);
669 }
670 else
671 {
672 return gl::error(GL_INVALID_ENUM, false);
673 }
674 default:
675 return gl::error(GL_INVALID_ENUM, false);
676 }
677 }
678
Geoff Lang784a8fd2013-09-24 12:33:16 -0400679 // If width or height is zero, it is a no-op. Return false without setting an error.
680 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400681}
682
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400683bool ValidateES2TexStorageParameters(gl::Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400684 GLsizei width, GLsizei height)
685{
686 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
687 {
688 return gl::error(GL_INVALID_ENUM, false);
689 }
690
691 if (width < 1 || height < 1 || levels < 1)
692 {
693 return gl::error(GL_INVALID_VALUE, false);
694 }
695
696 if (target == GL_TEXTURE_CUBE_MAP && width != height)
697 {
698 return gl::error(GL_INVALID_VALUE, false);
699 }
700
701 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
702 {
703 return gl::error(GL_INVALID_OPERATION, false);
704 }
705
Geoff Lang5d601382014-07-22 15:14:06 -0400706 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
707 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400708 {
709 return gl::error(GL_INVALID_ENUM, false);
710 }
711
Geoff Langaae65a42014-05-26 12:43:44 -0400712 const gl::Caps &caps = context->getCaps();
713
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400714 switch (target)
715 {
716 case GL_TEXTURE_2D:
Geoff Langaae65a42014-05-26 12:43:44 -0400717 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
718 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400719 {
720 return gl::error(GL_INVALID_VALUE, false);
721 }
722 break;
723 case GL_TEXTURE_CUBE_MAP:
Geoff Langaae65a42014-05-26 12:43:44 -0400724 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
725 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400726 {
727 return gl::error(GL_INVALID_VALUE, false);
728 }
729 break;
730 default:
731 return gl::error(GL_INVALID_ENUM, false);
732 }
733
Geoff Langc0b9ef42014-07-02 10:02:37 -0400734 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400735 {
736 if (!gl::isPow2(width) || !gl::isPow2(height))
737 {
738 return gl::error(GL_INVALID_OPERATION, false);
739 }
740 }
741
742 switch (internalformat)
743 {
744 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
745 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400746 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400747 {
748 return gl::error(GL_INVALID_ENUM, false);
749 }
750 break;
751 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400752 if (!context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400753 {
754 return gl::error(GL_INVALID_ENUM, false);
755 }
756 break;
757 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400758 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400759 {
760 return gl::error(GL_INVALID_ENUM, false);
761 }
762 break;
763 case GL_RGBA32F_EXT:
764 case GL_RGB32F_EXT:
765 case GL_ALPHA32F_EXT:
766 case GL_LUMINANCE32F_EXT:
767 case GL_LUMINANCE_ALPHA32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400768 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400769 {
770 return gl::error(GL_INVALID_ENUM, false);
771 }
772 break;
773 case GL_RGBA16F_EXT:
774 case GL_RGB16F_EXT:
775 case GL_ALPHA16F_EXT:
776 case GL_LUMINANCE16F_EXT:
777 case GL_LUMINANCE_ALPHA16F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400778 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400779 {
780 return gl::error(GL_INVALID_ENUM, false);
781 }
782 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400783 case GL_R8_EXT:
784 case GL_RG8_EXT:
785 case GL_R16F_EXT:
786 case GL_RG16F_EXT:
787 case GL_R32F_EXT:
788 case GL_RG32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400789 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400790 {
791 return gl::error(GL_INVALID_ENUM, false);
792 }
793 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400794 case GL_DEPTH_COMPONENT16:
795 case GL_DEPTH_COMPONENT32_OES:
796 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400797 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400798 {
799 return gl::error(GL_INVALID_ENUM, false);
800 }
801 if (target != GL_TEXTURE_2D)
802 {
803 return gl::error(GL_INVALID_OPERATION, false);
804 }
805 // ANGLE_depth_texture only supports 1-level textures
806 if (levels != 1)
807 {
808 return gl::error(GL_INVALID_OPERATION, false);
809 }
810 break;
811 default:
812 break;
813 }
814
815 gl::Texture *texture = NULL;
816 switch(target)
817 {
818 case GL_TEXTURE_2D:
819 texture = context->getTexture2D();
820 break;
821 case GL_TEXTURE_CUBE_MAP:
822 texture = context->getTextureCubeMap();
823 break;
824 default:
825 UNREACHABLE();
826 }
827
828 if (!texture || texture->id() == 0)
829 {
830 return gl::error(GL_INVALID_OPERATION, false);
831 }
832
833 if (texture->isImmutable())
834 {
835 return gl::error(GL_INVALID_OPERATION, false);
836 }
837
838 return true;
839}
840
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400841// check for combinations of format and type that are valid for ReadPixels
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400842bool ValidES2ReadFormatType(gl::Context *context, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400843{
844 switch (format)
845 {
846 case GL_RGBA:
847 switch (type)
848 {
849 case GL_UNSIGNED_BYTE:
850 break;
851 default:
852 return false;
853 }
854 break;
855 case GL_BGRA_EXT:
856 switch (type)
857 {
858 case GL_UNSIGNED_BYTE:
859 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
860 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
861 break;
862 default:
863 return false;
864 }
865 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400866 case GL_RG_EXT:
867 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400868 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400869 {
870 return false;
871 }
872 switch (type)
873 {
874 case GL_UNSIGNED_BYTE:
875 break;
876 default:
877 return false;
878 }
879 break;
880
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400881 default:
882 return false;
883 }
884 return true;
885}
886
887}