| Index: chrome/browser/android/compositor/compositor_view.cc
|
| diff --git a/chrome/browser/android/compositor/compositor_view.cc b/chrome/browser/android/compositor/compositor_view.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f09ac75cac5b00f5698e0004908d512e001b2b2a
|
| --- /dev/null
|
| +++ b/chrome/browser/android/compositor/compositor_view.cc
|
| @@ -0,0 +1,308 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/android/compositor/compositor_view.h"
|
| +
|
| +#include <vector>
|
| +
|
| +#include <android/bitmap.h>
|
| +#include <android/native_window_jni.h>
|
| +
|
| +#include "base/android/build_info.h"
|
| +#include "base/android/jni_android.h"
|
| +#include "base/bind.h"
|
| +#include "base/command_line.h"
|
| +#include "base/id_map.h"
|
| +#include "base/memory/scoped_ptr.h"
|
| +#include "base/rand_util.h"
|
| +#include "base/trace_event/trace_event.h"
|
| +#include "cc/layers/layer.h"
|
| +#include "cc/layers/layer_lists.h"
|
| +#include "cc/layers/solid_color_layer.h"
|
| +#include "cc/layers/texture_layer.h"
|
| +#include "chrome/browser/android/compositor/layer/toolbar_layer.h"
|
| +#include "chrome/browser/android/compositor/layer_title_cache.h"
|
| +#include "chrome/browser/android/compositor/scene_layer/scene_layer.h"
|
| +#include "chrome/browser/android/compositor/tab_content_manager.h"
|
| +#include "content/public/browser/android/compositor.h"
|
| +#include "content/public/browser/android/content_view_core.h"
|
| +#include "content/public/browser/child_process_data.h"
|
| +#include "content/public/browser/web_contents.h"
|
| +#include "content/public/common/process_type.h"
|
| +#include "jni/CompositorView_jni.h"
|
| +#include "third_party/skia/include/core/SkBitmap.h"
|
| +#include "ui/android/resources/resource_manager.h"
|
| +#include "ui/android/resources/ui_resource_provider.h"
|
| +#include "ui/android/window_android.h"
|
| +#include "ui/gfx/android/java_bitmap.h"
|
| +
|
| +namespace chrome {
|
| +namespace android {
|
| +
|
| +jlong Init(JNIEnv* env,
|
| + jobject obj,
|
| + jboolean low_mem_device,
|
| + jint empty_background_color,
|
| + jlong native_window_android,
|
| + jobject jlayer_title_cache,
|
| + jobject jtab_content_manager) {
|
| + CompositorView* view;
|
| + ui::WindowAndroid* window_android =
|
| + reinterpret_cast<ui::WindowAndroid*>(native_window_android);
|
| + LayerTitleCache* layer_title_cache =
|
| + LayerTitleCache::FromJavaObject(jlayer_title_cache);
|
| + TabContentManager* tab_content_manager =
|
| + TabContentManager::FromJavaObject(jtab_content_manager);
|
| +
|
| + DCHECK(tab_content_manager);
|
| +
|
| + // TODO(clholgat): Remove the compositor tabstrip flag.
|
| + view = new CompositorView(env, obj, empty_background_color, low_mem_device,
|
| + window_android, layer_title_cache,
|
| + tab_content_manager);
|
| +
|
| + ui::UIResourceProvider* ui_resource_provider = view->GetUIResourceProvider();
|
| + // TODO(dtrainor): Pass the ResourceManager on the Java side to the tree
|
| + // builders instead.
|
| + if (layer_title_cache)
|
| + layer_title_cache->SetResourceManager(view->GetResourceManager());
|
| + if (tab_content_manager)
|
| + tab_content_manager->SetUIResourceProvider(ui_resource_provider);
|
| +
|
| + return reinterpret_cast<intptr_t>(view);
|
| +}
|
| +
|
| +CompositorView::CompositorView(JNIEnv* env,
|
| + jobject obj,
|
| + jint empty_background_color,
|
| + jboolean low_mem_device,
|
| + ui::WindowAndroid* window_android,
|
| + LayerTitleCache* layer_title_cache,
|
| + TabContentManager* tab_content_manager)
|
| + : layer_title_cache_(layer_title_cache),
|
| + tab_content_manager_(tab_content_manager),
|
| + root_layer_(cc::SolidColorLayer::Create()),
|
| + toolbar_layer_(ToolbarLayer::Create()),
|
| + scene_layer_(nullptr),
|
| + current_surface_format_(0),
|
| + content_width_(0),
|
| + content_height_(0),
|
| + overdraw_bottom_height_(0),
|
| + overlay_video_mode_(false),
|
| + empty_background_color_(empty_background_color),
|
| + weak_factory_(this) {
|
| + content::BrowserChildProcessObserver::Add(this);
|
| + obj_.Reset(env, obj);
|
| + compositor_.reset(content::Compositor::Create(this, window_android));
|
| +
|
| + root_layer_->SetIsDrawable(true);
|
| + root_layer_->SetBackgroundColor(SK_ColorWHITE);
|
| +
|
| + toolbar_layer_->layer()->SetHideLayerAndSubtree(true);
|
| + root_layer_->AddChild(toolbar_layer_->layer());
|
| +}
|
| +
|
| +CompositorView::~CompositorView() {
|
| + content::BrowserChildProcessObserver::Remove(this);
|
| +
|
| + // Explicitly reset these scoped_ptrs here because otherwise we callbacks will
|
| + // try to access member variables during destruction.
|
| + compositor_.reset(NULL);
|
| +}
|
| +
|
| +void CompositorView::Destroy(JNIEnv* env, jobject object) {
|
| + delete this;
|
| +}
|
| +
|
| +ui::ResourceManager* CompositorView::GetResourceManager() {
|
| + if (!compositor_)
|
| + return NULL;
|
| + return &compositor_->GetResourceManager();
|
| +}
|
| +
|
| +base::android::ScopedJavaLocalRef<jobject> CompositorView::GetResourceManager(
|
| + JNIEnv* env,
|
| + jobject jobj) {
|
| + return compositor_->GetResourceManager().GetJavaObject();
|
| +}
|
| +
|
| +void CompositorView::Layout() {
|
| + JNIEnv* env = base::android::AttachCurrentThread();
|
| + Java_CompositorView_onCompositorLayout(env, obj_.obj());
|
| +}
|
| +
|
| +void CompositorView::OnSwapBuffersCompleted(int pending_swap_buffers) {
|
| + JNIEnv* env = base::android::AttachCurrentThread();
|
| + Java_CompositorView_onSwapBuffersCompleted(env, obj_.obj(),
|
| + pending_swap_buffers);
|
| +}
|
| +
|
| +ui::UIResourceProvider* CompositorView::GetUIResourceProvider() {
|
| + if (!compositor_)
|
| + return NULL;
|
| + return &compositor_->GetUIResourceProvider();
|
| +}
|
| +
|
| +void CompositorView::SurfaceCreated(JNIEnv* env, jobject object) {
|
| + compositor_->SetRootLayer(root_layer_);
|
| + current_surface_format_ = 0;
|
| +}
|
| +
|
| +void CompositorView::SurfaceDestroyed(JNIEnv* env, jobject object) {
|
| + compositor_->SetSurface(NULL);
|
| + current_surface_format_ = 0;
|
| +}
|
| +
|
| +void CompositorView::SurfaceChanged(JNIEnv* env,
|
| + jobject object,
|
| + jint format,
|
| + jint width,
|
| + jint height,
|
| + jobject surface) {
|
| + DCHECK(surface);
|
| + if (current_surface_format_ != format) {
|
| + current_surface_format_ = format;
|
| + compositor_->SetSurface(surface);
|
| + }
|
| + gfx::Size size = gfx::Size(width, height);
|
| + compositor_->SetWindowBounds(size);
|
| + content_width_ = size.width();
|
| + content_height_ = size.height();
|
| + root_layer_->SetBounds(gfx::Size(content_width_, content_height_));
|
| +}
|
| +
|
| +void CompositorView::SetLayoutViewport(JNIEnv* env,
|
| + jobject object,
|
| + jfloat x,
|
| + jfloat y,
|
| + jfloat width,
|
| + jfloat height,
|
| + jfloat visible_x_offset,
|
| + jfloat visible_y_offset,
|
| + jfloat overdraw_bottom_height,
|
| + jfloat dp_to_pixel) {
|
| + overdraw_bottom_height_ = overdraw_bottom_height;
|
| + compositor_->setDeviceScaleFactor(dp_to_pixel);
|
| + root_layer_->SetBounds(gfx::Size(content_width_, content_height_));
|
| +}
|
| +
|
| +void CompositorView::SetBackground(bool visible, SkColor color) {
|
| + if (overlay_video_mode_)
|
| + visible = false;
|
| + root_layer_->SetBackgroundColor(color);
|
| + root_layer_->SetIsDrawable(visible);
|
| +}
|
| +
|
| +void CompositorView::SetOverlayVideoMode(JNIEnv* env,
|
| + jobject object,
|
| + bool enabled) {
|
| + if (overlay_video_mode_ == enabled)
|
| + return;
|
| + overlay_video_mode_ = enabled;
|
| + compositor_->SetHasTransparentBackground(enabled);
|
| + SetNeedsComposite(env, object);
|
| +}
|
| +
|
| +void CompositorView::SetSceneLayer(JNIEnv* env,
|
| + jobject object,
|
| + jobject jscene_layer) {
|
| + SceneLayer* scene_layer = SceneLayer::FromJavaObject(env, jscene_layer);
|
| +
|
| + if (scene_layer_ != scene_layer) {
|
| + // Old tree provider is being detached.
|
| + if (scene_layer_ != nullptr)
|
| + scene_layer_->OnDetach();
|
| +
|
| + scene_layer_ = scene_layer;
|
| +
|
| + if (scene_layer == nullptr) {
|
| + scene_layer_layer_ = nullptr;
|
| + return;
|
| + }
|
| +
|
| + scene_layer_layer_ = scene_layer->layer();
|
| + root_layer_->InsertChild(scene_layer->layer(), 0);
|
| + }
|
| +
|
| + if (scene_layer) {
|
| + SetBackground(scene_layer->ShouldShowBackground(),
|
| + scene_layer->GetBackgroundColor());
|
| + } else {
|
| +#ifndef NDEBUG
|
| + // This should not happen. Setting red background just for debugging.
|
| + SetBackground(true, SK_ColorRED);
|
| +#else
|
| + SetBackground(true, SK_ColorBLACK);
|
| +#endif
|
| + }
|
| +}
|
| +
|
| +int CompositorView::GetUsableContentHeight() {
|
| + return std::max(content_height_ - overdraw_bottom_height_, 0);
|
| +}
|
| +
|
| +void CompositorView::UpdateToolbarLayer(JNIEnv* env,
|
| + jobject object,
|
| + jint toolbar_resource_id,
|
| + jint progress_resource_id,
|
| + jfloat top_offset,
|
| + bool visible) {
|
| + // Ensure the toolbar resource is available before making the layer visible.
|
| + ui::ResourceManager::Resource* resource =
|
| + compositor_->GetResourceManager().GetResource(
|
| + ui::ANDROID_RESOURCE_TYPE_DYNAMIC, toolbar_resource_id);
|
| + if (!resource)
|
| + visible = false;
|
| +
|
| + toolbar_layer_->layer()->SetHideLayerAndSubtree(!visible);
|
| + if (visible) {
|
| + toolbar_layer_->layer()->SetPosition(gfx::PointF(0, top_offset));
|
| +
|
| + ui::ResourceManager::Resource* progress_resource =
|
| + compositor_->GetResourceManager().GetResource(
|
| + ui::ANDROID_RESOURCE_TYPE_DYNAMIC, progress_resource_id);
|
| + toolbar_layer_->PushResource(resource, progress_resource, false, false,
|
| + false);
|
| +
|
| + // If we're at rest, hide the shadow. The Android view should be drawing.
|
| + toolbar_layer_->layer()->SetMasksToBounds(top_offset >= 0.f);
|
| + }
|
| +}
|
| +
|
| +void CompositorView::FinalizeLayers(JNIEnv* env, jobject jobj) {
|
| + UNSHIPPED_TRACE_EVENT0("compositor", "CompositorView::FinalizeLayers");
|
| +}
|
| +
|
| +void CompositorView::SetNeedsComposite(JNIEnv* env, jobject object) {
|
| + compositor_->SetNeedsComposite();
|
| +}
|
| +
|
| +void CompositorView::BrowserChildProcessHostDisconnected(
|
| + const content::ChildProcessData& data) {
|
| + LOG(WARNING) << "Child process disconnected (type=" << data.process_type
|
| + << ") pid=" << data.handle << ")";
|
| + if (base::android::BuildInfo::GetInstance()->sdk_int() <=
|
| + base::android::SDK_VERSION_JELLY_BEAN_MR2 &&
|
| + data.process_type == content::PROCESS_TYPE_GPU) {
|
| + JNIEnv* env = base::android::AttachCurrentThread();
|
| + compositor_->SetSurface(nullptr);
|
| + Java_CompositorView_onJellyBeanSurfaceDisconnectWorkaround(
|
| + env, obj_.obj(), overlay_video_mode_);
|
| + }
|
| +}
|
| +
|
| +void CompositorView::BrowserChildProcessCrashed(
|
| + const content::ChildProcessData& data,
|
| + int exit_code) {
|
| + // The Android TERMINATION_STATUS_OOM_PROTECTED hack causes us to never go
|
| + // through here but through BrowserChildProcessHostDisconnected() instead.
|
| +}
|
| +
|
| +// Register native methods
|
| +bool RegisterCompositorView(JNIEnv* env) {
|
| + return RegisterNativesImpl(env);
|
| +}
|
| +
|
| +} // namespace android
|
| +} // namespace chrome
|
|
|