blob: f4964498bcd14a1a78f591336f1a499bc6fbb107 [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
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500461 if (!ValidTexture2DDestinationTarget(context, target))
462 {
463 context->recordError(Error(GL_INVALID_ENUM, "Invalid texture target"));
464 return false;
465 }
466
Jamie Madill560a8d82014-05-21 13:06:20 -0400467 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
468 xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400469 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400470 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400471 }
472
Jamie Madillc29968b2016-01-20 11:17:23 -0500473 const gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400474 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat();
Jamie Madillbc393df2015-01-29 13:46:07 -0500475 const auto &internalFormatInfo = gl::GetInternalFormatInfo(textureInternalFormat);
476 GLenum textureFormat = internalFormatInfo.format;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400477
478 // [OpenGL ES 2.0.24] table 3.9
479 if (isSubImage)
480 {
481 switch (textureFormat)
482 {
483 case GL_ALPHA:
484 if (colorbufferFormat != GL_ALPHA8_EXT &&
485 colorbufferFormat != GL_RGBA4 &&
486 colorbufferFormat != GL_RGB5_A1 &&
487 colorbufferFormat != GL_RGBA8_OES)
488 {
Geoff Langb1196682014-07-23 13:47:29 -0400489 context->recordError(Error(GL_INVALID_OPERATION));
490 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400491 }
492 break;
493 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400494 if (colorbufferFormat != GL_R8_EXT &&
495 colorbufferFormat != GL_RG8_EXT &&
496 colorbufferFormat != GL_RGB565 &&
497 colorbufferFormat != GL_RGB8_OES &&
498 colorbufferFormat != GL_RGBA4 &&
499 colorbufferFormat != GL_RGB5_A1 &&
500 colorbufferFormat != GL_RGBA8_OES)
501 {
Geoff Langb1196682014-07-23 13:47:29 -0400502 context->recordError(Error(GL_INVALID_OPERATION));
503 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400504 }
505 break;
506 case GL_RED_EXT:
507 if (colorbufferFormat != GL_R8_EXT &&
508 colorbufferFormat != GL_RG8_EXT &&
509 colorbufferFormat != GL_RGB565 &&
510 colorbufferFormat != GL_RGB8_OES &&
511 colorbufferFormat != GL_RGBA4 &&
512 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500513 colorbufferFormat != GL_RGBA8_OES &&
514 colorbufferFormat != GL_R32F &&
515 colorbufferFormat != GL_RG32F &&
516 colorbufferFormat != GL_RGB32F &&
517 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400518 {
Geoff Langb1196682014-07-23 13:47:29 -0400519 context->recordError(Error(GL_INVALID_OPERATION));
520 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400521 }
522 break;
523 case GL_RG_EXT:
524 if (colorbufferFormat != GL_RG8_EXT &&
525 colorbufferFormat != GL_RGB565 &&
526 colorbufferFormat != GL_RGB8_OES &&
527 colorbufferFormat != GL_RGBA4 &&
528 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500529 colorbufferFormat != GL_RGBA8_OES &&
530 colorbufferFormat != GL_RG32F &&
531 colorbufferFormat != GL_RGB32F &&
532 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400533 {
Geoff Langb1196682014-07-23 13:47:29 -0400534 context->recordError(Error(GL_INVALID_OPERATION));
535 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400536 }
537 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400538 case GL_RGB:
539 if (colorbufferFormat != GL_RGB565 &&
540 colorbufferFormat != GL_RGB8_OES &&
541 colorbufferFormat != GL_RGBA4 &&
542 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500543 colorbufferFormat != GL_RGBA8_OES &&
544 colorbufferFormat != GL_RGB32F &&
545 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400546 {
Geoff Langb1196682014-07-23 13:47:29 -0400547 context->recordError(Error(GL_INVALID_OPERATION));
548 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400549 }
550 break;
551 case GL_LUMINANCE_ALPHA:
552 case GL_RGBA:
553 if (colorbufferFormat != GL_RGBA4 &&
554 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500555 colorbufferFormat != GL_RGBA8_OES &&
556 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400557 {
Geoff Langb1196682014-07-23 13:47:29 -0400558 context->recordError(Error(GL_INVALID_OPERATION));
559 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400560 }
561 break;
562 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
563 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
564 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
565 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Lang6ea6f942015-09-11 13:11:22 -0400566 case GL_ETC1_RGB8_OES:
Geoff Langb1196682014-07-23 13:47:29 -0400567 context->recordError(Error(GL_INVALID_OPERATION));
568 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400569 case GL_DEPTH_COMPONENT:
570 case GL_DEPTH_STENCIL_OES:
Geoff Langb1196682014-07-23 13:47:29 -0400571 context->recordError(Error(GL_INVALID_OPERATION));
572 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400573 default:
Geoff Langb1196682014-07-23 13:47:29 -0400574 context->recordError(Error(GL_INVALID_OPERATION));
575 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400576 }
Jamie Madillbc393df2015-01-29 13:46:07 -0500577
578 if (internalFormatInfo.type == GL_FLOAT &&
579 !context->getExtensions().textureFloat)
580 {
581 context->recordError(Error(GL_INVALID_OPERATION));
582 return false;
583 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400584 }
585 else
586 {
587 switch (internalformat)
588 {
589 case GL_ALPHA:
590 if (colorbufferFormat != GL_ALPHA8_EXT &&
591 colorbufferFormat != GL_RGBA4 &&
592 colorbufferFormat != GL_RGB5_A1 &&
593 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500594 colorbufferFormat != GL_RGBA8_OES &&
595 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400596 {
Geoff Langb1196682014-07-23 13:47:29 -0400597 context->recordError(Error(GL_INVALID_OPERATION));
598 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400599 }
600 break;
601 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400602 if (colorbufferFormat != GL_R8_EXT &&
603 colorbufferFormat != GL_RG8_EXT &&
604 colorbufferFormat != GL_RGB565 &&
605 colorbufferFormat != GL_RGB8_OES &&
606 colorbufferFormat != GL_RGBA4 &&
607 colorbufferFormat != GL_RGB5_A1 &&
608 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500609 colorbufferFormat != GL_RGBA8_OES &&
610 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400611 {
Geoff Langb1196682014-07-23 13:47:29 -0400612 context->recordError(Error(GL_INVALID_OPERATION));
613 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400614 }
615 break;
616 case GL_RED_EXT:
617 if (colorbufferFormat != GL_R8_EXT &&
618 colorbufferFormat != GL_RG8_EXT &&
619 colorbufferFormat != GL_RGB565 &&
620 colorbufferFormat != GL_RGB8_OES &&
621 colorbufferFormat != GL_RGBA4 &&
622 colorbufferFormat != GL_RGB5_A1 &&
623 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500624 colorbufferFormat != GL_RGBA8_OES &&
625 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400626 {
Geoff Langb1196682014-07-23 13:47:29 -0400627 context->recordError(Error(GL_INVALID_OPERATION));
628 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400629 }
630 break;
631 case GL_RG_EXT:
632 if (colorbufferFormat != GL_RG8_EXT &&
633 colorbufferFormat != GL_RGB565 &&
634 colorbufferFormat != GL_RGB8_OES &&
635 colorbufferFormat != GL_RGBA4 &&
636 colorbufferFormat != GL_RGB5_A1 &&
637 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500638 colorbufferFormat != GL_RGBA8_OES &&
639 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400640 {
Geoff Langb1196682014-07-23 13:47:29 -0400641 context->recordError(Error(GL_INVALID_OPERATION));
642 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400643 }
644 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400645 case GL_RGB:
646 if (colorbufferFormat != GL_RGB565 &&
647 colorbufferFormat != GL_RGB8_OES &&
648 colorbufferFormat != GL_RGBA4 &&
649 colorbufferFormat != GL_RGB5_A1 &&
650 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500651 colorbufferFormat != GL_RGBA8_OES &&
652 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400653 {
Geoff Langb1196682014-07-23 13:47:29 -0400654 context->recordError(Error(GL_INVALID_OPERATION));
655 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400656 }
657 break;
658 case GL_LUMINANCE_ALPHA:
659 case GL_RGBA:
660 if (colorbufferFormat != GL_RGBA4 &&
661 colorbufferFormat != GL_RGB5_A1 &&
662 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500663 colorbufferFormat != GL_RGBA8_OES &&
664 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400665 {
Geoff Langb1196682014-07-23 13:47:29 -0400666 context->recordError(Error(GL_INVALID_OPERATION));
667 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400668 }
669 break;
670 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
671 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400672 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400673 {
Geoff Langb1196682014-07-23 13:47:29 -0400674 context->recordError(Error(GL_INVALID_OPERATION));
675 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400676 }
677 else
678 {
Geoff Langb1196682014-07-23 13:47:29 -0400679 context->recordError(Error(GL_INVALID_ENUM));
680 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400681 }
682 break;
683 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400684 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400685 {
Geoff Langb1196682014-07-23 13:47:29 -0400686 context->recordError(Error(GL_INVALID_OPERATION));
687 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400688 }
689 else
690 {
Geoff Langb1196682014-07-23 13:47:29 -0400691 context->recordError(Error(GL_INVALID_ENUM));
692 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400693 }
694 break;
695 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400696 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400697 {
Geoff Langb1196682014-07-23 13:47:29 -0400698 context->recordError(Error(GL_INVALID_OPERATION));
699 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400700 }
701 else
702 {
Geoff Langb1196682014-07-23 13:47:29 -0400703 context->recordError(Error(GL_INVALID_ENUM));
704 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400705 }
706 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400707 case GL_ETC1_RGB8_OES:
708 if (context->getExtensions().compressedETC1RGB8Texture)
709 {
710 context->recordError(Error(GL_INVALID_OPERATION));
711 return false;
712 }
713 else
714 {
715 context->recordError(Error(GL_INVALID_ENUM));
716 return false;
717 }
718 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400719 case GL_DEPTH_COMPONENT:
720 case GL_DEPTH_COMPONENT16:
721 case GL_DEPTH_COMPONENT32_OES:
722 case GL_DEPTH_STENCIL_OES:
723 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400724 if (context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400725 {
Geoff Langb1196682014-07-23 13:47:29 -0400726 context->recordError(Error(GL_INVALID_OPERATION));
727 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400728 }
729 else
730 {
Geoff Langb1196682014-07-23 13:47:29 -0400731 context->recordError(Error(GL_INVALID_ENUM));
732 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400733 }
734 default:
Geoff Langb1196682014-07-23 13:47:29 -0400735 context->recordError(Error(GL_INVALID_ENUM));
736 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400737 }
738 }
739
Geoff Lang784a8fd2013-09-24 12:33:16 -0400740 // If width or height is zero, it is a no-op. Return false without setting an error.
741 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400742}
743
Geoff Langb1196682014-07-23 13:47:29 -0400744bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400745 GLsizei width, GLsizei height)
746{
747 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
748 {
Geoff Langb1196682014-07-23 13:47:29 -0400749 context->recordError(Error(GL_INVALID_ENUM));
750 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400751 }
752
753 if (width < 1 || height < 1 || levels < 1)
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 (target == GL_TEXTURE_CUBE_MAP && width != height)
760 {
Geoff Langb1196682014-07-23 13:47:29 -0400761 context->recordError(Error(GL_INVALID_VALUE));
762 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400763 }
764
765 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
766 {
Geoff Langb1196682014-07-23 13:47:29 -0400767 context->recordError(Error(GL_INVALID_OPERATION));
768 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400769 }
770
Geoff Lang5d601382014-07-22 15:14:06 -0400771 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
772 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400773 {
Geoff Langb1196682014-07-23 13:47:29 -0400774 context->recordError(Error(GL_INVALID_ENUM));
775 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400776 }
777
Geoff Langaae65a42014-05-26 12:43:44 -0400778 const gl::Caps &caps = context->getCaps();
779
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400780 switch (target)
781 {
782 case GL_TEXTURE_2D:
Geoff Langaae65a42014-05-26 12:43:44 -0400783 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
784 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400785 {
Geoff Langb1196682014-07-23 13:47:29 -0400786 context->recordError(Error(GL_INVALID_VALUE));
787 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400788 }
789 break;
790 case GL_TEXTURE_CUBE_MAP:
Geoff Langaae65a42014-05-26 12:43:44 -0400791 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
792 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400793 {
Geoff Langb1196682014-07-23 13:47:29 -0400794 context->recordError(Error(GL_INVALID_VALUE));
795 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400796 }
797 break;
798 default:
Geoff Langb1196682014-07-23 13:47:29 -0400799 context->recordError(Error(GL_INVALID_ENUM));
800 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400801 }
802
Geoff Langc0b9ef42014-07-02 10:02:37 -0400803 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400804 {
805 if (!gl::isPow2(width) || !gl::isPow2(height))
806 {
Geoff Langb1196682014-07-23 13:47:29 -0400807 context->recordError(Error(GL_INVALID_OPERATION));
808 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400809 }
810 }
811
812 switch (internalformat)
813 {
814 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
815 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400816 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400817 {
Geoff Langb1196682014-07-23 13:47:29 -0400818 context->recordError(Error(GL_INVALID_ENUM));
819 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400820 }
821 break;
822 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400823 if (!context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400824 {
Geoff Langb1196682014-07-23 13:47:29 -0400825 context->recordError(Error(GL_INVALID_ENUM));
826 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400827 }
828 break;
829 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400830 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400831 {
Geoff Langb1196682014-07-23 13:47:29 -0400832 context->recordError(Error(GL_INVALID_ENUM));
833 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400834 }
835 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400836 case GL_ETC1_RGB8_OES:
837 if (!context->getExtensions().compressedETC1RGB8Texture)
838 {
839 context->recordError(Error(GL_INVALID_ENUM));
840 return false;
841 }
842 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400843 case GL_RGBA32F_EXT:
844 case GL_RGB32F_EXT:
845 case GL_ALPHA32F_EXT:
846 case GL_LUMINANCE32F_EXT:
847 case GL_LUMINANCE_ALPHA32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400848 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400849 {
Geoff Langb1196682014-07-23 13:47:29 -0400850 context->recordError(Error(GL_INVALID_ENUM));
851 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400852 }
853 break;
854 case GL_RGBA16F_EXT:
855 case GL_RGB16F_EXT:
856 case GL_ALPHA16F_EXT:
857 case GL_LUMINANCE16F_EXT:
858 case GL_LUMINANCE_ALPHA16F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400859 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400860 {
Geoff Langb1196682014-07-23 13:47:29 -0400861 context->recordError(Error(GL_INVALID_ENUM));
862 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400863 }
864 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400865 case GL_R8_EXT:
866 case GL_RG8_EXT:
867 case GL_R16F_EXT:
868 case GL_RG16F_EXT:
869 case GL_R32F_EXT:
870 case GL_RG32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400871 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400872 {
Geoff Langb1196682014-07-23 13:47:29 -0400873 context->recordError(Error(GL_INVALID_ENUM));
874 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400875 }
876 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400877 case GL_DEPTH_COMPONENT16:
878 case GL_DEPTH_COMPONENT32_OES:
879 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400880 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400881 {
Geoff Langb1196682014-07-23 13:47:29 -0400882 context->recordError(Error(GL_INVALID_ENUM));
883 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400884 }
885 if (target != GL_TEXTURE_2D)
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 // ANGLE_depth_texture only supports 1-level textures
891 if (levels != 1)
892 {
Geoff Langb1196682014-07-23 13:47:29 -0400893 context->recordError(Error(GL_INVALID_OPERATION));
894 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400895 }
896 break;
897 default:
898 break;
899 }
900
Geoff Lang691e58c2014-12-19 17:03:25 -0500901 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400902 if (!texture || texture->id() == 0)
903 {
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
Geoff Lang69cce582015-09-17 13:20:36 -0400908 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400909 {
Geoff Langb1196682014-07-23 13:47:29 -0400910 context->recordError(Error(GL_INVALID_OPERATION));
911 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400912 }
913
914 return true;
915}
916
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400917// check for combinations of format and type that are valid for ReadPixels
Geoff Langb1196682014-07-23 13:47:29 -0400918bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400919{
920 switch (format)
921 {
922 case GL_RGBA:
923 switch (type)
924 {
925 case GL_UNSIGNED_BYTE:
926 break;
927 default:
928 return false;
929 }
930 break;
931 case GL_BGRA_EXT:
932 switch (type)
933 {
934 case GL_UNSIGNED_BYTE:
935 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
936 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
937 break;
938 default:
939 return false;
940 }
941 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400942 case GL_RG_EXT:
943 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400944 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400945 {
946 return false;
947 }
948 switch (type)
949 {
950 case GL_UNSIGNED_BYTE:
951 break;
952 default:
953 return false;
954 }
955 break;
956
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400957 default:
958 return false;
959 }
960 return true;
961}
962
Austin Kinross08332632015-05-05 13:35:47 -0700963bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
964 const GLenum *attachments)
965{
Jamie Madillc29968b2016-01-20 11:17:23 -0500966 if (!context->getExtensions().discardFramebuffer)
967 {
968 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
969 return false;
970 }
971
Austin Kinross08332632015-05-05 13:35:47 -0700972 bool defaultFramebuffer = false;
973
974 switch (target)
975 {
976 case GL_FRAMEBUFFER:
977 defaultFramebuffer = (context->getState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
978 break;
979 default:
980 context->recordError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
981 return false;
982 }
983
984 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
985}
986
Austin Kinrossbc781f32015-10-26 09:27:38 -0700987bool ValidateBindVertexArrayOES(Context *context, GLuint array)
988{
989 if (!context->getExtensions().vertexArrayObject)
990 {
991 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
992 return false;
993 }
994
995 return ValidateBindVertexArrayBase(context, array);
996}
997
998bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
999{
1000 if (!context->getExtensions().vertexArrayObject)
1001 {
1002 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1003 return false;
1004 }
1005
1006 return ValidateDeleteVertexArraysBase(context, n);
1007}
1008
1009bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1010{
1011 if (!context->getExtensions().vertexArrayObject)
1012 {
1013 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1014 return false;
1015 }
1016
1017 return ValidateGenVertexArraysBase(context, n);
1018}
1019
1020bool ValidateIsVertexArrayOES(Context *context)
1021{
1022 if (!context->getExtensions().vertexArrayObject)
1023 {
1024 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1025 return false;
1026 }
1027
1028 return true;
1029}
Geoff Langc5629752015-12-07 16:29:04 -05001030
1031bool ValidateProgramBinaryOES(Context *context,
1032 GLuint program,
1033 GLenum binaryFormat,
1034 const void *binary,
1035 GLint length)
1036{
1037 if (!context->getExtensions().getProgramBinary)
1038 {
1039 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1040 return false;
1041 }
1042
1043 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1044}
1045
1046bool ValidateGetProgramBinaryOES(Context *context,
1047 GLuint program,
1048 GLsizei bufSize,
1049 GLsizei *length,
1050 GLenum *binaryFormat,
1051 void *binary)
1052{
1053 if (!context->getExtensions().getProgramBinary)
1054 {
1055 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1056 return false;
1057 }
1058
1059 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1060}
Geoff Lange102fee2015-12-10 11:23:30 -05001061
Geoff Lang70d0f492015-12-10 17:45:46 -05001062static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1063{
1064 switch (source)
1065 {
1066 case GL_DEBUG_SOURCE_API:
1067 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1068 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1069 case GL_DEBUG_SOURCE_OTHER:
1070 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1071 return !mustBeThirdPartyOrApplication;
1072
1073 case GL_DEBUG_SOURCE_THIRD_PARTY:
1074 case GL_DEBUG_SOURCE_APPLICATION:
1075 return true;
1076
1077 default:
1078 return false;
1079 }
1080}
1081
1082static bool ValidDebugType(GLenum type)
1083{
1084 switch (type)
1085 {
1086 case GL_DEBUG_TYPE_ERROR:
1087 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1088 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1089 case GL_DEBUG_TYPE_PERFORMANCE:
1090 case GL_DEBUG_TYPE_PORTABILITY:
1091 case GL_DEBUG_TYPE_OTHER:
1092 case GL_DEBUG_TYPE_MARKER:
1093 case GL_DEBUG_TYPE_PUSH_GROUP:
1094 case GL_DEBUG_TYPE_POP_GROUP:
1095 return true;
1096
1097 default:
1098 return false;
1099 }
1100}
1101
1102static bool ValidDebugSeverity(GLenum severity)
1103{
1104 switch (severity)
1105 {
1106 case GL_DEBUG_SEVERITY_HIGH:
1107 case GL_DEBUG_SEVERITY_MEDIUM:
1108 case GL_DEBUG_SEVERITY_LOW:
1109 case GL_DEBUG_SEVERITY_NOTIFICATION:
1110 return true;
1111
1112 default:
1113 return false;
1114 }
1115}
1116
Geoff Lange102fee2015-12-10 11:23:30 -05001117bool ValidateDebugMessageControlKHR(Context *context,
1118 GLenum source,
1119 GLenum type,
1120 GLenum severity,
1121 GLsizei count,
1122 const GLuint *ids,
1123 GLboolean enabled)
1124{
1125 if (!context->getExtensions().debug)
1126 {
1127 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1128 return false;
1129 }
1130
Geoff Lang70d0f492015-12-10 17:45:46 -05001131 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1132 {
1133 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
1134 return false;
1135 }
1136
1137 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1138 {
1139 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug type."));
1140 return false;
1141 }
1142
1143 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1144 {
1145 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
1146 return false;
1147 }
1148
1149 if (count > 0)
1150 {
1151 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1152 {
1153 context->recordError(Error(
1154 GL_INVALID_OPERATION,
1155 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1156 return false;
1157 }
1158
1159 if (severity != GL_DONT_CARE)
1160 {
1161 context->recordError(
1162 Error(GL_INVALID_OPERATION,
1163 "If count is greater than zero, severity must be GL_DONT_CARE."));
1164 return false;
1165 }
1166 }
1167
Geoff Lange102fee2015-12-10 11:23:30 -05001168 return true;
1169}
1170
1171bool ValidateDebugMessageInsertKHR(Context *context,
1172 GLenum source,
1173 GLenum type,
1174 GLuint id,
1175 GLenum severity,
1176 GLsizei length,
1177 const GLchar *buf)
1178{
1179 if (!context->getExtensions().debug)
1180 {
1181 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1182 return false;
1183 }
1184
Geoff Lang70d0f492015-12-10 17:45:46 -05001185 if (!context->getState().getDebug().isOutputEnabled())
1186 {
1187 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1188 // not generate an error.
1189 return false;
1190 }
1191
1192 if (!ValidDebugSeverity(severity))
1193 {
1194 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
1195 return false;
1196 }
1197
1198 if (!ValidDebugType(type))
1199 {
1200 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug type."));
1201 return false;
1202 }
1203
1204 if (!ValidDebugSource(source, true))
1205 {
1206 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
1207 return false;
1208 }
1209
1210 size_t messageLength = (length < 0) ? strlen(buf) : length;
1211 if (messageLength > context->getExtensions().maxDebugMessageLength)
1212 {
1213 context->recordError(
1214 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1215 return false;
1216 }
1217
Geoff Lange102fee2015-12-10 11:23:30 -05001218 return true;
1219}
1220
1221bool ValidateDebugMessageCallbackKHR(Context *context,
1222 GLDEBUGPROCKHR callback,
1223 const void *userParam)
1224{
1225 if (!context->getExtensions().debug)
1226 {
1227 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1228 return false;
1229 }
1230
Geoff Lange102fee2015-12-10 11:23:30 -05001231 return true;
1232}
1233
1234bool ValidateGetDebugMessageLogKHR(Context *context,
1235 GLuint count,
1236 GLsizei bufSize,
1237 GLenum *sources,
1238 GLenum *types,
1239 GLuint *ids,
1240 GLenum *severities,
1241 GLsizei *lengths,
1242 GLchar *messageLog)
1243{
1244 if (!context->getExtensions().debug)
1245 {
1246 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1247 return false;
1248 }
1249
Geoff Lang70d0f492015-12-10 17:45:46 -05001250 if (bufSize < 0 && messageLog != nullptr)
1251 {
1252 context->recordError(
1253 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1254 return false;
1255 }
1256
Geoff Lange102fee2015-12-10 11:23:30 -05001257 return true;
1258}
1259
1260bool ValidatePushDebugGroupKHR(Context *context,
1261 GLenum source,
1262 GLuint id,
1263 GLsizei length,
1264 const GLchar *message)
1265{
1266 if (!context->getExtensions().debug)
1267 {
1268 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1269 return false;
1270 }
1271
Geoff Lang70d0f492015-12-10 17:45:46 -05001272 if (!ValidDebugSource(source, true))
1273 {
1274 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
1275 return false;
1276 }
1277
1278 size_t messageLength = (length < 0) ? strlen(message) : length;
1279 if (messageLength > context->getExtensions().maxDebugMessageLength)
1280 {
1281 context->recordError(
1282 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1283 return false;
1284 }
1285
1286 size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
1287 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1288 {
1289 context->recordError(
1290 Error(GL_STACK_OVERFLOW,
1291 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1292 return false;
1293 }
1294
Geoff Lange102fee2015-12-10 11:23:30 -05001295 return true;
1296}
1297
1298bool ValidatePopDebugGroupKHR(Context *context)
1299{
1300 if (!context->getExtensions().debug)
1301 {
1302 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1303 return false;
1304 }
1305
Geoff Lang70d0f492015-12-10 17:45:46 -05001306 size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
1307 if (currentStackSize <= 1)
1308 {
1309 context->recordError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
1310 return false;
1311 }
1312
1313 return true;
1314}
1315
1316static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1317{
1318 switch (identifier)
1319 {
1320 case GL_BUFFER:
1321 if (context->getBuffer(name) == nullptr)
1322 {
1323 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
1324 return false;
1325 }
1326 return true;
1327
1328 case GL_SHADER:
1329 if (context->getShader(name) == nullptr)
1330 {
1331 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
1332 return false;
1333 }
1334 return true;
1335
1336 case GL_PROGRAM:
1337 if (context->getProgram(name) == nullptr)
1338 {
1339 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid program."));
1340 return false;
1341 }
1342 return true;
1343
1344 case GL_VERTEX_ARRAY:
1345 if (context->getVertexArray(name) == nullptr)
1346 {
1347 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
1348 return false;
1349 }
1350 return true;
1351
1352 case GL_QUERY:
1353 if (context->getQuery(name) == nullptr)
1354 {
1355 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid query."));
1356 return false;
1357 }
1358 return true;
1359
1360 case GL_TRANSFORM_FEEDBACK:
1361 if (context->getTransformFeedback(name) == nullptr)
1362 {
1363 context->recordError(
1364 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1365 return false;
1366 }
1367 return true;
1368
1369 case GL_SAMPLER:
1370 if (context->getSampler(name) == nullptr)
1371 {
1372 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
1373 return false;
1374 }
1375 return true;
1376
1377 case GL_TEXTURE:
1378 if (context->getTexture(name) == nullptr)
1379 {
1380 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
1381 return false;
1382 }
1383 return true;
1384
1385 case GL_RENDERBUFFER:
1386 if (context->getRenderbuffer(name) == nullptr)
1387 {
1388 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
1389 return false;
1390 }
1391 return true;
1392
1393 case GL_FRAMEBUFFER:
1394 if (context->getFramebuffer(name) == nullptr)
1395 {
1396 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
1397 return false;
1398 }
1399 return true;
1400
1401 default:
1402 context->recordError(Error(GL_INVALID_ENUM, "Invalid identifier."));
1403 return false;
1404 }
1405
Geoff Lange102fee2015-12-10 11:23:30 -05001406 return true;
1407}
1408
1409bool ValidateObjectLabelKHR(Context *context,
1410 GLenum identifier,
1411 GLuint name,
1412 GLsizei length,
1413 const GLchar *label)
1414{
1415 if (!context->getExtensions().debug)
1416 {
1417 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1418 return false;
1419 }
1420
Geoff Lang70d0f492015-12-10 17:45:46 -05001421 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1422 {
1423 return false;
1424 }
1425
1426 size_t labelLength = (length < 0) ? strlen(label) : length;
1427 if (labelLength > context->getExtensions().maxLabelLength)
1428 {
1429 context->recordError(
1430 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1431 return false;
1432 }
1433
Geoff Lange102fee2015-12-10 11:23:30 -05001434 return true;
1435}
1436
1437bool ValidateGetObjectLabelKHR(Context *context,
1438 GLenum identifier,
1439 GLuint name,
1440 GLsizei bufSize,
1441 GLsizei *length,
1442 GLchar *label)
1443{
1444 if (!context->getExtensions().debug)
1445 {
1446 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1447 return false;
1448 }
1449
Geoff Lang70d0f492015-12-10 17:45:46 -05001450 if (bufSize < 0)
1451 {
1452 context->recordError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1453 return false;
1454 }
1455
1456 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1457 {
1458 return false;
1459 }
1460
1461 // Can no-op if bufSize is zero.
1462 return bufSize > 0;
1463}
1464
1465static bool ValidateObjectPtrName(Context *context, const void *ptr)
1466{
1467 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1468 {
1469 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
1470 return false;
1471 }
1472
Geoff Lange102fee2015-12-10 11:23:30 -05001473 return true;
1474}
1475
1476bool ValidateObjectPtrLabelKHR(Context *context,
1477 const void *ptr,
1478 GLsizei length,
1479 const GLchar *label)
1480{
1481 if (!context->getExtensions().debug)
1482 {
1483 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1484 return false;
1485 }
1486
Geoff Lang70d0f492015-12-10 17:45:46 -05001487 if (!ValidateObjectPtrName(context, ptr))
1488 {
1489 return false;
1490 }
1491
1492 size_t labelLength = (length < 0) ? strlen(label) : length;
1493 if (labelLength > context->getExtensions().maxLabelLength)
1494 {
1495 context->recordError(
1496 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1497 return false;
1498 }
1499
Geoff Lange102fee2015-12-10 11:23:30 -05001500 return true;
1501}
1502
1503bool ValidateGetObjectPtrLabelKHR(Context *context,
1504 const void *ptr,
1505 GLsizei bufSize,
1506 GLsizei *length,
1507 GLchar *label)
1508{
1509 if (!context->getExtensions().debug)
1510 {
1511 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1512 return false;
1513 }
1514
Geoff Lang70d0f492015-12-10 17:45:46 -05001515 if (bufSize < 0)
1516 {
1517 context->recordError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1518 return false;
1519 }
1520
1521 if (!ValidateObjectPtrName(context, ptr))
1522 {
1523 return false;
1524 }
1525
1526 // Can no-op if bufSize is zero.
1527 return bufSize > 0;
Geoff Lange102fee2015-12-10 11:23:30 -05001528}
1529
1530bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1531{
1532 if (!context->getExtensions().debug)
1533 {
1534 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1535 return false;
1536 }
1537
Geoff Lang70d0f492015-12-10 17:45:46 -05001538 // TODO: represent this in Context::getQueryParameterInfo.
1539 switch (pname)
1540 {
1541 case GL_DEBUG_CALLBACK_FUNCTION:
1542 case GL_DEBUG_CALLBACK_USER_PARAM:
1543 break;
1544
1545 default:
1546 context->recordError(Error(GL_INVALID_ENUM, "Invalid pname."));
1547 return false;
1548 }
1549
Geoff Lange102fee2015-12-10 11:23:30 -05001550 return true;
1551}
Jamie Madillc29968b2016-01-20 11:17:23 -05001552
1553bool ValidateBlitFramebufferANGLE(Context *context,
1554 GLint srcX0,
1555 GLint srcY0,
1556 GLint srcX1,
1557 GLint srcY1,
1558 GLint dstX0,
1559 GLint dstY0,
1560 GLint dstX1,
1561 GLint dstY1,
1562 GLbitfield mask,
1563 GLenum filter)
1564{
1565 if (!context->getExtensions().framebufferBlit)
1566 {
1567 context->recordError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
1568 return false;
1569 }
1570
1571 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1572 {
1573 // TODO(jmadill): Determine if this should be available on other implementations.
1574 context->recordError(Error(
1575 GL_INVALID_OPERATION,
1576 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1577 return false;
1578 }
1579
1580 if (filter == GL_LINEAR)
1581 {
1582 context->recordError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
1583 return false;
1584 }
1585
1586 const Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
1587 const Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
1588
1589 if (mask & GL_COLOR_BUFFER_BIT)
1590 {
1591 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1592 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1593
1594 if (readColorAttachment && drawColorAttachment)
1595 {
1596 if (!(readColorAttachment->type() == GL_TEXTURE &&
1597 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1598 readColorAttachment->type() != GL_RENDERBUFFER &&
1599 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1600 {
1601 context->recordError(Error(GL_INVALID_OPERATION));
1602 return false;
1603 }
1604
Geoff Langa15472a2015-08-11 11:48:03 -04001605 for (size_t drawbufferIdx = 0;
1606 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001607 {
Geoff Langa15472a2015-08-11 11:48:03 -04001608 const FramebufferAttachment *attachment =
1609 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1610 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001611 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001612 if (!(attachment->type() == GL_TEXTURE &&
1613 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1614 attachment->type() != GL_RENDERBUFFER &&
1615 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1616 {
1617 context->recordError(Error(GL_INVALID_OPERATION));
1618 return false;
1619 }
1620
1621 // Return an error if the destination formats do not match
1622 if (attachment->getInternalFormat() != readColorAttachment->getInternalFormat())
1623 {
1624 context->recordError(Error(GL_INVALID_OPERATION));
1625 return false;
1626 }
1627 }
1628 }
1629
1630 int readSamples = readFramebuffer->getSamples(context->getData());
1631
1632 if (readSamples != 0 &&
1633 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1634 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1635 {
1636 context->recordError(Error(GL_INVALID_OPERATION));
1637 return false;
1638 }
1639 }
1640 }
1641
1642 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1643 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1644 for (size_t i = 0; i < 2; i++)
1645 {
1646 if (mask & masks[i])
1647 {
1648 const FramebufferAttachment *readBuffer =
1649 readFramebuffer->getAttachment(attachments[i]);
1650 const FramebufferAttachment *drawBuffer =
1651 drawFramebuffer->getAttachment(attachments[i]);
1652
1653 if (readBuffer && drawBuffer)
1654 {
1655 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1656 dstX0, dstY0, dstX1, dstY1))
1657 {
1658 // only whole-buffer copies are permitted
1659 ERR(
1660 "Only whole-buffer depth and stencil blits are supported by this "
1661 "implementation.");
1662 context->recordError(Error(GL_INVALID_OPERATION));
1663 return false;
1664 }
1665
1666 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1667 {
1668 context->recordError(Error(GL_INVALID_OPERATION));
1669 return false;
1670 }
1671 }
1672 }
1673 }
1674
1675 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1676 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001677}
Jamie Madillc29968b2016-01-20 11:17:23 -05001678
1679bool ValidateClear(ValidationContext *context, GLbitfield mask)
1680{
1681 const Framebuffer *framebufferObject = context->getState().getDrawFramebuffer();
1682 ASSERT(framebufferObject);
1683
1684 if (framebufferObject->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
1685 {
1686 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
1687 return false;
1688 }
1689
1690 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1691 {
1692 context->recordError(Error(GL_INVALID_VALUE));
1693 return false;
1694 }
1695
1696 return true;
1697}
1698
1699bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1700{
1701 if (!context->getExtensions().drawBuffers)
1702 {
1703 context->recordError(Error(GL_INVALID_OPERATION, "Extension not supported."));
1704 return false;
1705 }
1706
1707 return ValidateDrawBuffersBase(context, n, bufs);
1708}
1709
1710} // namespace gl