| 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..79243ddaae0ccf1ad2a90b6d7dffbb3c233ac52f 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);
|
| }
|
|
|
| void ReflectorImpl::RemoveMirroringLayer(ui::Layer* layer) {
|
| @@ -114,44 +129,77 @@ void ReflectorImpl::RemoveMirroringLayer(ui::Layer* layer) {
|
| (*iter)->layer->SetShowSolidColorContent();
|
| mirroring_layers_.erase(iter);
|
|
|
| + layer->GetCompositor()->RemoveObserver(this);
|
| + composition_count_--;
|
| +
|
| 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 +210,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);
|
| }
|
|
|
|
|