[go: nahoru, domu]

blob: d4dd3b94a2a75542d4d14d152d15443131aebbb3 [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"
17#include "cc/slim/frame_sink_impl_client.h"
Jonathan Rossd3117112023-02-17 16:42:0918#include "components/viz/common/features.h"
Bo Liu677cece2023-03-07 17:44:1319#include "components/viz/common/quads/compositor_frame.h"
Bo Liue0e51f22023-02-02 19:33:0020#include "components/viz/common/resources/platform_color.h"
21#include "components/viz/common/resources/resource_format_utils.h"
Bo Liu873d13e32023-02-08 15:58:4222#include "components/viz/common/resources/resource_id.h"
Colin Blundell6828da72023-02-13 18:07:3323#include "components/viz/common/resources/shared_image_format.h"
Bo Liu677cece2023-03-07 17:44:1324#include "components/viz/common/resources/transferable_resource.h"
Bo Liue0e51f22023-02-02 19:33:0025#include "gpu/command_buffer/client/shared_image_interface.h"
26#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
27#include "gpu/command_buffer/common/shared_image_usage.h"
28#include "third_party/skia/include/core/SkAlphaType.h"
29#include "third_party/skia/include/gpu/GrTypes.h"
30#include "ui/gfx/buffer_types.h"
31#include "ui/gfx/color_space.h"
32
33namespace cc::slim {
34
35FrameSinkImpl::UploadedUIResource::UploadedUIResource() = default;
36FrameSinkImpl::UploadedUIResource::~UploadedUIResource() = default;
37FrameSinkImpl::UploadedUIResource::UploadedUIResource(
38 const UploadedUIResource&) = default;
39FrameSinkImpl::UploadedUIResource& FrameSinkImpl::UploadedUIResource::operator=(
40 const UploadedUIResource&) = default;
41
42FrameSinkImpl::FrameSinkImpl(
43 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
44 mojo::PendingAssociatedRemote<viz::mojom::CompositorFrameSink>
45 compositor_frame_sink_associated_remote,
46 mojo::PendingReceiver<viz::mojom::CompositorFrameSinkClient>
47 client_receiver,
Michael Thiessenc8842d02023-02-16 17:06:0248 scoped_refptr<viz::ContextProvider> context_provider,
49 base::PlatformThreadId io_thread_id)
Bo Liue0e51f22023-02-02 19:33:0050 : task_runner_(std::move(task_runner)),
51 pending_compositor_frame_sink_associated_remote_(
52 std::move(compositor_frame_sink_associated_remote)),
53 pending_client_receiver_(std::move(client_receiver)),
Michael Thiessenc8842d02023-02-16 17:06:0254 context_provider_(std::move(context_provider)),
55 io_thread_id_(io_thread_id) {}
Bo Liue0e51f22023-02-02 19:33:0056
57FrameSinkImpl::~FrameSinkImpl() {
Bo Liu9d07e212023-02-27 17:13:3758 // Iterate a copy of `uploaded_resources_` since it might be modified
59 // when `UIResourceReleased()` is called.
60 for (const auto& uploaded_resource_pair :
61 UploadedResourceMap(uploaded_resources_)) {
Bo Liu84fe45d2023-02-21 16:33:3762 resource_provider_.RemoveImportedResource(
63 uploaded_resource_pair.second.viz_resource_id);
64 }
Bo Liue0e51f22023-02-02 19:33:0065 resource_provider_.ShutdownAndReleaseAllResources();
66}
67
68void FrameSinkImpl::SetLocalSurfaceId(
69 const viz::LocalSurfaceId& local_surface_id) {
70 if (local_surface_id_ == local_surface_id) {
71 return;
72 }
73 local_surface_id_ = local_surface_id;
74 hit_test_region_list_.reset();
75}
76
77bool FrameSinkImpl::BindToClient(FrameSinkImplClient* client) {
78 DCHECK(client);
79 if (context_provider_) {
80 context_provider_->AddObserver(this);
81 auto result = context_provider_->BindToCurrentSequence();
82 if (result != gpu::ContextResult::kSuccess) {
83 context_provider_->RemoveObserver(this);
84 context_provider_ = nullptr;
85 return false;
86 }
87 }
88
89 client_ = client;
90
91 frame_sink_remote_.Bind(
92 std::move(pending_compositor_frame_sink_associated_remote_));
93 frame_sink_remote_.set_disconnect_handler(
94 base::BindOnce(&FrameSinkImpl::OnContextLost, base::Unretained(this)));
95 client_receiver_.Bind(std::move(pending_client_receiver_), task_runner_);
96
Bo Liubfe80a072023-02-17 20:09:1597 frame_sink_ = frame_sink_remote_.get();
98 frame_sink_->InitializeCompositorFrameSinkType(
Bo Liue0e51f22023-02-02 19:33:0099 viz::mojom::CompositorFrameSinkType::kLayerTree);
100
101#if BUILDFLAG(IS_ANDROID)
102 std::vector<int32_t> thread_ids;
103 thread_ids.push_back(base::PlatformThread::CurrentId());
Michael Thiessenc8842d02023-02-16 17:06:02104 if (io_thread_id_ != base::kInvalidThreadId) {
105 thread_ids.push_back(io_thread_id_);
106 }
Bo Liubfe80a072023-02-17 20:09:15107 frame_sink_->SetThreadIds(thread_ids);
Bo Liue0e51f22023-02-02 19:33:00108#endif
109 return true;
110}
111
112void FrameSinkImpl::OnContextLost() {
113 client_->DidLoseLayerTreeFrameSink();
114}
115
116void FrameSinkImpl::SetNeedsBeginFrame(bool needs_begin_frame) {
117 if (needs_begin_frame_ == needs_begin_frame) {
118 return;
119 }
120 needs_begin_frame_ = needs_begin_frame;
Bo Liubfe80a072023-02-17 20:09:15121 frame_sink_->SetNeedsBeginFrame(needs_begin_frame);
Bo Liue0e51f22023-02-02 19:33:00122}
123
124void FrameSinkImpl::UploadUIResource(cc::UIResourceId resource_id,
125 cc::UIResourceBitmap resource_bitmap) {
126 const gpu::Capabilities& caps = context_provider_->ContextCapabilities();
127 gfx::Size size = resource_bitmap.GetSize();
128 if (size.width() > caps.max_texture_size ||
129 size.height() > caps.max_texture_size) {
130 LOG(ERROR) << "Size exceeds max texture size";
131 return;
132 }
Colin Blundell836bf252023-02-15 08:33:58133 viz::SharedImageFormat format = viz::SinglePlaneFormat::kRGBA_8888;
Bo Liue0e51f22023-02-02 19:33:00134 switch (resource_bitmap.GetFormat()) {
135 case cc::UIResourceBitmap::RGBA8:
Colin Blundell836bf252023-02-15 08:33:58136 format = viz::PlatformColor::BestSupportedTextureFormat(caps);
Bo Liue0e51f22023-02-02 19:33:00137 break;
138 case cc::UIResourceBitmap::ALPHA_8:
Colin Blundell836bf252023-02-15 08:33:58139 format = viz::SinglePlaneFormat::kALPHA_8;
Bo Liue0e51f22023-02-02 19:33:00140 break;
141 case cc::UIResourceBitmap::ETC1:
Colin Blundell836bf252023-02-15 08:33:58142 format = viz::SinglePlaneFormat::kETC1;
Bo Liue0e51f22023-02-02 19:33:00143 break;
144 }
145
146 UploadedUIResource uploaded_resource;
147 auto* sii = context_provider_->SharedImageInterface();
148 constexpr gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB();
149 uint32_t shared_image_usage = gpu::SHARED_IMAGE_USAGE_DISPLAY_READ;
150 uploaded_resource.mailbox = sii->CreateSharedImage(
Colin Blundell836bf252023-02-15 08:33:58151 format, resource_bitmap.GetSize(), color_space, kTopLeft_GrSurfaceOrigin,
152 kPremul_SkAlphaType, shared_image_usage,
Bo Liue0e51f22023-02-02 19:33:00153 base::span<const uint8_t>(resource_bitmap.GetPixels(),
154 resource_bitmap.SizeInBytes()));
155 gpu::SyncToken sync_token = sii->GenUnverifiedSyncToken();
156
157 GLenum texture_target = gpu::GetBufferTextureTarget(
Colin Blundell836bf252023-02-15 08:33:58158 gfx::BufferUsage::SCANOUT, BufferFormat(format.resource_format()), caps);
Bo Liue0e51f22023-02-02 19:33:00159 uploaded_resource.viz_resource_id = resource_provider_.ImportResource(
160 viz::TransferableResource::MakeGpu(
161 uploaded_resource.mailbox, GL_LINEAR, texture_target, sync_token,
162 resource_bitmap.GetSize(), format, /*is_overlay_candidate=*/false),
163 base::BindOnce(&FrameSinkImpl::UIResourceReleased, base::Unretained(this),
164 resource_id));
165 uploaded_resource.size = resource_bitmap.GetSize();
166 uploaded_resource.is_opaque = resource_bitmap.GetOpaque();
167
Bo Liu9d07e212023-02-27 17:13:37168 DCHECK(!uploaded_resources_.contains(resource_id));
Bo Liue0e51f22023-02-02 19:33:00169 uploaded_resources_.emplace(resource_id, uploaded_resource);
170}
171
172void FrameSinkImpl::UIResourceReleased(cc::UIResourceId ui_resource_id,
173 const gpu::SyncToken& sync_token,
174 bool is_lost) {
175 auto itr = uploaded_resources_.find(ui_resource_id);
176 DCHECK(itr != uploaded_resources_.end());
177 auto* sii = context_provider_->SharedImageInterface();
178 sii->DestroySharedImage(sync_token, itr->second.mailbox);
179 uploaded_resources_.erase(itr);
180}
181
182void FrameSinkImpl::MarkUIResourceForDeletion(cc::UIResourceId resource_id) {
183 auto itr = uploaded_resources_.find(resource_id);
184 if (itr == uploaded_resources_.end()) {
185 return;
186 }
187 resource_provider_.RemoveImportedResource(itr->second.viz_resource_id);
188}
189
Bo Liu873d13e32023-02-08 15:58:42190viz::ResourceId FrameSinkImpl::GetVizResourceId(cc::UIResourceId resource_id) {
191 auto itr = uploaded_resources_.find(resource_id);
192 if (itr == uploaded_resources_.end()) {
193 return viz::kInvalidResourceId;
194 }
195 return itr->second.viz_resource_id;
Bo Liue0e51f22023-02-02 19:33:00196}
197
198bool FrameSinkImpl::IsUIResourceOpaque(cc::UIResourceId resource_id) {
199 auto it = uploaded_resources_.find(resource_id);
200 if (it == uploaded_resources_.end()) {
201 return true;
202 }
203 return it->second.is_opaque;
204}
205
206gfx::Size FrameSinkImpl::GetUIResourceSize(cc::UIResourceId resource_id) {
207 auto it = uploaded_resources_.find(resource_id);
208 if (it == uploaded_resources_.end()) {
209 return gfx::Size();
210 }
211
212 return it->second.size;
213}
214
215void FrameSinkImpl::DidReceiveCompositorFrameAck(
216 std::vector<viz::ReturnedResource> resources) {
217 ReclaimResources(std::move(resources));
218 client_->DidReceiveCompositorFrameAck();
219}
220
221void FrameSinkImpl::OnBeginFrame(
222 const viz::BeginFrameArgs& begin_frame_args,
Jonathan Rossd3117112023-02-17 16:42:09223 const viz::FrameTimingDetailsMap& timing_details,
224 bool frame_ack,
225 std::vector<viz::ReturnedResource> resources) {
226 if (features::IsOnBeginFrameAcksEnabled()) {
227 if (frame_ack) {
228 DidReceiveCompositorFrameAck(std::move(resources));
229 } else if (!resources.empty()) {
230 ReclaimResources(std::move(resources));
231 }
232 }
233
Bo Liuc078148b2023-02-22 18:29:22234 // Note order here is expected to be in order w.r.t viz::FrameTokenGT. This
235 // mostly holds because `FrameTimingDetailsMap` is a flat_map which is sorted.
236 // However this doesn't hold when frame token wraps.
Bo Liue0e51f22023-02-02 19:33:00237 for (const auto& pair : timing_details) {
238 client_->DidPresentCompositorFrame(pair.first, pair.second);
239 }
240
241 if (!local_surface_id_.is_valid()) {
Bo Liubfe80a072023-02-17 20:09:15242 frame_sink_->DidNotProduceFrame(
Bo Liue0e51f22023-02-02 19:33:00243 viz::BeginFrameAck(begin_frame_args, false));
244 return;
245 }
246
247 viz::CompositorFrame frame;
Bo Liu873d13e32023-02-08 15:58:42248 base::flat_set<viz::ResourceId> viz_resource_ids;
Bo Liue0e51f22023-02-02 19:33:00249 viz::HitTestRegionList hit_test_region_list;
Bo Liu873d13e32023-02-08 15:58:42250 if (!client_->BeginFrame(begin_frame_args, frame, viz_resource_ids,
Bo Liue0e51f22023-02-02 19:33:00251 hit_test_region_list)) {
Bo Liubfe80a072023-02-17 20:09:15252 frame_sink_->DidNotProduceFrame(
Bo Liue0e51f22023-02-02 19:33:00253 viz::BeginFrameAck(begin_frame_args, false));
254 return;
255 }
256
Bo Liubfe80a072023-02-17 20:09:15257 if (local_surface_id_ == last_submitted_local_surface_id_) {
258 DCHECK_EQ(last_submitted_device_scale_factor_, frame.device_scale_factor());
259 DCHECK_EQ(last_submitted_size_in_pixels_.height(),
260 frame.size_in_pixels().height());
261 DCHECK_EQ(last_submitted_size_in_pixels_.width(),
262 frame.size_in_pixels().width());
263 }
264
Bo Liu873d13e32023-02-08 15:58:42265 resource_provider_.PrepareSendToParent(std::move(viz_resource_ids).extract(),
266 &frame.resource_list,
Bo Liue0e51f22023-02-02 19:33:00267 context_provider_.get());
268
269 bool send_new_hit_test_region_list = false;
270 if (!hit_test_region_list_ ||
271 !viz::HitTestRegionList::IsEqual(*hit_test_region_list_,
272 hit_test_region_list)) {
273 send_new_hit_test_region_list = true;
274 hit_test_region_list_ = std::move(hit_test_region_list);
275 }
276
277 {
278 TRACE_EVENT0("cc", "SubmitCompositorFrame");
Bo Liubfe80a072023-02-17 20:09:15279 frame_sink_->SubmitCompositorFrame(
Bo Liue0e51f22023-02-02 19:33:00280 local_surface_id_, std::move(frame),
281 send_new_hit_test_region_list ? hit_test_region_list_ : absl::nullopt,
282 0);
283 }
284 client_->DidSubmitCompositorFrame();
285}
286
287void FrameSinkImpl::ReclaimResources(
288 std::vector<viz::ReturnedResource> resources) {
289 resource_provider_.ReceiveReturnsFromParent(std::move(resources));
290}
291
292} // namespace cc::slim