Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/compositor/reflector_impl.h" | 5 #include "content/browser/compositor/reflector_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/location.h" | 8 #include "base/location.h" |
| 9 #include "content/browser/compositor/browser_compositor_output_surface.h" | 9 #include "content/browser/compositor/browser_compositor_output_surface.h" |
| 10 #include "content/browser/compositor/owned_mailbox.h" | |
| 10 #include "content/common/gpu/client/gl_helper.h" | 11 #include "content/common/gpu/client/gl_helper.h" |
| 11 #include "ui/compositor/layer.h" | 12 #include "ui/compositor/layer.h" |
| 12 | 13 |
| 13 namespace content { | 14 namespace content { |
| 14 | 15 |
| 15 ReflectorImpl::ReflectorImpl( | 16 ReflectorImpl::ReflectorImpl( |
| 16 ui::Compositor* mirrored_compositor, | 17 ui::Compositor* mirrored_compositor, |
| 17 ui::Layer* mirroring_layer, | 18 ui::Layer* mirroring_layer, |
| 18 IDMap<BrowserCompositorOutputSurface>* output_surface_map, | 19 IDMap<BrowserCompositorOutputSurface>* output_surface_map, |
| 19 int surface_id) | 20 int surface_id) |
| 20 : texture_id_(0), | 21 : output_surface_map_(output_surface_map), |
| 21 texture_size_(mirrored_compositor->size()), | 22 output_surface_(NULL), |
| 22 output_surface_map_(output_surface_map), | 23 impl_thread_texture_id_(0), |
| 24 needs_set_mailbox_(true), | |
| 23 mirrored_compositor_(mirrored_compositor), | 25 mirrored_compositor_(mirrored_compositor), |
| 24 mirroring_compositor_(mirroring_layer->GetCompositor()), | |
| 25 mirroring_layer_(mirroring_layer), | 26 mirroring_layer_(mirroring_layer), |
| 26 impl_message_loop_(ui::Compositor::GetCompositorMessageLoop()), | 27 impl_message_loop_(ui::Compositor::GetCompositorMessageLoop()), |
| 27 main_message_loop_(base::MessageLoopProxy::current()), | 28 main_message_loop_(base::MessageLoopProxy::current()), |
| 28 surface_id_(surface_id) { | 29 surface_id_(surface_id) { |
| 29 impl_message_loop_->PostTask( | 30 GLHelper* helper = ImageTransportFactory::GetInstance()->GetGLHelper(); |
| 30 FROM_HERE, | 31 main_thread_mailbox_ = new OwnedMailbox(helper); |
| 31 base::Bind(&ReflectorImpl::InitOnImplThread, this)); | 32 impl_message_loop_->PostTask(FROM_HERE, |
| 33 base::Bind(&ReflectorImpl::InitOnImplThread, | |
| 34 this, | |
| 35 main_thread_mailbox_->holder())); | |
| 32 } | 36 } |
| 33 | 37 |
| 34 void ReflectorImpl::InitOnImplThread() { | 38 void ReflectorImpl::InitOnImplThread(const gpu::MailboxHolder& mailbox_holder) { |
| 35 // Ignore if the reflector was shutdown before | 39 // Ignore if the reflector was shutdown before |
| 36 // initialized, or it's already initialized. | 40 // initialized, or it's already initialized. |
| 37 if (!output_surface_map_ || gl_helper_.get()) | 41 if (!output_surface_map_ || gl_helper_.get()) |
| 38 return; | 42 return; |
| 39 | 43 |
| 44 impl_thread_mailbox_holder_ = mailbox_holder; | |
| 45 | |
| 40 BrowserCompositorOutputSurface* source_surface = | 46 BrowserCompositorOutputSurface* source_surface = |
| 41 output_surface_map_->Lookup(surface_id_); | 47 output_surface_map_->Lookup(surface_id_); |
| 42 // Skip if the source surface isn't ready yet. This will be | 48 // Skip if the source surface isn't ready yet. This will be |
| 43 // initiailze when the source surface becomes ready. | 49 // initialized when the source surface becomes ready. |
| 44 if (!source_surface) | 50 if (!source_surface) |
| 45 return; | 51 return; |
| 46 | 52 |
| 47 AttachToOutputSurfaceOnImplThread(source_surface); | 53 AttachToOutputSurfaceOnImplThread(impl_thread_mailbox_holder_, |
| 48 // The shared texture doesn't have the data, so invokes full redraw | 54 source_surface); |
| 49 // now. | |
| 50 main_message_loop_->PostTask( | |
| 51 FROM_HERE, | |
| 52 base::Bind(&ReflectorImpl::FullRedrawContentOnMainThread, | |
| 53 scoped_refptr<ReflectorImpl>(this))); | |
| 54 } | 55 } |
| 55 | 56 |
| 56 void ReflectorImpl::OnSourceSurfaceReady(int surface_id) { | 57 void ReflectorImpl::OnSourceSurfaceReady( |
| 57 DCHECK_EQ(surface_id_, surface_id); | 58 BrowserCompositorOutputSurface* source_surface) { |
| 58 InitOnImplThread(); | 59 AttachToOutputSurfaceOnImplThread(impl_thread_mailbox_holder_, |
| 60 source_surface); | |
| 59 } | 61 } |
| 60 | 62 |
| 61 void ReflectorImpl::Shutdown() { | 63 void ReflectorImpl::Shutdown() { |
| 62 mirroring_compositor_ = NULL; | 64 main_thread_mailbox_ = NULL; |
| 65 mirroring_layer_->SetShowPaintedContent(); | |
| 63 mirroring_layer_ = NULL; | 66 mirroring_layer_ = NULL; |
| 64 { | |
| 65 base::AutoLock lock(texture_lock_); | |
| 66 texture_id_ = 0; | |
| 67 } | |
| 68 shared_texture_ = NULL; | |
| 69 impl_message_loop_->PostTask( | 67 impl_message_loop_->PostTask( |
| 70 FROM_HERE, | 68 FROM_HERE, |
| 71 base::Bind(&ReflectorImpl::ShutdownOnImplThread, this)); | 69 base::Bind(&ReflectorImpl::ShutdownOnImplThread, this)); |
| 72 } | 70 } |
| 73 | 71 |
| 72 void ReflectorImpl::DetachFromOutputSurface() { | |
| 73 DCHECK(output_surface_); | |
| 74 output_surface_->SetReflector(NULL); | |
| 75 DCHECK(impl_thread_texture_id_); | |
| 76 gl_helper_->DeleteTexture(impl_thread_texture_id_); | |
| 77 impl_thread_texture_id_ = 0; | |
| 78 gl_helper_.reset(); | |
| 79 output_surface_ = NULL; | |
| 80 } | |
| 81 | |
| 74 void ReflectorImpl::ShutdownOnImplThread() { | 82 void ReflectorImpl::ShutdownOnImplThread() { |
| 75 BrowserCompositorOutputSurface* output_surface = | 83 if (output_surface_) |
| 76 output_surface_map_->Lookup(surface_id_); | 84 DetachFromOutputSurface(); |
| 77 if (output_surface) | |
| 78 output_surface->SetReflector(NULL); | |
| 79 output_surface_map_ = NULL; | 85 output_surface_map_ = NULL; |
| 80 gl_helper_.reset(); | |
| 81 // The instance must be deleted on main thread. | 86 // The instance must be deleted on main thread. |
| 82 main_message_loop_->PostTask( | 87 main_message_loop_->PostTask( |
| 83 FROM_HERE, | 88 FROM_HERE, |
| 84 base::Bind(&ReflectorImpl::DeleteOnMainThread, | 89 base::Bind(&ReflectorImpl::DeleteOnMainThread, |
| 85 scoped_refptr<ReflectorImpl>(this))); | 90 scoped_refptr<ReflectorImpl>(this))); |
| 86 } | 91 } |
| 87 | 92 |
| 88 void ReflectorImpl::ReattachToOutputSurfaceFromMainThread( | 93 void ReflectorImpl::ReattachToOutputSurfaceFromMainThread( |
| 89 BrowserCompositorOutputSurface* output_surface) { | 94 BrowserCompositorOutputSurface* output_surface) { |
| 95 GLHelper* helper = ImageTransportFactory::GetInstance()->GetGLHelper(); | |
| 96 main_thread_mailbox_ = new OwnedMailbox(helper); | |
| 97 needs_set_mailbox_ = true; | |
| 90 impl_message_loop_->PostTask( | 98 impl_message_loop_->PostTask( |
| 91 FROM_HERE, | 99 FROM_HERE, |
| 92 base::Bind(&ReflectorImpl::AttachToOutputSurfaceOnImplThread, | 100 base::Bind(&ReflectorImpl::AttachToOutputSurfaceOnImplThread, |
| 93 this, output_surface)); | 101 this, |
| 102 main_thread_mailbox_->holder(), | |
| 103 output_surface)); | |
| 94 } | 104 } |
| 95 | 105 |
| 96 void ReflectorImpl::OnMirroringCompositorResized() { | 106 void ReflectorImpl::OnMirroringCompositorResized() { |
| 97 mirroring_compositor_->ScheduleFullRedraw(); | 107 mirroring_layer_->SchedulePaint(mirroring_layer_->bounds()); |
| 98 } | 108 } |
| 99 | 109 |
| 100 void ReflectorImpl::OnLostResources() { | 110 void ReflectorImpl::OnSwapBuffers() { |
| 101 mirroring_layer_->SetShowPaintedContent(); | 111 gfx::Size size = output_surface_->SurfaceSize(); |
| 102 } | 112 if (impl_thread_texture_id_) { |
| 103 | 113 gl_helper_->CopyTextureFullImage(impl_thread_texture_id_, size); |
| 104 void ReflectorImpl::OnReshape(gfx::Size size) { | 114 gl_helper_->Flush(); |
| 105 if (texture_size_ == size) | |
| 106 return; | |
| 107 texture_size_ = size; | |
| 108 { | |
| 109 base::AutoLock lock(texture_lock_); | |
| 110 if (texture_id_) { | |
| 111 gl_helper_->ResizeTexture(texture_id_, size); | |
| 112 gl_helper_->Flush(); | |
| 113 } | |
| 114 } | 115 } |
| 115 main_message_loop_->PostTask( | 116 main_message_loop_->PostTask( |
| 116 FROM_HERE, | 117 FROM_HERE, |
| 117 base::Bind(&ReflectorImpl::UpdateTextureSizeOnMainThread, | 118 base::Bind( |
| 118 this->AsWeakPtr(), | 119 &ReflectorImpl::FullRedrawOnMainThread, this->AsWeakPtr(), size)); |
| 119 texture_size_)); | |
| 120 } | |
| 121 | |
| 122 void ReflectorImpl::OnSwapBuffers() { | |
| 123 { | |
| 124 base::AutoLock lock(texture_lock_); | |
| 125 if (texture_id_) { | |
| 126 gl_helper_->CopyTextureFullImage(texture_id_, texture_size_); | |
| 127 gl_helper_->Flush(); | |
| 128 } | |
| 129 } | |
| 130 main_message_loop_->PostTask( | |
| 131 FROM_HERE, | |
| 132 base::Bind(&ReflectorImpl::FullRedrawOnMainThread, | |
| 133 this->AsWeakPtr(), | |
| 134 texture_size_)); | |
| 135 } | 120 } |
| 136 | 121 |
| 137 void ReflectorImpl::OnPostSubBuffer(gfx::Rect rect) { | 122 void ReflectorImpl::OnPostSubBuffer(gfx::Rect rect) { |
| 138 { | 123 if (impl_thread_texture_id_) { |
| 139 base::AutoLock lock(texture_lock_); | 124 gl_helper_->CopyTextureSubImage(impl_thread_texture_id_, rect); |
| 140 if (texture_id_) { | 125 gl_helper_->Flush(); |
| 141 gl_helper_->CopyTextureSubImage(texture_id_, rect); | |
| 142 gl_helper_->Flush(); | |
| 143 } | |
| 144 } | 126 } |
| 145 main_message_loop_->PostTask( | 127 main_message_loop_->PostTask( |
| 146 FROM_HERE, | 128 FROM_HERE, |
| 147 base::Bind(&ReflectorImpl::UpdateSubBufferOnMainThread, | 129 base::Bind(&ReflectorImpl::UpdateSubBufferOnMainThread, |
| 148 this->AsWeakPtr(), | 130 this->AsWeakPtr(), |
| 149 texture_size_, | 131 output_surface_->SurfaceSize(), |
| 150 rect)); | 132 rect)); |
| 151 } | 133 } |
| 152 | 134 |
| 153 void ReflectorImpl::CreateSharedTextureOnMainThread(gfx::Size size) { | |
| 154 { | |
| 155 base::AutoLock lock(texture_lock_); | |
| 156 texture_id_ = | |
| 157 ImageTransportFactory::GetInstance()->GetGLHelper()->CreateTexture(); | |
| 158 shared_texture_ = | |
| 159 ImageTransportFactory::GetInstance()->CreateOwnedTexture( | |
| 160 size, 1.0f, texture_id_); | |
| 161 ImageTransportFactory::GetInstance()->GetGLHelper()->Flush(); | |
| 162 } | |
| 163 mirroring_layer_->SetExternalTexture(shared_texture_.get()); | |
| 164 FullRedrawOnMainThread(size); | |
| 165 } | |
| 166 | |
| 167 ReflectorImpl::~ReflectorImpl() { | 135 ReflectorImpl::~ReflectorImpl() { |
| 168 // Make sure the reflector is deleted on main thread. | 136 // Make sure the reflector is deleted on main thread. |
| 169 DCHECK_EQ(main_message_loop_.get(), | 137 DCHECK_EQ(main_message_loop_.get(), |
| 170 base::MessageLoopProxy::current().get()); | 138 base::MessageLoopProxy::current().get()); |
| 171 } | 139 } |
| 172 | 140 |
| 141 static void ReleaseMailbox(scoped_refptr<OwnedMailbox> mailbox, | |
| 142 unsigned int sync_point, | |
| 143 bool is_lost) { | |
| 144 mailbox->UpdateSyncPoint(sync_point); | |
| 145 } | |
| 146 | |
| 173 void ReflectorImpl::AttachToOutputSurfaceOnImplThread( | 147 void ReflectorImpl::AttachToOutputSurfaceOnImplThread( |
| 148 const gpu::MailboxHolder& mailbox_holder, | |
| 174 BrowserCompositorOutputSurface* output_surface) { | 149 BrowserCompositorOutputSurface* output_surface) { |
| 150 if (output_surface == output_surface_) | |
| 151 return; | |
| 152 if (output_surface_) | |
| 153 DetachFromOutputSurface(); | |
| 154 output_surface_ = output_surface; | |
| 175 output_surface->context_provider()->BindToCurrentThread(); | 155 output_surface->context_provider()->BindToCurrentThread(); |
| 176 gl_helper_.reset( | 156 gl_helper_.reset( |
| 177 new GLHelper(output_surface->context_provider()->ContextGL(), | 157 new GLHelper(output_surface->context_provider()->ContextGL(), |
| 178 output_surface->context_provider()->ContextSupport())); | 158 output_surface->context_provider()->ContextSupport())); |
| 159 impl_thread_texture_id_ = gl_helper_->ConsumeMailboxToTexture( | |
| 160 mailbox_holder.mailbox, mailbox_holder.sync_point); | |
| 161 gl_helper_->ResizeTexture(impl_thread_texture_id_, | |
| 162 output_surface->SurfaceSize()); | |
| 163 gl_helper_->Flush(); | |
| 179 output_surface->SetReflector(this); | 164 output_surface->SetReflector(this); |
| 165 // The texture doesn't have the data, so invokes full redraw now. | |
| 180 main_message_loop_->PostTask( | 166 main_message_loop_->PostTask( |
| 181 FROM_HERE, | 167 FROM_HERE, |
| 182 base::Bind(&ReflectorImpl::CreateSharedTextureOnMainThread, | 168 base::Bind(&ReflectorImpl::FullRedrawContentOnMainThread, |
| 183 this->AsWeakPtr(), | 169 scoped_refptr<ReflectorImpl>(this))); |
| 184 texture_size_)); | |
| 185 } | 170 } |
| 186 | 171 |
| 187 void ReflectorImpl::UpdateTextureSizeOnMainThread(gfx::Size size) { | 172 void ReflectorImpl::UpdateTextureSizeOnMainThread(gfx::Size size) { |
| 188 if (!mirroring_layer_) | 173 if (!mirroring_layer_ || !main_thread_mailbox_ || |
| 174 main_thread_mailbox_->mailbox().IsZero()) | |
|
danakj
2014/04/08 16:08:01
I'm not sure where this method is all called, but
piman
2014/04/08 23:17:46
It can't fail in ReattachToOutputSurfaceFromMainTh
| |
| 189 return; | 175 return; |
| 176 if (needs_set_mailbox_) { | |
| 177 mirroring_layer_->SetTextureMailbox( | |
| 178 cc::TextureMailbox(main_thread_mailbox_->holder()), | |
| 179 cc::SingleReleaseCallback::Create( | |
| 180 base::Bind(ReleaseMailbox, main_thread_mailbox_)), | |
| 181 size); | |
| 182 needs_set_mailbox_ = false; | |
| 183 } else if (size != texture_size_) { | |
|
danakj
2014/04/08 16:08:01
This texture_size_ is only here to prevent extra c
piman
2014/04/08 23:17:46
I wanted to avoid full layer invalidations if the
| |
| 184 mirroring_layer_->SetTextureSize(size); | |
| 185 } else { | |
| 186 return; | |
| 187 } | |
| 190 mirroring_layer_->SetBounds(gfx::Rect(size)); | 188 mirroring_layer_->SetBounds(gfx::Rect(size)); |
| 189 texture_size_ = size; | |
| 191 } | 190 } |
| 192 | 191 |
| 193 void ReflectorImpl::FullRedrawOnMainThread(gfx::Size size) { | 192 void ReflectorImpl::FullRedrawOnMainThread(gfx::Size size) { |
| 194 if (!mirroring_compositor_) | 193 if (!mirroring_layer_) |
| 195 return; | 194 return; |
| 196 UpdateTextureSizeOnMainThread(size); | 195 UpdateTextureSizeOnMainThread(size); |
| 197 mirroring_compositor_->ScheduleFullRedraw(); | 196 mirroring_layer_->SchedulePaint(mirroring_layer_->bounds()); |
| 198 } | 197 } |
| 199 | 198 |
| 200 void ReflectorImpl::UpdateSubBufferOnMainThread(gfx::Size size, | 199 void ReflectorImpl::UpdateSubBufferOnMainThread(gfx::Size size, |
| 201 gfx::Rect rect) { | 200 gfx::Rect rect) { |
| 202 if (!mirroring_compositor_) | 201 if (!mirroring_layer_) |
| 203 return; | 202 return; |
| 204 UpdateTextureSizeOnMainThread(size); | 203 UpdateTextureSizeOnMainThread(size); |
| 205 // Flip the coordinates to compositor's one. | 204 // Flip the coordinates to compositor's one. |
| 206 int y = size.height() - rect.y() - rect.height(); | 205 int y = size.height() - rect.y() - rect.height(); |
| 207 gfx::Rect new_rect(rect.x(), y, rect.width(), rect.height()); | 206 gfx::Rect new_rect(rect.x(), y, rect.width(), rect.height()); |
| 208 mirroring_layer_->SchedulePaint(new_rect); | 207 mirroring_layer_->SchedulePaint(new_rect); |
| 209 } | 208 } |
| 210 | 209 |
| 211 void ReflectorImpl::FullRedrawContentOnMainThread() { | 210 void ReflectorImpl::FullRedrawContentOnMainThread() { |
| 212 mirrored_compositor_->ScheduleFullRedraw(); | 211 mirrored_compositor_->ScheduleFullRedraw(); |
| 213 } | 212 } |
| 214 | 213 |
| 215 } // namespace content | 214 } // namespace content |
| OLD | NEW |