2 // Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
7 // validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
9 #include "libGLESv2/validationES3.h"
10 #include "libGLESv2/validationES.h"
11 #include "libGLESv2/Context.h"
12 #include "libGLESv2/Texture.h"
13 #include "libGLESv2/Framebuffer.h"
14 #include "libGLESv2/Renderbuffer.h"
15 #include "libGLESv2/formatutils.h"
16 #include "libGLESv2/main.h"
17 #include "libGLESv2/FramebufferAttachment.h"
19 #include "common/mathutil.h"
24 struct ES3FormatCombination
26 GLenum internalFormat;
31 bool operator<(const ES3FormatCombination& a, const ES3FormatCombination& b)
33 return memcmp(&a, &b, sizeof(ES3FormatCombination)) < 0;
36 typedef std::set<ES3FormatCombination> ES3FormatCombinationSet;
38 static inline void InsertES3FormatCombo(ES3FormatCombinationSet *set, GLenum internalFormat, GLenum format, GLenum type)
40 ES3FormatCombination info;
41 info.internalFormat = internalFormat;
47 ES3FormatCombinationSet BuildES3FormatSet()
49 ES3FormatCombinationSet set;
51 // Format combinations from ES 3.0.1 spec, table 3.2
53 // | Internal format | Format | Type |
55 InsertES3FormatCombo(&set, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE );
56 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE );
57 InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE );
58 InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE );
59 InsertES3FormatCombo(&set, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE );
60 InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 );
61 InsertES3FormatCombo(&set, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV );
62 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV );
63 InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 );
64 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT );
65 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT_OES );
66 InsertES3FormatCombo(&set, GL_RGBA32F, GL_RGBA, GL_FLOAT );
67 InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_FLOAT );
68 InsertES3FormatCombo(&set, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE );
69 InsertES3FormatCombo(&set, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE );
70 InsertES3FormatCombo(&set, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT );
71 InsertES3FormatCombo(&set, GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT );
72 InsertES3FormatCombo(&set, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT );
73 InsertES3FormatCombo(&set, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT );
74 InsertES3FormatCombo(&set, GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV );
75 InsertES3FormatCombo(&set, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE );
76 InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE );
77 InsertES3FormatCombo(&set, GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE );
78 InsertES3FormatCombo(&set, GL_RGB8_SNORM, GL_RGB, GL_BYTE );
79 InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 );
80 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV );
81 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV );
82 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT );
83 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT_OES );
84 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT );
85 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT_OES );
86 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT );
87 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT_OES );
88 InsertES3FormatCombo(&set, GL_RGB32F, GL_RGB, GL_FLOAT );
89 InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_FLOAT );
90 InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT );
91 InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_FLOAT );
92 InsertES3FormatCombo(&set, GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE );
93 InsertES3FormatCombo(&set, GL_RGB8I, GL_RGB_INTEGER, GL_BYTE );
94 InsertES3FormatCombo(&set, GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT );
95 InsertES3FormatCombo(&set, GL_RGB16I, GL_RGB_INTEGER, GL_SHORT );
96 InsertES3FormatCombo(&set, GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT );
97 InsertES3FormatCombo(&set, GL_RGB32I, GL_RGB_INTEGER, GL_INT );
98 InsertES3FormatCombo(&set, GL_RG8, GL_RG, GL_UNSIGNED_BYTE );
99 InsertES3FormatCombo(&set, GL_RG8_SNORM, GL_RG, GL_BYTE );
100 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT );
101 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT_OES );
102 InsertES3FormatCombo(&set, GL_RG32F, GL_RG, GL_FLOAT );
103 InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_FLOAT );
104 InsertES3FormatCombo(&set, GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE );
105 InsertES3FormatCombo(&set, GL_RG8I, GL_RG_INTEGER, GL_BYTE );
106 InsertES3FormatCombo(&set, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT );
107 InsertES3FormatCombo(&set, GL_RG16I, GL_RG_INTEGER, GL_SHORT );
108 InsertES3FormatCombo(&set, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT );
109 InsertES3FormatCombo(&set, GL_RG32I, GL_RG_INTEGER, GL_INT );
110 InsertES3FormatCombo(&set, GL_R8, GL_RED, GL_UNSIGNED_BYTE );
111 InsertES3FormatCombo(&set, GL_R8_SNORM, GL_RED, GL_BYTE );
112 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT );
113 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT_OES );
114 InsertES3FormatCombo(&set, GL_R32F, GL_RED, GL_FLOAT );
115 InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_FLOAT );
116 InsertES3FormatCombo(&set, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE );
117 InsertES3FormatCombo(&set, GL_R8I, GL_RED_INTEGER, GL_BYTE );
118 InsertES3FormatCombo(&set, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT );
119 InsertES3FormatCombo(&set, GL_R16I, GL_RED_INTEGER, GL_SHORT );
120 InsertES3FormatCombo(&set, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT );
121 InsertES3FormatCombo(&set, GL_R32I, GL_RED_INTEGER, GL_INT );
124 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE );
125 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 );
126 InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 );
127 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE );
128 InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 );
129 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE );
130 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE );
131 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE );
132 InsertES3FormatCombo(&set, GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE );
133 InsertES3FormatCombo(&set, GL_SRGB_EXT, GL_SRGB_EXT, GL_UNSIGNED_BYTE );
135 // Depth stencil formats
136 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT );
137 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
138 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
139 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT );
140 InsertES3FormatCombo(&set, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 );
141 InsertES3FormatCombo(&set, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
144 InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE );
145 InsertES3FormatCombo(&set, GL_SRGB8, GL_SRGB_EXT, GL_UNSIGNED_BYTE );
147 // From GL_OES_texture_float
148 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT );
149 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT );
150 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_FLOAT );
152 // From GL_OES_texture_half_float
153 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT );
154 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES );
155 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT );
156 InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES );
157 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT );
158 InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES );
160 // From GL_EXT_texture_format_BGRA8888
161 InsertES3FormatCombo(&set, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
163 // From GL_EXT_texture_storage
164 // | Internal format | Format | Type |
166 InsertES3FormatCombo(&set, GL_ALPHA8_EXT, GL_ALPHA, GL_UNSIGNED_BYTE );
167 InsertES3FormatCombo(&set, GL_LUMINANCE8_EXT, GL_LUMINANCE, GL_UNSIGNED_BYTE );
168 InsertES3FormatCombo(&set, GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE );
169 InsertES3FormatCombo(&set, GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT );
170 InsertES3FormatCombo(&set, GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT );
171 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT );
172 InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT );
173 InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT_OES );
174 InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT );
175 InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT_OES );
176 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT );
177 InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES );
179 // From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888
180 InsertES3FormatCombo(&set, GL_BGRA8_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
181 InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT);
182 InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
183 InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT);
184 InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
186 // From GL_ANGLE_depth_texture
187 InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8_OES );
189 // Compressed formats
190 // From ES 3.0.1 spec, table 3.16
191 // | Internal format | Format | Type |
193 InsertES3FormatCombo(&set, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE);
194 InsertES3FormatCombo(&set, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE);
195 InsertES3FormatCombo(&set, GL_COMPRESSED_SIGNED_R11_EAC, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE);
196 InsertES3FormatCombo(&set, GL_COMPRESSED_RG11_EAC, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE);
197 InsertES3FormatCombo(&set, GL_COMPRESSED_SIGNED_RG11_EAC, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE);
198 InsertES3FormatCombo(&set, GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE);
199 InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_ETC2, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE);
200 InsertES3FormatCombo(&set, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE);
201 InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE);
202 InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE);
203 InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE);
206 // From GL_EXT_texture_compression_dxt1
207 InsertES3FormatCombo(&set, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE);
208 InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE);
210 // From GL_ANGLE_texture_compression_dxt3
211 InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE);
213 // From GL_ANGLE_texture_compression_dxt5
214 InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE);
219 static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
221 // Note: dEQP 2013.4 expects an INVALID_VALUE error for TexImage3D with an invalid
222 // internal format. (dEQP-GLES3.functional.negative_api.texture.teximage3d)
223 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
224 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
226 context->recordError(Error(GL_INVALID_ENUM));
230 // The type and format are valid if any supported internal format has that type and format
231 bool formatSupported = false;
232 bool typeSupported = false;
234 static const ES3FormatCombinationSet es3FormatSet = BuildES3FormatSet();
235 for (ES3FormatCombinationSet::const_iterator i = es3FormatSet.begin(); i != es3FormatSet.end(); i++)
237 if (i->format == format || i->type == type)
239 const gl::InternalFormat &info = gl::GetInternalFormatInfo(i->internalFormat);
240 bool supported = info.textureSupport(context->getClientVersion(), context->getExtensions());
241 if (supported && i->type == type)
243 typeSupported = true;
245 if (supported && i->format == format)
247 formatSupported = true;
250 // Early-out if both type and format are supported now
251 if (typeSupported && formatSupported)
258 if (!typeSupported || !formatSupported)
260 context->recordError(Error(GL_INVALID_ENUM));
264 // Check if this is a valid format combination to load texture data
265 ES3FormatCombination searchFormat;
266 searchFormat.internalFormat = internalFormat;
267 searchFormat.format = format;
268 searchFormat.type = type;
270 if (es3FormatSet.find(searchFormat) == es3FormatSet.end())
272 context->recordError(Error(GL_INVALID_OPERATION));
279 bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
280 GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
281 GLint border, GLenum format, GLenum type, const GLvoid *pixels)
283 if (!ValidTexture2DDestinationTarget(context, target))
285 context->recordError(Error(GL_INVALID_ENUM));
289 // Validate image size
290 if (!ValidImageSize(context, target, level, width, height, depth))
292 context->recordError(Error(GL_INVALID_VALUE));
296 // Verify zero border
299 context->recordError(Error(GL_INVALID_VALUE));
303 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
304 std::numeric_limits<GLsizei>::max() - xoffset < width ||
305 std::numeric_limits<GLsizei>::max() - yoffset < height ||
306 std::numeric_limits<GLsizei>::max() - zoffset < depth)
308 context->recordError(Error(GL_INVALID_VALUE));
312 const gl::Caps &caps = context->getCaps();
314 gl::Texture *texture = NULL;
315 bool textureCompressed = false;
316 GLenum textureInternalFormat = GL_NONE;
317 GLint textureLevelWidth = 0;
318 GLint textureLevelHeight = 0;
319 GLint textureLevelDepth = 0;
324 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
325 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
327 context->recordError(Error(GL_INVALID_VALUE));
331 gl::Texture2D *texture2d = context->getTexture2D();
334 textureCompressed = texture2d->isCompressed(level);
335 textureInternalFormat = texture2d->getInternalFormat(level);
336 textureLevelWidth = texture2d->getWidth(level);
337 textureLevelHeight = texture2d->getHeight(level);
338 textureLevelDepth = 1;
344 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
345 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
346 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
347 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
348 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
349 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
351 if (!isSubImage && width != height)
353 context->recordError(Error(GL_INVALID_VALUE));
357 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
359 context->recordError(Error(GL_INVALID_VALUE));
363 gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
366 textureCompressed = textureCube->isCompressed(target, level);
367 textureInternalFormat = textureCube->getInternalFormat(target, level);
368 textureLevelWidth = textureCube->getWidth(target, level);
369 textureLevelHeight = textureCube->getHeight(target, level);
370 textureLevelDepth = 1;
371 texture = textureCube;
378 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
379 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
380 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
382 context->recordError(Error(GL_INVALID_VALUE));
386 gl::Texture3D *texture3d = context->getTexture3D();
389 textureCompressed = texture3d->isCompressed(level);
390 textureInternalFormat = texture3d->getInternalFormat(level);
391 textureLevelWidth = texture3d->getWidth(level);
392 textureLevelHeight = texture3d->getHeight(level);
393 textureLevelDepth = texture3d->getDepth(level);
399 case GL_TEXTURE_2D_ARRAY:
401 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
402 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
403 static_cast<GLuint>(depth) > (caps.maxArrayTextureLayers >> level))
405 context->recordError(Error(GL_INVALID_VALUE));
409 gl::Texture2DArray *texture2darray = context->getTexture2DArray();
412 textureCompressed = texture2darray->isCompressed(level);
413 textureInternalFormat = texture2darray->getInternalFormat(level);
414 textureLevelWidth = texture2darray->getWidth(level);
415 textureLevelHeight = texture2darray->getHeight(level);
416 textureLevelDepth = texture2darray->getLayers(level);
417 texture = texture2darray;
423 context->recordError(Error(GL_INVALID_ENUM));
429 context->recordError(Error(GL_INVALID_OPERATION));
433 if (texture->isImmutable() && !isSubImage)
435 context->recordError(Error(GL_INVALID_OPERATION));
439 // Validate texture formats
440 GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
441 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
444 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
446 context->recordError(Error(GL_INVALID_OPERATION));
450 if (!actualFormatInfo.compressed)
452 context->recordError(Error(GL_INVALID_ENUM));
456 if (target == GL_TEXTURE_3D)
458 context->recordError(Error(GL_INVALID_OPERATION));
464 if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
469 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
471 context->recordError(Error(GL_INVALID_OPERATION));
476 // Validate sub image parameters
479 if (isCompressed != textureCompressed)
481 context->recordError(Error(GL_INVALID_OPERATION));
487 if ((width % 4 != 0 && width != textureLevelWidth) ||
488 (height % 4 != 0 && height != textureLevelHeight))
490 context->recordError(Error(GL_INVALID_OPERATION));
495 if (width == 0 || height == 0 || depth == 0)
500 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
502 context->recordError(Error(GL_INVALID_VALUE));
506 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
507 std::numeric_limits<GLsizei>::max() - yoffset < height ||
508 std::numeric_limits<GLsizei>::max() - zoffset < depth)
510 context->recordError(Error(GL_INVALID_VALUE));
514 if (xoffset + width > textureLevelWidth ||
515 yoffset + height > textureLevelHeight ||
516 zoffset + depth > textureLevelDepth)
518 context->recordError(Error(GL_INVALID_VALUE));
523 // Check for pixel unpack buffer related API errors
524 gl::Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
525 if (pixelUnpackBuffer != NULL)
527 // ...the data would be unpacked from the buffer object such that the memory reads required
528 // would exceed the data store size.
529 size_t widthSize = static_cast<size_t>(width);
530 size_t heightSize = static_cast<size_t>(height);
531 size_t depthSize = static_cast<size_t>(depth);
532 GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type);
534 size_t pixelBytes = static_cast<size_t>(gl::GetInternalFormatInfo(sizedFormat).pixelBytes);
536 if (!rx::IsUnsignedMultiplicationSafe(widthSize, heightSize) ||
537 !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize, depthSize) ||
538 !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize * depthSize, pixelBytes))
540 // Overflow past the end of the buffer
541 context->recordError(Error(GL_INVALID_OPERATION));
545 size_t copyBytes = widthSize * heightSize * depthSize * pixelBytes;
546 size_t offset = reinterpret_cast<size_t>(pixels);
548 if (!rx::IsUnsignedAdditionSafe(offset, copyBytes) ||
549 ((offset + copyBytes) > static_cast<size_t>(pixelUnpackBuffer->getSize())))
551 // Overflow past the end of the buffer
552 context->recordError(Error(GL_INVALID_OPERATION));
556 // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
557 // indicated by type.
558 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
560 if ((offset % dataBytesPerPixel) != 0)
562 context->recordError(Error(GL_INVALID_OPERATION));
566 // ...the buffer object's data store is currently mapped.
567 if (pixelUnpackBuffer->isMapped())
569 context->recordError(Error(GL_INVALID_OPERATION));
577 struct EffectiveInternalFormatInfo
579 GLenum mEffectiveFormat;
583 GLuint mMinGreenBits;
584 GLuint mMaxGreenBits;
587 GLuint mMinAlphaBits;
588 GLuint mMaxAlphaBits;
590 EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits,
591 GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits,
592 GLuint minAlphaBits, GLuint maxAlphaBits)
593 : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits),
594 mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits),
595 mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits),
596 mMaxAlphaBits(maxAlphaBits) {};
599 typedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
601 static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList()
603 EffectiveInternalFormatList list;
605 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
606 // linear source buffer component sizes.
607 // | Source channel min/max sizes |
608 // Effective Internal Format | N/A | R | G | B | A |
609 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8));
610 list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0));
611 list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0));
612 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0));
613 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0));
614 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4));
615 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1));
616 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8));
617 list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2));
622 static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList()
624 EffectiveInternalFormatList list;
626 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
627 // linear source buffer component sizes.
628 // | Source channel min/max sizes |
629 // Effective Internal Format | Dest Format | R | G | B | A |
630 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
631 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX));
632 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
633 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX));
634 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX));
635 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4));
636 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1));
637 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8));
642 static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
643 GLenum *outEffectiveFormat)
645 const EffectiveInternalFormatList *list = NULL;
646 GLenum targetFormat = GL_NONE;
648 if (destFormat.pixelBytes > 0)
650 static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList();
655 static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList();
657 targetFormat = destFormat.format;
660 for (size_t curFormat = 0; curFormat < list->size(); ++curFormat)
662 const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat);
663 if ((formatInfo.mDestFormat == targetFormat) &&
664 (formatInfo.mMinRedBits <= srcFormat.redBits && formatInfo.mMaxRedBits >= srcFormat.redBits) &&
665 (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) &&
666 (formatInfo.mMinBlueBits <= srcFormat.blueBits && formatInfo.mMaxBlueBits >= srcFormat.blueBits) &&
667 (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits))
669 *outEffectiveFormat = formatInfo.mEffectiveFormat;
677 struct CopyConversion
679 GLenum mTextureFormat;
680 GLenum mFramebufferFormat;
682 CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
683 : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
685 bool operator<(const CopyConversion& other) const
687 return memcmp(this, &other, sizeof(CopyConversion)) < 0;
691 typedef std::set<CopyConversion> CopyConversionSet;
693 static CopyConversionSet BuildValidES3CopyTexImageCombinations()
695 CopyConversionSet set;
697 // From ES 3.0.1 spec, table 3.15
698 set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
699 set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
700 set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
701 set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
702 set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
703 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
704 set.insert(CopyConversion(GL_RED, GL_RED));
705 set.insert(CopyConversion(GL_RED, GL_RG));
706 set.insert(CopyConversion(GL_RED, GL_RGB));
707 set.insert(CopyConversion(GL_RED, GL_RGBA));
708 set.insert(CopyConversion(GL_RG, GL_RG));
709 set.insert(CopyConversion(GL_RG, GL_RGB));
710 set.insert(CopyConversion(GL_RG, GL_RGBA));
711 set.insert(CopyConversion(GL_RGB, GL_RGB));
712 set.insert(CopyConversion(GL_RGB, GL_RGBA));
713 set.insert(CopyConversion(GL_RGBA, GL_RGBA));
715 // Necessary for ANGLE back-buffers
716 set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
717 set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
718 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
719 set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
720 set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
721 set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
722 set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
724 set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
725 set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
726 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
727 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
728 set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
729 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
730 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
731 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
732 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
733 set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
738 static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle)
740 const InternalFormat &textureInternalFormatInfo = GetInternalFormatInfo(textureInternalFormat);
741 const InternalFormat &framebufferInternalFormatInfo = GetInternalFormatInfo(frameBufferInternalFormat);
743 static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
744 if (conversionSet.find(CopyConversion(textureInternalFormatInfo.format, framebufferInternalFormatInfo.format)) != conversionSet.end())
746 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
747 // must both be signed, unsigned, or fixed point and both source and destinations
748 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
749 // conversion between fixed and floating point.
751 if ((textureInternalFormatInfo.colorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.colorEncoding == GL_SRGB))
756 if (((textureInternalFormatInfo.componentType == GL_INT) != (framebufferInternalFormatInfo.componentType == GL_INT )) ||
757 ((textureInternalFormatInfo.componentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.componentType == GL_UNSIGNED_INT)))
762 if ((textureInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
763 textureInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
764 textureInternalFormatInfo.componentType == GL_FLOAT) &&
765 !(framebufferInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
766 framebufferInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
767 framebufferInternalFormatInfo.componentType == GL_FLOAT))
772 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
773 // The effective internal format of the source buffer is determined with the following rules applied in order:
774 // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
775 // effective internal format is the source buffer's sized internal format.
776 // * If the source buffer is a texture that was created with an unsized base internal format, then the
777 // effective internal format is the source image array's effective internal format, as specified by table
778 // 3.12, which is determined from the <format> and <type> that were used when the source image array was
779 // specified by TexImage*.
780 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
781 // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
782 // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
783 // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
785 const InternalFormat *sourceEffectiveFormat = NULL;
786 if (readBufferHandle != 0)
788 // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
789 if (framebufferInternalFormatInfo.pixelBytes > 0)
791 sourceEffectiveFormat = &framebufferInternalFormatInfo;
795 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
796 // texture. We can use the same table we use when creating textures to get its effective sized format.
797 const FormatType &typeInfo = GetFormatTypeInfo(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type);
798 sourceEffectiveFormat = &GetInternalFormatInfo(typeInfo.internalFormat);
803 // The effective internal format must be derived from the source framebuffer's channel sizes.
804 // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
805 if (framebufferInternalFormatInfo.colorEncoding == GL_LINEAR)
807 GLenum effectiveFormat;
808 if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat))
810 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
817 else if (framebufferInternalFormatInfo.colorEncoding == GL_SRGB)
819 // SRGB buffers can only be copied to sized format destinations according to table 3.18
820 if ((textureInternalFormatInfo.pixelBytes > 0) &&
821 (framebufferInternalFormatInfo.redBits >= 1 && framebufferInternalFormatInfo.redBits <= 8) &&
822 (framebufferInternalFormatInfo.greenBits >= 1 && framebufferInternalFormatInfo.greenBits <= 8) &&
823 (framebufferInternalFormatInfo.blueBits >= 1 && framebufferInternalFormatInfo.blueBits <= 8) &&
824 (framebufferInternalFormatInfo.alphaBits >= 1 && framebufferInternalFormatInfo.alphaBits <= 8))
826 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
840 if (textureInternalFormatInfo.pixelBytes > 0)
842 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is sized,
843 // component sizes of the source and destination formats must exactly match
844 if (textureInternalFormatInfo.redBits != sourceEffectiveFormat->redBits ||
845 textureInternalFormatInfo.greenBits != sourceEffectiveFormat->greenBits ||
846 textureInternalFormatInfo.blueBits != sourceEffectiveFormat->blueBits ||
847 textureInternalFormatInfo.alphaBits != sourceEffectiveFormat->alphaBits)
854 return true; // A conversion function exists, and no rule in the specification has precluded conversion
855 // between these formats.
861 bool ValidateES3CopyTexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat,
862 bool isSubImage, GLint xoffset, GLint yoffset, GLint zoffset,
863 GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
865 GLenum textureInternalFormat;
866 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
867 xoffset, yoffset, zoffset, x, y, width, height,
868 border, &textureInternalFormat))
873 gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
875 if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
877 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
881 if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0)
883 context->recordError(Error(GL_INVALID_OPERATION));
887 gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer();
888 GLenum colorbufferInternalFormat = source->getInternalFormat();
892 if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat,
893 context->getState().getReadFramebuffer()->id()))
895 context->recordError(Error(GL_INVALID_OPERATION));
901 if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat,
902 context->getState().getReadFramebuffer()->id()))
904 context->recordError(Error(GL_INVALID_OPERATION));
909 // If width or height is zero, it is a no-op. Return false without setting an error.
910 return (width > 0 && height > 0);
913 bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
914 GLsizei width, GLsizei height, GLsizei depth)
916 if (width < 1 || height < 1 || depth < 1 || levels < 1)
918 context->recordError(Error(GL_INVALID_VALUE));
922 if (levels > gl::log2(std::max(std::max(width, height), depth)) + 1)
924 context->recordError(Error(GL_INVALID_OPERATION));
928 const gl::Caps &caps = context->getCaps();
930 gl::Texture *texture = NULL;
935 texture = context->getTexture2D();
937 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
938 static_cast<GLuint>(height) > caps.max2DTextureSize)
940 context->recordError(Error(GL_INVALID_VALUE));
946 case GL_TEXTURE_CUBE_MAP:
948 texture = context->getTextureCubeMap();
952 context->recordError(Error(GL_INVALID_VALUE));
956 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
958 context->recordError(Error(GL_INVALID_VALUE));
966 texture = context->getTexture3D();
968 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
969 static_cast<GLuint>(height) > caps.max3DTextureSize ||
970 static_cast<GLuint>(depth) > caps.max3DTextureSize)
972 context->recordError(Error(GL_INVALID_VALUE));
978 case GL_TEXTURE_2D_ARRAY:
980 texture = context->getTexture2DArray();
982 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
983 static_cast<GLuint>(height) > caps.max2DTextureSize ||
984 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
986 context->recordError(Error(GL_INVALID_VALUE));
993 context->recordError(Error(GL_INVALID_ENUM));
997 if (!texture || texture->id() == 0)
999 context->recordError(Error(GL_INVALID_OPERATION));
1003 if (texture->isImmutable())
1005 context->recordError(Error(GL_INVALID_OPERATION));
1009 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1010 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
1012 context->recordError(Error(GL_INVALID_ENUM));
1016 if (formatInfo.pixelBytes == 0)
1018 context->recordError(Error(GL_INVALID_ENUM));
1025 bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
1026 GLuint texture, GLint level, GLint layer)
1028 if (context->getClientVersion() < 3)
1030 context->recordError(Error(GL_INVALID_OPERATION));
1036 context->recordError(Error(GL_INVALID_VALUE));
1040 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1045 const gl::Caps &caps = context->getCaps();
1048 gl::Texture *tex = context->getTexture(texture);
1051 switch (tex->getTarget())
1053 case GL_TEXTURE_2D_ARRAY:
1055 if (level > gl::log2(caps.max2DTextureSize))
1057 context->recordError(Error(GL_INVALID_VALUE));
1061 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1063 context->recordError(Error(GL_INVALID_VALUE));
1067 gl::Texture2DArray *texArray = static_cast<gl::Texture2DArray *>(tex);
1068 if (texArray->isCompressed(level))
1070 context->recordError(Error(GL_INVALID_OPERATION));
1078 if (level > gl::log2(caps.max3DTextureSize))
1080 context->recordError(Error(GL_INVALID_VALUE));
1084 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1086 context->recordError(Error(GL_INVALID_VALUE));
1090 gl::Texture3D *tex3d = static_cast<gl::Texture3D *>(tex);
1091 if (tex3d->isCompressed(level))
1093 context->recordError(Error(GL_INVALID_OPERATION));
1100 context->recordError(Error(GL_INVALID_OPERATION));
1108 bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type)
1110 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
1117 case GL_UNSIGNED_BYTE:
1119 case GL_UNSIGNED_INT_2_10_10_10_REV:
1120 if (internalFormat != GL_RGB10_A2)
1126 if (internalFormatInfo.componentType != GL_FLOAT)
1135 case GL_RGBA_INTEGER:
1139 if (internalFormatInfo.componentType != GL_INT)
1144 case GL_UNSIGNED_INT:
1145 if (internalFormatInfo.componentType != GL_UNSIGNED_INT)
1157 case GL_UNSIGNED_BYTE:
1158 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1159 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1167 if (!context->getExtensions().textureRG)
1173 case GL_UNSIGNED_BYTE:
1185 bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments,
1186 const GLenum* attachments)
1188 bool defaultFramebuffer = false;
1192 case GL_DRAW_FRAMEBUFFER:
1193 case GL_FRAMEBUFFER:
1194 defaultFramebuffer = context->getState().getDrawFramebuffer()->id() == 0;
1196 case GL_READ_FRAMEBUFFER:
1197 defaultFramebuffer = context->getState().getReadFramebuffer()->id() == 0;
1200 context->recordError(Error(GL_INVALID_ENUM));
1204 for (int i = 0; i < numAttachments; ++i)
1206 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15)
1208 if (defaultFramebuffer)
1210 context->recordError(Error(GL_INVALID_ENUM));
1214 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
1216 context->recordError(Error(GL_INVALID_OPERATION));
1222 switch (attachments[i])
1224 case GL_DEPTH_ATTACHMENT:
1225 case GL_STENCIL_ATTACHMENT:
1226 case GL_DEPTH_STENCIL_ATTACHMENT:
1227 if (defaultFramebuffer)
1229 context->recordError(Error(GL_INVALID_ENUM));
1236 if (!defaultFramebuffer)
1238 context->recordError(Error(GL_INVALID_ENUM));
1243 context->recordError(Error(GL_INVALID_ENUM));
1252 bool ValidateClearBuffer(Context *context)
1254 if (context->getClientVersion() < 3)
1256 context->recordError(Error(GL_INVALID_OPERATION));
1260 const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer();
1261 if (!fbo || fbo->completeness() != GL_FRAMEBUFFER_COMPLETE)
1263 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
1270 bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
1272 if (context->getClientVersion() < 3)
1274 context->recordError(Error(GL_INVALID_OPERATION));
1278 return ValidateGetUniformBase(context, program, location);