Flutter Engine
The Flutter Engine
image_shader.cpp
Go to the documentation of this file.
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 "gm/gm.h"
14#include "include/core/SkData.h"
21#include "include/core/SkRect.h"
24#include "include/core/SkSize.h"
32
33#include <utility>
34
35static void draw_something(SkCanvas* canvas, const SkRect& bounds) {
37 paint.setAntiAlias(true);
38 paint.setColor(SK_ColorRED);
40 paint.setStrokeWidth(10);
41 canvas->drawRect(bounds, paint);
43 paint.setColor(SK_ColorBLUE);
44 canvas->drawOval(bounds, paint);
45}
46
48
50 SkPicture* pic,
51 const SkImageInfo& info) {
53 surface->getCanvas()->clear(0);
54 surface->getCanvas()->drawPicture(pic);
55 return surface->makeImageSnapshot();
56}
57
59 SkPicture* pic,
60 const SkImageInfo& info) {
61 if (!ctx) {
62 return nullptr;
63 }
65 if (!surface) {
66 return nullptr;
67 }
68 surface->getCanvas()->clear(0);
69 surface->getCanvas()->drawPicture(pic);
70 return surface->makeImageSnapshot();
71}
72
74 SkPicture* pic,
75 const SkImageInfo& info) {
77 info.dimensions(),
78 nullptr,
79 nullptr,
82}
83
85 SkPicture* pic,
86 const SkImageInfo& info) {
88 if (!src) {
89 return nullptr;
90 }
91 sk_sp<SkData> encoded = SkPngEncoder::Encode(nullptr, src.get(), {});
92 if (!encoded) {
93 return nullptr;
94 }
95 return SkImages::DeferredFromEncodedData(std::move(encoded));
96}
97
103};
104
105/*
106 * Exercise drawing pictures inside an image, showing that the image version is pixelated
107 * (correctly) when it is inside an image.
108 */
109class ImageShaderGM : public skiagm::GM {
110 sk_sp<SkPicture> fPicture;
111
112public:
114
115protected:
116 SkString getName() const override { return SkString("image-shader"); }
117
118 SkISize getISize() override { return SkISize::Make(850, 450); }
119
120 void onOnceBeforeDraw() override {
121 const SkRect bounds = SkRect::MakeWH(100, 100);
122 SkPictureRecorder recorder;
124 fPicture = recorder.finishRecordingAsPicture();
125 }
126
127 void testImage(SkCanvas* canvas, SkImage* image) {
128 SkAutoCanvasRestore acr(canvas, true);
129
130 canvas->drawImage(image, 0, 0);
131 canvas->translate(0, 120);
132
133 const SkTileMode tile = SkTileMode::kRepeat;
134 const SkMatrix localM = SkMatrix::Translate(-50, -50);
136 paint.setShader(image->makeShader(tile, tile, SkSamplingOptions(), &localM));
137 paint.setAntiAlias(true);
138 canvas->drawCircle(50, 50, 50, paint);
139 }
140
141 void onDraw(SkCanvas* canvas) override {
142 canvas->translate(20, 20);
143
145
146 for (size_t i = 0; i < std::size(gProcs); ++i) {
147 sk_sp<SkImage> image(gProcs[i](canvas->recordingContext(), fPicture.get(), info));
148 if (image) {
149 this->testImage(canvas, image.get());
150 }
151 canvas->translate(120, 0);
152 }
153 }
154
155private:
156 using INHERITED = skiagm::GM;
157};
158DEF_GM( return new ImageShaderGM; )
159
160//////////////////////////////////////////////////////////////////////////////////////////////
161
162#include "tools/ToolUtils.h"
163
164static sk_sp<SkImage> make_checker_img(int w, int h, SkColor c0, SkColor c1, int size) {
166 bm.setImmutable();
167 return bm.asImage();
168}
169
170DEF_SIMPLE_GM(drawimage_sampling, canvas, 500, 500) {
171 constexpr int N = 256;
172 constexpr float kScale = 1.0f/6;
173 const SkRect dst = {0, 0, kScale*N, kScale*N};
174
176 const SkRect src = SkRect::MakeIWH(img->width(), img->height());
177
179
181
185
186 canvas->save();
187
188 canvas->save();
189 canvas->concat(mx);
190 canvas->drawImage(img.get(), 0, 0, sampling);
191 canvas->restore();
192
193 canvas->translate(dst.width() + 4, 0);
194
195 paint.setShader(img->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, sampling, &mx));
196 canvas->drawRect(dst, paint);
197
198 canvas->translate(dst.width() + 4, 0);
199
200 canvas->drawImageRect(img.get(), src, dst, sampling, nullptr,
202 canvas->restore();
203
204 canvas->translate(0, dst.height() + 8);
205 }
206 }
207
208}
209
210// Test case for skbug.com/12685 (texture-backed image shaders silently fail drawing to CPU canvas)
211DEF_SIMPLE_GM(textureimage_and_shader, canvas, 100, 50) {
212 canvas->clear(SK_ColorGREEN);
213
215 if (canvas->getSurface()) {
216 image = canvas->getSurface()->makeImageSnapshot();
217 canvas->clear(SK_ColorRED);
218 } else {
219 auto greenSurface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50));
220 greenSurface->getCanvas()->clear(SK_ColorGREEN);
221 image = greenSurface->makeImageSnapshot();
222 }
223
224 // At this point, 'image' contains a green image. If our original canvas is GPU-backed, then
225 // the snapped image will be a (GPU) texture. We will try to draw that image to a non-GPU
226 // surface, to ensure that we get automatic read-back. If all goes well, we will get a pure
227 // green result. If either draw fails, we'll get red (most likely).
228
230
231 // First, use drawImage:
232 surface->getCanvas()->clear(SK_ColorRED);
233 surface->getCanvas()->drawImage(image, 0, 0);
234 canvas->drawImage(surface->makeImageSnapshot(), 0, 0);
235
236 // Now, use an image shader:
239 surface->getCanvas()->clear(SK_ColorRED);
240 surface->getCanvas()->drawPaint(paint);
241 canvas->drawImage(surface->makeImageSnapshot(), 50, 0);
242}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
uint32_t SkColor
Definition: SkColor.h:37
constexpr SkColor SK_ColorBLUE
Definition: SkColor.h:135
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
constexpr SkColor SK_ColorBLACK
Definition: SkColor.h:103
constexpr SkColor SK_ColorGREEN
Definition: SkColor.h:131
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
SkTileMode
Definition: SkTileMode.h:13
#define N
Definition: beziers.cpp:19
void onOnceBeforeDraw() override
void onDraw(SkCanvas *canvas) override
SkISize getISize() override
void testImage(SkCanvas *canvas, SkImage *image)
SkString getName() const override
sk_sp< SkImage > asImage() const
Definition: SkBitmap.cpp:645
void setImmutable()
Definition: SkBitmap.cpp:400
void drawRect(const SkRect &rect, const SkPaint &paint)
Definition: SkCanvas.cpp:1673
void drawOval(const SkRect &oval, const SkPaint &paint)
Definition: SkCanvas.cpp:1698
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
virtual GrRecordingContext * recordingContext() const
Definition: SkCanvas.cpp:1637
@ kFast_SrcRectConstraint
sample outside bounds; faster
Definition: SkCanvas.h:1543
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition: SkCanvas.h:1528
void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint &paint)
Definition: SkCanvas.cpp:2707
static sk_sp< SkColorSpace > MakeSRGB()
sk_sp< SkImage > withDefaultMipmaps() const
Definition: SkImage.cpp:305
sk_sp< SkShader > makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions &, const SkMatrix *localMatrix=nullptr) const
Definition: SkImage.cpp:179
static SkMatrix RectToRect(const SkRect &src, const SkRect &dst, ScaleToFit mode=kFill_ScaleToFit)
Definition: SkMatrix.h:157
static SkMatrix Translate(SkScalar dx, SkScalar dy)
Definition: SkMatrix.h:91
@ kStroke_Style
set to stroke geometry
Definition: SkPaint.h:194
@ kFill_Style
set to fill geometry
Definition: SkPaint.h:193
SkCanvas * beginRecording(const SkRect &bounds, sk_sp< SkBBoxHierarchy > bbh)
sk_sp< SkPicture > finishRecordingAsPicture()
T * get() const
Definition: SkRefCnt.h:303
Definition: gm.h:110
const Paint & paint
Definition: color_source.cc:38
VkSurfaceKHR surface
Definition: main.cc:49
#define DEF_GM(CODE)
Definition: gm.h:40
const ImageMakerProc gProcs[]
static sk_sp< SkImage > make_texture(GrRecordingContext *ctx, SkPicture *pic, const SkImageInfo &info)
static sk_sp< SkImage > make_raster(GrRecordingContext *, SkPicture *pic, const SkImageInfo &info)
static sk_sp< SkImage > make_checker_img(int w, int h, SkColor c0, SkColor c1, int size)
sk_sp< SkImage >(* ImageMakerProc)(GrRecordingContext *, SkPicture *, const SkImageInfo &)
static sk_sp< SkImage > make_pict_gen(GrRecordingContext *, SkPicture *pic, const SkImageInfo &info)
static sk_sp< SkImage > make_encode_gen(GrRecordingContext *ctx, SkPicture *pic, const SkImageInfo &info)
static void draw_something(SkCanvas *canvas, const SkRect &bounds)
DEF_SIMPLE_GM(drawimage_sampling, canvas, 500, 500)
SK_API sk_sp< SkImage > DeferredFromPicture(sk_sp< SkPicture > picture, const SkISize &dimensions, const SkMatrix *matrix, const SkPaint *paint, BitDepth bitDepth, sk_sp< SkColorSpace > colorSpace, SkSurfaceProps props)
SK_API sk_sp< SkImage > DeferredFromEncodedData(sk_sp< SkData > encoded, std::optional< SkAlphaType > alphaType=std::nullopt)
@ kU8
uses 8-bit unsigned int per color component
SK_API bool Encode(SkWStream *dst, const SkPixmap &src, const Options &options)
Optional< SkRect > bounds
Definition: SkRecords.h:189
sk_sp< const SkImage > image
Definition: SkRecords.h:269
SkSamplingOptions sampling
Definition: SkRecords.h:337
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
SkBitmap create_checkerboard_bitmap(int w, int h, SkColor c1, SkColor c2, int checkSize)
Definition: ToolUtils.cpp:159
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
dst
Definition: cp.py:12
SkScalar w
SkScalar h
Definition: SkSize.h:16
static constexpr SkISize Make(int32_t w, int32_t h)
Definition: SkSize.h:20
static SkImageInfo MakeN32Premul(int width, int height)
static SkRect MakeIWH(int w, int h)
Definition: SkRect.h:623
static constexpr SkRect MakeWH(float w, float h)
Definition: SkRect.h:609