blob: 359958dfd9e3432673bfdc8b97ef40f6b534df13 [file] [log] [blame]
vmpstr94cfa882017-04-14 01:19:351// Copyright 2017 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 "cc/paint/paint_image.h"
Khushal1b8abc012017-08-10 05:16:176
vmpstr81a39a32017-05-16 19:30:217#include "base/atomic_sequence_num.h"
Khushalb41caaa2017-08-31 02:40:168#include "base/hash.h"
Khushal1b8abc012017-08-10 05:16:179#include "base/memory/ptr_util.h"
10#include "cc/paint/paint_image_generator.h"
Vladimir Levin4f2c08c2017-07-28 03:03:2811#include "cc/paint/paint_record.h"
Khushal1b8abc012017-08-10 05:16:1712#include "cc/paint/skia_paint_image_generator.h"
Vladimir Levin4f2c08c2017-07-28 03:03:2813#include "ui/gfx/skia_util.h"
vmpstr94cfa882017-04-14 01:19:3514
15namespace cc {
vmpstr81a39a32017-05-16 19:30:2116namespace {
tzik455b325fa2017-07-20 03:24:5717base::AtomicSequenceNumber s_next_id_;
Khushalb41caaa2017-08-31 02:40:1618base::AtomicSequenceNumber s_next_content_id_;
19} // namespace
vmpstr94cfa882017-04-14 01:19:3520
vmpstr55c7657ca2017-04-29 00:46:4821PaintImage::PaintImage() = default;
vmpstr55c7657ca2017-04-29 00:46:4822PaintImage::PaintImage(const PaintImage& other) = default;
23PaintImage::PaintImage(PaintImage&& other) = default;
vmpstr94cfa882017-04-14 01:19:3524PaintImage::~PaintImage() = default;
25
vmpstr55c7657ca2017-04-29 00:46:4826PaintImage& PaintImage::operator=(const PaintImage& other) = default;
27PaintImage& PaintImage::operator=(PaintImage&& other) = default;
28
khushalsagard5e13bf2017-05-17 08:08:5029bool PaintImage::operator==(const PaintImage& other) const {
Khushalb481b282017-08-24 00:06:5330 return sk_image_ == other.sk_image_ && paint_record_ == other.paint_record_ &&
31 paint_record_rect_ == other.paint_record_rect_ &&
Khushalb41caaa2017-08-31 02:40:1632 paint_record_content_id_ == other.paint_record_content_id_ &&
Khushalb481b282017-08-24 00:06:5333 paint_image_generator_ == other.paint_image_generator_ &&
34 id_ == other.id_ && animation_type_ == other.animation_type_ &&
vmpstr05729e72017-06-06 03:07:1835 completion_state_ == other.completion_state_ &&
Khushalb481b282017-08-24 00:06:5336 subset_rect_ == other.subset_rect_ &&
Khushalb41caaa2017-08-31 02:40:1637 frame_index_ == other.frame_index_ &&
38 is_multipart_ == other.is_multipart_ &&
39 sk_image_id_ == other.sk_image_id_;
vmpstr55c7657ca2017-04-29 00:46:4840}
41
vmpstr81a39a32017-05-16 19:30:2142PaintImage::Id PaintImage::GetNextId() {
43 return s_next_id_.GetNext();
44}
45
Khushalb41caaa2017-08-31 02:40:1646PaintImage::ContentId PaintImage::GetNextContentId() {
47 return s_next_content_id_.GetNext();
48}
49
Vladimir Levin4f2c08c2017-07-28 03:03:2850const sk_sp<SkImage>& PaintImage::GetSkImage() const {
51 if (cached_sk_image_)
52 return cached_sk_image_;
53
54 if (sk_image_) {
55 cached_sk_image_ = sk_image_;
56 } else if (paint_record_) {
57 cached_sk_image_ = SkImage::MakeFromPicture(
58 ToSkPicture(paint_record_, gfx::RectToSkRect(paint_record_rect_)),
59 SkISize::Make(paint_record_rect_.width(), paint_record_rect_.height()),
60 nullptr, nullptr, SkImage::BitDepth::kU8, SkColorSpace::MakeSRGB());
Khushal1b8abc012017-08-10 05:16:1761 } else if (paint_image_generator_) {
Khushalb41caaa2017-08-31 02:40:1662 cached_sk_image_ =
63 SkImage::MakeFromGenerator(base::MakeUnique<SkiaPaintImageGenerator>(
64 paint_image_generator_, frame_index_, sk_image_id_));
Vladimir Levin4f2c08c2017-07-28 03:03:2865 }
Khushalb481b282017-08-24 00:06:5366
67 if (!subset_rect_.IsEmpty() && cached_sk_image_) {
68 cached_sk_image_ =
69 cached_sk_image_->makeSubset(gfx::RectToSkIRect(subset_rect_));
70 }
Vladimir Levin4f2c08c2017-07-28 03:03:2871 return cached_sk_image_;
72}
73
Khushalb481b282017-08-24 00:06:5374PaintImage PaintImage::MakeSubset(const gfx::Rect& subset) const {
75 DCHECK(!subset.IsEmpty());
76
77 // If the subset is the same as the image bounds, we can return the same
78 // image.
79 gfx::Rect bounds(width(), height());
80 if (bounds == subset)
81 return *this;
82
83 DCHECK(bounds.Contains(subset))
84 << "Subset should not be greater than the image bounds";
85 PaintImage result(*this);
86 result.subset_rect_ = subset;
87 // Store the subset from the original image.
88 result.subset_rect_.Offset(subset_rect_.x(), subset_rect_.y());
89
90 // Creating the |cached_sk_image_| is an optimization to allow re-use of the
91 // original decode for image subsets in skia, for cases that rely on skia's
92 // image decode cache.
93 // TODO(khushalsagar): Remove this when we no longer have such cases. See
94 // crbug.com/753639.
95 result.cached_sk_image_ =
96 GetSkImage()->makeSubset(gfx::RectToSkIRect(subset));
97 return result;
98}
99
Vladimir Levin772dc5f2017-08-25 01:54:29100SkISize PaintImage::GetSupportedDecodeSize(
101 const SkISize& requested_size) const {
102 // TODO(vmpstr): For now, we ignore the requested size and just return the
103 // available image size.
104 return SkISize::Make(width(), height());
105}
106
107SkImageInfo PaintImage::CreateDecodeImageInfo(const SkISize& size,
108 SkColorType color_type) const {
109 DCHECK(GetSupportedDecodeSize(size) == size);
110 return SkImageInfo::Make(size.width(), size.height(), color_type,
111 kPremul_SkAlphaType);
112}
113
114bool PaintImage::Decode(void* memory,
115 SkImageInfo* info,
116 sk_sp<SkColorSpace> color_space) const {
117 auto image = GetSkImage();
118 DCHECK(image);
119 if (color_space) {
120 image =
121 image->makeColorSpace(color_space, SkTransferFunctionBehavior::kIgnore);
122 if (!image)
123 return false;
124 }
125 // Note that the readPixels has to happen before converting the info to the
126 // given color space, since it can produce incorrect results.
127 bool result = image->readPixels(*info, memory, info->minRowBytes(), 0, 0,
128 SkImage::kDisallow_CachingHint);
129 *info = info->makeColorSpace(color_space);
130 return result;
131}
132
Khushalb41caaa2017-08-31 02:40:16133PaintImage::FrameKey PaintImage::GetKeyForFrame(size_t frame_index) const {
134 DCHECK_LT(frame_index, FrameCount());
135 DCHECK(paint_image_generator_ || paint_record_);
136
137 // Query the content id that uniquely identifies the content for this frame
138 // from the content provider.
139 ContentId content_id = kInvalidContentId;
140 if (paint_image_generator_)
141 content_id = paint_image_generator_->GetContentIdForFrame(frame_index);
142 else
143 content_id = paint_record_content_id_;
144
145 DCHECK_NE(content_id, kInvalidContentId);
Khushal7ec0d58a2017-09-06 19:51:59146 return FrameKey(content_id, frame_index, subset_rect_);
Khushalb41caaa2017-08-31 02:40:16147}
148
149const std::vector<FrameMetadata>& PaintImage::GetFrameMetadata() const {
150 DCHECK_EQ(animation_type_, AnimationType::ANIMATED);
151 DCHECK(paint_image_generator_);
152
153 return paint_image_generator_->GetFrameMetadata();
154}
155
156size_t PaintImage::FrameCount() const {
157 if (!GetSkImage())
158 return 0u;
159 return paint_image_generator_
160 ? paint_image_generator_->GetFrameMetadata().size()
161 : 1u;
162}
163
164std::string PaintImage::ToString() const {
165 std::ostringstream str;
166 str << "sk_image_: " << sk_image_ << " paint_record_: " << paint_record_
167 << " paint_record_rect_: " << paint_record_rect_.ToString()
168 << " paint_image_generator_: " << paint_image_generator_
169 << " id_: " << id_
170 << " animation_type_: " << static_cast<int>(animation_type_)
171 << " completion_state_: " << static_cast<int>(completion_state_)
172 << " subset_rect_: " << subset_rect_.ToString()
173 << " frame_index_: " << frame_index_
174 << " is_multipart_: " << is_multipart_
175 << " sk_image_id_: " << sk_image_id_;
176 return str.str();
177}
178
Khushal7ec0d58a2017-09-06 19:51:59179PaintImage::FrameKey::FrameKey(ContentId content_id,
Khushalb41caaa2017-08-31 02:40:16180 size_t frame_index,
181 gfx::Rect subset_rect)
Khushal7ec0d58a2017-09-06 19:51:59182 : content_id_(content_id),
Khushalb41caaa2017-08-31 02:40:16183 frame_index_(frame_index),
184 subset_rect_(subset_rect) {
Khushal7ec0d58a2017-09-06 19:51:59185 size_t original_hash = base::HashInts(static_cast<uint64_t>(content_id_),
186 static_cast<uint64_t>(frame_index_));
Khushalb41caaa2017-08-31 02:40:16187 if (subset_rect_.IsEmpty()) {
188 hash_ = original_hash;
189 } else {
190 size_t subset_hash =
191 base::HashInts(static_cast<uint64_t>(
192 base::HashInts(subset_rect_.x(), subset_rect_.y())),
193 static_cast<uint64_t>(base::HashInts(
194 subset_rect_.width(), subset_rect_.height())));
195 hash_ = base::HashInts(original_hash, subset_hash);
196 }
197}
198
199bool PaintImage::FrameKey::operator==(const FrameKey& other) const {
Khushal7ec0d58a2017-09-06 19:51:59200 return content_id_ == other.content_id_ &&
Khushalb41caaa2017-08-31 02:40:16201 frame_index_ == other.frame_index_ &&
202 subset_rect_ == other.subset_rect_;
203}
204
205bool PaintImage::FrameKey::operator!=(const FrameKey& other) const {
206 return !(*this == other);
207}
208
209std::string PaintImage::FrameKey::ToString() const {
210 std::ostringstream str;
Khushal7ec0d58a2017-09-06 19:51:59211 str << "content_id: " << content_id_ << ","
Khushalb41caaa2017-08-31 02:40:16212 << "frame_index: " << frame_index_ << ","
213 << "subset_rect: " << subset_rect_.ToString();
214 return str.str();
215}
216
vmpstr94cfa882017-04-14 01:19:35217} // namespace cc