- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / aura / reflector_impl.cc
1 // Copyright (c) 2013 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/aura/reflector_impl.h"
6
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "content/browser/aura/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()->Context3d(),
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