blob: 07df17483f1c24a61f12c0b6bbb865b4526ac711 [file] [log] [blame]
// 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/x11.h"
#include "ui/gfx/x/x11_error_tracker.h"
#include "ui/gfx/x/x11_types.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 {
TEST(GLContextGLXTest, DoNotDestroyOnFailedMakeCurrent) {
auto* xdisplay = gfx::GetXDisplay();
ASSERT_TRUE(xdisplay);
gfx::X11ErrorTracker error_tracker;
XSetWindowAttributes swa;
memset(&swa, 0, sizeof(swa));
swa.background_pixmap = 0;
swa.override_redirect = x11::True;
auto xwindow = XCreateWindow(xdisplay, DefaultRootWindow(xdisplay), 0, 0, 10,
10, // x, y, width, height
0, // border width
CopyFromParent, // depth
InputOutput,
CopyFromParent, // visual
CWBackPixmap | CWOverrideRedirect, &swa);
XSelectInput(xdisplay, xwindow, StructureNotifyMask);
XEvent xevent;
XMapWindow(xdisplay, xwindow);
// Wait until the window is mapped.
while (XNextEvent(xdisplay, &xevent) && xevent.type != MapNotify &&
xevent.xmap.window != xwindow) {
}
GLImageTestSupport::InitializeGL(base::nullopt);
auto surface =
gl::InitializeGLSurface(base::MakeRefCounted<GLSurfaceGLXX11>(xwindow));
scoped_refptr<GLContext> 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());
// Destroy the window, and wait until the window is unmapped. There should be
// no x11 errors.
context->ReleaseCurrent(surface.get());
XDestroyWindow(xdisplay, xwindow);
while (XNextEvent(xdisplay, &xevent) && xevent.type != UnmapNotify) {
}
ASSERT_FALSE(error_tracker.FoundNewError());
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;
XSync(xdisplay, x11::True);
}
} // namespace gl