Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(507)

Side by Side Diff: ui/gl/gl_surface_glx.cc

Issue 11752002: Calculate the refresh period from GLX_OML_sync_control. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: More sanity checking. Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 extern "C" { 5 extern "C" {
6 #include <X11/Xlib.h> 6 #include <X11/Xlib.h>
7 } 7 }
8 8
9 #include "ui/gl/gl_surface_glx.h" 9 #include "ui/gl/gl_surface_glx.h"
10 10
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 // whole since on some platforms (e.g. crosbug.com/34585), glXGetMscRateOML 50 // whole since on some platforms (e.g. crosbug.com/34585), glXGetMscRateOML
51 // always fails even though GLX_OML_sync_control is reported as being supported. 51 // always fails even though GLX_OML_sync_control is reported as being supported.
52 bool g_glx_get_msc_rate_oml_supported = false; 52 bool g_glx_get_msc_rate_oml_supported = false;
53 53
54 bool g_glx_sgi_video_sync_supported = false; 54 bool g_glx_sgi_video_sync_supported = false;
55 55
56 class OMLSyncControlVSyncProvider 56 class OMLSyncControlVSyncProvider
57 : public gfx::NativeViewGLSurfaceGLX::VSyncProvider { 57 : public gfx::NativeViewGLSurfaceGLX::VSyncProvider {
58 public: 58 public:
59 explicit OMLSyncControlVSyncProvider(gfx::AcceleratedWidget window) 59 explicit OMLSyncControlVSyncProvider(gfx::AcceleratedWidget window)
60 : window_(window) { 60 : window_(window),
61 last_timebase_(),
62 last_media_stream_counter_(0),
63 last_good_interval_(kDefaultIntervalTime) {
61 } 64 }
62 65
63 virtual ~OMLSyncControlVSyncProvider() { } 66 virtual ~OMLSyncControlVSyncProvider() { }
64 67
65 virtual void GetVSyncParameters( 68 virtual void GetVSyncParameters(
66 const GLSurface::UpdateVSyncCallback& callback) OVERRIDE { 69 const GLSurface::UpdateVSyncCallback& callback) OVERRIDE {
67 base::TimeTicks timebase; 70 base::TimeTicks timebase;
68 base::TimeDelta interval;
69 71
70 // The actual clock used for the system time returned by glXGetSyncValuesOML 72 // The actual clock used for the system time returned by glXGetSyncValuesOML
71 // is unspecified. In practice, the clock used is likely to be either 73 // is unspecified. In practice, the clock used is likely to be either
72 // CLOCK_REALTIME or CLOCK_MONOTONIC, so we compare the returned time to the 74 // CLOCK_REALTIME or CLOCK_MONOTONIC, so we compare the returned time to the
73 // current time according to both clocks, and assume that the returned time 75 // current time according to both clocks, and assume that the returned time
74 // was produced by the clock whose current time is closest to it, subject 76 // was produced by the clock whose current time is closest to it, subject
75 // to the restriction that the returned time must not be in the future 77 // to the restriction that the returned time must not be in the future
76 // (since it is the time of a vblank that has already occurred). 78 // (since it is the time of a vblank that has already occurred).
77 int64 system_time; 79 int64 system_time;
78 int64 media_stream_counter; 80 int64 media_stream_counter;
(...skipping 27 matching lines...) Expand all
106 108
107 if (time_conversion_needed) { 109 if (time_conversion_needed) {
108 int64 time_difference = 110 int64 time_difference =
109 real_time_in_microseconds - monotonic_time_in_microseconds; 111 real_time_in_microseconds - monotonic_time_in_microseconds;
110 timebase = base::TimeTicks::FromInternalValue( 112 timebase = base::TimeTicks::FromInternalValue(
111 system_time - time_difference); 113 system_time - time_difference);
112 } else { 114 } else {
113 timebase = base::TimeTicks::FromInternalValue(system_time); 115 timebase = base::TimeTicks::FromInternalValue(system_time);
114 } 116 }
115 117
116 // On platforms where glXGetMscRateOML doesn't work, we fall back to the
117 // assumption that we're displaying 60 frames per second.
118 const int64 kDefaultIntervalTime =
119 base::Time::kMicrosecondsPerSecond / 60;
120 int64 interval_time = kDefaultIntervalTime;
121 int32 numerator;
122 int32 denominator;
123 if (g_glx_get_msc_rate_oml_supported) { 118 if (g_glx_get_msc_rate_oml_supported) {
119 int32 numerator, denominator;
124 if (glXGetMscRateOML(g_display, window_, &numerator, &denominator)) { 120 if (glXGetMscRateOML(g_display, window_, &numerator, &denominator)) {
125 interval_time = 121 last_good_interval_ =
126 (base::Time::kMicrosecondsPerSecond * denominator) / numerator; 122 (base::Time::kMicrosecondsPerSecond * denominator) / numerator;
127 } else { 123 } else {
128 // Once glXGetMscRateOML has been found to fail, don't try again, 124 // Once glXGetMscRateOML has been found to fail, don't try again,
129 // since each failing call may spew an error message. 125 // since each failing call may spew an error message.
130 g_glx_get_msc_rate_oml_supported = false; 126 g_glx_get_msc_rate_oml_supported = false;
131 } 127 }
128 } else {
129 if (!last_timebase_.is_null()) {
130 base::TimeDelta timebase_diff = timebase - last_timebase_;
131 uint64 counter_diff = media_stream_counter -
132 last_media_stream_counter_;
133 if (counter_diff > 0 && timebase > last_timebase_) {
134 last_good_interval_ = timebase_diff.InMicroseconds() /
135 counter_diff;
136 }
137 }
132 } 138 }
133 interval = base::TimeDelta::FromMicroseconds(interval_time); 139 last_timebase_ = timebase;
140 last_media_stream_counter_ = media_stream_counter;
141 base::TimeDelta interval =
142 base::TimeDelta::FromMicroseconds(last_good_interval_);
134 callback.Run(timebase, interval); 143 callback.Run(timebase, interval);
135 } 144 }
136 145
137 private: 146 private:
138 XID window_; 147 XID window_;
139 148
149 base::TimeTicks last_timebase_;
150 uint64 last_media_stream_counter_;
151 int64 last_good_interval_;
ajuma 2013/01/04 15:34:43 Nit: making this a TimeDelta instead of an int64 w
jonathan.backer 2013/01/04 16:26:45 Done.
152
153 // On platforms where we can't get an accurate reading on the refresh
154 // rate we fall back to the assumption that we're displaying 60 frames
155 // per second.
156 const int64 kDefaultIntervalTime = base::Time::kMicrosecondsPerSecond / 60;
157
140 DISALLOW_COPY_AND_ASSIGN(OMLSyncControlVSyncProvider); 158 DISALLOW_COPY_AND_ASSIGN(OMLSyncControlVSyncProvider);
141 }; 159 };
142 160
143 class SGIVideoSyncThread 161 class SGIVideoSyncThread
144 : public base::Thread, 162 : public base::Thread,
145 public base::NonThreadSafe, 163 public base::NonThreadSafe,
146 public base::RefCounted<SGIVideoSyncThread> { 164 public base::RefCounted<SGIVideoSyncThread> {
147 public: 165 public:
148 static scoped_refptr<SGIVideoSyncThread> Create() { 166 static scoped_refptr<SGIVideoSyncThread> Create() {
149 if (!g_video_sync_thread) { 167 if (!g_video_sync_thread) {
(...skipping 25 matching lines...) Expand all
175 : public base::SupportsWeakPtr<SGIVideoSyncProviderThreadShim> { 193 : public base::SupportsWeakPtr<SGIVideoSyncProviderThreadShim> {
176 public: 194 public:
177 explicit SGIVideoSyncProviderThreadShim(XID window) 195 explicit SGIVideoSyncProviderThreadShim(XID window)
178 : window_(window), 196 : window_(window),
179 context_(NULL), 197 context_(NULL),
180 message_loop_(base::MessageLoopProxy::current()), 198 message_loop_(base::MessageLoopProxy::current()),
181 cancel_vsync_flag_(), 199 cancel_vsync_flag_(),
182 vsync_lock_() { 200 vsync_lock_() {
183 // This ensures that creation of |window_| has occured when this shim 201 // This ensures that creation of |window_| has occured when this shim
184 // is executing in the same process as the call to create |window_|. 202 // is executing in the same process as the call to create |window_|.
185 XSync(::gfx::g_display, False); 203 XSync(g_display, False);
186 } 204 }
187 205
188 base::CancellationFlag* cancel_vsync_flag() { 206 base::CancellationFlag* cancel_vsync_flag() {
189 return &cancel_vsync_flag_; 207 return &cancel_vsync_flag_;
190 } 208 }
191 209
192 base::Lock* vsync_lock() { 210 base::Lock* vsync_lock() {
193 return &vsync_lock_; 211 return &vsync_lock_;
194 } 212 }
195 213
196 void Initialize() { 214 void Initialize() {
197 DCHECK(SGIVideoSyncProviderThreadShim::g_display); 215 DCHECK(display_);
198 216
199 XWindowAttributes attributes; 217 XWindowAttributes attributes;
200 if (!XGetWindowAttributes(SGIVideoSyncProviderThreadShim::g_display, 218 if (!XGetWindowAttributes(display_, window_, &attributes)) {
201 window_, &attributes)) {
202 LOG(ERROR) << "XGetWindowAttributes failed for window " << 219 LOG(ERROR) << "XGetWindowAttributes failed for window " <<
203 window_ << "."; 220 window_ << ".";
204 return; 221 return;
205 } 222 }
206 223
207 XVisualInfo visual_info_template; 224 XVisualInfo visual_info_template;
208 visual_info_template.visualid = XVisualIDFromVisual(attributes.visual); 225 visual_info_template.visualid = XVisualIDFromVisual(attributes.visual);
209 226
210 int visual_info_count = 0; 227 int visual_info_count = 0;
211 scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info_list( 228 scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info_list(
212 XGetVisualInfo(SGIVideoSyncProviderThreadShim::g_display, VisualIDMask, 229 XGetVisualInfo(display_, VisualIDMask,
213 &visual_info_template, &visual_info_count)); 230 &visual_info_template, &visual_info_count));
214 231
215 DCHECK(visual_info_list.get()); 232 DCHECK(visual_info_list.get());
216 if (visual_info_count == 0) { 233 if (visual_info_count == 0) {
217 LOG(ERROR) << "No visual info for visual ID."; 234 LOG(ERROR) << "No visual info for visual ID.";
218 return; 235 return;
219 } 236 }
220 237
221 context_ = glXCreateContext(SGIVideoSyncProviderThreadShim::g_display, 238 context_ = glXCreateContext(display_, visual_info_list.get(), NULL, True);
222 visual_info_list.get(),
223 NULL,
224 True);
225 239
226 DCHECK(NULL != context_); 240 DCHECK(NULL != context_);
227 } 241 }
228 242
229 void Destroy() { 243 void Destroy() {
230 if (context_) { 244 if (context_) {
231 glXDestroyContext(SGIVideoSyncProviderThreadShim::g_display, context_); 245 glXDestroyContext(display_, context_);
232 context_ = NULL; 246 context_ = NULL;
233 } 247 }
234 delete this; 248 delete this;
235 } 249 }
236 250
237 void GetVSyncParameters(const GLSurface::UpdateVSyncCallback& callback) { 251 void GetVSyncParameters(const GLSurface::UpdateVSyncCallback& callback) {
238 base::TimeTicks now; 252 base::TimeTicks now;
239 { 253 {
240 // Don't allow |window_| destruction while we're probing vsync. 254 // Don't allow |window_| destruction while we're probing vsync.
241 base::AutoLock locked(vsync_lock_); 255 base::AutoLock locked(vsync_lock_);
242 256
243 if (!context_ || cancel_vsync_flag_.IsSet()) 257 if (!context_ || cancel_vsync_flag_.IsSet())
244 return; 258 return;
245 259
246 glXMakeCurrent(SGIVideoSyncProviderThreadShim::g_display, 260 glXMakeCurrent(display_, window_, context_);
247 window_, context_);
248 261
249 unsigned int retrace_count = 0; 262 unsigned int retrace_count = 0;
250 if (glXWaitVideoSyncSGI(1, 0, &retrace_count) != 0) 263 if (glXWaitVideoSyncSGI(1, 0, &retrace_count) != 0)
251 return; 264 return;
252 265
253 TRACE_EVENT_INSTANT0("gpu", "vblank"); 266 TRACE_EVENT_INSTANT0("gpu", "vblank");
254 now = base::TimeTicks::HighResNow(); 267 now = base::TimeTicks::HighResNow();
255 268
256 glXMakeCurrent(SGIVideoSyncProviderThreadShim::g_display, 0, 0); 269 glXMakeCurrent(display_, 0, 0);
257 } 270 }
258 271
259 const int64 kDefaultIntervalTime = 272 const int64 kDefaultIntervalTime =
260 base::Time::kMicrosecondsPerSecond / 60; 273 base::Time::kMicrosecondsPerSecond / 60;
261 base::TimeDelta interval = 274 base::TimeDelta interval =
262 base::TimeDelta::FromMicroseconds(kDefaultIntervalTime); 275 base::TimeDelta::FromMicroseconds(kDefaultIntervalTime);
263 276
264 message_loop_->PostTask(FROM_HERE, base::Bind(callback, now, interval)); 277 message_loop_->PostTask(FROM_HERE, base::Bind(callback, now, interval));
265 } 278 }
266 279
267 private: 280 private:
268 // For initialization of g_display in GLSurface::InitializeOneOff before 281 // For initialization of display_ in GLSurface::InitializeOneOff before
269 // the sandbox goes up. 282 // the sandbox goes up.
270 friend class gfx::GLSurfaceGLX; 283 friend class gfx::GLSurfaceGLX;
271 284
272 virtual ~SGIVideoSyncProviderThreadShim() { 285 virtual ~SGIVideoSyncProviderThreadShim() {
273 } 286 }
274 287
275 static Display* g_display; 288 static Display* display_;
276 289
277 XID window_; 290 XID window_;
278 GLXContext context_; 291 GLXContext context_;
279 292
280 scoped_refptr<base::MessageLoopProxy> message_loop_; 293 scoped_refptr<base::MessageLoopProxy> message_loop_;
281 294
282 base::CancellationFlag cancel_vsync_flag_; 295 base::CancellationFlag cancel_vsync_flag_;
283 base::Lock vsync_lock_; 296 base::Lock vsync_lock_;
284 297
285 DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncProviderThreadShim); 298 DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncProviderThreadShim);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 base::Lock* vsync_lock_; 359 base::Lock* vsync_lock_;
347 360
348 DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncVSyncProvider); 361 DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncVSyncProvider);
349 }; 362 };
350 363
351 SGIVideoSyncThread* SGIVideoSyncThread::g_video_sync_thread = NULL; 364 SGIVideoSyncThread* SGIVideoSyncThread::g_video_sync_thread = NULL;
352 365
353 // In order to take advantage of GLX_SGI_video_sync, we need a display 366 // In order to take advantage of GLX_SGI_video_sync, we need a display
354 // for use on a separate thread. We must allocate this before the sandbox 367 // for use on a separate thread. We must allocate this before the sandbox
355 // goes up (rather than on-demand when we start the thread). 368 // goes up (rather than on-demand when we start the thread).
356 Display* SGIVideoSyncProviderThreadShim::g_display = NULL; 369 Display* SGIVideoSyncProviderThreadShim::display_ = NULL;
357 370
358 } // namespace 371 } // namespace
359 372
360 GLSurfaceGLX::GLSurfaceGLX() {} 373 GLSurfaceGLX::GLSurfaceGLX() {}
361 374
362 bool GLSurfaceGLX::InitializeOneOff() { 375 bool GLSurfaceGLX::InitializeOneOff() {
363 static bool initialized = false; 376 static bool initialized = false;
364 if (initialized) 377 if (initialized)
365 return true; 378 return true;
366 379
(...skipping 25 matching lines...) Expand all
392 HasGLXExtension("GLX_ARB_create_context_robustness"); 405 HasGLXExtension("GLX_ARB_create_context_robustness");
393 g_glx_texture_from_pixmap_supported = 406 g_glx_texture_from_pixmap_supported =
394 HasGLXExtension("GLX_EXT_texture_from_pixmap"); 407 HasGLXExtension("GLX_EXT_texture_from_pixmap");
395 g_glx_oml_sync_control_supported = 408 g_glx_oml_sync_control_supported =
396 HasGLXExtension("GLX_OML_sync_control"); 409 HasGLXExtension("GLX_OML_sync_control");
397 g_glx_get_msc_rate_oml_supported = g_glx_oml_sync_control_supported; 410 g_glx_get_msc_rate_oml_supported = g_glx_oml_sync_control_supported;
398 g_glx_sgi_video_sync_supported = 411 g_glx_sgi_video_sync_supported =
399 HasGLXExtension("GLX_SGI_video_sync"); 412 HasGLXExtension("GLX_SGI_video_sync");
400 413
401 if (!g_glx_get_msc_rate_oml_supported && g_glx_sgi_video_sync_supported) 414 if (!g_glx_get_msc_rate_oml_supported && g_glx_sgi_video_sync_supported)
402 SGIVideoSyncProviderThreadShim::g_display = XOpenDisplay(NULL); 415 SGIVideoSyncProviderThreadShim::display_ = XOpenDisplay(NULL);
403 416
404 initialized = true; 417 initialized = true;
405 return true; 418 return true;
406 } 419 }
407 420
408 // static 421 // static
409 const char* GLSurfaceGLX::GetGLXExtensions() { 422 const char* GLSurfaceGLX::GetGLXExtensions() {
410 return g_glx_extensions; 423 return g_glx_extensions;
411 } 424 }
412 425
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
669 682
670 void* PbufferGLSurfaceGLX::GetConfig() { 683 void* PbufferGLSurfaceGLX::GetConfig() {
671 return config_; 684 return config_;
672 } 685 }
673 686
674 PbufferGLSurfaceGLX::~PbufferGLSurfaceGLX() { 687 PbufferGLSurfaceGLX::~PbufferGLSurfaceGLX() {
675 Destroy(); 688 Destroy();
676 } 689 }
677 690
678 } // namespace gfx 691 } // namespace gfx
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698