blob: 9c016e3f824c6b1399cbaca69a6d436a610501f9 [file] [log] [blame]
// 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 "content/renderer/child_frame_compositing_helper.h"
#include <utility>
#include "build/build_config.h"
#include "cc/layers/picture_layer.h"
#include "cc/layers/surface_layer.h"
#include "cc/paint/paint_image.h"
#include "cc/paint/paint_image_builder.h"
#include "content/renderer/child_frame_compositor.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkImage.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/skia_util.h"
namespace content {
ChildFrameCompositingHelper::ChildFrameCompositingHelper(
ChildFrameCompositor* child_frame_compositor)
: child_frame_compositor_(child_frame_compositor) {
DCHECK(child_frame_compositor_);
}
ChildFrameCompositingHelper::~ChildFrameCompositingHelper() {
if (crash_ui_layer_)
crash_ui_layer_->ClearClient();
}
void ChildFrameCompositingHelper::ChildFrameGone(
const gfx::Size& frame_size_in_dip,
float device_scale_factor) {
surface_id_ = viz::SurfaceId();
device_scale_factor_ = device_scale_factor;
crash_ui_layer_ = cc::PictureLayer::Create(this);
crash_ui_layer_->SetMasksToBounds(true);
crash_ui_layer_->SetIsDrawable(true);
bool prevent_contents_opaque_changes = false;
bool is_surface_layer = false;
child_frame_compositor_->SetLayer(
crash_ui_layer_, prevent_contents_opaque_changes, is_surface_layer);
}
void ChildFrameCompositingHelper::SetSurfaceId(
const viz::SurfaceId& surface_id,
const gfx::Size& frame_size_in_dip,
const cc::DeadlinePolicy& deadline) {
if (surface_id_ == surface_id)
return;
surface_id_ = surface_id;
surface_layer_ = cc::SurfaceLayer::Create();
surface_layer_->SetMasksToBounds(true);
surface_layer_->SetSurfaceHitTestable(true);
surface_layer_->SetBackgroundColor(SK_ColorTRANSPARENT);
surface_layer_->SetSurfaceId(surface_id, deadline);
// TODO(lfg): Investigate if it's possible to propagate the information
// about the child surface's opacity. https://crbug.com/629851.
bool prevent_contents_opaque_changes = true;
child_frame_compositor_->SetLayer(surface_layer_,
prevent_contents_opaque_changes,
true /* is_surface_layer */);
UpdateVisibility(true);
surface_layer_->SetBounds(frame_size_in_dip);
}
void ChildFrameCompositingHelper::UpdateVisibility(bool visible) {
cc::Layer* layer = child_frame_compositor_->GetLayer();
if (layer) {
layer->SetIsDrawable(visible);
layer->SetHitTestable(visible);
}
}
gfx::Rect ChildFrameCompositingHelper::PaintableRegion() {
DCHECK(crash_ui_layer_);
return gfx::Rect(crash_ui_layer_->bounds());
}
scoped_refptr<cc::DisplayItemList>
ChildFrameCompositingHelper::PaintContentsToDisplayList(
PaintingControlSetting) {
DCHECK(crash_ui_layer_);
auto layer_size = crash_ui_layer_->bounds();
auto display_list = base::MakeRefCounted<cc::DisplayItemList>();
display_list->StartPaint();
display_list->push<cc::DrawColorOp>(SK_ColorGRAY, SkBlendMode::kSrc);
SkBitmap* sad_bitmap = child_frame_compositor_->GetSadPageBitmap();
if (sad_bitmap) {
int paint_width = sad_bitmap->width() * device_scale_factor_;
int paint_height = sad_bitmap->height() * device_scale_factor_;
if (layer_size.width() >= paint_width &&
layer_size.height() >= paint_height) {
int x = (layer_size.width() - paint_width) / 2;
int y = (layer_size.height() - paint_height) / 2;
if (device_scale_factor_ != 1.f) {
display_list->push<cc::SaveOp>();
display_list->push<cc::TranslateOp>(x, y);
display_list->push<cc::ScaleOp>(device_scale_factor_,
device_scale_factor_);
x = 0;
y = 0;
}
auto image = cc::PaintImageBuilder::WithDefault()
.set_id(cc::PaintImage::GetNextId())
.set_image(SkImage::MakeFromBitmap(*sad_bitmap),
cc::PaintImage::GetNextContentId())
.TakePaintImage();
display_list->push<cc::DrawImageOp>(image, x, y, nullptr);
if (device_scale_factor_ != 1.f)
display_list->push<cc::RestoreOp>();
}
}
display_list->EndPaintOfUnpaired(gfx::Rect(layer_size));
display_list->Finalize();
return display_list;
}
bool ChildFrameCompositingHelper::FillsBoundsCompletely() const {
// Because we paint a full opaque gray background.
return true;
}
size_t ChildFrameCompositingHelper::GetApproximateUnsharedMemoryUsage() const {
return sizeof(*this);
}
} // namespace content