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"
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/single_thread_task_runner.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/cancellation_flag.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/thread_task_runner_handle.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/non_thread_safe.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/events/platform/platform_event_source.h"
26a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ui/gfx/x/x11_connection.h"
2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/gfx/x/x11_types.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_bindings.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_implementation.h"
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/gl/sync_control_vsync_provider.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// scoped_ptr functor for XFree(). Use as follows:
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//   scoped_ptr<XVisualInfo, ScopedPtrXFree> foo(...);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// where "XVisualInfo" is any X type that is freed with XFree.
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct ScopedPtrXFree {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void operator()(void* x) const {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::XFree(x);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)Display* g_display = NULL;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* g_glx_extensions = NULL;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool g_glx_context_create = false;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool g_glx_create_context_robustness_supported = false;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool g_glx_texture_from_pixmap_supported = false;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool g_glx_oml_sync_control_supported = false;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Track support of glXGetMscRateOML separately from GLX_OML_sync_control as a
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// whole since on some platforms (e.g. crosbug.com/34585), glXGetMscRateOML
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// always fails even though GLX_OML_sync_control is reported as being supported.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool g_glx_get_msc_rate_oml_supported = false;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool g_glx_sgi_video_sync_supported = false;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic const base::TimeDelta kGetVSyncParametersMinPeriod =
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_LINUX)
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // See crbug.com/373489
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // On Linux, querying the vsync parameters might burn CPU for up to an
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // entire vsync, so we only query periodically to reduce CPU usage.
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // 5 seconds is chosen somewhat abitrarily as a balance between:
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    //  a) Drift in the phase of our signal.
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    //  b) Potential janks from periodically pegging the CPU.
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::TimeDelta::FromSeconds(5);
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#else
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::TimeDelta::FromSeconds(0);
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class OMLSyncControlVSyncProvider
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public gfx::SyncControlVSyncProvider {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit OMLSyncControlVSyncProvider(gfx::AcceleratedWidget window)
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : SyncControlVSyncProvider(),
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        window_(window) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~OMLSyncControlVSyncProvider() { }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool GetSyncValues(int64* system_time,
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int64* media_stream_counter,
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int64* swap_buffer_counter) OVERRIDE {
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return glXGetSyncValuesOML(g_display, window_, system_time,
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               media_stream_counter, swap_buffer_counter);
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool GetMscRate(int32* numerator, int32* denominator) OVERRIDE {
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!g_glx_get_msc_rate_oml_supported)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!glXGetMscRateOML(g_display, window_, numerator, denominator)) {
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Once glXGetMscRateOML has been found to fail, don't try again,
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // since each failing call may spew an error message.
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      g_glx_get_msc_rate_oml_supported = false;
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XID window_;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OMLSyncControlVSyncProvider);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SGIVideoSyncThread
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     : public base::Thread,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       public base::NonThreadSafe,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       public base::RefCounted<SGIVideoSyncThread> {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static scoped_refptr<SGIVideoSyncThread> Create() {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!g_video_sync_thread) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      g_video_sync_thread = new SGIVideoSyncThread();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      g_video_sync_thread->Start();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return g_video_sync_thread;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCounted<SGIVideoSyncThread>;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SGIVideoSyncThread() : base::Thread("SGI_video_sync") {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(CalledOnValidThread());
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~SGIVideoSyncThread() {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(CalledOnValidThread());
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_video_sync_thread = NULL;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Stop();
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static SGIVideoSyncThread* g_video_sync_thread;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncThread);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class SGIVideoSyncProviderThreadShim {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit SGIVideoSyncProviderThreadShim(XID window)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : window_(window),
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        context_(NULL),
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        task_runner_(base::ThreadTaskRunnerHandle::Get()),
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cancel_vsync_flag_(),
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        vsync_lock_() {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This ensures that creation of |window_| has occured when this shim
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // is executing in the same process as the call to create |window_|.
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    XSync(g_display, False);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~SGIVideoSyncProviderThreadShim() {
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (context_) {
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      glXDestroyContext(display_, context_);
15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      context_ = NULL;
15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::CancellationFlag* cancel_vsync_flag() {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &cancel_vsync_flag_;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Lock* vsync_lock() {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &vsync_lock_;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Initialize() {
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(display_);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XWindowAttributes attributes;
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!XGetWindowAttributes(display_, window_, &attributes)) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "XGetWindowAttributes failed for window " <<
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        window_ << ".";
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XVisualInfo visual_info_template;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    visual_info_template.visualid = XVisualIDFromVisual(attributes.visual);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int visual_info_count = 0;
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_ptr<XVisualInfo, ScopedPtrXFree> visual_info_list(
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        XGetVisualInfo(display_, VisualIDMask,
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       &visual_info_template, &visual_info_count));
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(visual_info_list.get());
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (visual_info_count == 0) {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "No visual info for visual ID.";
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    context_ = glXCreateContext(display_, visual_info_list.get(), NULL, True);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(NULL != context_);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void GetVSyncParameters(const VSyncProvider::UpdateVSyncCallback& callback) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeTicks now;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Don't allow |window_| destruction while we're probing vsync.
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::AutoLock locked(vsync_lock_);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!context_ || cancel_vsync_flag_.IsSet())
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      glXMakeCurrent(display_, window_, context_);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int retrace_count = 0;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (glXWaitVideoSyncSGI(1, 0, &retrace_count) != 0)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      TRACE_EVENT_INSTANT0("gpu", "vblank", TRACE_EVENT_SCOPE_THREAD);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      now = base::TimeTicks::HighResNow();
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      glXMakeCurrent(display_, 0, 0);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::TimeDelta kDefaultInterval =
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::TimeDelta::FromSeconds(1) / 60;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    task_runner_->PostTask(
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE, base::Bind(callback, now, kDefaultInterval));
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For initialization of display_ in GLSurface::InitializeOneOff before
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the sandbox goes up.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class gfx::GLSurfaceGLX;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static Display* display_;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XID window_;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLXContext context_;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::CancellationFlag cancel_vsync_flag_;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Lock vsync_lock_;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncProviderThreadShim);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SGIVideoSyncVSyncProvider
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public gfx::VSyncProvider,
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      public base::SupportsWeakPtr<SGIVideoSyncVSyncProvider> {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit SGIVideoSyncVSyncProvider(gfx::AcceleratedWidget window)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : vsync_thread_(SGIVideoSyncThread::Create()),
25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        shim_(new SGIVideoSyncProviderThreadShim(window)),
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cancel_vsync_flag_(shim_->cancel_vsync_flag()),
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        vsync_lock_(shim_->vsync_lock()) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vsync_thread_->message_loop()->PostTask(
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        base::Bind(&SGIVideoSyncProviderThreadShim::Initialize,
25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                   base::Unretained(shim_.get())));
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~SGIVideoSyncVSyncProvider() {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::AutoLock locked(*vsync_lock_);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cancel_vsync_flag_->Set();
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Hand-off |shim_| to be deleted on the |vsync_thread_|.
26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    vsync_thread_->message_loop()->DeleteSoon(
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
26890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        shim_.release());
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void GetVSyncParameters(
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const VSyncProvider::UpdateVSyncCallback& callback) OVERRIDE {
2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (kGetVSyncParametersMinPeriod > base::TimeDelta()) {
2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::TimeTicks now = base::TimeTicks::Now();
2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::TimeDelta delta = now - last_get_vsync_parameters_time_;
2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (delta < kGetVSyncParametersMinPeriod)
2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        return;
2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      last_get_vsync_parameters_time_ = now;
2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Only one outstanding request per surface.
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!pending_callback_) {
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_callback_.reset(
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new VSyncProvider::UpdateVSyncCallback(callback));
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      vsync_thread_->message_loop()->PostTask(
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE,
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&SGIVideoSyncProviderThreadShim::GetVSyncParameters,
28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     base::Unretained(shim_.get()),
28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     base::Bind(
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         &SGIVideoSyncVSyncProvider::PendingCallbackRunner,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         AsWeakPtr())));
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PendingCallbackRunner(const base::TimeTicks timebase,
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const base::TimeDelta interval) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(pending_callback_);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_callback_->Run(timebase, interval);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_callback_.reset();
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SGIVideoSyncThread> vsync_thread_;
30490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
30590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Thread shim through which the sync provider is accessed on |vsync_thread_|.
30690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SGIVideoSyncProviderThreadShim> shim_;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<VSyncProvider::UpdateVSyncCallback> pending_callback_;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Raw pointers to sync primitives owned by the shim_.
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These will only be referenced before we post a task to destroy
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the shim_, so they are safe to access.
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::CancellationFlag* cancel_vsync_flag_;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Lock* vsync_lock_;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::TimeTicks last_get_vsync_parameters_time_;
3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncVSyncProvider);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SGIVideoSyncThread* SGIVideoSyncThread::g_video_sync_thread = NULL;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In order to take advantage of GLX_SGI_video_sync, we need a display
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for use on a separate thread. We must allocate this before the sandbox
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// goes up (rather than on-demand when we start the thread).
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Display* SGIVideoSyncProviderThreadShim::display_ = NULL;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLSurfaceGLX::GLSurfaceGLX() {}
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::InitializeOneOff() {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool initialized = false;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (initialized)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // http://crbug.com/245466
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  setenv("force_s3tc_enable", "true", 1);
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SGIVideoSyncProviderShim (if instantiated) will issue X commands on
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it's own thread.
342a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  gfx::InitializeThreadedX11();
343a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  g_display = gfx::GetXDisplay();
344d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!g_display) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "XOpenDisplay failed.";
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int major, minor;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!glXQueryVersion(g_display, &major, &minor)) {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "glxQueryVersion failed";
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (major == 1 && minor < 3) {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "GLX 1.3 or later is required.";
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_glx_extensions = glXQueryExtensionsString(g_display, 0);
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_glx_context_create =
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      HasGLXExtension("GLX_ARB_create_context");
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_glx_create_context_robustness_supported =
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HasGLXExtension("GLX_ARB_create_context_robustness");
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_glx_texture_from_pixmap_supported =
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HasGLXExtension("GLX_EXT_texture_from_pixmap");
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_glx_oml_sync_control_supported =
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HasGLXExtension("GLX_OML_sync_control");
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_glx_get_msc_rate_oml_supported = g_glx_oml_sync_control_supported;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_glx_sgi_video_sync_supported =
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HasGLXExtension("GLX_SGI_video_sync");
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!g_glx_get_msc_rate_oml_supported && g_glx_sgi_video_sync_supported)
375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SGIVideoSyncProviderThreadShim::display_ = gfx::OpenNewXDisplay();
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  initialized = true;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* GLSurfaceGLX::GetGLXExtensions() {
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_glx_extensions;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::HasGLXExtension(const char* name) {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ExtensionsContain(GetGLXExtensions(), name);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GLSurfaceGLX::IsCreateContextSupported() {
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return g_glx_context_create;
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::IsCreateContextRobustnessSupported() {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_glx_create_context_robustness_supported;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::IsTextureFromPixmapSupported() {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_glx_texture_from_pixmap_supported;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::IsOMLSyncControlSupported() {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_glx_oml_sync_control_supported;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* GLSurfaceGLX::GetDisplay() {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_display;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLSurfaceGLX::~GLSurfaceGLX() {}
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::AcceleratedWidget window)
418d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  : parent_window_(window),
419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    window_(0),
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_(NULL) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
423d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)gfx::AcceleratedWidget NativeViewGLSurfaceGLX::GetDrawableHandle() const {
424cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return window_;
425d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
426d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::Initialize() {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XWindowAttributes attributes;
429d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!XGetWindowAttributes(g_display, parent_window_, &attributes)) {
430d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    LOG(ERROR) << "XGetWindowAttributes failed for window " << parent_window_
431d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        << ".";
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_ = gfx::Size(attributes.width, attributes.height);
435cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Create a child window, with a CopyFromParent visual (to avoid inducing
436cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // extra blits in the driver), that we can resize exactly in Resize(),
437cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // correctly ordered with GL, so that we don't have invalid transient states.
438cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // See https://crbug.com/326995.
439cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  window_ = XCreateWindow(g_display,
440cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          parent_window_,
441cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          0,
442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          0,
443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          size_.width(),
444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          size_.height(),
445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          0,
446cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          CopyFromParent,
447cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          InputOutput,
448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          CopyFromParent,
449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          0,
450cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          NULL);
451cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  XMapWindow(g_display, window_);
452cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
453cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ui::PlatformEventSource* event_source =
454cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ui::PlatformEventSource::GetInstance();
455cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Can be NULL in tests, when we don't care about Exposes.
456cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (event_source) {
457cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    XSelectInput(g_display, window_, ExposureMask);
458cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
459cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
460cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  XFlush(g_display);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
462cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  gfx::AcceleratedWidget window_for_vsync = window_;
463d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_glx_oml_sync_control_supported)
465d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    vsync_provider_.reset(new OMLSyncControlVSyncProvider(window_for_vsync));
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (g_glx_sgi_video_sync_supported)
467d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    vsync_provider_.reset(new SGIVideoSyncVSyncProvider(window_for_vsync));
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NativeViewGLSurfaceGLX::Destroy() {
473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (window_) {
474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ui::PlatformEventSource* event_source =
475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        ui::PlatformEventSource::GetInstance();
476cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (event_source)
477cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      event_source->RemovePlatformEventDispatcher(this);
478cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    XDestroyWindow(g_display, window_);
479cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    XFlush(g_display);
480cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
483cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool NativeViewGLSurfaceGLX::CanDispatchEvent(const ui::PlatformEvent& event) {
484cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return event->type == Expose && event->xexpose.window == window_;
485cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
487cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)uint32_t NativeViewGLSurfaceGLX::DispatchEvent(const ui::PlatformEvent& event) {
488cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  XEvent forwarded_event = *event;
489cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  forwarded_event.xexpose.window = parent_window_;
490cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  XSendEvent(g_display, parent_window_, False, ExposureMask,
491cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)             &forwarded_event);
492cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  XFlush(g_display);
493cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return ui::POST_DISPATCH_STOP_PROPAGATION;
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::Resize(const gfx::Size& size) {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_ = size;
498cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  glXWaitGL();
499cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  XResizeWindow(g_display, window_, size.width(), size.height());
500cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  glXWaitX();
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::IsOffscreen() {
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::SwapBuffers() {
5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TRACE_EVENT2("gpu", "NativeViewGLSurfaceGLX:RealSwapBuffers",
5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "width", GetSize().width(),
5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "height", GetSize().height());
5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
513d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  glXSwapBuffers(g_display, GetDrawableHandle());
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size NativeViewGLSurfaceGLX::GetSize() {
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return size_;
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* NativeViewGLSurfaceGLX::GetHandle() {
522d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return reinterpret_cast<void*>(GetDrawableHandle());
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool NativeViewGLSurfaceGLX::SupportsPostSubBuffer() {
526effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer;
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* NativeViewGLSurfaceGLX::GetConfig() {
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!config_) {
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This code path is expensive, but we only take it when
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // attempting to use GLX_ARB_create_context_robustness, in which
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // case we need a GLXFBConfig for the window in order to create a
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // context for it.
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(kbr): this is not a reliable code path. On platforms which
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // support it, we should use glXChooseFBConfig in the browser
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // process to choose the FBConfig and from there the X Visual to
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // use when creating the window in the first place. Then we can
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // pass that FBConfig down rather than attempting to reconstitute
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // it.
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XWindowAttributes attributes;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!XGetWindowAttributes(
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        g_display,
546cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        window_,
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &attributes)) {
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "XGetWindowAttributes failed for window " <<
549cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          window_ << ".";
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int visual_id = XVisualIDFromVisual(attributes.visual);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_elements = 0;
556a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_ptr<GLXFBConfig, ScopedPtrXFree> configs(
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        glXGetFBConfigs(g_display,
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        DefaultScreen(g_display),
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        &num_elements));
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!configs.get()) {
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "glXGetFBConfigs failed.";
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!num_elements) {
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "glXGetFBConfigs returned 0 elements.";
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool found = false;
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < num_elements; ++i) {
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int value;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (glXGetFBConfigAttrib(
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              g_display, configs.get()[i], GLX_VISUAL_ID, &value)) {
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(ERROR) << "glXGetFBConfigAttrib failed.";
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (value == visual_id) {
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        found = true;
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (found) {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      config_ = configs.get()[i];
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return config_;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::PostSubBuffer(
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int x, int y, int width, int height) {
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer);
593d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  glXCopySubBufferMESA(g_display, GetDrawableHandle(), x, y, width, height);
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)VSyncProvider* NativeViewGLSurfaceGLX::GetVSyncProvider() {
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return vsync_provider_.get();
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NativeViewGLSurfaceGLX::~NativeViewGLSurfaceGLX() {
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Destroy();
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PbufferGLSurfaceGLX::PbufferGLSurfaceGLX(const gfx::Size& size)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : size_(size),
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_(NULL),
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pbuffer_(0) {
609cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Some implementations of Pbuffer do not support having a 0 size. For such
610cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // cases use a (1, 1) surface.
611cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (size_.GetArea() == 0)
612cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    size_.SetSize(1, 1);
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PbufferGLSurfaceGLX::Initialize() {
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!pbuffer_);
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int config_attributes[] = {
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_BUFFER_SIZE, 32,
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_ALPHA_SIZE, 8,
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_BLUE_SIZE, 8,
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_GREEN_SIZE, 8,
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_RED_SIZE, 8,
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_RENDER_TYPE, GLX_RGBA_BIT,
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_DOUBLEBUFFER, False,
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_elements = 0;
631a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<GLXFBConfig, ScopedPtrXFree> configs(
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      glXChooseFBConfig(g_display,
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        DefaultScreen(g_display),
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        config_attributes,
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        &num_elements));
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!configs.get()) {
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "glXChooseFBConfig failed.";
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!num_elements) {
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "glXChooseFBConfig returned 0 elements.";
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_ = configs.get()[0];
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int pbuffer_attributes[] = {
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_PBUFFER_WIDTH, size_.width(),
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_PBUFFER_HEIGHT, size_.height(),
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pbuffer_ = glXCreatePbuffer(g_display,
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              static_cast<GLXFBConfig>(config_),
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              pbuffer_attributes);
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pbuffer_) {
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Destroy();
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "glXCreatePbuffer failed.";
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PbufferGLSurfaceGLX::Destroy() {
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pbuffer_) {
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    glXDestroyPbuffer(g_display, pbuffer_);
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pbuffer_ = 0;
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_ = NULL;
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PbufferGLSurfaceGLX::IsOffscreen() {
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PbufferGLSurfaceGLX::SwapBuffers() {
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer.";
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size PbufferGLSurfaceGLX::GetSize() {
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return size_;
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* PbufferGLSurfaceGLX::GetHandle() {
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return reinterpret_cast<void*>(pbuffer_);
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* PbufferGLSurfaceGLX::GetConfig() {
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return config_;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PbufferGLSurfaceGLX::~PbufferGLSurfaceGLX() {
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Destroy();
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gfx
699