OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #include "chrome/browser/android/compositor/compositor_view.h" |
| 6 |
| 7 #include <vector> |
| 8 |
| 9 #include <android/bitmap.h> |
| 10 #include <android/native_window_jni.h> |
| 11 |
| 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" |
| 39 |
| 40 namespace chrome { |
| 41 namespace android { |
| 42 |
| 43 jlong Init(JNIEnv* env, |
| 44 jobject obj, |
| 45 jboolean low_mem_device, |
| 46 jint empty_background_color, |
| 47 jlong native_window_android, |
| 48 jobject jlayer_title_cache, |
| 49 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); |
| 57 |
| 58 DCHECK(tab_content_manager); |
| 59 |
| 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); |
| 64 |
| 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); |
| 72 |
| 73 return reinterpret_cast<intptr_t>(view); |
| 74 } |
| 75 |
| 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_(cc::SolidColorLayer::Create()), |
| 86 toolbar_layer_(ToolbarLayer::Create()), |
| 87 scene_layer_(nullptr), |
| 88 current_surface_format_(0), |
| 89 content_width_(0), |
| 90 content_height_(0), |
| 91 overdraw_bottom_height_(0), |
| 92 overlay_video_mode_(false), |
| 93 empty_background_color_(empty_background_color), |
| 94 weak_factory_(this) { |
| 95 content::BrowserChildProcessObserver::Add(this); |
| 96 obj_.Reset(env, obj); |
| 97 compositor_.reset(content::Compositor::Create(this, window_android)); |
| 98 |
| 99 root_layer_->SetIsDrawable(true); |
| 100 root_layer_->SetBackgroundColor(SK_ColorWHITE); |
| 101 |
| 102 toolbar_layer_->layer()->SetHideLayerAndSubtree(true); |
| 103 root_layer_->AddChild(toolbar_layer_->layer()); |
| 104 } |
| 105 |
| 106 CompositorView::~CompositorView() { |
| 107 content::BrowserChildProcessObserver::Remove(this); |
| 108 |
| 109 // Explicitly reset these scoped_ptrs here because otherwise we callbacks will |
| 110 // try to access member variables during destruction. |
| 111 compositor_.reset(NULL); |
| 112 } |
| 113 |
| 114 void CompositorView::Destroy(JNIEnv* env, jobject object) { |
| 115 delete this; |
| 116 } |
| 117 |
| 118 ui::ResourceManager* CompositorView::GetResourceManager() { |
| 119 if (!compositor_) |
| 120 return NULL; |
| 121 return &compositor_->GetResourceManager(); |
| 122 } |
| 123 |
| 124 base::android::ScopedJavaLocalRef<jobject> CompositorView::GetResourceManager( |
| 125 JNIEnv* env, |
| 126 jobject jobj) { |
| 127 return compositor_->GetResourceManager().GetJavaObject(); |
| 128 } |
| 129 |
| 130 void CompositorView::Layout() { |
| 131 JNIEnv* env = base::android::AttachCurrentThread(); |
| 132 Java_CompositorView_onCompositorLayout(env, obj_.obj()); |
| 133 } |
| 134 |
| 135 void CompositorView::OnSwapBuffersCompleted(int pending_swap_buffers) { |
| 136 JNIEnv* env = base::android::AttachCurrentThread(); |
| 137 Java_CompositorView_onSwapBuffersCompleted(env, obj_.obj(), |
| 138 pending_swap_buffers); |
| 139 } |
| 140 |
| 141 ui::UIResourceProvider* CompositorView::GetUIResourceProvider() { |
| 142 if (!compositor_) |
| 143 return NULL; |
| 144 return &compositor_->GetUIResourceProvider(); |
| 145 } |
| 146 |
| 147 void CompositorView::SurfaceCreated(JNIEnv* env, jobject object) { |
| 148 compositor_->SetRootLayer(root_layer_); |
| 149 current_surface_format_ = 0; |
| 150 } |
| 151 |
| 152 void CompositorView::SurfaceDestroyed(JNIEnv* env, jobject object) { |
| 153 compositor_->SetSurface(NULL); |
| 154 current_surface_format_ = 0; |
| 155 } |
| 156 |
| 157 void CompositorView::SurfaceChanged(JNIEnv* env, |
| 158 jobject object, |
| 159 jint format, |
| 160 jint width, |
| 161 jint height, |
| 162 jobject surface) { |
| 163 DCHECK(surface); |
| 164 if (current_surface_format_ != format) { |
| 165 current_surface_format_ = format; |
| 166 compositor_->SetSurface(surface); |
| 167 } |
| 168 gfx::Size size = gfx::Size(width, height); |
| 169 compositor_->SetWindowBounds(size); |
| 170 content_width_ = size.width(); |
| 171 content_height_ = size.height(); |
| 172 root_layer_->SetBounds(gfx::Size(content_width_, content_height_)); |
| 173 } |
| 174 |
| 175 void CompositorView::SetLayoutViewport(JNIEnv* env, |
| 176 jobject object, |
| 177 jfloat x, |
| 178 jfloat y, |
| 179 jfloat width, |
| 180 jfloat height, |
| 181 jfloat visible_x_offset, |
| 182 jfloat visible_y_offset, |
| 183 jfloat overdraw_bottom_height, |
| 184 jfloat dp_to_pixel) { |
| 185 overdraw_bottom_height_ = overdraw_bottom_height; |
| 186 compositor_->setDeviceScaleFactor(dp_to_pixel); |
| 187 root_layer_->SetBounds(gfx::Size(content_width_, content_height_)); |
| 188 } |
| 189 |
| 190 void CompositorView::SetBackground(bool visible, SkColor color) { |
| 191 if (overlay_video_mode_) |
| 192 visible = false; |
| 193 root_layer_->SetBackgroundColor(color); |
| 194 root_layer_->SetIsDrawable(visible); |
| 195 } |
| 196 |
| 197 void CompositorView::SetOverlayVideoMode(JNIEnv* env, |
| 198 jobject object, |
| 199 bool enabled) { |
| 200 if (overlay_video_mode_ == enabled) |
| 201 return; |
| 202 overlay_video_mode_ = enabled; |
| 203 compositor_->SetHasTransparentBackground(enabled); |
| 204 SetNeedsComposite(env, object); |
| 205 } |
| 206 |
| 207 void CompositorView::SetSceneLayer(JNIEnv* env, |
| 208 jobject object, |
| 209 jobject jscene_layer) { |
| 210 SceneLayer* scene_layer = SceneLayer::FromJavaObject(env, jscene_layer); |
| 211 |
| 212 if (scene_layer_ != scene_layer) { |
| 213 // Old tree provider is being detached. |
| 214 if (scene_layer_ != nullptr) |
| 215 scene_layer_->OnDetach(); |
| 216 |
| 217 scene_layer_ = scene_layer; |
| 218 |
| 219 if (scene_layer == nullptr) { |
| 220 scene_layer_layer_ = nullptr; |
| 221 return; |
| 222 } |
| 223 |
| 224 scene_layer_layer_ = scene_layer->layer(); |
| 225 root_layer_->InsertChild(scene_layer->layer(), 0); |
| 226 } |
| 227 |
| 228 if (scene_layer) { |
| 229 SetBackground(scene_layer->ShouldShowBackground(), |
| 230 scene_layer->GetBackgroundColor()); |
| 231 } else { |
| 232 #ifndef NDEBUG |
| 233 // This should not happen. Setting red background just for debugging. |
| 234 SetBackground(true, SK_ColorRED); |
| 235 #else |
| 236 SetBackground(true, SK_ColorBLACK); |
| 237 #endif |
| 238 } |
| 239 } |
| 240 |
| 241 int CompositorView::GetUsableContentHeight() { |
| 242 return std::max(content_height_ - overdraw_bottom_height_, 0); |
| 243 } |
| 244 |
| 245 void CompositorView::UpdateToolbarLayer(JNIEnv* env, |
| 246 jobject object, |
| 247 jint toolbar_resource_id, |
| 248 jint progress_resource_id, |
| 249 jfloat top_offset, |
| 250 bool visible) { |
| 251 // Ensure the toolbar resource is available before making the layer visible. |
| 252 ui::ResourceManager::Resource* resource = |
| 253 compositor_->GetResourceManager().GetResource( |
| 254 ui::ANDROID_RESOURCE_TYPE_DYNAMIC, toolbar_resource_id); |
| 255 if (!resource) |
| 256 visible = false; |
| 257 |
| 258 toolbar_layer_->layer()->SetHideLayerAndSubtree(!visible); |
| 259 if (visible) { |
| 260 toolbar_layer_->layer()->SetPosition(gfx::PointF(0, top_offset)); |
| 261 |
| 262 ui::ResourceManager::Resource* progress_resource = |
| 263 compositor_->GetResourceManager().GetResource( |
| 264 ui::ANDROID_RESOURCE_TYPE_DYNAMIC, progress_resource_id); |
| 265 toolbar_layer_->PushResource(resource, progress_resource, false, false, |
| 266 false); |
| 267 |
| 268 // If we're at rest, hide the shadow. The Android view should be drawing. |
| 269 toolbar_layer_->layer()->SetMasksToBounds(top_offset >= 0.f); |
| 270 } |
| 271 } |
| 272 |
| 273 void CompositorView::FinalizeLayers(JNIEnv* env, jobject jobj) { |
| 274 UNSHIPPED_TRACE_EVENT0("compositor", "CompositorView::FinalizeLayers"); |
| 275 } |
| 276 |
| 277 void CompositorView::SetNeedsComposite(JNIEnv* env, jobject object) { |
| 278 compositor_->SetNeedsComposite(); |
| 279 } |
| 280 |
| 281 void CompositorView::BrowserChildProcessHostDisconnected( |
| 282 const content::ChildProcessData& data) { |
| 283 LOG(WARNING) << "Child process disconnected (type=" << data.process_type |
| 284 << ") pid=" << data.handle << ")"; |
| 285 if (base::android::BuildInfo::GetInstance()->sdk_int() <= |
| 286 base::android::SDK_VERSION_JELLY_BEAN_MR2 && |
| 287 data.process_type == content::PROCESS_TYPE_GPU) { |
| 288 JNIEnv* env = base::android::AttachCurrentThread(); |
| 289 compositor_->SetSurface(nullptr); |
| 290 Java_CompositorView_onJellyBeanSurfaceDisconnectWorkaround( |
| 291 env, obj_.obj(), overlay_video_mode_); |
| 292 } |
| 293 } |
| 294 |
| 295 void CompositorView::BrowserChildProcessCrashed( |
| 296 const content::ChildProcessData& data, |
| 297 int exit_code) { |
| 298 // The Android TERMINATION_STATUS_OOM_PROTECTED hack causes us to never go |
| 299 // through here but through BrowserChildProcessHostDisconnected() instead. |
| 300 } |
| 301 |
| 302 // Register native methods |
| 303 bool RegisterCompositorView(JNIEnv* env) { |
| 304 return RegisterNativesImpl(env); |
| 305 } |
| 306 |
| 307 } // namespace android |
| 308 } // namespace chrome |
OLD | NEW |