0

Add a new CreateSharedImage() to SharedImageInterface

This new interface is for supporting bitmap in software composition.

Bug: 1434885
Change-Id: I23ba7d205a90581139a20dd27ea1dc52712949b2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5191211
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com>
Commit-Queue: Maggie Chen <magchen@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1246791}
This commit is contained in:
Maggie Chen
2024-01-13 01:29:51 +00:00
committed by Chromium LUCI CQ
parent 3600f1e2bb
commit c5d2dbd8df
11 changed files with 218 additions and 66 deletions

@@ -181,6 +181,7 @@ class HudSoftwareBacking : public ResourcePool::SoftwareBacking {
if (shared_image) {
auto* sii = layer_tree_frame_sink->shared_image_interface();
if (sii) {
scoped_mapping.reset();
sii->DestroySharedImage(mailbox_sync_token, std::move(shared_image));
}
} else {
@@ -193,12 +194,20 @@ class HudSoftwareBacking : public ResourcePool::SoftwareBacking {
const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid,
uint64_t tracing_process_id,
int importance) const override {
pmd->CreateSharedMemoryOwnershipEdge(buffer_dump_guid,
shared_mapping.guid(), importance);
if (shared_image) {
scoped_mapping->OnMemoryDump(pmd, buffer_dump_guid, tracing_process_id,
importance);
} else {
pmd->CreateSharedMemoryOwnershipEdge(buffer_dump_guid,
shared_mapping.guid(), importance);
}
}
raw_ptr<LayerTreeFrameSink> layer_tree_frame_sink;
// Used for SharedImage.
base::WritableSharedMemoryMapping shared_mapping;
// Used for SharedBitmap
std::unique_ptr<gpu::ClientSharedImage::ScopedMapping> scoped_mapping;
};
bool HeadsUpDisplayLayerImpl::WillDraw(
@@ -339,29 +348,14 @@ void HeadsUpDisplayLayerImpl::UpdateHudTexture(
if (!pool_resource.software_backing()) {
auto backing = std::make_unique<HudSoftwareBacking>();
backing->layer_tree_frame_sink = layer_tree_frame_sink;
const size_t buffer_size = gfx::BufferSizeForBufferFormat(
pool_resource.size(), gfx::BufferFormat::BGRA_8888);
auto shared_memory_region =
base::UnsafeSharedMemoryRegion::Create(buffer_size);
backing->shared_mapping = shared_memory_region.Map();
CHECK(shared_memory_region.IsValid() &&
backing->shared_mapping.IsValid());
gfx::GpuMemoryBufferHandle handle;
handle.type = gfx::SHARED_MEMORY_BUFFER;
handle.offset = 0;
handle.stride = static_cast<int32_t>(gfx::RowSizeForBufferFormat(
pool_resource.size().width(), gfx::BufferFormat::BGRA_8888, 0));
handle.region = std::move(shared_memory_region);
backing->shared_image = sii->CreateSharedImage(
pool_resource.format(), pool_resource.size(),
pool_resource.color_space(), kTopLeft_GrSurfaceOrigin,
kPremul_SkAlphaType, gpu::SHARED_IMAGE_USAGE_CPU_WRITE,
"HeadsUpDisplayLayer", std::move(handle));
"HeadsUpDisplayLayer");
CHECK(backing->shared_image);
backing->scoped_mapping = backing->shared_image->Map();
CHECK(backing->scoped_mapping);
pool_resource.set_software_backing(std::move(backing));
}
@@ -460,8 +454,10 @@ void HeadsUpDisplayLayerImpl::UpdateHudTexture(
auto* backing =
static_cast<HudSoftwareBacking*>(pool_resource.software_backing());
SkSurfaceProps props = skia::LegacyDisplayGlobals::GetSkSurfaceProps();
sk_sp<SkSurface> surface = SkSurfaces::WrapPixels(
info, backing->shared_mapping.memory(), info.minRowBytes(), &props);
void* pixels = backing->scoped_mapping ? backing->scoped_mapping->Memory(0)
: backing->shared_mapping.memory();
sk_sp<SkSurface> surface =
SkSurfaces::WrapPixels(info, pixels, info.minRowBytes(), &props);
SkiaPaintCanvas canvas(surface->getCanvas());
DrawHudContents(&canvas);

@@ -37,6 +37,7 @@ class BitmapSoftwareBacking : public ResourcePool::SoftwareBacking {
public:
~BitmapSoftwareBacking() override {
if (shared_image) {
scoped_mapping.reset();
if (frame_sink->shared_image_interface()) {
frame_sink->shared_image_interface()->DestroySharedImage(
mailbox_sync_token, std::move(shared_image));
@@ -51,12 +52,20 @@ class BitmapSoftwareBacking : public ResourcePool::SoftwareBacking {
const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid,
uint64_t tracing_process_id,
int importance) const override {
pmd->CreateSharedMemoryOwnershipEdge(buffer_dump_guid, mapping.guid(),
importance);
if (shared_image) {
scoped_mapping->OnMemoryDump(pmd, buffer_dump_guid, tracing_process_id,
importance);
} else {
pmd->CreateSharedMemoryOwnershipEdge(buffer_dump_guid, mapping.guid(),
importance);
}
}
raw_ptr<LayerTreeFrameSink> frame_sink;
// Used for SharedBitmap.
base::WritableSharedMemoryMapping mapping;
// Used for SharedImage.
std::unique_ptr<gpu::ClientSharedImage::ScopedMapping> scoped_mapping;
};
class BitmapRasterBufferImpl : public RasterBuffer {
@@ -68,7 +77,8 @@ class BitmapRasterBufferImpl : public RasterBuffer {
uint64_t previous_content_id)
: resource_size_(size),
color_space_(color_space),
pixels_(backing->mapping.memory()),
pixels_(backing->shared_image ? backing->scoped_mapping->Memory(0)
: backing->mapping.memory()),
resource_has_previous_content_(
resource_content_id && resource_content_id == previous_content_id),
backing_(backing) {}
@@ -149,27 +159,14 @@ BitmapRasterBufferProvider::AcquireBufferForRaster(
backing->frame_sink = frame_sink_;
if (frame_sink_->shared_image_interface()) {
const size_t buffer_size =
gfx::BufferSizeForBufferFormat(size, gfx::BufferFormat::BGRA_8888);
auto shared_memory_region =
base::UnsafeSharedMemoryRegion::Create(buffer_size);
backing->mapping = shared_memory_region.Map();
CHECK(shared_memory_region.IsValid() && backing->mapping.IsValid());
gfx::GpuMemoryBufferHandle handle;
handle.type = gfx::SHARED_MEMORY_BUFFER;
handle.offset = 0;
handle.stride = static_cast<int32_t>(gfx::RowSizeForBufferFormat(
size.width(), gfx::BufferFormat::BGRA_8888, 0));
handle.region = std::move(shared_memory_region);
backing->shared_image =
frame_sink_->shared_image_interface()->CreateSharedImage(
viz::SinglePlaneFormat::kBGRA_8888, size, color_space,
kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
gpu::SHARED_IMAGE_USAGE_CPU_WRITE, "BitmapRasterBufferProvider",
std::move(handle));
gpu::SHARED_IMAGE_USAGE_CPU_WRITE, "BitmapRasterBufferProvider");
CHECK(backing->shared_image);
backing->scoped_mapping = backing->shared_image->Map();
CHECK(backing->scoped_mapping);
} else {
backing->shared_bitmap_id = viz::SharedBitmap::GenerateId();
base::MappedReadOnlyRegion shm =

@@ -4662,7 +4662,8 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid,
// For software compositing, shared memory will be allocated and the
// UIResource will be copied into it.
base::MappedReadOnlyRegion shm;
base::WritableSharedMemoryMapping mapping;
base::WritableSharedMemoryMapping shared_mapping;
std::unique_ptr<gpu::ClientSharedImage::ScopedMapping> scoped_mapping;
viz::SharedBitmapId shared_bitmap_id;
bool overlay_candidate = false;
bool use_shared_image =
@@ -4692,29 +4693,15 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid,
auto* sii = layer_tree_frame_sink_->shared_image_interface();
CHECK(sii);
const size_t buffer_size = gfx::BufferSizeForBufferFormat(
upload_size, gfx::BufferFormat::RGBA_8888);
auto shared_memory_region =
base::UnsafeSharedMemoryRegion::Create(buffer_size);
mapping = shared_memory_region.Map();
CHECK(shared_memory_region.IsValid() && mapping.IsValid());
gfx::GpuMemoryBufferHandle handle;
handle.type = gfx::SHARED_MEMORY_BUFFER;
handle.offset = 0;
handle.stride = static_cast<int32_t>(gfx::RowSizeForBufferFormat(
upload_size.width(), gfx::BufferFormat::RGBA_8888, 0));
handle.region = std::move(shared_memory_region);
client_shared_image = sii->CreateSharedImage(
format, upload_size, color_space, kTopLeft_GrSurfaceOrigin,
kPremul_SkAlphaType, shared_image_usage, "LayerTreeHostUIResource",
std::move(handle));
kPremul_SkAlphaType, shared_image_usage, "LayerTreeHostUIResource");
CHECK(client_shared_image);
shared_bitmap_id = client_shared_image->mailbox();
scoped_mapping = client_shared_image->Map();
CHECK(scoped_mapping);
} else {
shm = viz::bitmap_allocation::AllocateSharedBitmap(upload_size, format);
mapping = std::move(shm.mapping);
shared_mapping = std::move(shm.mapping);
shared_bitmap_id = viz::SharedBitmap::GenerateId();
}
@@ -4737,8 +4724,10 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid,
SkImageInfo dst_info =
SkImageInfo::MakeN32Premul(gfx::SizeToSkISize(upload_size));
sk_sp<SkSurface> surface = SkSurfaces::WrapPixels(
dst_info, mapping.memory(), dst_info.minRowBytes());
void* pixels =
scoped_mapping ? scoped_mapping->Memory(0) : shared_mapping.memory();
sk_sp<SkSurface> surface =
SkSurfaces::WrapPixels(dst_info, pixels, dst_info.minRowBytes());
surface->getCanvas()->writePixels(
src_info, const_cast<uint8_t*>(bitmap.GetPixels()),
bitmap.row_bytes(), 0, 0);
@@ -4774,8 +4763,10 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid,
} else {
SkImageInfo dst_info =
SkImageInfo::MakeN32Premul(gfx::SizeToSkISize(upload_size));
scaled_surface = SkSurfaces::WrapPixels(dst_info, mapping.memory(),
dst_info.minRowBytes());
void* pixels =
scoped_mapping ? scoped_mapping->Memory(0) : shared_mapping.memory();
scaled_surface =
SkSurfaces::WrapPixels(dst_info, pixels, dst_info.minRowBytes());
CHECK(scaled_surface); // This could fail on invalid parameters.
}
SkCanvas* scaled_canvas = scaled_surface->getCanvas();
@@ -4823,7 +4814,7 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid,
auto* sii = layer_tree_frame_sink_->shared_image_interface();
gpu::SyncToken sync_token = sii->GenVerifiedSyncToken();
transferable = viz::TransferableResource::MakeSoftware(
shared_bitmap_id, sync_token, upload_size, format,
client_shared_image->mailbox(), sync_token, upload_size, format,
viz::TransferableResource::ResourceSource::kUI);
} else {
layer_tree_frame_sink_->DidAllocateSharedBitmap(std::move(shm.region),
@@ -4847,7 +4838,7 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid,
data.format = format;
if (!use_shared_image) {
data.shared_bitmap_id = shared_bitmap_id;
data.shared_mapping = std::move(mapping);
data.shared_mapping = std::move(shared_mapping);
}
data.shared_image = std::move(client_shared_image);
data.resource_id_for_export = id;

@@ -264,6 +264,21 @@ TestSharedImageInterface::CreateSharedImage(
return base::MakeRefCounted<gpu::ClientSharedImage>(mailbox);
}
scoped_refptr<gpu::ClientSharedImage>
TestSharedImageInterface::CreateSharedImage(SharedImageFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
GrSurfaceOrigin surface_origin,
SkAlphaType alpha_type,
uint32_t usage,
base::StringPiece debug_label) {
base::AutoLock locked(lock_);
auto mailbox = gpu::Mailbox::GenerateForSharedImage();
shared_images_.insert(mailbox);
most_recent_size_ = size;
return base::MakeRefCounted<gpu::ClientSharedImage>(mailbox);
}
scoped_refptr<gpu::ClientSharedImage>
TestSharedImageInterface::CreateSharedImage(
gfx::GpuMemoryBuffer* gpu_memory_buffer,

@@ -97,6 +97,15 @@ class TestSharedImageInterface : public gpu::SharedImageInterface {
base::StringPiece debug_label,
gfx::GpuMemoryBufferHandle buffer_handle) override;
scoped_refptr<gpu::ClientSharedImage> CreateSharedImage(
SharedImageFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
GrSurfaceOrigin surface_origin,
SkAlphaType alpha_type,
uint32_t usage,
base::StringPiece debug_label) override;
scoped_refptr<gpu::ClientSharedImage> CreateSharedImage(
gfx::GpuMemoryBuffer* gpu_memory_buffer,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,

@@ -158,6 +158,19 @@ class GPU_EXPORT SharedImageInterface {
base::StringPiece debug_label,
gfx::GpuMemoryBufferHandle buffer_handle) = 0;
// Creates a shared image with the usage of gpu::SHARED_IMAGE_USAGE_CPU_WRITE
// only. A shared memory buffer is created internally and a shared image is
// created out this buffer. This method is used by the software compositor
// only.
virtual scoped_refptr<ClientSharedImage> CreateSharedImage(
viz::SharedImageFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
GrSurfaceOrigin surface_origin,
SkAlphaType alpha_type,
uint32_t usage,
base::StringPiece debug_label) = 0;
// NOTE: The below method is DEPRECATED for `gpu_memory_buffer` only with
// single planar eg. RGB BufferFormats. Please use the equivalent method above
// taking in single planar SharedImageFormat with GpuMemoryBufferHandle.

@@ -5,10 +5,12 @@
#include "gpu/command_buffer/service/shared_image_interface_in_process.h"
#include <optional>
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/synchronization/waitable_event.h"
#include "build/build_config.h"
#include "components/viz/common/resources/shared_image_format_utils.h"
#include "gpu/command_buffer/client/client_shared_image.h"
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
@@ -24,6 +26,7 @@
#include "gpu/config/gpu_feature_info.h"
#include "gpu/config/gpu_preferences.h"
#include "gpu/ipc/common/gpu_client_ids.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gl/gl_context.h"
namespace gpu {
@@ -503,6 +506,60 @@ SharedImageInterfaceInProcess::CreateSharedImage(
return base::MakeRefCounted<ClientSharedImage>(mailbox);
}
scoped_refptr<ClientSharedImage>
SharedImageInterfaceInProcess::CreateSharedImage(
viz::SharedImageFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
GrSurfaceOrigin surface_origin,
SkAlphaType alpha_type,
uint32_t usage,
base::StringPiece debug_label) {
DCHECK(gpu::IsValidClientUsage(usage));
DCHECK_EQ(usage, gpu::SHARED_IMAGE_USAGE_CPU_WRITE);
#if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_WIN)
CHECK(!format.PrefersExternalSampler());
#endif
gfx::BufferFormat buffer_format =
viz::SinglePlaneSharedImageFormatToBufferFormat(format);
const size_t buffer_size =
gfx::BufferSizeForBufferFormat(size, buffer_format);
auto shared_memory_region =
base::UnsafeSharedMemoryRegion::Create(buffer_size);
CHECK(shared_memory_region.IsValid());
gfx::GpuMemoryBufferHandle handle;
handle.type = gfx::SHARED_MEMORY_BUFFER;
handle.offset = 0;
handle.stride = static_cast<int32_t>(
gfx::RowSizeForBufferFormat(size.width(), buffer_format, 0));
handle.region = std::move(shared_memory_region);
GpuMemoryBufferHandleInfo handle_info = GpuMemoryBufferHandleInfo(
handle.Clone(), format, size, gfx::BufferUsage::SCANOUT_CPU_READ_WRITE);
auto mailbox = Mailbox::GenerateForSharedImage();
{
base::AutoLock lock(lock_);
SyncToken sync_token = MakeSyncToken(next_fence_sync_release_++);
// Note: we enqueue the task under the lock to guarantee monotonicity of
// the release ids as seen by the service. Unretained is safe because
// InProcessCommandBuffer synchronizes with the GPU thread at destruction
// time, cancelling tasks, before |this| is destroyed.
ScheduleGpuTask(
base::BindOnce(&SharedImageInterfaceInProcess::
CreateSharedImageWithBufferOnGpuThread,
base::Unretained(this), mailbox, format, size,
color_space, surface_origin, alpha_type, usage,
std::move(handle), std::string(debug_label), sync_token),
{});
}
return base::MakeRefCounted<ClientSharedImage>(mailbox,
std::move(handle_info));
}
void SharedImageInterfaceInProcess::CreateSharedImageWithBufferOnGpuThread(
const Mailbox& mailbox,

@@ -115,6 +115,14 @@ class GPU_GLES2_EXPORT SharedImageInterfaceInProcess
uint32_t usage,
base::StringPiece debug_label,
gfx::GpuMemoryBufferHandle buffer_handle) override;
scoped_refptr<ClientSharedImage> CreateSharedImage(
viz::SharedImageFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
GrSurfaceOrigin surface_origin,
SkAlphaType alpha_type,
uint32_t usage,
base::StringPiece debug_label) override;
scoped_refptr<ClientSharedImage> CreateSharedImage(
gfx::GpuMemoryBuffer* gpu_memory_buffer,
GpuMemoryBufferManager* gpu_memory_buffer_manager,

@@ -12,6 +12,7 @@
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/ipc/client/gpu_channel_host.h"
#include "gpu/ipc/client/shared_image_interface_proxy.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/gpu_fence.h"
#include "ui/gfx/gpu_memory_buffer.h"
@@ -198,6 +199,47 @@ scoped_refptr<ClientSharedImage> ClientSharedImageInterface::CreateSharedImage(
debug_label, std::move(buffer_handle))));
}
scoped_refptr<ClientSharedImage> ClientSharedImageInterface::CreateSharedImage(
viz::SharedImageFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
GrSurfaceOrigin surface_origin,
SkAlphaType alpha_type,
uint32_t usage,
base::StringPiece debug_label) {
DCHECK(gpu::IsValidClientUsage(usage)) << usage;
DCHECK_EQ(usage, gpu::SHARED_IMAGE_USAGE_CPU_WRITE);
DCHECK(viz::HasEquivalentBufferFormat(format)) << format.ToString();
CHECK(!format.IsLegacyMultiplanar()) << format.ToString();
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
CHECK(!format.PrefersExternalSampler()) << format.ToString();
#endif
gfx::BufferFormat buffer_format =
viz::SinglePlaneSharedImageFormatToBufferFormat(format);
const size_t buffer_size =
gfx::BufferSizeForBufferFormat(size, buffer_format);
auto shared_memory_region =
base::UnsafeSharedMemoryRegion::Create(buffer_size);
CHECK(shared_memory_region.IsValid());
gfx::GpuMemoryBufferHandle handle;
handle.type = gfx::SHARED_MEMORY_BUFFER;
handle.offset = 0;
handle.stride = static_cast<int32_t>(
gfx::RowSizeForBufferFormat(size.width(), buffer_format, 0));
handle.region = std::move(shared_memory_region);
GpuMemoryBufferHandleInfo handle_info = GpuMemoryBufferHandleInfo(
handle.Clone(), format, size, gfx::BufferUsage::SCANOUT_CPU_READ_WRITE);
return base::MakeRefCounted<ClientSharedImage>(
AddMailbox(proxy_->CreateSharedImage(format, size, color_space,
surface_origin, alpha_type, usage,
debug_label, std::move(handle))),
std::move(handle_info));
}
scoped_refptr<ClientSharedImage> ClientSharedImageInterface::CreateSharedImage(
gfx::GpuMemoryBuffer* gpu_memory_buffer,
GpuMemoryBufferManager* gpu_memory_buffer_manager,

@@ -96,6 +96,19 @@ class GPU_EXPORT ClientSharedImageInterface : public SharedImageInterface {
uint32_t usage,
base::StringPiece debug_label,
gfx::GpuMemoryBufferHandle buffer_handle) override;
// Used by the software compositor only. |useage| must be
// gpu::SHARED_IMAGE_USAGE_CPU_WRITE. Call client_shared_image->Map() later to
// get the shared memory mapping.
scoped_refptr<ClientSharedImage> CreateSharedImage(
viz::SharedImageFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
GrSurfaceOrigin surface_origin,
SkAlphaType alpha_type,
uint32_t usage,
base::StringPiece debug_label) override;
// NOTE: The below method is DEPRECATED for `gpu_memory_buffer` only with
// single planar eg. RGB BufferFormats. Please use the equivalent method above
// taking in single planar SharedImageFormat with GpuMemoryBufferHandle.

@@ -159,6 +159,17 @@ class TestSharedImageInterface : public gpu::SharedImageInterface {
return base::MakeRefCounted<gpu::ClientSharedImage>(result);
}
scoped_refptr<gpu::ClientSharedImage> CreateSharedImage(
viz::SharedImageFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
GrSurfaceOrigin surface_origin,
SkAlphaType alpha_type,
uint32_t usage,
base::StringPiece debug_label) override {
return base::MakeRefCounted<gpu::ClientSharedImage>(gpu::Mailbox());
}
scoped_refptr<gpu::ClientSharedImage> CreateSharedImage(
gfx::GpuMemoryBuffer* gpu_memory_buffer,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,