paint_op_buffer_serializer.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  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_op_buffer_serializer.h"
  5. #include <limits>
  6. #include <memory>
  7. #include <utility>
  8. #include <vector>
  9. #include "base/bind.h"
  10. #include "base/trace_event/trace_event.h"
  11. #include "cc/paint/clear_for_opaque_raster.h"
  12. #include "cc/paint/scoped_raster_flags.h"
  13. #include "skia/ext/legacy_display_globals.h"
  14. #include "third_party/skia/include/core/SkColorSpace.h"
  15. #include "ui/gfx/geometry/skia_conversions.h"
  16. namespace cc {
  17. namespace {
  18. PlaybackParams MakeParams(const SkCanvas* canvas) {
  19. // We don't use an ImageProvider here since the ops are played onto a no-draw
  20. // canvas for state tracking and don't need decoded images.
  21. PlaybackParams params(nullptr, canvas->getLocalToDevice());
  22. params.is_analyzing = true;
  23. return params;
  24. }
  25. std::unique_ptr<SkCanvas> MakeAnalysisCanvas(
  26. const PaintOp::SerializeOptions& options) {
  27. // Use half of the max int as the extent for the SkNoDrawCanvas. The correct
  28. // clip is applied to the canvas during serialization.
  29. const int kMaxExtent = std::numeric_limits<int>::max() >> 1;
  30. return options.strike_server
  31. ? options.strike_server->makeAnalysisCanvas(
  32. kMaxExtent, kMaxExtent,
  33. skia::LegacyDisplayGlobals::ComputeSurfaceProps(
  34. options.can_use_lcd_text),
  35. options.color_space,
  36. options.context_supports_distance_field_text)
  37. : std::make_unique<SkNoDrawCanvas>(kMaxExtent, kMaxExtent);
  38. }
  39. } // namespace
  40. PaintOpBufferSerializer::PaintOpBufferSerializer(
  41. SerializeCallback serialize_cb,
  42. const PaintOp::SerializeOptions& options)
  43. : serialize_cb_(std::move(serialize_cb)), options_(options) {
  44. DCHECK(serialize_cb_);
  45. }
  46. PaintOpBufferSerializer::~PaintOpBufferSerializer() = default;
  47. void PaintOpBufferSerializer::Serialize(const PaintOpBuffer* buffer,
  48. const std::vector<size_t>* offsets,
  49. const Preamble& preamble) {
  50. std::unique_ptr<SkCanvas> canvas = MakeAnalysisCanvas(options_);
  51. // These PlaybackParams use the initial (identity) canvas matrix, as they are
  52. // only used for serializing the preamble and the initial save / final restore
  53. // SerializeBuffer will create its own PlaybackParams based on the
  54. // post-preamble canvas.
  55. PlaybackParams params = MakeParams(canvas.get());
  56. int saveCount = canvas->getSaveCount();
  57. Save(canvas.get(), params);
  58. SerializePreamble(canvas.get(), preamble, params);
  59. SerializeBuffer(canvas.get(), buffer, offsets);
  60. RestoreToCount(canvas.get(), saveCount, params);
  61. }
  62. void PaintOpBufferSerializer::SerializeAndDestroy(
  63. PaintOpBuffer* buffer,
  64. const std::vector<size_t>* offsets,
  65. const Preamble& preamble) {
  66. std::unique_ptr<SkCanvas> canvas = MakeAnalysisCanvas(options_);
  67. // These PlaybackParams use the initial (identity) canvas matrix, as they are
  68. // only used for serializing the preamble and the initial save / final restore
  69. // SerializeBuffer will create its own PlaybackParams based on the
  70. // post-preamble canvas.
  71. PlaybackParams params = MakeParams(canvas.get());
  72. int saveCount = canvas->getSaveCount();
  73. Save(canvas.get(), params);
  74. SerializePreamble(canvas.get(), preamble, params);
  75. SerializeBufferAndDestroy(canvas.get(), buffer, offsets);
  76. RestoreToCount(canvas.get(), saveCount, params);
  77. }
  78. void PaintOpBufferSerializer::Serialize(const PaintOpBuffer* buffer) {
  79. std::unique_ptr<SkCanvas> canvas = MakeAnalysisCanvas(options_);
  80. SerializeBuffer(canvas.get(), buffer, nullptr);
  81. }
  82. void PaintOpBufferSerializer::Serialize(const PaintOpBuffer* buffer,
  83. const gfx::Rect& playback_rect,
  84. const gfx::SizeF& post_scale) {
  85. std::unique_ptr<SkCanvas> canvas = MakeAnalysisCanvas(options_);
  86. PlaybackParams params = MakeParams(canvas.get());
  87. // TODO(khushalsagar): remove this clip rect if it's not needed.
  88. if (!playback_rect.IsEmpty()) {
  89. ClipRectOp clip_op(gfx::RectToSkRect(playback_rect), SkClipOp::kIntersect,
  90. false);
  91. SerializeOp(canvas.get(), &clip_op, nullptr, params);
  92. }
  93. if (post_scale.width() != 1.f || post_scale.height() != 1.f) {
  94. ScaleOp scale_op(post_scale.width(), post_scale.height());
  95. SerializeOp(canvas.get(), &scale_op, nullptr, params);
  96. }
  97. SerializeBuffer(canvas.get(), buffer, nullptr);
  98. }
  99. // This function needs to have the exact same behavior as
  100. // RasterSource::ClearForOpaqueRaster.
  101. void PaintOpBufferSerializer::ClearForOpaqueRaster(
  102. SkCanvas* canvas,
  103. const Preamble& preamble,
  104. const PlaybackParams& params) {
  105. gfx::Rect outer_rect;
  106. gfx::Rect inner_rect;
  107. if (!CalculateClearForOpaqueRasterRects(
  108. preamble.post_translation, preamble.post_scale, preamble.content_size,
  109. preamble.full_raster_rect, preamble.playback_rect, outer_rect,
  110. inner_rect))
  111. return;
  112. Save(canvas, params);
  113. ClipRectOp outer_clip_op(gfx::RectToSkRect(outer_rect), SkClipOp::kIntersect,
  114. false);
  115. SerializeOp(canvas, &outer_clip_op, nullptr, params);
  116. if (!inner_rect.IsEmpty()) {
  117. ClipRectOp inner_clip_op(gfx::RectToSkRect(inner_rect),
  118. SkClipOp::kDifference, false);
  119. SerializeOp(canvas, &inner_clip_op, nullptr, params);
  120. }
  121. DrawColorOp clear_op(preamble.background_color, SkBlendMode::kSrc);
  122. SerializeOp(canvas, &clear_op, nullptr, params);
  123. RestoreToCount(canvas, 1, params);
  124. }
  125. void PaintOpBufferSerializer::SerializePreamble(SkCanvas* canvas,
  126. const Preamble& preamble,
  127. const PlaybackParams& params) {
  128. DCHECK(preamble.full_raster_rect.Contains(preamble.playback_rect))
  129. << "full: " << preamble.full_raster_rect.ToString()
  130. << ", playback: " << preamble.playback_rect.ToString();
  131. // NOTE: The following code should be kept consistent with
  132. // RasterSource::PlaybackToCanvas().
  133. bool is_partial_raster = preamble.full_raster_rect != preamble.playback_rect;
  134. if (!preamble.requires_clear) {
  135. ClearForOpaqueRaster(canvas, preamble, params);
  136. } else if (!is_partial_raster) {
  137. // If rastering the entire tile, clear to transparent pre-clip. This is so
  138. // that any external texels outside of the playback rect also get cleared.
  139. // There's not enough information at this point to know if this texture is
  140. // being reused from another tile, so the external texels could have been
  141. // cleared to some wrong value.
  142. DrawColorOp clear(SkColors::kTransparent, SkBlendMode::kSrc);
  143. SerializeOp(canvas, &clear, nullptr, params);
  144. }
  145. if (!preamble.full_raster_rect.OffsetFromOrigin().IsZero()) {
  146. TranslateOp translate_op(-preamble.full_raster_rect.x(),
  147. -preamble.full_raster_rect.y());
  148. SerializeOp(canvas, &translate_op, nullptr, params);
  149. }
  150. if (!preamble.playback_rect.IsEmpty()) {
  151. ClipRectOp clip_op(gfx::RectToSkRect(preamble.playback_rect),
  152. SkClipOp::kIntersect, false);
  153. SerializeOp(canvas, &clip_op, nullptr, params);
  154. }
  155. if (!preamble.post_translation.IsZero()) {
  156. TranslateOp translate_op(preamble.post_translation.x(),
  157. preamble.post_translation.y());
  158. SerializeOp(canvas, &translate_op, nullptr, params);
  159. }
  160. if (preamble.post_scale.x() != 1.f || preamble.post_scale.y() != 1.f) {
  161. ScaleOp scale_op(preamble.post_scale.x(), preamble.post_scale.y());
  162. SerializeOp(canvas, &scale_op, nullptr, params);
  163. }
  164. // If tile is transparent and this is partial raster, just clear the
  165. // section that is being rastered. If this is opaque, trust the raster
  166. // to write all the pixels inside of the full_raster_rect.
  167. if (preamble.requires_clear && is_partial_raster) {
  168. DrawColorOp clear_op(SkColors::kTransparent, SkBlendMode::kSrc);
  169. SerializeOp(canvas, &clear_op, nullptr, params);
  170. }
  171. }
  172. bool PaintOpBufferSerializer::WillSerializeNextOp(const PaintOp* op,
  173. SkCanvas* canvas,
  174. PlaybackParams params,
  175. uint8_t alpha) {
  176. // Skip ops outside the current clip if they have images. This saves
  177. // performing an unnecessary expensive decode.
  178. bool skip_op = PaintOp::OpHasDiscardableImages(op) &&
  179. PaintOp::QuickRejectDraw(op, canvas);
  180. // Skip text ops if there is no SkStrikeServer.
  181. skip_op |=
  182. op->GetType() == PaintOpType::DrawTextBlob && !options_.strike_server;
  183. if (skip_op)
  184. return true;
  185. if (op->GetType() == PaintOpType::DrawRecord) {
  186. int save_count = canvas->getSaveCount();
  187. Save(canvas, params);
  188. SerializeBuffer(canvas, static_cast<const DrawRecordOp*>(op)->record.get(),
  189. nullptr);
  190. RestoreToCount(canvas, save_count, params);
  191. return true;
  192. }
  193. if (op->GetType() == PaintOpType::DrawImageRect &&
  194. static_cast<const DrawImageRectOp*>(op)->image.IsPaintWorklet()) {
  195. DCHECK(options_.image_provider);
  196. const DrawImageRectOp* draw_op = static_cast<const DrawImageRectOp*>(op);
  197. ImageProvider::ScopedResult result =
  198. options_.image_provider->GetRasterContent(DrawImage(draw_op->image));
  199. if (!result || !result.paint_record())
  200. return true;
  201. int save_count = canvas->getSaveCount();
  202. Save(canvas, params);
  203. // The following ops are copying the canvas's ops from
  204. // DrawImageRectOp::RasterWithFlags.
  205. SkM44 trans = SkM44(SkMatrix::RectToRect(draw_op->src, draw_op->dst));
  206. ConcatOp concat_op(trans);
  207. bool success = SerializeOp(canvas, &concat_op, nullptr, params);
  208. if (!success)
  209. return false;
  210. ClipRectOp clip_rect_op(draw_op->src, SkClipOp::kIntersect, false);
  211. success = SerializeOp(canvas, &clip_rect_op, nullptr, params);
  212. if (!success)
  213. return false;
  214. // In DrawImageRectOp::RasterWithFlags, the save layer uses the
  215. // flags_to_serialize or default(null) flags. At this point in the
  216. // serialization, flags_to_serialize is always null as well.
  217. SaveLayerOp save_layer_op(&draw_op->src, nullptr);
  218. success = SerializeOpWithFlags(canvas, &save_layer_op, params, 255);
  219. if (!success)
  220. return false;
  221. SerializeBuffer(canvas, result.paint_record(), nullptr);
  222. RestoreToCount(canvas, save_count, params);
  223. return true;
  224. } else {
  225. if (op->IsPaintOpWithFlags()) {
  226. return SerializeOpWithFlags(
  227. canvas, static_cast<const PaintOpWithFlags*>(op), params, alpha);
  228. } else {
  229. return SerializeOp(canvas, op, nullptr, params);
  230. }
  231. }
  232. }
  233. void PaintOpBufferSerializer::SerializeBuffer(
  234. SkCanvas* canvas,
  235. const PaintOpBuffer* buffer,
  236. const std::vector<size_t>* offsets) {
  237. DCHECK(buffer);
  238. // This updates the original_ctm to reflect the canvas transformation at
  239. // start of this call to SerializeBuffer.
  240. PlaybackParams params = MakeParams(canvas);
  241. for (PaintOpBuffer::PlaybackFoldingIterator iter(buffer, offsets); iter;
  242. ++iter) {
  243. const PaintOp* op = *iter;
  244. if (!WillSerializeNextOp(op, canvas, params, iter.alpha())) {
  245. return;
  246. }
  247. }
  248. }
  249. void PaintOpBufferSerializer::SerializeBufferAndDestroy(
  250. SkCanvas* canvas,
  251. PaintOpBuffer* buffer,
  252. const std::vector<size_t>* offsets) {
  253. DCHECK(buffer);
  254. // This updates the original_ctm to reflect the canvas transformation at
  255. // start of this call to SerializeBuffer.
  256. PlaybackParams params = MakeParams(canvas);
  257. bool destroy_op_only = false;
  258. for (PaintOpBuffer::PlaybackFoldingIterator iter(buffer, offsets); iter;
  259. ++iter) {
  260. PaintOp* op = const_cast<PaintOp*>(*iter);
  261. if (!destroy_op_only) {
  262. // If serialization failed, destroy PaintOps in |buffer|.
  263. destroy_op_only = !WillSerializeNextOp(op, canvas, params, iter.alpha());
  264. }
  265. op->DestroyThis();
  266. }
  267. // Each PaintOp in |buffer| is destroyed. Update the flag |ops_destroyed| to
  268. // true, so it skip calling destruction in PaintOpsBuffer::Reset().
  269. const_cast<PaintOpBuffer*>(buffer)->MarkOpsDestroyed();
  270. }
  271. bool PaintOpBufferSerializer::SerializeOpWithFlags(
  272. SkCanvas* canvas,
  273. const PaintOpWithFlags* flags_op,
  274. const PlaybackParams& params,
  275. uint8_t alpha) {
  276. // We use a null |image_provider| here because images are decoded during
  277. // serialization.
  278. const ScopedRasterFlags scoped_flags(
  279. &flags_op->flags, nullptr, canvas->getTotalMatrix(),
  280. options_.max_texture_size, alpha / 255.0f);
  281. const PaintFlags* flags_to_serialize = scoped_flags.flags();
  282. if (!flags_to_serialize)
  283. return true;
  284. return SerializeOp(canvas, flags_op, flags_to_serialize, params);
  285. }
  286. bool PaintOpBufferSerializer::SerializeOp(SkCanvas* canvas,
  287. const PaintOp* op,
  288. const PaintFlags* flags_to_serialize,
  289. const PlaybackParams& params) {
  290. TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
  291. "PaintOpBufferSerializer::SerializeOp", "op",
  292. PaintOpTypeToString(op->GetType()));
  293. if (!valid_)
  294. return false;
  295. // Playback on analysis canvas first to make sure the canvas transform is set
  296. // correctly for analysis of records in filters.
  297. PlaybackOnAnalysisCanvas(canvas, op, flags_to_serialize, params);
  298. size_t bytes =
  299. serialize_cb_.Run(op, options_, flags_to_serialize,
  300. canvas->getLocalToDevice(), params.original_ctm);
  301. if (!bytes) {
  302. valid_ = false;
  303. return false;
  304. }
  305. DCHECK_GE(bytes, 4u);
  306. DCHECK_EQ(bytes % PaintOpBuffer::PaintOpAlign, 0u);
  307. return true;
  308. }
  309. void PaintOpBufferSerializer::PlaybackOnAnalysisCanvas(
  310. SkCanvas* canvas,
  311. const PaintOp* op,
  312. const PaintFlags* flags_to_serialize,
  313. const PlaybackParams& params) {
  314. // Only 2 types of ops need to played on the analysis canvas.
  315. // 1) Non-draw ops which affect the transform/clip state on the canvas, since
  316. // we need the correct ctm at which text and images will be rasterized, and
  317. // the clip rect so we can skip sending data for ops which will not be
  318. // rasterized.
  319. // 2) DrawTextBlob ops since they need to be analyzed by the cache diff canvas
  320. // to serialize/lock the requisite glyphs for this op.
  321. if (op->IsDrawOp() && op->GetType() != PaintOpType::DrawTextBlob)
  322. return;
  323. if (op->IsPaintOpWithFlags() && flags_to_serialize) {
  324. static_cast<const PaintOpWithFlags*>(op)->RasterWithFlags(
  325. canvas, flags_to_serialize, params);
  326. } else {
  327. op->Raster(canvas, params);
  328. }
  329. }
  330. void PaintOpBufferSerializer::Save(SkCanvas* canvas,
  331. const PlaybackParams& params) {
  332. SaveOp save_op;
  333. SerializeOp(canvas, &save_op, nullptr, params);
  334. }
  335. void PaintOpBufferSerializer::RestoreToCount(SkCanvas* canvas,
  336. int count,
  337. const PlaybackParams& params) {
  338. RestoreOp restore_op;
  339. while (canvas->getSaveCount() > count) {
  340. if (!SerializeOp(canvas, &restore_op, nullptr, params))
  341. return;
  342. }
  343. }
  344. SimpleBufferSerializer::SimpleBufferSerializer(
  345. void* memory,
  346. size_t size,
  347. const PaintOp::SerializeOptions& options)
  348. : PaintOpBufferSerializer(
  349. base::BindRepeating(&SimpleBufferSerializer::SerializeToMemory,
  350. base::Unretained(this)),
  351. options),
  352. memory_(memory),
  353. total_(size) {}
  354. SimpleBufferSerializer::~SimpleBufferSerializer() = default;
  355. size_t SimpleBufferSerializer::SerializeToMemory(
  356. const PaintOp* op,
  357. const PaintOp::SerializeOptions& options,
  358. const PaintFlags* flags_to_serialize,
  359. const SkM44& current_ctm,
  360. const SkM44& original_ctm) {
  361. if (written_ == total_)
  362. return 0u;
  363. size_t bytes =
  364. op->Serialize(static_cast<char*>(memory_) + written_, total_ - written_,
  365. options, flags_to_serialize, current_ctm, original_ctm);
  366. if (!bytes)
  367. return 0u;
  368. written_ += bytes;
  369. DCHECK_GE(total_, written_);
  370. return bytes;
  371. }
  372. } // namespace cc