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"
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"
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
) {
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
,
65 ui::UIResourceProvider
* ui_resource_provider
= view
->GetUIResourceProvider();
66 // TODO(dtrainor): Pass the ResourceManager on the Java side to the tree
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
,
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
),
86 cc::SolidColorLayer::Create(content::Compositor::LayerSettings())),
87 toolbar_layer_(ToolbarLayer::Create()),
88 scene_layer_(nullptr),
89 current_surface_format_(0),
92 overdraw_bottom_height_(0),
93 overlay_video_mode_(false),
94 empty_background_color_(empty_background_color
),
96 content::BrowserChildProcessObserver::Add(this);
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
) {
119 ui::ResourceManager
* CompositorView::GetResourceManager() {
122 return &compositor_
->GetResourceManager();
125 base::android::ScopedJavaLocalRef
<jobject
> CompositorView::GetResourceManager(
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() {
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
,
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
,
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_
)
194 root_layer_
->SetBackgroundColor(color
);
195 root_layer_
->SetIsDrawable(visible
);
198 void CompositorView::SetOverlayVideoMode(JNIEnv
* env
,
201 if (overlay_video_mode_
== enabled
)
203 overlay_video_mode_
= enabled
;
204 compositor_
->SetHasTransparentBackground(enabled
);
205 SetNeedsComposite(env
, object
);
208 void CompositorView::SetSceneLayer(JNIEnv
* env
,
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;
225 scene_layer_layer_
= scene_layer
->layer();
226 root_layer_
->InsertChild(scene_layer
->layer(), 0);
230 SetBackground(scene_layer
->ShouldShowBackground(),
231 scene_layer
->GetBackgroundColor());
234 // This should not happen. Setting red background just for debugging.
235 SetBackground(true, SK_ColorRED
);
237 SetBackground(true, SK_ColorBLACK
);
242 int CompositorView::GetUsableContentHeight() {
243 return std::max(content_height_
- overdraw_bottom_height_
, 0);
246 void CompositorView::UpdateToolbarLayer(JNIEnv
* env
,
248 jint toolbar_resource_id
,
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
);
260 toolbar_layer_
->layer()->SetHideLayerAndSubtree(!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
272 void CompositorView::UpdateProgressBar(JNIEnv
* env
,
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
,
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
,
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