Commit 8b7817c7 authored by Christopher Cameron's avatar Christopher Cameron Committed by Commit Bot

Enable SharedImages for VTVideoDecodeAccelerator

Add a method to media::VideoDecodeAccelerator to indicate whether
SharedImage-backed picture buffers are supported. Make this return
true only for the VTVideoDecodeAccelerator.

Add a parameter to media::PictureBufferManager::CreatePictureBuffers
to indicate if SharedImage-backed PictureBuffers are desired.

Hook the two of these together in the ProvidePictureBuffersAsync
method of media::VdaVideoDecoder.

Video playback fails with the Metal-based command decoder, because
it binds IOSurfaces as TEXTURE_2D, not TEXTURE_RECTANGLE. Plumb
through a flag to specify if TEXTURE_RECTANGLE support is present.

Bug: 1108909
Change-Id: I1e42aa38e122714517724cee87eb51987645e410
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2427545
Commit-Queue: ccameron <ccameron@chromium.org>
Reviewed-by: default avatarccameron <ccameron@chromium.org>
Reviewed-by: default avatarDan Sanders <sandersd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#811077}
parent c6a5f505
...@@ -199,6 +199,15 @@ class CommandBufferHelperImpl ...@@ -199,6 +199,15 @@ class CommandBufferHelperImpl
->is_passthrough_cmd_decoder(); ->is_passthrough_cmd_decoder();
} }
bool SupportsTextureRectangle() const override {
if (!stub_)
return false;
return stub_->decoder_context()
->GetFeatureInfo()
->feature_flags()
.arb_texture_rectangle;
}
private: private:
~CommandBufferHelperImpl() override { ~CommandBufferHelperImpl() override {
DVLOG(1) << __func__; DVLOG(1) << __func__;
......
...@@ -137,6 +137,9 @@ class MEDIA_GPU_EXPORT CommandBufferHelper ...@@ -137,6 +137,9 @@ class MEDIA_GPU_EXPORT CommandBufferHelper
// Is the backing command buffer passthrough (versus validating). // Is the backing command buffer passthrough (versus validating).
virtual bool IsPassthrough() const = 0; virtual bool IsPassthrough() const = 0;
// Does this command buffer support ARB_texture_rectangle.
virtual bool SupportsTextureRectangle() const = 0;
protected: protected:
explicit CommandBufferHelper( explicit CommandBufferHelper(
scoped_refptr<base::SequencedTaskRunner> task_runner); scoped_refptr<base::SequencedTaskRunner> task_runner);
......
...@@ -112,6 +112,9 @@ struct MEDIA_GPU_EXPORT GpuVideoDecodeGLClient { ...@@ -112,6 +112,9 @@ struct MEDIA_GPU_EXPORT GpuVideoDecodeGLClient {
// Whether or not the command buffer is passthrough. // Whether or not the command buffer is passthrough.
bool is_passthrough = false; bool is_passthrough = false;
// Whether or not ARB_texture_rectangle is present.
bool supports_arb_texture_rectangle = false;
}; };
// Convert vector of VDA::SupportedProfile to vector of // Convert vector of VDA::SupportedProfile to vector of
......
...@@ -191,6 +191,10 @@ GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator( ...@@ -191,6 +191,10 @@ GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator(
base::BindRepeating(&CreateAbstractTexture, stub_->AsWeakPtr()); base::BindRepeating(&CreateAbstractTexture, stub_->AsWeakPtr());
gl_client_.is_passthrough = gl_client_.is_passthrough =
stub_->decoder_context()->GetFeatureInfo()->is_passthrough_cmd_decoder(); stub_->decoder_context()->GetFeatureInfo()->is_passthrough_cmd_decoder();
gl_client_.supports_arb_texture_rectangle = stub_->decoder_context()
->GetFeatureInfo()
->feature_flags()
.arb_texture_rectangle;
} }
GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() { GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() {
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/synchronization/lock.h" #include "base/synchronization/lock.h"
#include "base/thread_annotations.h" #include "base/thread_annotations.h"
#include "build/build_config.h"
#include "gpu/command_buffer/common/mailbox_holder.h" #include "gpu/command_buffer/common/mailbox_holder.h"
#include "media/base/video_util.h" #include "media/base/video_util.h"
...@@ -27,11 +28,6 @@ int32_t NextID(int32_t* counter) { ...@@ -27,11 +28,6 @@ int32_t NextID(int32_t* counter) {
return value; return value;
} }
bool UseSharedImage() {
// TODO(https://crbug.com/1108909): Enable shared image use on macOS.
return false;
}
class PictureBufferManagerImpl : public PictureBufferManager { class PictureBufferManagerImpl : public PictureBufferManager {
public: public:
explicit PictureBufferManagerImpl( explicit PictureBufferManagerImpl(
...@@ -79,7 +75,8 @@ class PictureBufferManagerImpl : public PictureBufferManager { ...@@ -79,7 +75,8 @@ class PictureBufferManagerImpl : public PictureBufferManager {
VideoPixelFormat pixel_format, VideoPixelFormat pixel_format,
uint32_t planes, uint32_t planes,
gfx::Size texture_size, gfx::Size texture_size,
uint32_t texture_target) override { uint32_t texture_target,
bool use_shared_image) override {
DVLOG(2) << __func__; DVLOG(2) << __func__;
DCHECK(gpu_task_runner_); DCHECK(gpu_task_runner_);
DCHECK(gpu_task_runner_->BelongsToCurrentThread()); DCHECK(gpu_task_runner_->BelongsToCurrentThread());
...@@ -87,7 +84,7 @@ class PictureBufferManagerImpl : public PictureBufferManager { ...@@ -87,7 +84,7 @@ class PictureBufferManagerImpl : public PictureBufferManager {
DCHECK(planes); DCHECK(planes);
DCHECK_LE(planes, static_cast<uint32_t>(VideoFrame::kMaxPlanes)); DCHECK_LE(planes, static_cast<uint32_t>(VideoFrame::kMaxPlanes));
if (!UseSharedImage()) { if (!use_shared_image) {
// TODO(sandersd): Consider requiring that CreatePictureBuffers() is // TODO(sandersd): Consider requiring that CreatePictureBuffers() is
// called with the context current. // called with the context current.
if (!command_buffer_helper_->MakeContextCurrent()) { if (!command_buffer_helper_->MakeContextCurrent()) {
...@@ -98,9 +95,10 @@ class PictureBufferManagerImpl : public PictureBufferManager { ...@@ -98,9 +95,10 @@ class PictureBufferManagerImpl : public PictureBufferManager {
std::vector<PictureBuffer> picture_buffers; std::vector<PictureBuffer> picture_buffers;
for (uint32_t i = 0; i < count; i++) { for (uint32_t i = 0; i < count; i++) {
PictureBufferData picture_data = {pixel_format, texture_size}; PictureBufferData picture_data = {pixel_format, texture_size,
use_shared_image};
if (!UseSharedImage()) { if (!use_shared_image) {
for (uint32_t j = 0; j < planes; j++) { for (uint32_t j = 0; j < planes; j++) {
// Create a texture for this plane. // Create a texture for this plane.
GLuint service_id = command_buffer_helper_->CreateTexture( GLuint service_id = command_buffer_helper_->CreateTexture(
...@@ -219,7 +217,8 @@ class PictureBufferManagerImpl : public PictureBufferManager { ...@@ -219,7 +217,8 @@ class PictureBufferManagerImpl : public PictureBufferManager {
// If this |picture| has a SharedImage, then keep a reference to the // If this |picture| has a SharedImage, then keep a reference to the
// SharedImage in |picture_buffer_data| and update the gpu::MailboxHolder. // SharedImage in |picture_buffer_data| and update the gpu::MailboxHolder.
DCHECK_EQ(UseSharedImage(), !!picture.scoped_shared_image()); DCHECK_EQ(picture_buffer_data.use_shared_image,
!!picture.scoped_shared_image());
if (auto scoped_shared_image = picture.scoped_shared_image()) { if (auto scoped_shared_image = picture.scoped_shared_image()) {
picture_buffer_data.scoped_shared_image = scoped_shared_image; picture_buffer_data.scoped_shared_image = scoped_shared_image;
picture_buffer_data.mailbox_holders[0] = picture_buffer_data.mailbox_holders[0] =
...@@ -350,6 +349,7 @@ class PictureBufferManagerImpl : public PictureBufferManager { ...@@ -350,6 +349,7 @@ class PictureBufferManagerImpl : public PictureBufferManager {
struct PictureBufferData { struct PictureBufferData {
VideoPixelFormat pixel_format; VideoPixelFormat pixel_format;
gfx::Size texture_size; gfx::Size texture_size;
bool use_shared_image = false;
std::vector<GLuint> service_ids; std::vector<GLuint> service_ids;
gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes]; gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes];
scoped_refptr<Picture::ScopedSharedImage> scoped_shared_image; scoped_refptr<Picture::ScopedSharedImage> scoped_shared_image;
......
...@@ -62,6 +62,7 @@ class PictureBufferManager ...@@ -62,6 +62,7 @@ class PictureBufferManager
// |planes|: Number of image planes (textures) in the picture. // |planes|: Number of image planes (textures) in the picture.
// |texture_size|: Size of textures to create. // |texture_size|: Size of textures to create.
// |texture_target|: Type of textures to create. // |texture_target|: Type of textures to create.
// |use_shared_image|: True if the created buffers should use shared images.
// //
// Must be called on the GPU thread. // Must be called on the GPU thread.
// //
...@@ -77,7 +78,8 @@ class PictureBufferManager ...@@ -77,7 +78,8 @@ class PictureBufferManager
VideoPixelFormat pixel_format, VideoPixelFormat pixel_format,
uint32_t planes, uint32_t planes,
gfx::Size texture_size, gfx::Size texture_size,
uint32_t texture_target) = 0; uint32_t texture_target,
bool use_shared_image) = 0;
// Dismisses a picture buffer from the pool. // Dismisses a picture buffer from the pool.
// //
......
...@@ -41,7 +41,8 @@ class PictureBufferManagerImplTest : public testing::Test { ...@@ -41,7 +41,8 @@ class PictureBufferManagerImplTest : public testing::Test {
std::vector<PictureBuffer> CreateARGBPictureBuffers(uint32_t count) { std::vector<PictureBuffer> CreateARGBPictureBuffers(uint32_t count) {
return pbm_->CreatePictureBuffers(count, PIXEL_FORMAT_ARGB, 1, return pbm_->CreatePictureBuffers(count, PIXEL_FORMAT_ARGB, 1,
gfx::Size(320, 240), GL_TEXTURE_2D); gfx::Size(320, 240), GL_TEXTURE_2D,
false /* use_shared_image */);
} }
PictureBuffer CreateARGBPictureBuffer() { PictureBuffer CreateARGBPictureBuffer() {
......
...@@ -76,6 +76,8 @@ std::unique_ptr<VideoDecodeAccelerator> CreateAndInitializeVda( ...@@ -76,6 +76,8 @@ std::unique_ptr<VideoDecodeAccelerator> CreateAndInitializeVda(
&CommandBufferHelper::MakeContextCurrent, command_buffer_helper); &CommandBufferHelper::MakeContextCurrent, command_buffer_helper);
gl_client.bind_image = base::BindRepeating(&BindImage, command_buffer_helper); gl_client.bind_image = base::BindRepeating(&BindImage, command_buffer_helper);
gl_client.is_passthrough = command_buffer_helper->IsPassthrough(); gl_client.is_passthrough = command_buffer_helper->IsPassthrough();
gl_client.supports_arb_texture_rectangle =
command_buffer_helper->SupportsTextureRectangle();
std::unique_ptr<GpuVideoDecodeAcceleratorFactory> factory = std::unique_ptr<GpuVideoDecodeAcceleratorFactory> factory =
GpuVideoDecodeAcceleratorFactory::Create(gl_client); GpuVideoDecodeAcceleratorFactory::Create(gl_client);
...@@ -539,7 +541,8 @@ void VdaVideoDecoder::ProvidePictureBuffersAsync(uint32_t count, ...@@ -539,7 +541,8 @@ void VdaVideoDecoder::ProvidePictureBuffersAsync(uint32_t count,
std::vector<PictureBuffer> picture_buffers = std::vector<PictureBuffer> picture_buffers =
picture_buffer_manager_->CreatePictureBuffers( picture_buffer_manager_->CreatePictureBuffers(
count, pixel_format, planes, texture_size, texture_target); count, pixel_format, planes, texture_size, texture_target,
vda_->SupportsSharedImagePictureBuffers());
if (picture_buffers.empty()) { if (picture_buffers.empty()) {
parent_task_runner_->PostTask( parent_task_runner_->PostTask(
FROM_HERE, FROM_HERE,
......
...@@ -1533,7 +1533,10 @@ bool VTVideoDecodeAccelerator::SendFrame(const Frame& frame) { ...@@ -1533,7 +1533,10 @@ bool VTVideoDecodeAccelerator::SendFrame(const Frame& frame) {
gpu::Mailbox mailbox = gpu::Mailbox::GenerateForSharedImage(); gpu::Mailbox mailbox = gpu::Mailbox::GenerateForSharedImage();
gpu::SharedImageBackingGLCommon::InitializeGLTextureParams gl_params; gpu::SharedImageBackingGLCommon::InitializeGLTextureParams gl_params;
gl_params.target = GL_TEXTURE_RECTANGLE_ARB; // ANGLE-on-Metal exposes IOSurfaces via GL_TEXTURE_2D. Be robust to that.
gl_params.target = gl_client_.supports_arb_texture_rectangle
? GL_TEXTURE_RECTANGLE_ARB
: GL_TEXTURE_2D;
gl_params.internal_format = gl_format; gl_params.internal_format = gl_format;
gl_params.format = gl_format; gl_params.format = gl_format;
gl_params.type = GL_UNSIGNED_BYTE; gl_params.type = GL_UNSIGNED_BYTE;
...@@ -1567,7 +1570,7 @@ bool VTVideoDecodeAccelerator::SendFrame(const Frame& frame) { ...@@ -1567,7 +1570,7 @@ bool VTVideoDecodeAccelerator::SendFrame(const Frame& frame) {
gpu_task_runner_); gpu_task_runner_);
scoped_shared_image = scoped_refptr<Picture::ScopedSharedImage>( scoped_shared_image = scoped_refptr<Picture::ScopedSharedImage>(
new Picture::ScopedSharedImage( new Picture::ScopedSharedImage(
mailbox, GL_TEXTURE_RECTANGLE_ARB, mailbox, gl_params.target,
std::move(destroy_shared_image_callback))); std::move(destroy_shared_image_callback)));
} else { } else {
if (!gl_client_.bind_image.Run(picture_info->client_texture_id, if (!gl_client_.bind_image.Run(picture_info->client_texture_id,
...@@ -1687,6 +1690,10 @@ bool VTVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread( ...@@ -1687,6 +1690,10 @@ bool VTVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
return false; return false;
} }
bool VTVideoDecodeAccelerator::SupportsSharedImagePictureBuffers() const {
return true;
}
// static // static
VideoDecodeAccelerator::SupportedProfiles VideoDecodeAccelerator::SupportedProfiles
VTVideoDecodeAccelerator::GetSupportedProfiles() { VTVideoDecodeAccelerator::GetSupportedProfiles() {
......
...@@ -63,6 +63,7 @@ class VTVideoDecodeAccelerator : public VideoDecodeAccelerator, ...@@ -63,6 +63,7 @@ class VTVideoDecodeAccelerator : public VideoDecodeAccelerator,
const base::WeakPtr<Client>& decode_client, const base::WeakPtr<Client>& decode_client,
const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner)
override; override;
bool SupportsSharedImagePictureBuffers() const override;
// MemoryDumpProvider implementation. // MemoryDumpProvider implementation.
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
......
...@@ -168,4 +168,8 @@ bool FakeCommandBufferHelper::IsPassthrough() const { ...@@ -168,4 +168,8 @@ bool FakeCommandBufferHelper::IsPassthrough() const {
return false; return false;
} }
bool FakeCommandBufferHelper::SupportsTextureRectangle() const {
return false;
}
} // namespace media } // namespace media
...@@ -62,6 +62,7 @@ class FakeCommandBufferHelper : public CommandBufferHelper { ...@@ -62,6 +62,7 @@ class FakeCommandBufferHelper : public CommandBufferHelper {
base::OnceClosure done_cb) override; base::OnceClosure done_cb) override;
void SetWillDestroyStubCB(WillDestroyStubCB will_destroy_stub_cb) override; void SetWillDestroyStubCB(WillDestroyStubCB will_destroy_stub_cb) override;
bool IsPassthrough() const override; bool IsPassthrough() const override;
bool SupportsTextureRectangle() const override;
private: private:
~FakeCommandBufferHelper() override; ~FakeCommandBufferHelper() override;
......
...@@ -101,6 +101,10 @@ GLenum VideoDecodeAccelerator::GetSurfaceInternalFormat() const { ...@@ -101,6 +101,10 @@ GLenum VideoDecodeAccelerator::GetSurfaceInternalFormat() const {
return GL_RGBA; return GL_RGBA;
} }
bool VideoDecodeAccelerator::SupportsSharedImagePictureBuffers() const {
return false;
}
VideoDecodeAccelerator::SupportedProfile::SupportedProfile() VideoDecodeAccelerator::SupportedProfile::SupportedProfile()
: profile(media::VIDEO_CODEC_PROFILE_UNKNOWN), encrypted_only(false) {} : profile(media::VIDEO_CODEC_PROFILE_UNKNOWN), encrypted_only(false) {}
......
...@@ -414,6 +414,10 @@ class MEDIA_EXPORT VideoDecodeAccelerator { ...@@ -414,6 +414,10 @@ class MEDIA_EXPORT VideoDecodeAccelerator {
// TODO(dshwang): after moving to D3D11, remove this. crbug.com/438691 // TODO(dshwang): after moving to D3D11, remove this. crbug.com/438691
virtual GLenum GetSurfaceInternalFormat() const; virtual GLenum GetSurfaceInternalFormat() const;
// Returns true if the decoder supports SharedImage backed picture buffers.
// May be called on any thread at any time.
virtual bool SupportsSharedImagePictureBuffers() const;
protected: protected:
// Do not delete directly; use Destroy() or own it with a scoped_ptr, which // Do not delete directly; use Destroy() or own it with a scoped_ptr, which
// will Destroy() it properly by default. // will Destroy() it properly by default.
......
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