| Index: chrome/browser/android/compositor/layer/content_layer.cc
|
| diff --git a/chrome/browser/android/compositor/layer/content_layer.cc b/chrome/browser/android/compositor/layer/content_layer.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d64a3066fc51720f776b80d603fa1b047fe5e3b0
|
| --- /dev/null
|
| +++ b/chrome/browser/android/compositor/layer/content_layer.cc
|
| @@ -0,0 +1,246 @@
|
| +// Copyright 2014 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/layer/content_layer.h"
|
| +
|
| +#include "cc/layers/layer.h"
|
| +#include "cc/layers/layer_lists.h"
|
| +#include "chrome/browser/android/compositor/layer/thumbnail_layer.h"
|
| +#include "chrome/browser/android/compositor/tab_content_manager.h"
|
| +#include "ui/gfx/size.h"
|
| +
|
| +namespace chrome {
|
| +namespace android {
|
| +
|
| +// static
|
| +scoped_refptr<ContentLayer> ContentLayer::Create(
|
| + TabContentManager* tab_content_manager) {
|
| + return make_scoped_refptr(new ContentLayer(tab_content_manager));
|
| +}
|
| +
|
| +static void SetOpacityOnLeaf(scoped_refptr<cc::Layer> layer, float alpha) {
|
| + const cc::LayerList& children = layer->children();
|
| + if (children.size() > 0) {
|
| + layer->SetOpacity(1.0f);
|
| + for (uint i = 0; i < children.size(); ++i)
|
| + SetOpacityOnLeaf(children[i], alpha);
|
| + } else {
|
| + layer->SetOpacity(alpha);
|
| + }
|
| +}
|
| +
|
| +static bool DoesLeafDrawContents(scoped_refptr<cc::Layer> layer) {
|
| + if (!layer.get())
|
| + return false;
|
| +
|
| + // TODO: Remove the need for this logic. We can't really guess from
|
| + // an opaque layer type whether it has valid live contents, or for example
|
| + // just a background color placeholder. Need to get this from somewhere else
|
| + // like ContentViewCore or RWHV.
|
| + if (layer->DrawsContent() && !layer->hide_layer_and_subtree() &&
|
| + !layer->background_color()) {
|
| + return true;
|
| + }
|
| +
|
| + const cc::LayerList& children = layer->children();
|
| + for (unsigned i = 0; i < children.size(); i++) {
|
| + if (DoesLeafDrawContents(children[i]))
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +static gfx::Size GetLeafBounds(scoped_refptr<cc::Layer> layer) {
|
| + if (layer->children().size() > 0)
|
| + return GetLeafBounds(layer->children()[0]);
|
| + return layer->bounds();
|
| +}
|
| +
|
| +void ContentLayer::SetProperties(int id,
|
| + bool can_use_live_layer,
|
| + bool can_use_ntp_fallback,
|
| + float static_to_view_blend,
|
| + bool should_override_content_alpha,
|
| + float content_alpha_override,
|
| + float saturation,
|
| + const gfx::Rect& desired_bounds,
|
| + const gfx::Size& content_size) {
|
| + scoped_refptr<cc::Layer> content_layer =
|
| + tab_content_manager_->GetLiveLayer(id);
|
| + ClipContentLayer(content_layer, desired_bounds, content_size);
|
| + bool content_layer_draws = DoesLeafDrawContents(content_layer);
|
| +
|
| + scoped_refptr<ThumbnailLayer> static_layer =
|
| + tab_content_manager_->GetStaticLayer(id, !content_layer_draws);
|
| +
|
| + ClipStaticLayer(static_layer, desired_bounds);
|
| +
|
| + // Reset the attachment logic if the number of children doesn't match the
|
| + // boolean flags. At some point while a tab is in the background one or more
|
| + // layers may be removed from this tree.
|
| + // Note that this needs to be checked *after* we access TabContentManager, as
|
| + // that class might remove layers internally, messing up our own tracking.
|
| + unsigned int expected_layers = 0;
|
| + expected_layers += content_attached_ ? 1 : 0;
|
| + expected_layers += static_attached_ ? 1 : 0;
|
| + if (layer_->children().size() != expected_layers) {
|
| + content_attached_ = false;
|
| + static_attached_ = false;
|
| + const cc::LayerList& layer_children = layer_->children();
|
| + for (unsigned i = 0; i < layer_children.size(); i++)
|
| + layer_children[i]->RemoveFromParent();
|
| + }
|
| +
|
| + gfx::Size content_bounds(0, 0);
|
| + if (!content_layer.get() || !can_use_live_layer) {
|
| + SetContentLayer(nullptr);
|
| + SetStaticLayer(static_layer);
|
| + if (static_layer.get())
|
| + content_bounds = static_layer->layer()->bounds();
|
| + else
|
| + content_bounds.set_width(content_size.width());
|
| + } else {
|
| + SetContentLayer(content_layer);
|
| + content_bounds = content_layer->bounds();
|
| +
|
| + if (static_to_view_blend == 0.0f && !content_layer_draws)
|
| + static_to_view_blend = 1.0f;
|
| +
|
| + if (static_to_view_blend != 0.0f && static_layer.get()) {
|
| + static_layer->layer()->SetOpacity(static_to_view_blend);
|
| + SetStaticLayer(static_layer);
|
| + if (content_bounds.GetArea() == 0 || !content_layer_draws)
|
| + content_bounds = static_layer->layer()->bounds();
|
| + } else {
|
| + SetStaticLayer(nullptr);
|
| + }
|
| + }
|
| +
|
| + if (should_override_content_alpha) {
|
| + for (unsigned int i = 0; i < layer_->children().size(); ++i)
|
| + SetOpacityOnLeaf(layer_->children()[i], content_alpha_override);
|
| + }
|
| +
|
| + if (!content_layer_draws && !static_attached_)
|
| + content_bounds = gfx::Size(0, 0);
|
| +
|
| + layer_->SetBounds(content_bounds);
|
| +
|
| + // Only worry about saturation on the static layer
|
| + if (static_layer.get()) {
|
| + if (saturation != saturation_) {
|
| + saturation_ = saturation;
|
| + cc::FilterOperations filters;
|
| + if (saturation_ < 1.0f)
|
| + filters.Append(cc::FilterOperation::CreateSaturateFilter(saturation_));
|
| + static_layer->layer()->SetFilters(filters);
|
| + }
|
| + }
|
| +}
|
| +
|
| +gfx::Size ContentLayer::GetContentSize() {
|
| + if (content_attached_ && DoesLeafDrawContents(layer()->children()[0]))
|
| + return layer_->children()[0]->bounds();
|
| + return gfx::Size(0, 0);
|
| +}
|
| +
|
| +scoped_refptr<cc::Layer> ContentLayer::layer() {
|
| + return layer_;
|
| +}
|
| +
|
| +ContentLayer::ContentLayer(TabContentManager* tab_content_manager)
|
| + : layer_(cc::Layer::Create()),
|
| + content_attached_(false),
|
| + static_attached_(false),
|
| + saturation_(1.0f),
|
| + tab_content_manager_(tab_content_manager) {
|
| +}
|
| +
|
| +ContentLayer::~ContentLayer() {
|
| +}
|
| +
|
| +void ContentLayer::SetContentLayer(scoped_refptr<cc::Layer> layer) {
|
| + // Check indices
|
| + // content_attached_, expect at least 1 child.
|
| + DCHECK(!content_attached_ || layer_->children().size() > 0);
|
| +
|
| + if (!layer.get()) {
|
| + if (content_attached_)
|
| + layer_->child_at(0)->RemoveFromParent();
|
| + content_attached_ = false;
|
| + return;
|
| + }
|
| +
|
| + bool new_layer = false;
|
| + if (content_attached_ && layer_->child_at(0)->id() != layer->id()) {
|
| + layer_->ReplaceChild(layer_->child_at(0), layer);
|
| + new_layer = true;
|
| + } else if (!content_attached_) {
|
| + layer_->InsertChild(layer, 0);
|
| + new_layer = true;
|
| + }
|
| +
|
| + // If this is a new layer, reset it's opacity.
|
| + if (new_layer)
|
| + SetOpacityOnLeaf(layer, 1.0f);
|
| +
|
| + content_attached_ = true;
|
| +}
|
| +
|
| +void ContentLayer::SetStaticLayer(
|
| + scoped_refptr<ThumbnailLayer> new_static_layer) {
|
| + // Make sure child access will be valid.
|
| + // !content_attached_ AND !static_attached_, expect 0 children.
|
| + // content_attached_ XOR static_attached_, expect 1 child.
|
| + // content_attached_ AND static_attached_, expect 2 children.
|
| + DCHECK((!content_attached_ && !static_attached_) ||
|
| + (content_attached_ != static_attached_ &&
|
| + layer_->children().size() >= 1) ||
|
| + (content_attached_ && static_attached_ &&
|
| + layer_->children().size() >= 2));
|
| +
|
| + if (!new_static_layer.get()) {
|
| + if (static_layer_.get()) {
|
| + static_layer_->layer()->RemoveFromParent();
|
| + static_layer_ = nullptr;
|
| + }
|
| + static_attached_ = false;
|
| + return;
|
| + }
|
| + static_layer_ = new_static_layer;
|
| + static_layer_->AddSelfToParentOrReplaceAt(layer_, content_attached_ ? 1 : 0);
|
| + saturation_ = -1.0f;
|
| + static_layer_->layer()->SetIsDrawable(true);
|
| + static_attached_ = true;
|
| +}
|
| +
|
| +void ContentLayer::ClipContentLayer(scoped_refptr<cc::Layer> content_layer,
|
| + gfx::Rect clipping,
|
| + gfx::Size content_size) {
|
| + if (!content_layer.get())
|
| + return;
|
| +
|
| + gfx::Size bounds(GetLeafBounds(content_layer));
|
| + content_layer->SetMasksToBounds(true);
|
| + gfx::Size clamped_bounds(bounds);
|
| + clamped_bounds.SetToMin(clipping.size());
|
| + content_layer->SetBounds(clamped_bounds);
|
| +
|
| + if (content_layer->children().size() > 0) {
|
| + gfx::PointF offset(
|
| + std::min(content_size.width() - bounds.width() - clipping.x(), 0),
|
| + std::min(content_size.height() - bounds.height() - clipping.y(), 0));
|
| + content_layer->children()[0]->SetPosition(offset);
|
| + }
|
| +}
|
| +
|
| +void ContentLayer::ClipStaticLayer(scoped_refptr<ThumbnailLayer> static_layer,
|
| + gfx::Rect clipping) {
|
| + if (!static_layer.get())
|
| + return;
|
| + static_layer->Clip(clipping);
|
| +}
|
| +
|
| +} // namespace android
|
| +} // namespace chrome
|
|
|