[go: nahoru, domu]

blob: 26dd621b3950905becf567e7cc203f05c051856c [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
167 UploadedUIResource uploaded_resource;
168 auto* sii = context_provider_->SharedImageInterface();
169 constexpr gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB();
170 uint32_t shared_image_usage = gpu::SHARED_IMAGE_USAGE_DISPLAY_READ;
Mingjing Zhangf23582c2023-11-20 16:30:19171 uploaded_resource.shared_image = sii->CreateSharedImage(
Colin Blundell836bf252023-02-15 08:33:58172 format, resource_bitmap.GetSize(), color_space, kTopLeft_GrSurfaceOrigin,
Rafael Cintronde3d9b82023-04-19 20:19:28173 kPremul_SkAlphaType, shared_image_usage, "SlimCompositorUIResource",
Bo Liue0e51f22023-02-02 19:33:00174 base::span<const uint8_t>(resource_bitmap.GetPixels(),
175 resource_bitmap.SizeInBytes()));
Mingjing Zhangf23582c2023-11-20 16:30:19176 CHECK(uploaded_resource.shared_image);
Bo Liue0e51f22023-02-02 19:33:00177 gpu::SyncToken sync_token = sii->GenUnverifiedSyncToken();
178
179 GLenum texture_target = gpu::GetBufferTextureTarget(
Colin Blundell81fb20ca2023-05-30 09:37:54180 gfx::BufferUsage::SCANOUT,
181 viz::SinglePlaneSharedImageFormatToBufferFormat(format), caps);
Bo Liue0e51f22023-02-02 19:33:00182 uploaded_resource.viz_resource_id = resource_provider_.ImportResource(
183 viz::TransferableResource::MakeGpu(
Mingjing Zhangf23582c2023-11-20 16:30:19184 uploaded_resource.shared_image, texture_target, sync_token,
Jonathan Ross5914b992023-09-28 15:30:53185 resource_bitmap.GetSize(), format, /*is_overlay_candidate=*/false,
186 viz::TransferableResource::ResourceSource::kUI),
Bo Liue0e51f22023-02-02 19:33:00187 base::BindOnce(&FrameSinkImpl::UIResourceReleased, base::Unretained(this),
188 resource_id));
189 uploaded_resource.size = resource_bitmap.GetSize();
190 uploaded_resource.is_opaque = resource_bitmap.GetOpaque();
191
Bo Liu9d07e212023-02-27 17:13:37192 DCHECK(!uploaded_resources_.contains(resource_id));
Bo Liue0e51f22023-02-02 19:33:00193 uploaded_resources_.emplace(resource_id, uploaded_resource);
194}
195
196void FrameSinkImpl::UIResourceReleased(cc::UIResourceId ui_resource_id,
197 const gpu::SyncToken& sync_token,
198 bool is_lost) {
199 auto itr = uploaded_resources_.find(ui_resource_id);
200 DCHECK(itr != uploaded_resources_.end());
201 auto* sii = context_provider_->SharedImageInterface();
Mingjing Zhangf23582c2023-11-20 16:30:19202 sii->DestroySharedImage(sync_token, std::move(itr->second.shared_image));
Bo Liue0e51f22023-02-02 19:33:00203 uploaded_resources_.erase(itr);
204}
205
206void FrameSinkImpl::MarkUIResourceForDeletion(cc::UIResourceId resource_id) {
207 auto itr = uploaded_resources_.find(resource_id);
208 if (itr == uploaded_resources_.end()) {
209 return;
210 }
211 resource_provider_.RemoveImportedResource(itr->second.viz_resource_id);
212}
213
Bo Liu873d13e32023-02-08 15:58:42214viz::ResourceId FrameSinkImpl::GetVizResourceId(cc::UIResourceId resource_id) {
215 auto itr = uploaded_resources_.find(resource_id);
216 if (itr == uploaded_resources_.end()) {
217 return viz::kInvalidResourceId;
218 }
219 return itr->second.viz_resource_id;
Bo Liue0e51f22023-02-02 19:33:00220}
221
222bool FrameSinkImpl::IsUIResourceOpaque(cc::UIResourceId resource_id) {
223 auto it = uploaded_resources_.find(resource_id);
224 if (it == uploaded_resources_.end()) {
225 return true;
226 }
227 return it->second.is_opaque;
228}
229
230gfx::Size FrameSinkImpl::GetUIResourceSize(cc::UIResourceId resource_id) {
231 auto it = uploaded_resources_.find(resource_id);
232 if (it == uploaded_resources_.end()) {
233 return gfx::Size();
234 }
235
236 return it->second.size;
237}
238
Bo Liuf5bd17342023-03-10 17:55:45239int FrameSinkImpl::GetMaxTextureSize() const {
240 if (context_provider_) {
241 return context_provider_->ContextCapabilities().max_texture_size;
242 }
243 return kSoftwareMaxTextureSize;
244}
245
Bo Liue0e51f22023-02-02 19:33:00246void FrameSinkImpl::DidReceiveCompositorFrameAck(
247 std::vector<viz::ReturnedResource> resources) {
248 ReclaimResources(std::move(resources));
Bo Liu3380083a2023-03-22 16:11:04249 DCHECK_GT(num_unacked_frames_, 0u);
250 num_unacked_frames_--;
Bo Liu11af9412023-04-05 19:49:39251 if (!num_unacked_frames_) {
252 scheduler_->SetIsSwapThrottled(false);
253 }
Bo Liue0e51f22023-02-02 19:33:00254 client_->DidReceiveCompositorFrameAck();
255}
256
Bo Liu3380083a2023-03-22 16:11:04257void FrameSinkImpl::ReclaimResources(
258 std::vector<viz::ReturnedResource> resources) {
259 resource_provider_.ReceiveReturnsFromParent(std::move(resources));
260}
261
Bo Liue0e51f22023-02-02 19:33:00262void FrameSinkImpl::OnBeginFrame(
263 const viz::BeginFrameArgs& begin_frame_args,
Jonathan Rossd3117112023-02-17 16:42:09264 const viz::FrameTimingDetailsMap& timing_details,
265 bool frame_ack,
266 std::vector<viz::ReturnedResource> resources) {
267 if (features::IsOnBeginFrameAcksEnabled()) {
268 if (frame_ack) {
269 DidReceiveCompositorFrameAck(std::move(resources));
270 } else if (!resources.empty()) {
271 ReclaimResources(std::move(resources));
272 }
273 }
274
Bo Liuc078148b2023-02-22 18:29:22275 // Note order here is expected to be in order w.r.t viz::FrameTokenGT. This
276 // mostly holds because `FrameTimingDetailsMap` is a flat_map which is sorted.
277 // However this doesn't hold when frame token wraps.
Bo Liue0e51f22023-02-02 19:33:00278 for (const auto& pair : timing_details) {
279 client_->DidPresentCompositorFrame(pair.first, pair.second);
280 }
281
Bo Liu3380083a2023-03-22 16:11:04282 scheduler_->OnBeginFrameFromViz(begin_frame_args);
283}
284
285bool FrameSinkImpl::DoBeginFrame(const viz::BeginFrameArgs& begin_frame_args) {
286 if (num_unacked_frames_) {
287 return false;
288 }
289
Bo Liue0e51f22023-02-02 19:33:00290 if (!local_surface_id_.is_valid()) {
Bo Liu3380083a2023-03-22 16:11:04291 return false;
Bo Liue0e51f22023-02-02 19:33:00292 }
293
Bo Liufe5b6212023-04-06 16:56:28294 TRACE_EVENT0("cc", "slim::FrameSinkImpl::DoBeginFrame");
Bo Liue0e51f22023-02-02 19:33:00295 viz::CompositorFrame frame;
Bo Liu873d13e32023-02-08 15:58:42296 base::flat_set<viz::ResourceId> viz_resource_ids;
Bo Liue0e51f22023-02-02 19:33:00297 viz::HitTestRegionList hit_test_region_list;
Bo Liu873d13e32023-02-08 15:58:42298 if (!client_->BeginFrame(begin_frame_args, frame, viz_resource_ids,
Bo Liue0e51f22023-02-02 19:33:00299 hit_test_region_list)) {
Bo Liu3380083a2023-03-22 16:11:04300 return false;
Bo Liue0e51f22023-02-02 19:33:00301 }
302
Bo Liubfe80a072023-02-17 20:09:15303 if (local_surface_id_ == last_submitted_local_surface_id_) {
304 DCHECK_EQ(last_submitted_device_scale_factor_, frame.device_scale_factor());
305 DCHECK_EQ(last_submitted_size_in_pixels_.height(),
306 frame.size_in_pixels().height());
307 DCHECK_EQ(last_submitted_size_in_pixels_.width(),
308 frame.size_in_pixels().width());
309 }
310
Bo Liu873d13e32023-02-08 15:58:42311 resource_provider_.PrepareSendToParent(std::move(viz_resource_ids).extract(),
312 &frame.resource_list,
Bo Liue0e51f22023-02-02 19:33:00313 context_provider_.get());
314
315 bool send_new_hit_test_region_list = false;
316 if (!hit_test_region_list_ ||
317 !viz::HitTestRegionList::IsEqual(*hit_test_region_list_,
318 hit_test_region_list)) {
319 send_new_hit_test_region_list = true;
320 hit_test_region_list_ = std::move(hit_test_region_list);
321 }
322
323 {
Aman Vermab5f203c2023-07-31 18:32:41324 TRACE_EVENT(
Aman Vermae40f10842023-08-09 15:30:19325 "viz,benchmark,graphics.pipeline", "Graphics.Pipeline",
Aman Vermab5f203c2023-07-31 18:32:41326 perfetto::Flow::Global(begin_frame_args.trace_id),
327 [&](perfetto::EventContext ctx) {
328 auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>();
329 auto* data = event->set_chrome_graphics_pipeline();
330 data->set_step(perfetto::protos::pbzero::ChromeGraphicsPipeline::
331 StepName::STEP_SUBMIT_COMPOSITOR_FRAME);
332 });
Bo Liubfe80a072023-02-17 20:09:15333 frame_sink_->SubmitCompositorFrame(
Bo Liue0e51f22023-02-02 19:33:00334 local_surface_id_, std::move(frame),
Arthur Sonzognica067f262023-11-10 14:18:10335 send_new_hit_test_region_list ? hit_test_region_list_ : std::nullopt,
Bo Liue0e51f22023-02-02 19:33:00336 0);
337 }
Bo Liu3380083a2023-03-22 16:11:04338 num_unacked_frames_++;
Bo Liu11af9412023-04-05 19:49:39339 if (num_unacked_frames_ == 1) {
340 scheduler_->SetIsSwapThrottled(true);
341 }
Bo Liue0e51f22023-02-02 19:33:00342 client_->DidSubmitCompositorFrame();
Bo Liu3380083a2023-03-22 16:11:04343 return true;
Bo Liue0e51f22023-02-02 19:33:00344}
345
Bo Liu3380083a2023-03-22 16:11:04346void FrameSinkImpl::SendDidNotProduceFrame(
347 const viz::BeginFrameArgs& begin_frame_args) {
Aman Vermab5f203c2023-07-31 18:32:41348 TRACE_EVENT(
Aman Vermae40f10842023-08-09 15:30:19349 "viz,benchmark,graphics.pipeline", "Graphics.Pipeline",
Aman Vermab5f203c2023-07-31 18:32:41350 perfetto::Flow::Global(begin_frame_args.trace_id),
351 [&](perfetto::EventContext ctx) {
352 auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>();
353 auto* data = event->set_chrome_graphics_pipeline();
354 data->set_step(perfetto::protos::pbzero::ChromeGraphicsPipeline::
355 StepName::STEP_DID_NOT_PRODUCE_FRAME);
356 });
Bo Liu3380083a2023-03-22 16:11:04357 frame_sink_->DidNotProduceFrame(viz::BeginFrameAck(begin_frame_args, false));
Bo Liue0e51f22023-02-02 19:33:00358}
359
360} // namespace cc::slim