summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/common/gpu/media/vaapi_drm_picture.cc119
-rw-r--r--content/common/gpu/media/vaapi_drm_picture.h22
-rw-r--r--ui/ozone/platform/cast/surface_factory_cast.cc4
-rw-r--r--ui/ozone/platform/drm/gpu/gbm_buffer.cc37
-rw-r--r--ui/ozone/platform/drm/gpu/gbm_buffer.h7
-rw-r--r--ui/ozone/public/native_pixmap.h10
6 files changed, 173 insertions, 26 deletions
diff --git a/content/common/gpu/media/vaapi_drm_picture.cc b/content/common/gpu/media/vaapi_drm_picture.cc
index bf694d2..66e4328 100644
--- a/content/common/gpu/media/vaapi_drm_picture.cc
+++ b/content/common/gpu/media/vaapi_drm_picture.cc
@@ -28,7 +28,8 @@ VaapiDrmPicture::VaapiDrmPicture(
const gfx::Size& size)
: VaapiPicture(picture_buffer_id, texture_id, size),
vaapi_wrapper_(vaapi_wrapper),
- make_context_current_(make_context_current) {
+ make_context_current_(make_context_current),
+ weak_this_factory_(this) {
}
VaapiDrmPicture::~VaapiDrmPicture() {
@@ -40,37 +41,24 @@ VaapiDrmPicture::~VaapiDrmPicture() {
}
}
-bool VaapiDrmPicture::Initialize() {
- // We want to create a VASurface and an EGLImage out of the same
- // memory buffer, so we can output decoded pictures to it using
- // VAAPI and also use it to paint with GL.
- ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance();
- ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone();
-
- // Create a buffer from Ozone.
- pixmap_ = factory->CreateNativePixmap(gfx::kNullAcceleratedWidget, size(),
- ui::SurfaceFactoryOzone::BGRA_8888,
- ui::SurfaceFactoryOzone::SCANOUT);
- if (!pixmap_) {
- LOG(ERROR) << "Failed creating an Ozone NativePixmap";
- return false;
- }
-
+scoped_refptr<VASurface> VaapiDrmPicture::CreateVASurfaceForPixmap(
+ scoped_refptr<ui::NativePixmap> pixmap,
+ gfx::Size pixmap_size) {
// Get the dmabuf of the created buffer.
- int dmabuf_fd = pixmap_->GetDmaBufFd();
+ int dmabuf_fd = pixmap->GetDmaBufFd();
if (dmabuf_fd < 0) {
LOG(ERROR) << "Failed to get dmabuf from an Ozone NativePixmap";
- return false;
+ return nullptr;
}
- int dmabuf_pitch = pixmap_->GetDmaBufPitch();
+ int dmabuf_pitch = pixmap->GetDmaBufPitch();
// Create a VASurface out of the created buffer using the dmabuf.
VASurfaceAttribExternalBuffers va_attrib_extbuf;
memset(&va_attrib_extbuf, 0, sizeof(va_attrib_extbuf));
va_attrib_extbuf.pixel_format = VA_FOURCC_BGRX;
- va_attrib_extbuf.width = size().width();
- va_attrib_extbuf.height = size().height();
- va_attrib_extbuf.data_size = size().height() * dmabuf_pitch;
+ va_attrib_extbuf.width = pixmap_size.width();
+ va_attrib_extbuf.height = pixmap_size.height();
+ va_attrib_extbuf.data_size = pixmap_size.height() * dmabuf_pitch;
va_attrib_extbuf.num_planes = 1;
va_attrib_extbuf.pitches[0] = dmabuf_pitch;
va_attrib_extbuf.offsets[0] = 0;
@@ -92,13 +80,49 @@ bool VaapiDrmPicture::Initialize() {
va_attribs[1].value.type = VAGenericValueTypePointer;
va_attribs[1].value.value.p = &va_attrib_extbuf;
- va_surface_ = vaapi_wrapper_->CreateUnownedSurface(VA_RT_FORMAT_RGB32, size(),
- va_attribs);
- if (!va_surface_) {
+ scoped_refptr<VASurface> va_surface = vaapi_wrapper_->CreateUnownedSurface(
+ VA_RT_FORMAT_RGB32, pixmap_size, va_attribs);
+ if (!va_surface) {
LOG(ERROR) << "Failed to create VASurface for an Ozone NativePixmap";
+ return nullptr;
+ }
+
+ return va_surface;
+}
+
+scoped_refptr<ui::NativePixmap> VaapiDrmPicture::CreateNativePixmap(
+ gfx::Size size) {
+ ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance();
+ ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone();
+
+ // Create a buffer from Ozone.
+ return factory->CreateNativePixmap(gfx::kNullAcceleratedWidget, size,
+ ui::SurfaceFactoryOzone::BGRA_8888,
+ ui::SurfaceFactoryOzone::SCANOUT);
+}
+
+bool VaapiDrmPicture::Initialize() {
+ // We want to create a VASurface and an EGLImage out of the same
+ // memory buffer, so we can output decoded pictures to it using
+ // VAAPI and also use it to paint with GL.
+ pixmap_ = CreateNativePixmap(size());
+ if (!pixmap_) {
+ LOG(ERROR) << "Failed creating an Ozone NativePixmap";
+ return false;
+ }
+
+ va_surface_ = CreateVASurfaceForPixmap(pixmap_, size());
+ if (!va_surface_) {
+ LOG(ERROR) << "Failed creating VASurface for NativePixmap";
return false;
}
+ // Weak pointers can only bind to methods without return values,
+ // hence we cannot bind ScalePixmap here. Instead we use a
+ // static function to solve this problem.
+ pixmap_->SetScalingCallback(base::Bind(&VaapiDrmPicture::CallScalePixmap,
+ weak_this_factory_.GetWeakPtr()));
+
if (!make_context_current_.Run())
return false;
@@ -124,6 +148,49 @@ bool VaapiDrmPicture::DownloadFromSurface(
va_surface_->id(), va_surface_->size());
}
+// static
+scoped_refptr<ui::NativePixmap> VaapiDrmPicture::CallScalePixmap(
+ base::WeakPtr<VaapiDrmPicture> weak_ptr,
+ gfx::Size new_size) {
+ if (!weak_ptr.get()) {
+ LOG(ERROR) << "Failed scaling NativePixmap as scaling "
+ "unit(VaapiDrmPicture) is deleted";
+ return nullptr;
+ }
+ return weak_ptr->ScalePixmap(new_size);
+}
+
+scoped_refptr<ui::NativePixmap> VaapiDrmPicture::ScalePixmap(
+ gfx::Size new_size) {
+ if (!scaled_va_surface_.get() || scaled_va_surface_->size() != new_size) {
+ scaled_pixmap_ = CreateNativePixmap(new_size);
+ if (!scaled_pixmap_) {
+ LOG(ERROR) << "Failed creating an Ozone NativePixmap for scaling";
+ scaled_va_surface_ = nullptr;
+ return nullptr;
+ }
+ scaled_va_surface_ = CreateVASurfaceForPixmap(scaled_pixmap_, new_size);
+ if (!scaled_va_surface_) {
+ LOG(ERROR) << "Failed creating VA Surface for pixmap";
+ scaled_pixmap_ = nullptr;
+ return nullptr;
+ }
+ }
+
+ DCHECK(scaled_pixmap_);
+ bool vpp_result = vaapi_wrapper_->BlitSurface(
+ va_surface_->id(), va_surface_->size(), scaled_va_surface_->id(),
+ scaled_va_surface_->size());
+ if (!vpp_result) {
+ LOG(ERROR) << "Failed scaling NativePixmap";
+ scaled_pixmap_ = nullptr;
+ scaled_va_surface_ = nullptr;
+ return nullptr;
+ }
+
+ return scaled_pixmap_;
+}
+
scoped_refptr<gfx::GLImage> VaapiDrmPicture::GetImageToBind() {
return gl_image_;
}
diff --git a/content/common/gpu/media/vaapi_drm_picture.h b/content/common/gpu/media/vaapi_drm_picture.h
index e982b59..4a0b83b 100644
--- a/content/common/gpu/media/vaapi_drm_picture.h
+++ b/content/common/gpu/media/vaapi_drm_picture.h
@@ -11,6 +11,7 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "content/common/gpu/media/vaapi_picture.h"
#include "ui/gfx/geometry/size.h"
@@ -46,18 +47,39 @@ class VaapiDrmPicture : public VaapiPicture {
bool AllowOverlay() const override;
private:
+ // Calls ScalePixmap() if weak_ptr is not NULL.
+ static scoped_refptr<ui::NativePixmap> CallScalePixmap(
+ base::WeakPtr<VaapiDrmPicture> weak_ptr,
+ gfx::Size new_size);
+ // Use VPP to scale underlying pixmap_ to |new_size| and return the
+ // scaling result with a new pixmap.
+ scoped_refptr<ui::NativePixmap> ScalePixmap(gfx::Size new_size);
+ scoped_refptr<VASurface> CreateVASurfaceForPixmap(
+ scoped_refptr<ui::NativePixmap> pixmap,
+ gfx::Size pixmap_size);
+ scoped_refptr<ui::NativePixmap> CreateNativePixmap(gfx::Size size);
+
VaapiWrapper* vaapi_wrapper_; // Not owned.
base::Callback<bool(void)> make_context_current_;
// Ozone buffer, the storage of the EGLImage and the VASurface.
scoped_refptr<ui::NativePixmap> pixmap_;
+ // Ozone buffer, the storage of the scaled buffer for overlay.
+ scoped_refptr<ui::NativePixmap> scaled_pixmap_;
+
// EGLImage bound to the GL textures used by the VDA client.
scoped_refptr<gfx::GLImage> gl_image_;
// VASurface used to transfer from the decoder's pixel format.
scoped_refptr<VASurface> va_surface_;
+ // VaSurface used to apply scaling.
+ scoped_refptr<VASurface> scaled_va_surface_;
+
+ // The WeakPtrFactory for VaapiDrmPicture.
+ base::WeakPtrFactory<VaapiDrmPicture> weak_this_factory_;
+
DISALLOW_COPY_AND_ASSIGN(VaapiDrmPicture);
};
diff --git a/ui/ozone/platform/cast/surface_factory_cast.cc b/ui/ozone/platform/cast/surface_factory_cast.cc
index 9a0a466..3288f43 100644
--- a/ui/ozone/platform/cast/surface_factory_cast.cc
+++ b/ui/ozone/platform/cast/surface_factory_cast.cc
@@ -197,6 +197,10 @@ scoped_refptr<NativePixmap> SurfaceFactoryCast::CreateNativePixmap(
const gfx::RectF& crop_rect) override {
return true;
}
+ void SetScalingCallback(const ScalingCallback& scaling_callback) override {}
+ scoped_refptr<NativePixmap> GetScaledPixmap(gfx::Size new_size) override {
+ return nullptr;
+ }
private:
~CastPixmap() override {}
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.cc b/ui/ozone/platform/drm/gpu/gbm_buffer.cc
index 8da5e5d..c92ba44 100644
--- a/ui/ozone/platform/drm/gpu/gbm_buffer.cc
+++ b/ui/ozone/platform/drm/gpu/gbm_buffer.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/trace_event/trace_event.h"
+#include "ui/gfx/geometry/size_conversions.h"
#include "ui/ozone/platform/drm/gpu/drm_window.h"
#include "ui/ozone/platform/drm/gpu/gbm_device.h"
@@ -83,6 +84,14 @@ bool GbmPixmap::Initialize() {
return true;
}
+void GbmPixmap::SetScalingCallback(const ScalingCallback& scaling_callback) {
+ scaling_callback_ = scaling_callback;
+}
+
+scoped_refptr<NativePixmap> GbmPixmap::GetScaledPixmap(gfx::Size new_size) {
+ return scaling_callback_.Run(new_size);
+}
+
GbmPixmap::~GbmPixmap() {
if (dma_buf_ > 0)
close(dma_buf_);
@@ -105,9 +114,37 @@ bool GbmPixmap::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
gfx::OverlayTransform plane_transform,
const gfx::Rect& display_bounds,
const gfx::RectF& crop_rect) {
+ gfx::Size required_size;
+ if (plane_z_order &&
+ ShouldApplyScaling(display_bounds, crop_rect, &required_size)) {
+ scoped_refptr<NativePixmap> scaled_pixmap = GetScaledPixmap(required_size);
+ if (scaled_pixmap) {
+ return scaled_pixmap->ScheduleOverlayPlane(
+ widget, plane_z_order, plane_transform, display_bounds, crop_rect);
+ } else {
+ return false;
+ }
+ }
+
screen_manager_->GetWindow(widget)->QueueOverlayPlane(OverlayPlane(
buffer_, plane_z_order, plane_transform, display_bounds, crop_rect));
return true;
}
+bool GbmPixmap::ShouldApplyScaling(const gfx::Rect& display_bounds,
+ const gfx::RectF& crop_rect,
+ gfx::Size* required_size) {
+ if (crop_rect.width() == 0 || crop_rect.height() == 0) {
+ PLOG(ERROR) << "ShouldApplyScaling passed zero scaling target.";
+ return false;
+ }
+
+ gfx::Size pixmap_size = buffer_->GetSize();
+ // If the required size is not integer-sized, round it to the next integer.
+ *required_size = gfx::ToCeiledSize(
+ gfx::SizeF(display_bounds.width() / crop_rect.width(),
+ display_bounds.height() / crop_rect.height()));
+ return pixmap_size != *required_size;
+}
+
} // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.h b/ui/ozone/platform/drm/gpu/gbm_buffer.h
index 3f0c5d7..4f420e7 100644
--- a/ui/ozone/platform/drm/gpu/gbm_buffer.h
+++ b/ui/ozone/platform/drm/gpu/gbm_buffer.h
@@ -39,6 +39,8 @@ class GbmPixmap : public NativePixmap {
GbmPixmap(const scoped_refptr<GbmBuffer>& buffer,
ScreenManager* screen_manager);
bool Initialize();
+ void SetScalingCallback(const ScalingCallback& scaling_callback) override;
+ scoped_refptr<NativePixmap> GetScaledPixmap(gfx::Size new_size) override;
// NativePixmap:
void* GetEGLClientBuffer() override;
@@ -54,12 +56,17 @@ class GbmPixmap : public NativePixmap {
private:
~GbmPixmap() override;
+ bool ShouldApplyScaling(const gfx::Rect& display_bounds,
+ const gfx::RectF& crop_rect,
+ gfx::Size* required_size);
scoped_refptr<GbmBuffer> buffer_;
int dma_buf_ = -1;
ScreenManager* screen_manager_; // Not owned.
+ ScalingCallback scaling_callback_;
+
DISALLOW_COPY_AND_ASSIGN(GbmPixmap);
};
diff --git a/ui/ozone/public/native_pixmap.h b/ui/ozone/public/native_pixmap.h
index a1204f7..0251a12 100644
--- a/ui/ozone/public/native_pixmap.h
+++ b/ui/ozone/public/native_pixmap.h
@@ -5,6 +5,7 @@
#ifndef UI_OZONE_PUBLIC_NATIVE_PIXMAP_H_
#define UI_OZONE_PUBLIC_NATIVE_PIXMAP_H_
+#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/overlay_transform.h"
@@ -43,6 +44,15 @@ class NativePixmap : public base::RefCountedThreadSafe<NativePixmap> {
const gfx::Rect& display_bounds,
const gfx::RectF& crop_rect) = 0;
+ // This represents a callback function pointing to scaling unit like VPP
+ // to do scaling operations on native pixmap with required size.
+ typedef base::Callback<scoped_refptr<NativePixmap>(gfx::Size)>
+ ScalingCallback;
+
+ // Set callback function for the pixmap used for scaling.
+ virtual void SetScalingCallback(const ScalingCallback& scaling_callback) = 0;
+ virtual scoped_refptr<NativePixmap> GetScaledPixmap(gfx::Size new_size) = 0;
+
protected:
virtual ~NativePixmap() {}