blob: e5c3da5eb505d671c559bd3831fba06763ea084a [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 {
113 if (texture->isImmutable())
114 {
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 Langa9be0dc2014-12-17 12:34:40 -0500127 GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat;
128 const InternalFormat &actualFormatInfo = GetInternalFormatInfo(actualInternalFormat);
129
130 if (isCompressed != actualFormatInfo.compressed)
131 {
132 context->recordError(Error(GL_INVALID_OPERATION));
133 return false;
134 }
135
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400136 if (isCompressed)
137 {
Geoff Langd4f180b2013-09-24 13:57:44 -0400138 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
139 {
Geoff Langb1196682014-07-23 13:47:29 -0400140 context->recordError(Error(GL_INVALID_OPERATION));
141 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400142 }
143
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400144 switch (actualInternalFormat)
145 {
146 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
147 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400148 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400149 {
Geoff Langb1196682014-07-23 13:47:29 -0400150 context->recordError(Error(GL_INVALID_ENUM));
151 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400152 }
153 break;
154 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400155 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400156 {
Geoff Langb1196682014-07-23 13:47:29 -0400157 context->recordError(Error(GL_INVALID_ENUM));
158 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400159 }
160 break;
161 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langb1196682014-07-23 13:47:29 -0400162 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400163 {
Geoff Langb1196682014-07-23 13:47:29 -0400164 context->recordError(Error(GL_INVALID_ENUM));
165 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400166 }
167 break;
168 default:
Geoff Langb1196682014-07-23 13:47:29 -0400169 context->recordError(Error(GL_INVALID_ENUM));
170 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400171 }
172 }
173 else
174 {
175 // validate <type> by itself (used as secondary key below)
176 switch (type)
177 {
178 case GL_UNSIGNED_BYTE:
179 case GL_UNSIGNED_SHORT_5_6_5:
180 case GL_UNSIGNED_SHORT_4_4_4_4:
181 case GL_UNSIGNED_SHORT_5_5_5_1:
182 case GL_UNSIGNED_SHORT:
183 case GL_UNSIGNED_INT:
184 case GL_UNSIGNED_INT_24_8_OES:
185 case GL_HALF_FLOAT_OES:
186 case GL_FLOAT:
187 break;
188 default:
Geoff Langb1196682014-07-23 13:47:29 -0400189 context->recordError(Error(GL_INVALID_ENUM));
190 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400191 }
192
193 // validate <format> + <type> combinations
194 // - invalid <format> -> sets INVALID_ENUM
195 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
196 switch (format)
197 {
198 case GL_ALPHA:
199 case GL_LUMINANCE:
200 case GL_LUMINANCE_ALPHA:
201 switch (type)
202 {
203 case GL_UNSIGNED_BYTE:
204 case GL_FLOAT:
205 case GL_HALF_FLOAT_OES:
206 break;
Geoff Langb1196682014-07-23 13:47:29 -0400207 default:
208 context->recordError(Error(GL_INVALID_OPERATION));
209 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400210 }
211 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400212 case GL_RED:
Geoff Langcec35902014-04-16 10:52:36 -0400213 case GL_RG:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400214 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400215 {
Geoff Langb1196682014-07-23 13:47:29 -0400216 context->recordError(Error(GL_INVALID_ENUM));
217 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400218 }
219 switch (type)
220 {
221 case GL_UNSIGNED_BYTE:
222 case GL_FLOAT:
223 case GL_HALF_FLOAT_OES:
224 break;
225 default:
Geoff Langb1196682014-07-23 13:47:29 -0400226 context->recordError(Error(GL_INVALID_OPERATION));
227 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400228 }
229 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400230 case GL_RGB:
231 switch (type)
232 {
233 case GL_UNSIGNED_BYTE:
234 case GL_UNSIGNED_SHORT_5_6_5:
235 case GL_FLOAT:
236 case GL_HALF_FLOAT_OES:
237 break;
238 default:
Geoff Langb1196682014-07-23 13:47:29 -0400239 context->recordError(Error(GL_INVALID_OPERATION));
240 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400241 }
242 break;
243 case GL_RGBA:
244 switch (type)
245 {
246 case GL_UNSIGNED_BYTE:
247 case GL_UNSIGNED_SHORT_4_4_4_4:
248 case GL_UNSIGNED_SHORT_5_5_5_1:
249 case GL_FLOAT:
250 case GL_HALF_FLOAT_OES:
251 break;
252 default:
Geoff Langb1196682014-07-23 13:47:29 -0400253 context->recordError(Error(GL_INVALID_OPERATION));
254 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400255 }
256 break;
257 case GL_BGRA_EXT:
258 switch (type)
259 {
260 case GL_UNSIGNED_BYTE:
261 break;
262 default:
Geoff Langb1196682014-07-23 13:47:29 -0400263 context->recordError(Error(GL_INVALID_OPERATION));
264 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400265 }
266 break;
Geoff Lang05b05022014-06-11 15:31:45 -0400267 case GL_SRGB_EXT:
268 case GL_SRGB_ALPHA_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400269 if (!context->getExtensions().sRGB)
Geoff Lang05b05022014-06-11 15:31:45 -0400270 {
Geoff Langb1196682014-07-23 13:47:29 -0400271 context->recordError(Error(GL_INVALID_ENUM));
272 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400273 }
274 switch (type)
275 {
276 case GL_UNSIGNED_BYTE:
277 break;
278 default:
Geoff Langb1196682014-07-23 13:47:29 -0400279 context->recordError(Error(GL_INVALID_OPERATION));
280 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400281 }
282 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400283 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
284 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
285 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
286 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
287 break;
288 case GL_DEPTH_COMPONENT:
289 switch (type)
290 {
291 case GL_UNSIGNED_SHORT:
292 case GL_UNSIGNED_INT:
293 break;
294 default:
Geoff Langb1196682014-07-23 13:47:29 -0400295 context->recordError(Error(GL_INVALID_OPERATION));
296 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400297 }
298 break;
299 case GL_DEPTH_STENCIL_OES:
300 switch (type)
301 {
302 case GL_UNSIGNED_INT_24_8_OES:
303 break;
304 default:
Geoff Langb1196682014-07-23 13:47:29 -0400305 context->recordError(Error(GL_INVALID_OPERATION));
306 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400307 }
308 break;
309 default:
Geoff Langb1196682014-07-23 13:47:29 -0400310 context->recordError(Error(GL_INVALID_ENUM));
311 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400312 }
313
314 switch (format)
315 {
316 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
317 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400318 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400319 {
Geoff Langb1196682014-07-23 13:47:29 -0400320 context->recordError(Error(GL_INVALID_OPERATION));
321 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400322 }
323 else
324 {
Geoff Langb1196682014-07-23 13:47:29 -0400325 context->recordError(Error(GL_INVALID_ENUM));
326 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400327 }
328 break;
329 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400330 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400331 {
Geoff Langb1196682014-07-23 13:47:29 -0400332 context->recordError(Error(GL_INVALID_OPERATION));
333 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400334 }
335 else
336 {
Geoff Langb1196682014-07-23 13:47:29 -0400337 context->recordError(Error(GL_INVALID_ENUM));
338 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400339 }
340 break;
341 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400342 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400343 {
Geoff Langb1196682014-07-23 13:47:29 -0400344 context->recordError(Error(GL_INVALID_OPERATION));
345 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400346 }
347 else
348 {
Geoff Langb1196682014-07-23 13:47:29 -0400349 context->recordError(Error(GL_INVALID_ENUM));
350 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400351 }
352 break;
353 case GL_DEPTH_COMPONENT:
354 case GL_DEPTH_STENCIL_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400355 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400356 {
Geoff Langb1196682014-07-23 13:47:29 -0400357 context->recordError(Error(GL_INVALID_VALUE));
358 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400359 }
360 if (target != GL_TEXTURE_2D)
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 // OES_depth_texture supports loading depth data and multiple levels,
366 // but ANGLE_depth_texture does not
367 if (pixels != NULL || level != 0)
368 {
Geoff Langb1196682014-07-23 13:47:29 -0400369 context->recordError(Error(GL_INVALID_OPERATION));
370 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400371 }
372 break;
373 default:
374 break;
375 }
376
377 if (type == GL_FLOAT)
378 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400379 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400380 {
Geoff Langb1196682014-07-23 13:47:29 -0400381 context->recordError(Error(GL_INVALID_ENUM));
382 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400383 }
384 }
385 else if (type == GL_HALF_FLOAT_OES)
386 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400387 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400388 {
Geoff Langb1196682014-07-23 13:47:29 -0400389 context->recordError(Error(GL_INVALID_ENUM));
390 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400391 }
392 }
393 }
394
395 return true;
396}
397
398
399
Geoff Langb1196682014-07-23 13:47:29 -0400400bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400401 GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height,
402 GLint border)
403{
Jamie Madill560a8d82014-05-21 13:06:20 -0400404 GLenum textureInternalFormat = GL_NONE;
Shannon Woods4dfed832014-03-17 20:03:39 -0400405
Jamie Madill560a8d82014-05-21 13:06:20 -0400406 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
407 xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400408 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400409 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400410 }
411
Shannon Woods53a94a82014-06-24 15:20:36 -0400412 gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400413 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat();
Geoff Lang5d601382014-07-22 15:14:06 -0400414 GLenum textureFormat = gl::GetInternalFormatInfo(textureInternalFormat).format;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400415
416 // [OpenGL ES 2.0.24] table 3.9
417 if (isSubImage)
418 {
419 switch (textureFormat)
420 {
421 case GL_ALPHA:
422 if (colorbufferFormat != GL_ALPHA8_EXT &&
423 colorbufferFormat != GL_RGBA4 &&
424 colorbufferFormat != GL_RGB5_A1 &&
425 colorbufferFormat != GL_RGBA8_OES)
426 {
Geoff Langb1196682014-07-23 13:47:29 -0400427 context->recordError(Error(GL_INVALID_OPERATION));
428 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400429 }
430 break;
431 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400432 if (colorbufferFormat != GL_R8_EXT &&
433 colorbufferFormat != GL_RG8_EXT &&
434 colorbufferFormat != GL_RGB565 &&
435 colorbufferFormat != GL_RGB8_OES &&
436 colorbufferFormat != GL_RGBA4 &&
437 colorbufferFormat != GL_RGB5_A1 &&
438 colorbufferFormat != GL_RGBA8_OES)
439 {
Geoff Langb1196682014-07-23 13:47:29 -0400440 context->recordError(Error(GL_INVALID_OPERATION));
441 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400442 }
443 break;
444 case GL_RED_EXT:
445 if (colorbufferFormat != GL_R8_EXT &&
446 colorbufferFormat != GL_RG8_EXT &&
447 colorbufferFormat != GL_RGB565 &&
448 colorbufferFormat != GL_RGB8_OES &&
449 colorbufferFormat != GL_RGBA4 &&
450 colorbufferFormat != GL_RGB5_A1 &&
451 colorbufferFormat != GL_RGBA8_OES)
452 {
Geoff Langb1196682014-07-23 13:47:29 -0400453 context->recordError(Error(GL_INVALID_OPERATION));
454 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400455 }
456 break;
457 case GL_RG_EXT:
458 if (colorbufferFormat != GL_RG8_EXT &&
459 colorbufferFormat != GL_RGB565 &&
460 colorbufferFormat != GL_RGB8_OES &&
461 colorbufferFormat != GL_RGBA4 &&
462 colorbufferFormat != GL_RGB5_A1 &&
463 colorbufferFormat != GL_RGBA8_OES)
464 {
Geoff Langb1196682014-07-23 13:47:29 -0400465 context->recordError(Error(GL_INVALID_OPERATION));
466 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400467 }
468 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400469 case GL_RGB:
470 if (colorbufferFormat != GL_RGB565 &&
471 colorbufferFormat != GL_RGB8_OES &&
472 colorbufferFormat != GL_RGBA4 &&
473 colorbufferFormat != GL_RGB5_A1 &&
474 colorbufferFormat != GL_RGBA8_OES)
475 {
Geoff Langb1196682014-07-23 13:47:29 -0400476 context->recordError(Error(GL_INVALID_OPERATION));
477 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400478 }
479 break;
480 case GL_LUMINANCE_ALPHA:
481 case GL_RGBA:
482 if (colorbufferFormat != GL_RGBA4 &&
483 colorbufferFormat != GL_RGB5_A1 &&
484 colorbufferFormat != GL_RGBA8_OES)
485 {
Geoff Langb1196682014-07-23 13:47:29 -0400486 context->recordError(Error(GL_INVALID_OPERATION));
487 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400488 }
489 break;
490 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
491 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
492 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
493 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langb1196682014-07-23 13:47:29 -0400494 context->recordError(Error(GL_INVALID_OPERATION));
495 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400496 case GL_DEPTH_COMPONENT:
497 case GL_DEPTH_STENCIL_OES:
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 default:
Geoff Langb1196682014-07-23 13:47:29 -0400501 context->recordError(Error(GL_INVALID_OPERATION));
502 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400503 }
504 }
505 else
506 {
507 switch (internalformat)
508 {
509 case GL_ALPHA:
510 if (colorbufferFormat != GL_ALPHA8_EXT &&
511 colorbufferFormat != GL_RGBA4 &&
512 colorbufferFormat != GL_RGB5_A1 &&
513 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500514 colorbufferFormat != GL_RGBA8_OES &&
515 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400516 {
Geoff Langb1196682014-07-23 13:47:29 -0400517 context->recordError(Error(GL_INVALID_OPERATION));
518 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400519 }
520 break;
521 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400522 if (colorbufferFormat != GL_R8_EXT &&
523 colorbufferFormat != GL_RG8_EXT &&
524 colorbufferFormat != GL_RGB565 &&
525 colorbufferFormat != GL_RGB8_OES &&
526 colorbufferFormat != GL_RGBA4 &&
527 colorbufferFormat != GL_RGB5_A1 &&
528 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500529 colorbufferFormat != GL_RGBA8_OES &&
530 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400531 {
Geoff Langb1196682014-07-23 13:47:29 -0400532 context->recordError(Error(GL_INVALID_OPERATION));
533 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400534 }
535 break;
536 case GL_RED_EXT:
537 if (colorbufferFormat != GL_R8_EXT &&
538 colorbufferFormat != GL_RG8_EXT &&
539 colorbufferFormat != GL_RGB565 &&
540 colorbufferFormat != GL_RGB8_OES &&
541 colorbufferFormat != GL_RGBA4 &&
542 colorbufferFormat != GL_RGB5_A1 &&
543 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500544 colorbufferFormat != GL_RGBA8_OES &&
545 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400546 {
Geoff Langb1196682014-07-23 13:47:29 -0400547 context->recordError(Error(GL_INVALID_OPERATION));
548 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400549 }
550 break;
551 case GL_RG_EXT:
552 if (colorbufferFormat != GL_RG8_EXT &&
553 colorbufferFormat != GL_RGB565 &&
554 colorbufferFormat != GL_RGB8_OES &&
555 colorbufferFormat != GL_RGBA4 &&
556 colorbufferFormat != GL_RGB5_A1 &&
557 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500558 colorbufferFormat != GL_RGBA8_OES &&
559 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400560 {
Geoff Langb1196682014-07-23 13:47:29 -0400561 context->recordError(Error(GL_INVALID_OPERATION));
562 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400563 }
564 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400565 case GL_RGB:
566 if (colorbufferFormat != GL_RGB565 &&
567 colorbufferFormat != GL_RGB8_OES &&
568 colorbufferFormat != GL_RGBA4 &&
569 colorbufferFormat != GL_RGB5_A1 &&
570 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500571 colorbufferFormat != GL_RGBA8_OES &&
572 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400573 {
Geoff Langb1196682014-07-23 13:47:29 -0400574 context->recordError(Error(GL_INVALID_OPERATION));
575 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400576 }
577 break;
578 case GL_LUMINANCE_ALPHA:
579 case GL_RGBA:
580 if (colorbufferFormat != GL_RGBA4 &&
581 colorbufferFormat != GL_RGB5_A1 &&
582 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500583 colorbufferFormat != GL_RGBA8_OES &&
584 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400585 {
Geoff Langb1196682014-07-23 13:47:29 -0400586 context->recordError(Error(GL_INVALID_OPERATION));
587 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400588 }
589 break;
590 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
591 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400592 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400593 {
Geoff Langb1196682014-07-23 13:47:29 -0400594 context->recordError(Error(GL_INVALID_OPERATION));
595 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400596 }
597 else
598 {
Geoff Langb1196682014-07-23 13:47:29 -0400599 context->recordError(Error(GL_INVALID_ENUM));
600 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400601 }
602 break;
603 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400604 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400605 {
Geoff Langb1196682014-07-23 13:47:29 -0400606 context->recordError(Error(GL_INVALID_OPERATION));
607 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400608 }
609 else
610 {
Geoff Langb1196682014-07-23 13:47:29 -0400611 context->recordError(Error(GL_INVALID_ENUM));
612 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400613 }
614 break;
615 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400616 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400617 {
Geoff Langb1196682014-07-23 13:47:29 -0400618 context->recordError(Error(GL_INVALID_OPERATION));
619 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400620 }
621 else
622 {
Geoff Langb1196682014-07-23 13:47:29 -0400623 context->recordError(Error(GL_INVALID_ENUM));
624 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400625 }
626 break;
627 case GL_DEPTH_COMPONENT:
628 case GL_DEPTH_COMPONENT16:
629 case GL_DEPTH_COMPONENT32_OES:
630 case GL_DEPTH_STENCIL_OES:
631 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400632 if (context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400633 {
Geoff Langb1196682014-07-23 13:47:29 -0400634 context->recordError(Error(GL_INVALID_OPERATION));
635 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400636 }
637 else
638 {
Geoff Langb1196682014-07-23 13:47:29 -0400639 context->recordError(Error(GL_INVALID_ENUM));
640 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400641 }
642 default:
Geoff Langb1196682014-07-23 13:47:29 -0400643 context->recordError(Error(GL_INVALID_ENUM));
644 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400645 }
646 }
647
Geoff Lang784a8fd2013-09-24 12:33:16 -0400648 // If width or height is zero, it is a no-op. Return false without setting an error.
649 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400650}
651
Geoff Langb1196682014-07-23 13:47:29 -0400652bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400653 GLsizei width, GLsizei height)
654{
655 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
656 {
Geoff Langb1196682014-07-23 13:47:29 -0400657 context->recordError(Error(GL_INVALID_ENUM));
658 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400659 }
660
661 if (width < 1 || height < 1 || levels < 1)
662 {
Geoff Langb1196682014-07-23 13:47:29 -0400663 context->recordError(Error(GL_INVALID_VALUE));
664 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400665 }
666
667 if (target == GL_TEXTURE_CUBE_MAP && width != height)
668 {
Geoff Langb1196682014-07-23 13:47:29 -0400669 context->recordError(Error(GL_INVALID_VALUE));
670 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400671 }
672
673 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
674 {
Geoff Langb1196682014-07-23 13:47:29 -0400675 context->recordError(Error(GL_INVALID_OPERATION));
676 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400677 }
678
Geoff Lang5d601382014-07-22 15:14:06 -0400679 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
680 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400681 {
Geoff Langb1196682014-07-23 13:47:29 -0400682 context->recordError(Error(GL_INVALID_ENUM));
683 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400684 }
685
Geoff Langaae65a42014-05-26 12:43:44 -0400686 const gl::Caps &caps = context->getCaps();
687
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400688 switch (target)
689 {
690 case GL_TEXTURE_2D:
Geoff Langaae65a42014-05-26 12:43:44 -0400691 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
692 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400693 {
Geoff Langb1196682014-07-23 13:47:29 -0400694 context->recordError(Error(GL_INVALID_VALUE));
695 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400696 }
697 break;
698 case GL_TEXTURE_CUBE_MAP:
Geoff Langaae65a42014-05-26 12:43:44 -0400699 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
700 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400701 {
Geoff Langb1196682014-07-23 13:47:29 -0400702 context->recordError(Error(GL_INVALID_VALUE));
703 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400704 }
705 break;
706 default:
Geoff Langb1196682014-07-23 13:47:29 -0400707 context->recordError(Error(GL_INVALID_ENUM));
708 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400709 }
710
Geoff Langc0b9ef42014-07-02 10:02:37 -0400711 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400712 {
713 if (!gl::isPow2(width) || !gl::isPow2(height))
714 {
Geoff Langb1196682014-07-23 13:47:29 -0400715 context->recordError(Error(GL_INVALID_OPERATION));
716 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400717 }
718 }
719
720 switch (internalformat)
721 {
722 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
723 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400724 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400725 {
Geoff Langb1196682014-07-23 13:47:29 -0400726 context->recordError(Error(GL_INVALID_ENUM));
727 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400728 }
729 break;
730 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400731 if (!context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400732 {
Geoff Langb1196682014-07-23 13:47:29 -0400733 context->recordError(Error(GL_INVALID_ENUM));
734 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400735 }
736 break;
737 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400738 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400739 {
Geoff Langb1196682014-07-23 13:47:29 -0400740 context->recordError(Error(GL_INVALID_ENUM));
741 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400742 }
743 break;
744 case GL_RGBA32F_EXT:
745 case GL_RGB32F_EXT:
746 case GL_ALPHA32F_EXT:
747 case GL_LUMINANCE32F_EXT:
748 case GL_LUMINANCE_ALPHA32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400749 if (!context->getExtensions().textureFloat)
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_RGBA16F_EXT:
756 case GL_RGB16F_EXT:
757 case GL_ALPHA16F_EXT:
758 case GL_LUMINANCE16F_EXT:
759 case GL_LUMINANCE_ALPHA16F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400760 if (!context->getExtensions().textureHalfFloat)
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;
Geoff Lang632192d2013-10-04 13:40:46 -0400766 case GL_R8_EXT:
767 case GL_RG8_EXT:
768 case GL_R16F_EXT:
769 case GL_RG16F_EXT:
770 case GL_R32F_EXT:
771 case GL_RG32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400772 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400773 {
Geoff Langb1196682014-07-23 13:47:29 -0400774 context->recordError(Error(GL_INVALID_ENUM));
775 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400776 }
777 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400778 case GL_DEPTH_COMPONENT16:
779 case GL_DEPTH_COMPONENT32_OES:
780 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400781 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400782 {
Geoff Langb1196682014-07-23 13:47:29 -0400783 context->recordError(Error(GL_INVALID_ENUM));
784 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400785 }
786 if (target != GL_TEXTURE_2D)
787 {
Geoff Langb1196682014-07-23 13:47:29 -0400788 context->recordError(Error(GL_INVALID_OPERATION));
789 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400790 }
791 // ANGLE_depth_texture only supports 1-level textures
792 if (levels != 1)
793 {
Geoff Langb1196682014-07-23 13:47:29 -0400794 context->recordError(Error(GL_INVALID_OPERATION));
795 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400796 }
797 break;
798 default:
799 break;
800 }
801
Geoff Lang691e58c2014-12-19 17:03:25 -0500802 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400803 if (!texture || texture->id() == 0)
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
809 if (texture->isImmutable())
810 {
Geoff Langb1196682014-07-23 13:47:29 -0400811 context->recordError(Error(GL_INVALID_OPERATION));
812 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400813 }
814
815 return true;
816}
817
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400818// check for combinations of format and type that are valid for ReadPixels
Geoff Langb1196682014-07-23 13:47:29 -0400819bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400820{
821 switch (format)
822 {
823 case GL_RGBA:
824 switch (type)
825 {
826 case GL_UNSIGNED_BYTE:
827 break;
828 default:
829 return false;
830 }
831 break;
832 case GL_BGRA_EXT:
833 switch (type)
834 {
835 case GL_UNSIGNED_BYTE:
836 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
837 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
838 break;
839 default:
840 return false;
841 }
842 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400843 case GL_RG_EXT:
844 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400845 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400846 {
847 return false;
848 }
849 switch (type)
850 {
851 case GL_UNSIGNED_BYTE:
852 break;
853 default:
854 return false;
855 }
856 break;
857
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400858 default:
859 return false;
860 }
861 return true;
862}
863
864}