Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / android / compositor / compositor_view.cc
blobff75b95fa2dfbd395b874293023e231d0dc0a936
1 // Copyright 2015 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 "chrome/browser/android/compositor/compositor_view.h"
7 #include <vector>
9 #include <android/bitmap.h>
10 #include <android/native_window_jni.h>
12 #include "base/android/build_info.h"
13 #include "base/android/jni_android.h"
14 #include "base/bind.h"
15 #include "base/command_line.h"
16 #include "base/id_map.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/rand_util.h"
19 #include "base/trace_event/trace_event.h"
20 #include "cc/layers/layer.h"
21 #include "cc/layers/layer_lists.h"
22 #include "cc/layers/solid_color_layer.h"
23 #include "cc/layers/texture_layer.h"
24 #include "chrome/browser/android/compositor/layer/toolbar_layer.h"
25 #include "chrome/browser/android/compositor/layer_title_cache.h"
26 #include "chrome/browser/android/compositor/scene_layer/scene_layer.h"
27 #include "chrome/browser/android/compositor/tab_content_manager.h"
28 #include "content/public/browser/android/compositor.h"
29 #include "content/public/browser/android/content_view_core.h"
30 #include "content/public/browser/child_process_data.h"
31 #include "content/public/browser/web_contents.h"
32 #include "content/public/common/process_type.h"
33 #include "jni/CompositorView_jni.h"
34 #include "third_party/skia/include/core/SkBitmap.h"
35 #include "ui/android/resources/resource_manager.h"
36 #include "ui/android/resources/ui_resource_provider.h"
37 #include "ui/android/window_android.h"
38 #include "ui/gfx/android/java_bitmap.h"
40 namespace chrome {
41 namespace android {
43 jlong Init(JNIEnv* env,
44 const JavaParamRef<jobject>& obj,
45 jboolean low_mem_device,
46 jint empty_background_color,
47 jlong native_window_android,
48 const JavaParamRef<jobject>& jlayer_title_cache,
49 const JavaParamRef<jobject>& jtab_content_manager) {
50 CompositorView* view;
51 ui::WindowAndroid* window_android =
52 reinterpret_cast<ui::WindowAndroid*>(native_window_android);
53 LayerTitleCache* layer_title_cache =
54 LayerTitleCache::FromJavaObject(jlayer_title_cache);
55 TabContentManager* tab_content_manager =
56 TabContentManager::FromJavaObject(jtab_content_manager);
58 DCHECK(tab_content_manager);
60 // TODO(clholgat): Remove the compositor tabstrip flag.
61 view = new CompositorView(env, obj, empty_background_color, low_mem_device,
62 window_android, layer_title_cache,
63 tab_content_manager);
65 ui::UIResourceProvider* ui_resource_provider = view->GetUIResourceProvider();
66 // TODO(dtrainor): Pass the ResourceManager on the Java side to the tree
67 // builders instead.
68 if (layer_title_cache)
69 layer_title_cache->SetResourceManager(view->GetResourceManager());
70 if (tab_content_manager)
71 tab_content_manager->SetUIResourceProvider(ui_resource_provider);
73 return reinterpret_cast<intptr_t>(view);
76 CompositorView::CompositorView(JNIEnv* env,
77 jobject obj,
78 jint empty_background_color,
79 jboolean low_mem_device,
80 ui::WindowAndroid* window_android,
81 LayerTitleCache* layer_title_cache,
82 TabContentManager* tab_content_manager)
83 : layer_title_cache_(layer_title_cache),
84 tab_content_manager_(tab_content_manager),
85 root_layer_(
86 cc::SolidColorLayer::Create(content::Compositor::LayerSettings())),
87 toolbar_layer_(ToolbarLayer::Create()),
88 scene_layer_(nullptr),
89 current_surface_format_(0),
90 content_width_(0),
91 content_height_(0),
92 overdraw_bottom_height_(0),
93 overlay_video_mode_(false),
94 empty_background_color_(empty_background_color),
95 weak_factory_(this) {
96 content::BrowserChildProcessObserver::Add(this);
97 obj_.Reset(env, obj);
98 compositor_.reset(content::Compositor::Create(this, window_android));
100 root_layer_->SetIsDrawable(true);
101 root_layer_->SetBackgroundColor(SK_ColorWHITE);
103 toolbar_layer_->layer()->SetHideLayerAndSubtree(true);
104 root_layer_->AddChild(toolbar_layer_->layer());
107 CompositorView::~CompositorView() {
108 content::BrowserChildProcessObserver::Remove(this);
110 // Explicitly reset these scoped_ptrs here because otherwise we callbacks will
111 // try to access member variables during destruction.
112 compositor_.reset(NULL);
115 void CompositorView::Destroy(JNIEnv* env, jobject object) {
116 delete this;
119 ui::ResourceManager* CompositorView::GetResourceManager() {
120 if (!compositor_)
121 return NULL;
122 return &compositor_->GetResourceManager();
125 base::android::ScopedJavaLocalRef<jobject> CompositorView::GetResourceManager(
126 JNIEnv* env,
127 jobject jobj) {
128 return compositor_->GetResourceManager().GetJavaObject();
131 void CompositorView::Layout() {
132 JNIEnv* env = base::android::AttachCurrentThread();
133 Java_CompositorView_onCompositorLayout(env, obj_.obj());
136 void CompositorView::OnSwapBuffersCompleted(int pending_swap_buffers) {
137 JNIEnv* env = base::android::AttachCurrentThread();
138 Java_CompositorView_onSwapBuffersCompleted(env, obj_.obj(),
139 pending_swap_buffers);
142 ui::UIResourceProvider* CompositorView::GetUIResourceProvider() {
143 if (!compositor_)
144 return NULL;
145 return &compositor_->GetUIResourceProvider();
148 void CompositorView::SurfaceCreated(JNIEnv* env, jobject object) {
149 compositor_->SetRootLayer(root_layer_);
150 current_surface_format_ = 0;
153 void CompositorView::SurfaceDestroyed(JNIEnv* env, jobject object) {
154 compositor_->SetSurface(NULL);
155 current_surface_format_ = 0;
158 void CompositorView::SurfaceChanged(JNIEnv* env,
159 jobject object,
160 jint format,
161 jint width,
162 jint height,
163 jobject surface) {
164 DCHECK(surface);
165 if (current_surface_format_ != format) {
166 current_surface_format_ = format;
167 compositor_->SetSurface(surface);
169 gfx::Size size = gfx::Size(width, height);
170 compositor_->SetWindowBounds(size);
171 content_width_ = size.width();
172 content_height_ = size.height();
173 root_layer_->SetBounds(gfx::Size(content_width_, content_height_));
176 void CompositorView::SetLayoutViewport(JNIEnv* env,
177 jobject object,
178 jfloat x,
179 jfloat y,
180 jfloat width,
181 jfloat height,
182 jfloat visible_x_offset,
183 jfloat visible_y_offset,
184 jfloat overdraw_bottom_height,
185 jfloat dp_to_pixel) {
186 overdraw_bottom_height_ = overdraw_bottom_height;
187 compositor_->setDeviceScaleFactor(dp_to_pixel);
188 root_layer_->SetBounds(gfx::Size(content_width_, content_height_));
191 void CompositorView::SetBackground(bool visible, SkColor color) {
192 if (overlay_video_mode_)
193 visible = false;
194 root_layer_->SetBackgroundColor(color);
195 root_layer_->SetIsDrawable(visible);
198 void CompositorView::SetOverlayVideoMode(JNIEnv* env,
199 jobject object,
200 bool enabled) {
201 if (overlay_video_mode_ == enabled)
202 return;
203 overlay_video_mode_ = enabled;
204 compositor_->SetHasTransparentBackground(enabled);
205 SetNeedsComposite(env, object);
208 void CompositorView::SetSceneLayer(JNIEnv* env,
209 jobject object,
210 jobject jscene_layer) {
211 SceneLayer* scene_layer = SceneLayer::FromJavaObject(env, jscene_layer);
213 if (scene_layer_ != scene_layer) {
214 // Old tree provider is being detached.
215 if (scene_layer_ != nullptr)
216 scene_layer_->OnDetach();
218 scene_layer_ = scene_layer;
220 if (scene_layer == nullptr) {
221 scene_layer_layer_ = nullptr;
222 return;
225 scene_layer_layer_ = scene_layer->layer();
226 root_layer_->InsertChild(scene_layer->layer(), 0);
229 if (scene_layer) {
230 SetBackground(scene_layer->ShouldShowBackground(),
231 scene_layer->GetBackgroundColor());
232 } else {
233 #ifndef NDEBUG
234 // This should not happen. Setting red background just for debugging.
235 SetBackground(true, SK_ColorRED);
236 #else
237 SetBackground(true, SK_ColorBLACK);
238 #endif
242 int CompositorView::GetUsableContentHeight() {
243 return std::max(content_height_ - overdraw_bottom_height_, 0);
246 void CompositorView::UpdateToolbarLayer(JNIEnv* env,
247 jobject object,
248 jint toolbar_resource_id,
249 jfloat top_offset,
250 jfloat brightness,
251 bool visible,
252 bool show_shadow) {
253 // Ensure the toolbar resource is available before making the layer visible.
254 ui::ResourceManager::Resource* resource =
255 compositor_->GetResourceManager().GetResource(
256 ui::ANDROID_RESOURCE_TYPE_DYNAMIC, toolbar_resource_id);
257 if (!resource)
258 visible = false;
260 toolbar_layer_->layer()->SetHideLayerAndSubtree(!visible);
261 if (visible) {
262 toolbar_layer_->layer()->SetPosition(gfx::PointF(0, top_offset));
263 toolbar_layer_->PushResource(
264 resource, SK_ColorWHITE, false, false, brightness);
266 // If we're at rest, hide the shadow. The Android view should be drawing.
267 toolbar_layer_->layer()->SetMasksToBounds(top_offset >= 0.f
268 && !show_shadow);
272 void CompositorView::UpdateProgressBar(JNIEnv* env,
273 jobject object,
274 jint progress_bar_x,
275 jint progress_bar_y,
276 jint progress_bar_width,
277 jint progress_bar_height,
278 jint progress_bar_color,
279 jint progress_bar_background_x,
280 jint progress_bar_background_y,
281 jint progress_bar_background_width,
282 jint progress_bar_background_height,
283 jint progress_bar_background_color) {
284 toolbar_layer_->UpdateProgressBar(progress_bar_x,
285 progress_bar_y,
286 progress_bar_width,
287 progress_bar_height,
288 progress_bar_color,
289 progress_bar_background_x,
290 progress_bar_background_y,
291 progress_bar_background_width,
292 progress_bar_background_height,
293 progress_bar_background_color);
296 void CompositorView::FinalizeLayers(JNIEnv* env, jobject jobj) {
297 UNSHIPPED_TRACE_EVENT0("compositor", "CompositorView::FinalizeLayers");
300 void CompositorView::SetNeedsComposite(JNIEnv* env, jobject object) {
301 compositor_->SetNeedsComposite();
304 void CompositorView::BrowserChildProcessHostDisconnected(
305 const content::ChildProcessData& data) {
306 LOG(WARNING) << "Child process disconnected (type=" << data.process_type
307 << ") pid=" << data.handle << ")";
308 if (base::android::BuildInfo::GetInstance()->sdk_int() <=
309 base::android::SDK_VERSION_JELLY_BEAN_MR2 &&
310 data.process_type == content::PROCESS_TYPE_GPU) {
311 JNIEnv* env = base::android::AttachCurrentThread();
312 compositor_->SetSurface(nullptr);
313 Java_CompositorView_onJellyBeanSurfaceDisconnectWorkaround(
314 env, obj_.obj(), overlay_video_mode_);
318 void CompositorView::BrowserChildProcessCrashed(
319 const content::ChildProcessData& data,
320 int exit_code) {
321 // The Android TERMINATION_STATUS_OOM_PROTECTED hack causes us to never go
322 // through here but through BrowserChildProcessHostDisconnected() instead.
325 // Register native methods
326 bool RegisterCompositorView(JNIEnv* env) {
327 return RegisterNativesImpl(env);
330 } // namespace android
331 } // namespace chrome