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 #include "ui/gl/gl_surface_glx.h" | 5 #include "ui/gl/gl_surface_glx.h" |
6 | 6 |
7 extern "C" { | 7 extern "C" { |
8 #include <X11/Xlib.h> | 8 #include <X11/Xlib.h> |
9 } | 9 } |
10 #include <memory> | 10 #include <memory> |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 bool g_glx_texture_from_pixmap_supported = false; | 43 bool g_glx_texture_from_pixmap_supported = false; |
44 bool g_glx_oml_sync_control_supported = false; | 44 bool g_glx_oml_sync_control_supported = false; |
45 | 45 |
46 // Track support of glXGetMscRateOML separately from GLX_OML_sync_control as a | 46 // Track support of glXGetMscRateOML separately from GLX_OML_sync_control as a |
47 // whole since on some platforms (e.g. crosbug.com/34585), glXGetMscRateOML | 47 // whole since on some platforms (e.g. crosbug.com/34585), glXGetMscRateOML |
48 // always fails even though GLX_OML_sync_control is reported as being supported. | 48 // always fails even though GLX_OML_sync_control is reported as being supported. |
49 bool g_glx_get_msc_rate_oml_supported = false; | 49 bool g_glx_get_msc_rate_oml_supported = false; |
50 | 50 |
51 bool g_glx_sgi_video_sync_supported = false; | 51 bool g_glx_sgi_video_sync_supported = false; |
52 | 52 |
53 static const int kGetVSyncParametersMinSeconds = | |
54 #if defined(OS_LINUX) | |
55 // See crbug.com/373489 | |
56 // On Linux, querying the vsync parameters might burn CPU for up to an | |
57 // entire vsync, so we only query periodically to reduce CPU usage. | |
58 // 5 seconds is chosen somewhat abitrarily as a balance between: | |
59 // a) Drift in the phase of our signal. | |
60 // b) Potential janks from periodically pegging the CPU. | |
61 5; | |
62 #else | |
63 0; | |
64 #endif | |
65 | |
66 GLXFBConfig GetConfigForWindow(Display* display, | 53 GLXFBConfig GetConfigForWindow(Display* display, |
67 gfx::AcceleratedWidget window) { | 54 gfx::AcceleratedWidget window) { |
68 DCHECK(window != 0); | 55 DCHECK(window != 0); |
69 | 56 |
70 // This code path is expensive, but we only take it when | 57 // This code path is expensive, but we only take it when |
71 // attempting to use GLX_ARB_create_context_robustness, in which | 58 // attempting to use GLX_ARB_create_context_robustness, in which |
72 // case we need a GLXFBConfig for the window in order to create a | 59 // case we need a GLXFBConfig for the window in order to create a |
73 // context for it. | 60 // context for it. |
74 // | 61 // |
75 // TODO(kbr): this is not a reliable code path. On platforms which | 62 // TODO(kbr): this is not a reliable code path. On platforms which |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 found = true; | 98 found = true; |
112 break; | 99 break; |
113 } | 100 } |
114 } | 101 } |
115 if (found) { | 102 if (found) { |
116 return configs.get()[i]; | 103 return configs.get()[i]; |
117 } | 104 } |
118 return nullptr; | 105 return nullptr; |
119 } | 106 } |
120 | 107 |
| 108 bool CreateDummyWindow(Display* display) { |
| 109 DCHECK(display); |
| 110 gfx::AcceleratedWidget parent_window = |
| 111 RootWindow(display, DefaultScreen(display)); |
| 112 // We create a window with CopyFromParent visual so that we have the same |
| 113 // visual as NativeViewGLSurfaceGLX (i.e. same GLXFBConfig), to ensure |
| 114 // contexts are compatible and can be made current with either. |
| 115 gfx::AcceleratedWidget window = |
| 116 XCreateWindow(display, parent_window, 0, 0, 1, 1, 0, CopyFromParent, |
| 117 InputOutput, CopyFromParent, 0, nullptr); |
| 118 if (!window) { |
| 119 LOG(ERROR) << "XCreateWindow failed"; |
| 120 return false; |
| 121 } |
| 122 GLXFBConfig config = GetConfigForWindow(display, window); |
| 123 GLXWindow glx_window = glXCreateWindow(display, config, window, nullptr); |
| 124 if (!glx_window) { |
| 125 LOG(ERROR) << "glXCreateWindow failed"; |
| 126 XDestroyWindow(display, window); |
| 127 return false; |
| 128 } |
| 129 glXDestroyWindow(display, glx_window); |
| 130 XDestroyWindow(display, window); |
| 131 return true; |
| 132 } |
| 133 |
121 class OMLSyncControlVSyncProvider : public SyncControlVSyncProvider { | 134 class OMLSyncControlVSyncProvider : public SyncControlVSyncProvider { |
122 public: | 135 public: |
123 explicit OMLSyncControlVSyncProvider(GLXWindow glx_window) | 136 explicit OMLSyncControlVSyncProvider(GLXWindow glx_window) |
124 : SyncControlVSyncProvider(), | 137 : SyncControlVSyncProvider(), glx_window_(glx_window) {} |
125 glx_window_(glx_window) { | |
126 } | |
127 | 138 |
128 ~OMLSyncControlVSyncProvider() override {} | 139 ~OMLSyncControlVSyncProvider() override {} |
129 | 140 |
130 protected: | 141 protected: |
131 bool GetSyncValues(int64_t* system_time, | 142 bool GetSyncValues(int64_t* system_time, |
132 int64_t* media_stream_counter, | 143 int64_t* media_stream_counter, |
133 int64_t* swap_buffer_counter) override { | 144 int64_t* swap_buffer_counter) override { |
134 return glXGetSyncValuesOML(g_display, glx_window_, system_time, | 145 return glXGetSyncValuesOML(g_display, glx_window_, system_time, |
135 media_stream_counter, swap_buffer_counter); | 146 media_stream_counter, swap_buffer_counter); |
136 } | 147 } |
(...skipping 11 matching lines...) Expand all Loading... |
148 | 159 |
149 return true; | 160 return true; |
150 } | 161 } |
151 | 162 |
152 private: | 163 private: |
153 GLXWindow glx_window_; | 164 GLXWindow glx_window_; |
154 | 165 |
155 DISALLOW_COPY_AND_ASSIGN(OMLSyncControlVSyncProvider); | 166 DISALLOW_COPY_AND_ASSIGN(OMLSyncControlVSyncProvider); |
156 }; | 167 }; |
157 | 168 |
158 class SGIVideoSyncThread | 169 class SGIVideoSyncThread : public base::Thread, |
159 : public base::Thread, | 170 public base::NonThreadSafe, |
160 public base::NonThreadSafe, | 171 public base::RefCounted<SGIVideoSyncThread> { |
161 public base::RefCounted<SGIVideoSyncThread> { | |
162 public: | 172 public: |
163 static scoped_refptr<SGIVideoSyncThread> Create() { | 173 static scoped_refptr<SGIVideoSyncThread> Create() { |
164 if (!g_video_sync_thread) { | 174 if (!g_video_sync_thread) { |
165 g_video_sync_thread = new SGIVideoSyncThread(); | 175 g_video_sync_thread = new SGIVideoSyncThread(); |
166 g_video_sync_thread->Start(); | 176 g_video_sync_thread->Start(); |
167 } | 177 } |
168 return g_video_sync_thread; | 178 return g_video_sync_thread; |
169 } | 179 } |
170 | 180 |
171 private: | 181 private: |
172 friend class base::RefCounted<SGIVideoSyncThread>; | 182 friend class base::RefCounted<SGIVideoSyncThread>; |
173 | 183 |
174 SGIVideoSyncThread() : base::Thread("SGI_video_sync") { | 184 SGIVideoSyncThread() : base::Thread("SGI_video_sync") { |
175 DCHECK(CalledOnValidThread()); | 185 DCHECK(CalledOnValidThread()); |
176 } | 186 } |
177 | 187 |
178 ~SGIVideoSyncThread() override { | 188 ~SGIVideoSyncThread() override { |
179 DCHECK(CalledOnValidThread()); | 189 DCHECK(CalledOnValidThread()); |
180 g_video_sync_thread = nullptr; | 190 g_video_sync_thread = nullptr; |
181 Stop(); | 191 Stop(); |
182 } | 192 } |
183 | 193 |
184 static SGIVideoSyncThread* g_video_sync_thread; | 194 static SGIVideoSyncThread* g_video_sync_thread; |
185 | 195 |
186 DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncThread); | 196 DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncThread); |
187 }; | 197 }; |
188 | 198 |
189 class SGIVideoSyncProviderThreadShim { | 199 class SGIVideoSyncProviderThreadShim { |
190 public: | 200 public: |
191 explicit SGIVideoSyncProviderThreadShim(GLXFBConfig config, | 201 explicit SGIVideoSyncProviderThreadShim(gfx::AcceleratedWidget parent_window) |
192 GLXWindow glx_window) | 202 : parent_window_(parent_window), |
193 : config_(config), | 203 window_(0), |
194 glx_window_(glx_window), | 204 glx_window_(0), |
195 context_(nullptr), | |
196 task_runner_(base::ThreadTaskRunnerHandle::Get()), | 205 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
197 cancel_vsync_flag_(), | 206 cancel_vsync_flag_(), |
198 vsync_lock_() { | 207 vsync_lock_() { |
199 // This ensures that creation of |window_| has occured when this shim | 208 // This ensures that creation of |parent_window_| has occured when this shim |
200 // is executing in the same process as the call to create |window_|. | 209 // is executing in the same thread as the call to create |parent_window_|. |
201 XSync(g_display, False); | 210 XSync(g_display, False); |
202 } | 211 } |
203 | 212 |
204 virtual ~SGIVideoSyncProviderThreadShim() { | 213 virtual ~SGIVideoSyncProviderThreadShim() { |
205 if (context_) { | 214 if (glx_window_) |
206 glXDestroyContext(display_, context_); | 215 glXDestroyWindow(display_, glx_window_); |
207 context_ = nullptr; | 216 |
208 } | 217 if (window_) |
| 218 XDestroyWindow(display_, window_); |
209 } | 219 } |
210 | 220 |
211 base::CancellationFlag* cancel_vsync_flag() { | 221 base::CancellationFlag* cancel_vsync_flag() { return &cancel_vsync_flag_; } |
212 return &cancel_vsync_flag_; | |
213 } | |
214 | 222 |
215 base::Lock* vsync_lock() { | 223 base::Lock* vsync_lock() { return &vsync_lock_; } |
216 return &vsync_lock_; | |
217 } | |
218 | 224 |
219 void Initialize() { | 225 void Initialize() { |
220 DCHECK(display_); | 226 DCHECK(display_); |
221 | 227 |
222 context_ = | 228 window_ = |
223 glXCreateNewContext(display_, config_, GLX_RGBA_TYPE, nullptr, True); | 229 XCreateWindow(display_, parent_window_, 0, 0, 1, 1, 0, CopyFromParent, |
| 230 InputOutput, CopyFromParent, 0, nullptr); |
| 231 if (!window_) { |
| 232 LOG(ERROR) << "video_sync: XCreateWindow failed"; |
| 233 return; |
| 234 } |
224 | 235 |
225 DCHECK(nullptr != context_); | 236 GLXFBConfig config = GetConfigForWindow(display_, window_); |
| 237 DCHECK(config); |
| 238 |
| 239 glx_window_ = glXCreateWindow(display_, config, window_, nullptr); |
| 240 if (!glx_window_) { |
| 241 LOG(ERROR) << "video_sync: glXCreateWindow failed"; |
| 242 return; |
| 243 } |
| 244 |
| 245 // Create the context only once for all vsync providers. |
| 246 if (!context_) { |
| 247 context_ = |
| 248 glXCreateNewContext(display_, config, GLX_RGBA_TYPE, nullptr, True); |
| 249 if (!context_) |
| 250 LOG(ERROR) << "video_sync: glXCreateNewContext failed"; |
| 251 } |
226 } | 252 } |
227 | 253 |
228 void GetVSyncParameters( | 254 void GetVSyncParameters( |
229 const gfx::VSyncProvider::UpdateVSyncCallback& callback) { | 255 const gfx::VSyncProvider::UpdateVSyncCallback& callback) { |
230 base::TimeTicks now; | 256 base::TimeTicks now; |
231 { | 257 { |
232 // Don't allow |window_| destruction while we're probing vsync. | 258 // Don't allow |window_| destruction while we're probing vsync. |
233 base::AutoLock locked(vsync_lock_); | 259 base::AutoLock locked(vsync_lock_); |
234 | 260 |
235 if (!context_ || cancel_vsync_flag_.IsSet()) | 261 if (!context_ || cancel_vsync_flag_.IsSet()) |
236 return; | 262 return; |
237 | 263 |
238 glXMakeContextCurrent(display_, glx_window_, glx_window_, context_); | 264 glXMakeContextCurrent(display_, glx_window_, glx_window_, context_); |
239 | 265 |
240 unsigned int retrace_count = 0; | 266 unsigned int retrace_count = 0; |
241 if (glXWaitVideoSyncSGI(1, 0, &retrace_count) != 0) | 267 if (glXWaitVideoSyncSGI(1, 0, &retrace_count) != 0) |
242 return; | 268 return; |
243 | 269 |
244 TRACE_EVENT_INSTANT0("gpu", "vblank", TRACE_EVENT_SCOPE_THREAD); | 270 TRACE_EVENT_INSTANT0("gpu", "vblank", TRACE_EVENT_SCOPE_THREAD); |
245 now = base::TimeTicks::Now(); | 271 now = base::TimeTicks::Now(); |
246 | 272 |
247 glXMakeContextCurrent(display_, 0, 0, nullptr); | 273 glXMakeContextCurrent(display_, 0, 0, nullptr); |
248 } | 274 } |
249 | 275 |
250 const base::TimeDelta kDefaultInterval = | 276 const base::TimeDelta kDefaultInterval = |
251 base::TimeDelta::FromSeconds(1) / 60; | 277 base::TimeDelta::FromSeconds(1) / 60; |
252 | 278 |
253 task_runner_->PostTask( | 279 task_runner_->PostTask(FROM_HERE, |
254 FROM_HERE, base::Bind(callback, now, kDefaultInterval)); | 280 base::Bind(callback, now, kDefaultInterval)); |
255 } | 281 } |
256 | 282 |
257 private: | 283 private: |
258 // For initialization of display_ in GLSurface::InitializeOneOff before | 284 // For initialization of display_ in GLSurface::InitializeOneOff before |
259 // the sandbox goes up. | 285 // the sandbox goes up. |
260 friend class gl::GLSurfaceGLX; | 286 friend class gl::GLSurfaceGLX; |
261 | 287 |
| 288 // We only need one Display and GLXContext because we only use one thread for |
| 289 // SGI_video_sync. The display is created in GLSurfaceGLX::InitializeOneOff |
| 290 // and the context is created the first time a vsync provider is initialized. |
262 static Display* display_; | 291 static Display* display_; |
| 292 static GLXContext context_; |
263 | 293 |
264 GLXFBConfig config_; | 294 gfx::AcceleratedWidget parent_window_; |
| 295 |
| 296 gfx::AcceleratedWidget window_; |
265 GLXWindow glx_window_; | 297 GLXWindow glx_window_; |
266 GLXContext context_; | |
267 | 298 |
268 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | 299 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
269 | 300 |
270 base::CancellationFlag cancel_vsync_flag_; | 301 base::CancellationFlag cancel_vsync_flag_; |
271 base::Lock vsync_lock_; | 302 base::Lock vsync_lock_; |
272 | 303 |
273 DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncProviderThreadShim); | 304 DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncProviderThreadShim); |
274 }; | 305 }; |
275 | 306 |
276 class SGIVideoSyncVSyncProvider | 307 class SGIVideoSyncVSyncProvider |
277 : public gfx::VSyncProvider, | 308 : public gfx::VSyncProvider, |
278 public base::SupportsWeakPtr<SGIVideoSyncVSyncProvider> { | 309 public base::SupportsWeakPtr<SGIVideoSyncVSyncProvider> { |
279 public: | 310 public: |
280 explicit SGIVideoSyncVSyncProvider(GLXFBConfig config, GLXWindow glx_window) | 311 explicit SGIVideoSyncVSyncProvider(gfx::AcceleratedWidget parent_window) |
281 : vsync_thread_(SGIVideoSyncThread::Create()), | 312 : vsync_thread_(SGIVideoSyncThread::Create()), |
282 shim_(new SGIVideoSyncProviderThreadShim(config, glx_window)), | 313 shim_(new SGIVideoSyncProviderThreadShim(parent_window)), |
283 cancel_vsync_flag_(shim_->cancel_vsync_flag()), | 314 cancel_vsync_flag_(shim_->cancel_vsync_flag()), |
284 vsync_lock_(shim_->vsync_lock()) { | 315 vsync_lock_(shim_->vsync_lock()) { |
285 vsync_thread_->task_runner()->PostTask( | 316 vsync_thread_->task_runner()->PostTask( |
286 FROM_HERE, base::Bind(&SGIVideoSyncProviderThreadShim::Initialize, | 317 FROM_HERE, base::Bind(&SGIVideoSyncProviderThreadShim::Initialize, |
287 base::Unretained(shim_.get()))); | 318 base::Unretained(shim_.get()))); |
288 } | 319 } |
289 | 320 |
290 ~SGIVideoSyncVSyncProvider() override { | 321 ~SGIVideoSyncVSyncProvider() override { |
291 { | 322 { |
292 base::AutoLock locked(*vsync_lock_); | 323 base::AutoLock locked(*vsync_lock_); |
293 cancel_vsync_flag_->Set(); | 324 cancel_vsync_flag_->Set(); |
294 } | 325 } |
295 | 326 |
296 // Hand-off |shim_| to be deleted on the |vsync_thread_|. | 327 // Hand-off |shim_| to be deleted on the |vsync_thread_|. |
297 vsync_thread_->task_runner()->DeleteSoon(FROM_HERE, shim_.release()); | 328 vsync_thread_->task_runner()->DeleteSoon(FROM_HERE, shim_.release()); |
298 } | 329 } |
299 | 330 |
300 void GetVSyncParameters( | 331 void GetVSyncParameters( |
301 const gfx::VSyncProvider::UpdateVSyncCallback& callback) override { | 332 const gfx::VSyncProvider::UpdateVSyncCallback& callback) override { |
302 if (kGetVSyncParametersMinSeconds > 0) { | |
303 base::TimeTicks now = base::TimeTicks::Now(); | |
304 base::TimeDelta delta = now - last_get_vsync_parameters_time_; | |
305 if (delta.InSeconds() < kGetVSyncParametersMinSeconds) | |
306 return; | |
307 last_get_vsync_parameters_time_ = now; | |
308 } | |
309 | |
310 // Only one outstanding request per surface. | 333 // Only one outstanding request per surface. |
311 if (!pending_callback_) { | 334 if (!pending_callback_) { |
312 pending_callback_.reset( | 335 pending_callback_.reset( |
313 new gfx::VSyncProvider::UpdateVSyncCallback(callback)); | 336 new gfx::VSyncProvider::UpdateVSyncCallback(callback)); |
314 vsync_thread_->task_runner()->PostTask( | 337 vsync_thread_->task_runner()->PostTask( |
315 FROM_HERE, | 338 FROM_HERE, |
316 base::Bind( | 339 base::Bind( |
317 &SGIVideoSyncProviderThreadShim::GetVSyncParameters, | 340 &SGIVideoSyncProviderThreadShim::GetVSyncParameters, |
318 base::Unretained(shim_.get()), | 341 base::Unretained(shim_.get()), |
319 base::Bind(&SGIVideoSyncVSyncProvider::PendingCallbackRunner, | 342 base::Bind(&SGIVideoSyncVSyncProvider::PendingCallbackRunner, |
(...skipping 15 matching lines...) Expand all Loading... |
335 std::unique_ptr<SGIVideoSyncProviderThreadShim> shim_; | 358 std::unique_ptr<SGIVideoSyncProviderThreadShim> shim_; |
336 | 359 |
337 std::unique_ptr<gfx::VSyncProvider::UpdateVSyncCallback> pending_callback_; | 360 std::unique_ptr<gfx::VSyncProvider::UpdateVSyncCallback> pending_callback_; |
338 | 361 |
339 // Raw pointers to sync primitives owned by the shim_. | 362 // Raw pointers to sync primitives owned by the shim_. |
340 // These will only be referenced before we post a task to destroy | 363 // These will only be referenced before we post a task to destroy |
341 // the shim_, so they are safe to access. | 364 // the shim_, so they are safe to access. |
342 base::CancellationFlag* cancel_vsync_flag_; | 365 base::CancellationFlag* cancel_vsync_flag_; |
343 base::Lock* vsync_lock_; | 366 base::Lock* vsync_lock_; |
344 | 367 |
345 base::TimeTicks last_get_vsync_parameters_time_; | |
346 | |
347 DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncVSyncProvider); | 368 DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncVSyncProvider); |
348 }; | 369 }; |
349 | 370 |
350 SGIVideoSyncThread* SGIVideoSyncThread::g_video_sync_thread = nullptr; | 371 SGIVideoSyncThread* SGIVideoSyncThread::g_video_sync_thread = nullptr; |
351 | 372 |
352 // In order to take advantage of GLX_SGI_video_sync, we need a display | 373 // In order to take advantage of GLX_SGI_video_sync, we need a display |
353 // for use on a separate thread. We must allocate this before the sandbox | 374 // for use on a separate thread. We must allocate this before the sandbox |
354 // goes up (rather than on-demand when we start the thread). | 375 // goes up (rather than on-demand when we start the thread). |
355 Display* SGIVideoSyncProviderThreadShim::display_ = nullptr; | 376 Display* SGIVideoSyncProviderThreadShim::display_ = nullptr; |
| 377 GLXContext SGIVideoSyncProviderThreadShim::context_ = 0; |
356 | 378 |
357 } // namespace | 379 } // namespace |
358 | 380 |
359 GLSurfaceGLX::GLSurfaceGLX() {} | 381 GLSurfaceGLX::GLSurfaceGLX() {} |
360 | 382 |
361 bool GLSurfaceGLX::InitializeOneOff() { | 383 bool GLSurfaceGLX::InitializeOneOff() { |
362 static bool initialized = false; | 384 static bool initialized = false; |
363 if (initialized) | 385 if (initialized) |
364 return true; | 386 return true; |
365 | 387 |
(...skipping 14 matching lines...) Expand all Loading... |
380 if (!glXQueryVersion(g_display, &major, &minor)) { | 402 if (!glXQueryVersion(g_display, &major, &minor)) { |
381 LOG(ERROR) << "glxQueryVersion failed"; | 403 LOG(ERROR) << "glxQueryVersion failed"; |
382 return false; | 404 return false; |
383 } | 405 } |
384 | 406 |
385 if (major == 1 && minor < 3) { | 407 if (major == 1 && minor < 3) { |
386 LOG(ERROR) << "GLX 1.3 or later is required."; | 408 LOG(ERROR) << "GLX 1.3 or later is required."; |
387 return false; | 409 return false; |
388 } | 410 } |
389 | 411 |
390 g_glx_context_create = | 412 g_glx_context_create = HasGLXExtension("GLX_ARB_create_context"); |
391 HasGLXExtension("GLX_ARB_create_context"); | |
392 g_glx_create_context_robustness_supported = | 413 g_glx_create_context_robustness_supported = |
393 HasGLXExtension("GLX_ARB_create_context_robustness"); | 414 HasGLXExtension("GLX_ARB_create_context_robustness"); |
394 g_glx_create_context_profile_supported = | 415 g_glx_create_context_profile_supported = |
395 HasGLXExtension("GLX_ARB_create_context_profile"); | 416 HasGLXExtension("GLX_ARB_create_context_profile"); |
396 g_glx_create_context_profile_es2_supported = | 417 g_glx_create_context_profile_es2_supported = |
397 HasGLXExtension("GLX_ARB_create_context_es2_profile"); | 418 HasGLXExtension("GLX_ARB_create_context_es2_profile"); |
398 g_glx_texture_from_pixmap_supported = | 419 g_glx_texture_from_pixmap_supported = |
399 HasGLXExtension("GLX_EXT_texture_from_pixmap"); | 420 HasGLXExtension("GLX_EXT_texture_from_pixmap"); |
400 g_glx_oml_sync_control_supported = | 421 g_glx_oml_sync_control_supported = HasGLXExtension("GLX_OML_sync_control"); |
401 HasGLXExtension("GLX_OML_sync_control"); | |
402 g_glx_get_msc_rate_oml_supported = g_glx_oml_sync_control_supported; | 422 g_glx_get_msc_rate_oml_supported = g_glx_oml_sync_control_supported; |
403 g_glx_sgi_video_sync_supported = | 423 g_glx_sgi_video_sync_supported = HasGLXExtension("GLX_SGI_video_sync"); |
404 HasGLXExtension("GLX_SGI_video_sync") && | |
405 base::CommandLine::ForCurrentProcess()->HasSwitch( | |
406 switches::kEnableSgiVideoSync); | |
407 | 424 |
408 if (!g_glx_get_msc_rate_oml_supported && g_glx_sgi_video_sync_supported) | 425 // We create a dummy unmapped window for both the main Display and the video |
409 SGIVideoSyncProviderThreadShim::display_ = gfx::OpenNewXDisplay(); | 426 // sync Display so that the Nvidia driver can initialize itself before the |
| 427 // sandbox is set up. |
| 428 // Unfortunately some fds e.g. /dev/nvidia0 are cached per thread and because |
| 429 // we can't start threads before the sandbox is set up, these are accessed |
| 430 // through the broker process. See GpuProcessPolicy::InitGpuBrokerProcess. |
| 431 if (!CreateDummyWindow(g_display)) { |
| 432 LOG(ERROR) << "CreateDummyWindow(g_display) failed"; |
| 433 return false; |
| 434 } |
| 435 |
| 436 if (!g_glx_get_msc_rate_oml_supported && g_glx_sgi_video_sync_supported) { |
| 437 Display* video_sync_display = gfx::OpenNewXDisplay(); |
| 438 if (!CreateDummyWindow(video_sync_display)) { |
| 439 LOG(ERROR) << "CreateDummyWindow(video_sync_display) failed"; |
| 440 return false; |
| 441 } |
| 442 SGIVideoSyncProviderThreadShim::display_ = video_sync_display; |
| 443 } |
410 | 444 |
411 initialized = true; | 445 initialized = true; |
412 return true; | 446 return true; |
413 } | 447 } |
414 | 448 |
415 // static | 449 // static |
416 const char* GLSurfaceGLX::GetGLXExtensions() { | 450 const char* GLSurfaceGLX::GetGLXExtensions() { |
417 return glXQueryExtensionsString(g_display, 0); | 451 return glXQueryExtensionsString(g_display, 0); |
418 } | 452 } |
419 | 453 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 return g_glx_oml_sync_control_supported; | 486 return g_glx_oml_sync_control_supported; |
453 } | 487 } |
454 | 488 |
455 void* GLSurfaceGLX::GetDisplay() { | 489 void* GLSurfaceGLX::GetDisplay() { |
456 return g_display; | 490 return g_display; |
457 } | 491 } |
458 | 492 |
459 GLSurfaceGLX::~GLSurfaceGLX() {} | 493 GLSurfaceGLX::~GLSurfaceGLX() {} |
460 | 494 |
461 NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::AcceleratedWidget window) | 495 NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::AcceleratedWidget window) |
462 : parent_window_(window), window_(0), glx_window_(0), config_(nullptr) { | 496 : parent_window_(window), window_(0), glx_window_(0), config_(nullptr) {} |
463 } | |
464 | 497 |
465 GLXDrawable NativeViewGLSurfaceGLX::GetDrawableHandle() const { | 498 GLXDrawable NativeViewGLSurfaceGLX::GetDrawableHandle() const { |
466 return glx_window_; | 499 return glx_window_; |
467 } | 500 } |
468 | 501 |
469 bool NativeViewGLSurfaceGLX::Initialize(GLSurface::Format format) { | 502 bool NativeViewGLSurfaceGLX::Initialize(GLSurface::Format format) { |
470 XWindowAttributes attributes; | 503 XWindowAttributes attributes; |
471 if (!XGetWindowAttributes(g_display, parent_window_, &attributes)) { | 504 if (!XGetWindowAttributes(g_display, parent_window_, &attributes)) { |
472 LOG(ERROR) << "XGetWindowAttributes failed for window " << parent_window_ | 505 LOG(ERROR) << "XGetWindowAttributes failed for window " << parent_window_ |
473 << "."; | 506 << "."; |
474 return false; | 507 return false; |
475 } | 508 } |
476 size_ = gfx::Size(attributes.width, attributes.height); | 509 size_ = gfx::Size(attributes.width, attributes.height); |
477 // Create a child window, with a CopyFromParent visual (to avoid inducing | 510 // Create a child window, with a CopyFromParent visual (to avoid inducing |
478 // extra blits in the driver), that we can resize exactly in Resize(), | 511 // extra blits in the driver), that we can resize exactly in Resize(), |
479 // correctly ordered with GL, so that we don't have invalid transient states. | 512 // correctly ordered with GL, so that we don't have invalid transient states. |
480 // See https://crbug.com/326995. | 513 // See https://crbug.com/326995. |
481 XSetWindowAttributes swa; | 514 XSetWindowAttributes swa; |
482 memset(&swa, 0, sizeof(swa)); | 515 memset(&swa, 0, sizeof(swa)); |
483 swa.background_pixmap = 0; | 516 swa.background_pixmap = 0; |
(...skipping 12 matching lines...) Expand all Loading... |
496 } | 529 } |
497 XFlush(g_display); | 530 XFlush(g_display); |
498 | 531 |
499 GetConfig(); | 532 GetConfig(); |
500 DCHECK(config_); | 533 DCHECK(config_); |
501 glx_window_ = glXCreateWindow(g_display, config_, window_, NULL); | 534 glx_window_ = glXCreateWindow(g_display, config_, window_, NULL); |
502 | 535 |
503 if (g_glx_oml_sync_control_supported) { | 536 if (g_glx_oml_sync_control_supported) { |
504 vsync_provider_.reset(new OMLSyncControlVSyncProvider(glx_window_)); | 537 vsync_provider_.reset(new OMLSyncControlVSyncProvider(glx_window_)); |
505 } else if (g_glx_sgi_video_sync_supported) { | 538 } else if (g_glx_sgi_video_sync_supported) { |
506 vsync_provider_.reset(new SGIVideoSyncVSyncProvider(config_, glx_window_)); | 539 vsync_provider_.reset(new SGIVideoSyncVSyncProvider(parent_window_)); |
507 } else { | 540 } else { |
508 // Assume a refresh rate of 59.9 Hz, which will cause us to skip | 541 // Assume a refresh rate of 59.9 Hz, which will cause us to skip |
509 // 1 frame every 10 seconds on a 60Hz monitor, but will prevent us | 542 // 1 frame every 10 seconds on a 60Hz monitor, but will prevent us |
510 // from blocking the GPU service due to back pressure. This would still | 543 // from blocking the GPU service due to back pressure. This would still |
511 // encounter backpressure on a <60Hz monitor, but hopefully that is | 544 // encounter backpressure on a <60Hz monitor, but hopefully that is |
512 // not common. | 545 // not common. |
513 const base::TimeTicks kDefaultTimebase; | 546 const base::TimeTicks kDefaultTimebase; |
514 const base::TimeDelta kDefaultInterval = | 547 const base::TimeDelta kDefaultInterval = |
515 base::TimeDelta::FromSeconds(1) / 59.9; | 548 base::TimeDelta::FromSeconds(1) / 59.9; |
516 vsync_provider_.reset( | 549 vsync_provider_.reset( |
(...skipping 20 matching lines...) Expand all Loading... |
537 } | 570 } |
538 } | 571 } |
539 | 572 |
540 bool NativeViewGLSurfaceGLX::CanDispatchEvent(const ui::PlatformEvent& event) { | 573 bool NativeViewGLSurfaceGLX::CanDispatchEvent(const ui::PlatformEvent& event) { |
541 return event->type == Expose && event->xexpose.window == window_; | 574 return event->type == Expose && event->xexpose.window == window_; |
542 } | 575 } |
543 | 576 |
544 uint32_t NativeViewGLSurfaceGLX::DispatchEvent(const ui::PlatformEvent& event) { | 577 uint32_t NativeViewGLSurfaceGLX::DispatchEvent(const ui::PlatformEvent& event) { |
545 XEvent forwarded_event = *event; | 578 XEvent forwarded_event = *event; |
546 forwarded_event.xexpose.window = parent_window_; | 579 forwarded_event.xexpose.window = parent_window_; |
547 XSendEvent(g_display, parent_window_, False, ExposureMask, | 580 XSendEvent(g_display, parent_window_, False, ExposureMask, &forwarded_event); |
548 &forwarded_event); | |
549 XFlush(g_display); | 581 XFlush(g_display); |
550 return ui::POST_DISPATCH_STOP_PROPAGATION; | 582 return ui::POST_DISPATCH_STOP_PROPAGATION; |
551 } | 583 } |
552 | 584 |
553 bool NativeViewGLSurfaceGLX::Resize(const gfx::Size& size, | 585 bool NativeViewGLSurfaceGLX::Resize(const gfx::Size& size, |
554 float scale_factor, | 586 float scale_factor, |
555 bool has_alpha) { | 587 bool has_alpha) { |
556 size_ = size; | 588 size_ = size; |
557 glXWaitGL(); | 589 glXWaitGL(); |
558 XResizeWindow(g_display, window_, size.width(), size.height()); | 590 XResizeWindow(g_display, window_, size.width(), size.height()); |
559 glXWaitX(); | 591 glXWaitX(); |
560 return true; | 592 return true; |
561 } | 593 } |
562 | 594 |
563 bool NativeViewGLSurfaceGLX::IsOffscreen() { | 595 bool NativeViewGLSurfaceGLX::IsOffscreen() { |
564 return false; | 596 return false; |
565 } | 597 } |
566 | 598 |
567 gfx::SwapResult NativeViewGLSurfaceGLX::SwapBuffers() { | 599 gfx::SwapResult NativeViewGLSurfaceGLX::SwapBuffers() { |
568 TRACE_EVENT2("gpu", "NativeViewGLSurfaceGLX:RealSwapBuffers", | 600 TRACE_EVENT2("gpu", "NativeViewGLSurfaceGLX:RealSwapBuffers", "width", |
569 "width", GetSize().width(), | 601 GetSize().width(), "height", GetSize().height()); |
570 "height", GetSize().height()); | |
571 | 602 |
572 glXSwapBuffers(g_display, GetDrawableHandle()); | 603 glXSwapBuffers(g_display, GetDrawableHandle()); |
573 return gfx::SwapResult::SWAP_ACK; | 604 return gfx::SwapResult::SWAP_ACK; |
574 } | 605 } |
575 | 606 |
576 gfx::Size NativeViewGLSurfaceGLX::GetSize() { | 607 gfx::Size NativeViewGLSurfaceGLX::GetSize() { |
577 return size_; | 608 return size_; |
578 } | 609 } |
579 | 610 |
580 void* NativeViewGLSurfaceGLX::GetHandle() { | 611 void* NativeViewGLSurfaceGLX::GetHandle() { |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 if (!config_) | 698 if (!config_) |
668 config_ = GetConfigForWindow(g_display, window_); | 699 config_ = GetConfigForWindow(g_display, window_); |
669 return config_; | 700 return config_; |
670 } | 701 } |
671 | 702 |
672 UnmappedNativeViewGLSurfaceGLX::~UnmappedNativeViewGLSurfaceGLX() { | 703 UnmappedNativeViewGLSurfaceGLX::~UnmappedNativeViewGLSurfaceGLX() { |
673 Destroy(); | 704 Destroy(); |
674 } | 705 } |
675 | 706 |
676 } // namespace gl | 707 } // namespace gl |
OLD | NEW |