/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "GLESv2Validation.h" #include <sstream> namespace GLESv2Validation { GLbitfield allBufferMapAccessFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT; bool bufferTarget(GL2Encoder* ctx, GLenum target) { int glesMajorVersion = ctx->majorVersion(); int glesMinorVersion = ctx->minorVersion(); switch (target) { case GL_ARRAY_BUFFER: // Vertex attributes case GL_ELEMENT_ARRAY_BUFFER: // Vertex array indices return true; // GLES 3.0 buffers case GL_COPY_READ_BUFFER: // Buffer copy source case GL_COPY_WRITE_BUFFER: // Buffer copy destination case GL_PIXEL_PACK_BUFFER: // Pixel read target case GL_PIXEL_UNPACK_BUFFER: // Texture data source case GL_TRANSFORM_FEEDBACK_BUFFER: // Transform feedback buffer case GL_UNIFORM_BUFFER: // Uniform block storage return glesMajorVersion >= 3; // GLES 3.1 buffers case GL_ATOMIC_COUNTER_BUFFER: // Atomic counter storage case GL_DISPATCH_INDIRECT_BUFFER: // Indirect compute dispatch commands case GL_DRAW_INDIRECT_BUFFER: // Indirect command arguments case GL_SHADER_STORAGE_BUFFER: // Read-write storage for shaders return glesMajorVersion >= 3 && glesMinorVersion >= 1; default: return false; } } bool bufferParam(GL2Encoder* ctx, GLenum pname) { int glesMajorVersion = ctx->majorVersion(); int glesMinorVersion = ctx->minorVersion(); switch (pname) { case GL_BUFFER_SIZE: case GL_BUFFER_USAGE: return true; case GL_BUFFER_ACCESS_FLAGS: case GL_BUFFER_MAPPED: case GL_BUFFER_MAP_LENGTH: case GL_BUFFER_MAP_OFFSET: return glesMajorVersion >= 3; default: return false; } } bool pixelStoreParam(GL2Encoder* ctx, GLenum param) { int glesMajorVersion = ctx->majorVersion(); switch(param) { case GL_UNPACK_ALIGNMENT: case GL_PACK_ALIGNMENT: return true; case GL_UNPACK_ROW_LENGTH: case GL_UNPACK_IMAGE_HEIGHT: case GL_UNPACK_SKIP_PIXELS: case GL_UNPACK_SKIP_ROWS: case GL_UNPACK_SKIP_IMAGES: case GL_PACK_ROW_LENGTH: case GL_PACK_SKIP_PIXELS: case GL_PACK_SKIP_ROWS: return glesMajorVersion >= 3; default: return false; } } bool pixelStoreValue(GLenum param, GLint value) { switch(param) { case GL_UNPACK_ALIGNMENT: case GL_PACK_ALIGNMENT: return (value == 1) || (value == 2) || (value == 4) || (value == 8); case GL_UNPACK_ROW_LENGTH: case GL_UNPACK_IMAGE_HEIGHT: case GL_UNPACK_SKIP_PIXELS: case GL_UNPACK_SKIP_ROWS: case GL_UNPACK_SKIP_IMAGES: case GL_PACK_ROW_LENGTH: case GL_PACK_SKIP_PIXELS: case GL_PACK_SKIP_ROWS: return value >= 0; default: return false; } } bool rboFormat(GL2Encoder* ctx, GLenum internalformat) { int glesMajorVersion = ctx->majorVersion(); switch (internalformat) { // Funny internal formats // that will cause an incomplete framebuffer // attachment error pre-gles3. For dEQP, // we can also just abort early here in // RenderbufferStorage with a GL_INVALID_ENUM. case GL_DEPTH_COMPONENT32F: case GL_R8: case GL_R8UI: case GL_R8I: case GL_R16UI: case GL_R16I: case GL_R32UI: case GL_R32I: case GL_RG8: case GL_RG8UI: case GL_RG8I: case GL_RG16UI: case GL_RG16I: case GL_RG32UI: case GL_RG32I: case GL_SRGB8_ALPHA8: case GL_RGBA8UI: case GL_RGBA8I: case GL_RGB10_A2: case GL_RGB10_A2UI: case GL_RGBA16UI: case GL_RGBA16I: case GL_RGBA32I: case GL_RGBA32UI: case GL_RGB32F: return glesMajorVersion >= 3; // These 4 formats are still not OK, // but dEQP expects GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT or // GL_FRAMEBUFFER_UNSUPPORTED if the extension is not present, // not a GL_INVALID_ENUM from earlier on. // So let's forward these to the rest of // FBO initialization // In GLES 3, these are rejected immediately if not // supported. case GL_R16F: case GL_RG16F: case GL_RGBA16F: case GL_R32F: case GL_RG32F: case GL_RGBA32F: case GL_R11F_G11F_B10F: return glesMajorVersion >= 3 && ctx->hasExtension("GL_EXT_color_buffer_float"); case GL_RGB16F: return glesMajorVersion >= 3 && ctx->hasExtension("GL_EXT_color_buffer_half_float"); // dEQP expects GL_FRAMEBUFFER_UNSUPPORTED or GL_FRAMEBUFFER_COMPLETE // for this format // These formats are OK case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT24: case GL_DEPTH_COMPONENT32_OES: case GL_RGBA4: case GL_RGB5_A1: case GL_RGB565: case GL_RGB8_OES: case GL_RGBA8_OES: case GL_STENCIL_INDEX8: case GL_DEPTH32F_STENCIL8: case GL_DEPTH24_STENCIL8_OES: return true; break; // Everything else: still not OK, // and they need the GL_INVALID_ENUM } return false; } bool framebufferTarget(GL2Encoder* ctx, GLenum target) { int glesMajorVersion = ctx->majorVersion(); switch (target) { case GL_FRAMEBUFFER: return true; case GL_DRAW_FRAMEBUFFER: case GL_READ_FRAMEBUFFER: return glesMajorVersion >= 3; } return false; } bool framebufferAttachment(GL2Encoder* ctx, GLenum attachment) { int glesMajorVersion = ctx->majorVersion(); switch (attachment) { case GL_COLOR_ATTACHMENT0: case GL_DEPTH_ATTACHMENT: case GL_STENCIL_ATTACHMENT: return true; case GL_COLOR_ATTACHMENT1: case GL_COLOR_ATTACHMENT2: case GL_COLOR_ATTACHMENT3: case GL_COLOR_ATTACHMENT4: case GL_COLOR_ATTACHMENT5: case GL_COLOR_ATTACHMENT6: case GL_COLOR_ATTACHMENT7: case GL_COLOR_ATTACHMENT8: case GL_COLOR_ATTACHMENT9: case GL_COLOR_ATTACHMENT10: case GL_COLOR_ATTACHMENT11: case GL_COLOR_ATTACHMENT12: case GL_COLOR_ATTACHMENT13: case GL_COLOR_ATTACHMENT14: case GL_COLOR_ATTACHMENT15: case GL_DEPTH_STENCIL_ATTACHMENT: return glesMajorVersion >= 3; } return false; } bool readPixelsFormat(GLenum format) { switch (format) { case GL_RED: case GL_RED_INTEGER: case GL_RG: case GL_RG_INTEGER: case GL_RGB: case GL_RGB_INTEGER: case GL_RGBA: case GL_RGBA_INTEGER: case GL_LUMINANCE_ALPHA: case GL_LUMINANCE: case GL_ALPHA: return true; } return false; } bool readPixelsType(GLenum format) { switch (format) { case GL_UNSIGNED_BYTE: case GL_BYTE: case GL_HALF_FLOAT: case GL_FLOAT: case GL_INT: case GL_UNSIGNED_SHORT_5_6_5: case GL_UNSIGNED_SHORT_4_4_4_4: case GL_UNSIGNED_SHORT_5_5_5_1: case GL_UNSIGNED_INT: case GL_UNSIGNED_INT_2_10_10_10_REV: case GL_UNSIGNED_INT_10F_11F_11F_REV: case GL_UNSIGNED_INT_5_9_9_9_REV: return true; } return false; } bool vertexAttribType(GL2Encoder* ctx, GLenum type) { int glesMajorVersion = ctx->majorVersion(); bool retval = false; switch (type) { case GL_BYTE: case GL_UNSIGNED_BYTE: case GL_SHORT: case GL_UNSIGNED_SHORT: case GL_FIXED: case GL_FLOAT: // The following are technically only available if certain GLES2 extensions are. // However, they are supported by desktop GL3, which is a reasonable requirement // for the desktop GL version. Therefore, consider them valid. case GL_INT: case GL_UNSIGNED_INT: case GL_HALF_FLOAT_OES: retval = true; break; case GL_HALF_FLOAT: case GL_INT_2_10_10_10_REV: case GL_UNSIGNED_INT_2_10_10_10_REV: retval = glesMajorVersion >= 3; break; } return retval; } bool readPixelsFboFormatMatch(GLenum format, GLenum type, GLenum fboTexType) { #define INVALID_TYPE_MATCH(x, y) \ if (type == x && fboTexType == y) return false; \ if (type == y && fboTexType == x) return false; \ // These are meant to reject additional format/type mismatches // not caught by underlying system. INVALID_TYPE_MATCH(GL_FLOAT, GL_BYTE) INVALID_TYPE_MATCH(GL_FLOAT, GL_UNSIGNED_BYTE) INVALID_TYPE_MATCH(GL_FLOAT, GL_UNSIGNED_INT) INVALID_TYPE_MATCH(GL_FLOAT, GL_INT) return true; } bool blitFramebufferFormat(GLenum readFormat, GLenum drawFormat) { #define INVALID_MATCH(x, y) \ if (readFormat == x && drawFormat == y) return false; \ if (readFormat == y && drawFormat == x) return false; \ INVALID_MATCH(GL_FLOAT, GL_BYTE) INVALID_MATCH(GL_FLOAT, GL_UNSIGNED_BYTE) INVALID_MATCH(GL_FLOAT, GL_UNSIGNED_INT) INVALID_MATCH(GL_FLOAT, GL_INT) INVALID_MATCH(GL_INT, GL_UNSIGNED_BYTE); INVALID_MATCH(GL_UNSIGNED_INT, GL_UNSIGNED_BYTE); INVALID_MATCH(GL_INT, GL_BYTE); INVALID_MATCH(GL_UNSIGNED_INT, GL_BYTE); INVALID_MATCH(GL_DEPTH32F_STENCIL8, GL_DEPTH24_STENCIL8); return true; } bool textureTarget(GL2Encoder* ctx, GLenum target) { int glesMajorVersion = ctx->majorVersion(); int glesMinorVersion = ctx->minorVersion(); switch (target) { case GL_TEXTURE_EXTERNAL_OES: case GL_TEXTURE_2D: case GL_TEXTURE_CUBE_MAP: case GL_TEXTURE_CUBE_MAP_POSITIVE_X: case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: return true; case GL_TEXTURE_2D_ARRAY: case GL_TEXTURE_3D: return glesMajorVersion >= 3; case GL_TEXTURE_2D_MULTISAMPLE: return glesMajorVersion >= 3 && glesMinorVersion >= 1; default: break; } return false; } static GLsizei ceildiv(GLsizei x, GLsizei y) { return (x + y - 1) / y; } GLsizei compressedTexImageSize(GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { GLsizei base_size = ceildiv(width, 4) * ceildiv(height, 4) * depth; #define COMPRESSED_TEX_IMAGE_SIZE_CASE(internal, multiplier) \ case internal: \ return base_size * multiplier; \ switch (internalformat) { COMPRESSED_TEX_IMAGE_SIZE_CASE(GL_COMPRESSED_R11_EAC, 8) COMPRESSED_TEX_IMAGE_SIZE_CASE(GL_COMPRESSED_SIGNED_R11_EAC, 8) COMPRESSED_TEX_IMAGE_SIZE_CASE(GL_COMPRESSED_RG11_EAC, 16) COMPRESSED_TEX_IMAGE_SIZE_CASE(GL_COMPRESSED_SIGNED_RG11_EAC, 16) COMPRESSED_TEX_IMAGE_SIZE_CASE(GL_COMPRESSED_RGB8_ETC2, 8) COMPRESSED_TEX_IMAGE_SIZE_CASE(GL_COMPRESSED_SRGB8_ETC2, 8) COMPRESSED_TEX_IMAGE_SIZE_CASE(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 8) COMPRESSED_TEX_IMAGE_SIZE_CASE(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 8) COMPRESSED_TEX_IMAGE_SIZE_CASE(GL_COMPRESSED_RGBA8_ETC2_EAC, 16) COMPRESSED_TEX_IMAGE_SIZE_CASE(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, 16) default: break; } return 0; } bool isCompressedFormat(GLenum internalformat) { #define COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(internal) \ case internal: \ return true; \ switch (internalformat) { COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_R11_EAC) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_SIGNED_R11_EAC) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_RG11_EAC) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_SIGNED_RG11_EAC) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_RGB8_ETC2) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_SRGB8_ETC2) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_RGBA8_ETC2_EAC) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_RGBA_ASTC_4x4_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_RGBA_ASTC_5x4_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_RGBA_ASTC_5x5_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_RGBA_ASTC_6x5_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_RGBA_ASTC_6x6_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_RGBA_ASTC_8x5_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_RGBA_ASTC_8x6_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_RGBA_ASTC_8x8_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_RGBA_ASTC_10x5_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_RGBA_ASTC_10x6_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_RGBA_ASTC_10x8_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_RGBA_ASTC_10x10_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_RGBA_ASTC_12x10_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_RGBA_ASTC_12x12_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR) COMPRESSED_TEX_IMAGE_IS_COMPRESSED_FORMAT_CASE(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR) default: break; } return false; } bool supportedCompressedFormat(GL2Encoder* ctx, GLenum internalformat) { int glesMajorVersion = ctx->majorVersion(); int glesMinorVersion = ctx->minorVersion(); #define COMPRESSED_TEX_IMAGE_SUPPORT_CASE(internal, maj, min) \ case internal: \ if (maj < 3) return true; \ if (glesMajorVersion < maj) return false; \ if (glesMinorVersion < min) return false; \ break; \ #define COMPRESSED_TEX_IMAGE_NOTSUPPORTED(internal) \ case internal: \ return false ; \ switch (internalformat) { COMPRESSED_TEX_IMAGE_SUPPORT_CASE(GL_COMPRESSED_R11_EAC, 2, 0) COMPRESSED_TEX_IMAGE_SUPPORT_CASE(GL_COMPRESSED_SIGNED_R11_EAC, 2, 0) COMPRESSED_TEX_IMAGE_SUPPORT_CASE(GL_COMPRESSED_RG11_EAC, 2, 0) COMPRESSED_TEX_IMAGE_SUPPORT_CASE(GL_COMPRESSED_SIGNED_RG11_EAC, 2, 0) COMPRESSED_TEX_IMAGE_SUPPORT_CASE(GL_COMPRESSED_RGB8_ETC2, 2, 0) COMPRESSED_TEX_IMAGE_SUPPORT_CASE(GL_COMPRESSED_SRGB8_ETC2, 2, 0) COMPRESSED_TEX_IMAGE_SUPPORT_CASE(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 2, 0) COMPRESSED_TEX_IMAGE_SUPPORT_CASE(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 2, 0) COMPRESSED_TEX_IMAGE_SUPPORT_CASE(GL_COMPRESSED_RGBA8_ETC2_EAC, 2, 0) COMPRESSED_TEX_IMAGE_SUPPORT_CASE(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, 2, 0) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_RGBA_ASTC_4x4_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_RGBA_ASTC_5x4_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_RGBA_ASTC_5x5_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_RGBA_ASTC_6x5_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_RGBA_ASTC_6x6_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_RGBA_ASTC_8x5_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_RGBA_ASTC_8x6_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_RGBA_ASTC_8x8_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_RGBA_ASTC_10x5_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_RGBA_ASTC_10x6_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_RGBA_ASTC_10x8_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_RGBA_ASTC_10x10_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_RGBA_ASTC_12x10_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_RGBA_ASTC_12x12_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR) COMPRESSED_TEX_IMAGE_NOTSUPPORTED(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR) default: break; } return true; } bool unsizedFormat(GLenum format) { switch (format) { case GL_RED: case GL_RED_INTEGER: case GL_DEPTH_COMPONENT: case GL_DEPTH_STENCIL: case GL_RG: case GL_RG_INTEGER: case GL_RGB: case GL_RGB_INTEGER: case GL_RGBA: case GL_RGBA_INTEGER: case GL_ALPHA: case GL_LUMINANCE: case GL_LUMINANCE_ALPHA: return true; } return false; } // TODO: fix this bool filterableTexFormat(GL2Encoder* ctx, GLenum internalformat) { switch (internalformat) { case GL_R32F: case GL_RG32F: case GL_RGB32F: case GL_RGBA32F: return ctx->hasExtension("GL_OES_texture_float"); case GL_R8UI: case GL_R8I: case GL_R16UI: case GL_R16I: case GL_R32UI: case GL_R32I: case GL_RG8UI: case GL_RG8I: case GL_RG16UI: case GL_RG16I: case GL_RG32UI: case GL_RG32I: case GL_RGBA8UI: case GL_RGBA8I: case GL_RGB10_A2UI: case GL_RGBA16UI: case GL_RGBA16I: case GL_RGBA32I: case GL_RGBA32UI: return false; } return true; } bool colorRenderableFormat(GL2Encoder* ctx, GLenum internalformat) { int glesMajorVersion = ctx->majorVersion(); switch (internalformat) { case GL_R8: case GL_RG8: case GL_RGB8: case GL_RGB565: case GL_RGBA4: case GL_RGB5_A1: case GL_RGBA8: case GL_RGB10_A2: case GL_RGB10_A2UI: case GL_SRGB8_ALPHA8: case GL_R8I: case GL_R8UI: case GL_R16I: case GL_R16UI: case GL_R32I: case GL_R32UI: case GL_RG8I: case GL_RG8UI: case GL_RG16I: case GL_RG16UI: case GL_RG32I: case GL_RG32UI: case GL_RGBA8I: case GL_RGBA8UI: case GL_RGBA16I: case GL_RGBA16UI: case GL_RGBA32I: case GL_RGBA32UI: return true; case GL_R16F: case GL_RG16F: case GL_RGBA16F: case GL_R32F: case GL_RG32F: case GL_RGBA32F: case GL_R11F_G11F_B10F: return glesMajorVersion >= 3 && ctx->hasExtension("GL_EXT_color_buffer_float"); break; case GL_RGB16F: return glesMajorVersion >= 3 && ctx->hasExtension("GL_EXT_color_buffer_half_float"); break; } return false; } bool depthRenderableFormat(GL2Encoder* ctx, GLenum internalformat) { switch (internalformat) { case GL_DEPTH_COMPONENT: case GL_DEPTH_STENCIL: case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT24: case GL_DEPTH_COMPONENT32F: case GL_DEPTH24_STENCIL8: case GL_DEPTH32F_STENCIL8: return true; } return false; } bool stencilRenderableFormat(GL2Encoder* ctx, GLenum internalformat) { switch (internalformat) { case GL_DEPTH_STENCIL: case GL_STENCIL_INDEX8: case GL_DEPTH24_STENCIL8: case GL_DEPTH32F_STENCIL8: return true; } return false; } bool isCubeMapTarget(GLenum target) { switch (target) { case GL_TEXTURE_CUBE_MAP_POSITIVE_X: case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: return true; default: break; } return false; } #define LIST_VALID_TEXFORMATS(f) \ f(GL_DEPTH_COMPONENT) \ f(GL_DEPTH_STENCIL) \ f(GL_RED) \ f(GL_RED_INTEGER) \ f(GL_RG) \ f(GL_RGB) \ f(GL_RGBA) \ f(GL_RGBA_INTEGER) \ f(GL_RGB_INTEGER) \ f(GL_RG_INTEGER) \ f(GL_BGRA_EXT) \ f(GL_ALPHA) \ f(GL_LUMINANCE) \ f(GL_LUMINANCE_ALPHA) \ #define LIST_VALID_TEXTYPES(f) \ f(GL_BYTE) \ f(GL_FLOAT) \ f(GL_FLOAT_32_UNSIGNED_INT_24_8_REV) \ f(GL_HALF_FLOAT) \ f(GL_HALF_FLOAT_OES) \ f(GL_INT) \ f(GL_SHORT) \ f(GL_UNSIGNED_BYTE) \ f(GL_UNSIGNED_INT) \ f(GL_UNSIGNED_INT_10F_11F_11F_REV) \ f(GL_UNSIGNED_INT_2_10_10_10_REV) \ f(GL_UNSIGNED_INT_24_8) \ f(GL_UNSIGNED_INT_5_9_9_9_REV) \ f(GL_UNSIGNED_SHORT) \ f(GL_UNSIGNED_SHORT_4_4_4_4) \ f(GL_UNSIGNED_SHORT_5_5_5_1) \ f(GL_UNSIGNED_SHORT_5_6_5) \ bool pixelType(GL2Encoder* ctx, GLenum type) { int glesMajorVersion = ctx->majorVersion(); if (glesMajorVersion < 3) { switch (type) { case GL_UNSIGNED_BYTE: case GL_UNSIGNED_SHORT: case GL_UNSIGNED_SHORT_5_6_5: case GL_UNSIGNED_SHORT_4_4_4_4: case GL_UNSIGNED_SHORT_5_5_5_1: case GL_UNSIGNED_INT: case GL_UNSIGNED_INT_10F_11F_11F_REV: case GL_UNSIGNED_INT_24_8: case GL_HALF_FLOAT: case GL_HALF_FLOAT_OES: case GL_FLOAT: return true; } return false; } #define GLES3_TYPE_CASE(type) \ case type: \ switch (type) { LIST_VALID_TEXTYPES(GLES3_TYPE_CASE) return glesMajorVersion >= 3; default: break; } return false; } bool pixelFormat(GL2Encoder* ctx, GLenum format) { int glesMajorVersion = ctx->majorVersion(); if (glesMajorVersion < 3) { switch (format) { case GL_DEPTH_COMPONENT: // GLES3 compatible // Required in dEQP case GL_RED: case GL_RG: case GL_DEPTH_STENCIL_OES: case GL_ALPHA: case GL_RGB: case GL_RGBA: case GL_BGRA_EXT: case GL_LUMINANCE: case GL_LUMINANCE_ALPHA: return true; } return false; } #define GLES3_FORMAT_CASE(format) \ case format: switch (format) { LIST_VALID_TEXFORMATS(GLES3_FORMAT_CASE) return glesMajorVersion >= 3; default: break; } return false; } #define LIST_VALID_TEX_INTERNALFORMATS(f) \ f(GL_R8) \ f(GL_R8_SNORM) \ f(GL_R16F) \ f(GL_R32F) \ f(GL_R8UI) \ f(GL_R8I) \ f(GL_R16UI) \ f(GL_R16I) \ f(GL_R32UI) \ f(GL_R32I) \ f(GL_RG8) \ f(GL_RG8_SNORM) \ f(GL_RG16F) \ f(GL_RG32F) \ f(GL_RG8UI) \ f(GL_RG8I) \ f(GL_RG16UI) \ f(GL_RG16I) \ f(GL_RG32UI) \ f(GL_RG32I) \ f(GL_RGB8) \ f(GL_SRGB8) \ f(GL_RGB565) \ f(GL_RGB8_SNORM) \ f(GL_R11F_G11F_B10F) \ f(GL_RGB9_E5) \ f(GL_RGB16F) \ f(GL_RGB32F) \ f(GL_RGB8UI) \ f(GL_RGB8I) \ f(GL_RGB16UI) \ f(GL_RGB16I) \ f(GL_RGB32UI) \ f(GL_RGB32I) \ f(GL_RGBA8) \ f(GL_SRGB8_ALPHA8) \ f(GL_RGBA8_SNORM) \ f(GL_RGB5_A1) \ f(GL_RGBA4) \ f(GL_RGB10_A2) \ f(GL_RGBA16F) \ f(GL_RGBA32F) \ f(GL_RGBA8UI) \ f(GL_RGBA8I) \ f(GL_RGB10_A2UI) \ f(GL_RGBA16UI) \ f(GL_RGBA16I) \ f(GL_RGBA32I) \ f(GL_RGBA32UI) \ f(GL_DEPTH_COMPONENT16) \ f(GL_DEPTH_COMPONENT24) \ f(GL_DEPTH_COMPONENT32F) \ f(GL_DEPTH24_STENCIL8) \ f(GL_DEPTH32F_STENCIL8) \ f(GL_COMPRESSED_R11_EAC) \ f(GL_COMPRESSED_SIGNED_R11_EAC) \ f(GL_COMPRESSED_RG11_EAC) \ f(GL_COMPRESSED_SIGNED_RG11_EAC) \ f(GL_COMPRESSED_RGB8_ETC2) \ f(GL_COMPRESSED_SRGB8_ETC2) \ f(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2) \ f(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2) \ f(GL_COMPRESSED_RGBA8_ETC2_EAC) \ f(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC) \ bool pixelInternalFormat(GLenum internalformat) { #define VALID_INTERNAL_FORMAT(format) \ case format: \ return true; \ switch (internalformat) { LIST_VALID_TEX_INTERNALFORMATS(VALID_INTERNAL_FORMAT) default: break; } return false; } bool shaderType(GL2Encoder* ctx, GLenum type) { int glesMajorVersion = ctx->majorVersion(); int glesMinorVersion = ctx->minorVersion(); switch (type) { case GL_VERTEX_SHADER: case GL_FRAGMENT_SHADER: return true; case GL_COMPUTE_SHADER: return glesMajorVersion >= 3 && glesMinorVersion >= 1; } return false; } bool internalFormatTarget(GL2Encoder* ctx, GLenum target) { int glesMajorVersion = ctx->majorVersion(); int glesMinorVersion = ctx->minorVersion(); switch (target) { case GL_RENDERBUFFER: return true; case GL_TEXTURE_2D_MULTISAMPLE: return glesMajorVersion >= 3 && glesMinorVersion >= 1; } return false; } std::string vertexAttribIndexRangeErrorMsg(GL2Encoder* ctx, GLuint index) { std::stringstream ss; GLint maxIndex; ctx->glGetIntegerv(ctx, GL_MAX_VERTEX_ATTRIBS, &maxIndex); ss << "Invalid vertex attribute index. Wanted index: " << index << ". Max index: " << maxIndex; return ss.str(); } } // namespace GLESv2Validation