Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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) {
87 sk_sp<SkImage> src(make_raster(ctx, pic, 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
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;
123 draw_something(recorder.beginRecording(bounds), bounds);
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
178 SkMatrix mx = SkMatrix::RectToRect(src, dst);
179
181
184 SkSamplingOptions sampling(fm, mm);
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)
void drawOval(const SkRect &oval, const SkPaint &paint)
void translate(SkScalar dx, SkScalar dy)
virtual GrRecordingContext * recordingContext() const
@ 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)
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
const Paint & paint
VkSurfaceKHR surface
Definition main.cc:49
sk_sp< SkImage > image
Definition examples.cpp:29
#define DEF_GM(CODE)
Definition gm.h:40
#define DEF_SIMPLE_GM(NAME, CANVAS, W, H)
Definition gm.h:50
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)
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)
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)
SkScalar w
SkScalar h
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
static constexpr int kScale