Home | History | Annotate | Download | only in aura
      1 // Copyright (c) 2013 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/aura/reflector_impl.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/location.h"
      9 #include "content/browser/aura/browser_compositor_output_surface.h"
     10 #include "content/common/gpu/client/gl_helper.h"
     11 #include "ui/compositor/layer.h"
     12 
     13 namespace content {
     14 
     15 ReflectorImpl::ReflectorImpl(
     16     ui::Compositor* mirrored_compositor,
     17     ui::Layer* mirroring_layer,
     18     IDMap<BrowserCompositorOutputSurface>* output_surface_map,
     19     int surface_id)
     20     : texture_id_(0),
     21       texture_size_(mirrored_compositor->size()),
     22       output_surface_map_(output_surface_map),
     23       mirrored_compositor_(mirrored_compositor),
     24       mirroring_compositor_(mirroring_layer->GetCompositor()),
     25       mirroring_layer_(mirroring_layer),
     26       impl_message_loop_(ui::Compositor::GetCompositorMessageLoop()),
     27       main_message_loop_(base::MessageLoopProxy::current()),
     28       surface_id_(surface_id) {
     29   CreateSharedTexture();
     30   impl_message_loop_->PostTask(
     31       FROM_HERE,
     32       base::Bind(&ReflectorImpl::InitOnImplThread, this));
     33 }
     34 
     35 void ReflectorImpl::InitOnImplThread() {
     36   // Ignore if the reflector was shutdown before
     37   // initialized, or it's already initialized.
     38   if (!output_surface_map_ || gl_helper_.get())
     39     return;
     40 
     41   BrowserCompositorOutputSurface* source_surface =
     42       output_surface_map_->Lookup(surface_id_);
     43   // Skip if the source surface isn't ready yet. This will be
     44   // initiailze when the source surface becomes ready.
     45   if (!source_surface)
     46     return;
     47 
     48   AttachToOutputSurface(source_surface);
     49   gl_helper_->CopyTextureFullImage(texture_id_, texture_size_);
     50   // The shared texture doesn't have the data, so invokes full redraw
     51   // now.
     52   main_message_loop_->PostTask(
     53       FROM_HERE,
     54       base::Bind(&ReflectorImpl::FullRedrawContentOnMainThread,
     55                  scoped_refptr<ReflectorImpl>(this)));
     56 }
     57 
     58 void ReflectorImpl::OnSourceSurfaceReady(int surface_id) {
     59   DCHECK_EQ(surface_id_, surface_id);
     60   InitOnImplThread();
     61 }
     62 
     63 void ReflectorImpl::Shutdown() {
     64   mirroring_compositor_ = NULL;
     65   mirroring_layer_ = NULL;
     66   shared_texture_ = NULL;
     67   impl_message_loop_->PostTask(
     68       FROM_HERE,
     69       base::Bind(&ReflectorImpl::ShutdownOnImplThread, this));
     70 }
     71 
     72 void ReflectorImpl::ShutdownOnImplThread() {
     73   BrowserCompositorOutputSurface* output_surface =
     74       output_surface_map_->Lookup(surface_id_);
     75   if (output_surface)
     76     output_surface->SetReflector(NULL);
     77   output_surface_map_ = NULL;
     78   gl_helper_.reset();
     79   // The instance must be deleted on main thread.
     80   main_message_loop_->PostTask(
     81       FROM_HERE,
     82       base::Bind(&ReflectorImpl::DeleteOnMainThread,
     83                  scoped_refptr<ReflectorImpl>(this)));
     84 }
     85 
     86 // This must be called on ImplThread, or before the surface is passed to
     87 // ImplThread.
     88 void ReflectorImpl::AttachToOutputSurface(
     89     BrowserCompositorOutputSurface* output_surface) {
     90   gl_helper_.reset(
     91       new GLHelper(output_surface->context_provider()->Context3d(),
     92                    output_surface->context_provider()->ContextSupport()));
     93   output_surface->SetReflector(this);
     94 }
     95 
     96 void ReflectorImpl::OnMirroringCompositorResized() {
     97   mirroring_compositor_->ScheduleFullRedraw();
     98 }
     99 
    100 void ReflectorImpl::OnLostResources() {
    101   shared_texture_ = NULL;
    102   mirroring_layer_->SetShowPaintedContent();
    103 }
    104 
    105 void ReflectorImpl::OnReshape(gfx::Size size) {
    106   if (texture_size_ == size)
    107     return;
    108   texture_size_ = size;
    109   DCHECK(texture_id_);
    110   gl_helper_->ResizeTexture(texture_id_, size);
    111   main_message_loop_->PostTask(
    112       FROM_HERE,
    113       base::Bind(&ReflectorImpl::UpdateTextureSizeOnMainThread,
    114                  this->AsWeakPtr(),
    115                  texture_size_));
    116 }
    117 
    118 void ReflectorImpl::OnSwapBuffers() {
    119   DCHECK(texture_id_);
    120   gl_helper_->CopyTextureFullImage(texture_id_, texture_size_);
    121   main_message_loop_->PostTask(
    122       FROM_HERE,
    123       base::Bind(&ReflectorImpl::FullRedrawOnMainThread,
    124                  this->AsWeakPtr(),
    125                  texture_size_));
    126 }
    127 
    128 void ReflectorImpl::OnPostSubBuffer(gfx::Rect rect) {
    129   DCHECK(texture_id_);
    130   gl_helper_->CopyTextureSubImage(texture_id_, rect);
    131   main_message_loop_->PostTask(
    132       FROM_HERE,
    133       base::Bind(&ReflectorImpl::UpdateSubBufferOnMainThread,
    134                  this->AsWeakPtr(),
    135                  texture_size_,
    136                  rect));
    137 }
    138 
    139 void ReflectorImpl::CreateSharedTexture() {
    140   texture_id_ =
    141       ImageTransportFactory::GetInstance()->GetGLHelper()->CreateTexture();
    142   shared_texture_ =
    143       ImageTransportFactory::GetInstance()->CreateOwnedTexture(
    144           texture_size_, 1.0f, texture_id_);
    145   mirroring_layer_->SetExternalTexture(shared_texture_.get());
    146 }
    147 
    148 ReflectorImpl::~ReflectorImpl() {
    149   // Make sure the reflector is deleted on main thread.
    150   DCHECK_EQ(main_message_loop_.get(),
    151             base::MessageLoopProxy::current().get());
    152 }
    153 
    154 void ReflectorImpl::UpdateTextureSizeOnMainThread(gfx::Size size) {
    155   if (!mirroring_layer_)
    156     return;
    157   mirroring_layer_->SetBounds(gfx::Rect(size));
    158 }
    159 
    160 void ReflectorImpl::FullRedrawOnMainThread(gfx::Size size) {
    161   if (!mirroring_compositor_)
    162     return;
    163   UpdateTextureSizeOnMainThread(size);
    164   mirroring_compositor_->ScheduleFullRedraw();
    165 }
    166 
    167 void ReflectorImpl::UpdateSubBufferOnMainThread(gfx::Size size,
    168                                                 gfx::Rect rect) {
    169   if (!mirroring_compositor_)
    170     return;
    171   UpdateTextureSizeOnMainThread(size);
    172   // Flip the coordinates to compositor's one.
    173   int y = size.height() - rect.y() - rect.height();
    174   gfx::Rect new_rect(rect.x(), y, rect.width(), rect.height());
    175   mirroring_layer_->SchedulePaint(new_rect);
    176 }
    177 
    178 void ReflectorImpl::FullRedrawContentOnMainThread() {
    179   mirrored_compositor_->ScheduleFullRedraw();
    180 }
    181 
    182 }  // namespace content
    183