OLD | NEW |
---|---|
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 Loading... | |
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_(), | |
apatrick_chromium
2013/01/04 21:21:09
nit: this line is redundant.
jonathan.backer
2013/01/04 21:29:22
Done.
| |
62 last_media_stream_counter_(0), | |
63 last_good_interval_() { | |
apatrick_chromium
2013/01/04 21:21:09
and here
jonathan.backer
2013/01/04 21:29:22
Done.
| |
64 // On platforms where we can't get an accurate reading on the refresh | |
65 // rate we fall back to the assumption that we're displaying 60 frames | |
66 // per second. | |
67 last_good_interval_ = base::TimeDelta::FromSeconds(1) / 60; | |
61 } | 68 } |
62 | 69 |
63 virtual ~OMLSyncControlVSyncProvider() { } | 70 virtual ~OMLSyncControlVSyncProvider() { } |
64 | 71 |
65 virtual void GetVSyncParameters( | 72 virtual void GetVSyncParameters( |
66 const GLSurface::UpdateVSyncCallback& callback) OVERRIDE { | 73 const GLSurface::UpdateVSyncCallback& callback) OVERRIDE { |
67 base::TimeTicks timebase; | 74 base::TimeTicks timebase; |
68 base::TimeDelta interval; | |
69 | 75 |
70 // The actual clock used for the system time returned by glXGetSyncValuesOML | 76 // The actual clock used for the system time returned by glXGetSyncValuesOML |
71 // is unspecified. In practice, the clock used is likely to be either | 77 // 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 | 78 // 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 | 79 // 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 | 80 // 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 | 81 // 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). | 82 // (since it is the time of a vblank that has already occurred). |
77 int64 system_time; | 83 int64 system_time; |
78 int64 media_stream_counter; | 84 int64 media_stream_counter; |
(...skipping 27 matching lines...) Expand all Loading... | |
106 | 112 |
107 if (time_conversion_needed) { | 113 if (time_conversion_needed) { |
108 int64 time_difference = | 114 int64 time_difference = |
109 real_time_in_microseconds - monotonic_time_in_microseconds; | 115 real_time_in_microseconds - monotonic_time_in_microseconds; |
110 timebase = base::TimeTicks::FromInternalValue( | 116 timebase = base::TimeTicks::FromInternalValue( |
111 system_time - time_difference); | 117 system_time - time_difference); |
112 } else { | 118 } else { |
113 timebase = base::TimeTicks::FromInternalValue(system_time); | 119 timebase = base::TimeTicks::FromInternalValue(system_time); |
114 } | 120 } |
115 | 121 |
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) { | 122 if (g_glx_get_msc_rate_oml_supported) { |
123 int32 numerator, denominator; | |
124 if (glXGetMscRateOML(g_display, window_, &numerator, &denominator)) { | 124 if (glXGetMscRateOML(g_display, window_, &numerator, &denominator)) { |
125 interval_time = | 125 last_good_interval_ = |
126 (base::Time::kMicrosecondsPerSecond * denominator) / numerator; | 126 base::TimeDelta::FromSeconds(denominator) / numerator; |
127 } else { | 127 } else { |
128 // Once glXGetMscRateOML has been found to fail, don't try again, | 128 // Once glXGetMscRateOML has been found to fail, don't try again, |
129 // since each failing call may spew an error message. | 129 // since each failing call may spew an error message. |
130 g_glx_get_msc_rate_oml_supported = false; | 130 g_glx_get_msc_rate_oml_supported = false; |
131 } | 131 } |
132 } else { | |
133 if (!last_timebase_.is_null()) { | |
apatrick_chromium
2013/01/04 21:21:09
indentation is out
jonathan.backer
2013/01/04 21:29:22
Done.
| |
134 base::TimeDelta timebase_diff = timebase - last_timebase_; | |
135 uint64 counter_diff = media_stream_counter - | |
136 last_media_stream_counter_; | |
137 if (counter_diff > 0 && timebase > last_timebase_) | |
138 last_good_interval_ = timebase_diff / counter_diff; | |
139 } | |
132 } | 140 } |
133 interval = base::TimeDelta::FromMicroseconds(interval_time); | 141 last_timebase_ = timebase; |
134 callback.Run(timebase, interval); | 142 last_media_stream_counter_ = media_stream_counter; |
143 callback.Run(timebase, last_good_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 base::TimeDelta last_good_interval_; | |
152 | |
140 DISALLOW_COPY_AND_ASSIGN(OMLSyncControlVSyncProvider); | 153 DISALLOW_COPY_AND_ASSIGN(OMLSyncControlVSyncProvider); |
141 }; | 154 }; |
142 | 155 |
143 class SGIVideoSyncThread | 156 class SGIVideoSyncThread |
144 : public base::Thread, | 157 : public base::Thread, |
145 public base::NonThreadSafe, | 158 public base::NonThreadSafe, |
146 public base::RefCounted<SGIVideoSyncThread> { | 159 public base::RefCounted<SGIVideoSyncThread> { |
147 public: | 160 public: |
148 static scoped_refptr<SGIVideoSyncThread> Create() { | 161 static scoped_refptr<SGIVideoSyncThread> Create() { |
149 if (!g_video_sync_thread) { | 162 if (!g_video_sync_thread) { |
(...skipping 25 matching lines...) Expand all Loading... | |
175 : public base::SupportsWeakPtr<SGIVideoSyncProviderThreadShim> { | 188 : public base::SupportsWeakPtr<SGIVideoSyncProviderThreadShim> { |
176 public: | 189 public: |
177 explicit SGIVideoSyncProviderThreadShim(XID window) | 190 explicit SGIVideoSyncProviderThreadShim(XID window) |
178 : window_(window), | 191 : window_(window), |
179 context_(NULL), | 192 context_(NULL), |
180 message_loop_(base::MessageLoopProxy::current()), | 193 message_loop_(base::MessageLoopProxy::current()), |
181 cancel_vsync_flag_(), | 194 cancel_vsync_flag_(), |
182 vsync_lock_() { | 195 vsync_lock_() { |
183 // This ensures that creation of |window_| has occured when this shim | 196 // This ensures that creation of |window_| has occured when this shim |
184 // is executing in the same process as the call to create |window_|. | 197 // is executing in the same process as the call to create |window_|. |
185 XSync(::gfx::g_display, False); | 198 XSync(g_display, False); |
186 } | 199 } |
187 | 200 |
188 base::CancellationFlag* cancel_vsync_flag() { | 201 base::CancellationFlag* cancel_vsync_flag() { |
189 return &cancel_vsync_flag_; | 202 return &cancel_vsync_flag_; |
190 } | 203 } |
191 | 204 |
192 base::Lock* vsync_lock() { | 205 base::Lock* vsync_lock() { |
193 return &vsync_lock_; | 206 return &vsync_lock_; |
194 } | 207 } |
195 | 208 |
196 void Initialize() { | 209 void Initialize() { |
197 DCHECK(SGIVideoSyncProviderThreadShim::g_display); | 210 DCHECK(display_); |
198 | 211 |
199 XWindowAttributes attributes; | 212 XWindowAttributes attributes; |
200 if (!XGetWindowAttributes(SGIVideoSyncProviderThreadShim::g_display, | 213 if (!XGetWindowAttributes(display_, window_, &attributes)) { |
201 window_, &attributes)) { | |
202 LOG(ERROR) << "XGetWindowAttributes failed for window " << | 214 LOG(ERROR) << "XGetWindowAttributes failed for window " << |
203 window_ << "."; | 215 window_ << "."; |
204 return; | 216 return; |
205 } | 217 } |
206 | 218 |
207 XVisualInfo visual_info_template; | 219 XVisualInfo visual_info_template; |
208 visual_info_template.visualid = XVisualIDFromVisual(attributes.visual); | 220 visual_info_template.visualid = XVisualIDFromVisual(attributes.visual); |
209 | 221 |
210 int visual_info_count = 0; | 222 int visual_info_count = 0; |
211 scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info_list( | 223 scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info_list( |
212 XGetVisualInfo(SGIVideoSyncProviderThreadShim::g_display, VisualIDMask, | 224 XGetVisualInfo(display_, VisualIDMask, |
213 &visual_info_template, &visual_info_count)); | 225 &visual_info_template, &visual_info_count)); |
214 | 226 |
215 DCHECK(visual_info_list.get()); | 227 DCHECK(visual_info_list.get()); |
216 if (visual_info_count == 0) { | 228 if (visual_info_count == 0) { |
217 LOG(ERROR) << "No visual info for visual ID."; | 229 LOG(ERROR) << "No visual info for visual ID."; |
218 return; | 230 return; |
219 } | 231 } |
220 | 232 |
221 context_ = glXCreateContext(SGIVideoSyncProviderThreadShim::g_display, | 233 context_ = glXCreateContext(display_, visual_info_list.get(), NULL, True); |
222 visual_info_list.get(), | |
223 NULL, | |
224 True); | |
225 | 234 |
226 DCHECK(NULL != context_); | 235 DCHECK(NULL != context_); |
227 } | 236 } |
228 | 237 |
229 void Destroy() { | 238 void Destroy() { |
230 if (context_) { | 239 if (context_) { |
231 glXDestroyContext(SGIVideoSyncProviderThreadShim::g_display, context_); | 240 glXDestroyContext(display_, context_); |
232 context_ = NULL; | 241 context_ = NULL; |
233 } | 242 } |
234 delete this; | 243 delete this; |
235 } | 244 } |
236 | 245 |
237 void GetVSyncParameters(const GLSurface::UpdateVSyncCallback& callback) { | 246 void GetVSyncParameters(const GLSurface::UpdateVSyncCallback& callback) { |
238 base::TimeTicks now; | 247 base::TimeTicks now; |
239 { | 248 { |
240 // Don't allow |window_| destruction while we're probing vsync. | 249 // Don't allow |window_| destruction while we're probing vsync. |
241 base::AutoLock locked(vsync_lock_); | 250 base::AutoLock locked(vsync_lock_); |
242 | 251 |
243 if (!context_ || cancel_vsync_flag_.IsSet()) | 252 if (!context_ || cancel_vsync_flag_.IsSet()) |
244 return; | 253 return; |
245 | 254 |
246 glXMakeCurrent(SGIVideoSyncProviderThreadShim::g_display, | 255 glXMakeCurrent(display_, window_, context_); |
247 window_, context_); | |
248 | 256 |
249 unsigned int retrace_count = 0; | 257 unsigned int retrace_count = 0; |
250 if (glXWaitVideoSyncSGI(1, 0, &retrace_count) != 0) | 258 if (glXWaitVideoSyncSGI(1, 0, &retrace_count) != 0) |
251 return; | 259 return; |
252 | 260 |
253 TRACE_EVENT_INSTANT0("gpu", "vblank"); | 261 TRACE_EVENT_INSTANT0("gpu", "vblank"); |
254 now = base::TimeTicks::HighResNow(); | 262 now = base::TimeTicks::HighResNow(); |
255 | 263 |
256 glXMakeCurrent(SGIVideoSyncProviderThreadShim::g_display, 0, 0); | 264 glXMakeCurrent(display_, 0, 0); |
257 } | 265 } |
258 | 266 |
259 const int64 kDefaultIntervalTime = | 267 const base::TimeDelta kDefaultInterval = |
260 base::Time::kMicrosecondsPerSecond / 60; | 268 base::TimeDelta::FromSeconds(1) / 60; |
261 base::TimeDelta interval = | |
262 base::TimeDelta::FromMicroseconds(kDefaultIntervalTime); | |
263 | 269 |
264 message_loop_->PostTask(FROM_HERE, base::Bind(callback, now, interval)); | 270 message_loop_->PostTask( |
271 FROM_HERE, base::Bind(callback, now, kDefaultInterval)); | |
265 } | 272 } |
266 | 273 |
267 private: | 274 private: |
268 // For initialization of g_display in GLSurface::InitializeOneOff before | 275 // For initialization of display_ in GLSurface::InitializeOneOff before |
269 // the sandbox goes up. | 276 // the sandbox goes up. |
270 friend class gfx::GLSurfaceGLX; | 277 friend class gfx::GLSurfaceGLX; |
271 | 278 |
272 virtual ~SGIVideoSyncProviderThreadShim() { | 279 virtual ~SGIVideoSyncProviderThreadShim() { |
273 } | 280 } |
274 | 281 |
275 static Display* g_display; | 282 static Display* display_; |
276 | 283 |
277 XID window_; | 284 XID window_; |
278 GLXContext context_; | 285 GLXContext context_; |
279 | 286 |
280 scoped_refptr<base::MessageLoopProxy> message_loop_; | 287 scoped_refptr<base::MessageLoopProxy> message_loop_; |
281 | 288 |
282 base::CancellationFlag cancel_vsync_flag_; | 289 base::CancellationFlag cancel_vsync_flag_; |
283 base::Lock vsync_lock_; | 290 base::Lock vsync_lock_; |
284 | 291 |
285 DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncProviderThreadShim); | 292 DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncProviderThreadShim); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
346 base::Lock* vsync_lock_; | 353 base::Lock* vsync_lock_; |
347 | 354 |
348 DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncVSyncProvider); | 355 DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncVSyncProvider); |
349 }; | 356 }; |
350 | 357 |
351 SGIVideoSyncThread* SGIVideoSyncThread::g_video_sync_thread = NULL; | 358 SGIVideoSyncThread* SGIVideoSyncThread::g_video_sync_thread = NULL; |
352 | 359 |
353 // In order to take advantage of GLX_SGI_video_sync, we need a display | 360 // 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 | 361 // 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). | 362 // goes up (rather than on-demand when we start the thread). |
356 Display* SGIVideoSyncProviderThreadShim::g_display = NULL; | 363 Display* SGIVideoSyncProviderThreadShim::display_ = NULL; |
357 | 364 |
358 } // namespace | 365 } // namespace |
359 | 366 |
360 GLSurfaceGLX::GLSurfaceGLX() {} | 367 GLSurfaceGLX::GLSurfaceGLX() {} |
361 | 368 |
362 bool GLSurfaceGLX::InitializeOneOff() { | 369 bool GLSurfaceGLX::InitializeOneOff() { |
363 static bool initialized = false; | 370 static bool initialized = false; |
364 if (initialized) | 371 if (initialized) |
365 return true; | 372 return true; |
366 | 373 |
(...skipping 25 matching lines...) Expand all Loading... | |
392 HasGLXExtension("GLX_ARB_create_context_robustness"); | 399 HasGLXExtension("GLX_ARB_create_context_robustness"); |
393 g_glx_texture_from_pixmap_supported = | 400 g_glx_texture_from_pixmap_supported = |
394 HasGLXExtension("GLX_EXT_texture_from_pixmap"); | 401 HasGLXExtension("GLX_EXT_texture_from_pixmap"); |
395 g_glx_oml_sync_control_supported = | 402 g_glx_oml_sync_control_supported = |
396 HasGLXExtension("GLX_OML_sync_control"); | 403 HasGLXExtension("GLX_OML_sync_control"); |
397 g_glx_get_msc_rate_oml_supported = g_glx_oml_sync_control_supported; | 404 g_glx_get_msc_rate_oml_supported = g_glx_oml_sync_control_supported; |
398 g_glx_sgi_video_sync_supported = | 405 g_glx_sgi_video_sync_supported = |
399 HasGLXExtension("GLX_SGI_video_sync"); | 406 HasGLXExtension("GLX_SGI_video_sync"); |
400 | 407 |
401 if (!g_glx_get_msc_rate_oml_supported && g_glx_sgi_video_sync_supported) | 408 if (!g_glx_get_msc_rate_oml_supported && g_glx_sgi_video_sync_supported) |
402 SGIVideoSyncProviderThreadShim::g_display = XOpenDisplay(NULL); | 409 SGIVideoSyncProviderThreadShim::display_ = XOpenDisplay(NULL); |
403 | 410 |
404 initialized = true; | 411 initialized = true; |
405 return true; | 412 return true; |
406 } | 413 } |
407 | 414 |
408 // static | 415 // static |
409 const char* GLSurfaceGLX::GetGLXExtensions() { | 416 const char* GLSurfaceGLX::GetGLXExtensions() { |
410 return g_glx_extensions; | 417 return g_glx_extensions; |
411 } | 418 } |
412 | 419 |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
669 | 676 |
670 void* PbufferGLSurfaceGLX::GetConfig() { | 677 void* PbufferGLSurfaceGLX::GetConfig() { |
671 return config_; | 678 return config_; |
672 } | 679 } |
673 | 680 |
674 PbufferGLSurfaceGLX::~PbufferGLSurfaceGLX() { | 681 PbufferGLSurfaceGLX::~PbufferGLSurfaceGLX() { |
675 Destroy(); | 682 Destroy(); |
676 } | 683 } |
677 | 684 |
678 } // namespace gfx | 685 } // namespace gfx |
OLD | NEW |