Commit 79812c1a authored by achaulk's avatar achaulk Committed by Commit bot

vaapi plumbing to allow hardware video overlays

Uses ozone GLImage instead of GLImageLinuxDMABuffer and binds it in the
TextureManager, this lets it be scheduled as an overlay

BUG=370522
TEST=loaded on device (with 812913003, 806413004, 855403002, 810343004), play h264 video, verify that overlays are used and no artifacts are produced)

Review URL: https://codereview.chromium.org/858653002

Cr-Commit-Position: refs/heads/master@{#314376}
parent 8e47fd58
......@@ -22,6 +22,7 @@
#include "ipc/message_filter.h"
#include "media/base/limits.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_image.h"
#include "ui/gl/gl_surface_egl.h"
#if defined(OS_WIN)
......@@ -336,11 +337,24 @@ GpuVideoDecodeAccelerator::CreateV4L2SliceVDA() {
return decoder.Pass();
}
void GpuVideoDecodeAccelerator::BindImage(uint32 client_texture_id,
uint32 texture_target,
scoped_refptr<gfx::GLImage> image) {
gpu::gles2::GLES2Decoder* command_decoder = stub_->decoder();
gpu::gles2::TextureManager* texture_manager =
command_decoder->GetContextGroup()->texture_manager();
gpu::gles2::TextureRef* ref = texture_manager->GetTexture(client_texture_id);
if (ref)
texture_manager->SetLevelImage(ref, texture_target, 0, image.get());
}
scoped_ptr<media::VideoDecodeAccelerator>
GpuVideoDecodeAccelerator::CreateVaapiVDA() {
scoped_ptr<media::VideoDecodeAccelerator> decoder;
#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
decoder.reset(new VaapiVideoDecodeAccelerator(make_context_current_));
decoder.reset(new VaapiVideoDecodeAccelerator(
make_context_current_, base::Bind(&GpuVideoDecodeAccelerator::BindImage,
base::Unretained(this))));
#endif
return decoder.Pass();
}
......@@ -467,15 +481,9 @@ void GpuVideoDecodeAccelerator::OnAssignPictureBuffers(
width, height, 1, 0, format, 0, false);
}
}
uint32 service_texture_id;
if (!command_decoder->GetServiceTextureId(
texture_ids[i], &service_texture_id)) {
DLOG(ERROR) << "Failed to translate texture!";
NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
return;
}
buffers.push_back(media::PictureBuffer(
buffer_ids[i], texture_dimensions_, service_texture_id));
buffers.push_back(media::PictureBuffer(buffer_ids[i], texture_dimensions_,
texture_ref->service_id(),
texture_ids[i]));
textures.push_back(texture_ref);
}
video_decode_accelerator_->AssignPictureBuffers(buffers);
......
......@@ -104,6 +104,11 @@ class GpuVideoDecodeAccelerator
// Helper for replying to the creation request.
void SendCreateDecoderReply(IPC::Message* message, bool succeeded);
// Helper to bind |image| to the texture specified by |client_texture_id|.
void BindImage(uint32 client_texture_id,
uint32 texture_target,
scoped_refptr<gfx::GLImage> image);
// Route ID to communicate with the host.
int32 host_route_id_;
......
......@@ -13,6 +13,7 @@
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_image_linux_dma_buffer.h"
#include "ui/gl/scoped_binders.h"
#include "ui/ozone/gpu/gpu_memory_buffer_factory_ozone_native_buffer.h"
#include "ui/ozone/public/native_pixmap.h"
#include "ui/ozone/public/ozone_platform.h"
#include "ui/ozone/public/surface_factory_ozone.h"
......@@ -101,17 +102,14 @@ bool VaapiDrmPicture::Initialize() {
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());
gl_image_ = ui::GpuMemoryBufferFactoryOzoneNativeBuffer::CreateImageForPixmap(
pixmap_, size(), gfx::GpuMemoryBuffer::RGBA_8888, GL_RGBA);
if (!gl_image_) {
LOG(ERROR) << "Failed to create GLImage";
return false;
}
if (!gl_image_->BindTexImage(GL_TEXTURE_EXTERNAL_OES)) {
LOG(ERROR) << "Failed to bind texture to GLImage";
return false;
......@@ -126,4 +124,12 @@ bool VaapiDrmPicture::DownloadFromSurface(
va_surface_->id(), va_surface_->size());
}
scoped_refptr<gfx::GLImage> VaapiDrmPicture::GetImageToBind() {
return gl_image_;
}
bool VaapiDrmPicture::AllowOverlay() const {
return true;
}
} // namespace
......@@ -15,7 +15,7 @@
#include "ui/gfx/geometry/size.h"
namespace gfx {
class GLImageLinuxDMABuffer;
class GLImage;
}
namespace ui {
......@@ -41,6 +41,10 @@ class VaapiDrmPicture : public VaapiPicture {
bool DownloadFromSurface(const scoped_refptr<VASurface>& va_surface) override;
scoped_refptr<gfx::GLImage> GetImageToBind() override;
bool AllowOverlay() const override;
private:
VaapiWrapper* vaapi_wrapper_; // Not owned.
base::Callback<bool(void)> make_context_current_;
......@@ -49,7 +53,7 @@ class VaapiDrmPicture : public VaapiPicture {
scoped_refptr<ui::NativePixmap> pixmap_;
// EGLImage bound to the GL textures used by the VDA client.
scoped_refptr<gfx::GLImageLinuxDMABuffer> gl_image_;
scoped_refptr<gfx::GLImage> gl_image_;
// VASurface used to transfer from the decoder's pixel format.
scoped_refptr<VASurface> va_surface_;
......
......@@ -37,6 +37,10 @@ linked_ptr<VaapiPicture> VaapiPicture::CreatePicture(
return picture;
}
bool VaapiPicture::AllowOverlay() const {
return false;
}
// static
uint32 VaapiPicture::GetGLTextureTarget() {
#if defined(USE_OZONE)
......
......@@ -16,6 +16,10 @@
#include "base/threading/non_thread_safe.h"
#include "ui/gfx/geometry/size.h"
namespace gfx {
class GLImage;
}
namespace content {
class VASurface;
......@@ -33,6 +37,11 @@ class VaapiPicture : public base::NonThreadSafe {
uint32 texture_id() const { return texture_id_; }
const gfx::Size& size() const { return size_; }
virtual bool AllowOverlay() const;
// Returns the |GLImage|, if any, to bind to the texture.
virtual scoped_refptr<gfx::GLImage> GetImageToBind() = 0;
// Downloads the |va_surface| into the picture, potentially scaling
// it if needed.
virtual bool DownloadFromSurface(
......
......@@ -74,4 +74,8 @@ bool VaapiTFPPicture::DownloadFromSurface(
va_surface->size());
}
scoped_refptr<gfx::GLImage> VaapiTFPPicture::GetImageToBind() {
return nullptr;
}
} // namespace content
......@@ -39,6 +39,8 @@ class VaapiTFPPicture : public VaapiPicture {
bool DownloadFromSurface(const scoped_refptr<VASurface>& va_surface) override;
scoped_refptr<gfx::GLImage> GetImageToBind() override;
private:
VaapiWrapper* vaapi_wrapper_; // Not owned.
......
......@@ -15,6 +15,7 @@
#include "media/base/bind_to_current_loop.h"
#include "media/video/picture.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_image.h"
static void ReportToUMA(
content::VaapiH264Decoder::VAVDAH264DecoderFailure failure) {
......@@ -72,7 +73,9 @@ VaapiPicture* VaapiVideoDecodeAccelerator::PictureById(
}
VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
const base::Callback<bool(void)>& make_context_current)
const base::Callback<bool(void)>& make_context_current,
const base::Callback<void(uint32, uint32, scoped_refptr<gfx::GLImage>)>&
bind_image)
: make_context_current_(make_context_current),
state_(kUninitialized),
input_ready_(&lock_),
......@@ -84,6 +87,7 @@ VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
finish_flush_pending_(false),
awaiting_va_surfaces_recycle_(false),
requested_num_pics_(0),
bind_image_(bind_image),
weak_this_factory_(this) {
weak_this_ = weak_this_factory_.GetWeakPtr();
va_surface_release_cb_ = media::BindToCurrentLoop(
......@@ -186,8 +190,9 @@ void VaapiVideoDecodeAccelerator::OutputPicture(
// TODO(posciak): Use visible size from decoder here instead
// (crbug.com/402760).
if (client_)
client_->PictureReady(
media::Picture(output_id, input_id, gfx::Rect(picture->size()), false));
client_->PictureReady(media::Picture(output_id, input_id,
gfx::Rect(picture->size()),
picture->AllowOverlay()));
}
void VaapiVideoDecodeAccelerator::TryOutputSurface() {
......@@ -525,6 +530,12 @@ void VaapiVideoDecodeAccelerator::AssignPictureBuffers(
vaapi_wrapper_.get(), make_context_current_, buffers[i].id(),
buffers[i].texture_id(), requested_pic_size_));
scoped_refptr<gfx::GLImage> image = picture->GetImageToBind();
if (image) {
bind_image_.Run(buffers[i].internal_texture_id(),
VaapiPicture::GetGLTextureTarget(), image);
}
RETURN_AND_NOTIFY_ON_FAILURE(
picture.get(), "Failed assigning picture buffer to a texture.",
PLATFORM_FAILURE, );
......
......@@ -28,6 +28,10 @@
#include "media/video/picture.h"
#include "media/video/video_decode_accelerator.h"
namespace gfx {
class GLImage;
}
namespace content {
class VaapiPicture;
......@@ -44,7 +48,9 @@ class CONTENT_EXPORT VaapiVideoDecodeAccelerator
: public media::VideoDecodeAccelerator {
public:
VaapiVideoDecodeAccelerator(
const base::Callback<bool(void)>& make_context_current);
const base::Callback<bool(void)>& make_context_current,
const base::Callback<void(uint32, uint32, scoped_refptr<gfx::GLImage>)>&
bind_image);
~VaapiVideoDecodeAccelerator() override;
// media::VideoDecodeAccelerator implementation.
......@@ -264,6 +270,10 @@ private:
size_t requested_num_pics_;
gfx::Size requested_pic_size_;
// Binds the provided GLImage to a givenr client texture ID & texture target
// combination in GLES.
base::Callback<void(uint32, uint32, scoped_refptr<gfx::GLImage>)> bind_image_;
// The WeakPtrFactory for |weak_this_|.
base::WeakPtrFactory<VaapiVideoDecodeAccelerator> weak_this_factory_;
......
......@@ -52,6 +52,7 @@
#include "content/public/common/content_switches.h"
#include "media/filters/h264_parser.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gl/gl_image.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
......@@ -334,6 +335,10 @@ class GLRenderingVDAClient
scoped_ptr<media::VideoDecodeAccelerator> CreateV4L2SliceVDA();
scoped_ptr<media::VideoDecodeAccelerator> CreateVaapiVDA();
void BindImage(uint32 client_texture_id,
uint32 texture_target,
scoped_refptr<gfx::GLImage> image);
void SetState(ClientState new_state);
void FinishInitialization();
void ReturnPicture(int32 picture_buffer_id);
......@@ -515,16 +520,23 @@ GLRenderingVDAClient::CreateV4L2SliceVDA() {
#endif
return decoder.Pass();
}
scoped_ptr<media::VideoDecodeAccelerator>
GLRenderingVDAClient::CreateVaapiVDA() {
scoped_ptr<media::VideoDecodeAccelerator> decoder;
#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
decoder.reset(
new VaapiVideoDecodeAccelerator(base::Bind(&DoNothingReturnTrue)));
decoder.reset(new VaapiVideoDecodeAccelerator(
base::Bind(&DoNothingReturnTrue),
base::Bind(&GLRenderingVDAClient::BindImage, base::Unretained(this))));
#endif
return decoder.Pass();
}
void GLRenderingVDAClient::BindImage(uint32 client_texture_id,
uint32 texture_target,
scoped_refptr<gfx::GLImage> image) {
}
void GLRenderingVDAClient::CreateAndStartDecoder() {
CHECK(decoder_deleted());
CHECK(!decoder_.get());
......
......@@ -7,9 +7,17 @@
namespace media {
PictureBuffer::PictureBuffer(int32 id, gfx::Size size, uint32 texture_id)
: id_(id), size_(size), texture_id_(texture_id), internal_texture_id_(0) {
}
PictureBuffer::PictureBuffer(int32 id,
gfx::Size size,
uint32 texture_id,
uint32 internal_texture_id)
: id_(id),
size_(size),
texture_id_(texture_id) {
texture_id_(texture_id),
internal_texture_id_(internal_texture_id) {
}
PictureBuffer::PictureBuffer(int32 id,
......@@ -19,6 +27,7 @@ PictureBuffer::PictureBuffer(int32 id,
: id_(id),
size_(size),
texture_id_(texture_id),
internal_texture_id_(0),
texture_mailbox_(texture_mailbox) {
}
......
......@@ -18,6 +18,10 @@ namespace media {
class MEDIA_EXPORT PictureBuffer {
public:
PictureBuffer(int32 id, gfx::Size size, uint32 texture_id);
PictureBuffer(int32 id,
gfx::Size size,
uint32 texture_id,
uint32 internal_texture_id);
PictureBuffer(int32 id,
gfx::Size size,
uint32 texture_id,
......@@ -40,6 +44,8 @@ class MEDIA_EXPORT PictureBuffer {
return texture_id_;
}
uint32 internal_texture_id() const { return internal_texture_id_; }
const gpu::Mailbox& texture_mailbox() const {
return texture_mailbox_;
}
......@@ -48,6 +54,7 @@ class MEDIA_EXPORT PictureBuffer {
int32 id_;
gfx::Size size_;
uint32 texture_id_;
uint32 internal_texture_id_;
gpu::Mailbox texture_mailbox_;
};
......
......@@ -161,10 +161,19 @@ GpuMemoryBufferFactoryOzoneNativeBuffer::CreateImageForGpuMemoryBuffer(
}
pixmap = it->second.get();
}
return CreateImageForPixmap(pixmap, size, format, internalformat);
}
scoped_refptr<gfx::GLImage>
GpuMemoryBufferFactoryOzoneNativeBuffer::CreateImageForPixmap(
scoped_refptr<NativePixmap> pixmap,
const gfx::Size& size,
gfx::GpuMemoryBuffer::Format format,
unsigned internalformat) {
if (pixmap->GetEGLClientBuffer()) {
scoped_refptr<GLImageOzoneNativePixmap> image =
new GLImageOzoneNativePixmap(size);
if (!image->Initialize(pixmap)) {
if (!image->Initialize(pixmap.get())) {
return scoped_refptr<gfx::GLImage>();
}
return image;
......@@ -172,7 +181,7 @@ GpuMemoryBufferFactoryOzoneNativeBuffer::CreateImageForGpuMemoryBuffer(
if (pixmap->GetDmaBufFd() > 0) {
scoped_refptr<GLImageOzoneNativePixmapDmaBuf> image =
new GLImageOzoneNativePixmapDmaBuf(size, internalformat);
if (!image->Initialize(pixmap, format)) {
if (!image->Initialize(pixmap.get(), format)) {
return scoped_refptr<gfx::GLImage>();
}
return image;
......
......@@ -13,6 +13,7 @@
#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/ozone/gpu/ozone_gpu_export.h"
#include "ui/ozone/public/native_pixmap.h"
namespace gfx {
class GLImage;
......@@ -48,6 +49,12 @@ class OZONE_GPU_EXPORT GpuMemoryBufferFactoryOzoneNativeBuffer {
unsigned internalformat,
int client_id);
static scoped_refptr<gfx::GLImage> CreateImageForPixmap(
scoped_refptr<NativePixmap> pixmap,
const gfx::Size& size,
gfx::GpuMemoryBuffer::Format format,
unsigned internalformat);
private:
BufferToPixmapMap native_pixmap_map_;
base::Lock native_pixmap_map_lock_;
......
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