// 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();
}
Exemple #17
0
//  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);
}