| Index: content/common/gpu/media/vaapi_video_decode_accelerator.cc
|
| diff --git a/content/common/gpu/media/vaapi_video_decode_accelerator.cc b/content/common/gpu/media/vaapi_video_decode_accelerator.cc
|
| index cd18574a8d8142d65f6fb5485444a60218d62a25..5b145f2867bbacc46662bd2f4a17c2cb403434cc 100644
|
| --- a/content/common/gpu/media/vaapi_video_decode_accelerator.cc
|
| +++ b/content/common/gpu/media/vaapi_video_decode_accelerator.cc
|
| @@ -80,6 +80,13 @@ class VaapiVideoDecodeAccelerator::TFPPicture {
|
| uint32 texture_id,
|
| gfx::Size size);
|
|
|
| + static linked_ptr<TFPPicture> Create(
|
| + const base::Callback<bool(void)>& make_context_current,
|
| + const EGLDisplay egl_display,
|
| + Display* x_display,
|
| + int32 picture_buffer_id,
|
| + uint32 texture_id,
|
| + gfx::Size size);
|
| int32 picture_buffer_id() {
|
| return picture_buffer_id_;
|
| }
|
| @@ -101,12 +108,20 @@ class VaapiVideoDecodeAccelerator::TFPPicture {
|
|
|
| private:
|
| TFPPicture(const base::Callback<bool(void)>& make_context_current,
|
| + GLXFBConfig& fb_config,
|
| + Display* x_display,
|
| + int32 picture_buffer_id,
|
| + uint32 texture_id,
|
| + gfx::Size size);
|
| + TFPPicture(const base::Callback<bool(void)>& make_context_current,
|
| + EGLDisplay egl_display,
|
| Display* x_display,
|
| int32 picture_buffer_id,
|
| uint32 texture_id,
|
| gfx::Size size);
|
|
|
| bool Initialize(const GLXFBConfig& fb_config);
|
| + bool Initialize(const EGLDisplay egl_display);
|
|
|
| base::Callback<bool(void)> make_context_current_;
|
|
|
| @@ -120,13 +135,33 @@ class VaapiVideoDecodeAccelerator::TFPPicture {
|
|
|
| // Pixmaps bound to this texture.
|
| Pixmap x_pixmap_;
|
| + EGLDisplay egl_display_;
|
| + EGLImageKHR egl_image_;
|
| GLXPixmap glx_pixmap_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(TFPPicture);
|
| };
|
| +VaapiVideoDecodeAccelerator::TFPPicture::TFPPicture(
|
| + const base::Callback<bool(void)>& make_context_current,
|
| + GLXFBConfig& fb_config,
|
| + Display* x_display,
|
| + int32 picture_buffer_id,
|
| + uint32 texture_id,
|
| + gfx::Size size)
|
| + : make_context_current_(make_context_current),
|
| + x_display_(x_display),
|
| + picture_buffer_id_(picture_buffer_id),
|
| + texture_id_(texture_id),
|
| + size_(size),
|
| + x_pixmap_(0),
|
| + egl_image_(0),
|
| + glx_pixmap_(0) {
|
| + DCHECK(!make_context_current_.is_null());
|
| +};
|
|
|
| VaapiVideoDecodeAccelerator::TFPPicture::TFPPicture(
|
| const base::Callback<bool(void)>& make_context_current,
|
| + EGLDisplay egl_display,
|
| Display* x_display,
|
| int32 picture_buffer_id,
|
| uint32 texture_id,
|
| @@ -137,6 +172,8 @@ VaapiVideoDecodeAccelerator::TFPPicture::TFPPicture(
|
| texture_id_(texture_id),
|
| size_(size),
|
| x_pixmap_(0),
|
| + egl_display_(egl_display),
|
| + egl_image_(0),
|
| glx_pixmap_(0) {
|
| DCHECK(!make_context_current_.is_null());
|
| };
|
| @@ -151,8 +188,8 @@ VaapiVideoDecodeAccelerator::TFPPicture::Create(
|
| gfx::Size size) {
|
|
|
| linked_ptr<TFPPicture> tfp_picture(
|
| - new TFPPicture(make_context_current, x_display, picture_buffer_id,
|
| - texture_id, size));
|
| + new TFPPicture(make_context_current, fb_config, x_display,
|
| + picture_buffer_id, texture_id, size));
|
|
|
| if (!tfp_picture->Initialize(fb_config))
|
| tfp_picture.reset();
|
| @@ -160,6 +197,24 @@ VaapiVideoDecodeAccelerator::TFPPicture::Create(
|
| return tfp_picture;
|
| }
|
|
|
| +linked_ptr<VaapiVideoDecodeAccelerator::TFPPicture>
|
| +VaapiVideoDecodeAccelerator::TFPPicture::Create(
|
| + const base::Callback<bool(void)>& make_context_current,
|
| + const EGLDisplay egl_display,
|
| + Display* x_display,
|
| + int32 picture_buffer_id,
|
| + uint32 texture_id,
|
| + gfx::Size size) {
|
| +
|
| + linked_ptr<TFPPicture> tfp_picture(
|
| + new TFPPicture(make_context_current, egl_display, x_display,
|
| + picture_buffer_id, texture_id, size));
|
| +
|
| + if (!tfp_picture->Initialize(egl_display))
|
| + tfp_picture.reset();
|
| +
|
| + return tfp_picture;
|
| +}
|
| bool VaapiVideoDecodeAccelerator::TFPPicture::Initialize(
|
| const GLXFBConfig& fb_config) {
|
| // Check for NULL prevents unittests from crashing on nonexistent ChildThread.
|
| @@ -196,6 +251,41 @@ bool VaapiVideoDecodeAccelerator::TFPPicture::Initialize(
|
| return true;
|
| }
|
|
|
| +bool VaapiVideoDecodeAccelerator::TFPPicture::Initialize(
|
| + EGLDisplay egl_display) {
|
| + // Check for NULL prevents unittests from crashing on nonexistent ChildThread.
|
| + DCHECK(ChildThread::current() == NULL ||
|
| + ChildThread::current()->message_loop() == base::MessageLoop::current());
|
| +
|
| + if (!make_context_current_.Run())
|
| + return false;
|
| +
|
| + XWindowAttributes win_attr;
|
| + int screen = DefaultScreen(x_display_);
|
| + XGetWindowAttributes(x_display_, RootWindow(x_display_, screen), &win_attr);
|
| + //TODO(posciak): pass the depth required by libva, not the RootWindow's depth
|
| + x_pixmap_ = XCreatePixmap(x_display_, RootWindow(x_display_, screen),
|
| + size_.width(), size_.height(), win_attr.depth);
|
| + if (!x_pixmap_) {
|
| + DVLOG(1) << "Failed creating an X Pixmap for TFP";
|
| + return false;
|
| + }
|
| +
|
| + egl_display_ = egl_display;
|
| + EGLint image_attrs[] = { EGL_IMAGE_PRESERVED_KHR, 1 , EGL_NONE };
|
| +
|
| + egl_image_ = eglCreateImageKHR(egl_display_,
|
| + EGL_NO_CONTEXT,
|
| + EGL_NATIVE_PIXMAP_KHR,
|
| + (EGLClientBuffer)x_pixmap_,
|
| + image_attrs);
|
| + if (!egl_image_) {
|
| + DVLOG(1) << "Failed creating a EGLImage from Pixmap for KHR";
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| VaapiVideoDecodeAccelerator::TFPPicture::~TFPPicture() {
|
| // Check for NULL prevents unittests from crashing on nonexistent ChildThread.
|
| DCHECK(ChildThread::current() == NULL ||
|
| @@ -207,6 +297,10 @@ VaapiVideoDecodeAccelerator::TFPPicture::~TFPPicture() {
|
| glXDestroyPixmap(x_display_, glx_pixmap_);
|
| }
|
|
|
| + if (egl_image_ && make_context_current_.Run()) {
|
| + eglDestroyImageKHR(egl_display_, egl_image_);
|
| + }
|
| +
|
| if (x_pixmap_)
|
| XFreePixmap(x_display_, x_pixmap_);
|
| XSync(x_display_, False); // Needed to work around buggy vdpau-driver.
|
| @@ -214,7 +308,7 @@ VaapiVideoDecodeAccelerator::TFPPicture::~TFPPicture() {
|
|
|
| bool VaapiVideoDecodeAccelerator::TFPPicture::Bind() {
|
| DCHECK(x_pixmap_);
|
| - DCHECK(glx_pixmap_);
|
| +
|
| // Check for NULL prevents unittests from crashing on nonexistent ChildThread.
|
| DCHECK(ChildThread::current() == NULL ||
|
| ChildThread::current()->message_loop() == base::MessageLoop::current());
|
| @@ -223,8 +317,13 @@ bool VaapiVideoDecodeAccelerator::TFPPicture::Bind() {
|
| return false;
|
|
|
| gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id_);
|
| - glXBindTexImageEXT(x_display_, glx_pixmap_, GLX_FRONT_LEFT_EXT, NULL);
|
| -
|
| + if(glx_pixmap_) {
|
| + glXBindTexImageEXT(x_display_, glx_pixmap_, GLX_FRONT_LEFT_EXT, NULL);
|
| + } else if(egl_image_) {
|
| + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_);
|
| + } else {
|
| + return false;
|
| + }
|
| return true;
|
| }
|
|
|
| @@ -244,6 +343,7 @@ VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
|
| Client* client,
|
| const base::Callback<bool(void)>& make_context_current)
|
| : x_display_(x_display),
|
| + egl_context_(0),
|
| glx_context_(glx_context),
|
| make_context_current_(make_context_current),
|
| state_(kUninitialized),
|
| @@ -262,6 +362,30 @@ VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
|
| DCHECK(client);
|
| }
|
|
|
| +VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
|
| + EGLDisplay egl_display, EGLContext egl_context,
|
| + Client* client,
|
| + const base::Callback<bool(void)>& make_context_current)
|
| + : x_display_(0),
|
| + egl_display_(egl_display),
|
| + egl_context_(egl_context),
|
| + glx_context_(0),
|
| + make_context_current_(make_context_current),
|
| + state_(kUninitialized),
|
| + input_ready_(&lock_),
|
| + surfaces_available_(&lock_),
|
| + message_loop_(base::MessageLoop::current()),
|
| + weak_this_(base::AsWeakPtr(this)),
|
| + client_ptr_factory_(client),
|
| + client_(client_ptr_factory_.GetWeakPtr()),
|
| + decoder_thread_("VaapiDecoderThread"),
|
| + num_frames_at_client_(0),
|
| + num_stream_bufs_at_decoder_(0),
|
| + finish_flush_pending_(false),
|
| + awaiting_va_surfaces_recycle_(false),
|
| + requested_num_pics_(0) {
|
| + DCHECK(client);
|
| +}
|
| VaapiVideoDecodeAccelerator::~VaapiVideoDecodeAccelerator() {
|
| DCHECK_EQ(message_loop_, base::MessageLoop::current());
|
| }
|
| @@ -274,24 +398,31 @@ class ScopedPtrXFree {
|
| };
|
|
|
| bool VaapiVideoDecodeAccelerator::InitializeFBConfig() {
|
| - const int fbconfig_attr[] = {
|
| - GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
|
| - GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
|
| - GLX_BIND_TO_TEXTURE_RGB_EXT, GL_TRUE,
|
| - GLX_Y_INVERTED_EXT, GL_TRUE,
|
| - GL_NONE,
|
| - };
|
| -
|
| - int num_fbconfigs;
|
| - scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> glx_fb_configs(
|
| + if(glx_context_) {
|
| + const int fbconfig_attr[] = {
|
| + GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
|
| + GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
|
| + GLX_BIND_TO_TEXTURE_RGB_EXT, GL_TRUE,
|
| + GLX_Y_INVERTED_EXT, GL_TRUE,
|
| + GL_NONE,
|
| + };
|
| +
|
| + int num_fbconfigs;
|
| + scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> glx_fb_configs(
|
| glXChooseFBConfig(x_display_, DefaultScreen(x_display_), fbconfig_attr,
|
| &num_fbconfigs));
|
| - if (!glx_fb_configs)
|
| - return false;
|
| - if (!num_fbconfigs)
|
| + if (!glx_fb_configs)
|
| + return false;
|
| + if (!num_fbconfigs)
|
| + return false;
|
| +
|
| + fb_config_ = glx_fb_configs.get()[0];
|
| + } else if(egl_context_) {
|
| + x_display_ = base::MessagePumpForUI::GetDefaultXDisplay();
|
| + } else {
|
| return false;
|
| + }
|
|
|
| - fb_config_ = glx_fb_configs.get()[0];
|
| return true;
|
| }
|
|
|
| @@ -716,19 +847,33 @@ void VaapiVideoDecodeAccelerator::AssignPictureBuffers(
|
| DVLOG(2) << "Assigning picture id: " << buffers[i].id()
|
| << " to texture id: " << buffers[i].texture_id()
|
| << " VASurfaceID: " << va_surface_ids[i];
|
| + if(glx_context_) {
|
| + linked_ptr<TFPPicture> tfp_picture(
|
| + TFPPicture::Create(make_context_current_, fb_config_, x_display_,
|
| + buffers[i].id(), buffers[i].texture_id(),
|
| + requested_pic_size_));
|
| +
|
| + RETURN_AND_NOTIFY_ON_FAILURE(
|
| + tfp_picture.get(), "Failed assigning picture buffer to a texture.",
|
| + PLATFORM_FAILURE, );
|
|
|
| - linked_ptr<TFPPicture> tfp_picture(
|
| - TFPPicture::Create(make_context_current_, fb_config_, x_display_,
|
| - buffers[i].id(), buffers[i].texture_id(),
|
| - requested_pic_size_));
|
| -
|
| - RETURN_AND_NOTIFY_ON_FAILURE(
|
| - tfp_picture.get(), "Failed assigning picture buffer to a texture.",
|
| - PLATFORM_FAILURE, );
|
| + bool inserted = tfp_pictures_.insert(std::make_pair(
|
| + buffers[i].id(), tfp_picture)).second;
|
| + DCHECK(inserted);
|
| + } else if(egl_context_) {
|
| + linked_ptr<TFPPicture> tfp_picture(
|
| + TFPPicture::Create(make_context_current_, egl_display_, x_display_,
|
| + buffers[i].id(), buffers[i].texture_id(),
|
| + requested_pic_size_));
|
| +
|
| + RETURN_AND_NOTIFY_ON_FAILURE(
|
| + tfp_picture.get(), "Failed assigning picture buffer to a texture.",
|
| + PLATFORM_FAILURE, );
|
|
|
| - bool inserted = tfp_pictures_.insert(std::make_pair(
|
| - buffers[i].id(), tfp_picture)).second;
|
| - DCHECK(inserted);
|
| + bool inserted = tfp_pictures_.insert(std::make_pair(
|
| + buffers[i].id(), tfp_picture)).second;
|
| + DCHECK(inserted);
|
| + }
|
|
|
| output_buffers_.push(buffers[i].id());
|
| available_va_surfaces_.push_back(va_surface_ids[i]);
|
|
|