gl_surface_glx.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" {
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/Xlib.h>
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_surface_glx.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h"
13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/lazy_instance.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h"
17ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/cancellation_flag.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/non_thread_safe.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/mesa/src/include/GL/osmesa.h"
2468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/gfx/x/x11_types.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_bindings.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_implementation.h"
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/gl/sync_control_vsync_provider.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// scoped_ptr functor for XFree(). Use as follows:
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//   scoped_ptr<XVisualInfo, ScopedPtrXFree> foo(...);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// where "XVisualInfo" is any X type that is freed with XFree.
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct ScopedPtrXFree {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void operator()(void* x) const {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::XFree(x);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)Display* g_display = NULL;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* g_glx_extensions = NULL;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool g_glx_context_create = false;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool g_glx_create_context_robustness_supported = false;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool g_glx_texture_from_pixmap_supported = false;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool g_glx_oml_sync_control_supported = false;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Track support of glXGetMscRateOML separately from GLX_OML_sync_control as a
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// whole since on some platforms (e.g. crosbug.com/34585), glXGetMscRateOML
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// always fails even though GLX_OML_sync_control is reported as being supported.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool g_glx_get_msc_rate_oml_supported = false;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool g_glx_sgi_video_sync_supported = false;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class OMLSyncControlVSyncProvider
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public gfx::SyncControlVSyncProvider {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit OMLSyncControlVSyncProvider(gfx::AcceleratedWidget window)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : SyncControlVSyncProvider(),
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        window_(window) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~OMLSyncControlVSyncProvider() { }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool GetSyncValues(int64* system_time,
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int64* media_stream_counter,
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int64* swap_buffer_counter) OVERRIDE {
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return glXGetSyncValuesOML(g_display, window_, system_time,
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               media_stream_counter, swap_buffer_counter);
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool GetMscRate(int32* numerator, int32* denominator) OVERRIDE {
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!g_glx_get_msc_rate_oml_supported)
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!glXGetMscRateOML(g_display, window_, numerator, denominator)) {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Once glXGetMscRateOML has been found to fail, don't try again,
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // since each failing call may spew an error message.
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      g_glx_get_msc_rate_oml_supported = false;
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XID window_;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OMLSyncControlVSyncProvider);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SGIVideoSyncThread
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     : public base::Thread,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       public base::NonThreadSafe,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       public base::RefCounted<SGIVideoSyncThread> {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static scoped_refptr<SGIVideoSyncThread> Create() {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!g_video_sync_thread) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      g_video_sync_thread = new SGIVideoSyncThread();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      g_video_sync_thread->Start();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return g_video_sync_thread;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCounted<SGIVideoSyncThread>;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SGIVideoSyncThread() : base::Thread("SGI_video_sync") {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(CalledOnValidThread());
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~SGIVideoSyncThread() {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(CalledOnValidThread());
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_video_sync_thread = NULL;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Stop();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static SGIVideoSyncThread* g_video_sync_thread;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncThread);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class SGIVideoSyncProviderThreadShim {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit SGIVideoSyncProviderThreadShim(XID window)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : window_(window),
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        context_(NULL),
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        message_loop_(base::MessageLoopProxy::current()),
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cancel_vsync_flag_(),
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        vsync_lock_() {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This ensures that creation of |window_| has occured when this shim
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // is executing in the same process as the call to create |window_|.
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    XSync(g_display, False);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~SGIVideoSyncProviderThreadShim() {
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (context_) {
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      glXDestroyContext(display_, context_);
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      context_ = NULL;
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::CancellationFlag* cancel_vsync_flag() {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &cancel_vsync_flag_;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Lock* vsync_lock() {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &vsync_lock_;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Initialize() {
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(display_);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XWindowAttributes attributes;
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!XGetWindowAttributes(display_, window_, &attributes)) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "XGetWindowAttributes failed for window " <<
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        window_ << ".";
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XVisualInfo visual_info_template;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    visual_info_template.visualid = XVisualIDFromVisual(attributes.visual);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int visual_info_count = 0;
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_ptr<XVisualInfo, ScopedPtrXFree> visual_info_list(
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        XGetVisualInfo(display_, VisualIDMask,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       &visual_info_template, &visual_info_count));
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(visual_info_list.get());
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (visual_info_count == 0) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "No visual info for visual ID.";
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    context_ = glXCreateContext(display_, visual_info_list.get(), NULL, True);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(NULL != context_);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void GetVSyncParameters(const VSyncProvider::UpdateVSyncCallback& callback) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeTicks now;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Don't allow |window_| destruction while we're probing vsync.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::AutoLock locked(vsync_lock_);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!context_ || cancel_vsync_flag_.IsSet())
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      glXMakeCurrent(display_, window_, context_);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int retrace_count = 0;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (glXWaitVideoSyncSGI(1, 0, &retrace_count) != 0)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      TRACE_EVENT_INSTANT0("gpu", "vblank", TRACE_EVENT_SCOPE_THREAD);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      now = base::TimeTicks::HighResNow();
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      glXMakeCurrent(display_, 0, 0);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::TimeDelta kDefaultInterval =
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::TimeDelta::FromSeconds(1) / 60;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    message_loop_->PostTask(
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE, base::Bind(callback, now, kDefaultInterval));
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For initialization of display_ in GLSurface::InitializeOneOff before
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the sandbox goes up.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class gfx::GLSurfaceGLX;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static Display* display_;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XID window_;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLXContext context_;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> message_loop_;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::CancellationFlag cancel_vsync_flag_;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Lock vsync_lock_;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncProviderThreadShim);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SGIVideoSyncVSyncProvider
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public gfx::VSyncProvider,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      public base::SupportsWeakPtr<SGIVideoSyncVSyncProvider> {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit SGIVideoSyncVSyncProvider(gfx::AcceleratedWidget window)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : vsync_thread_(SGIVideoSyncThread::Create()),
23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        shim_(new SGIVideoSyncProviderThreadShim(window)),
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cancel_vsync_flag_(shim_->cancel_vsync_flag()),
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        vsync_lock_(shim_->vsync_lock()) {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vsync_thread_->message_loop()->PostTask(
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        base::Bind(&SGIVideoSyncProviderThreadShim::Initialize,
24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                   base::Unretained(shim_.get())));
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~SGIVideoSyncVSyncProvider() {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::AutoLock locked(*vsync_lock_);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cancel_vsync_flag_->Set();
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
24990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Hand-off |shim_| to be deleted on the |vsync_thread_|.
25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    vsync_thread_->message_loop()->DeleteSoon(
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
25290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        shim_.release());
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void GetVSyncParameters(
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const VSyncProvider::UpdateVSyncCallback& callback) OVERRIDE {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Only one outstanding request per surface.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!pending_callback_) {
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_callback_.reset(
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new VSyncProvider::UpdateVSyncCallback(callback));
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      vsync_thread_->message_loop()->PostTask(
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE,
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&SGIVideoSyncProviderThreadShim::GetVSyncParameters,
26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     base::Unretained(shim_.get()),
26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     base::Bind(
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         &SGIVideoSyncVSyncProvider::PendingCallbackRunner,
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         AsWeakPtr())));
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PendingCallbackRunner(const base::TimeTicks timebase,
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const base::TimeDelta interval) {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(pending_callback_);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_callback_->Run(timebase, interval);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_callback_.reset();
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SGIVideoSyncThread> vsync_thread_;
28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Thread shim through which the sync provider is accessed on |vsync_thread_|.
28290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SGIVideoSyncProviderThreadShim> shim_;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<VSyncProvider::UpdateVSyncCallback> pending_callback_;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Raw pointers to sync primitives owned by the shim_.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These will only be referenced before we post a task to destroy
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the shim_, so they are safe to access.
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::CancellationFlag* cancel_vsync_flag_;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Lock* vsync_lock_;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncVSyncProvider);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SGIVideoSyncThread* SGIVideoSyncThread::g_video_sync_thread = NULL;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In order to take advantage of GLX_SGI_video_sync, we need a display
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for use on a separate thread. We must allocate this before the sandbox
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// goes up (rather than on-demand when we start the thread).
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Display* SGIVideoSyncProviderThreadShim::display_ = NULL;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
302d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if defined(TOOLKIT_GTK)
303d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// A mechanism for forwarding XExpose events from one window to another.
304d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Because in the workaround for http://crbug.com/145600 the child window
305d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// is placed on top of the parent window, only the child window will receive
306d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// all expose events. These need to be forwared to the parent window to inform
307d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// it that it should paint.
308d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)class XExposeEventForwarder : public base::MessagePumpObserver {
309d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public:
310d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  XExposeEventForwarder() {}
311d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual ~XExposeEventForwarder() {
312d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DCHECK(child_to_parent_map_.empty());
313d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
314d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void AddParentChildPair(gfx::AcceleratedWidget parent_window,
315d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                          gfx::AcceleratedWidget child_window) {
316d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (child_to_parent_map_.empty())
317d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      base::MessagePumpX11::Current()->AddObserver(this);
318d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
319d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DCHECK(child_to_parent_map_.find(child_window) ==
320d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)           child_to_parent_map_.end());
321d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    child_to_parent_map_.insert(std::make_pair(
322d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        child_window, parent_window));
323d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
324d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void RemoveParentChildPair(gfx::AcceleratedWidget parent_window,
325d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                             gfx::AcceleratedWidget child_window) {
326d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DCHECK(child_to_parent_map_.find(child_window) !=
327d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)           child_to_parent_map_.end());
328d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    child_to_parent_map_.erase(child_window);
329d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
330d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (child_to_parent_map_.empty())
331d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      base::MessagePumpX11::Current()->RemoveObserver(this);
332d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
333d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
334d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private:
335d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual base::EventStatus WillProcessEvent (
336d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      const base::NativeEvent& xevent) OVERRIDE {
337d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (xevent->type != Expose)
338d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return base::EVENT_CONTINUE;
339d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
340d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    WindowMap::const_iterator found = child_to_parent_map_.find(
341d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        xevent->xexpose.window);
342d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (found == child_to_parent_map_.end())
343d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return base::EVENT_CONTINUE;
344d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
345d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    gfx::AcceleratedWidget target_window = found->second;
346d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    XEvent forwarded_event = *xevent;
347d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    forwarded_event.xexpose.window = target_window;
348d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    XSendEvent(g_display, target_window, False, ExposureMask,
349d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)               &forwarded_event);
350d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return base::EVENT_CONTINUE;
351d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
352d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void DidProcessEvent(const base::NativeEvent& xevent) OVERRIDE {
353d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
354d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
355d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  typedef std::map<gfx::AcceleratedWidget, gfx::AcceleratedWidget> WindowMap;
356d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  WindowMap child_to_parent_map_;
357d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
358d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(XExposeEventForwarder);
359d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)};
360d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
361d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)static base::LazyInstance<XExposeEventForwarder> g_xexpose_event_forwarder =
362d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    LAZY_INSTANCE_INITIALIZER;
363d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
364d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Do not use this workaround when running in test harnesses that do not have
365d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// a message loop or do not have a TYPE_GPU message loop.
366d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool g_create_child_windows = false;
367d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif
368d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLSurfaceGLX::GLSurfaceGLX() {}
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::InitializeOneOff() {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool initialized = false;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (initialized)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // http://crbug.com/245466
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  setenv("force_s3tc_enable", "true", 1);
380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SGIVideoSyncProviderShim (if instantiated) will issue X commands on
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it's own thread.
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XInitThreads();
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if defined(TOOLKIT_GTK)
386d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Be sure to use the X display handle and not the GTK display handle if this
387d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // is the GPU process.
388d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  g_create_child_windows =
389d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      base::MessageLoop::current() &&
390d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      base::MessageLoop::current()->type() == base::MessageLoop::TYPE_GPU;
391d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
392d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (g_create_child_windows)
393d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    g_display = base::MessagePumpX11::GetDefaultXDisplay();
394d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  else
395d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    g_display = base::MessagePumpForUI::GetDefaultXDisplay();
396d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#else
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_display = base::MessagePumpForUI::GetDefaultXDisplay();
398d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif
399d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!g_display) {
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "XOpenDisplay failed.";
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int major, minor;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!glXQueryVersion(g_display, &major, &minor)) {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "glxQueryVersion failed";
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (major == 1 && minor < 3) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "GLX 1.3 or later is required.";
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_glx_extensions = glXQueryExtensionsString(g_display, 0);
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_glx_context_create =
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      HasGLXExtension("GLX_ARB_create_context");
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_glx_create_context_robustness_supported =
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HasGLXExtension("GLX_ARB_create_context_robustness");
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_glx_texture_from_pixmap_supported =
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HasGLXExtension("GLX_EXT_texture_from_pixmap");
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_glx_oml_sync_control_supported =
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HasGLXExtension("GLX_OML_sync_control");
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_glx_get_msc_rate_oml_supported = g_glx_oml_sync_control_supported;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_glx_sgi_video_sync_supported =
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HasGLXExtension("GLX_SGI_video_sync");
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!g_glx_get_msc_rate_oml_supported && g_glx_sgi_video_sync_supported)
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SGIVideoSyncProviderThreadShim::display_ = XOpenDisplay(NULL);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  initialized = true;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* GLSurfaceGLX::GetGLXExtensions() {
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_glx_extensions;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::HasGLXExtension(const char* name) {
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ExtensionsContain(GetGLXExtensions(), name);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GLSurfaceGLX::IsCreateContextSupported() {
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return g_glx_context_create;
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::IsCreateContextRobustnessSupported() {
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_glx_create_context_robustness_supported;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::IsTextureFromPixmapSupported() {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_glx_texture_from_pixmap_supported;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::IsOMLSyncControlSupported() {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_glx_oml_sync_control_supported;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* GLSurfaceGLX::GetDisplay() {
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_display;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLSurfaceGLX::~GLSurfaceGLX() {}
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
472d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if defined(TOOLKIT_GTK)
473d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool NativeViewGLSurfaceGLX::SetBackbufferAllocation(bool allocated) {
474d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  backbuffer_allocated_ = allocated;
475d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  AdjustBufferAllocation();
476d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return true;
477d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
478d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
479d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void NativeViewGLSurfaceGLX::SetFrontbufferAllocation(bool allocated) {
480d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  frontbuffer_allocated_ = allocated;
481d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  AdjustBufferAllocation();
482d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
483d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
484d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void NativeViewGLSurfaceGLX::AdjustBufferAllocation() {
485d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!g_create_child_windows)
486d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
487d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
488d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (frontbuffer_allocated_ || backbuffer_allocated_)
489d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    CreateChildWindow();
490d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  else
491d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DestroyChildWindow();
492d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
493d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
494d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void NativeViewGLSurfaceGLX::CreateChildWindow() {
495d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(g_create_child_windows);
496d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
497d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (child_window_)
498d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
499d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
500d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  XSetWindowAttributes set_window_attributes;
501d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  set_window_attributes.event_mask = ExposureMask;
502d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  child_window_ = XCreateWindow(
503d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      g_display, parent_window_, 0, 0, size_.width(), size_.height(), 0,
504d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      CopyFromParent, InputOutput, CopyFromParent, CWEventMask,
505d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      &set_window_attributes);
506d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  g_xexpose_event_forwarder.Pointer()->AddParentChildPair(
507d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      parent_window_, child_window_);
508d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
509d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  XMapWindow(g_display, child_window_);
510d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  XFlush(g_display);
511d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
512d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
513d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void NativeViewGLSurfaceGLX::DestroyChildWindow() {
514d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!child_window_)
515d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
516d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
517d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  g_xexpose_event_forwarder.Pointer()->RemoveParentChildPair(
518d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      parent_window_, child_window_);
519d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  XDestroyWindow(g_display, child_window_);
520d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  XFlush(g_display);
521d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  child_window_ = 0;
522d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
523d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif
524d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::AcceleratedWidget window)
526d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  : parent_window_(window),
527d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if defined(TOOLKIT_GTK)
528d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    child_window_(0),
529d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    dummy_window_(0),
530d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    backbuffer_allocated_(true),
531d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    frontbuffer_allocated_(true),
532d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_(NULL) {
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
536d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)gfx::AcceleratedWidget NativeViewGLSurfaceGLX::GetDrawableHandle() const {
537d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if defined(TOOLKIT_GTK)
538d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (g_create_child_windows) {
539d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (child_window_)
540d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return child_window_;
541d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return dummy_window_;
542d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
543d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif
544d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return parent_window_;
545d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
546d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::Initialize() {
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XWindowAttributes attributes;
549d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!XGetWindowAttributes(g_display, parent_window_, &attributes)) {
550d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    LOG(ERROR) << "XGetWindowAttributes failed for window " << parent_window_
551d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        << ".";
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_ = gfx::Size(attributes.width, attributes.height);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
556d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  gfx::AcceleratedWidget window_for_vsync = parent_window_;
557d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
558d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if defined(TOOLKIT_GTK)
559d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (g_create_child_windows) {
560d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    dummy_window_ = XCreateWindow(
561d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        g_display,
562d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        RootWindow(g_display, XScreenNumberOfScreen(attributes.screen)),
563d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        0, 0, 1, 1, 0, CopyFromParent, InputOutput, attributes.visual, 0, NULL);
564d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    window_for_vsync = dummy_window_;
565d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    CreateChildWindow();
566d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
567d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif
568d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_glx_oml_sync_control_supported)
570d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    vsync_provider_.reset(new OMLSyncControlVSyncProvider(window_for_vsync));
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (g_glx_sgi_video_sync_supported)
572d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    vsync_provider_.reset(new SGIVideoSyncVSyncProvider(window_for_vsync));
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NativeViewGLSurfaceGLX::Destroy() {
578d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if defined(TOOLKIT_GTK)
579d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DestroyChildWindow();
580d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (dummy_window_)
581d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    XDestroyWindow(g_display, dummy_window_);
582d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  dummy_window_ = 0;
583d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::Resize(const gfx::Size& size) {
587d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if defined(TOOLKIT_GTK)
588d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (child_window_) {
589d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    XResizeWindow(g_display, child_window_, size.width(), size.height());
590d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    XFlush(g_display);
591d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
592d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_ = size;
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::IsOffscreen() {
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::SwapBuffers() {
6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TRACE_EVENT2("gpu", "NativeViewGLSurfaceGLX:RealSwapBuffers",
6035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "width", GetSize().width(),
6045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "height", GetSize().height());
6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
606d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  glXSwapBuffers(g_display, GetDrawableHandle());
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size NativeViewGLSurfaceGLX::GetSize() {
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return size_;
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* NativeViewGLSurfaceGLX::GetHandle() {
615d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return reinterpret_cast<void*>(GetDrawableHandle());
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
618effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool NativeViewGLSurfaceGLX::SupportsPostSubBuffer() {
619effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer;
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* NativeViewGLSurfaceGLX::GetConfig() {
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!config_) {
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This code path is expensive, but we only take it when
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // attempting to use GLX_ARB_create_context_robustness, in which
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // case we need a GLXFBConfig for the window in order to create a
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // context for it.
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(kbr): this is not a reliable code path. On platforms which
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // support it, we should use glXChooseFBConfig in the browser
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // process to choose the FBConfig and from there the X Visual to
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // use when creating the window in the first place. Then we can
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // pass that FBConfig down rather than attempting to reconstitute
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // it.
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XWindowAttributes attributes;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!XGetWindowAttributes(
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        g_display,
639d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        parent_window_,
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &attributes)) {
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "XGetWindowAttributes failed for window " <<
642d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          parent_window_ << ".";
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int visual_id = XVisualIDFromVisual(attributes.visual);
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_elements = 0;
649a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_ptr<GLXFBConfig, ScopedPtrXFree> configs(
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        glXGetFBConfigs(g_display,
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        DefaultScreen(g_display),
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        &num_elements));
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!configs.get()) {
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "glXGetFBConfigs failed.";
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!num_elements) {
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "glXGetFBConfigs returned 0 elements.";
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool found = false;
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < num_elements; ++i) {
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int value;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (glXGetFBConfigAttrib(
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              g_display, configs.get()[i], GLX_VISUAL_ID, &value)) {
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(ERROR) << "glXGetFBConfigAttrib failed.";
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (value == visual_id) {
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        found = true;
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (found) {
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      config_ = configs.get()[i];
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return config_;
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::PostSubBuffer(
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int x, int y, int width, int height) {
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer);
686d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  glXCopySubBufferMESA(g_display, GetDrawableHandle(), x, y, width, height);
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)VSyncProvider* NativeViewGLSurfaceGLX::GetVSyncProvider() {
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return vsync_provider_.get();
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX()
695d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  : parent_window_(0),
696d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if defined(TOOLKIT_GTK)
697d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    child_window_(0),
698d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    dummy_window_(0),
699d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    backbuffer_allocated_(true),
700d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    frontbuffer_allocated_(true),
701d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_(NULL) {
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NativeViewGLSurfaceGLX::~NativeViewGLSurfaceGLX() {
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Destroy();
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PbufferGLSurfaceGLX::PbufferGLSurfaceGLX(const gfx::Size& size)
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : size_(size),
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_(NULL),
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pbuffer_(0) {
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PbufferGLSurfaceGLX::Initialize() {
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!pbuffer_);
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int config_attributes[] = {
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_BUFFER_SIZE, 32,
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_ALPHA_SIZE, 8,
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_BLUE_SIZE, 8,
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_GREEN_SIZE, 8,
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_RED_SIZE, 8,
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_RENDER_TYPE, GLX_RGBA_BIT,
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_DOUBLEBUFFER, False,
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_elements = 0;
731a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<GLXFBConfig, ScopedPtrXFree> configs(
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      glXChooseFBConfig(g_display,
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        DefaultScreen(g_display),
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        config_attributes,
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        &num_elements));
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!configs.get()) {
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "glXChooseFBConfig failed.";
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!num_elements) {
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "glXChooseFBConfig returned 0 elements.";
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_ = configs.get()[0];
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int pbuffer_attributes[] = {
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_PBUFFER_WIDTH, size_.width(),
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_PBUFFER_HEIGHT, size_.height(),
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pbuffer_ = glXCreatePbuffer(g_display,
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              static_cast<GLXFBConfig>(config_),
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              pbuffer_attributes);
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pbuffer_) {
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Destroy();
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "glXCreatePbuffer failed.";
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PbufferGLSurfaceGLX::Destroy() {
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pbuffer_) {
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    glXDestroyPbuffer(g_display, pbuffer_);
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pbuffer_ = 0;
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_ = NULL;
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PbufferGLSurfaceGLX::IsOffscreen() {
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PbufferGLSurfaceGLX::SwapBuffers() {
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer.";
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size PbufferGLSurfaceGLX::GetSize() {
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return size_;
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* PbufferGLSurfaceGLX::GetHandle() {
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return reinterpret_cast<void*>(pbuffer_);
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* PbufferGLSurfaceGLX::GetConfig() {
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return config_;
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PbufferGLSurfaceGLX::~PbufferGLSurfaceGLX() {
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Destroy();
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gfx
799