[go: nahoru, domu]

blob: 204317260751e27b7b8609cc15e35c39dcc50121 [file] [log] [blame]
Bo Liue0e51f22023-02-02 19:33:001// Copyright 2023 The Chromium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "cc/slim/frame_sink_impl.h"
6
7#include <string>
8#include <utility>
9#include <vector>
10
11#include "base/check.h"
12#include "base/containers/flat_set.h"
13#include "base/functional/bind.h"
14#include "base/threading/platform_thread.h"
15#include "base/trace_event/trace_event.h"
16#include "build/build_config.h"
Bo Liuf5bd17342023-03-10 17:55:4517#include "cc/slim/constants.h"
Bo Liu11af9412023-04-05 19:49:3918#include "cc/slim/delayed_scheduler.h"
Bo Liue0e51f22023-02-02 19:33:0019#include "cc/slim/frame_sink_impl_client.h"
Jonathan Rossd3117112023-02-17 16:42:0920#include "components/viz/common/features.h"
Bo Liu677cece2023-03-07 17:44:1321#include "components/viz/common/quads/compositor_frame.h"
Bo Liue0e51f22023-02-02 19:33:0022#include "components/viz/common/resources/platform_color.h"
23#include "components/viz/common/resources/resource_format_utils.h"
Bo Liu873d13e32023-02-08 15:58:4224#include "components/viz/common/resources/resource_id.h"
Colin Blundell6828da72023-02-13 18:07:3325#include "components/viz/common/resources/shared_image_format.h"
Colin Blundell81fb20ca2023-05-30 09:37:5426#include "components/viz/common/resources/shared_image_format_utils.h"
Bo Liu677cece2023-03-07 17:44:1327#include "components/viz/common/resources/transferable_resource.h"
Bo Liue0e51f22023-02-02 19:33:0028#include "gpu/command_buffer/client/shared_image_interface.h"
29#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
30#include "gpu/command_buffer/common/shared_image_usage.h"
31#include "third_party/skia/include/core/SkAlphaType.h"
32#include "third_party/skia/include/gpu/GrTypes.h"
33#include "ui/gfx/buffer_types.h"
34#include "ui/gfx/color_space.h"
35
36namespace cc::slim {
37
38FrameSinkImpl::UploadedUIResource::UploadedUIResource() = default;
39FrameSinkImpl::UploadedUIResource::~UploadedUIResource() = default;
40FrameSinkImpl::UploadedUIResource::UploadedUIResource(
41 const UploadedUIResource&) = default;
42FrameSinkImpl::UploadedUIResource& FrameSinkImpl::UploadedUIResource::operator=(
43 const UploadedUIResource&) = default;
44
45FrameSinkImpl::FrameSinkImpl(
46 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
47 mojo::PendingAssociatedRemote<viz::mojom::CompositorFrameSink>
48 compositor_frame_sink_associated_remote,
49 mojo::PendingReceiver<viz::mojom::CompositorFrameSinkClient>
50 client_receiver,
Michael Thiessenc8842d02023-02-16 17:06:0251 scoped_refptr<viz::ContextProvider> context_provider,
Bo Liu3380083a2023-03-22 16:11:0452 base::PlatformThreadId io_thread_id,
53 std::unique_ptr<Scheduler> scheduler)
Bo Liue0e51f22023-02-02 19:33:0054 : task_runner_(std::move(task_runner)),
Bo Liu3380083a2023-03-22 16:11:0455 scheduler_(std::move(scheduler)),
Bo Liue0e51f22023-02-02 19:33:0056 pending_compositor_frame_sink_associated_remote_(
57 std::move(compositor_frame_sink_associated_remote)),
58 pending_client_receiver_(std::move(client_receiver)),
Michael Thiessenc8842d02023-02-16 17:06:0259 context_provider_(std::move(context_provider)),
Bo Liu3380083a2023-03-22 16:11:0460 io_thread_id_(io_thread_id) {
61 scheduler_->Initialize(this);
62}
Bo Liue0e51f22023-02-02 19:33:0063
64FrameSinkImpl::~FrameSinkImpl() {
Bo Liu9d07e212023-02-27 17:13:3765 // Iterate a copy of `uploaded_resources_` since it might be modified
66 // when `UIResourceReleased()` is called.
67 for (const auto& uploaded_resource_pair :
68 UploadedResourceMap(uploaded_resources_)) {
Bo Liu84fe45d2023-02-21 16:33:3769 resource_provider_.RemoveImportedResource(
70 uploaded_resource_pair.second.viz_resource_id);
71 }
Bo Liue0e51f22023-02-02 19:33:0072 resource_provider_.ShutdownAndReleaseAllResources();
73}
74
75void FrameSinkImpl::SetLocalSurfaceId(
76 const viz::LocalSurfaceId& local_surface_id) {
77 if (local_surface_id_ == local_surface_id) {
78 return;
79 }
80 local_surface_id_ = local_surface_id;
81 hit_test_region_list_.reset();
82}
83
84bool FrameSinkImpl::BindToClient(FrameSinkImplClient* client) {
85 DCHECK(client);
86 if (context_provider_) {
87 context_provider_->AddObserver(this);
88 auto result = context_provider_->BindToCurrentSequence();
89 if (result != gpu::ContextResult::kSuccess) {
90 context_provider_->RemoveObserver(this);
91 context_provider_ = nullptr;
92 return false;
93 }
94 }
95
96 client_ = client;
97
98 frame_sink_remote_.Bind(
99 std::move(pending_compositor_frame_sink_associated_remote_));
100 frame_sink_remote_.set_disconnect_handler(
101 base::BindOnce(&FrameSinkImpl::OnContextLost, base::Unretained(this)));
102 client_receiver_.Bind(std::move(pending_client_receiver_), task_runner_);
103
Bo Liubfe80a072023-02-17 20:09:15104 frame_sink_ = frame_sink_remote_.get();
105 frame_sink_->InitializeCompositorFrameSinkType(
Bo Liue0e51f22023-02-02 19:33:00106 viz::mojom::CompositorFrameSinkType::kLayerTree);
107
108#if BUILDFLAG(IS_ANDROID)
109 std::vector<int32_t> thread_ids;
110 thread_ids.push_back(base::PlatformThread::CurrentId());
Michael Thiessenc8842d02023-02-16 17:06:02111 if (io_thread_id_ != base::kInvalidThreadId) {
112 thread_ids.push_back(io_thread_id_);
113 }
Bo Liubfe80a072023-02-17 20:09:15114 frame_sink_->SetThreadIds(thread_ids);
Bo Liue0e51f22023-02-02 19:33:00115#endif
116 return true;
117}
118
119void FrameSinkImpl::OnContextLost() {
120 client_->DidLoseLayerTreeFrameSink();
121}
122
123void FrameSinkImpl::SetNeedsBeginFrame(bool needs_begin_frame) {
124 if (needs_begin_frame_ == needs_begin_frame) {
125 return;
126 }
127 needs_begin_frame_ = needs_begin_frame;
Bo Liu11af9412023-04-05 19:49:39128 scheduler_->SetNeedsBeginFrame(needs_begin_frame);
Bo Liubfe80a072023-02-17 20:09:15129 frame_sink_->SetNeedsBeginFrame(needs_begin_frame);
Bo Liue0e51f22023-02-02 19:33:00130}
131
Bo Liu11af9412023-04-05 19:49:39132void FrameSinkImpl::MaybeCompositeNow() {
133 scheduler_->MaybeCompositeNow();
134}
135
Bo Liue0e51f22023-02-02 19:33:00136void FrameSinkImpl::UploadUIResource(cc::UIResourceId resource_id,
137 cc::UIResourceBitmap resource_bitmap) {
Bo Liue0e51f22023-02-02 19:33:00138 gfx::Size size = resource_bitmap.GetSize();
Bo Liue54865a2023-05-01 17:52:48139 TRACE_EVENT1("cc", "slim::FrameSinkImpl::UploadUIResource", "size",
140 size.ToString());
141 const gpu::Capabilities& caps = context_provider_->ContextCapabilities();
Bo Liue0e51f22023-02-02 19:33:00142 if (size.width() > caps.max_texture_size ||
143 size.height() > caps.max_texture_size) {
144 LOG(ERROR) << "Size exceeds max texture size";
145 return;
146 }
Colin Blundell836bf252023-02-15 08:33:58147 viz::SharedImageFormat format = viz::SinglePlaneFormat::kRGBA_8888;
Bo Liue0e51f22023-02-02 19:33:00148 switch (resource_bitmap.GetFormat()) {
149 case cc::UIResourceBitmap::RGBA8:
Colin Blundell836bf252023-02-15 08:33:58150 format = viz::PlatformColor::BestSupportedTextureFormat(caps);
Bo Liue0e51f22023-02-02 19:33:00151 break;
152 case cc::UIResourceBitmap::ALPHA_8:
Colin Blundell836bf252023-02-15 08:33:58153 format = viz::SinglePlaneFormat::kALPHA_8;
Bo Liue0e51f22023-02-02 19:33:00154 break;
155 case cc::UIResourceBitmap::ETC1:
Colin Blundell836bf252023-02-15 08:33:58156 format = viz::SinglePlaneFormat::kETC1;
Bo Liue0e51f22023-02-02 19:33:00157 break;
158 }
159
160 UploadedUIResource uploaded_resource;
161 auto* sii = context_provider_->SharedImageInterface();
162 constexpr gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB();
163 uint32_t shared_image_usage = gpu::SHARED_IMAGE_USAGE_DISPLAY_READ;
164 uploaded_resource.mailbox = sii->CreateSharedImage(
Colin Blundell836bf252023-02-15 08:33:58165 format, resource_bitmap.GetSize(), color_space, kTopLeft_GrSurfaceOrigin,
Rafael Cintronde3d9b82023-04-19 20:19:28166 kPremul_SkAlphaType, shared_image_usage, "SlimCompositorUIResource",
Bo Liue0e51f22023-02-02 19:33:00167 base::span<const uint8_t>(resource_bitmap.GetPixels(),
168 resource_bitmap.SizeInBytes()));
169 gpu::SyncToken sync_token = sii->GenUnverifiedSyncToken();
170
171 GLenum texture_target = gpu::GetBufferTextureTarget(
Colin Blundell81fb20ca2023-05-30 09:37:54172 gfx::BufferUsage::SCANOUT,
173 viz::SinglePlaneSharedImageFormatToBufferFormat(format), caps);
Bo Liue0e51f22023-02-02 19:33:00174 uploaded_resource.viz_resource_id = resource_provider_.ImportResource(
175 viz::TransferableResource::MakeGpu(
kylechar35a372d2023-04-25 16:05:17176 uploaded_resource.mailbox, texture_target, sync_token,
Bo Liue0e51f22023-02-02 19:33:00177 resource_bitmap.GetSize(), format, /*is_overlay_candidate=*/false),
178 base::BindOnce(&FrameSinkImpl::UIResourceReleased, base::Unretained(this),
179 resource_id));
180 uploaded_resource.size = resource_bitmap.GetSize();
181 uploaded_resource.is_opaque = resource_bitmap.GetOpaque();
182
Bo Liu9d07e212023-02-27 17:13:37183 DCHECK(!uploaded_resources_.contains(resource_id));
Bo Liue0e51f22023-02-02 19:33:00184 uploaded_resources_.emplace(resource_id, uploaded_resource);
185}
186
187void FrameSinkImpl::UIResourceReleased(cc::UIResourceId ui_resource_id,
188 const gpu::SyncToken& sync_token,
189 bool is_lost) {
190 auto itr = uploaded_resources_.find(ui_resource_id);
191 DCHECK(itr != uploaded_resources_.end());
192 auto* sii = context_provider_->SharedImageInterface();
193 sii->DestroySharedImage(sync_token, itr->second.mailbox);
194 uploaded_resources_.erase(itr);
195}
196
197void FrameSinkImpl::MarkUIResourceForDeletion(cc::UIResourceId resource_id) {
198 auto itr = uploaded_resources_.find(resource_id);
199 if (itr == uploaded_resources_.end()) {
200 return;
201 }
202 resource_provider_.RemoveImportedResource(itr->second.viz_resource_id);
203}
204
Bo Liu873d13e32023-02-08 15:58:42205viz::ResourceId FrameSinkImpl::GetVizResourceId(cc::UIResourceId resource_id) {
206 auto itr = uploaded_resources_.find(resource_id);
207 if (itr == uploaded_resources_.end()) {
208 return viz::kInvalidResourceId;
209 }
210 return itr->second.viz_resource_id;
Bo Liue0e51f22023-02-02 19:33:00211}
212
213bool FrameSinkImpl::IsUIResourceOpaque(cc::UIResourceId resource_id) {
214 auto it = uploaded_resources_.find(resource_id);
215 if (it == uploaded_resources_.end()) {
216 return true;
217 }
218 return it->second.is_opaque;
219}
220
221gfx::Size FrameSinkImpl::GetUIResourceSize(cc::UIResourceId resource_id) {
222 auto it = uploaded_resources_.find(resource_id);
223 if (it == uploaded_resources_.end()) {
224 return gfx::Size();
225 }
226
227 return it->second.size;
228}
229
Bo Liuf5bd17342023-03-10 17:55:45230int FrameSinkImpl::GetMaxTextureSize() const {
231 if (context_provider_) {
232 return context_provider_->ContextCapabilities().max_texture_size;
233 }
234 return kSoftwareMaxTextureSize;
235}
236
Bo Liue0e51f22023-02-02 19:33:00237void FrameSinkImpl::DidReceiveCompositorFrameAck(
238 std::vector<viz::ReturnedResource> resources) {
239 ReclaimResources(std::move(resources));
Bo Liu3380083a2023-03-22 16:11:04240 DCHECK_GT(num_unacked_frames_, 0u);
241 num_unacked_frames_--;
Bo Liu11af9412023-04-05 19:49:39242 if (!num_unacked_frames_) {
243 scheduler_->SetIsSwapThrottled(false);
244 }
Bo Liue0e51f22023-02-02 19:33:00245 client_->DidReceiveCompositorFrameAck();
246}
247
Bo Liu3380083a2023-03-22 16:11:04248void FrameSinkImpl::ReclaimResources(
249 std::vector<viz::ReturnedResource> resources) {
250 resource_provider_.ReceiveReturnsFromParent(std::move(resources));
251}
252
Bo Liue0e51f22023-02-02 19:33:00253void FrameSinkImpl::OnBeginFrame(
254 const viz::BeginFrameArgs& begin_frame_args,
Jonathan Rossd3117112023-02-17 16:42:09255 const viz::FrameTimingDetailsMap& timing_details,
256 bool frame_ack,
257 std::vector<viz::ReturnedResource> resources) {
258 if (features::IsOnBeginFrameAcksEnabled()) {
259 if (frame_ack) {
260 DidReceiveCompositorFrameAck(std::move(resources));
261 } else if (!resources.empty()) {
262 ReclaimResources(std::move(resources));
263 }
264 }
265
Bo Liuc078148b2023-02-22 18:29:22266 // Note order here is expected to be in order w.r.t viz::FrameTokenGT. This
267 // mostly holds because `FrameTimingDetailsMap` is a flat_map which is sorted.
268 // However this doesn't hold when frame token wraps.
Bo Liue0e51f22023-02-02 19:33:00269 for (const auto& pair : timing_details) {
270 client_->DidPresentCompositorFrame(pair.first, pair.second);
271 }
272
Bo Liu3380083a2023-03-22 16:11:04273 scheduler_->OnBeginFrameFromViz(begin_frame_args);
274}
275
276bool FrameSinkImpl::DoBeginFrame(const viz::BeginFrameArgs& begin_frame_args) {
277 if (num_unacked_frames_) {
278 return false;
279 }
280
Bo Liue0e51f22023-02-02 19:33:00281 if (!local_surface_id_.is_valid()) {
Bo Liu3380083a2023-03-22 16:11:04282 return false;
Bo Liue0e51f22023-02-02 19:33:00283 }
284
Bo Liufe5b6212023-04-06 16:56:28285 TRACE_EVENT0("cc", "slim::FrameSinkImpl::DoBeginFrame");
Bo Liue0e51f22023-02-02 19:33:00286 viz::CompositorFrame frame;
Bo Liu873d13e32023-02-08 15:58:42287 base::flat_set<viz::ResourceId> viz_resource_ids;
Bo Liue0e51f22023-02-02 19:33:00288 viz::HitTestRegionList hit_test_region_list;
Bo Liu873d13e32023-02-08 15:58:42289 if (!client_->BeginFrame(begin_frame_args, frame, viz_resource_ids,
Bo Liue0e51f22023-02-02 19:33:00290 hit_test_region_list)) {
Bo Liu3380083a2023-03-22 16:11:04291 return false;
Bo Liue0e51f22023-02-02 19:33:00292 }
293
Bo Liubfe80a072023-02-17 20:09:15294 if (local_surface_id_ == last_submitted_local_surface_id_) {
295 DCHECK_EQ(last_submitted_device_scale_factor_, frame.device_scale_factor());
296 DCHECK_EQ(last_submitted_size_in_pixels_.height(),
297 frame.size_in_pixels().height());
298 DCHECK_EQ(last_submitted_size_in_pixels_.width(),
299 frame.size_in_pixels().width());
300 }
301
Bo Liu873d13e32023-02-08 15:58:42302 resource_provider_.PrepareSendToParent(std::move(viz_resource_ids).extract(),
303 &frame.resource_list,
Bo Liue0e51f22023-02-02 19:33:00304 context_provider_.get());
305
306 bool send_new_hit_test_region_list = false;
307 if (!hit_test_region_list_ ||
308 !viz::HitTestRegionList::IsEqual(*hit_test_region_list_,
309 hit_test_region_list)) {
310 send_new_hit_test_region_list = true;
311 hit_test_region_list_ = std::move(hit_test_region_list);
312 }
313
314 {
Bo Liufe5b6212023-04-06 16:56:28315 TRACE_EVENT_WITH_FLOW1("viz,benchmark", "Graphics.Pipeline",
316 TRACE_ID_GLOBAL(begin_frame_args.trace_id),
317 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
318 "step", "SubmitCompositorFrame");
Bo Liubfe80a072023-02-17 20:09:15319 frame_sink_->SubmitCompositorFrame(
Bo Liue0e51f22023-02-02 19:33:00320 local_surface_id_, std::move(frame),
321 send_new_hit_test_region_list ? hit_test_region_list_ : absl::nullopt,
322 0);
323 }
Bo Liu3380083a2023-03-22 16:11:04324 num_unacked_frames_++;
Bo Liu11af9412023-04-05 19:49:39325 if (num_unacked_frames_ == 1) {
326 scheduler_->SetIsSwapThrottled(true);
327 }
Bo Liue0e51f22023-02-02 19:33:00328 client_->DidSubmitCompositorFrame();
Bo Liu3380083a2023-03-22 16:11:04329 return true;
Bo Liue0e51f22023-02-02 19:33:00330}
331
Bo Liu3380083a2023-03-22 16:11:04332void FrameSinkImpl::SendDidNotProduceFrame(
333 const viz::BeginFrameArgs& begin_frame_args) {
Bo Liufe5b6212023-04-06 16:56:28334 TRACE_EVENT_WITH_FLOW1("viz,benchmark", "Graphics.Pipeline",
335 TRACE_ID_GLOBAL(begin_frame_args.trace_id),
336 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
337 "step", "DidNotProduceFrame");
Bo Liu3380083a2023-03-22 16:11:04338 frame_sink_->DidNotProduceFrame(viz::BeginFrameAck(begin_frame_args, false));
Bo Liue0e51f22023-02-02 19:33:00339}
340
341} // namespace cc::slim