| Index: ui/gl/gl_surface_egl_x11.cc
|
| diff --git a/ui/gl/gl_surface_egl_x11.cc b/ui/gl/gl_surface_egl_x11.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..91b2f54d084cdae4d3c41c4f53c0af6060431d6c
|
| --- /dev/null
|
| +++ b/ui/gl/gl_surface_egl_x11.cc
|
| @@ -0,0 +1,179 @@
|
| +// Copyright (c) 2015 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_surface_egl_x11.h"
|
| +
|
| +#include "ui/events/platform/platform_event_source.h"
|
| +#include "ui/gl/egl_util.h"
|
| +
|
| +extern "C" {
|
| +#include <X11/Xlib.h>
|
| +}
|
| +
|
| +using ui::GetLastEGLErrorString;
|
| +using ui::PlatformEvent;
|
| +using ui::PlatformEventSource;
|
| +
|
| +namespace gfx {
|
| +
|
| +NativeViewGLSurfaceEGLX11::NativeViewGLSurfaceEGLX11(EGLNativeWindowType window)
|
| + : NativeViewGLSurfaceEGL(0),
|
| + parent_window_(window) {
|
| +}
|
| +
|
| +bool NativeViewGLSurfaceEGLX11::InitializeNativeWindow() {
|
| + Display* x11_display = GetNativeDisplay();
|
| + XWindowAttributes attributes;
|
| + if (!XGetWindowAttributes(x11_display, parent_window_, &attributes)) {
|
| + LOG(ERROR) << "XGetWindowAttributes failed for window " << parent_window_
|
| + << ".";
|
| + return false;
|
| + }
|
| +
|
| + size_ = gfx::Size(attributes.width, attributes.height);
|
| +
|
| + // Create a child window, with a CopyFromParent visual (to avoid inducing
|
| + // extra blits in the driver), that we can resize exactly in Resize(),
|
| + // correctly ordered with GL, so that we don't have invalid transient states.
|
| + // See https://crbug.com/326995.
|
| + XSetWindowAttributes swa;
|
| + memset(&swa, 0, sizeof(swa));
|
| + swa.background_pixmap = 0;
|
| + swa.bit_gravity = NorthWestGravity;
|
| + window_ = XCreateWindow(x11_display, parent_window_, 0, 0, size_.width(),
|
| + size_.height(), 0, CopyFromParent, InputOutput,
|
| + CopyFromParent, CWBackPixmap | CWBitGravity, &swa);
|
| + XMapWindow(x11_display, window_);
|
| +
|
| + // The event source can be nullptr in tests, when we don't care about Exposes.
|
| + if (PlatformEventSource* source = PlatformEventSource::GetInstance()) {
|
| + XSelectInput(x11_display, window_, ExposureMask);
|
| + source->AddPlatformEventDispatcher(this);
|
| + }
|
| + XFlush(x11_display);
|
| +
|
| + return true;
|
| +}
|
| +
|
| +void NativeViewGLSurfaceEGLX11::Destroy() {
|
| + if (window_) {
|
| + if (PlatformEventSource* source = PlatformEventSource::GetInstance())
|
| + source->RemovePlatformEventDispatcher(this);
|
| +
|
| + Display* x11_display = GetNativeDisplay();
|
| + XDestroyWindow(x11_display, window_);
|
| + window_ = 0;
|
| + XFlush(x11_display);
|
| + }
|
| +
|
| + NativeViewGLSurfaceEGL::Destroy();
|
| +}
|
| +
|
| +EGLConfig NativeViewGLSurfaceEGLX11::GetConfig() {
|
| + if (!config_) {
|
| + // Get a config compatible with the window
|
| + DCHECK(window_);
|
| + XWindowAttributes win_attribs;
|
| + if (!XGetWindowAttributes(GetNativeDisplay(), window_, &win_attribs)) {
|
| + return NULL;
|
| + }
|
| +
|
| + // Try matching the window depth with an alpha channel,
|
| + // because we're worried the destination alpha width could
|
| + // constrain blending precision.
|
| + const int kBufferSizeOffset = 1;
|
| + const int kAlphaSizeOffset = 3;
|
| + EGLint config_attribs[] = {
|
| + EGL_BUFFER_SIZE, ~0,
|
| + EGL_ALPHA_SIZE, 8,
|
| + EGL_BLUE_SIZE, 8,
|
| + EGL_GREEN_SIZE, 8,
|
| + EGL_RED_SIZE, 8,
|
| + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
| + EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
|
| + EGL_NONE
|
| + };
|
| + config_attribs[kBufferSizeOffset] = win_attribs.depth;
|
| +
|
| + EGLDisplay display = GetHardwareDisplay();
|
| + EGLint num_configs;
|
| + if (!eglChooseConfig(display,
|
| + config_attribs,
|
| + &config_,
|
| + 1,
|
| + &num_configs)) {
|
| + LOG(ERROR) << "eglChooseConfig failed with error "
|
| + << GetLastEGLErrorString();
|
| + return NULL;
|
| + }
|
| +
|
| + if (num_configs) {
|
| + EGLint config_depth;
|
| + if (!eglGetConfigAttrib(display,
|
| + config_,
|
| + EGL_BUFFER_SIZE,
|
| + &config_depth)) {
|
| + LOG(ERROR) << "eglGetConfigAttrib failed with error "
|
| + << GetLastEGLErrorString();
|
| + return NULL;
|
| + }
|
| +
|
| + if (config_depth == win_attribs.depth) {
|
| + return config_;
|
| + }
|
| + }
|
| +
|
| + // Try without an alpha channel.
|
| + config_attribs[kAlphaSizeOffset] = 0;
|
| + if (!eglChooseConfig(display,
|
| + config_attribs,
|
| + &config_,
|
| + 1,
|
| + &num_configs)) {
|
| + LOG(ERROR) << "eglChooseConfig failed with error "
|
| + << GetLastEGLErrorString();
|
| + return NULL;
|
| + }
|
| +
|
| + if (num_configs == 0) {
|
| + LOG(ERROR) << "No suitable EGL configs found.";
|
| + return NULL;
|
| + }
|
| + }
|
| + return config_;
|
| +}
|
| +
|
| +bool NativeViewGLSurfaceEGLX11::Resize(const gfx::Size& size,
|
| + float scale_factor) {
|
| + if (size == GetSize())
|
| + return true;
|
| +
|
| + size_ = size;
|
| +
|
| + eglWaitGL();
|
| + XResizeWindow(GetNativeDisplay(), window_, size.width(), size.height());
|
| + eglWaitNative(EGL_CORE_NATIVE_ENGINE);
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool NativeViewGLSurfaceEGLX11::CanDispatchEvent(const PlatformEvent& event) {
|
| + return event->type == Expose && event->xexpose.window == window_;
|
| +}
|
| +
|
| +uint32_t NativeViewGLSurfaceEGLX11::DispatchEvent(const PlatformEvent& event) {
|
| + XEvent x_event = *event;
|
| + x_event.xexpose.window = parent_window_;
|
| +
|
| + Display* x11_display = GetNativeDisplay();
|
| + XSendEvent(x11_display, parent_window_, False, ExposureMask, &x_event);
|
| + XFlush(x11_display);
|
| + return ui::POST_DISPATCH_STOP_PROPAGATION;
|
| +}
|
| +
|
| +NativeViewGLSurfaceEGLX11::~NativeViewGLSurfaceEGLX11() {
|
| + Destroy();
|
| +}
|
| +
|
| +} // namespace gfx
|
|
|