blob: b099c5eb71b8d98057e34ec97a3bbe7e4aac4a65 [file] [log] [blame]
// Copyright 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 "media/gpu/vaapi_tfp_picture.h"
#include <X11/Xlib.h>
#include "media/gpu/va_surface.h"
#include "media/gpu/vaapi_wrapper.h"
#include "ui/gfx/x/x11_types.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_image_glx.h"
#include "ui/gl/scoped_binders.h"
namespace media {
VaapiTFPPicture::VaapiTFPPicture(
const scoped_refptr<VaapiWrapper>& vaapi_wrapper,
const MakeGLContextCurrentCallback& make_context_current_cb,
const BindGLImageCallback& bind_image_cb,
int32_t picture_buffer_id,
const gfx::Size& size,
uint32_t texture_id,
uint32_t client_texture_id)
: VaapiPicture(vaapi_wrapper,
make_context_current_cb,
bind_image_cb,
picture_buffer_id,
size,
texture_id,
client_texture_id),
x_display_(gfx::GetXDisplay()),
x_pixmap_(0) {}
VaapiTFPPicture::~VaapiTFPPicture() {
if (glx_image_.get() && make_context_current_cb_.Run()) {
glx_image_->ReleaseTexImage(GL_TEXTURE_2D);
glx_image_->Destroy(true);
DCHECK_EQ(glGetError(), static_cast<GLenum>(GL_NO_ERROR));
}
if (x_pixmap_)
XFreePixmap(x_display_, x_pixmap_);
}
bool VaapiTFPPicture::Initialize() {
DCHECK(x_pixmap_);
if (texture_id_ != 0 && !make_context_current_cb_.is_null()) {
if (!make_context_current_cb_.Run())
return false;
glx_image_ = new gl::GLImageGLX(size_, GL_RGB);
if (!glx_image_->Initialize(x_pixmap_)) {
// x_pixmap_ will be freed in the destructor.
LOG(ERROR) << "Failed creating a GLX Pixmap for TFP";
return false;
}
gl::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id_);
if (!glx_image_->BindTexImage(GL_TEXTURE_2D)) {
LOG(ERROR) << "Failed to bind texture to glx image";
return false;
}
}
return true;
}
bool VaapiTFPPicture::Allocate(gfx::BufferFormat format) {
if (format != gfx::BufferFormat::BGRX_8888 &&
format != gfx::BufferFormat::BGRA_8888) {
LOG(ERROR) << "Unsupported format";
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;
}
return Initialize();
}
bool VaapiTFPPicture::ImportGpuMemoryBufferHandle(
gfx::BufferFormat format,
const gfx::GpuMemoryBufferHandle& gpu_memory_buffer_handle) {
NOTIMPLEMENTED() << "GpuMemoryBufferHandle import not implemented";
return false;
}
bool VaapiTFPPicture::DownloadFromSurface(
const scoped_refptr<VASurface>& va_surface) {
return vaapi_wrapper_->PutSurfaceIntoPixmap(va_surface->id(), x_pixmap_,
va_surface->size());
}
} // namespace media