blob: 555c5e3cfa1a68e4a77b4d5e7e347c373af3bf16 [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();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400319 gl::Renderbuffer *source = framebuffer->getReadColorbuffer();
320 GLenum colorbufferInternalFormat = source->getInternalFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400321
322 if (isSubImage)
323 {
Jamie Madill6f38f822014-06-06 17:12:20 -0400324 if (!gl::IsValidCopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat,
325 context->getReadFramebufferHandle(),
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400326 context->getClientVersion()))
327 {
328 return gl::error(GL_INVALID_OPERATION, false);
329 }
330 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400331 else
332 {
Jamie Madill6f38f822014-06-06 17:12:20 -0400333 if (!gl::IsValidCopyTexImageCombination(internalformat, colorbufferInternalFormat,
334 context->getReadFramebufferHandle(),
Shannon Woods4d161ba2014-03-17 18:13:30 -0400335 context->getClientVersion()))
336 {
337 return gl::error(GL_INVALID_OPERATION, false);
338 }
339 }
340
Geoff Lang784a8fd2013-09-24 12:33:16 -0400341 // If width or height is zero, it is a no-op. Return false without setting an error.
342 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400343}
344
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400345bool ValidateES3TexStorageParameters(gl::Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400346 GLsizei width, GLsizei height, GLsizei depth)
347{
348 if (width < 1 || height < 1 || depth < 1 || levels < 1)
349 {
350 return gl::error(GL_INVALID_VALUE, false);
351 }
352
353 if (levels > gl::log2(std::max(std::max(width, height), depth)) + 1)
354 {
355 return gl::error(GL_INVALID_OPERATION, false);
356 }
357
358 gl::Texture *texture = NULL;
359 switch (target)
360 {
361 case GL_TEXTURE_2D:
362 {
363 texture = context->getTexture2D();
364
365 if (width > (context->getMaximum2DTextureDimension()) ||
366 height > (context->getMaximum2DTextureDimension()))
367 {
368 return gl::error(GL_INVALID_VALUE, false);
369 }
370 }
371 break;
372
Geoff Lang01c21d22013-09-24 11:52:16 -0400373 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400374 {
375 texture = context->getTextureCubeMap();
376
377 if (width != height)
378 {
379 return gl::error(GL_INVALID_VALUE, false);
380 }
381
382 if (width > (context->getMaximumCubeTextureDimension()))
383 {
384 return gl::error(GL_INVALID_VALUE, false);
385 }
386 }
387 break;
388
389 case GL_TEXTURE_3D:
390 {
391 texture = context->getTexture3D();
392
393 if (width > (context->getMaximum3DTextureDimension()) ||
394 height > (context->getMaximum3DTextureDimension()) ||
395 depth > (context->getMaximum3DTextureDimension()))
396 {
397 return gl::error(GL_INVALID_VALUE, false);
398 }
399 }
400 break;
401
402 case GL_TEXTURE_2D_ARRAY:
403 {
404 texture = context->getTexture2DArray();
405
406 if (width > (context->getMaximum2DTextureDimension()) ||
407 height > (context->getMaximum2DTextureDimension()) ||
408 depth > (context->getMaximum2DArrayTextureLayers()))
409 {
410 return gl::error(GL_INVALID_VALUE, false);
411 }
412 }
413 break;
414
415 default:
416 return gl::error(GL_INVALID_ENUM, false);
417 }
418
419 if (!texture || texture->id() == 0)
420 {
421 return gl::error(GL_INVALID_OPERATION, false);
422 }
423
424 if (texture->isImmutable())
425 {
426 return gl::error(GL_INVALID_OPERATION, false);
427 }
428
429 if (!gl::IsValidInternalFormat(internalformat, context))
430 {
431 return gl::error(GL_INVALID_ENUM, false);
432 }
433
434 if (!gl::IsSizedInternalFormat(internalformat, context->getClientVersion()))
435 {
436 return gl::error(GL_INVALID_ENUM, false);
437 }
438
439 return true;
440}
441
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400442bool ValidateES3FramebufferTextureParameters(gl::Context *context, GLenum target, GLenum attachment,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400443 GLenum textarget, GLuint texture, GLint level, GLint layer,
444 bool layerCall)
445{
446 if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
447 {
448 return gl::error(GL_INVALID_ENUM, false);
449 }
450
451 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
452 {
453 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0);
454 if (colorAttachment >= context->getMaximumRenderTargets())
455 {
456 return gl::error(GL_INVALID_VALUE, false);
457 }
458 }
459 else
460 {
461 switch (attachment)
462 {
463 case GL_DEPTH_ATTACHMENT:
464 case GL_STENCIL_ATTACHMENT:
465 case GL_DEPTH_STENCIL_ATTACHMENT:
466 break;
467 default:
468 return gl::error(GL_INVALID_ENUM, false);
469 }
470 }
471
472 if (texture != 0)
473 {
474 gl::Texture *tex = context->getTexture(texture);
475
476 if (tex == NULL)
477 {
478 return gl::error(GL_INVALID_OPERATION, false);
479 }
480
481 if (level < 0)
482 {
483 return gl::error(GL_INVALID_VALUE, false);
484 }
485
486 if (layer < 0)
487 {
488 return gl::error(GL_INVALID_VALUE, false);
489 }
490
491 if (!layerCall)
492 {
493 switch (textarget)
494 {
495 case GL_TEXTURE_2D:
496 {
497 if (level > gl::log2(context->getMaximum2DTextureDimension()))
498 {
499 return gl::error(GL_INVALID_VALUE, false);
500 }
501 if (tex->getTarget() != GL_TEXTURE_2D)
502 {
503 return gl::error(GL_INVALID_OPERATION, false);
504 }
505 gl::Texture2D *tex2d = static_cast<gl::Texture2D *>(tex);
506 if (tex2d->isCompressed(level))
507 {
508 return gl::error(GL_INVALID_OPERATION, false);
509 }
510 break;
511 }
512
513 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
514 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
515 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
516 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
517 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
518 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
519 {
520 if (level > gl::log2(context->getMaximumCubeTextureDimension()))
521 {
522 return gl::error(GL_INVALID_VALUE, false);
523 }
524 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
525 {
526 return gl::error(GL_INVALID_OPERATION, false);
527 }
528 gl::TextureCubeMap *texcube = static_cast<gl::TextureCubeMap *>(tex);
529 if (texcube->isCompressed(textarget, level))
530 {
531 return gl::error(GL_INVALID_OPERATION, false);
532 }
533 break;
534 }
535
536 default:
537 return gl::error(GL_INVALID_ENUM, false);
538 }
539 }
540 else
541 {
542 switch (tex->getTarget())
543 {
544 case GL_TEXTURE_2D_ARRAY:
545 {
546 if (level > gl::log2(context->getMaximum2DTextureDimension()))
547 {
548 return gl::error(GL_INVALID_VALUE, false);
549 }
550
551 if (layer >= context->getMaximum2DArrayTextureLayers())
552 {
553 return gl::error(GL_INVALID_VALUE, false);
554 }
555
556 gl::Texture2DArray *texArray = static_cast<gl::Texture2DArray *>(tex);
557 if (texArray->isCompressed(level))
558 {
559 return gl::error(GL_INVALID_OPERATION, false);
560 }
561
562 break;
563 }
564
565 case GL_TEXTURE_3D:
566 {
567 if (level > gl::log2(context->getMaximum3DTextureDimension()))
568 {
569 return gl::error(GL_INVALID_VALUE, false);
570 }
571
572 if (layer >= context->getMaximum3DTextureDimension())
573 {
574 return gl::error(GL_INVALID_VALUE, false);
575 }
576
577 gl::Texture3D *tex3d = static_cast<gl::Texture3D *>(tex);
578 if (tex3d->isCompressed(level))
579 {
580 return gl::error(GL_INVALID_OPERATION, false);
581 }
582
583 break;
584 }
585
586 default:
587 return gl::error(GL_INVALID_OPERATION, false);
588 }
589 }
590 }
591
592 gl::Framebuffer *framebuffer = NULL;
593 GLuint framebufferHandle = 0;
594 if (target == GL_READ_FRAMEBUFFER)
595 {
596 framebuffer = context->getReadFramebuffer();
597 framebufferHandle = context->getReadFramebufferHandle();
598 }
599 else
600 {
601 framebuffer = context->getDrawFramebuffer();
602 framebufferHandle = context->getDrawFramebufferHandle();
603 }
604
605 if (framebufferHandle == 0 || !framebuffer)
606 {
607 return gl::error(GL_INVALID_OPERATION, false);
608 }
609
610 return true;
611}
612
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400613bool ValidES3ReadFormatType(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400614{
615 switch (format)
616 {
617 case GL_RGBA:
618 switch (type)
619 {
620 case GL_UNSIGNED_BYTE:
621 break;
622 case GL_UNSIGNED_INT_2_10_10_10_REV:
623 if (internalFormat != GL_RGB10_A2)
624 {
625 return false;
626 }
627 break;
Geoff Lang1ec57f82013-10-16 11:43:23 -0400628 case GL_FLOAT:
629 if (gl::GetComponentType(internalFormat, 3) != GL_FLOAT)
630 {
631 return false;
632 }
633 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400634 default:
635 return false;
636 }
637 break;
638 case GL_RGBA_INTEGER:
639 switch (type)
640 {
641 case GL_INT:
Geoff Langb2f3d052013-08-13 12:49:27 -0400642 if (gl::GetComponentType(internalFormat, 3) != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400643 {
644 return false;
645 }
646 break;
647 case GL_UNSIGNED_INT:
Geoff Langb2f3d052013-08-13 12:49:27 -0400648 if (gl::GetComponentType(internalFormat, 3) != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400649 {
650 return false;
651 }
652 break;
653 default:
654 return false;
655 }
656 break;
657 case GL_BGRA_EXT:
658 switch (type)
659 {
660 case GL_UNSIGNED_BYTE:
661 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
662 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
663 break;
664 default:
665 return false;
666 }
667 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400668 case GL_RG_EXT:
669 case GL_RED_EXT:
670 if (!context->supportsRGTextures())
671 {
672 return false;
673 }
674 switch (type)
675 {
676 case GL_UNSIGNED_BYTE:
677 break;
678 default:
679 return false;
680 }
681 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400682 default:
683 return false;
684 }
685 return true;
686}
687
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400688bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target, GLsizei numAttachments,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400689 const GLenum* attachments)
690{
691 bool defaultFramebuffer = false;
692
693 switch (target)
694 {
695 case GL_DRAW_FRAMEBUFFER:
696 case GL_FRAMEBUFFER:
697 defaultFramebuffer = context->getDrawFramebufferHandle() == 0;
698 break;
699 case GL_READ_FRAMEBUFFER:
700 defaultFramebuffer = context->getReadFramebufferHandle() == 0;
701 break;
702 default:
703 return gl::error(GL_INVALID_ENUM, false);
704 }
705
706 for (int i = 0; i < numAttachments; ++i)
707 {
708 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15)
709 {
710 if (defaultFramebuffer)
711 {
712 return gl::error(GL_INVALID_ENUM, false);
713 }
714
715 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getMaximumRenderTargets())
716 {
717 return gl::error(GL_INVALID_OPERATION, false);
718 }
719 }
720 else
721 {
722 switch (attachments[i])
723 {
724 case GL_DEPTH_ATTACHMENT:
725 case GL_STENCIL_ATTACHMENT:
726 case GL_DEPTH_STENCIL_ATTACHMENT:
727 if (defaultFramebuffer)
728 {
729 return gl::error(GL_INVALID_ENUM, false);
730 }
731 break;
732 case GL_COLOR:
733 case GL_DEPTH:
734 case GL_STENCIL:
735 if (!defaultFramebuffer)
736 {
737 return gl::error(GL_INVALID_ENUM, false);
738 }
739 break;
740 default:
741 return gl::error(GL_INVALID_ENUM, false);
742 }
743 }
744 }
745
746 return true;
747}
748
749}