diff options
-rw-r--r-- | content/common/gpu/media/vaapi_drm_picture.cc | 119 | ||||
-rw-r--r-- | content/common/gpu/media/vaapi_drm_picture.h | 22 | ||||
-rw-r--r-- | ui/ozone/platform/cast/surface_factory_cast.cc | 4 | ||||
-rw-r--r-- | ui/ozone/platform/drm/gpu/gbm_buffer.cc | 37 | ||||
-rw-r--r-- | ui/ozone/platform/drm/gpu/gbm_buffer.h | 7 | ||||
-rw-r--r-- | ui/ozone/public/native_pixmap.h | 10 |
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() {} |