| Index: ui/gl/gl_surface_glx.cc
|
| diff --git a/ui/gl/gl_surface_glx.cc b/ui/gl/gl_surface_glx.cc
|
| index 8b705dfbe93751c899daa05752cc585d64229097..5614b518aec219021de9c5d4dc174b7f2ec29065 100644
|
| --- a/ui/gl/gl_surface_glx.cc
|
| +++ b/ui/gl/gl_surface_glx.cc
|
| @@ -10,6 +10,7 @@ extern "C" {
|
|
|
| #include "base/basictypes.h"
|
| #include "base/debug/trace_event.h"
|
| +#include "base/lazy_instance.h"
|
| #include "base/logging.h"
|
| #include "base/memory/scoped_ptr.h"
|
| #include "base/memory/weak_ptr.h"
|
| @@ -39,7 +40,7 @@ class ScopedPtrXFree {
|
| }
|
| };
|
|
|
| -Display* g_display;
|
| +Display* g_display = NULL;
|
| const char* g_glx_extensions = NULL;
|
| bool g_glx_context_create = false;
|
| bool g_glx_create_context_robustness_supported = false;
|
| @@ -315,7 +316,17 @@ bool GLSurfaceGLX::InitializeOneOff() {
|
| // it's own thread.
|
| XInitThreads();
|
|
|
| +#if defined(TOOLKIT_GTK)
|
| + // Be sure to use the X display handle and not the GTK display handle if this
|
| + // is the GPU process.
|
| + if (base::MessageLoop::current()->type() == base::MessageLoop::TYPE_GPU)
|
| + g_display = base::MessagePumpX11::GetDefaultXDisplay();
|
| + else
|
| + g_display = base::MessagePumpForUI::GetDefaultXDisplay();
|
| +#else
|
| g_display = base::MessagePumpForUI::GetDefaultXDisplay();
|
| +#endif
|
| +
|
| if (!g_display) {
|
| LOG(ERROR) << "XOpenDisplay failed.";
|
| return false;
|
| @@ -388,31 +399,110 @@ void* GLSurfaceGLX::GetDisplay() {
|
|
|
| GLSurfaceGLX::~GLSurfaceGLX() {}
|
|
|
| +class XExposeEventForwarder : public base::MessagePumpObserver {
|
| + public:
|
| + XExposeEventForwarder() {
|
| + base::MessagePumpX11::Current()->AddObserver(this);
|
| + }
|
| + ~XExposeEventForwarder() {
|
| + base::MessagePumpX11::Current()->RemoveObserver(this);
|
| + }
|
| +
|
| + void AddParentChildPair(gfx::AcceleratedWidget parent_window,
|
| + gfx::AcceleratedWidget child_window) {
|
| + DCHECK(child_to_parent_map_.find(child_window) ==
|
| + child_to_parent_map_.end());
|
| + child_to_parent_map_.insert(std::make_pair(
|
| + child_window, parent_window));
|
| + }
|
| + void RemoveParentChildPair(gfx::AcceleratedWidget parent_window,
|
| + gfx::AcceleratedWidget child_window) {
|
| + DCHECK(child_to_parent_map_.find(child_window) !=
|
| + child_to_parent_map_.end());
|
| + child_to_parent_map_.erase(child_window);
|
| + }
|
| +
|
| + private:
|
| + virtual base::EventStatus WillProcessEvent(
|
| + const base::NativeEvent& xevent) OVERRIDE {
|
| + if (xevent->type != Expose)
|
| + return base::EVENT_CONTINUE;
|
| +
|
| + WindowMap::const_iterator found = child_to_parent_map_.find(
|
| + xevent->xexpose.window);
|
| + if (found == child_to_parent_map_.end())
|
| + return base::EVENT_CONTINUE;
|
| +
|
| + gfx::AcceleratedWidget target_window = found->second;
|
| + XEvent forwarded_event = *xevent;
|
| + forwarded_event.xexpose.window = target_window;
|
| + XSendEvent(g_display, target_window, False, ExposureMask,
|
| + &forwarded_event);
|
| + return base::EVENT_CONTINUE;
|
| + }
|
| + virtual void DidProcessEvent(const base::NativeEvent& xevent) {
|
| + }
|
| +
|
| + typedef std::map<gfx::AcceleratedWidget, gfx::AcceleratedWidget> WindowMap;
|
| + WindowMap child_to_parent_map_;
|
| +};
|
| +
|
| +static base::LazyInstance<XExposeEventForwarder> g_xexpose_event_forwarder =
|
| + LAZY_INSTANCE_INITIALIZER;
|
| +
|
| NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::AcceleratedWidget window)
|
| - : window_(window),
|
| + : parent_window_(window),
|
| + child_window_(0),
|
| config_(NULL) {
|
| }
|
|
|
| bool NativeViewGLSurfaceGLX::Initialize() {
|
| XWindowAttributes attributes;
|
| - if (!XGetWindowAttributes(g_display, window_, &attributes)) {
|
| - LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
|
| + if (!XGetWindowAttributes(g_display, parent_window_, &attributes)) {
|
| + LOG(ERROR) << "XGetWindowAttributes failed for window " << parent_window_
|
| + << ".";
|
| return false;
|
| }
|
| size_ = gfx::Size(attributes.width, attributes.height);
|
|
|
| + // Workaround for http://crbug.com/145600:
|
| + // Some NVIDIA drivers don't allow deleting GLX windows separately from their
|
| + // parent X windows. Work around this by creating a child X window to the
|
| + // window passed in, creating the GLX window against the child window, and
|
| + // then destroying the child window to destroy the GLX window.
|
| + XSetWindowAttributes set_window_attributes;
|
| + set_window_attributes.event_mask = ExposureMask;
|
| + child_window_ = XCreateWindow(
|
| + g_display, parent_window_, 0, 0, attributes.width, attributes.height, 0,
|
| + attributes.depth, InputOutput, attributes.visual, CWEventMask,
|
| + &set_window_attributes);
|
| + // Because the child window covers the parent window, it will receive all
|
| + // expose events instead of the parent. Set up an explicit forwarding of
|
| + // these events from the child window to the parent window.
|
| + g_xexpose_event_forwarder.Pointer()->AddParentChildPair(
|
| + parent_window_, child_window_);
|
| + XMapWindow(g_display, child_window_);
|
| + XFlush(g_display);
|
| +
|
| if (g_glx_oml_sync_control_supported)
|
| - vsync_provider_.reset(new OMLSyncControlVSyncProvider(window_));
|
| + vsync_provider_.reset(new OMLSyncControlVSyncProvider(parent_window_));
|
| else if (g_glx_sgi_video_sync_supported)
|
| - vsync_provider_.reset(new SGIVideoSyncVSyncProvider(window_));
|
| + vsync_provider_.reset(new SGIVideoSyncVSyncProvider(parent_window_));
|
|
|
| return true;
|
| }
|
|
|
| void NativeViewGLSurfaceGLX::Destroy() {
|
| + g_xexpose_event_forwarder.Pointer()->RemoveParentChildPair(
|
| + parent_window_, child_window_);
|
| + XDestroyWindow(g_display, child_window_);
|
| + XFlush(g_display);
|
| + child_window_ = 0;
|
| }
|
|
|
| bool NativeViewGLSurfaceGLX::Resize(const gfx::Size& size) {
|
| + XResizeWindow(g_display, child_window_, size.width(), size.height());
|
| + XFlush(g_display);
|
| size_ = size;
|
| return true;
|
| }
|
| @@ -422,7 +512,7 @@ bool NativeViewGLSurfaceGLX::IsOffscreen() {
|
| }
|
|
|
| bool NativeViewGLSurfaceGLX::SwapBuffers() {
|
| - glXSwapBuffers(g_display, window_);
|
| + glXSwapBuffers(g_display, child_window_);
|
| return true;
|
| }
|
|
|
| @@ -431,7 +521,7 @@ gfx::Size NativeViewGLSurfaceGLX::GetSize() {
|
| }
|
|
|
| void* NativeViewGLSurfaceGLX::GetHandle() {
|
| - return reinterpret_cast<void*>(window_);
|
| + return reinterpret_cast<void*>(child_window_);
|
| }
|
|
|
| std::string NativeViewGLSurfaceGLX::GetExtensions() {
|
| @@ -460,10 +550,10 @@ void* NativeViewGLSurfaceGLX::GetConfig() {
|
| XWindowAttributes attributes;
|
| if (!XGetWindowAttributes(
|
| g_display,
|
| - window_,
|
| + parent_window_,
|
| &attributes)) {
|
| LOG(ERROR) << "XGetWindowAttributes failed for window " <<
|
| - window_ << ".";
|
| + parent_window_ << ".";
|
| return NULL;
|
| }
|
|
|
| @@ -507,7 +597,7 @@ void* NativeViewGLSurfaceGLX::GetConfig() {
|
| bool NativeViewGLSurfaceGLX::PostSubBuffer(
|
| int x, int y, int width, int height) {
|
| DCHECK(gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer);
|
| - glXCopySubBufferMESA(g_display, window_, x, y, width, height);
|
| + glXCopySubBufferMESA(g_display, child_window_, x, y, width, height);
|
| return true;
|
| }
|
|
|
| @@ -516,7 +606,8 @@ VSyncProvider* NativeViewGLSurfaceGLX::GetVSyncProvider() {
|
| }
|
|
|
| NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX()
|
| - : window_(0),
|
| + : parent_window_(0),
|
| + child_window_(0),
|
| config_(NULL) {
|
| }
|
|
|
|
|