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"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h"
16ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/cancellation_flag.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/non_thread_safe.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/mesa/src/include/GL/osmesa.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/x/x11_util.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_bindings.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_implementation.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gl/vsync_provider.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// scoped_ptr functor for XFree(). Use as follows:
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> foo(...);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// where "XVisualInfo" is any X type that is freed with XFree.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ScopedPtrXFree {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void operator()(void* x) const {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::XFree(x);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Display* g_display;
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;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr_malloc<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)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLSurfaceGLX::GLSurfaceGLX() {}
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::InitializeOneOff() {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool initialized = false;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (initialized)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // http://crbug.com/245466
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  setenv("force_s3tc_enable", "true", 1);
313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SGIVideoSyncProviderShim (if instantiated) will issue X commands on
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it's own thread.
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XInitThreads();
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_display = base::MessagePumpForUI::GetDefaultXDisplay();
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!g_display) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "XOpenDisplay failed.";
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int major, minor;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!glXQueryVersion(g_display, &major, &minor)) {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "glxQueryVersion failed";
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (major == 1 && minor < 3) {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "GLX 1.3 or later is required.";
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_glx_extensions = glXQueryExtensionsString(g_display, 0);
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_glx_context_create =
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      HasGLXExtension("GLX_ARB_create_context");
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_glx_create_context_robustness_supported =
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HasGLXExtension("GLX_ARB_create_context_robustness");
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_glx_texture_from_pixmap_supported =
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HasGLXExtension("GLX_EXT_texture_from_pixmap");
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_glx_oml_sync_control_supported =
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HasGLXExtension("GLX_OML_sync_control");
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_glx_get_msc_rate_oml_supported = g_glx_oml_sync_control_supported;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_glx_sgi_video_sync_supported =
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HasGLXExtension("GLX_SGI_video_sync");
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!g_glx_get_msc_rate_oml_supported && g_glx_sgi_video_sync_supported)
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SGIVideoSyncProviderThreadShim::display_ = XOpenDisplay(NULL);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  initialized = true;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* GLSurfaceGLX::GetGLXExtensions() {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_glx_extensions;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::HasGLXExtension(const char* name) {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ExtensionsContain(GetGLXExtensions(), name);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GLSurfaceGLX::IsCreateContextSupported() {
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return g_glx_context_create;
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::IsCreateContextRobustnessSupported() {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_glx_create_context_robustness_supported;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::IsTextureFromPixmapSupported() {
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_glx_texture_from_pixmap_supported;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::IsOMLSyncControlSupported() {
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_glx_oml_sync_control_supported;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* GLSurfaceGLX::GetDisplay() {
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_display;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLSurfaceGLX::~GLSurfaceGLX() {}
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::AcceleratedWidget window)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : window_(window),
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_(NULL) {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::Initialize() {
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XWindowAttributes attributes;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!XGetWindowAttributes(g_display, window_, &attributes)) {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_ = gfx::Size(attributes.width, attributes.height);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_glx_oml_sync_control_supported)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vsync_provider_.reset(new OMLSyncControlVSyncProvider(window_));
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (g_glx_sgi_video_sync_supported)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vsync_provider_.reset(new SGIVideoSyncVSyncProvider(window_));
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NativeViewGLSurfaceGLX::Destroy() {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::Resize(const gfx::Size& size) {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_ = size;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::IsOffscreen() {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::SwapBuffers() {
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glXSwapBuffers(g_display, window_);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size NativeViewGLSurfaceGLX::GetSize() {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return size_;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* NativeViewGLSurfaceGLX::GetHandle() {
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return reinterpret_cast<void*>(window_);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string NativeViewGLSurfaceGLX::GetExtensions() {
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string extensions = GLSurface::GetExtensions();
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer) {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions += extensions.empty() ? "" : " ";
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions += "GL_CHROMIUM_post_sub_buffer";
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return extensions;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* NativeViewGLSurfaceGLX::GetConfig() {
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!config_) {
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This code path is expensive, but we only take it when
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // attempting to use GLX_ARB_create_context_robustness, in which
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // case we need a GLXFBConfig for the window in order to create a
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // context for it.
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(kbr): this is not a reliable code path. On platforms which
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // support it, we should use glXChooseFBConfig in the browser
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // process to choose the FBConfig and from there the X Visual to
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // use when creating the window in the first place. Then we can
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // pass that FBConfig down rather than attempting to reconstitute
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // it.
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XWindowAttributes attributes;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!XGetWindowAttributes(
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        g_display,
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        window_,
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &attributes)) {
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "XGetWindowAttributes failed for window " <<
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          window_ << ".";
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int visual_id = XVisualIDFromVisual(attributes.visual);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_elements = 0;
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> configs(
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        glXGetFBConfigs(g_display,
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        DefaultScreen(g_display),
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        &num_elements));
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!configs.get()) {
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "glXGetFBConfigs failed.";
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!num_elements) {
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "glXGetFBConfigs returned 0 elements.";
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool found = false;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < num_elements; ++i) {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int value;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (glXGetFBConfigAttrib(
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              g_display, configs.get()[i], GLX_VISUAL_ID, &value)) {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(ERROR) << "glXGetFBConfigAttrib failed.";
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (value == visual_id) {
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        found = true;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (found) {
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      config_ = configs.get()[i];
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return config_;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::PostSubBuffer(
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int x, int y, int width, int height) {
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glXCopySubBufferMESA(g_display, window_, x, y, width, height);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)VSyncProvider* NativeViewGLSurfaceGLX::GetVSyncProvider() {
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return vsync_provider_.get();
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX()
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : window_(0),
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_(NULL) {
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NativeViewGLSurfaceGLX::~NativeViewGLSurfaceGLX() {
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Destroy();
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PbufferGLSurfaceGLX::PbufferGLSurfaceGLX(const gfx::Size& size)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : size_(size),
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_(NULL),
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pbuffer_(0) {
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PbufferGLSurfaceGLX::Initialize() {
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!pbuffer_);
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int config_attributes[] = {
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_BUFFER_SIZE, 32,
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_ALPHA_SIZE, 8,
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_BLUE_SIZE, 8,
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_GREEN_SIZE, 8,
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_RED_SIZE, 8,
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_RENDER_TYPE, GLX_RGBA_BIT,
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_DOUBLEBUFFER, False,
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_elements = 0;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> configs(
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      glXChooseFBConfig(g_display,
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        DefaultScreen(g_display),
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        config_attributes,
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        &num_elements));
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!configs.get()) {
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "glXChooseFBConfig failed.";
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!num_elements) {
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "glXChooseFBConfig returned 0 elements.";
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_ = configs.get()[0];
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int pbuffer_attributes[] = {
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_PBUFFER_WIDTH, size_.width(),
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLX_PBUFFER_HEIGHT, size_.height(),
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pbuffer_ = glXCreatePbuffer(g_display,
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              static_cast<GLXFBConfig>(config_),
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              pbuffer_attributes);
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pbuffer_) {
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Destroy();
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "glXCreatePbuffer failed.";
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PbufferGLSurfaceGLX::Destroy() {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pbuffer_) {
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    glXDestroyPbuffer(g_display, pbuffer_);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pbuffer_ = 0;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_ = NULL;
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PbufferGLSurfaceGLX::IsOffscreen() {
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PbufferGLSurfaceGLX::SwapBuffers() {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer.";
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size PbufferGLSurfaceGLX::GetSize() {
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return size_;
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* PbufferGLSurfaceGLX::GetHandle() {
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return reinterpret_cast<void*>(pbuffer_);
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* PbufferGLSurfaceGLX::GetConfig() {
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return config_;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PbufferGLSurfaceGLX::~PbufferGLSurfaceGLX() {
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Destroy();
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gfx
617