blob: 92ee329d92ed65959de4b38ae6be8586ef221849 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001#include "precompiled.h"
2//
Geoff Langcec35902014-04-16 10:52:36 -04003// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004// 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"
Jamie Madille261b442014-06-25 12:42:21 -040018#include "libGLESv2/FramebufferAttachment.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040019
20#include "common/mathutil.h"
21
22namespace gl
23{
24
Geoff Lang005df412013-10-16 14:12:50 -040025bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
Geoff Lange8ebe7f2013-08-05 15:03:13 -040026 GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
Jamie Madillefb2a6f2013-09-24 10:22:42 -040027 GLint border, GLenum format, GLenum type, const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040028{
Jamie Madill6f38f822014-06-06 17:12:20 -040029 if (!ValidTexture2DDestinationTarget(context, target))
30 {
31 return gl::error(GL_INVALID_ENUM, false);
32 }
33
Geoff Lange8ebe7f2013-08-05 15:03:13 -040034 // Validate image size
Geoff Langce635692013-09-24 13:56:32 -040035 if (!ValidImageSize(context, target, level, width, height, depth))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040036 {
37 return gl::error(GL_INVALID_VALUE, false);
38 }
39
Geoff Lange8ebe7f2013-08-05 15:03:13 -040040 // Verify zero border
41 if (border != 0)
42 {
43 return gl::error(GL_INVALID_VALUE, false);
44 }
45
Jamie Madill6f38f822014-06-06 17:12:20 -040046 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
47 std::numeric_limits<GLsizei>::max() - xoffset < width ||
48 std::numeric_limits<GLsizei>::max() - yoffset < height ||
49 std::numeric_limits<GLsizei>::max() - zoffset < depth)
50 {
51 return gl::error(GL_INVALID_VALUE, false);
52 }
53
Geoff Lange8ebe7f2013-08-05 15:03:13 -040054 gl::Texture *texture = NULL;
55 bool textureCompressed = false;
56 GLenum textureInternalFormat = GL_NONE;
57 GLint textureLevelWidth = 0;
58 GLint textureLevelHeight = 0;
59 GLint textureLevelDepth = 0;
60 switch (target)
61 {
62 case GL_TEXTURE_2D:
63 {
64 if (width > (context->getMaximum2DTextureDimension() >> level) ||
65 height > (context->getMaximum2DTextureDimension() >> level))
66 {
67 return gl::error(GL_INVALID_VALUE, false);
68 }
69
70 gl::Texture2D *texture2d = context->getTexture2D();
71 if (texture2d)
72 {
73 textureCompressed = texture2d->isCompressed(level);
74 textureInternalFormat = texture2d->getInternalFormat(level);
75 textureLevelWidth = texture2d->getWidth(level);
76 textureLevelHeight = texture2d->getHeight(level);
77 textureLevelDepth = 1;
78 texture = texture2d;
79 }
80 }
81 break;
82
83 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
84 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
85 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
86 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
87 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
88 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
89 {
90 if (!isSubImage && width != height)
91 {
92 return gl::error(GL_INVALID_VALUE, false);
93 }
94
95 if (width > (context->getMaximumCubeTextureDimension() >> level))
96 {
97 return gl::error(GL_INVALID_VALUE, false);
98 }
99
100 gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
101 if (textureCube)
102 {
103 textureCompressed = textureCube->isCompressed(target, level);
104 textureInternalFormat = textureCube->getInternalFormat(target, level);
105 textureLevelWidth = textureCube->getWidth(target, level);
106 textureLevelHeight = textureCube->getHeight(target, level);
107 textureLevelDepth = 1;
108 texture = textureCube;
109 }
110 }
111 break;
112
113 case GL_TEXTURE_3D:
114 {
115 if (width > (context->getMaximum3DTextureDimension() >> level) ||
116 height > (context->getMaximum3DTextureDimension() >> level) ||
117 depth > (context->getMaximum3DTextureDimension() >> level))
118 {
119 return gl::error(GL_INVALID_VALUE, false);
120 }
121
122 gl::Texture3D *texture3d = context->getTexture3D();
123 if (texture3d)
124 {
125 textureCompressed = texture3d->isCompressed(level);
126 textureInternalFormat = texture3d->getInternalFormat(level);
127 textureLevelWidth = texture3d->getWidth(level);
128 textureLevelHeight = texture3d->getHeight(level);
129 textureLevelDepth = texture3d->getDepth(level);
130 texture = texture3d;
131 }
132 }
133 break;
134
135 case GL_TEXTURE_2D_ARRAY:
136 {
137 if (width > (context->getMaximum2DTextureDimension() >> level) ||
138 height > (context->getMaximum2DTextureDimension() >> level) ||
139 depth > (context->getMaximum2DArrayTextureLayers() >> level))
140 {
141 return gl::error(GL_INVALID_VALUE, false);
142 }
143
144 gl::Texture2DArray *texture2darray = context->getTexture2DArray();
145 if (texture2darray)
146 {
147 textureCompressed = texture2darray->isCompressed(level);
148 textureInternalFormat = texture2darray->getInternalFormat(level);
149 textureLevelWidth = texture2darray->getWidth(level);
150 textureLevelHeight = texture2darray->getHeight(level);
Jamie Madillb8f8b892014-01-07 10:12:50 -0500151 textureLevelDepth = texture2darray->getLayers(level);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400152 texture = texture2darray;
153 }
154 }
155 break;
156
157 default:
158 return gl::error(GL_INVALID_ENUM, false);
159 }
160
161 if (!texture)
162 {
163 return gl::error(GL_INVALID_OPERATION, false);
164 }
165
166 if (texture->isImmutable() && !isSubImage)
167 {
168 return gl::error(GL_INVALID_OPERATION, false);
169 }
170
171 // Validate texture formats
172 GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
173 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
Geoff Lange4a492b2014-06-19 14:14:41 -0400180 if (!gl::IsFormatCompressed(actualInternalFormat))
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 Langcec35902014-04-16 10:52:36 -0400194 if (!gl::IsValidInternalFormat(actualInternalFormat, context->getCaps().extensions, context->getClientVersion()) ||
Geoff Lange4a492b2014-06-19 14:14:41 -0400195 !gl::IsValidFormat(format, context->getCaps().extensions, context->getClientVersion()) ||
196 !gl::IsValidType(type, context->getCaps().extensions, context->getClientVersion()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400197 {
198 return gl::error(GL_INVALID_ENUM, false);
199 }
200
Geoff Lange4a492b2014-06-19 14:14:41 -0400201 if (!gl::IsValidFormatCombination(actualInternalFormat, format, type, context->getCaps().extensions, context->getClientVersion()))
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);
Geoff Lange4a492b2014-06-19 14:14:41 -0400263 GLenum sizedFormat = gl::IsSizedInternalFormat(actualInternalFormat) ? actualInternalFormat
264 : gl::GetSizedInternalFormat(actualInternalFormat, type);
Jamie Madill6f38f822014-06-06 17:12:20 -0400265
Geoff Lange4a492b2014-06-19 14:14:41 -0400266 size_t pixelBytes = static_cast<size_t>(gl::GetPixelBytes(sizedFormat));
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400267
268 if (!rx::IsUnsignedMultiplicationSafe(widthSize, heightSize) ||
269 !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize, depthSize) ||
270 !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize * depthSize, pixelBytes))
271 {
272 // Overflow past the end of the buffer
273 return gl::error(GL_INVALID_OPERATION, false);
274 }
275
276 size_t copyBytes = widthSize * heightSize * depthSize * pixelBytes;
277 size_t offset = reinterpret_cast<size_t>(pixels);
278
Jamie Madill6f38f822014-06-06 17:12:20 -0400279 if (!rx::IsUnsignedAdditionSafe(offset, copyBytes) ||
Brandon Jonesd38f9262014-06-18 16:26:45 -0700280 ((offset + copyBytes) > static_cast<size_t>(pixelUnpackBuffer->getSize())))
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400281 {
282 // Overflow past the end of the buffer
283 return gl::error(GL_INVALID_OPERATION, false);
284 }
285
286 // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
287 // indicated by type.
288 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeBytes(type));
289
290 if ((offset % dataBytesPerPixel) != 0)
291 {
292 return gl::error(GL_INVALID_OPERATION, false);
293 }
294
Jamie Madill7a5f7382014-03-05 15:01:24 -0500295 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700296 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500297 {
298 return gl::error(GL_INVALID_OPERATION, false);
299 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400300 }
301
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400302 return true;
303}
304
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400305bool ValidateES3CopyTexImageParameters(gl::Context *context, GLenum target, GLint level, GLenum internalformat,
Jamie Madill6f38f822014-06-06 17:12:20 -0400306 bool isSubImage, GLint xoffset, GLint yoffset, GLint zoffset,
307 GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400308{
Jamie Madill560a8d82014-05-21 13:06:20 -0400309 GLenum textureInternalFormat;
310 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill6f38f822014-06-06 17:12:20 -0400311 xoffset, yoffset, zoffset, x, y, width, height,
312 border, &textureInternalFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400313 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400314 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400315 }
316
317 gl::Framebuffer *framebuffer = context->getReadFramebuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400318
319 if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
320 {
321 return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
322 }
323
324 if (context->getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0)
325 {
326 return gl::error(GL_INVALID_OPERATION, false);
327 }
328
329 gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400330 GLenum colorbufferInternalFormat = source->getInternalFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400331
332 if (isSubImage)
333 {
Jamie Madill6f38f822014-06-06 17:12:20 -0400334 if (!gl::IsValidCopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat,
335 context->getReadFramebufferHandle(),
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400336 context->getClientVersion()))
337 {
338 return gl::error(GL_INVALID_OPERATION, false);
339 }
340 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400341 else
342 {
Jamie Madill6f38f822014-06-06 17:12:20 -0400343 if (!gl::IsValidCopyTexImageCombination(internalformat, colorbufferInternalFormat,
344 context->getReadFramebufferHandle(),
Shannon Woods4d161ba2014-03-17 18:13:30 -0400345 context->getClientVersion()))
346 {
347 return gl::error(GL_INVALID_OPERATION, false);
348 }
349 }
350
Geoff Lang784a8fd2013-09-24 12:33:16 -0400351 // If width or height is zero, it is a no-op. Return false without setting an error.
352 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400353}
354
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400355bool ValidateES3TexStorageParameters(gl::Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400356 GLsizei width, GLsizei height, GLsizei depth)
357{
358 if (width < 1 || height < 1 || depth < 1 || levels < 1)
359 {
360 return gl::error(GL_INVALID_VALUE, false);
361 }
362
363 if (levels > gl::log2(std::max(std::max(width, height), depth)) + 1)
364 {
365 return gl::error(GL_INVALID_OPERATION, false);
366 }
367
368 gl::Texture *texture = NULL;
369 switch (target)
370 {
371 case GL_TEXTURE_2D:
372 {
373 texture = context->getTexture2D();
374
375 if (width > (context->getMaximum2DTextureDimension()) ||
376 height > (context->getMaximum2DTextureDimension()))
377 {
378 return gl::error(GL_INVALID_VALUE, false);
379 }
380 }
381 break;
382
Geoff Lang01c21d22013-09-24 11:52:16 -0400383 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400384 {
385 texture = context->getTextureCubeMap();
386
387 if (width != height)
388 {
389 return gl::error(GL_INVALID_VALUE, false);
390 }
391
392 if (width > (context->getMaximumCubeTextureDimension()))
393 {
394 return gl::error(GL_INVALID_VALUE, false);
395 }
396 }
397 break;
398
399 case GL_TEXTURE_3D:
400 {
401 texture = context->getTexture3D();
402
403 if (width > (context->getMaximum3DTextureDimension()) ||
404 height > (context->getMaximum3DTextureDimension()) ||
405 depth > (context->getMaximum3DTextureDimension()))
406 {
407 return gl::error(GL_INVALID_VALUE, false);
408 }
409 }
410 break;
411
412 case GL_TEXTURE_2D_ARRAY:
413 {
414 texture = context->getTexture2DArray();
415
416 if (width > (context->getMaximum2DTextureDimension()) ||
417 height > (context->getMaximum2DTextureDimension()) ||
418 depth > (context->getMaximum2DArrayTextureLayers()))
419 {
420 return gl::error(GL_INVALID_VALUE, false);
421 }
422 }
423 break;
424
425 default:
426 return gl::error(GL_INVALID_ENUM, false);
427 }
428
429 if (!texture || texture->id() == 0)
430 {
431 return gl::error(GL_INVALID_OPERATION, false);
432 }
433
434 if (texture->isImmutable())
435 {
436 return gl::error(GL_INVALID_OPERATION, false);
437 }
438
Geoff Langcec35902014-04-16 10:52:36 -0400439 if (!gl::IsValidInternalFormat(internalformat, context->getCaps().extensions, context->getClientVersion()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400440 {
441 return gl::error(GL_INVALID_ENUM, false);
442 }
443
Geoff Lange4a492b2014-06-19 14:14:41 -0400444 if (!gl::IsSizedInternalFormat(internalformat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400445 {
446 return gl::error(GL_INVALID_ENUM, false);
447 }
448
449 return true;
450}
451
Jamie Madill570f7c82014-07-03 10:38:54 -0400452bool ValidateES3FramebufferTextureParameters(const gl::Context *context, GLenum target, GLenum attachment,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400453 GLenum textarget, GLuint texture, GLint level, GLint layer,
454 bool layerCall)
455{
456 if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
457 {
458 return gl::error(GL_INVALID_ENUM, false);
459 }
460
Jamie Madillb4472272014-07-03 10:38:55 -0400461 if (!ValidateAttachmentTarget(context, attachment))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400462 {
Jamie Madillb4472272014-07-03 10:38:55 -0400463 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400464 }
465
466 if (texture != 0)
467 {
468 gl::Texture *tex = context->getTexture(texture);
469
470 if (tex == NULL)
471 {
472 return gl::error(GL_INVALID_OPERATION, false);
473 }
474
475 if (level < 0)
476 {
477 return gl::error(GL_INVALID_VALUE, false);
478 }
479
480 if (layer < 0)
481 {
482 return gl::error(GL_INVALID_VALUE, false);
483 }
484
485 if (!layerCall)
486 {
487 switch (textarget)
488 {
489 case GL_TEXTURE_2D:
490 {
491 if (level > gl::log2(context->getMaximum2DTextureDimension()))
492 {
493 return gl::error(GL_INVALID_VALUE, false);
494 }
495 if (tex->getTarget() != GL_TEXTURE_2D)
496 {
497 return gl::error(GL_INVALID_OPERATION, false);
498 }
499 gl::Texture2D *tex2d = static_cast<gl::Texture2D *>(tex);
500 if (tex2d->isCompressed(level))
501 {
502 return gl::error(GL_INVALID_OPERATION, false);
503 }
504 break;
505 }
506
507 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
508 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
509 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
510 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
511 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
512 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
513 {
514 if (level > gl::log2(context->getMaximumCubeTextureDimension()))
515 {
516 return gl::error(GL_INVALID_VALUE, false);
517 }
518 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
519 {
520 return gl::error(GL_INVALID_OPERATION, false);
521 }
522 gl::TextureCubeMap *texcube = static_cast<gl::TextureCubeMap *>(tex);
523 if (texcube->isCompressed(textarget, level))
524 {
525 return gl::error(GL_INVALID_OPERATION, false);
526 }
527 break;
528 }
529
530 default:
531 return gl::error(GL_INVALID_ENUM, false);
532 }
533 }
534 else
535 {
536 switch (tex->getTarget())
537 {
538 case GL_TEXTURE_2D_ARRAY:
539 {
540 if (level > gl::log2(context->getMaximum2DTextureDimension()))
541 {
542 return gl::error(GL_INVALID_VALUE, false);
543 }
544
545 if (layer >= context->getMaximum2DArrayTextureLayers())
546 {
547 return gl::error(GL_INVALID_VALUE, false);
548 }
549
550 gl::Texture2DArray *texArray = static_cast<gl::Texture2DArray *>(tex);
551 if (texArray->isCompressed(level))
552 {
553 return gl::error(GL_INVALID_OPERATION, false);
554 }
555
556 break;
557 }
558
559 case GL_TEXTURE_3D:
560 {
561 if (level > gl::log2(context->getMaximum3DTextureDimension()))
562 {
563 return gl::error(GL_INVALID_VALUE, false);
564 }
565
566 if (layer >= context->getMaximum3DTextureDimension())
567 {
568 return gl::error(GL_INVALID_VALUE, false);
569 }
570
571 gl::Texture3D *tex3d = static_cast<gl::Texture3D *>(tex);
572 if (tex3d->isCompressed(level))
573 {
574 return gl::error(GL_INVALID_OPERATION, false);
575 }
576
577 break;
578 }
579
580 default:
581 return gl::error(GL_INVALID_OPERATION, false);
582 }
583 }
584 }
585
Jamie Madill570f7c82014-07-03 10:38:54 -0400586 const gl::Framebuffer *framebuffer = NULL;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400587 GLuint framebufferHandle = 0;
588 if (target == GL_READ_FRAMEBUFFER)
589 {
590 framebuffer = context->getReadFramebuffer();
591 framebufferHandle = context->getReadFramebufferHandle();
592 }
593 else
594 {
595 framebuffer = context->getDrawFramebuffer();
596 framebufferHandle = context->getDrawFramebufferHandle();
597 }
598
599 if (framebufferHandle == 0 || !framebuffer)
600 {
601 return gl::error(GL_INVALID_OPERATION, false);
602 }
603
604 return true;
605}
606
Jamie Madill570f7c82014-07-03 10:38:54 -0400607bool ValidateFramebufferTextureLayer(const gl::Context *context, GLenum target, GLenum attachment,
608 GLuint texture, GLint level, GLint layer)
609{
610 if (context->getClientVersion() < 3)
611 {
612 return gl::error(GL_INVALID_OPERATION, false);
613 }
614
615 return ValidateES3FramebufferTextureParameters(context, target, attachment, GL_NONE, texture, level, layer, true);
616}
617
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400618bool ValidES3ReadFormatType(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400619{
620 switch (format)
621 {
622 case GL_RGBA:
623 switch (type)
624 {
625 case GL_UNSIGNED_BYTE:
626 break;
627 case GL_UNSIGNED_INT_2_10_10_10_REV:
628 if (internalFormat != GL_RGB10_A2)
629 {
630 return false;
631 }
632 break;
Geoff Lang1ec57f82013-10-16 11:43:23 -0400633 case GL_FLOAT:
Geoff Lange4a492b2014-06-19 14:14:41 -0400634 if (gl::GetComponentType(internalFormat) != GL_FLOAT)
Geoff Lang1ec57f82013-10-16 11:43:23 -0400635 {
636 return false;
637 }
638 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400639 default:
640 return false;
641 }
642 break;
643 case GL_RGBA_INTEGER:
644 switch (type)
645 {
646 case GL_INT:
Geoff Lange4a492b2014-06-19 14:14:41 -0400647 if (gl::GetComponentType(internalFormat) != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400648 {
649 return false;
650 }
651 break;
652 case GL_UNSIGNED_INT:
Geoff Lange4a492b2014-06-19 14:14:41 -0400653 if (gl::GetComponentType(internalFormat) != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400654 {
655 return false;
656 }
657 break;
658 default:
659 return false;
660 }
661 break;
662 case GL_BGRA_EXT:
663 switch (type)
664 {
665 case GL_UNSIGNED_BYTE:
666 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
667 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
668 break;
669 default:
670 return false;
671 }
672 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400673 case GL_RG_EXT:
674 case GL_RED_EXT:
Geoff Langcec35902014-04-16 10:52:36 -0400675 if (!context->getCaps().extensions.textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400676 {
677 return false;
678 }
679 switch (type)
680 {
681 case GL_UNSIGNED_BYTE:
682 break;
683 default:
684 return false;
685 }
686 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400687 default:
688 return false;
689 }
690 return true;
691}
692
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400693bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target, GLsizei numAttachments,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400694 const GLenum* attachments)
695{
696 bool defaultFramebuffer = false;
697
698 switch (target)
699 {
700 case GL_DRAW_FRAMEBUFFER:
701 case GL_FRAMEBUFFER:
702 defaultFramebuffer = context->getDrawFramebufferHandle() == 0;
703 break;
704 case GL_READ_FRAMEBUFFER:
705 defaultFramebuffer = context->getReadFramebufferHandle() == 0;
706 break;
707 default:
708 return gl::error(GL_INVALID_ENUM, false);
709 }
710
711 for (int i = 0; i < numAttachments; ++i)
712 {
713 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15)
714 {
715 if (defaultFramebuffer)
716 {
717 return gl::error(GL_INVALID_ENUM, false);
718 }
719
720 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getMaximumRenderTargets())
721 {
722 return gl::error(GL_INVALID_OPERATION, false);
723 }
724 }
725 else
726 {
727 switch (attachments[i])
728 {
729 case GL_DEPTH_ATTACHMENT:
730 case GL_STENCIL_ATTACHMENT:
731 case GL_DEPTH_STENCIL_ATTACHMENT:
732 if (defaultFramebuffer)
733 {
734 return gl::error(GL_INVALID_ENUM, false);
735 }
736 break;
737 case GL_COLOR:
738 case GL_DEPTH:
739 case GL_STENCIL:
740 if (!defaultFramebuffer)
741 {
742 return gl::error(GL_INVALID_ENUM, false);
743 }
744 break;
745 default:
746 return gl::error(GL_INVALID_ENUM, false);
747 }
748 }
749 }
750
751 return true;
752}
753
Jamie Madill13f7d7d2014-06-20 13:21:27 -0400754bool ValidateClearBuffer(const gl::Context *context)
755{
756 if (context->getClientVersion() < 3)
757 {
758 return gl::error(GL_INVALID_OPERATION, false);
759 }
760
761 const gl::Framebuffer *fbo = context->getDrawFramebuffer();
762 if (!fbo || fbo->completeness() != GL_FRAMEBUFFER_COMPLETE)
763 {
764 return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
765 }
766
767 return true;
768}
769
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400770}