1 /*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "include/core/SkCanvas.h"
9 #include "include/core/SkImageGenerator.h"
10 #include "include/core/SkMatrix.h"
11 #include "include/core/SkPaint.h"
12 #include "include/core/SkPicture.h"
13 #include "include/core/SkSurface.h"
14 #include "src/core/SkTLazy.h"
15 #include "src/image/SkImage_Base.h"
16
17 class SkPictureImageGenerator : public SkImageGenerator {
18 public:
19 SkPictureImageGenerator(const SkImageInfo& info, sk_sp<SkPicture>, const SkMatrix*,
20 const SkPaint*);
21
22 protected:
23 bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options& opts)
24 override;
25
26 #if SK_SUPPORT_GPU
27 GrSurfaceProxyView onGenerateTexture(GrRecordingContext*, const SkImageInfo&, const SkIPoint&,
28 GrMipmapped, GrImageTexGenPolicy) override;
29 #endif
30
31 private:
32 sk_sp<SkPicture> fPicture;
33 SkMatrix fMatrix;
34 SkTLazy<SkPaint> fPaint;
35
36 using INHERITED = SkImageGenerator;
37 };
38
39 ///////////////////////////////////////////////////////////////////////////////////////////////////
40
41 std::unique_ptr<SkImageGenerator>
MakeFromPicture(const SkISize & size,sk_sp<SkPicture> picture,const SkMatrix * matrix,const SkPaint * paint,SkImage::BitDepth bitDepth,sk_sp<SkColorSpace> colorSpace)42 SkImageGenerator::MakeFromPicture(const SkISize& size, sk_sp<SkPicture> picture,
43 const SkMatrix* matrix, const SkPaint* paint,
44 SkImage::BitDepth bitDepth, sk_sp<SkColorSpace> colorSpace) {
45 if (!picture || !colorSpace || size.isEmpty()) {
46 return nullptr;
47 }
48
49 SkColorType colorType = kN32_SkColorType;
50 if (SkImage::BitDepth::kF16 == bitDepth) {
51 colorType = kRGBA_F16_SkColorType;
52 }
53
54 SkImageInfo info =
55 SkImageInfo::Make(size, colorType, kPremul_SkAlphaType, std::move(colorSpace));
56 return std::unique_ptr<SkImageGenerator>(
57 new SkPictureImageGenerator(info, std::move(picture), matrix, paint));
58 }
59
60 ///////////////////////////////////////////////////////////////////////////////////////////////////
61
SkPictureImageGenerator(const SkImageInfo & info,sk_sp<SkPicture> picture,const SkMatrix * matrix,const SkPaint * paint)62 SkPictureImageGenerator::SkPictureImageGenerator(const SkImageInfo& info, sk_sp<SkPicture> picture,
63 const SkMatrix* matrix, const SkPaint* paint)
64 : INHERITED(info)
65 , fPicture(std::move(picture)) {
66
67 if (matrix) {
68 fMatrix = *matrix;
69 } else {
70 fMatrix.reset();
71 }
72
73 if (paint) {
74 fPaint.set(*paint);
75 }
76 }
77
onGetPixels(const SkImageInfo & info,void * pixels,size_t rowBytes,const Options & opts)78 bool SkPictureImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
79 const Options& opts) {
80 SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
81 std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(info, pixels, rowBytes, &props);
82 if (!canvas) {
83 return false;
84 }
85 canvas->clear(0);
86 canvas->drawPicture(fPicture, &fMatrix, fPaint.getMaybeNull());
87 return true;
88 }
89
90 ///////////////////////////////////////////////////////////////////////////////////////////////////
91
92 #if SK_SUPPORT_GPU
93 #include "include/gpu/GrRecordingContext.h"
94 #include "src/gpu/GrRecordingContextPriv.h"
95 #include "src/gpu/SkGr.h"
96
onGenerateTexture(GrRecordingContext * ctx,const SkImageInfo & info,const SkIPoint & origin,GrMipmapped mipmapped,GrImageTexGenPolicy texGenPolicy)97 GrSurfaceProxyView SkPictureImageGenerator::onGenerateTexture(GrRecordingContext* ctx,
98 const SkImageInfo& info,
99 const SkIPoint& origin,
100 GrMipmapped mipmapped,
101 GrImageTexGenPolicy texGenPolicy) {
102 SkASSERT(ctx);
103
104 SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
105
106 SkBudgeted budgeted = texGenPolicy == GrImageTexGenPolicy::kNew_Uncached_Unbudgeted
107 ? SkBudgeted::kNo
108 : SkBudgeted::kYes;
109 auto surface = SkSurface::MakeRenderTarget(ctx, budgeted, info, 0, kTopLeft_GrSurfaceOrigin,
110 &props, mipmapped == GrMipmapped::kYes);
111 if (!surface) {
112 return {};
113 }
114
115 SkMatrix matrix = fMatrix;
116 matrix.postTranslate(-origin.x(), -origin.y());
117 surface->getCanvas()->clear(0);
118 surface->getCanvas()->drawPicture(fPicture.get(), &matrix, fPaint.getMaybeNull());
119 sk_sp<SkImage> image(surface->makeImageSnapshot());
120 if (!image) {
121 return {};
122 }
123 auto [view, ct] = as_IB(image)->asView(ctx, mipmapped);
124 SkASSERT(view);
125 SkASSERT(mipmapped == GrMipmapped::kNo ||
126 view.asTextureProxy()->mipmapped() == GrMipmapped::kYes);
127 return view;
128 }
129 #endif
130