blob: ea6b80735a8d542a8e24fc337475f5f0d27b5617 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES2.h"
10#include "libANGLE/validationES.h"
11#include "libANGLE/Context.h"
12#include "libANGLE/Texture.h"
13#include "libANGLE/Framebuffer.h"
14#include "libANGLE/Renderbuffer.h"
15#include "libANGLE/formatutils.h"
16#include "libANGLE/FramebufferAttachment.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040017
18#include "common/mathutil.h"
19#include "common/utilities.h"
20
21namespace gl
22{
23
Geoff Langb1196682014-07-23 13:47:29 -040024bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
26 GLint border, GLenum format, GLenum type, const GLvoid *pixels)
27{
Jamie Madill6f38f822014-06-06 17:12:20 -040028 if (!ValidTexture2DDestinationTarget(context, target))
29 {
Geoff Langb1196682014-07-23 13:47:29 -040030 context->recordError(Error(GL_INVALID_ENUM));
31 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -040032 }
33
Geoff Langce635692013-09-24 13:56:32 -040034 if (!ValidImageSize(context, target, level, width, height, 1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040035 {
Geoff Langb1196682014-07-23 13:47:29 -040036 context->recordError(Error(GL_INVALID_VALUE));
37 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040038 }
39
Geoff Lange8ebe7f2013-08-05 15:03:13 -040040 if (level < 0 || xoffset < 0 ||
41 std::numeric_limits<GLsizei>::max() - xoffset < width ||
42 std::numeric_limits<GLsizei>::max() - yoffset < height)
43 {
Geoff Langb1196682014-07-23 13:47:29 -040044 context->recordError(Error(GL_INVALID_VALUE));
45 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040046 }
47
Geoff Lang005df412013-10-16 14:12:50 -040048 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040049 {
Geoff Langb1196682014-07-23 13:47:29 -040050 context->recordError(Error(GL_INVALID_OPERATION));
51 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040052 }
53
Geoff Langaae65a42014-05-26 12:43:44 -040054 const gl::Caps &caps = context->getCaps();
55
Geoff Langa9be0dc2014-12-17 12:34:40 -050056 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040057 {
Geoff Langa9be0dc2014-12-17 12:34:40 -050058 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
59 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040060 {
Geoff Langa9be0dc2014-12-17 12:34:40 -050061 context->recordError(Error(GL_INVALID_VALUE));
62 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040063 }
Geoff Langa9be0dc2014-12-17 12:34:40 -050064 }
Geoff Lang691e58c2014-12-19 17:03:25 -050065 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -050066 {
67 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040068 {
Geoff Langa9be0dc2014-12-17 12:34:40 -050069 context->recordError(Error(GL_INVALID_VALUE));
70 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040071 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -040072
Geoff Langa9be0dc2014-12-17 12:34:40 -050073 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
74 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
75 {
76 context->recordError(Error(GL_INVALID_VALUE));
77 return false;
78 }
79 }
80 else
81 {
Geoff Langb1196682014-07-23 13:47:29 -040082 context->recordError(Error(GL_INVALID_ENUM));
83 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040084 }
85
Geoff Lang691e58c2014-12-19 17:03:25 -050086 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -040087 if (!texture)
88 {
Geoff Langb1196682014-07-23 13:47:29 -040089 context->recordError(Error(GL_INVALID_OPERATION));
90 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040091 }
92
Geoff Langa9be0dc2014-12-17 12:34:40 -050093 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040094 {
Geoff Langa9be0dc2014-12-17 12:34:40 -050095 if (format != GL_NONE)
96 {
Geoff Lang051dbc72015-01-05 15:48:58 -050097 if (gl::GetSizedInternalFormat(format, type) != texture->getInternalFormat(target, level))
Geoff Langa9be0dc2014-12-17 12:34:40 -050098 {
99 context->recordError(Error(GL_INVALID_OPERATION));
100 return false;
101 }
102 }
103
104 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
105 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
106 {
107 context->recordError(Error(GL_INVALID_VALUE));
108 return false;
109 }
110 }
111 else
112 {
Geoff Lang69cce582015-09-17 13:20:36 -0400113 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500114 {
115 context->recordError(Error(GL_INVALID_OPERATION));
116 return false;
117 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400118 }
119
120 // Verify zero border
121 if (border != 0)
122 {
Geoff Langb1196682014-07-23 13:47:29 -0400123 context->recordError(Error(GL_INVALID_VALUE));
124 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400125 }
126
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400127 if (isCompressed)
128 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400129 GLenum actualInternalFormat =
130 isSubImage ? texture->getInternalFormat(target, level) : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400131 switch (actualInternalFormat)
132 {
133 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
134 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400135 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400136 {
Geoff Langb1196682014-07-23 13:47:29 -0400137 context->recordError(Error(GL_INVALID_ENUM));
138 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400139 }
140 break;
141 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400142 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400143 {
Geoff Langb1196682014-07-23 13:47:29 -0400144 context->recordError(Error(GL_INVALID_ENUM));
145 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400146 }
147 break;
148 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langb1196682014-07-23 13:47:29 -0400149 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400150 {
Geoff Langb1196682014-07-23 13:47:29 -0400151 context->recordError(Error(GL_INVALID_ENUM));
152 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400153 }
154 break;
155 default:
tmartino0ccd5ae2015-10-01 14:33:14 -0400156 context->recordError(Error(
157 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format"));
158 return false;
159 }
160 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
161 {
162 context->recordError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400163 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400164 }
165 }
166 else
167 {
168 // validate <type> by itself (used as secondary key below)
169 switch (type)
170 {
171 case GL_UNSIGNED_BYTE:
172 case GL_UNSIGNED_SHORT_5_6_5:
173 case GL_UNSIGNED_SHORT_4_4_4_4:
174 case GL_UNSIGNED_SHORT_5_5_5_1:
175 case GL_UNSIGNED_SHORT:
176 case GL_UNSIGNED_INT:
177 case GL_UNSIGNED_INT_24_8_OES:
178 case GL_HALF_FLOAT_OES:
179 case GL_FLOAT:
180 break;
181 default:
Geoff Langb1196682014-07-23 13:47:29 -0400182 context->recordError(Error(GL_INVALID_ENUM));
183 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400184 }
185
186 // validate <format> + <type> combinations
187 // - invalid <format> -> sets INVALID_ENUM
188 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
189 switch (format)
190 {
191 case GL_ALPHA:
192 case GL_LUMINANCE:
193 case GL_LUMINANCE_ALPHA:
194 switch (type)
195 {
196 case GL_UNSIGNED_BYTE:
197 case GL_FLOAT:
198 case GL_HALF_FLOAT_OES:
199 break;
Geoff Langb1196682014-07-23 13:47:29 -0400200 default:
201 context->recordError(Error(GL_INVALID_OPERATION));
202 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400203 }
204 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400205 case GL_RED:
Geoff Langcec35902014-04-16 10:52:36 -0400206 case GL_RG:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400207 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400208 {
Geoff Langb1196682014-07-23 13:47:29 -0400209 context->recordError(Error(GL_INVALID_ENUM));
210 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400211 }
212 switch (type)
213 {
214 case GL_UNSIGNED_BYTE:
215 case GL_FLOAT:
216 case GL_HALF_FLOAT_OES:
217 break;
218 default:
Geoff Langb1196682014-07-23 13:47:29 -0400219 context->recordError(Error(GL_INVALID_OPERATION));
220 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400221 }
222 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400223 case GL_RGB:
224 switch (type)
225 {
226 case GL_UNSIGNED_BYTE:
227 case GL_UNSIGNED_SHORT_5_6_5:
228 case GL_FLOAT:
229 case GL_HALF_FLOAT_OES:
230 break;
231 default:
Geoff Langb1196682014-07-23 13:47:29 -0400232 context->recordError(Error(GL_INVALID_OPERATION));
233 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400234 }
235 break;
236 case GL_RGBA:
237 switch (type)
238 {
239 case GL_UNSIGNED_BYTE:
240 case GL_UNSIGNED_SHORT_4_4_4_4:
241 case GL_UNSIGNED_SHORT_5_5_5_1:
242 case GL_FLOAT:
243 case GL_HALF_FLOAT_OES:
244 break;
245 default:
Geoff Langb1196682014-07-23 13:47:29 -0400246 context->recordError(Error(GL_INVALID_OPERATION));
247 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400248 }
249 break;
250 case GL_BGRA_EXT:
251 switch (type)
252 {
253 case GL_UNSIGNED_BYTE:
254 break;
255 default:
Geoff Langb1196682014-07-23 13:47:29 -0400256 context->recordError(Error(GL_INVALID_OPERATION));
257 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400258 }
259 break;
Geoff Lang05b05022014-06-11 15:31:45 -0400260 case GL_SRGB_EXT:
261 case GL_SRGB_ALPHA_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400262 if (!context->getExtensions().sRGB)
Geoff Lang05b05022014-06-11 15:31:45 -0400263 {
Geoff Langb1196682014-07-23 13:47:29 -0400264 context->recordError(Error(GL_INVALID_ENUM));
265 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400266 }
267 switch (type)
268 {
269 case GL_UNSIGNED_BYTE:
270 break;
271 default:
Geoff Langb1196682014-07-23 13:47:29 -0400272 context->recordError(Error(GL_INVALID_OPERATION));
273 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400274 }
275 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400276 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
277 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
278 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
279 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
280 break;
281 case GL_DEPTH_COMPONENT:
282 switch (type)
283 {
284 case GL_UNSIGNED_SHORT:
285 case GL_UNSIGNED_INT:
286 break;
287 default:
Geoff Langb1196682014-07-23 13:47:29 -0400288 context->recordError(Error(GL_INVALID_OPERATION));
289 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400290 }
291 break;
292 case GL_DEPTH_STENCIL_OES:
293 switch (type)
294 {
295 case GL_UNSIGNED_INT_24_8_OES:
296 break;
297 default:
Geoff Langb1196682014-07-23 13:47:29 -0400298 context->recordError(Error(GL_INVALID_OPERATION));
299 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400300 }
301 break;
302 default:
Geoff Langb1196682014-07-23 13:47:29 -0400303 context->recordError(Error(GL_INVALID_ENUM));
304 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400305 }
306
307 switch (format)
308 {
309 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
310 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400311 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400312 {
Geoff Langb1196682014-07-23 13:47:29 -0400313 context->recordError(Error(GL_INVALID_OPERATION));
314 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400315 }
316 else
317 {
Geoff Langb1196682014-07-23 13:47:29 -0400318 context->recordError(Error(GL_INVALID_ENUM));
319 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400320 }
321 break;
322 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400323 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400324 {
Geoff Langb1196682014-07-23 13:47:29 -0400325 context->recordError(Error(GL_INVALID_OPERATION));
326 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400327 }
328 else
329 {
Geoff Langb1196682014-07-23 13:47:29 -0400330 context->recordError(Error(GL_INVALID_ENUM));
331 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400332 }
333 break;
334 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400335 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400336 {
Geoff Langb1196682014-07-23 13:47:29 -0400337 context->recordError(Error(GL_INVALID_OPERATION));
338 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400339 }
340 else
341 {
Geoff Langb1196682014-07-23 13:47:29 -0400342 context->recordError(Error(GL_INVALID_ENUM));
343 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400344 }
345 break;
346 case GL_DEPTH_COMPONENT:
347 case GL_DEPTH_STENCIL_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400348 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400349 {
Geoff Langb1196682014-07-23 13:47:29 -0400350 context->recordError(Error(GL_INVALID_VALUE));
351 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400352 }
353 if (target != GL_TEXTURE_2D)
354 {
Geoff Langb1196682014-07-23 13:47:29 -0400355 context->recordError(Error(GL_INVALID_OPERATION));
356 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400357 }
358 // OES_depth_texture supports loading depth data and multiple levels,
359 // but ANGLE_depth_texture does not
360 if (pixels != NULL || level != 0)
361 {
Geoff Langb1196682014-07-23 13:47:29 -0400362 context->recordError(Error(GL_INVALID_OPERATION));
363 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400364 }
365 break;
366 default:
367 break;
368 }
369
370 if (type == GL_FLOAT)
371 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400372 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400373 {
Geoff Langb1196682014-07-23 13:47:29 -0400374 context->recordError(Error(GL_INVALID_ENUM));
375 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400376 }
377 }
378 else if (type == GL_HALF_FLOAT_OES)
379 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400380 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400381 {
Geoff Langb1196682014-07-23 13:47:29 -0400382 context->recordError(Error(GL_INVALID_ENUM));
383 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400384 }
385 }
386 }
387
388 return true;
389}
390
391
392
Geoff Langb1196682014-07-23 13:47:29 -0400393bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400394 GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height,
395 GLint border)
396{
Jamie Madill560a8d82014-05-21 13:06:20 -0400397 GLenum textureInternalFormat = GL_NONE;
Shannon Woods4dfed832014-03-17 20:03:39 -0400398
Jamie Madill560a8d82014-05-21 13:06:20 -0400399 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
400 xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400401 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400402 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400403 }
404
Shannon Woods53a94a82014-06-24 15:20:36 -0400405 gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400406 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat();
Jamie Madillbc393df2015-01-29 13:46:07 -0500407 const auto &internalFormatInfo = gl::GetInternalFormatInfo(textureInternalFormat);
408 GLenum textureFormat = internalFormatInfo.format;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400409
410 // [OpenGL ES 2.0.24] table 3.9
411 if (isSubImage)
412 {
413 switch (textureFormat)
414 {
415 case GL_ALPHA:
416 if (colorbufferFormat != GL_ALPHA8_EXT &&
417 colorbufferFormat != GL_RGBA4 &&
418 colorbufferFormat != GL_RGB5_A1 &&
419 colorbufferFormat != GL_RGBA8_OES)
420 {
Geoff Langb1196682014-07-23 13:47:29 -0400421 context->recordError(Error(GL_INVALID_OPERATION));
422 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400423 }
424 break;
425 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400426 if (colorbufferFormat != GL_R8_EXT &&
427 colorbufferFormat != GL_RG8_EXT &&
428 colorbufferFormat != GL_RGB565 &&
429 colorbufferFormat != GL_RGB8_OES &&
430 colorbufferFormat != GL_RGBA4 &&
431 colorbufferFormat != GL_RGB5_A1 &&
432 colorbufferFormat != GL_RGBA8_OES)
433 {
Geoff Langb1196682014-07-23 13:47:29 -0400434 context->recordError(Error(GL_INVALID_OPERATION));
435 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400436 }
437 break;
438 case GL_RED_EXT:
439 if (colorbufferFormat != GL_R8_EXT &&
440 colorbufferFormat != GL_RG8_EXT &&
441 colorbufferFormat != GL_RGB565 &&
442 colorbufferFormat != GL_RGB8_OES &&
443 colorbufferFormat != GL_RGBA4 &&
444 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500445 colorbufferFormat != GL_RGBA8_OES &&
446 colorbufferFormat != GL_R32F &&
447 colorbufferFormat != GL_RG32F &&
448 colorbufferFormat != GL_RGB32F &&
449 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400450 {
Geoff Langb1196682014-07-23 13:47:29 -0400451 context->recordError(Error(GL_INVALID_OPERATION));
452 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400453 }
454 break;
455 case GL_RG_EXT:
456 if (colorbufferFormat != GL_RG8_EXT &&
457 colorbufferFormat != GL_RGB565 &&
458 colorbufferFormat != GL_RGB8_OES &&
459 colorbufferFormat != GL_RGBA4 &&
460 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500461 colorbufferFormat != GL_RGBA8_OES &&
462 colorbufferFormat != GL_RG32F &&
463 colorbufferFormat != GL_RGB32F &&
464 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400465 {
Geoff Langb1196682014-07-23 13:47:29 -0400466 context->recordError(Error(GL_INVALID_OPERATION));
467 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400468 }
469 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400470 case GL_RGB:
471 if (colorbufferFormat != GL_RGB565 &&
472 colorbufferFormat != GL_RGB8_OES &&
473 colorbufferFormat != GL_RGBA4 &&
474 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500475 colorbufferFormat != GL_RGBA8_OES &&
476 colorbufferFormat != GL_RGB32F &&
477 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400478 {
Geoff Langb1196682014-07-23 13:47:29 -0400479 context->recordError(Error(GL_INVALID_OPERATION));
480 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400481 }
482 break;
483 case GL_LUMINANCE_ALPHA:
484 case GL_RGBA:
485 if (colorbufferFormat != GL_RGBA4 &&
486 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500487 colorbufferFormat != GL_RGBA8_OES &&
488 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400489 {
Geoff Langb1196682014-07-23 13:47:29 -0400490 context->recordError(Error(GL_INVALID_OPERATION));
491 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400492 }
493 break;
494 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
495 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
496 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
497 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langb1196682014-07-23 13:47:29 -0400498 context->recordError(Error(GL_INVALID_OPERATION));
499 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400500 case GL_DEPTH_COMPONENT:
501 case GL_DEPTH_STENCIL_OES:
Geoff Langb1196682014-07-23 13:47:29 -0400502 context->recordError(Error(GL_INVALID_OPERATION));
503 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400504 default:
Geoff Langb1196682014-07-23 13:47:29 -0400505 context->recordError(Error(GL_INVALID_OPERATION));
506 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400507 }
Jamie Madillbc393df2015-01-29 13:46:07 -0500508
509 if (internalFormatInfo.type == GL_FLOAT &&
510 !context->getExtensions().textureFloat)
511 {
512 context->recordError(Error(GL_INVALID_OPERATION));
513 return false;
514 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400515 }
516 else
517 {
518 switch (internalformat)
519 {
520 case GL_ALPHA:
521 if (colorbufferFormat != GL_ALPHA8_EXT &&
522 colorbufferFormat != GL_RGBA4 &&
523 colorbufferFormat != GL_RGB5_A1 &&
524 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500525 colorbufferFormat != GL_RGBA8_OES &&
526 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400527 {
Geoff Langb1196682014-07-23 13:47:29 -0400528 context->recordError(Error(GL_INVALID_OPERATION));
529 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400530 }
531 break;
532 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400533 if (colorbufferFormat != GL_R8_EXT &&
534 colorbufferFormat != GL_RG8_EXT &&
535 colorbufferFormat != GL_RGB565 &&
536 colorbufferFormat != GL_RGB8_OES &&
537 colorbufferFormat != GL_RGBA4 &&
538 colorbufferFormat != GL_RGB5_A1 &&
539 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500540 colorbufferFormat != GL_RGBA8_OES &&
541 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400542 {
Geoff Langb1196682014-07-23 13:47:29 -0400543 context->recordError(Error(GL_INVALID_OPERATION));
544 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400545 }
546 break;
547 case GL_RED_EXT:
548 if (colorbufferFormat != GL_R8_EXT &&
549 colorbufferFormat != GL_RG8_EXT &&
550 colorbufferFormat != GL_RGB565 &&
551 colorbufferFormat != GL_RGB8_OES &&
552 colorbufferFormat != GL_RGBA4 &&
553 colorbufferFormat != GL_RGB5_A1 &&
554 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500555 colorbufferFormat != GL_RGBA8_OES &&
556 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400557 {
Geoff Langb1196682014-07-23 13:47:29 -0400558 context->recordError(Error(GL_INVALID_OPERATION));
559 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400560 }
561 break;
562 case GL_RG_EXT:
563 if (colorbufferFormat != GL_RG8_EXT &&
564 colorbufferFormat != GL_RGB565 &&
565 colorbufferFormat != GL_RGB8_OES &&
566 colorbufferFormat != GL_RGBA4 &&
567 colorbufferFormat != GL_RGB5_A1 &&
568 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500569 colorbufferFormat != GL_RGBA8_OES &&
570 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400571 {
Geoff Langb1196682014-07-23 13:47:29 -0400572 context->recordError(Error(GL_INVALID_OPERATION));
573 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400574 }
575 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400576 case GL_RGB:
577 if (colorbufferFormat != GL_RGB565 &&
578 colorbufferFormat != GL_RGB8_OES &&
579 colorbufferFormat != GL_RGBA4 &&
580 colorbufferFormat != GL_RGB5_A1 &&
581 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500582 colorbufferFormat != GL_RGBA8_OES &&
583 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400584 {
Geoff Langb1196682014-07-23 13:47:29 -0400585 context->recordError(Error(GL_INVALID_OPERATION));
586 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400587 }
588 break;
589 case GL_LUMINANCE_ALPHA:
590 case GL_RGBA:
591 if (colorbufferFormat != GL_RGBA4 &&
592 colorbufferFormat != GL_RGB5_A1 &&
593 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500594 colorbufferFormat != GL_RGBA8_OES &&
595 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400596 {
Geoff Langb1196682014-07-23 13:47:29 -0400597 context->recordError(Error(GL_INVALID_OPERATION));
598 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400599 }
600 break;
601 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
602 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400603 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400604 {
Geoff Langb1196682014-07-23 13:47:29 -0400605 context->recordError(Error(GL_INVALID_OPERATION));
606 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400607 }
608 else
609 {
Geoff Langb1196682014-07-23 13:47:29 -0400610 context->recordError(Error(GL_INVALID_ENUM));
611 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400612 }
613 break;
614 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400615 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400616 {
Geoff Langb1196682014-07-23 13:47:29 -0400617 context->recordError(Error(GL_INVALID_OPERATION));
618 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400619 }
620 else
621 {
Geoff Langb1196682014-07-23 13:47:29 -0400622 context->recordError(Error(GL_INVALID_ENUM));
623 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400624 }
625 break;
626 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400627 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400628 {
Geoff Langb1196682014-07-23 13:47:29 -0400629 context->recordError(Error(GL_INVALID_OPERATION));
630 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400631 }
632 else
633 {
Geoff Langb1196682014-07-23 13:47:29 -0400634 context->recordError(Error(GL_INVALID_ENUM));
635 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400636 }
637 break;
638 case GL_DEPTH_COMPONENT:
639 case GL_DEPTH_COMPONENT16:
640 case GL_DEPTH_COMPONENT32_OES:
641 case GL_DEPTH_STENCIL_OES:
642 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400643 if (context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400644 {
Geoff Langb1196682014-07-23 13:47:29 -0400645 context->recordError(Error(GL_INVALID_OPERATION));
646 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400647 }
648 else
649 {
Geoff Langb1196682014-07-23 13:47:29 -0400650 context->recordError(Error(GL_INVALID_ENUM));
651 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400652 }
653 default:
Geoff Langb1196682014-07-23 13:47:29 -0400654 context->recordError(Error(GL_INVALID_ENUM));
655 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400656 }
657 }
658
Geoff Lang784a8fd2013-09-24 12:33:16 -0400659 // If width or height is zero, it is a no-op. Return false without setting an error.
660 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400661}
662
Geoff Langb1196682014-07-23 13:47:29 -0400663bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400664 GLsizei width, GLsizei height)
665{
666 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
667 {
Geoff Langb1196682014-07-23 13:47:29 -0400668 context->recordError(Error(GL_INVALID_ENUM));
669 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400670 }
671
672 if (width < 1 || height < 1 || levels < 1)
673 {
Geoff Langb1196682014-07-23 13:47:29 -0400674 context->recordError(Error(GL_INVALID_VALUE));
675 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400676 }
677
678 if (target == GL_TEXTURE_CUBE_MAP && width != height)
679 {
Geoff Langb1196682014-07-23 13:47:29 -0400680 context->recordError(Error(GL_INVALID_VALUE));
681 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400682 }
683
684 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
685 {
Geoff Langb1196682014-07-23 13:47:29 -0400686 context->recordError(Error(GL_INVALID_OPERATION));
687 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400688 }
689
Geoff Lang5d601382014-07-22 15:14:06 -0400690 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
691 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400692 {
Geoff Langb1196682014-07-23 13:47:29 -0400693 context->recordError(Error(GL_INVALID_ENUM));
694 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400695 }
696
Geoff Langaae65a42014-05-26 12:43:44 -0400697 const gl::Caps &caps = context->getCaps();
698
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400699 switch (target)
700 {
701 case GL_TEXTURE_2D:
Geoff Langaae65a42014-05-26 12:43:44 -0400702 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
703 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400704 {
Geoff Langb1196682014-07-23 13:47:29 -0400705 context->recordError(Error(GL_INVALID_VALUE));
706 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400707 }
708 break;
709 case GL_TEXTURE_CUBE_MAP:
Geoff Langaae65a42014-05-26 12:43:44 -0400710 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
711 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400712 {
Geoff Langb1196682014-07-23 13:47:29 -0400713 context->recordError(Error(GL_INVALID_VALUE));
714 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400715 }
716 break;
717 default:
Geoff Langb1196682014-07-23 13:47:29 -0400718 context->recordError(Error(GL_INVALID_ENUM));
719 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400720 }
721
Geoff Langc0b9ef42014-07-02 10:02:37 -0400722 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400723 {
724 if (!gl::isPow2(width) || !gl::isPow2(height))
725 {
Geoff Langb1196682014-07-23 13:47:29 -0400726 context->recordError(Error(GL_INVALID_OPERATION));
727 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400728 }
729 }
730
731 switch (internalformat)
732 {
733 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
734 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400735 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400736 {
Geoff Langb1196682014-07-23 13:47:29 -0400737 context->recordError(Error(GL_INVALID_ENUM));
738 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400739 }
740 break;
741 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400742 if (!context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400743 {
Geoff Langb1196682014-07-23 13:47:29 -0400744 context->recordError(Error(GL_INVALID_ENUM));
745 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400746 }
747 break;
748 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400749 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400750 {
Geoff Langb1196682014-07-23 13:47:29 -0400751 context->recordError(Error(GL_INVALID_ENUM));
752 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400753 }
754 break;
755 case GL_RGBA32F_EXT:
756 case GL_RGB32F_EXT:
757 case GL_ALPHA32F_EXT:
758 case GL_LUMINANCE32F_EXT:
759 case GL_LUMINANCE_ALPHA32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400760 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400761 {
Geoff Langb1196682014-07-23 13:47:29 -0400762 context->recordError(Error(GL_INVALID_ENUM));
763 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400764 }
765 break;
766 case GL_RGBA16F_EXT:
767 case GL_RGB16F_EXT:
768 case GL_ALPHA16F_EXT:
769 case GL_LUMINANCE16F_EXT:
770 case GL_LUMINANCE_ALPHA16F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400771 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400772 {
Geoff Langb1196682014-07-23 13:47:29 -0400773 context->recordError(Error(GL_INVALID_ENUM));
774 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400775 }
776 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400777 case GL_R8_EXT:
778 case GL_RG8_EXT:
779 case GL_R16F_EXT:
780 case GL_RG16F_EXT:
781 case GL_R32F_EXT:
782 case GL_RG32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400783 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400784 {
Geoff Langb1196682014-07-23 13:47:29 -0400785 context->recordError(Error(GL_INVALID_ENUM));
786 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400787 }
788 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400789 case GL_DEPTH_COMPONENT16:
790 case GL_DEPTH_COMPONENT32_OES:
791 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400792 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400793 {
Geoff Langb1196682014-07-23 13:47:29 -0400794 context->recordError(Error(GL_INVALID_ENUM));
795 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400796 }
797 if (target != GL_TEXTURE_2D)
798 {
Geoff Langb1196682014-07-23 13:47:29 -0400799 context->recordError(Error(GL_INVALID_OPERATION));
800 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400801 }
802 // ANGLE_depth_texture only supports 1-level textures
803 if (levels != 1)
804 {
Geoff Langb1196682014-07-23 13:47:29 -0400805 context->recordError(Error(GL_INVALID_OPERATION));
806 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400807 }
808 break;
809 default:
810 break;
811 }
812
Geoff Lang691e58c2014-12-19 17:03:25 -0500813 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400814 if (!texture || texture->id() == 0)
815 {
Geoff Langb1196682014-07-23 13:47:29 -0400816 context->recordError(Error(GL_INVALID_OPERATION));
817 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400818 }
819
Geoff Lang69cce582015-09-17 13:20:36 -0400820 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400821 {
Geoff Langb1196682014-07-23 13:47:29 -0400822 context->recordError(Error(GL_INVALID_OPERATION));
823 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400824 }
825
826 return true;
827}
828
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400829// check for combinations of format and type that are valid for ReadPixels
Geoff Langb1196682014-07-23 13:47:29 -0400830bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400831{
832 switch (format)
833 {
834 case GL_RGBA:
835 switch (type)
836 {
837 case GL_UNSIGNED_BYTE:
838 break;
839 default:
840 return false;
841 }
842 break;
843 case GL_BGRA_EXT:
844 switch (type)
845 {
846 case GL_UNSIGNED_BYTE:
847 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
848 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
849 break;
850 default:
851 return false;
852 }
853 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400854 case GL_RG_EXT:
855 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400856 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400857 {
858 return false;
859 }
860 switch (type)
861 {
862 case GL_UNSIGNED_BYTE:
863 break;
864 default:
865 return false;
866 }
867 break;
868
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400869 default:
870 return false;
871 }
872 return true;
873}
874
Austin Kinross08332632015-05-05 13:35:47 -0700875bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
876 const GLenum *attachments)
877{
878 bool defaultFramebuffer = false;
879
880 switch (target)
881 {
882 case GL_FRAMEBUFFER:
883 defaultFramebuffer = (context->getState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
884 break;
885 default:
886 context->recordError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
887 return false;
888 }
889
890 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
891}
892
Dian Xiangbf18ed02015-09-11 10:50:04 -0700893bool ValidateDrawBuffers(Context *context, GLsizei n, const GLenum *bufs)
894{
895 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
896 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
897 {
898 context->recordError(
899 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
900 return false;
901 }
902
903 ASSERT(context->getState().getDrawFramebuffer());
904 GLuint frameBufferId = context->getState().getDrawFramebuffer()->id();
905 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
906
907 // This should come first before the check for the default frame buffer
908 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
909 // rather than INVALID_OPERATION
910 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
911 {
912 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
913
914 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
915 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0_EXT ||
916 bufs[colorAttachment] >= maxColorAttachment))
917 {
918 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
919 // In the 3.0 specs, the error should return GL_INVALID_OPERATION.
920 // When we move to 3.1 specs, we should change the error to be GL_INVALID_ENUM
921 context->recordError(Error(GL_INVALID_OPERATION, "Invalid buffer value"));
922 return false;
923 }
924 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
925 frameBufferId != 0)
926 {
927 // INVALID_OPERATION-GL is bound to buffer and ith argument
928 // is not COLOR_ATTACHMENTi or NONE
929 context->recordError(
930 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
931 return false;
932 }
933 }
934
935 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
936 // and n is not 1 or bufs is bound to value other than BACK and NONE
937 if (frameBufferId == 0)
938 {
939 if (n != 1)
940 {
941 context->recordError(Error(GL_INVALID_OPERATION,
942 "n must be 1 when GL is bound to the default framebuffer"));
943 return false;
944 }
945
946 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
947 {
948 context->recordError(Error(
949 GL_INVALID_OPERATION,
950 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
951 return false;
952 }
953 }
954
955 return true;
956}
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400957}