gl_surface_glx.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/time.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/mesa/MesaLib/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) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SGIVideoSyncProviderShim (if instantiated) will issue X commands on 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it's own thread. 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XInitThreads(); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_display = base::MessagePumpForUI::GetDefaultXDisplay(); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!g_display) { 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "XOpenDisplay failed."; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int major, minor; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!glXQueryVersion(g_display, &major, &minor)) { 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "glxQueryVersion failed"; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (major == 1 && minor < 3) { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "GLX 1.3 or later is required."; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_glx_extensions = glXQueryExtensionsString(g_display, 0); 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) g_glx_context_create = 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HasGLXExtension("GLX_ARB_create_context"); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_glx_create_context_robustness_supported = 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HasGLXExtension("GLX_ARB_create_context_robustness"); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_glx_texture_from_pixmap_supported = 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HasGLXExtension("GLX_EXT_texture_from_pixmap"); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_glx_oml_sync_control_supported = 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HasGLXExtension("GLX_OML_sync_control"); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_glx_get_msc_rate_oml_supported = g_glx_oml_sync_control_supported; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_glx_sgi_video_sync_supported = 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HasGLXExtension("GLX_SGI_video_sync"); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!g_glx_get_msc_rate_oml_supported && g_glx_sgi_video_sync_supported) 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SGIVideoSyncProviderThreadShim::display_ = XOpenDisplay(NULL); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized = true; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* GLSurfaceGLX::GetGLXExtensions() { 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_glx_extensions; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::HasGLXExtension(const char* name) { 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ExtensionsContain(GetGLXExtensions(), name); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GLSurfaceGLX::IsCreateContextSupported() { 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return g_glx_context_create; 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::IsCreateContextRobustnessSupported() { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_glx_create_context_robustness_supported; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::IsTextureFromPixmapSupported() { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_glx_texture_from_pixmap_supported; 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceGLX::IsOMLSyncControlSupported() { 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_glx_oml_sync_control_supported; 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* GLSurfaceGLX::GetDisplay() { 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_display; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLSurfaceGLX::~GLSurfaceGLX() {} 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::AcceleratedWidget window) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : window_(window), 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config_(NULL) { 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::Initialize() { 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XWindowAttributes attributes; 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!XGetWindowAttributes(g_display, window_, &attributes)) { 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << "."; 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_ = gfx::Size(attributes.width, attributes.height); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (g_glx_oml_sync_control_supported) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vsync_provider_.reset(new OMLSyncControlVSyncProvider(window_)); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (g_glx_sgi_video_sync_supported) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vsync_provider_.reset(new SGIVideoSyncVSyncProvider(window_)); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NativeViewGLSurfaceGLX::Destroy() { 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::Resize(const gfx::Size& size) { 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On Intel drivers, the frame buffer won't be resize until the next swap. If 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we only do PostSubBuffer, then we're stuck in the old size. Force a swap 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // now. 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer && size_ != size) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SwapBuffers(); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_ = size; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::IsOffscreen() { 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::SwapBuffers() { 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXSwapBuffers(g_display, window_); 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For latency_tests.cc: 430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UNSHIPPED_TRACE_EVENT_INSTANT0("test_gpu", "CompositorSwapBuffersComplete", 431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TRACE_EVENT_SCOPE_THREAD); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size NativeViewGLSurfaceGLX::GetSize() { 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return size_; 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* NativeViewGLSurfaceGLX::GetHandle() { 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<void*>(window_); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string NativeViewGLSurfaceGLX::GetExtensions() { 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string extensions = GLSurface::GetExtensions(); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer) { 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions += extensions.empty() ? "" : " "; 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions += "GL_CHROMIUM_post_sub_buffer"; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return extensions; 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* NativeViewGLSurfaceGLX::GetConfig() { 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!config_) { 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This code path is expensive, but we only take it when 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // attempting to use GLX_ARB_create_context_robustness, in which 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // case we need a GLXFBConfig for the window in order to create a 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // context for it. 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(kbr): this is not a reliable code path. On platforms which 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // support it, we should use glXChooseFBConfig in the browser 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // process to choose the FBConfig and from there the X Visual to 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // use when creating the window in the first place. Then we can 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pass that FBConfig down rather than attempting to reconstitute 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it. 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XWindowAttributes attributes; 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!XGetWindowAttributes( 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_display, 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) window_, 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &attributes)) { 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "XGetWindowAttributes failed for window " << 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) window_ << "."; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int visual_id = XVisualIDFromVisual(attributes.visual); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_elements = 0; 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> configs( 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXGetFBConfigs(g_display, 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DefaultScreen(g_display), 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &num_elements)); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!configs.get()) { 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "glXGetFBConfigs failed."; 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!num_elements) { 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "glXGetFBConfigs returned 0 elements."; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool found = false; 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < num_elements; ++i) { 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int value; 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (glXGetFBConfigAttrib( 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_display, configs.get()[i], GLX_VISUAL_ID, &value)) { 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "glXGetFBConfigAttrib failed."; 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (value == visual_id) { 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found = true; 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found) { 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config_ = configs.get()[i]; 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return config_; 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeViewGLSurfaceGLX::PostSubBuffer( 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x, int y, int width, int height) { 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXCopySubBufferMESA(g_display, window_, x, y, width, height); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)VSyncProvider* NativeViewGLSurfaceGLX::GetVSyncProvider() { 5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return vsync_provider_.get(); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX() 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : window_(0), 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config_(NULL) { 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NativeViewGLSurfaceGLX::~NativeViewGLSurfaceGLX() { 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Destroy(); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PbufferGLSurfaceGLX::PbufferGLSurfaceGLX(const gfx::Size& size) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : size_(size), 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config_(NULL), 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pbuffer_(0) { 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PbufferGLSurfaceGLX::Initialize() { 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!pbuffer_); 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int config_attributes[] = { 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLX_BUFFER_SIZE, 32, 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLX_ALPHA_SIZE, 8, 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLX_BLUE_SIZE, 8, 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLX_GREEN_SIZE, 8, 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLX_RED_SIZE, 8, 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLX_RENDER_TYPE, GLX_RGBA_BIT, 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLX_DOUBLEBUFFER, False, 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_elements = 0; 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> configs( 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXChooseFBConfig(g_display, 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DefaultScreen(g_display), 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config_attributes, 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &num_elements)); 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!configs.get()) { 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "glXChooseFBConfig failed."; 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!num_elements) { 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "glXChooseFBConfig returned 0 elements."; 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config_ = configs.get()[0]; 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int pbuffer_attributes[] = { 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLX_PBUFFER_WIDTH, size_.width(), 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLX_PBUFFER_HEIGHT, size_.height(), 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pbuffer_ = glXCreatePbuffer(g_display, 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<GLXFBConfig>(config_), 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pbuffer_attributes); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pbuffer_) { 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Destroy(); 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "glXCreatePbuffer failed."; 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PbufferGLSurfaceGLX::Destroy() { 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pbuffer_) { 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXDestroyPbuffer(g_display, pbuffer_); 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pbuffer_ = 0; 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config_ = NULL; 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PbufferGLSurfaceGLX::IsOffscreen() { 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PbufferGLSurfaceGLX::SwapBuffers() { 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer."; 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size PbufferGLSurfaceGLX::GetSize() { 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return size_; 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* PbufferGLSurfaceGLX::GetHandle() { 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<void*>(pbuffer_); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* PbufferGLSurfaceGLX::GetConfig() { 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return config_; 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PbufferGLSurfaceGLX::~PbufferGLSurfaceGLX() { 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Destroy(); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace gfx 623