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

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

Issue 23452026: Destroy GLX windows when they are backgrounded (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Clean up patch Created 7 years, 3 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 | « ui/gl/gl_surface_glx.h ('k') | 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
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/lazy_instance.h"
13 #include "base/logging.h" 14 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h" 15 #include "base/memory/scoped_ptr.h"
15 #include "base/memory/weak_ptr.h" 16 #include "base/memory/weak_ptr.h"
16 #include "base/message_loop/message_loop.h" 17 #include "base/message_loop/message_loop.h"
17 #include "base/synchronization/cancellation_flag.h" 18 #include "base/synchronization/cancellation_flag.h"
18 #include "base/synchronization/lock.h" 19 #include "base/synchronization/lock.h"
19 #include "base/threading/non_thread_safe.h" 20 #include "base/threading/non_thread_safe.h"
20 #include "base/threading/thread.h" 21 #include "base/threading/thread.h"
21 #include "base/time/time.h" 22 #include "base/time/time.h"
22 #include "third_party/mesa/src/include/GL/osmesa.h" 23 #include "third_party/mesa/src/include/GL/osmesa.h"
23 #include "ui/base/x/x11_util.h" 24 #include "ui/base/x/x11_util.h"
24 #include "ui/gl/gl_bindings.h" 25 #include "ui/gl/gl_bindings.h"
25 #include "ui/gl/gl_implementation.h" 26 #include "ui/gl/gl_implementation.h"
26 #include "ui/gl/vsync_provider.h" 27 #include "ui/gl/vsync_provider.h"
27 28
28 namespace gfx { 29 namespace gfx {
29 30
30 namespace { 31 namespace {
31 32
32 // scoped_ptr functor for XFree(). Use as follows: 33 // scoped_ptr functor for XFree(). Use as follows:
33 // scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> foo(...); 34 // scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> foo(...);
34 // where "XVisualInfo" is any X type that is freed with XFree. 35 // where "XVisualInfo" is any X type that is freed with XFree.
35 class ScopedPtrXFree { 36 class ScopedPtrXFree {
36 public: 37 public:
37 void operator()(void* x) const { 38 void operator()(void* x) const {
38 ::XFree(x); 39 ::XFree(x);
39 } 40 }
40 }; 41 };
41 42
42 Display* g_display; 43 Display* g_display = NULL;
43 const char* g_glx_extensions = NULL; 44 const char* g_glx_extensions = NULL;
44 bool g_glx_context_create = false; 45 bool g_glx_context_create = false;
45 bool g_glx_create_context_robustness_supported = false; 46 bool g_glx_create_context_robustness_supported = false;
46 bool g_glx_texture_from_pixmap_supported = false; 47 bool g_glx_texture_from_pixmap_supported = false;
47 bool g_glx_oml_sync_control_supported = false; 48 bool g_glx_oml_sync_control_supported = false;
48 49
49 // Track support of glXGetMscRateOML separately from GLX_OML_sync_control as a 50 // Track support of glXGetMscRateOML separately from GLX_OML_sync_control as a
50 // whole since on some platforms (e.g. crosbug.com/34585), glXGetMscRateOML 51 // 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. 52 // always fails even though GLX_OML_sync_control is reported as being supported.
52 bool g_glx_get_msc_rate_oml_supported = false; 53 bool g_glx_get_msc_rate_oml_supported = false;
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncVSyncProvider); 293 DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncVSyncProvider);
293 }; 294 };
294 295
295 SGIVideoSyncThread* SGIVideoSyncThread::g_video_sync_thread = NULL; 296 SGIVideoSyncThread* SGIVideoSyncThread::g_video_sync_thread = NULL;
296 297
297 // In order to take advantage of GLX_SGI_video_sync, we need a display 298 // In order to take advantage of GLX_SGI_video_sync, we need a display
298 // for use on a separate thread. We must allocate this before the sandbox 299 // for use on a separate thread. We must allocate this before the sandbox
299 // goes up (rather than on-demand when we start the thread). 300 // goes up (rather than on-demand when we start the thread).
300 Display* SGIVideoSyncProviderThreadShim::display_ = NULL; 301 Display* SGIVideoSyncProviderThreadShim::display_ = NULL;
301 302
303 #if defined(TOOLKIT_GTK)
304 // A mechanism for forwarding XExpose events from one window to another.
305 // Because in the workaround for http://crbug.com/145600 the child window
306 // is placed on top of the parent window, only the child window will receive
307 // all expose events. These need to be forwared to the parent window to inform
308 // it that it should paint.
309 class XExposeEventForwarder : public base::MessagePumpObserver {
310 public:
311 void AddParentChildPair(gfx::AcceleratedWidget parent_window,
312 gfx::AcceleratedWidget child_window) {
313 if (child_to_parent_map_.empty())
314 base::MessagePumpX11::Current()->AddObserver(this);
315
316 DCHECK(child_to_parent_map_.find(child_window) ==
317 child_to_parent_map_.end());
318 child_to_parent_map_.insert(std::make_pair(
319 child_window, parent_window));
320 }
321 void RemoveParentChildPair(gfx::AcceleratedWidget parent_window,
322 gfx::AcceleratedWidget child_window) {
323 DCHECK(child_to_parent_map_.find(child_window) !=
324 child_to_parent_map_.end());
325 child_to_parent_map_.erase(child_window);
326
327 if (child_to_parent_map_.empty())
328 base::MessagePumpX11::Current()->RemoveObserver(this);
329 }
330
331 private:
332 virtual base::EventStatus WillProcessEvent(
333 const base::NativeEvent& xevent) OVERRIDE {
334 if (xevent->type != Expose)
335 return base::EVENT_CONTINUE;
336
337 WindowMap::const_iterator found = child_to_parent_map_.find(
338 xevent->xexpose.window);
339 if (found == child_to_parent_map_.end())
340 return base::EVENT_CONTINUE;
341
342 gfx::AcceleratedWidget target_window = found->second;
343 XEvent forwarded_event = *xevent;
344 forwarded_event.xexpose.window = target_window;
345 XSendEvent(g_display, target_window, False, ExposureMask,
346 &forwarded_event);
347 return base::EVENT_CONTINUE;
348 }
349 virtual void DidProcessEvent(const base::NativeEvent& xevent) {
350 }
351
352 typedef std::map<gfx::AcceleratedWidget, gfx::AcceleratedWidget> WindowMap;
353 WindowMap child_to_parent_map_;
354 };
piman 2013/09/12 20:35:52 nit: DISALLOW_COPY_AND_ASSIGN. Maybe DCHECK in th
ccameron 2013/09/13 09:33:38 Done.
355
356 static base::LazyInstance<XExposeEventForwarder> g_xexpose_event_forwarder =
357 LAZY_INSTANCE_INITIALIZER;
358 #endif
359
302 } // namespace 360 } // namespace
303 361
304 GLSurfaceGLX::GLSurfaceGLX() {} 362 GLSurfaceGLX::GLSurfaceGLX() {}
305 363
306 bool GLSurfaceGLX::InitializeOneOff() { 364 bool GLSurfaceGLX::InitializeOneOff() {
307 static bool initialized = false; 365 static bool initialized = false;
308 if (initialized) 366 if (initialized)
309 return true; 367 return true;
310 368
311 // http://crbug.com/245466 369 // http://crbug.com/245466
312 setenv("force_s3tc_enable", "true", 1); 370 setenv("force_s3tc_enable", "true", 1);
313 371
314 // SGIVideoSyncProviderShim (if instantiated) will issue X commands on 372 // SGIVideoSyncProviderShim (if instantiated) will issue X commands on
315 // it's own thread. 373 // it's own thread.
316 XInitThreads(); 374 XInitThreads();
317 375
376 #if defined(TOOLKIT_GTK)
377 // Be sure to use the X display handle and not the GTK display handle if this
378 // is the GPU process.
379 if (base::MessageLoop::current()->type() == base::MessageLoop::TYPE_GPU)
380 g_display = base::MessagePumpX11::GetDefaultXDisplay();
381 else
382 g_display = base::MessagePumpForUI::GetDefaultXDisplay();
383 #else
318 g_display = base::MessagePumpForUI::GetDefaultXDisplay(); 384 g_display = base::MessagePumpForUI::GetDefaultXDisplay();
385 #endif
386
319 if (!g_display) { 387 if (!g_display) {
320 LOG(ERROR) << "XOpenDisplay failed."; 388 LOG(ERROR) << "XOpenDisplay failed.";
321 return false; 389 return false;
322 } 390 }
323 391
324 int major, minor; 392 int major, minor;
325 if (!glXQueryVersion(g_display, &major, &minor)) { 393 if (!glXQueryVersion(g_display, &major, &minor)) {
326 LOG(ERROR) << "glxQueryVersion failed"; 394 LOG(ERROR) << "glxQueryVersion failed";
327 return false; 395 return false;
328 } 396 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 bool GLSurfaceGLX::IsOMLSyncControlSupported() { 449 bool GLSurfaceGLX::IsOMLSyncControlSupported() {
382 return g_glx_oml_sync_control_supported; 450 return g_glx_oml_sync_control_supported;
383 } 451 }
384 452
385 void* GLSurfaceGLX::GetDisplay() { 453 void* GLSurfaceGLX::GetDisplay() {
386 return g_display; 454 return g_display;
387 } 455 }
388 456
389 GLSurfaceGLX::~GLSurfaceGLX() {} 457 GLSurfaceGLX::~GLSurfaceGLX() {}
390 458
459 #if defined(TOOLKIT_GTK)
460 bool NativeViewGLSurfaceGLX::SetBackbufferAllocation(bool allocated) {
461 backbuffer_allocated_ = allocated;
462 AdjustBufferAllocation();
463 return true;
464 }
465
466 void NativeViewGLSurfaceGLX::SetFrontbufferAllocation(bool allocated) {
467 frontbuffer_allocated_ = allocated;
468 AdjustBufferAllocation();
469 }
470
471 void NativeViewGLSurfaceGLX::AdjustBufferAllocation() {
472 if (frontbuffer_allocated_ || backbuffer_allocated_)
473 CreateChildWindow();
474 else
475 DestroyChildWindow();
476 }
477
478 void NativeViewGLSurfaceGLX::CreateChildWindow() {
479 if (child_window_)
480 return;
481
482 XSetWindowAttributes set_window_attributes;
483 set_window_attributes.event_mask = ExposureMask;
484 child_window_ = XCreateWindow(
485 g_display, parent_window_, 0, 0, size_.width(), size_.height(), 0,
486 CopyFromParent, InputOutput, CopyFromParent, CWEventMask,
487 &set_window_attributes);
488 g_xexpose_event_forwarder.Pointer()->AddParentChildPair(
489 parent_window_, child_window_);
490
491 XMapWindow(g_display, child_window_);
492 XFlush(g_display);
493
494 return;
piman 2013/09/12 20:35:52 nit: return at the end of a method, not needed.
ccameron 2013/09/13 09:33:38 Done.
495 }
496
497 void NativeViewGLSurfaceGLX::DestroyChildWindow() {
498 if (!child_window_)
499 return;
500
501 g_xexpose_event_forwarder.Pointer()->RemoveParentChildPair(
502 parent_window_, child_window_);
503 XDestroyWindow(g_display, child_window_);
504 XFlush(g_display);
505 child_window_ = 0;
506 }
507 #endif
508
391 NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::AcceleratedWidget window) 509 NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::AcceleratedWidget window)
392 : window_(window), 510 : parent_window_(window),
511 #if defined(TOOLKIT_GTK)
512 child_window_(0),
513 dummy_window_(0),
514 backbuffer_allocated_(true),
515 frontbuffer_allocated_(true),
516 #endif
393 config_(NULL) { 517 config_(NULL) {
394 } 518 }
395 519
520 gfx::AcceleratedWidget NativeViewGLSurfaceGLX::GetDrawableHandle() const {
521 #if defined(TOOLKIT_GTK)
522 if (child_window_)
523 return child_window_;
524 return dummy_window_;
525 #else
526 return parent_window_;
527 #endif
528 }
529
396 bool NativeViewGLSurfaceGLX::Initialize() { 530 bool NativeViewGLSurfaceGLX::Initialize() {
397 XWindowAttributes attributes; 531 XWindowAttributes attributes;
398 if (!XGetWindowAttributes(g_display, window_, &attributes)) { 532 if (!XGetWindowAttributes(g_display, parent_window_, &attributes)) {
399 LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << "."; 533 LOG(ERROR) << "XGetWindowAttributes failed for window " << parent_window_
534 << ".";
400 return false; 535 return false;
401 } 536 }
402 size_ = gfx::Size(attributes.width, attributes.height); 537 size_ = gfx::Size(attributes.width, attributes.height);
403 538
539 gfx::AcceleratedWidget window_for_vsync = parent_window_;
540
541 #if defined(TOOLKIT_GTK)
542 dummy_window_ = XCreateWindow(
543 g_display,
544 RootWindow(g_display, XScreenNumberOfScreen(attributes.screen)),
545 0, 0, 1, 1, 0, CopyFromParent, InputOutput, attributes.visual, 0, NULL);
546 window_for_vsync = dummy_window_;
547 CreateChildWindow();
548 #endif
549
404 if (g_glx_oml_sync_control_supported) 550 if (g_glx_oml_sync_control_supported)
405 vsync_provider_.reset(new OMLSyncControlVSyncProvider(window_)); 551 vsync_provider_.reset(new OMLSyncControlVSyncProvider(window_for_vsync));
406 else if (g_glx_sgi_video_sync_supported) 552 else if (g_glx_sgi_video_sync_supported)
407 vsync_provider_.reset(new SGIVideoSyncVSyncProvider(window_)); 553 vsync_provider_.reset(new SGIVideoSyncVSyncProvider(window_for_vsync));
408 554
409 return true; 555 return true;
410 } 556 }
411 557
412 void NativeViewGLSurfaceGLX::Destroy() { 558 void NativeViewGLSurfaceGLX::Destroy() {
559 #if defined(TOOLKIT_GTK)
560 DestroyChildWindow();
561 if (dummy_window_)
562 XDestroyWindow(g_display, dummy_window_);
563 dummy_window_ = 0;
564 #endif
413 } 565 }
414 566
415 bool NativeViewGLSurfaceGLX::Resize(const gfx::Size& size) { 567 bool NativeViewGLSurfaceGLX::Resize(const gfx::Size& size) {
568 #if defined(TOOLKIT_GTK)
569 if (child_window_) {
570 XResizeWindow(g_display, child_window_, size.width(), size.height());
571 XFlush(g_display);
572 }
573 #endif
416 size_ = size; 574 size_ = size;
417 return true; 575 return true;
418 } 576 }
419 577
420 bool NativeViewGLSurfaceGLX::IsOffscreen() { 578 bool NativeViewGLSurfaceGLX::IsOffscreen() {
421 return false; 579 return false;
422 } 580 }
423 581
424 bool NativeViewGLSurfaceGLX::SwapBuffers() { 582 bool NativeViewGLSurfaceGLX::SwapBuffers() {
425 glXSwapBuffers(g_display, window_); 583 glXSwapBuffers(g_display, GetDrawableHandle());
426 return true; 584 return true;
427 } 585 }
428 586
429 gfx::Size NativeViewGLSurfaceGLX::GetSize() { 587 gfx::Size NativeViewGLSurfaceGLX::GetSize() {
430 return size_; 588 return size_;
431 } 589 }
432 590
433 void* NativeViewGLSurfaceGLX::GetHandle() { 591 void* NativeViewGLSurfaceGLX::GetHandle() {
434 return reinterpret_cast<void*>(window_); 592 return reinterpret_cast<void*>(GetDrawableHandle());
435 } 593 }
436 594
437 std::string NativeViewGLSurfaceGLX::GetExtensions() { 595 std::string NativeViewGLSurfaceGLX::GetExtensions() {
438 std::string extensions = GLSurface::GetExtensions(); 596 std::string extensions = GLSurface::GetExtensions();
439 if (gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer) { 597 if (gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer) {
440 extensions += extensions.empty() ? "" : " "; 598 extensions += extensions.empty() ? "" : " ";
441 extensions += "GL_CHROMIUM_post_sub_buffer"; 599 extensions += "GL_CHROMIUM_post_sub_buffer";
442 } 600 }
443 return extensions; 601 return extensions;
444 } 602 }
445 603
446 void* NativeViewGLSurfaceGLX::GetConfig() { 604 void* NativeViewGLSurfaceGLX::GetConfig() {
447 if (!config_) { 605 if (!config_) {
448 // This code path is expensive, but we only take it when 606 // This code path is expensive, but we only take it when
449 // attempting to use GLX_ARB_create_context_robustness, in which 607 // attempting to use GLX_ARB_create_context_robustness, in which
450 // case we need a GLXFBConfig for the window in order to create a 608 // case we need a GLXFBConfig for the window in order to create a
451 // context for it. 609 // context for it.
452 // 610 //
453 // TODO(kbr): this is not a reliable code path. On platforms which 611 // TODO(kbr): this is not a reliable code path. On platforms which
454 // support it, we should use glXChooseFBConfig in the browser 612 // support it, we should use glXChooseFBConfig in the browser
455 // process to choose the FBConfig and from there the X Visual to 613 // process to choose the FBConfig and from there the X Visual to
456 // use when creating the window in the first place. Then we can 614 // use when creating the window in the first place. Then we can
457 // pass that FBConfig down rather than attempting to reconstitute 615 // pass that FBConfig down rather than attempting to reconstitute
458 // it. 616 // it.
459 617
460 XWindowAttributes attributes; 618 XWindowAttributes attributes;
461 if (!XGetWindowAttributes( 619 if (!XGetWindowAttributes(
462 g_display, 620 g_display,
463 window_, 621 parent_window_,
464 &attributes)) { 622 &attributes)) {
465 LOG(ERROR) << "XGetWindowAttributes failed for window " << 623 LOG(ERROR) << "XGetWindowAttributes failed for window " <<
466 window_ << "."; 624 parent_window_ << ".";
467 return NULL; 625 return NULL;
468 } 626 }
469 627
470 int visual_id = XVisualIDFromVisual(attributes.visual); 628 int visual_id = XVisualIDFromVisual(attributes.visual);
471 629
472 int num_elements = 0; 630 int num_elements = 0;
473 scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> configs( 631 scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> configs(
474 glXGetFBConfigs(g_display, 632 glXGetFBConfigs(g_display,
475 DefaultScreen(g_display), 633 DefaultScreen(g_display),
476 &num_elements)); 634 &num_elements));
(...skipping 23 matching lines...) Expand all
500 config_ = configs.get()[i]; 658 config_ = configs.get()[i];
501 } 659 }
502 } 660 }
503 661
504 return config_; 662 return config_;
505 } 663 }
506 664
507 bool NativeViewGLSurfaceGLX::PostSubBuffer( 665 bool NativeViewGLSurfaceGLX::PostSubBuffer(
508 int x, int y, int width, int height) { 666 int x, int y, int width, int height) {
509 DCHECK(gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer); 667 DCHECK(gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer);
510 glXCopySubBufferMESA(g_display, window_, x, y, width, height); 668 glXCopySubBufferMESA(g_display, GetDrawableHandle(), x, y, width, height);
511 return true; 669 return true;
512 } 670 }
513 671
514 VSyncProvider* NativeViewGLSurfaceGLX::GetVSyncProvider() { 672 VSyncProvider* NativeViewGLSurfaceGLX::GetVSyncProvider() {
515 return vsync_provider_.get(); 673 return vsync_provider_.get();
516 } 674 }
517 675
518 NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX() 676 NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX()
519 : window_(0), 677 : parent_window_(0),
678 #if defined(TOOLKIT_GTK)
679 child_window_(0),
680 dummy_window_(0),
681 backbuffer_allocated_(true),
682 frontbuffer_allocated_(true),
683 #endif
520 config_(NULL) { 684 config_(NULL) {
521 } 685 }
522 686
523 NativeViewGLSurfaceGLX::~NativeViewGLSurfaceGLX() { 687 NativeViewGLSurfaceGLX::~NativeViewGLSurfaceGLX() {
524 Destroy(); 688 Destroy();
525 } 689 }
526 690
527 PbufferGLSurfaceGLX::PbufferGLSurfaceGLX(const gfx::Size& size) 691 PbufferGLSurfaceGLX::PbufferGLSurfaceGLX(const gfx::Size& size)
528 : size_(size), 692 : size_(size),
529 config_(NULL), 693 config_(NULL),
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
607 771
608 void* PbufferGLSurfaceGLX::GetConfig() { 772 void* PbufferGLSurfaceGLX::GetConfig() {
609 return config_; 773 return config_;
610 } 774 }
611 775
612 PbufferGLSurfaceGLX::~PbufferGLSurfaceGLX() { 776 PbufferGLSurfaceGLX::~PbufferGLSurfaceGLX() {
613 Destroy(); 777 Destroy();
614 } 778 }
615 779
616 } // namespace gfx 780 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gl/gl_surface_glx.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698