| Index: content/common/gpu/media/vaapi_picture_provider_x11.cc
|
| diff --git a/content/common/gpu/media/vaapi_picture_provider_x11.cc b/content/common/gpu/media/vaapi_picture_provider_x11.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..13185c530023de5de2caaaef9f8f01484cb0bdc3
|
| --- /dev/null
|
| +++ b/content/common/gpu/media/vaapi_picture_provider_x11.cc
|
| @@ -0,0 +1,180 @@
|
| +// Copyright (c) 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "content/common/gpu/media/vaapi_picture_provider_x11.h"
|
| +#include "ui/gl/gl_bindings.h"
|
| +#include "ui/gl/gl_context_glx.h"
|
| +#include "ui/gl/gl_image.h"
|
| +#include "ui/gl/scoped_binders.h"
|
| +
|
| +namespace content {
|
| +
|
| +class TFPPicture : public VaapiPictureProvider::Picture {
|
| + public:
|
| + TFPPicture(scoped_refptr<VaapiWrapper> vaapi_wrapper,
|
| + gfx::GLContextGLX* glx_context,
|
| + const base::Callback<bool(void)> make_context_current,
|
| + GLXFBConfig fb_config,
|
| + int32 picture_buffer_id,
|
| + uint32 texture_id,
|
| + const gfx::Size& size)
|
| + : Picture(picture_buffer_id, texture_id, size),
|
| + vaapi_wrapper_(vaapi_wrapper),
|
| + glx_context_(glx_context),
|
| + make_context_current_(make_context_current),
|
| + x_display_(glx_context_->display()),
|
| + fb_config_(fb_config) {}
|
| +
|
| + virtual ~TFPPicture();
|
| +
|
| + bool Initialize() override;
|
| +
|
| + bool DownloadFromSurface(VASurfaceID va_surface_id,
|
| + const gfx::Size& surface_size) override;
|
| +
|
| + private:
|
| + scoped_refptr<VaapiWrapper> vaapi_wrapper_;
|
| +
|
| + gfx::GLContextGLX* glx_context_;
|
| + base::Callback<bool(void)> make_context_current_;
|
| + Display* x_display_;
|
| + GLXFBConfig fb_config_;
|
| +
|
| + Pixmap x_pixmap_;
|
| + GLXPixmap glx_pixmap_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TFPPicture);
|
| +};
|
| +
|
| +TFPPicture::~TFPPicture() {
|
| + if (glx_pixmap_ && make_context_current_.Run()) {
|
| + glXReleaseTexImageEXT(x_display_, glx_pixmap_, GLX_FRONT_LEFT_EXT);
|
| + glXDestroyPixmap(x_display_, glx_pixmap_);
|
| + }
|
| +
|
| + if (x_pixmap_)
|
| + XFreePixmap(x_display_, x_pixmap_);
|
| + XSync(x_display_, False); // Needed to work around buggy vdpau-driver.
|
| +}
|
| +
|
| +bool TFPPicture::Initialize() {
|
| + 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_) {
|
| + LOG(ERROR) << "Failed creating an X Pixmap for TFP";
|
| + return false;
|
| + }
|
| +
|
| + static const int pixmap_attr[] = {
|
| + GLX_TEXTURE_TARGET_EXT,
|
| + GLX_TEXTURE_2D_EXT,
|
| + GLX_TEXTURE_FORMAT_EXT,
|
| + GLX_TEXTURE_FORMAT_RGB_EXT,
|
| + GL_NONE,
|
| + };
|
| +
|
| + glx_pixmap_ = glXCreatePixmap(x_display_, fb_config_, x_pixmap_, pixmap_attr);
|
| + if (!glx_pixmap_) {
|
| + // x_pixmap_ will be freed in the destructor.
|
| + LOG(ERROR) << "Failed creating a GLX Pixmap for TFP";
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool TFPPicture::DownloadFromSurface(VASurfaceID va_surface_id,
|
| + const gfx::Size& surface_size) {
|
| + if (!make_context_current_.Run()) {
|
| + DVLOG(1) << "Failed making gl context current";
|
| + return false;
|
| + }
|
| +
|
| + gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id());
|
| + glXBindTexImageEXT(x_display_, glx_pixmap_, GLX_FRONT_LEFT_EXT, NULL);
|
| + if (glGetError() != GL_NO_ERROR)
|
| + return false;
|
| +
|
| + return vaapi_wrapper_->PutSurfaceIntoPixmap(va_surface_id, x_pixmap_, size());
|
| +}
|
| +
|
| +class XFreeDeleter {
|
| + public:
|
| + void operator()(void* x) const { ::XFree(x); }
|
| +};
|
| +
|
| +X11VaapiPictureProvider::X11VaapiPictureProvider(
|
| + scoped_refptr<VaapiWrapper> vaapi_wrapper,
|
| + gfx::GLContextGLX* glx_context,
|
| + const base::Callback<bool(void)> make_context_current)
|
| + : glx_context_(glx_context),
|
| + make_context_current_(make_context_current),
|
| + x_display_(glx_context_->display()),
|
| + vaapi_wrapper_(vaapi_wrapper) {
|
| +}
|
| +
|
| +X11VaapiPictureProvider::~X11VaapiPictureProvider() {
|
| +}
|
| +
|
| +linked_ptr<VaapiPictureProvider::Picture>
|
| +X11VaapiPictureProvider::AllocatePicture(int32 picture_buffer_id,
|
| + uint32 texture_id,
|
| + const gfx::Size& size) {
|
| + return linked_ptr<VaapiPictureProvider::Picture>(
|
| + new TFPPicture(vaapi_wrapper_,
|
| + glx_context_,
|
| + make_context_current_,
|
| + fb_config_,
|
| + picture_buffer_id,
|
| + texture_id,
|
| + size));
|
| +}
|
| +
|
| +bool X11VaapiPictureProvider::Initialize() {
|
| + if (!make_context_current_.Run()) {
|
| + DVLOG(1) << "Couldn't make context current";
|
| + return false;
|
| + }
|
| +
|
| + 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<GLXFBConfig, XFreeDeleter> glx_fb_configs(glXChooseFBConfig(
|
| + x_display_, DefaultScreen(x_display_), fbconfig_attr, &num_fbconfigs));
|
| +
|
| + if (!glx_fb_configs) {
|
| + DVLOG(1) << "Couldn't get glx configs";
|
| + return false;
|
| + }
|
| + if (!num_fbconfigs) {
|
| + DVLOG(1) << "Couldn't get at least a glx config";
|
| + return false;
|
| + }
|
| +
|
| + fb_config_ = glx_fb_configs.get()[0];
|
| + return true;
|
| +}
|
| +
|
| +} // namespace content
|
|
|