paint_preview_recorder_utils.cc 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. // Copyright 2019 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 "components/paint_preview/renderer/paint_preview_recorder_utils.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/trace_event/common/trace_event_common.h"
  8. #include "base/trace_event/trace_event.h"
  9. #include "cc/paint/paint_image.h"
  10. #include "cc/paint/paint_image_builder.h"
  11. #include "components/paint_preview/common/file_stream.h"
  12. #include "components/paint_preview/common/paint_preview_tracker.h"
  13. #include "mojo/public/cpp/base/shared_memory_utils.h"
  14. #include "third_party/skia/include/core/SkData.h"
  15. #include "third_party/skia/include/core/SkRefCnt.h"
  16. namespace paint_preview {
  17. namespace {
  18. // Converts a texture backed paint image in the PaintOpBuffer to one that is not
  19. // texture backed.
  20. cc::PaintImage MakeUnaccelerated(cc::PaintImage& paint_image) {
  21. DCHECK(paint_image.IsTextureBacked());
  22. auto sk_image = paint_image.GetSwSkImage();
  23. if (sk_image->isLazyGenerated()) {
  24. // Texture backed images should always be returned as SkImage_Raster type
  25. // (bitmap). This is just a catchall in the event a lazy image is somehow
  26. // returned in which case we should just raster it.
  27. SkBitmap bitmap;
  28. bitmap.allocPixels(sk_image->imageInfo(),
  29. sk_image->imageInfo().minRowBytes());
  30. if (!sk_image->readPixels(bitmap.pixmap(), 0, 0)) {
  31. return paint_image;
  32. }
  33. // Make immutable to skip an extra copy.
  34. bitmap.setImmutable();
  35. sk_image = SkImage::MakeFromBitmap(bitmap);
  36. }
  37. return cc::PaintImageBuilder::WithDefault()
  38. .set_id(cc::PaintImage::GetNextId())
  39. .set_image(sk_image, cc::PaintImage::GetNextContentId())
  40. .TakePaintImage();
  41. }
  42. } // namespace
  43. void PreProcessPaintOpBuffer(const cc::PaintOpBuffer* buffer,
  44. PaintPreviewTracker* tracker) {
  45. for (cc::PaintOpBuffer::Iterator it(buffer); it; ++it) {
  46. switch (it->GetType()) {
  47. case cc::PaintOpType::DrawTextBlob: {
  48. auto* text_blob_op = static_cast<cc::DrawTextBlobOp*>(*it);
  49. tracker->AddGlyphs(text_blob_op->blob.get());
  50. break;
  51. }
  52. case cc::PaintOpType::DrawRecord: {
  53. // Recurse into nested records if they contain text blobs (equivalent to
  54. // nested SkPictures).
  55. auto* record_op = static_cast<cc::DrawRecordOp*>(*it);
  56. PreProcessPaintOpBuffer(record_op->record.get(), tracker);
  57. break;
  58. }
  59. case cc::PaintOpType::Annotate: {
  60. auto* annotate_op = static_cast<cc::AnnotateOp*>(*it);
  61. tracker->AnnotateLink(GURL(std::string(reinterpret_cast<const char*>(
  62. annotate_op->data->data()),
  63. annotate_op->data->size())),
  64. annotate_op->rect);
  65. // Delete the data. We no longer need it.
  66. annotate_op->data.reset();
  67. break;
  68. }
  69. case cc::PaintOpType::CustomData: {
  70. auto* custom_op = static_cast<cc::CustomDataOp*>(*it);
  71. tracker->TransformClipForFrame(custom_op->id);
  72. break;
  73. }
  74. case cc::PaintOpType::Save: {
  75. tracker->Save();
  76. break;
  77. }
  78. case cc::PaintOpType::SaveLayer: {
  79. tracker->Save();
  80. break;
  81. }
  82. case cc::PaintOpType::SaveLayerAlpha: {
  83. tracker->Save();
  84. break;
  85. }
  86. case cc::PaintOpType::Restore: {
  87. tracker->Restore();
  88. break;
  89. }
  90. case cc::PaintOpType::SetMatrix: {
  91. auto* matrix_op = static_cast<cc::SetMatrixOp*>(*it);
  92. tracker->SetMatrix(matrix_op->matrix.asM33());
  93. break;
  94. }
  95. case cc::PaintOpType::Concat: {
  96. auto* concat_op = static_cast<cc::ConcatOp*>(*it);
  97. tracker->Concat(concat_op->matrix.asM33());
  98. break;
  99. }
  100. case cc::PaintOpType::Scale: {
  101. auto* scale_op = static_cast<cc::ScaleOp*>(*it);
  102. tracker->Scale(scale_op->sx, scale_op->sy);
  103. break;
  104. }
  105. case cc::PaintOpType::Rotate: {
  106. auto* rotate_op = static_cast<cc::RotateOp*>(*it);
  107. tracker->Rotate(rotate_op->degrees);
  108. break;
  109. }
  110. case cc::PaintOpType::Translate: {
  111. auto* translate_op = static_cast<cc::TranslateOp*>(*it);
  112. tracker->Translate(translate_op->dx, translate_op->dy);
  113. break;
  114. }
  115. case cc::PaintOpType::DrawImage: {
  116. auto* image_op = static_cast<cc::DrawImageOp*>(*it);
  117. if (image_op->image.IsTextureBacked()) {
  118. image_op->image = MakeUnaccelerated(image_op->image);
  119. }
  120. break;
  121. }
  122. case cc::PaintOpType::DrawImageRect: {
  123. auto* image_op = static_cast<cc::DrawImageRectOp*>(*it);
  124. if (image_op->image.IsTextureBacked()) {
  125. image_op->image = MakeUnaccelerated(image_op->image);
  126. }
  127. break;
  128. }
  129. default:
  130. continue;
  131. }
  132. }
  133. }
  134. sk_sp<const SkPicture> PaintRecordToSkPicture(
  135. sk_sp<const cc::PaintRecord> recording,
  136. PaintPreviewTracker* tracker,
  137. const gfx::Rect& bounds) {
  138. // base::Unretained is safe as |tracker| outlives the usage of
  139. // |custom_callback|.
  140. cc::PlaybackParams::CustomDataRasterCallback custom_callback =
  141. base::BindRepeating(&PaintPreviewTracker::CustomDataToSkPictureCallback,
  142. base::Unretained(tracker));
  143. auto skp =
  144. ToSkPicture(recording, SkRect::MakeWH(bounds.width(), bounds.height()),
  145. nullptr, custom_callback);
  146. if (!skp || skp->cullRect().width() == 0 || skp->cullRect().height() == 0)
  147. return nullptr;
  148. return skp;
  149. }
  150. void BuildResponse(PaintPreviewTracker* tracker,
  151. mojom::PaintPreviewCaptureResponse* response) {
  152. // Ensure these always exist.
  153. DCHECK(tracker);
  154. DCHECK(response);
  155. response->embedding_token = tracker->EmbeddingToken();
  156. tracker->MoveLinks(&response->links);
  157. PictureSerializationContext* picture_context =
  158. tracker->GetPictureSerializationContext();
  159. if (!picture_context)
  160. return;
  161. for (const auto& id_pair : picture_context->content_id_to_embedding_token) {
  162. response->content_id_to_embedding_token.insert(id_pair);
  163. }
  164. }
  165. } // namespace paint_preview