| 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 11 matching lines...) Expand all Loading... |
| 22 #include "base/threading/thread.h" | 22 #include "base/threading/thread.h" |
| 23 #include "base/threading/thread_task_runner_handle.h" | 23 #include "base/threading/thread_task_runner_handle.h" |
| 24 #include "base/time/time.h" | 24 #include "base/time/time.h" |
| 25 #include "base/trace_event/trace_event.h" | 25 #include "base/trace_event/trace_event.h" |
| 26 #include "build/build_config.h" | 26 #include "build/build_config.h" |
| 27 #include "ui/events/platform/platform_event_source.h" | 27 #include "ui/events/platform/platform_event_source.h" |
| 28 #include "ui/gfx/x/x11_connection.h" | 28 #include "ui/gfx/x/x11_connection.h" |
| 29 #include "ui/gfx/x/x11_types.h" | 29 #include "ui/gfx/x/x11_types.h" |
| 30 #include "ui/gl/gl_bindings.h" | 30 #include "ui/gl/gl_bindings.h" |
| 31 #include "ui/gl/gl_implementation.h" | 31 #include "ui/gl/gl_implementation.h" |
| 32 #include "ui/gl/gl_visual_picker_glx.h" |
| 32 #include "ui/gl/sync_control_vsync_provider.h" | 33 #include "ui/gl/sync_control_vsync_provider.h" |
| 33 | 34 |
| 34 namespace gl { | 35 namespace gl { |
| 35 | 36 |
| 36 namespace { | 37 namespace { |
| 37 | 38 |
| 38 Display* g_display = nullptr; | 39 Display* g_display = nullptr; |
| 39 bool g_glx_context_create = false; | 40 bool g_glx_context_create = false; |
| 40 bool g_glx_create_context_robustness_supported = false; | 41 bool g_glx_create_context_robustness_supported = false; |
| 41 bool g_glx_create_context_profile_supported = false; | 42 bool g_glx_create_context_profile_supported = false; |
| 42 bool g_glx_create_context_profile_es2_supported = false; | 43 bool g_glx_create_context_profile_es2_supported = false; |
| 43 bool g_glx_texture_from_pixmap_supported = false; | 44 bool g_glx_texture_from_pixmap_supported = false; |
| 44 bool g_glx_oml_sync_control_supported = false; | 45 bool g_glx_oml_sync_control_supported = false; |
| 45 | 46 |
| 46 // Track support of glXGetMscRateOML separately from GLX_OML_sync_control as a | 47 // Track support of glXGetMscRateOML separately from GLX_OML_sync_control as a |
| 47 // whole since on some platforms (e.g. crosbug.com/34585), glXGetMscRateOML | 48 // 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. | 49 // always fails even though GLX_OML_sync_control is reported as being supported. |
| 49 bool g_glx_get_msc_rate_oml_supported = false; | 50 bool g_glx_get_msc_rate_oml_supported = false; |
| 50 | 51 |
| 51 bool g_glx_sgi_video_sync_supported = false; | 52 bool g_glx_sgi_video_sync_supported = false; |
| 52 | 53 |
| 54 // A 24-bit RGB visual and colormap to use when creating offscreen surfaces. |
| 55 Visual* g_visual = nullptr; |
| 56 int g_depth = CopyFromParent; |
| 57 Colormap g_colormap = CopyFromParent; |
| 58 |
| 53 GLXFBConfig GetConfigForWindow(Display* display, | 59 GLXFBConfig GetConfigForWindow(Display* display, |
| 54 gfx::AcceleratedWidget window) { | 60 gfx::AcceleratedWidget window) { |
| 55 DCHECK(window != 0); | 61 DCHECK(window != 0); |
| 56 | 62 |
| 57 // This code path is expensive, but we only take it when | 63 // This code path is expensive, but we only take it when |
| 58 // attempting to use GLX_ARB_create_context_robustness, in which | 64 // attempting to use GLX_ARB_create_context_robustness, in which |
| 59 // case we need a GLXFBConfig for the window in order to create a | 65 // case we need a GLXFBConfig for the window in order to create a |
| 60 // context for it. | 66 // context for it. |
| 61 // | 67 // |
| 62 // TODO(kbr): this is not a reliable code path. On platforms which | 68 // TODO(kbr): this is not a reliable code path. On platforms which |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 if (found) { | 108 if (found) { |
| 103 return configs.get()[i]; | 109 return configs.get()[i]; |
| 104 } | 110 } |
| 105 return nullptr; | 111 return nullptr; |
| 106 } | 112 } |
| 107 | 113 |
| 108 bool CreateDummyWindow(Display* display) { | 114 bool CreateDummyWindow(Display* display) { |
| 109 DCHECK(display); | 115 DCHECK(display); |
| 110 gfx::AcceleratedWidget parent_window = | 116 gfx::AcceleratedWidget parent_window = |
| 111 RootWindow(display, DefaultScreen(display)); | 117 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 = | 118 gfx::AcceleratedWidget window = |
| 116 XCreateWindow(display, parent_window, 0, 0, 1, 1, 0, CopyFromParent, | 119 XCreateWindow(display, parent_window, 0, 0, 1, 1, 0, CopyFromParent, |
| 117 InputOutput, CopyFromParent, 0, nullptr); | 120 InputOutput, CopyFromParent, 0, nullptr); |
| 118 if (!window) { | 121 if (!window) { |
| 119 LOG(ERROR) << "XCreateWindow failed"; | 122 LOG(ERROR) << "XCreateWindow failed"; |
| 120 return false; | 123 return false; |
| 121 } | 124 } |
| 122 GLXFBConfig config = GetConfigForWindow(display, window); | 125 GLXFBConfig config = GetConfigForWindow(display, window); |
| 123 GLXWindow glx_window = glXCreateWindow(display, config, window, nullptr); | 126 GLXWindow glx_window = glXCreateWindow(display, config, window, nullptr); |
| 124 if (!glx_window) { | 127 if (!glx_window) { |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 g_glx_create_context_profile_supported = | 418 g_glx_create_context_profile_supported = |
| 416 HasGLXExtension("GLX_ARB_create_context_profile"); | 419 HasGLXExtension("GLX_ARB_create_context_profile"); |
| 417 g_glx_create_context_profile_es2_supported = | 420 g_glx_create_context_profile_es2_supported = |
| 418 HasGLXExtension("GLX_ARB_create_context_es2_profile"); | 421 HasGLXExtension("GLX_ARB_create_context_es2_profile"); |
| 419 g_glx_texture_from_pixmap_supported = | 422 g_glx_texture_from_pixmap_supported = |
| 420 HasGLXExtension("GLX_EXT_texture_from_pixmap"); | 423 HasGLXExtension("GLX_EXT_texture_from_pixmap"); |
| 421 g_glx_oml_sync_control_supported = HasGLXExtension("GLX_OML_sync_control"); | 424 g_glx_oml_sync_control_supported = HasGLXExtension("GLX_OML_sync_control"); |
| 422 g_glx_get_msc_rate_oml_supported = g_glx_oml_sync_control_supported; | 425 g_glx_get_msc_rate_oml_supported = g_glx_oml_sync_control_supported; |
| 423 g_glx_sgi_video_sync_supported = HasGLXExtension("GLX_SGI_video_sync"); | 426 g_glx_sgi_video_sync_supported = HasGLXExtension("GLX_SGI_video_sync"); |
| 424 | 427 |
| 428 const XVisualInfo& visual_info = |
| 429 gl::GLVisualPickerGLX::GetInstance()->system_visual(); |
| 430 g_visual = visual_info.visual; |
| 431 g_depth = visual_info.depth; |
| 432 g_colormap = XCreateColormap(g_display, DefaultRootWindow(g_display), |
| 433 visual_info.visual, AllocNone); |
| 434 |
| 425 // We create a dummy unmapped window for both the main Display and the video | 435 // We create a dummy unmapped window for both the main Display and the video |
| 426 // sync Display so that the Nvidia driver can initialize itself before the | 436 // sync Display so that the Nvidia driver can initialize itself before the |
| 427 // sandbox is set up. | 437 // sandbox is set up. |
| 428 // Unfortunately some fds e.g. /dev/nvidia0 are cached per thread and because | 438 // 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 | 439 // we can't start threads before the sandbox is set up, these are accessed |
| 430 // through the broker process. See GpuProcessPolicy::InitGpuBrokerProcess. | 440 // through the broker process. See GpuProcessPolicy::InitGpuBrokerProcess. |
| 431 if (!CreateDummyWindow(g_display)) { | 441 if (!CreateDummyWindow(g_display)) { |
| 432 LOG(ERROR) << "CreateDummyWindow(g_display) failed"; | 442 LOG(ERROR) << "CreateDummyWindow(g_display) failed"; |
| 433 return false; | 443 return false; |
| 434 } | 444 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 486 return g_glx_oml_sync_control_supported; | 496 return g_glx_oml_sync_control_supported; |
| 487 } | 497 } |
| 488 | 498 |
| 489 void* GLSurfaceGLX::GetDisplay() { | 499 void* GLSurfaceGLX::GetDisplay() { |
| 490 return g_display; | 500 return g_display; |
| 491 } | 501 } |
| 492 | 502 |
| 493 GLSurfaceGLX::~GLSurfaceGLX() {} | 503 GLSurfaceGLX::~GLSurfaceGLX() {} |
| 494 | 504 |
| 495 NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::AcceleratedWidget window) | 505 NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::AcceleratedWidget window) |
| 496 : parent_window_(window), window_(0), glx_window_(0), config_(nullptr) {} | 506 : parent_window_(window), |
| 507 window_(0), |
| 508 glx_window_(0), |
| 509 config_(nullptr), |
| 510 visual_id_(CopyFromParent) {} |
| 497 | 511 |
| 498 GLXDrawable NativeViewGLSurfaceGLX::GetDrawableHandle() const { | 512 GLXDrawable NativeViewGLSurfaceGLX::GetDrawableHandle() const { |
| 499 return glx_window_; | 513 return glx_window_; |
| 500 } | 514 } |
| 501 | 515 |
| 502 bool NativeViewGLSurfaceGLX::Initialize(GLSurface::Format format) { | 516 bool NativeViewGLSurfaceGLX::Initialize(GLSurface::Format format) { |
| 503 XWindowAttributes attributes; | 517 XWindowAttributes attributes; |
| 504 if (!XGetWindowAttributes(g_display, parent_window_, &attributes)) { | 518 if (!XGetWindowAttributes(g_display, parent_window_, &attributes)) { |
| 505 LOG(ERROR) << "XGetWindowAttributes failed for window " << parent_window_ | 519 LOG(ERROR) << "XGetWindowAttributes failed for window " << parent_window_ |
| 506 << "."; | 520 << "."; |
| 507 return false; | 521 return false; |
| 508 } | 522 } |
| 509 size_ = gfx::Size(attributes.width, attributes.height); | 523 size_ = gfx::Size(attributes.width, attributes.height); |
| 524 visual_id_ = XVisualIDFromVisual(attributes.visual); |
| 510 // Create a child window, with a CopyFromParent visual (to avoid inducing | 525 // Create a child window, with a CopyFromParent visual (to avoid inducing |
| 511 // extra blits in the driver), that we can resize exactly in Resize(), | 526 // extra blits in the driver), that we can resize exactly in Resize(), |
| 512 // correctly ordered with GL, so that we don't have invalid transient states. | 527 // correctly ordered with GL, so that we don't have invalid transient states. |
| 513 // See https://crbug.com/326995. | 528 // See https://crbug.com/326995. |
| 514 XSetWindowAttributes swa; | 529 XSetWindowAttributes swa; |
| 515 memset(&swa, 0, sizeof(swa)); | 530 memset(&swa, 0, sizeof(swa)); |
| 516 swa.background_pixmap = 0; | 531 swa.background_pixmap = 0; |
| 517 swa.bit_gravity = NorthWestGravity; | 532 swa.bit_gravity = NorthWestGravity; |
| 518 window_ = XCreateWindow(g_display, parent_window_, 0, 0, size_.width(), | 533 window_ = XCreateWindow(g_display, parent_window_, 0, 0, size_.width(), |
| 519 size_.height(), 0, CopyFromParent, InputOutput, | 534 size_.height(), 0, CopyFromParent, InputOutput, |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 594 bool NativeViewGLSurfaceGLX::SupportsPostSubBuffer() { | 609 bool NativeViewGLSurfaceGLX::SupportsPostSubBuffer() { |
| 595 return g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer; | 610 return g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer; |
| 596 } | 611 } |
| 597 | 612 |
| 598 void* NativeViewGLSurfaceGLX::GetConfig() { | 613 void* NativeViewGLSurfaceGLX::GetConfig() { |
| 599 if (!config_) | 614 if (!config_) |
| 600 config_ = GetConfigForWindow(g_display, window_); | 615 config_ = GetConfigForWindow(g_display, window_); |
| 601 return config_; | 616 return config_; |
| 602 } | 617 } |
| 603 | 618 |
| 619 unsigned long NativeViewGLSurfaceGLX::GetCompatibilityKey() { |
| 620 return visual_id_; |
| 621 } |
| 622 |
| 604 gfx::SwapResult NativeViewGLSurfaceGLX::PostSubBuffer(int x, | 623 gfx::SwapResult NativeViewGLSurfaceGLX::PostSubBuffer(int x, |
| 605 int y, | 624 int y, |
| 606 int width, | 625 int width, |
| 607 int height) { | 626 int height) { |
| 608 DCHECK(g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer); | 627 DCHECK(g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer); |
| 609 glXCopySubBufferMESA(g_display, GetDrawableHandle(), x, y, width, height); | 628 glXCopySubBufferMESA(g_display, GetDrawableHandle(), x, y, width, height); |
| 610 return gfx::SwapResult::SWAP_ACK; | 629 return gfx::SwapResult::SWAP_ACK; |
| 611 } | 630 } |
| 612 | 631 |
| 613 gfx::VSyncProvider* NativeViewGLSurfaceGLX::GetVSyncProvider() { | 632 gfx::VSyncProvider* NativeViewGLSurfaceGLX::GetVSyncProvider() { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 634 const gfx::Size& size) | 653 const gfx::Size& size) |
| 635 : size_(size), config_(nullptr), window_(0), glx_window_(0) { | 654 : size_(size), config_(nullptr), window_(0), glx_window_(0) { |
| 636 // Ensure that we don't create a window with zero size. | 655 // Ensure that we don't create a window with zero size. |
| 637 if (size_.GetArea() == 0) | 656 if (size_.GetArea() == 0) |
| 638 size_.SetSize(1, 1); | 657 size_.SetSize(1, 1); |
| 639 } | 658 } |
| 640 | 659 |
| 641 bool UnmappedNativeViewGLSurfaceGLX::Initialize(GLSurface::Format format) { | 660 bool UnmappedNativeViewGLSurfaceGLX::Initialize(GLSurface::Format format) { |
| 642 DCHECK(!window_); | 661 DCHECK(!window_); |
| 643 | 662 |
| 644 gfx::AcceleratedWidget parent_window = | 663 gfx::AcceleratedWidget parent_window = DefaultRootWindow(g_display); |
| 645 RootWindow(g_display, DefaultScreen(g_display)); | |
| 646 | 664 |
| 647 // We create a window with CopyFromParent visual so that we have the same | 665 XSetWindowAttributes attrs; |
| 648 // visual as NativeViewGLSurfaceGLX (i.e. same GLXFBConfig), to ensure | 666 attrs.border_pixel = 0; |
| 649 // contexts are compatible and can be made current with either. | 667 attrs.colormap = g_colormap; |
| 650 window_ = XCreateWindow(g_display, parent_window, 0, 0, size_.width(), | 668 window_ = XCreateWindow(g_display, parent_window, 0, 0, size_.width(), |
| 651 size_.height(), 0, CopyFromParent, InputOutput, | 669 size_.height(), 0, g_depth, InputOutput, g_visual, |
| 652 CopyFromParent, 0, nullptr); | 670 CWBorderPixel | CWColormap, &attrs); |
| 653 GetConfig(); | 671 GetConfig(); |
| 654 DCHECK(config_); | 672 DCHECK(config_); |
| 655 glx_window_ = glXCreateWindow(g_display, config_, window_, NULL); | 673 glx_window_ = glXCreateWindow(g_display, config_, window_, NULL); |
| 656 return window_ != 0; | 674 return window_ != 0; |
| 657 } | 675 } |
| 658 | 676 |
| 659 void UnmappedNativeViewGLSurfaceGLX::Destroy() { | 677 void UnmappedNativeViewGLSurfaceGLX::Destroy() { |
| 660 config_ = nullptr; | 678 config_ = nullptr; |
| 661 if (glx_window_) { | 679 if (glx_window_) { |
| 662 glXDestroyWindow(g_display, glx_window_); | 680 glXDestroyWindow(g_display, glx_window_); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 684 void* UnmappedNativeViewGLSurfaceGLX::GetHandle() { | 702 void* UnmappedNativeViewGLSurfaceGLX::GetHandle() { |
| 685 return reinterpret_cast<void*>(glx_window_); | 703 return reinterpret_cast<void*>(glx_window_); |
| 686 } | 704 } |
| 687 | 705 |
| 688 void* UnmappedNativeViewGLSurfaceGLX::GetConfig() { | 706 void* UnmappedNativeViewGLSurfaceGLX::GetConfig() { |
| 689 if (!config_) | 707 if (!config_) |
| 690 config_ = GetConfigForWindow(g_display, window_); | 708 config_ = GetConfigForWindow(g_display, window_); |
| 691 return config_; | 709 return config_; |
| 692 } | 710 } |
| 693 | 711 |
| 712 unsigned long UnmappedNativeViewGLSurfaceGLX::GetCompatibilityKey() { |
| 713 return XVisualIDFromVisual(g_visual); |
| 714 } |
| 715 |
| 694 UnmappedNativeViewGLSurfaceGLX::~UnmappedNativeViewGLSurfaceGLX() { | 716 UnmappedNativeViewGLSurfaceGLX::~UnmappedNativeViewGLSurfaceGLX() { |
| 695 Destroy(); | 717 Destroy(); |
| 696 } | 718 } |
| 697 | 719 |
| 698 } // namespace gl | 720 } // namespace gl |
| OLD | NEW |