// Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ui/gl/gl_context_glx.h" #include "base/memory/scoped_refptr.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/x/connection.h" #include "ui/gfx/x/future.h" #include "ui/gfx/x/xproto.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_surface_glx_x11.h" #include "ui/gl/init/gl_factory.h" #include "ui/gl/test/gl_image_test_support.h" namespace gl { #if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \ defined(THREAD_SANITIZER) // https://crbug.com/830653 #define MAYBE_DoNotDestroyOnFailedMakeCurrent \ DISABLED_DoNotDestroyOnFailedMakeCurrent #else #define MAYBE_DoNotDestroyOnFailedMakeCurrent DoNotDestroyOnFailedMakeCurrent #endif TEST(GLContextGLXTest, MAYBE_DoNotDestroyOnFailedMakeCurrent) { auto* connection = x11::Connection::Get(); ASSERT_TRUE(connection && connection->Ready()); auto xwindow = connection->GenerateId(); connection->CreateWindow({ .wid = xwindow, .parent = connection->default_root(), .width = 10, .height = 10, .c_class = x11::WindowClass::InputOutput, .background_pixmap = x11::Pixmap::None, .override_redirect = x11::Bool32(true), }); connection->MapWindow({xwindow}); // Since this window is override-redirect, syncing is sufficient // to ensure the map is complete. connection->Sync(); GLImageTestSupport::InitializeGL(absl::nullopt); auto surface = gl::InitializeGLSurface(base::MakeRefCounted( static_cast(xwindow))); scoped_refptr context = gl::init::CreateGLContext(nullptr, surface.get(), GLContextAttribs()); // Verify that MakeCurrent() is successful. ASSERT_TRUE(context->GetHandle()); ASSERT_TRUE(context->MakeCurrent(surface.get())); EXPECT_TRUE(context->GetHandle()); context->ReleaseCurrent(surface.get()); connection->DestroyWindow({xwindow}); // Since this window is override-redirect, syncing is sufficient // to ensure the window is destroyed and unmapped. connection->Sync(); ASSERT_TRUE(connection->Ready()); if (context->MakeCurrent(surface.get())) { // With some drivers, MakeCurrent() does not fail for an already-destroyed // window. In those cases, override the glx api to force MakeCurrent() to // fail. context->ReleaseCurrent(surface.get()); auto real_fn = g_driver_glx.fn.glXMakeContextCurrentFn; g_driver_glx.fn.glXMakeContextCurrentFn = [](Display* display, GLXDrawable drawable, GLXDrawable read, GLXContext context) -> int { return 0; }; EXPECT_FALSE(context->MakeCurrent(surface.get())); g_driver_glx.fn.glXMakeContextCurrentFn = real_fn; } // At this point, MakeCurrent() failed. Make sure the GLContextGLX still was // not destroyed. ASSERT_TRUE(context->GetHandle()); surface = nullptr; connection->Sync(); connection->events().clear(); } } // namespace gl