blob: 5f9bf5540f9f5c7575f8fb068fc8c85721cd2c6c [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
Jamie Madillc29968b2016-01-20 11:17:23 -050024namespace
25{
26
27bool IsPartialBlit(gl::Context *context,
28 const FramebufferAttachment *readBuffer,
29 const FramebufferAttachment *writeBuffer,
30 GLint srcX0,
31 GLint srcY0,
32 GLint srcX1,
33 GLint srcY1,
34 GLint dstX0,
35 GLint dstY0,
36 GLint dstX1,
37 GLint dstY1)
38{
39 const Extents &writeSize = writeBuffer->getSize();
40 const Extents &readSize = readBuffer->getSize();
41
42 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
43 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
44 {
45 return true;
46 }
47
48 if (context->getState().isScissorTestEnabled())
49 {
50 const Rectangle &scissor = context->getState().getScissor();
51 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
52 scissor.height < writeSize.height;
53 }
54
55 return false;
56}
57
58} // anonymous namespace
59
Geoff Langb1196682014-07-23 13:47:29 -040060bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
Geoff Lange8ebe7f2013-08-05 15:03:13 -040061 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
62 GLint border, GLenum format, GLenum type, const GLvoid *pixels)
63{
Jamie Madill6f38f822014-06-06 17:12:20 -040064 if (!ValidTexture2DDestinationTarget(context, target))
65 {
Geoff Langb1196682014-07-23 13:47:29 -040066 context->recordError(Error(GL_INVALID_ENUM));
67 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -040068 }
69
Austin Kinross08528e12015-10-07 16:24:40 -070070 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040071 {
Geoff Langb1196682014-07-23 13:47:29 -040072 context->recordError(Error(GL_INVALID_VALUE));
73 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040074 }
75
Geoff Lange8ebe7f2013-08-05 15:03:13 -040076 if (level < 0 || xoffset < 0 ||
77 std::numeric_limits<GLsizei>::max() - xoffset < width ||
78 std::numeric_limits<GLsizei>::max() - yoffset < height)
79 {
Geoff Langb1196682014-07-23 13:47:29 -040080 context->recordError(Error(GL_INVALID_VALUE));
81 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040082 }
83
Geoff Lang005df412013-10-16 14:12:50 -040084 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040085 {
Geoff Langb1196682014-07-23 13:47:29 -040086 context->recordError(Error(GL_INVALID_OPERATION));
87 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040088 }
89
Geoff Langaae65a42014-05-26 12:43:44 -040090 const gl::Caps &caps = context->getCaps();
91
Geoff Langa9be0dc2014-12-17 12:34:40 -050092 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040093 {
Geoff Langa9be0dc2014-12-17 12:34:40 -050094 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
95 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040096 {
Geoff Langa9be0dc2014-12-17 12:34:40 -050097 context->recordError(Error(GL_INVALID_VALUE));
98 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040099 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500100 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500101 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500102 {
103 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400104 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500105 context->recordError(Error(GL_INVALID_VALUE));
106 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400107 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400108
Geoff Langa9be0dc2014-12-17 12:34:40 -0500109 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
110 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
111 {
112 context->recordError(Error(GL_INVALID_VALUE));
113 return false;
114 }
115 }
116 else
117 {
Geoff Langb1196682014-07-23 13:47:29 -0400118 context->recordError(Error(GL_INVALID_ENUM));
119 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400120 }
121
Geoff Lang691e58c2014-12-19 17:03:25 -0500122 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400123 if (!texture)
124 {
Geoff Langb1196682014-07-23 13:47:29 -0400125 context->recordError(Error(GL_INVALID_OPERATION));
126 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400127 }
128
Geoff Langa9be0dc2014-12-17 12:34:40 -0500129 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400130 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500131 if (format != GL_NONE)
132 {
Geoff Lang051dbc72015-01-05 15:48:58 -0500133 if (gl::GetSizedInternalFormat(format, type) != texture->getInternalFormat(target, level))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500134 {
135 context->recordError(Error(GL_INVALID_OPERATION));
136 return false;
137 }
138 }
139
140 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
141 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
142 {
143 context->recordError(Error(GL_INVALID_VALUE));
144 return false;
145 }
146 }
147 else
148 {
Geoff Lang69cce582015-09-17 13:20:36 -0400149 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500150 {
151 context->recordError(Error(GL_INVALID_OPERATION));
152 return false;
153 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400154 }
155
156 // Verify zero border
157 if (border != 0)
158 {
Geoff Langb1196682014-07-23 13:47:29 -0400159 context->recordError(Error(GL_INVALID_VALUE));
160 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400161 }
162
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400163 if (isCompressed)
164 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400165 GLenum actualInternalFormat =
166 isSubImage ? texture->getInternalFormat(target, level) : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400167 switch (actualInternalFormat)
168 {
169 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
170 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400171 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400172 {
Geoff Langb1196682014-07-23 13:47:29 -0400173 context->recordError(Error(GL_INVALID_ENUM));
174 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400175 }
176 break;
177 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400178 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400179 {
Geoff Langb1196682014-07-23 13:47:29 -0400180 context->recordError(Error(GL_INVALID_ENUM));
181 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400182 }
183 break;
184 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langb1196682014-07-23 13:47:29 -0400185 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400186 {
Geoff Langb1196682014-07-23 13:47:29 -0400187 context->recordError(Error(GL_INVALID_ENUM));
188 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400189 }
190 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400191 case GL_ETC1_RGB8_OES:
192 if (!context->getExtensions().compressedETC1RGB8Texture)
193 {
194 context->recordError(Error(GL_INVALID_ENUM));
195 return false;
196 }
197 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400198 default:
tmartino0ccd5ae2015-10-01 14:33:14 -0400199 context->recordError(Error(
200 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format"));
201 return false;
202 }
203 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
204 {
205 context->recordError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400206 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400207 }
208 }
209 else
210 {
211 // validate <type> by itself (used as secondary key below)
212 switch (type)
213 {
214 case GL_UNSIGNED_BYTE:
215 case GL_UNSIGNED_SHORT_5_6_5:
216 case GL_UNSIGNED_SHORT_4_4_4_4:
217 case GL_UNSIGNED_SHORT_5_5_5_1:
218 case GL_UNSIGNED_SHORT:
219 case GL_UNSIGNED_INT:
220 case GL_UNSIGNED_INT_24_8_OES:
221 case GL_HALF_FLOAT_OES:
222 case GL_FLOAT:
223 break;
224 default:
Geoff Langb1196682014-07-23 13:47:29 -0400225 context->recordError(Error(GL_INVALID_ENUM));
226 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400227 }
228
229 // validate <format> + <type> combinations
230 // - invalid <format> -> sets INVALID_ENUM
231 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
232 switch (format)
233 {
234 case GL_ALPHA:
235 case GL_LUMINANCE:
236 case GL_LUMINANCE_ALPHA:
237 switch (type)
238 {
239 case GL_UNSIGNED_BYTE:
240 case GL_FLOAT:
241 case GL_HALF_FLOAT_OES:
242 break;
Geoff Langb1196682014-07-23 13:47:29 -0400243 default:
244 context->recordError(Error(GL_INVALID_OPERATION));
245 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400246 }
247 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400248 case GL_RED:
Geoff Langcec35902014-04-16 10:52:36 -0400249 case GL_RG:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400250 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400251 {
Geoff Langb1196682014-07-23 13:47:29 -0400252 context->recordError(Error(GL_INVALID_ENUM));
253 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400254 }
255 switch (type)
256 {
257 case GL_UNSIGNED_BYTE:
258 case GL_FLOAT:
259 case GL_HALF_FLOAT_OES:
260 break;
261 default:
Geoff Langb1196682014-07-23 13:47:29 -0400262 context->recordError(Error(GL_INVALID_OPERATION));
263 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400264 }
265 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400266 case GL_RGB:
267 switch (type)
268 {
269 case GL_UNSIGNED_BYTE:
270 case GL_UNSIGNED_SHORT_5_6_5:
271 case GL_FLOAT:
272 case GL_HALF_FLOAT_OES:
273 break;
274 default:
Geoff Langb1196682014-07-23 13:47:29 -0400275 context->recordError(Error(GL_INVALID_OPERATION));
276 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400277 }
278 break;
279 case GL_RGBA:
280 switch (type)
281 {
282 case GL_UNSIGNED_BYTE:
283 case GL_UNSIGNED_SHORT_4_4_4_4:
284 case GL_UNSIGNED_SHORT_5_5_5_1:
285 case GL_FLOAT:
286 case GL_HALF_FLOAT_OES:
287 break;
288 default:
Geoff Langb1196682014-07-23 13:47:29 -0400289 context->recordError(Error(GL_INVALID_OPERATION));
290 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400291 }
292 break;
293 case GL_BGRA_EXT:
294 switch (type)
295 {
296 case GL_UNSIGNED_BYTE:
297 break;
298 default:
Geoff Langb1196682014-07-23 13:47:29 -0400299 context->recordError(Error(GL_INVALID_OPERATION));
300 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400301 }
302 break;
Geoff Lang05b05022014-06-11 15:31:45 -0400303 case GL_SRGB_EXT:
304 case GL_SRGB_ALPHA_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400305 if (!context->getExtensions().sRGB)
Geoff Lang05b05022014-06-11 15:31:45 -0400306 {
Geoff Langb1196682014-07-23 13:47:29 -0400307 context->recordError(Error(GL_INVALID_ENUM));
308 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400309 }
310 switch (type)
311 {
312 case GL_UNSIGNED_BYTE:
313 break;
314 default:
Geoff Langb1196682014-07-23 13:47:29 -0400315 context->recordError(Error(GL_INVALID_OPERATION));
316 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400317 }
318 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400319 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
320 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
321 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
322 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
323 break;
324 case GL_DEPTH_COMPONENT:
325 switch (type)
326 {
327 case GL_UNSIGNED_SHORT:
328 case GL_UNSIGNED_INT:
329 break;
330 default:
Geoff Langb1196682014-07-23 13:47:29 -0400331 context->recordError(Error(GL_INVALID_OPERATION));
332 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400333 }
334 break;
335 case GL_DEPTH_STENCIL_OES:
336 switch (type)
337 {
338 case GL_UNSIGNED_INT_24_8_OES:
339 break;
340 default:
Geoff Langb1196682014-07-23 13:47:29 -0400341 context->recordError(Error(GL_INVALID_OPERATION));
342 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400343 }
344 break;
345 default:
Geoff Langb1196682014-07-23 13:47:29 -0400346 context->recordError(Error(GL_INVALID_ENUM));
347 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400348 }
349
350 switch (format)
351 {
352 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
353 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400354 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400355 {
Geoff Langb1196682014-07-23 13:47:29 -0400356 context->recordError(Error(GL_INVALID_OPERATION));
357 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400358 }
359 else
360 {
Geoff Langb1196682014-07-23 13:47:29 -0400361 context->recordError(Error(GL_INVALID_ENUM));
362 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400363 }
364 break;
365 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400366 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400367 {
Geoff Langb1196682014-07-23 13:47:29 -0400368 context->recordError(Error(GL_INVALID_OPERATION));
369 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400370 }
371 else
372 {
Geoff Langb1196682014-07-23 13:47:29 -0400373 context->recordError(Error(GL_INVALID_ENUM));
374 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400375 }
376 break;
377 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400378 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400379 {
Geoff Langb1196682014-07-23 13:47:29 -0400380 context->recordError(Error(GL_INVALID_OPERATION));
381 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400382 }
383 else
384 {
Geoff Langb1196682014-07-23 13:47:29 -0400385 context->recordError(Error(GL_INVALID_ENUM));
386 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400387 }
388 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400389 case GL_ETC1_RGB8_OES:
390 if (context->getExtensions().compressedETC1RGB8Texture)
391 {
392 context->recordError(Error(GL_INVALID_OPERATION));
393 return false;
394 }
395 else
396 {
397 context->recordError(Error(GL_INVALID_ENUM));
398 return false;
399 }
400 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400401 case GL_DEPTH_COMPONENT:
402 case GL_DEPTH_STENCIL_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400403 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400404 {
Geoff Langb1196682014-07-23 13:47:29 -0400405 context->recordError(Error(GL_INVALID_VALUE));
406 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400407 }
408 if (target != GL_TEXTURE_2D)
409 {
Geoff Langb1196682014-07-23 13:47:29 -0400410 context->recordError(Error(GL_INVALID_OPERATION));
411 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400412 }
413 // OES_depth_texture supports loading depth data and multiple levels,
414 // but ANGLE_depth_texture does not
415 if (pixels != NULL || level != 0)
416 {
Geoff Langb1196682014-07-23 13:47:29 -0400417 context->recordError(Error(GL_INVALID_OPERATION));
418 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400419 }
420 break;
421 default:
422 break;
423 }
424
425 if (type == GL_FLOAT)
426 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400427 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400428 {
Geoff Langb1196682014-07-23 13:47:29 -0400429 context->recordError(Error(GL_INVALID_ENUM));
430 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400431 }
432 }
433 else if (type == GL_HALF_FLOAT_OES)
434 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400435 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400436 {
Geoff Langb1196682014-07-23 13:47:29 -0400437 context->recordError(Error(GL_INVALID_ENUM));
438 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400439 }
440 }
441 }
442
443 return true;
444}
445
Jamie Madillc29968b2016-01-20 11:17:23 -0500446bool ValidateES2CopyTexImageParameters(ValidationContext *context,
447 GLenum target,
448 GLint level,
449 GLenum internalformat,
450 bool isSubImage,
451 GLint xoffset,
452 GLint yoffset,
453 GLint x,
454 GLint y,
455 GLsizei width,
456 GLsizei height,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400457 GLint border)
458{
Jamie Madill560a8d82014-05-21 13:06:20 -0400459 GLenum textureInternalFormat = GL_NONE;
Shannon Woods4dfed832014-03-17 20:03:39 -0400460
Jamie Madill560a8d82014-05-21 13:06:20 -0400461 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
462 xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400463 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400464 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400465 }
466
Jamie Madillc29968b2016-01-20 11:17:23 -0500467 const gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400468 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat();
Jamie Madillbc393df2015-01-29 13:46:07 -0500469 const auto &internalFormatInfo = gl::GetInternalFormatInfo(textureInternalFormat);
470 GLenum textureFormat = internalFormatInfo.format;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400471
472 // [OpenGL ES 2.0.24] table 3.9
473 if (isSubImage)
474 {
475 switch (textureFormat)
476 {
477 case GL_ALPHA:
478 if (colorbufferFormat != GL_ALPHA8_EXT &&
479 colorbufferFormat != GL_RGBA4 &&
480 colorbufferFormat != GL_RGB5_A1 &&
481 colorbufferFormat != GL_RGBA8_OES)
482 {
Geoff Langb1196682014-07-23 13:47:29 -0400483 context->recordError(Error(GL_INVALID_OPERATION));
484 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400485 }
486 break;
487 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400488 if (colorbufferFormat != GL_R8_EXT &&
489 colorbufferFormat != GL_RG8_EXT &&
490 colorbufferFormat != GL_RGB565 &&
491 colorbufferFormat != GL_RGB8_OES &&
492 colorbufferFormat != GL_RGBA4 &&
493 colorbufferFormat != GL_RGB5_A1 &&
494 colorbufferFormat != GL_RGBA8_OES)
495 {
Geoff Langb1196682014-07-23 13:47:29 -0400496 context->recordError(Error(GL_INVALID_OPERATION));
497 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400498 }
499 break;
500 case GL_RED_EXT:
501 if (colorbufferFormat != GL_R8_EXT &&
502 colorbufferFormat != GL_RG8_EXT &&
503 colorbufferFormat != GL_RGB565 &&
504 colorbufferFormat != GL_RGB8_OES &&
505 colorbufferFormat != GL_RGBA4 &&
506 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500507 colorbufferFormat != GL_RGBA8_OES &&
508 colorbufferFormat != GL_R32F &&
509 colorbufferFormat != GL_RG32F &&
510 colorbufferFormat != GL_RGB32F &&
511 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400512 {
Geoff Langb1196682014-07-23 13:47:29 -0400513 context->recordError(Error(GL_INVALID_OPERATION));
514 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400515 }
516 break;
517 case GL_RG_EXT:
518 if (colorbufferFormat != GL_RG8_EXT &&
519 colorbufferFormat != GL_RGB565 &&
520 colorbufferFormat != GL_RGB8_OES &&
521 colorbufferFormat != GL_RGBA4 &&
522 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500523 colorbufferFormat != GL_RGBA8_OES &&
524 colorbufferFormat != GL_RG32F &&
525 colorbufferFormat != GL_RGB32F &&
526 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400527 {
Geoff Langb1196682014-07-23 13:47:29 -0400528 context->recordError(Error(GL_INVALID_OPERATION));
529 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400530 }
531 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400532 case GL_RGB:
533 if (colorbufferFormat != GL_RGB565 &&
534 colorbufferFormat != GL_RGB8_OES &&
535 colorbufferFormat != GL_RGBA4 &&
536 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500537 colorbufferFormat != GL_RGBA8_OES &&
538 colorbufferFormat != GL_RGB32F &&
539 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400540 {
Geoff Langb1196682014-07-23 13:47:29 -0400541 context->recordError(Error(GL_INVALID_OPERATION));
542 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400543 }
544 break;
545 case GL_LUMINANCE_ALPHA:
546 case GL_RGBA:
547 if (colorbufferFormat != GL_RGBA4 &&
548 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500549 colorbufferFormat != GL_RGBA8_OES &&
550 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400551 {
Geoff Langb1196682014-07-23 13:47:29 -0400552 context->recordError(Error(GL_INVALID_OPERATION));
553 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400554 }
555 break;
556 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
557 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
558 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
559 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Lang6ea6f942015-09-11 13:11:22 -0400560 case GL_ETC1_RGB8_OES:
Geoff Langb1196682014-07-23 13:47:29 -0400561 context->recordError(Error(GL_INVALID_OPERATION));
562 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400563 case GL_DEPTH_COMPONENT:
564 case GL_DEPTH_STENCIL_OES:
Geoff Langb1196682014-07-23 13:47:29 -0400565 context->recordError(Error(GL_INVALID_OPERATION));
566 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400567 default:
Geoff Langb1196682014-07-23 13:47:29 -0400568 context->recordError(Error(GL_INVALID_OPERATION));
569 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400570 }
Jamie Madillbc393df2015-01-29 13:46:07 -0500571
572 if (internalFormatInfo.type == GL_FLOAT &&
573 !context->getExtensions().textureFloat)
574 {
575 context->recordError(Error(GL_INVALID_OPERATION));
576 return false;
577 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400578 }
579 else
580 {
581 switch (internalformat)
582 {
583 case GL_ALPHA:
584 if (colorbufferFormat != GL_ALPHA8_EXT &&
585 colorbufferFormat != GL_RGBA4 &&
586 colorbufferFormat != GL_RGB5_A1 &&
587 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500588 colorbufferFormat != GL_RGBA8_OES &&
589 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400590 {
Geoff Langb1196682014-07-23 13:47:29 -0400591 context->recordError(Error(GL_INVALID_OPERATION));
592 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400593 }
594 break;
595 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400596 if (colorbufferFormat != GL_R8_EXT &&
597 colorbufferFormat != GL_RG8_EXT &&
598 colorbufferFormat != GL_RGB565 &&
599 colorbufferFormat != GL_RGB8_OES &&
600 colorbufferFormat != GL_RGBA4 &&
601 colorbufferFormat != GL_RGB5_A1 &&
602 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500603 colorbufferFormat != GL_RGBA8_OES &&
604 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400605 {
Geoff Langb1196682014-07-23 13:47:29 -0400606 context->recordError(Error(GL_INVALID_OPERATION));
607 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400608 }
609 break;
610 case GL_RED_EXT:
611 if (colorbufferFormat != GL_R8_EXT &&
612 colorbufferFormat != GL_RG8_EXT &&
613 colorbufferFormat != GL_RGB565 &&
614 colorbufferFormat != GL_RGB8_OES &&
615 colorbufferFormat != GL_RGBA4 &&
616 colorbufferFormat != GL_RGB5_A1 &&
617 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500618 colorbufferFormat != GL_RGBA8_OES &&
619 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400620 {
Geoff Langb1196682014-07-23 13:47:29 -0400621 context->recordError(Error(GL_INVALID_OPERATION));
622 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400623 }
624 break;
625 case GL_RG_EXT:
626 if (colorbufferFormat != GL_RG8_EXT &&
627 colorbufferFormat != GL_RGB565 &&
628 colorbufferFormat != GL_RGB8_OES &&
629 colorbufferFormat != GL_RGBA4 &&
630 colorbufferFormat != GL_RGB5_A1 &&
631 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500632 colorbufferFormat != GL_RGBA8_OES &&
633 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400634 {
Geoff Langb1196682014-07-23 13:47:29 -0400635 context->recordError(Error(GL_INVALID_OPERATION));
636 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400637 }
638 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400639 case GL_RGB:
640 if (colorbufferFormat != GL_RGB565 &&
641 colorbufferFormat != GL_RGB8_OES &&
642 colorbufferFormat != GL_RGBA4 &&
643 colorbufferFormat != GL_RGB5_A1 &&
644 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500645 colorbufferFormat != GL_RGBA8_OES &&
646 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400647 {
Geoff Langb1196682014-07-23 13:47:29 -0400648 context->recordError(Error(GL_INVALID_OPERATION));
649 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400650 }
651 break;
652 case GL_LUMINANCE_ALPHA:
653 case GL_RGBA:
654 if (colorbufferFormat != GL_RGBA4 &&
655 colorbufferFormat != GL_RGB5_A1 &&
656 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500657 colorbufferFormat != GL_RGBA8_OES &&
658 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400659 {
Geoff Langb1196682014-07-23 13:47:29 -0400660 context->recordError(Error(GL_INVALID_OPERATION));
661 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400662 }
663 break;
664 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
665 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400666 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400667 {
Geoff Langb1196682014-07-23 13:47:29 -0400668 context->recordError(Error(GL_INVALID_OPERATION));
669 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400670 }
671 else
672 {
Geoff Langb1196682014-07-23 13:47:29 -0400673 context->recordError(Error(GL_INVALID_ENUM));
674 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400675 }
676 break;
677 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400678 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400679 {
Geoff Langb1196682014-07-23 13:47:29 -0400680 context->recordError(Error(GL_INVALID_OPERATION));
681 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400682 }
683 else
684 {
Geoff Langb1196682014-07-23 13:47:29 -0400685 context->recordError(Error(GL_INVALID_ENUM));
686 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400687 }
688 break;
689 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400690 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400691 {
Geoff Langb1196682014-07-23 13:47:29 -0400692 context->recordError(Error(GL_INVALID_OPERATION));
693 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400694 }
695 else
696 {
Geoff Langb1196682014-07-23 13:47:29 -0400697 context->recordError(Error(GL_INVALID_ENUM));
698 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400699 }
700 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400701 case GL_ETC1_RGB8_OES:
702 if (context->getExtensions().compressedETC1RGB8Texture)
703 {
704 context->recordError(Error(GL_INVALID_OPERATION));
705 return false;
706 }
707 else
708 {
709 context->recordError(Error(GL_INVALID_ENUM));
710 return false;
711 }
712 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400713 case GL_DEPTH_COMPONENT:
714 case GL_DEPTH_COMPONENT16:
715 case GL_DEPTH_COMPONENT32_OES:
716 case GL_DEPTH_STENCIL_OES:
717 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400718 if (context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400719 {
Geoff Langb1196682014-07-23 13:47:29 -0400720 context->recordError(Error(GL_INVALID_OPERATION));
721 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400722 }
723 else
724 {
Geoff Langb1196682014-07-23 13:47:29 -0400725 context->recordError(Error(GL_INVALID_ENUM));
726 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400727 }
728 default:
Geoff Langb1196682014-07-23 13:47:29 -0400729 context->recordError(Error(GL_INVALID_ENUM));
730 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400731 }
732 }
733
Geoff Lang784a8fd2013-09-24 12:33:16 -0400734 // If width or height is zero, it is a no-op. Return false without setting an error.
735 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400736}
737
Geoff Langb1196682014-07-23 13:47:29 -0400738bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400739 GLsizei width, GLsizei height)
740{
741 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
742 {
Geoff Langb1196682014-07-23 13:47:29 -0400743 context->recordError(Error(GL_INVALID_ENUM));
744 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400745 }
746
747 if (width < 1 || height < 1 || levels < 1)
748 {
Geoff Langb1196682014-07-23 13:47:29 -0400749 context->recordError(Error(GL_INVALID_VALUE));
750 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400751 }
752
753 if (target == GL_TEXTURE_CUBE_MAP && width != height)
754 {
Geoff Langb1196682014-07-23 13:47:29 -0400755 context->recordError(Error(GL_INVALID_VALUE));
756 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400757 }
758
759 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
760 {
Geoff Langb1196682014-07-23 13:47:29 -0400761 context->recordError(Error(GL_INVALID_OPERATION));
762 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400763 }
764
Geoff Lang5d601382014-07-22 15:14:06 -0400765 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
766 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400767 {
Geoff Langb1196682014-07-23 13:47:29 -0400768 context->recordError(Error(GL_INVALID_ENUM));
769 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400770 }
771
Geoff Langaae65a42014-05-26 12:43:44 -0400772 const gl::Caps &caps = context->getCaps();
773
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400774 switch (target)
775 {
776 case GL_TEXTURE_2D:
Geoff Langaae65a42014-05-26 12:43:44 -0400777 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
778 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400779 {
Geoff Langb1196682014-07-23 13:47:29 -0400780 context->recordError(Error(GL_INVALID_VALUE));
781 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400782 }
783 break;
784 case GL_TEXTURE_CUBE_MAP:
Geoff Langaae65a42014-05-26 12:43:44 -0400785 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
786 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400787 {
Geoff Langb1196682014-07-23 13:47:29 -0400788 context->recordError(Error(GL_INVALID_VALUE));
789 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400790 }
791 break;
792 default:
Geoff Langb1196682014-07-23 13:47:29 -0400793 context->recordError(Error(GL_INVALID_ENUM));
794 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400795 }
796
Geoff Langc0b9ef42014-07-02 10:02:37 -0400797 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400798 {
799 if (!gl::isPow2(width) || !gl::isPow2(height))
800 {
Geoff Langb1196682014-07-23 13:47:29 -0400801 context->recordError(Error(GL_INVALID_OPERATION));
802 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400803 }
804 }
805
806 switch (internalformat)
807 {
808 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
809 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400810 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400811 {
Geoff Langb1196682014-07-23 13:47:29 -0400812 context->recordError(Error(GL_INVALID_ENUM));
813 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400814 }
815 break;
816 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400817 if (!context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400818 {
Geoff Langb1196682014-07-23 13:47:29 -0400819 context->recordError(Error(GL_INVALID_ENUM));
820 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400821 }
822 break;
823 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400824 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400825 {
Geoff Langb1196682014-07-23 13:47:29 -0400826 context->recordError(Error(GL_INVALID_ENUM));
827 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400828 }
829 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400830 case GL_ETC1_RGB8_OES:
831 if (!context->getExtensions().compressedETC1RGB8Texture)
832 {
833 context->recordError(Error(GL_INVALID_ENUM));
834 return false;
835 }
836 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400837 case GL_RGBA32F_EXT:
838 case GL_RGB32F_EXT:
839 case GL_ALPHA32F_EXT:
840 case GL_LUMINANCE32F_EXT:
841 case GL_LUMINANCE_ALPHA32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400842 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400843 {
Geoff Langb1196682014-07-23 13:47:29 -0400844 context->recordError(Error(GL_INVALID_ENUM));
845 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400846 }
847 break;
848 case GL_RGBA16F_EXT:
849 case GL_RGB16F_EXT:
850 case GL_ALPHA16F_EXT:
851 case GL_LUMINANCE16F_EXT:
852 case GL_LUMINANCE_ALPHA16F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400853 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400854 {
Geoff Langb1196682014-07-23 13:47:29 -0400855 context->recordError(Error(GL_INVALID_ENUM));
856 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400857 }
858 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400859 case GL_R8_EXT:
860 case GL_RG8_EXT:
861 case GL_R16F_EXT:
862 case GL_RG16F_EXT:
863 case GL_R32F_EXT:
864 case GL_RG32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400865 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400866 {
Geoff Langb1196682014-07-23 13:47:29 -0400867 context->recordError(Error(GL_INVALID_ENUM));
868 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400869 }
870 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400871 case GL_DEPTH_COMPONENT16:
872 case GL_DEPTH_COMPONENT32_OES:
873 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400874 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400875 {
Geoff Langb1196682014-07-23 13:47:29 -0400876 context->recordError(Error(GL_INVALID_ENUM));
877 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400878 }
879 if (target != GL_TEXTURE_2D)
880 {
Geoff Langb1196682014-07-23 13:47:29 -0400881 context->recordError(Error(GL_INVALID_OPERATION));
882 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400883 }
884 // ANGLE_depth_texture only supports 1-level textures
885 if (levels != 1)
886 {
Geoff Langb1196682014-07-23 13:47:29 -0400887 context->recordError(Error(GL_INVALID_OPERATION));
888 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400889 }
890 break;
891 default:
892 break;
893 }
894
Geoff Lang691e58c2014-12-19 17:03:25 -0500895 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400896 if (!texture || texture->id() == 0)
897 {
Geoff Langb1196682014-07-23 13:47:29 -0400898 context->recordError(Error(GL_INVALID_OPERATION));
899 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400900 }
901
Geoff Lang69cce582015-09-17 13:20:36 -0400902 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400903 {
Geoff Langb1196682014-07-23 13:47:29 -0400904 context->recordError(Error(GL_INVALID_OPERATION));
905 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400906 }
907
908 return true;
909}
910
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400911// check for combinations of format and type that are valid for ReadPixels
Geoff Langb1196682014-07-23 13:47:29 -0400912bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400913{
914 switch (format)
915 {
916 case GL_RGBA:
917 switch (type)
918 {
919 case GL_UNSIGNED_BYTE:
920 break;
921 default:
922 return false;
923 }
924 break;
925 case GL_BGRA_EXT:
926 switch (type)
927 {
928 case GL_UNSIGNED_BYTE:
929 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
930 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
931 break;
932 default:
933 return false;
934 }
935 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400936 case GL_RG_EXT:
937 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400938 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400939 {
940 return false;
941 }
942 switch (type)
943 {
944 case GL_UNSIGNED_BYTE:
945 break;
946 default:
947 return false;
948 }
949 break;
950
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400951 default:
952 return false;
953 }
954 return true;
955}
956
Austin Kinross08332632015-05-05 13:35:47 -0700957bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
958 const GLenum *attachments)
959{
Jamie Madillc29968b2016-01-20 11:17:23 -0500960 if (!context->getExtensions().discardFramebuffer)
961 {
962 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
963 return false;
964 }
965
Austin Kinross08332632015-05-05 13:35:47 -0700966 bool defaultFramebuffer = false;
967
968 switch (target)
969 {
970 case GL_FRAMEBUFFER:
971 defaultFramebuffer = (context->getState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
972 break;
973 default:
974 context->recordError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
975 return false;
976 }
977
978 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
979}
980
Austin Kinrossbc781f32015-10-26 09:27:38 -0700981bool ValidateBindVertexArrayOES(Context *context, GLuint array)
982{
983 if (!context->getExtensions().vertexArrayObject)
984 {
985 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
986 return false;
987 }
988
989 return ValidateBindVertexArrayBase(context, array);
990}
991
992bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
993{
994 if (!context->getExtensions().vertexArrayObject)
995 {
996 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
997 return false;
998 }
999
1000 return ValidateDeleteVertexArraysBase(context, n);
1001}
1002
1003bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1004{
1005 if (!context->getExtensions().vertexArrayObject)
1006 {
1007 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1008 return false;
1009 }
1010
1011 return ValidateGenVertexArraysBase(context, n);
1012}
1013
1014bool ValidateIsVertexArrayOES(Context *context)
1015{
1016 if (!context->getExtensions().vertexArrayObject)
1017 {
1018 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1019 return false;
1020 }
1021
1022 return true;
1023}
Geoff Langc5629752015-12-07 16:29:04 -05001024
1025bool ValidateProgramBinaryOES(Context *context,
1026 GLuint program,
1027 GLenum binaryFormat,
1028 const void *binary,
1029 GLint length)
1030{
1031 if (!context->getExtensions().getProgramBinary)
1032 {
1033 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1034 return false;
1035 }
1036
1037 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1038}
1039
1040bool ValidateGetProgramBinaryOES(Context *context,
1041 GLuint program,
1042 GLsizei bufSize,
1043 GLsizei *length,
1044 GLenum *binaryFormat,
1045 void *binary)
1046{
1047 if (!context->getExtensions().getProgramBinary)
1048 {
1049 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1050 return false;
1051 }
1052
1053 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1054}
Geoff Lange102fee2015-12-10 11:23:30 -05001055
Geoff Lang70d0f492015-12-10 17:45:46 -05001056static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1057{
1058 switch (source)
1059 {
1060 case GL_DEBUG_SOURCE_API:
1061 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1062 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1063 case GL_DEBUG_SOURCE_OTHER:
1064 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1065 return !mustBeThirdPartyOrApplication;
1066
1067 case GL_DEBUG_SOURCE_THIRD_PARTY:
1068 case GL_DEBUG_SOURCE_APPLICATION:
1069 return true;
1070
1071 default:
1072 return false;
1073 }
1074}
1075
1076static bool ValidDebugType(GLenum type)
1077{
1078 switch (type)
1079 {
1080 case GL_DEBUG_TYPE_ERROR:
1081 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1082 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1083 case GL_DEBUG_TYPE_PERFORMANCE:
1084 case GL_DEBUG_TYPE_PORTABILITY:
1085 case GL_DEBUG_TYPE_OTHER:
1086 case GL_DEBUG_TYPE_MARKER:
1087 case GL_DEBUG_TYPE_PUSH_GROUP:
1088 case GL_DEBUG_TYPE_POP_GROUP:
1089 return true;
1090
1091 default:
1092 return false;
1093 }
1094}
1095
1096static bool ValidDebugSeverity(GLenum severity)
1097{
1098 switch (severity)
1099 {
1100 case GL_DEBUG_SEVERITY_HIGH:
1101 case GL_DEBUG_SEVERITY_MEDIUM:
1102 case GL_DEBUG_SEVERITY_LOW:
1103 case GL_DEBUG_SEVERITY_NOTIFICATION:
1104 return true;
1105
1106 default:
1107 return false;
1108 }
1109}
1110
Geoff Lange102fee2015-12-10 11:23:30 -05001111bool ValidateDebugMessageControlKHR(Context *context,
1112 GLenum source,
1113 GLenum type,
1114 GLenum severity,
1115 GLsizei count,
1116 const GLuint *ids,
1117 GLboolean enabled)
1118{
1119 if (!context->getExtensions().debug)
1120 {
1121 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1122 return false;
1123 }
1124
Geoff Lang70d0f492015-12-10 17:45:46 -05001125 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1126 {
1127 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
1128 return false;
1129 }
1130
1131 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1132 {
1133 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug type."));
1134 return false;
1135 }
1136
1137 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1138 {
1139 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
1140 return false;
1141 }
1142
1143 if (count > 0)
1144 {
1145 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1146 {
1147 context->recordError(Error(
1148 GL_INVALID_OPERATION,
1149 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1150 return false;
1151 }
1152
1153 if (severity != GL_DONT_CARE)
1154 {
1155 context->recordError(
1156 Error(GL_INVALID_OPERATION,
1157 "If count is greater than zero, severity must be GL_DONT_CARE."));
1158 return false;
1159 }
1160 }
1161
Geoff Lange102fee2015-12-10 11:23:30 -05001162 return true;
1163}
1164
1165bool ValidateDebugMessageInsertKHR(Context *context,
1166 GLenum source,
1167 GLenum type,
1168 GLuint id,
1169 GLenum severity,
1170 GLsizei length,
1171 const GLchar *buf)
1172{
1173 if (!context->getExtensions().debug)
1174 {
1175 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1176 return false;
1177 }
1178
Geoff Lang70d0f492015-12-10 17:45:46 -05001179 if (!context->getState().getDebug().isOutputEnabled())
1180 {
1181 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1182 // not generate an error.
1183 return false;
1184 }
1185
1186 if (!ValidDebugSeverity(severity))
1187 {
1188 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
1189 return false;
1190 }
1191
1192 if (!ValidDebugType(type))
1193 {
1194 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug type."));
1195 return false;
1196 }
1197
1198 if (!ValidDebugSource(source, true))
1199 {
1200 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
1201 return false;
1202 }
1203
1204 size_t messageLength = (length < 0) ? strlen(buf) : length;
1205 if (messageLength > context->getExtensions().maxDebugMessageLength)
1206 {
1207 context->recordError(
1208 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1209 return false;
1210 }
1211
Geoff Lange102fee2015-12-10 11:23:30 -05001212 return true;
1213}
1214
1215bool ValidateDebugMessageCallbackKHR(Context *context,
1216 GLDEBUGPROCKHR callback,
1217 const void *userParam)
1218{
1219 if (!context->getExtensions().debug)
1220 {
1221 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1222 return false;
1223 }
1224
Geoff Lange102fee2015-12-10 11:23:30 -05001225 return true;
1226}
1227
1228bool ValidateGetDebugMessageLogKHR(Context *context,
1229 GLuint count,
1230 GLsizei bufSize,
1231 GLenum *sources,
1232 GLenum *types,
1233 GLuint *ids,
1234 GLenum *severities,
1235 GLsizei *lengths,
1236 GLchar *messageLog)
1237{
1238 if (!context->getExtensions().debug)
1239 {
1240 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1241 return false;
1242 }
1243
Geoff Lang70d0f492015-12-10 17:45:46 -05001244 if (bufSize < 0 && messageLog != nullptr)
1245 {
1246 context->recordError(
1247 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1248 return false;
1249 }
1250
Geoff Lange102fee2015-12-10 11:23:30 -05001251 return true;
1252}
1253
1254bool ValidatePushDebugGroupKHR(Context *context,
1255 GLenum source,
1256 GLuint id,
1257 GLsizei length,
1258 const GLchar *message)
1259{
1260 if (!context->getExtensions().debug)
1261 {
1262 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1263 return false;
1264 }
1265
Geoff Lang70d0f492015-12-10 17:45:46 -05001266 if (!ValidDebugSource(source, true))
1267 {
1268 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
1269 return false;
1270 }
1271
1272 size_t messageLength = (length < 0) ? strlen(message) : length;
1273 if (messageLength > context->getExtensions().maxDebugMessageLength)
1274 {
1275 context->recordError(
1276 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1277 return false;
1278 }
1279
1280 size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
1281 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1282 {
1283 context->recordError(
1284 Error(GL_STACK_OVERFLOW,
1285 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1286 return false;
1287 }
1288
Geoff Lange102fee2015-12-10 11:23:30 -05001289 return true;
1290}
1291
1292bool ValidatePopDebugGroupKHR(Context *context)
1293{
1294 if (!context->getExtensions().debug)
1295 {
1296 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1297 return false;
1298 }
1299
Geoff Lang70d0f492015-12-10 17:45:46 -05001300 size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
1301 if (currentStackSize <= 1)
1302 {
1303 context->recordError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
1304 return false;
1305 }
1306
1307 return true;
1308}
1309
1310static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1311{
1312 switch (identifier)
1313 {
1314 case GL_BUFFER:
1315 if (context->getBuffer(name) == nullptr)
1316 {
1317 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
1318 return false;
1319 }
1320 return true;
1321
1322 case GL_SHADER:
1323 if (context->getShader(name) == nullptr)
1324 {
1325 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
1326 return false;
1327 }
1328 return true;
1329
1330 case GL_PROGRAM:
1331 if (context->getProgram(name) == nullptr)
1332 {
1333 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid program."));
1334 return false;
1335 }
1336 return true;
1337
1338 case GL_VERTEX_ARRAY:
1339 if (context->getVertexArray(name) == nullptr)
1340 {
1341 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
1342 return false;
1343 }
1344 return true;
1345
1346 case GL_QUERY:
1347 if (context->getQuery(name) == nullptr)
1348 {
1349 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid query."));
1350 return false;
1351 }
1352 return true;
1353
1354 case GL_TRANSFORM_FEEDBACK:
1355 if (context->getTransformFeedback(name) == nullptr)
1356 {
1357 context->recordError(
1358 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1359 return false;
1360 }
1361 return true;
1362
1363 case GL_SAMPLER:
1364 if (context->getSampler(name) == nullptr)
1365 {
1366 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
1367 return false;
1368 }
1369 return true;
1370
1371 case GL_TEXTURE:
1372 if (context->getTexture(name) == nullptr)
1373 {
1374 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
1375 return false;
1376 }
1377 return true;
1378
1379 case GL_RENDERBUFFER:
1380 if (context->getRenderbuffer(name) == nullptr)
1381 {
1382 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
1383 return false;
1384 }
1385 return true;
1386
1387 case GL_FRAMEBUFFER:
1388 if (context->getFramebuffer(name) == nullptr)
1389 {
1390 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
1391 return false;
1392 }
1393 return true;
1394
1395 default:
1396 context->recordError(Error(GL_INVALID_ENUM, "Invalid identifier."));
1397 return false;
1398 }
1399
Geoff Lange102fee2015-12-10 11:23:30 -05001400 return true;
1401}
1402
1403bool ValidateObjectLabelKHR(Context *context,
1404 GLenum identifier,
1405 GLuint name,
1406 GLsizei length,
1407 const GLchar *label)
1408{
1409 if (!context->getExtensions().debug)
1410 {
1411 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1412 return false;
1413 }
1414
Geoff Lang70d0f492015-12-10 17:45:46 -05001415 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1416 {
1417 return false;
1418 }
1419
1420 size_t labelLength = (length < 0) ? strlen(label) : length;
1421 if (labelLength > context->getExtensions().maxLabelLength)
1422 {
1423 context->recordError(
1424 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1425 return false;
1426 }
1427
Geoff Lange102fee2015-12-10 11:23:30 -05001428 return true;
1429}
1430
1431bool ValidateGetObjectLabelKHR(Context *context,
1432 GLenum identifier,
1433 GLuint name,
1434 GLsizei bufSize,
1435 GLsizei *length,
1436 GLchar *label)
1437{
1438 if (!context->getExtensions().debug)
1439 {
1440 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1441 return false;
1442 }
1443
Geoff Lang70d0f492015-12-10 17:45:46 -05001444 if (bufSize < 0)
1445 {
1446 context->recordError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1447 return false;
1448 }
1449
1450 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1451 {
1452 return false;
1453 }
1454
1455 // Can no-op if bufSize is zero.
1456 return bufSize > 0;
1457}
1458
1459static bool ValidateObjectPtrName(Context *context, const void *ptr)
1460{
1461 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1462 {
1463 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
1464 return false;
1465 }
1466
Geoff Lange102fee2015-12-10 11:23:30 -05001467 return true;
1468}
1469
1470bool ValidateObjectPtrLabelKHR(Context *context,
1471 const void *ptr,
1472 GLsizei length,
1473 const GLchar *label)
1474{
1475 if (!context->getExtensions().debug)
1476 {
1477 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1478 return false;
1479 }
1480
Geoff Lang70d0f492015-12-10 17:45:46 -05001481 if (!ValidateObjectPtrName(context, ptr))
1482 {
1483 return false;
1484 }
1485
1486 size_t labelLength = (length < 0) ? strlen(label) : length;
1487 if (labelLength > context->getExtensions().maxLabelLength)
1488 {
1489 context->recordError(
1490 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1491 return false;
1492 }
1493
Geoff Lange102fee2015-12-10 11:23:30 -05001494 return true;
1495}
1496
1497bool ValidateGetObjectPtrLabelKHR(Context *context,
1498 const void *ptr,
1499 GLsizei bufSize,
1500 GLsizei *length,
1501 GLchar *label)
1502{
1503 if (!context->getExtensions().debug)
1504 {
1505 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1506 return false;
1507 }
1508
Geoff Lang70d0f492015-12-10 17:45:46 -05001509 if (bufSize < 0)
1510 {
1511 context->recordError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1512 return false;
1513 }
1514
1515 if (!ValidateObjectPtrName(context, ptr))
1516 {
1517 return false;
1518 }
1519
1520 // Can no-op if bufSize is zero.
1521 return bufSize > 0;
Geoff Lange102fee2015-12-10 11:23:30 -05001522}
1523
1524bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1525{
1526 if (!context->getExtensions().debug)
1527 {
1528 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1529 return false;
1530 }
1531
Geoff Lang70d0f492015-12-10 17:45:46 -05001532 // TODO: represent this in Context::getQueryParameterInfo.
1533 switch (pname)
1534 {
1535 case GL_DEBUG_CALLBACK_FUNCTION:
1536 case GL_DEBUG_CALLBACK_USER_PARAM:
1537 break;
1538
1539 default:
1540 context->recordError(Error(GL_INVALID_ENUM, "Invalid pname."));
1541 return false;
1542 }
1543
Geoff Lange102fee2015-12-10 11:23:30 -05001544 return true;
1545}
Jamie Madillc29968b2016-01-20 11:17:23 -05001546
1547bool ValidateBlitFramebufferANGLE(Context *context,
1548 GLint srcX0,
1549 GLint srcY0,
1550 GLint srcX1,
1551 GLint srcY1,
1552 GLint dstX0,
1553 GLint dstY0,
1554 GLint dstX1,
1555 GLint dstY1,
1556 GLbitfield mask,
1557 GLenum filter)
1558{
1559 if (!context->getExtensions().framebufferBlit)
1560 {
1561 context->recordError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
1562 return false;
1563 }
1564
1565 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1566 {
1567 // TODO(jmadill): Determine if this should be available on other implementations.
1568 context->recordError(Error(
1569 GL_INVALID_OPERATION,
1570 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1571 return false;
1572 }
1573
1574 if (filter == GL_LINEAR)
1575 {
1576 context->recordError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
1577 return false;
1578 }
1579
1580 const Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
1581 const Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
1582
1583 if (mask & GL_COLOR_BUFFER_BIT)
1584 {
1585 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1586 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1587
1588 if (readColorAttachment && drawColorAttachment)
1589 {
1590 if (!(readColorAttachment->type() == GL_TEXTURE &&
1591 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1592 readColorAttachment->type() != GL_RENDERBUFFER &&
1593 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1594 {
1595 context->recordError(Error(GL_INVALID_OPERATION));
1596 return false;
1597 }
1598
1599 for (size_t colorAttachment = 0;
1600 colorAttachment < drawFramebuffer->getNumColorBuffers(); ++colorAttachment)
1601 {
1602 if (drawFramebuffer->isEnabledColorAttachment(colorAttachment))
1603 {
1604 const FramebufferAttachment *attachment =
1605 drawFramebuffer->getColorbuffer(colorAttachment);
1606 ASSERT(attachment);
1607
1608 if (!(attachment->type() == GL_TEXTURE &&
1609 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1610 attachment->type() != GL_RENDERBUFFER &&
1611 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1612 {
1613 context->recordError(Error(GL_INVALID_OPERATION));
1614 return false;
1615 }
1616
1617 // Return an error if the destination formats do not match
1618 if (attachment->getInternalFormat() != readColorAttachment->getInternalFormat())
1619 {
1620 context->recordError(Error(GL_INVALID_OPERATION));
1621 return false;
1622 }
1623 }
1624 }
1625
1626 int readSamples = readFramebuffer->getSamples(context->getData());
1627
1628 if (readSamples != 0 &&
1629 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1630 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1631 {
1632 context->recordError(Error(GL_INVALID_OPERATION));
1633 return false;
1634 }
1635 }
1636 }
1637
1638 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1639 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1640 for (size_t i = 0; i < 2; i++)
1641 {
1642 if (mask & masks[i])
1643 {
1644 const FramebufferAttachment *readBuffer =
1645 readFramebuffer->getAttachment(attachments[i]);
1646 const FramebufferAttachment *drawBuffer =
1647 drawFramebuffer->getAttachment(attachments[i]);
1648
1649 if (readBuffer && drawBuffer)
1650 {
1651 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1652 dstX0, dstY0, dstX1, dstY1))
1653 {
1654 // only whole-buffer copies are permitted
1655 ERR(
1656 "Only whole-buffer depth and stencil blits are supported by this "
1657 "implementation.");
1658 context->recordError(Error(GL_INVALID_OPERATION));
1659 return false;
1660 }
1661
1662 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1663 {
1664 context->recordError(Error(GL_INVALID_OPERATION));
1665 return false;
1666 }
1667 }
1668 }
1669 }
1670
1671 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1672 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001673}
Jamie Madillc29968b2016-01-20 11:17:23 -05001674
1675bool ValidateClear(ValidationContext *context, GLbitfield mask)
1676{
1677 const Framebuffer *framebufferObject = context->getState().getDrawFramebuffer();
1678 ASSERT(framebufferObject);
1679
1680 if (framebufferObject->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
1681 {
1682 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
1683 return false;
1684 }
1685
1686 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1687 {
1688 context->recordError(Error(GL_INVALID_VALUE));
1689 return false;
1690 }
1691
1692 return true;
1693}
1694
1695bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1696{
1697 if (!context->getExtensions().drawBuffers)
1698 {
1699 context->recordError(Error(GL_INVALID_OPERATION, "Extension not supported."));
1700 return false;
1701 }
1702
1703 return ValidateDrawBuffersBase(context, n, bufs);
1704}
1705
1706} // namespace gl