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 : impl_unsafe_(output_surface_map), |
21 texture_size_(mirrored_compositor->size()), | 22 main_unsafe_(mirrored_compositor, mirroring_layer), |
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()), | 23 impl_message_loop_(ui::Compositor::GetCompositorMessageLoop()), |
27 main_message_loop_(base::MessageLoopProxy::current()), | 24 main_message_loop_(base::MessageLoopProxy::current()), |
28 surface_id_(surface_id) { | 25 surface_id_(surface_id) { |
| 26 GLHelper* helper = ImageTransportFactory::GetInstance()->GetGLHelper(); |
| 27 MainThreadData& main = GetMain(); |
| 28 main.mailbox = new OwnedMailbox(helper); |
29 impl_message_loop_->PostTask( | 29 impl_message_loop_->PostTask( |
30 FROM_HERE, | 30 FROM_HERE, |
31 base::Bind(&ReflectorImpl::InitOnImplThread, this)); | 31 base::Bind( |
32 } | 32 &ReflectorImpl::InitOnImplThread, this, main.mailbox->holder())); |
33 | 33 } |
34 void ReflectorImpl::InitOnImplThread() { | 34 |
| 35 ReflectorImpl::MainThreadData::MainThreadData( |
| 36 ui::Compositor* mirrored_compositor, |
| 37 ui::Layer* mirroring_layer) |
| 38 : needs_set_mailbox(true), |
| 39 mirrored_compositor(mirrored_compositor), |
| 40 mirroring_layer(mirroring_layer) {} |
| 41 |
| 42 ReflectorImpl::MainThreadData::~MainThreadData() {} |
| 43 |
| 44 ReflectorImpl::ImplThreadData::ImplThreadData( |
| 45 IDMap<BrowserCompositorOutputSurface>* output_surface_map) |
| 46 : output_surface_map(output_surface_map), |
| 47 output_surface(NULL), |
| 48 texture_id(0) {} |
| 49 |
| 50 ReflectorImpl::ImplThreadData::~ImplThreadData() {} |
| 51 |
| 52 ReflectorImpl::ImplThreadData& ReflectorImpl::GetImpl() { |
| 53 DCHECK(impl_message_loop_->BelongsToCurrentThread()); |
| 54 return impl_unsafe_; |
| 55 } |
| 56 |
| 57 ReflectorImpl::MainThreadData& ReflectorImpl::GetMain() { |
| 58 DCHECK(main_message_loop_->BelongsToCurrentThread()); |
| 59 return main_unsafe_; |
| 60 } |
| 61 |
| 62 void ReflectorImpl::InitOnImplThread(const gpu::MailboxHolder& mailbox_holder) { |
| 63 ImplThreadData& impl = GetImpl(); |
35 // Ignore if the reflector was shutdown before | 64 // Ignore if the reflector was shutdown before |
36 // initialized, or it's already initialized. | 65 // initialized, or it's already initialized. |
37 if (!output_surface_map_ || gl_helper_.get()) | 66 if (!impl.output_surface_map || impl.gl_helper.get()) |
38 return; | 67 return; |
| 68 |
| 69 impl.mailbox_holder = mailbox_holder; |
39 | 70 |
40 BrowserCompositorOutputSurface* source_surface = | 71 BrowserCompositorOutputSurface* source_surface = |
41 output_surface_map_->Lookup(surface_id_); | 72 impl.output_surface_map->Lookup(surface_id_); |
42 // Skip if the source surface isn't ready yet. This will be | 73 // Skip if the source surface isn't ready yet. This will be |
43 // initiailze when the source surface becomes ready. | 74 // initialized when the source surface becomes ready. |
44 if (!source_surface) | 75 if (!source_surface) |
45 return; | 76 return; |
46 | 77 |
47 AttachToOutputSurfaceOnImplThread(source_surface); | 78 AttachToOutputSurfaceOnImplThread(impl.mailbox_holder, source_surface); |
48 // The shared texture doesn't have the data, so invokes full redraw | 79 } |
49 // now. | 80 |
| 81 void ReflectorImpl::OnSourceSurfaceReady( |
| 82 BrowserCompositorOutputSurface* source_surface) { |
| 83 ImplThreadData& impl = GetImpl(); |
| 84 AttachToOutputSurfaceOnImplThread(impl.mailbox_holder, source_surface); |
| 85 } |
| 86 |
| 87 void ReflectorImpl::Shutdown() { |
| 88 MainThreadData& main = GetMain(); |
| 89 main.mailbox = NULL; |
| 90 main.mirroring_layer->SetShowPaintedContent(); |
| 91 main.mirroring_layer = NULL; |
| 92 impl_message_loop_->PostTask( |
| 93 FROM_HERE, base::Bind(&ReflectorImpl::ShutdownOnImplThread, this)); |
| 94 } |
| 95 |
| 96 void ReflectorImpl::DetachFromOutputSurface() { |
| 97 ImplThreadData& impl = GetImpl(); |
| 98 DCHECK(impl.output_surface); |
| 99 impl.output_surface->SetReflector(NULL); |
| 100 DCHECK(impl.texture_id); |
| 101 impl.gl_helper->DeleteTexture(impl.texture_id); |
| 102 impl.texture_id = 0; |
| 103 impl.gl_helper.reset(); |
| 104 impl.output_surface = NULL; |
| 105 } |
| 106 |
| 107 void ReflectorImpl::ShutdownOnImplThread() { |
| 108 ImplThreadData& impl = GetImpl(); |
| 109 if (impl.output_surface) |
| 110 DetachFromOutputSurface(); |
| 111 impl.output_surface_map = NULL; |
| 112 // The instance must be deleted on main thread. |
| 113 main_message_loop_->PostTask(FROM_HERE, |
| 114 base::Bind(&ReflectorImpl::DeleteOnMainThread, |
| 115 scoped_refptr<ReflectorImpl>(this))); |
| 116 } |
| 117 |
| 118 void ReflectorImpl::ReattachToOutputSurfaceFromMainThread( |
| 119 BrowserCompositorOutputSurface* output_surface) { |
| 120 MainThreadData& main = GetMain(); |
| 121 GLHelper* helper = ImageTransportFactory::GetInstance()->GetGLHelper(); |
| 122 main.mailbox = new OwnedMailbox(helper); |
| 123 main.needs_set_mailbox = true; |
| 124 main.mirroring_layer->SetShowPaintedContent(); |
| 125 impl_message_loop_->PostTask( |
| 126 FROM_HERE, |
| 127 base::Bind(&ReflectorImpl::AttachToOutputSurfaceOnImplThread, |
| 128 this, |
| 129 main.mailbox->holder(), |
| 130 output_surface)); |
| 131 } |
| 132 |
| 133 void ReflectorImpl::OnMirroringCompositorResized() { |
| 134 MainThreadData& main = GetMain(); |
| 135 main.mirroring_layer->SchedulePaint(main.mirroring_layer->bounds()); |
| 136 } |
| 137 |
| 138 void ReflectorImpl::OnSwapBuffers() { |
| 139 ImplThreadData& impl = GetImpl(); |
| 140 gfx::Size size = impl.output_surface->SurfaceSize(); |
| 141 if (impl.texture_id) { |
| 142 impl.gl_helper->CopyTextureFullImage(impl.texture_id, size); |
| 143 impl.gl_helper->Flush(); |
| 144 } |
| 145 main_message_loop_->PostTask( |
| 146 FROM_HERE, |
| 147 base::Bind( |
| 148 &ReflectorImpl::FullRedrawOnMainThread, this->AsWeakPtr(), size)); |
| 149 } |
| 150 |
| 151 void ReflectorImpl::OnPostSubBuffer(gfx::Rect rect) { |
| 152 ImplThreadData& impl = GetImpl(); |
| 153 if (impl.texture_id) { |
| 154 impl.gl_helper->CopyTextureSubImage(impl.texture_id, rect); |
| 155 impl.gl_helper->Flush(); |
| 156 } |
| 157 main_message_loop_->PostTask( |
| 158 FROM_HERE, |
| 159 base::Bind(&ReflectorImpl::UpdateSubBufferOnMainThread, |
| 160 this->AsWeakPtr(), |
| 161 impl.output_surface->SurfaceSize(), |
| 162 rect)); |
| 163 } |
| 164 |
| 165 ReflectorImpl::~ReflectorImpl() { |
| 166 // Make sure the reflector is deleted on main thread. |
| 167 DCHECK_EQ(main_message_loop_.get(), base::MessageLoopProxy::current().get()); |
| 168 } |
| 169 |
| 170 static void ReleaseMailbox(scoped_refptr<OwnedMailbox> mailbox, |
| 171 unsigned int sync_point, |
| 172 bool is_lost) { |
| 173 mailbox->UpdateSyncPoint(sync_point); |
| 174 } |
| 175 |
| 176 void ReflectorImpl::AttachToOutputSurfaceOnImplThread( |
| 177 const gpu::MailboxHolder& mailbox_holder, |
| 178 BrowserCompositorOutputSurface* output_surface) { |
| 179 ImplThreadData& impl = GetImpl(); |
| 180 if (output_surface == impl.output_surface) |
| 181 return; |
| 182 if (impl.output_surface) |
| 183 DetachFromOutputSurface(); |
| 184 impl.output_surface = output_surface; |
| 185 output_surface->context_provider()->BindToCurrentThread(); |
| 186 impl.gl_helper.reset( |
| 187 new GLHelper(output_surface->context_provider()->ContextGL(), |
| 188 output_surface->context_provider()->ContextSupport())); |
| 189 impl.texture_id = impl.gl_helper->ConsumeMailboxToTexture( |
| 190 mailbox_holder.mailbox, mailbox_holder.sync_point); |
| 191 impl.gl_helper->ResizeTexture(impl.texture_id, output_surface->SurfaceSize()); |
| 192 impl.gl_helper->Flush(); |
| 193 output_surface->SetReflector(this); |
| 194 // The texture doesn't have the data, so invokes full redraw now. |
50 main_message_loop_->PostTask( | 195 main_message_loop_->PostTask( |
51 FROM_HERE, | 196 FROM_HERE, |
52 base::Bind(&ReflectorImpl::FullRedrawContentOnMainThread, | 197 base::Bind(&ReflectorImpl::FullRedrawContentOnMainThread, |
53 scoped_refptr<ReflectorImpl>(this))); | 198 scoped_refptr<ReflectorImpl>(this))); |
54 } | 199 } |
55 | 200 |
56 void ReflectorImpl::OnSourceSurfaceReady(int surface_id) { | 201 void ReflectorImpl::UpdateTextureSizeOnMainThread(gfx::Size size) { |
57 DCHECK_EQ(surface_id_, surface_id); | 202 MainThreadData& main = GetMain(); |
58 InitOnImplThread(); | 203 if (!main.mirroring_layer || !main.mailbox || |
59 } | 204 main.mailbox->mailbox().IsZero()) |
60 | 205 return; |
61 void ReflectorImpl::Shutdown() { | 206 if (main.needs_set_mailbox) { |
62 mirroring_compositor_ = NULL; | 207 main.mirroring_layer->SetTextureMailbox( |
63 mirroring_layer_ = NULL; | 208 cc::TextureMailbox(main.mailbox->holder()), |
64 { | 209 cc::SingleReleaseCallback::Create( |
65 base::AutoLock lock(texture_lock_); | 210 base::Bind(ReleaseMailbox, main.mailbox)), |
66 texture_id_ = 0; | 211 size); |
| 212 main.needs_set_mailbox = false; |
| 213 } else { |
| 214 main.mirroring_layer->SetTextureSize(size); |
67 } | 215 } |
68 shared_texture_ = NULL; | 216 main.mirroring_layer->SetBounds(gfx::Rect(size)); |
69 impl_message_loop_->PostTask( | |
70 FROM_HERE, | |
71 base::Bind(&ReflectorImpl::ShutdownOnImplThread, this)); | |
72 } | |
73 | |
74 void ReflectorImpl::ShutdownOnImplThread() { | |
75 BrowserCompositorOutputSurface* output_surface = | |
76 output_surface_map_->Lookup(surface_id_); | |
77 if (output_surface) | |
78 output_surface->SetReflector(NULL); | |
79 output_surface_map_ = NULL; | |
80 gl_helper_.reset(); | |
81 // The instance must be deleted on main thread. | |
82 main_message_loop_->PostTask( | |
83 FROM_HERE, | |
84 base::Bind(&ReflectorImpl::DeleteOnMainThread, | |
85 scoped_refptr<ReflectorImpl>(this))); | |
86 } | |
87 | |
88 void ReflectorImpl::ReattachToOutputSurfaceFromMainThread( | |
89 BrowserCompositorOutputSurface* output_surface) { | |
90 impl_message_loop_->PostTask( | |
91 FROM_HERE, | |
92 base::Bind(&ReflectorImpl::AttachToOutputSurfaceOnImplThread, | |
93 this, output_surface)); | |
94 } | |
95 | |
96 void ReflectorImpl::OnMirroringCompositorResized() { | |
97 mirroring_compositor_->ScheduleFullRedraw(); | |
98 } | |
99 | |
100 void ReflectorImpl::OnLostResources() { | |
101 mirroring_layer_->SetShowPaintedContent(); | |
102 } | |
103 | |
104 void ReflectorImpl::OnReshape(gfx::Size size) { | |
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 main_message_loop_->PostTask( | |
116 FROM_HERE, | |
117 base::Bind(&ReflectorImpl::UpdateTextureSizeOnMainThread, | |
118 this->AsWeakPtr(), | |
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 } | |
136 | |
137 void ReflectorImpl::OnPostSubBuffer(gfx::Rect rect) { | |
138 { | |
139 base::AutoLock lock(texture_lock_); | |
140 if (texture_id_) { | |
141 gl_helper_->CopyTextureSubImage(texture_id_, rect); | |
142 gl_helper_->Flush(); | |
143 } | |
144 } | |
145 main_message_loop_->PostTask( | |
146 FROM_HERE, | |
147 base::Bind(&ReflectorImpl::UpdateSubBufferOnMainThread, | |
148 this->AsWeakPtr(), | |
149 texture_size_, | |
150 rect)); | |
151 } | |
152 | |
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() { | |
168 // Make sure the reflector is deleted on main thread. | |
169 DCHECK_EQ(main_message_loop_.get(), | |
170 base::MessageLoopProxy::current().get()); | |
171 } | |
172 | |
173 void ReflectorImpl::AttachToOutputSurfaceOnImplThread( | |
174 BrowserCompositorOutputSurface* output_surface) { | |
175 output_surface->context_provider()->BindToCurrentThread(); | |
176 gl_helper_.reset( | |
177 new GLHelper(output_surface->context_provider()->ContextGL(), | |
178 output_surface->context_provider()->ContextSupport())); | |
179 output_surface->SetReflector(this); | |
180 main_message_loop_->PostTask( | |
181 FROM_HERE, | |
182 base::Bind(&ReflectorImpl::CreateSharedTextureOnMainThread, | |
183 this->AsWeakPtr(), | |
184 texture_size_)); | |
185 } | |
186 | |
187 void ReflectorImpl::UpdateTextureSizeOnMainThread(gfx::Size size) { | |
188 if (!mirroring_layer_) | |
189 return; | |
190 mirroring_layer_->SetBounds(gfx::Rect(size)); | |
191 } | 217 } |
192 | 218 |
193 void ReflectorImpl::FullRedrawOnMainThread(gfx::Size size) { | 219 void ReflectorImpl::FullRedrawOnMainThread(gfx::Size size) { |
194 if (!mirroring_compositor_) | 220 MainThreadData& main = GetMain(); |
| 221 if (!main.mirroring_layer) |
195 return; | 222 return; |
196 UpdateTextureSizeOnMainThread(size); | 223 UpdateTextureSizeOnMainThread(size); |
197 mirroring_compositor_->ScheduleFullRedraw(); | 224 main.mirroring_layer->SchedulePaint(main.mirroring_layer->bounds()); |
198 } | 225 } |
199 | 226 |
200 void ReflectorImpl::UpdateSubBufferOnMainThread(gfx::Size size, | 227 void ReflectorImpl::UpdateSubBufferOnMainThread(gfx::Size size, |
201 gfx::Rect rect) { | 228 gfx::Rect rect) { |
202 if (!mirroring_compositor_) | 229 MainThreadData& main = GetMain(); |
| 230 if (!main.mirroring_layer) |
203 return; | 231 return; |
204 UpdateTextureSizeOnMainThread(size); | 232 UpdateTextureSizeOnMainThread(size); |
205 // Flip the coordinates to compositor's one. | 233 // Flip the coordinates to compositor's one. |
206 int y = size.height() - rect.y() - rect.height(); | 234 int y = size.height() - rect.y() - rect.height(); |
207 gfx::Rect new_rect(rect.x(), y, rect.width(), rect.height()); | 235 gfx::Rect new_rect(rect.x(), y, rect.width(), rect.height()); |
208 mirroring_layer_->SchedulePaint(new_rect); | 236 main.mirroring_layer->SchedulePaint(new_rect); |
209 } | 237 } |
210 | 238 |
211 void ReflectorImpl::FullRedrawContentOnMainThread() { | 239 void ReflectorImpl::FullRedrawContentOnMainThread() { |
212 mirrored_compositor_->ScheduleFullRedraw(); | 240 MainThreadData& main = GetMain(); |
| 241 main.mirrored_compositor->ScheduleFullRedraw(); |
213 } | 242 } |
214 | 243 |
215 } // namespace content | 244 } // namespace content |
OLD | NEW |