Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(285)

Side by Side Diff: content/browser/compositor/reflector_impl.cc

Issue 1123763003: Draw the offscreen texture to reflector's surface without extra copy (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698