blob: d237c70e7c5265af68f8af870b7c27b2f934c2a4 [file] [log] [blame]
//
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// ActiveTextureCacheTest.cpp: Regression tests of ANGLE's ActiveTextureCache inside gl::State.
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
namespace angle
{
class ActiveTextureCacheTest : public ANGLETest
{
protected:
ActiveTextureCacheTest()
{
setWindowWidth(128);
setWindowHeight(128);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
}
void testSetUp() override
{
constexpr char kVS[] =
"precision highp float;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = vec4(0.0, 0.0, 0.0, 0.0);\n"
"}\n";
constexpr char k2DFS[] =
"precision highp float;\n"
"uniform sampler2D tex2D;\n"
"uniform samplerCube texCube;\n"
"\n"
"void main()\n"
"{\n"
" gl_FragColor = texture2D(tex2D, vec2(0.0, 0.0)) + textureCube(texCube, vec3(0.0, "
"0.0, 0.0));\n"
"}\n";
mProgram = CompileProgram(kVS, k2DFS);
ASSERT_NE(0u, mProgram);
m2DTextureLocation = glGetUniformLocation(mProgram, "tex2D");
ASSERT_NE(-1, m2DTextureLocation);
mCubeTextureLocation = glGetUniformLocation(mProgram, "texCube");
ASSERT_NE(-1, mCubeTextureLocation);
}
void testTearDown() override { glDeleteProgram(mProgram); }
GLuint mProgram = 0;
GLint m2DTextureLocation = -1;
GLint mCubeTextureLocation = -1;
};
// Regression test for a bug that causes the ActiveTexturesCache to get out of sync with the
// currently bound textures when changing program uniforms in such a way that the program becomes
// invalid.
TEST_P(ActiveTextureCacheTest, UniformChangeUpdatesActiveTextureCache)
{
glUseProgram(mProgram);
// Generate two textures and reset the texture binding
GLuint tex0 = 0;
glGenTextures(1, &tex0);
glBindTexture(GL_TEXTURE_2D, tex0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
GLuint tex1 = 0;
glGenTextures(1, &tex1);
glBindTexture(GL_TEXTURE_2D, tex1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glBindTexture(GL_TEXTURE_2D, 0);
// Set the active texture to 1 and bind tex0.
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, tex0);
// Point the program's 2D sampler at texture binding 1. The texture will be added to the
// ActiveTexturesCache because it matches the program's sampler type for this texture binding.
glUniform1i(m2DTextureLocation, 1);
// Point the program's cube sampler to texture binding 1 as well. This causes the program's
// samplers become invalid and the ActiveTexturesCache is NOT updated.
glUniform1i(mCubeTextureLocation, 1);
// Bind tex1. ActiveTexturesCache is NOT updated (still contains tex0). The current texture
// bindings do not match ActiveTexturesCache's state.
glBindTexture(GL_TEXTURE_2D, tex1);
// Delete tex0. The ActiveTexturesCache entry that points to tex0 is not cleared because tex0 is
// not currently bound.
glDeleteTextures(1, &tex0);
// Use-after-free occurs during context destruction when the ActiveTexturesCache is cleared.
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(ActiveTextureCacheTest);
} // namespace angle