[go: nahoru, domu]

blob: 0fbd624cb93a13326dca265e6fa0783e2e1c2443 [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"
Aman Vermab5f203c2023-07-31 18:32:4116#include "base/trace_event/typed_macros.h"
Bo Liue0e51f22023-02-02 19:33:0017#include "build/build_config.h"
Bo Liuf5bd17342023-03-10 17:55:4518#include "cc/slim/constants.h"
Bo Liu11af9412023-04-05 19:49:3919#include "cc/slim/delayed_scheduler.h"
Bo Liue0e51f22023-02-02 19:33:0020#include "cc/slim/frame_sink_impl_client.h"
Jonathan Rossd3117112023-02-17 16:42:0921#include "components/viz/common/features.h"
Bo Liu677cece2023-03-07 17:44:1322#include "components/viz/common/quads/compositor_frame.h"
Bo Liue0e51f22023-02-02 19:33:0023#include "components/viz/common/resources/platform_color.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"
Mingjing Zhang65eedcc2023-10-24 15:12:4228#include "gpu/command_buffer/client/client_shared_image.h"
Bo Liue0e51f22023-02-02 19:33:0029#include "gpu/command_buffer/client/shared_image_interface.h"
30#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
31#include "gpu/command_buffer/common/shared_image_usage.h"
32#include "third_party/skia/include/core/SkAlphaType.h"
33#include "third_party/skia/include/gpu/GrTypes.h"
34#include "ui/gfx/buffer_types.h"
35#include "ui/gfx/color_space.h"
36
37namespace cc::slim {
38
39FrameSinkImpl::UploadedUIResource::UploadedUIResource() = default;
40FrameSinkImpl::UploadedUIResource::~UploadedUIResource() = default;
41FrameSinkImpl::UploadedUIResource::UploadedUIResource(
42 const UploadedUIResource&) = default;
43FrameSinkImpl::UploadedUIResource& FrameSinkImpl::UploadedUIResource::operator=(
44 const UploadedUIResource&) = default;
45
46FrameSinkImpl::FrameSinkImpl(
47 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
48 mojo::PendingAssociatedRemote<viz::mojom::CompositorFrameSink>
49 compositor_frame_sink_associated_remote,
50 mojo::PendingReceiver<viz::mojom::CompositorFrameSinkClient>
51 client_receiver,
kylecharffcf0912023-06-09 18:57:2252 scoped_refptr<viz::RasterContextProvider> context_provider,
Bo Liu3380083a2023-03-22 16:11:0453 base::PlatformThreadId io_thread_id,
54 std::unique_ptr<Scheduler> scheduler)
Bo Liue0e51f22023-02-02 19:33:0055 : task_runner_(std::move(task_runner)),
Bo Liu3380083a2023-03-22 16:11:0456 scheduler_(std::move(scheduler)),
Bo Liue0e51f22023-02-02 19:33:0057 pending_compositor_frame_sink_associated_remote_(
58 std::move(compositor_frame_sink_associated_remote)),
59 pending_client_receiver_(std::move(client_receiver)),
Michael Thiessenc8842d02023-02-16 17:06:0260 context_provider_(std::move(context_provider)),
Bo Liu3380083a2023-03-22 16:11:0461 io_thread_id_(io_thread_id) {
62 scheduler_->Initialize(this);
63}
Bo Liue0e51f22023-02-02 19:33:0064
65FrameSinkImpl::~FrameSinkImpl() {
Mingjing Zhangf23582c2023-11-20 16:30:1966 // Iterate a copy of the viz_resource_ids since `uploaded_resources_` might
67 // be modified when `UIResourceReleased()` is called.
68 // Also note that the DestroySharedImage() call in UIResourceRelease()
69 // requires the `ClientSharedImage` stored in the to-be-released resource to
70 // have precisely one reference. Therefore, it is advisable to avoid any
71 // operation that might alter the `ClientSharedImage`'s refcount, e.g.
72 // creating a full copy of `uploaded_resources_`.
73 auto resource_ids = base::MakeFlatSet<viz::ResourceId>(
74 uploaded_resources_, {},
75 [](auto& resource_pair) { return resource_pair.second.viz_resource_id; });
76 for (const auto& uploaded_resource_id : resource_ids) {
77 resource_provider_.RemoveImportedResource(uploaded_resource_id);
Bo Liu84fe45d2023-02-21 16:33:3778 }
Bo Liue0e51f22023-02-02 19:33:0079 resource_provider_.ShutdownAndReleaseAllResources();
80}
81
82void FrameSinkImpl::SetLocalSurfaceId(
83 const viz::LocalSurfaceId& local_surface_id) {
84 if (local_surface_id_ == local_surface_id) {
85 return;
86 }
87 local_surface_id_ = local_surface_id;
88 hit_test_region_list_.reset();
89}
90
91bool FrameSinkImpl::BindToClient(FrameSinkImplClient* client) {
92 DCHECK(client);
93 if (context_provider_) {
94 context_provider_->AddObserver(this);
95 auto result = context_provider_->BindToCurrentSequence();
96 if (result != gpu::ContextResult::kSuccess) {
97 context_provider_->RemoveObserver(this);
98 context_provider_ = nullptr;
99 return false;
100 }
101 }
102
103 client_ = client;
104
105 frame_sink_remote_.Bind(
106 std::move(pending_compositor_frame_sink_associated_remote_));
107 frame_sink_remote_.set_disconnect_handler(
108 base::BindOnce(&FrameSinkImpl::OnContextLost, base::Unretained(this)));
109 client_receiver_.Bind(std::move(pending_client_receiver_), task_runner_);
110
Bo Liubfe80a072023-02-17 20:09:15111 frame_sink_ = frame_sink_remote_.get();
112 frame_sink_->InitializeCompositorFrameSinkType(
Bo Liue0e51f22023-02-02 19:33:00113 viz::mojom::CompositorFrameSinkType::kLayerTree);
114
115#if BUILDFLAG(IS_ANDROID)
116 std::vector<int32_t> thread_ids;
117 thread_ids.push_back(base::PlatformThread::CurrentId());
Michael Thiessenc8842d02023-02-16 17:06:02118 if (io_thread_id_ != base::kInvalidThreadId) {
119 thread_ids.push_back(io_thread_id_);
120 }
Bo Liubfe80a072023-02-17 20:09:15121 frame_sink_->SetThreadIds(thread_ids);
Bo Liue0e51f22023-02-02 19:33:00122#endif
123 return true;
124}
125
126void FrameSinkImpl::OnContextLost() {
127 client_->DidLoseLayerTreeFrameSink();
128}
129
130void FrameSinkImpl::SetNeedsBeginFrame(bool needs_begin_frame) {
131 if (needs_begin_frame_ == needs_begin_frame) {
132 return;
133 }
134 needs_begin_frame_ = needs_begin_frame;
Bo Liu11af9412023-04-05 19:49:39135 scheduler_->SetNeedsBeginFrame(needs_begin_frame);
Bo Liubfe80a072023-02-17 20:09:15136 frame_sink_->SetNeedsBeginFrame(needs_begin_frame);
Bo Liue0e51f22023-02-02 19:33:00137}
138
Bo Liu11af9412023-04-05 19:49:39139void FrameSinkImpl::MaybeCompositeNow() {
140 scheduler_->MaybeCompositeNow();
141}
142
Bo Liue0e51f22023-02-02 19:33:00143void FrameSinkImpl::UploadUIResource(cc::UIResourceId resource_id,
144 cc::UIResourceBitmap resource_bitmap) {
Bo Liue0e51f22023-02-02 19:33:00145 gfx::Size size = resource_bitmap.GetSize();
Bo Liue54865a2023-05-01 17:52:48146 TRACE_EVENT1("cc", "slim::FrameSinkImpl::UploadUIResource", "size",
147 size.ToString());
148 const gpu::Capabilities& caps = context_provider_->ContextCapabilities();
Bo Liue0e51f22023-02-02 19:33:00149 if (size.width() > caps.max_texture_size ||
150 size.height() > caps.max_texture_size) {
151 LOG(ERROR) << "Size exceeds max texture size";
152 return;
153 }
Colin Blundell836bf252023-02-15 08:33:58154 viz::SharedImageFormat format = viz::SinglePlaneFormat::kRGBA_8888;
Bo Liue0e51f22023-02-02 19:33:00155 switch (resource_bitmap.GetFormat()) {
156 case cc::UIResourceBitmap::RGBA8:
Colin Blundell836bf252023-02-15 08:33:58157 format = viz::PlatformColor::BestSupportedTextureFormat(caps);
Bo Liue0e51f22023-02-02 19:33:00158 break;
159 case cc::UIResourceBitmap::ALPHA_8:
Colin Blundell836bf252023-02-15 08:33:58160 format = viz::SinglePlaneFormat::kALPHA_8;
Bo Liue0e51f22023-02-02 19:33:00161 break;
162 case cc::UIResourceBitmap::ETC1:
Colin Blundell836bf252023-02-15 08:33:58163 format = viz::SinglePlaneFormat::kETC1;
Bo Liue0e51f22023-02-02 19:33:00164 break;
165 }
166
kylechar54eab042024-02-01 14:42:26167 // CreateSharedImage() with initial pixels doesn't support specifying
168 // non-standard stride so data must be exactly the minimum size required to
169 // hold all pixels.
170 DCHECK_EQ(format.EstimatedSizeInBytes(size), resource_bitmap.SizeInBytes());
171
Bo Liue0e51f22023-02-02 19:33:00172 UploadedUIResource uploaded_resource;
173 auto* sii = context_provider_->SharedImageInterface();
174 constexpr gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB();
175 uint32_t shared_image_usage = gpu::SHARED_IMAGE_USAGE_DISPLAY_READ;
Mingjing Zhangf23582c2023-11-20 16:30:19176 uploaded_resource.shared_image = sii->CreateSharedImage(
Colin Blundell836bf252023-02-15 08:33:58177 format, resource_bitmap.GetSize(), color_space, kTopLeft_GrSurfaceOrigin,
Rafael Cintronde3d9b82023-04-19 20:19:28178 kPremul_SkAlphaType, shared_image_usage, "SlimCompositorUIResource",
Bo Liue0e51f22023-02-02 19:33:00179 base::span<const uint8_t>(resource_bitmap.GetPixels(),
180 resource_bitmap.SizeInBytes()));
Mingjing Zhangf23582c2023-11-20 16:30:19181 CHECK(uploaded_resource.shared_image);
Bo Liue0e51f22023-02-02 19:33:00182 gpu::SyncToken sync_token = sii->GenUnverifiedSyncToken();
183
184 GLenum texture_target = gpu::GetBufferTextureTarget(
Colin Blundell81fb20ca2023-05-30 09:37:54185 gfx::BufferUsage::SCANOUT,
186 viz::SinglePlaneSharedImageFormatToBufferFormat(format), caps);
Bo Liue0e51f22023-02-02 19:33:00187 uploaded_resource.viz_resource_id = resource_provider_.ImportResource(
188 viz::TransferableResource::MakeGpu(
Mingjing Zhangf23582c2023-11-20 16:30:19189 uploaded_resource.shared_image, texture_target, sync_token,
Jonathan Ross5914b992023-09-28 15:30:53190 resource_bitmap.GetSize(), format, /*is_overlay_candidate=*/false,
191 viz::TransferableResource::ResourceSource::kUI),
Bo Liue0e51f22023-02-02 19:33:00192 base::BindOnce(&FrameSinkImpl::UIResourceReleased, base::Unretained(this),
193 resource_id));
194 uploaded_resource.size = resource_bitmap.GetSize();
195 uploaded_resource.is_opaque = resource_bitmap.GetOpaque();
196
Bo Liu9d07e212023-02-27 17:13:37197 DCHECK(!uploaded_resources_.contains(resource_id));
Bo Liue0e51f22023-02-02 19:33:00198 uploaded_resources_.emplace(resource_id, uploaded_resource);
199}
200
201void FrameSinkImpl::UIResourceReleased(cc::UIResourceId ui_resource_id,
202 const gpu::SyncToken& sync_token,
203 bool is_lost) {
204 auto itr = uploaded_resources_.find(ui_resource_id);
205 DCHECK(itr != uploaded_resources_.end());
206 auto* sii = context_provider_->SharedImageInterface();
Mingjing Zhangf23582c2023-11-20 16:30:19207 sii->DestroySharedImage(sync_token, std::move(itr->second.shared_image));
Bo Liue0e51f22023-02-02 19:33:00208 uploaded_resources_.erase(itr);
209}
210
211void FrameSinkImpl::MarkUIResourceForDeletion(cc::UIResourceId resource_id) {
212 auto itr = uploaded_resources_.find(resource_id);
213 if (itr == uploaded_resources_.end()) {
214 return;
215 }
216 resource_provider_.RemoveImportedResource(itr->second.viz_resource_id);
217}
218
Bo Liu873d13e32023-02-08 15:58:42219viz::ResourceId FrameSinkImpl::GetVizResourceId(cc::UIResourceId resource_id) {
220 auto itr = uploaded_resources_.find(resource_id);
221 if (itr == uploaded_resources_.end()) {
222 return viz::kInvalidResourceId;
223 }
224 return itr->second.viz_resource_id;
Bo Liue0e51f22023-02-02 19:33:00225}
226
227bool FrameSinkImpl::IsUIResourceOpaque(cc::UIResourceId resource_id) {
228 auto it = uploaded_resources_.find(resource_id);
229 if (it == uploaded_resources_.end()) {
230 return true;
231 }
232 return it->second.is_opaque;
233}
234
235gfx::Size FrameSinkImpl::GetUIResourceSize(cc::UIResourceId resource_id) {
236 auto it = uploaded_resources_.find(resource_id);
237 if (it == uploaded_resources_.end()) {
238 return gfx::Size();
239 }
240
241 return it->second.size;
242}
243
Bo Liuf5bd17342023-03-10 17:55:45244int FrameSinkImpl::GetMaxTextureSize() const {
245 if (context_provider_) {
246 return context_provider_->ContextCapabilities().max_texture_size;
247 }
248 return kSoftwareMaxTextureSize;
249}
250
Bo Liue0e51f22023-02-02 19:33:00251void FrameSinkImpl::DidReceiveCompositorFrameAck(
252 std::vector<viz::ReturnedResource> resources) {
253 ReclaimResources(std::move(resources));
Bo Liu3380083a2023-03-22 16:11:04254 DCHECK_GT(num_unacked_frames_, 0u);
255 num_unacked_frames_--;
Bo Liu11af9412023-04-05 19:49:39256 if (!num_unacked_frames_) {
257 scheduler_->SetIsSwapThrottled(false);
258 }
Bo Liue0e51f22023-02-02 19:33:00259 client_->DidReceiveCompositorFrameAck();
260}
261
Bo Liu3380083a2023-03-22 16:11:04262void FrameSinkImpl::ReclaimResources(
263 std::vector<viz::ReturnedResource> resources) {
264 resource_provider_.ReceiveReturnsFromParent(std::move(resources));
265}
266
Bo Liue0e51f22023-02-02 19:33:00267void FrameSinkImpl::OnBeginFrame(
268 const viz::BeginFrameArgs& begin_frame_args,
Jonathan Rossd3117112023-02-17 16:42:09269 const viz::FrameTimingDetailsMap& timing_details,
270 bool frame_ack,
271 std::vector<viz::ReturnedResource> resources) {
272 if (features::IsOnBeginFrameAcksEnabled()) {
273 if (frame_ack) {
274 DidReceiveCompositorFrameAck(std::move(resources));
275 } else if (!resources.empty()) {
276 ReclaimResources(std::move(resources));
277 }
278 }
279
Bo Liuc078148b2023-02-22 18:29:22280 // Note order here is expected to be in order w.r.t viz::FrameTokenGT. This
281 // mostly holds because `FrameTimingDetailsMap` is a flat_map which is sorted.
282 // However this doesn't hold when frame token wraps.
Bo Liue0e51f22023-02-02 19:33:00283 for (const auto& pair : timing_details) {
284 client_->DidPresentCompositorFrame(pair.first, pair.second);
285 }
286
Bo Liu3380083a2023-03-22 16:11:04287 scheduler_->OnBeginFrameFromViz(begin_frame_args);
288}
289
290bool FrameSinkImpl::DoBeginFrame(const viz::BeginFrameArgs& begin_frame_args) {
291 if (num_unacked_frames_) {
292 return false;
293 }
294
Bo Liue0e51f22023-02-02 19:33:00295 if (!local_surface_id_.is_valid()) {
Bo Liu3380083a2023-03-22 16:11:04296 return false;
Bo Liue0e51f22023-02-02 19:33:00297 }
298
Bo Liufe5b6212023-04-06 16:56:28299 TRACE_EVENT0("cc", "slim::FrameSinkImpl::DoBeginFrame");
Bo Liue0e51f22023-02-02 19:33:00300 viz::CompositorFrame frame;
Bo Liu873d13e32023-02-08 15:58:42301 base::flat_set<viz::ResourceId> viz_resource_ids;
Bo Liue0e51f22023-02-02 19:33:00302 viz::HitTestRegionList hit_test_region_list;
Bo Liu873d13e32023-02-08 15:58:42303 if (!client_->BeginFrame(begin_frame_args, frame, viz_resource_ids,
Bo Liue0e51f22023-02-02 19:33:00304 hit_test_region_list)) {
Bo Liu3380083a2023-03-22 16:11:04305 return false;
Bo Liue0e51f22023-02-02 19:33:00306 }
307
Bo Liubfe80a072023-02-17 20:09:15308 if (local_surface_id_ == last_submitted_local_surface_id_) {
309 DCHECK_EQ(last_submitted_device_scale_factor_, frame.device_scale_factor());
310 DCHECK_EQ(last_submitted_size_in_pixels_.height(),
311 frame.size_in_pixels().height());
312 DCHECK_EQ(last_submitted_size_in_pixels_.width(),
313 frame.size_in_pixels().width());
314 }
315
Bo Liu873d13e32023-02-08 15:58:42316 resource_provider_.PrepareSendToParent(std::move(viz_resource_ids).extract(),
317 &frame.resource_list,
Bo Liue0e51f22023-02-02 19:33:00318 context_provider_.get());
319
320 bool send_new_hit_test_region_list = false;
321 if (!hit_test_region_list_ ||
322 !viz::HitTestRegionList::IsEqual(*hit_test_region_list_,
323 hit_test_region_list)) {
324 send_new_hit_test_region_list = true;
325 hit_test_region_list_ = std::move(hit_test_region_list);
326 }
327
328 {
Aman Vermab5f203c2023-07-31 18:32:41329 TRACE_EVENT(
Aman Vermae40f10842023-08-09 15:30:19330 "viz,benchmark,graphics.pipeline", "Graphics.Pipeline",
Aman Vermab5f203c2023-07-31 18:32:41331 perfetto::Flow::Global(begin_frame_args.trace_id),
332 [&](perfetto::EventContext ctx) {
333 auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>();
334 auto* data = event->set_chrome_graphics_pipeline();
335 data->set_step(perfetto::protos::pbzero::ChromeGraphicsPipeline::
336 StepName::STEP_SUBMIT_COMPOSITOR_FRAME);
337 });
Bo Liubfe80a072023-02-17 20:09:15338 frame_sink_->SubmitCompositorFrame(
Bo Liue0e51f22023-02-02 19:33:00339 local_surface_id_, std::move(frame),
Arthur Sonzognica067f262023-11-10 14:18:10340 send_new_hit_test_region_list ? hit_test_region_list_ : std::nullopt,
Bo Liue0e51f22023-02-02 19:33:00341 0);
342 }
Bo Liu3380083a2023-03-22 16:11:04343 num_unacked_frames_++;
Bo Liu11af9412023-04-05 19:49:39344 if (num_unacked_frames_ == 1) {
345 scheduler_->SetIsSwapThrottled(true);
346 }
Bo Liue0e51f22023-02-02 19:33:00347 client_->DidSubmitCompositorFrame();
Bo Liu3380083a2023-03-22 16:11:04348 return true;
Bo Liue0e51f22023-02-02 19:33:00349}
350
Bo Liu3380083a2023-03-22 16:11:04351void FrameSinkImpl::SendDidNotProduceFrame(
352 const viz::BeginFrameArgs& begin_frame_args) {
Aman Vermab5f203c2023-07-31 18:32:41353 TRACE_EVENT(
Aman Vermae40f10842023-08-09 15:30:19354 "viz,benchmark,graphics.pipeline", "Graphics.Pipeline",
Aman Vermab5f203c2023-07-31 18:32:41355 perfetto::Flow::Global(begin_frame_args.trace_id),
356 [&](perfetto::EventContext ctx) {
357 auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>();
358 auto* data = event->set_chrome_graphics_pipeline();
359 data->set_step(perfetto::protos::pbzero::ChromeGraphicsPipeline::
360 StepName::STEP_DID_NOT_PRODUCE_FRAME);
361 });
Bo Liu3380083a2023-03-22 16:11:04362 frame_sink_->DidNotProduceFrame(viz::BeginFrameAck(begin_frame_args, false));
Bo Liue0e51f22023-02-02 19:33:00363}
364
365} // namespace cc::slim