1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2015 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageGenerator.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPicture.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPictureRecorder.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrRecordingContext.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrTypes.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrExternalTextureGenerator.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/SkSurfaceGanesh.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTextureGenerator.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRecordingContextPriv.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSamplerState.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrTextureProxy.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/SurfaceContext.h"
39*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/image/GrImageUtils.h"
40*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/image/SkImage_Ganesh.h"
41*c8dee2aaSAndroid Build Coastguard Worker #include "src/image/SkImageGeneratorPriv.h"
42*c8dee2aaSAndroid Build Coastguard Worker #include "src/image/SkImage_Base.h"
43*c8dee2aaSAndroid Build Coastguard Worker
44*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
45*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
46*c8dee2aaSAndroid Build Coastguard Worker
47*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GRAPHITE)
48*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Surface.h"
49*c8dee2aaSAndroid Build Coastguard Worker #endif
50*c8dee2aaSAndroid Build Coastguard Worker
51*c8dee2aaSAndroid Build Coastguard Worker class GrRecordingContext;
52*c8dee2aaSAndroid Build Coastguard Worker
draw_something(SkCanvas * canvas,const SkRect & bounds)53*c8dee2aaSAndroid Build Coastguard Worker static void draw_something(SkCanvas* canvas, const SkRect& bounds) {
54*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
55*c8dee2aaSAndroid Build Coastguard Worker paint.setAntiAlias(true);
56*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SK_ColorRED);
57*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kStroke_Style);
58*c8dee2aaSAndroid Build Coastguard Worker paint.setStrokeWidth(10);
59*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(bounds, paint);
60*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kFill_Style);
61*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SK_ColorBLUE);
62*c8dee2aaSAndroid Build Coastguard Worker canvas->drawOval(bounds, paint);
63*c8dee2aaSAndroid Build Coastguard Worker }
64*c8dee2aaSAndroid Build Coastguard Worker
65*c8dee2aaSAndroid Build Coastguard Worker /*
66*c8dee2aaSAndroid Build Coastguard Worker * Exercise drawing pictures inside an image, showing that the image version is pixelated
67*c8dee2aaSAndroid Build Coastguard Worker * (correctly) when it is inside an image.
68*c8dee2aaSAndroid Build Coastguard Worker */
69*c8dee2aaSAndroid Build Coastguard Worker class ImagePictGM : public skiagm::GM {
70*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkPicture> fPicture;
71*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> fImage0;
72*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> fImage1;
73*c8dee2aaSAndroid Build Coastguard Worker public:
ImagePictGM()74*c8dee2aaSAndroid Build Coastguard Worker ImagePictGM() {}
75*c8dee2aaSAndroid Build Coastguard Worker
76*c8dee2aaSAndroid Build Coastguard Worker protected:
getName() const77*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override { return SkString("image-picture"); }
78*c8dee2aaSAndroid Build Coastguard Worker
getISize()79*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return SkISize::Make(850, 450); }
80*c8dee2aaSAndroid Build Coastguard Worker
onOnceBeforeDraw()81*c8dee2aaSAndroid Build Coastguard Worker void onOnceBeforeDraw() override {
82*c8dee2aaSAndroid Build Coastguard Worker const SkRect bounds = SkRect::MakeXYWH(100, 100, 100, 100);
83*c8dee2aaSAndroid Build Coastguard Worker SkPictureRecorder recorder;
84*c8dee2aaSAndroid Build Coastguard Worker draw_something(recorder.beginRecording(bounds), bounds);
85*c8dee2aaSAndroid Build Coastguard Worker fPicture = recorder.finishRecordingAsPicture();
86*c8dee2aaSAndroid Build Coastguard Worker
87*c8dee2aaSAndroid Build Coastguard Worker // extract enough just for the oval.
88*c8dee2aaSAndroid Build Coastguard Worker const SkISize size = SkISize::Make(100, 100);
89*c8dee2aaSAndroid Build Coastguard Worker auto srgbColorSpace = SkColorSpace::MakeSRGB();
90*c8dee2aaSAndroid Build Coastguard Worker
91*c8dee2aaSAndroid Build Coastguard Worker SkMatrix matrix;
92*c8dee2aaSAndroid Build Coastguard Worker matrix.setTranslate(-100, -100);
93*c8dee2aaSAndroid Build Coastguard Worker fImage0 = SkImages::DeferredFromPicture(
94*c8dee2aaSAndroid Build Coastguard Worker fPicture, size, &matrix, nullptr, SkImages::BitDepth::kU8, srgbColorSpace);
95*c8dee2aaSAndroid Build Coastguard Worker matrix.postTranslate(-50, -50);
96*c8dee2aaSAndroid Build Coastguard Worker matrix.postRotate(45);
97*c8dee2aaSAndroid Build Coastguard Worker matrix.postTranslate(50, 50);
98*c8dee2aaSAndroid Build Coastguard Worker fImage1 = SkImages::DeferredFromPicture(
99*c8dee2aaSAndroid Build Coastguard Worker fPicture, size, &matrix, nullptr, SkImages::BitDepth::kU8, srgbColorSpace);
100*c8dee2aaSAndroid Build Coastguard Worker }
101*c8dee2aaSAndroid Build Coastguard Worker
drawSet(SkCanvas * canvas) const102*c8dee2aaSAndroid Build Coastguard Worker void drawSet(SkCanvas* canvas) const {
103*c8dee2aaSAndroid Build Coastguard Worker SkMatrix matrix = SkMatrix::Translate(-100, -100);
104*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPicture(fPicture, &matrix, nullptr);
105*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(fImage0.get(), 150, 0);
106*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(fImage1.get(), 300, 0);
107*c8dee2aaSAndroid Build Coastguard Worker }
108*c8dee2aaSAndroid Build Coastguard Worker
onDraw(SkCanvas * canvas)109*c8dee2aaSAndroid Build Coastguard Worker void onDraw(SkCanvas* canvas) override {
110*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(20, 20);
111*c8dee2aaSAndroid Build Coastguard Worker
112*c8dee2aaSAndroid Build Coastguard Worker this->drawSet(canvas);
113*c8dee2aaSAndroid Build Coastguard Worker
114*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
115*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, 130);
116*c8dee2aaSAndroid Build Coastguard Worker canvas->scale(0.25f, 0.25f);
117*c8dee2aaSAndroid Build Coastguard Worker this->drawSet(canvas);
118*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
119*c8dee2aaSAndroid Build Coastguard Worker
120*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
121*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, 200);
122*c8dee2aaSAndroid Build Coastguard Worker canvas->scale(2, 2);
123*c8dee2aaSAndroid Build Coastguard Worker this->drawSet(canvas);
124*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
125*c8dee2aaSAndroid Build Coastguard Worker }
126*c8dee2aaSAndroid Build Coastguard Worker
127*c8dee2aaSAndroid Build Coastguard Worker private:
128*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = skiagm::GM;
129*c8dee2aaSAndroid Build Coastguard Worker };
DEF_GM(return new ImagePictGM;)130*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ImagePictGM; )
131*c8dee2aaSAndroid Build Coastguard Worker
132*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////////////////////////
133*c8dee2aaSAndroid Build Coastguard Worker
134*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<SkImageGenerator> make_pic_generator(SkCanvas*,
135*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkPicture> pic) {
136*c8dee2aaSAndroid Build Coastguard Worker SkMatrix matrix;
137*c8dee2aaSAndroid Build Coastguard Worker matrix.setTranslate(-100, -100);
138*c8dee2aaSAndroid Build Coastguard Worker return SkImageGenerators::MakeFromPicture({100, 100},
139*c8dee2aaSAndroid Build Coastguard Worker std::move(pic),
140*c8dee2aaSAndroid Build Coastguard Worker &matrix,
141*c8dee2aaSAndroid Build Coastguard Worker nullptr,
142*c8dee2aaSAndroid Build Coastguard Worker SkImages::BitDepth::kU8,
143*c8dee2aaSAndroid Build Coastguard Worker SkColorSpace::MakeSRGB());
144*c8dee2aaSAndroid Build Coastguard Worker }
145*c8dee2aaSAndroid Build Coastguard Worker
146*c8dee2aaSAndroid Build Coastguard Worker class RasterGenerator : public SkImageGenerator {
147*c8dee2aaSAndroid Build Coastguard Worker public:
RasterGenerator(const SkBitmap & bm)148*c8dee2aaSAndroid Build Coastguard Worker RasterGenerator(const SkBitmap& bm) : SkImageGenerator(bm.info()), fBM(bm)
149*c8dee2aaSAndroid Build Coastguard Worker {}
150*c8dee2aaSAndroid Build Coastguard Worker
151*c8dee2aaSAndroid Build Coastguard Worker protected:
onGetPixels(const SkImageInfo & info,void * pixels,size_t rowBytes,const Options &)152*c8dee2aaSAndroid Build Coastguard Worker bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
153*c8dee2aaSAndroid Build Coastguard Worker const Options&) override {
154*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fBM.width() == info.width());
155*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fBM.height() == info.height());
156*c8dee2aaSAndroid Build Coastguard Worker return fBM.readPixels(info, pixels, rowBytes, 0, 0);
157*c8dee2aaSAndroid Build Coastguard Worker }
158*c8dee2aaSAndroid Build Coastguard Worker private:
159*c8dee2aaSAndroid Build Coastguard Worker SkBitmap fBM;
160*c8dee2aaSAndroid Build Coastguard Worker };
make_ras_generator(SkCanvas *,sk_sp<SkPicture> pic)161*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<SkImageGenerator> make_ras_generator(SkCanvas*,
162*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkPicture> pic) {
163*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bm;
164*c8dee2aaSAndroid Build Coastguard Worker bm.allocN32Pixels(100, 100);
165*c8dee2aaSAndroid Build Coastguard Worker SkCanvas canvas(bm);
166*c8dee2aaSAndroid Build Coastguard Worker canvas.clear(0);
167*c8dee2aaSAndroid Build Coastguard Worker canvas.translate(-100, -100);
168*c8dee2aaSAndroid Build Coastguard Worker canvas.drawPicture(pic);
169*c8dee2aaSAndroid Build Coastguard Worker return std::make_unique<RasterGenerator>(bm);
170*c8dee2aaSAndroid Build Coastguard Worker }
171*c8dee2aaSAndroid Build Coastguard Worker
172*c8dee2aaSAndroid Build Coastguard Worker class TextureGenerator : public GrTextureGenerator {
173*c8dee2aaSAndroid Build Coastguard Worker public:
TextureGenerator(SkCanvas * canvas,const SkImageInfo & info,sk_sp<SkPicture> pic)174*c8dee2aaSAndroid Build Coastguard Worker TextureGenerator(SkCanvas* canvas, const SkImageInfo& info, sk_sp<SkPicture> pic)
175*c8dee2aaSAndroid Build Coastguard Worker : GrTextureGenerator(info) {
176*c8dee2aaSAndroid Build Coastguard Worker
177*c8dee2aaSAndroid Build Coastguard Worker fRContext = sk_ref_sp(canvas->recordingContext());
178*c8dee2aaSAndroid Build Coastguard Worker
179*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface;
180*c8dee2aaSAndroid Build Coastguard Worker
181*c8dee2aaSAndroid Build Coastguard Worker if (fRContext) {
182*c8dee2aaSAndroid Build Coastguard Worker surface = SkSurfaces::RenderTarget(fRContext.get(),
183*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted::kYes,
184*c8dee2aaSAndroid Build Coastguard Worker info,
185*c8dee2aaSAndroid Build Coastguard Worker 0,
186*c8dee2aaSAndroid Build Coastguard Worker kTopLeft_GrSurfaceOrigin,
187*c8dee2aaSAndroid Build Coastguard Worker nullptr);
188*c8dee2aaSAndroid Build Coastguard Worker }
189*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GRAPHITE)
190*c8dee2aaSAndroid Build Coastguard Worker if (skgpu::graphite::Recorder* recorder = canvas->recorder()) {
191*c8dee2aaSAndroid Build Coastguard Worker surface = SkSurfaces::RenderTarget(recorder, info);
192*c8dee2aaSAndroid Build Coastguard Worker }
193*c8dee2aaSAndroid Build Coastguard Worker #endif
194*c8dee2aaSAndroid Build Coastguard Worker
195*c8dee2aaSAndroid Build Coastguard Worker if (surface) {
196*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->clear(0);
197*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->translate(-100, -100);
198*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->drawPicture(pic);
199*c8dee2aaSAndroid Build Coastguard Worker fImage = surface->makeImageSnapshot();
200*c8dee2aaSAndroid Build Coastguard Worker }
201*c8dee2aaSAndroid Build Coastguard Worker }
202*c8dee2aaSAndroid Build Coastguard Worker protected:
onGenerateTexture(GrRecordingContext * rContext,const SkImageInfo & info,skgpu::Mipmapped mipmapped,GrImageTexGenPolicy policy)203*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceProxyView onGenerateTexture(GrRecordingContext* rContext,
204*c8dee2aaSAndroid Build Coastguard Worker const SkImageInfo& info,
205*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped mipmapped,
206*c8dee2aaSAndroid Build Coastguard Worker GrImageTexGenPolicy policy) override {
207*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(rContext);
208*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(rContext->priv().matches(fRContext.get()));
209*c8dee2aaSAndroid Build Coastguard Worker
210*c8dee2aaSAndroid Build Coastguard Worker auto [view, _] = skgpu::ganesh::AsView(rContext, fImage, skgpu::Mipmapped::kNo);
211*c8dee2aaSAndroid Build Coastguard Worker if (!view) {
212*c8dee2aaSAndroid Build Coastguard Worker return {};
213*c8dee2aaSAndroid Build Coastguard Worker }
214*c8dee2aaSAndroid Build Coastguard Worker
215*c8dee2aaSAndroid Build Coastguard Worker SkASSERT_RELEASE(info.dimensions() == view.proxy()->dimensions());
216*c8dee2aaSAndroid Build Coastguard Worker
217*c8dee2aaSAndroid Build Coastguard Worker if (policy == GrImageTexGenPolicy::kDraw) {
218*c8dee2aaSAndroid Build Coastguard Worker return view;
219*c8dee2aaSAndroid Build Coastguard Worker }
220*c8dee2aaSAndroid Build Coastguard Worker auto budgeted = policy == GrImageTexGenPolicy::kNew_Uncached_Unbudgeted
221*c8dee2aaSAndroid Build Coastguard Worker ? skgpu::Budgeted::kNo
222*c8dee2aaSAndroid Build Coastguard Worker : skgpu::Budgeted::kYes;
223*c8dee2aaSAndroid Build Coastguard Worker return GrSurfaceProxyView::Copy(
224*c8dee2aaSAndroid Build Coastguard Worker fRContext.get(),
225*c8dee2aaSAndroid Build Coastguard Worker view,
226*c8dee2aaSAndroid Build Coastguard Worker mipmapped,
227*c8dee2aaSAndroid Build Coastguard Worker SkIRect::MakeWH(info.width(), info.height()),
228*c8dee2aaSAndroid Build Coastguard Worker SkBackingFit::kExact,
229*c8dee2aaSAndroid Build Coastguard Worker budgeted,
230*c8dee2aaSAndroid Build Coastguard Worker /*label=*/"SurfaceProxyView_GenerateTexture");
231*c8dee2aaSAndroid Build Coastguard Worker }
232*c8dee2aaSAndroid Build Coastguard Worker
233*c8dee2aaSAndroid Build Coastguard Worker private:
234*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrRecordingContext> fRContext;
235*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> fImage;
236*c8dee2aaSAndroid Build Coastguard Worker };
237*c8dee2aaSAndroid Build Coastguard Worker
make_tex_generator(SkCanvas * canvas,sk_sp<SkPicture> pic)238*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<SkImageGenerator> make_tex_generator(SkCanvas* canvas,
239*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkPicture> pic) {
240*c8dee2aaSAndroid Build Coastguard Worker auto dContext = GrAsDirectContext(canvas->recordingContext());
241*c8dee2aaSAndroid Build Coastguard Worker if (!dContext && !canvas->recorder()) {
242*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
243*c8dee2aaSAndroid Build Coastguard Worker }
244*c8dee2aaSAndroid Build Coastguard Worker
245*c8dee2aaSAndroid Build Coastguard Worker const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
246*c8dee2aaSAndroid Build Coastguard Worker
247*c8dee2aaSAndroid Build Coastguard Worker return std::make_unique<TextureGenerator>(canvas, info, pic);
248*c8dee2aaSAndroid Build Coastguard Worker }
249*c8dee2aaSAndroid Build Coastguard Worker
250*c8dee2aaSAndroid Build Coastguard Worker class ImageCacheratorGM : public skiagm::GM {
251*c8dee2aaSAndroid Build Coastguard Worker typedef std::unique_ptr<SkImageGenerator> (*FactoryFunc)(SkCanvas*, sk_sp<SkPicture>);
252*c8dee2aaSAndroid Build Coastguard Worker
253*c8dee2aaSAndroid Build Coastguard Worker SkString fName;
254*c8dee2aaSAndroid Build Coastguard Worker FactoryFunc fFactory;
255*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkPicture> fPicture;
256*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> fImage;
257*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> fImageSubset;
258*c8dee2aaSAndroid Build Coastguard Worker bool fUseTexture;
259*c8dee2aaSAndroid Build Coastguard Worker
260*c8dee2aaSAndroid Build Coastguard Worker public:
ImageCacheratorGM(const char suffix[],FactoryFunc factory,bool useTexture)261*c8dee2aaSAndroid Build Coastguard Worker ImageCacheratorGM(const char suffix[], FactoryFunc factory, bool useTexture) :
262*c8dee2aaSAndroid Build Coastguard Worker fFactory(factory), fUseTexture(useTexture) {
263*c8dee2aaSAndroid Build Coastguard Worker fName.printf("image-cacherator-from-%s", suffix);
264*c8dee2aaSAndroid Build Coastguard Worker }
265*c8dee2aaSAndroid Build Coastguard Worker
266*c8dee2aaSAndroid Build Coastguard Worker protected:
getName() const267*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override { return fName; }
268*c8dee2aaSAndroid Build Coastguard Worker
getISize()269*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return SkISize::Make(960, 450); }
270*c8dee2aaSAndroid Build Coastguard Worker
onOnceBeforeDraw()271*c8dee2aaSAndroid Build Coastguard Worker void onOnceBeforeDraw() override {
272*c8dee2aaSAndroid Build Coastguard Worker const SkRect bounds = SkRect::MakeXYWH(100, 100, 100, 100);
273*c8dee2aaSAndroid Build Coastguard Worker SkPictureRecorder recorder;
274*c8dee2aaSAndroid Build Coastguard Worker draw_something(recorder.beginRecording(bounds), bounds);
275*c8dee2aaSAndroid Build Coastguard Worker fPicture = recorder.finishRecordingAsPicture();
276*c8dee2aaSAndroid Build Coastguard Worker }
277*c8dee2aaSAndroid Build Coastguard Worker
makeCaches(SkCanvas * canvas)278*c8dee2aaSAndroid Build Coastguard Worker bool makeCaches(SkCanvas* canvas) {
279*c8dee2aaSAndroid Build Coastguard Worker auto dContext = GrAsDirectContext(canvas->recordingContext());
280*c8dee2aaSAndroid Build Coastguard Worker
281*c8dee2aaSAndroid Build Coastguard Worker {
282*c8dee2aaSAndroid Build Coastguard Worker auto gen = fFactory(canvas, fPicture);
283*c8dee2aaSAndroid Build Coastguard Worker if (!gen) {
284*c8dee2aaSAndroid Build Coastguard Worker return false;
285*c8dee2aaSAndroid Build Coastguard Worker }
286*c8dee2aaSAndroid Build Coastguard Worker if (fUseTexture) {
287*c8dee2aaSAndroid Build Coastguard Worker auto textureGen = std::unique_ptr<GrTextureGenerator>(
288*c8dee2aaSAndroid Build Coastguard Worker static_cast<GrTextureGenerator*>(gen.release()));
289*c8dee2aaSAndroid Build Coastguard Worker fImage = SkImages::DeferredFromTextureGenerator(std::move(textureGen));
290*c8dee2aaSAndroid Build Coastguard Worker } else {
291*c8dee2aaSAndroid Build Coastguard Worker fImage = SkImages::DeferredFromGenerator(std::move(gen));
292*c8dee2aaSAndroid Build Coastguard Worker }
293*c8dee2aaSAndroid Build Coastguard Worker if (!fImage) {
294*c8dee2aaSAndroid Build Coastguard Worker return false;
295*c8dee2aaSAndroid Build Coastguard Worker }
296*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fImage->dimensions() == SkISize::Make(100, 100));
297*c8dee2aaSAndroid Build Coastguard Worker }
298*c8dee2aaSAndroid Build Coastguard Worker
299*c8dee2aaSAndroid Build Coastguard Worker {
300*c8dee2aaSAndroid Build Coastguard Worker const SkIRect subset = SkIRect::MakeLTRB(50, 50, 100, 100);
301*c8dee2aaSAndroid Build Coastguard Worker
302*c8dee2aaSAndroid Build Coastguard Worker // We re-create the generator here on the off chance that making a subset from
303*c8dee2aaSAndroid Build Coastguard Worker // 'fImage' might perturb its state.
304*c8dee2aaSAndroid Build Coastguard Worker auto gen = fFactory(canvas, fPicture);
305*c8dee2aaSAndroid Build Coastguard Worker if (!gen) {
306*c8dee2aaSAndroid Build Coastguard Worker return false;
307*c8dee2aaSAndroid Build Coastguard Worker }
308*c8dee2aaSAndroid Build Coastguard Worker
309*c8dee2aaSAndroid Build Coastguard Worker if (dContext) {
310*c8dee2aaSAndroid Build Coastguard Worker if (fUseTexture) {
311*c8dee2aaSAndroid Build Coastguard Worker auto textureGen = std::unique_ptr<GrTextureGenerator>(
312*c8dee2aaSAndroid Build Coastguard Worker static_cast<GrTextureGenerator*>(gen.release()));
313*c8dee2aaSAndroid Build Coastguard Worker fImageSubset = SkImages::DeferredFromTextureGenerator(std::move(textureGen))
314*c8dee2aaSAndroid Build Coastguard Worker ->makeSubset(dContext, subset);
315*c8dee2aaSAndroid Build Coastguard Worker } else {
316*c8dee2aaSAndroid Build Coastguard Worker fImageSubset = SkImages::DeferredFromGenerator(std::move(gen))
317*c8dee2aaSAndroid Build Coastguard Worker ->makeSubset(dContext, subset);
318*c8dee2aaSAndroid Build Coastguard Worker }
319*c8dee2aaSAndroid Build Coastguard Worker } else {
320*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GRAPHITE)
321*c8dee2aaSAndroid Build Coastguard Worker auto recorder = canvas->recorder();
322*c8dee2aaSAndroid Build Coastguard Worker fImageSubset = SkImages::DeferredFromGenerator(std::move(gen))
323*c8dee2aaSAndroid Build Coastguard Worker ->makeSubset(recorder, subset, {});
324*c8dee2aaSAndroid Build Coastguard Worker #endif
325*c8dee2aaSAndroid Build Coastguard Worker }
326*c8dee2aaSAndroid Build Coastguard Worker if (!fImageSubset) {
327*c8dee2aaSAndroid Build Coastguard Worker return false;
328*c8dee2aaSAndroid Build Coastguard Worker }
329*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fImageSubset->dimensions() == SkISize::Make(50, 50));
330*c8dee2aaSAndroid Build Coastguard Worker }
331*c8dee2aaSAndroid Build Coastguard Worker
332*c8dee2aaSAndroid Build Coastguard Worker return true;
333*c8dee2aaSAndroid Build Coastguard Worker }
334*c8dee2aaSAndroid Build Coastguard Worker
draw_placeholder(SkCanvas * canvas,SkScalar x,SkScalar y,int w,int h)335*c8dee2aaSAndroid Build Coastguard Worker static void draw_placeholder(SkCanvas* canvas, SkScalar x, SkScalar y, int w, int h) {
336*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
337*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kStroke_Style);
338*c8dee2aaSAndroid Build Coastguard Worker SkRect r = SkRect::MakeXYWH(x, y, SkIntToScalar(w), SkIntToScalar(h));
339*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
340*c8dee2aaSAndroid Build Coastguard Worker canvas->drawLine(r.left(), r.top(), r.right(), r.bottom(), paint);
341*c8dee2aaSAndroid Build Coastguard Worker canvas->drawLine(r.left(), r.bottom(), r.right(), r.top(), paint);
342*c8dee2aaSAndroid Build Coastguard Worker }
343*c8dee2aaSAndroid Build Coastguard Worker
draw_as_bitmap(GrDirectContext * dContext,SkCanvas * canvas,SkImage * image,SkScalar x,SkScalar y)344*c8dee2aaSAndroid Build Coastguard Worker static void draw_as_bitmap(GrDirectContext* dContext, SkCanvas* canvas, SkImage* image,
345*c8dee2aaSAndroid Build Coastguard Worker SkScalar x, SkScalar y) {
346*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bitmap;
347*c8dee2aaSAndroid Build Coastguard Worker if (as_IB(image)->getROPixels(dContext, &bitmap)) {
348*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(bitmap.asImage(), x, y);
349*c8dee2aaSAndroid Build Coastguard Worker } else {
350*c8dee2aaSAndroid Build Coastguard Worker draw_placeholder(canvas, x, y, image->width(), image->height());
351*c8dee2aaSAndroid Build Coastguard Worker }
352*c8dee2aaSAndroid Build Coastguard Worker }
353*c8dee2aaSAndroid Build Coastguard Worker
draw_as_tex(SkCanvas * canvas,SkImage * image,SkScalar x,SkScalar y)354*c8dee2aaSAndroid Build Coastguard Worker static void draw_as_tex(SkCanvas* canvas, SkImage* image, SkScalar x, SkScalar y) {
355*c8dee2aaSAndroid Build Coastguard Worker if (as_IB(image)->isGaneshBacked()) {
356*c8dee2aaSAndroid Build Coastguard Worker // The gpu-backed images are drawn in this manner bc the generator backed images
357*c8dee2aaSAndroid Build Coastguard Worker // aren't considered texture-backed
358*c8dee2aaSAndroid Build Coastguard Worker auto [view, ct] =
359*c8dee2aaSAndroid Build Coastguard Worker skgpu::ganesh::AsView(canvas->recordingContext(), image, skgpu::Mipmapped::kNo);
360*c8dee2aaSAndroid Build Coastguard Worker if (!view) {
361*c8dee2aaSAndroid Build Coastguard Worker // show placeholder if we have no texture
362*c8dee2aaSAndroid Build Coastguard Worker draw_placeholder(canvas, x, y, image->width(), image->height());
363*c8dee2aaSAndroid Build Coastguard Worker return;
364*c8dee2aaSAndroid Build Coastguard Worker }
365*c8dee2aaSAndroid Build Coastguard Worker SkColorInfo colorInfo(GrColorTypeToSkColorType(ct),
366*c8dee2aaSAndroid Build Coastguard Worker image->alphaType(),
367*c8dee2aaSAndroid Build Coastguard Worker image->refColorSpace());
368*c8dee2aaSAndroid Build Coastguard Worker // No API to draw a GrTexture directly, so we cheat and create a private image subclass
369*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> texImage(new SkImage_Ganesh(sk_ref_sp(canvas->recordingContext()),
370*c8dee2aaSAndroid Build Coastguard Worker image->uniqueID(),
371*c8dee2aaSAndroid Build Coastguard Worker std::move(view),
372*c8dee2aaSAndroid Build Coastguard Worker std::move(colorInfo)));
373*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(texImage.get(), x, y);
374*c8dee2aaSAndroid Build Coastguard Worker } else {
375*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(image, x, y);
376*c8dee2aaSAndroid Build Coastguard Worker }
377*c8dee2aaSAndroid Build Coastguard Worker }
378*c8dee2aaSAndroid Build Coastguard Worker
drawRow(GrDirectContext * dContext,SkCanvas * canvas,float scale) const379*c8dee2aaSAndroid Build Coastguard Worker void drawRow(GrDirectContext* dContext, SkCanvas* canvas, float scale) const {
380*c8dee2aaSAndroid Build Coastguard Worker canvas->scale(scale, scale);
381*c8dee2aaSAndroid Build Coastguard Worker
382*c8dee2aaSAndroid Build Coastguard Worker SkMatrix matrix = SkMatrix::Translate(-100, -100);
383*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPicture(fPicture, &matrix, nullptr);
384*c8dee2aaSAndroid Build Coastguard Worker
385*c8dee2aaSAndroid Build Coastguard Worker // Draw the tex first, so it doesn't hit a lucky cache from the raster version. This
386*c8dee2aaSAndroid Build Coastguard Worker // way we also can force the generateTexture call.
387*c8dee2aaSAndroid Build Coastguard Worker
388*c8dee2aaSAndroid Build Coastguard Worker draw_as_tex(canvas, fImage.get(), 150, 0);
389*c8dee2aaSAndroid Build Coastguard Worker draw_as_tex(canvas, fImageSubset.get(), 150+101, 0);
390*c8dee2aaSAndroid Build Coastguard Worker
391*c8dee2aaSAndroid Build Coastguard Worker draw_as_bitmap(dContext, canvas, fImage.get(), 310, 0);
392*c8dee2aaSAndroid Build Coastguard Worker draw_as_bitmap(dContext, canvas, fImageSubset.get(), 310+101, 0);
393*c8dee2aaSAndroid Build Coastguard Worker }
394*c8dee2aaSAndroid Build Coastguard Worker
onDraw(SkCanvas * canvas,SkString * errorMsg)395*c8dee2aaSAndroid Build Coastguard Worker DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
396*c8dee2aaSAndroid Build Coastguard Worker auto dContext = GrAsDirectContext(canvas->recordingContext());
397*c8dee2aaSAndroid Build Coastguard Worker if (!this->makeCaches(canvas)) {
398*c8dee2aaSAndroid Build Coastguard Worker errorMsg->printf("Could not create cached images");
399*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kSkip;
400*c8dee2aaSAndroid Build Coastguard Worker }
401*c8dee2aaSAndroid Build Coastguard Worker
402*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
403*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(20, 20);
404*c8dee2aaSAndroid Build Coastguard Worker this->drawRow(dContext, canvas, 1.0);
405*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
406*c8dee2aaSAndroid Build Coastguard Worker
407*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
408*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(20, 150);
409*c8dee2aaSAndroid Build Coastguard Worker this->drawRow(dContext, canvas, 0.25f);
410*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
411*c8dee2aaSAndroid Build Coastguard Worker
412*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
413*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(20, 220);
414*c8dee2aaSAndroid Build Coastguard Worker this->drawRow(dContext, canvas, 2.0f);
415*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
416*c8dee2aaSAndroid Build Coastguard Worker
417*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kOk;
418*c8dee2aaSAndroid Build Coastguard Worker }
419*c8dee2aaSAndroid Build Coastguard Worker
420*c8dee2aaSAndroid Build Coastguard Worker private:
421*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = skiagm::GM;
422*c8dee2aaSAndroid Build Coastguard Worker };
423*c8dee2aaSAndroid Build Coastguard Worker
424*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ImageCacheratorGM("picture", make_pic_generator, false); )
425*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ImageCacheratorGM("raster", make_ras_generator, false); )
426*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ImageCacheratorGM("texture", make_tex_generator, true); )
427