1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
|
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_DISPLAY_RESOURCE_PROVIDER_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_DISPLAY_RESOURCE_PROVIDER_H_
#include <stddef.h>
#include <map>
#include <memory>
#include <unordered_map>
#include <utility>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "base/memory/stack_allocated.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/trace_event/memory_dump_provider.h"
#include "build/build_config.h"
#include "components/viz/common/resources/resource_id.h"
#include "components/viz/common/resources/return_callback.h"
#include "components/viz/common/resources/transferable_resource.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/service/display/external_use_client.h"
#include "components/viz/service/display/resource_fence.h"
#include "components/viz/service/viz_service_export.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/size.h"
namespace gfx {
class ColorSpace;
} // namespace gfx
namespace viz {
class ScopedAllowGpuAccessForDisplayResourceProvider;
// This class provides abstractions for receiving and using resources from other
// modules/threads/processes. It abstracts away GL textures vs GpuMemoryBuffers
// vs software bitmaps behind a single ResourceId so that code in common can
// hold onto ResourceIds, as long as the code using them knows the correct type.
// It accepts as input TransferableResources which it holds internally, tracks
// state on, and exposes as a ResourceId.
//
// The resource's underlying type is accessed through locks that help to
// scope and safeguard correct usage with DCHECKs.
//
// This class is not thread-safe and can only be called from the thread it was
// created on.
class VIZ_SERVICE_EXPORT DisplayResourceProvider
: public base::trace_event::MemoryDumpProvider {
public:
enum Mode {
kGpu,
kSoftware,
};
~DisplayResourceProvider() override;
DisplayResourceProvider(const DisplayResourceProvider&) = delete;
DisplayResourceProvider& operator=(const DisplayResourceProvider&) = delete;
bool IsSoftware() const { return mode_ == kSoftware; }
size_t num_resources() const { return resources_.size(); }
// base::trace_event::MemoryDumpProvider implementation.
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) override;
base::WeakPtr<DisplayResourceProvider> GetWeakPtr();
#if BUILDFLAG(IS_ANDROID)
// Indicates if this resource is backed by an Android SurfaceView, and thus
// can be promoted to an overlay via legacy (SurfaceView/Dialog) overlay
// system.
bool IsBackedBySurfaceView(ResourceId id) const;
#endif
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN)
// Indicates if this resource wants to receive promotion hints.
bool DoesResourceWantPromotionHint(ResourceId id) const;
#endif
// Returns the size in pixels of the underlying gpu mailbox/software bitmap.
const gfx::Size GetResourceBackedSize(ResourceId id) const;
bool IsResourceSoftwareBacked(ResourceId id) const;
// Return the SharedImageFormat of the underlying buffer that can be used for
// scanout.
SharedImageFormat GetSharedImageFormat(ResourceId id) const;
// Returns the color space of the resource.
const gfx::ColorSpace& GetColorSpace(ResourceId id) const;
// Returns true if the resource needs a detiling pass before scanout.
bool GetNeedsDetiling(ResourceId id) const;
const gfx::HDRMetadata& GetHDRMetadata(ResourceId id) const;
GrSurfaceOrigin GetOrigin(ResourceId id) const;
SkAlphaType GetAlphaType(ResourceId id) const;
// Indicates if this resource may be used for a hardware overlay plane.
bool IsOverlayCandidate(ResourceId id) const;
// Indicates if this resource uses low latency rendering.
bool IsLowLatencyRendering(ResourceId id) const;
SurfaceId GetSurfaceId(ResourceId id) const;
int GetChildId(ResourceId id) const;
// Checks whether a resource is in use.
bool InUse(ResourceId id) const;
// Try removing the resources that are pending the |resource_fence|.
void OnResourceFencePassed(ResourceFence* resource_fence,
base::flat_set<ResourceId> resources);
// The following lock classes are part of the DisplayResourceProvider API and
// are needed to read the resource contents. The user must ensure that they
// only use GL locks on GL resources, etc, and this is enforced by assertions.
protected:
// Forward declared for ScopedReadLockSharedImage below.
struct ChildResource;
public:
// Lock the resource to make sure the shared image is alive when accessing
// SharedImage Mailbox.
class VIZ_SERVICE_EXPORT ScopedReadLockSharedImage {
public:
ScopedReadLockSharedImage(DisplayResourceProvider* resource_provider,
ResourceId resource_id);
~ScopedReadLockSharedImage();
ScopedReadLockSharedImage(ScopedReadLockSharedImage&& other);
ScopedReadLockSharedImage& operator=(ScopedReadLockSharedImage&& other);
const gpu::Mailbox& mailbox() const {
DCHECK(resource_);
return resource_->transferable.mailbox();
}
const gpu::SyncToken& sync_token() const {
DCHECK(resource_);
return resource_->sync_token();
}
// Sets the given |release_fence| onto this resource.
// This is propagated to ReturnedResource when the resource is freed.
void SetReleaseFence(gfx::GpuFenceHandle release_fence);
// Returns true iff this resource has a read lock fence set.
bool HasReadLockFence() const;
protected:
ChildResource* resource() { return resource_; }
private:
void Reset();
// RAW_PTR_EXCLUSION: Performance reasons (based on analysis of MotionMark).
RAW_PTR_EXCLUSION DisplayResourceProvider* resource_provider_ = nullptr;
ResourceId resource_id_ = kInvalidResourceId;
// RAW_PTR_EXCLUSION: Performance reasons (based on analysis of MotionMark).
RAW_PTR_EXCLUSION ChildResource* resource_ = nullptr;
};
// All resources that are returned to children while an instance of this
// class exists will be stored and returned when the instance is destroyed.
class VIZ_SERVICE_EXPORT ScopedBatchReturnResources {
STACK_ALLOCATED();
public:
explicit ScopedBatchReturnResources(
DisplayResourceProvider* resource_provider,
bool allow_access_to_gpu_thread = false);
~ScopedBatchReturnResources();
private:
DisplayResourceProvider* const resource_provider_ = nullptr;
const bool was_access_to_gpu_thread_allowed_;
};
// Creates accounting for a child. Returns a child ID. surface_id is used to
// associate resources to the surface they belong to. This is used for
// overlays on webview where overlays are updated outside of normal draw (i.e
// DrawAndSwap isn't called).
int CreateChild(ReturnCallback return_callback, const SurfaceId& surface_id);
// Destroys accounting for the child, deleting all accounted resources.
void DestroyChild(int child);
// Gets the child->parent resource ID map.
const std::unordered_map<ResourceId, ResourceId, ResourceIdHasher>&
GetChildToParentMap(int child) const;
// Receives resources from a child, moving them from mailboxes. ResourceIds
// passed are in the child namespace, and will be translated to the parent
// namespace, added to the child->parent map.
// This adds the resources to the working set in the ResourceProvider without
// declaring which resources are in use. Use DeclareUsedResourcesFromChild
// after calling this method to do that. All calls to ReceiveFromChild should
// be followed by a DeclareUsedResourcesFromChild.
// NOTE: if the sync_token is set on any TransferableResource, this will
// wait on it.
void ReceiveFromChild(
int child,
const std::vector<TransferableResource>& transferable_resources);
// Once a set of resources have been received, they may or may not be used.
// This declares what set of resources are currently in use from the child,
// releasing any other resources back to the child.
void DeclareUsedResourcesFromChild(int child,
const ResourceIdSet& resources_from_child);
// Returns the mailbox corresponding to a resource id.
gpu::Mailbox GetMailbox(ResourceId resource_id) const;
// Sets if the GPU thread is available (it always is for Chrome, but for
// WebView it happens only when Android calls us on RenderThread.
void SetAllowAccessToGPUThread(bool allow);
protected:
friend class ScopedAllowGpuAccessForDisplayResourceProvider;
enum class CanDeleteNowResult { kYes, kYesButLoseResource, kNo };
enum DeleteStyle {
NORMAL,
FOR_SHUTDOWN,
};
struct Child {
Child();
Child(Child&& other);
Child& operator=(Child&& other);
~Child();
int id;
std::unordered_map<ResourceId, ResourceId, ResourceIdHasher>
child_to_parent_map;
ReturnCallback return_callback;
SurfaceId surface_id;
bool marked_for_deletion = false;
};
// The data structure used to track state of Gpu and Software-based
// resources and the service, for resources transferred
// between the two. This is an implementation detail of the resource tracking
// for client and service libraries and should not be used directly from
// external client code.
struct ChildResource {
ChildResource(int child_id, const TransferableResource& transferable);
ChildResource(ChildResource&& other);
~ChildResource();
bool is_gpu_resource_type() const { return !transferable.is_software; }
const gpu::SyncToken& sync_token() const { return sync_token_; }
bool InUse() const {
return lock_for_read_count > 0 || locked_for_external_use ||
lock_for_overlay_count > 0;
}
void UpdateSyncToken(const gpu::SyncToken& sync_token);
// This is the id of the client the resource comes from.
const int child_id;
// Data received from the client that describes the resource fully.
const TransferableResource transferable;
// The number of times the resource has been received from a client. It must
// have this many number of references returned back to the client in order
// for it to know it is no longer in use in the service. This is used to
// avoid races where a resource is in flight to the service while also being
// returned to the client. It starts with an initial count of 1, for the
// first time the resource is received.
int imported_count = 1;
// The number of active users of a resource in the display compositor. While
// a resource is in use, it will not be returned back to the client even if
// the ResourceId is deleted.
int lock_for_read_count = 0;
// When true, the resource is currently being used externally. This is a
// parallel counter to |lock_for_read_count| which can only go to 1.
bool locked_for_external_use = false;
// The number of active users using this resource as overlay content.
int lock_for_overlay_count = 0;
// When the resource should be deleted until it is actually reaped.
bool marked_for_deletion = false;
// Indicate whether the shared_image has been locked at lease once.
bool shared_image_representation_created_and_set = false;
// A fence used for returning resources after the display compositor has
// completed accessing the resources it received from a client. This can
// either be a read lock or a release fence. If the |transferable| has
// synchronization type set as kGpuCommandsCompleted, the resource can be
// returned after ResourceFence::HasPassed is true. If the |transferable|
// has the synchronization type set as kReleaseFence, the resource can be
// returned after the fence has a release fence set.
scoped_refptr<ResourceFence> resource_fence;
// SkiaRenderer specific details about this resource. Added to ChildResource
// to avoid map lookups further down the pipeline.
std::unique_ptr<ExternalUseClient::ImageContext> image_context;
// A release fence to propagate to ReturnedResource so clients may
// use it.
gfx::GpuFenceHandle release_fence;
private:
// A SyncToken associated with a texture-backed or GpuMemoryBuffer-backed
// resource. It is given from a child to the service, and waited on in order
// to use the resource.
gpu::SyncToken sync_token_;
};
using ChildMap = std::unordered_map<int, Child>;
using ResourceMap =
std::unordered_map<ResourceId, ChildResource, ResourceIdHasher>;
explicit DisplayResourceProvider(Mode mode);
const ChildResource* GetResource(ResourceId id) const;
ChildResource* GetResource(ResourceId id);
// TODO(ericrk): TryGetResource is part of a temporary workaround for cases
// where resources which should be available are missing. This version may
// return nullptr if a resource is not found. https://crbug.com/811858
const ChildResource* TryGetResource(ResourceId id) const;
ChildResource* TryGetResource(ResourceId id);
void TryReleaseResource(ResourceId id, ChildResource* resource);
bool ResourceFenceHasPassed(const ChildResource* resource) const;
void DeleteAndReturnUnusedResourcesToChild(
ChildMap::iterator child_it,
DeleteStyle style,
const std::vector<ResourceId>& unused);
virtual std::vector<ReturnedResource>
DeleteAndReturnUnusedResourcesToChildImpl(
Child& child_info,
DeleteStyle style,
const std::vector<ResourceId>& unused) = 0;
CanDeleteNowResult CanDeleteNow(const Child& child_info,
const ChildResource& resource,
DeleteStyle style) const;
// Destroys DisplayResourceProvider, must be called before destructor because
// it might call virtual functions from inside.
void Destroy();
void DestroyChildInternal(ChildMap::iterator it, DeleteStyle style);
void SetBatchReturnResources(bool aggregate);
void TryFlushBatchedResources();
SEQUENCE_CHECKER(sequence_checker_);
const Mode mode_;
ResourceMap resources_;
ChildMap children_;
base::flat_map<int, std::vector<ResourceId>> batched_returning_resources_;
// Keep track of whether deleted resources should be batched up or returned
// immediately.
int batch_return_resources_lock_count_ = 0;
// The ResourceIds in DisplayResourceProvider start from 2 to avoid
// conflicts with id from ClientResourceProvider.
ResourceIdGenerator resource_id_generator_{2u};
// Used as child id when creating a child.
int next_child_ = 1;
// A process-unique ID used for disambiguating memory dumps from different
// resource providers.
int tracing_id_;
// Indicates that gpu thread is available and calls like
// ReleaseImageContexts() are expected to finish in finite time. It's always
// true for Chrome, but on WebView we need to have access to RenderThread.
bool can_access_gpu_thread_ = true;
// OnResourceFencePassed() may be called by resource_fence that lives past
// destruction of this class.
base::WeakPtrFactory<DisplayResourceProvider> weak_factory_{this};
};
} // namespace viz
#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_DISPLAY_RESOURCE_PROVIDER_H_
|