blob: 924a94d4cb0cc1b9960452affb6317eb66896956 [file]
// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GL_GLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
#endif
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <GLES3/gl3.h>
#include <stdint.h>
#include "gpu/command_buffer/tests/gl_manager.h"
#include "gpu/command_buffer/tests/gl_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace gpu {
class GLInvalidateFramebufferTest : public testing::Test {
protected:
GLManager::Options GetGlManagerOptions() {
GLManager::Options options;
options.context_type = CONTEXT_TYPE_OPENGLES3;
return options;
}
void SetUp() override { gl_.Initialize(GetGlManagerOptions()); }
void TearDown() override { gl_.Destroy(); }
GLManager gl_;
};
// Port of the POC for b/507508103.
// Creates an incomplete framebuffer and calls glInvalidateFramebuffer.
// Should not crash.
TEST_F(GLInvalidateFramebufferTest, IncompleteFBOInvalidate) {
// If ES3 is not supported, skip the test.
if (!gl_.decoder() || !gl_.decoder()->GetContextGroup()) {
GTEST_SKIP() << "ES3 not supported";
}
GLuint tex, fbo;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
// 2 levels, GL_RGBA8 (not depth/stencil renderable), 4x4, 1 layer
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_RGBA8, 4, 4, 1);
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// Try to attach level 2 (out of range, levels are 0 and 1) to
// GL_DEPTH_STENCIL_ATTACHMENT. This should fail validation and generate
// GL_INVALID_VALUE in validating decoder.
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, tex, 2,
0);
GLenum att[] = {GL_DEPTH_STENCIL_ATTACHMENT};
// This call triggered the crash on vulnerable Qualcomm drivers.
// With the workaround, it should be skipped or handled safely without
// crashing.
glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, att);
// We call glFinish to ensure the GPU has processed the commands and we don't
// crash asynchronously.
glFinish();
// Clean up
glDeleteFramebuffers(1, &fbo);
glDeleteTextures(1, &tex);
// Consume expected errors (GL_INVALID_VALUE from glFramebufferTextureLayer,
// and potentially GL_INVALID_OPERATION from glInvalidateFramebuffer if not
// skipped by ANGLE) to avoid failing CheckGLError.
while (glGetError() != GL_NO_ERROR) {
}
GLTestHelper::CheckGLError("no errors at the end of test", __LINE__);
}
} // namespace gpu