blob: a66f917193c086bf55aa5ad0d7427d70980a3021 [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// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
9
10#include "libGLESv2/validationES3.h"
11#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"
17
18#include "common/mathutil.h"
19
20namespace gl
21{
22
23static bool validImageSize(const gl::Context *context, GLint level, GLsizei width, GLsizei height, GLsizei depth)
24{
25 if (level < 0 || width < 0 || height < 0 || depth < 0)
26 {
27 return false;
28 }
29
30 if (context->supportsNonPower2Texture())
31 {
32 return true;
33 }
34
35 if (level == 0)
36 {
37 return true;
38 }
39
40 if (gl::isPow2(width) && gl::isPow2(height) && gl::isPow2(depth))
41 {
42 return true;
43 }
44
45 return false;
46}
47
48static bool validCompressedImageSize(GLsizei width, GLsizei height)
49{
50 if (width != 1 && width != 2 && width % 4 != 0)
51 {
52 return false;
53 }
54
55 if (height != 1 && height != 2 && height % 4 != 0)
56 {
57 return false;
58 }
59
60 return true;
61}
62
Geoff Lang34dbb6f2013-08-05 15:05:47 -040063bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint level, GLint internalformat, bool isCompressed, bool isSubImage,
Geoff Lange8ebe7f2013-08-05 15:03:13 -040064 GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
65 GLint border, GLenum format, GLenum type)
66{
67 // Validate image size
68 if (!validImageSize(context, level, width, height, depth))
69 {
70 return gl::error(GL_INVALID_VALUE, false);
71 }
72
73 if (isCompressed && !validCompressedImageSize(width, height))
74 {
75 return gl::error(GL_INVALID_OPERATION, false);
76 }
77
78 // Verify zero border
79 if (border != 0)
80 {
81 return gl::error(GL_INVALID_VALUE, false);
82 }
83
84 // Validate dimensions based on Context limits and validate the texture
85 if (level > context->getMaximumTextureLevel())
86 {
87 return gl::error(GL_INVALID_VALUE, false);
88 }
89
90 gl::Texture *texture = NULL;
91 bool textureCompressed = false;
92 GLenum textureInternalFormat = GL_NONE;
93 GLint textureLevelWidth = 0;
94 GLint textureLevelHeight = 0;
95 GLint textureLevelDepth = 0;
96 switch (target)
97 {
98 case GL_TEXTURE_2D:
99 {
100 if (width > (context->getMaximum2DTextureDimension() >> level) ||
101 height > (context->getMaximum2DTextureDimension() >> level))
102 {
103 return gl::error(GL_INVALID_VALUE, false);
104 }
105
106 gl::Texture2D *texture2d = context->getTexture2D();
107 if (texture2d)
108 {
109 textureCompressed = texture2d->isCompressed(level);
110 textureInternalFormat = texture2d->getInternalFormat(level);
111 textureLevelWidth = texture2d->getWidth(level);
112 textureLevelHeight = texture2d->getHeight(level);
113 textureLevelDepth = 1;
114 texture = texture2d;
115 }
116 }
117 break;
118
119 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
120 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
121 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
122 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
123 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
124 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
125 {
126 if (!isSubImage && width != height)
127 {
128 return gl::error(GL_INVALID_VALUE, false);
129 }
130
131 if (width > (context->getMaximumCubeTextureDimension() >> level))
132 {
133 return gl::error(GL_INVALID_VALUE, false);
134 }
135
136 gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
137 if (textureCube)
138 {
139 textureCompressed = textureCube->isCompressed(target, level);
140 textureInternalFormat = textureCube->getInternalFormat(target, level);
141 textureLevelWidth = textureCube->getWidth(target, level);
142 textureLevelHeight = textureCube->getHeight(target, level);
143 textureLevelDepth = 1;
144 texture = textureCube;
145 }
146 }
147 break;
148
149 case GL_TEXTURE_3D:
150 {
151 if (width > (context->getMaximum3DTextureDimension() >> level) ||
152 height > (context->getMaximum3DTextureDimension() >> level) ||
153 depth > (context->getMaximum3DTextureDimension() >> level))
154 {
155 return gl::error(GL_INVALID_VALUE, false);
156 }
157
158 gl::Texture3D *texture3d = context->getTexture3D();
159 if (texture3d)
160 {
161 textureCompressed = texture3d->isCompressed(level);
162 textureInternalFormat = texture3d->getInternalFormat(level);
163 textureLevelWidth = texture3d->getWidth(level);
164 textureLevelHeight = texture3d->getHeight(level);
165 textureLevelDepth = texture3d->getDepth(level);
166 texture = texture3d;
167 }
168 }
169 break;
170
171 case GL_TEXTURE_2D_ARRAY:
172 {
173 if (width > (context->getMaximum2DTextureDimension() >> level) ||
174 height > (context->getMaximum2DTextureDimension() >> level) ||
175 depth > (context->getMaximum2DArrayTextureLayers() >> level))
176 {
177 return gl::error(GL_INVALID_VALUE, false);
178 }
179
180 gl::Texture2DArray *texture2darray = context->getTexture2DArray();
181 if (texture2darray)
182 {
183 textureCompressed = texture2darray->isCompressed(level);
184 textureInternalFormat = texture2darray->getInternalFormat(level);
185 textureLevelWidth = texture2darray->getWidth(level);
186 textureLevelHeight = texture2darray->getHeight(level);
187 textureLevelDepth = texture2darray->getDepth(level);
188 texture = texture2darray;
189 }
190 }
191 break;
192
193 default:
194 return gl::error(GL_INVALID_ENUM, false);
195 }
196
197 if (!texture)
198 {
199 return gl::error(GL_INVALID_OPERATION, false);
200 }
201
202 if (texture->isImmutable() && !isSubImage)
203 {
204 return gl::error(GL_INVALID_OPERATION, false);
205 }
206
207 // Validate texture formats
208 GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
209 if (isCompressed)
210 {
211 if (!gl::IsFormatCompressed(actualInternalFormat, context->getClientVersion()))
212 {
213 return gl::error(GL_INVALID_ENUM, false);
214 }
215
216 if (target == GL_TEXTURE_3D)
217 {
218 return gl::error(GL_INVALID_OPERATION, false);
219 }
220 }
221 else
222 {
223 if (!gl::IsValidInternalFormat(actualInternalFormat, context) ||
224 !gl::IsValidFormat(format, context->getClientVersion()) ||
225 !gl::IsValidType(type, context->getClientVersion()))
226 {
227 return gl::error(GL_INVALID_ENUM, false);
228 }
229
230 if (!gl::IsValidFormatCombination(actualInternalFormat, format, type, context->getClientVersion()))
231 {
232 return gl::error(GL_INVALID_OPERATION, false);
233 }
234
235 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
236 {
237 return gl::error(GL_INVALID_OPERATION, false);
238 }
239 }
240
241 // Validate sub image parameters
242 if (isSubImage)
243 {
244 if (isCompressed != textureCompressed)
245 {
246 return gl::error(GL_INVALID_OPERATION, false);
247 }
248
249 if (format != GL_NONE)
250 {
251 GLenum internalformat = gl::GetSizedInternalFormat(format, type, context->getClientVersion());
252 if (internalformat != textureInternalFormat)
253 {
254 return gl::error(GL_INVALID_OPERATION, false);
255 }
256 }
257
258 if (isCompressed)
259 {
260 if ((width % 4 != 0 && width != textureLevelWidth) ||
261 (height % 4 != 0 && height != textureLevelHeight))
262 {
263 return gl::error(GL_INVALID_OPERATION, false);
264 }
265 }
266
267 if (width == 0 || height == 0 || depth == 0)
268 {
269 return false;
270 }
271
272 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
273 {
274 return gl::error(GL_INVALID_VALUE, false);
275 }
276
277 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
278 std::numeric_limits<GLsizei>::max() - yoffset < height ||
279 std::numeric_limits<GLsizei>::max() - zoffset < depth)
280 {
281 return gl::error(GL_INVALID_VALUE, false);
282 }
283
284 if (xoffset + width > textureLevelWidth ||
285 yoffset + height > textureLevelHeight ||
286 zoffset + depth > textureLevelDepth)
287 {
288 return gl::error(GL_INVALID_VALUE, false);
289 }
290 }
291
292 return true;
293}
294
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400295bool ValidateES3CopyTexImageParameters(gl::Context *context, GLenum target, GLint level, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400296 bool isSubImage, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y,
297 GLsizei width, GLsizei height, GLint border)
298{
299 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
300 {
301 return gl::error(GL_INVALID_VALUE, false);
302 }
303
304 if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
305 {
306 return gl::error(GL_INVALID_VALUE, false);
307 }
308
309 if (width == 0 || height == 0)
310 {
311 return false;
312 }
313
314 if (border != 0)
315 {
316 return gl::error(GL_INVALID_VALUE, false);
317 }
318
319 if (level > context->getMaximumTextureLevel())
320 {
321 return gl::error(GL_INVALID_VALUE, false);
322 }
323
324 gl::Framebuffer *framebuffer = context->getReadFramebuffer();
325
326 if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
327 {
328 return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
329 }
330
331 if (context->getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0)
332 {
333 return gl::error(GL_INVALID_OPERATION, false);
334 }
335
336 gl::Renderbuffer *source = framebuffer->getReadColorbuffer();
337 GLenum colorbufferInternalFormat = source->getInternalFormat();
338 gl::Texture *texture = NULL;
339 GLenum textureInternalFormat = GL_NONE;
340 bool textureCompressed = false;
341 bool textureIsDepth = false;
342 GLint textureLevelWidth = 0;
343 GLint textureLevelHeight = 0;
344 GLint textureLevelDepth = 0;
345 switch (target)
346 {
347 case GL_TEXTURE_2D:
348 {
349 gl::Texture2D *texture2d = context->getTexture2D();
350 if (texture2d)
351 {
352 textureInternalFormat = texture2d->getInternalFormat(level);
353 textureCompressed = texture2d->isCompressed(level);
354 textureIsDepth = texture2d->isDepth(level);
355 textureLevelWidth = texture2d->getWidth(level);
356 textureLevelHeight = texture2d->getHeight(level);
357 textureLevelDepth = 1;
358 texture = texture2d;
359 }
360 }
361 break;
362
363 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
364 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
365 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
366 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
367 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
368 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
369 {
370 gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
371 if (textureCube)
372 {
373 textureInternalFormat = textureCube->getInternalFormat(target, level);
374 textureCompressed = textureCube->isCompressed(target, level);
375 textureIsDepth = false;
376 textureLevelWidth = textureCube->getWidth(target, level);
377 textureLevelHeight = textureCube->getHeight(target, level);
378 textureLevelDepth = 1;
379 texture = textureCube;
380 }
381 }
382 break;
383
384 case GL_TEXTURE_2D_ARRAY:
385 {
386 gl::Texture2DArray *texture2dArray = context->getTexture2DArray();
387 if (texture2dArray)
388 {
389 textureInternalFormat = texture2dArray->getInternalFormat(level);
390 textureCompressed = texture2dArray->isCompressed(level);
391 textureIsDepth = texture2dArray->isDepth(level);
392 textureLevelWidth = texture2dArray->getWidth(level);
393 textureLevelHeight = texture2dArray->getHeight(level);
394 textureLevelDepth = texture2dArray->getDepth(level);
395 texture = texture2dArray;
396 }
397 }
398 break;
399
400 case GL_TEXTURE_3D:
401 {
402 gl::Texture3D *texture3d = context->getTexture3D();
403 if (texture3d)
404 {
405 textureInternalFormat = texture3d->getInternalFormat(level);
406 textureCompressed = texture3d->isCompressed(level);
407 textureIsDepth = texture3d->isDepth(level);
408 textureLevelWidth = texture3d->getWidth(level);
409 textureLevelHeight = texture3d->getHeight(level);
410 textureLevelDepth = texture3d->getDepth(level);
411 texture = texture3d;
412 }
413 }
414 break;
415
416 default:
417 return gl::error(GL_INVALID_ENUM, false);
418 }
419
420 if (!texture)
421 {
422 return gl::error(GL_INVALID_OPERATION, false);
423 }
424
425 if (texture->isImmutable() && !isSubImage)
426 {
427 return gl::error(GL_INVALID_OPERATION, false);
428 }
429
430 if (textureIsDepth)
431 {
432 return gl::error(GL_INVALID_OPERATION, false);
433 }
434
435 if (textureCompressed)
436 {
437 if ((width % 4 != 0 && width != textureLevelWidth) ||
438 (height % 4 != 0 && height != textureLevelHeight))
439 {
440 return gl::error(GL_INVALID_OPERATION, false);
441 }
442 }
443
444 if (isSubImage)
445 {
446 if (xoffset + width > textureLevelWidth ||
447 yoffset + height > textureLevelHeight ||
448 zoffset >= textureLevelDepth)
449 {
450 return gl::error(GL_INVALID_VALUE, false);
451 }
452
453 if (!gl::IsValidCopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat,
454 context->getClientVersion()))
455 {
456 return gl::error(GL_INVALID_OPERATION, false);
457 }
458 }
459
460 return true;
461}
462
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400463bool ValidateES3TexStorageParameters(gl::Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400464 GLsizei width, GLsizei height, GLsizei depth)
465{
466 if (width < 1 || height < 1 || depth < 1 || levels < 1)
467 {
468 return gl::error(GL_INVALID_VALUE, false);
469 }
470
471 if (levels > gl::log2(std::max(std::max(width, height), depth)) + 1)
472 {
473 return gl::error(GL_INVALID_OPERATION, false);
474 }
475
476 gl::Texture *texture = NULL;
477 switch (target)
478 {
479 case GL_TEXTURE_2D:
480 {
481 texture = context->getTexture2D();
482
483 if (width > (context->getMaximum2DTextureDimension()) ||
484 height > (context->getMaximum2DTextureDimension()))
485 {
486 return gl::error(GL_INVALID_VALUE, false);
487 }
488 }
489 break;
490
491 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
492 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
493 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
494 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
495 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
496 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
497 {
498 texture = context->getTextureCubeMap();
499
500 if (width != height)
501 {
502 return gl::error(GL_INVALID_VALUE, false);
503 }
504
505 if (width > (context->getMaximumCubeTextureDimension()))
506 {
507 return gl::error(GL_INVALID_VALUE, false);
508 }
509 }
510 break;
511
512 case GL_TEXTURE_3D:
513 {
514 texture = context->getTexture3D();
515
516 if (width > (context->getMaximum3DTextureDimension()) ||
517 height > (context->getMaximum3DTextureDimension()) ||
518 depth > (context->getMaximum3DTextureDimension()))
519 {
520 return gl::error(GL_INVALID_VALUE, false);
521 }
522 }
523 break;
524
525 case GL_TEXTURE_2D_ARRAY:
526 {
527 texture = context->getTexture2DArray();
528
529 if (width > (context->getMaximum2DTextureDimension()) ||
530 height > (context->getMaximum2DTextureDimension()) ||
531 depth > (context->getMaximum2DArrayTextureLayers()))
532 {
533 return gl::error(GL_INVALID_VALUE, false);
534 }
535 }
536 break;
537
538 default:
539 return gl::error(GL_INVALID_ENUM, false);
540 }
541
542 if (!texture || texture->id() == 0)
543 {
544 return gl::error(GL_INVALID_OPERATION, false);
545 }
546
547 if (texture->isImmutable())
548 {
549 return gl::error(GL_INVALID_OPERATION, false);
550 }
551
552 if (!gl::IsValidInternalFormat(internalformat, context))
553 {
554 return gl::error(GL_INVALID_ENUM, false);
555 }
556
557 if (!gl::IsSizedInternalFormat(internalformat, context->getClientVersion()))
558 {
559 return gl::error(GL_INVALID_ENUM, false);
560 }
561
562 return true;
563}
564
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400565bool ValidateES3FramebufferTextureParameters(gl::Context *context, GLenum target, GLenum attachment,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400566 GLenum textarget, GLuint texture, GLint level, GLint layer,
567 bool layerCall)
568{
569 if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
570 {
571 return gl::error(GL_INVALID_ENUM, false);
572 }
573
574 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
575 {
576 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0);
577 if (colorAttachment >= context->getMaximumRenderTargets())
578 {
579 return gl::error(GL_INVALID_VALUE, false);
580 }
581 }
582 else
583 {
584 switch (attachment)
585 {
586 case GL_DEPTH_ATTACHMENT:
587 case GL_STENCIL_ATTACHMENT:
588 case GL_DEPTH_STENCIL_ATTACHMENT:
589 break;
590 default:
591 return gl::error(GL_INVALID_ENUM, false);
592 }
593 }
594
595 if (texture != 0)
596 {
597 gl::Texture *tex = context->getTexture(texture);
598
599 if (tex == NULL)
600 {
601 return gl::error(GL_INVALID_OPERATION, false);
602 }
603
604 if (level < 0)
605 {
606 return gl::error(GL_INVALID_VALUE, false);
607 }
608
609 if (layer < 0)
610 {
611 return gl::error(GL_INVALID_VALUE, false);
612 }
613
614 if (!layerCall)
615 {
616 switch (textarget)
617 {
618 case GL_TEXTURE_2D:
619 {
620 if (level > gl::log2(context->getMaximum2DTextureDimension()))
621 {
622 return gl::error(GL_INVALID_VALUE, false);
623 }
624 if (tex->getTarget() != GL_TEXTURE_2D)
625 {
626 return gl::error(GL_INVALID_OPERATION, false);
627 }
628 gl::Texture2D *tex2d = static_cast<gl::Texture2D *>(tex);
629 if (tex2d->isCompressed(level))
630 {
631 return gl::error(GL_INVALID_OPERATION, false);
632 }
633 break;
634 }
635
636 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
637 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
638 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
639 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
640 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
641 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
642 {
643 if (level > gl::log2(context->getMaximumCubeTextureDimension()))
644 {
645 return gl::error(GL_INVALID_VALUE, false);
646 }
647 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
648 {
649 return gl::error(GL_INVALID_OPERATION, false);
650 }
651 gl::TextureCubeMap *texcube = static_cast<gl::TextureCubeMap *>(tex);
652 if (texcube->isCompressed(textarget, level))
653 {
654 return gl::error(GL_INVALID_OPERATION, false);
655 }
656 break;
657 }
658
659 default:
660 return gl::error(GL_INVALID_ENUM, false);
661 }
662 }
663 else
664 {
665 switch (tex->getTarget())
666 {
667 case GL_TEXTURE_2D_ARRAY:
668 {
669 if (level > gl::log2(context->getMaximum2DTextureDimension()))
670 {
671 return gl::error(GL_INVALID_VALUE, false);
672 }
673
674 if (layer >= context->getMaximum2DArrayTextureLayers())
675 {
676 return gl::error(GL_INVALID_VALUE, false);
677 }
678
679 gl::Texture2DArray *texArray = static_cast<gl::Texture2DArray *>(tex);
680 if (texArray->isCompressed(level))
681 {
682 return gl::error(GL_INVALID_OPERATION, false);
683 }
684
685 break;
686 }
687
688 case GL_TEXTURE_3D:
689 {
690 if (level > gl::log2(context->getMaximum3DTextureDimension()))
691 {
692 return gl::error(GL_INVALID_VALUE, false);
693 }
694
695 if (layer >= context->getMaximum3DTextureDimension())
696 {
697 return gl::error(GL_INVALID_VALUE, false);
698 }
699
700 gl::Texture3D *tex3d = static_cast<gl::Texture3D *>(tex);
701 if (tex3d->isCompressed(level))
702 {
703 return gl::error(GL_INVALID_OPERATION, false);
704 }
705
706 break;
707 }
708
709 default:
710 return gl::error(GL_INVALID_OPERATION, false);
711 }
712 }
713 }
714
715 gl::Framebuffer *framebuffer = NULL;
716 GLuint framebufferHandle = 0;
717 if (target == GL_READ_FRAMEBUFFER)
718 {
719 framebuffer = context->getReadFramebuffer();
720 framebufferHandle = context->getReadFramebufferHandle();
721 }
722 else
723 {
724 framebuffer = context->getDrawFramebuffer();
725 framebufferHandle = context->getDrawFramebufferHandle();
726 }
727
728 if (framebufferHandle == 0 || !framebuffer)
729 {
730 return gl::error(GL_INVALID_OPERATION, false);
731 }
732
733 return true;
734}
735
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400736bool ValidES3ReadFormatType(GLenum internalFormat, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400737{
738 switch (format)
739 {
740 case GL_RGBA:
741 switch (type)
742 {
743 case GL_UNSIGNED_BYTE:
744 break;
745 case GL_UNSIGNED_INT_2_10_10_10_REV:
746 if (internalFormat != GL_RGB10_A2)
747 {
748 return false;
749 }
750 break;
751 default:
752 return false;
753 }
754 break;
755 case GL_RGBA_INTEGER:
756 switch (type)
757 {
758 case GL_INT:
759 if (!gl::IsSignedIntegerFormat(internalFormat, 3))
760 {
761 return false;
762 }
763 break;
764 case GL_UNSIGNED_INT:
765 if (!gl::IsUnsignedIntegerFormat(internalFormat, 3))
766 {
767 return false;
768 }
769 break;
770 default:
771 return false;
772 }
773 break;
774 case GL_BGRA_EXT:
775 switch (type)
776 {
777 case GL_UNSIGNED_BYTE:
778 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
779 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
780 break;
781 default:
782 return false;
783 }
784 break;
785 default:
786 return false;
787 }
788 return true;
789}
790
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400791bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target, GLsizei numAttachments,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400792 const GLenum* attachments)
793{
794 bool defaultFramebuffer = false;
795
796 switch (target)
797 {
798 case GL_DRAW_FRAMEBUFFER:
799 case GL_FRAMEBUFFER:
800 defaultFramebuffer = context->getDrawFramebufferHandle() == 0;
801 break;
802 case GL_READ_FRAMEBUFFER:
803 defaultFramebuffer = context->getReadFramebufferHandle() == 0;
804 break;
805 default:
806 return gl::error(GL_INVALID_ENUM, false);
807 }
808
809 for (int i = 0; i < numAttachments; ++i)
810 {
811 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15)
812 {
813 if (defaultFramebuffer)
814 {
815 return gl::error(GL_INVALID_ENUM, false);
816 }
817
818 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getMaximumRenderTargets())
819 {
820 return gl::error(GL_INVALID_OPERATION, false);
821 }
822 }
823 else
824 {
825 switch (attachments[i])
826 {
827 case GL_DEPTH_ATTACHMENT:
828 case GL_STENCIL_ATTACHMENT:
829 case GL_DEPTH_STENCIL_ATTACHMENT:
830 if (defaultFramebuffer)
831 {
832 return gl::error(GL_INVALID_ENUM, false);
833 }
834 break;
835 case GL_COLOR:
836 case GL_DEPTH:
837 case GL_STENCIL:
838 if (!defaultFramebuffer)
839 {
840 return gl::error(GL_INVALID_ENUM, false);
841 }
842 break;
843 default:
844 return gl::error(GL_INVALID_ENUM, false);
845 }
846 }
847 }
848
849 return true;
850}
851
852}