1 // Copyright 2014 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 "content/renderer/child_frame_compositing_helper.h"
6
7 #include <utility>
8
9 #include "build/build_config.h"
10 #include "cc/layers/picture_layer.h"
11 #include "cc/layers/surface_layer.h"
12 #include "cc/paint/paint_image.h"
13 #include "cc/paint/paint_image_builder.h"
14 #include "content/renderer/child_frame_compositor.h"
15 #include "skia/ext/image_operations.h"
16 #include "third_party/skia/include/core/SkBitmap.h"
17 #include "third_party/skia/include/core/SkImage.h"
18 #include "ui/gfx/geometry/point_f.h"
19 #include "ui/gfx/geometry/size.h"
20 #include "ui/gfx/skia_util.h"
21
22 namespace content {
23
ChildFrameCompositingHelper(ChildFrameCompositor * child_frame_compositor)24 ChildFrameCompositingHelper::ChildFrameCompositingHelper(
25 ChildFrameCompositor* child_frame_compositor)
26 : child_frame_compositor_(child_frame_compositor) {
27 DCHECK(child_frame_compositor_);
28 }
29
~ChildFrameCompositingHelper()30 ChildFrameCompositingHelper::~ChildFrameCompositingHelper() {
31 if (crash_ui_layer_)
32 crash_ui_layer_->ClearClient();
33 }
34
ChildFrameGone(const gfx::Size & frame_size_in_dip,float device_scale_factor)35 void ChildFrameCompositingHelper::ChildFrameGone(
36 const gfx::Size& frame_size_in_dip,
37 float device_scale_factor) {
38 surface_id_ = viz::SurfaceId();
39 device_scale_factor_ = device_scale_factor;
40
41 crash_ui_layer_ = cc::PictureLayer::Create(this);
42 crash_ui_layer_->SetMasksToBounds(true);
43 crash_ui_layer_->SetIsDrawable(true);
44
45 bool prevent_contents_opaque_changes = false;
46 bool is_surface_layer = false;
47 child_frame_compositor_->SetLayer(
48 crash_ui_layer_, prevent_contents_opaque_changes, is_surface_layer);
49 }
50
SetSurfaceId(const viz::SurfaceId & surface_id,const gfx::Size & frame_size_in_dip,const cc::DeadlinePolicy & deadline)51 void ChildFrameCompositingHelper::SetSurfaceId(
52 const viz::SurfaceId& surface_id,
53 const gfx::Size& frame_size_in_dip,
54 const cc::DeadlinePolicy& deadline) {
55 if (surface_id_ == surface_id)
56 return;
57
58 surface_id_ = surface_id;
59
60 surface_layer_ = cc::SurfaceLayer::Create();
61 surface_layer_->SetMasksToBounds(true);
62 surface_layer_->SetSurfaceHitTestable(true);
63 surface_layer_->SetBackgroundColor(SK_ColorTRANSPARENT);
64
65 surface_layer_->SetSurfaceId(surface_id, deadline);
66
67 // TODO(lfg): Investigate if it's possible to propagate the information
68 // about the child surface's opacity. https://crbug.com/629851.
69 bool prevent_contents_opaque_changes = true;
70 child_frame_compositor_->SetLayer(surface_layer_,
71 prevent_contents_opaque_changes,
72 true /* is_surface_layer */);
73
74 UpdateVisibility(true);
75
76 surface_layer_->SetBounds(frame_size_in_dip);
77 }
78
UpdateVisibility(bool visible)79 void ChildFrameCompositingHelper::UpdateVisibility(bool visible) {
80 cc::Layer* layer = child_frame_compositor_->GetLayer();
81 if (layer) {
82 layer->SetIsDrawable(visible);
83 layer->SetHitTestable(visible);
84 }
85 }
86
PaintableRegion()87 gfx::Rect ChildFrameCompositingHelper::PaintableRegion() {
88 DCHECK(crash_ui_layer_);
89 return gfx::Rect(crash_ui_layer_->bounds());
90 }
91
92 scoped_refptr<cc::DisplayItemList>
PaintContentsToDisplayList(PaintingControlSetting)93 ChildFrameCompositingHelper::PaintContentsToDisplayList(
94 PaintingControlSetting) {
95 DCHECK(crash_ui_layer_);
96 auto layer_size = crash_ui_layer_->bounds();
97 auto display_list = base::MakeRefCounted<cc::DisplayItemList>();
98 display_list->StartPaint();
99 display_list->push<cc::DrawColorOp>(SK_ColorGRAY, SkBlendMode::kSrc);
100
101 SkBitmap* sad_bitmap = child_frame_compositor_->GetSadPageBitmap();
102 if (sad_bitmap) {
103 int paint_width = sad_bitmap->width() * device_scale_factor_;
104 int paint_height = sad_bitmap->height() * device_scale_factor_;
105 if (layer_size.width() >= paint_width &&
106 layer_size.height() >= paint_height) {
107 int x = (layer_size.width() - paint_width) / 2;
108 int y = (layer_size.height() - paint_height) / 2;
109 if (device_scale_factor_ != 1.f) {
110 display_list->push<cc::SaveOp>();
111 display_list->push<cc::TranslateOp>(x, y);
112 display_list->push<cc::ScaleOp>(device_scale_factor_,
113 device_scale_factor_);
114 x = 0;
115 y = 0;
116 }
117
118 auto image = cc::PaintImageBuilder::WithDefault()
119 .set_id(cc::PaintImage::GetNextId())
120 .set_image(SkImage::MakeFromBitmap(*sad_bitmap),
121 cc::PaintImage::GetNextContentId())
122 .TakePaintImage();
123 display_list->push<cc::DrawImageOp>(image, x, y, nullptr);
124
125 if (device_scale_factor_ != 1.f)
126 display_list->push<cc::RestoreOp>();
127 }
128 }
129 display_list->EndPaintOfUnpaired(gfx::Rect(layer_size));
130 display_list->Finalize();
131 return display_list;
132 }
133
FillsBoundsCompletely() const134 bool ChildFrameCompositingHelper::FillsBoundsCompletely() const {
135 // Because we paint a full opaque gray background.
136 return true;
137 }
138
GetApproximateUnsharedMemoryUsage() const139 size_t ChildFrameCompositingHelper::GetApproximateUnsharedMemoryUsage() const {
140 return sizeof(*this);
141 }
142
143 } // namespace content
144