Blink roll 25b6bd3a7a131ffe68d809546ad1a20707915cdc:3a503f41ae42e5b79cfcd2ff10e65afde...
[chromium-blink-merge.git] / content / browser / compositor / reflector_impl.cc
blobac3bdda748e0d8c56bf346ddb3f4a73ec643f08d
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"
7 #include "base/bind.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"
14 namespace content {
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,
21 int surface_id)
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(
31 FROM_HERE,
32 base::Bind(
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),
48 output_surface(NULL),
49 texture_id(0) {}
51 ReflectorImpl::ImplThreadData::~ImplThreadData() {}
53 ReflectorImpl::ImplThreadData& ReflectorImpl::GetImpl() {
54 DCHECK(impl_message_loop_->BelongsToCurrentThread());
55 return impl_unsafe_;
58 ReflectorImpl::MainThreadData& ReflectorImpl::GetMain() {
59 DCHECK(main_message_loop_->BelongsToCurrentThread());
60 return main_unsafe_;
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())
68 return;
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.
76 if (!source_surface)
77 return;
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();
90 main.mailbox = NULL;
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);
103 impl.texture_id = 0;
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(
127 FROM_HERE,
128 base::Bind(&ReflectorImpl::AttachToOutputSurfaceOnImplThread,
129 this,
130 main.mailbox->holder(),
131 output_surface));
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(
147 FROM_HERE,
148 base::Bind(
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(
159 FROM_HERE,
160 base::Bind(&ReflectorImpl::UpdateSubBufferOnMainThread,
161 this->AsWeakPtr(),
162 impl.output_surface->SurfaceSize(),
163 rect));
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,
173 bool is_lost) {
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)
182 return;
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(
197 FROM_HERE,
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())
206 return;
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)),
212 size);
213 main.needs_set_mailbox = false;
214 } else {
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)
223 return;
224 UpdateTextureSizeOnMainThread(size);
225 main.mirroring_layer->SchedulePaint(main.mirroring_layer->bounds());
228 void ReflectorImpl::UpdateSubBufferOnMainThread(gfx::Size size,
229 gfx::Rect rect) {
230 MainThreadData& main = GetMain();
231 if (!main.mirroring_layer)
232 return;
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