scoped_raster_flags.cc 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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/scoped_raster_flags.h"
  5. #include <utility>
  6. #include "cc/paint/image_provider.h"
  7. #include "cc/paint/image_transfer_cache_entry.h"
  8. #include "cc/paint/paint_filter.h"
  9. #include "cc/paint/paint_image_builder.h"
  10. namespace cc {
  11. ScopedRasterFlags::~ScopedRasterFlags() = default;
  12. void ScopedRasterFlags::DecodeImageShader(const SkMatrix& ctm) {
  13. if (!flags()->HasShader() ||
  14. flags()->getShader()->shader_type() != PaintShader::Type::kImage)
  15. return;
  16. PaintImage image = flags()->getShader()->paint_image();
  17. if (image.IsPaintWorklet()) {
  18. ImageProvider::ScopedResult result =
  19. decode_stashing_image_provider_->GetRasterContent(DrawImage(image));
  20. if (result && result.paint_record()) {
  21. const PaintShader* shader = flags()->getShader();
  22. SkMatrix local_matrix = shader->GetLocalMatrix();
  23. auto decoded_shader = PaintShader::MakePaintRecord(
  24. sk_ref_sp<PaintRecord>(result.paint_record()), shader->tile(),
  25. shader->tx(), shader->tx(), &local_matrix);
  26. MutableFlags()->setShader(decoded_shader);
  27. } else {
  28. decode_failed_ = true;
  29. }
  30. return;
  31. }
  32. uint32_t transfer_cache_entry_id = kInvalidImageTransferCacheEntryId;
  33. PaintFlags::FilterQuality raster_quality = flags()->getFilterQuality();
  34. bool transfer_cache_entry_needs_mips = false;
  35. gpu::Mailbox mailbox;
  36. auto decoded_shader = flags()->getShader()->CreateDecodedImage(
  37. ctm, flags()->getFilterQuality(), &*decode_stashing_image_provider_,
  38. &transfer_cache_entry_id, &raster_quality,
  39. &transfer_cache_entry_needs_mips, &mailbox);
  40. DCHECK_EQ(transfer_cache_entry_id, kInvalidImageTransferCacheEntryId);
  41. DCHECK_EQ(transfer_cache_entry_needs_mips, false);
  42. DCHECK(mailbox.IsZero());
  43. if (!decoded_shader) {
  44. decode_failed_ = true;
  45. return;
  46. }
  47. MutableFlags()->setFilterQuality(raster_quality);
  48. MutableFlags()->setShader(decoded_shader);
  49. }
  50. void ScopedRasterFlags::DecodeRecordShader(const SkMatrix& ctm,
  51. int max_texture_size) {
  52. if (!flags()->HasShader() ||
  53. flags()->getShader()->shader_type() != PaintShader::Type::kPaintRecord)
  54. return;
  55. // Only replace shaders with animated images. Creating transient shaders for
  56. // replacing decodes during raster results in cache misses in skia's picture
  57. // shader cache, which results in re-rasterizing the picture for every draw.
  58. if (flags()->getShader()->image_analysis_state() !=
  59. ImageAnalysisState::kAnimatedImages) {
  60. return;
  61. }
  62. gfx::SizeF raster_scale(1.f, 1.f);
  63. auto decoded_shader = flags()->getShader()->CreateScaledPaintRecord(
  64. ctm, max_texture_size, &raster_scale);
  65. decoded_shader->ResolveSkObjects(&raster_scale,
  66. &*decode_stashing_image_provider_);
  67. MutableFlags()->setShader(std::move(decoded_shader));
  68. }
  69. void ScopedRasterFlags::DecodeFilter() {
  70. if (!flags()->getImageFilter() ||
  71. !flags()->getImageFilter()->has_discardable_images() ||
  72. flags()->getImageFilter()->image_analysis_state() !=
  73. ImageAnalysisState::kAnimatedImages) {
  74. return;
  75. }
  76. MutableFlags()->setImageFilter(flags()->getImageFilter()->SnapshotWithImages(
  77. &*decode_stashing_image_provider_));
  78. }
  79. void ScopedRasterFlags::AdjustStrokeIfNeeded(const SkMatrix& ctm) {
  80. // With anti-aliasing turned off, strokes with a device space width in (0, 1)
  81. // may not raster at all. To avoid this, we have two options:
  82. //
  83. // 1) force a hairline stroke (stroke-width == 0)
  84. // 2) force anti-aliasing on
  85. SkSize scale;
  86. if (flags()->isAntiAlias() || // safe to raster
  87. flags()->getStyle() == PaintFlags::kFill_Style || // not a stroke
  88. !flags()->getStrokeWidth() || // explicit hairline
  89. !ctm.decomposeScale(&scale)) { // cannot decompose
  90. return;
  91. }
  92. const auto stroke_vec =
  93. SkVector::Make(flags()->getStrokeWidth() * scale.width(),
  94. flags()->getStrokeWidth() * scale.height());
  95. if (stroke_vec.x() >= 1.f && stroke_vec.y() >= 1.f)
  96. return; // safe to raster
  97. const auto can_substitute_hairline =
  98. flags()->getStrokeCap() == PaintFlags::kDefault_Cap &&
  99. flags()->getStrokeJoin() == PaintFlags::kDefault_Join;
  100. if (can_substitute_hairline && stroke_vec.x() < 1.f && stroke_vec.y() < 1.f) {
  101. // Use modulated hairline when possible, as it is faster and produces
  102. // results closer to the original intent.
  103. MutableFlags()->setStrokeWidth(0);
  104. MutableFlags()->setAlpha(std::round(
  105. flags()->getAlpha() * std::sqrt(stroke_vec.x() * stroke_vec.y())));
  106. return;
  107. }
  108. // Fall back to anti-aliasing.
  109. MutableFlags()->setAntiAlias(true);
  110. }
  111. } // namespace cc