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 @@ ...@@ -6,6 +6,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/macros.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/client/gpu_channel_host.h"
#include "gpu/ipc/common/gpu_messages.h" #include "gpu/ipc/common/gpu_messages.h"
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
...@@ -147,7 +148,12 @@ unsigned StreamTextureFactory::CreateStreamTexture() { ...@@ -147,7 +148,12 @@ unsigned StreamTextureFactory::CreateStreamTexture() {
} }
gpu::SharedImageInterface* StreamTextureFactory::SharedImageInterface() { 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 } // namespace content
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
namespace gpu { namespace gpu {
class ClientSharedImageInterface;
class GpuChannelHost; class GpuChannelHost;
class SharedImageInterface; class SharedImageInterface;
struct SyncToken; struct SyncToken;
...@@ -124,6 +125,7 @@ class CONTENT_EXPORT StreamTextureFactory ...@@ -124,6 +125,7 @@ class CONTENT_EXPORT StreamTextureFactory
unsigned CreateStreamTexture(); unsigned CreateStreamTexture();
scoped_refptr<gpu::GpuChannelHost> channel_; scoped_refptr<gpu::GpuChannelHost> channel_;
std::unique_ptr<gpu::ClientSharedImageInterface> shared_image_interface_;
DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureFactory); DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureFactory);
}; };
......
...@@ -67,6 +67,7 @@ jumbo_source_set("client_sources") { ...@@ -67,6 +67,7 @@ jumbo_source_set("client_sources") {
"mapped_memory.h", "mapped_memory.h",
"ring_buffer.cc", "ring_buffer.cc",
"ring_buffer.h", "ring_buffer.h",
"shared_image_interface.cc",
"shared_image_interface.h", "shared_image_interface.h",
"transfer_buffer.cc", "transfer_buffer.cc",
"transfer_buffer.h", "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 @@ ...@@ -12,9 +12,13 @@
#include "components/viz/common/resources/resource_format.h" #include "components/viz/common/resources/resource_format.h"
#include "gpu/command_buffer/common/mailbox.h" #include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/sync_token.h" #include "gpu/command_buffer/common/sync_token.h"
#include "gpu/gpu_export.h"
#include "ui/gfx/buffer_types.h" #include "ui/gfx/buffer_types.h"
#if !defined(OS_NACL)
#include "ui/gfx/native_pixmap.h" #include "ui/gfx/native_pixmap.h"
#include "ui/gfx/native_pixmap_handle.h" #include "ui/gfx/native_pixmap_handle.h"
#endif
#if defined(OS_FUCHSIA) #if defined(OS_FUCHSIA)
#include <lib/zx/channel.h> #include <lib/zx/channel.h>
...@@ -35,7 +39,7 @@ class GpuMemoryBufferManager; ...@@ -35,7 +39,7 @@ class GpuMemoryBufferManager;
// It is asynchronous in the same sense as GLES2Interface or RasterInterface in // It is asynchronous in the same sense as GLES2Interface or RasterInterface in
// that commands are executed asynchronously on the service side, but can be // that commands are executed asynchronously on the service side, but can be
// synchronized using SyncTokens. See //docs/design/gpu_synchronization.md. // synchronized using SyncTokens. See //docs/design/gpu_synchronization.md.
class SharedImageInterface { class GPU_EXPORT SharedImageInterface {
public: public:
virtual ~SharedImageInterface() {} virtual ~SharedImageInterface() {}
...@@ -159,6 +163,7 @@ class SharedImageInterface { ...@@ -159,6 +163,7 @@ class SharedImageInterface {
// Flush the SharedImageInterface, issuing any deferred IPCs. // Flush the SharedImageInterface, issuing any deferred IPCs.
virtual void Flush() = 0; virtual void Flush() = 0;
#if !defined(OS_NACL)
// Returns the NativePixmap backing |mailbox|. This is a privileged API. Only // Returns the NativePixmap backing |mailbox|. This is a privileged API. Only
// the callers living inside the GPU process are able to retrieve the // the callers living inside the GPU process are able to retrieve the
// NativePixmap; otherwise null is returned. Also returns null if the // NativePixmap; otherwise null is returned. Also returns null if the
...@@ -168,6 +173,11 @@ class SharedImageInterface { ...@@ -168,6 +173,11 @@ class SharedImageInterface {
// facilitate pageflip testing on the viz thread. // facilitate pageflip testing on the viz thread.
virtual scoped_refptr<gfx::NativePixmap> GetNativePixmap( virtual scoped_refptr<gfx::NativePixmap> GetNativePixmap(
const gpu::Mailbox& mailbox) = 0; 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 } // namespace gpu
......
...@@ -6,18 +6,16 @@ import("//build/config/ui.gni") ...@@ -6,18 +6,16 @@ import("//build/config/ui.gni")
group("client") { group("client") {
if (is_component_build) { if (is_component_build) {
public_deps = [ public_deps = [ "//gpu" ]
"//gpu",
]
} else { } else {
public_deps = [ public_deps = [ ":ipc_client_sources" ]
":ipc_client_sources",
]
} }
} }
source_set("ipc_client_sources") { source_set("ipc_client_sources") {
sources = [ sources = [
"client_shared_image_interface.cc",
"client_shared_image_interface.h",
"command_buffer_proxy_impl.cc", "command_buffer_proxy_impl.cc",
"command_buffer_proxy_impl.h", "command_buffer_proxy_impl.h",
"gpu_channel_host.cc", "gpu_channel_host.cc",
...@@ -43,7 +41,5 @@ source_set("ipc_client_sources") { ...@@ -43,7 +41,5 @@ source_set("ipc_client_sources") {
"//ui/gfx/geometry", "//ui/gfx/geometry",
"//ui/gl", "//ui/gl",
] ]
public_deps = [ public_deps = [ "//ipc" ]
"//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 @@ ...@@ -14,6 +14,7 @@
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.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/command_buffer_id.h"
#include "gpu/ipc/common/gpu_messages.h" #include "gpu/ipc/common/gpu_messages.h"
#include "gpu/ipc/common/gpu_param_traits_macros.h" #include "gpu/ipc/common/gpu_param_traits_macros.h"
...@@ -239,6 +240,11 @@ void GpuChannelHost::CrashGpuProcessForTesting() { ...@@ -239,6 +240,11 @@ void GpuChannelHost::CrashGpuProcessForTesting() {
Send(new GpuChannelMsg_CrashForTesting()); Send(new GpuChannelMsg_CrashForTesting());
} }
std::unique_ptr<ClientSharedImageInterface>
GpuChannelHost::CreateClientSharedImageInterface() {
return std::make_unique<ClientSharedImageInterface>(&shared_image_interface_);
}
GpuChannelHost::~GpuChannelHost() = default; GpuChannelHost::~GpuChannelHost() = default;
GpuChannelHost::Listener::RouteInfo::RouteInfo() = default; GpuChannelHost::Listener::RouteInfo::RouteInfo() = default;
......
...@@ -38,6 +38,7 @@ class ChannelMojo; ...@@ -38,6 +38,7 @@ class ChannelMojo;
struct GpuDeferredMessage; struct GpuDeferredMessage;
namespace gpu { namespace gpu {
class ClientSharedImageInterface;
struct SyncToken; struct SyncToken;
class GpuChannelHost; class GpuChannelHost;
class GpuMemoryBufferManager; class GpuMemoryBufferManager;
...@@ -135,9 +136,8 @@ class GPU_EXPORT GpuChannelHost ...@@ -135,9 +136,8 @@ class GPU_EXPORT GpuChannelHost
// otherwise ignored. // otherwise ignored.
void CrashGpuProcessForTesting(); void CrashGpuProcessForTesting();
SharedImageInterface* shared_image_interface() { std::unique_ptr<ClientSharedImageInterface>
return &shared_image_interface_; CreateClientSharedImageInterface();
}
ImageDecodeAcceleratorProxy* image_decode_accelerator_proxy() { ImageDecodeAcceleratorProxy* image_decode_accelerator_proxy() {
return &image_decode_accelerator_proxy_; return &image_decode_accelerator_proxy_;
......
...@@ -70,12 +70,14 @@ Mailbox SharedImageInterfaceProxy::CreateSharedImage( ...@@ -70,12 +70,14 @@ Mailbox SharedImageInterfaceProxy::CreateSharedImage(
params.usage = usage; params.usage = usage;
{ {
base::AutoLock lock(lock_); base::AutoLock lock(lock_);
AddMailbox(params.mailbox, usage);
params.release_id = ++next_release_id_; params.release_id = ++next_release_id_;
// Note: we enqueue the IPC under the lock to guarantee monotonicity of the // Note: we enqueue the IPC under the lock to guarantee monotonicity of the
// release ids as seen by the service. // release ids as seen by the service.
last_flush_id_ = host_->EnqueueDeferredMessage( last_flush_id_ = host_->EnqueueDeferredMessage(
GpuChannelMsg_CreateSharedImage(route_id_, params)); GpuChannelMsg_CreateSharedImage(route_id_, params));
} }
return params.mailbox; return params.mailbox;
} }
...@@ -117,6 +119,8 @@ Mailbox SharedImageInterfaceProxy::CreateSharedImage( ...@@ -117,6 +119,8 @@ Mailbox SharedImageInterfaceProxy::CreateSharedImage(
params.release_id = ++next_release_id_; params.release_id = ++next_release_id_;
last_flush_id_ = host_->EnqueueDeferredMessage( last_flush_id_ = host_->EnqueueDeferredMessage(
GpuChannelMsg_CreateSharedImageWithData(route_id_, params)); GpuChannelMsg_CreateSharedImageWithData(route_id_, params));
AddMailbox(params.mailbox, usage);
return params.mailbox; return params.mailbox;
} }
...@@ -163,6 +167,9 @@ Mailbox SharedImageInterfaceProxy::CreateSharedImage( ...@@ -163,6 +167,9 @@ Mailbox SharedImageInterfaceProxy::CreateSharedImage(
gpu_memory_buffer_manager->SetDestructionSyncToken(gpu_memory_buffer, gpu_memory_buffer_manager->SetDestructionSyncToken(gpu_memory_buffer,
sync_token); sync_token);
} }
base::AutoLock lock(lock_);
AddMailbox(params.mailbox, usage);
return mailbox; return mailbox;
} }
...@@ -228,6 +235,10 @@ void SharedImageInterfaceProxy::DestroySharedImage(const SyncToken& sync_token, ...@@ -228,6 +235,10 @@ void SharedImageInterfaceProxy::DestroySharedImage(const SyncToken& sync_token,
} }
{ {
base::AutoLock lock(lock_); base::AutoLock lock(lock_);
DCHECK_NE(mailbox_to_usage_.count(mailbox), 0u);
mailbox_to_usage_.erase(mailbox);
last_flush_id_ = host_->EnqueueDeferredMessage( last_flush_id_ = host_->EnqueueDeferredMessage(
GpuChannelMsg_DestroySharedImage(route_id_, mailbox), GpuChannelMsg_DestroySharedImage(route_id_, mailbox),
std::move(dependencies)); std::move(dependencies));
...@@ -333,6 +344,10 @@ SharedImageInterfaceProxy::CreateSwapChain(viz::ResourceFormat format, ...@@ -333,6 +344,10 @@ SharedImageInterfaceProxy::CreateSwapChain(viz::ResourceFormat format,
params.usage = usage; params.usage = usage;
{ {
base::AutoLock lock(lock_); base::AutoLock lock(lock_);
AddMailbox(params.front_buffer_mailbox, usage);
AddMailbox(params.back_buffer_mailbox, usage);
params.release_id = ++next_release_id_; params.release_id = ++next_release_id_;
last_flush_id_ = host_->EnqueueDeferredMessage( last_flush_id_ = host_->EnqueueDeferredMessage(
GpuChannelMsg_CreateSwapChain(route_id_, params)); GpuChannelMsg_CreateSwapChain(route_id_, params));
...@@ -394,4 +409,23 @@ scoped_refptr<gfx::NativePixmap> SharedImageInterfaceProxy::GetNativePixmap( ...@@ -394,4 +409,23 @@ scoped_refptr<gfx::NativePixmap> SharedImageInterfaceProxy::GetNativePixmap(
return nullptr; 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 } // namespace gpu
...@@ -15,58 +15,59 @@ ...@@ -15,58 +15,59 @@
namespace gpu { namespace gpu {
class GpuChannelHost; class GpuChannelHost;
// Implementation of SharedImageInterface that sends commands over GPU channel // Proxy that sends commands over GPU channel IPCs for managing shared images.
// IPCs. class SharedImageInterfaceProxy {
class SharedImageInterfaceProxy : public SharedImageInterface {
public: public:
explicit SharedImageInterfaceProxy(GpuChannelHost* host, int32_t route_id); explicit SharedImageInterfaceProxy(GpuChannelHost* host, int32_t route_id);
~SharedImageInterfaceProxy() override; ~SharedImageInterfaceProxy();
Mailbox CreateSharedImage(viz::ResourceFormat format, Mailbox CreateSharedImage(viz::ResourceFormat format,
const gfx::Size& size, const gfx::Size& size,
const gfx::ColorSpace& color_space, const gfx::ColorSpace& color_space,
uint32_t usage) override; uint32_t usage);
Mailbox CreateSharedImage(viz::ResourceFormat format, Mailbox CreateSharedImage(viz::ResourceFormat format,
const gfx::Size& size, const gfx::Size& size,
const gfx::ColorSpace& color_space, const gfx::ColorSpace& color_space,
uint32_t usage, 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, Mailbox CreateSharedImage(gfx::GpuMemoryBuffer* gpu_memory_buffer,
GpuMemoryBufferManager* gpu_memory_buffer_manager, GpuMemoryBufferManager* gpu_memory_buffer_manager,
const gfx::ColorSpace& color_space, const gfx::ColorSpace& color_space,
uint32_t usage) override; uint32_t usage);
void UpdateSharedImage(const SyncToken& sync_token, void UpdateSharedImage(const SyncToken& sync_token, const Mailbox& mailbox);
const Mailbox& mailbox) override;
void UpdateSharedImage(const SyncToken& sync_token, void UpdateSharedImage(const SyncToken& sync_token,
std::unique_ptr<gfx::GpuFence> acquire_fence, std::unique_ptr<gfx::GpuFence> acquire_fence,
const Mailbox& mailbox) override; const Mailbox& mailbox);
void DestroySharedImage(const SyncToken& sync_token, void DestroySharedImage(const SyncToken& sync_token, const Mailbox& mailbox);
const Mailbox& mailbox) override; SyncToken GenVerifiedSyncToken();
SyncToken GenVerifiedSyncToken() override; SyncToken GenUnverifiedSyncToken();
SyncToken GenUnverifiedSyncToken() override; void Flush();
void Flush() override;
SwapChainMailboxes CreateSwapChain(viz::ResourceFormat format, SharedImageInterface::SwapChainMailboxes CreateSwapChain(
const gfx::Size& size, viz::ResourceFormat format,
const gfx::ColorSpace& color_space, const gfx::Size& size,
uint32_t usage) override; const gfx::ColorSpace& color_space,
void PresentSwapChain(const SyncToken& sync_token, uint32_t usage);
const Mailbox& mailbox) override; void PresentSwapChain(const SyncToken& sync_token, const Mailbox& mailbox);
#if defined(OS_FUCHSIA) #if defined(OS_FUCHSIA)
void RegisterSysmemBufferCollection(gfx::SysmemBufferCollectionId id, void RegisterSysmemBufferCollection(gfx::SysmemBufferCollectionId id,
zx::channel token) override; zx::channel token);
void ReleaseSysmemBufferCollection(gfx::SysmemBufferCollectionId id) override; void ReleaseSysmemBufferCollection(gfx::SysmemBufferCollectionId id);
#endif // defined(OS_FUCHSIA) #endif // defined(OS_FUCHSIA)
scoped_refptr<gfx::NativePixmap> GetNativePixmap( scoped_refptr<gfx::NativePixmap> GetNativePixmap(const gpu::Mailbox& mailbox);
const gpu::Mailbox& mailbox) override;
uint32_t UsageForMailbox(const Mailbox& mailbox);
private: private:
bool GetSHMForPixelData(base::span<const uint8_t> pixel_data, bool GetSHMForPixelData(base::span<const uint8_t> pixel_data,
size_t* shm_offset, size_t* shm_offset,
bool* done_with_shm) EXCLUSIVE_LOCKS_REQUIRED(lock_); bool* done_with_shm) EXCLUSIVE_LOCKS_REQUIRED(lock_);
void AddMailbox(const Mailbox& mailbox, uint32_t usage)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
GpuChannelHost* const host_; GpuChannelHost* const host_;
const int32_t route_id_; const int32_t route_id_;
base::Lock lock_; base::Lock lock_;
...@@ -77,6 +78,8 @@ class SharedImageInterfaceProxy : public SharedImageInterface { ...@@ -77,6 +78,8 @@ class SharedImageInterfaceProxy : public SharedImageInterface {
base::MappedReadOnlyRegion upload_buffer_ GUARDED_BY(lock_); base::MappedReadOnlyRegion upload_buffer_ GUARDED_BY(lock_);
// The offset into |upload_buffer_| at which data is no longer used. // The offset into |upload_buffer_| at which data is no longer used.
size_t upload_buffer_offset_ GUARDED_BY(lock_) = 0; size_t upload_buffer_offset_ GUARDED_BY(lock_) = 0;
base::flat_map<Mailbox, uint32_t> mailbox_to_usage_ GUARDED_BY(lock_);
}; };
} // namespace gpu } // namespace gpu
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "gpu/command_buffer/common/skia_utils.h" #include "gpu/command_buffer/common/skia_utils.h"
#include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/config/skia_limits.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/command_buffer_proxy_impl.h"
#include "gpu/ipc/client/gpu_channel_host.h" #include "gpu/ipc/client/gpu_channel_host.h"
#include "gpu/skia_bindings/gles2_implementation_with_grcontext_support.h" #include "gpu/skia_bindings/gles2_implementation_with_grcontext_support.h"
...@@ -325,6 +326,10 @@ gpu::ContextResult ContextProviderCommandBuffer::BindToCurrentThread() { ...@@ -325,6 +326,10 @@ gpu::ContextResult ContextProviderCommandBuffer::BindToCurrentThread() {
command_buffer_->SetLock(&context_lock_); command_buffer_->SetLock(&context_lock_);
cache_controller_->SetLock(&context_lock_); cache_controller_->SetLock(&context_lock_);
} }
shared_image_interface_ = channel_->CreateClientSharedImageInterface();
DCHECK(shared_image_interface_);
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
this, "ContextProviderCommandBuffer", std::move(task_runner)); this, "ContextProviderCommandBuffer", std::move(task_runner));
return bind_result_; return bind_result_;
...@@ -412,7 +417,7 @@ class GrContext* ContextProviderCommandBuffer::GrContext() { ...@@ -412,7 +417,7 @@ class GrContext* ContextProviderCommandBuffer::GrContext() {
gpu::SharedImageInterface* gpu::SharedImageInterface*
ContextProviderCommandBuffer::SharedImageInterface() { ContextProviderCommandBuffer::SharedImageInterface() {
return command_buffer_->channel()->shared_image_interface(); return shared_image_interface_.get();
} }
ContextCacheController* ContextProviderCommandBuffer::CacheController() { ContextCacheController* ContextProviderCommandBuffer::CacheController() {
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
namespace gpu { namespace gpu {
class CommandBufferHelper; class CommandBufferHelper;
class CommandBufferProxyImpl; class CommandBufferProxyImpl;
class ClientSharedImageInterface;
class GpuChannelHost; class GpuChannelHost;
struct GpuFeatureInfo; struct GpuFeatureInfo;
class GpuMemoryBufferManager; class GpuMemoryBufferManager;
...@@ -148,6 +149,11 @@ class ContextProviderCommandBuffer ...@@ -148,6 +149,11 @@ class ContextProviderCommandBuffer
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_; gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_;
scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_; 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_. base::Lock context_lock_; // Referenced by command_buffer_.
std::unique_ptr<gpu::CommandBufferProxyImpl> command_buffer_; std::unique_ptr<gpu::CommandBufferProxyImpl> command_buffer_;
std::unique_ptr<gpu::CommandBufferHelper> helper_; std::unique_ptr<gpu::CommandBufferHelper> helper_;
......
...@@ -111,7 +111,6 @@ static void ReleaseFrameResources( ...@@ -111,7 +111,6 @@ static void ReleaseFrameResources(
// TODO(khushalsagar): If multiple readers had access to this resource, losing // TODO(khushalsagar): If multiple readers had access to this resource, losing
// it once should make sure subsequent releases don't try to recycle this // it once should make sure subsequent releases don't try to recycle this
// resource. // resource.
// Also what about single buffered canvas?
if (lost_resource) if (lost_resource)
resource->NotifyResourceLost(); resource->NotifyResourceLost();
if (resource_provider && !lost_resource && resource->IsRecycleable()) if (resource_provider && !lost_resource && resource->IsRecycleable())
...@@ -286,6 +285,12 @@ void CanvasResourceSharedBitmap::Abandon() { ...@@ -286,6 +285,12 @@ void CanvasResourceSharedBitmap::Abandon() {
shared_mapping_ = {}; 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( const gpu::Mailbox& CanvasResourceSharedBitmap::GetOrCreateGpuMailbox(
MailboxSyncMode sync_mode) { MailboxSyncMode sync_mode) {
return shared_bitmap_id_; return shared_bitmap_id_;
...@@ -425,6 +430,8 @@ CanvasResourceSharedImage::~CanvasResourceSharedImage() { ...@@ -425,6 +430,8 @@ CanvasResourceSharedImage::~CanvasResourceSharedImage() {
void CanvasResourceSharedImage::TearDown() { void CanvasResourceSharedImage::TearDown() {
DCHECK(!is_cross_thread()); 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()) { if (ContextProviderWrapper()) {
auto* raster_interface = RasterInterface(); auto* raster_interface = RasterInterface();
auto* shared_image_interface = auto* shared_image_interface =
...@@ -455,11 +462,8 @@ void CanvasResourceSharedImage::TearDown() { ...@@ -455,11 +462,8 @@ void CanvasResourceSharedImage::TearDown() {
} }
void CanvasResourceSharedImage::Abandon() { void CanvasResourceSharedImage::Abandon() {
if (auto context_provider = SharedGpuContext::ContextProviderWrapper()) { // Called when the owning thread has been torn down which will destroy the
auto* sii = context_provider->ContextProvider()->SharedImageInterface(); // context on which the shared image was created so no cleanup is necessary.
if (sii)
sii->DestroySharedImage(gpu::SyncToken(), mailbox());
}
} }
void CanvasResourceSharedImage::WillDraw() { void CanvasResourceSharedImage::WillDraw() {
...@@ -807,17 +811,16 @@ scoped_refptr<StaticBitmapImage> CanvasResourceSwapChain::Bitmap() { ...@@ -807,17 +811,16 @@ scoped_refptr<StaticBitmapImage> CanvasResourceSwapChain::Bitmap() {
} }
void CanvasResourceSwapChain::Abandon() { void CanvasResourceSwapChain::Abandon() {
if (auto context_provider = SharedGpuContext::ContextProviderWrapper()) { // Called when the owning thread has been torn down which will destroy the
auto* sii = context_provider->ContextProvider()->SharedImageInterface(); // context on which the shared image was created so no cleanup is necessary.
DCHECK(sii);
sii->DestroySharedImage(gpu::SyncToken(), front_buffer_mailbox_);
sii->DestroySharedImage(gpu::SyncToken(), back_buffer_mailbox_);
}
} }
void CanvasResourceSwapChain::TearDown() { 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_) if (!context_provider_wrapper_)
return; return;
auto* raster_interface = auto* raster_interface =
context_provider_wrapper_->ContextProvider()->RasterInterface(); context_provider_wrapper_->ContextProvider()->RasterInterface();
DCHECK(raster_interface); DCHECK(raster_interface);
......
...@@ -140,12 +140,7 @@ class PLATFORM_EXPORT CanvasResource ...@@ -140,12 +140,7 @@ class PLATFORM_EXPORT CanvasResource
// token for the resource to be safely recycled and its the GL state may be // 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 // 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. // should not be recycled for writing again but can be safely read from.
virtual void NotifyResourceLost() { virtual void NotifyResourceLost() = 0;
// 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();
}
void SetFilterQuality(SkFilterQuality filter) { filter_quality_ = filter; } void SetFilterQuality(SkFilterQuality filter) { filter_quality_ = filter; }
// The filter quality to use when the resource is drawn by the compositor. // The filter quality to use when the resource is drawn by the compositor.
...@@ -240,6 +235,7 @@ class PLATFORM_EXPORT CanvasResourceSharedBitmap final : public CanvasResource { ...@@ -240,6 +235,7 @@ class PLATFORM_EXPORT CanvasResourceSharedBitmap final : public CanvasResource {
bool OriginClean() const final { return is_origin_clean_; } bool OriginClean() const final { return is_origin_clean_; }
void SetOriginClean(bool flag) final { is_origin_clean_ = flag; } void SetOriginClean(bool flag) final { is_origin_clean_ = flag; }
const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) override; const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) override;
void NotifyResourceLost() override;
private: private:
void TearDown() override; void TearDown() override;
...@@ -420,6 +416,10 @@ class PLATFORM_EXPORT ExternalCanvasResource final : public CanvasResource { ...@@ -420,6 +416,10 @@ class PLATFORM_EXPORT ExternalCanvasResource final : public CanvasResource {
void Abandon() final; void Abandon() final;
IntSize Size() const final { return size_; } IntSize Size() const final { return size_; }
void TakeSkImage(sk_sp<SkImage> image) final; 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; scoped_refptr<StaticBitmapImage> Bitmap() override;
const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) override; const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) override;
...@@ -473,6 +473,10 @@ class PLATFORM_EXPORT CanvasResourceSwapChain final : public CanvasResource { ...@@ -473,6 +473,10 @@ class PLATFORM_EXPORT CanvasResourceSwapChain final : public CanvasResource {
void Abandon() final; void Abandon() final;
IntSize Size() const final { return size_; } IntSize Size() const final { return size_; }
void TakeSkImage(sk_sp<SkImage> image) final; 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; 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