Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / compositor / reflector_impl.cc
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/browser/compositor/owned_mailbox.h"
11 #include "content/common/gpu/client/gl_helper.h"
12 #include "ui/compositor/layer.h"
13
14 namespace content {
15
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()));
34 }
35
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) {}
42
43 ReflectorImpl::MainThreadData::~MainThreadData() {}
44
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) {}
50
51 ReflectorImpl::ImplThreadData::~ImplThreadData() {}
52
53 ReflectorImpl::ImplThreadData& ReflectorImpl::GetImpl() {
54   DCHECK(impl_message_loop_->BelongsToCurrentThread());
55   return impl_unsafe_;
56 }
57
58 ReflectorImpl::MainThreadData& ReflectorImpl::GetMain() {
59   DCHECK(main_message_loop_->BelongsToCurrentThread());
60   return main_unsafe_;
61 }
62
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;
69
70   impl.mailbox_holder = mailbox_holder;
71
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;
78
79   AttachToOutputSurfaceOnImplThread(impl.mailbox_holder, source_surface);
80 }
81
82 void ReflectorImpl::OnSourceSurfaceReady(
83     BrowserCompositorOutputSurface* source_surface) {
84   ImplThreadData& impl = GetImpl();
85   AttachToOutputSurfaceOnImplThread(impl.mailbox_holder, source_surface);
86 }
87
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));
95 }
96
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;
106 }
107
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)));
117 }
118
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));
132 }
133
134 void ReflectorImpl::OnMirroringCompositorResized() {
135   MainThreadData& main = GetMain();
136   main.mirroring_layer->SchedulePaint(main.mirroring_layer->bounds());
137 }
138
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();
145   }
146   main_message_loop_->PostTask(
147       FROM_HERE,
148       base::Bind(
149           &ReflectorImpl::FullRedrawOnMainThread, this->AsWeakPtr(), size));
150 }
151
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();
157   }
158   main_message_loop_->PostTask(
159       FROM_HERE,
160       base::Bind(&ReflectorImpl::UpdateSubBufferOnMainThread,
161                  this->AsWeakPtr(),
162                  impl.output_surface->SurfaceSize(),
163                  rect));
164 }
165
166 ReflectorImpl::~ReflectorImpl() {
167   // Make sure the reflector is deleted on main thread.
168   DCHECK_EQ(main_message_loop_.get(), base::MessageLoopProxy::current().get());
169 }
170
171 static void ReleaseMailbox(scoped_refptr<OwnedMailbox> mailbox,
172                            unsigned int sync_point,
173                            bool is_lost) {
174   mailbox->UpdateSyncPoint(sync_point);
175 }
176
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)));
200 }
201
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);
216   }
217   main.mirroring_layer->SetBounds(gfx::Rect(size));
218 }
219
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());
226 }
227
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);
238 }
239
240 void ReflectorImpl::FullRedrawContentOnMainThread() {
241   MainThreadData& main = GetMain();
242   main.mirrored_compositor->ScheduleFullRedraw();
243 }
244
245 }  // namespace content