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