skia_paint_canvas.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  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/skia_paint_canvas.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/notreached.h"
  8. #include "base/trace_event/trace_event.h"
  9. #include "cc/paint/display_item_list.h"
  10. #include "cc/paint/paint_recorder.h"
  11. #include "cc/paint/scoped_raster_flags.h"
  12. #include "cc/paint/skottie_wrapper.h"
  13. #include "skia/ext/legacy_display_globals.h"
  14. #include "third_party/skia/include/core/SkAnnotation.h"
  15. #include "third_party/skia/include/core/SkCanvas.h"
  16. #include "third_party/skia/include/core/SkImageInfo.h"
  17. #include "third_party/skia/include/core/SkPoint.h"
  18. #include "third_party/skia/include/core/SkTextBlob.h"
  19. #include "third_party/skia/include/docs/SkPDFDocument.h"
  20. #include "third_party/skia/include/gpu/GrRecordingContext.h"
  21. namespace cc {
  22. SkiaPaintCanvas::ContextFlushes::ContextFlushes()
  23. : enable(false), max_draws_before_flush(-1) {}
  24. SkiaPaintCanvas::SkiaPaintCanvas(SkCanvas* canvas,
  25. ImageProvider* image_provider,
  26. ContextFlushes context_flushes)
  27. : canvas_(canvas),
  28. image_provider_(image_provider),
  29. context_flushes_(context_flushes) {}
  30. SkiaPaintCanvas::SkiaPaintCanvas(const SkBitmap& bitmap,
  31. ImageProvider* image_provider)
  32. : canvas_(new SkCanvas(bitmap,
  33. skia::LegacyDisplayGlobals::GetSkSurfaceProps())),
  34. bitmap_(bitmap),
  35. owned_(canvas_),
  36. image_provider_(image_provider) {}
  37. SkiaPaintCanvas::SkiaPaintCanvas(const SkBitmap& bitmap,
  38. const SkSurfaceProps& props)
  39. : canvas_(new SkCanvas(bitmap, props)), bitmap_(bitmap), owned_(canvas_) {}
  40. SkiaPaintCanvas::~SkiaPaintCanvas() = default;
  41. SkImageInfo SkiaPaintCanvas::imageInfo() const {
  42. return canvas_->imageInfo();
  43. }
  44. void* SkiaPaintCanvas::accessTopLayerPixels(SkImageInfo* info,
  45. size_t* rowBytes,
  46. SkIPoint* origin) {
  47. if (bitmap_.isNull() || bitmap_.isImmutable())
  48. return nullptr;
  49. return canvas_->accessTopLayerPixels(info, rowBytes, origin);
  50. }
  51. void SkiaPaintCanvas::flush() {
  52. canvas_->flush();
  53. }
  54. bool SkiaPaintCanvas::NeedsFlush() const {
  55. // Since flush() is always capable of flushing immediately with
  56. // SkiaPaintCanvas, there is never any need for deferred flushing.
  57. return false;
  58. }
  59. int SkiaPaintCanvas::save() {
  60. return canvas_->save();
  61. }
  62. int SkiaPaintCanvas::saveLayer(const SkRect* bounds, const PaintFlags* flags) {
  63. if (!flags)
  64. return canvas_->saveLayer(bounds, nullptr);
  65. SkPaint paint = flags->ToSkPaint();
  66. return canvas_->saveLayer(bounds, &paint);
  67. }
  68. int SkiaPaintCanvas::saveLayerAlpha(const SkRect* bounds, uint8_t alpha) {
  69. return canvas_->saveLayerAlpha(bounds, alpha);
  70. }
  71. void SkiaPaintCanvas::restore() {
  72. canvas_->restore();
  73. }
  74. int SkiaPaintCanvas::getSaveCount() const {
  75. return canvas_->getSaveCount();
  76. }
  77. void SkiaPaintCanvas::restoreToCount(int save_count) {
  78. canvas_->restoreToCount(save_count);
  79. }
  80. void SkiaPaintCanvas::translate(SkScalar dx, SkScalar dy) {
  81. canvas_->translate(dx, dy);
  82. }
  83. void SkiaPaintCanvas::scale(SkScalar sx, SkScalar sy) {
  84. canvas_->scale(sx, sy);
  85. }
  86. void SkiaPaintCanvas::rotate(SkScalar degrees) {
  87. canvas_->rotate(degrees);
  88. }
  89. void SkiaPaintCanvas::setMatrix(const SkM44& matrix) {
  90. canvas_->setMatrix(matrix);
  91. }
  92. void SkiaPaintCanvas::concat(const SkM44& matrix) {
  93. canvas_->concat(matrix);
  94. }
  95. void SkiaPaintCanvas::concat(const SkMatrix& matrix) {
  96. canvas_->concat(matrix);
  97. }
  98. void SkiaPaintCanvas::setMatrix(const SkMatrix& matrix) {
  99. canvas_->setMatrix(matrix);
  100. }
  101. void SkiaPaintCanvas::clipRect(const SkRect& rect,
  102. SkClipOp op,
  103. bool do_anti_alias) {
  104. canvas_->clipRect(rect, op, do_anti_alias);
  105. }
  106. void SkiaPaintCanvas::clipRRect(const SkRRect& rrect,
  107. SkClipOp op,
  108. bool do_anti_alias) {
  109. canvas_->clipRRect(rrect, op, do_anti_alias);
  110. }
  111. void SkiaPaintCanvas::clipPath(const SkPath& path,
  112. SkClipOp op,
  113. bool do_anti_alias,
  114. UsePaintCache) {
  115. canvas_->clipPath(path, op, do_anti_alias);
  116. }
  117. SkRect SkiaPaintCanvas::getLocalClipBounds() const {
  118. return canvas_->getLocalClipBounds();
  119. }
  120. bool SkiaPaintCanvas::getLocalClipBounds(SkRect* bounds) const {
  121. return canvas_->getLocalClipBounds(bounds);
  122. }
  123. SkIRect SkiaPaintCanvas::getDeviceClipBounds() const {
  124. return canvas_->getDeviceClipBounds();
  125. }
  126. bool SkiaPaintCanvas::getDeviceClipBounds(SkIRect* bounds) const {
  127. return canvas_->getDeviceClipBounds(bounds);
  128. }
  129. void SkiaPaintCanvas::drawColor(SkColor4f color, SkBlendMode mode) {
  130. canvas_->drawColor(color, mode);
  131. }
  132. void SkiaPaintCanvas::clear(SkColor4f color) {
  133. canvas_->clear(color);
  134. }
  135. void SkiaPaintCanvas::drawLine(SkScalar x0,
  136. SkScalar y0,
  137. SkScalar x1,
  138. SkScalar y1,
  139. const PaintFlags& flags) {
  140. ScopedRasterFlags raster_flags(&flags, image_provider_,
  141. canvas_->getTotalMatrix(), GetMaxTextureSize(),
  142. 1.0f);
  143. if (!raster_flags.flags())
  144. return;
  145. raster_flags.flags()->DrawToSk(
  146. canvas_, [x0, y0, x1, y1](SkCanvas* c, const SkPaint& p) {
  147. c->drawLine(x0, y0, x1, y1, p);
  148. });
  149. FlushAfterDrawIfNeeded();
  150. }
  151. void SkiaPaintCanvas::drawRect(const SkRect& rect, const PaintFlags& flags) {
  152. ScopedRasterFlags raster_flags(&flags, image_provider_,
  153. canvas_->getTotalMatrix(), GetMaxTextureSize(),
  154. 1.0f);
  155. if (!raster_flags.flags())
  156. return;
  157. raster_flags.flags()->DrawToSk(
  158. canvas_,
  159. [&rect](SkCanvas* c, const SkPaint& p) { c->drawRect(rect, p); });
  160. FlushAfterDrawIfNeeded();
  161. }
  162. void SkiaPaintCanvas::drawIRect(const SkIRect& rect, const PaintFlags& flags) {
  163. ScopedRasterFlags raster_flags(&flags, image_provider_,
  164. canvas_->getTotalMatrix(), GetMaxTextureSize(),
  165. 1.0f);
  166. if (!raster_flags.flags())
  167. return;
  168. raster_flags.flags()->DrawToSk(
  169. canvas_,
  170. [&rect](SkCanvas* c, const SkPaint& p) { c->drawIRect(rect, p); });
  171. FlushAfterDrawIfNeeded();
  172. }
  173. void SkiaPaintCanvas::drawOval(const SkRect& oval, const PaintFlags& flags) {
  174. ScopedRasterFlags raster_flags(&flags, image_provider_,
  175. canvas_->getTotalMatrix(), GetMaxTextureSize(),
  176. 1.0f);
  177. if (!raster_flags.flags())
  178. return;
  179. raster_flags.flags()->DrawToSk(
  180. canvas_,
  181. [&oval](SkCanvas* c, const SkPaint& p) { c->drawOval(oval, p); });
  182. FlushAfterDrawIfNeeded();
  183. }
  184. void SkiaPaintCanvas::drawRRect(const SkRRect& rrect, const PaintFlags& flags) {
  185. ScopedRasterFlags raster_flags(&flags, image_provider_,
  186. canvas_->getTotalMatrix(), GetMaxTextureSize(),
  187. 1.0f);
  188. if (!raster_flags.flags())
  189. return;
  190. raster_flags.flags()->DrawToSk(
  191. canvas_,
  192. [&rrect](SkCanvas* c, const SkPaint& p) { c->drawRRect(rrect, p); });
  193. FlushAfterDrawIfNeeded();
  194. }
  195. void SkiaPaintCanvas::drawDRRect(const SkRRect& outer,
  196. const SkRRect& inner,
  197. const PaintFlags& flags) {
  198. ScopedRasterFlags raster_flags(&flags, image_provider_,
  199. canvas_->getTotalMatrix(), GetMaxTextureSize(),
  200. 1.0f);
  201. if (!raster_flags.flags())
  202. return;
  203. raster_flags.flags()->DrawToSk(
  204. canvas_, [&outer, &inner](SkCanvas* c, const SkPaint& p) {
  205. c->drawDRRect(outer, inner, p);
  206. });
  207. FlushAfterDrawIfNeeded();
  208. }
  209. void SkiaPaintCanvas::drawRoundRect(const SkRect& rect,
  210. SkScalar rx,
  211. SkScalar ry,
  212. const PaintFlags& flags) {
  213. ScopedRasterFlags raster_flags(&flags, image_provider_,
  214. canvas_->getTotalMatrix(), GetMaxTextureSize(),
  215. 1.0f);
  216. if (!raster_flags.flags())
  217. return;
  218. raster_flags.flags()->DrawToSk(
  219. canvas_, [&rect, rx, ry](SkCanvas* c, const SkPaint& p) {
  220. c->drawRoundRect(rect, rx, ry, p);
  221. });
  222. FlushAfterDrawIfNeeded();
  223. }
  224. void SkiaPaintCanvas::drawPath(const SkPath& path,
  225. const PaintFlags& flags,
  226. UsePaintCache) {
  227. ScopedRasterFlags raster_flags(&flags, image_provider_,
  228. canvas_->getTotalMatrix(), GetMaxTextureSize(),
  229. 1.0f);
  230. if (!raster_flags.flags())
  231. return;
  232. raster_flags.flags()->DrawToSk(
  233. canvas_,
  234. [&path](SkCanvas* c, const SkPaint& p) { c->drawPath(path, p); });
  235. FlushAfterDrawIfNeeded();
  236. }
  237. void SkiaPaintCanvas::drawImage(const PaintImage& image,
  238. SkScalar left,
  239. SkScalar top,
  240. const SkSamplingOptions& sampling,
  241. const PaintFlags* flags) {
  242. DCHECK(!image.IsPaintWorklet());
  243. absl::optional<ScopedRasterFlags> scoped_flags;
  244. if (flags) {
  245. scoped_flags.emplace(flags, image_provider_, canvas_->getTotalMatrix(),
  246. GetMaxTextureSize(), 1.0f);
  247. if (!scoped_flags->flags())
  248. return;
  249. }
  250. const PaintFlags* raster_flags = scoped_flags ? scoped_flags->flags() : flags;
  251. PlaybackParams params(image_provider_, canvas_->getLocalToDevice());
  252. DrawImageOp draw_image_op(image, left, top, sampling, nullptr);
  253. DrawImageOp::RasterWithFlags(&draw_image_op, raster_flags, canvas_, params);
  254. FlushAfterDrawIfNeeded();
  255. }
  256. void SkiaPaintCanvas::drawImageRect(const PaintImage& image,
  257. const SkRect& src,
  258. const SkRect& dst,
  259. const SkSamplingOptions& sampling,
  260. const PaintFlags* flags,
  261. SkCanvas::SrcRectConstraint constraint) {
  262. absl::optional<ScopedRasterFlags> scoped_flags;
  263. if (flags) {
  264. scoped_flags.emplace(flags, image_provider_, canvas_->getTotalMatrix(),
  265. GetMaxTextureSize(), 1.0f);
  266. if (!scoped_flags->flags())
  267. return;
  268. }
  269. const PaintFlags* raster_flags = scoped_flags ? scoped_flags->flags() : flags;
  270. PlaybackParams params(image_provider_, canvas_->getLocalToDevice());
  271. DrawImageRectOp draw_image_rect_op(image, src, dst, sampling, flags,
  272. constraint);
  273. DrawImageRectOp::RasterWithFlags(&draw_image_rect_op, raster_flags, canvas_,
  274. params);
  275. FlushAfterDrawIfNeeded();
  276. }
  277. void SkiaPaintCanvas::drawSkottie(scoped_refptr<SkottieWrapper> skottie,
  278. const SkRect& dst,
  279. float t,
  280. SkottieFrameDataMap images,
  281. const SkottieColorMap& color_map,
  282. SkottieTextPropertyValueMap text_map) {
  283. if (!images.empty()) {
  284. // This is not implemented solely because there's no use case yet. To
  285. // implement, we could retrieve the underlying SkImage from each
  286. // PaintImage in |images| here and call SkottieWrapper::SetImageForAsset().
  287. NOTIMPLEMENTED()
  288. << "Rendering skottie frames with image assets directly to a "
  289. "SkiaPaintCanvas is currently not supported.";
  290. }
  291. skottie->Draw(canvas_, t, dst, SkottieWrapper::FrameDataCallback(), color_map,
  292. std::move(text_map));
  293. }
  294. void SkiaPaintCanvas::drawTextBlob(sk_sp<SkTextBlob> blob,
  295. SkScalar x,
  296. SkScalar y,
  297. const PaintFlags& flags) {
  298. ScopedRasterFlags raster_flags(&flags, image_provider_,
  299. canvas_->getTotalMatrix(), GetMaxTextureSize(),
  300. 1.0f);
  301. if (!raster_flags.flags())
  302. return;
  303. raster_flags.flags()->DrawToSk(canvas_,
  304. [&blob, x, y](SkCanvas* c, const SkPaint& p) {
  305. c->drawTextBlob(blob, x, y, p);
  306. });
  307. FlushAfterDrawIfNeeded();
  308. }
  309. void SkiaPaintCanvas::drawTextBlob(sk_sp<SkTextBlob> blob,
  310. SkScalar x,
  311. SkScalar y,
  312. NodeId node_id,
  313. const PaintFlags& flags) {
  314. if (node_id)
  315. SkPDF::SetNodeId(canvas_, node_id);
  316. drawTextBlob(blob, x, y, flags);
  317. if (node_id)
  318. SkPDF::SetNodeId(canvas_, 0);
  319. }
  320. void SkiaPaintCanvas::drawPicture(sk_sp<const PaintRecord> record) {
  321. drawPicture(record, PlaybackParams::CustomDataRasterCallback());
  322. }
  323. bool SkiaPaintCanvas::isClipEmpty() const {
  324. return canvas_->isClipEmpty();
  325. }
  326. SkMatrix SkiaPaintCanvas::getTotalMatrix() const {
  327. return canvas_->getTotalMatrix();
  328. }
  329. SkM44 SkiaPaintCanvas::getLocalToDevice() const {
  330. return canvas_->getLocalToDevice();
  331. }
  332. void SkiaPaintCanvas::Annotate(AnnotationType type,
  333. const SkRect& rect,
  334. sk_sp<SkData> data) {
  335. switch (type) {
  336. case AnnotationType::URL:
  337. SkAnnotateRectWithURL(canvas_, rect, data.get());
  338. break;
  339. case AnnotationType::LINK_TO_DESTINATION:
  340. SkAnnotateLinkToDestination(canvas_, rect, data.get());
  341. break;
  342. case AnnotationType::NAMED_DESTINATION: {
  343. SkPoint point = SkPoint::Make(rect.x(), rect.y());
  344. SkAnnotateNamedDestination(canvas_, point, data.get());
  345. break;
  346. }
  347. }
  348. }
  349. void SkiaPaintCanvas::setNodeId(int node_id) {
  350. SkPDF::SetNodeId(canvas_, node_id);
  351. }
  352. void SkiaPaintCanvas::drawPicture(
  353. sk_sp<const PaintRecord> record,
  354. PlaybackParams::CustomDataRasterCallback custom_raster_callback) {
  355. auto did_draw_op_cb =
  356. context_flushes_.enable
  357. ? base::BindRepeating(&SkiaPaintCanvas::FlushAfterDrawIfNeeded,
  358. base::Unretained(this))
  359. : PlaybackParams::DidDrawOpCallback();
  360. PlaybackParams params(image_provider_, canvas_->getLocalToDevice(),
  361. custom_raster_callback, did_draw_op_cb);
  362. record->Playback(canvas_, params);
  363. }
  364. void SkiaPaintCanvas::FlushAfterDrawIfNeeded() {
  365. if (!context_flushes_.enable)
  366. return;
  367. if (++num_of_ops_ > context_flushes_.max_draws_before_flush) {
  368. num_of_ops_ = 0;
  369. TRACE_EVENT0("cc",
  370. "SkiaPaintCanvas::FlushAfterDrawIfNeeded::FlushGrContext");
  371. canvas_->flush();
  372. }
  373. }
  374. int SkiaPaintCanvas::GetMaxTextureSize() const {
  375. auto* context = canvas_->recordingContext();
  376. return context ? context->maxTextureSize() : 0;
  377. }
  378. } // namespace cc