Update texure cache after teleting bound texture.
The texture cache could become out of sync. And we could end up
dereferencing an invalid pointer.
Bug: chromium:943538
Change-Id: I6a99a04e80fc551b6177e25b7bee09c6ae226340
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1558957
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/State.cpp b/src/libANGLE/State.cpp
index 8cdcb17..e3e88df 100644
--- a/src/libANGLE/State.cpp
+++ b/src/libANGLE/State.cpp
@@ -538,9 +538,16 @@
}
}
- mTexturesIncompatibleWithSamplers[textureIndex] =
- !texture->getTextureState().compatibleWithSamplerFormat(
- mProgram->getState().getSamplerFormatForTextureUnitIndex(textureIndex));
+ if (mProgram)
+ {
+ mTexturesIncompatibleWithSamplers[textureIndex] =
+ !texture->getTextureState().compatibleWithSamplerFormat(
+ mProgram->getState().getSamplerFormatForTextureUnitIndex(textureIndex));
+ }
+ else
+ {
+ mTexturesIncompatibleWithSamplers[textureIndex] = false;
+ }
mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS);
}
@@ -1123,15 +1130,17 @@
for (TextureType type : angle::AllEnums<TextureType>())
{
TextureBindingVector &textureVector = mSamplerTextures[type];
- for (BindingPointer<Texture> &binding : textureVector)
+
+ for (size_t bindingIndex = 0; bindingIndex < textureVector.size(); ++bindingIndex)
{
+ BindingPointer<Texture> &binding = textureVector[bindingIndex];
if (binding.id() == texture)
{
+ // Zero textures are the "default" textures instead of NULL
Texture *zeroTexture = zeroTextures[type].get();
ASSERT(zeroTexture != nullptr);
- // Zero textures are the "default" textures instead of NULL
binding.set(context, zeroTexture);
- mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS);
+ updateActiveTexture(context, bindingIndex, zeroTexture);
}
}
}
diff --git a/src/tests/gl_tests/StateChangeTest.cpp b/src/tests/gl_tests/StateChangeTest.cpp
index 650908d..350f180 100644
--- a/src/tests/gl_tests/StateChangeTest.cpp
+++ b/src/tests/gl_tests/StateChangeTest.cpp
@@ -3367,6 +3367,42 @@
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
}
+
+// Tests that deleting a texture successfully binds the zero texture.
+TEST_P(SimpleStateChangeTest, DeleteTextureThenDraw)
+{
+ constexpr char kFS[] =
+ "uniform sampler2D us; void main() { gl_FragColor = texture2D(us, vec2(0)); }";
+ ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
+ glUseProgram(program);
+ GLint loc = glGetUniformLocation(program, "us");
+ ASSERT_EQ(0, loc);
+
+ auto quadVertices = GetQuadVertices();
+ GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
+ ASSERT_EQ(0, posLoc);
+
+ GLBuffer buffer;
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
+ glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(quadVertices[0]),
+ quadVertices.data(), GL_STATIC_DRAW);
+ glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
+ glEnableVertexAttribArray(posLoc);
+
+ constexpr size_t kSize = 2;
+ std::vector<GLColor> red(kSize * kSize, GLColor::red);
+
+ GLTexture tex;
+ glBindTexture(GL_TEXTURE_2D, tex);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glUniform1i(loc, 1);
+ tex.reset();
+
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+ ASSERT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
+}
} // anonymous namespace
ANGLE_INSTANTIATE_TEST(StateChangeTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_VULKAN());