Commit 5e3de235 authored by Christopher Cameron's avatar Christopher Cameron Committed by Commit Bot

Add blink::Picture::ScopedSharedImage

Create a blink::Picture::ScopedSharedImage structure, which will
keep a SharedImage alive as long as it is alive. This will be
used to pass a SharedImage from the hardware decoder across to
the VTVideoDecodeAccelerator.

The PictureBufferManager is where the decision about use of
SharedImage will be made. It will be sent to the
VTVideoDecodeAccelerator by specifying an empty PictureBuffer.

Bug: 1108909
Change-Id: Iabb71b1b69dd922dc44aca3821f243fcdd22c6d2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2377419
Commit-Queue: ccameron <ccameron@chromium.org>
Reviewed-by: default avatarDan Sanders <sandersd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#802723}
parent 546db6c3
......@@ -992,6 +992,12 @@ bool VideoFrame::IsMappable() const {
}
bool VideoFrame::HasTextures() const {
// A SharedImage can be turned into a texture, and so it counts as a texture
// in the context of this call.
if (mailbox_holders_[0].mailbox.IsSharedImage())
return true;
DCHECK(!wrapped_frame_ || !wrapped_frame_->HasTextures());
return wrapped_frame_ ? wrapped_frame_->HasTextures()
: !mailbox_holders_[0].mailbox.IsZero();
}
......
......@@ -27,6 +27,11 @@ int32_t NextID(int32_t* counter) {
return value;
}
bool UseSharedImage() {
// TODO(https://crbug.com/1108909): Enable shared image use on macOS.
return false;
}
class PictureBufferManagerImpl : public PictureBufferManager {
public:
explicit PictureBufferManagerImpl(
......@@ -82,17 +87,20 @@ class PictureBufferManagerImpl : public PictureBufferManager {
DCHECK(planes);
DCHECK_LE(planes, static_cast<uint32_t>(VideoFrame::kMaxPlanes));
// TODO(sandersd): Consider requiring that CreatePictureBuffers() is called
// with the context current.
if (!UseSharedImage()) {
// TODO(sandersd): Consider requiring that CreatePictureBuffers() is
// called with the context current.
if (!command_buffer_helper_->MakeContextCurrent()) {
DVLOG(1) << "Failed to make context current";
return std::vector<PictureBuffer>();
}
}
std::vector<PictureBuffer> picture_buffers;
for (uint32_t i = 0; i < count; i++) {
PictureBufferData picture_data = {pixel_format, texture_size};
if (!UseSharedImage()) {
for (uint32_t j = 0; j < planes; j++) {
// Create a texture for this plane.
GLuint service_id = command_buffer_helper_->CreateTexture(
......@@ -101,15 +109,16 @@ class PictureBufferManagerImpl : public PictureBufferManager {
DCHECK(service_id);
picture_data.service_ids.push_back(service_id);
// The texture is not cleared yet, but it will be before the VDA outputs
// it. Rather than requiring output to happen on the GPU thread, mark
// the texture as cleared immediately.
// The texture is not cleared yet, but it will be before the VDA
// outputs it. Rather than requiring output to happen on the GPU
// thread, mark the texture as cleared immediately.
command_buffer_helper_->SetCleared(service_id);
// Generate a mailbox while we are still on the GPU thread.
picture_data.mailbox_holders[j] = gpu::MailboxHolder(
command_buffer_helper_->CreateMailbox(service_id), gpu::SyncToken(),
texture_target);
command_buffer_helper_->CreateMailbox(service_id),
gpu::SyncToken(), texture_target);
}
}
// Generate a picture buffer ID and record the picture buffer.
......@@ -208,6 +217,15 @@ class PictureBufferManagerImpl : public PictureBufferManager {
// Record the output.
picture_buffer_data.output_count++;
// If this |picture| has a SharedImage, then keep a reference to the
// SharedImage in |picture_buffer_data| and update the gpu::MailboxHolder.
DCHECK_EQ(UseSharedImage(), !!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.mailbox_holders[0] =
scoped_shared_image->GetMailboxHolder();
}
// Create and return a VideoFrame for the picture buffer.
scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTextures(
picture_buffer_data.pixel_format, picture_buffer_data.mailbox_holders,
......@@ -297,6 +315,7 @@ class PictureBufferManagerImpl : public PictureBufferManager {
DCHECK(gpu_task_runner_->BelongsToCurrentThread());
std::vector<GLuint> service_ids;
scoped_refptr<Picture::ScopedSharedImage> scoped_shared_image;
{
base::AutoLock lock(picture_buffers_lock_);
const auto& it = picture_buffers_.find(picture_buffer_id);
......@@ -304,9 +323,16 @@ class PictureBufferManagerImpl : public PictureBufferManager {
DCHECK(it->second.dismissed);
DCHECK(!it->second.IsInUse());
service_ids = std::move(it->second.service_ids);
scoped_shared_image = std::move(it->second.scoped_shared_image);
picture_buffers_.erase(it);
}
// If this PictureBuffer is using a SharedImage, let it fall out of scope.
if (scoped_shared_image) {
DCHECK(service_ids.empty());
return;
}
if (!command_buffer_helper_->MakeContextCurrent())
return;
......@@ -326,6 +352,7 @@ class PictureBufferManagerImpl : public PictureBufferManager {
gfx::Size texture_size;
std::vector<GLuint> service_ids;
gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes];
scoped_refptr<Picture::ScopedSharedImage> scoped_shared_image;
bool dismissed = false;
// The same picture buffer can be output from the VDA multiple times
......
......@@ -32,7 +32,6 @@ PictureBuffer::PictureBuffer(int32_t id,
service_texture_ids_(service_texture_ids),
texture_target_(texture_target),
pixel_format_(pixel_format) {
DCHECK(!service_texture_ids_.empty());
// We either not have client texture ids at all, or if we do, then their
// number must be the same as the number of service texture ids.
DCHECK(client_texture_ids_.empty() ||
......@@ -86,4 +85,15 @@ Picture::Picture(const Picture& other) = default;
Picture::~Picture() = default;
Picture::ScopedSharedImage::ScopedSharedImage(
gpu::Mailbox mailbox,
uint32_t texture_target,
base::OnceClosure destruction_closure)
: destruction_closure_(std::move(destruction_closure)),
mailbox_holder_(mailbox, gpu::SyncToken(), texture_target) {}
Picture::ScopedSharedImage::~ScopedSharedImage() {
std::move(destruction_closure_).Run();
}
} // namespace media
......@@ -9,7 +9,9 @@
#include <vector>
#include "gpu/command_buffer/common/mailbox.h"
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
#include "media/base/media_export.h"
#include "media/base/video_types.h"
#include "ui/gfx/color_space.h"
......@@ -78,6 +80,26 @@ class MEDIA_EXPORT PictureBuffer {
// This is the media-namespace equivalent of PP_Picture_Dev.
class MEDIA_EXPORT Picture {
public:
// An object that keeps alive a SharedImage until it goes out of scope.
// Used to manage the lifetime of SharedImage-backed decoded frames.
class MEDIA_EXPORT ScopedSharedImage
: public base::RefCountedThreadSafe<ScopedSharedImage> {
public:
ScopedSharedImage(gpu::Mailbox mailbox,
uint32_t texture_target,
base::OnceClosure destruction_closure);
const gpu::MailboxHolder& GetMailboxHolder() const {
return mailbox_holder_;
}
private:
friend class base::RefCountedThreadSafe<ScopedSharedImage>;
~ScopedSharedImage();
base::OnceClosure destruction_closure_;
gpu::MailboxHolder mailbox_holder_;
};
// Defaults |size_changed_| to false. Size changed is currently only used
// by AVDA and is set via set_size_changd().
Picture(int32_t picture_buffer_id,
......@@ -128,6 +150,14 @@ class MEDIA_EXPORT Picture {
wants_promotion_hint_ = wants_promotion_hint;
}
void set_scoped_shared_image(
scoped_refptr<ScopedSharedImage> scoped_shared_image) {
scoped_shared_image_ = scoped_shared_image;
}
scoped_refptr<ScopedSharedImage> scoped_shared_image() const {
return scoped_shared_image_;
}
private:
int32_t picture_buffer_id_;
int32_t bitstream_buffer_id_;
......@@ -138,6 +168,7 @@ class MEDIA_EXPORT Picture {
bool size_changed_;
bool texture_owner_;
bool wants_promotion_hint_;
scoped_refptr<ScopedSharedImage> scoped_shared_image_;
};
} // namespace media
......
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