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 |