Skip to content

Commit

Permalink
canvas2d: Use shared images for single buffered canvas.
Browse files Browse the repository at this point in the history
This adds support for using shared images for single buffered canvas.
In the default mode, service side code for shared images expects
exclusive write access to a resource. Since single buffered canvas does
not satisfy this constraint, a usage flag has been added to indicate it.

The current change does not update any service side code to use this
flag, which is not needed for the legacy path.

R=ericrk@chromium.org, mcasas@chromium.org

Bug: 900706
Change-Id: Icf9fb25870592c14e8d04de763295a5838e99692
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1726938
Commit-Queue: Khushal <khushalsagar@chromium.org>
Auto-Submit: Khushal <khushalsagar@chromium.org>
Reviewed-by: Eric Karl <ericrk@chromium.org>
Reviewed-by: Fernando Serboncini <fserb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#685829}
  • Loading branch information
khushalsagar authored and Commit Bot committed Aug 10, 2019
1 parent 700ce1f commit df6de6b
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 45 deletions.
4 changes: 4 additions & 0 deletions gpu/command_buffer/common/shared_image_usage.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ enum SharedImageUsage : uint32_t {
SHARED_IMAGE_USAGE_WEBGPU = 1 << 7,
// Image will be used in a protected Vulkan context on Fuchsia.
SHARED_IMAGE_USAGE_PROTECTED = 1 << 8,
// Image may use concurrent read/write access. Used by single buffered canvas.
// TODO(crbug.com/969114): This usage is currently not supported in GL/Vulkan
// interop cases.
SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE = 1 << 9,
};

} // namespace gpu
Expand Down
9 changes: 9 additions & 0 deletions gpu/command_buffer/service/shared_image_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,15 @@ SharedImageBackingFactory* SharedImageFactory::GetFactoryByUsage(
LOG_IF(ERROR, !interop_backing_factory_)
<< "Unable to create SharedImage backing: GL / Vulkan interoperability "
"is not supported on this platform";

// TODO(crbug.com/969114): Not all shared image factory implementations
// support concurrent read/write usage.
if (usage & SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE) {
LOG(ERROR) << "Unable to create SharedImage backing: Interoperability is "
"not supported for concurrent read/write usage";
return nullptr;
}

return interop_backing_factory_.get();
}

Expand Down
41 changes: 31 additions & 10 deletions third_party/blink/renderer/platform/graphics/canvas_resource.cc
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,8 @@ CanvasResourceSharedImage::CanvasResourceSharedImage(
SkFilterQuality filter_quality,
const CanvasColorParams& color_params,
bool is_overlay_candidate,
bool is_origin_top_left)
bool is_origin_top_left,
bool allow_concurrent_read_write_access)
: CanvasResource(std::move(provider), filter_quality, color_params),
context_provider_wrapper_(std::move(context_provider_wrapper)),
is_overlay_candidate_(is_overlay_candidate),
Expand Down Expand Up @@ -713,6 +714,8 @@ CanvasResourceSharedImage::CanvasResourceSharedImage(
gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT;
if (is_overlay_candidate_)
flags |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
if (allow_concurrent_read_write_access)
flags |= gpu::SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE;

auto shared_image_mailbox = shared_image_interface->CreateSharedImage(
ColorParams().TransferableResourceFormat(), gfx::Size(size),
Expand All @@ -724,8 +727,15 @@ CanvasResourceSharedImage::CanvasResourceSharedImage(
auto* gl = ContextGL();
DCHECK(gl);
owning_thread_data().shared_image_mailbox = shared_image_mailbox;
owning_thread_data().texture_id =
owning_thread_data().texture_id_for_read_access =
gl->CreateAndTexStorage2DSharedImageCHROMIUM(shared_image_mailbox.name);
if (allow_concurrent_read_write_access) {
owning_thread_data().texture_id_for_write_access =
gl->CreateAndTexStorage2DSharedImageCHROMIUM(shared_image_mailbox.name);
} else {
owning_thread_data().texture_id_for_write_access =
owning_thread_data().texture_id_for_read_access;
}
}

scoped_refptr<CanvasResourceSharedImage> CanvasResourceSharedImage::Create(
Expand All @@ -735,11 +745,13 @@ scoped_refptr<CanvasResourceSharedImage> CanvasResourceSharedImage::Create(
SkFilterQuality filter_quality,
const CanvasColorParams& color_params,
bool is_overlay_candidate,
bool is_origin_top_left) {
bool is_origin_top_left,
bool allow_concurrent_read_write_access) {
TRACE_EVENT0("blink", "CanvasResourceSharedImage::Create");
auto resource = base::AdoptRef(new CanvasResourceSharedImage(
size, std::move(context_provider_wrapper), std::move(provider),
filter_quality, color_params, is_overlay_candidate, is_origin_top_left));
filter_quality, color_params, is_overlay_candidate, is_origin_top_left,
allow_concurrent_read_write_access));
return resource->IsValid() ? resource : nullptr;
}

Expand Down Expand Up @@ -768,10 +780,19 @@ void CanvasResourceSharedImage::TearDown() {
shared_image_interface->DestroySharedImage(shared_image_sync_token,
mailbox());
}
if (gl && owning_thread_data().texture_id)
gl->DeleteTextures(1, &owning_thread_data().texture_id);
if (gl) {
if (owning_thread_data().texture_id_for_read_access) {
gl->DeleteTextures(1, &owning_thread_data().texture_id_for_read_access);
}
if (owning_thread_data().texture_id_for_write_access) {
gl->DeleteTextures(1,
&owning_thread_data().texture_id_for_write_access);
}
}
}
owning_thread_data().texture_id = 0u;

owning_thread_data().texture_id_for_read_access = 0u;
owning_thread_data().texture_id_for_write_access = 0u;
}

void CanvasResourceSharedImage::Abandon() {
Expand Down Expand Up @@ -815,7 +836,7 @@ void CanvasResourceSharedImage::OnBitmapImageDestroyed(
if (resource->owning_thread_data().bitmap_image_read_refs == 0u &&
resource->ContextGL()) {
resource->ContextGL()->EndSharedImageAccessDirectCHROMIUM(
resource->owning_thread_data().texture_id);
resource->owning_thread_data().texture_id_for_read_access);
}
}

Expand Down Expand Up @@ -859,7 +880,7 @@ scoped_refptr<StaticBitmapImage> CanvasResourceSharedImage::Bitmap() {
const bool has_read_ref_on_texture = !is_cross_thread();
GLuint texture_id_for_image = 0u;
if (has_read_ref_on_texture) {
texture_id_for_image = owning_thread_data().texture_id;
texture_id_for_image = owning_thread_data().texture_id_for_read_access;
owning_thread_data().bitmap_image_read_refs++;
if (owning_thread_data().bitmap_image_read_refs == 1u && ContextGL()) {
ContextGL()->BeginSharedImageAccessDirectCHROMIUM(
Expand Down Expand Up @@ -919,7 +940,7 @@ void CanvasResourceSharedImage::SetGLFilterIfNeeded() {
!WeakProvider())
return;

ContextGL()->BindTexture(TextureTarget(), GetTextureIdForBackendTexture());
ContextGL()->BindTexture(TextureTarget(), GetTextureIdForReadAccess());
ContextGL()->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GLFilter());
ContextGL()->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GLFilter());
ContextGL()->BindTexture(TextureTarget(), 0u);
Expand Down
23 changes: 18 additions & 5 deletions third_party/blink/renderer/platform/graphics/canvas_resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,8 @@ class PLATFORM_EXPORT CanvasResourceSharedImage final : public CanvasResource {
SkFilterQuality,
const CanvasColorParams&,
bool is_overlay_candidate,
bool is_origin_top_left);
bool is_origin_top_left,
bool allow_concurrent_read_write_access);
~CanvasResourceSharedImage() override;

bool IsRecycleable() const final { return true; }
Expand All @@ -359,9 +360,13 @@ class PLATFORM_EXPORT CanvasResourceSharedImage final : public CanvasResource {
void TakeSkImage(sk_sp<SkImage> image) final { NOTREACHED(); }
void NotifyResourceLost() final;

GLuint GetTextureIdForBackendTexture() const {
return owning_thread_data().texture_id;
GLuint GetTextureIdForReadAccess() const {
return owning_thread_data().texture_id_for_read_access;
}
GLuint GetTextureIdForWriteAccess() const {
return owning_thread_data().texture_id_for_write_access;
}

void WillDraw();
bool is_cross_thread() const {
return base::PlatformThread::CurrentId() != owning_thread_id_;
Expand All @@ -382,9 +387,16 @@ class PLATFORM_EXPORT CanvasResourceSharedImage final : public CanvasResource {
gpu::SyncToken sync_token;
bool needs_gl_filter_reset = true;
size_t bitmap_image_read_refs = 0u;
GLuint texture_id = 0u;
MailboxSyncMode mailbox_sync_mode = kVerifiedSyncToken;
bool is_lost = false;

// We need to create 2 representations if canvas is operating in single
// buffered mode to allow concurrent scopes for read and write access,
// because the Begin/EndSharedImageAccessDirectCHROMIUM APIs allow only one
// active access mode for a representation.
// In non single buffered mode, the 2 texture ids are the same.
GLuint texture_id_for_read_access = 0u;
GLuint texture_id_for_write_access = 0u;
};

static void OnBitmapImageDestroyed(
Expand All @@ -409,7 +421,8 @@ class PLATFORM_EXPORT CanvasResourceSharedImage final : public CanvasResource {
SkFilterQuality,
const CanvasColorParams&,
bool is_overlay_candidate,
bool is_origin_top_left);
bool is_origin_top_left,
bool allow_concurrent_read_write_access);
void SetGLFilterIfNeeded();

OwningThreadData& owning_thread_data() {
Expand Down

0 comments on commit df6de6b

Please sign in to comment.