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   AttachToOutputSurface(output_surface_map_->Lookup(surface_id_));
     37   gl_helper_->CopyTextureFullImage(texture_id_, texture_size_);
     38   // The shared texture doesn't have the data, so invokes full redraw
     39   // now.
     40   main_message_loop_->PostTask(
     41       FROM_HERE,
     42       base::Bind(&ReflectorImpl::FullRedrawContentOnMainThread,
     43                  scoped_refptr<ReflectorImpl>(this)));
     44 }
     45 
     46 void ReflectorImpl::Shutdown() {
     47   mirroring_compositor_ = NULL;
     48   mirroring_layer_ = NULL;
     49   shared_texture_ = NULL;
     50   impl_message_loop_->PostTask(
     51       FROM_HERE,
     52       base::Bind(&ReflectorImpl::ShutdownOnImplThread, this));
     53 }
     54 
     55 void ReflectorImpl::ShutdownOnImplThread() {
     56   BrowserCompositorOutputSurface* output_surface =
     57       output_surface_map_->Lookup(surface_id_);
     58   output_surface->SetReflector(NULL);
     59   gl_helper_.reset();
     60   // The instance must be deleted on main thread.
     61   main_message_loop_->PostTask(
     62       FROM_HERE,
     63       base::Bind(&ReflectorImpl::DeleteOnMainThread,
     64                  scoped_refptr<ReflectorImpl>(this)));
     65 }
     66 
     67 // This must be called on ImplThread, or before the surface is passed to
     68 // ImplThread.
     69 void ReflectorImpl::AttachToOutputSurface(
     70     BrowserCompositorOutputSurface* output_surface) {
     71   gl_helper_.reset(new GLHelper(output_surface->context3d()));
     72   output_surface->SetReflector(this);
     73 }
     74 
     75 void ReflectorImpl::OnMirroringCompositorResized() {
     76   mirroring_compositor_->ScheduleFullRedraw();
     77 }
     78 
     79 void ReflectorImpl::OnLostResources() {
     80   shared_texture_ = NULL;
     81   mirroring_layer_->SetExternalTexture(NULL);
     82 }
     83 
     84 void ReflectorImpl::OnReshape(gfx::Size size) {
     85   if (texture_size_ == size)
     86     return;
     87   texture_size_ = size;
     88   DCHECK(texture_id_);
     89   gl_helper_->ResizeTexture(texture_id_, size);
     90   main_message_loop_->PostTask(
     91       FROM_HERE,
     92       base::Bind(&ReflectorImpl::UpdateTextureSizeOnMainThread,
     93                  this->AsWeakPtr(),
     94                  texture_size_));
     95 }
     96 
     97 void ReflectorImpl::OnSwapBuffers() {
     98   DCHECK(texture_id_);
     99   gl_helper_->CopyTextureFullImage(texture_id_, texture_size_);
    100   main_message_loop_->PostTask(
    101       FROM_HERE,
    102       base::Bind(&ReflectorImpl::FullRedrawOnMainThread,
    103                  this->AsWeakPtr(),
    104                  texture_size_));
    105 }
    106 
    107 void ReflectorImpl::OnPostSubBuffer(gfx::Rect rect) {
    108   DCHECK(texture_id_);
    109   gl_helper_->CopyTextureSubImage(texture_id_, rect);
    110   main_message_loop_->PostTask(
    111       FROM_HERE,
    112       base::Bind(&ReflectorImpl::UpdateSubBufferOnMainThread,
    113                  this->AsWeakPtr(),
    114                  texture_size_,
    115                  rect));
    116 }
    117 
    118 void ReflectorImpl::CreateSharedTexture() {
    119   texture_id_ =
    120       ImageTransportFactory::GetInstance()->GetGLHelper()->CreateTexture();
    121   shared_texture_ =
    122       ImageTransportFactory::GetInstance()->CreateOwnedTexture(
    123           texture_size_, 1.0f, texture_id_);
    124   mirroring_layer_->SetExternalTexture(shared_texture_.get());
    125 }
    126 
    127 ReflectorImpl::~ReflectorImpl() {
    128   // Make sure the reflector is deleted on main thread.
    129   DCHECK_EQ(main_message_loop_.get(),
    130             base::MessageLoopProxy::current().get());
    131 }
    132 
    133 void ReflectorImpl::UpdateTextureSizeOnMainThread(gfx::Size size) {
    134   if (!mirroring_layer_)
    135     return;
    136   mirroring_layer_->SetBounds(gfx::Rect(size));
    137 }
    138 
    139 void ReflectorImpl::FullRedrawOnMainThread(gfx::Size size) {
    140   if (!mirroring_compositor_)
    141     return;
    142   UpdateTextureSizeOnMainThread(size);
    143   mirroring_compositor_->ScheduleFullRedraw();
    144 }
    145 
    146 void ReflectorImpl::UpdateSubBufferOnMainThread(gfx::Size size,
    147                                                 gfx::Rect rect) {
    148   if (!mirroring_compositor_)
    149     return;
    150   UpdateTextureSizeOnMainThread(size);
    151   // Flip the coordinates to compositor's one.
    152   int y = size.height() - rect.y() - rect.height();
    153   gfx::Rect new_rect(rect.x(), y, rect.width(), rect.height());
    154   mirroring_layer_->SchedulePaint(new_rect);
    155 }
    156 
    157 void ReflectorImpl::FullRedrawContentOnMainThread() {
    158   mirrored_compositor_->ScheduleFullRedraw();
    159 }
    160 
    161 }  // namespace content
    162