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

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: Add missing OVERRIDE 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 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 if (initialized) 309 if (initialized)
309 return true; 310 return true;
310 311
311 // http://crbug.com/245466 312 // http://crbug.com/245466
312 setenv("force_s3tc_enable", "true", 1); 313 setenv("force_s3tc_enable", "true", 1);
313 314
314 // SGIVideoSyncProviderShim (if instantiated) will issue X commands on 315 // SGIVideoSyncProviderShim (if instantiated) will issue X commands on
315 // it's own thread. 316 // it's own thread.
316 XInitThreads(); 317 XInitThreads();
317 318
319 #if defined(TOOLKIT_GTK)
320 // Be sure to use the X display handle and not the GTK display handle if this
321 // is the GPU process.
322 if (base::MessageLoop::current()->type() == base::MessageLoop::TYPE_GPU)
323 g_display = base::MessagePumpX11::GetDefaultXDisplay();
324 else
325 g_display = base::MessagePumpForUI::GetDefaultXDisplay();
326 #else
318 g_display = base::MessagePumpForUI::GetDefaultXDisplay(); 327 g_display = base::MessagePumpForUI::GetDefaultXDisplay();
328 #endif
329
319 if (!g_display) { 330 if (!g_display) {
320 LOG(ERROR) << "XOpenDisplay failed."; 331 LOG(ERROR) << "XOpenDisplay failed.";
321 return false; 332 return false;
322 } 333 }
323 334
324 int major, minor; 335 int major, minor;
325 if (!glXQueryVersion(g_display, &major, &minor)) { 336 if (!glXQueryVersion(g_display, &major, &minor)) {
326 LOG(ERROR) << "glxQueryVersion failed"; 337 LOG(ERROR) << "glxQueryVersion failed";
327 return false; 338 return false;
328 } 339 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 bool GLSurfaceGLX::IsOMLSyncControlSupported() { 392 bool GLSurfaceGLX::IsOMLSyncControlSupported() {
382 return g_glx_oml_sync_control_supported; 393 return g_glx_oml_sync_control_supported;
383 } 394 }
384 395
385 void* GLSurfaceGLX::GetDisplay() { 396 void* GLSurfaceGLX::GetDisplay() {
386 return g_display; 397 return g_display;
387 } 398 }
388 399
389 GLSurfaceGLX::~GLSurfaceGLX() {} 400 GLSurfaceGLX::~GLSurfaceGLX() {}
390 401
402 #if defined(TOOLKIT_GTK)
403 // A mechanism for forwarding XExpose events from one window to another.
404 // Because in the workaround for http://crbug.com/145600 the child window
405 // is placed on top of the parent window, only the child window will receive
406 // all expose events. These need to be forwared to the parent window to inform
407 // it that it should paint.
408 class XExposeEventForwarder : public base::MessagePumpObserver {
piman 2013/09/11 23:05:09 nit: move this to an anonoymous namespace.
ccameron 2013/09/12 01:37:13 Done.
409 public:
410 XExposeEventForwarder() {
411 base::MessagePumpX11::Current()->AddObserver(this);
412 }
413 ~XExposeEventForwarder() {
414 base::MessagePumpX11::Current()->RemoveObserver(this);
piman 2013/09/11 23:05:09 If this is a lazy instance, the destructor will ru
ccameron 2013/09/12 01:37:13 Good catch, thanks. Moved to the Add/RemoveParentC
415 }
416
417 void AddParentChildPair(gfx::AcceleratedWidget parent_window,
418 gfx::AcceleratedWidget child_window) {
419 DCHECK(child_to_parent_map_.find(child_window) ==
420 child_to_parent_map_.end());
421 child_to_parent_map_.insert(std::make_pair(
422 child_window, parent_window));
423 }
424 void RemoveParentChildPair(gfx::AcceleratedWidget parent_window,
425 gfx::AcceleratedWidget child_window) {
426 DCHECK(child_to_parent_map_.find(child_window) !=
427 child_to_parent_map_.end());
428 child_to_parent_map_.erase(child_window);
429 }
430
431 private:
432 virtual base::EventStatus WillProcessEvent(
433 const base::NativeEvent& xevent) OVERRIDE {
434 if (xevent->type != Expose)
435 return base::EVENT_CONTINUE;
436
437 WindowMap::const_iterator found = child_to_parent_map_.find(
438 xevent->xexpose.window);
439 if (found == child_to_parent_map_.end())
440 return base::EVENT_CONTINUE;
441
442 gfx::AcceleratedWidget target_window = found->second;
443 XEvent forwarded_event = *xevent;
444 forwarded_event.xexpose.window = target_window;
445 XSendEvent(g_display, target_window, False, ExposureMask,
446 &forwarded_event);
447 return base::EVENT_CONTINUE;
448 }
449 virtual void DidProcessEvent(const base::NativeEvent& xevent) {
450 }
451
452 typedef std::map<gfx::AcceleratedWidget, gfx::AcceleratedWidget> WindowMap;
453 WindowMap child_to_parent_map_;
454 };
455
456 static base::LazyInstance<XExposeEventForwarder> g_xexpose_event_forwarder =
457 LAZY_INSTANCE_INITIALIZER;
458
459 bool NativeViewGLSurfaceGLX::SetBackbufferAllocation(bool allocated) {
460 if (allocated)
461 return CreateChildWindow();
462 else
463 DestroyChildWindow();
464 return true;
465 }
466
467 bool NativeViewGLSurfaceGLX::CreateChildWindow() {
468 if (child_window_)
469 return true;
470
471 XWindowAttributes attributes;
472 if (!XGetWindowAttributes(g_display, parent_window_, &attributes)) {
piman 2013/09/11 23:05:09 Could we cache this? It requires a round trip to X
ccameron 2013/09/12 01:37:13 Actually, we can just use CopyFromParent and avoid
473 LOG(ERROR) << "XGetWindowAttributes failed for window " << parent_window_
474 << ".";
475 return false;
476 }
477
478 XSetWindowAttributes set_window_attributes;
479 set_window_attributes.event_mask = ExposureMask;
480 child_window_ = XCreateWindow(
481 g_display, parent_window_, 0, 0, attributes.width, attributes.height, 0,
482 attributes.depth, InputOutput, attributes.visual, CWEventMask,
483 &set_window_attributes);
484 g_xexpose_event_forwarder.Pointer()->AddParentChildPair(
485 parent_window_, child_window_);
486
487 XMapWindow(g_display, child_window_);
488 XFlush(g_display);
489
490 // If the dummy window was current, make the child window current now.
491 if (dummy_window_ == glXGetCurrentDrawable())
492 glXMakeCurrent(g_display, child_window_, glXGetCurrentContext());
493
494 return true;
495 }
496
497 void NativeViewGLSurfaceGLX::DestroyChildWindow() {
498 if (!child_window_)
499 return;
500
piman 2013/09/11 23:05:09 Do we need to glXMakeCurrent the dummy_window_ her
ccameron 2013/09/12 01:37:13 Doesn't look like it. And I may make dummy_window_
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 #endif
393 config_(NULL) { 515 config_(NULL) {
394 } 516 }
395 517
518 gfx::AcceleratedWidget NativeViewGLSurfaceGLX::GetDrawableHandle() const {
519 #if defined(TOOLKIT_GTK)
520 if (child_window_)
521 return child_window_;
522 return dummy_window_;
523 #else
524 return parent_window_;
525 #endif
526 }
527
396 bool NativeViewGLSurfaceGLX::Initialize() { 528 bool NativeViewGLSurfaceGLX::Initialize() {
397 XWindowAttributes attributes; 529 XWindowAttributes attributes;
398 if (!XGetWindowAttributes(g_display, window_, &attributes)) { 530 if (!XGetWindowAttributes(g_display, parent_window_, &attributes)) {
399 LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << "."; 531 LOG(ERROR) << "XGetWindowAttributes failed for window " << parent_window_
532 << ".";
400 return false; 533 return false;
401 } 534 }
402 size_ = gfx::Size(attributes.width, attributes.height); 535 size_ = gfx::Size(attributes.width, attributes.height);
403 536
537 gfx::AcceleratedWidget window_for_vsync = parent_window_;
538
539 #if defined(TOOLKIT_GTK)
540 CreateChildWindow();
541 dummy_window_ = XCreateWindow(
542 g_display, parent_window_, 0, 0, 1, 1, 0, attributes.depth, InputOutput,
543 attributes.visual, 0, NULL);
544 window_for_vsync = dummy_window_;
545 #endif
546
404 if (g_glx_oml_sync_control_supported) 547 if (g_glx_oml_sync_control_supported)
405 vsync_provider_.reset(new OMLSyncControlVSyncProvider(window_)); 548 vsync_provider_.reset(new OMLSyncControlVSyncProvider(window_for_vsync));
406 else if (g_glx_sgi_video_sync_supported) 549 else if (g_glx_sgi_video_sync_supported)
407 vsync_provider_.reset(new SGIVideoSyncVSyncProvider(window_)); 550 vsync_provider_.reset(new SGIVideoSyncVSyncProvider(window_for_vsync));
408 551
409 return true; 552 return true;
410 } 553 }
411 554
412 void NativeViewGLSurfaceGLX::Destroy() { 555 void NativeViewGLSurfaceGLX::Destroy() {
556 #if defined(TOOLKIT_GTK)
557 if (dummy_window_)
558 XDestroyWindow(g_display, dummy_window_);
559 dummy_window_ = 0;
560
561 DestroyChildWindow();
562 #endif
413 } 563 }
414 564
415 bool NativeViewGLSurfaceGLX::Resize(const gfx::Size& size) { 565 bool NativeViewGLSurfaceGLX::Resize(const gfx::Size& size) {
566 #if defined(TOOLKIT_GTK)
567 if (child_window_) {
568 XResizeWindow(g_display, child_window_, size.width(), size.height());
569 XFlush(g_display);
570 }
571 #endif
416 size_ = size; 572 size_ = size;
417 return true; 573 return true;
418 } 574 }
419 575
420 bool NativeViewGLSurfaceGLX::IsOffscreen() { 576 bool NativeViewGLSurfaceGLX::IsOffscreen() {
421 return false; 577 return false;
422 } 578 }
423 579
424 bool NativeViewGLSurfaceGLX::SwapBuffers() { 580 bool NativeViewGLSurfaceGLX::SwapBuffers() {
425 glXSwapBuffers(g_display, window_); 581 glXSwapBuffers(g_display, GetDrawableHandle());
426 return true; 582 return true;
427 } 583 }
428 584
429 gfx::Size NativeViewGLSurfaceGLX::GetSize() { 585 gfx::Size NativeViewGLSurfaceGLX::GetSize() {
430 return size_; 586 return size_;
431 } 587 }
432 588
433 void* NativeViewGLSurfaceGLX::GetHandle() { 589 void* NativeViewGLSurfaceGLX::GetHandle() {
434 return reinterpret_cast<void*>(window_); 590 return reinterpret_cast<void*>(GetDrawableHandle());
435 } 591 }
436 592
437 std::string NativeViewGLSurfaceGLX::GetExtensions() { 593 std::string NativeViewGLSurfaceGLX::GetExtensions() {
438 std::string extensions = GLSurface::GetExtensions(); 594 std::string extensions = GLSurface::GetExtensions();
439 if (gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer) { 595 if (gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer) {
440 extensions += extensions.empty() ? "" : " "; 596 extensions += extensions.empty() ? "" : " ";
441 extensions += "GL_CHROMIUM_post_sub_buffer"; 597 extensions += "GL_CHROMIUM_post_sub_buffer";
442 } 598 }
443 return extensions; 599 return extensions;
444 } 600 }
445 601
446 void* NativeViewGLSurfaceGLX::GetConfig() { 602 void* NativeViewGLSurfaceGLX::GetConfig() {
447 if (!config_) { 603 if (!config_) {
448 // This code path is expensive, but we only take it when 604 // This code path is expensive, but we only take it when
449 // attempting to use GLX_ARB_create_context_robustness, in which 605 // attempting to use GLX_ARB_create_context_robustness, in which
450 // case we need a GLXFBConfig for the window in order to create a 606 // case we need a GLXFBConfig for the window in order to create a
451 // context for it. 607 // context for it.
452 // 608 //
453 // TODO(kbr): this is not a reliable code path. On platforms which 609 // TODO(kbr): this is not a reliable code path. On platforms which
454 // support it, we should use glXChooseFBConfig in the browser 610 // support it, we should use glXChooseFBConfig in the browser
455 // process to choose the FBConfig and from there the X Visual to 611 // 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 612 // use when creating the window in the first place. Then we can
457 // pass that FBConfig down rather than attempting to reconstitute 613 // pass that FBConfig down rather than attempting to reconstitute
458 // it. 614 // it.
459 615
460 XWindowAttributes attributes; 616 XWindowAttributes attributes;
461 if (!XGetWindowAttributes( 617 if (!XGetWindowAttributes(
462 g_display, 618 g_display,
463 window_, 619 parent_window_,
464 &attributes)) { 620 &attributes)) {
465 LOG(ERROR) << "XGetWindowAttributes failed for window " << 621 LOG(ERROR) << "XGetWindowAttributes failed for window " <<
466 window_ << "."; 622 parent_window_ << ".";
467 return NULL; 623 return NULL;
468 } 624 }
469 625
470 int visual_id = XVisualIDFromVisual(attributes.visual); 626 int visual_id = XVisualIDFromVisual(attributes.visual);
471 627
472 int num_elements = 0; 628 int num_elements = 0;
473 scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> configs( 629 scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> configs(
474 glXGetFBConfigs(g_display, 630 glXGetFBConfigs(g_display,
475 DefaultScreen(g_display), 631 DefaultScreen(g_display),
476 &num_elements)); 632 &num_elements));
(...skipping 23 matching lines...) Expand all
500 config_ = configs.get()[i]; 656 config_ = configs.get()[i];
501 } 657 }
502 } 658 }
503 659
504 return config_; 660 return config_;
505 } 661 }
506 662
507 bool NativeViewGLSurfaceGLX::PostSubBuffer( 663 bool NativeViewGLSurfaceGLX::PostSubBuffer(
508 int x, int y, int width, int height) { 664 int x, int y, int width, int height) {
509 DCHECK(gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer); 665 DCHECK(gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer);
510 glXCopySubBufferMESA(g_display, window_, x, y, width, height); 666 glXCopySubBufferMESA(g_display, GetDrawableHandle(), x, y, width, height);
511 return true; 667 return true;
512 } 668 }
513 669
514 VSyncProvider* NativeViewGLSurfaceGLX::GetVSyncProvider() { 670 VSyncProvider* NativeViewGLSurfaceGLX::GetVSyncProvider() {
515 return vsync_provider_.get(); 671 return vsync_provider_.get();
516 } 672 }
517 673
518 NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX() 674 NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX()
519 : window_(0), 675 : parent_window_(0),
676 #if defined(TOOLKIT_GTK)
677 child_window_(0),
678 dummy_window_(0),
679 #endif
520 config_(NULL) { 680 config_(NULL) {
521 } 681 }
522 682
523 NativeViewGLSurfaceGLX::~NativeViewGLSurfaceGLX() { 683 NativeViewGLSurfaceGLX::~NativeViewGLSurfaceGLX() {
524 Destroy(); 684 Destroy();
525 } 685 }
526 686
527 PbufferGLSurfaceGLX::PbufferGLSurfaceGLX(const gfx::Size& size) 687 PbufferGLSurfaceGLX::PbufferGLSurfaceGLX(const gfx::Size& size)
528 : size_(size), 688 : size_(size),
529 config_(NULL), 689 config_(NULL),
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
607 767
608 void* PbufferGLSurfaceGLX::GetConfig() { 768 void* PbufferGLSurfaceGLX::GetConfig() {
609 return config_; 769 return config_;
610 } 770 }
611 771
612 PbufferGLSurfaceGLX::~PbufferGLSurfaceGLX() { 772 PbufferGLSurfaceGLX::~PbufferGLSurfaceGLX() {
613 Destroy(); 773 Destroy();
614 } 774 }
615 775
616 } // namespace gfx 776 } // 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