blob: 873ddbecccec70792a5a385f0496815dd9f80ba5 [file] [log] [blame]
// Copyright 2019 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.
#ifndef UI_OZONE_PLATFORM_SCENIC_SYSMEM_BUFFER_COLLECTION_H_
#define UI_OZONE_PLATFORM_SCENIC_SYSMEM_BUFFER_COLLECTION_H_
#include <fuchsia/sysmem/cpp/fidl.h>
#include <lib/ui/scenic/cpp/session.h>
#include <vulkan/vulkan.h>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
#include "base/threading/thread_checker.h"
#include "gpu/ipc/common/vulkan_ycbcr_info.h"
#include "gpu/vulkan/fuchsia/vulkan_fuchsia_ext.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/native_pixmap_handle.h"
#include "ui/ozone/platform/scenic/scenic_overlay_view.h"
namespace gfx {
class NativePixmap;
} // namespace gfx
namespace ui {
class ScenicSurfaceFactory;
// SysmemBufferCollection keeps sysmem.BufferCollection interface along with the
// corresponding VkBufferCollectionFUCHSIA. It allows to create either
// gfx::NativePixmap or VkImage from the buffers in the collection.
// A collection can be initialized and used on any thread. CreateVkImage() must
// be called on the same thread (because it may be be safe to use
// VkBufferCollectionFUCHSIA concurrently on different threads).
class SysmemBufferCollection
: public base::RefCountedThreadSafe<SysmemBufferCollection> {
public:
static bool IsNativePixmapConfigSupported(gfx::BufferFormat format,
gfx::BufferUsage usage);
SysmemBufferCollection();
explicit SysmemBufferCollection(gfx::SysmemBufferCollectionId id);
// Initializes the buffer collection and registers it with Vulkan using the
// specified |vk_device|. If |token_handle| is null then a new collection
// collection is created. |size| may be empty. In that case |token_handle|
// must not be null and the image size is determined by the other sysmem
// participants.
// If |register_with_image_pipe| is true, new ScenicOverlayView instance is
// created and |token_handle| gets duplicated to be added to its ImagePipe.
bool Initialize(fuchsia::sysmem::Allocator_Sync* allocator,
ScenicSurfaceFactory* scenic_surface_factory,
zx::channel token_handle,
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
VkDevice vk_device,
size_t min_buffer_count,
bool force_protected,
bool register_with_image_pipe);
// Must not be called more than once.
void SetOnDeletedCallback(base::OnceClosure on_deleted);
// Creates a NativePixmap the buffer with the specified index. Returned
// NativePixmap holds a reference to the collection, so the collection is not
// deleted until all NativePixmap are destroyed.
scoped_refptr<gfx::NativePixmap> CreateNativePixmap(size_t buffer_index);
// Creates a new Vulkan image for the buffer with the specified index.
bool CreateVkImage(size_t buffer_index,
VkDevice vk_device,
gfx::Size size,
VkImage* vk_image,
VkImageCreateInfo* vk_image_info,
VkDeviceMemory* vk_device_memory,
VkDeviceSize* mem_allocation_size,
base::Optional<gpu::VulkanYCbCrInfo>* ycbcr_info);
gfx::SysmemBufferCollectionId id() const { return id_; }
size_t num_buffers() const { return buffers_info_.buffer_count; }
gfx::Size size() const { return image_size_; }
gfx::BufferFormat format() const { return format_; }
size_t buffer_size() const {
return buffers_info_.settings.buffer_settings.size_bytes;
}
ScenicOverlayView* scenic_overlay_view() {
return scenic_overlay_view_.has_value() ? &scenic_overlay_view_.value()
: nullptr;
}
ScenicSurfaceFactory* surface_factory() { return surface_factory_; }
private:
friend class base::RefCountedThreadSafe<SysmemBufferCollection>;
~SysmemBufferCollection();
bool InitializeInternal(
fuchsia::sysmem::Allocator_Sync* allocator,
fuchsia::sysmem::BufferCollectionTokenSyncPtr collection_token,
size_t buffers_for_camping);
void InitializeImageCreateInfo(VkImageCreateInfo* vk_image_info,
gfx::Size size);
bool is_mappable() const {
return usage_ == gfx::BufferUsage::SCANOUT_CPU_READ_WRITE ||
usage_ == gfx::BufferUsage::GPU_READ_CPU_READ_WRITE;
}
const gfx::SysmemBufferCollectionId id_;
// Image size passed to vkSetBufferCollectionConstraintsFUCHSIA(). The actual
// buffers size may be larger depending on constraints set by other
// sysmem clients. Size of the image is passed to CreateVkImage().
gfx::Size min_size_;
gfx::BufferFormat format_ = gfx::BufferFormat::RGBA_8888;
gfx::BufferUsage usage_ = gfx::BufferUsage::GPU_READ_CPU_READ_WRITE;
fuchsia::sysmem::BufferCollectionSyncPtr collection_;
fuchsia::sysmem::BufferCollectionInfo_2 buffers_info_;
// Vulkan device for which the collection was initialized.
VkDevice vk_device_ = VK_NULL_HANDLE;
// Handle for the Vulkan object that holds the same logical buffer collection
// that is referenced by |collection_|.
VkBufferCollectionFUCHSIA vk_buffer_collection_ = VK_NULL_HANDLE;
// If ScenicOverlayView is created and its ImagePipe is added as a participant
// in buffer allocation negotiations, the associated images can be displayed
// as overlays.
base::Optional<ScenicOverlayView> scenic_overlay_view_;
ScenicSurfaceFactory* surface_factory_ = nullptr;
// Thread checker used to verify that CreateVkImage() is always called from
// the same thread. It may be unsafe to use vk_buffer_collection_ on different
// threads.
THREAD_CHECKER(vulkan_thread_checker_);
gfx::Size image_size_;
size_t buffer_size_ = 0;
bool is_protected_ = false;
base::OnceClosure on_deleted_;
DISALLOW_COPY_AND_ASSIGN(SysmemBufferCollection);
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_SCENIC_SYSMEM_BUFFER_COLLECTION_H_