[go: nahoru, domu]

blob: a41d22b3ab9b9fe2244537617150d3b1e1af73c4 [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 Liue0e51f22023-02-02 19:33:0019#include "components/viz/common/resources/platform_color.h"
20#include "components/viz/common/resources/resource_format_utils.h"
Bo Liu873d13e32023-02-08 15:58:4221#include "components/viz/common/resources/resource_id.h"
Colin Blundell6828da72023-02-13 18:07:3322#include "components/viz/common/resources/shared_image_format.h"
Bo Liue0e51f22023-02-02 19:33:0023#include "gpu/command_buffer/client/shared_image_interface.h"
24#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
25#include "gpu/command_buffer/common/shared_image_usage.h"
26#include "third_party/skia/include/core/SkAlphaType.h"
27#include "third_party/skia/include/gpu/GrTypes.h"
28#include "ui/gfx/buffer_types.h"
29#include "ui/gfx/color_space.h"
30
31namespace cc::slim {
32
33FrameSinkImpl::UploadedUIResource::UploadedUIResource() = default;
34FrameSinkImpl::UploadedUIResource::~UploadedUIResource() = default;
35FrameSinkImpl::UploadedUIResource::UploadedUIResource(
36 const UploadedUIResource&) = default;
37FrameSinkImpl::UploadedUIResource& FrameSinkImpl::UploadedUIResource::operator=(
38 const UploadedUIResource&) = default;
39
40FrameSinkImpl::FrameSinkImpl(
41 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
42 mojo::PendingAssociatedRemote<viz::mojom::CompositorFrameSink>
43 compositor_frame_sink_associated_remote,
44 mojo::PendingReceiver<viz::mojom::CompositorFrameSinkClient>
45 client_receiver,
Michael Thiessenc8842d02023-02-16 17:06:0246 scoped_refptr<viz::ContextProvider> context_provider,
47 base::PlatformThreadId io_thread_id)
Bo Liue0e51f22023-02-02 19:33:0048 : task_runner_(std::move(task_runner)),
49 pending_compositor_frame_sink_associated_remote_(
50 std::move(compositor_frame_sink_associated_remote)),
51 pending_client_receiver_(std::move(client_receiver)),
Michael Thiessenc8842d02023-02-16 17:06:0252 context_provider_(std::move(context_provider)),
53 io_thread_id_(io_thread_id) {}
Bo Liue0e51f22023-02-02 19:33:0054
55FrameSinkImpl::~FrameSinkImpl() {
Bo Liu84fe45d2023-02-21 16:33:3756 for (const auto& uploaded_resource_pair : uploaded_resources_) {
57 resource_provider_.RemoveImportedResource(
58 uploaded_resource_pair.second.viz_resource_id);
59 }
Bo Liue0e51f22023-02-02 19:33:0060 resource_provider_.ShutdownAndReleaseAllResources();
61}
62
63void FrameSinkImpl::SetLocalSurfaceId(
64 const viz::LocalSurfaceId& local_surface_id) {
65 if (local_surface_id_ == local_surface_id) {
66 return;
67 }
68 local_surface_id_ = local_surface_id;
69 hit_test_region_list_.reset();
70}
71
72bool FrameSinkImpl::BindToClient(FrameSinkImplClient* client) {
73 DCHECK(client);
74 if (context_provider_) {
75 context_provider_->AddObserver(this);
76 auto result = context_provider_->BindToCurrentSequence();
77 if (result != gpu::ContextResult::kSuccess) {
78 context_provider_->RemoveObserver(this);
79 context_provider_ = nullptr;
80 return false;
81 }
82 }
83
84 client_ = client;
85
86 frame_sink_remote_.Bind(
87 std::move(pending_compositor_frame_sink_associated_remote_));
88 frame_sink_remote_.set_disconnect_handler(
89 base::BindOnce(&FrameSinkImpl::OnContextLost, base::Unretained(this)));
90 client_receiver_.Bind(std::move(pending_client_receiver_), task_runner_);
91
Bo Liubfe80a072023-02-17 20:09:1592 frame_sink_ = frame_sink_remote_.get();
93 frame_sink_->InitializeCompositorFrameSinkType(
Bo Liue0e51f22023-02-02 19:33:0094 viz::mojom::CompositorFrameSinkType::kLayerTree);
95
96#if BUILDFLAG(IS_ANDROID)
97 std::vector<int32_t> thread_ids;
98 thread_ids.push_back(base::PlatformThread::CurrentId());
Michael Thiessenc8842d02023-02-16 17:06:0299 if (io_thread_id_ != base::kInvalidThreadId) {
100 thread_ids.push_back(io_thread_id_);
101 }
Bo Liubfe80a072023-02-17 20:09:15102 frame_sink_->SetThreadIds(thread_ids);
Bo Liue0e51f22023-02-02 19:33:00103#endif
104 return true;
105}
106
107void FrameSinkImpl::OnContextLost() {
108 client_->DidLoseLayerTreeFrameSink();
109}
110
111void FrameSinkImpl::SetNeedsBeginFrame(bool needs_begin_frame) {
112 if (needs_begin_frame_ == needs_begin_frame) {
113 return;
114 }
115 needs_begin_frame_ = needs_begin_frame;
Bo Liubfe80a072023-02-17 20:09:15116 frame_sink_->SetNeedsBeginFrame(needs_begin_frame);
Bo Liue0e51f22023-02-02 19:33:00117}
118
119void FrameSinkImpl::UploadUIResource(cc::UIResourceId resource_id,
120 cc::UIResourceBitmap resource_bitmap) {
121 const gpu::Capabilities& caps = context_provider_->ContextCapabilities();
122 gfx::Size size = resource_bitmap.GetSize();
123 if (size.width() > caps.max_texture_size ||
124 size.height() > caps.max_texture_size) {
125 LOG(ERROR) << "Size exceeds max texture size";
126 return;
127 }
Colin Blundell836bf252023-02-15 08:33:58128 viz::SharedImageFormat format = viz::SinglePlaneFormat::kRGBA_8888;
Bo Liue0e51f22023-02-02 19:33:00129 switch (resource_bitmap.GetFormat()) {
130 case cc::UIResourceBitmap::RGBA8:
Colin Blundell836bf252023-02-15 08:33:58131 format = viz::PlatformColor::BestSupportedTextureFormat(caps);
Bo Liue0e51f22023-02-02 19:33:00132 break;
133 case cc::UIResourceBitmap::ALPHA_8:
Colin Blundell836bf252023-02-15 08:33:58134 format = viz::SinglePlaneFormat::kALPHA_8;
Bo Liue0e51f22023-02-02 19:33:00135 break;
136 case cc::UIResourceBitmap::ETC1:
Colin Blundell836bf252023-02-15 08:33:58137 format = viz::SinglePlaneFormat::kETC1;
Bo Liue0e51f22023-02-02 19:33:00138 break;
139 }
140
141 UploadedUIResource uploaded_resource;
142 auto* sii = context_provider_->SharedImageInterface();
143 constexpr gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB();
144 uint32_t shared_image_usage = gpu::SHARED_IMAGE_USAGE_DISPLAY_READ;
145 uploaded_resource.mailbox = sii->CreateSharedImage(
Colin Blundell836bf252023-02-15 08:33:58146 format, resource_bitmap.GetSize(), color_space, kTopLeft_GrSurfaceOrigin,
147 kPremul_SkAlphaType, shared_image_usage,
Bo Liue0e51f22023-02-02 19:33:00148 base::span<const uint8_t>(resource_bitmap.GetPixels(),
149 resource_bitmap.SizeInBytes()));
150 gpu::SyncToken sync_token = sii->GenUnverifiedSyncToken();
151
152 GLenum texture_target = gpu::GetBufferTextureTarget(
Colin Blundell836bf252023-02-15 08:33:58153 gfx::BufferUsage::SCANOUT, BufferFormat(format.resource_format()), caps);
Bo Liue0e51f22023-02-02 19:33:00154 uploaded_resource.viz_resource_id = resource_provider_.ImportResource(
155 viz::TransferableResource::MakeGpu(
156 uploaded_resource.mailbox, GL_LINEAR, texture_target, sync_token,
157 resource_bitmap.GetSize(), format, /*is_overlay_candidate=*/false),
158 base::BindOnce(&FrameSinkImpl::UIResourceReleased, base::Unretained(this),
159 resource_id));
160 uploaded_resource.size = resource_bitmap.GetSize();
161 uploaded_resource.is_opaque = resource_bitmap.GetOpaque();
162
163 uploaded_resources_.emplace(resource_id, uploaded_resource);
164}
165
166void FrameSinkImpl::UIResourceReleased(cc::UIResourceId ui_resource_id,
167 const gpu::SyncToken& sync_token,
168 bool is_lost) {
169 auto itr = uploaded_resources_.find(ui_resource_id);
170 DCHECK(itr != uploaded_resources_.end());
171 auto* sii = context_provider_->SharedImageInterface();
172 sii->DestroySharedImage(sync_token, itr->second.mailbox);
173 uploaded_resources_.erase(itr);
174}
175
176void FrameSinkImpl::MarkUIResourceForDeletion(cc::UIResourceId resource_id) {
177 auto itr = uploaded_resources_.find(resource_id);
178 if (itr == uploaded_resources_.end()) {
179 return;
180 }
181 resource_provider_.RemoveImportedResource(itr->second.viz_resource_id);
182}
183
Bo Liu873d13e32023-02-08 15:58:42184viz::ResourceId FrameSinkImpl::GetVizResourceId(cc::UIResourceId resource_id) {
185 auto itr = uploaded_resources_.find(resource_id);
186 if (itr == uploaded_resources_.end()) {
187 return viz::kInvalidResourceId;
188 }
189 return itr->second.viz_resource_id;
Bo Liue0e51f22023-02-02 19:33:00190}
191
192bool FrameSinkImpl::IsUIResourceOpaque(cc::UIResourceId resource_id) {
193 auto it = uploaded_resources_.find(resource_id);
194 if (it == uploaded_resources_.end()) {
195 return true;
196 }
197 return it->second.is_opaque;
198}
199
200gfx::Size FrameSinkImpl::GetUIResourceSize(cc::UIResourceId resource_id) {
201 auto it = uploaded_resources_.find(resource_id);
202 if (it == uploaded_resources_.end()) {
203 return gfx::Size();
204 }
205
206 return it->second.size;
207}
208
209void FrameSinkImpl::DidReceiveCompositorFrameAck(
210 std::vector<viz::ReturnedResource> resources) {
211 ReclaimResources(std::move(resources));
212 client_->DidReceiveCompositorFrameAck();
213}
214
215void FrameSinkImpl::OnBeginFrame(
216 const viz::BeginFrameArgs& begin_frame_args,
Jonathan Rossd3117112023-02-17 16:42:09217 const viz::FrameTimingDetailsMap& timing_details,
218 bool frame_ack,
219 std::vector<viz::ReturnedResource> resources) {
220 if (features::IsOnBeginFrameAcksEnabled()) {
221 if (frame_ack) {
222 DidReceiveCompositorFrameAck(std::move(resources));
223 } else if (!resources.empty()) {
224 ReclaimResources(std::move(resources));
225 }
226 }
227
Bo Liue0e51f22023-02-02 19:33:00228 for (const auto& pair : timing_details) {
229 client_->DidPresentCompositorFrame(pair.first, pair.second);
230 }
231
232 if (!local_surface_id_.is_valid()) {
Bo Liubfe80a072023-02-17 20:09:15233 frame_sink_->DidNotProduceFrame(
Bo Liue0e51f22023-02-02 19:33:00234 viz::BeginFrameAck(begin_frame_args, false));
235 return;
236 }
237
238 viz::CompositorFrame frame;
Bo Liu873d13e32023-02-08 15:58:42239 base::flat_set<viz::ResourceId> viz_resource_ids;
Bo Liue0e51f22023-02-02 19:33:00240 viz::HitTestRegionList hit_test_region_list;
Bo Liu873d13e32023-02-08 15:58:42241 if (!client_->BeginFrame(begin_frame_args, frame, viz_resource_ids,
Bo Liue0e51f22023-02-02 19:33:00242 hit_test_region_list)) {
Bo Liubfe80a072023-02-17 20:09:15243 frame_sink_->DidNotProduceFrame(
Bo Liue0e51f22023-02-02 19:33:00244 viz::BeginFrameAck(begin_frame_args, false));
245 return;
246 }
247
Bo Liubfe80a072023-02-17 20:09:15248 if (local_surface_id_ == last_submitted_local_surface_id_) {
249 DCHECK_EQ(last_submitted_device_scale_factor_, frame.device_scale_factor());
250 DCHECK_EQ(last_submitted_size_in_pixels_.height(),
251 frame.size_in_pixels().height());
252 DCHECK_EQ(last_submitted_size_in_pixels_.width(),
253 frame.size_in_pixels().width());
254 }
255
Bo Liu873d13e32023-02-08 15:58:42256 resource_provider_.PrepareSendToParent(std::move(viz_resource_ids).extract(),
257 &frame.resource_list,
Bo Liue0e51f22023-02-02 19:33:00258 context_provider_.get());
259
260 bool send_new_hit_test_region_list = false;
261 if (!hit_test_region_list_ ||
262 !viz::HitTestRegionList::IsEqual(*hit_test_region_list_,
263 hit_test_region_list)) {
264 send_new_hit_test_region_list = true;
265 hit_test_region_list_ = std::move(hit_test_region_list);
266 }
267
268 {
269 TRACE_EVENT0("cc", "SubmitCompositorFrame");
Bo Liubfe80a072023-02-17 20:09:15270 frame_sink_->SubmitCompositorFrame(
Bo Liue0e51f22023-02-02 19:33:00271 local_surface_id_, std::move(frame),
272 send_new_hit_test_region_list ? hit_test_region_list_ : absl::nullopt,
273 0);
274 }
275 client_->DidSubmitCompositorFrame();
276}
277
278void FrameSinkImpl::ReclaimResources(
279 std::vector<viz::ReturnedResource> resources) {
280 resource_provider_.ReceiveReturnsFromParent(std::move(resources));
281}
282
283} // namespace cc::slim