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