Chromium Code Reviews| Index: content/browser/compositor/reflector_impl.cc |
| diff --git a/content/browser/compositor/reflector_impl.cc b/content/browser/compositor/reflector_impl.cc |
| index c58ee567640d107ab725888d5902e0f322e6c0ee..1c80d5179379ea140ed69f9b3ae09344dafa9a44 100644 |
| --- a/content/browser/compositor/reflector_impl.cc |
| +++ b/content/browser/compositor/reflector_impl.cc |
| @@ -25,9 +25,10 @@ ReflectorImpl::ReflectorImpl(ui::Compositor* mirrored_compositor, |
| : mirrored_compositor_(mirrored_compositor), |
| mirrored_compositor_gl_helper_texture_id_(0), |
| flip_texture_(false), |
| + composition_count_(0), |
| output_surface_(nullptr) { |
| if (mirroring_layer) |
| - mirroring_layers_.push_back(new LayerData(mirroring_layer)); |
| + AddMirroringLayer(mirroring_layer); |
| } |
| ReflectorImpl::~ReflectorImpl() { |
| @@ -46,10 +47,12 @@ void ReflectorImpl::DetachFromOutputSurface() { |
| DCHECK(mailbox_.get()); |
| mailbox_ = nullptr; |
| output_surface_ = nullptr; |
| - mirrored_compositor_gl_helper_->DeleteTexture( |
| - mirrored_compositor_gl_helper_texture_id_); |
| - mirrored_compositor_gl_helper_texture_id_ = 0; |
| - mirrored_compositor_gl_helper_ = nullptr; |
| + if (mirrored_compositor_gl_helper_.get()) { |
| + mirrored_compositor_gl_helper_->DeleteTexture( |
| + mirrored_compositor_gl_helper_texture_id_); |
| + mirrored_compositor_gl_helper_texture_id_ = 0; |
| + mirrored_compositor_gl_helper_ = nullptr; |
| + } |
| for (LayerData* layer_data : mirroring_layers_) |
| layer_data->layer->SetShowSolidColorContent(); |
| } |
| @@ -63,24 +66,35 @@ void ReflectorImpl::OnSourceSurfaceReady( |
| if (output_surface_) |
| DetachFromOutputSurface(); |
| - // Use the GLHelper from the ImageTransportFactory for our OwnedMailbox so we |
| - // don't have to manage the lifetime of the GLHelper relative to the lifetime |
| - // of the mailbox. |
| - GLHelper* shared_helper = ImageTransportFactory::GetInstance()->GetGLHelper(); |
| - mailbox_ = new OwnedMailbox(shared_helper); |
| - for (LayerData* layer_data : mirroring_layers_) |
| - layer_data->needs_set_mailbox = true; |
| + output_surface_ = output_surface; |
| - // Create a GLHelper attached to the mirrored compositor's output surface for |
| - // copying the output of the mirrored compositor. |
| - mirrored_compositor_gl_helper_.reset( |
| - new GLHelper(output_surface->context_provider()->ContextGL(), |
| - output_surface->context_provider()->ContextSupport())); |
| - // Create a texture id in the name space of the new GLHelper to update the |
| - // mailbox being held by the |mirroring_layer_|. |
| - mirrored_compositor_gl_helper_texture_id_ = |
| - mirrored_compositor_gl_helper_->ConsumeMailboxToTexture( |
| - mailbox_->mailbox(), mailbox_->sync_point()); |
| + composition_started_callback_ = |
| + output_surface_->CreateCompositionStartedCallback(); |
| + OnSourceTextureMailboxUpdated(); |
| + // If the source output surface didn't have its own |
| + // mailbox, create one for mirror mode. |
| + if (!mailbox_.get()) { |
| + // Use the GLHelper from the ImageTransportFactory for our OwnedMailbox |
| + // so we don't have to manage the lifetime of the GLHelper relative to |
| + // the lifetime of the mailbox. |
| + GLHelper* shared_helper = |
| + ImageTransportFactory::GetInstance()->GetGLHelper(); |
| + mailbox_ = new OwnedMailbox(shared_helper); |
| + |
| + // Create a GLHelper attached to the mirrored compositor's output |
| + // surface for copying the output of the mirrored compositor. |
| + mirrored_compositor_gl_helper_.reset( |
| + new GLHelper(output_surface_->context_provider()->ContextGL(), |
| + output_surface_->context_provider()->ContextSupport())); |
| + // Create a texture id in the name space of the new GLHelper to update the |
| + // mailbox being held by the |mirroring_layer_|. |
| + mirrored_compositor_gl_helper_texture_id_ = |
| + mirrored_compositor_gl_helper_->ConsumeMailboxToTexture( |
| + mailbox_->mailbox(), mailbox_->sync_point()); |
| + |
| + for (LayerData* layer_data : mirroring_layers_) |
| + layer_data->needs_set_mailbox = true; |
| + } |
| flip_texture_ = !output_surface->capabilities().flipped_output_surface; |
| @@ -90,7 +104,6 @@ void ReflectorImpl::OnSourceSurfaceReady( |
| // texture appropriately. |
| mirrored_compositor_->ScheduleFullRedraw(); |
| - output_surface_ = output_surface; |
| output_surface_->SetReflector(this); |
| } |
| @@ -106,6 +119,8 @@ void ReflectorImpl::AddMirroringLayer(ui::Layer* layer) { |
| layer_data->needs_set_mailbox = true; |
| mirroring_layers_.push_back(layer_data); |
| mirrored_compositor_->ScheduleFullRedraw(); |
| + |
| + 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
|
| } |
| void ReflectorImpl::RemoveMirroringLayer(ui::Layer* layer) { |
| @@ -114,44 +129,79 @@ void ReflectorImpl::RemoveMirroringLayer(ui::Layer* layer) { |
| (*iter)->layer->SetShowSolidColorContent(); |
| mirroring_layers_.erase(iter); |
| + layer->GetCompositor()->RemoveObserver(this); |
| + composition_count_--; |
| + if (composition_count_ == 0 && !composition_started_callback_.is_null()) |
| + composition_started_callback_.Run(); |
| + |
| if (mirroring_layers_.empty() && output_surface_) |
| DetachFromOutputSurface(); |
| } |
| +void ReflectorImpl::OnCompositingStarted(ui::Compositor* compositor, |
| + base::TimeTicks start_time) { |
| + if (composition_count_ > 0 && |
| + --composition_count_ == 0 && |
| + !composition_started_callback_.is_null()) { |
| + composition_started_callback_.Run(); |
| + } |
| +} |
| + |
| +void ReflectorImpl::OnSourceTextureMailboxUpdated() { |
| + mailbox_ = output_surface_->GetTextureMailbox(); |
| + for (LayerData* layer_data : mirroring_layers_) |
| + layer_data->needs_set_mailbox = true; |
| +} |
| + |
| void ReflectorImpl::OnSourceSwapBuffers() { |
| - if (mirroring_layers_.empty()) |
| + if (mirroring_layers_.empty()) { |
| + if (!composition_started_callback_.is_null()) |
| + composition_started_callback_.Run(); |
| return; |
| + } |
| + |
| // Should be attached to the source output surface already. |
| DCHECK(mailbox_.get()); |
| gfx::Size size = output_surface_->SurfaceSize(); |
| - mirrored_compositor_gl_helper_->CopyTextureFullImage( |
| - mirrored_compositor_gl_helper_texture_id_, size); |
| - // Insert a barrier to make the copy show up in the mirroring compositor's |
| - // mailbox. Since the the compositor contexts and the ImageTransportFactory's |
| - // GLHelper are all on the same GPU channel, this is sufficient instead of |
| - // plumbing through a sync point. |
| - mirrored_compositor_gl_helper_->InsertOrderingBarrier(); |
| + if (mirrored_compositor_gl_helper_.get()) { |
| + mirrored_compositor_gl_helper_->CopyTextureFullImage( |
| + mirrored_compositor_gl_helper_texture_id_, size); |
| + // Insert a barrier to make the copy show up in the mirroring compositor's |
| + // mailbox. Since the the compositor contexts and the |
| + // ImageTransportFactory's |
| + // GLHelper are all on the same GPU channel, this is sufficient instead of |
| + // plumbing through a sync point. |
| + mirrored_compositor_gl_helper_->InsertOrderingBarrier(); |
| + } |
| // Request full redraw on mirroring compositor. |
| for (LayerData* layer_data : mirroring_layers_) |
| UpdateTexture(layer_data, size, layer_data->layer->bounds()); |
| + composition_count_ = mirroring_layers_.size(); |
| } |
| void ReflectorImpl::OnSourcePostSubBuffer(const gfx::Rect& rect) { |
| - if (mirroring_layers_.empty()) |
| + if (mirroring_layers_.empty()) { |
| + if (!composition_started_callback_.is_null()) |
| + composition_started_callback_.Run(); |
| return; |
| + } |
| + |
| // Should be attached to the source output surface already. |
| DCHECK(mailbox_.get()); |
| gfx::Size size = output_surface_->SurfaceSize(); |
| - mirrored_compositor_gl_helper_->CopyTextureSubImage( |
| - mirrored_compositor_gl_helper_texture_id_, rect); |
| - // Insert a barrier to make the copy show up in the mirroring compositor's |
| - // mailbox. Since the the compositor contexts and the ImageTransportFactory's |
| - // GLHelper are all on the same GPU channel, this is sufficient instead of |
| - // plumbing through a sync point. |
| - mirrored_compositor_gl_helper_->InsertOrderingBarrier(); |
| + if (mirrored_compositor_gl_helper_.get()) { |
| + mirrored_compositor_gl_helper_->CopyTextureSubImage( |
| + mirrored_compositor_gl_helper_texture_id_, rect); |
| + // Insert a barrier to make the copy show up in the mirroring compositor's |
| + // mailbox. Since the the compositor contexts and the |
| + // ImageTransportFactory's |
| + // GLHelper are all on the same GPU channel, this is sufficient instead of |
| + // plumbing through a sync point. |
| + mirrored_compositor_gl_helper_->InsertOrderingBarrier(); |
| + } |
| int y = rect.y(); |
| // Flip the coordinates to compositor's one. |
| @@ -162,11 +212,12 @@ void ReflectorImpl::OnSourcePostSubBuffer(const gfx::Rect& rect) { |
| // Request redraw of the dirty portion in mirroring compositor. |
| for (LayerData* layer_data : mirroring_layers_) |
| UpdateTexture(layer_data, size, mirroring_rect); |
| + composition_count_ = mirroring_layers_.size(); |
| } |
| static void ReleaseMailbox(scoped_refptr<OwnedMailbox> mailbox, |
| - unsigned int sync_point, |
| - bool is_lost) { |
| + unsigned int sync_point, |
| + bool is_lost) { |
| mailbox->UpdateSyncPoint(sync_point); |
| } |