Patch for Intel GPU's, but doesn't seem to work on NVIDIA/ATI cards Thanks to Saikrishna Arcot (saiarcot895) Originally from https://raw.githubusercontent.com/saiarcot895/chromium-ubuntu-build/master/debian/patches/enable_vaapi_on_linux.diff The patch for bpf_gpu_policy_linux.cc initially came from https://codereview.chromium.org/15955009/diff/92001/content/common/sandbox_linux/bpf_gpu_policy_linux.cc. diff -aur chromium-53.0.2785.89.orig/content/common/sandbox_linux/bpf_gpu_policy_linux.cc chromium-53.0.2785.89/content/common/sandbox_linux/bpf_gpu_policy_linux.cc --- chromium-53.0.2785.89.orig/content/common/sandbox_linux/bpf_gpu_policy_linux.cc 2016-08-31 15:03:31.000000000 -0700 +++ chromium-53.0.2785.89/content/common/sandbox_linux/bpf_gpu_policy_linux.cc 2016-09-02 01:35:26.224998192 -0700 @@ -23,6 +23,12 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "build/build_config.h" + +#if !defined(__arm__) +// Auto-generated for dlopen libva libraries +#include "content/common/va_stubs.h" +#endif + #include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h" #include "content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h" #include "content/common/set_process_title.h" @@ -34,6 +40,14 @@ #include "sandbox/linux/syscall_broker/broker_process.h" #include "sandbox/linux/system_headers/linux_syscalls.h" +#if !defined(__arm__) +#include "third_party/libva/va/va.h" +#include "third_party/libva/va/va_x11.h" +#if defined(USE_OZONE) +#include "third_party/libva/va/wayland/va_wayland.h" +#endif +#endif + using sandbox::arch_seccomp_data; using sandbox::bpf_dsl::Allow; using sandbox::bpf_dsl::ResultExpr; @@ -42,6 +56,16 @@ using sandbox::syscall_broker::BrokerProcess; using sandbox::SyscallSets; +#if !defined(__arm__) +using content_common::kModuleVa; +using content_common::kModuleVa_x11; +#if defined(USE_OZONE) +using content_common::kModuleVa_drm; +#endif +using content_common::InitializeStubs; +using content_common::StubPathMap; +#endif + namespace content { namespace { @@ -96,7 +120,7 @@ bool IsAcceleratedVaapiVideoEncodeEnabled() { bool accelerated_encode_enabled = false; -#if defined(OS_CHROMEOS) +#if defined(OS_CHROMEOS) || defined(OS_LINUX) const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); accelerated_encode_enabled = @@ -297,32 +321,72 @@ GpuBrokerProcessPolicy::Create, std::vector()); // No extra files in whitelist. +#if !defined(__arm__) if (IsArchitectureX86_64() || IsArchitectureI386()) { // Accelerated video dlopen()'s some shared objects // inside the sandbox, so preload them now. if (IsAcceleratedVaapiVideoEncodeEnabled() || IsAcceleratedVideoDecodeEnabled()) { - const char* I965DrvVideoPath = NULL; - const char* I965HybridDrvVideoPath = NULL; - - if (IsArchitectureX86_64()) { - I965DrvVideoPath = "/usr/lib64/va/drivers/i965_drv_video.so"; - I965HybridDrvVideoPath = "/usr/lib64/va/drivers/hybrid_drv_video.so"; - } else if (IsArchitectureI386()) { - I965DrvVideoPath = "/usr/lib/va/drivers/i965_drv_video.so"; + VLOG(1) << "Attempting to enable hardware video acceleration."; + StubPathMap paths; + paths[kModuleVa].push_back("libva.so.1"); + paths[kModuleVa_x11].push_back("libva-x11.so.1"); +#if defined(USE_OZONE) + paths[kModuleVa_drm].push_back("libva-drm.so.1"); +#endif + if (!InitializeStubs(paths)) { + LOG(WARNING) << "Failed to initialize stubs"; + return true; } - dlopen(I965DrvVideoPath, RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE); - if (I965HybridDrvVideoPath) - dlopen(I965HybridDrvVideoPath, RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE); - dlopen("libva.so.1", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE); + // libva drivers won't get loaded even above two libraries get dlopened. + // Thus, libva calls will fail after post sandbox stage. + // + // To get the va driver loaded before sandboxing, upstream simply dlopen + // the hard-coded va driver path because ChromeOS is the only platform + // that Google want to support libva. + // + // While generic linux distros ship va driver as anywhere they want. + // Fortunately, the va driver will be loadded when vaInitialize() get + // called. + // So the following code is to call vaInitialize() before sandboxing. + + VADisplay va_display = NULL; #if defined(USE_OZONE) - dlopen("libva-drm.so.1", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE); -#elif defined(USE_X11) - dlopen("libva-x11.so.1", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE); + struct wl_display* wayland_display = wl_display_connect(NULL); + if (wayland_display) { + va_display = vaGetDisplayWl(wayland_display); + if (!vaDisplayIsValid(va_display)) { + LOG(WARNING) << "Failed to call vaGetDisplayWl()"; + va_display = NULL; + } + } else { + LOG(WARNING) << "Failed to find Wayland display"; + } +#endif + + if (!va_display) { + Display* x_display = XOpenDisplay(NULL); + if (!x_display) { + LOG(WARNING) << "Failed to find X-Display"; + return true; + } + va_display = vaGetDisplay(x_display); + if (!vaDisplayIsValid(va_display)) { + LOG(WARNING) << "Failed to call vaGetDisplay()"; + return true; + } + } + + int major_version, minor_version; + if (vaInitialize(va_display, &major_version, &minor_version) + != VA_STATUS_SUCCESS) { + LOG(WARNING) << "Failed to call vaInitialize()"; + return true; + } + } // end of IsAcceleratedVaapiVideoEncodeEnabled() || IsAcceleratedVideoDecodeEnabled() + } // end of IsArchitectureX86_64() || IsArchitectureI386() #endif - } - } return true; }