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 |