File: display_resource_provider_software.cc

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 (187 lines) | stat: -rw-r--r-- 6,853 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
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/viz/service/display/display_resource_provider_software.h"

#include <memory>
#include <vector>

#include "gpu/command_buffer/service/scheduler.h"
#include "gpu/command_buffer/service/shared_image/shared_image_manager.h"
#include "third_party/skia/include/core/SkImage.h"

namespace viz {

DisplayResourceProviderSoftware::DisplayResourceProviderSoftware(
    gpu::SharedImageManager* shared_image_manager,
    gpu::Scheduler* scheduler)
    : DisplayResourceProvider(DisplayResourceProvider::kSoftware),
      shared_image_manager_(shared_image_manager),
      gpu_scheduler_(scheduler) {
  memory_tracker_ = std::make_unique<gpu::MemoryTypeTracker>(nullptr);
}

DisplayResourceProviderSoftware::~DisplayResourceProviderSoftware() {
  Destroy();
}

std::unique_ptr<gpu::MemoryImageRepresentation>
DisplayResourceProviderSoftware::GetSharedImageRepresentation(
    const gpu::Mailbox& mailbox,
    const gpu::SyncToken& sync_token) {
  if (!blocking_sequence_runner_) {
    // There are cases where a nullptr `gpu_scheduler_` is used. In such cases,
    // this method shouldn't be called.
    CHECK(gpu_scheduler_);
    blocking_sequence_runner_ =
        std::make_unique<gpu::BlockingSequenceRunner>(gpu_scheduler_);
  }
  blocking_sequence_runner_->AddTask(base::OnceClosure(base::DoNothing()),
                                     {sync_token}, gpu::SyncToken());
  blocking_sequence_runner_->RunAllTasks();
  return shared_image_manager_->ProduceMemory(mailbox, memory_tracker_.get());
}

const DisplayResourceProvider::ChildResource*
DisplayResourceProviderSoftware::LockForRead(ResourceId id) {
  ChildResource* resource = GetResource(id);
  DCHECK(!resource->is_gpu_resource_type());

  // Determine whether this resource is using a software SharedImage or a legacy
  // shared bitmap.
  DCHECK(shared_image_manager_);
  auto it = resource_shared_images_.find(id);
  if (it == resource_shared_images_.end()) {
    const gpu::Mailbox& mailbox = resource->transferable.mailbox();
    auto access = std::make_unique<SharedImageAccess>();
    access->representation = GetSharedImageRepresentation(
        mailbox, resource->transferable.sync_token());
    if (!access->representation) {
      return nullptr;
    }

    access->read_access = access->representation->BeginScopedReadAccess();
    resource_shared_images_.emplace(id, std::move(access));
    resource->shared_image_representation_created_and_set = true;
  }

  resource->lock_for_read_count++;
  return resource;
}

void DisplayResourceProviderSoftware::UnlockForRead(ResourceId id,
                                                    const SkImage* sk_image) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  ChildResource* resource = GetResource(id);
  DCHECK(!resource->is_gpu_resource_type());
  if (sk_image) {
    DCHECK_GE(resource->lock_for_read_count, 0);
    resource->lock_for_read_count--;
  }
  TryReleaseResource(id, resource);
}

std::vector<ReturnedResource>
DisplayResourceProviderSoftware::DeleteAndReturnUnusedResourcesToChildImpl(
    Child& child_info,
    DeleteStyle style,
    const std::vector<ResourceId>& unused) {
  std::vector<ReturnedResource> to_return;
  // Reserve enough space to avoid re-allocating, so we can keep item pointers
  // for later using.
  to_return.reserve(unused.size());

  for (ResourceId local_id : unused) {
    auto it = resources_.find(local_id);
    CHECK(it != resources_.end());
    ChildResource& resource = it->second;
    DCHECK(!resource.is_gpu_resource_type());

    auto sk_image_it = resource_sk_images_.find(local_id);
    if (sk_image_it != resource_sk_images_.end()) {
      resource_sk_images_.erase(sk_image_it);
    }

    auto si_image_it = resource_shared_images_.find(local_id);
    if (si_image_it != resource_shared_images_.end()) {
      resource_shared_images_.erase(si_image_it);
    }

    ResourceId child_id = resource.transferable.id;
    DCHECK(child_info.child_to_parent_map.count(child_id));

    auto can_delete = CanDeleteNow(child_info, resource, style);
    if (can_delete == CanDeleteNowResult::kNo) {
      // Defer this resource deletion.
      resource.marked_for_deletion = true;
      continue;
    }

    const bool is_lost = can_delete == CanDeleteNowResult::kYesButLoseResource;

    to_return.emplace_back(child_id, resource.sync_token(),
                           std::move(resource.release_fence),
                           resource.imported_count, is_lost);

    child_info.child_to_parent_map.erase(child_id);
    resource.imported_count = 0;
    resources_.erase(it);
  }

  return to_return;
}

DisplayResourceProviderSoftware::ScopedReadLockSkImage::ScopedReadLockSkImage(
    DisplayResourceProviderSoftware* resource_provider,
    ResourceId resource_id)
    : resource_provider_(resource_provider), resource_id_(resource_id) {
  const ChildResource* resource = resource_provider->LockForRead(resource_id);
  if (!resource) {
    return;
  }
  DCHECK(!resource->is_gpu_resource_type());

  // Use cached SkImage if possible.
  auto it = resource_provider_->resource_sk_images_.find(resource_id);
  if (it != resource_provider_->resource_sk_images_.end()) {
    sk_image_ = it->second;
    return;
  }

  auto si_image_it =
      resource_provider->resource_shared_images_.find(resource_id);

  if (si_image_it != resource_provider->resource_shared_images_.end()) {
    sk_image_ = SkImages::RasterFromPixmap(
        si_image_it->second->read_access->pixmap(), nullptr, nullptr);
    resource_provider_->resource_sk_images_[resource_id] = sk_image_;
  } else {
    // If a CompositorFrameSink is destroyed, it destroys all reported
    // resource_shared_images_. In this case, a CompositorFrame can be drawn
    // with Mailboxes that are not known in the viz service. As well, a
    // misbehaved client can use software shared_image that it did not report to
    // the service. Then this read lock will not be valid. Software-compositing
    // users of this read lock must check for valid() to deal with this
    // scenario.
    sk_image_ = nullptr;
    return;
  }
}

DisplayResourceProviderSoftware::ScopedReadLockSkImage::
    ~ScopedReadLockSkImage() {
  resource_provider_->UnlockForRead(resource_id_, sk_image_.get());
}

DisplayResourceProviderSoftware::SharedImageAccess::SharedImageAccess() =
    default;
DisplayResourceProviderSoftware::SharedImageAccess::~SharedImageAccess() =
    default;
DisplayResourceProviderSoftware::SharedImageAccess::SharedImageAccess(
    SharedImageAccess&& other) = default;
DisplayResourceProviderSoftware::SharedImageAccess&
DisplayResourceProviderSoftware::SharedImageAccess::operator=(
    SharedImageAccess&& other) = default;

}  // namespace viz