OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/compositor/reflector_impl.h" | 5 #include "content/browser/compositor/reflector_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/location.h" | 8 #include "base/location.h" |
9 #include "content/browser/compositor/browser_compositor_output_surface.h" | 9 #include "content/browser/compositor/browser_compositor_output_surface.h" |
10 #include "content/browser/compositor/owned_mailbox.h" | 10 #include "content/browser/compositor/owned_mailbox.h" |
11 #include "content/common/gpu/client/gl_helper.h" | 11 #include "content/common/gpu/client/gl_helper.h" |
12 #include "ui/compositor/layer.h" | 12 #include "ui/compositor/layer.h" |
13 | 13 |
14 namespace content { | 14 namespace content { |
15 | 15 |
16 struct ReflectorImpl::LayerData { | 16 struct ReflectorImpl::LayerData { |
17 LayerData(ui::Layer* layer) : layer(layer) {} | 17 LayerData(ui::Layer* layer) : layer(layer) {} |
18 | 18 |
19 ui::Layer* layer; | 19 ui::Layer* layer; |
20 bool needs_set_mailbox = false; | 20 bool needs_set_mailbox = false; |
21 }; | 21 }; |
22 | 22 |
23 ReflectorImpl::ReflectorImpl(ui::Compositor* mirrored_compositor, | 23 ReflectorImpl::ReflectorImpl(ui::Compositor* mirrored_compositor, |
24 ui::Layer* mirroring_layer) | 24 ui::Layer* mirroring_layer) |
25 : mirrored_compositor_(mirrored_compositor), | 25 : mirrored_compositor_(mirrored_compositor), |
26 mirrored_compositor_gl_helper_texture_id_(0), | 26 mirrored_compositor_gl_helper_texture_id_(0), |
27 flip_texture_(false), | 27 flip_texture_(false), |
28 composition_count_(0), | |
28 output_surface_(nullptr) { | 29 output_surface_(nullptr) { |
29 if (mirroring_layer) | 30 if (mirroring_layer) |
30 mirroring_layers_.push_back(new LayerData(mirroring_layer)); | 31 AddMirroringLayer(mirroring_layer); |
31 } | 32 } |
32 | 33 |
33 ReflectorImpl::~ReflectorImpl() { | 34 ReflectorImpl::~ReflectorImpl() { |
34 } | 35 } |
35 | 36 |
36 void ReflectorImpl::Shutdown() { | 37 void ReflectorImpl::Shutdown() { |
37 if (output_surface_) | 38 if (output_surface_) |
38 DetachFromOutputSurface(); | 39 DetachFromOutputSurface(); |
39 // Prevent the ReflectorImpl from picking up a new output surface. | 40 // Prevent the ReflectorImpl from picking up a new output surface. |
40 mirroring_layers_.clear(); | 41 mirroring_layers_.clear(); |
41 } | 42 } |
42 | 43 |
43 void ReflectorImpl::DetachFromOutputSurface() { | 44 void ReflectorImpl::DetachFromOutputSurface() { |
44 DCHECK(output_surface_); | 45 DCHECK(output_surface_); |
45 output_surface_->SetReflector(nullptr); | 46 output_surface_->SetReflector(nullptr); |
46 DCHECK(mailbox_.get()); | 47 DCHECK(mailbox_.get()); |
47 mailbox_ = nullptr; | 48 mailbox_ = nullptr; |
48 output_surface_ = nullptr; | 49 output_surface_ = nullptr; |
49 mirrored_compositor_gl_helper_->DeleteTexture( | 50 if (mirrored_compositor_gl_helper_.get()) { |
50 mirrored_compositor_gl_helper_texture_id_); | 51 mirrored_compositor_gl_helper_->DeleteTexture( |
51 mirrored_compositor_gl_helper_texture_id_ = 0; | 52 mirrored_compositor_gl_helper_texture_id_); |
52 mirrored_compositor_gl_helper_ = nullptr; | 53 mirrored_compositor_gl_helper_texture_id_ = 0; |
54 mirrored_compositor_gl_helper_ = nullptr; | |
55 } | |
53 for (LayerData* layer_data : mirroring_layers_) | 56 for (LayerData* layer_data : mirroring_layers_) |
54 layer_data->layer->SetShowSolidColorContent(); | 57 layer_data->layer->SetShowSolidColorContent(); |
55 } | 58 } |
56 | 59 |
57 void ReflectorImpl::OnSourceSurfaceReady( | 60 void ReflectorImpl::OnSourceSurfaceReady( |
58 BrowserCompositorOutputSurface* output_surface) { | 61 BrowserCompositorOutputSurface* output_surface) { |
59 if (mirroring_layers_.empty()) | 62 if (mirroring_layers_.empty()) |
60 return; // Was already Shutdown(). | 63 return; // Was already Shutdown(). |
61 if (output_surface == output_surface_) | 64 if (output_surface == output_surface_) |
62 return; // Is already attached. | 65 return; // Is already attached. |
63 if (output_surface_) | 66 if (output_surface_) |
64 DetachFromOutputSurface(); | 67 DetachFromOutputSurface(); |
65 | 68 |
66 // Use the GLHelper from the ImageTransportFactory for our OwnedMailbox so we | 69 output_surface_ = output_surface; |
67 // don't have to manage the lifetime of the GLHelper relative to the lifetime | |
68 // of the mailbox. | |
69 GLHelper* shared_helper = ImageTransportFactory::GetInstance()->GetGLHelper(); | |
70 mailbox_ = new OwnedMailbox(shared_helper); | |
71 for (LayerData* layer_data : mirroring_layers_) | |
72 layer_data->needs_set_mailbox = true; | |
73 | 70 |
74 // Create a GLHelper attached to the mirrored compositor's output surface for | 71 composition_started_callback_ = |
75 // copying the output of the mirrored compositor. | 72 output_surface_->CreateCompositionStartedCallback(); |
76 mirrored_compositor_gl_helper_.reset( | 73 OnSourceTextureMailboxUpdated(); |
77 new GLHelper(output_surface->context_provider()->ContextGL(), | 74 // If the source output surface didn't have its own |
78 output_surface->context_provider()->ContextSupport())); | 75 // mailbox, create one for mirror mode. |
79 // Create a texture id in the name space of the new GLHelper to update the | 76 if (!mailbox_.get()) { |
80 // mailbox being held by the |mirroring_layer_|. | 77 // Use the GLHelper from the ImageTransportFactory for our OwnedMailbox |
81 mirrored_compositor_gl_helper_texture_id_ = | 78 // so we don't have to manage the lifetime of the GLHelper relative to |
82 mirrored_compositor_gl_helper_->ConsumeMailboxToTexture( | 79 // the lifetime of the mailbox. |
83 mailbox_->mailbox(), mailbox_->sync_point()); | 80 GLHelper* shared_helper = |
81 ImageTransportFactory::GetInstance()->GetGLHelper(); | |
82 mailbox_ = new OwnedMailbox(shared_helper); | |
83 | |
84 // Create a GLHelper attached to the mirrored compositor's output | |
85 // surface for copying the output of the mirrored compositor. | |
86 mirrored_compositor_gl_helper_.reset( | |
87 new GLHelper(output_surface_->context_provider()->ContextGL(), | |
88 output_surface_->context_provider()->ContextSupport())); | |
89 // Create a texture id in the name space of the new GLHelper to update the | |
90 // mailbox being held by the |mirroring_layer_|. | |
91 mirrored_compositor_gl_helper_texture_id_ = | |
92 mirrored_compositor_gl_helper_->ConsumeMailboxToTexture( | |
93 mailbox_->mailbox(), mailbox_->sync_point()); | |
94 | |
95 for (LayerData* layer_data : mirroring_layers_) | |
96 layer_data->needs_set_mailbox = true; | |
97 } | |
84 | 98 |
85 flip_texture_ = !output_surface->capabilities().flipped_output_surface; | 99 flip_texture_ = !output_surface->capabilities().flipped_output_surface; |
86 | 100 |
87 // The texture doesn't have the data. Request full redraw on mirrored | 101 // The texture doesn't have the data. Request full redraw on mirrored |
88 // compositor so that the full content will be copied to mirroring compositor. | 102 // compositor so that the full content will be copied to mirroring compositor. |
89 // This full redraw should land us in OnSourceSwapBuffers() to resize the | 103 // This full redraw should land us in OnSourceSwapBuffers() to resize the |
90 // texture appropriately. | 104 // texture appropriately. |
91 mirrored_compositor_->ScheduleFullRedraw(); | 105 mirrored_compositor_->ScheduleFullRedraw(); |
92 | 106 |
93 output_surface_ = output_surface; | |
94 output_surface_->SetReflector(this); | 107 output_surface_->SetReflector(this); |
95 } | 108 } |
96 | 109 |
97 void ReflectorImpl::OnMirroringCompositorResized() { | 110 void ReflectorImpl::OnMirroringCompositorResized() { |
98 for (LayerData* layer_data : mirroring_layers_) | 111 for (LayerData* layer_data : mirroring_layers_) |
99 layer_data->layer->SchedulePaint(layer_data->layer->bounds()); | 112 layer_data->layer->SchedulePaint(layer_data->layer->bounds()); |
100 } | 113 } |
101 | 114 |
102 void ReflectorImpl::AddMirroringLayer(ui::Layer* layer) { | 115 void ReflectorImpl::AddMirroringLayer(ui::Layer* layer) { |
103 DCHECK(mirroring_layers_.end() == FindLayerData(layer)); | 116 DCHECK(mirroring_layers_.end() == FindLayerData(layer)); |
104 LayerData* layer_data = new LayerData(layer); | 117 LayerData* layer_data = new LayerData(layer); |
105 if (mailbox_) | 118 if (mailbox_) |
106 layer_data->needs_set_mailbox = true; | 119 layer_data->needs_set_mailbox = true; |
107 mirroring_layers_.push_back(layer_data); | 120 mirroring_layers_.push_back(layer_data); |
108 mirrored_compositor_->ScheduleFullRedraw(); | 121 mirrored_compositor_->ScheduleFullRedraw(); |
122 | |
123 layer->GetCompositor()->AddObserver(this); | |
piman
2015/05/07 01:56:45
Is the layer guaranteed to be in the tree at that
oshima
2015/05/07 16:43:24
Yes, it's supposed to be in the tree. I'll add DCH
| |
109 } | 124 } |
110 | 125 |
111 void ReflectorImpl::RemoveMirroringLayer(ui::Layer* layer) { | 126 void ReflectorImpl::RemoveMirroringLayer(ui::Layer* layer) { |
112 ScopedVector<LayerData>::iterator iter = FindLayerData(layer); | 127 ScopedVector<LayerData>::iterator iter = FindLayerData(layer); |
113 DCHECK(iter != mirroring_layers_.end()); | 128 DCHECK(iter != mirroring_layers_.end()); |
114 (*iter)->layer->SetShowSolidColorContent(); | 129 (*iter)->layer->SetShowSolidColorContent(); |
115 mirroring_layers_.erase(iter); | 130 mirroring_layers_.erase(iter); |
116 | 131 |
132 layer->GetCompositor()->RemoveObserver(this); | |
133 composition_count_--; | |
134 if (composition_count_ == 0 && !composition_started_callback_.is_null()) | |
135 composition_started_callback_.Run(); | |
136 | |
117 if (mirroring_layers_.empty() && output_surface_) | 137 if (mirroring_layers_.empty() && output_surface_) |
118 DetachFromOutputSurface(); | 138 DetachFromOutputSurface(); |
119 } | 139 } |
120 | 140 |
141 void ReflectorImpl::OnCompositingStarted(ui::Compositor* compositor, | |
142 base::TimeTicks start_time) { | |
143 if (composition_count_ > 0 && | |
144 --composition_count_ == 0 && | |
145 !composition_started_callback_.is_null()) { | |
146 composition_started_callback_.Run(); | |
147 } | |
148 } | |
149 | |
150 void ReflectorImpl::OnSourceTextureMailboxUpdated() { | |
151 mailbox_ = output_surface_->GetTextureMailbox(); | |
152 for (LayerData* layer_data : mirroring_layers_) | |
153 layer_data->needs_set_mailbox = true; | |
154 } | |
155 | |
121 void ReflectorImpl::OnSourceSwapBuffers() { | 156 void ReflectorImpl::OnSourceSwapBuffers() { |
122 if (mirroring_layers_.empty()) | 157 if (mirroring_layers_.empty()) { |
158 if (!composition_started_callback_.is_null()) | |
159 composition_started_callback_.Run(); | |
123 return; | 160 return; |
161 } | |
162 | |
124 // Should be attached to the source output surface already. | 163 // Should be attached to the source output surface already. |
125 DCHECK(mailbox_.get()); | 164 DCHECK(mailbox_.get()); |
126 | 165 |
127 gfx::Size size = output_surface_->SurfaceSize(); | 166 gfx::Size size = output_surface_->SurfaceSize(); |
128 mirrored_compositor_gl_helper_->CopyTextureFullImage( | 167 if (mirrored_compositor_gl_helper_.get()) { |
129 mirrored_compositor_gl_helper_texture_id_, size); | 168 mirrored_compositor_gl_helper_->CopyTextureFullImage( |
130 // Insert a barrier to make the copy show up in the mirroring compositor's | 169 mirrored_compositor_gl_helper_texture_id_, size); |
131 // mailbox. Since the the compositor contexts and the ImageTransportFactory's | 170 // Insert a barrier to make the copy show up in the mirroring compositor's |
132 // GLHelper are all on the same GPU channel, this is sufficient instead of | 171 // mailbox. Since the the compositor contexts and the |
133 // plumbing through a sync point. | 172 // ImageTransportFactory's |
134 mirrored_compositor_gl_helper_->InsertOrderingBarrier(); | 173 // GLHelper are all on the same GPU channel, this is sufficient instead of |
174 // plumbing through a sync point. | |
175 mirrored_compositor_gl_helper_->InsertOrderingBarrier(); | |
176 } | |
135 | 177 |
136 // Request full redraw on mirroring compositor. | 178 // Request full redraw on mirroring compositor. |
137 for (LayerData* layer_data : mirroring_layers_) | 179 for (LayerData* layer_data : mirroring_layers_) |
138 UpdateTexture(layer_data, size, layer_data->layer->bounds()); | 180 UpdateTexture(layer_data, size, layer_data->layer->bounds()); |
181 composition_count_ = mirroring_layers_.size(); | |
139 } | 182 } |
140 | 183 |
141 void ReflectorImpl::OnSourcePostSubBuffer(const gfx::Rect& rect) { | 184 void ReflectorImpl::OnSourcePostSubBuffer(const gfx::Rect& rect) { |
142 if (mirroring_layers_.empty()) | 185 if (mirroring_layers_.empty()) { |
186 if (!composition_started_callback_.is_null()) | |
187 composition_started_callback_.Run(); | |
143 return; | 188 return; |
189 } | |
190 | |
144 // Should be attached to the source output surface already. | 191 // Should be attached to the source output surface already. |
145 DCHECK(mailbox_.get()); | 192 DCHECK(mailbox_.get()); |
146 | 193 |
147 gfx::Size size = output_surface_->SurfaceSize(); | 194 gfx::Size size = output_surface_->SurfaceSize(); |
148 mirrored_compositor_gl_helper_->CopyTextureSubImage( | 195 if (mirrored_compositor_gl_helper_.get()) { |
149 mirrored_compositor_gl_helper_texture_id_, rect); | 196 mirrored_compositor_gl_helper_->CopyTextureSubImage( |
150 // Insert a barrier to make the copy show up in the mirroring compositor's | 197 mirrored_compositor_gl_helper_texture_id_, rect); |
151 // mailbox. Since the the compositor contexts and the ImageTransportFactory's | 198 // Insert a barrier to make the copy show up in the mirroring compositor's |
152 // GLHelper are all on the same GPU channel, this is sufficient instead of | 199 // mailbox. Since the the compositor contexts and the |
153 // plumbing through a sync point. | 200 // ImageTransportFactory's |
154 mirrored_compositor_gl_helper_->InsertOrderingBarrier(); | 201 // GLHelper are all on the same GPU channel, this is sufficient instead of |
202 // plumbing through a sync point. | |
203 mirrored_compositor_gl_helper_->InsertOrderingBarrier(); | |
204 } | |
155 | 205 |
156 int y = rect.y(); | 206 int y = rect.y(); |
157 // Flip the coordinates to compositor's one. | 207 // Flip the coordinates to compositor's one. |
158 if (flip_texture_) | 208 if (flip_texture_) |
159 y = size.height() - rect.y() - rect.height(); | 209 y = size.height() - rect.y() - rect.height(); |
160 gfx::Rect mirroring_rect(rect.x(), y, rect.width(), rect.height()); | 210 gfx::Rect mirroring_rect(rect.x(), y, rect.width(), rect.height()); |
161 | 211 |
162 // Request redraw of the dirty portion in mirroring compositor. | 212 // Request redraw of the dirty portion in mirroring compositor. |
163 for (LayerData* layer_data : mirroring_layers_) | 213 for (LayerData* layer_data : mirroring_layers_) |
164 UpdateTexture(layer_data, size, mirroring_rect); | 214 UpdateTexture(layer_data, size, mirroring_rect); |
215 composition_count_ = mirroring_layers_.size(); | |
165 } | 216 } |
166 | 217 |
167 static void ReleaseMailbox(scoped_refptr<OwnedMailbox> mailbox, | 218 static void ReleaseMailbox(scoped_refptr<OwnedMailbox> mailbox, |
168 unsigned int sync_point, | 219 unsigned int sync_point, |
169 bool is_lost) { | 220 bool is_lost) { |
170 mailbox->UpdateSyncPoint(sync_point); | 221 mailbox->UpdateSyncPoint(sync_point); |
171 } | 222 } |
172 | 223 |
173 ScopedVector<ReflectorImpl::LayerData>::iterator ReflectorImpl::FindLayerData( | 224 ScopedVector<ReflectorImpl::LayerData>::iterator ReflectorImpl::FindLayerData( |
174 ui::Layer* layer) { | 225 ui::Layer* layer) { |
175 return std::find_if(mirroring_layers_.begin(), mirroring_layers_.end(), | 226 return std::find_if(mirroring_layers_.begin(), mirroring_layers_.end(), |
176 [layer](const LayerData* layer_data) { | 227 [layer](const LayerData* layer_data) { |
177 return layer_data->layer == layer; | 228 return layer_data->layer == layer; |
178 }); | 229 }); |
179 } | 230 } |
180 | 231 |
181 void ReflectorImpl::UpdateTexture(ReflectorImpl::LayerData* layer_data, | 232 void ReflectorImpl::UpdateTexture(ReflectorImpl::LayerData* layer_data, |
182 const gfx::Size& source_size, | 233 const gfx::Size& source_size, |
183 const gfx::Rect& redraw_rect) { | 234 const gfx::Rect& redraw_rect) { |
184 if (layer_data->needs_set_mailbox) { | 235 if (layer_data->needs_set_mailbox) { |
185 layer_data->layer->SetTextureMailbox( | 236 layer_data->layer->SetTextureMailbox( |
186 cc::TextureMailbox(mailbox_->holder()), | 237 cc::TextureMailbox(mailbox_->holder()), |
187 cc::SingleReleaseCallback::Create(base::Bind(ReleaseMailbox, mailbox_)), | 238 cc::SingleReleaseCallback::Create(base::Bind(ReleaseMailbox, mailbox_)), |
188 source_size); | 239 source_size); |
189 layer_data->needs_set_mailbox = false; | 240 layer_data->needs_set_mailbox = false; |
190 } else { | 241 } else { |
191 layer_data->layer->SetTextureSize(source_size); | 242 layer_data->layer->SetTextureSize(source_size); |
192 } | 243 } |
193 layer_data->layer->SetBounds(gfx::Rect(source_size)); | 244 layer_data->layer->SetBounds(gfx::Rect(source_size)); |
194 layer_data->layer->SetTextureFlipped(flip_texture_); | 245 layer_data->layer->SetTextureFlipped(flip_texture_); |
195 layer_data->layer->SchedulePaint(redraw_rect); | 246 layer_data->layer->SchedulePaint(redraw_rect); |
196 } | 247 } |
197 | 248 |
198 } // namespace content | 249 } // namespace content |
OLD | NEW |