gl_surface_glx.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/process_util.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/cancellation_flag.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/non_thread_safe.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/mesa/src/include/GL/osmesa.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/x/x11_util.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_bindings.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_implementation.h" 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gl/vsync_provider.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// scoped_ptr functor for XFree(). Use as follows: 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> foo(...); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// where "XVisualInfo" is any X type that is freed with XFree. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ScopedPtrXFree { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void operator()(void* x) const { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::XFree(x); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Display* g_display; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* g_glx_extensions = NULL; 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool g_glx_context_create = false; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool g_glx_create_context_robustness_supported = false; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool g_glx_texture_from_pixmap_supported = false; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool g_glx_oml_sync_control_supported = false; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Track support of glXGetMscRateOML separately from GLX_OML_sync_control as a 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// whole since on some platforms (e.g. crosbug.com/34585), glXGetMscRateOML 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// always fails even though GLX_OML_sync_control is reported as being supported. 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool g_glx_get_msc_rate_oml_supported = false; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool g_glx_sgi_video_sync_supported = false; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class OMLSyncControlVSyncProvider 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : public gfx::SyncControlVSyncProvider { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit OMLSyncControlVSyncProvider(gfx::AcceleratedWidget window) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : SyncControlVSyncProvider(), 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) window_(window) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~OMLSyncControlVSyncProvider() { } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected: 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool GetSyncValues(int64* system_time, 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64* media_stream_counter, 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64* swap_buffer_counter) OVERRIDE { 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return glXGetSyncValuesOML(g_display, window_, system_time, 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) media_stream_counter, swap_buffer_counter); 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool GetMscRate(int32* numerator, int32* denominator) OVERRIDE { 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!g_glx_get_msc_rate_oml_supported) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!glXGetMscRateOML(g_display, window_, numerator, denominator)) { 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Once glXGetMscRateOML has been found to fail, don't try again, 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // since each failing call may spew an error message. 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) g_glx_get_msc_rate_oml_supported = false; 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID window_; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(OMLSyncControlVSyncProvider); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SGIVideoSyncThread 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public base::Thread, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public base::NonThreadSafe, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public base::RefCounted<SGIVideoSyncThread> { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static scoped_refptr<SGIVideoSyncThread> Create() { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!g_video_sync_thread) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_video_sync_thread = new SGIVideoSyncThread(); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_video_sync_thread->Start(); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_video_sync_thread; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::RefCounted<SGIVideoSyncThread>; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SGIVideoSyncThread() : base::Thread("SGI_video_sync") { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~SGIVideoSyncThread() { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_video_sync_thread = NULL; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Stop(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static SGIVideoSyncThread* g_video_sync_thread; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncThread); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class SGIVideoSyncProviderThreadShim { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit SGIVideoSyncProviderThreadShim(XID window) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : window_(window), 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_(NULL), 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_(base::MessageLoopProxy::current()), 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cancel_vsync_flag_(), 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vsync_lock_() { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This ensures that creation of |window_| has occured when this shim 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is executing in the same process as the call to create |window_|. 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) XSync(g_display, False); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual ~SGIVideoSyncProviderThreadShim() { 14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (context_) { 14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glXDestroyContext(display_, context_); 14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) context_ = NULL; 14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::CancellationFlag* cancel_vsync_flag() { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &cancel_vsync_flag_; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Lock* vsync_lock() { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &vsync_lock_; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Initialize() { 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(display_); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XWindowAttributes attributes; 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!XGetWindowAttributes(display_, window_, &attributes)) { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "XGetWindowAttributes failed for window " << 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_ << "."; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XVisualInfo visual_info_template; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visual_info_template.visualid = XVisualIDFromVisual(attributes.visual); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int visual_info_count = 0; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info_list( 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) XGetVisualInfo(display_, VisualIDMask, 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &visual_info_template, &visual_info_count)); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(visual_info_list.get()); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visual_info_count == 0) { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "No visual info for visual ID."; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) context_ = glXCreateContext(display_, visual_info_list.get(), NULL, True); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(NULL != context_); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void GetVSyncParameters(const VSyncProvider::UpdateVSyncCallback& callback) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks now; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't allow |window_| destruction while we're probing vsync. 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock locked(vsync_lock_); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!context_ || cancel_vsync_flag_.IsSet()) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) glXMakeCurrent(display_, window_, context_); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int retrace_count = 0; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (glXWaitVideoSyncSGI(1, 0, &retrace_count) != 0) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TRACE_EVENT_INSTANT0("gpu", "vblank", TRACE_EVENT_SCOPE_THREAD); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) now = base::TimeTicks::HighResNow(); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) glXMakeCurrent(display_, 0, 0); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::TimeDelta kDefaultInterval = 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta::FromSeconds(1) / 60; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_loop_->PostTask( 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, base::Bind(callback, now, kDefaultInterval)); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // For initialization of display_ in GLSurface::InitializeOneOff before 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the sandbox goes up. 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class gfx::GLSurfaceGLX; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static Display* display_; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID window_; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLXContext context_; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::MessageLoopProxy> message_loop_; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::CancellationFlag cancel_vsync_flag_; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Lock vsync_lock_; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncProviderThreadShim); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SGIVideoSyncVSyncProvider 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : public gfx::VSyncProvider, 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public base::SupportsWeakPtr<SGIVideoSyncVSyncProvider> { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit SGIVideoSyncVSyncProvider(gfx::AcceleratedWidget window) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : vsync_thread_(SGIVideoSyncThread::Create()), 23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) shim_(new SGIVideoSyncProviderThreadShim(window)), 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cancel_vsync_flag_(shim_->cancel_vsync_flag()), 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vsync_lock_(shim_->vsync_lock()) { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vsync_thread_->message_loop()->PostTask( 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Bind(&SGIVideoSyncProviderThreadShim::Initialize, 24190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Unretained(shim_.get()))); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~SGIVideoSyncVSyncProvider() { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock locked(*vsync_lock_); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cancel_vsync_flag_->Set(); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Hand-off |shim_| to be deleted on the |vsync_thread_|. 25190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) vsync_thread_->message_loop()->DeleteSoon( 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 25390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) shim_.release()); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void GetVSyncParameters( 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const VSyncProvider::UpdateVSyncCallback& callback) OVERRIDE { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only one outstanding request per surface. 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pending_callback_) { 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pending_callback_.reset( 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new VSyncProvider::UpdateVSyncCallback(callback)); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vsync_thread_->message_loop()->PostTask( 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&SGIVideoSyncProviderThreadShim::GetVSyncParameters, 26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Unretained(shim_.get()), 26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Bind( 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &SGIVideoSyncVSyncProvider::PendingCallbackRunner, 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsWeakPtr()))); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void PendingCallbackRunner(const base::TimeTicks timebase, 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::TimeDelta interval) { 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(pending_callback_); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_callback_->Run(timebase, interval); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_callback_.reset(); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<SGIVideoSyncThread> vsync_thread_; 28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 28290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Thread shim through which the sync provider is accessed on |vsync_thread_|. 28390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SGIVideoSyncProviderThreadShim> shim_; 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<VSyncProvider::UpdateVSyncCallback> pending_callback_; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Raw pointers to sync primitives owned by the shim_. 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These will only be referenced before we post a task to destroy 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the shim_, so they are safe to access. 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::CancellationFlag* cancel_vsync_flag_; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Lock* vsync_lock_; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncVSyncProvider); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SGIVideoSyncThread* SGIVideoSyncThread::g_video_sync_thread = NULL; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In order to take advantage of GLX_SGI_video_sync, we need a display 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for use on a separate thread. We must allocate this before the sandbox 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// goes up (rather than on-demand when we start the thread). 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Display* SGIVideoSyncProviderThreadShim::display_ = NULL; 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLSurfaceGLX::GLSurfaceGLX() {} 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::InitializeOneOff() { 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool initialized = false; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (initialized) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // http://crbug.com/245466 313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) setenv("force_s3tc_enable", "true", 1); 314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SGIVideoSyncProviderShim (if instantiated) will issue X commands on 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it's own thread. 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XInitThreads(); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_display = base::MessagePumpForUI::GetDefaultXDisplay(); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!g_display) { 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "XOpenDisplay failed."; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int major, minor; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!glXQueryVersion(g_display, &major, &minor)) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "glxQueryVersion failed"; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (major == 1 && minor < 3) { 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "GLX 1.3 or later is required."; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_glx_extensions = glXQueryExtensionsString(g_display, 0); 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) g_glx_context_create = 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HasGLXExtension("GLX_ARB_create_context"); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_glx_create_context_robustness_supported = 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HasGLXExtension("GLX_ARB_create_context_robustness"); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_glx_texture_from_pixmap_supported = 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HasGLXExtension("GLX_EXT_texture_from_pixmap"); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_glx_oml_sync_control_supported = 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HasGLXExtension("GLX_OML_sync_control"); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_glx_get_msc_rate_oml_supported = g_glx_oml_sync_control_supported; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_glx_sgi_video_sync_supported = 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HasGLXExtension("GLX_SGI_video_sync"); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!g_glx_get_msc_rate_oml_supported && g_glx_sgi_video_sync_supported) 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SGIVideoSyncProviderThreadShim::display_ = XOpenDisplay(NULL); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized = true; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* GLSurfaceGLX::GetGLXExtensions() { 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_glx_extensions; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::HasGLXExtension(const char* name) { 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ExtensionsContain(GetGLXExtensions(), name); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GLSurfaceGLX::IsCreateContextSupported() { 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return g_glx_context_create; 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::IsCreateContextRobustnessSupported() { 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_glx_create_context_robustness_supported; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::IsTextureFromPixmapSupported() { 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_glx_texture_from_pixmap_supported; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::IsOMLSyncControlSupported() { 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_glx_oml_sync_control_supported; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* GLSurfaceGLX::GetDisplay() { 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_display; 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLSurfaceGLX::~GLSurfaceGLX() {} 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::AcceleratedWidget window) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : window_(window), 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config_(NULL) { 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::Initialize() { 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XWindowAttributes attributes; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!XGetWindowAttributes(g_display, window_, &attributes)) { 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << "."; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_ = gfx::Size(attributes.width, attributes.height); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (g_glx_oml_sync_control_supported) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vsync_provider_.reset(new OMLSyncControlVSyncProvider(window_)); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (g_glx_sgi_video_sync_supported) 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vsync_provider_.reset(new SGIVideoSyncVSyncProvider(window_)); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NativeViewGLSurfaceGLX::Destroy() { 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::Resize(const gfx::Size& size) { 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_ = size; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::IsOffscreen() { 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::SwapBuffers() { 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXSwapBuffers(g_display, window_); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size NativeViewGLSurfaceGLX::GetSize() { 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return size_; 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* NativeViewGLSurfaceGLX::GetHandle() { 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<void*>(window_); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string NativeViewGLSurfaceGLX::GetExtensions() { 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string extensions = GLSurface::GetExtensions(); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer) { 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions += extensions.empty() ? "" : " "; 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions += "GL_CHROMIUM_post_sub_buffer"; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return extensions; 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* NativeViewGLSurfaceGLX::GetConfig() { 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!config_) { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This code path is expensive, but we only take it when 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // attempting to use GLX_ARB_create_context_robustness, in which 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // case we need a GLXFBConfig for the window in order to create a 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // context for it. 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(kbr): this is not a reliable code path. On platforms which 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // support it, we should use glXChooseFBConfig in the browser 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // process to choose the FBConfig and from there the X Visual to 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // use when creating the window in the first place. Then we can 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pass that FBConfig down rather than attempting to reconstitute 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it. 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XWindowAttributes attributes; 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!XGetWindowAttributes( 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_display, 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) window_, 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &attributes)) { 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "XGetWindowAttributes failed for window " << 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) window_ << "."; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int visual_id = XVisualIDFromVisual(attributes.visual); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_elements = 0; 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> configs( 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXGetFBConfigs(g_display, 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DefaultScreen(g_display), 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &num_elements)); 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!configs.get()) { 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "glXGetFBConfigs failed."; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!num_elements) { 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "glXGetFBConfigs returned 0 elements."; 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool found = false; 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < num_elements; ++i) { 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int value; 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (glXGetFBConfigAttrib( 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_display, configs.get()[i], GLX_VISUAL_ID, &value)) { 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "glXGetFBConfigAttrib failed."; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (value == visual_id) { 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found = true; 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found) { 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config_ = configs.get()[i]; 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return config_; 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::PostSubBuffer( 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x, int y, int width, int height) { 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXCopySubBufferMESA(g_display, window_, x, y, width, height); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)VSyncProvider* NativeViewGLSurfaceGLX::GetVSyncProvider() { 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return vsync_provider_.get(); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX() 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : window_(0), 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config_(NULL) { 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NativeViewGLSurfaceGLX::~NativeViewGLSurfaceGLX() { 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Destroy(); 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PbufferGLSurfaceGLX::PbufferGLSurfaceGLX(const gfx::Size& size) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : size_(size), 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config_(NULL), 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pbuffer_(0) { 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PbufferGLSurfaceGLX::Initialize() { 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!pbuffer_); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int config_attributes[] = { 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLX_BUFFER_SIZE, 32, 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLX_ALPHA_SIZE, 8, 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLX_BLUE_SIZE, 8, 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLX_GREEN_SIZE, 8, 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLX_RED_SIZE, 8, 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLX_RENDER_TYPE, GLX_RGBA_BIT, 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLX_DOUBLEBUFFER, False, 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_elements = 0; 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> configs( 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXChooseFBConfig(g_display, 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DefaultScreen(g_display), 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config_attributes, 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &num_elements)); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!configs.get()) { 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "glXChooseFBConfig failed."; 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!num_elements) { 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "glXChooseFBConfig returned 0 elements."; 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config_ = configs.get()[0]; 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int pbuffer_attributes[] = { 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLX_PBUFFER_WIDTH, size_.width(), 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLX_PBUFFER_HEIGHT, size_.height(), 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pbuffer_ = glXCreatePbuffer(g_display, 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<GLXFBConfig>(config_), 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pbuffer_attributes); 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pbuffer_) { 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Destroy(); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "glXCreatePbuffer failed."; 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PbufferGLSurfaceGLX::Destroy() { 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pbuffer_) { 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXDestroyPbuffer(g_display, pbuffer_); 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pbuffer_ = 0; 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config_ = NULL; 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PbufferGLSurfaceGLX::IsOffscreen() { 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PbufferGLSurfaceGLX::SwapBuffers() { 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer."; 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size PbufferGLSurfaceGLX::GetSize() { 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return size_; 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* PbufferGLSurfaceGLX::GetHandle() { 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<void*>(pbuffer_); 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* PbufferGLSurfaceGLX::GetConfig() { 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return config_; 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PbufferGLSurfaceGLX::~PbufferGLSurfaceGLX() { 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Destroy(); 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace gfx 618