[go: nahoru, domu]

blob: a0ddfb3bad4da4ce81173341109fbbf93e5eb7b8 [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"
18#include "components/viz/common/resources/platform_color.h"
19#include "components/viz/common/resources/resource_format_utils.h"
Bo Liu873d13e32023-02-08 15:58:4220#include "components/viz/common/resources/resource_id.h"
Bo Liue0e51f22023-02-02 19:33:0021#include "gpu/command_buffer/client/shared_image_interface.h"
22#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
23#include "gpu/command_buffer/common/shared_image_usage.h"
24#include "third_party/skia/include/core/SkAlphaType.h"
25#include "third_party/skia/include/gpu/GrTypes.h"
26#include "ui/gfx/buffer_types.h"
27#include "ui/gfx/color_space.h"
28
29namespace cc::slim {
30
31FrameSinkImpl::UploadedUIResource::UploadedUIResource() = default;
32FrameSinkImpl::UploadedUIResource::~UploadedUIResource() = default;
33FrameSinkImpl::UploadedUIResource::UploadedUIResource(
34 const UploadedUIResource&) = default;
35FrameSinkImpl::UploadedUIResource& FrameSinkImpl::UploadedUIResource::operator=(
36 const UploadedUIResource&) = default;
37
38FrameSinkImpl::FrameSinkImpl(
39 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
40 mojo::PendingAssociatedRemote<viz::mojom::CompositorFrameSink>
41 compositor_frame_sink_associated_remote,
42 mojo::PendingReceiver<viz::mojom::CompositorFrameSinkClient>
43 client_receiver,
44 scoped_refptr<viz::ContextProvider> context_provider)
45 : task_runner_(std::move(task_runner)),
46 pending_compositor_frame_sink_associated_remote_(
47 std::move(compositor_frame_sink_associated_remote)),
48 pending_client_receiver_(std::move(client_receiver)),
49 context_provider_(std::move(context_provider)) {}
50
51FrameSinkImpl::~FrameSinkImpl() {
52 resource_provider_.ShutdownAndReleaseAllResources();
53}
54
55void FrameSinkImpl::SetLocalSurfaceId(
56 const viz::LocalSurfaceId& local_surface_id) {
57 if (local_surface_id_ == local_surface_id) {
58 return;
59 }
60 local_surface_id_ = local_surface_id;
61 hit_test_region_list_.reset();
62}
63
64bool FrameSinkImpl::BindToClient(FrameSinkImplClient* client) {
65 DCHECK(client);
66 if (context_provider_) {
67 context_provider_->AddObserver(this);
68 auto result = context_provider_->BindToCurrentSequence();
69 if (result != gpu::ContextResult::kSuccess) {
70 context_provider_->RemoveObserver(this);
71 context_provider_ = nullptr;
72 return false;
73 }
74 }
75
76 client_ = client;
77
78 frame_sink_remote_.Bind(
79 std::move(pending_compositor_frame_sink_associated_remote_));
80 frame_sink_remote_.set_disconnect_handler(
81 base::BindOnce(&FrameSinkImpl::OnContextLost, base::Unretained(this)));
82 client_receiver_.Bind(std::move(pending_client_receiver_), task_runner_);
83
84 frame_sink_remote_->InitializeCompositorFrameSinkType(
85 viz::mojom::CompositorFrameSinkType::kLayerTree);
86
87#if BUILDFLAG(IS_ANDROID)
88 std::vector<int32_t> thread_ids;
89 thread_ids.push_back(base::PlatformThread::CurrentId());
90 frame_sink_remote_->SetThreadIds(thread_ids);
91#endif
92 return true;
93}
94
95void FrameSinkImpl::OnContextLost() {
96 client_->DidLoseLayerTreeFrameSink();
97}
98
99void FrameSinkImpl::SetNeedsBeginFrame(bool needs_begin_frame) {
100 if (needs_begin_frame_ == needs_begin_frame) {
101 return;
102 }
103 needs_begin_frame_ = needs_begin_frame;
104 frame_sink_remote_->SetNeedsBeginFrame(needs_begin_frame);
105}
106
107void FrameSinkImpl::UploadUIResource(cc::UIResourceId resource_id,
108 cc::UIResourceBitmap resource_bitmap) {
109 const gpu::Capabilities& caps = context_provider_->ContextCapabilities();
110 gfx::Size size = resource_bitmap.GetSize();
111 if (size.width() > caps.max_texture_size ||
112 size.height() > caps.max_texture_size) {
113 LOG(ERROR) << "Size exceeds max texture size";
114 return;
115 }
116 viz::ResourceFormat format = viz::ResourceFormat::RGBA_8888;
117 switch (resource_bitmap.GetFormat()) {
118 case cc::UIResourceBitmap::RGBA8:
119 format = viz::PlatformColor::BestSupportedTextureFormat(caps);
120 break;
121 case cc::UIResourceBitmap::ALPHA_8:
122 format = viz::ALPHA_8;
123 break;
124 case cc::UIResourceBitmap::ETC1:
125 format = viz::ETC1;
126 break;
127 }
128
129 UploadedUIResource uploaded_resource;
130 auto* sii = context_provider_->SharedImageInterface();
131 constexpr gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB();
132 uint32_t shared_image_usage = gpu::SHARED_IMAGE_USAGE_DISPLAY_READ;
133 uploaded_resource.mailbox = sii->CreateSharedImage(
134 format, resource_bitmap.GetSize(), color_space, kTopLeft_GrSurfaceOrigin,
135 kPremul_SkAlphaType, shared_image_usage,
136 base::span<const uint8_t>(resource_bitmap.GetPixels(),
137 resource_bitmap.SizeInBytes()));
138 gpu::SyncToken sync_token = sii->GenUnverifiedSyncToken();
139
140 GLenum texture_target = gpu::GetBufferTextureTarget(
141 gfx::BufferUsage::SCANOUT, BufferFormat(format), caps);
142 uploaded_resource.viz_resource_id = resource_provider_.ImportResource(
143 viz::TransferableResource::MakeGpu(
144 uploaded_resource.mailbox, GL_LINEAR, texture_target, sync_token,
145 resource_bitmap.GetSize(), format, /*is_overlay_candidate=*/false),
146 base::BindOnce(&FrameSinkImpl::UIResourceReleased, base::Unretained(this),
147 resource_id));
148 uploaded_resource.size = resource_bitmap.GetSize();
149 uploaded_resource.is_opaque = resource_bitmap.GetOpaque();
150
151 uploaded_resources_.emplace(resource_id, uploaded_resource);
152}
153
154void FrameSinkImpl::UIResourceReleased(cc::UIResourceId ui_resource_id,
155 const gpu::SyncToken& sync_token,
156 bool is_lost) {
157 auto itr = uploaded_resources_.find(ui_resource_id);
158 DCHECK(itr != uploaded_resources_.end());
159 auto* sii = context_provider_->SharedImageInterface();
160 sii->DestroySharedImage(sync_token, itr->second.mailbox);
161 uploaded_resources_.erase(itr);
162}
163
164void FrameSinkImpl::MarkUIResourceForDeletion(cc::UIResourceId resource_id) {
165 auto itr = uploaded_resources_.find(resource_id);
166 if (itr == uploaded_resources_.end()) {
167 return;
168 }
169 resource_provider_.RemoveImportedResource(itr->second.viz_resource_id);
170}
171
Bo Liu873d13e32023-02-08 15:58:42172viz::ResourceId FrameSinkImpl::GetVizResourceId(cc::UIResourceId resource_id) {
173 auto itr = uploaded_resources_.find(resource_id);
174 if (itr == uploaded_resources_.end()) {
175 return viz::kInvalidResourceId;
176 }
177 return itr->second.viz_resource_id;
Bo Liue0e51f22023-02-02 19:33:00178}
179
180bool FrameSinkImpl::IsUIResourceOpaque(cc::UIResourceId resource_id) {
181 auto it = uploaded_resources_.find(resource_id);
182 if (it == uploaded_resources_.end()) {
183 return true;
184 }
185 return it->second.is_opaque;
186}
187
188gfx::Size FrameSinkImpl::GetUIResourceSize(cc::UIResourceId resource_id) {
189 auto it = uploaded_resources_.find(resource_id);
190 if (it == uploaded_resources_.end()) {
191 return gfx::Size();
192 }
193
194 return it->second.size;
195}
196
197void FrameSinkImpl::DidReceiveCompositorFrameAck(
198 std::vector<viz::ReturnedResource> resources) {
199 ReclaimResources(std::move(resources));
200 client_->DidReceiveCompositorFrameAck();
201}
202
203void FrameSinkImpl::OnBeginFrame(
204 const viz::BeginFrameArgs& begin_frame_args,
205 const viz::FrameTimingDetailsMap& timing_details) {
206 for (const auto& pair : timing_details) {
207 client_->DidPresentCompositorFrame(pair.first, pair.second);
208 }
209
210 if (!local_surface_id_.is_valid()) {
211 frame_sink_remote_->DidNotProduceFrame(
212 viz::BeginFrameAck(begin_frame_args, false));
213 return;
214 }
215
216 viz::CompositorFrame frame;
Bo Liu873d13e32023-02-08 15:58:42217 base::flat_set<viz::ResourceId> viz_resource_ids;
Bo Liue0e51f22023-02-02 19:33:00218 viz::HitTestRegionList hit_test_region_list;
Bo Liu873d13e32023-02-08 15:58:42219 if (!client_->BeginFrame(begin_frame_args, frame, viz_resource_ids,
Bo Liue0e51f22023-02-02 19:33:00220 hit_test_region_list)) {
221 frame_sink_remote_->DidNotProduceFrame(
222 viz::BeginFrameAck(begin_frame_args, false));
223 return;
224 }
225
Bo Liu873d13e32023-02-08 15:58:42226 resource_provider_.PrepareSendToParent(std::move(viz_resource_ids).extract(),
227 &frame.resource_list,
Bo Liue0e51f22023-02-02 19:33:00228 context_provider_.get());
229
230 bool send_new_hit_test_region_list = false;
231 if (!hit_test_region_list_ ||
232 !viz::HitTestRegionList::IsEqual(*hit_test_region_list_,
233 hit_test_region_list)) {
234 send_new_hit_test_region_list = true;
235 hit_test_region_list_ = std::move(hit_test_region_list);
236 }
237
238 {
239 TRACE_EVENT0("cc", "SubmitCompositorFrame");
240 frame_sink_remote_->SubmitCompositorFrame(
241 local_surface_id_, std::move(frame),
242 send_new_hit_test_region_list ? hit_test_region_list_ : absl::nullopt,
243 0);
244 }
245 client_->DidSubmitCompositorFrame();
246}
247
248void FrameSinkImpl::ReclaimResources(
249 std::vector<viz::ReturnedResource> resources) {
250 resource_provider_.ReceiveReturnsFromParent(std::move(resources));
251}
252
253} // namespace cc::slim