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/common/gpu/client/gl_helper.h"
11 #include "ui/compositor/layer.h"
15 ReflectorImpl::ReflectorImpl(
16 ui::Compositor
* mirrored_compositor
,
17 ui::Layer
* mirroring_layer
,
18 IDMap
<BrowserCompositorOutputSurface
>* output_surface_map
,
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 impl_message_loop_
->PostTask(
31 base::Bind(&ReflectorImpl::InitOnImplThread
, this));
34 void ReflectorImpl::InitOnImplThread() {
35 // Ignore if the reflector was shutdown before
36 // initialized, or it's already initialized.
37 if (!output_surface_map_
|| gl_helper_
.get())
40 BrowserCompositorOutputSurface
* source_surface
=
41 output_surface_map_
->Lookup(surface_id_
);
42 // Skip if the source surface isn't ready yet. This will be
43 // initiailze when the source surface becomes ready.
47 AttachToOutputSurfaceOnImplThread(source_surface
);
48 // The shared texture doesn't have the data, so invokes full redraw
50 main_message_loop_
->PostTask(
52 base::Bind(&ReflectorImpl::FullRedrawContentOnMainThread
,
53 scoped_refptr
<ReflectorImpl
>(this)));
56 void ReflectorImpl::OnSourceSurfaceReady(int surface_id
) {
57 DCHECK_EQ(surface_id_
, surface_id
);
61 void ReflectorImpl::Shutdown() {
62 mirroring_compositor_
= NULL
;
63 mirroring_layer_
= NULL
;
65 base::AutoLock
lock(texture_lock_
);
68 shared_texture_
= NULL
;
69 impl_message_loop_
->PostTask(
71 base::Bind(&ReflectorImpl::ShutdownOnImplThread
, this));
74 void ReflectorImpl::ShutdownOnImplThread() {
75 BrowserCompositorOutputSurface
* output_surface
=
76 output_surface_map_
->Lookup(surface_id_
);
78 output_surface
->SetReflector(NULL
);
79 output_surface_map_
= NULL
;
81 // The instance must be deleted on main thread.
82 main_message_loop_
->PostTask(
84 base::Bind(&ReflectorImpl::DeleteOnMainThread
,
85 scoped_refptr
<ReflectorImpl
>(this)));
88 void ReflectorImpl::ReattachToOutputSurfaceFromMainThread(
89 BrowserCompositorOutputSurface
* output_surface
) {
90 impl_message_loop_
->PostTask(
92 base::Bind(&ReflectorImpl::AttachToOutputSurfaceOnImplThread
,
93 this, output_surface
));
96 void ReflectorImpl::OnMirroringCompositorResized() {
97 mirroring_compositor_
->ScheduleFullRedraw();
100 void ReflectorImpl::OnLostResources() {
101 mirroring_layer_
->SetShowPaintedContent();
104 void ReflectorImpl::OnReshape(gfx::Size size
) {
105 if (texture_size_
== size
)
107 texture_size_
= size
;
109 base::AutoLock
lock(texture_lock_
);
111 gl_helper_
->ResizeTexture(texture_id_
, size
);
115 main_message_loop_
->PostTask(
117 base::Bind(&ReflectorImpl::UpdateTextureSizeOnMainThread
,
122 void ReflectorImpl::OnSwapBuffers() {
124 base::AutoLock
lock(texture_lock_
);
126 gl_helper_
->CopyTextureFullImage(texture_id_
, texture_size_
);
130 main_message_loop_
->PostTask(
132 base::Bind(&ReflectorImpl::FullRedrawOnMainThread
,
137 void ReflectorImpl::OnPostSubBuffer(gfx::Rect rect
) {
139 base::AutoLock
lock(texture_lock_
);
141 gl_helper_
->CopyTextureSubImage(texture_id_
, rect
);
145 main_message_loop_
->PostTask(
147 base::Bind(&ReflectorImpl::UpdateSubBufferOnMainThread
,
153 void ReflectorImpl::CreateSharedTextureOnMainThread(gfx::Size size
) {
155 base::AutoLock
lock(texture_lock_
);
157 ImageTransportFactory::GetInstance()->GetGLHelper()->CreateTexture();
159 ImageTransportFactory::GetInstance()->CreateOwnedTexture(
160 size
, 1.0f
, texture_id_
);
162 mirroring_layer_
->SetExternalTexture(shared_texture_
.get());
163 FullRedrawOnMainThread(size
);
166 ReflectorImpl::~ReflectorImpl() {
167 // Make sure the reflector is deleted on main thread.
168 DCHECK_EQ(main_message_loop_
.get(),
169 base::MessageLoopProxy::current().get());
172 void ReflectorImpl::AttachToOutputSurfaceOnImplThread(
173 BrowserCompositorOutputSurface
* output_surface
) {
174 output_surface
->context_provider()->BindToCurrentThread();
176 new GLHelper(output_surface
->context_provider()->ContextGL(),
177 output_surface
->context_provider()->ContextSupport()));
178 output_surface
->SetReflector(this);
179 main_message_loop_
->PostTask(
181 base::Bind(&ReflectorImpl::CreateSharedTextureOnMainThread
,
186 void ReflectorImpl::UpdateTextureSizeOnMainThread(gfx::Size size
) {
187 if (!mirroring_layer_
)
189 mirroring_layer_
->SetBounds(gfx::Rect(size
));
192 void ReflectorImpl::FullRedrawOnMainThread(gfx::Size size
) {
193 if (!mirroring_compositor_
)
195 UpdateTextureSizeOnMainThread(size
);
196 mirroring_compositor_
->ScheduleFullRedraw();
199 void ReflectorImpl::UpdateSubBufferOnMainThread(gfx::Size size
,
201 if (!mirroring_compositor_
)
203 UpdateTextureSizeOnMainThread(size
);
204 // Flip the coordinates to compositor's one.
205 int y
= size
.height() - rect
.y() - rect
.height();
206 gfx::Rect
new_rect(rect
.x(), y
, rect
.width(), rect
.height());
207 mirroring_layer_
->SchedulePaint(new_rect
);
210 void ReflectorImpl::FullRedrawContentOnMainThread() {
211 mirrored_compositor_
->ScheduleFullRedraw();
214 } // namespace content