blob: a45a5a31d3fc341bd178cd433c5f95e8dcb06a06 [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{
Jamie Madill6f38f822014-06-06 17:12:20 -040028 if (!ValidTexture2DDestinationTarget(context, target))
29 {
30 return gl::error(GL_INVALID_ENUM, false);
31 }
32
Geoff Lange8ebe7f2013-08-05 15:03:13 -040033 // Validate image size
Geoff Langce635692013-09-24 13:56:32 -040034 if (!ValidImageSize(context, target, level, width, height, depth))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040035 {
36 return gl::error(GL_INVALID_VALUE, false);
37 }
38
Geoff Lange8ebe7f2013-08-05 15:03:13 -040039 // Verify zero border
40 if (border != 0)
41 {
42 return gl::error(GL_INVALID_VALUE, false);
43 }
44
Jamie Madill6f38f822014-06-06 17:12:20 -040045 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
46 std::numeric_limits<GLsizei>::max() - xoffset < width ||
47 std::numeric_limits<GLsizei>::max() - yoffset < height ||
48 std::numeric_limits<GLsizei>::max() - zoffset < depth)
49 {
50 return gl::error(GL_INVALID_VALUE, false);
51 }
52
Geoff Lange8ebe7f2013-08-05 15:03:13 -040053 gl::Texture *texture = NULL;
54 bool textureCompressed = false;
55 GLenum textureInternalFormat = GL_NONE;
56 GLint textureLevelWidth = 0;
57 GLint textureLevelHeight = 0;
58 GLint textureLevelDepth = 0;
59 switch (target)
60 {
61 case GL_TEXTURE_2D:
62 {
63 if (width > (context->getMaximum2DTextureDimension() >> level) ||
64 height > (context->getMaximum2DTextureDimension() >> level))
65 {
66 return gl::error(GL_INVALID_VALUE, false);
67 }
68
69 gl::Texture2D *texture2d = context->getTexture2D();
70 if (texture2d)
71 {
72 textureCompressed = texture2d->isCompressed(level);
73 textureInternalFormat = texture2d->getInternalFormat(level);
74 textureLevelWidth = texture2d->getWidth(level);
75 textureLevelHeight = texture2d->getHeight(level);
76 textureLevelDepth = 1;
77 texture = texture2d;
78 }
79 }
80 break;
81
82 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
83 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
84 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
85 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
86 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
87 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
88 {
89 if (!isSubImage && width != height)
90 {
91 return gl::error(GL_INVALID_VALUE, false);
92 }
93
94 if (width > (context->getMaximumCubeTextureDimension() >> level))
95 {
96 return gl::error(GL_INVALID_VALUE, false);
97 }
98
99 gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
100 if (textureCube)
101 {
102 textureCompressed = textureCube->isCompressed(target, level);
103 textureInternalFormat = textureCube->getInternalFormat(target, level);
104 textureLevelWidth = textureCube->getWidth(target, level);
105 textureLevelHeight = textureCube->getHeight(target, level);
106 textureLevelDepth = 1;
107 texture = textureCube;
108 }
109 }
110 break;
111
112 case GL_TEXTURE_3D:
113 {
114 if (width > (context->getMaximum3DTextureDimension() >> level) ||
115 height > (context->getMaximum3DTextureDimension() >> level) ||
116 depth > (context->getMaximum3DTextureDimension() >> level))
117 {
118 return gl::error(GL_INVALID_VALUE, false);
119 }
120
121 gl::Texture3D *texture3d = context->getTexture3D();
122 if (texture3d)
123 {
124 textureCompressed = texture3d->isCompressed(level);
125 textureInternalFormat = texture3d->getInternalFormat(level);
126 textureLevelWidth = texture3d->getWidth(level);
127 textureLevelHeight = texture3d->getHeight(level);
128 textureLevelDepth = texture3d->getDepth(level);
129 texture = texture3d;
130 }
131 }
132 break;
133
134 case GL_TEXTURE_2D_ARRAY:
135 {
136 if (width > (context->getMaximum2DTextureDimension() >> level) ||
137 height > (context->getMaximum2DTextureDimension() >> level) ||
138 depth > (context->getMaximum2DArrayTextureLayers() >> level))
139 {
140 return gl::error(GL_INVALID_VALUE, false);
141 }
142
143 gl::Texture2DArray *texture2darray = context->getTexture2DArray();
144 if (texture2darray)
145 {
146 textureCompressed = texture2darray->isCompressed(level);
147 textureInternalFormat = texture2darray->getInternalFormat(level);
148 textureLevelWidth = texture2darray->getWidth(level);
149 textureLevelHeight = texture2darray->getHeight(level);
Jamie Madillb8f8b892014-01-07 10:12:50 -0500150 textureLevelDepth = texture2darray->getLayers(level);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400151 texture = texture2darray;
152 }
153 }
154 break;
155
156 default:
157 return gl::error(GL_INVALID_ENUM, false);
158 }
159
160 if (!texture)
161 {
162 return gl::error(GL_INVALID_OPERATION, false);
163 }
164
165 if (texture->isImmutable() && !isSubImage)
166 {
167 return gl::error(GL_INVALID_OPERATION, false);
168 }
169
170 // Validate texture formats
171 GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
Jamie Madill6f38f822014-06-06 17:12:20 -0400172 int clientVersion = context->getClientVersion();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400173 if (isCompressed)
174 {
Geoff Langd4f180b2013-09-24 13:57:44 -0400175 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
176 {
177 return gl::error(GL_INVALID_OPERATION, false);
178 }
179
Jamie Madill6f38f822014-06-06 17:12:20 -0400180 if (!gl::IsFormatCompressed(actualInternalFormat, clientVersion))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400181 {
182 return gl::error(GL_INVALID_ENUM, false);
183 }
184
185 if (target == GL_TEXTURE_3D)
186 {
187 return gl::error(GL_INVALID_OPERATION, false);
188 }
189 }
190 else
191 {
Jamie Madill6f38f822014-06-06 17:12:20 -0400192 // Note: dEQP 2013.4 expects an INVALID_VALUE error for TexImage3D with an invalid
193 // internal format. (dEQP-GLES3.functional.negative_api.texture.teximage3d)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400194 if (!gl::IsValidInternalFormat(actualInternalFormat, context) ||
Jamie Madill6f38f822014-06-06 17:12:20 -0400195 !gl::IsValidFormat(format, clientVersion) ||
196 !gl::IsValidType(type, clientVersion))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400197 {
198 return gl::error(GL_INVALID_ENUM, false);
199 }
200
Jamie Madill6f38f822014-06-06 17:12:20 -0400201 if (!gl::IsValidFormatCombination(actualInternalFormat, format, type, clientVersion))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400202 {
203 return gl::error(GL_INVALID_OPERATION, false);
204 }
205
206 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
207 {
208 return gl::error(GL_INVALID_OPERATION, false);
209 }
210 }
211
212 // Validate sub image parameters
213 if (isSubImage)
214 {
215 if (isCompressed != textureCompressed)
216 {
217 return gl::error(GL_INVALID_OPERATION, false);
218 }
219
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400220 if (isCompressed)
221 {
222 if ((width % 4 != 0 && width != textureLevelWidth) ||
223 (height % 4 != 0 && height != textureLevelHeight))
224 {
225 return gl::error(GL_INVALID_OPERATION, false);
226 }
227 }
228
229 if (width == 0 || height == 0 || depth == 0)
230 {
231 return false;
232 }
233
234 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
235 {
236 return gl::error(GL_INVALID_VALUE, false);
237 }
238
239 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
240 std::numeric_limits<GLsizei>::max() - yoffset < height ||
241 std::numeric_limits<GLsizei>::max() - zoffset < depth)
242 {
243 return gl::error(GL_INVALID_VALUE, false);
244 }
245
246 if (xoffset + width > textureLevelWidth ||
247 yoffset + height > textureLevelHeight ||
248 zoffset + depth > textureLevelDepth)
249 {
250 return gl::error(GL_INVALID_VALUE, false);
251 }
252 }
253
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400254 // Check for pixel unpack buffer related API errors
255 gl::Buffer *pixelUnpackBuffer = context->getPixelUnpackBuffer();
256 if (pixelUnpackBuffer != NULL)
257 {
258 // ...the data would be unpacked from the buffer object such that the memory reads required
259 // would exceed the data store size.
260 size_t widthSize = static_cast<size_t>(width);
261 size_t heightSize = static_cast<size_t>(height);
262 size_t depthSize = static_cast<size_t>(depth);
Jamie Madill6f38f822014-06-06 17:12:20 -0400263 GLenum sizedFormat = gl::IsSizedInternalFormat(actualInternalFormat, clientVersion) ?
264 actualInternalFormat :
265 gl::GetSizedInternalFormat(actualInternalFormat, type, clientVersion);
266
267 size_t pixelBytes = static_cast<size_t>(gl::GetPixelBytes(sizedFormat, clientVersion));
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400268
269 if (!rx::IsUnsignedMultiplicationSafe(widthSize, heightSize) ||
270 !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize, depthSize) ||
271 !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize * depthSize, pixelBytes))
272 {
273 // Overflow past the end of the buffer
274 return gl::error(GL_INVALID_OPERATION, false);
275 }
276
277 size_t copyBytes = widthSize * heightSize * depthSize * pixelBytes;
278 size_t offset = reinterpret_cast<size_t>(pixels);
279
Jamie Madill6f38f822014-06-06 17:12:20 -0400280 if (!rx::IsUnsignedAdditionSafe(offset, copyBytes) ||
281 ((offset + copyBytes) > static_cast<size_t>(pixelUnpackBuffer->size())))
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400282 {
283 // Overflow past the end of the buffer
284 return gl::error(GL_INVALID_OPERATION, false);
285 }
286
287 // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
288 // indicated by type.
289 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeBytes(type));
290
291 if ((offset % dataBytesPerPixel) != 0)
292 {
293 return gl::error(GL_INVALID_OPERATION, false);
294 }
295
Jamie Madill7a5f7382014-03-05 15:01:24 -0500296 // ...the buffer object's data store is currently mapped.
297 if (pixelUnpackBuffer->mapped())
298 {
299 return gl::error(GL_INVALID_OPERATION, false);
300 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400301 }
302
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400303 return true;
304}
305
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400306bool ValidateES3CopyTexImageParameters(gl::Context *context, GLenum target, GLint level, GLenum internalformat,
Jamie Madill6f38f822014-06-06 17:12:20 -0400307 bool isSubImage, GLint xoffset, GLint yoffset, GLint zoffset,
308 GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400309{
Jamie Madill560a8d82014-05-21 13:06:20 -0400310 GLenum textureInternalFormat;
311 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill6f38f822014-06-06 17:12:20 -0400312 xoffset, yoffset, zoffset, x, y, width, height,
313 border, &textureInternalFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400314 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400315 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400316 }
317
318 gl::Framebuffer *framebuffer = context->getReadFramebuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400319
320 if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
321 {
322 return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
323 }
324
325 if (context->getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0)
326 {
327 return gl::error(GL_INVALID_OPERATION, false);
328 }
329
330 gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400331 GLenum colorbufferInternalFormat = source->getInternalFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400332
333 if (isSubImage)
334 {
Jamie Madill6f38f822014-06-06 17:12:20 -0400335 if (!gl::IsValidCopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat,
336 context->getReadFramebufferHandle(),
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400337 context->getClientVersion()))
338 {
339 return gl::error(GL_INVALID_OPERATION, false);
340 }
341 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400342 else
343 {
Jamie Madill6f38f822014-06-06 17:12:20 -0400344 if (!gl::IsValidCopyTexImageCombination(internalformat, colorbufferInternalFormat,
345 context->getReadFramebufferHandle(),
Shannon Woods4d161ba2014-03-17 18:13:30 -0400346 context->getClientVersion()))
347 {
348 return gl::error(GL_INVALID_OPERATION, false);
349 }
350 }
351
Geoff Lang784a8fd2013-09-24 12:33:16 -0400352 // If width or height is zero, it is a no-op. Return false without setting an error.
353 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400354}
355
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400356bool ValidateES3TexStorageParameters(gl::Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400357 GLsizei width, GLsizei height, GLsizei depth)
358{
359 if (width < 1 || height < 1 || depth < 1 || levels < 1)
360 {
361 return gl::error(GL_INVALID_VALUE, false);
362 }
363
364 if (levels > gl::log2(std::max(std::max(width, height), depth)) + 1)
365 {
366 return gl::error(GL_INVALID_OPERATION, false);
367 }
368
369 gl::Texture *texture = NULL;
370 switch (target)
371 {
372 case GL_TEXTURE_2D:
373 {
374 texture = context->getTexture2D();
375
376 if (width > (context->getMaximum2DTextureDimension()) ||
377 height > (context->getMaximum2DTextureDimension()))
378 {
379 return gl::error(GL_INVALID_VALUE, false);
380 }
381 }
382 break;
383
Geoff Lang01c21d22013-09-24 11:52:16 -0400384 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400385 {
386 texture = context->getTextureCubeMap();
387
388 if (width != height)
389 {
390 return gl::error(GL_INVALID_VALUE, false);
391 }
392
393 if (width > (context->getMaximumCubeTextureDimension()))
394 {
395 return gl::error(GL_INVALID_VALUE, false);
396 }
397 }
398 break;
399
400 case GL_TEXTURE_3D:
401 {
402 texture = context->getTexture3D();
403
404 if (width > (context->getMaximum3DTextureDimension()) ||
405 height > (context->getMaximum3DTextureDimension()) ||
406 depth > (context->getMaximum3DTextureDimension()))
407 {
408 return gl::error(GL_INVALID_VALUE, false);
409 }
410 }
411 break;
412
413 case GL_TEXTURE_2D_ARRAY:
414 {
415 texture = context->getTexture2DArray();
416
417 if (width > (context->getMaximum2DTextureDimension()) ||
418 height > (context->getMaximum2DTextureDimension()) ||
419 depth > (context->getMaximum2DArrayTextureLayers()))
420 {
421 return gl::error(GL_INVALID_VALUE, false);
422 }
423 }
424 break;
425
426 default:
427 return gl::error(GL_INVALID_ENUM, false);
428 }
429
430 if (!texture || texture->id() == 0)
431 {
432 return gl::error(GL_INVALID_OPERATION, false);
433 }
434
435 if (texture->isImmutable())
436 {
437 return gl::error(GL_INVALID_OPERATION, false);
438 }
439
440 if (!gl::IsValidInternalFormat(internalformat, context))
441 {
442 return gl::error(GL_INVALID_ENUM, false);
443 }
444
445 if (!gl::IsSizedInternalFormat(internalformat, context->getClientVersion()))
446 {
447 return gl::error(GL_INVALID_ENUM, false);
448 }
449
450 return true;
451}
452
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400453bool ValidateES3FramebufferTextureParameters(gl::Context *context, GLenum target, GLenum attachment,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400454 GLenum textarget, GLuint texture, GLint level, GLint layer,
455 bool layerCall)
456{
457 if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
458 {
459 return gl::error(GL_INVALID_ENUM, false);
460 }
461
462 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
463 {
464 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0);
465 if (colorAttachment >= context->getMaximumRenderTargets())
466 {
467 return gl::error(GL_INVALID_VALUE, false);
468 }
469 }
470 else
471 {
472 switch (attachment)
473 {
474 case GL_DEPTH_ATTACHMENT:
475 case GL_STENCIL_ATTACHMENT:
476 case GL_DEPTH_STENCIL_ATTACHMENT:
477 break;
478 default:
479 return gl::error(GL_INVALID_ENUM, false);
480 }
481 }
482
483 if (texture != 0)
484 {
485 gl::Texture *tex = context->getTexture(texture);
486
487 if (tex == NULL)
488 {
489 return gl::error(GL_INVALID_OPERATION, false);
490 }
491
492 if (level < 0)
493 {
494 return gl::error(GL_INVALID_VALUE, false);
495 }
496
497 if (layer < 0)
498 {
499 return gl::error(GL_INVALID_VALUE, false);
500 }
501
502 if (!layerCall)
503 {
504 switch (textarget)
505 {
506 case GL_TEXTURE_2D:
507 {
508 if (level > gl::log2(context->getMaximum2DTextureDimension()))
509 {
510 return gl::error(GL_INVALID_VALUE, false);
511 }
512 if (tex->getTarget() != GL_TEXTURE_2D)
513 {
514 return gl::error(GL_INVALID_OPERATION, false);
515 }
516 gl::Texture2D *tex2d = static_cast<gl::Texture2D *>(tex);
517 if (tex2d->isCompressed(level))
518 {
519 return gl::error(GL_INVALID_OPERATION, false);
520 }
521 break;
522 }
523
524 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
525 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
526 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
527 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
528 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
529 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
530 {
531 if (level > gl::log2(context->getMaximumCubeTextureDimension()))
532 {
533 return gl::error(GL_INVALID_VALUE, false);
534 }
535 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
536 {
537 return gl::error(GL_INVALID_OPERATION, false);
538 }
539 gl::TextureCubeMap *texcube = static_cast<gl::TextureCubeMap *>(tex);
540 if (texcube->isCompressed(textarget, level))
541 {
542 return gl::error(GL_INVALID_OPERATION, false);
543 }
544 break;
545 }
546
547 default:
548 return gl::error(GL_INVALID_ENUM, false);
549 }
550 }
551 else
552 {
553 switch (tex->getTarget())
554 {
555 case GL_TEXTURE_2D_ARRAY:
556 {
557 if (level > gl::log2(context->getMaximum2DTextureDimension()))
558 {
559 return gl::error(GL_INVALID_VALUE, false);
560 }
561
562 if (layer >= context->getMaximum2DArrayTextureLayers())
563 {
564 return gl::error(GL_INVALID_VALUE, false);
565 }
566
567 gl::Texture2DArray *texArray = static_cast<gl::Texture2DArray *>(tex);
568 if (texArray->isCompressed(level))
569 {
570 return gl::error(GL_INVALID_OPERATION, false);
571 }
572
573 break;
574 }
575
576 case GL_TEXTURE_3D:
577 {
578 if (level > gl::log2(context->getMaximum3DTextureDimension()))
579 {
580 return gl::error(GL_INVALID_VALUE, false);
581 }
582
583 if (layer >= context->getMaximum3DTextureDimension())
584 {
585 return gl::error(GL_INVALID_VALUE, false);
586 }
587
588 gl::Texture3D *tex3d = static_cast<gl::Texture3D *>(tex);
589 if (tex3d->isCompressed(level))
590 {
591 return gl::error(GL_INVALID_OPERATION, false);
592 }
593
594 break;
595 }
596
597 default:
598 return gl::error(GL_INVALID_OPERATION, false);
599 }
600 }
601 }
602
603 gl::Framebuffer *framebuffer = NULL;
604 GLuint framebufferHandle = 0;
605 if (target == GL_READ_FRAMEBUFFER)
606 {
607 framebuffer = context->getReadFramebuffer();
608 framebufferHandle = context->getReadFramebufferHandle();
609 }
610 else
611 {
612 framebuffer = context->getDrawFramebuffer();
613 framebufferHandle = context->getDrawFramebufferHandle();
614 }
615
616 if (framebufferHandle == 0 || !framebuffer)
617 {
618 return gl::error(GL_INVALID_OPERATION, false);
619 }
620
621 return true;
622}
623
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400624bool ValidES3ReadFormatType(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400625{
626 switch (format)
627 {
628 case GL_RGBA:
629 switch (type)
630 {
631 case GL_UNSIGNED_BYTE:
632 break;
633 case GL_UNSIGNED_INT_2_10_10_10_REV:
634 if (internalFormat != GL_RGB10_A2)
635 {
636 return false;
637 }
638 break;
Geoff Lang1ec57f82013-10-16 11:43:23 -0400639 case GL_FLOAT:
640 if (gl::GetComponentType(internalFormat, 3) != GL_FLOAT)
641 {
642 return false;
643 }
644 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400645 default:
646 return false;
647 }
648 break;
649 case GL_RGBA_INTEGER:
650 switch (type)
651 {
652 case GL_INT:
Geoff Langb2f3d052013-08-13 12:49:27 -0400653 if (gl::GetComponentType(internalFormat, 3) != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400654 {
655 return false;
656 }
657 break;
658 case GL_UNSIGNED_INT:
Geoff Langb2f3d052013-08-13 12:49:27 -0400659 if (gl::GetComponentType(internalFormat, 3) != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400660 {
661 return false;
662 }
663 break;
664 default:
665 return false;
666 }
667 break;
668 case GL_BGRA_EXT:
669 switch (type)
670 {
671 case GL_UNSIGNED_BYTE:
672 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
673 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
674 break;
675 default:
676 return false;
677 }
678 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400679 case GL_RG_EXT:
680 case GL_RED_EXT:
681 if (!context->supportsRGTextures())
682 {
683 return false;
684 }
685 switch (type)
686 {
687 case GL_UNSIGNED_BYTE:
688 break;
689 default:
690 return false;
691 }
692 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400693 default:
694 return false;
695 }
696 return true;
697}
698
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400699bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target, GLsizei numAttachments,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400700 const GLenum* attachments)
701{
702 bool defaultFramebuffer = false;
703
704 switch (target)
705 {
706 case GL_DRAW_FRAMEBUFFER:
707 case GL_FRAMEBUFFER:
708 defaultFramebuffer = context->getDrawFramebufferHandle() == 0;
709 break;
710 case GL_READ_FRAMEBUFFER:
711 defaultFramebuffer = context->getReadFramebufferHandle() == 0;
712 break;
713 default:
714 return gl::error(GL_INVALID_ENUM, false);
715 }
716
717 for (int i = 0; i < numAttachments; ++i)
718 {
719 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15)
720 {
721 if (defaultFramebuffer)
722 {
723 return gl::error(GL_INVALID_ENUM, false);
724 }
725
726 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getMaximumRenderTargets())
727 {
728 return gl::error(GL_INVALID_OPERATION, false);
729 }
730 }
731 else
732 {
733 switch (attachments[i])
734 {
735 case GL_DEPTH_ATTACHMENT:
736 case GL_STENCIL_ATTACHMENT:
737 case GL_DEPTH_STENCIL_ATTACHMENT:
738 if (defaultFramebuffer)
739 {
740 return gl::error(GL_INVALID_ENUM, false);
741 }
742 break;
743 case GL_COLOR:
744 case GL_DEPTH:
745 case GL_STENCIL:
746 if (!defaultFramebuffer)
747 {
748 return gl::error(GL_INVALID_ENUM, false);
749 }
750 break;
751 default:
752 return gl::error(GL_INVALID_ENUM, false);
753 }
754 }
755 }
756
757 return true;
758}
759
760}