summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlionel.g.landwerlin <lionel.g.landwerlin@intel.com>2015-01-02 15:50:52 -0800
committerCommit bot <commit-bot@chromium.org>2015-01-02 23:51:45 +0000
commitb056abc3ccfaaa7da280084ce55724a0f07d85a0 (patch)
tree55710ed0195007776a4a99a0789a859133511f2c
parent80059b3ba15fe5c333dc0aef70f3bc6908cd2e2d (diff)
downloadchromium_src-b056abc3ccfaaa7da280084ce55724a0f07d85a0.zip
chromium_src-b056abc3ccfaaa7da280084ce55724a0f07d85a0.tar.gz
chromium_src-b056abc3ccfaaa7da280084ce55724a0f07d85a0.tar.bz2
Add Vaapi support on Ozone/Freon
BUG=403058 TEST=video_decode_accelerator_unittest and video_encode_accelerator_unittest TBR=jln,scherkus Review URL: https://codereview.chromium.org/825163004 Cr-Commit-Position: refs/heads/master@{#309863}
-rw-r--r--content/common/BUILD.gn9
-rw-r--r--content/common/gpu/media/DEPS2
-rw-r--r--content/common/gpu/media/rendering_helper.cc89
-rw-r--r--content/common/gpu/media/rendering_helper.h13
-rw-r--r--content/common/gpu/media/va_drm.sigs8
-rw-r--r--content/common/gpu/media/va_stub_header.fragment1
-rw-r--r--content/common/gpu/media/vaapi_drm_picture.cc129
-rw-r--r--content/common/gpu/media/vaapi_drm_picture.h62
-rw-r--r--content/common/gpu/media/vaapi_picture.cc9
-rw-r--r--content/common/gpu/media/vaapi_video_decode_accelerator.cc6
-rw-r--r--content/common/gpu/media/vaapi_wrapper.cc144
-rw-r--r--content/common/gpu/media/vaapi_wrapper.h35
-rw-r--r--content/common/gpu/media/video_decode_accelerator_unittest.cc8
-rw-r--r--content/common/gpu/media/video_encode_accelerator_unittest.cc11
-rw-r--r--content/common/sandbox_linux/bpf_gpu_policy_linux.cc4
-rw-r--r--content/content_common.gypi5
-rw-r--r--content/content_tests.gypi29
-rw-r--r--media/test/data/test-25fps.h264.md512
-rw-r--r--ui/ozone/platform/dri/ozone_platform_gbm.cc3
19 files changed, 568 insertions, 11 deletions
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 8cec06a..2ce16ac 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -21,6 +21,9 @@ if (is_chromeos && cpu_arch != "arm") {
if (use_x11) {
sources += [ "gpu/media/va_x11.sigs" ]
}
+ if (use_ozone) {
+ sources += [ "gpu/media/va_drm.sigs" ]
+ }
stubs_filename_root = "va_stubs"
outputs = [
@@ -329,6 +332,12 @@ source_set("common") {
"gpu/media/vaapi_tfp_picture.h",
]
}
+ if (use_ozone) {
+ sources += [
+ "gpu/media/vaapi_drm_picture.cc",
+ "gpu/media/vaapi_drm_picture.h",
+ ]
+ }
}
}
diff --git a/content/common/gpu/media/DEPS b/content/common/gpu/media/DEPS
index 987a2b1..93b26ae 100644
--- a/content/common/gpu/media/DEPS
+++ b/content/common/gpu/media/DEPS
@@ -2,4 +2,6 @@ include_rules = [
"+media",
"+third_party/libva",
"+third_party/libyuv",
+ "+ui/display/chromeos",
+ "+ui/platform_window",
]
diff --git a/content/common/gpu/media/rendering_helper.cc b/content/common/gpu/media/rendering_helper.cc
index 4e9b60c..8d42e71 100644
--- a/content/common/gpu/media/rendering_helper.cc
+++ b/content/common/gpu/media/rendering_helper.cc
@@ -36,6 +36,16 @@
#define GL_VARIANT_EGL 1
#endif
+#if defined(USE_OZONE)
+#if defined(OS_CHROMEOS)
+#include "ui/display/chromeos/display_configurator.h"
+#endif // defined(OS_CHROMEOS)
+#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/ui_thread_gpu.h"
+#include "ui/platform_window/platform_window.h"
+#include "ui/platform_window/platform_window_delegate.h"
+#endif // defined(USE_OZONE)
+
// Helper for Shader creation.
static void CreateShader(GLuint program,
GLenum type,
@@ -58,6 +68,54 @@ static void CreateShader(GLuint program,
namespace content {
+#if defined(USE_OZONE)
+
+class RenderingHelper::StubOzoneDelegate : public ui::PlatformWindowDelegate {
+ public:
+ StubOzoneDelegate() : accelerated_widget_(gfx::kNullAcceleratedWidget) {
+ ui_thread_gpu_.Initialize();
+ platform_window_ = ui::OzonePlatform::GetInstance()->CreatePlatformWindow(
+ this, gfx::Rect());
+ }
+ virtual ~StubOzoneDelegate() {}
+
+ void OnBoundsChanged(const gfx::Rect& new_bounds) override {}
+
+ void OnDamageRect(const gfx::Rect& damaged_region) override {}
+
+ void DispatchEvent(ui::Event* event) override {}
+
+ void OnCloseRequest() override {}
+ void OnClosed() override {}
+
+ void OnWindowStateChanged(ui::PlatformWindowState new_state) override {}
+
+ void OnLostCapture() override {};
+
+ void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) override {
+ accelerated_widget_ = widget;
+ };
+
+ void OnActivationChanged(bool active) override {};
+
+ gfx::AcceleratedWidget accelerated_widget() const {
+ return accelerated_widget_;
+ }
+
+ gfx::Size GetSize() { return platform_window_->GetBounds().size(); }
+
+ ui::PlatformWindow* platform_window() const { return platform_window_.get(); }
+
+ private:
+ ui::UiThreadGpu ui_thread_gpu_;
+ scoped_ptr<ui::PlatformWindow> platform_window_;
+ gfx::AcceleratedWidget accelerated_widget_;
+
+ DISALLOW_COPY_AND_ASSIGN(StubOzoneDelegate);
+};
+
+#endif // defined(USE_OZONE)
+
RenderingHelperParams::RenderingHelperParams()
: rendering_fps(0), warm_up_iterations(0), render_as_thumbnails(false) {
}
@@ -93,6 +151,9 @@ bool RenderingHelper::InitializeOneOff() {
#else
cmd_line->AppendSwitchASCII(switches::kUseGL, gfx::kGLImplementationEGLName);
#endif
+#if defined(USE_OZONE)
+ ui::OzonePlatform::InitializeForUI();
+#endif
return gfx::GLSurface::InitializeOneOff();
}
@@ -167,6 +228,18 @@ void RenderingHelper::Initialize(const RenderingHelperParams& params,
XStoreName(display, window_, "VideoDecodeAcceleratorTest");
XSelectInput(display, window_, ExposureMask);
XMapWindow(display, window_);
+#elif defined(USE_OZONE)
+ platform_window_delegate_.reset(new RenderingHelper::StubOzoneDelegate());
+ window_ = platform_window_delegate_->accelerated_widget();
+#if defined(OS_CHROMEOS)
+ display_configurator_.reset(new ui::DisplayConfigurator());
+ display_configurator_->Init(true);
+ display_configurator_->ForceInitialConfigure(0);
+ platform_window_delegate_->platform_window()->SetBounds(
+ gfx::Rect(display_configurator_->framebuffer_size()));
+#else
+ platform_window_delegate_->platform_window()->SetBounds(gfx::Rect(800, 600));
+#endif
#else
#error unknown platform
#endif
@@ -305,6 +378,16 @@ void RenderingHelper::Initialize(const RenderingHelperParams& params,
if (frame_duration_ != base::TimeDelta()) {
int warm_up_iterations = params.warm_up_iterations;
+#if defined(USE_OZONE)
+ // On Ozone the VSyncProvider can't provide a vsync interval until
+ // we render at least a frame, so we warm up with at least one
+ // frame.
+ // On top of this, we want to make sure all the buffers backing
+ // the GL surface are cleared, otherwise we can see the previous
+ // test's last frames, so we set warm up iterations to 2, to clear
+ // the front and back buffers.
+ warm_up_iterations = std::max(2, warm_up_iterations);
+#endif
WarmUpRendering(warm_up_iterations);
}
@@ -346,6 +429,10 @@ void RenderingHelper::WarmUpRendering(int warm_up_iterations) {
void RenderingHelper::UnInitialize(base::WaitableEvent* done) {
CHECK_EQ(base::MessageLoop::current(), message_loop_);
+#if defined(USE_OZONE) && defined(OS_CHROMEOS)
+ display_configurator_->PrepareForExit();
+#endif
+
render_task_.Cancel();
if (render_as_thumbnails_) {
@@ -500,6 +587,8 @@ void RenderingHelper::Clear() {
CHECK(XUnmapWindow(gfx::GetXDisplay(), window_));
CHECK(XDestroyWindow(gfx::GetXDisplay(), window_));
}
+#elif defined(USE_OZONE)
+ platform_window_delegate_.reset();
#endif
window_ = gfx::kNullAcceleratedWidget;
}
diff --git a/content/common/gpu/media/rendering_helper.h b/content/common/gpu/media/rendering_helper.h
index e013fa7..817ab19 100644
--- a/content/common/gpu/media/rendering_helper.h
+++ b/content/common/gpu/media/rendering_helper.h
@@ -23,6 +23,10 @@ class MessageLoop;
class WaitableEvent;
}
+namespace ui {
+class DisplayConfigurator;
+}
+
namespace content {
class VideoFrameTexture : public base::RefCounted<VideoFrameTexture> {
@@ -172,6 +176,15 @@ class RenderingHelper {
scoped_refptr<gfx::GLContext> gl_context_;
scoped_refptr<gfx::GLSurface> gl_surface_;
+#if defined(USE_OZONE)
+ class StubOzoneDelegate;
+ scoped_ptr<StubOzoneDelegate> platform_window_delegate_;
+
+#if defined(OS_CHROMEOS)
+ scoped_ptr<ui::DisplayConfigurator> display_configurator_;
+#endif
+#endif
+
gfx::AcceleratedWidget window_;
gfx::Size screen_size_;
diff --git a/content/common/gpu/media/va_drm.sigs b/content/common/gpu/media/va_drm.sigs
new file mode 100644
index 0000000..093e36c
--- /dev/null
+++ b/content/common/gpu/media/va_drm.sigs
@@ -0,0 +1,8 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//------------------------------------------------
+// Functions from libva-drm used in chromium code.
+//------------------------------------------------
+VADisplay vaGetDisplayDRM(int fd);
diff --git a/content/common/gpu/media/va_stub_header.fragment b/content/common/gpu/media/va_stub_header.fragment
index 8d89c16..fdcf35f 100644
--- a/content/common/gpu/media/va_stub_header.fragment
+++ b/content/common/gpu/media/va_stub_header.fragment
@@ -3,6 +3,7 @@
extern "C" {
+#include "third_party/libva/va/drm/va_drm.h"
#include "third_party/libva/va/va.h"
#include "third_party/libva/va/va_x11.h"
diff --git a/content/common/gpu/media/vaapi_drm_picture.cc b/content/common/gpu/media/vaapi_drm_picture.cc
new file mode 100644
index 0000000..82e16ec
--- /dev/null
+++ b/content/common/gpu/media/vaapi_drm_picture.cc
@@ -0,0 +1,129 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/file_descriptor_posix.h"
+#include "content/common/gpu/media/va_surface.h"
+#include "content/common/gpu/media/vaapi_drm_picture.h"
+#include "content/common/gpu/media/vaapi_wrapper.h"
+#include "third_party/libva/va/drm/va_drm.h"
+#include "third_party/libva/va/va.h"
+#include "third_party/libva/va/va_drmcommon.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_image_linux_dma_buffer.h"
+#include "ui/gl/scoped_binders.h"
+#include "ui/ozone/public/native_pixmap.h"
+#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/surface_factory_ozone.h"
+
+namespace content {
+
+VaapiDrmPicture::VaapiDrmPicture(
+ VaapiWrapper* vaapi_wrapper,
+ const base::Callback<bool(void)>& make_context_current,
+ int32 picture_buffer_id,
+ uint32 texture_id,
+ const gfx::Size& size)
+ : VaapiPicture(picture_buffer_id, texture_id, size),
+ vaapi_wrapper_(vaapi_wrapper),
+ make_context_current_(make_context_current) {
+}
+
+VaapiDrmPicture::~VaapiDrmPicture() {
+ if (gl_image_ && make_context_current_.Run()) {
+ gl_image_->ReleaseTexImage(GL_TEXTURE_EXTERNAL_OES);
+ gl_image_->Destroy(true);
+
+ DCHECK_EQ(glGetError(), static_cast<GLenum>(GL_NO_ERROR));
+ }
+}
+
+bool VaapiDrmPicture::Initialize() {
+ // We want to create a VASurface and an EGLImage out of the same
+ // memory buffer, so we can output decoded pictures to it using
+ // VAAPI and also use it to paint with GL.
+ ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance();
+ ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone();
+
+ // Create a buffer from Ozone.
+ pixmap_ = factory->CreateNativePixmap(gfx::kNullAcceleratedWidget, size(),
+ ui::SurfaceFactoryOzone::RGBA_8888,
+ ui::SurfaceFactoryOzone::SCANOUT);
+ if (!pixmap_) {
+ LOG(ERROR) << "Failed creating an Ozone NativePixmap";
+ return false;
+ }
+
+ // Get the dmabuf of the created buffer.
+ int dmabuf_fd = pixmap_->GetDmaBufFd();
+ if (dmabuf_fd < 0) {
+ LOG(ERROR) << "Failed to get dmabuf from an Ozone NativePixmap";
+ return false;
+ }
+ int dmabuf_pitch = pixmap_->GetDmaBufPitch();
+
+ // Create a VASurface out of the created buffer using the dmabuf.
+ VASurfaceAttribExternalBuffers va_attrib_extbuf;
+ memset(&va_attrib_extbuf, 0, sizeof(va_attrib_extbuf));
+ va_attrib_extbuf.pixel_format = VA_FOURCC_BGRX;
+ va_attrib_extbuf.width = size().width();
+ va_attrib_extbuf.height = size().height();
+ va_attrib_extbuf.data_size = size().height() * dmabuf_pitch;
+ va_attrib_extbuf.num_planes = 1;
+ va_attrib_extbuf.pitches[0] = dmabuf_pitch;
+ va_attrib_extbuf.offsets[0] = 0;
+ va_attrib_extbuf.buffers = reinterpret_cast<unsigned long*>(&dmabuf_fd);
+ va_attrib_extbuf.num_buffers = 1;
+ va_attrib_extbuf.flags = 0;
+ va_attrib_extbuf.private_data = NULL;
+
+ std::vector<VASurfaceAttrib> va_attribs;
+ va_attribs.resize(2);
+
+ va_attribs[0].type = VASurfaceAttribMemoryType;
+ va_attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
+ va_attribs[0].value.type = VAGenericValueTypeInteger;
+ va_attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
+
+ va_attribs[1].type = VASurfaceAttribExternalBufferDescriptor;
+ va_attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
+ va_attribs[1].value.type = VAGenericValueTypePointer;
+ va_attribs[1].value.value.p = &va_attrib_extbuf;
+
+ va_surface_ = vaapi_wrapper_->CreateUnownedSurface(VA_RT_FORMAT_RGB32, size(),
+ va_attribs);
+ if (!va_surface_) {
+ LOG(ERROR) << "Failed to create VASurface for an Ozone NativePixmap";
+ return false;
+ }
+
+ if (!make_context_current_.Run())
+ return false;
+
+ // Create an EGLImage out of the same buffer.
+ gl_image_ = new gfx::GLImageLinuxDMABuffer(size(), GL_RGBA);
+ if (!gl_image_->Initialize(base::FileDescriptor(dmabuf_fd, false),
+ gfx::GpuMemoryBuffer::BGRA_8888, dmabuf_pitch)) {
+ LOG(ERROR) << "Failed to create a GLImageLinuxDMABuffer for a NativePixmap";
+ return false;
+ }
+
+ // Bind the EGLImage to the given GL texture.
+ gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_EXTERNAL_OES,
+ texture_id());
+ if (!gl_image_->BindTexImage(GL_TEXTURE_EXTERNAL_OES)) {
+ LOG(ERROR) << "Failed to bind texture to GLImage";
+ return false;
+ }
+
+ return true;
+}
+
+bool VaapiDrmPicture::DownloadFromSurface(
+ const scoped_refptr<VASurface>& va_surface) {
+ return vaapi_wrapper_->BlitSurface(va_surface->id(), va_surface->size(),
+ va_surface_->id(), va_surface_->size());
+}
+
+} // namespace
diff --git a/content/common/gpu/media/vaapi_drm_picture.h b/content/common/gpu/media/vaapi_drm_picture.h
new file mode 100644
index 0000000..5d8617c
--- /dev/null
+++ b/content/common/gpu/media/vaapi_drm_picture.h
@@ -0,0 +1,62 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This file contains an implementation of picture allocation for the
+// Ozone window system used by VaapiVideoDecodeAccelerator to produce
+// output pictures.
+
+#ifndef CONTENT_COMMON_GPU_MEDIA_VAAPI_DRM_PICTURE_H_
+#define CONTENT_COMMON_GPU_MEDIA_VAAPI_DRM_PICTURE_H_
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "content/common/gpu/media/vaapi_picture.h"
+#include "ui/gfx/size.h"
+
+namespace gfx {
+class GLImageLinuxDMABuffer;
+}
+
+namespace ui {
+class NativePixmap;
+}
+
+namespace content {
+
+class VaapiWrapper;
+
+// Implementation of VaapiPicture for the ozone/drm backed chromium.
+class VaapiDrmPicture : public VaapiPicture {
+ public:
+ VaapiDrmPicture(VaapiWrapper* vaapi_wrapper,
+ const base::Callback<bool(void)>& make_context_current,
+ int32 picture_buffer_id,
+ uint32 texture_id,
+ const gfx::Size& size);
+
+ ~VaapiDrmPicture() override;
+
+ bool Initialize() override;
+
+ bool DownloadFromSurface(const scoped_refptr<VASurface>& va_surface) override;
+
+ private:
+ VaapiWrapper* vaapi_wrapper_; // Not owned.
+ base::Callback<bool(void)> make_context_current_;
+
+ // Ozone buffer, the storage of the EGLImage and the VASurface.
+ scoped_refptr<ui::NativePixmap> pixmap_;
+
+ // EGLImage bound to the GL textures used by the VDA client.
+ scoped_refptr<gfx::GLImageLinuxDMABuffer> gl_image_;
+
+ // VASurface used to transfer from the decoder's pixel format.
+ scoped_refptr<VASurface> va_surface_;
+
+ DISALLOW_COPY_AND_ASSIGN(VaapiDrmPicture);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_MEDIA_VAAPI_DRM_PICTURE_H_
diff --git a/content/common/gpu/media/vaapi_picture.cc b/content/common/gpu/media/vaapi_picture.cc
index d02f6d6..782971c 100644
--- a/content/common/gpu/media/vaapi_picture.cc
+++ b/content/common/gpu/media/vaapi_picture.cc
@@ -9,6 +9,8 @@
#if defined(USE_X11)
#include "content/common/gpu/media/vaapi_tfp_picture.h"
+#elif defined(USE_OZONE)
+#include "content/common/gpu/media/vaapi_drm_picture.h"
#endif
namespace content {
@@ -24,6 +26,9 @@ linked_ptr<VaapiPicture> VaapiPicture::CreatePicture(
#if defined(USE_X11)
picture.reset(new VaapiTFPPicture(vaapi_wrapper, make_context_current,
picture_buffer_id, texture_id, size));
+#elif defined(USE_OZONE)
+ picture.reset(new VaapiDrmPicture(vaapi_wrapper, make_context_current,
+ picture_buffer_id, texture_id, size));
#endif // USE_X11
if (picture.get() && !picture->Initialize())
@@ -34,7 +39,11 @@ linked_ptr<VaapiPicture> VaapiPicture::CreatePicture(
// static
uint32 VaapiPicture::GetGLTextureTarget() {
+#if defined(USE_OZONE)
+ return GL_TEXTURE_EXTERNAL_OES;
+#else
return GL_TEXTURE_2D;
+#endif
}
} // namespace content
diff --git a/content/common/gpu/media/vaapi_video_decode_accelerator.cc b/content/common/gpu/media/vaapi_video_decode_accelerator.cc
index add0b63..b5f2b90 100644
--- a/content/common/gpu/media/vaapi_video_decode_accelerator.cc
+++ b/content/common/gpu/media/vaapi_video_decode_accelerator.cc
@@ -111,6 +111,12 @@ bool VaapiVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile,
"DesktopGL (GLX).";
return false;
}
+#elif defined(USE_OZONE)
+ if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
+ DVLOG(1) << "HW video decode acceleration not available without "
+ << "EGLGLES2.";
+ return false;
+ }
#endif // USE_X11
vaapi_wrapper_ = VaapiWrapper::Create(
diff --git a/content/common/gpu/media/vaapi_wrapper.cc b/content/common/gpu/media/vaapi_wrapper.cc
index 4b5c046..63450b4a 100644
--- a/content/common/gpu/media/vaapi_wrapper.cc
+++ b/content/common/gpu/media/vaapi_wrapper.cc
@@ -18,11 +18,17 @@
#include "ui/gl/gl_bindings.h"
#if defined(USE_X11)
#include "ui/gfx/x/x11_types.h"
+#elif defined(USE_OZONE)
+#include "third_party/libva/va/drm/va_drm.h"
+#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/surface_factory_ozone.h"
#endif // USE_X11
using content_common_gpu_media::kModuleVa;
#if defined(USE_X11)
using content_common_gpu_media::kModuleVa_x11;
+#elif defined(USE_OZONE)
+using content_common_gpu_media::kModuleVa_drm;
#endif // USE_X11
using content_common_gpu_media::InitializeStubs;
using content_common_gpu_media::StubPathMap;
@@ -142,13 +148,17 @@ VaapiWrapper::VaapiWrapper()
: va_display_(NULL),
va_config_id_(VA_INVALID_ID),
va_context_id_(VA_INVALID_ID),
- va_initialized_(false) {
+ va_initialized_(false),
+ va_vpp_config_id_(VA_INVALID_ID),
+ va_vpp_context_id_(VA_INVALID_ID),
+ va_vpp_buffer_id_(VA_INVALID_ID) {
}
VaapiWrapper::~VaapiWrapper() {
DestroyPendingBuffers();
DestroyCodedBuffers();
DestroySurfaces();
+ DeinitializeVpp();
Deinitialize();
}
@@ -227,6 +237,11 @@ bool VaapiWrapper::VaInitialize(const base::Closure& report_error_to_uma_cb) {
#if defined(USE_X11)
va_display_ = vaGetDisplay(gfx::GetXDisplay());
+#elif defined(USE_OZONE)
+ ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance();
+ ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone();
+
+ va_display_ = vaGetDisplayDRM(factory->GetDrmFd());
#endif // USE_X11
if (!vaDisplayIsValid(va_display_)) {
@@ -445,6 +460,39 @@ void VaapiWrapper::DestroySurfaces() {
va_context_id_ = VA_INVALID_ID;
}
+scoped_refptr<VASurface> VaapiWrapper::CreateUnownedSurface(
+ unsigned int va_format,
+ const gfx::Size& size,
+ const std::vector<VASurfaceAttrib>& va_attribs) {
+ base::AutoLock auto_lock(va_lock_);
+
+ std::vector<VASurfaceAttrib> attribs(va_attribs);
+ VASurfaceID va_surface_id;
+ VAStatus va_res =
+ vaCreateSurfaces(va_display_, va_format, size.width(), size.height(),
+ &va_surface_id, 1, &attribs[0], attribs.size());
+
+ scoped_refptr<VASurface> va_surface;
+ VA_SUCCESS_OR_RETURN(va_res, "Failed to create unowned VASurface",
+ va_surface);
+
+ // This is safe to use Unretained() here, because the VDA takes care
+ // of the destruction order. All the surfaces will be destroyed
+ // before VaapiWrapper.
+ va_surface = new VASurface(
+ va_surface_id, size,
+ base::Bind(&VaapiWrapper::DestroyUnownedSurface, base::Unretained(this)));
+
+ return va_surface;
+}
+
+void VaapiWrapper::DestroyUnownedSurface(VASurfaceID va_surface_id) {
+ base::AutoLock auto_lock(va_lock_);
+
+ VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_id, 1);
+ VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces on surface failed");
+}
+
bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type,
size_t size,
void* buffer) {
@@ -757,6 +805,98 @@ bool VaapiWrapper::DownloadAndDestroyCodedBuffer(VABufferID buffer_id,
return buffer_segment == NULL;
}
+bool VaapiWrapper::BlitSurface(VASurfaceID va_surface_id_src,
+ const gfx::Size& src_size,
+ VASurfaceID va_surface_id_dest,
+ const gfx::Size& dest_size) {
+ base::AutoLock auto_lock(va_lock_);
+
+ // Initialize the post processing engine if not already done.
+ if (va_vpp_buffer_id_ == VA_INVALID_ID) {
+ if (!InitializeVpp_Locked())
+ return false;
+ }
+
+ VAProcPipelineParameterBuffer* pipeline_param;
+ VA_SUCCESS_OR_RETURN(vaMapBuffer(va_display_, va_vpp_buffer_id_,
+ reinterpret_cast<void**>(&pipeline_param)),
+ "Couldn't map vpp buffer", false);
+
+ memset(pipeline_param, 0, sizeof *pipeline_param);
+
+ VARectangle input_region;
+ input_region.x = input_region.y = 0;
+ input_region.width = src_size.width();
+ input_region.height = src_size.height();
+ pipeline_param->surface_region = &input_region;
+ pipeline_param->surface = va_surface_id_src;
+ pipeline_param->surface_color_standard = VAProcColorStandardNone;
+
+ VARectangle output_region;
+ output_region.x = output_region.y = 0;
+ output_region.width = dest_size.width();
+ output_region.height = dest_size.height();
+ pipeline_param->output_region = &output_region;
+ pipeline_param->output_background_color = 0xff000000;
+ pipeline_param->output_color_standard = VAProcColorStandardNone;
+
+ VA_SUCCESS_OR_RETURN(vaUnmapBuffer(va_display_, va_vpp_buffer_id_),
+ "Couldn't unmap vpp buffer", false);
+
+ VA_SUCCESS_OR_RETURN(
+ vaBeginPicture(va_display_, va_vpp_context_id_, va_surface_id_dest),
+ "Couldn't begin picture", false);
+
+ VA_SUCCESS_OR_RETURN(
+ vaRenderPicture(va_display_, va_vpp_context_id_, &va_vpp_buffer_id_, 1),
+ "Couldn't render picture", false);
+
+ VA_SUCCESS_OR_RETURN(vaEndPicture(va_display_, va_vpp_context_id_),
+ "Couldn't end picture", false);
+
+ return true;
+}
+
+bool VaapiWrapper::InitializeVpp_Locked() {
+ va_lock_.AssertAcquired();
+
+ VA_SUCCESS_OR_RETURN(
+ vaCreateConfig(va_display_, VAProfileNone, VAEntrypointVideoProc, NULL, 0,
+ &va_vpp_config_id_),
+ "Couldn't create config", false);
+
+ // The size of the picture for the context is irrelevant in the case
+ // of the VPP, just passing 1x1.
+ VA_SUCCESS_OR_RETURN(vaCreateContext(va_display_, va_vpp_config_id_, 1, 1, 0,
+ NULL, 0, &va_vpp_context_id_),
+ "Couldn't create context", false);
+
+ VA_SUCCESS_OR_RETURN(vaCreateBuffer(va_display_, va_vpp_context_id_,
+ VAProcPipelineParameterBufferType,
+ sizeof(VAProcPipelineParameterBuffer), 1,
+ NULL, &va_vpp_buffer_id_),
+ "Couldn't create buffer", false);
+
+ return true;
+}
+
+void VaapiWrapper::DeinitializeVpp() {
+ base::AutoLock auto_lock(va_lock_);
+
+ if (va_vpp_buffer_id_ != VA_INVALID_ID) {
+ vaDestroyBuffer(va_display_, va_vpp_buffer_id_);
+ va_vpp_buffer_id_ = VA_INVALID_ID;
+ }
+ if (va_vpp_context_id_ != VA_INVALID_ID) {
+ vaDestroyContext(va_display_, va_vpp_context_id_);
+ va_vpp_context_id_ = VA_INVALID_ID;
+ }
+ if (va_vpp_config_id_ != VA_INVALID_ID) {
+ vaDestroyConfig(va_display_, va_vpp_config_id_);
+ va_vpp_config_id_ = VA_INVALID_ID;
+ }
+}
+
// static
bool VaapiWrapper::PostSandboxInitialization() {
StubPathMap paths;
@@ -765,6 +905,8 @@ bool VaapiWrapper::PostSandboxInitialization() {
#if defined(USE_X11)
paths[kModuleVa_x11].push_back("libva-x11.so.1");
+#elif defined(USE_OZONE)
+ paths[kModuleVa_drm].push_back("libva-drm.so.1");
#endif
return InitializeStubs(paths);
diff --git a/content/common/gpu/media/vaapi_wrapper.h b/content/common/gpu/media/vaapi_wrapper.h
index 242684e..c4e72a4 100644
--- a/content/common/gpu/media/vaapi_wrapper.h
+++ b/content/common/gpu/media/vaapi_wrapper.h
@@ -20,6 +20,7 @@
#include "media/base/video_decoder_config.h"
#include "media/base/video_frame.h"
#include "third_party/libva/va/va.h"
+#include "third_party/libva/va/va_vpp.h"
#include "ui/gfx/size.h"
#if defined(USE_X11)
#include "third_party/libva/va/va_x11.h"
@@ -71,6 +72,15 @@ class CONTENT_EXPORT VaapiWrapper {
// Free all memory allocated in CreateSurfaces.
void DestroySurfaces();
+ // Create a VASurface of |va_format|, |size| and using |va_attribs|
+ // attributes. The ownership of the surface is transferred to the
+ // caller. It differs from surfaces created using CreateSurfaces(),
+ // where VaapiWrapper is the owner of the surfaces.
+ scoped_refptr<VASurface> CreateUnownedSurface(
+ unsigned int va_format,
+ const gfx::Size& size,
+ const std::vector<VASurfaceAttrib>& va_attribs);
+
// Submit parameters or slice data of |va_buffer_type|, copying them from
// |buffer| of size |size|, into HW codec. The data in |buffer| is no
// longer needed and can be freed after this method returns.
@@ -141,6 +151,14 @@ class CONTENT_EXPORT VaapiWrapper {
// Destroy all previously-allocated (and not yet destroyed) coded buffers.
void DestroyCodedBuffers();
+ // Blits a VASurface |va_surface_id_src| into another VASurface
+ // |va_surface_id_dest| applying pixel format conversion and scaling
+ // if needed.
+ bool BlitSurface(VASurfaceID va_surface_id_src,
+ const gfx::Size& src_size,
+ VASurfaceID va_surface_id_dest,
+ const gfx::Size& dest_size);
+
private:
VaapiWrapper();
@@ -155,6 +173,16 @@ class CONTENT_EXPORT VaapiWrapper {
VAEntrypoint entrypoint,
const std::vector<VAConfigAttrib>& required_attribs);
+ // Destroys a |va_surface| created using CreateUnownedSurface.
+ void DestroyUnownedSurface(VASurfaceID va_surface_id);
+
+ // Initialize the video post processing context with the |size| of
+ // the input pictures to be processed.
+ bool InitializeVpp_Locked();
+
+ // Deinitialize the video post processing context.
+ void DeinitializeVpp();
+
// Execute pending job in hardware and destroy pending buffers. Return false
// if vaapi driver refuses to accept parameter or slice buffers submitted
// by client, or if execution fails in hardware.
@@ -199,6 +227,13 @@ class CONTENT_EXPORT VaapiWrapper {
// return values from public methods.
base::Closure report_error_to_uma_cb_;
+ // VPP (Video Post Processing) context, this is used to convert
+ // pictures used by the decoder to RGBA pictures usable by GL or the
+ // display hardware.
+ VAConfigID va_vpp_config_id_;
+ VAContextID va_vpp_context_id_;
+ VABufferID va_vpp_buffer_id_;
+
DISALLOW_COPY_AND_ASSIGN(VaapiWrapper);
};
diff --git a/content/common/gpu/media/video_decode_accelerator_unittest.cc b/content/common/gpu/media/video_decode_accelerator_unittest.cc
index 3049896..3e1a9fd 100644
--- a/content/common/gpu/media/video_decode_accelerator_unittest.cc
+++ b/content/common/gpu/media/video_decode_accelerator_unittest.cc
@@ -887,11 +887,13 @@ void VideoDecodeAcceleratorTest::SetUp() {
// Initialize the rendering thread.
base::Thread::Options options;
options.message_loop_type = base::MessageLoop::TYPE_DEFAULT;
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(USE_OZONE)
// For windows the decoding thread initializes the media foundation decoder
// which uses COM. We need the thread to be a UI thread.
+ // On Ozone, the backend initializes the event system using a UI
+ // thread.
options.message_loop_type = base::MessageLoop::TYPE_UI;
-#endif // OS_WIN
+#endif // OS_WIN || USE_OZONE
rendering_thread_.StartWithOptions(options);
rendering_loop_proxy_ = rendering_thread_.message_loop_proxy();
@@ -1467,6 +1469,8 @@ int main(int argc, char **argv) {
}
if (it->first == "v" || it->first == "vmodule")
continue;
+ if (it->first == "ozone-platform" || it->first == "ozone-use-surfaceless")
+ continue;
LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second;
}
diff --git a/content/common/gpu/media/video_encode_accelerator_unittest.cc b/content/common/gpu/media/video_encode_accelerator_unittest.cc
index 51bb7cd..37bb030 100644
--- a/content/common/gpu/media/video_encode_accelerator_unittest.cc
+++ b/content/common/gpu/media/video_encode_accelerator_unittest.cc
@@ -23,6 +23,10 @@
#include "media/video/video_encode_accelerator.h"
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(USE_OZONE)
+#include "ui/ozone/public/ozone_platform.h"
+#endif
+
#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL)
#include "content/common/gpu/media/v4l2_video_encode_accelerator.h"
#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
@@ -1287,6 +1291,11 @@ int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv); // Removes gtest-specific args.
base::CommandLine::Init(argc, argv);
+#if defined(USE_OZONE)
+ ui::OzonePlatform::InitializeForUI();
+ ui::OzonePlatform::InitializeForGPU();
+#endif
+
base::ShadowingAtExitManager at_exit_manager;
scoped_ptr<base::FilePath::StringType> test_stream_data(
new base::FilePath::StringType(
@@ -1321,6 +1330,8 @@ int main(int argc, char** argv) {
}
if (it->first == "v" || it->first == "vmodule")
continue;
+ if (it->first == "ozone-platform" || it->first == "ozone-use-surfaceless")
+ continue;
LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second;
}
diff --git a/content/common/sandbox_linux/bpf_gpu_policy_linux.cc b/content/common/sandbox_linux/bpf_gpu_policy_linux.cc
index 00740db..81d389e 100644
--- a/content/common/sandbox_linux/bpf_gpu_policy_linux.cc
+++ b/content/common/sandbox_linux/bpf_gpu_policy_linux.cc
@@ -273,7 +273,11 @@ bool GpuProcessPolicy::PreSandboxHook() {
dlopen(I965DrvVideoPath, RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
dlopen("libva.so.1", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
+#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);
+#endif
}
}
diff --git a/content/content_common.gypi b/content/content_common.gypi
index 197bbc6..69ec533 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -817,8 +817,13 @@
'variables': {
'sig_files': [
'common/gpu/media/va.sigs',
+ 'common/gpu/media/va_drm.sigs',
],
},
+ 'sources': [
+ 'common/gpu/media/vaapi_drm_picture.cc',
+ 'common/gpu/media/vaapi_drm_picture.h',
+ ],
}],
],
'variables': {
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 280d2e8..4b0e9c0 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -1550,7 +1550,7 @@
},
],
}],
- ['(chromeos==1 or OS=="win" or OS=="android") and use_ozone==0', {
+ ['chromeos==1 or OS=="win" or OS=="android"', {
'targets': [
{
'target_name': 'video_decode_accelerator_unittest',
@@ -1618,13 +1618,19 @@
'../ui/gfx/x/gfx_x11.gyp:gfx_x11',
],
}],
+ ['use_ozone==1 and chromeos==1', {
+ 'dependencies': [
+ '../ui/display/display.gyp:display', # Used by rendering_helper.cc
+ '../ui/ozone/ozone.gyp:ozone', # Used by rendering_helper.cc
+ ],
+ }],
],
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
'msvs_disabled_warnings': [ 4267, ],
},
]
}],
- ['chromeos==1 and use_x11 == 1 and target_arch != "arm"', {
+ ['chromeos==1 and target_arch != "arm"', {
'targets': [
{
'target_name': 'vaapi_h264_decoder_unittest',
@@ -1632,7 +1638,6 @@
'dependencies': [
'content.gyp:content_common',
'../base/base.gyp:base',
- '../build/linux/system.gyp:x11',
'../media/media.gyp:media',
'../testing/gtest.gyp:gtest',
'../third_party/libyuv/libyuv.gyp:libyuv',
@@ -1644,10 +1649,21 @@
'include_dirs': [
'<(DEPTH)/third_party/libva',
],
+ 'conditions': [
+ ['use_x11==1', {
+ 'dependencies': [
+ '../build/linux/system.gyp:x11',
+ ]
+ }, {
+ 'dependencies': [
+ '../build/linux/system.gyp:libdrm',
+ ]
+ }],
+ ],
},
]
}],
- ['chromeos==1 and (target_arch == "arm" or use_x11 == 1)', {
+ ['chromeos==1', {
'targets': [
{
'target_name': 'video_encode_accelerator_unittest',
@@ -1678,6 +1694,11 @@
'../ui/gfx/x/gfx_x11.gyp:gfx_x11',
],
}],
+ ['use_ozone==1', {
+ 'dependencies': [
+ '../ui/ozone/ozone.gyp:ozone',
+ ],
+ }],
],
},
]
diff --git a/media/test/data/test-25fps.h264.md5 b/media/test/data/test-25fps.h264.md5
index 4c02016..c58f260 100644
--- a/media/test/data/test-25fps.h264.md5
+++ b/media/test/data/test-25fps.h264.md5
@@ -1,8 +1,14 @@
# --test_video_data="test-25fps.h264:320:240:250:258:35:150:1"
-# Intel - Haswell
-# Intel - Ivy Bridge
+# Intel Haswell - EGL
+92a0c14b4c1a13ca21317d2e75f17f76
+# Intel Ivy Bridge - EGL
+75d2f70272df8687dbda32e2eddd0a00
+# Intel Sandy Brige - EGL
+42e78b8ac231dc24e6db5fac2d26da7b
+# Intel - Haswell - X11
+# Intel - Ivy Bridge - X11
5f697b015b7af0afa7ff202905f748fa
-# Intel - Sandy Bridge
+# Intel - Sandy Bridge - X11
07bac7ad907bcb75004324645637a06c
# ARM - Exynos
04436cf1cf06b4bb6c1efd838e68257d
diff --git a/ui/ozone/platform/dri/ozone_platform_gbm.cc b/ui/ozone/platform/dri/ozone_platform_gbm.cc
index 6464538..c32ec61 100644
--- a/ui/ozone/platform/dri/ozone_platform_gbm.cc
+++ b/ui/ozone/platform/dri/ozone_platform_gbm.cc
@@ -128,7 +128,8 @@ class OzonePlatformGbm : public OzonePlatform {
display_manager_.reset(new DisplayManager());
// Needed since the browser process creates the accelerated widgets and that
// happens through SFO.
- surface_factory_ozone_.reset(new GbmSurfaceFactory(use_surfaceless_));
+ if (!surface_factory_ozone_)
+ surface_factory_ozone_.reset(new GbmSurfaceFactory(use_surfaceless_));
device_manager_ = CreateDeviceManager();
gpu_platform_support_host_.reset(new DriGpuPlatformSupportHost());
cursor_factory_ozone_.reset(new BitmapCursorFactoryOzone);