Commit 121fd31c authored by Khushal's avatar Khushal Committed by Commit Bot

gpu: Ensure correct shared image lifetime.

A lot of client code assumes that if a context is lost (which could be
a GPU process crash or an error in the command stream) any resources
created by it will be cleaned up automatically. This is particularly
true for SharedGpuContext where all users hold a weakptr and the object
is destroyed on a context error.

While the above assumption is true for any resources created using the
command buffer (GL/Raster/Dawn) which is per context, its not true for
shared images where the service side ties their lifetime to the shared
GpuChannel for a process. This inconsistency can result in leaking these
images if the client doesn't try to re-create a new context to delete
them. On the flip side deleting a non-existent shared image results in a
fatal error on the service side which tears down the GpuChannel, which
means clients need to distinguish between losing a single context versus
the GpuChannel to know when cleanup is needed making the ownership
management here quite brittle.

This change makes shared image ownership semantics similar to other
resources created using a context by adding tracking for shared images
created using the SharedImageInterface on a particular context. If that
context is destroyed, it internally ensures any associated alive shared
images are destroyed.

R=ericrk@chromium.org

Change-Id: Iaba4b1f791a2c0ed7890d3a593b9f158c152bc7d
Bug: 1042446,1042481,1036142
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2006731Reviewed-by: default avatarEric Karl <ericrk@chromium.org>
Reviewed-by: default avatarFrank Liberato <liberato@chromium.org>
Commit-Queue: Khushal <khushalsagar@chromium.org>
Auto-Submit: Khushal <khushalsagar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#734034}
parent 1f961201
......@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/macros.h"
#include "gpu/ipc/client/client_shared_image_interface.h"
#include "gpu/ipc/client/gpu_channel_host.h"
#include "gpu/ipc/common/gpu_messages.h"
#include "ui/gfx/geometry/size.h"
......@@ -147,7 +148,12 @@ unsigned StreamTextureFactory::CreateStreamTexture() {
}
gpu::SharedImageInterface* StreamTextureFactory::SharedImageInterface() {
return channel_->shared_image_interface();
if (shared_image_interface_)
return shared_image_interface_.get();
shared_image_interface_ = channel_->CreateClientSharedImageInterface();
DCHECK(shared_image_interface_);
return shared_image_interface_.get();
}
} // namespace content
......@@ -20,6 +20,7 @@
#include "ui/gfx/geometry/size.h"
namespace gpu {
class ClientSharedImageInterface;
class GpuChannelHost;
class SharedImageInterface;
struct SyncToken;
......@@ -124,6 +125,7 @@ class CONTENT_EXPORT StreamTextureFactory
unsigned CreateStreamTexture();
scoped_refptr<gpu::GpuChannelHost> channel_;
std::unique_ptr<gpu::ClientSharedImageInterface> shared_image_interface_;
DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureFactory);
};
......
......@@ -67,6 +67,7 @@ jumbo_source_set("client_sources") {
"mapped_memory.h",
"ring_buffer.cc",
"ring_buffer.h",
"shared_image_interface.cc",
"shared_image_interface.h",
"transfer_buffer.cc",
"transfer_buffer.h",
......
// Copyright 2020 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.
#include "gpu/command_buffer/client/shared_image_interface.h"
namespace gpu {
uint32_t SharedImageInterface::UsageForMailbox(const Mailbox& mailbox) {
return 0u;
}
} // namespace gpu
......@@ -12,9 +12,13 @@
#include "components/viz/common/resources/resource_format.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "gpu/gpu_export.h"
#include "ui/gfx/buffer_types.h"
#if !defined(OS_NACL)
#include "ui/gfx/native_pixmap.h"
#include "ui/gfx/native_pixmap_handle.h"
#endif
#if defined(OS_FUCHSIA)
#include <lib/zx/channel.h>
......@@ -35,7 +39,7 @@ class GpuMemoryBufferManager;
// It is asynchronous in the same sense as GLES2Interface or RasterInterface in
// that commands are executed asynchronously on the service side, but can be
// synchronized using SyncTokens. See //docs/design/gpu_synchronization.md.
class SharedImageInterface {
class GPU_EXPORT SharedImageInterface {
public:
virtual ~SharedImageInterface() {}
......@@ -159,6 +163,7 @@ class SharedImageInterface {
// Flush the SharedImageInterface, issuing any deferred IPCs.
virtual void Flush() = 0;
#if !defined(OS_NACL)
// Returns the NativePixmap backing |mailbox|. This is a privileged API. Only
// the callers living inside the GPU process are able to retrieve the
// NativePixmap; otherwise null is returned. Also returns null if the
......@@ -168,6 +173,11 @@ class SharedImageInterface {
// facilitate pageflip testing on the viz thread.
virtual scoped_refptr<gfx::NativePixmap> GetNativePixmap(
const gpu::Mailbox& mailbox) = 0;
#endif
// Provides the usage flags supported by the given |mailbox|. This must have
// been created using a SharedImageInterface on the same channel.
virtual uint32_t UsageForMailbox(const Mailbox& mailbox);
};
} // namespace gpu
......
......@@ -6,18 +6,16 @@ import("//build/config/ui.gni")
group("client") {
if (is_component_build) {
public_deps = [
"//gpu",
]
public_deps = [ "//gpu" ]
} else {
public_deps = [
":ipc_client_sources",
]
public_deps = [ ":ipc_client_sources" ]
}
}
source_set("ipc_client_sources") {
sources = [
"client_shared_image_interface.cc",
"client_shared_image_interface.h",
"command_buffer_proxy_impl.cc",
"command_buffer_proxy_impl.h",
"gpu_channel_host.cc",
......@@ -43,7 +41,5 @@ source_set("ipc_client_sources") {
"//ui/gfx/geometry",
"//ui/gl",
]
public_deps = [
"//ipc",
]
public_deps = [ "//ipc" ]
}
// Copyright 2020 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.
#include "gpu/ipc/client/client_shared_image_interface.h"
#include "gpu/ipc/client/shared_image_interface_proxy.h"
#include "ui/gfx/gpu_fence.h"
namespace gpu {
ClientSharedImageInterface::ClientSharedImageInterface(
SharedImageInterfaceProxy* proxy)
: proxy_(proxy) {}
ClientSharedImageInterface::~ClientSharedImageInterface() {
gpu::SyncToken sync_token;
auto mailboxes_to_delete = mailboxes_;
for (const auto& mailbox : mailboxes_to_delete)
DestroySharedImage(sync_token, mailbox);
}
void ClientSharedImageInterface::UpdateSharedImage(const SyncToken& sync_token,
const Mailbox& mailbox) {
proxy_->UpdateSharedImage(sync_token, mailbox);
}
void ClientSharedImageInterface::UpdateSharedImage(
const SyncToken& sync_token,
std::unique_ptr<gfx::GpuFence> acquire_fence,
const Mailbox& mailbox) {
proxy_->UpdateSharedImage(sync_token, std::move(acquire_fence), mailbox);
}
void ClientSharedImageInterface::PresentSwapChain(const SyncToken& sync_token,
const Mailbox& mailbox) {
proxy_->PresentSwapChain(sync_token, mailbox);
}
#if defined(OS_FUCHSIA)
void ClientSharedImageInterface::RegisterSysmemBufferCollection(
gfx::SysmemBufferCollectionId id,
zx::channel token) {
proxy_->RegisterSysmemBufferCollection(id, std::move(token));
}
void ClientSharedImageInterface::ReleaseSysmemBufferCollection(
gfx::SysmemBufferCollectionId id) {
proxy_->ReleaseSysmemBufferCollection(id);
}
#endif // defined(OS_FUCHSIA)
SyncToken ClientSharedImageInterface::GenUnverifiedSyncToken() {
return proxy_->GenUnverifiedSyncToken();
}
SyncToken ClientSharedImageInterface::GenVerifiedSyncToken() {
return proxy_->GenVerifiedSyncToken();
}
void ClientSharedImageInterface::Flush() {
proxy_->Flush();
}
scoped_refptr<gfx::NativePixmap> ClientSharedImageInterface::GetNativePixmap(
const gpu::Mailbox& mailbox) {
return proxy_->GetNativePixmap(mailbox);
}
Mailbox ClientSharedImageInterface::CreateSharedImage(
viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage) {
return AddMailbox(
proxy_->CreateSharedImage(format, size, color_space, usage));
}
Mailbox ClientSharedImageInterface::CreateSharedImage(
viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage,
base::span<const uint8_t> pixel_data) {
return AddMailbox(
proxy_->CreateSharedImage(format, size, color_space, usage, pixel_data));
}
Mailbox ClientSharedImageInterface::CreateSharedImage(
gfx::GpuMemoryBuffer* gpu_memory_buffer,
GpuMemoryBufferManager* gpu_memory_buffer_manager,
const gfx::ColorSpace& color_space,
uint32_t usage) {
return AddMailbox(proxy_->CreateSharedImage(
gpu_memory_buffer, gpu_memory_buffer_manager, color_space, usage));
}
ClientSharedImageInterface::SwapChainMailboxes
ClientSharedImageInterface::CreateSwapChain(viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage) {
auto mailboxes = proxy_->CreateSwapChain(format, size, color_space, usage);
AddMailbox(mailboxes.front_buffer);
AddMailbox(mailboxes.back_buffer);
return mailboxes;
}
void ClientSharedImageInterface::DestroySharedImage(const SyncToken& sync_token,
const Mailbox& mailbox) {
DCHECK(!mailbox.IsZero());
{
base::AutoLock lock(lock_);
DCHECK_NE(mailboxes_.count(mailbox), 0u);
mailboxes_.erase(mailbox);
}
proxy_->DestroySharedImage(sync_token, mailbox);
}
uint32_t ClientSharedImageInterface::UsageForMailbox(const Mailbox& mailbox) {
return proxy_->UsageForMailbox(mailbox);
}
Mailbox ClientSharedImageInterface::AddMailbox(const gpu::Mailbox& mailbox) {
if (mailbox.IsZero())
return mailbox;
base::AutoLock lock(lock_);
DCHECK_EQ(mailboxes_.count(mailbox), 0u);
mailboxes_.insert(mailbox);
return mailbox;
}
} // namespace gpu
// Copyright 2020 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 GPU_IPC_CLIENT_CLIENT_SHARED_IMAGE_INTERFACE_H_
#define GPU_IPC_CLIENT_CLIENT_SHARED_IMAGE_INTERFACE_H_
#include "gpu/command_buffer/client/shared_image_interface.h"
#include "base/containers/flat_set.h"
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
namespace gpu {
class SharedImageInterfaceProxy;
// Tracks shared images created by a single context and ensures they are deleted
// if the context is lost.
class GPU_EXPORT ClientSharedImageInterface : public SharedImageInterface {
public:
ClientSharedImageInterface(SharedImageInterfaceProxy* proxy);
~ClientSharedImageInterface() override;
// SharedImageInterface implementation.
void UpdateSharedImage(const SyncToken& sync_token,
const Mailbox& mailbox) override;
void UpdateSharedImage(const SyncToken& sync_token,
std::unique_ptr<gfx::GpuFence> acquire_fence,
const Mailbox& mailbox) override;
void PresentSwapChain(const SyncToken& sync_token,
const Mailbox& mailbox) override;
#if defined(OS_FUCHSIA)
void RegisterSysmemBufferCollection(gfx::SysmemBufferCollectionId id,
zx::channel token) override;
void ReleaseSysmemBufferCollection(gfx::SysmemBufferCollectionId id) override;
#endif // defined(OS_FUCHSIA)
SyncToken GenUnverifiedSyncToken() override;
SyncToken GenVerifiedSyncToken() override;
void Flush() override;
scoped_refptr<gfx::NativePixmap> GetNativePixmap(
const Mailbox& mailbox) override;
Mailbox CreateSharedImage(viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage) override;
Mailbox CreateSharedImage(viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage,
base::span<const uint8_t> pixel_data) override;
Mailbox CreateSharedImage(gfx::GpuMemoryBuffer* gpu_memory_buffer,
GpuMemoryBufferManager* gpu_memory_buffer_manager,
const gfx::ColorSpace& color_space,
uint32_t usage) override;
SwapChainMailboxes CreateSwapChain(viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage) override;
void DestroySharedImage(const SyncToken& sync_token,
const Mailbox& mailbox) override;
uint32_t UsageForMailbox(const Mailbox& mailbox) override;
private:
Mailbox AddMailbox(const Mailbox& mailbox);
SharedImageInterfaceProxy* const proxy_;
base::Lock lock_;
base::flat_set<Mailbox> mailboxes_ GUARDED_BY(lock_);
};
} // namespace gpu
#endif // GPU_IPC_CLIENT_CLIENT_SHARED_IMAGE_INTERFACE_H_
......@@ -14,6 +14,7 @@
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "gpu/ipc/client/client_shared_image_interface.h"
#include "gpu/ipc/common/command_buffer_id.h"
#include "gpu/ipc/common/gpu_messages.h"
#include "gpu/ipc/common/gpu_param_traits_macros.h"
......@@ -239,6 +240,11 @@ void GpuChannelHost::CrashGpuProcessForTesting() {
Send(new GpuChannelMsg_CrashForTesting());
}
std::unique_ptr<ClientSharedImageInterface>
GpuChannelHost::CreateClientSharedImageInterface() {
return std::make_unique<ClientSharedImageInterface>(&shared_image_interface_);
}
GpuChannelHost::~GpuChannelHost() = default;
GpuChannelHost::Listener::RouteInfo::RouteInfo() = default;
......
......@@ -38,6 +38,7 @@ class ChannelMojo;
struct GpuDeferredMessage;
namespace gpu {
class ClientSharedImageInterface;
struct SyncToken;
class GpuChannelHost;
class GpuMemoryBufferManager;
......@@ -135,9 +136,8 @@ class GPU_EXPORT GpuChannelHost
// otherwise ignored.
void CrashGpuProcessForTesting();
SharedImageInterface* shared_image_interface() {
return &shared_image_interface_;
}
std::unique_ptr<ClientSharedImageInterface>
CreateClientSharedImageInterface();
ImageDecodeAcceleratorProxy* image_decode_accelerator_proxy() {
return &image_decode_accelerator_proxy_;
......
......@@ -70,12 +70,14 @@ Mailbox SharedImageInterfaceProxy::CreateSharedImage(
params.usage = usage;
{
base::AutoLock lock(lock_);
AddMailbox(params.mailbox, usage);
params.release_id = ++next_release_id_;
// Note: we enqueue the IPC under the lock to guarantee monotonicity of the
// release ids as seen by the service.
last_flush_id_ = host_->EnqueueDeferredMessage(
GpuChannelMsg_CreateSharedImage(route_id_, params));
}
return params.mailbox;
}
......@@ -117,6 +119,8 @@ Mailbox SharedImageInterfaceProxy::CreateSharedImage(
params.release_id = ++next_release_id_;
last_flush_id_ = host_->EnqueueDeferredMessage(
GpuChannelMsg_CreateSharedImageWithData(route_id_, params));
AddMailbox(params.mailbox, usage);
return params.mailbox;
}
......@@ -163,6 +167,9 @@ Mailbox SharedImageInterfaceProxy::CreateSharedImage(
gpu_memory_buffer_manager->SetDestructionSyncToken(gpu_memory_buffer,
sync_token);
}
base::AutoLock lock(lock_);
AddMailbox(params.mailbox, usage);
return mailbox;
}
......@@ -228,6 +235,10 @@ void SharedImageInterfaceProxy::DestroySharedImage(const SyncToken& sync_token,
}
{
base::AutoLock lock(lock_);
DCHECK_NE(mailbox_to_usage_.count(mailbox), 0u);
mailbox_to_usage_.erase(mailbox);
last_flush_id_ = host_->EnqueueDeferredMessage(
GpuChannelMsg_DestroySharedImage(route_id_, mailbox),
std::move(dependencies));
......@@ -333,6 +344,10 @@ SharedImageInterfaceProxy::CreateSwapChain(viz::ResourceFormat format,
params.usage = usage;
{
base::AutoLock lock(lock_);
AddMailbox(params.front_buffer_mailbox, usage);
AddMailbox(params.back_buffer_mailbox, usage);
params.release_id = ++next_release_id_;
last_flush_id_ = host_->EnqueueDeferredMessage(
GpuChannelMsg_CreateSwapChain(route_id_, params));
......@@ -394,4 +409,23 @@ scoped_refptr<gfx::NativePixmap> SharedImageInterfaceProxy::GetNativePixmap(
return nullptr;
}
void SharedImageInterfaceProxy::AddMailbox(const Mailbox& mailbox,
uint32_t usage) {
lock_.AssertAcquired();
DCHECK_EQ(mailbox_to_usage_.count(mailbox), 0u);
mailbox_to_usage_[mailbox] = usage;
}
uint32_t SharedImageInterfaceProxy::UsageForMailbox(const Mailbox& mailbox) {
base::AutoLock lock(lock_);
// The mailbox may have been destroyed if the context on which the shared
// image was created is deleted.
auto it = mailbox_to_usage_.find(mailbox);
if (it == mailbox_to_usage_.end())
return 0u;
return it->second;
}
} // namespace gpu
......@@ -15,58 +15,59 @@
namespace gpu {
class GpuChannelHost;
// Implementation of SharedImageInterface that sends commands over GPU channel
// IPCs.
class SharedImageInterfaceProxy : public SharedImageInterface {
// Proxy that sends commands over GPU channel IPCs for managing shared images.
class SharedImageInterfaceProxy {
public:
explicit SharedImageInterfaceProxy(GpuChannelHost* host, int32_t route_id);
~SharedImageInterfaceProxy() override;
~SharedImageInterfaceProxy();
Mailbox CreateSharedImage(viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage) override;
uint32_t usage);
Mailbox CreateSharedImage(viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage,
base::span<const uint8_t> pixel_data) override;
base::span<const uint8_t> pixel_data);
Mailbox CreateSharedImage(gfx::GpuMemoryBuffer* gpu_memory_buffer,
GpuMemoryBufferManager* gpu_memory_buffer_manager,
const gfx::ColorSpace& color_space,
uint32_t usage) override;
void UpdateSharedImage(const SyncToken& sync_token,
const Mailbox& mailbox) override;
uint32_t usage);
void UpdateSharedImage(const SyncToken& sync_token, const Mailbox& mailbox);
void UpdateSharedImage(const SyncToken& sync_token,
std::unique_ptr<gfx::GpuFence> acquire_fence,
const Mailbox& mailbox) override;
const Mailbox& mailbox);
void DestroySharedImage(const SyncToken& sync_token,
const Mailbox& mailbox) override;
SyncToken GenVerifiedSyncToken() override;
SyncToken GenUnverifiedSyncToken() override;
void Flush() override;
void DestroySharedImage(const SyncToken& sync_token, const Mailbox& mailbox);
SyncToken GenVerifiedSyncToken();
SyncToken GenUnverifiedSyncToken();
void Flush();
SwapChainMailboxes CreateSwapChain(viz::ResourceFormat format,
SharedImageInterface::SwapChainMailboxes CreateSwapChain(
viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage) override;
void PresentSwapChain(const SyncToken& sync_token,
const Mailbox& mailbox) override;
uint32_t usage);
void PresentSwapChain(const SyncToken& sync_token, const Mailbox& mailbox);
#if defined(OS_FUCHSIA)
void RegisterSysmemBufferCollection(gfx::SysmemBufferCollectionId id,
zx::channel token) override;
void ReleaseSysmemBufferCollection(gfx::SysmemBufferCollectionId id) override;
zx::channel token);
void ReleaseSysmemBufferCollection(gfx::SysmemBufferCollectionId id);
#endif // defined(OS_FUCHSIA)
scoped_refptr<gfx::NativePixmap> GetNativePixmap(
const gpu::Mailbox& mailbox) override;
scoped_refptr<gfx::NativePixmap> GetNativePixmap(const gpu::Mailbox& mailbox);
uint32_t UsageForMailbox(const Mailbox& mailbox);
private:
bool GetSHMForPixelData(base::span<const uint8_t> pixel_data,
size_t* shm_offset,
bool* done_with_shm) EXCLUSIVE_LOCKS_REQUIRED(lock_);
void AddMailbox(const Mailbox& mailbox, uint32_t usage)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
GpuChannelHost* const host_;
const int32_t route_id_;
base::Lock lock_;
......@@ -77,6 +78,8 @@ class SharedImageInterfaceProxy : public SharedImageInterface {
base::MappedReadOnlyRegion upload_buffer_ GUARDED_BY(lock_);
// The offset into |upload_buffer_| at which data is no longer used.
size_t upload_buffer_offset_ GUARDED_BY(lock_) = 0;
base::flat_map<Mailbox, uint32_t> mailbox_to_usage_ GUARDED_BY(lock_);
};
} // namespace gpu
......
......@@ -36,6 +36,7 @@
#include "gpu/command_buffer/common/skia_utils.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/config/skia_limits.h"
#include "gpu/ipc/client/client_shared_image_interface.h"
#include "gpu/ipc/client/command_buffer_proxy_impl.h"
#include "gpu/ipc/client/gpu_channel_host.h"
#include "gpu/skia_bindings/gles2_implementation_with_grcontext_support.h"
......@@ -325,6 +326,10 @@ gpu::ContextResult ContextProviderCommandBuffer::BindToCurrentThread() {
command_buffer_->SetLock(&context_lock_);
cache_controller_->SetLock(&context_lock_);
}
shared_image_interface_ = channel_->CreateClientSharedImageInterface();
DCHECK(shared_image_interface_);
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
this, "ContextProviderCommandBuffer", std::move(task_runner));
return bind_result_;
......@@ -412,7 +417,7 @@ class GrContext* ContextProviderCommandBuffer::GrContext() {
gpu::SharedImageInterface*
ContextProviderCommandBuffer::SharedImageInterface() {
return command_buffer_->channel()->shared_image_interface();
return shared_image_interface_.get();
}
ContextCacheController* ContextProviderCommandBuffer::CacheController() {
......
......@@ -29,6 +29,7 @@
namespace gpu {
class CommandBufferHelper;
class CommandBufferProxyImpl;
class ClientSharedImageInterface;
class GpuChannelHost;
struct GpuFeatureInfo;
class GpuMemoryBufferManager;
......@@ -148,6 +149,11 @@ class ContextProviderCommandBuffer
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_;
scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
// |shared_image_interface_| must be torn down after |command_buffer_| to
// ensure any dependent commands in the command stream are flushed before the
// associated shared images are destroyed.
std::unique_ptr<gpu::ClientSharedImageInterface> shared_image_interface_;
base::Lock context_lock_; // Referenced by command_buffer_.
std::unique_ptr<gpu::CommandBufferProxyImpl> command_buffer_;
std::unique_ptr<gpu::CommandBufferHelper> helper_;
......
......@@ -111,7 +111,6 @@ static void ReleaseFrameResources(
// TODO(khushalsagar): If multiple readers had access to this resource, losing
// it once should make sure subsequent releases don't try to recycle this
// resource.
// Also what about single buffered canvas?
if (lost_resource)
resource->NotifyResourceLost();
if (resource_provider && !lost_resource && resource->IsRecycleable())
......@@ -286,6 +285,12 @@ void CanvasResourceSharedBitmap::Abandon() {
shared_mapping_ = {};
}
void CanvasResourceSharedBitmap::NotifyResourceLost() {
// Release our reference to the shared memory mapping since the resource can
// no longer be safely recycled and this memory is needed for copy-on-write.
shared_mapping_ = {};
}
const gpu::Mailbox& CanvasResourceSharedBitmap::GetOrCreateGpuMailbox(
MailboxSyncMode sync_mode) {
return shared_bitmap_id_;
......@@ -425,6 +430,8 @@ CanvasResourceSharedImage::~CanvasResourceSharedImage() {
void CanvasResourceSharedImage::TearDown() {
DCHECK(!is_cross_thread());
// The context deletes all shared images on destruction which means no
// cleanup is needed if the context was lost.
if (ContextProviderWrapper()) {
auto* raster_interface = RasterInterface();
auto* shared_image_interface =
......@@ -455,11 +462,8 @@ void CanvasResourceSharedImage::TearDown() {
}
void CanvasResourceSharedImage::Abandon() {
if (auto context_provider = SharedGpuContext::ContextProviderWrapper()) {
auto* sii = context_provider->ContextProvider()->SharedImageInterface();
if (sii)
sii->DestroySharedImage(gpu::SyncToken(), mailbox());
}
// Called when the owning thread has been torn down which will destroy the
// context on which the shared image was created so no cleanup is necessary.
}
void CanvasResourceSharedImage::WillDraw() {
......@@ -807,17 +811,16 @@ scoped_refptr<StaticBitmapImage> CanvasResourceSwapChain::Bitmap() {
}
void CanvasResourceSwapChain::Abandon() {
if (auto context_provider = SharedGpuContext::ContextProviderWrapper()) {
auto* sii = context_provider->ContextProvider()->SharedImageInterface();
DCHECK(sii);
sii->DestroySharedImage(gpu::SyncToken(), front_buffer_mailbox_);
sii->DestroySharedImage(gpu::SyncToken(), back_buffer_mailbox_);
}
// Called when the owning thread has been torn down which will destroy the
// context on which the shared image was created so no cleanup is necessary.
}
void CanvasResourceSwapChain::TearDown() {
// The context deletes all shared images on destruction which means no
// cleanup is needed if the context was lost.
if (!context_provider_wrapper_)
return;
auto* raster_interface =
context_provider_wrapper_->ContextProvider()->RasterInterface();
DCHECK(raster_interface);
......
......@@ -140,12 +140,7 @@ class PLATFORM_EXPORT CanvasResource
// token for the resource to be safely recycled and its the GL state may be
// inconsistent with when the resource was given to the compositor. So it
// should not be recycled for writing again but can be safely read from.
virtual void NotifyResourceLost() {
// TODO(khushalsagar): Some implementations respect the don't write again
// policy but some don't. Fix that once shared images replace all
// accelerated use-cases.
Abandon();
}
virtual void NotifyResourceLost() = 0;
void SetFilterQuality(SkFilterQuality filter) { filter_quality_ = filter; }
// The filter quality to use when the resource is drawn by the compositor.
......@@ -240,6 +235,7 @@ class PLATFORM_EXPORT CanvasResourceSharedBitmap final : public CanvasResource {
bool OriginClean() const final { return is_origin_clean_; }
void SetOriginClean(bool flag) final { is_origin_clean_ = flag; }
const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) override;
void NotifyResourceLost() override;
private:
void TearDown() override;
......@@ -420,6 +416,10 @@ class PLATFORM_EXPORT ExternalCanvasResource final : public CanvasResource {
void Abandon() final;
IntSize Size() const final { return size_; }
void TakeSkImage(sk_sp<SkImage> image) final;
void NotifyResourceLost() override {
// Used for single buffering mode which doesn't need to care about sync
// token synchronization.
}
scoped_refptr<StaticBitmapImage> Bitmap() override;
const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) override;
......@@ -473,6 +473,10 @@ class PLATFORM_EXPORT CanvasResourceSwapChain final : public CanvasResource {
void Abandon() final;
IntSize Size() const final { return size_; }
void TakeSkImage(sk_sp<SkImage> image) final;
void NotifyResourceLost() override {
// Used for single buffering mode which doesn't need to care about sync
// token synchronization.
}
scoped_refptr<StaticBitmapImage> Bitmap() override;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment