File: display_resource_provider.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (390 lines) | stat: -rw-r--r-- 15,552 bytes parent folder | download | duplicates (5)
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_