blob: b3108a1ab6e5f8230d7379c63d402d2e06220c76 [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"
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
21namespace gl
22{
23
Geoff Lang005df412013-10-16 14:12:50 -040024bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025 GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
Jamie Madillefb2a6f2013-09-24 10:22:42 -040026 GLint border, GLenum format, GLenum type, const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040027{
28 // Validate image size
Geoff Langce635692013-09-24 13:56:32 -040029 if (!ValidImageSize(context, target, level, width, height, depth))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040030 {
31 return gl::error(GL_INVALID_VALUE, false);
32 }
33
Geoff Lange8ebe7f2013-08-05 15:03:13 -040034 // Verify zero border
35 if (border != 0)
36 {
37 return gl::error(GL_INVALID_VALUE, false);
38 }
39
Geoff Lange8ebe7f2013-08-05 15:03:13 -040040 gl::Texture *texture = NULL;
41 bool textureCompressed = false;
42 GLenum textureInternalFormat = GL_NONE;
43 GLint textureLevelWidth = 0;
44 GLint textureLevelHeight = 0;
45 GLint textureLevelDepth = 0;
46 switch (target)
47 {
48 case GL_TEXTURE_2D:
49 {
50 if (width > (context->getMaximum2DTextureDimension() >> level) ||
51 height > (context->getMaximum2DTextureDimension() >> level))
52 {
53 return gl::error(GL_INVALID_VALUE, false);
54 }
55
56 gl::Texture2D *texture2d = context->getTexture2D();
57 if (texture2d)
58 {
59 textureCompressed = texture2d->isCompressed(level);
60 textureInternalFormat = texture2d->getInternalFormat(level);
61 textureLevelWidth = texture2d->getWidth(level);
62 textureLevelHeight = texture2d->getHeight(level);
63 textureLevelDepth = 1;
64 texture = texture2d;
65 }
66 }
67 break;
68
69 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
70 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
71 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
72 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
73 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
74 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
75 {
76 if (!isSubImage && width != height)
77 {
78 return gl::error(GL_INVALID_VALUE, false);
79 }
80
81 if (width > (context->getMaximumCubeTextureDimension() >> level))
82 {
83 return gl::error(GL_INVALID_VALUE, false);
84 }
85
86 gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
87 if (textureCube)
88 {
89 textureCompressed = textureCube->isCompressed(target, level);
90 textureInternalFormat = textureCube->getInternalFormat(target, level);
91 textureLevelWidth = textureCube->getWidth(target, level);
92 textureLevelHeight = textureCube->getHeight(target, level);
93 textureLevelDepth = 1;
94 texture = textureCube;
95 }
96 }
97 break;
98
99 case GL_TEXTURE_3D:
100 {
101 if (width > (context->getMaximum3DTextureDimension() >> level) ||
102 height > (context->getMaximum3DTextureDimension() >> level) ||
103 depth > (context->getMaximum3DTextureDimension() >> level))
104 {
105 return gl::error(GL_INVALID_VALUE, false);
106 }
107
108 gl::Texture3D *texture3d = context->getTexture3D();
109 if (texture3d)
110 {
111 textureCompressed = texture3d->isCompressed(level);
112 textureInternalFormat = texture3d->getInternalFormat(level);
113 textureLevelWidth = texture3d->getWidth(level);
114 textureLevelHeight = texture3d->getHeight(level);
115 textureLevelDepth = texture3d->getDepth(level);
116 texture = texture3d;
117 }
118 }
119 break;
120
121 case GL_TEXTURE_2D_ARRAY:
122 {
123 if (width > (context->getMaximum2DTextureDimension() >> level) ||
124 height > (context->getMaximum2DTextureDimension() >> level) ||
125 depth > (context->getMaximum2DArrayTextureLayers() >> level))
126 {
127 return gl::error(GL_INVALID_VALUE, false);
128 }
129
130 gl::Texture2DArray *texture2darray = context->getTexture2DArray();
131 if (texture2darray)
132 {
133 textureCompressed = texture2darray->isCompressed(level);
134 textureInternalFormat = texture2darray->getInternalFormat(level);
135 textureLevelWidth = texture2darray->getWidth(level);
136 textureLevelHeight = texture2darray->getHeight(level);
Jamie Madillb8f8b892014-01-07 10:12:50 -0500137 textureLevelDepth = texture2darray->getLayers(level);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400138 texture = texture2darray;
139 }
140 }
141 break;
142
143 default:
144 return gl::error(GL_INVALID_ENUM, false);
145 }
146
147 if (!texture)
148 {
149 return gl::error(GL_INVALID_OPERATION, false);
150 }
151
152 if (texture->isImmutable() && !isSubImage)
153 {
154 return gl::error(GL_INVALID_OPERATION, false);
155 }
156
157 // Validate texture formats
158 GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
159 if (isCompressed)
160 {
Geoff Langd4f180b2013-09-24 13:57:44 -0400161 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
162 {
163 return gl::error(GL_INVALID_OPERATION, false);
164 }
165
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400166 if (!gl::IsFormatCompressed(actualInternalFormat, context->getClientVersion()))
167 {
168 return gl::error(GL_INVALID_ENUM, false);
169 }
170
171 if (target == GL_TEXTURE_3D)
172 {
173 return gl::error(GL_INVALID_OPERATION, false);
174 }
175 }
176 else
177 {
178 if (!gl::IsValidInternalFormat(actualInternalFormat, context) ||
179 !gl::IsValidFormat(format, context->getClientVersion()) ||
180 !gl::IsValidType(type, context->getClientVersion()))
181 {
182 return gl::error(GL_INVALID_ENUM, false);
183 }
184
185 if (!gl::IsValidFormatCombination(actualInternalFormat, format, type, context->getClientVersion()))
186 {
187 return gl::error(GL_INVALID_OPERATION, false);
188 }
189
190 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
191 {
192 return gl::error(GL_INVALID_OPERATION, false);
193 }
194 }
195
196 // Validate sub image parameters
197 if (isSubImage)
198 {
199 if (isCompressed != textureCompressed)
200 {
201 return gl::error(GL_INVALID_OPERATION, false);
202 }
203
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400204 if (isCompressed)
205 {
206 if ((width % 4 != 0 && width != textureLevelWidth) ||
207 (height % 4 != 0 && height != textureLevelHeight))
208 {
209 return gl::error(GL_INVALID_OPERATION, false);
210 }
211 }
212
213 if (width == 0 || height == 0 || depth == 0)
214 {
215 return false;
216 }
217
218 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
219 {
220 return gl::error(GL_INVALID_VALUE, false);
221 }
222
223 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
224 std::numeric_limits<GLsizei>::max() - yoffset < height ||
225 std::numeric_limits<GLsizei>::max() - zoffset < depth)
226 {
227 return gl::error(GL_INVALID_VALUE, false);
228 }
229
230 if (xoffset + width > textureLevelWidth ||
231 yoffset + height > textureLevelHeight ||
232 zoffset + depth > textureLevelDepth)
233 {
234 return gl::error(GL_INVALID_VALUE, false);
235 }
236 }
237
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400238 // Check for pixel unpack buffer related API errors
239 gl::Buffer *pixelUnpackBuffer = context->getPixelUnpackBuffer();
240 if (pixelUnpackBuffer != NULL)
241 {
242 // ...the data would be unpacked from the buffer object such that the memory reads required
243 // would exceed the data store size.
244 size_t widthSize = static_cast<size_t>(width);
245 size_t heightSize = static_cast<size_t>(height);
246 size_t depthSize = static_cast<size_t>(depth);
247 size_t pixelBytes = static_cast<size_t>(gl::GetPixelBytes(actualInternalFormat, context->getClientVersion()));
248
249 if (!rx::IsUnsignedMultiplicationSafe(widthSize, heightSize) ||
250 !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize, depthSize) ||
251 !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize * depthSize, pixelBytes))
252 {
253 // Overflow past the end of the buffer
254 return gl::error(GL_INVALID_OPERATION, false);
255 }
256
257 size_t copyBytes = widthSize * heightSize * depthSize * pixelBytes;
258 size_t offset = reinterpret_cast<size_t>(pixels);
259
260 if (!rx::IsUnsignedAdditionSafe(offset, copyBytes) || ((offset + copyBytes) > static_cast<size_t>(pixelUnpackBuffer->size())))
261 {
262 // Overflow past the end of the buffer
263 return gl::error(GL_INVALID_OPERATION, false);
264 }
265
266 // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
267 // indicated by type.
268 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeBytes(type));
269
270 if ((offset % dataBytesPerPixel) != 0)
271 {
272 return gl::error(GL_INVALID_OPERATION, false);
273 }
274
Jamie Madill7a5f7382014-03-05 15:01:24 -0500275 // ...the buffer object's data store is currently mapped.
276 if (pixelUnpackBuffer->mapped())
277 {
278 return gl::error(GL_INVALID_OPERATION, false);
279 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400280 }
281
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400282 return true;
283}
284
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400285bool ValidateES3CopyTexImageParameters(gl::Context *context, GLenum target, GLint level, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400286 bool isSubImage, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y,
287 GLsizei width, GLsizei height, GLint border)
288{
Jamie Madill560a8d82014-05-21 13:06:20 -0400289 GLenum textureInternalFormat;
290 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
291 xoffset, yoffset, zoffset, x, y, width, height, border, &textureInternalFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400292 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400293 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400294 }
295
296 gl::Framebuffer *framebuffer = context->getReadFramebuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400297 gl::Renderbuffer *source = framebuffer->getReadColorbuffer();
298 GLenum colorbufferInternalFormat = source->getInternalFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400299
300 if (isSubImage)
301 {
Shannon Woods4d161ba2014-03-17 18:13:30 -0400302 if (!gl::IsValidCopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat, context->getReadFramebufferHandle(),
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400303 context->getClientVersion()))
304 {
305 return gl::error(GL_INVALID_OPERATION, false);
306 }
307 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400308 else
309 {
310 if (!gl::IsValidCopyTexImageCombination(internalformat, colorbufferInternalFormat, context->getReadFramebufferHandle(),
311 context->getClientVersion()))
312 {
313 return gl::error(GL_INVALID_OPERATION, false);
314 }
315 }
316
Geoff Lang784a8fd2013-09-24 12:33:16 -0400317 // If width or height is zero, it is a no-op. Return false without setting an error.
318 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400319}
320
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400321bool ValidateES3TexStorageParameters(gl::Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400322 GLsizei width, GLsizei height, GLsizei depth)
323{
324 if (width < 1 || height < 1 || depth < 1 || levels < 1)
325 {
326 return gl::error(GL_INVALID_VALUE, false);
327 }
328
329 if (levels > gl::log2(std::max(std::max(width, height), depth)) + 1)
330 {
331 return gl::error(GL_INVALID_OPERATION, false);
332 }
333
334 gl::Texture *texture = NULL;
335 switch (target)
336 {
337 case GL_TEXTURE_2D:
338 {
339 texture = context->getTexture2D();
340
341 if (width > (context->getMaximum2DTextureDimension()) ||
342 height > (context->getMaximum2DTextureDimension()))
343 {
344 return gl::error(GL_INVALID_VALUE, false);
345 }
346 }
347 break;
348
Geoff Lang01c21d22013-09-24 11:52:16 -0400349 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400350 {
351 texture = context->getTextureCubeMap();
352
353 if (width != height)
354 {
355 return gl::error(GL_INVALID_VALUE, false);
356 }
357
358 if (width > (context->getMaximumCubeTextureDimension()))
359 {
360 return gl::error(GL_INVALID_VALUE, false);
361 }
362 }
363 break;
364
365 case GL_TEXTURE_3D:
366 {
367 texture = context->getTexture3D();
368
369 if (width > (context->getMaximum3DTextureDimension()) ||
370 height > (context->getMaximum3DTextureDimension()) ||
371 depth > (context->getMaximum3DTextureDimension()))
372 {
373 return gl::error(GL_INVALID_VALUE, false);
374 }
375 }
376 break;
377
378 case GL_TEXTURE_2D_ARRAY:
379 {
380 texture = context->getTexture2DArray();
381
382 if (width > (context->getMaximum2DTextureDimension()) ||
383 height > (context->getMaximum2DTextureDimension()) ||
384 depth > (context->getMaximum2DArrayTextureLayers()))
385 {
386 return gl::error(GL_INVALID_VALUE, false);
387 }
388 }
389 break;
390
391 default:
392 return gl::error(GL_INVALID_ENUM, false);
393 }
394
395 if (!texture || texture->id() == 0)
396 {
397 return gl::error(GL_INVALID_OPERATION, false);
398 }
399
400 if (texture->isImmutable())
401 {
402 return gl::error(GL_INVALID_OPERATION, false);
403 }
404
405 if (!gl::IsValidInternalFormat(internalformat, context))
406 {
407 return gl::error(GL_INVALID_ENUM, false);
408 }
409
410 if (!gl::IsSizedInternalFormat(internalformat, context->getClientVersion()))
411 {
412 return gl::error(GL_INVALID_ENUM, false);
413 }
414
415 return true;
416}
417
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400418bool ValidateES3FramebufferTextureParameters(gl::Context *context, GLenum target, GLenum attachment,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400419 GLenum textarget, GLuint texture, GLint level, GLint layer,
420 bool layerCall)
421{
422 if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
423 {
424 return gl::error(GL_INVALID_ENUM, false);
425 }
426
427 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
428 {
429 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0);
430 if (colorAttachment >= context->getMaximumRenderTargets())
431 {
432 return gl::error(GL_INVALID_VALUE, false);
433 }
434 }
435 else
436 {
437 switch (attachment)
438 {
439 case GL_DEPTH_ATTACHMENT:
440 case GL_STENCIL_ATTACHMENT:
441 case GL_DEPTH_STENCIL_ATTACHMENT:
442 break;
443 default:
444 return gl::error(GL_INVALID_ENUM, false);
445 }
446 }
447
448 if (texture != 0)
449 {
450 gl::Texture *tex = context->getTexture(texture);
451
452 if (tex == NULL)
453 {
454 return gl::error(GL_INVALID_OPERATION, false);
455 }
456
457 if (level < 0)
458 {
459 return gl::error(GL_INVALID_VALUE, false);
460 }
461
462 if (layer < 0)
463 {
464 return gl::error(GL_INVALID_VALUE, false);
465 }
466
467 if (!layerCall)
468 {
469 switch (textarget)
470 {
471 case GL_TEXTURE_2D:
472 {
473 if (level > gl::log2(context->getMaximum2DTextureDimension()))
474 {
475 return gl::error(GL_INVALID_VALUE, false);
476 }
477 if (tex->getTarget() != GL_TEXTURE_2D)
478 {
479 return gl::error(GL_INVALID_OPERATION, false);
480 }
481 gl::Texture2D *tex2d = static_cast<gl::Texture2D *>(tex);
482 if (tex2d->isCompressed(level))
483 {
484 return gl::error(GL_INVALID_OPERATION, false);
485 }
486 break;
487 }
488
489 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
490 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
491 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
492 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
493 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
494 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
495 {
496 if (level > gl::log2(context->getMaximumCubeTextureDimension()))
497 {
498 return gl::error(GL_INVALID_VALUE, false);
499 }
500 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
501 {
502 return gl::error(GL_INVALID_OPERATION, false);
503 }
504 gl::TextureCubeMap *texcube = static_cast<gl::TextureCubeMap *>(tex);
505 if (texcube->isCompressed(textarget, level))
506 {
507 return gl::error(GL_INVALID_OPERATION, false);
508 }
509 break;
510 }
511
512 default:
513 return gl::error(GL_INVALID_ENUM, false);
514 }
515 }
516 else
517 {
518 switch (tex->getTarget())
519 {
520 case GL_TEXTURE_2D_ARRAY:
521 {
522 if (level > gl::log2(context->getMaximum2DTextureDimension()))
523 {
524 return gl::error(GL_INVALID_VALUE, false);
525 }
526
527 if (layer >= context->getMaximum2DArrayTextureLayers())
528 {
529 return gl::error(GL_INVALID_VALUE, false);
530 }
531
532 gl::Texture2DArray *texArray = static_cast<gl::Texture2DArray *>(tex);
533 if (texArray->isCompressed(level))
534 {
535 return gl::error(GL_INVALID_OPERATION, false);
536 }
537
538 break;
539 }
540
541 case GL_TEXTURE_3D:
542 {
543 if (level > gl::log2(context->getMaximum3DTextureDimension()))
544 {
545 return gl::error(GL_INVALID_VALUE, false);
546 }
547
548 if (layer >= context->getMaximum3DTextureDimension())
549 {
550 return gl::error(GL_INVALID_VALUE, false);
551 }
552
553 gl::Texture3D *tex3d = static_cast<gl::Texture3D *>(tex);
554 if (tex3d->isCompressed(level))
555 {
556 return gl::error(GL_INVALID_OPERATION, false);
557 }
558
559 break;
560 }
561
562 default:
563 return gl::error(GL_INVALID_OPERATION, false);
564 }
565 }
566 }
567
568 gl::Framebuffer *framebuffer = NULL;
569 GLuint framebufferHandle = 0;
570 if (target == GL_READ_FRAMEBUFFER)
571 {
572 framebuffer = context->getReadFramebuffer();
573 framebufferHandle = context->getReadFramebufferHandle();
574 }
575 else
576 {
577 framebuffer = context->getDrawFramebuffer();
578 framebufferHandle = context->getDrawFramebufferHandle();
579 }
580
581 if (framebufferHandle == 0 || !framebuffer)
582 {
583 return gl::error(GL_INVALID_OPERATION, false);
584 }
585
586 return true;
587}
588
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400589bool ValidES3ReadFormatType(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400590{
591 switch (format)
592 {
593 case GL_RGBA:
594 switch (type)
595 {
596 case GL_UNSIGNED_BYTE:
597 break;
598 case GL_UNSIGNED_INT_2_10_10_10_REV:
599 if (internalFormat != GL_RGB10_A2)
600 {
601 return false;
602 }
603 break;
Geoff Lang1ec57f82013-10-16 11:43:23 -0400604 case GL_FLOAT:
605 if (gl::GetComponentType(internalFormat, 3) != GL_FLOAT)
606 {
607 return false;
608 }
609 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400610 default:
611 return false;
612 }
613 break;
614 case GL_RGBA_INTEGER:
615 switch (type)
616 {
617 case GL_INT:
Geoff Langb2f3d052013-08-13 12:49:27 -0400618 if (gl::GetComponentType(internalFormat, 3) != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400619 {
620 return false;
621 }
622 break;
623 case GL_UNSIGNED_INT:
Geoff Langb2f3d052013-08-13 12:49:27 -0400624 if (gl::GetComponentType(internalFormat, 3) != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400625 {
626 return false;
627 }
628 break;
629 default:
630 return false;
631 }
632 break;
633 case GL_BGRA_EXT:
634 switch (type)
635 {
636 case GL_UNSIGNED_BYTE:
637 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
638 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
639 break;
640 default:
641 return false;
642 }
643 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400644 case GL_RG_EXT:
645 case GL_RED_EXT:
646 if (!context->supportsRGTextures())
647 {
648 return false;
649 }
650 switch (type)
651 {
652 case GL_UNSIGNED_BYTE:
653 break;
654 default:
655 return false;
656 }
657 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400658 default:
659 return false;
660 }
661 return true;
662}
663
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400664bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target, GLsizei numAttachments,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400665 const GLenum* attachments)
666{
667 bool defaultFramebuffer = false;
668
669 switch (target)
670 {
671 case GL_DRAW_FRAMEBUFFER:
672 case GL_FRAMEBUFFER:
673 defaultFramebuffer = context->getDrawFramebufferHandle() == 0;
674 break;
675 case GL_READ_FRAMEBUFFER:
676 defaultFramebuffer = context->getReadFramebufferHandle() == 0;
677 break;
678 default:
679 return gl::error(GL_INVALID_ENUM, false);
680 }
681
682 for (int i = 0; i < numAttachments; ++i)
683 {
684 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15)
685 {
686 if (defaultFramebuffer)
687 {
688 return gl::error(GL_INVALID_ENUM, false);
689 }
690
691 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getMaximumRenderTargets())
692 {
693 return gl::error(GL_INVALID_OPERATION, false);
694 }
695 }
696 else
697 {
698 switch (attachments[i])
699 {
700 case GL_DEPTH_ATTACHMENT:
701 case GL_STENCIL_ATTACHMENT:
702 case GL_DEPTH_STENCIL_ATTACHMENT:
703 if (defaultFramebuffer)
704 {
705 return gl::error(GL_INVALID_ENUM, false);
706 }
707 break;
708 case GL_COLOR:
709 case GL_DEPTH:
710 case GL_STENCIL:
711 if (!defaultFramebuffer)
712 {
713 return gl::error(GL_INVALID_ENUM, false);
714 }
715 break;
716 default:
717 return gl::error(GL_INVALID_ENUM, false);
718 }
719 }
720 }
721
722 return true;
723}
724
725}