paint_op_writer.cc 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  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_writer.h"
  5. #include <memory>
  6. #include <type_traits>
  7. #include "base/bits.h"
  8. #include "base/notreached.h"
  9. #include "cc/paint/draw_image.h"
  10. #include "cc/paint/image_provider.h"
  11. #include "cc/paint/image_transfer_cache_entry.h"
  12. #include "cc/paint/paint_cache.h"
  13. #include "cc/paint/paint_flags.h"
  14. #include "cc/paint/paint_op_buffer_serializer.h"
  15. #include "cc/paint/paint_shader.h"
  16. #include "cc/paint/skottie_transfer_cache_entry.h"
  17. #include "cc/paint/skottie_wrapper.h"
  18. #include "cc/paint/transfer_cache_serialize_helper.h"
  19. #include "gpu/command_buffer/common/mailbox.h"
  20. #include "third_party/skia/include/core/SkBitmap.h"
  21. #include "third_party/skia/include/core/SkColor.h"
  22. #include "third_party/skia/include/core/SkColorSpace.h"
  23. #include "third_party/skia/include/core/SkData.h"
  24. #include "third_party/skia/include/core/SkFlattenable.h"
  25. #include "third_party/skia/include/core/SkM44.h"
  26. #include "third_party/skia/include/core/SkMatrix.h"
  27. #include "third_party/skia/include/core/SkPath.h"
  28. #include "third_party/skia/include/core/SkRect.h"
  29. #include "third_party/skia/include/core/SkRefCnt.h"
  30. #include "third_party/skia/include/core/SkRegion.h"
  31. #include "third_party/skia/include/core/SkSamplingOptions.h"
  32. #include "third_party/skia/include/core/SkScalar.h"
  33. #include "third_party/skia/include/core/SkSerialProcs.h"
  34. #include "third_party/skia/include/core/SkSize.h"
  35. #include "third_party/skia/include/private/chromium/GrSlug.h"
  36. #include "third_party/skia/include/private/chromium/SkChromeRemoteGlyphCache.h"
  37. #include "ui/gfx/geometry/rect_conversions.h"
  38. #include "ui/gfx/geometry/skia_conversions.h"
  39. namespace cc {
  40. namespace {
  41. SkIRect MakeSrcRect(const PaintImage& image) {
  42. if (!image)
  43. return SkIRect::MakeEmpty();
  44. return SkIRect::MakeWH(image.width(), image.height());
  45. }
  46. } // namespace
  47. // static
  48. size_t PaintOpWriter::GetFlattenableSize(const SkFlattenable* flattenable) {
  49. // The first bit is always written to indicate the serialized size of the
  50. // flattenable, or zero if it doesn't exist.
  51. size_t total_size = sizeof(uint64_t) + sizeof(uint64_t) /* alignment */;
  52. if (!flattenable)
  53. return total_size;
  54. // There is no method to know the serialized size of a flattenable without
  55. // serializing it.
  56. sk_sp<SkData> data = flattenable->serialize();
  57. total_size += data->isEmpty() ? 0u : data->size();
  58. return total_size;
  59. }
  60. // static
  61. size_t PaintOpWriter::GetImageSize(const PaintImage& image) {
  62. // Image Serialization type.
  63. size_t image_size = sizeof(PaintOp::SerializedImageType);
  64. if (image) {
  65. auto info = SkImageInfo::Make(image.width(), image.height(),
  66. kN32_SkColorType, kPremul_SkAlphaType);
  67. image_size += sizeof(info.colorType());
  68. image_size += sizeof(info.width());
  69. image_size += sizeof(info.height());
  70. image_size += sizeof(uint64_t) + sizeof(uint64_t) /* alignment */;
  71. image_size += info.computeMinByteSize();
  72. }
  73. return image_size;
  74. }
  75. // static
  76. size_t PaintOpWriter::GetRecordSize(const PaintRecord* record) {
  77. // Zero size indicates no record.
  78. // TODO(khushalsagar): Querying the size of a PaintRecord is not supported.
  79. // This works only for security constrained serialization which ignores
  80. // records.
  81. return sizeof(uint64_t);
  82. }
  83. PaintOpWriter::PaintOpWriter(void* memory,
  84. size_t size,
  85. const PaintOp::SerializeOptions& options,
  86. bool enable_security_constraints)
  87. : memory_(static_cast<char*>(memory) + HeaderBytes()),
  88. size_(base::bits::AlignDown(size, Alignment())),
  89. remaining_bytes_(size_ - HeaderBytes()),
  90. options_(options),
  91. enable_security_constraints_(enable_security_constraints) {
  92. // Leave space for header of type/skip.
  93. DCHECK_GE(size, HeaderBytes());
  94. DCHECK_EQ(memory_.get(), base::bits::AlignUp(memory_.get(), Alignment()));
  95. }
  96. PaintOpWriter::~PaintOpWriter() = default;
  97. template <typename T>
  98. void PaintOpWriter::WriteSimple(const T& val) {
  99. static_assert(std::is_trivially_copyable_v<T>);
  100. // Round up each write to 4 bytes. This is not technically perfect alignment,
  101. // but it is about 30% faster to post-align each write to 4 bytes than it is
  102. // to pre-align memory to the correct alignment.
  103. DCHECK_EQ(memory_.get(), base::bits::AlignUp(memory_.get(), Alignment()));
  104. static constexpr size_t size = base::bits::AlignUp(sizeof(T), Alignment());
  105. EnsureBytes(size);
  106. if (!valid_)
  107. return;
  108. reinterpret_cast<T*>(memory_.get())[0] = val;
  109. memory_ += size;
  110. remaining_bytes_ -= size;
  111. }
  112. void PaintOpWriter::WriteFlattenable(const SkFlattenable* val) {
  113. if (!val) {
  114. WriteSize(static_cast<size_t>(0u));
  115. return;
  116. }
  117. uint64_t* size_memory = WriteSize(0u);
  118. if (!valid_)
  119. return;
  120. size_t bytes_written = val->serialize(
  121. memory_, base::bits::AlignDown(remaining_bytes_, Alignment()));
  122. if (bytes_written == 0u) {
  123. valid_ = false;
  124. return;
  125. }
  126. *size_memory = bytes_written;
  127. DidWrite(bytes_written);
  128. }
  129. uint64_t* PaintOpWriter::WriteSize(size_t size) {
  130. AlignMemory(8);
  131. uint64_t* memory = reinterpret_cast<uint64_t*>(memory_.get());
  132. WriteSimple<uint64_t>(size);
  133. return memory;
  134. }
  135. void PaintOpWriter::Write(SkScalar data) {
  136. WriteSimple(data);
  137. }
  138. void PaintOpWriter::Write(uint8_t data) {
  139. WriteSimple(data);
  140. }
  141. void PaintOpWriter::Write(uint32_t data) {
  142. WriteSimple(data);
  143. }
  144. void PaintOpWriter::Write(uint64_t data) {
  145. WriteSimple(data);
  146. }
  147. void PaintOpWriter::Write(int32_t data) {
  148. WriteSimple(data);
  149. }
  150. void PaintOpWriter::Write(const SkRect& rect) {
  151. WriteSimple(rect);
  152. }
  153. void PaintOpWriter::Write(const SkIRect& rect) {
  154. WriteSimple(rect);
  155. }
  156. void PaintOpWriter::Write(const SkRRect& rect) {
  157. WriteSimple(rect);
  158. }
  159. void PaintOpWriter::Write(const SkColor4f& color) {
  160. WriteSimple(color);
  161. }
  162. void PaintOpWriter::Write(const SkPath& path, UsePaintCache use_paint_cache) {
  163. auto id = path.getGenerationID();
  164. if (!options_.for_identifiability_study)
  165. Write(id);
  166. DCHECK(use_paint_cache == UsePaintCache::kEnabled ||
  167. !options_.paint_cache->Get(PaintCacheDataType::kPath, id));
  168. if (use_paint_cache == UsePaintCache::kEnabled &&
  169. options_.paint_cache->Get(PaintCacheDataType::kPath, id)) {
  170. Write(static_cast<uint32_t>(PaintCacheEntryState::kCached));
  171. return;
  172. }
  173. // The SkPath may fail to serialize if the bytes required would overflow.
  174. uint64_t bytes_required = path.writeToMemory(nullptr);
  175. if (bytes_required == 0u) {
  176. Write(static_cast<uint32_t>(PaintCacheEntryState::kEmpty));
  177. return;
  178. }
  179. if (use_paint_cache == UsePaintCache::kEnabled) {
  180. Write(static_cast<uint32_t>(PaintCacheEntryState::kInlined));
  181. } else {
  182. Write(static_cast<uint32_t>(PaintCacheEntryState::kInlinedDoNotCache));
  183. }
  184. uint64_t* bytes_to_skip = WriteSize(0u);
  185. if (!valid_)
  186. return;
  187. if (bytes_required > remaining_bytes_) {
  188. valid_ = false;
  189. return;
  190. }
  191. size_t bytes_written = path.writeToMemory(memory_);
  192. DCHECK_EQ(bytes_written, bytes_required);
  193. if (use_paint_cache == UsePaintCache::kEnabled) {
  194. options_.paint_cache->Put(PaintCacheDataType::kPath, id, bytes_written);
  195. }
  196. *bytes_to_skip = bytes_written;
  197. DidWrite(bytes_written);
  198. }
  199. void PaintOpWriter::Write(const PaintFlags& flags, const SkM44& current_ctm) {
  200. WriteSimple(flags.color_);
  201. Write(flags.width_);
  202. Write(flags.miter_limit_);
  203. Write(flags.blend_mode_);
  204. WriteSimple(flags.bitfields_uint_);
  205. WriteFlattenable(flags.path_effect_.get());
  206. WriteFlattenable(flags.mask_filter_.get());
  207. WriteFlattenable(flags.color_filter_.get());
  208. if (enable_security_constraints_)
  209. WriteSize(static_cast<size_t>(0u));
  210. else
  211. WriteFlattenable(flags.draw_looper_.get());
  212. Write(flags.image_filter_.get(), current_ctm);
  213. Write(flags.shader_.get(), flags.getFilterQuality(), current_ctm);
  214. }
  215. void PaintOpWriter::Write(const DrawImage& draw_image,
  216. SkSize* scale_adjustment) {
  217. const PaintImage& paint_image = draw_image.paint_image();
  218. // Empty image.
  219. if (!draw_image.paint_image()) {
  220. Write(static_cast<uint8_t>(PaintOp::SerializedImageType::kNoImage));
  221. return;
  222. }
  223. // We never ask for subsets during serialization.
  224. DCHECK_EQ(paint_image.width(), draw_image.src_rect().width());
  225. DCHECK_EQ(paint_image.height(), draw_image.src_rect().height());
  226. // Security constrained serialization inlines the image bitmap.
  227. if (enable_security_constraints_) {
  228. SkBitmap bm;
  229. if (!draw_image.paint_image().GetSwSkImage()->asLegacyBitmap(&bm)) {
  230. Write(static_cast<uint8_t>(PaintOp::SerializedImageType::kNoImage));
  231. return;
  232. }
  233. Write(static_cast<uint8_t>(PaintOp::SerializedImageType::kImageData));
  234. const auto& pixmap = bm.pixmap();
  235. Write(pixmap.colorType());
  236. Write(pixmap.width());
  237. Write(pixmap.height());
  238. size_t pixmap_size = pixmap.computeByteSize();
  239. WriteSize(pixmap_size);
  240. WriteData(pixmap_size, pixmap.addr());
  241. return;
  242. }
  243. // Default mode uses the transfer cache.
  244. auto decoded_image = options_.image_provider->GetRasterContent(draw_image);
  245. DCHECK(!decoded_image.decoded_image().image())
  246. << "Use transfer cache for image serialization";
  247. const DecodedDrawImage& decoded_draw_image = decoded_image.decoded_image();
  248. DCHECK(decoded_draw_image.src_rect_offset().isEmpty())
  249. << "We shouldn't ask for image subsets";
  250. *scale_adjustment = decoded_draw_image.scale_adjustment();
  251. WriteImage(decoded_draw_image);
  252. }
  253. void PaintOpWriter::Write(scoped_refptr<SkottieWrapper> skottie) {
  254. uint32_t id = skottie->id();
  255. Write(id);
  256. uint64_t* bytes_to_skip = WriteSize(0u);
  257. if (!valid_)
  258. return;
  259. bool locked =
  260. options_.transfer_cache->LockEntry(TransferCacheEntryType::kSkottie, id);
  261. // Add a cache entry for the skottie animation.
  262. uint64_t bytes_written = 0u;
  263. if (!locked) {
  264. bytes_written = options_.transfer_cache->CreateEntry(
  265. ClientSkottieTransferCacheEntry(skottie), memory_);
  266. options_.transfer_cache->AssertLocked(TransferCacheEntryType::kSkottie, id);
  267. }
  268. DCHECK_LE(bytes_written, remaining_bytes_);
  269. *bytes_to_skip = bytes_written;
  270. DidWrite(bytes_written);
  271. }
  272. void PaintOpWriter::WriteImage(const DecodedDrawImage& decoded_draw_image) {
  273. if (!decoded_draw_image.mailbox().IsZero()) {
  274. WriteImage(decoded_draw_image.mailbox());
  275. return;
  276. }
  277. absl::optional<uint32_t> id = decoded_draw_image.transfer_cache_entry_id();
  278. // In the case of a decode failure, id may not be set. Send an invalid ID.
  279. WriteImage(id.value_or(kInvalidImageTransferCacheEntryId),
  280. decoded_draw_image.transfer_cache_entry_needs_mips());
  281. }
  282. void PaintOpWriter::WriteImage(uint32_t transfer_cache_entry_id,
  283. bool needs_mips) {
  284. if (transfer_cache_entry_id == kInvalidImageTransferCacheEntryId) {
  285. Write(static_cast<uint8_t>(PaintOp::SerializedImageType::kNoImage));
  286. return;
  287. }
  288. Write(
  289. static_cast<uint8_t>(PaintOp::SerializedImageType::kTransferCacheEntry));
  290. Write(transfer_cache_entry_id);
  291. Write(needs_mips);
  292. }
  293. void PaintOpWriter::WriteImage(const gpu::Mailbox& mailbox) {
  294. DCHECK(!mailbox.IsZero());
  295. Write(static_cast<uint8_t>(PaintOp::SerializedImageType::kMailbox));
  296. EnsureBytes(sizeof(mailbox.name));
  297. if (!valid_)
  298. return;
  299. memcpy(memory_, mailbox.name, sizeof(mailbox.name));
  300. DidWrite(sizeof(mailbox.name));
  301. }
  302. void PaintOpWriter::Write(const sk_sp<SkData>& data) {
  303. if (data.get() && data->size()) {
  304. WriteSize(data->size());
  305. WriteData(data->size(), data->data());
  306. } else {
  307. // Differentiate between nullptr and valid but zero size. It's not clear
  308. // that this happens in practice, but seems better to be consistent.
  309. WriteSize(static_cast<size_t>(0));
  310. Write(!!data.get());
  311. }
  312. }
  313. void PaintOpWriter::Write(const SkSamplingOptions& sampling) {
  314. Write(sampling.useCubic);
  315. if (sampling.useCubic) {
  316. Write(sampling.cubic.B);
  317. Write(sampling.cubic.C);
  318. } else {
  319. Write(sampling.filter);
  320. Write(sampling.mipmap);
  321. }
  322. }
  323. void PaintOpWriter::Write(const SkColorSpace* color_space) {
  324. if (!color_space) {
  325. WriteSize(static_cast<size_t>(0));
  326. return;
  327. }
  328. size_t size = color_space->writeToMemory(nullptr);
  329. WriteSize(size);
  330. EnsureBytes(size);
  331. if (!valid_)
  332. return;
  333. size_t written = color_space->writeToMemory(memory_);
  334. CHECK_EQ(written, size);
  335. DidWrite(written);
  336. }
  337. void PaintOpWriter::Write(const sk_sp<GrSlug>& slug) {
  338. if (!valid_)
  339. return;
  340. AssertAlignment(Alignment());
  341. uint64_t* size_memory = WriteSize(0u);
  342. if (!valid_)
  343. return;
  344. size_t bytes_written = 0;
  345. if (slug) {
  346. // TODO(penghuang): should we use a unique id to avoid sending the same
  347. // slug?
  348. bytes_written = slug->serialize(
  349. memory_, base::bits::AlignDown(remaining_bytes_, Alignment()));
  350. if (bytes_written == 0u) {
  351. valid_ = false;
  352. return;
  353. }
  354. }
  355. *size_memory = bytes_written;
  356. DidWrite(bytes_written);
  357. }
  358. sk_sp<PaintShader> PaintOpWriter::TransformShaderIfNecessary(
  359. const PaintShader* original,
  360. PaintFlags::FilterQuality quality,
  361. const SkM44& current_ctm,
  362. uint32_t* paint_image_transfer_cache_entry_id,
  363. gfx::SizeF* paint_record_post_scale,
  364. bool* paint_image_needs_mips,
  365. gpu::Mailbox* mailbox_out) {
  366. DCHECK(!enable_security_constraints_);
  367. const auto type = original->shader_type();
  368. const auto& ctm = current_ctm.asM33();
  369. if (type == PaintShader::Type::kImage) {
  370. if (!original->paint_image().IsPaintWorklet()) {
  371. return original->CreateDecodedImage(ctm, quality, options_.image_provider,
  372. paint_image_transfer_cache_entry_id,
  373. &quality, paint_image_needs_mips,
  374. mailbox_out);
  375. }
  376. sk_sp<PaintShader> record_shader =
  377. original->CreatePaintWorkletRecord(options_.image_provider);
  378. if (!record_shader)
  379. return nullptr;
  380. return record_shader->CreateScaledPaintRecord(
  381. ctm, options_.max_texture_size, paint_record_post_scale);
  382. }
  383. if (type == PaintShader::Type::kPaintRecord) {
  384. return original->CreateScaledPaintRecord(ctm, options_.max_texture_size,
  385. paint_record_post_scale);
  386. }
  387. return sk_ref_sp<PaintShader>(original);
  388. }
  389. void PaintOpWriter::Write(SkMatrix matrix) {
  390. if (!matrix.isIdentity())
  391. matrix.dirtyMatrixTypeCache();
  392. WriteSimple(matrix);
  393. }
  394. void PaintOpWriter::Write(const SkM44& matrix) {
  395. WriteSimple(matrix);
  396. }
  397. void PaintOpWriter::Write(const PaintShader* shader,
  398. PaintFlags::FilterQuality quality,
  399. const SkM44& current_ctm) {
  400. sk_sp<PaintShader> transformed_shader;
  401. uint32_t paint_image_transfer_cache_id = kInvalidImageTransferCacheEntryId;
  402. gfx::SizeF paint_record_post_scale(1.f, 1.f);
  403. bool paint_image_needs_mips = false;
  404. gpu::Mailbox mailbox;
  405. if (!enable_security_constraints_ && shader) {
  406. transformed_shader = TransformShaderIfNecessary(
  407. shader, quality, current_ctm, &paint_image_transfer_cache_id,
  408. &paint_record_post_scale, &paint_image_needs_mips, &mailbox);
  409. shader = transformed_shader.get();
  410. }
  411. if (!shader) {
  412. WriteSimple(false);
  413. return;
  414. }
  415. // TODO(vmpstr): This could be optimized to only serialize fields relevant to
  416. // the specific shader type. If done, then corresponding reading and tests
  417. // would have to also be updated.
  418. WriteSimple(true);
  419. WriteSimple(shader->shader_type_);
  420. WriteSimple(shader->flags_);
  421. WriteSimple(shader->end_radius_);
  422. WriteSimple(shader->start_radius_);
  423. Write(shader->tx_);
  424. Write(shader->ty_);
  425. WriteSimple(shader->fallback_color_);
  426. WriteSimple(shader->scaling_behavior_);
  427. if (shader->local_matrix_) {
  428. Write(true);
  429. Write(*shader->local_matrix_);
  430. } else {
  431. Write(false);
  432. }
  433. WriteSimple(shader->center_);
  434. WriteSimple(shader->tile_);
  435. WriteSimple(shader->start_point_);
  436. WriteSimple(shader->end_point_);
  437. WriteSimple(shader->start_degrees_);
  438. WriteSimple(shader->end_degrees_);
  439. if (enable_security_constraints_) {
  440. DrawImage draw_image(shader->image_, false, MakeSrcRect(shader->image_),
  441. quality, SkM44());
  442. SkSize scale_adjustment = SkSize::Make(1.f, 1.f);
  443. Write(draw_image, &scale_adjustment);
  444. DCHECK_EQ(scale_adjustment.width(), 1.f);
  445. DCHECK_EQ(scale_adjustment.height(), 1.f);
  446. } else {
  447. if (!mailbox.IsZero())
  448. WriteImage(mailbox);
  449. else
  450. WriteImage(paint_image_transfer_cache_id, paint_image_needs_mips);
  451. }
  452. if (shader->record_) {
  453. Write(true);
  454. DCHECK_NE(shader->id_, PaintShader::kInvalidRecordShaderId);
  455. if (!options_.for_identifiability_study)
  456. Write(shader->id_);
  457. const gfx::Rect playback_rect(
  458. gfx::ToEnclosingRect(gfx::SkRectToRectF(shader->tile())));
  459. Write(shader->record_.get(), playback_rect, paint_record_post_scale);
  460. } else {
  461. DCHECK_EQ(shader->id_, PaintShader::kInvalidRecordShaderId);
  462. Write(false);
  463. }
  464. WriteSize(shader->colors_.size());
  465. WriteData(shader->colors_.size() *
  466. (shader->colors_.size() > 0 ? sizeof(shader->colors_[0]) : 0u),
  467. shader->colors_.data());
  468. WriteSize(shader->positions_.size());
  469. WriteData(shader->positions_.size() * sizeof(SkScalar),
  470. shader->positions_.data());
  471. // Explicitly don't write the cached_shader_ because that can be regenerated
  472. // using other fields.
  473. }
  474. void PaintOpWriter::Write(SkYUVColorSpace yuv_color_space) {
  475. WriteSimple(static_cast<uint32_t>(yuv_color_space));
  476. }
  477. void PaintOpWriter::Write(SkYUVAInfo::PlaneConfig plane_config) {
  478. WriteSimple(static_cast<uint32_t>(plane_config));
  479. }
  480. void PaintOpWriter::Write(SkYUVAInfo::Subsampling subsampling) {
  481. WriteSimple(static_cast<uint32_t>(subsampling));
  482. }
  483. void PaintOpWriter::WriteData(size_t bytes, const void* input) {
  484. DCHECK_EQ(memory_.get(),
  485. base::bits::AlignUp(memory_.get(), PaintOpWriter::Alignment()));
  486. if (bytes == 0)
  487. return;
  488. EnsureBytes(bytes);
  489. if (!valid_)
  490. return;
  491. memcpy(memory_, input, bytes);
  492. DidWrite(bytes);
  493. }
  494. void PaintOpWriter::AlignMemory(size_t alignment) {
  495. // Due to the math below, alignment must be a power of two.
  496. DCHECK_GT(alignment, 0u);
  497. DCHECK_EQ(alignment & (alignment - 1), 0u);
  498. uintptr_t memory = reinterpret_cast<uintptr_t>(memory_.get());
  499. // The following is equivalent to:
  500. // padding = (alignment - memory % alignment) % alignment;
  501. // because alignment is a power of two. This doesn't use modulo operator
  502. // however, since it can be slow.
  503. size_t padding = base::bits::AlignUp(memory, alignment) - memory;
  504. EnsureBytes(padding);
  505. if (!valid_)
  506. return;
  507. memory_ += padding;
  508. remaining_bytes_ -= padding;
  509. }
  510. void PaintOpWriter::Write(const PaintFilter* filter, const SkM44& current_ctm) {
  511. if (!filter) {
  512. WriteEnum(PaintFilter::Type::kNullFilter);
  513. return;
  514. }
  515. WriteEnum(filter->type());
  516. auto* crop_rect = filter->GetCropRect();
  517. WriteSimple(static_cast<uint32_t>(!!crop_rect));
  518. if (crop_rect) {
  519. WriteSimple(*crop_rect);
  520. }
  521. if (!valid_)
  522. return;
  523. AssertAlignment(Alignment());
  524. switch (filter->type()) {
  525. case PaintFilter::Type::kNullFilter:
  526. NOTREACHED();
  527. break;
  528. case PaintFilter::Type::kColorFilter:
  529. Write(static_cast<const ColorFilterPaintFilter&>(*filter), current_ctm);
  530. break;
  531. case PaintFilter::Type::kBlur:
  532. Write(static_cast<const BlurPaintFilter&>(*filter), current_ctm);
  533. break;
  534. case PaintFilter::Type::kDropShadow:
  535. Write(static_cast<const DropShadowPaintFilter&>(*filter), current_ctm);
  536. break;
  537. case PaintFilter::Type::kMagnifier:
  538. Write(static_cast<const MagnifierPaintFilter&>(*filter), current_ctm);
  539. break;
  540. case PaintFilter::Type::kCompose:
  541. Write(static_cast<const ComposePaintFilter&>(*filter), current_ctm);
  542. break;
  543. case PaintFilter::Type::kAlphaThreshold:
  544. Write(static_cast<const AlphaThresholdPaintFilter&>(*filter),
  545. current_ctm);
  546. break;
  547. case PaintFilter::Type::kXfermode:
  548. Write(static_cast<const XfermodePaintFilter&>(*filter), current_ctm);
  549. break;
  550. case PaintFilter::Type::kArithmetic:
  551. Write(static_cast<const ArithmeticPaintFilter&>(*filter), current_ctm);
  552. break;
  553. case PaintFilter::Type::kMatrixConvolution:
  554. Write(static_cast<const MatrixConvolutionPaintFilter&>(*filter),
  555. current_ctm);
  556. break;
  557. case PaintFilter::Type::kDisplacementMapEffect:
  558. Write(static_cast<const DisplacementMapEffectPaintFilter&>(*filter),
  559. current_ctm);
  560. break;
  561. case PaintFilter::Type::kImage:
  562. Write(static_cast<const ImagePaintFilter&>(*filter), current_ctm);
  563. break;
  564. case PaintFilter::Type::kPaintRecord:
  565. Write(static_cast<const RecordPaintFilter&>(*filter), current_ctm);
  566. break;
  567. case PaintFilter::Type::kMerge:
  568. Write(static_cast<const MergePaintFilter&>(*filter), current_ctm);
  569. break;
  570. case PaintFilter::Type::kMorphology:
  571. Write(static_cast<const MorphologyPaintFilter&>(*filter), current_ctm);
  572. break;
  573. case PaintFilter::Type::kOffset:
  574. Write(static_cast<const OffsetPaintFilter&>(*filter), current_ctm);
  575. break;
  576. case PaintFilter::Type::kTile:
  577. Write(static_cast<const TilePaintFilter&>(*filter), current_ctm);
  578. break;
  579. case PaintFilter::Type::kTurbulence:
  580. Write(static_cast<const TurbulencePaintFilter&>(*filter), current_ctm);
  581. break;
  582. case PaintFilter::Type::kShader:
  583. Write(static_cast<const ShaderPaintFilter&>(*filter), current_ctm);
  584. break;
  585. case PaintFilter::Type::kMatrix:
  586. Write(static_cast<const MatrixPaintFilter&>(*filter), current_ctm);
  587. break;
  588. case PaintFilter::Type::kLightingDistant:
  589. Write(static_cast<const LightingDistantPaintFilter&>(*filter),
  590. current_ctm);
  591. break;
  592. case PaintFilter::Type::kLightingPoint:
  593. Write(static_cast<const LightingPointPaintFilter&>(*filter), current_ctm);
  594. break;
  595. case PaintFilter::Type::kLightingSpot:
  596. Write(static_cast<const LightingSpotPaintFilter&>(*filter), current_ctm);
  597. break;
  598. case PaintFilter::Type::kStretch:
  599. Write(static_cast<const StretchPaintFilter&>(*filter), current_ctm);
  600. break;
  601. }
  602. }
  603. void PaintOpWriter::Write(const ColorFilterPaintFilter& filter,
  604. const SkM44& current_ctm) {
  605. WriteFlattenable(filter.color_filter().get());
  606. Write(filter.input().get(), current_ctm);
  607. }
  608. void PaintOpWriter::Write(const BlurPaintFilter& filter,
  609. const SkM44& current_ctm) {
  610. WriteSimple(filter.sigma_x());
  611. WriteSimple(filter.sigma_y());
  612. Write(filter.tile_mode());
  613. Write(filter.input().get(), current_ctm);
  614. }
  615. void PaintOpWriter::Write(const DropShadowPaintFilter& filter,
  616. const SkM44& current_ctm) {
  617. WriteSimple(filter.dx());
  618. WriteSimple(filter.dy());
  619. WriteSimple(filter.sigma_x());
  620. WriteSimple(filter.sigma_y());
  621. // TODO(crbug/1308932): Remove toSkColor and make all SkColor4f.
  622. WriteSimple(filter.color().toSkColor());
  623. WriteEnum(filter.shadow_mode());
  624. Write(filter.input().get(), current_ctm);
  625. }
  626. void PaintOpWriter::Write(const MagnifierPaintFilter& filter,
  627. const SkM44& current_ctm) {
  628. WriteSimple(filter.src_rect());
  629. WriteSimple(filter.inset());
  630. Write(filter.input().get(), current_ctm);
  631. }
  632. void PaintOpWriter::Write(const ComposePaintFilter& filter,
  633. const SkM44& current_ctm) {
  634. Write(filter.outer().get(), current_ctm);
  635. Write(filter.inner().get(), current_ctm);
  636. }
  637. void PaintOpWriter::Write(const AlphaThresholdPaintFilter& filter,
  638. const SkM44& current_ctm) {
  639. Write(filter.region());
  640. WriteSimple(filter.inner_min());
  641. WriteSimple(filter.outer_max());
  642. Write(filter.input().get(), current_ctm);
  643. }
  644. void PaintOpWriter::Write(const XfermodePaintFilter& filter,
  645. const SkM44& current_ctm) {
  646. Write(filter.blend_mode());
  647. Write(filter.background().get(), current_ctm);
  648. Write(filter.foreground().get(), current_ctm);
  649. }
  650. void PaintOpWriter::Write(const ArithmeticPaintFilter& filter,
  651. const SkM44& current_ctm) {
  652. WriteSimple(filter.k1());
  653. WriteSimple(filter.k2());
  654. WriteSimple(filter.k3());
  655. WriteSimple(filter.k4());
  656. WriteSimple(filter.enforce_pm_color());
  657. Write(filter.background().get(), current_ctm);
  658. Write(filter.foreground().get(), current_ctm);
  659. }
  660. void PaintOpWriter::Write(const MatrixConvolutionPaintFilter& filter,
  661. const SkM44& current_ctm) {
  662. WriteSimple(filter.kernel_size());
  663. auto size = static_cast<size_t>(
  664. sk_64_mul(filter.kernel_size().width(), filter.kernel_size().height()));
  665. for (size_t i = 0; i < size; ++i)
  666. WriteSimple(filter.kernel_at(i));
  667. WriteSimple(filter.gain());
  668. WriteSimple(filter.bias());
  669. WriteSimple(filter.kernel_offset());
  670. Write(filter.tile_mode());
  671. WriteSimple(filter.convolve_alpha());
  672. Write(filter.input().get(), current_ctm);
  673. }
  674. void PaintOpWriter::Write(const DisplacementMapEffectPaintFilter& filter,
  675. const SkM44& current_ctm) {
  676. WriteEnum(filter.channel_x());
  677. WriteEnum(filter.channel_y());
  678. WriteSimple(filter.scale());
  679. Write(filter.displacement().get(), current_ctm);
  680. Write(filter.color().get(), current_ctm);
  681. }
  682. void PaintOpWriter::Write(const ImagePaintFilter& filter,
  683. const SkM44& current_ctm) {
  684. DrawImage draw_image(
  685. filter.image(), false,
  686. SkIRect::MakeWH(filter.image().width(), filter.image().height()),
  687. filter.filter_quality(), SkM44());
  688. SkSize scale_adjustment = SkSize::Make(1.f, 1.f);
  689. Write(draw_image, &scale_adjustment);
  690. DCHECK_EQ(scale_adjustment.width(), 1.f);
  691. DCHECK_EQ(scale_adjustment.height(), 1.f);
  692. Write(filter.src_rect());
  693. Write(filter.dst_rect());
  694. Write(filter.filter_quality());
  695. }
  696. void PaintOpWriter::Write(const RecordPaintFilter& filter,
  697. const SkM44& current_ctm) {
  698. // Convert to a fixed scale filter so that any content contained within
  699. // the filter's PaintRecord is rasterized at the scale we use here for
  700. // analysis (e.g. this ensures any contained text blobs will not be missing
  701. // from the cache).
  702. auto scaled_filter = filter.CreateScaledPaintRecord(
  703. current_ctm.asM33(), options_.max_texture_size);
  704. if (!scaled_filter) {
  705. WriteSimple(false);
  706. return;
  707. }
  708. WriteSimple(true);
  709. WriteSimple(scaled_filter->record_bounds());
  710. WriteSimple(scaled_filter->raster_scale());
  711. WriteSimple(scaled_filter->scaling_behavior());
  712. Write(scaled_filter->record().get(), gfx::Rect(),
  713. scaled_filter->raster_scale());
  714. }
  715. void PaintOpWriter::Write(const MergePaintFilter& filter,
  716. const SkM44& current_ctm) {
  717. WriteSize(filter.input_count());
  718. for (size_t i = 0; i < filter.input_count(); ++i)
  719. Write(filter.input_at(i), current_ctm);
  720. }
  721. void PaintOpWriter::Write(const MorphologyPaintFilter& filter,
  722. const SkM44& current_ctm) {
  723. WriteEnum(filter.morph_type());
  724. WriteSimple(filter.radius_x());
  725. WriteSimple(filter.radius_y());
  726. Write(filter.input().get(), current_ctm);
  727. }
  728. void PaintOpWriter::Write(const OffsetPaintFilter& filter,
  729. const SkM44& current_ctm) {
  730. WriteSimple(filter.dx());
  731. WriteSimple(filter.dy());
  732. Write(filter.input().get(), current_ctm);
  733. }
  734. void PaintOpWriter::Write(const TilePaintFilter& filter,
  735. const SkM44& current_ctm) {
  736. WriteSimple(filter.src());
  737. WriteSimple(filter.dst());
  738. Write(filter.input().get(), current_ctm);
  739. }
  740. void PaintOpWriter::Write(const TurbulencePaintFilter& filter,
  741. const SkM44& current_ctm) {
  742. WriteEnum(filter.turbulence_type());
  743. WriteSimple(filter.base_frequency_x());
  744. WriteSimple(filter.base_frequency_y());
  745. WriteSimple(filter.num_octaves());
  746. WriteSimple(filter.seed());
  747. WriteSimple(filter.tile_size());
  748. }
  749. void PaintOpWriter::Write(const ShaderPaintFilter& filter,
  750. const SkM44& current_ctm) {
  751. Write(&filter.shader(), filter.filter_quality(), current_ctm);
  752. Write(filter.alpha());
  753. Write(filter.filter_quality());
  754. WriteEnum(filter.dither());
  755. }
  756. void PaintOpWriter::Write(const MatrixPaintFilter& filter,
  757. const SkM44& current_ctm) {
  758. Write(filter.matrix());
  759. Write(filter.filter_quality());
  760. Write(filter.input().get(), current_ctm);
  761. }
  762. void PaintOpWriter::Write(const LightingDistantPaintFilter& filter,
  763. const SkM44& current_ctm) {
  764. WriteEnum(filter.lighting_type());
  765. WriteSimple(filter.direction());
  766. // TODO(crbug/1308932): Remove toSkColor and make all SkColor4f.
  767. WriteSimple(filter.light_color().toSkColor());
  768. WriteSimple(filter.surface_scale());
  769. WriteSimple(filter.kconstant());
  770. WriteSimple(filter.shininess());
  771. Write(filter.input().get(), current_ctm);
  772. }
  773. void PaintOpWriter::Write(const LightingPointPaintFilter& filter,
  774. const SkM44& current_ctm) {
  775. WriteEnum(filter.lighting_type());
  776. WriteSimple(filter.location());
  777. // TODO(crbug/1308932): Remove toSkColor and make all SkColor4f.
  778. WriteSimple(filter.light_color().toSkColor());
  779. WriteSimple(filter.surface_scale());
  780. WriteSimple(filter.kconstant());
  781. WriteSimple(filter.shininess());
  782. Write(filter.input().get(), current_ctm);
  783. }
  784. void PaintOpWriter::Write(const LightingSpotPaintFilter& filter,
  785. const SkM44& current_ctm) {
  786. WriteEnum(filter.lighting_type());
  787. WriteSimple(filter.location());
  788. WriteSimple(filter.target());
  789. WriteSimple(filter.specular_exponent());
  790. WriteSimple(filter.cutoff_angle());
  791. // TODO(crbug/1308932): Remove toSkColor and make all SkColor4f.
  792. WriteSimple(filter.light_color().toSkColor());
  793. WriteSimple(filter.surface_scale());
  794. WriteSimple(filter.kconstant());
  795. WriteSimple(filter.shininess());
  796. Write(filter.input().get(), current_ctm);
  797. }
  798. void PaintOpWriter::Write(const StretchPaintFilter& filter,
  799. const SkM44& current_ctm) {
  800. WriteSimple(filter.stretch_x());
  801. WriteSimple(filter.stretch_y());
  802. WriteSimple(filter.width());
  803. WriteSimple(filter.height());
  804. Write(filter.input().get(), current_ctm);
  805. }
  806. void PaintOpWriter::Write(const PaintRecord* record,
  807. const gfx::Rect& playback_rect,
  808. const gfx::SizeF& post_scale) {
  809. AlignMemory(PaintOpBuffer::PaintOpAlign);
  810. // We need to record how many bytes we will serialize, but we don't know this
  811. // information until we do the serialization. So, skip the amount needed
  812. // before writing.
  813. size_t size_offset = sizeof(uint64_t);
  814. EnsureBytes(size_offset);
  815. if (!valid_)
  816. return;
  817. uint64_t* size_memory = WriteSize(0u);
  818. if (!valid_)
  819. return;
  820. if (enable_security_constraints_) {
  821. // We don't serialize PaintRecords when security constraints are enabled.
  822. return;
  823. }
  824. // Nested records are used for picture shaders and filters. These are always
  825. // converted to a fixed scale mode (hence |post_scale|), which means they are
  826. // first rendered offscreen via SkImage::MakeFromPicture. This inherently does
  827. // not support lcd text, so reflect that in the serialization options.
  828. PaintOp::SerializeOptions lcd_disabled_options = options_;
  829. lcd_disabled_options.can_use_lcd_text = false;
  830. SimpleBufferSerializer serializer(memory_, remaining_bytes_,
  831. lcd_disabled_options);
  832. serializer.Serialize(record, playback_rect, post_scale);
  833. if (!serializer.valid()) {
  834. valid_ = false;
  835. return;
  836. }
  837. // Now we can write the number of bytes we used. Ensure this amount is size_t,
  838. // since that's what we allocated for it.
  839. static_assert(sizeof(serializer.written()) == sizeof(size_t),
  840. "written() return type size is different from sizeof(size_t)");
  841. // Write the size to the size memory, which preceeds the memory for the
  842. // record.
  843. *size_memory = serializer.written();
  844. // The serializer should have failed if it ran out of space. DCHECK to verify
  845. // that it wrote at most as many bytes as we had left.
  846. DCHECK_LE(serializer.written(), remaining_bytes_);
  847. DidWrite(serializer.written());
  848. }
  849. void PaintOpWriter::Write(const SkRegion& region) {
  850. size_t bytes_required = region.writeToMemory(nullptr);
  851. std::unique_ptr<char[]> data(new char[bytes_required]);
  852. size_t bytes_written = region.writeToMemory(data.get());
  853. DCHECK_EQ(bytes_required, bytes_written);
  854. WriteSize(bytes_written);
  855. WriteData(bytes_written, data.get());
  856. }
  857. inline void PaintOpWriter::DidWrite(size_t bytes_written) {
  858. // All data are aligned with PaintOpWriter::Alignment() at least.
  859. size_t aligned_bytes = base::bits::AlignUp(bytes_written, Alignment());
  860. memory_ += aligned_bytes;
  861. DCHECK_LE(aligned_bytes, remaining_bytes_);
  862. remaining_bytes_ -= aligned_bytes;
  863. }
  864. inline void PaintOpWriter::EnsureBytes(size_t required_bytes) {
  865. if (remaining_bytes_ < required_bytes)
  866. valid_ = false;
  867. }
  868. } // namespace cc