Commit f3947c5a authored by Paulo Warren's avatar Paulo Warren Committed by Commit Bot

gpu: Add a new vaapi shared image representation

This CL creates a new shared image representation as a VASurface. This
representation will be used in an Ozone context to represent a video
frame that was produced by the video acceleration api.

This representation will allow us to pass a NativePixmap to the VA-API
for the purposes of hardware accelerated video decoding.

We currently follow a VideoFrame centered design where the decoded
buffer is written onto from the hardware decoder as a VASurfaceID. The
decoded graphics buffer is wrapped in a VideoFrame, and passed to the
graphics pipeline as a Mailbox. This change eliminates the need to
convert buffers into the various required forms, and instead centralize
the lifetime as a single entity.

BUG=1058103
TEST=None

Change-Id: I482f3aa6d29a7093e8016ab4e74762e61c600865
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2083662Reviewed-by: default avatarMiguel Casas <mcasas@chromium.org>
Reviewed-by: default avatarAndres Calderon Jaramillo <andrescj@chromium.org>
Reviewed-by: default avatarKhushal <khushalsagar@chromium.org>
Commit-Queue: Paulo Warren <pwarren@chromium.org>
Cr-Commit-Position: refs/heads/master@{#754533}
parent bbb9bf14
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import("//build/config/jumbo.gni") import("//build/config/jumbo.gni")
import("//build/config/ui.gni") import("//build/config/ui.gni")
import("//gpu/vulkan/features.gni") import("//gpu/vulkan/features.gni")
import("//media/gpu/args.gni")
import("//skia/features.gni") import("//skia/features.gni")
import("//third_party/protobuf/proto_library.gni") import("//third_party/protobuf/proto_library.gni")
import("//ui/gl/features.gni") import("//ui/gl/features.gni")
...@@ -304,6 +305,7 @@ target(link_target_type, "gles2_sources") { ...@@ -304,6 +305,7 @@ target(link_target_type, "gles2_sources") {
"//gpu/config", "//gpu/config",
"//gpu/ipc/common", "//gpu/ipc/common",
"//gpu/vulkan:buildflags", "//gpu/vulkan:buildflags",
"//media/gpu:buildflags",
"//skia:buildflags", "//skia:buildflags",
"//third_party/angle:angle_image_util", "//third_party/angle:angle_image_util",
"//third_party/angle:commit_id", "//third_party/angle:commit_id",
...@@ -350,6 +352,9 @@ target(link_target_type, "gles2_sources") { ...@@ -350,6 +352,9 @@ target(link_target_type, "gles2_sources") {
"shared_image_representation_gl_ozone.cc", "shared_image_representation_gl_ozone.cc",
"shared_image_representation_gl_ozone.h", "shared_image_representation_gl_ozone.h",
] ]
if (use_vaapi) {
deps += [ "//media/gpu/vaapi:common" ]
}
} }
if (is_linux && use_dawn) { if (is_linux && use_dawn) {
......
...@@ -12,7 +12,17 @@ include_rules = [ ...@@ -12,7 +12,17 @@ include_rules = [
] ]
specific_include_rules = { specific_include_rules = {
"image_reader_gl_owner_unittest.cc": [ "image_reader_gl_owner_unittest\.cc": [
"+media/base/media_switches.h", "+media/base/media_switches.h",
], ],
"shared_image_backing_ozone\.cc": [
"+media/gpu/vaapi/vaapi_wrapper.h",
"+media/gpu/vaapi/va_surface.h",
],
"shared_image_representation\.cc": [
"+media/gpu/vaapi/va_surface.h",
],
"shared_image_.*\.h": [
"+media/gpu/buildflags.h",
],
} }
...@@ -78,6 +78,14 @@ SharedImageBacking::ProduceOverlay(SharedImageManager* manager, ...@@ -78,6 +78,14 @@ SharedImageBacking::ProduceOverlay(SharedImageManager* manager,
return nullptr; return nullptr;
} }
#if BUILDFLAG(USE_VAAPI)
std::unique_ptr<SharedImageRepresentationVaapi>
SharedImageBacking::ProduceVASurface(SharedImageManager* manager,
MemoryTypeTracker* tracker) {
return nullptr;
}
#endif
void SharedImageBacking::AddRef(SharedImageRepresentation* representation) { void SharedImageBacking::AddRef(SharedImageRepresentation* representation) {
AutoLock auto_lock(this); AutoLock auto_lock(this);
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "components/viz/common/resources/resource_format.h" #include "components/viz/common/resources/resource_format.h"
#include "gpu/command_buffer/common/mailbox.h" #include "gpu/command_buffer/common/mailbox.h"
#include "gpu/gpu_gles2_export.h" #include "gpu/gpu_gles2_export.h"
#include "media/gpu/buildflags.h"
#include "ui/gfx/color_space.h" #include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
...@@ -43,6 +44,7 @@ class SharedImageRepresentationGLTexturePassthrough; ...@@ -43,6 +44,7 @@ class SharedImageRepresentationGLTexturePassthrough;
class SharedImageRepresentationSkia; class SharedImageRepresentationSkia;
class SharedImageRepresentationDawn; class SharedImageRepresentationDawn;
class SharedImageRepresentationOverlay; class SharedImageRepresentationOverlay;
class SharedImageRepresentationVaapi;
class MemoryTypeTracker; class MemoryTypeTracker;
// Represents the actual storage (GL texture, VkImage, GMB) for a SharedImage. // Represents the actual storage (GL texture, VkImage, GMB) for a SharedImage.
...@@ -139,6 +141,11 @@ class GPU_GLES2_EXPORT SharedImageBacking { ...@@ -139,6 +141,11 @@ class GPU_GLES2_EXPORT SharedImageBacking {
virtual std::unique_ptr<SharedImageRepresentationOverlay> ProduceOverlay( virtual std::unique_ptr<SharedImageRepresentationOverlay> ProduceOverlay(
SharedImageManager* manager, SharedImageManager* manager,
MemoryTypeTracker* tracker); MemoryTypeTracker* tracker);
#if BUILDFLAG(USE_VAAPI)
virtual std::unique_ptr<SharedImageRepresentationVaapi> ProduceVASurface(
SharedImageManager* manager,
MemoryTypeTracker* tracker);
#endif
// Used by subclasses during destruction. // Used by subclasses during destruction.
bool have_context() const EXCLUSIVE_LOCKS_REQUIRED(lock_); bool have_context() const EXCLUSIVE_LOCKS_REQUIRED(lock_);
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
#include <memory> #include <memory>
#include <utility>
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
...@@ -42,6 +43,10 @@ ...@@ -42,6 +43,10 @@
#include "gpu/command_buffer/service/shared_image_representation_dawn_ozone.h" #include "gpu/command_buffer/service/shared_image_representation_dawn_ozone.h"
#endif // BUILDFLAG(USE_DAWN) #endif // BUILDFLAG(USE_DAWN)
#if BUILDFLAG(USE_VAAPI)
#include "media/gpu/vaapi/vaapi_wrapper.h"
#endif // BUILDFLAG(USE_VAAPI)
namespace gpu { namespace gpu {
namespace { namespace {
...@@ -95,7 +100,11 @@ std::unique_ptr<SharedImageBackingOzone> SharedImageBackingOzone::Create( ...@@ -95,7 +100,11 @@ std::unique_ptr<SharedImageBackingOzone> SharedImageBackingOzone::Create(
std::move(pixmap), std::move(dawn_procs))); std::move(pixmap), std::move(dawn_procs)));
} }
SharedImageBackingOzone::~SharedImageBackingOzone() = default; SharedImageBackingOzone::~SharedImageBackingOzone() {
#if BUILDFLAG(USE_VAAPI)
DCHECK(surface_->HasOneRef());
#endif
}
void SharedImageBackingOzone::Update(std::unique_ptr<gfx::GpuFence> in_fence) { void SharedImageBackingOzone::Update(std::unique_ptr<gfx::GpuFence> in_fence) {
NOTIMPLEMENTED_LOG_ONCE(); NOTIMPLEMENTED_LOG_ONCE();
...@@ -173,6 +182,34 @@ SharedImageBackingOzone::ProduceOverlay(SharedImageManager* manager, ...@@ -173,6 +182,34 @@ SharedImageBackingOzone::ProduceOverlay(SharedImageManager* manager,
return nullptr; return nullptr;
} }
#if BUILDFLAG(USE_VAAPI)
std::unique_ptr<SharedImageRepresentationVaapi>
SharedImageBackingOzone::ProduceVASurface(SharedImageManager* manager,
MemoryTypeTracker* tracker) {
DCHECK(pixmap_);
// We will only use |vaapi_wrapper_| to import surfaces and do
// synchronization, so the mode and profile is irrelevant.
// TODO(pwarren): Add a UMA callback to report VA-API errors.
if (!vaapi_wrapper_) {
DCHECK(!surface_);
vaapi_wrapper_ = media::VaapiWrapper::Create(
media::VaapiWrapper::CodecMode::kDecode, VAProfile::VAProfileNone,
/*report_error_to_uma_cb=*/base::DoNothing());
// We reuse the surface in subsequent calls to ProduceVASurface.
// |surface_| is self-cleaning. When all references are gone,
// VaapiWrapper::DestroySurface() is called for us.
surface_ = vaapi_wrapper_->CreateVASurfaceForPixmap(pixmap_);
}
DCHECK(surface_);
return std::make_unique<SharedImageRepresentationVaapi>(manager, this,
tracker, surface_);
}
#endif
SharedImageBackingOzone::SharedImageBackingOzone( SharedImageBackingOzone::SharedImageBackingOzone(
const Mailbox& mailbox, const Mailbox& mailbox,
viz::ResourceFormat format, viz::ResourceFormat format,
......
...@@ -21,11 +21,19 @@ ...@@ -21,11 +21,19 @@
#include "gpu/command_buffer/service/shared_image_manager.h" #include "gpu/command_buffer/service/shared_image_manager.h"
#include "gpu/command_buffer/service/shared_image_representation.h" #include "gpu/command_buffer/service/shared_image_representation.h"
#include "gpu/ipc/common/surface_handle.h" #include "gpu/ipc/common/surface_handle.h"
#include "media/gpu/buildflags.h"
#include "ui/gfx/color_space.h" #include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
#include "ui/gfx/gpu_fence.h" #include "ui/gfx/gpu_fence.h"
#include "ui/gfx/native_pixmap.h" #include "ui/gfx/native_pixmap.h"
#if BUILDFLAG(USE_VAAPI)
namespace media {
class VaapiWrapper;
class VASurface;
} // namespace media
#endif
namespace gpu { namespace gpu {
// Implementation of SharedImageBacking that uses a NativePixmap created via // Implementation of SharedImageBacking that uses a NativePixmap created via
...@@ -66,6 +74,11 @@ class SharedImageBackingOzone final : public ClearTrackingSharedImageBacking { ...@@ -66,6 +74,11 @@ class SharedImageBackingOzone final : public ClearTrackingSharedImageBacking {
std::unique_ptr<SharedImageRepresentationOverlay> ProduceOverlay( std::unique_ptr<SharedImageRepresentationOverlay> ProduceOverlay(
SharedImageManager* manager, SharedImageManager* manager,
MemoryTypeTracker* tracker) override; MemoryTypeTracker* tracker) override;
#if BUILDFLAG(USE_VAAPI)
std::unique_ptr<SharedImageRepresentationVaapi> ProduceVASurface(
SharedImageManager* manager,
MemoryTypeTracker* tracker) override;
#endif
private: private:
SharedImageBackingOzone( SharedImageBackingOzone(
...@@ -81,6 +94,15 @@ class SharedImageBackingOzone final : public ClearTrackingSharedImageBacking { ...@@ -81,6 +94,15 @@ class SharedImageBackingOzone final : public ClearTrackingSharedImageBacking {
scoped_refptr<gfx::NativePixmap> pixmap_; scoped_refptr<gfx::NativePixmap> pixmap_;
scoped_refptr<base::RefCountedData<DawnProcTable>> dawn_procs_; scoped_refptr<base::RefCountedData<DawnProcTable>> dawn_procs_;
#if BUILDFLAG(USE_VAAPI)
// Cached VA-API wrapper used to call the VA-API.
scoped_refptr<media::VaapiWrapper> vaapi_wrapper_;
// Cached VASurface that should be created once, and passed to all
// representations produced by this backing.
scoped_refptr<media::VASurface> surface_;
#endif
DISALLOW_COPY_AND_ASSIGN(SharedImageBackingOzone); DISALLOW_COPY_AND_ASSIGN(SharedImageBackingOzone);
}; };
......
...@@ -271,6 +271,31 @@ SharedImageManager::ProduceOverlay(const gpu::Mailbox& mailbox, ...@@ -271,6 +271,31 @@ SharedImageManager::ProduceOverlay(const gpu::Mailbox& mailbox,
return representation; return representation;
} }
#if BUILDFLAG(USE_VAAPI)
std::unique_ptr<SharedImageRepresentationVaapi>
SharedImageManager::ProduceVASurface(const Mailbox& mailbox,
MemoryTypeTracker* tracker) {
CALLED_ON_VALID_THREAD();
AutoLock autolock(this);
auto found = images_.find(mailbox);
if (found == images_.end()) {
LOG(ERROR) << "SharedImageManager::ProduceVASurface: Trying to produce a "
"VA-API representation from a non-existent mailbox.";
return nullptr;
}
auto representation = (*found)->ProduceVASurface(this, tracker);
if (!representation) {
LOG(ERROR) << "SharedImageManager::ProduceVASurface: Trying to produce a "
"VA-API representation from an incompatible mailbox.";
return nullptr;
}
return representation;
}
#endif
void SharedImageManager::OnRepresentationDestroyed( void SharedImageManager::OnRepresentationDestroyed(
const Mailbox& mailbox, const Mailbox& mailbox,
SharedImageRepresentation* representation) { SharedImageRepresentation* representation) {
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "gpu/command_buffer/common/mailbox.h" #include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/service/shared_image_backing.h" #include "gpu/command_buffer/service/shared_image_backing.h"
#include "gpu/gpu_gles2_export.h" #include "gpu/gpu_gles2_export.h"
#include "media/gpu/buildflags.h"
namespace gpu { namespace gpu {
class SharedImageRepresentationFactoryRef; class SharedImageRepresentationFactoryRef;
...@@ -63,6 +64,11 @@ class GPU_GLES2_EXPORT SharedImageManager { ...@@ -63,6 +64,11 @@ class GPU_GLES2_EXPORT SharedImageManager {
std::unique_ptr<SharedImageRepresentationOverlay> ProduceOverlay( std::unique_ptr<SharedImageRepresentationOverlay> ProduceOverlay(
const Mailbox& mailbox, const Mailbox& mailbox,
MemoryTypeTracker* ref); MemoryTypeTracker* ref);
#if BUILDFLAG(USE_VAAPI)
std::unique_ptr<SharedImageRepresentationVaapi> ProduceVASurface(
const Mailbox& mailbox,
MemoryTypeTracker* ref);
#endif
// Called by SharedImageRepresentation in the destructor. // Called by SharedImageRepresentation in the destructor.
void OnRepresentationDestroyed(const Mailbox& mailbox, void OnRepresentationDestroyed(const Mailbox& mailbox,
......
...@@ -7,6 +7,10 @@ ...@@ -7,6 +7,10 @@
#include "gpu/command_buffer/service/texture_manager.h" #include "gpu/command_buffer/service/texture_manager.h"
#include "third_party/skia/include/core/SkPromiseImageTexture.h" #include "third_party/skia/include/core/SkPromiseImageTexture.h"
#if BUILDFLAG(USE_VAAPI)
#include "media/gpu/vaapi/va_surface.h"
#endif
namespace gpu { namespace gpu {
SharedImageRepresentation::SharedImageRepresentation( SharedImageRepresentation::SharedImageRepresentation(
...@@ -213,4 +217,36 @@ SharedImageRepresentationFactoryRef::~SharedImageRepresentationFactoryRef() { ...@@ -213,4 +217,36 @@ SharedImageRepresentationFactoryRef::~SharedImageRepresentationFactoryRef() {
backing()->MarkForDestruction(); backing()->MarkForDestruction();
} }
#if BUILDFLAG(USE_VAAPI)
SharedImageRepresentationVaapi::SharedImageRepresentationVaapi(
SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker,
scoped_refptr<media::VASurface> va_surface)
: SharedImageRepresentation(manager, backing, tracker),
va_surface_(std::move(va_surface)) {}
SharedImageRepresentationVaapi::~SharedImageRepresentationVaapi() = default;
SharedImageRepresentationVaapi::ScopedWriteAccess::ScopedWriteAccess(
util::PassKey<SharedImageRepresentationVaapi> /* pass_key */,
SharedImageRepresentationVaapi* representation)
: ScopedAccessBase(representation) {}
SharedImageRepresentationVaapi::ScopedWriteAccess::~ScopedWriteAccess() {
representation()->EndAccess();
}
const media::VASurface*
SharedImageRepresentationVaapi::ScopedWriteAccess::va_surface() const {
return representation()->va_surface_.get();
}
std::unique_ptr<SharedImageRepresentationVaapi::ScopedWriteAccess>
SharedImageRepresentationVaapi::BeginScopedWriteAccess() {
return std::make_unique<ScopedWriteAccess>(
util::PassKey<SharedImageRepresentationVaapi>(), this);
}
#endif
} // namespace gpu } // namespace gpu
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "gpu/command_buffer/service/shared_image_backing.h" #include "gpu/command_buffer/service/shared_image_backing.h"
#include "gpu/command_buffer/service/shared_image_manager.h" #include "gpu/command_buffer/service/shared_image_manager.h"
#include "gpu/gpu_gles2_export.h" #include "gpu/gpu_gles2_export.h"
#include "media/gpu/buildflags.h"
#include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/core/SkSurface.h"
#include "ui/gfx/color_space.h" #include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
...@@ -28,6 +29,12 @@ namespace gl { ...@@ -28,6 +29,12 @@ namespace gl {
class GLImage; class GLImage;
} }
#if BUILDFLAG(USE_VAAPI)
namespace media {
class VASurface;
}
#endif
namespace gpu { namespace gpu {
class TextureBase; class TextureBase;
...@@ -94,7 +101,7 @@ class GPU_GLES2_EXPORT SharedImageRepresentation { ...@@ -94,7 +101,7 @@ class GPU_GLES2_EXPORT SharedImageRepresentation {
representation_->has_scoped_access_ = false; representation_->has_scoped_access_ = false;
} }
RepresentationClass* representation() { return representation_; } RepresentationClass* representation() const { return representation_; }
private: private:
RepresentationClass* const representation_; RepresentationClass* const representation_;
...@@ -374,6 +381,52 @@ class GPU_GLES2_EXPORT SharedImageRepresentationOverlay ...@@ -374,6 +381,52 @@ class GPU_GLES2_EXPORT SharedImageRepresentationOverlay
virtual gl::GLImage* GetGLImage() = 0; virtual gl::GLImage* GetGLImage() = 0;
}; };
// Representation of a SharedImageBacking as a VA-API surface.
// This representation is currently only supported by SharedImageBackingOzone.
//
// Synchronized access is currently not required in this representation because:
//
// For reads:
// We will be using this for the destination of decoding work, so no read access
// synchronization is needed from the point of view of the VA-API.
//
// For writes:
// Because of the design of the current video pipeline, we don't start the
// decoding work until we're sure that the destination buffer is not being used
// by the rest of the pipeline. However, we still need to keep track of write
// accesses so that other representations can synchronize with the decoder.
//
// TODO(pwarren): create subclass SharedImageRepresentationVaapiOzone that
// implements EndAccess.
#if BUILDFLAG(USE_VAAPI)
class GPU_GLES2_EXPORT SharedImageRepresentationVaapi
: public SharedImageRepresentation {
public:
class GPU_GLES2_EXPORT ScopedWriteAccess
: public ScopedAccessBase<SharedImageRepresentationVaapi> {
public:
ScopedWriteAccess(util::PassKey<SharedImageRepresentationVaapi> pass_key,
SharedImageRepresentationVaapi* representation);
~ScopedWriteAccess();
const media::VASurface* va_surface() const;
};
SharedImageRepresentationVaapi(SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker,
scoped_refptr<media::VASurface> va_surface);
~SharedImageRepresentationVaapi() override;
std::unique_ptr<ScopedWriteAccess> BeginScopedWriteAccess();
private:
scoped_refptr<media::VASurface> va_surface_;
// TODO(pwarren): Make EndAccess purely virtual.
virtual void EndAccess() {}
};
#endif
} // namespace gpu } // namespace gpu
#endif // GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_REPRESENTATION_H_ #endif // GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_REPRESENTATION_H_
...@@ -100,6 +100,10 @@ gles2::Texture* SharedImageRepresentationGLOzone::GetTexture() { ...@@ -100,6 +100,10 @@ gles2::Texture* SharedImageRepresentationGLOzone::GetTexture() {
bool SharedImageRepresentationGLOzone::BeginAccess(GLenum mode) { bool SharedImageRepresentationGLOzone::BeginAccess(GLenum mode) {
// TODO(hob): Synchronize access to the dma-buf by waiting on all semaphores // TODO(hob): Synchronize access to the dma-buf by waiting on all semaphores
// tracked by SharedImageBackingOzone. // tracked by SharedImageBackingOzone.
//
// TODO(pwarren): When this representation is involved with a VA-API decode,
// we must call VaapiWrapper::SyncSurface() to ensure all VA-API work is done
// prior to using the buffer in a graphics API.
return true; return true;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment