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.
5 #include "content/browser/compositor/reflector_impl.h"
8 #include "base/location.h"
9 #include "content/browser/compositor/browser_compositor_output_surface.h"
10 #include "content/browser/compositor/owned_mailbox.h"
11 #include "content/common/gpu/client/gl_helper.h"
12 #include "ui/compositor/layer.h"
16 ReflectorImpl::ReflectorImpl(
17 ui::Compositor
* mirrored_compositor
,
18 ui::Layer
* mirroring_layer
,
19 IDMap
<BrowserCompositorOutputSurface
>* output_surface_map
,
20 base::MessageLoopProxy
* compositor_thread_loop
,
22 : impl_unsafe_(output_surface_map
),
23 main_unsafe_(mirrored_compositor
, mirroring_layer
),
24 impl_message_loop_(compositor_thread_loop
),
25 main_message_loop_(base::MessageLoopProxy::current()),
26 surface_id_(surface_id
) {
27 GLHelper
* helper
= ImageTransportFactory::GetInstance()->GetGLHelper();
28 MainThreadData
& main
= GetMain();
29 main
.mailbox
= new OwnedMailbox(helper
);
30 impl_message_loop_
->PostTask(
33 &ReflectorImpl::InitOnImplThread
, this, main
.mailbox
->holder()));
36 ReflectorImpl::MainThreadData::MainThreadData(
37 ui::Compositor
* mirrored_compositor
,
38 ui::Layer
* mirroring_layer
)
39 : needs_set_mailbox(true),
40 mirrored_compositor(mirrored_compositor
),
41 mirroring_layer(mirroring_layer
) {}
43 ReflectorImpl::MainThreadData::~MainThreadData() {}
45 ReflectorImpl::ImplThreadData::ImplThreadData(
46 IDMap
<BrowserCompositorOutputSurface
>* output_surface_map
)
47 : output_surface_map(output_surface_map
),
51 ReflectorImpl::ImplThreadData::~ImplThreadData() {}
53 ReflectorImpl::ImplThreadData
& ReflectorImpl::GetImpl() {
54 DCHECK(impl_message_loop_
->BelongsToCurrentThread());
58 ReflectorImpl::MainThreadData
& ReflectorImpl::GetMain() {
59 DCHECK(main_message_loop_
->BelongsToCurrentThread());
63 void ReflectorImpl::InitOnImplThread(const gpu::MailboxHolder
& mailbox_holder
) {
64 ImplThreadData
& impl
= GetImpl();
65 // Ignore if the reflector was shutdown before
66 // initialized, or it's already initialized.
67 if (!impl
.output_surface_map
|| impl
.gl_helper
.get())
70 impl
.mailbox_holder
= mailbox_holder
;
72 BrowserCompositorOutputSurface
* source_surface
=
73 impl
.output_surface_map
->Lookup(surface_id_
);
74 // Skip if the source surface isn't ready yet. This will be
75 // initialized when the source surface becomes ready.
79 AttachToOutputSurfaceOnImplThread(impl
.mailbox_holder
, source_surface
);
82 void ReflectorImpl::OnSourceSurfaceReady(
83 BrowserCompositorOutputSurface
* source_surface
) {
84 ImplThreadData
& impl
= GetImpl();
85 AttachToOutputSurfaceOnImplThread(impl
.mailbox_holder
, source_surface
);
88 void ReflectorImpl::Shutdown() {
89 MainThreadData
& main
= GetMain();
91 main
.mirroring_layer
->SetShowSolidColorContent();
92 main
.mirroring_layer
= NULL
;
93 impl_message_loop_
->PostTask(
94 FROM_HERE
, base::Bind(&ReflectorImpl::ShutdownOnImplThread
, this));
97 void ReflectorImpl::DetachFromOutputSurface() {
98 ImplThreadData
& impl
= GetImpl();
99 DCHECK(impl
.output_surface
);
100 impl
.output_surface
->SetReflector(NULL
);
101 DCHECK(impl
.texture_id
);
102 impl
.gl_helper
->DeleteTexture(impl
.texture_id
);
104 impl
.gl_helper
.reset();
105 impl
.output_surface
= NULL
;
108 void ReflectorImpl::ShutdownOnImplThread() {
109 ImplThreadData
& impl
= GetImpl();
110 if (impl
.output_surface
)
111 DetachFromOutputSurface();
112 impl
.output_surface_map
= NULL
;
113 // The instance must be deleted on main thread.
114 main_message_loop_
->PostTask(FROM_HERE
,
115 base::Bind(&ReflectorImpl::DeleteOnMainThread
,
116 scoped_refptr
<ReflectorImpl
>(this)));
119 void ReflectorImpl::ReattachToOutputSurfaceFromMainThread(
120 BrowserCompositorOutputSurface
* output_surface
) {
121 MainThreadData
& main
= GetMain();
122 GLHelper
* helper
= ImageTransportFactory::GetInstance()->GetGLHelper();
123 main
.mailbox
= new OwnedMailbox(helper
);
124 main
.needs_set_mailbox
= true;
125 main
.mirroring_layer
->SetShowSolidColorContent();
126 impl_message_loop_
->PostTask(
128 base::Bind(&ReflectorImpl::AttachToOutputSurfaceOnImplThread
,
130 main
.mailbox
->holder(),
134 void ReflectorImpl::OnMirroringCompositorResized() {
135 MainThreadData
& main
= GetMain();
136 main
.mirroring_layer
->SchedulePaint(main
.mirroring_layer
->bounds());
139 void ReflectorImpl::OnSwapBuffers() {
140 ImplThreadData
& impl
= GetImpl();
141 gfx::Size size
= impl
.output_surface
->SurfaceSize();
142 if (impl
.texture_id
) {
143 impl
.gl_helper
->CopyTextureFullImage(impl
.texture_id
, size
);
144 impl
.gl_helper
->Flush();
146 main_message_loop_
->PostTask(
149 &ReflectorImpl::FullRedrawOnMainThread
, this->AsWeakPtr(), size
));
152 void ReflectorImpl::OnPostSubBuffer(gfx::Rect rect
) {
153 ImplThreadData
& impl
= GetImpl();
154 if (impl
.texture_id
) {
155 impl
.gl_helper
->CopyTextureSubImage(impl
.texture_id
, rect
);
156 impl
.gl_helper
->Flush();
158 main_message_loop_
->PostTask(
160 base::Bind(&ReflectorImpl::UpdateSubBufferOnMainThread
,
162 impl
.output_surface
->SurfaceSize(),
166 ReflectorImpl::~ReflectorImpl() {
167 // Make sure the reflector is deleted on main thread.
168 DCHECK_EQ(main_message_loop_
.get(), base::MessageLoopProxy::current().get());
171 static void ReleaseMailbox(scoped_refptr
<OwnedMailbox
> mailbox
,
172 unsigned int sync_point
,
174 mailbox
->UpdateSyncPoint(sync_point
);
177 void ReflectorImpl::AttachToOutputSurfaceOnImplThread(
178 const gpu::MailboxHolder
& mailbox_holder
,
179 BrowserCompositorOutputSurface
* output_surface
) {
180 ImplThreadData
& impl
= GetImpl();
181 if (output_surface
== impl
.output_surface
)
183 if (impl
.output_surface
)
184 DetachFromOutputSurface();
185 impl
.output_surface
= output_surface
;
186 output_surface
->context_provider()->BindToCurrentThread();
187 impl
.gl_helper
.reset(
188 new GLHelper(output_surface
->context_provider()->ContextGL(),
189 output_surface
->context_provider()->ContextSupport()));
190 impl
.texture_id
= impl
.gl_helper
->ConsumeMailboxToTexture(
191 mailbox_holder
.mailbox
, mailbox_holder
.sync_point
);
192 impl
.gl_helper
->ResizeTexture(impl
.texture_id
, output_surface
->SurfaceSize());
193 impl
.gl_helper
->Flush();
194 output_surface
->SetReflector(this);
195 // The texture doesn't have the data, so invokes full redraw now.
196 main_message_loop_
->PostTask(
198 base::Bind(&ReflectorImpl::FullRedrawContentOnMainThread
,
199 scoped_refptr
<ReflectorImpl
>(this)));
202 void ReflectorImpl::UpdateTextureSizeOnMainThread(gfx::Size size
) {
203 MainThreadData
& main
= GetMain();
204 if (!main
.mirroring_layer
|| !main
.mailbox
.get() ||
205 main
.mailbox
->mailbox().IsZero())
207 if (main
.needs_set_mailbox
) {
208 main
.mirroring_layer
->SetTextureMailbox(
209 cc::TextureMailbox(main
.mailbox
->holder()),
210 cc::SingleReleaseCallback::Create(
211 base::Bind(ReleaseMailbox
, main
.mailbox
)),
213 main
.needs_set_mailbox
= false;
215 main
.mirroring_layer
->SetTextureSize(size
);
217 main
.mirroring_layer
->SetBounds(gfx::Rect(size
));
220 void ReflectorImpl::FullRedrawOnMainThread(gfx::Size size
) {
221 MainThreadData
& main
= GetMain();
222 if (!main
.mirroring_layer
)
224 UpdateTextureSizeOnMainThread(size
);
225 main
.mirroring_layer
->SchedulePaint(main
.mirroring_layer
->bounds());
228 void ReflectorImpl::UpdateSubBufferOnMainThread(gfx::Size size
,
230 MainThreadData
& main
= GetMain();
231 if (!main
.mirroring_layer
)
233 UpdateTextureSizeOnMainThread(size
);
234 // Flip the coordinates to compositor's one.
235 int y
= size
.height() - rect
.y() - rect
.height();
236 gfx::Rect
new_rect(rect
.x(), y
, rect
.width(), rect
.height());
237 main
.mirroring_layer
->SchedulePaint(new_rect
);
240 void ReflectorImpl::FullRedrawContentOnMainThread() {
241 MainThreadData
& main
= GetMain();
242 main
.mirrored_compositor
->ScheduleFullRedraw();
245 } // namespace content