// Test that invalid IDs in CopySubTexture are validated TEST_P(CopyTextureTest, CopySubTextureInvalidTextureIds) { if (!checkExtensions()) { return; } glBindTexture(GL_TEXTURE_2D, mTextures[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glBindTexture(GL_TEXTURE_2D, mTextures[1]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glCopySubTextureCHROMIUM(mTextures[0], 99993, 1, 1, 0, 0, 1, 1, false, false, false); EXPECT_GL_ERROR(GL_INVALID_VALUE); glCopySubTextureCHROMIUM(99994, mTextures[1], 1, 1, 0, 0, 1, 1, false, false, false); EXPECT_GL_ERROR(GL_INVALID_VALUE); glCopySubTextureCHROMIUM(99995, 99996, 1, 1, 0, 0, 1, 1, false, false, false); EXPECT_GL_ERROR(GL_INVALID_VALUE); glCopySubTextureCHROMIUM(mTextures[0], mTextures[1], 1, 1, 0, 0, 1, 1, false, false, false); EXPECT_GL_NO_ERROR(); }
// Verify that GL_BIND_GENERATES_RESOURCE_CHROMIUM can be queried but not changed TEST_P(BindGeneratesResourceTest, QueryValidation) { GLint intValue = 2; glGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM, &intValue); EXPECT_GL_NO_ERROR(); EXPECT_GL_FALSE(intValue); float floatValue = 2.0f; glGetFloatv(GL_BIND_GENERATES_RESOURCE_CHROMIUM, &floatValue); EXPECT_GL_NO_ERROR(); EXPECT_EQ(floatValue, 0.0f); GLboolean boolValue = GL_TRUE; glGetBooleanv(GL_BIND_GENERATES_RESOURCE_CHROMIUM, &boolValue); EXPECT_GL_NO_ERROR(); EXPECT_GL_FALSE(boolValue); boolValue = glIsEnabled(GL_BIND_GENERATES_RESOURCE_CHROMIUM); EXPECT_GL_NO_ERROR(); EXPECT_GL_FALSE(boolValue); glEnable(GL_BIND_GENERATES_RESOURCE_CHROMIUM); EXPECT_GL_ERROR(GL_INVALID_ENUM); glDisable(GL_BIND_GENERATES_RESOURCE_CHROMIUM); EXPECT_GL_ERROR(GL_INVALID_ENUM); }
// Test validation of texture IDs TEST_P(CopyCompressedTextureTest, InvalidTextureIds) { if (!checkExtensions()) { return; } glBindTexture(GL_TEXTURE_2D, mTextures[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, sizeof(CompressedImageDXT1), CompressedImageDXT1); ASSERT_GL_NO_ERROR(); glBindTexture(GL_TEXTURE_2D, mTextures[1]); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); ASSERT_GL_NO_ERROR(); glCompressedCopyTextureCHROMIUM(mTextures[0], 99993); EXPECT_GL_ERROR(GL_INVALID_VALUE); glCompressedCopyTextureCHROMIUM(99994, mTextures[1]); EXPECT_GL_ERROR(GL_INVALID_VALUE); glCompressedCopyTextureCHROMIUM(99995, 99996); EXPECT_GL_ERROR(GL_INVALID_VALUE); glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]); EXPECT_GL_NO_ERROR(); }
TEST_F(SRGBTextureTest, srgba_validation) { bool supported = extensionEnabled("GL_EXT_sRGB") || getClientVersion() == 3; GLuint tex = 0; glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); GLubyte pixel[4] = { 0 }; glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, pixel); if (supported) { EXPECT_GL_NO_ERROR(); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, pixel); EXPECT_GL_NO_ERROR(); glGenerateMipmap(GL_TEXTURE_2D); if (getClientVersion() == 2) { EXPECT_GL_ERROR(GL_INVALID_OPERATION); } else { EXPECT_GL_NO_ERROR(); } } else { EXPECT_GL_ERROR(GL_INVALID_ENUM); } glDeleteTextures(1, &tex); }
// Test that invalid dimensions in CopySubTexture are validated TEST_P(CopyTextureTest, CopySubTextureDimension) { if (!checkExtensions()) { return; } glBindTexture(GL_TEXTURE_2D, mTextures[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glBindTexture(GL_TEXTURE_2D, mTextures[1]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glCopySubTextureCHROMIUM(mTextures[0], mTextures[1], 1, 1, 0, 0, 1, 1, false, false, false); EXPECT_GL_NO_ERROR(); // xoffset < 0 glCopySubTextureCHROMIUM(mTextures[0], mTextures[1], -1, 1, 0, 0, 1, 1, false, false, false); EXPECT_GL_ERROR(GL_INVALID_VALUE); // x < 0 glCopySubTextureCHROMIUM(mTextures[0], mTextures[1], 1, 1, -1, 0, 1, 1, false, false, false); EXPECT_GL_ERROR(GL_INVALID_VALUE); // xoffset + width > dest_width glCopySubTextureCHROMIUM(mTextures[0], mTextures[1], 2, 2, 0, 0, 2, 2, false, false, false); EXPECT_GL_ERROR(GL_INVALID_VALUE); // x + width > source_width glCopySubTextureCHROMIUM(mTextures[0], mTextures[1], 0, 0, 1, 1, 2, 2, false, false, false); EXPECT_GL_ERROR(GL_INVALID_VALUE); }
// Test the destination texture cannot be immutable TEST_P(CopyCompressedTextureTest, Immutable) { if (!checkExtensions() || getClientMajorVersion() < 3) { return; } glBindTexture(GL_TEXTURE_2D, mTextures[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, sizeof(CompressedImageDXT1), CompressedImageDXT1); ASSERT_GL_NO_ERROR(); glBindTexture(GL_TEXTURE_2D, mTextures[1]); glTexStorage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); ASSERT_GL_NO_ERROR(); glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]); EXPECT_GL_ERROR(GL_INVALID_OPERATION); }
// Test that only 2D textures are valid TEST_P(CopyCompressedTextureTest, BindingPoints) { if (!checkExtensions()) { return; } glBindTexture(GL_TEXTURE_CUBE_MAP, mTextures[0]); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; face++) { glCompressedTexImage2D(face, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, sizeof(CompressedImageDXT1), CompressedImageDXT1); } ASSERT_GL_NO_ERROR(); glBindTexture(GL_TEXTURE_CUBE_MAP, mTextures[1]); glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); ASSERT_GL_NO_ERROR(); glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]); EXPECT_GL_ERROR(GL_INVALID_VALUE); }
// Test that uncompressed textures generate errors when copying TEST_P(CopyCompressedTextureTest, InternalFormatNotSupported) { if (!checkExtensions()) { return; } glBindTexture(GL_TEXTURE_2D, mTextures[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red); ASSERT_GL_NO_ERROR(); glBindTexture(GL_TEXTURE_2D, mTextures[1]); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); ASSERT_GL_NO_ERROR(); // Check that the GL_RGBA format reports an error. glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]); EXPECT_GL_ERROR(GL_INVALID_OPERATION); }
// Test that textures cannot be generated on bind TEST_P(BindGeneratesResourceTest, Textures) { glBindTexture(GL_TEXTURE_2D, 2); EXPECT_GL_ERROR(GL_INVALID_OPERATION); glBindTexture(GL_TEXTURE_2D, 0); EXPECT_GL_NO_ERROR(); }
// Test that renderbuffer cannot be generated on bind TEST_P(BindGeneratesResourceTest, Renderbuffers) { glBindRenderbuffer(GL_RENDERBUFFER, 2); EXPECT_GL_ERROR(GL_INVALID_OPERATION); glBindRenderbuffer(GL_RENDERBUFFER, 0); EXPECT_GL_NO_ERROR(); }
// Test that framebuffers cannot be generated on bind TEST_P(BindGeneratesResourceTest, Framebuffers) { glBindFramebuffer(GL_FRAMEBUFFER, 2); EXPECT_GL_ERROR(GL_INVALID_OPERATION); glBindFramebuffer(GL_FRAMEBUFFER, 0); EXPECT_GL_NO_ERROR(); }
TEST_F(SRGBTextureTest, srgba_renderbuffer) { bool supported = extensionEnabled("GL_EXT_sRGB") || getClientVersion() == 3; GLuint rbo = 0; glGenRenderbuffers(1, &rbo); glBindRenderbuffer(GL_RENDERBUFFER, rbo); glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8_ALPHA8_EXT, 1, 1); if (supported) { EXPECT_GL_NO_ERROR(); } else { EXPECT_GL_ERROR(GL_INVALID_ENUM); // Make sure the rbo has a size for future tests glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, 1, 1); EXPECT_GL_NO_ERROR(); } GLuint fbo = 0; glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo); EXPECT_GL_NO_ERROR(); GLint colorEncoding = 0; glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT, &colorEncoding); if (supported) { EXPECT_GL_NO_ERROR(); EXPECT_EQ(GL_SRGB_EXT, colorEncoding); } else { EXPECT_GL_ERROR(GL_INVALID_ENUM); } glDeleteFramebuffers(1, &fbo); glDeleteRenderbuffers(1, &rbo); }
// Test to ensure that the destination texture is redefined if the properties are different. TEST_P(CopyTextureTest, RedefineDestinationTexture) { if (!checkExtensions()) { return; } GLColor pixels[4] = {GLColor::red, GLColor::red, GLColor::red, GLColor::red}; glBindTexture(GL_TEXTURE_2D, mTextures[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glBindTexture(GL_TEXTURE_2D, mTextures[1]); glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, 1, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels); EXPECT_GL_NO_ERROR(); // GL_INVALID_OPERATION due to "intrinsic format" != "internal format". glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels); EXPECT_GL_ERROR(GL_INVALID_OPERATION); // GL_INVALID_VALUE due to bad dimensions. glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels); EXPECT_GL_ERROR(GL_INVALID_VALUE); // If the dest texture has different properties, glCopyTextureCHROMIUM() // redefines them. glCopyTextureCHROMIUM(mTextures[0], mTextures[1], GL_RGBA, GL_UNSIGNED_BYTE, false, false, false); EXPECT_GL_NO_ERROR(); // glTexSubImage2D() succeeds because mTextures[1] is redefined into 2x2 // dimension and GL_RGBA format. glBindTexture(GL_TEXTURE_2D, mTextures[1]); glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels); EXPECT_GL_NO_ERROR(); // Check that FB is complete. EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); EXPECT_PIXEL_COLOR_EQ(1, 1, pixels[3]); EXPECT_GL_NO_ERROR(); }
// Check that invalid internal formats return errors. TEST_P(CopyTextureTest, InternalFormatNotSupported) { if (!checkExtensions()) { return; } glBindTexture(GL_TEXTURE_2D, mTextures[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); EXPECT_GL_NO_ERROR(); std::vector<GLint> unsupportedDestFormats; unsupportedDestFormats.push_back(GL_ALPHA); unsupportedDestFormats.push_back(GL_LUMINANCE); unsupportedDestFormats.push_back(GL_LUMINANCE_ALPHA); if (!extensionEnabled("GL_EXT_texture_format_BGRA8888")) { unsupportedDestFormats.push_back(GL_BGRA_EXT); } // Check unsupported format reports an error. for (GLint unsupportedDestFormat : unsupportedDestFormats) { glCopyTextureCHROMIUM(mTextures[0], mTextures[1], unsupportedDestFormat, GL_UNSIGNED_BYTE, false, false, false); EXPECT_GL_ERROR(GL_INVALID_OPERATION); } for (GLint unsupportedDestFormat : unsupportedDestFormats) { glBindTexture(GL_TEXTURE_2D, mTextures[1]); glTexImage2D(GL_TEXTURE_2D, 0, unsupportedDestFormat, 1, 1, 0, unsupportedDestFormat, GL_UNSIGNED_BYTE, nullptr); glCopySubTextureCHROMIUM(mTextures[0], mTextures[1], 0, 0, 0, 0, 1, 1, false, false, false); EXPECT_GL_ERROR(GL_INVALID_OPERATION); } }
// Test that buffers cannot be generated on bind TEST_P(BindGeneratesResourceTest, Buffers) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 2); EXPECT_GL_ERROR(GL_INVALID_OPERATION); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); EXPECT_GL_NO_ERROR(); if (getClientMajorVersion() >= 3) { glBindBufferBase(GL_UNIFORM_BUFFER, 0, 3); EXPECT_GL_ERROR(GL_INVALID_OPERATION); glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0); EXPECT_GL_NO_ERROR(); glBindBufferRange(GL_UNIFORM_BUFFER, 0, 4, 1, 2); EXPECT_GL_ERROR(GL_INVALID_OPERATION); glBindBufferRange(GL_UNIFORM_BUFFER, 0, 0, 1, 2); EXPECT_GL_NO_ERROR(); } }
// Test that CopyTexture cannot redefine an immutable texture and CopySubTexture can copy data to // immutable textures TEST_P(CopyTextureTest, ImmutableTexture) { if (!checkExtensions()) { return; } if (getClientMajorVersion() < 3 && (!extensionEnabled("GL_EXT_texture_storage") || !extensionEnabled("GL_OES_rgb8_rgba8"))) { std::cout << "Test skipped due to missing ES3 or GL_EXT_texture_storage or GL_OES_rgb8_rgba8" << std::endl; return; } GLColor pixels = GLColor::red; glBindTexture(GL_TEXTURE_2D, mTextures[0]); glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, 1, 1); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixels); glBindTexture(GL_TEXTURE_2D, mTextures[1]); glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, 1, 1); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0); EXPECT_GL_NO_ERROR(); // Should generate an error when the texture is redefined glCopyTextureCHROMIUM(mTextures[0], mTextures[1], GL_RGBA, GL_UNSIGNED_BYTE, false, false, false); EXPECT_GL_ERROR(GL_INVALID_OPERATION); // Should succeed when using CopySubTexture glCopySubTextureCHROMIUM(mTextures[0], mTextures[1], 0, 0, 0, 0, 1, 1, false, false, false); EXPECT_GL_NO_ERROR(); // Check that FB is complete. EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); EXPECT_PIXEL_COLOR_EQ(0, 0, pixels); EXPECT_GL_NO_ERROR(); }
// The test verifies that glCopyTexSubImage2D generates a GL_INVALID_OPERATION error // when the read buffer is GL_NONE. // Reference: GLES 3.0.4, Section 3.8.5 Alternate Texture Image Specification Commands TEST_P(CopyTexImageTestES3, ReadBufferIsNone) { GLfloat color[] = { 0.25f, 1.0f, 0.75f, 0.5f, }; GLuint fbo = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color); GLuint tex = createTextureFromCopyTexImage(fbo, GL_RGBA); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glBindTexture(GL_TEXTURE_2D, tex); glReadBuffer(GL_NONE); EXPECT_GL_NO_ERROR(); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 4, 4); EXPECT_GL_ERROR(GL_INVALID_OPERATION); glDeleteFramebuffers(1, &fbo); glDeleteTextures(1, &tex); }