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