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