| // 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 |