| OLD | NEW |
| (Empty) |
| 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/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()->ContextGL(), | |
| 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 | |
| OLD | NEW |