Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / compositor / reflector_impl.cc
blobdcc0dc2bbe675af19151a929184a1353e7e00cb9
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"
7 #include "base/bind.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"
14 namespace content {
16 struct ReflectorImpl::LayerData {
17 LayerData(ui::Layer* layer) : layer(layer) {}
19 ui::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),
26 flip_texture_(false),
27 composition_count_(0),
28 output_surface_(nullptr) {
29 if (mirroring_layer)
30 AddMirroringLayer(mirroring_layer);
33 ReflectorImpl::~ReflectorImpl() {
36 void ReflectorImpl::Shutdown() {
37 if (output_surface_)
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());
47 mailbox_ = nullptr;
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.
59 if (output_surface_)
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);
82 if (mailbox_)
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);
99 composition_count_--;
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) {
117 mailbox_ = 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();
134 return;
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();
152 return;
155 // Should be attached to the source output surface already.
156 DCHECK(mailbox_.get());
158 gfx::Size size = output_surface_->SurfaceSize();
160 int y = rect.y();
161 // Flip the coordinates to compositor's one.
162 if (flip_texture_)
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,
174 bool is_lost) {
175 mailbox->UpdateSyncPoint(sync_point);
178 ScopedVector<ReflectorImpl::LayerData>::iterator ReflectorImpl::FindLayerData(
179 ui::Layer* layer) {
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_)),
193 source_size);
194 layer_data->needs_set_mailbox = false;
195 } else {
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