| Index: content/browser/compositor/reflector_impl.cc
|
| diff --git a/content/browser/compositor/reflector_impl.cc b/content/browser/compositor/reflector_impl.cc
|
| index 428aaad4105cee636b9a6fab236f2c9365a157c6..14e992b939ac2145411a2f269d595ab16df5fd93 100644
|
| --- a/content/browser/compositor/reflector_impl.cc
|
| +++ b/content/browser/compositor/reflector_impl.cc
|
| @@ -7,6 +7,7 @@
|
| #include "base/bind.h"
|
| #include "base/location.h"
|
| #include "content/browser/compositor/browser_compositor_output_surface.h"
|
| +#include "content/browser/compositor/owned_mailbox.h"
|
| #include "content/common/gpu/client/gl_helper.h"
|
| #include "ui/compositor/layer.h"
|
|
|
| @@ -17,199 +18,227 @@ ReflectorImpl::ReflectorImpl(
|
| ui::Layer* mirroring_layer,
|
| IDMap<BrowserCompositorOutputSurface>* output_surface_map,
|
| int surface_id)
|
| - : texture_id_(0),
|
| - texture_size_(mirrored_compositor->size()),
|
| - output_surface_map_(output_surface_map),
|
| - mirrored_compositor_(mirrored_compositor),
|
| - mirroring_compositor_(mirroring_layer->GetCompositor()),
|
| - mirroring_layer_(mirroring_layer),
|
| + : impl_unsafe_(output_surface_map),
|
| + main_unsafe_(mirrored_compositor, mirroring_layer),
|
| impl_message_loop_(ui::Compositor::GetCompositorMessageLoop()),
|
| main_message_loop_(base::MessageLoopProxy::current()),
|
| surface_id_(surface_id) {
|
| + GLHelper* helper = ImageTransportFactory::GetInstance()->GetGLHelper();
|
| + MainThreadData& main = GetMain();
|
| + main.mailbox = new OwnedMailbox(helper);
|
| impl_message_loop_->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&ReflectorImpl::InitOnImplThread, this));
|
| + base::Bind(
|
| + &ReflectorImpl::InitOnImplThread, this, main.mailbox->holder()));
|
| }
|
|
|
| -void ReflectorImpl::InitOnImplThread() {
|
| +ReflectorImpl::MainThreadData::MainThreadData(
|
| + ui::Compositor* mirrored_compositor,
|
| + ui::Layer* mirroring_layer)
|
| + : needs_set_mailbox(true),
|
| + mirrored_compositor(mirrored_compositor),
|
| + mirroring_layer(mirroring_layer) {}
|
| +
|
| +ReflectorImpl::MainThreadData::~MainThreadData() {}
|
| +
|
| +ReflectorImpl::ImplThreadData::ImplThreadData(
|
| + IDMap<BrowserCompositorOutputSurface>* output_surface_map)
|
| + : output_surface_map(output_surface_map),
|
| + output_surface(NULL),
|
| + texture_id(0) {}
|
| +
|
| +ReflectorImpl::ImplThreadData::~ImplThreadData() {}
|
| +
|
| +ReflectorImpl::ImplThreadData& ReflectorImpl::GetImpl() {
|
| + DCHECK(impl_message_loop_->BelongsToCurrentThread());
|
| + return impl_unsafe_;
|
| +}
|
| +
|
| +ReflectorImpl::MainThreadData& ReflectorImpl::GetMain() {
|
| + DCHECK(main_message_loop_->BelongsToCurrentThread());
|
| + return main_unsafe_;
|
| +}
|
| +
|
| +void ReflectorImpl::InitOnImplThread(const gpu::MailboxHolder& mailbox_holder) {
|
| + ImplThreadData& impl = GetImpl();
|
| // Ignore if the reflector was shutdown before
|
| // initialized, or it's already initialized.
|
| - if (!output_surface_map_ || gl_helper_.get())
|
| + if (!impl.output_surface_map || impl.gl_helper.get())
|
| return;
|
|
|
| + impl.mailbox_holder = mailbox_holder;
|
| +
|
| BrowserCompositorOutputSurface* source_surface =
|
| - output_surface_map_->Lookup(surface_id_);
|
| + impl.output_surface_map->Lookup(surface_id_);
|
| // Skip if the source surface isn't ready yet. This will be
|
| - // initiailze when the source surface becomes ready.
|
| + // initialized when the source surface becomes ready.
|
| if (!source_surface)
|
| return;
|
|
|
| - AttachToOutputSurfaceOnImplThread(source_surface);
|
| - // The shared texture doesn't have the data, so invokes full redraw
|
| - // now.
|
| - main_message_loop_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&ReflectorImpl::FullRedrawContentOnMainThread,
|
| - scoped_refptr<ReflectorImpl>(this)));
|
| + AttachToOutputSurfaceOnImplThread(impl.mailbox_holder, source_surface);
|
| }
|
|
|
| -void ReflectorImpl::OnSourceSurfaceReady(int surface_id) {
|
| - DCHECK_EQ(surface_id_, surface_id);
|
| - InitOnImplThread();
|
| +void ReflectorImpl::OnSourceSurfaceReady(
|
| + BrowserCompositorOutputSurface* source_surface) {
|
| + ImplThreadData& impl = GetImpl();
|
| + AttachToOutputSurfaceOnImplThread(impl.mailbox_holder, source_surface);
|
| }
|
|
|
| void ReflectorImpl::Shutdown() {
|
| - mirroring_compositor_ = NULL;
|
| - mirroring_layer_ = NULL;
|
| - {
|
| - base::AutoLock lock(texture_lock_);
|
| - texture_id_ = 0;
|
| - }
|
| - shared_texture_ = NULL;
|
| + MainThreadData& main = GetMain();
|
| + main.mailbox = NULL;
|
| + main.mirroring_layer->SetShowPaintedContent();
|
| + main.mirroring_layer = NULL;
|
| impl_message_loop_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&ReflectorImpl::ShutdownOnImplThread, this));
|
| + FROM_HERE, base::Bind(&ReflectorImpl::ShutdownOnImplThread, this));
|
| +}
|
| +
|
| +void ReflectorImpl::DetachFromOutputSurface() {
|
| + ImplThreadData& impl = GetImpl();
|
| + DCHECK(impl.output_surface);
|
| + impl.output_surface->SetReflector(NULL);
|
| + DCHECK(impl.texture_id);
|
| + impl.gl_helper->DeleteTexture(impl.texture_id);
|
| + impl.texture_id = 0;
|
| + impl.gl_helper.reset();
|
| + impl.output_surface = NULL;
|
| }
|
|
|
| void ReflectorImpl::ShutdownOnImplThread() {
|
| - BrowserCompositorOutputSurface* output_surface =
|
| - output_surface_map_->Lookup(surface_id_);
|
| - if (output_surface)
|
| - output_surface->SetReflector(NULL);
|
| - output_surface_map_ = NULL;
|
| - gl_helper_.reset();
|
| + ImplThreadData& impl = GetImpl();
|
| + if (impl.output_surface)
|
| + DetachFromOutputSurface();
|
| + impl.output_surface_map = NULL;
|
| // The instance must be deleted on main thread.
|
| - main_message_loop_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&ReflectorImpl::DeleteOnMainThread,
|
| - scoped_refptr<ReflectorImpl>(this)));
|
| + main_message_loop_->PostTask(FROM_HERE,
|
| + base::Bind(&ReflectorImpl::DeleteOnMainThread,
|
| + scoped_refptr<ReflectorImpl>(this)));
|
| }
|
|
|
| void ReflectorImpl::ReattachToOutputSurfaceFromMainThread(
|
| BrowserCompositorOutputSurface* output_surface) {
|
| + MainThreadData& main = GetMain();
|
| + GLHelper* helper = ImageTransportFactory::GetInstance()->GetGLHelper();
|
| + main.mailbox = new OwnedMailbox(helper);
|
| + main.needs_set_mailbox = true;
|
| + main.mirroring_layer->SetShowPaintedContent();
|
| impl_message_loop_->PostTask(
|
| FROM_HERE,
|
| base::Bind(&ReflectorImpl::AttachToOutputSurfaceOnImplThread,
|
| - this, output_surface));
|
| + this,
|
| + main.mailbox->holder(),
|
| + output_surface));
|
| }
|
|
|
| void ReflectorImpl::OnMirroringCompositorResized() {
|
| - mirroring_compositor_->ScheduleFullRedraw();
|
| -}
|
| -
|
| -void ReflectorImpl::OnLostResources() {
|
| - mirroring_layer_->SetShowPaintedContent();
|
| -}
|
| -
|
| -void ReflectorImpl::OnReshape(gfx::Size size) {
|
| - if (texture_size_ == size)
|
| - return;
|
| - texture_size_ = size;
|
| - {
|
| - base::AutoLock lock(texture_lock_);
|
| - if (texture_id_) {
|
| - gl_helper_->ResizeTexture(texture_id_, size);
|
| - gl_helper_->Flush();
|
| - }
|
| - }
|
| - main_message_loop_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&ReflectorImpl::UpdateTextureSizeOnMainThread,
|
| - this->AsWeakPtr(),
|
| - texture_size_));
|
| + MainThreadData& main = GetMain();
|
| + main.mirroring_layer->SchedulePaint(main.mirroring_layer->bounds());
|
| }
|
|
|
| void ReflectorImpl::OnSwapBuffers() {
|
| - {
|
| - base::AutoLock lock(texture_lock_);
|
| - if (texture_id_) {
|
| - gl_helper_->CopyTextureFullImage(texture_id_, texture_size_);
|
| - gl_helper_->Flush();
|
| - }
|
| + ImplThreadData& impl = GetImpl();
|
| + gfx::Size size = impl.output_surface->SurfaceSize();
|
| + if (impl.texture_id) {
|
| + impl.gl_helper->CopyTextureFullImage(impl.texture_id, size);
|
| + impl.gl_helper->Flush();
|
| }
|
| main_message_loop_->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&ReflectorImpl::FullRedrawOnMainThread,
|
| - this->AsWeakPtr(),
|
| - texture_size_));
|
| + base::Bind(
|
| + &ReflectorImpl::FullRedrawOnMainThread, this->AsWeakPtr(), size));
|
| }
|
|
|
| void ReflectorImpl::OnPostSubBuffer(gfx::Rect rect) {
|
| - {
|
| - base::AutoLock lock(texture_lock_);
|
| - if (texture_id_) {
|
| - gl_helper_->CopyTextureSubImage(texture_id_, rect);
|
| - gl_helper_->Flush();
|
| - }
|
| + ImplThreadData& impl = GetImpl();
|
| + if (impl.texture_id) {
|
| + impl.gl_helper->CopyTextureSubImage(impl.texture_id, rect);
|
| + impl.gl_helper->Flush();
|
| }
|
| main_message_loop_->PostTask(
|
| FROM_HERE,
|
| base::Bind(&ReflectorImpl::UpdateSubBufferOnMainThread,
|
| this->AsWeakPtr(),
|
| - texture_size_,
|
| + impl.output_surface->SurfaceSize(),
|
| rect));
|
| }
|
|
|
| -void ReflectorImpl::CreateSharedTextureOnMainThread(gfx::Size size) {
|
| - {
|
| - base::AutoLock lock(texture_lock_);
|
| - texture_id_ =
|
| - ImageTransportFactory::GetInstance()->GetGLHelper()->CreateTexture();
|
| - shared_texture_ =
|
| - ImageTransportFactory::GetInstance()->CreateOwnedTexture(
|
| - size, 1.0f, texture_id_);
|
| - ImageTransportFactory::GetInstance()->GetGLHelper()->Flush();
|
| - }
|
| - mirroring_layer_->SetExternalTexture(shared_texture_.get());
|
| - FullRedrawOnMainThread(size);
|
| -}
|
| -
|
| ReflectorImpl::~ReflectorImpl() {
|
| // Make sure the reflector is deleted on main thread.
|
| - DCHECK_EQ(main_message_loop_.get(),
|
| - base::MessageLoopProxy::current().get());
|
| + DCHECK_EQ(main_message_loop_.get(), base::MessageLoopProxy::current().get());
|
| +}
|
| +
|
| +static void ReleaseMailbox(scoped_refptr<OwnedMailbox> mailbox,
|
| + unsigned int sync_point,
|
| + bool is_lost) {
|
| + mailbox->UpdateSyncPoint(sync_point);
|
| }
|
|
|
| void ReflectorImpl::AttachToOutputSurfaceOnImplThread(
|
| + const gpu::MailboxHolder& mailbox_holder,
|
| BrowserCompositorOutputSurface* output_surface) {
|
| + ImplThreadData& impl = GetImpl();
|
| + if (output_surface == impl.output_surface)
|
| + return;
|
| + if (impl.output_surface)
|
| + DetachFromOutputSurface();
|
| + impl.output_surface = output_surface;
|
| output_surface->context_provider()->BindToCurrentThread();
|
| - gl_helper_.reset(
|
| + impl.gl_helper.reset(
|
| new GLHelper(output_surface->context_provider()->ContextGL(),
|
| output_surface->context_provider()->ContextSupport()));
|
| + impl.texture_id = impl.gl_helper->ConsumeMailboxToTexture(
|
| + mailbox_holder.mailbox, mailbox_holder.sync_point);
|
| + impl.gl_helper->ResizeTexture(impl.texture_id, output_surface->SurfaceSize());
|
| + impl.gl_helper->Flush();
|
| output_surface->SetReflector(this);
|
| + // The texture doesn't have the data, so invokes full redraw now.
|
| main_message_loop_->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&ReflectorImpl::CreateSharedTextureOnMainThread,
|
| - this->AsWeakPtr(),
|
| - texture_size_));
|
| + base::Bind(&ReflectorImpl::FullRedrawContentOnMainThread,
|
| + scoped_refptr<ReflectorImpl>(this)));
|
| }
|
|
|
| void ReflectorImpl::UpdateTextureSizeOnMainThread(gfx::Size size) {
|
| - if (!mirroring_layer_)
|
| + MainThreadData& main = GetMain();
|
| + if (!main.mirroring_layer || !main.mailbox ||
|
| + main.mailbox->mailbox().IsZero())
|
| return;
|
| - mirroring_layer_->SetBounds(gfx::Rect(size));
|
| + if (main.needs_set_mailbox) {
|
| + main.mirroring_layer->SetTextureMailbox(
|
| + cc::TextureMailbox(main.mailbox->holder()),
|
| + cc::SingleReleaseCallback::Create(
|
| + base::Bind(ReleaseMailbox, main.mailbox)),
|
| + size);
|
| + main.needs_set_mailbox = false;
|
| + } else {
|
| + main.mirroring_layer->SetTextureSize(size);
|
| + }
|
| + main.mirroring_layer->SetBounds(gfx::Rect(size));
|
| }
|
|
|
| void ReflectorImpl::FullRedrawOnMainThread(gfx::Size size) {
|
| - if (!mirroring_compositor_)
|
| + MainThreadData& main = GetMain();
|
| + if (!main.mirroring_layer)
|
| return;
|
| UpdateTextureSizeOnMainThread(size);
|
| - mirroring_compositor_->ScheduleFullRedraw();
|
| + main.mirroring_layer->SchedulePaint(main.mirroring_layer->bounds());
|
| }
|
|
|
| void ReflectorImpl::UpdateSubBufferOnMainThread(gfx::Size size,
|
| gfx::Rect rect) {
|
| - if (!mirroring_compositor_)
|
| + MainThreadData& main = GetMain();
|
| + if (!main.mirroring_layer)
|
| return;
|
| UpdateTextureSizeOnMainThread(size);
|
| // Flip the coordinates to compositor's one.
|
| int y = size.height() - rect.y() - rect.height();
|
| gfx::Rect new_rect(rect.x(), y, rect.width(), rect.height());
|
| - mirroring_layer_->SchedulePaint(new_rect);
|
| + main.mirroring_layer->SchedulePaint(new_rect);
|
| }
|
|
|
| void ReflectorImpl::FullRedrawContentOnMainThread() {
|
| - mirrored_compositor_->ScheduleFullRedraw();
|
| + MainThreadData& main = GetMain();
|
| + main.mirrored_compositor->ScheduleFullRedraw();
|
| }
|
|
|
| } // namespace content
|
|
|