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