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 { | |
17 LayerData(ui::Layer* layer) : layer(layer) {} | |
18 | |
19 ui::Layer* layer; | |
20 bool needs_set_mailbox = false; | |
21 }; | |
22 | |
16 ReflectorImpl::ReflectorImpl(ui::Compositor* mirrored_compositor, | 23 ReflectorImpl::ReflectorImpl(ui::Compositor* mirrored_compositor, |
17 ui::Layer* mirroring_layer) | 24 ui::Layer* mirroring_layer) |
18 : mirrored_compositor_(mirrored_compositor), | 25 : mirrored_compositor_(mirrored_compositor), |
19 mirroring_layer_(mirroring_layer), | |
20 mirrored_compositor_gl_helper_texture_id_(0), | 26 mirrored_compositor_gl_helper_texture_id_(0), |
21 needs_set_mailbox_(false), | |
22 flip_texture_(false), | 27 flip_texture_(false), |
23 output_surface_(nullptr) { | 28 output_surface_(nullptr) { |
29 if (mirroring_layer) | |
30 mirroring_layers_.push_back(new LayerData(mirroring_layer)); | |
24 } | 31 } |
25 | 32 |
26 ReflectorImpl::~ReflectorImpl() { | 33 ReflectorImpl::~ReflectorImpl() { |
27 } | 34 } |
28 | 35 |
29 void ReflectorImpl::Shutdown() { | 36 void ReflectorImpl::Shutdown() { |
30 if (output_surface_) | 37 if (output_surface_) |
31 DetachFromOutputSurface(); | 38 DetachFromOutputSurface(); |
32 // Prevent the ReflectorImpl from picking up a new output surface. | 39 // Prevent the ReflectorImpl from picking up a new output surface. |
33 mirroring_layer_ = nullptr; | 40 mirroring_layers_.clear(); |
34 } | 41 } |
35 | 42 |
36 void ReflectorImpl::DetachFromOutputSurface() { | 43 void ReflectorImpl::DetachFromOutputSurface() { |
37 DCHECK(output_surface_); | 44 DCHECK(output_surface_); |
38 output_surface_->SetReflector(nullptr); | 45 output_surface_->SetReflector(nullptr); |
39 DCHECK(mailbox_.get()); | 46 DCHECK(mailbox_.get()); |
40 mailbox_ = nullptr; | 47 mailbox_ = nullptr; |
41 output_surface_ = nullptr; | 48 output_surface_ = nullptr; |
42 mirrored_compositor_gl_helper_->DeleteTexture( | 49 mirrored_compositor_gl_helper_->DeleteTexture( |
43 mirrored_compositor_gl_helper_texture_id_); | 50 mirrored_compositor_gl_helper_texture_id_); |
44 mirrored_compositor_gl_helper_texture_id_ = 0; | 51 mirrored_compositor_gl_helper_texture_id_ = 0; |
45 mirrored_compositor_gl_helper_ = nullptr; | 52 mirrored_compositor_gl_helper_ = nullptr; |
46 mirroring_layer_->SetShowSolidColorContent(); | 53 for (LayerData* layer_data : mirroring_layers_) |
54 layer_data->layer->SetShowSolidColorContent(); | |
47 } | 55 } |
48 | 56 |
49 void ReflectorImpl::OnSourceSurfaceReady( | 57 void ReflectorImpl::OnSourceSurfaceReady( |
50 BrowserCompositorOutputSurface* output_surface) { | 58 BrowserCompositorOutputSurface* output_surface) { |
51 if (!mirroring_layer_) | 59 if (mirroring_layers_.empty()) |
52 return; // Was already Shutdown(). | 60 return; // Was already Shutdown(). |
53 if (output_surface == output_surface_) | 61 if (output_surface == output_surface_) |
54 return; // Is already attached. | 62 return; // Is already attached. |
55 if (output_surface_) | 63 if (output_surface_) |
56 DetachFromOutputSurface(); | 64 DetachFromOutputSurface(); |
57 | 65 |
58 // Use the GLHelper from the ImageTransportFactory for our OwnedMailbox so we | 66 // Use the GLHelper from the ImageTransportFactory for our OwnedMailbox so we |
59 // don't have to manage the lifetime of the GLHelper relative to the lifetime | 67 // don't have to manage the lifetime of the GLHelper relative to the lifetime |
60 // of the mailbox. | 68 // of the mailbox. |
61 GLHelper* shared_helper = ImageTransportFactory::GetInstance()->GetGLHelper(); | 69 GLHelper* shared_helper = ImageTransportFactory::GetInstance()->GetGLHelper(); |
62 mailbox_ = new OwnedMailbox(shared_helper); | 70 mailbox_ = new OwnedMailbox(shared_helper); |
63 needs_set_mailbox_ = true; | 71 for (LayerData* layer_data : mirroring_layers_) |
72 layer_data->needs_set_mailbox = true; | |
64 | 73 |
65 // Create a GLHelper attached to the mirrored compositor's output surface for | 74 // Create a GLHelper attached to the mirrored compositor's output surface for |
66 // copying the output of the mirrored compositor. | 75 // copying the output of the mirrored compositor. |
67 mirrored_compositor_gl_helper_.reset( | 76 mirrored_compositor_gl_helper_.reset( |
68 new GLHelper(output_surface->context_provider()->ContextGL(), | 77 new GLHelper(output_surface->context_provider()->ContextGL(), |
69 output_surface->context_provider()->ContextSupport())); | 78 output_surface->context_provider()->ContextSupport())); |
70 // Create a texture id in the name space of the new GLHelper to update the | 79 // Create a texture id in the name space of the new GLHelper to update the |
71 // mailbox being held by the |mirroring_layer_|. | 80 // mailbox being held by the |mirroring_layer_|. |
72 mirrored_compositor_gl_helper_texture_id_ = | 81 mirrored_compositor_gl_helper_texture_id_ = |
73 mirrored_compositor_gl_helper_->ConsumeMailboxToTexture( | 82 mirrored_compositor_gl_helper_->ConsumeMailboxToTexture( |
74 mailbox_->mailbox(), mailbox_->sync_point()); | 83 mailbox_->mailbox(), mailbox_->sync_point()); |
75 | 84 |
76 flip_texture_ = !output_surface->capabilities().flipped_output_surface; | 85 flip_texture_ = !output_surface->capabilities().flipped_output_surface; |
77 | 86 |
78 // The texture doesn't have the data. Request full redraw on mirrored | 87 // The texture doesn't have the data. Request full redraw on mirrored |
79 // compositor so that the full content will be copied to mirroring compositor. | 88 // compositor so that the full content will be copied to mirroring compositor. |
80 // This full redraw should land us in OnSourceSwapBuffers() to resize the | 89 // This full redraw should land us in OnSourceSwapBuffers() to resize the |
81 // texture appropriately. | 90 // texture appropriately. |
82 mirrored_compositor_->ScheduleFullRedraw(); | 91 mirrored_compositor_->ScheduleFullRedraw(); |
83 | 92 |
84 output_surface_ = output_surface; | 93 output_surface_ = output_surface; |
85 output_surface_->SetReflector(this); | 94 output_surface_->SetReflector(this); |
86 } | 95 } |
87 | 96 |
88 void ReflectorImpl::OnMirroringCompositorResized() { | 97 void ReflectorImpl::OnMirroringCompositorResized() { |
89 mirroring_layer_->SchedulePaint(mirroring_layer_->bounds()); | 98 for (LayerData* layer_data : mirroring_layers_) |
99 layer_data->layer->SchedulePaint(layer_data->layer->bounds()); | |
100 } | |
101 | |
102 void ReflectorImpl::AddMirroringLayer(ui::Layer* layer) { | |
103 DCHECK(mirroring_layers_.end() == FindLayerData(layer)); | |
104 LayerData* layer_data = new LayerData(layer); | |
105 if (mailbox_) | |
106 layer_data->needs_set_mailbox = true; | |
107 mirroring_layers_.push_back(layer_data); | |
108 mirrored_compositor_->ScheduleFullRedraw(); | |
109 } | |
110 | |
111 void ReflectorImpl::RemoveMirroringLayer(ui::Layer* layer) { | |
112 ScopedVector<LayerData>::iterator iter = FindLayerData(layer); | |
113 DCHECK(iter != mirroring_layers_.end()); | |
114 (*iter)->layer->SetShowSolidColorContent(); | |
115 mirroring_layers_.erase(iter); | |
116 | |
117 if (mirroring_layers_.empty() && output_surface_) | |
118 DetachFromOutputSurface(); | |
90 } | 119 } |
91 | 120 |
92 void ReflectorImpl::OnSourceSwapBuffers() { | 121 void ReflectorImpl::OnSourceSwapBuffers() { |
93 if (!mirroring_layer_) | 122 if (mirroring_layers_.empty()) |
94 return; | 123 return; |
95 // Should be attached to the source output surface already. | 124 // Should be attached to the source output surface already. |
96 DCHECK(mailbox_.get()); | 125 DCHECK(mailbox_.get()); |
97 | 126 |
98 gfx::Size size = output_surface_->SurfaceSize(); | 127 gfx::Size size = output_surface_->SurfaceSize(); |
99 mirrored_compositor_gl_helper_->CopyTextureFullImage( | 128 mirrored_compositor_gl_helper_->CopyTextureFullImage( |
100 mirrored_compositor_gl_helper_texture_id_, size); | 129 mirrored_compositor_gl_helper_texture_id_, size); |
101 // Insert a barrier to make the copy show up in the mirroring compositor's | 130 // Insert a barrier to make the copy show up in the mirroring compositor's |
102 // mailbox. Since the the compositor contexts and the ImageTransportFactory's | 131 // mailbox. Since the the compositor contexts and the ImageTransportFactory's |
103 // GLHelper are all on the same GPU channel, this is sufficient instead of | 132 // GLHelper are all on the same GPU channel, this is sufficient instead of |
104 // plumbing through a sync point. | 133 // plumbing through a sync point. |
105 mirrored_compositor_gl_helper_->InsertOrderingBarrier(); | 134 mirrored_compositor_gl_helper_->InsertOrderingBarrier(); |
106 | 135 |
107 // Request full redraw on mirroring compositor. | 136 // Request full redraw on mirroring compositor. |
108 UpdateTexture(size, mirroring_layer_->bounds()); | 137 for (LayerData* layer_data : mirroring_layers_) |
138 UpdateTexture(layer_data, size, layer_data->layer->bounds()); | |
109 } | 139 } |
110 | 140 |
111 void ReflectorImpl::OnSourcePostSubBuffer(const gfx::Rect& rect) { | 141 void ReflectorImpl::OnSourcePostSubBuffer(const gfx::Rect& rect) { |
112 if (!mirroring_layer_) | 142 if (mirroring_layers_.empty()) |
113 return; | 143 return; |
114 // Should be attached to the source output surface already. | 144 // Should be attached to the source output surface already. |
115 DCHECK(mailbox_.get()); | 145 DCHECK(mailbox_.get()); |
116 | 146 |
117 gfx::Size size = output_surface_->SurfaceSize(); | 147 gfx::Size size = output_surface_->SurfaceSize(); |
118 mirrored_compositor_gl_helper_->CopyTextureSubImage( | 148 mirrored_compositor_gl_helper_->CopyTextureSubImage( |
119 mirrored_compositor_gl_helper_texture_id_, rect); | 149 mirrored_compositor_gl_helper_texture_id_, rect); |
120 // Insert a barrier to make the copy show up in the mirroring compositor's | 150 // Insert a barrier to make the copy show up in the mirroring compositor's |
121 // mailbox. Since the the compositor contexts and the ImageTransportFactory's | 151 // mailbox. Since the the compositor contexts and the ImageTransportFactory's |
122 // GLHelper are all on the same GPU channel, this is sufficient instead of | 152 // GLHelper are all on the same GPU channel, this is sufficient instead of |
123 // plumbing through a sync point. | 153 // plumbing through a sync point. |
124 mirrored_compositor_gl_helper_->InsertOrderingBarrier(); | 154 mirrored_compositor_gl_helper_->InsertOrderingBarrier(); |
125 | 155 |
126 int y = rect.y(); | 156 int y = rect.y(); |
127 // Flip the coordinates to compositor's one. | 157 // Flip the coordinates to compositor's one. |
128 if (flip_texture_) | 158 if (flip_texture_) |
129 y = size.height() - rect.y() - rect.height(); | 159 y = size.height() - rect.y() - rect.height(); |
130 gfx::Rect mirroring_rect(rect.x(), y, rect.width(), rect.height()); | 160 gfx::Rect mirroring_rect(rect.x(), y, rect.width(), rect.height()); |
131 | 161 |
132 // Request redraw of the dirty portion in mirroring compositor. | 162 // Request redraw of the dirty portion in mirroring compositor. |
133 UpdateTexture(size, mirroring_rect); | 163 for (LayerData* layer_data : mirroring_layers_) |
164 UpdateTexture(layer_data, size, mirroring_rect); | |
134 } | 165 } |
135 | 166 |
136 static void ReleaseMailbox(scoped_refptr<OwnedMailbox> mailbox, | 167 static void ReleaseMailbox(scoped_refptr<OwnedMailbox> mailbox, |
137 unsigned int sync_point, | 168 unsigned int sync_point, |
138 bool is_lost) { | 169 bool is_lost) { |
139 mailbox->UpdateSyncPoint(sync_point); | 170 mailbox->UpdateSyncPoint(sync_point); |
140 } | 171 } |
141 | 172 |
142 void ReflectorImpl::UpdateTexture(const gfx::Size& source_size, | 173 ScopedVector<ReflectorImpl::LayerData>::iterator ReflectorImpl::FindLayerData( |
174 ui::Layer* layer) { | |
175 return std::find_if(mirroring_layers_.begin(), mirroring_layers_.end(), | |
176 [layer](const LayerData* layer_data) { | |
177 return layer_data->layer == layer; | |
178 }); | |
179 } | |
180 | |
181 void ReflectorImpl::UpdateTexture(ReflectorImpl::LayerData* layer_data, | |
182 const gfx::Size& source_size, | |
143 const gfx::Rect& redraw_rect) { | 183 const gfx::Rect& redraw_rect) { |
144 if (needs_set_mailbox_) { | 184 if (layer_data->needs_set_mailbox) { |
145 mirroring_layer_->SetTextureMailbox( | 185 layer_data->layer->SetTextureMailbox( |
146 cc::TextureMailbox(mailbox_->holder()), | 186 cc::TextureMailbox(mailbox_->holder()), |
147 cc::SingleReleaseCallback::Create(base::Bind(ReleaseMailbox, mailbox_)), | 187 cc::SingleReleaseCallback::Create(base::Bind(ReleaseMailbox, mailbox_)), |
148 source_size); | 188 source_size); |
149 needs_set_mailbox_ = false; | 189 layer_data->needs_set_mailbox = false; |
150 } else { | 190 } else { |
151 mirroring_layer_->SetTextureSize(source_size); | 191 layer_data->layer->SetTextureSize(source_size); |
152 } | 192 } |
153 mirroring_layer_->SetBounds(gfx::Rect(source_size)); | 193 layer_data->layer->SetBounds(gfx::Rect(source_size)); |
oshima
2015/04/28 16:05:39
This is inefficient as each reflector has a textur
piman
2015/04/28 18:38:13
Agreed, avoiding the copy altogether is a better p
| |
154 mirroring_layer_->SetTextureFlipped(flip_texture_); | 194 layer_data->layer->SetTextureFlipped(flip_texture_); |
155 mirroring_layer_->SchedulePaint(redraw_rect); | 195 layer_data->layer->SchedulePaint(redraw_rect); |
156 } | 196 } |
157 | 197 |
158 } // namespace content | 198 } // namespace content |
OLD | NEW |