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 |
11 #include "base/basictypes.h" | 11 #include "base/basictypes.h" |
12 #include "base/debug/trace_event.h" | 12 #include "base/debug/trace_event.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/memory/scoped_ptr.h" | 14 #include "base/memory/scoped_ptr.h" |
15 #include "base/message_loop.h" | 15 #include "base/message_loop.h" |
16 #include "base/process_util.h" | 16 #include "base/process_util.h" |
17 #include "base/time.h" | |
17 #include "third_party/mesa/MesaLib/include/GL/osmesa.h" | 18 #include "third_party/mesa/MesaLib/include/GL/osmesa.h" |
18 #include "ui/base/x/x11_util.h" | 19 #include "ui/base/x/x11_util.h" |
19 #include "ui/gl/gl_bindings.h" | 20 #include "ui/gl/gl_bindings.h" |
20 #include "ui/gl/gl_implementation.h" | 21 #include "ui/gl/gl_implementation.h" |
21 | 22 |
22 namespace gfx { | 23 namespace gfx { |
23 | 24 |
24 namespace { | 25 namespace { |
25 | 26 |
26 // scoped_ptr functor for XFree(). Use as follows: | 27 // scoped_ptr functor for XFree(). Use as follows: |
27 // scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> foo(...); | 28 // scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> foo(...); |
28 // where "XVisualInfo" is any X type that is freed with XFree. | 29 // where "XVisualInfo" is any X type that is freed with XFree. |
29 class ScopedPtrXFree { | 30 class ScopedPtrXFree { |
30 public: | 31 public: |
31 void operator()(void* x) const { | 32 void operator()(void* x) const { |
32 ::XFree(x); | 33 ::XFree(x); |
33 } | 34 } |
34 }; | 35 }; |
35 | 36 |
36 Display* g_display; | 37 Display* g_display; |
37 const char* g_glx_extensions = NULL; | 38 const char* g_glx_extensions = NULL; |
38 bool g_glx_create_context_robustness_supported = false; | 39 bool g_glx_create_context_robustness_supported = false; |
39 bool g_glx_texture_from_pixmap_supported = false; | 40 bool g_glx_texture_from_pixmap_supported = false; |
41 bool g_glx_oml_sync_control_supported = false; | |
42 | |
43 // Track support of glXGetMscRateOML separately from GLX_OML_sync_control as a | |
44 // whole since on some platforms (e.g. crosbug.com/34585), glXGetMscRateOML | |
45 // always fails even though GLX_OML_sync_control is reported as being supported. | |
46 bool g_glx_get_msc_rate_oml_supported = false; | |
40 | 47 |
41 } // namespace | 48 } // namespace |
42 | 49 |
43 GLSurfaceGLX::GLSurfaceGLX() {} | 50 GLSurfaceGLX::GLSurfaceGLX() {} |
44 | 51 |
45 bool GLSurfaceGLX::InitializeOneOff() { | 52 bool GLSurfaceGLX::InitializeOneOff() { |
46 static bool initialized = false; | 53 static bool initialized = false; |
47 if (initialized) | 54 if (initialized) |
48 return true; | 55 return true; |
49 | 56 |
(...skipping 12 matching lines...) Expand all Loading... | |
62 if (major == 1 && minor < 3) { | 69 if (major == 1 && minor < 3) { |
63 LOG(ERROR) << "GLX 1.3 or later is required."; | 70 LOG(ERROR) << "GLX 1.3 or later is required."; |
64 return false; | 71 return false; |
65 } | 72 } |
66 | 73 |
67 g_glx_extensions = glXQueryExtensionsString(g_display, 0); | 74 g_glx_extensions = glXQueryExtensionsString(g_display, 0); |
68 g_glx_create_context_robustness_supported = | 75 g_glx_create_context_robustness_supported = |
69 HasGLXExtension("GLX_ARB_create_context_robustness"); | 76 HasGLXExtension("GLX_ARB_create_context_robustness"); |
70 g_glx_texture_from_pixmap_supported = | 77 g_glx_texture_from_pixmap_supported = |
71 HasGLXExtension("GLX_EXT_texture_from_pixmap"); | 78 HasGLXExtension("GLX_EXT_texture_from_pixmap"); |
79 g_glx_oml_sync_control_supported = | |
80 HasGLXExtension("GLX_OML_sync_control"); | |
81 g_glx_get_msc_rate_oml_supported = g_glx_oml_sync_control_supported; | |
82 | |
72 | 83 |
73 initialized = true; | 84 initialized = true; |
74 return true; | 85 return true; |
75 } | 86 } |
76 | 87 |
77 // static | 88 // static |
78 const char* GLSurfaceGLX::GetGLXExtensions() { | 89 const char* GLSurfaceGLX::GetGLXExtensions() { |
79 return g_glx_extensions; | 90 return g_glx_extensions; |
80 } | 91 } |
81 | 92 |
82 // static | 93 // static |
83 bool GLSurfaceGLX::HasGLXExtension(const char* name) { | 94 bool GLSurfaceGLX::HasGLXExtension(const char* name) { |
84 return ExtensionsContain(GetGLXExtensions(), name); | 95 return ExtensionsContain(GetGLXExtensions(), name); |
85 } | 96 } |
86 | 97 |
87 // static | 98 // static |
88 bool GLSurfaceGLX::IsCreateContextRobustnessSupported() { | 99 bool GLSurfaceGLX::IsCreateContextRobustnessSupported() { |
89 return g_glx_create_context_robustness_supported; | 100 return g_glx_create_context_robustness_supported; |
90 } | 101 } |
91 | 102 |
92 // static | 103 // static |
93 bool GLSurfaceGLX::IsTextureFromPixmapSupported() { | 104 bool GLSurfaceGLX::IsTextureFromPixmapSupported() { |
94 return g_glx_texture_from_pixmap_supported; | 105 return g_glx_texture_from_pixmap_supported; |
95 } | 106 } |
96 | 107 |
108 // static | |
109 bool GLSurfaceGLX::IsOMLSyncControlSupported() { | |
110 return g_glx_oml_sync_control_supported; | |
111 } | |
112 | |
97 void* GLSurfaceGLX::GetDisplay() { | 113 void* GLSurfaceGLX::GetDisplay() { |
98 return g_display; | 114 return g_display; |
99 } | 115 } |
100 | 116 |
101 GLSurfaceGLX::~GLSurfaceGLX() {} | 117 GLSurfaceGLX::~GLSurfaceGLX() {} |
102 | 118 |
103 NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::AcceleratedWidget window) | 119 NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::AcceleratedWidget window) |
104 : window_(window), | 120 : window_(window), |
105 config_(NULL) { | 121 config_(NULL) { |
106 } | 122 } |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
217 return config_; | 233 return config_; |
218 } | 234 } |
219 | 235 |
220 bool NativeViewGLSurfaceGLX::PostSubBuffer( | 236 bool NativeViewGLSurfaceGLX::PostSubBuffer( |
221 int x, int y, int width, int height) { | 237 int x, int y, int width, int height) { |
222 DCHECK(g_GLX_MESA_copy_sub_buffer); | 238 DCHECK(g_GLX_MESA_copy_sub_buffer); |
223 glXCopySubBufferMESA(g_display, window_, x, y, width, height); | 239 glXCopySubBufferMESA(g_display, window_, x, y, width, height); |
224 return true; | 240 return true; |
225 } | 241 } |
226 | 242 |
243 bool NativeViewGLSurfaceGLX::GetVSyncParameters(base::TimeTicks* timebase, | |
244 base::TimeDelta* interval) { | |
245 if (g_glx_oml_sync_control_supported) { | |
jonathan.backer
2012/10/26 20:31:03
I'm concerned that this may be per monitor (in the
ajuma
2012/10/29 17:02:26
AIUI, since we only XOpenDisplay() once, we're onl
| |
246 // The actual clock used for the system time returned by glXGetSyncValuesOML | |
247 // is unspecified. In practice, the clock used is likely to be either | |
248 // CLOCK_REALTIME or CLOCK_MONOTONIC. We test if the returned time is | |
249 // "close" (within a minute) to the current time according to either of | |
250 // these clocks, and if so, we assume that the corresponding clock was used | |
251 // to produce this time. | |
252 int64 system_time; | |
253 int64 media_stream_counter; | |
254 int64 swap_buffer_counter; | |
255 if (glXGetSyncValuesOML(g_display, window_, &system_time, | |
256 &media_stream_counter, &swap_buffer_counter)) { | |
257 struct timespec real_time; | |
258 struct timespec monotonic_time; | |
259 clock_gettime(CLOCK_REALTIME, &real_time); | |
260 clock_gettime(CLOCK_MONOTONIC, &monotonic_time); | |
261 | |
262 int64 real_time_in_microseconds = | |
263 real_time.tv_sec * base::Time::kMicrosecondsPerSecond + | |
264 real_time.tv_nsec / base::Time::kNanosecondsPerMicrosecond; | |
265 int64 monotonic_time_in_microseconds = | |
266 monotonic_time.tv_sec * base::Time::kMicrosecondsPerSecond + | |
267 monotonic_time.tv_nsec / base::Time::kNanosecondsPerMicrosecond; | |
268 | |
269 if (real_time_in_microseconds - system_time <= | |
270 base::Time::kMicrosecondsPerMinute) { | |
271 // Convert from CLOCK_REALTIME to CLOCK_MONOTONIC. | |
272 int64 time_difference = | |
273 real_time_in_microseconds - monotonic_time_in_microseconds; | |
274 *timebase = base::TimeTicks::FromInternalValue( | |
275 system_time - time_difference); | |
276 } else if (monotonic_time_in_microseconds - system_time <= | |
277 base::Time::kMicrosecondsPerMinute) { | |
278 *timebase = base::TimeTicks::FromInternalValue(system_time); | |
279 } else { | |
280 // We don't know how to interpret system_time. | |
281 return false; | |
282 } | |
283 | |
284 // On platforms where glXGetMscRateOML doesn't work, we fall back to the | |
285 // assumption that we're displaying 60 frames per second. | |
286 const int64 kDefaultIntervalTime = | |
287 base::Time::kMicrosecondsPerSecond / 60; | |
288 int64 interval_time = kDefaultIntervalTime; | |
289 int32 numerator; | |
290 int32 denominator; | |
291 if (g_glx_get_msc_rate_oml_supported) { | |
292 if (glXGetMscRateOML(g_display, window_, &numerator, &denominator)) { | |
293 interval_time = | |
294 (base::Time::kMicrosecondsPerSecond * denominator) / numerator; | |
295 } else { | |
296 // Once glXGetMscRateOML has been found to fail, don't try again, | |
297 // since each failing call may spew an error message. | |
298 g_glx_get_msc_rate_oml_supported = false; | |
299 } | |
300 } | |
301 | |
302 *interval = base::TimeDelta::FromMicroseconds(interval_time); | |
303 return true; | |
304 } | |
305 } | |
306 | |
307 return false; | |
308 } | |
309 | |
227 NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX() | 310 NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX() |
228 : window_(0), | 311 : window_(0), |
229 config_(NULL) { | 312 config_(NULL) { |
230 } | 313 } |
231 | 314 |
232 NativeViewGLSurfaceGLX::~NativeViewGLSurfaceGLX() { | 315 NativeViewGLSurfaceGLX::~NativeViewGLSurfaceGLX() { |
233 Destroy(); | 316 Destroy(); |
234 } | 317 } |
235 | 318 |
236 PbufferGLSurfaceGLX::PbufferGLSurfaceGLX(const gfx::Size& size) | 319 PbufferGLSurfaceGLX::PbufferGLSurfaceGLX(const gfx::Size& size) |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
316 | 399 |
317 void* PbufferGLSurfaceGLX::GetConfig() { | 400 void* PbufferGLSurfaceGLX::GetConfig() { |
318 return config_; | 401 return config_; |
319 } | 402 } |
320 | 403 |
321 PbufferGLSurfaceGLX::~PbufferGLSurfaceGLX() { | 404 PbufferGLSurfaceGLX::~PbufferGLSurfaceGLX() { |
322 Destroy(); | 405 Destroy(); |
323 } | 406 } |
324 | 407 |
325 } // namespace gfx | 408 } // namespace gfx |
OLD | NEW |