blob: c76e2713207151548b9b600633220ee9ed5eb094 [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{
Geoff Langce635692013-09-24 13:56:32 -0400111 if (!ValidImageSize(context, target, level, width, height, 1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400112 {
113 return gl::error(GL_INVALID_VALUE, false);
114 }
115
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400116 if (level < 0 || xoffset < 0 ||
117 std::numeric_limits<GLsizei>::max() - xoffset < width ||
118 std::numeric_limits<GLsizei>::max() - yoffset < height)
119 {
120 return gl::error(GL_INVALID_VALUE, false);
121 }
122
Geoff Lang005df412013-10-16 14:12:50 -0400123 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400124 {
125 return gl::error(GL_INVALID_OPERATION, false);
126 }
127
128 gl::Texture *texture = NULL;
129 bool textureCompressed = false;
130 GLenum textureInternalFormat = GL_NONE;
131 GLint textureLevelWidth = 0;
132 GLint textureLevelHeight = 0;
133 switch (target)
134 {
135 case GL_TEXTURE_2D:
136 {
137 if (width > (context->getMaximum2DTextureDimension() >> level) ||
138 height > (context->getMaximum2DTextureDimension() >> level))
139 {
140 return gl::error(GL_INVALID_VALUE, false);
141 }
142
143 gl::Texture2D *tex2d = context->getTexture2D();
144 if (tex2d)
145 {
146 textureCompressed = tex2d->isCompressed(level);
147 textureInternalFormat = tex2d->getInternalFormat(level);
148 textureLevelWidth = tex2d->getWidth(level);
149 textureLevelHeight = tex2d->getHeight(level);
150 texture = tex2d;
151 }
152
153 if (isSubImage && !validateSubImageParams2D(isCompressed, width, height, xoffset, yoffset,
154 level, format, type, tex2d))
155 {
156 return false;
157 }
158
159 texture = tex2d;
160 }
161 break;
162
163 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
164 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
165 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
166 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
167 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
168 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
169 {
170 if (!isSubImage && width != height)
171 {
172 return gl::error(GL_INVALID_VALUE, false);
173 }
174
175 if (width > (context->getMaximumCubeTextureDimension() >> level) ||
176 height > (context->getMaximumCubeTextureDimension() >> level))
177 {
178 return gl::error(GL_INVALID_VALUE, false);
179 }
180
181 gl::TextureCubeMap *texCube = context->getTextureCubeMap();
182 if (texCube)
183 {
184 textureCompressed = texCube->isCompressed(target, level);
185 textureInternalFormat = texCube->getInternalFormat(target, level);
186 textureLevelWidth = texCube->getWidth(target, level);
187 textureLevelHeight = texCube->getHeight(target, level);
188 texture = texCube;
189 }
190
191 if (isSubImage && !validateSubImageParamsCube(isCompressed, width, height, xoffset, yoffset,
192 target, level, format, type, texCube))
193 {
194 return false;
195 }
196 }
197 break;
198
199 default:
200 return gl::error(GL_INVALID_ENUM, false);
201 }
202
203 if (!texture)
204 {
205 return gl::error(GL_INVALID_OPERATION, false);
206 }
207
208 if (!isSubImage && texture->isImmutable())
209 {
210 return gl::error(GL_INVALID_OPERATION, false);
211 }
212
213 // Verify zero border
214 if (border != 0)
215 {
216 return gl::error(GL_INVALID_VALUE, false);
217 }
218
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400219 GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
220 if (isCompressed)
221 {
Geoff Langd4f180b2013-09-24 13:57:44 -0400222 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
223 {
224 return gl::error(GL_INVALID_OPERATION, false);
225 }
226
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400227 switch (actualInternalFormat)
228 {
229 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
230 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
231 if (!context->supportsDXT1Textures())
232 {
233 return gl::error(GL_INVALID_ENUM, false);
234 }
235 break;
236 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
237 if (!context->supportsDXT3Textures())
238 {
239 return gl::error(GL_INVALID_ENUM, false);
240 }
241 break;
242 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
243 if (!context->supportsDXT5Textures())
244 {
245 return gl::error(GL_INVALID_ENUM, false);
246 }
247 break;
248 default:
249 return gl::error(GL_INVALID_ENUM, false);
250 }
251 }
252 else
253 {
254 // validate <type> by itself (used as secondary key below)
255 switch (type)
256 {
257 case GL_UNSIGNED_BYTE:
258 case GL_UNSIGNED_SHORT_5_6_5:
259 case GL_UNSIGNED_SHORT_4_4_4_4:
260 case GL_UNSIGNED_SHORT_5_5_5_1:
261 case GL_UNSIGNED_SHORT:
262 case GL_UNSIGNED_INT:
263 case GL_UNSIGNED_INT_24_8_OES:
264 case GL_HALF_FLOAT_OES:
265 case GL_FLOAT:
266 break;
267 default:
268 return gl::error(GL_INVALID_ENUM, false);
269 }
270
271 // validate <format> + <type> combinations
272 // - invalid <format> -> sets INVALID_ENUM
273 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
274 switch (format)
275 {
276 case GL_ALPHA:
277 case GL_LUMINANCE:
278 case GL_LUMINANCE_ALPHA:
279 switch (type)
280 {
281 case GL_UNSIGNED_BYTE:
282 case GL_FLOAT:
283 case GL_HALF_FLOAT_OES:
284 break;
285 default:
286 return gl::error(GL_INVALID_OPERATION, false);
287 }
288 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400289 case GL_RED:
290 if (!context->supportsRGTextures())
291 {
292 return gl::error(GL_INVALID_ENUM, false);
293 }
294 switch (type)
295 {
296 case GL_UNSIGNED_BYTE:
297 case GL_FLOAT:
298 case GL_HALF_FLOAT_OES:
299 break;
300 default:
301 return gl::error(GL_INVALID_OPERATION, false);
302 }
303 break;
304 case GL_RG:
305 if (!context->supportsRGTextures())
306 {
307 return gl::error(GL_INVALID_ENUM, false);
308 }
309 switch (type)
310 {
311 case GL_UNSIGNED_BYTE:
312 case GL_FLOAT:
313 case GL_HALF_FLOAT_OES:
314 break;
315 default:
316 return gl::error(GL_INVALID_OPERATION, false);
317 }
318 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400319 case GL_RGB:
320 switch (type)
321 {
322 case GL_UNSIGNED_BYTE:
323 case GL_UNSIGNED_SHORT_5_6_5:
324 case GL_FLOAT:
325 case GL_HALF_FLOAT_OES:
326 break;
327 default:
328 return gl::error(GL_INVALID_OPERATION, false);
329 }
330 break;
331 case GL_RGBA:
332 switch (type)
333 {
334 case GL_UNSIGNED_BYTE:
335 case GL_UNSIGNED_SHORT_4_4_4_4:
336 case GL_UNSIGNED_SHORT_5_5_5_1:
337 case GL_FLOAT:
338 case GL_HALF_FLOAT_OES:
339 break;
340 default:
341 return gl::error(GL_INVALID_OPERATION, false);
342 }
343 break;
344 case GL_BGRA_EXT:
345 switch (type)
346 {
347 case GL_UNSIGNED_BYTE:
348 break;
349 default:
350 return gl::error(GL_INVALID_OPERATION, false);
351 }
352 break;
353 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
354 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
355 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
356 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
357 break;
358 case GL_DEPTH_COMPONENT:
359 switch (type)
360 {
361 case GL_UNSIGNED_SHORT:
362 case GL_UNSIGNED_INT:
363 break;
364 default:
365 return gl::error(GL_INVALID_OPERATION, false);
366 }
367 break;
368 case GL_DEPTH_STENCIL_OES:
369 switch (type)
370 {
371 case GL_UNSIGNED_INT_24_8_OES:
372 break;
373 default:
374 return gl::error(GL_INVALID_OPERATION, false);
375 }
376 break;
377 default:
378 return gl::error(GL_INVALID_ENUM, false);
379 }
380
381 switch (format)
382 {
383 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
384 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
385 if (context->supportsDXT1Textures())
386 {
387 return gl::error(GL_INVALID_OPERATION, false);
388 }
389 else
390 {
391 return gl::error(GL_INVALID_ENUM, false);
392 }
393 break;
394 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
395 if (context->supportsDXT3Textures())
396 {
397 return gl::error(GL_INVALID_OPERATION, false);
398 }
399 else
400 {
401 return gl::error(GL_INVALID_ENUM, false);
402 }
403 break;
404 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
405 if (context->supportsDXT5Textures())
406 {
407 return gl::error(GL_INVALID_OPERATION, false);
408 }
409 else
410 {
411 return gl::error(GL_INVALID_ENUM, false);
412 }
413 break;
414 case GL_DEPTH_COMPONENT:
415 case GL_DEPTH_STENCIL_OES:
416 if (!context->supportsDepthTextures())
417 {
418 return gl::error(GL_INVALID_VALUE, false);
419 }
420 if (target != GL_TEXTURE_2D)
421 {
422 return gl::error(GL_INVALID_OPERATION, false);
423 }
424 // OES_depth_texture supports loading depth data and multiple levels,
425 // but ANGLE_depth_texture does not
426 if (pixels != NULL || level != 0)
427 {
428 return gl::error(GL_INVALID_OPERATION, false);
429 }
430 break;
431 default:
432 break;
433 }
434
435 if (type == GL_FLOAT)
436 {
437 if (!context->supportsFloat32Textures())
438 {
439 return gl::error(GL_INVALID_ENUM, false);
440 }
441 }
442 else if (type == GL_HALF_FLOAT_OES)
443 {
444 if (!context->supportsFloat16Textures())
445 {
446 return gl::error(GL_INVALID_ENUM, false);
447 }
448 }
449 }
450
451 return true;
452}
453
454
455
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400456bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400457 GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height,
458 GLint border)
459{
Jamie Madill560a8d82014-05-21 13:06:20 -0400460 GLenum textureInternalFormat = GL_NONE;
Shannon Woods4dfed832014-03-17 20:03:39 -0400461
Jamie Madill560a8d82014-05-21 13:06:20 -0400462 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
463 xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400464 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400465 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400466 }
467
468 gl::Framebuffer *framebuffer = context->getReadFramebuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400469 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat();
Jamie Madill560a8d82014-05-21 13:06:20 -0400470 GLenum textureFormat = gl::GetFormat(textureInternalFormat, context->getClientVersion());
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400471
472 // [OpenGL ES 2.0.24] table 3.9
473 if (isSubImage)
474 {
475 switch (textureFormat)
476 {
477 case GL_ALPHA:
478 if (colorbufferFormat != GL_ALPHA8_EXT &&
479 colorbufferFormat != GL_RGBA4 &&
480 colorbufferFormat != GL_RGB5_A1 &&
481 colorbufferFormat != GL_RGBA8_OES)
482 {
483 return gl::error(GL_INVALID_OPERATION, false);
484 }
485 break;
486 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400487 if (colorbufferFormat != GL_R8_EXT &&
488 colorbufferFormat != GL_RG8_EXT &&
489 colorbufferFormat != GL_RGB565 &&
490 colorbufferFormat != GL_RGB8_OES &&
491 colorbufferFormat != GL_RGBA4 &&
492 colorbufferFormat != GL_RGB5_A1 &&
493 colorbufferFormat != GL_RGBA8_OES)
494 {
495 return gl::error(GL_INVALID_OPERATION, false);
496 }
497 break;
498 case GL_RED_EXT:
499 if (colorbufferFormat != GL_R8_EXT &&
500 colorbufferFormat != GL_RG8_EXT &&
501 colorbufferFormat != GL_RGB565 &&
502 colorbufferFormat != GL_RGB8_OES &&
503 colorbufferFormat != GL_RGBA4 &&
504 colorbufferFormat != GL_RGB5_A1 &&
505 colorbufferFormat != GL_RGBA8_OES)
506 {
507 return gl::error(GL_INVALID_OPERATION, false);
508 }
509 break;
510 case GL_RG_EXT:
511 if (colorbufferFormat != GL_RG8_EXT &&
512 colorbufferFormat != GL_RGB565 &&
513 colorbufferFormat != GL_RGB8_OES &&
514 colorbufferFormat != GL_RGBA4 &&
515 colorbufferFormat != GL_RGB5_A1 &&
516 colorbufferFormat != GL_RGBA8_OES)
517 {
518 return gl::error(GL_INVALID_OPERATION, false);
519 }
520 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400521 case GL_RGB:
522 if (colorbufferFormat != GL_RGB565 &&
523 colorbufferFormat != GL_RGB8_OES &&
524 colorbufferFormat != GL_RGBA4 &&
525 colorbufferFormat != GL_RGB5_A1 &&
526 colorbufferFormat != GL_RGBA8_OES)
527 {
528 return gl::error(GL_INVALID_OPERATION, false);
529 }
530 break;
531 case GL_LUMINANCE_ALPHA:
532 case GL_RGBA:
533 if (colorbufferFormat != GL_RGBA4 &&
534 colorbufferFormat != GL_RGB5_A1 &&
535 colorbufferFormat != GL_RGBA8_OES)
536 {
537 return gl::error(GL_INVALID_OPERATION, false);
538 }
539 break;
540 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
541 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
542 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
543 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
544 return gl::error(GL_INVALID_OPERATION, false);
545 case GL_DEPTH_COMPONENT:
546 case GL_DEPTH_STENCIL_OES:
547 return gl::error(GL_INVALID_OPERATION, false);
548 default:
549 return gl::error(GL_INVALID_OPERATION, false);
550 }
551 }
552 else
553 {
554 switch (internalformat)
555 {
556 case GL_ALPHA:
557 if (colorbufferFormat != GL_ALPHA8_EXT &&
558 colorbufferFormat != GL_RGBA4 &&
559 colorbufferFormat != GL_RGB5_A1 &&
560 colorbufferFormat != GL_BGRA8_EXT &&
561 colorbufferFormat != GL_RGBA8_OES)
562 {
563 return gl::error(GL_INVALID_OPERATION, false);
564 }
565 break;
566 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400567 if (colorbufferFormat != GL_R8_EXT &&
568 colorbufferFormat != GL_RG8_EXT &&
569 colorbufferFormat != GL_RGB565 &&
570 colorbufferFormat != GL_RGB8_OES &&
571 colorbufferFormat != GL_RGBA4 &&
572 colorbufferFormat != GL_RGB5_A1 &&
573 colorbufferFormat != GL_BGRA8_EXT &&
574 colorbufferFormat != GL_RGBA8_OES)
575 {
576 return gl::error(GL_INVALID_OPERATION, false);
577 }
578 break;
579 case GL_RED_EXT:
580 if (colorbufferFormat != GL_R8_EXT &&
581 colorbufferFormat != GL_RG8_EXT &&
582 colorbufferFormat != GL_RGB565 &&
583 colorbufferFormat != GL_RGB8_OES &&
584 colorbufferFormat != GL_RGBA4 &&
585 colorbufferFormat != GL_RGB5_A1 &&
586 colorbufferFormat != GL_BGRA8_EXT &&
587 colorbufferFormat != GL_RGBA8_OES)
588 {
589 return gl::error(GL_INVALID_OPERATION, false);
590 }
591 break;
592 case GL_RG_EXT:
593 if (colorbufferFormat != GL_RG8_EXT &&
594 colorbufferFormat != GL_RGB565 &&
595 colorbufferFormat != GL_RGB8_OES &&
596 colorbufferFormat != GL_RGBA4 &&
597 colorbufferFormat != GL_RGB5_A1 &&
598 colorbufferFormat != GL_BGRA8_EXT &&
599 colorbufferFormat != GL_RGBA8_OES)
600 {
601 return gl::error(GL_INVALID_OPERATION, false);
602 }
603 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400604 case GL_RGB:
605 if (colorbufferFormat != GL_RGB565 &&
606 colorbufferFormat != GL_RGB8_OES &&
607 colorbufferFormat != GL_RGBA4 &&
608 colorbufferFormat != GL_RGB5_A1 &&
609 colorbufferFormat != GL_BGRA8_EXT &&
610 colorbufferFormat != GL_RGBA8_OES)
611 {
612 return gl::error(GL_INVALID_OPERATION, false);
613 }
614 break;
615 case GL_LUMINANCE_ALPHA:
616 case GL_RGBA:
617 if (colorbufferFormat != GL_RGBA4 &&
618 colorbufferFormat != GL_RGB5_A1 &&
619 colorbufferFormat != GL_BGRA8_EXT &&
620 colorbufferFormat != GL_RGBA8_OES)
621 {
622 return gl::error(GL_INVALID_OPERATION, false);
623 }
624 break;
625 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
626 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
627 if (context->supportsDXT1Textures())
628 {
629 return gl::error(GL_INVALID_OPERATION, false);
630 }
631 else
632 {
633 return gl::error(GL_INVALID_ENUM, false);
634 }
635 break;
636 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
637 if (context->supportsDXT3Textures())
638 {
639 return gl::error(GL_INVALID_OPERATION, false);
640 }
641 else
642 {
643 return gl::error(GL_INVALID_ENUM, false);
644 }
645 break;
646 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
647 if (context->supportsDXT5Textures())
648 {
649 return gl::error(GL_INVALID_OPERATION, false);
650 }
651 else
652 {
653 return gl::error(GL_INVALID_ENUM, false);
654 }
655 break;
656 case GL_DEPTH_COMPONENT:
657 case GL_DEPTH_COMPONENT16:
658 case GL_DEPTH_COMPONENT32_OES:
659 case GL_DEPTH_STENCIL_OES:
660 case GL_DEPTH24_STENCIL8_OES:
661 if (context->supportsDepthTextures())
662 {
663 return gl::error(GL_INVALID_OPERATION, false);
664 }
665 else
666 {
667 return gl::error(GL_INVALID_ENUM, false);
668 }
669 default:
670 return gl::error(GL_INVALID_ENUM, false);
671 }
672 }
673
Geoff Lang784a8fd2013-09-24 12:33:16 -0400674 // If width or height is zero, it is a no-op. Return false without setting an error.
675 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400676}
677
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400678bool ValidateES2TexStorageParameters(gl::Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400679 GLsizei width, GLsizei height)
680{
681 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
682 {
683 return gl::error(GL_INVALID_ENUM, false);
684 }
685
686 if (width < 1 || height < 1 || levels < 1)
687 {
688 return gl::error(GL_INVALID_VALUE, false);
689 }
690
691 if (target == GL_TEXTURE_CUBE_MAP && width != height)
692 {
693 return gl::error(GL_INVALID_VALUE, false);
694 }
695
696 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
697 {
698 return gl::error(GL_INVALID_OPERATION, false);
699 }
700
701 GLenum format = gl::GetFormat(internalformat, context->getClientVersion());
702 GLenum type = gl::GetType(internalformat, context->getClientVersion());
703
704 if (format == GL_NONE || type == GL_NONE)
705 {
706 return gl::error(GL_INVALID_ENUM, false);
707 }
708
709 switch (target)
710 {
711 case GL_TEXTURE_2D:
712 if (width > context->getMaximum2DTextureDimension() ||
713 height > context->getMaximum2DTextureDimension())
714 {
715 return gl::error(GL_INVALID_VALUE, false);
716 }
717 break;
718 case GL_TEXTURE_CUBE_MAP:
719 if (width > context->getMaximumCubeTextureDimension() ||
720 height > context->getMaximumCubeTextureDimension())
721 {
722 return gl::error(GL_INVALID_VALUE, false);
723 }
724 break;
725 default:
726 return gl::error(GL_INVALID_ENUM, false);
727 }
728
729 if (levels != 1 && !context->supportsNonPower2Texture())
730 {
731 if (!gl::isPow2(width) || !gl::isPow2(height))
732 {
733 return gl::error(GL_INVALID_OPERATION, false);
734 }
735 }
736
737 switch (internalformat)
738 {
739 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
740 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
741 if (!context->supportsDXT1Textures())
742 {
743 return gl::error(GL_INVALID_ENUM, false);
744 }
745 break;
746 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
747 if (!context->supportsDXT3Textures())
748 {
749 return gl::error(GL_INVALID_ENUM, false);
750 }
751 break;
752 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
753 if (!context->supportsDXT5Textures())
754 {
755 return gl::error(GL_INVALID_ENUM, false);
756 }
757 break;
758 case GL_RGBA32F_EXT:
759 case GL_RGB32F_EXT:
760 case GL_ALPHA32F_EXT:
761 case GL_LUMINANCE32F_EXT:
762 case GL_LUMINANCE_ALPHA32F_EXT:
763 if (!context->supportsFloat32Textures())
764 {
765 return gl::error(GL_INVALID_ENUM, false);
766 }
767 break;
768 case GL_RGBA16F_EXT:
769 case GL_RGB16F_EXT:
770 case GL_ALPHA16F_EXT:
771 case GL_LUMINANCE16F_EXT:
772 case GL_LUMINANCE_ALPHA16F_EXT:
773 if (!context->supportsFloat16Textures())
774 {
775 return gl::error(GL_INVALID_ENUM, false);
776 }
777 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400778 case GL_R8_EXT:
779 case GL_RG8_EXT:
780 case GL_R16F_EXT:
781 case GL_RG16F_EXT:
782 case GL_R32F_EXT:
783 case GL_RG32F_EXT:
784 if (!context->supportsRGTextures())
785 {
786 return gl::error(GL_INVALID_ENUM, false);
787 }
788 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400789 case GL_DEPTH_COMPONENT16:
790 case GL_DEPTH_COMPONENT32_OES:
791 case GL_DEPTH24_STENCIL8_OES:
792 if (!context->supportsDepthTextures())
793 {
794 return gl::error(GL_INVALID_ENUM, false);
795 }
796 if (target != GL_TEXTURE_2D)
797 {
798 return gl::error(GL_INVALID_OPERATION, false);
799 }
800 // ANGLE_depth_texture only supports 1-level textures
801 if (levels != 1)
802 {
803 return gl::error(GL_INVALID_OPERATION, false);
804 }
805 break;
806 default:
807 break;
808 }
809
810 gl::Texture *texture = NULL;
811 switch(target)
812 {
813 case GL_TEXTURE_2D:
814 texture = context->getTexture2D();
815 break;
816 case GL_TEXTURE_CUBE_MAP:
817 texture = context->getTextureCubeMap();
818 break;
819 default:
820 UNREACHABLE();
821 }
822
823 if (!texture || texture->id() == 0)
824 {
825 return gl::error(GL_INVALID_OPERATION, false);
826 }
827
828 if (texture->isImmutable())
829 {
830 return gl::error(GL_INVALID_OPERATION, false);
831 }
832
833 return true;
834}
835
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400836bool ValidateES2FramebufferTextureParameters(gl::Context *context, GLenum target, GLenum attachment,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400837 GLenum textarget, GLuint texture, GLint level)
838{
839 META_ASSERT(GL_DRAW_FRAMEBUFFER == GL_DRAW_FRAMEBUFFER_ANGLE && GL_READ_FRAMEBUFFER == GL_READ_FRAMEBUFFER_ANGLE);
840
841 if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
842 {
843 return gl::error(GL_INVALID_ENUM, false);
844 }
845
846 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
847 {
848 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0);
849 if (colorAttachment >= context->getMaximumRenderTargets())
850 {
851 return gl::error(GL_INVALID_VALUE, false);
852 }
853 }
854 else
855 {
856 switch (attachment)
857 {
858 case GL_DEPTH_ATTACHMENT:
859 case GL_STENCIL_ATTACHMENT:
860 break;
861 default:
862 return gl::error(GL_INVALID_ENUM, false);
863 }
864 }
865
866 if (texture != 0)
867 {
868 gl::Texture *tex = context->getTexture(texture);
869
870 if (tex == NULL)
871 {
872 return gl::error(GL_INVALID_OPERATION, false);
873 }
874
875 switch (textarget)
876 {
877 case GL_TEXTURE_2D:
878 {
879 if (tex->getTarget() != GL_TEXTURE_2D)
880 {
881 return gl::error(GL_INVALID_OPERATION, false);
882 }
883 gl::Texture2D *tex2d = static_cast<gl::Texture2D *>(tex);
884 if (tex2d->isCompressed(level))
885 {
886 return gl::error(GL_INVALID_OPERATION, false);
887 }
888 break;
889 }
890
891 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
892 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
893 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
894 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
895 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
896 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
897 {
898 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
899 {
900 return gl::error(GL_INVALID_OPERATION, false);
901 }
902 gl::TextureCubeMap *texcube = static_cast<gl::TextureCubeMap *>(tex);
903 if (texcube->isCompressed(textarget, level))
904 {
905 return gl::error(GL_INVALID_OPERATION, false);
906 }
907 break;
908 }
909
910 default:
911 return gl::error(GL_INVALID_ENUM, false);
912 }
913
914 if (level != 0)
915 {
916 return gl::error(GL_INVALID_VALUE, false);
917 }
918 }
919
920 gl::Framebuffer *framebuffer = NULL;
921 GLuint framebufferHandle = 0;
922 if (target == GL_READ_FRAMEBUFFER)
923 {
924 framebuffer = context->getReadFramebuffer();
925 framebufferHandle = context->getReadFramebufferHandle();
926 }
927 else
928 {
929 framebuffer = context->getDrawFramebuffer();
930 framebufferHandle = context->getDrawFramebufferHandle();
931 }
932
933 if (framebufferHandle == 0 || !framebuffer)
934 {
935 return gl::error(GL_INVALID_OPERATION, false);
936 }
937
938 return true;
939}
940
941// check for combinations of format and type that are valid for ReadPixels
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400942bool ValidES2ReadFormatType(gl::Context *context, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400943{
944 switch (format)
945 {
946 case GL_RGBA:
947 switch (type)
948 {
949 case GL_UNSIGNED_BYTE:
950 break;
951 default:
952 return false;
953 }
954 break;
955 case GL_BGRA_EXT:
956 switch (type)
957 {
958 case GL_UNSIGNED_BYTE:
959 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
960 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
961 break;
962 default:
963 return false;
964 }
965 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400966 case GL_RG_EXT:
967 case GL_RED_EXT:
968 if (!context->supportsRGTextures())
969 {
970 return false;
971 }
972 switch (type)
973 {
974 case GL_UNSIGNED_BYTE:
975 break;
976 default:
977 return false;
978 }
979 break;
980
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400981 default:
982 return false;
983 }
984 return true;
985}
986
987}