1 // 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 "third_party/blink/renderer/platform/graphics/surface_layer_bridge.h"
6
7 #include <utility>
8
9 #include "base/feature_list.h"
10 #include "cc/layers/layer.h"
11 #include "cc/layers/solid_color_layer.h"
12 #include "cc/layers/surface_layer.h"
13 #include "components/viz/common/surfaces/surface_id.h"
14 #include "components/viz/common/surfaces/surface_info.h"
15 #include "media/base/media_switches.h"
16 #include "mojo/public/cpp/bindings/remote.h"
17 #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
18 #include "third_party/blink/public/mojom/frame_sinks/embedded_frame_sink.mojom-blink.h"
19 #include "third_party/blink/public/platform/platform.h"
20 #include "third_party/blink/renderer/platform/mojo/mojo_helper.h"
21 #include "third_party/blink/renderer/platform/wtf/functional.h"
22 #include "ui/gfx/geometry/size.h"
23
24 namespace blink {
25
SurfaceLayerBridge(viz::FrameSinkId parent_frame_sink_id,ContainsVideo contains_video,WebSurfaceLayerBridgeObserver * observer,cc::UpdateSubmissionStateCB update_submission_state_callback)26 SurfaceLayerBridge::SurfaceLayerBridge(
27 viz::FrameSinkId parent_frame_sink_id,
28 ContainsVideo contains_video,
29 WebSurfaceLayerBridgeObserver* observer,
30 cc::UpdateSubmissionStateCB update_submission_state_callback)
31 : observer_(observer),
32 update_submission_state_callback_(
33 std::move(update_submission_state_callback)),
34 frame_sink_id_(Platform::Current()->GenerateFrameSinkId()),
35 contains_video_(contains_video),
36 parent_frame_sink_id_(parent_frame_sink_id) {
37 mojo::Remote<mojom::blink::EmbeddedFrameSinkProvider> provider;
38 Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
39 provider.BindNewPipeAndPassReceiver());
40 // TODO(xlai): Ensure OffscreenCanvas commit() is still functional when a
41 // frame-less HTML canvas's document is reparenting under another frame.
42 // See crbug.com/683172.
43 provider->RegisterEmbeddedFrameSink(parent_frame_sink_id_, frame_sink_id_,
44 receiver_.BindNewPipeAndPassRemote());
45 }
46
47 SurfaceLayerBridge::~SurfaceLayerBridge() = default;
48
CreateSolidColorLayer()49 void SurfaceLayerBridge::CreateSolidColorLayer() {
50 // TODO(lethalantidote): Remove this logic. It should be covered by setting
51 // the layer's opacity to false.
52 solid_color_layer_ = cc::SolidColorLayer::Create();
53 solid_color_layer_->SetBackgroundColor(SK_ColorTRANSPARENT);
54 if (observer_)
55 observer_->RegisterContentsLayer(solid_color_layer_.get());
56 }
57
SetLocalSurfaceId(const viz::LocalSurfaceId & local_surface_id)58 void SurfaceLayerBridge::SetLocalSurfaceId(
59 const viz::LocalSurfaceId& local_surface_id) {
60 EmbedSurface(viz::SurfaceId(frame_sink_id_, local_surface_id));
61 }
62
EmbedSurface(const viz::SurfaceId & surface_id)63 void SurfaceLayerBridge::EmbedSurface(const viz::SurfaceId& surface_id) {
64 surface_activated_ = true;
65 if (solid_color_layer_) {
66 if (observer_)
67 observer_->UnregisterContentsLayer(solid_color_layer_.get());
68 solid_color_layer_->RemoveFromParent();
69 solid_color_layer_ = nullptr;
70 }
71 if (!surface_layer_) {
72 // This covers non-video cases, where we don't create the SurfaceLayer
73 // early.
74 // TODO(lethalantidote): Eliminate this case. Once you do that, you can
75 // also just store the surface_id and not the frame_sink_id.
76 CreateSurfaceLayer();
77 }
78
79 current_surface_id_ = surface_id;
80
81 surface_layer_->SetSurfaceId(surface_id,
82 cc::DeadlinePolicy::UseSpecifiedDeadline(0u));
83
84 if (observer_) {
85 observer_->OnWebLayerUpdated();
86 observer_->OnSurfaceIdUpdated(surface_id);
87 }
88
89 surface_layer_->SetContentsOpaque(opaque_);
90 }
91
BindSurfaceEmbedder(mojo::PendingReceiver<mojom::blink::SurfaceEmbedder> receiver)92 void SurfaceLayerBridge::BindSurfaceEmbedder(
93 mojo::PendingReceiver<mojom::blink::SurfaceEmbedder> receiver) {
94 surface_embedder_receiver_.Bind(std::move(receiver));
95 }
96
GetCcLayer() const97 cc::Layer* SurfaceLayerBridge::GetCcLayer() const {
98 if (surface_layer_)
99 return surface_layer_.get();
100
101 return solid_color_layer_.get();
102 }
103
GetFrameSinkId() const104 const viz::FrameSinkId& SurfaceLayerBridge::GetFrameSinkId() const {
105 return frame_sink_id_;
106 }
107
ClearObserver()108 void SurfaceLayerBridge::ClearObserver() {
109 observer_ = nullptr;
110 }
111
SetContentsOpaque(bool opaque)112 void SurfaceLayerBridge::SetContentsOpaque(bool opaque) {
113 // If the surface isn't activated, we have nothing to show, do not change
114 // opacity (defaults to false on surface_layer creation).
115 if (surface_layer_ && surface_activated_)
116 surface_layer_->SetContentsOpaque(opaque);
117 opaque_ = opaque;
118 }
119
CreateSurfaceLayer()120 void SurfaceLayerBridge::CreateSurfaceLayer() {
121 surface_layer_ = cc::SurfaceLayer::Create(update_submission_state_callback_);
122
123 // This surface_id is essentially just a placeholder for the real one we will
124 // get in OnFirstSurfaceActivation. We need it so that we properly get a
125 // WillDraw, which then pushes the first compositor frame.
126 parent_local_surface_id_allocator_.GenerateId();
127 current_surface_id_ = viz::SurfaceId(
128 frame_sink_id_,
129 parent_local_surface_id_allocator_.GetCurrentLocalSurfaceId());
130
131 surface_layer_->SetSurfaceId(current_surface_id_,
132 cc::DeadlinePolicy::UseDefaultDeadline());
133
134 surface_layer_->SetStretchContentToFillBounds(true);
135 surface_layer_->SetIsDrawable(true);
136 surface_layer_->SetHitTestable(true);
137 surface_layer_->SetMayContainVideo(contains_video_ == ContainsVideo::kYes);
138
139 if (observer_) {
140 observer_->RegisterContentsLayer(surface_layer_.get());
141 }
142 // We ignore our opacity until we are sure that we have something to show,
143 // as indicated by getting an OnFirstSurfaceActivation call.
144 surface_layer_->SetContentsOpaque(false);
145 }
146
147 } // namespace blink
148