[go: nahoru, domu]

blob: da0d50b04755805961f9c7146159663dcc23ec00 [file] [log] [blame]
khushalsagara693aa72016-08-16 22:18:061// Copyright 2016 The Chromium Authors. All rights reserved.
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 "ui/android/delegated_frame_host_android.h"
6
xlai180af792016-08-26 22:07:427#include "base/bind.h"
khushalsagara693aa72016-08-16 22:18:068#include "base/logging.h"
9#include "cc/layers/solid_color_layer.h"
10#include "cc/layers/surface_layer.h"
11#include "cc/output/compositor_frame.h"
12#include "cc/output/copy_output_result.h"
13#include "cc/surfaces/surface.h"
14#include "cc/surfaces/surface_id.h"
15#include "cc/surfaces/surface_id_allocator.h"
16#include "cc/surfaces/surface_manager.h"
17#include "ui/android/context_provider_factory.h"
18#include "ui/android/view_android.h"
19#include "ui/android/window_android_compositor.h"
20#include "ui/gfx/android/device_display_info.h"
21#include "ui/gfx/geometry/dip_util.h"
22
23namespace ui {
24
25namespace {
26
27void SatisfyCallback(cc::SurfaceManager* manager,
28 const cc::SurfaceSequence& sequence) {
29 std::vector<uint32_t> sequences;
30 sequences.push_back(sequence.sequence);
fsamuele0f705b2016-10-01 14:07:1431 manager->DidSatisfySequences(sequence.frame_sink_id, &sequences);
khushalsagara693aa72016-08-16 22:18:0632}
33
34void RequireCallback(cc::SurfaceManager* manager,
35 const cc::SurfaceId& id,
36 const cc::SurfaceSequence& sequence) {
37 cc::Surface* surface = manager->GetSurfaceForId(id);
38 if (!surface) {
39 LOG(ERROR) << "Attempting to require callback on nonexistent surface";
40 return;
41 }
42 surface->AddDestructionDependency(sequence);
43}
44
45scoped_refptr<cc::SurfaceLayer> CreateSurfaceLayer(
46 cc::SurfaceManager* surface_manager,
47 cc::SurfaceId surface_id,
jbauman862bef92016-09-08 00:32:4748 const gfx::Size surface_size,
49 bool surface_opaque) {
khushalsagara693aa72016-08-16 22:18:0650 // manager must outlive compositors using it.
51 scoped_refptr<cc::SurfaceLayer> layer = cc::SurfaceLayer::Create(
52 base::Bind(&SatisfyCallback, base::Unretained(surface_manager)),
53 base::Bind(&RequireCallback, base::Unretained(surface_manager)));
54 layer->SetSurfaceId(surface_id, 1.f, surface_size);
55 layer->SetBounds(surface_size);
56 layer->SetIsDrawable(true);
jbauman862bef92016-09-08 00:32:4757 layer->SetContentsOpaque(surface_opaque);
khushalsagara693aa72016-08-16 22:18:0658
59 return layer;
60}
61
62void CopyOutputRequestCallback(
63 scoped_refptr<cc::Layer> readback_layer,
64 cc::CopyOutputRequest::CopyOutputRequestCallback result_callback,
65 std::unique_ptr<cc::CopyOutputResult> copy_output_result) {
66 readback_layer->RemoveFromParent();
67 result_callback.Run(std::move(copy_output_result));
68}
69
70} // namespace
71
72DelegatedFrameHostAndroid::DelegatedFrameHostAndroid(
73 ui::ViewAndroid* view,
74 SkColor background_color,
75 ReturnResourcesCallback return_resources_callback)
fsamuelb6acafa2016-10-04 03:21:5276 : frame_sink_id_(
77 ui::ContextProviderFactory::GetInstance()->AllocateFrameSinkId()),
78 view_(view),
khushalsagara693aa72016-08-16 22:18:0679 return_resources_callback_(return_resources_callback),
80 background_layer_(cc::SolidColorLayer::Create()) {
81 DCHECK(view_);
82 DCHECK(!return_resources_callback_.is_null());
83
84 surface_manager_ =
85 ui::ContextProviderFactory::GetInstance()->GetSurfaceManager();
fsamuel01f36202016-10-06 01:08:2886 surface_id_allocator_.reset(new cc::SurfaceIdAllocator());
fsamuelb6acafa2016-10-04 03:21:5287 surface_manager_->RegisterFrameSinkId(frame_sink_id_);
pimand6da33fd2016-11-08 18:35:3588 surface_factory_ = base::WrapUnique(
89 new cc::SurfaceFactory(frame_sink_id_, surface_manager_, this));
khushalsagara693aa72016-08-16 22:18:0690
91 background_layer_->SetBackgroundColor(background_color);
92 view_->GetLayer()->AddChild(background_layer_);
93 UpdateBackgroundLayer();
94}
95
96DelegatedFrameHostAndroid::~DelegatedFrameHostAndroid() {
97 DestroyDelegatedContent();
98 surface_factory_.reset();
fsamuele0f705b2016-10-01 14:07:1499 UnregisterFrameSinkHierarchy();
fsamuelb6acafa2016-10-04 03:21:52100 surface_manager_->InvalidateFrameSinkId(frame_sink_id_);
khushalsagara693aa72016-08-16 22:18:06101 background_layer_->RemoveFromParent();
102}
103
104DelegatedFrameHostAndroid::FrameData::FrameData() = default;
105
106DelegatedFrameHostAndroid::FrameData::~FrameData() = default;
107
108void DelegatedFrameHostAndroid::SubmitCompositorFrame(
109 cc::CompositorFrame frame,
110 cc::SurfaceFactory::DrawCallback draw_callback) {
samans4ba3a0e2016-10-29 02:27:45111 cc::RenderPass* root_pass = frame.render_pass_list.back().get();
khushalsagara693aa72016-08-16 22:18:06112 gfx::Size surface_size = root_pass->output_rect.size();
113
114 if (!current_frame_ || surface_size != current_frame_->surface_size ||
ianwene5fc5782016-08-18 04:05:15115 current_frame_->top_controls_height !=
116 frame.metadata.top_controls_height ||
117 current_frame_->top_controls_shown_ratio !=
118 frame.metadata.top_controls_shown_ratio ||
119 current_frame_->bottom_controls_height !=
120 frame.metadata.bottom_controls_height ||
121 current_frame_->bottom_controls_shown_ratio !=
122 frame.metadata.bottom_controls_shown_ratio ||
jbauman862bef92016-09-08 00:32:47123 current_frame_->viewport_selection != frame.metadata.selection ||
124 current_frame_->has_transparent_background !=
125 root_pass->has_transparent_background) {
khushalsagara693aa72016-08-16 22:18:06126 DestroyDelegatedContent();
127 DCHECK(!content_layer_);
128 DCHECK(!current_frame_);
129
130 current_frame_ = base::MakeUnique<FrameData>();
fsamuel01f36202016-10-06 01:08:28131 current_frame_->local_frame_id = surface_id_allocator_->GenerateId();
132 surface_factory_->Create(current_frame_->local_frame_id);
khushalsagara693aa72016-08-16 22:18:06133
134 current_frame_->surface_size = surface_size;
ianwene5fc5782016-08-18 04:05:15135 current_frame_->top_controls_height = frame.metadata.top_controls_height;
136 current_frame_->top_controls_shown_ratio =
137 frame.metadata.top_controls_shown_ratio;
138 current_frame_->bottom_controls_height =
139 frame.metadata.bottom_controls_height;
140 current_frame_->bottom_controls_shown_ratio =
141 frame.metadata.bottom_controls_shown_ratio;
jbauman862bef92016-09-08 00:32:47142 current_frame_->has_transparent_background =
143 root_pass->has_transparent_background;
ianwene5fc5782016-08-18 04:05:15144
khushalsagara693aa72016-08-16 22:18:06145 current_frame_->viewport_selection = frame.metadata.selection;
fsamuel01f36202016-10-06 01:08:28146 content_layer_ = CreateSurfaceLayer(
147 surface_manager_, cc::SurfaceId(surface_factory_->frame_sink_id(),
148 current_frame_->local_frame_id),
149 current_frame_->surface_size,
150 !current_frame_->has_transparent_background);
khushalsagara693aa72016-08-16 22:18:06151 view_->GetLayer()->AddChild(content_layer_);
152 UpdateBackgroundLayer();
153 }
154
fsamuel01f36202016-10-06 01:08:28155 surface_factory_->SubmitCompositorFrame(current_frame_->local_frame_id,
khushalsagara693aa72016-08-16 22:18:06156 std::move(frame), draw_callback);
157}
158
fsamuele0f705b2016-10-01 14:07:14159cc::FrameSinkId DelegatedFrameHostAndroid::GetFrameSinkId() const {
fsamuelb6acafa2016-10-04 03:21:52160 return frame_sink_id_;
khushalsagara693aa72016-08-16 22:18:06161}
162
163void DelegatedFrameHostAndroid::RequestCopyOfSurface(
164 WindowAndroidCompositor* compositor,
165 const gfx::Rect& src_subrect_in_pixel,
166 cc::CopyOutputRequest::CopyOutputRequestCallback result_callback) {
167 DCHECK(current_frame_);
168 DCHECK(!result_callback.is_null());
169
fsamuel01f36202016-10-06 01:08:28170 scoped_refptr<cc::Layer> readback_layer = CreateSurfaceLayer(
171 surface_manager_, cc::SurfaceId(surface_factory_->frame_sink_id(),
172 current_frame_->local_frame_id),
173 current_frame_->surface_size,
174 !current_frame_->has_transparent_background);
khushalsagara693aa72016-08-16 22:18:06175 readback_layer->SetHideLayerAndSubtree(true);
176 compositor->AttachLayerForReadback(readback_layer);
177 std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
178 cc::CopyOutputRequest::CreateRequest(base::Bind(
179 &CopyOutputRequestCallback, readback_layer, result_callback));
180
181 if (!src_subrect_in_pixel.IsEmpty())
182 copy_output_request->set_area(src_subrect_in_pixel);
183
sievers700fe262016-08-26 00:54:42184 readback_layer->RequestCopyOfOutput(std::move(copy_output_request));
khushalsagara693aa72016-08-16 22:18:06185}
186
187void DelegatedFrameHostAndroid::DestroyDelegatedContent() {
188 if (!current_frame_)
189 return;
190
khushalsagara693aa72016-08-16 22:18:06191 DCHECK(content_layer_);
192
193 content_layer_->RemoveFromParent();
194 content_layer_ = nullptr;
fsamuel01f36202016-10-06 01:08:28195 surface_factory_->Destroy(current_frame_->local_frame_id);
khushalsagara693aa72016-08-16 22:18:06196 current_frame_.reset();
197
198 UpdateBackgroundLayer();
199}
200
201bool DelegatedFrameHostAndroid::HasDelegatedContent() const {
202 return current_frame_.get() != nullptr;
203}
204
danakj1120f4c2016-09-15 02:05:32205void DelegatedFrameHostAndroid::CompositorFrameSinkChanged() {
khushalsagara693aa72016-08-16 22:18:06206 DestroyDelegatedContent();
pimand6da33fd2016-11-08 18:35:35207 surface_factory_->Reset();
khushalsagara693aa72016-08-16 22:18:06208}
209
210void DelegatedFrameHostAndroid::UpdateBackgroundColor(SkColor color) {
211 background_layer_->SetBackgroundColor(color);
khushalsagara693aa72016-08-16 22:18:06212}
213
214void DelegatedFrameHostAndroid::UpdateContainerSizeinDIP(
215 const gfx::Size& size_in_dip) {
216 container_size_in_dip_ = size_in_dip;
217 background_layer_->SetBounds(gfx::ConvertSizeToPixel(
218 gfx::DeviceDisplayInfo().GetDIPScale(), container_size_in_dip_));
219 UpdateBackgroundLayer();
220}
221
fsamuele0f705b2016-10-01 14:07:14222void DelegatedFrameHostAndroid::RegisterFrameSinkHierarchy(
223 const cc::FrameSinkId& parent_id) {
starazf907282a2016-11-09 21:06:58224 if (registered_parent_frame_sink_id_.is_valid())
fsamuele0f705b2016-10-01 14:07:14225 UnregisterFrameSinkHierarchy();
226 registered_parent_frame_sink_id_ = parent_id;
fsamuelb6acafa2016-10-04 03:21:52227 surface_manager_->RegisterSurfaceFactoryClient(frame_sink_id_, this);
228 surface_manager_->RegisterFrameSinkHierarchy(parent_id, frame_sink_id_);
ennea487a272016-09-30 19:56:18229}
230
fsamuele0f705b2016-10-01 14:07:14231void DelegatedFrameHostAndroid::UnregisterFrameSinkHierarchy() {
starazf907282a2016-11-09 21:06:58232 if (!registered_parent_frame_sink_id_.is_valid())
ennea487a272016-09-30 19:56:18233 return;
fsamuelb6acafa2016-10-04 03:21:52234 surface_manager_->UnregisterSurfaceFactoryClient(frame_sink_id_);
fsamuele0f705b2016-10-01 14:07:14235 surface_manager_->UnregisterFrameSinkHierarchy(
fsamuelb6acafa2016-10-04 03:21:52236 registered_parent_frame_sink_id_, frame_sink_id_);
fsamuele0f705b2016-10-01 14:07:14237 registered_parent_frame_sink_id_ = cc::FrameSinkId();
ennea487a272016-09-30 19:56:18238}
239
khushalsagara693aa72016-08-16 22:18:06240void DelegatedFrameHostAndroid::ReturnResources(
241 const cc::ReturnedResourceArray& resources) {
242 return_resources_callback_.Run(resources);
243}
244
245void DelegatedFrameHostAndroid::SetBeginFrameSource(
246 cc::BeginFrameSource* begin_frame_source) {
ennea487a272016-09-30 19:56:18247 // TODO(enne): hook this up instead of making RWHVAndroid a
248 // WindowAndroidObserver.
khushalsagara693aa72016-08-16 22:18:06249}
250
251void DelegatedFrameHostAndroid::UpdateBackgroundLayer() {
252 // The background layer draws in 2 cases:
253 // 1) When we don't have any content from the renderer.
254 // 2) When the bounds of the content received from the renderer does not match
255 // the desired content bounds.
256 bool background_is_drawable = false;
257
258 if (current_frame_) {
259 float device_scale_factor = gfx::DeviceDisplayInfo().GetDIPScale();
260 gfx::Size content_size_in_dip = gfx::ConvertSizeToDIP(
261 device_scale_factor, current_frame_->surface_size);
khushalsagara693aa72016-08-16 22:18:06262 background_is_drawable =
263 content_size_in_dip.width() < container_size_in_dip_.width() ||
264 content_size_in_dip.height() < container_size_in_dip_.height();
265 } else {
266 background_is_drawable = true;
267 }
268
269 background_layer_->SetIsDrawable(background_is_drawable);
270}
271
272} // namespace ui