1 // Copyright 2014 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.
5 #include "content/browser/compositor/reflector_impl.h"
8 #include "base/location.h"
9 #include "content/browser/compositor/browser_compositor_output_surface.h"
10 #include "content/browser/compositor/owned_mailbox.h"
11 //#include "content/common/gpu/client/gl_helper.h"
12 #include "ui/compositor/layer.h"
16 struct ReflectorImpl::LayerData
{
17 LayerData(ui::Layer
* layer
) : layer(layer
) {}
20 bool needs_set_mailbox
= false;
23 ReflectorImpl::ReflectorImpl(ui::Compositor
* mirrored_compositor
,
24 ui::Layer
* mirroring_layer
)
25 : mirrored_compositor_(mirrored_compositor
),
27 composition_count_(0),
28 output_surface_(nullptr) {
30 AddMirroringLayer(mirroring_layer
);
33 ReflectorImpl::~ReflectorImpl() {
36 void ReflectorImpl::Shutdown() {
38 DetachFromOutputSurface();
39 // Prevent the ReflectorImpl from picking up a new output surface.
40 mirroring_layers_
.clear();
43 void ReflectorImpl::DetachFromOutputSurface() {
44 DCHECK(output_surface_
);
45 output_surface_
->SetReflector(nullptr);
46 DCHECK(mailbox_
.get());
48 output_surface_
= nullptr;
49 for (LayerData
* layer_data
: mirroring_layers_
)
50 layer_data
->layer
->SetShowSolidColorContent();
53 void ReflectorImpl::OnSourceSurfaceReady(
54 BrowserCompositorOutputSurface
* output_surface
) {
55 if (mirroring_layers_
.empty())
56 return; // Was already Shutdown().
57 if (output_surface
== output_surface_
)
58 return; // Is already attached.
60 DetachFromOutputSurface();
62 output_surface_
= output_surface
;
64 composition_started_callback_
=
65 output_surface_
->CreateCompositionStartedCallback();
67 flip_texture_
= !output_surface
->capabilities().flipped_output_surface
;
69 output_surface_
->SetReflector(this);
72 void ReflectorImpl::OnMirroringCompositorResized() {
73 for (LayerData
* layer_data
: mirroring_layers_
)
74 layer_data
->layer
->SchedulePaint(layer_data
->layer
->bounds());
77 void ReflectorImpl::AddMirroringLayer(ui::Layer
* layer
) {
78 DCHECK(layer
->GetCompositor());
79 DCHECK(mirroring_layers_
.end() == FindLayerData(layer
));
81 LayerData
* layer_data
= new LayerData(layer
);
83 layer_data
->needs_set_mailbox
= true;
84 mirroring_layers_
.push_back(layer_data
);
85 mirrored_compositor_
->ScheduleFullRedraw();
87 layer
->GetCompositor()->AddObserver(this);
90 void ReflectorImpl::RemoveMirroringLayer(ui::Layer
* layer
) {
91 DCHECK(layer
->GetCompositor());
93 ScopedVector
<LayerData
>::iterator iter
= FindLayerData(layer
);
94 DCHECK(iter
!= mirroring_layers_
.end());
95 (*iter
)->layer
->SetShowSolidColorContent();
96 mirroring_layers_
.erase(iter
);
98 layer
->GetCompositor()->RemoveObserver(this);
100 if (composition_count_
== 0 && !composition_started_callback_
.is_null())
101 composition_started_callback_
.Run();
103 if (mirroring_layers_
.empty() && output_surface_
)
104 DetachFromOutputSurface();
107 void ReflectorImpl::OnCompositingStarted(ui::Compositor
* compositor
,
108 base::TimeTicks start_time
) {
109 if (composition_count_
> 0 && --composition_count_
== 0 &&
110 !composition_started_callback_
.is_null()) {
111 composition_started_callback_
.Run();
115 void ReflectorImpl::OnSourceTextureMailboxUpdated(
116 scoped_refptr
<OwnedMailbox
> mailbox
) {
118 if (mailbox_
.get()) {
119 for (LayerData
* layer_data
: mirroring_layers_
)
120 layer_data
->needs_set_mailbox
= true;
122 // The texture doesn't have the data. Request full redraw on mirrored
123 // compositor so that the full content will be copied to mirroring
124 // compositor. This full redraw should land us in OnSourceSwapBuffers() to
125 // resize the texture appropriately.
126 mirrored_compositor_
->ScheduleFullRedraw();
130 void ReflectorImpl::OnSourceSwapBuffers() {
131 if (mirroring_layers_
.empty()) {
132 if (!composition_started_callback_
.is_null())
133 composition_started_callback_
.Run();
137 // Should be attached to the source output surface already.
138 DCHECK(mailbox_
.get());
140 gfx::Size size
= output_surface_
->SurfaceSize();
142 // Request full redraw on mirroring compositor.
143 for (LayerData
* layer_data
: mirroring_layers_
)
144 UpdateTexture(layer_data
, size
, layer_data
->layer
->bounds());
145 composition_count_
= mirroring_layers_
.size();
148 void ReflectorImpl::OnSourcePostSubBuffer(const gfx::Rect
& rect
) {
149 if (mirroring_layers_
.empty()) {
150 if (!composition_started_callback_
.is_null())
151 composition_started_callback_
.Run();
155 // Should be attached to the source output surface already.
156 DCHECK(mailbox_
.get());
158 gfx::Size size
= output_surface_
->SurfaceSize();
161 // Flip the coordinates to compositor's one.
163 y
= size
.height() - rect
.y() - rect
.height();
164 gfx::Rect
mirroring_rect(rect
.x(), y
, rect
.width(), rect
.height());
166 // Request redraw of the dirty portion in mirroring compositor.
167 for (LayerData
* layer_data
: mirroring_layers_
)
168 UpdateTexture(layer_data
, size
, mirroring_rect
);
169 composition_count_
= mirroring_layers_
.size();
172 static void ReleaseMailbox(scoped_refptr
<OwnedMailbox
> mailbox
,
173 unsigned int sync_point
,
175 mailbox
->UpdateSyncPoint(sync_point
);
178 ScopedVector
<ReflectorImpl::LayerData
>::iterator
ReflectorImpl::FindLayerData(
180 return std::find_if(mirroring_layers_
.begin(), mirroring_layers_
.end(),
181 [layer
](const LayerData
* layer_data
) {
182 return layer_data
->layer
== layer
;
186 void ReflectorImpl::UpdateTexture(ReflectorImpl::LayerData
* layer_data
,
187 const gfx::Size
& source_size
,
188 const gfx::Rect
& redraw_rect
) {
189 if (layer_data
->needs_set_mailbox
) {
190 layer_data
->layer
->SetTextureMailbox(
191 cc::TextureMailbox(mailbox_
->holder()),
192 cc::SingleReleaseCallback::Create(base::Bind(ReleaseMailbox
, mailbox_
)),
194 layer_data
->needs_set_mailbox
= false;
196 layer_data
->layer
->SetTextureSize(source_size
);
198 layer_data
->layer
->SetBounds(gfx::Rect(source_size
));
199 layer_data
->layer
->SetTextureFlipped(flip_texture_
);
200 layer_data
->layer
->SchedulePaint(redraw_rect
);
203 } // namespace content