Home | History | Annotate | Download | only in compositor
      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
      3 // found in the LICENSE file.
      4 
      5 #include "content/browser/compositor/reflector_impl.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/location.h"
      9 #include "content/browser/compositor/browser_compositor_output_surface.h"
     10 #include "content/browser/compositor/owned_mailbox.h"
     11 #include "content/common/gpu/client/gl_helper.h"
     12 #include "ui/compositor/layer.h"
     13 
     14 namespace content {
     15 
     16 ReflectorImpl::ReflectorImpl(
     17     ui::Compositor* mirrored_compositor,
     18     ui::Layer* mirroring_layer,
     19     IDMap<BrowserCompositorOutputSurface>* output_surface_map,
     20     base::MessageLoopProxy* compositor_thread_loop,
     21     int surface_id)
     22     : impl_unsafe_(output_surface_map),
     23       main_unsafe_(mirrored_compositor, mirroring_layer),
     24       impl_message_loop_(compositor_thread_loop),
     25       main_message_loop_(base::MessageLoopProxy::current()),
     26       surface_id_(surface_id) {
     27   GLHelper* helper = ImageTransportFactory::GetInstance()->GetGLHelper();
     28   MainThreadData& main = GetMain();
     29   main.mailbox = new OwnedMailbox(helper);
     30   impl_message_loop_->PostTask(
     31       FROM_HERE,
     32       base::Bind(
     33           &ReflectorImpl::InitOnImplThread, this, main.mailbox->holder()));
     34 }
     35 
     36 ReflectorImpl::MainThreadData::MainThreadData(
     37     ui::Compositor* mirrored_compositor,
     38     ui::Layer* mirroring_layer)
     39     : needs_set_mailbox(true),
     40       mirrored_compositor(mirrored_compositor),
     41       mirroring_layer(mirroring_layer) {}
     42 
     43 ReflectorImpl::MainThreadData::~MainThreadData() {}
     44 
     45 ReflectorImpl::ImplThreadData::ImplThreadData(
     46     IDMap<BrowserCompositorOutputSurface>* output_surface_map)
     47     : output_surface_map(output_surface_map),
     48       output_surface(NULL),
     49       texture_id(0) {}
     50 
     51 ReflectorImpl::ImplThreadData::~ImplThreadData() {}
     52 
     53 ReflectorImpl::ImplThreadData& ReflectorImpl::GetImpl() {
     54   DCHECK(impl_message_loop_->BelongsToCurrentThread());
     55   return impl_unsafe_;
     56 }
     57 
     58 ReflectorImpl::MainThreadData& ReflectorImpl::GetMain() {
     59   DCHECK(main_message_loop_->BelongsToCurrentThread());
     60   return main_unsafe_;
     61 }
     62 
     63 void ReflectorImpl::InitOnImplThread(const gpu::MailboxHolder& mailbox_holder) {
     64   ImplThreadData& impl = GetImpl();
     65   // Ignore if the reflector was shutdown before
     66   // initialized, or it's already initialized.
     67   if (!impl.output_surface_map || impl.gl_helper.get())
     68     return;
     69 
     70   impl.mailbox_holder = mailbox_holder;
     71 
     72   BrowserCompositorOutputSurface* source_surface =
     73       impl.output_surface_map->Lookup(surface_id_);
     74   // Skip if the source surface isn't ready yet. This will be
     75   // initialized when the source surface becomes ready.
     76   if (!source_surface)
     77     return;
     78 
     79   AttachToOutputSurfaceOnImplThread(impl.mailbox_holder, source_surface);
     80 }
     81 
     82 void ReflectorImpl::OnSourceSurfaceReady(
     83     BrowserCompositorOutputSurface* source_surface) {
     84   ImplThreadData& impl = GetImpl();
     85   AttachToOutputSurfaceOnImplThread(impl.mailbox_holder, source_surface);
     86 }
     87 
     88 void ReflectorImpl::Shutdown() {
     89   MainThreadData& main = GetMain();
     90   main.mailbox = NULL;
     91   main.mirroring_layer->SetShowPaintedContent();
     92   main.mirroring_layer = NULL;
     93   impl_message_loop_->PostTask(
     94       FROM_HERE, base::Bind(&ReflectorImpl::ShutdownOnImplThread, this));
     95 }
     96 
     97 void ReflectorImpl::DetachFromOutputSurface() {
     98   ImplThreadData& impl = GetImpl();
     99   DCHECK(impl.output_surface);
    100   impl.output_surface->SetReflector(NULL);
    101   DCHECK(impl.texture_id);
    102   impl.gl_helper->DeleteTexture(impl.texture_id);
    103   impl.texture_id = 0;
    104   impl.gl_helper.reset();
    105   impl.output_surface = NULL;
    106 }
    107 
    108 void ReflectorImpl::ShutdownOnImplThread() {
    109   ImplThreadData& impl = GetImpl();
    110   if (impl.output_surface)
    111     DetachFromOutputSurface();
    112   impl.output_surface_map = NULL;
    113   // The instance must be deleted on main thread.
    114   main_message_loop_->PostTask(FROM_HERE,
    115                                base::Bind(&ReflectorImpl::DeleteOnMainThread,
    116                                           scoped_refptr<ReflectorImpl>(this)));
    117 }
    118 
    119 void ReflectorImpl::ReattachToOutputSurfaceFromMainThread(
    120     BrowserCompositorOutputSurface* output_surface) {
    121   MainThreadData& main = GetMain();
    122   GLHelper* helper = ImageTransportFactory::GetInstance()->GetGLHelper();
    123   main.mailbox = new OwnedMailbox(helper);
    124   main.needs_set_mailbox = true;
    125   main.mirroring_layer->SetShowPaintedContent();
    126   impl_message_loop_->PostTask(
    127       FROM_HERE,
    128       base::Bind(&ReflectorImpl::AttachToOutputSurfaceOnImplThread,
    129                  this,
    130                  main.mailbox->holder(),
    131                  output_surface));
    132 }
    133 
    134 void ReflectorImpl::OnMirroringCompositorResized() {
    135   MainThreadData& main = GetMain();
    136   main.mirroring_layer->SchedulePaint(main.mirroring_layer->bounds());
    137 }
    138 
    139 void ReflectorImpl::OnSwapBuffers() {
    140   ImplThreadData& impl = GetImpl();
    141   gfx::Size size = impl.output_surface->SurfaceSize();
    142   if (impl.texture_id) {
    143     impl.gl_helper->CopyTextureFullImage(impl.texture_id, size);
    144     impl.gl_helper->Flush();
    145   }
    146   main_message_loop_->PostTask(
    147       FROM_HERE,
    148       base::Bind(
    149           &ReflectorImpl::FullRedrawOnMainThread, this->AsWeakPtr(), size));
    150 }
    151 
    152 void ReflectorImpl::OnPostSubBuffer(gfx::Rect rect) {
    153   ImplThreadData& impl = GetImpl();
    154   if (impl.texture_id) {
    155     impl.gl_helper->CopyTextureSubImage(impl.texture_id, rect);
    156     impl.gl_helper->Flush();
    157   }
    158   main_message_loop_->PostTask(
    159       FROM_HERE,
    160       base::Bind(&ReflectorImpl::UpdateSubBufferOnMainThread,
    161                  this->AsWeakPtr(),
    162                  impl.output_surface->SurfaceSize(),
    163                  rect));
    164 }
    165 
    166 ReflectorImpl::~ReflectorImpl() {
    167   // Make sure the reflector is deleted on main thread.
    168   DCHECK_EQ(main_message_loop_.get(), base::MessageLoopProxy::current().get());
    169 }
    170 
    171 static void ReleaseMailbox(scoped_refptr<OwnedMailbox> mailbox,
    172                            unsigned int sync_point,
    173                            bool is_lost) {
    174   mailbox->UpdateSyncPoint(sync_point);
    175 }
    176 
    177 void ReflectorImpl::AttachToOutputSurfaceOnImplThread(
    178     const gpu::MailboxHolder& mailbox_holder,
    179     BrowserCompositorOutputSurface* output_surface) {
    180   ImplThreadData& impl = GetImpl();
    181   if (output_surface == impl.output_surface)
    182     return;
    183   if (impl.output_surface)
    184     DetachFromOutputSurface();
    185   impl.output_surface = output_surface;
    186   output_surface->context_provider()->BindToCurrentThread();
    187   impl.gl_helper.reset(
    188       new GLHelper(output_surface->context_provider()->ContextGL(),
    189                    output_surface->context_provider()->ContextSupport()));
    190   impl.texture_id = impl.gl_helper->ConsumeMailboxToTexture(
    191       mailbox_holder.mailbox, mailbox_holder.sync_point);
    192   impl.gl_helper->ResizeTexture(impl.texture_id, output_surface->SurfaceSize());
    193   impl.gl_helper->Flush();
    194   output_surface->SetReflector(this);
    195   // The texture doesn't have the data, so invokes full redraw now.
    196   main_message_loop_->PostTask(
    197       FROM_HERE,
    198       base::Bind(&ReflectorImpl::FullRedrawContentOnMainThread,
    199                  scoped_refptr<ReflectorImpl>(this)));
    200 }
    201 
    202 void ReflectorImpl::UpdateTextureSizeOnMainThread(gfx::Size size) {
    203   MainThreadData& main = GetMain();
    204   if (!main.mirroring_layer || !main.mailbox ||
    205       main.mailbox->mailbox().IsZero())
    206     return;
    207   if (main.needs_set_mailbox) {
    208     main.mirroring_layer->SetTextureMailbox(
    209         cc::TextureMailbox(main.mailbox->holder()),
    210         cc::SingleReleaseCallback::Create(
    211             base::Bind(ReleaseMailbox, main.mailbox)),
    212         size);
    213     main.needs_set_mailbox = false;
    214   } else {
    215     main.mirroring_layer->SetTextureSize(size);
    216   }
    217   main.mirroring_layer->SetBounds(gfx::Rect(size));
    218 }
    219 
    220 void ReflectorImpl::FullRedrawOnMainThread(gfx::Size size) {
    221   MainThreadData& main = GetMain();
    222   if (!main.mirroring_layer)
    223     return;
    224   UpdateTextureSizeOnMainThread(size);
    225   main.mirroring_layer->SchedulePaint(main.mirroring_layer->bounds());
    226 }
    227 
    228 void ReflectorImpl::UpdateSubBufferOnMainThread(gfx::Size size,
    229                                                 gfx::Rect rect) {
    230   MainThreadData& main = GetMain();
    231   if (!main.mirroring_layer)
    232     return;
    233   UpdateTextureSizeOnMainThread(size);
    234   // Flip the coordinates to compositor's one.
    235   int y = size.height() - rect.y() - rect.height();
    236   gfx::Rect new_rect(rect.x(), y, rect.width(), rect.height());
    237   main.mirroring_layer->SchedulePaint(new_rect);
    238 }
    239 
    240 void ReflectorImpl::FullRedrawContentOnMainThread() {
    241   MainThreadData& main = GetMain();
    242   main.mirrored_compositor->ScheduleFullRedraw();
    243 }
    244 
    245 }  // namespace content
    246