blob: a0ef855e327297619028a034fb9b79c56755dfd6 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001#include "precompiled.h"
2//
3// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style license that can be
5// found in the LICENSE file.
6//
7
8// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
9
10#include "libGLESv2/validationES2.h"
Geoff Langce635692013-09-24 13:56:32 -040011#include "libGLESv2/validationES.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040012#include "libGLESv2/Context.h"
13#include "libGLESv2/Texture.h"
14#include "libGLESv2/Framebuffer.h"
15#include "libGLESv2/Renderbuffer.h"
16#include "libGLESv2/formatutils.h"
17#include "libGLESv2/main.h"
18
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 {
41 GLenum internalformat = gl::GetSizedInternalFormat(format, type, 2);
42 if (internalformat != texture->getInternalFormat(level))
43 {
44 return gl::error(GL_INVALID_OPERATION, false);
45 }
46 }
47
48 if (compressed)
49 {
Geoff Langa836e482014-04-28 10:08:27 -040050 if ((width % 4 != 0 && width != texture->getWidth(level)) ||
51 (height % 4 != 0 && height != texture->getHeight(level)))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040052 {
53 return gl::error(GL_INVALID_OPERATION, false);
54 }
55 }
56
57 if (xoffset + width > texture->getWidth(level) ||
58 yoffset + height > texture->getHeight(level))
59 {
60 return gl::error(GL_INVALID_VALUE, false);
61 }
62
63 return true;
64}
65
66static bool validateSubImageParamsCube(bool compressed, GLsizei width, GLsizei height,
67 GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, GLenum type,
68 gl::TextureCubeMap *texture)
69{
70 if (!texture)
71 {
72 return gl::error(GL_INVALID_OPERATION, false);
73 }
74
75 if (compressed != texture->isCompressed(target, level))
76 {
77 return gl::error(GL_INVALID_OPERATION, false);
78 }
79
80 if (format != GL_NONE)
81 {
82 GLenum internalformat = gl::GetSizedInternalFormat(format, type, 2);
83 if (internalformat != texture->getInternalFormat(target, level))
84 {
85 return gl::error(GL_INVALID_OPERATION, false);
86 }
87 }
88
89 if (compressed)
90 {
91 if ((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
92 (height % 4 != 0 && height != texture->getHeight(target, 0)))
93 {
94 return gl::error(GL_INVALID_OPERATION, false);
95 }
96 }
97
98 if (xoffset + width > texture->getWidth(target, level) ||
99 yoffset + height > texture->getHeight(target, level))
100 {
101 return gl::error(GL_INVALID_VALUE, false);
102 }
103
104 return true;
105}
106
Geoff Lang005df412013-10-16 14:12:50 -0400107bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400108 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
109 GLint border, GLenum format, GLenum type, const GLvoid *pixels)
110{
Jamie Madill6f38f822014-06-06 17:12:20 -0400111 if (!ValidTexture2DDestinationTarget(context, target))
112 {
113 return gl::error(GL_INVALID_ENUM, false);
114 }
115
Geoff Langce635692013-09-24 13:56:32 -0400116 if (!ValidImageSize(context, target, level, width, height, 1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400117 {
118 return gl::error(GL_INVALID_VALUE, false);
119 }
120
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400121 if (level < 0 || xoffset < 0 ||
122 std::numeric_limits<GLsizei>::max() - xoffset < width ||
123 std::numeric_limits<GLsizei>::max() - yoffset < height)
124 {
125 return gl::error(GL_INVALID_VALUE, false);
126 }
127
Geoff Lang005df412013-10-16 14:12:50 -0400128 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400129 {
130 return gl::error(GL_INVALID_OPERATION, false);
131 }
132
133 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 {
142 if (width > (context->getMaximum2DTextureDimension() >> level) ||
143 height > (context->getMaximum2DTextureDimension() >> level))
144 {
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
180 if (width > (context->getMaximumCubeTextureDimension() >> level) ||
181 height > (context->getMaximumCubeTextureDimension() >> level))
182 {
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:
236 if (!context->supportsDXT1Textures())
237 {
238 return gl::error(GL_INVALID_ENUM, false);
239 }
240 break;
241 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
242 if (!context->supportsDXT3Textures())
243 {
244 return gl::error(GL_INVALID_ENUM, false);
245 }
246 break;
247 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
248 if (!context->supportsDXT5Textures())
249 {
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:
295 if (!context->supportsRGTextures())
296 {
297 return gl::error(GL_INVALID_ENUM, false);
298 }
299 switch (type)
300 {
301 case GL_UNSIGNED_BYTE:
302 case GL_FLOAT:
303 case GL_HALF_FLOAT_OES:
304 break;
305 default:
306 return gl::error(GL_INVALID_OPERATION, false);
307 }
308 break;
309 case GL_RG:
310 if (!context->supportsRGTextures())
311 {
312 return gl::error(GL_INVALID_ENUM, false);
313 }
314 switch (type)
315 {
316 case GL_UNSIGNED_BYTE:
317 case GL_FLOAT:
318 case GL_HALF_FLOAT_OES:
319 break;
320 default:
321 return gl::error(GL_INVALID_OPERATION, false);
322 }
323 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400324 case GL_RGB:
325 switch (type)
326 {
327 case GL_UNSIGNED_BYTE:
328 case GL_UNSIGNED_SHORT_5_6_5:
329 case GL_FLOAT:
330 case GL_HALF_FLOAT_OES:
331 break;
332 default:
333 return gl::error(GL_INVALID_OPERATION, false);
334 }
335 break;
336 case GL_RGBA:
337 switch (type)
338 {
339 case GL_UNSIGNED_BYTE:
340 case GL_UNSIGNED_SHORT_4_4_4_4:
341 case GL_UNSIGNED_SHORT_5_5_5_1:
342 case GL_FLOAT:
343 case GL_HALF_FLOAT_OES:
344 break;
345 default:
346 return gl::error(GL_INVALID_OPERATION, false);
347 }
348 break;
349 case GL_BGRA_EXT:
350 switch (type)
351 {
352 case GL_UNSIGNED_BYTE:
353 break;
354 default:
355 return gl::error(GL_INVALID_OPERATION, false);
356 }
357 break;
358 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:
390 if (context->supportsDXT1Textures())
391 {
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:
400 if (context->supportsDXT3Textures())
401 {
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:
410 if (context->supportsDXT5Textures())
411 {
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:
421 if (!context->supportsDepthTextures())
422 {
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 {
442 if (!context->supportsFloat32Textures())
443 {
444 return gl::error(GL_INVALID_ENUM, false);
445 }
446 }
447 else if (type == GL_HALF_FLOAT_OES)
448 {
449 if (!context->supportsFloat16Textures())
450 {
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
473 gl::Framebuffer *framebuffer = context->getReadFramebuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400474 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat();
Jamie Madill560a8d82014-05-21 13:06:20 -0400475 GLenum textureFormat = gl::GetFormat(textureInternalFormat, context->getClientVersion());
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:
632 if (context->supportsDXT1Textures())
633 {
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:
642 if (context->supportsDXT3Textures())
643 {
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:
652 if (context->supportsDXT5Textures())
653 {
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:
666 if (context->supportsDepthTextures())
667 {
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
706 GLenum format = gl::GetFormat(internalformat, context->getClientVersion());
707 GLenum type = gl::GetType(internalformat, context->getClientVersion());
708
709 if (format == GL_NONE || type == GL_NONE)
710 {
711 return gl::error(GL_INVALID_ENUM, false);
712 }
713
714 switch (target)
715 {
716 case GL_TEXTURE_2D:
717 if (width > context->getMaximum2DTextureDimension() ||
718 height > context->getMaximum2DTextureDimension())
719 {
720 return gl::error(GL_INVALID_VALUE, false);
721 }
722 break;
723 case GL_TEXTURE_CUBE_MAP:
724 if (width > context->getMaximumCubeTextureDimension() ||
725 height > context->getMaximumCubeTextureDimension())
726 {
727 return gl::error(GL_INVALID_VALUE, false);
728 }
729 break;
730 default:
731 return gl::error(GL_INVALID_ENUM, false);
732 }
733
734 if (levels != 1 && !context->supportsNonPower2Texture())
735 {
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:
746 if (!context->supportsDXT1Textures())
747 {
748 return gl::error(GL_INVALID_ENUM, false);
749 }
750 break;
751 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
752 if (!context->supportsDXT3Textures())
753 {
754 return gl::error(GL_INVALID_ENUM, false);
755 }
756 break;
757 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
758 if (!context->supportsDXT5Textures())
759 {
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:
768 if (!context->supportsFloat32Textures())
769 {
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:
778 if (!context->supportsFloat16Textures())
779 {
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:
789 if (!context->supportsRGTextures())
790 {
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:
797 if (!context->supportsDepthTextures())
798 {
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 Lang34dbb6f2013-08-05 15:05:47 -0400841bool ValidateES2FramebufferTextureParameters(gl::Context *context, GLenum target, GLenum attachment,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400842 GLenum textarget, GLuint texture, GLint level)
843{
844 META_ASSERT(GL_DRAW_FRAMEBUFFER == GL_DRAW_FRAMEBUFFER_ANGLE && GL_READ_FRAMEBUFFER == GL_READ_FRAMEBUFFER_ANGLE);
845
846 if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
847 {
848 return gl::error(GL_INVALID_ENUM, false);
849 }
850
851 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
852 {
853 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0);
854 if (colorAttachment >= context->getMaximumRenderTargets())
855 {
856 return gl::error(GL_INVALID_VALUE, false);
857 }
858 }
859 else
860 {
861 switch (attachment)
862 {
863 case GL_DEPTH_ATTACHMENT:
864 case GL_STENCIL_ATTACHMENT:
865 break;
866 default:
867 return gl::error(GL_INVALID_ENUM, false);
868 }
869 }
870
871 if (texture != 0)
872 {
873 gl::Texture *tex = context->getTexture(texture);
874
875 if (tex == NULL)
876 {
877 return gl::error(GL_INVALID_OPERATION, false);
878 }
879
880 switch (textarget)
881 {
882 case GL_TEXTURE_2D:
883 {
884 if (tex->getTarget() != GL_TEXTURE_2D)
885 {
886 return gl::error(GL_INVALID_OPERATION, false);
887 }
888 gl::Texture2D *tex2d = static_cast<gl::Texture2D *>(tex);
889 if (tex2d->isCompressed(level))
890 {
891 return gl::error(GL_INVALID_OPERATION, false);
892 }
893 break;
894 }
895
896 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
897 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
898 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
899 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
900 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
901 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
902 {
903 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
904 {
905 return gl::error(GL_INVALID_OPERATION, false);
906 }
907 gl::TextureCubeMap *texcube = static_cast<gl::TextureCubeMap *>(tex);
908 if (texcube->isCompressed(textarget, level))
909 {
910 return gl::error(GL_INVALID_OPERATION, false);
911 }
912 break;
913 }
914
915 default:
916 return gl::error(GL_INVALID_ENUM, false);
917 }
918
919 if (level != 0)
920 {
921 return gl::error(GL_INVALID_VALUE, false);
922 }
923 }
924
925 gl::Framebuffer *framebuffer = NULL;
926 GLuint framebufferHandle = 0;
927 if (target == GL_READ_FRAMEBUFFER)
928 {
929 framebuffer = context->getReadFramebuffer();
930 framebufferHandle = context->getReadFramebufferHandle();
931 }
932 else
933 {
934 framebuffer = context->getDrawFramebuffer();
935 framebufferHandle = context->getDrawFramebufferHandle();
936 }
937
938 if (framebufferHandle == 0 || !framebuffer)
939 {
940 return gl::error(GL_INVALID_OPERATION, false);
941 }
942
943 return true;
944}
945
946// check for combinations of format and type that are valid for ReadPixels
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400947bool ValidES2ReadFormatType(gl::Context *context, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400948{
949 switch (format)
950 {
951 case GL_RGBA:
952 switch (type)
953 {
954 case GL_UNSIGNED_BYTE:
955 break;
956 default:
957 return false;
958 }
959 break;
960 case GL_BGRA_EXT:
961 switch (type)
962 {
963 case GL_UNSIGNED_BYTE:
964 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
965 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
966 break;
967 default:
968 return false;
969 }
970 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400971 case GL_RG_EXT:
972 case GL_RED_EXT:
973 if (!context->supportsRGTextures())
974 {
975 return false;
976 }
977 switch (type)
978 {
979 case GL_UNSIGNED_BYTE:
980 break;
981 default:
982 return false;
983 }
984 break;
985
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400986 default:
987 return false;
988 }
989 return true;
990}
991
992}