paint_image.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. // 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. #include "cc/paint/paint_image.h"
  5. #include <memory>
  6. #include <sstream>
  7. #include <utility>
  8. #include "base/atomic_sequence_num.h"
  9. #include "base/hash/hash.h"
  10. #include "base/logging.h"
  11. #include "cc/paint/paint_image_builder.h"
  12. #include "cc/paint/paint_image_generator.h"
  13. #include "cc/paint/paint_record.h"
  14. #include "cc/paint/paint_worklet_input.h"
  15. #include "cc/paint/skia_paint_image_generator.h"
  16. #include "third_party/skia/include/core/SkColorSpace.h"
  17. #include "third_party/skia/include/gpu/GrBackendSurface.h"
  18. #include "ui/gfx/geometry/skia_conversions.h"
  19. namespace cc {
  20. namespace {
  21. base::AtomicSequenceNumber g_next_image_id;
  22. base::AtomicSequenceNumber g_next_image_content_id;
  23. base::AtomicSequenceNumber g_next_generator_client_id;
  24. } // namespace
  25. const PaintImage::Id PaintImage::kNonLazyStableId = -1;
  26. const size_t PaintImage::kDefaultFrameIndex = 0u;
  27. const PaintImage::Id PaintImage::kInvalidId = -2;
  28. const PaintImage::ContentId PaintImage::kInvalidContentId = -1;
  29. const PaintImage::GeneratorClientId PaintImage::kDefaultGeneratorClientId = 0;
  30. ImageHeaderMetadata::ImageHeaderMetadata() = default;
  31. ImageHeaderMetadata::ImageHeaderMetadata(const ImageHeaderMetadata& other) =
  32. default;
  33. ImageHeaderMetadata& ImageHeaderMetadata::operator=(
  34. const ImageHeaderMetadata& other) = default;
  35. ImageHeaderMetadata::ImageHeaderMetadata::~ImageHeaderMetadata() = default;
  36. PaintImage::PaintImage() = default;
  37. PaintImage::PaintImage(const PaintImage& other) = default;
  38. PaintImage::PaintImage(PaintImage&& other) = default;
  39. PaintImage::~PaintImage() = default;
  40. PaintImage& PaintImage::operator=(const PaintImage& other) = default;
  41. PaintImage& PaintImage::operator=(PaintImage&& other) = default;
  42. bool PaintImage::operator==(const PaintImage& other) const {
  43. if (sk_image_ != other.sk_image_)
  44. return false;
  45. if (paint_record_ != other.paint_record_)
  46. return false;
  47. if (paint_record_rect_ != other.paint_record_rect_)
  48. return false;
  49. if (content_id_ != other.content_id_)
  50. return false;
  51. if (paint_image_generator_ != other.paint_image_generator_)
  52. return false;
  53. if (id_ != other.id_)
  54. return false;
  55. if (animation_type_ != other.animation_type_)
  56. return false;
  57. if (completion_state_ != other.completion_state_)
  58. return false;
  59. if (is_multipart_ != other.is_multipart_)
  60. return false;
  61. if (texture_backing_ != other.texture_backing_)
  62. return false;
  63. if (paint_worklet_input_ != other.paint_worklet_input_)
  64. return false;
  65. // Do not check may_be_lcp_candidate_ as it should not affect any rendering
  66. // operation, only metrics collection.
  67. return true;
  68. }
  69. // static
  70. PaintImage::DecodingMode PaintImage::GetConservative(DecodingMode one,
  71. DecodingMode two) {
  72. if (one == two)
  73. return one;
  74. if (one == DecodingMode::kSync || two == DecodingMode::kSync)
  75. return DecodingMode::kSync;
  76. if (one == DecodingMode::kUnspecified || two == DecodingMode::kUnspecified)
  77. return DecodingMode::kUnspecified;
  78. DCHECK_EQ(one, DecodingMode::kAsync);
  79. DCHECK_EQ(two, DecodingMode::kAsync);
  80. return DecodingMode::kAsync;
  81. }
  82. // static
  83. PaintImage::Id PaintImage::GetNextId() {
  84. return g_next_image_id.GetNext();
  85. }
  86. // static
  87. PaintImage::ContentId PaintImage::GetNextContentId() {
  88. return g_next_image_content_id.GetNext();
  89. }
  90. // static
  91. PaintImage::GeneratorClientId PaintImage::GetNextGeneratorClientId() {
  92. // These IDs must start from 1, since 0 is the kDefaultGeneratorClientId.
  93. return g_next_generator_client_id.GetNext() + 1;
  94. }
  95. // static
  96. PaintImage PaintImage::CreateFromBitmap(SkBitmap bitmap) {
  97. if (bitmap.drawsNothing())
  98. return PaintImage();
  99. return PaintImageBuilder::WithDefault()
  100. .set_id(PaintImage::GetNextId())
  101. .set_image(SkImage::MakeFromBitmap(bitmap),
  102. PaintImage::GetNextContentId())
  103. .TakePaintImage();
  104. }
  105. const sk_sp<SkImage>& PaintImage::GetSkImage() const {
  106. return cached_sk_image_;
  107. }
  108. sk_sp<SkImage> PaintImage::GetSwSkImage() const {
  109. if (texture_backing_) {
  110. return texture_backing_->GetSkImageViaReadback();
  111. } else if (cached_sk_image_ && cached_sk_image_->isTextureBacked()) {
  112. return cached_sk_image_->makeNonTextureImage();
  113. }
  114. return cached_sk_image_;
  115. }
  116. sk_sp<SkImage> PaintImage::GetAcceleratedSkImage() const {
  117. DCHECK(!cached_sk_image_ || cached_sk_image_->isTextureBacked());
  118. return cached_sk_image_;
  119. }
  120. bool PaintImage::readPixels(const SkImageInfo& dst_info,
  121. void* dst_pixels,
  122. size_t dst_row_bytes,
  123. int src_x,
  124. int src_y) const {
  125. if (texture_backing_) {
  126. return texture_backing_->readPixels(dst_info, dst_pixels, dst_row_bytes,
  127. src_x, src_y);
  128. } else if (cached_sk_image_) {
  129. return cached_sk_image_->readPixels(dst_info, dst_pixels, dst_row_bytes,
  130. src_x, src_y);
  131. }
  132. return false;
  133. }
  134. SkImageInfo PaintImage::GetSkImageInfo() const {
  135. if (paint_image_generator_) {
  136. return paint_image_generator_->GetSkImageInfo();
  137. } else if (texture_backing_) {
  138. return texture_backing_->GetSkImageInfo();
  139. } else if (cached_sk_image_) {
  140. return cached_sk_image_->imageInfo();
  141. } else if (paint_worklet_input_) {
  142. auto size = paint_worklet_input_->GetSize();
  143. return SkImageInfo::MakeUnknown(static_cast<int>(size.width()),
  144. static_cast<int>(size.height()));
  145. } else {
  146. return SkImageInfo::MakeUnknown();
  147. }
  148. }
  149. gpu::Mailbox PaintImage::GetMailbox() const {
  150. DCHECK(texture_backing_);
  151. return texture_backing_->GetMailbox();
  152. }
  153. bool PaintImage::IsOpaque() const {
  154. if (IsPaintWorklet())
  155. return paint_worklet_input_->KnownToBeOpaque();
  156. return GetSkImageInfo().isOpaque();
  157. }
  158. void PaintImage::CreateSkImage() {
  159. DCHECK(!cached_sk_image_);
  160. if (sk_image_) {
  161. cached_sk_image_ = sk_image_;
  162. } else if (paint_record_) {
  163. cached_sk_image_ = SkImage::MakeFromPicture(
  164. ToSkPicture(paint_record_, gfx::RectToSkRect(paint_record_rect_)),
  165. SkISize::Make(paint_record_rect_.width(), paint_record_rect_.height()),
  166. nullptr, nullptr, SkImage::BitDepth::kU8, SkColorSpace::MakeSRGB());
  167. } else if (paint_image_generator_) {
  168. cached_sk_image_ =
  169. SkImage::MakeFromGenerator(std::make_unique<SkiaPaintImageGenerator>(
  170. paint_image_generator_, kDefaultFrameIndex,
  171. kDefaultGeneratorClientId));
  172. } else if (texture_backing_) {
  173. cached_sk_image_ = texture_backing_->GetAcceleratedSkImage();
  174. }
  175. }
  176. SkISize PaintImage::GetSupportedDecodeSize(
  177. const SkISize& requested_size) const {
  178. if (paint_image_generator_)
  179. return paint_image_generator_->GetSupportedDecodeSize(requested_size);
  180. return SkISize::Make(width(), height());
  181. }
  182. bool PaintImage::Decode(void* memory,
  183. SkImageInfo* info,
  184. sk_sp<SkColorSpace> color_space,
  185. size_t frame_index,
  186. GeneratorClientId client_id) const {
  187. // We don't support SkImageInfo's with color spaces on them. Color spaces
  188. // should always be passed via the |color_space| arg.
  189. DCHECK(!info->colorSpace());
  190. // We only support decode to supported decode size.
  191. DCHECK(info->dimensions() == GetSupportedDecodeSize(info->dimensions()));
  192. if (paint_image_generator_) {
  193. return DecodeFromGenerator(memory, info, std::move(color_space),
  194. frame_index, client_id);
  195. }
  196. return DecodeFromSkImage(memory, info, std::move(color_space), frame_index,
  197. client_id);
  198. }
  199. bool PaintImage::DecodeYuv(const SkYUVAPixmaps& pixmaps,
  200. size_t frame_index,
  201. GeneratorClientId client_id) const {
  202. DCHECK(pixmaps.isValid());
  203. DCHECK(paint_image_generator_);
  204. const uint32_t lazy_pixel_ref = stable_id();
  205. return paint_image_generator_->GetYUVAPlanes(pixmaps, frame_index,
  206. lazy_pixel_ref, client_id);
  207. }
  208. bool PaintImage::DecodeFromGenerator(void* memory,
  209. SkImageInfo* info,
  210. sk_sp<SkColorSpace> color_space,
  211. size_t frame_index,
  212. GeneratorClientId client_id) const {
  213. DCHECK(paint_image_generator_);
  214. // First convert the info to have the requested color space, since the decoder
  215. // will convert this for us.
  216. *info = info->makeColorSpace(std::move(color_space));
  217. const uint32_t lazy_pixel_ref = stable_id();
  218. return paint_image_generator_->GetPixels(*info, memory, info->minRowBytes(),
  219. frame_index, client_id,
  220. lazy_pixel_ref);
  221. }
  222. bool PaintImage::DecodeFromSkImage(void* memory,
  223. SkImageInfo* info,
  224. sk_sp<SkColorSpace> color_space,
  225. size_t frame_index,
  226. GeneratorClientId client_id) const {
  227. auto image = GetSkImageForFrame(frame_index, client_id);
  228. DCHECK(image);
  229. if (color_space) {
  230. image = image->makeColorSpace(color_space, nullptr);
  231. if (!image)
  232. return false;
  233. }
  234. // Note that the readPixels has to happen before converting the info to the
  235. // given color space, since it can produce incorrect results.
  236. bool result = image->readPixels(*info, memory, info->minRowBytes(), 0, 0,
  237. SkImage::kDisallow_CachingHint);
  238. *info = info->makeColorSpace(std::move(color_space));
  239. return result;
  240. }
  241. bool PaintImage::ShouldAnimate() const {
  242. return animation_type_ == AnimationType::ANIMATED &&
  243. repetition_count_ != kAnimationNone && FrameCount() > 1;
  244. }
  245. PaintImage::FrameKey PaintImage::GetKeyForFrame(size_t frame_index) const {
  246. DCHECK_LT(frame_index, FrameCount());
  247. return FrameKey(GetContentIdForFrame(frame_index), frame_index);
  248. }
  249. PaintImage::ContentId PaintImage::GetContentIdForFrame(
  250. size_t frame_index) const {
  251. if (paint_image_generator_)
  252. return paint_image_generator_->GetContentIdForFrame(frame_index);
  253. DCHECK_NE(content_id_, kInvalidContentId);
  254. return content_id_;
  255. }
  256. bool PaintImage::IsTextureBacked() const {
  257. if (texture_backing_)
  258. return true;
  259. if (cached_sk_image_)
  260. return cached_sk_image_->isTextureBacked();
  261. return false;
  262. }
  263. void PaintImage::FlushPendingSkiaOps() {
  264. if (texture_backing_)
  265. texture_backing_->FlushPendingSkiaOps();
  266. }
  267. gfx::ContentColorUsage PaintImage::GetContentColorUsage(bool* is_hlg) const {
  268. if (is_hlg)
  269. *is_hlg = false;
  270. // Right now, JS paint worklets can only be in sRGB
  271. if (paint_worklet_input_)
  272. return gfx::ContentColorUsage::kSRGB;
  273. const auto* color_space = GetSkImageInfo().colorSpace();
  274. // Assume the image will be sRGB if we don't know yet.
  275. if (!color_space || color_space->isSRGB())
  276. return gfx::ContentColorUsage::kSRGB;
  277. skcms_TransferFunction fn;
  278. if (!color_space->isNumericalTransferFn(&fn)) {
  279. if (skcms_TransferFunction_isPQish(&fn))
  280. return gfx::ContentColorUsage::kHDR;
  281. if (skcms_TransferFunction_isHLGish(&fn)) {
  282. if (is_hlg)
  283. *is_hlg = true;
  284. return gfx::ContentColorUsage::kHDR;
  285. }
  286. }
  287. // If it's not HDR and not SRGB, report it as WCG.
  288. return gfx::ContentColorUsage::kWideColorGamut;
  289. }
  290. const ImageHeaderMetadata* PaintImage::GetImageHeaderMetadata() const {
  291. if (paint_image_generator_)
  292. return paint_image_generator_->GetMetadataForDecodeAcceleration();
  293. return nullptr;
  294. }
  295. bool PaintImage::IsYuv(
  296. const SkYUVAPixmapInfo::SupportedDataTypes& supported_data_types,
  297. SkYUVAPixmapInfo* info) const {
  298. SkYUVAPixmapInfo temp_info;
  299. if (!info)
  300. info = &temp_info;
  301. // ImageDecoder will fill out the SkYUVColorSpace in |info| depending on the
  302. // codec's specification.
  303. return paint_image_generator_ &&
  304. paint_image_generator_->QueryYUVA(supported_data_types, info);
  305. }
  306. const std::vector<FrameMetadata>& PaintImage::GetFrameMetadata() const {
  307. DCHECK_EQ(animation_type_, AnimationType::ANIMATED);
  308. DCHECK(paint_image_generator_);
  309. return paint_image_generator_->GetFrameMetadata();
  310. }
  311. size_t PaintImage::FrameCount() const {
  312. if (!*this)
  313. return 0u;
  314. return paint_image_generator_
  315. ? paint_image_generator_->GetFrameMetadata().size()
  316. : 1u;
  317. }
  318. sk_sp<SkImage> PaintImage::GetSkImageForFrame(
  319. size_t index,
  320. GeneratorClientId client_id) const {
  321. DCHECK_LT(index, FrameCount());
  322. DCHECK(!IsTextureBacked());
  323. // |client_id| and |index| are only relevant for generator backed images which
  324. // perform lazy decoding and can be multi-frame.
  325. if (!paint_image_generator_) {
  326. DCHECK_EQ(index, kDefaultFrameIndex);
  327. return GetSwSkImage();
  328. }
  329. // The internally cached SkImage is constructed using the default frame index
  330. // and GeneratorClientId. Avoid creating a new SkImage.
  331. if (index == kDefaultFrameIndex && client_id == kDefaultGeneratorClientId)
  332. return GetSwSkImage();
  333. sk_sp<SkImage> image =
  334. SkImage::MakeFromGenerator(std::make_unique<SkiaPaintImageGenerator>(
  335. paint_image_generator_, index, client_id));
  336. return image;
  337. }
  338. std::string PaintImage::ToString() const {
  339. std::ostringstream str;
  340. str << "sk_image_: " << sk_image_ << " paint_record_: " << paint_record_
  341. << " paint_record_rect_: " << paint_record_rect_.ToString()
  342. << " paint_image_generator_: " << paint_image_generator_
  343. << " id_: " << id_
  344. << " animation_type_: " << static_cast<int>(animation_type_)
  345. << " completion_state_: " << static_cast<int>(completion_state_)
  346. << " is_multipart_: " << is_multipart_
  347. << " may_be_lcp_candidate_: " << may_be_lcp_candidate_
  348. << " is YUV: " << IsYuv(SkYUVAPixmapInfo::SupportedDataTypes::All());
  349. return str.str();
  350. }
  351. PaintImage::FrameKey::FrameKey(ContentId content_id, size_t frame_index)
  352. : content_id_(content_id), frame_index_(frame_index) {
  353. hash_ = base::HashInts(static_cast<uint64_t>(content_id_),
  354. static_cast<uint64_t>(frame_index_));
  355. }
  356. bool PaintImage::FrameKey::operator==(const FrameKey& other) const {
  357. return content_id_ == other.content_id_ && frame_index_ == other.frame_index_;
  358. }
  359. bool PaintImage::FrameKey::operator!=(const FrameKey& other) const {
  360. return !(*this == other);
  361. }
  362. std::string PaintImage::FrameKey::ToString() const {
  363. std::ostringstream str;
  364. str << "content_id: " << content_id_ << ","
  365. << "frame_index: " << frame_index_;
  366. return str.str();
  367. }
  368. } // namespace cc