379 lines
15 KiB
Diff
379 lines
15 KiB
Diff
From 53b93dfe87fd10cced5d2a2a63072dfc7a2af6e4 Mon Sep 17 00:00:00 2001
|
|
From: Daniel Charles <daniel.charles@intel.com>
|
|
Date: Fri, 28 Jul 2017 16:31:47 -0700
|
|
Subject: [PATCH] Enable VAVDA, VAVEA and VAJDA on linux with VAAPI only
|
|
|
|
This patch contains all the changes necessary to use VA-API along with
|
|
vaapi-driver to run all media use cases supported with hardware acceleration.
|
|
|
|
It is intended to remain as experimental accessible from chrome://flags on linux.
|
|
It requires libva/intel-vaapi-driver to be installed on the system path where
|
|
chrome is executed. Other drivers could be tested if available. Flags are
|
|
kept independent for linux, where this feature has to be enabled before
|
|
actually using it. This should not change how other OSes use the flags
|
|
already, the new flags will show at the buttom on the section of unavailable
|
|
experiments
|
|
|
|
The changes cover a range of compiler pre-processor flags to enable the stack.
|
|
It moves the presandbox operations to the vaapi_wrapper class as the hook function
|
|
is available there. vaInit will open driver on the correct installed folder.
|
|
|
|
chrome flags consolidtation into only two flags for linux. Mjpeg and accelerated
|
|
video are used. The other flags are kept for ChromeOS and other OSes.
|
|
|
|
Developer testing was made on skylake hardware, ChromeOS and Ubuntu.
|
|
|
|
BUG=NONE
|
|
TEST="subjective testing with VAVDA,VAVEA and VAJDA, autotest for encoder"
|
|
TEST="and decoder hardware accelerated"
|
|
TEST="have libva/intel-vaapi-driver installed and not installed in the system"
|
|
TEST="repeat on different hardware families"
|
|
R=posciak@chromium.org
|
|
R=kcwu@chromium.org
|
|
|
|
Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
|
|
Change-Id: Ifbbf5c9e5221a8b5733fc6d4d0cf984a1f103171
|
|
Signed-off-by: Daniel Charles <daniel.charles@intel.com>
|
|
---
|
|
|
|
Index: dev/chrome/browser/about_flags.cc
|
|
===================================================================
|
|
--- chrome/browser/about_flags.cc
|
|
+++ chrome/browser/about_flags.cc
|
|
@@ -1772,7 +1772,7 @@ const FeatureEntry kFeatureEntries[] = {
|
|
"disable-accelerated-video-decode",
|
|
flag_descriptions::kAcceleratedVideoDecodeName,
|
|
flag_descriptions::kAcceleratedVideoDecodeDescription,
|
|
- kOsMac | kOsWin | kOsCrOS | kOsAndroid,
|
|
+ kOsAll,
|
|
SINGLE_DISABLE_VALUE_TYPE(switches::kDisableAcceleratedVideoDecode),
|
|
},
|
|
{
|
|
@@ -2245,10 +2245,10 @@ const FeatureEntry kFeatureEntries[] = {
|
|
FEATURE_VALUE_TYPE(service_manager::features::kXRSandbox)},
|
|
#endif // !defined(OS_ANDROID)
|
|
#endif // ENABLE_VR
|
|
-#if defined(OS_CHROMEOS)
|
|
+#if defined(OS_LINUX) && !defined(OS_ANDROID)
|
|
{"disable-accelerated-mjpeg-decode",
|
|
flag_descriptions::kAcceleratedMjpegDecodeName,
|
|
- flag_descriptions::kAcceleratedMjpegDecodeDescription, kOsCrOS,
|
|
+ flag_descriptions::kAcceleratedMjpegDecodeDescription, kOsCrOS | kOsLinux,
|
|
SINGLE_DISABLE_VALUE_TYPE(switches::kDisableAcceleratedMjpegDecode)},
|
|
#endif // OS_CHROMEOS
|
|
{"system-keyboard-lock", flag_descriptions::kSystemKeyboardLockName,
|
|
Index: dev/chrome/browser/flag_descriptions.cc
|
|
===================================================================
|
|
--- chrome/browser/flag_descriptions.cc
|
|
+++ chrome/browser/flag_descriptions.cc
|
|
@@ -3110,9 +3110,7 @@ const char kMacSystemMediaPermissionsInf
|
|
|
|
#endif
|
|
|
|
-// Chrome OS -------------------------------------------------------------------
|
|
-
|
|
-#if defined(OS_CHROMEOS)
|
|
+#if defined(OS_LINUX) && !defined(OS_ANDROID)
|
|
|
|
const char kAcceleratedMjpegDecodeName[] =
|
|
"Hardware-accelerated mjpeg decode for captured frame";
|
|
@@ -3120,6 +3118,12 @@ const char kAcceleratedMjpegDecodeDescri
|
|
"Enable hardware-accelerated mjpeg decode for captured frame where "
|
|
"available.";
|
|
|
|
+#endif
|
|
+
|
|
+// Chrome OS -------------------------------------------------------------------
|
|
+
|
|
+#if defined(OS_CHROMEOS)
|
|
+
|
|
const char kAggregatedMlAppRankingName[] = "Rank suggested apps with ML.";
|
|
const char kAggregatedMlAppRankingDescription[] =
|
|
"Use the aggregated ML model to rank the suggested apps.";
|
|
Index: dev/chrome/browser/flag_descriptions.h
|
|
===================================================================
|
|
--- chrome/browser/flag_descriptions.h
|
|
+++ chrome/browser/flag_descriptions.h
|
|
@@ -1838,13 +1838,17 @@ extern const char kPermissionPromptPersi
|
|
|
|
#endif // defined(OS_MACOSX)
|
|
|
|
-// Chrome OS ------------------------------------------------------------------
|
|
-
|
|
-#if defined(OS_CHROMEOS)
|
|
+#if defined(OS_LINUX) && !defined(OS_ANDROID)
|
|
|
|
extern const char kAcceleratedMjpegDecodeName[];
|
|
extern const char kAcceleratedMjpegDecodeDescription[];
|
|
|
|
+#endif
|
|
+
|
|
+// Chrome OS ------------------------------------------------------------------
|
|
+
|
|
+#if defined(OS_CHROMEOS)
|
|
+
|
|
extern const char kAggregatedMlAppRankingName[];
|
|
extern const char kAggregatedMlAppRankingDescription[];
|
|
|
|
Index: dev/content/gpu/BUILD.gn
|
|
===================================================================
|
|
--- content/gpu/BUILD.gn
|
|
+++ content/gpu/BUILD.gn
|
|
@@ -6,6 +6,7 @@ import("//build/config/jumbo.gni")
|
|
import("//build/config/ui.gni")
|
|
import("//gpu/vulkan/features.gni")
|
|
import("//media/media_options.gni")
|
|
+import("//media/gpu/args.gni")
|
|
import("//ui/ozone/ozone.gni")
|
|
|
|
# See //content/BUILD.gn for how this works.
|
|
@@ -128,4 +129,8 @@ target(link_target_type, "gpu_sources")
|
|
(!is_chromecast || is_cast_desktop_build)) {
|
|
configs += [ "//build/config/linux/dri" ]
|
|
}
|
|
+
|
|
+ if (is_desktop_linux && use_vaapi) {
|
|
+ public_configs = [ "//build/config/linux/libva" ]
|
|
+ }
|
|
}
|
|
Index: dev/gpu/config/software_rendering_list.json
|
|
===================================================================
|
|
--- gpu/config/software_rendering_list.json
|
|
+++ gpu/config/software_rendering_list.json
|
|
@@ -333,17 +333,6 @@
|
|
]
|
|
},
|
|
{
|
|
- "id": 48,
|
|
- "description": "Accelerated video decode is unavailable on Linux",
|
|
- "cr_bugs": [137247],
|
|
- "os": {
|
|
- "type": "linux"
|
|
- },
|
|
- "features": [
|
|
- "accelerated_video_decode"
|
|
- ]
|
|
- },
|
|
- {
|
|
"id": 50,
|
|
"description": "Disable VMware software renderer on older Mesa",
|
|
"cr_bugs": [145531, 332596, 571899, 629434],
|
|
Index: dev/media/base/media_switches.cc
|
|
===================================================================
|
|
--- media/base/media_switches.cc
|
|
+++ media/base/media_switches.cc
|
|
@@ -619,7 +619,7 @@ bool IsVideoCaptureAcceleratedJpegDecodi
|
|
switches::kUseFakeMjpegDecodeAccelerator)) {
|
|
return true;
|
|
}
|
|
-#if defined(OS_CHROMEOS)
|
|
+#if defined(OS_LINUX) && !defined(OS_ANDROID)
|
|
return true;
|
|
#endif
|
|
return false;
|
|
Index: dev/media/gpu/BUILD.gn
|
|
===================================================================
|
|
--- media/gpu/BUILD.gn
|
|
+++ media/gpu/BUILD.gn
|
|
@@ -541,6 +541,7 @@ if (use_v4l2_codec || use_vaapi || is_ma
|
|
if (use_ozone) {
|
|
deps += [ "//ui/ozone" ]
|
|
}
|
|
+ public_configs = [ "//build/config/linux/libva" ]
|
|
}
|
|
}
|
|
|
|
Index: dev/media/gpu/gpu_video_decode_accelerator_factory.cc
|
|
===================================================================
|
|
--- media/gpu/gpu_video_decode_accelerator_factory.cc
|
|
+++ media/gpu/gpu_video_decode_accelerator_factory.cc
|
|
@@ -185,6 +185,8 @@ GpuVideoDecodeAcceleratorFactory::Create
|
|
vda = (this->*create_vda_function)(workarounds, gpu_preferences, media_log);
|
|
if (vda && vda->Initialize(config, client))
|
|
return vda;
|
|
+ else
|
|
+ LOG(ERROR) << "Initialization of one or more VDAs failed.";
|
|
}
|
|
|
|
return nullptr;
|
|
@@ -243,6 +245,7 @@ GpuVideoDecodeAcceleratorFactory::Create
|
|
const gpu::GpuDriverBugWorkarounds& workarounds,
|
|
const gpu::GpuPreferences& gpu_preferences,
|
|
MediaLog* media_log) const {
|
|
+ LOG(WARNING) << "Initializing VAAPI VDA.";
|
|
std::unique_ptr<VideoDecodeAccelerator> decoder;
|
|
decoder.reset(new VaapiVideoDecodeAccelerator(make_context_current_cb_,
|
|
bind_image_cb_));
|
|
Index: dev/media/gpu/ipc/service/gpu_video_decode_accelerator.cc
|
|
===================================================================
|
|
--- media/gpu/ipc/service/gpu_video_decode_accelerator.cc
|
|
+++ media/gpu/ipc/service/gpu_video_decode_accelerator.cc
|
|
@@ -380,6 +380,7 @@ bool GpuVideoDecodeAccelerator::Initiali
|
|
LOG(ERROR) << "Failed creating the VDA factory";
|
|
return false;
|
|
}
|
|
+ LOG(WARNING) << "Created the VDA factory";
|
|
|
|
const gpu::GpuDriverBugWorkarounds& gpu_workarounds =
|
|
stub_->channel()->gpu_channel_manager()->gpu_driver_bug_workarounds();
|
|
@@ -393,6 +394,7 @@ bool GpuVideoDecodeAccelerator::Initiali
|
|
<< (config.is_encrypted() ? " with encryption" : "");
|
|
return false;
|
|
}
|
|
+ LOG(WARNING) << "Created VDA";
|
|
|
|
// Attempt to set up performing decoding tasks on IO thread, if supported by
|
|
// the VDA.
|
|
Index: dev/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
|
|
===================================================================
|
|
--- media/gpu/vaapi/vaapi_video_decode_accelerator.cc
|
|
+++ media/gpu/vaapi/vaapi_video_decode_accelerator.cc
|
|
@@ -63,6 +63,7 @@ void ReportToUMA(VAVDADecoderFailure fai
|
|
VAVDA_DECODER_FAILURES_MAX + 1);
|
|
}
|
|
|
|
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
|
|
// Returns true if the CPU is an Intel Gemini Lake or later (including Kaby
|
|
// Lake) Cpu platform id's are referenced from the following file in kernel
|
|
// source arch/x86/include/asm/intel-family.h
|
|
@@ -75,6 +76,7 @@ bool IsGeminiLakeOrLater() {
|
|
cpuid.model() >= kGeminiLakeModelId;
|
|
return is_geminilake_or_later;
|
|
}
|
|
+#endif
|
|
|
|
} // namespace
|
|
|
|
@@ -637,6 +639,10 @@ void VaapiVideoDecodeAccelerator::Assign
|
|
va_surface_format_ = GetVaFormatForVideoCodecProfile(profile_);
|
|
std::vector<VASurfaceID> va_surface_ids;
|
|
|
|
+ // Nvidia doesn't support VAProfileNone, so don't try to create a temporary
|
|
+ // copy buffer there. It's not needed anyways for hardware video decoding
|
|
+ // to work.
|
|
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
|
|
// If we aren't in BufferAllocationMode::kNone, we have to allocate a
|
|
// |vpp_vaapi_wrapper_| for VaapiPicture to DownloadFromSurface() the VA's
|
|
// internal decoded frame.
|
|
@@ -650,6 +656,7 @@ void VaapiVideoDecodeAccelerator::Assign
|
|
NotifyError(PLATFORM_FAILURE);
|
|
}
|
|
}
|
|
+#endif
|
|
|
|
for (size_t i = 0; i < buffers.size(); ++i) {
|
|
// If we aren't in BufferAllocationMode::kNone, this |picture| is
|
|
@@ -661,9 +668,13 @@ void VaapiVideoDecodeAccelerator::Assign
|
|
PictureBuffer buffer = buffers[i];
|
|
buffer.set_size(requested_pic_size_);
|
|
std::unique_ptr<VaapiPicture> picture = vaapi_picture_factory_->Create(
|
|
+#if defined(OS_LINUX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
|
|
+ vaapi_wrapper_,
|
|
+#else
|
|
(buffer_allocation_mode_ == BufferAllocationMode::kNone)
|
|
? vaapi_wrapper_
|
|
: vpp_vaapi_wrapper_,
|
|
+#endif
|
|
make_context_current_cb_, bind_image_cb_, buffer);
|
|
RETURN_AND_NOTIFY_ON_FAILURE(picture, "Failed creating a VaapiPicture",
|
|
PLATFORM_FAILURE, );
|
|
@@ -1089,6 +1100,9 @@ VaapiVideoDecodeAccelerator::GetSupporte
|
|
|
|
VaapiVideoDecodeAccelerator::BufferAllocationMode
|
|
VaapiVideoDecodeAccelerator::DecideBufferAllocationMode() {
|
|
+#if defined(OS_LINUX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
|
|
+ return BufferAllocationMode::kNormal;
|
|
+#else
|
|
// TODO(crbug.com/912295): Enable a better BufferAllocationMode for IMPORT
|
|
// |output_mode_| as well.
|
|
if (output_mode_ == VideoDecodeAccelerator::Config::OutputMode::IMPORT)
|
|
@@ -1124,6 +1138,7 @@ VaapiVideoDecodeAccelerator::DecideBuffe
|
|
return BufferAllocationMode::kReduced;
|
|
|
|
return BufferAllocationMode::kSuperReduced;
|
|
+#endif
|
|
}
|
|
|
|
bool VaapiVideoDecodeAccelerator::IsBufferAllocationModeReducedOrSuperReduced()
|
|
Index: dev/media/gpu/vaapi/vaapi_wrapper.cc
|
|
===================================================================
|
|
--- media/gpu/vaapi/vaapi_wrapper.cc
|
|
+++ media/gpu/vaapi/vaapi_wrapper.cc
|
|
@@ -325,6 +325,11 @@ void VADisplayState::PreSandboxInitializ
|
|
base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE);
|
|
if (drm_file.IsValid())
|
|
VADisplayState::Get()->SetDrmFd(drm_file.GetPlatformFile());
|
|
+
|
|
+ const char kNvidiaPath[] = "/dev/dri/nvidiactl";
|
|
+ base::File nvidia_file = base::File(
|
|
+ base::FilePath::FromUTF8Unsafe(kNvidiaPath),
|
|
+ base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE);
|
|
}
|
|
|
|
VADisplayState::VADisplayState()
|
|
@@ -352,10 +357,6 @@ bool VADisplayState::Initialize() {
|
|
}
|
|
|
|
bool VADisplayState::InitializeOnce() {
|
|
- static_assert(
|
|
- VA_MAJOR_VERSION >= 2 || (VA_MAJOR_VERSION == 1 && VA_MINOR_VERSION >= 1),
|
|
- "Requires VA-API >= 1.1.0");
|
|
-
|
|
switch (gl::GetGLImplementation()) {
|
|
case gl::kGLImplementationEGLGLES2:
|
|
va_display_ = vaGetDisplayDRM(drm_fd_.get());
|
|
@@ -363,10 +364,10 @@ bool VADisplayState::InitializeOnce() {
|
|
case gl::kGLImplementationDesktopGL:
|
|
#if defined(USE_X11)
|
|
va_display_ = vaGetDisplay(gfx::GetXDisplay());
|
|
-#else
|
|
- LOG(WARNING) << "VAAPI video acceleration not available without "
|
|
- "DesktopGL (GLX).";
|
|
+ if (vaDisplayIsValid(va_display_))
|
|
+ break;
|
|
#endif // USE_X11
|
|
+ va_display_ = vaGetDisplayDRM(drm_fd_.get());
|
|
break;
|
|
// Cannot infer platform from GL, try all available displays
|
|
case gl::kGLImplementationNone:
|
|
@@ -399,8 +400,19 @@ bool VADisplayState::InitializeOnce() {
|
|
int major_version, minor_version;
|
|
VAStatus va_res = vaInitialize(va_display_, &major_version, &minor_version);
|
|
if (va_res != VA_STATUS_SUCCESS) {
|
|
- LOG(ERROR) << "vaInitialize failed: " << vaErrorStr(va_res);
|
|
- return false;
|
|
+ LOG(ERROR) << "vaInitialize failed (ignore if using Wayland desktop environment): " << vaErrorStr(va_res);
|
|
+ va_display_ = vaGetDisplayDRM(drm_fd_.get());
|
|
+ if (!vaDisplayIsValid(va_display_)) {
|
|
+ LOG(ERROR) << "Could not get a valid DRM VA display";
|
|
+ return false;
|
|
+ }
|
|
+ va_res = vaInitialize(va_display_, &major_version, &minor_version);
|
|
+ if (va_res != VA_STATUS_SUCCESS) {
|
|
+ LOG(ERROR) << "vaInitialize failed using DRM: " << vaErrorStr(va_res);
|
|
+ return false;
|
|
+ } else {
|
|
+ LOG(WARNING) << "vaInitialize succeeded for DRM";
|
|
+ }
|
|
}
|
|
|
|
va_initialized_ = true;
|
|
@@ -408,7 +420,7 @@ bool VADisplayState::InitializeOnce() {
|
|
va_vendor_string_ = vaQueryVendorString(va_display_);
|
|
DLOG_IF(WARNING, va_vendor_string_.empty())
|
|
<< "Vendor string empty or error reading.";
|
|
- DVLOG(1) << "VAAPI version: " << major_version << "." << minor_version << " "
|
|
+ VLOG(1) << "VAAPI version: " << major_version << "." << minor_version << " "
|
|
<< va_vendor_string_;
|
|
|
|
// The VAAPI version is determined from what is loaded on the system by
|
|
@@ -740,7 +752,7 @@ bool VASupportedProfiles::AreAttribsSupp
|
|
if (attribs[i].type != required_attribs[i].type ||
|
|
(attribs[i].value & required_attribs[i].value) !=
|
|
required_attribs[i].value) {
|
|
- DVLOG(1) << "Unsupported value " << required_attribs[i].value
|
|
+ VLOG(1) << "Unsupported value " << required_attribs[i].value
|
|
<< " for attribute type " << required_attribs[i].type;
|
|
return false;
|
|
}
|