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/SkColorSpace.h"
10 #include "include/core/SkImageGenerator.h"
11 #include "include/core/SkMatrix.h"
12 #include "include/core/SkPaint.h"
13 #include "include/core/SkPicture.h"
14 #include "include/core/SkSurface.h"
15 #include "src/base/SkTLazy.h"
16 #include "src/image/SkImage_Base.h"
17
18 #if defined(SK_GANESH)
19 #include "src/gpu/ganesh/GrTextureProxy.h"
20 #endif
21
22 class SkPictureImageGenerator : public SkImageGenerator {
23 public:
24 SkPictureImageGenerator(const SkImageInfo&, sk_sp<SkPicture>, const SkMatrix*,
25 const SkPaint*, const SkSurfaceProps&);
26
27 protected:
28 bool onGetPixels(const SkImageInfo&, void* pixels, size_t rowBytes, const Options&) override;
29
30 #if defined(SK_GANESH)
31 GrSurfaceProxyView onGenerateTexture(GrRecordingContext*, const SkImageInfo&,
32 GrMipmapped, GrImageTexGenPolicy) override;
33 #endif
34
35 #if SK_GRAPHITE
36 sk_sp<SkImage> onMakeTextureImage(skgpu::graphite::Recorder*,
37 const SkImageInfo&,
38 skgpu::Mipmapped) override;
39 #endif
40
41 private:
42 sk_sp<SkPicture> fPicture;
43 SkMatrix fMatrix;
44 SkTLazy<SkPaint> fPaint;
45 SkSurfaceProps fProps;
46
47 using INHERITED = SkImageGenerator;
48 };
49
50 ///////////////////////////////////////////////////////////////////////////////////////////////////
51
52 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,SkSurfaceProps props)53 SkImageGenerator::MakeFromPicture(const SkISize& size, sk_sp<SkPicture> picture,
54 const SkMatrix* matrix, const SkPaint* paint,
55 SkImage::BitDepth bitDepth, sk_sp<SkColorSpace> colorSpace,
56 SkSurfaceProps props) {
57 if (!picture || !colorSpace || size.isEmpty()) {
58 return nullptr;
59 }
60
61 SkColorType colorType = kN32_SkColorType;
62 if (SkImage::BitDepth::kF16 == bitDepth) {
63 colorType = kRGBA_F16_SkColorType;
64 }
65
66 SkImageInfo info =
67 SkImageInfo::Make(size, colorType, kPremul_SkAlphaType, std::move(colorSpace));
68 return std::unique_ptr<SkImageGenerator>(
69 new SkPictureImageGenerator(info, std::move(picture), matrix, paint, props));
70 }
71
72 ///////////////////////////////////////////////////////////////////////////////////////////////////
73
SkPictureImageGenerator(const SkImageInfo & info,sk_sp<SkPicture> picture,const SkMatrix * matrix,const SkPaint * paint,const SkSurfaceProps & props)74 SkPictureImageGenerator::SkPictureImageGenerator(const SkImageInfo& info, sk_sp<SkPicture> picture,
75 const SkMatrix* matrix, const SkPaint* paint,
76 const SkSurfaceProps& props)
77 : SkImageGenerator(info)
78 , fPicture(std::move(picture))
79 , fProps(props) {
80
81 if (matrix) {
82 fMatrix = *matrix;
83 } else {
84 fMatrix.reset();
85 }
86
87 if (paint) {
88 fPaint.set(*paint);
89 }
90 }
91
onGetPixels(const SkImageInfo & info,void * pixels,size_t rowBytes,const Options & opts)92 bool SkPictureImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
93 const Options& opts) {
94 std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(info, pixels, rowBytes, &fProps);
95 if (!canvas) {
96 return false;
97 }
98 canvas->clear(0);
99 canvas->drawPicture(fPicture, &fMatrix, fPaint.getMaybeNull());
100 return true;
101 }
102
103 ///////////////////////////////////////////////////////////////////////////////////////////////////
104
105 #if defined(SK_GANESH)
106 #include "include/gpu/GrRecordingContext.h"
107 #include "src/gpu/ganesh/GrRecordingContextPriv.h"
108 #include "src/gpu/ganesh/SkGr.h"
109
onGenerateTexture(GrRecordingContext * ctx,const SkImageInfo & info,GrMipmapped mipmapped,GrImageTexGenPolicy texGenPolicy)110 GrSurfaceProxyView SkPictureImageGenerator::onGenerateTexture(GrRecordingContext* ctx,
111 const SkImageInfo& info,
112 GrMipmapped mipmapped,
113 GrImageTexGenPolicy texGenPolicy) {
114 SkASSERT(ctx);
115
116 skgpu::Budgeted budgeted = texGenPolicy == GrImageTexGenPolicy::kNew_Uncached_Unbudgeted
117 ? skgpu::Budgeted::kNo
118 : skgpu::Budgeted::kYes;
119 auto surface = SkSurface::MakeRenderTarget(ctx, budgeted, info, 0, kTopLeft_GrSurfaceOrigin,
120 &fProps, mipmapped == GrMipmapped::kYes);
121 if (!surface) {
122 return {};
123 }
124
125 surface->getCanvas()->clear(SkColors::kTransparent);
126 surface->getCanvas()->drawPicture(fPicture.get(), &fMatrix, fPaint.getMaybeNull());
127 sk_sp<SkImage> image(surface->makeImageSnapshot());
128 if (!image) {
129 return {};
130 }
131 auto [view, ct] = as_IB(image)->asView(ctx, mipmapped);
132 SkASSERT(view);
133 SkASSERT(mipmapped == GrMipmapped::kNo ||
134 view.asTextureProxy()->mipmapped() == GrMipmapped::kYes);
135 return view;
136 }
137
138 #endif // defined(SK_GANESH)
139
140 ///////////////////////////////////////////////////////////////////////////////////////////////////
141
142 #if SK_GRAPHITE
143 #include "src/gpu/graphite/Log.h"
144
onMakeTextureImage(skgpu::graphite::Recorder * recorder,const SkImageInfo & info,skgpu::Mipmapped mipmapped)145 sk_sp<SkImage> SkPictureImageGenerator::onMakeTextureImage(skgpu::graphite::Recorder* recorder,
146 const SkImageInfo& info,
147 skgpu::Mipmapped mipmapped) {
148 using namespace skgpu::graphite;
149
150 sk_sp<SkSurface> surface = SkSurface::MakeGraphite(recorder, info, mipmapped);
151 if (!surface) {
152 SKGPU_LOG_E("Failed to create Surface");
153 return nullptr;
154 }
155
156 surface->getCanvas()->clear(SkColors::kTransparent);
157 surface->getCanvas()->drawPicture(fPicture.get(), &fMatrix, fPaint.getMaybeNull());
158 return surface->asImage();
159 }
160
161 #endif // SK_GRAPHITE
162