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/gpu/SkGr.h"
16#include "src/image/SkImage_Base.h"
17
18class SkPictureImageGenerator : public SkImageGenerator {
19public:
20 SkPictureImageGenerator(const SkImageInfo& info, sk_sp<SkPicture>, const SkMatrix*,
21 const SkPaint*);
22
23protected:
24 bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options& opts)
25 override;
26
27#if SK_SUPPORT_GPU
28 GrSurfaceProxyView onGenerateTexture(GrRecordingContext*, const SkImageInfo&, const SkIPoint&,
29 GrMipMapped, GrImageTexGenPolicy) override;
30#endif
31
32private:
33 sk_sp<SkPicture> fPicture;
34 SkMatrix fMatrix;
35 SkTLazy<SkPaint> fPaint;
36
37 typedef SkImageGenerator INHERITED;
38};
39
40///////////////////////////////////////////////////////////////////////////////////////////////////
41
42std::unique_ptr<SkImageGenerator>
43SkImageGenerator::MakeFromPicture(const SkISize& size, sk_sp<SkPicture> picture,
44 const SkMatrix* matrix, const SkPaint* paint,
45 SkImage::BitDepth bitDepth, sk_sp<SkColorSpace> colorSpace) {
46 if (!picture || !colorSpace || size.isEmpty()) {
47 return nullptr;
48 }
49
50 SkColorType colorType = kN32_SkColorType;
51 if (SkImage::BitDepth::kF16 == bitDepth) {
52 colorType = kRGBA_F16_SkColorType;
53 }
54
55 SkImageInfo info =
56 SkImageInfo::Make(size, colorType, kPremul_SkAlphaType, std::move(colorSpace));
57 return std::unique_ptr<SkImageGenerator>(
58 new SkPictureImageGenerator(info, std::move(picture), matrix, paint));
59}
60
61///////////////////////////////////////////////////////////////////////////////////////////////////
62
63SkPictureImageGenerator::SkPictureImageGenerator(const SkImageInfo& info, sk_sp<SkPicture> picture,
64 const SkMatrix* matrix, const SkPaint* paint)
65 : INHERITED(info)
66 , fPicture(std::move(picture)) {
67
68 if (matrix) {
69 fMatrix = *matrix;
70 } else {
71 fMatrix.reset();
72 }
73
74 if (paint) {
75 fPaint.set(*paint);
76 }
77}
78
79bool SkPictureImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
80 const Options& opts) {
81 SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
82 std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(info, pixels, rowBytes, &props);
83 if (!canvas) {
84 return false;
85 }
86 canvas->clear(0);
87 canvas->drawPicture(fPicture, &fMatrix, fPaint.getMaybeNull());
88 return true;
89}
90
91///////////////////////////////////////////////////////////////////////////////////////////////////
92
93#if SK_SUPPORT_GPU
94#include "include/private/GrRecordingContext.h"
95#include "src/gpu/GrRecordingContextPriv.h"
96
97GrSurfaceProxyView 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 // CONTEXT TODO: remove this use of 'backdoor' to create an SkSkSurface
110 auto surface = SkSurface::MakeRenderTarget(ctx->priv().backdoor(), budgeted, info, 0,
111 kTopLeft_GrSurfaceOrigin, &props,
112 mipMapped == GrMipMapped::kYes);
113 if (!surface) {
114 return {};
115 }
116
117 SkMatrix matrix = fMatrix;
118 matrix.postTranslate(-origin.x(), -origin.y());
119 surface->getCanvas()->clear(0);
120 surface->getCanvas()->drawPicture(fPicture.get(), &matrix, fPaint.getMaybeNull());
121 sk_sp<SkImage> image(surface->makeImageSnapshot());
122 if (!image) {
123 return {};
124 }
125 const GrSurfaceProxyView* view = as_IB(image)->view(ctx);
126 SkASSERT(view);
127 SkASSERT(mipMapped == GrMipMapped::kNo ||
128 view->asTextureProxy()->mipMapped() == GrMipMapped::kYes);
129 return *view;
130}
131#endif
132