Flutter Engine
The Flutter Engine
texelsubset.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2014 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// This test only works with the GPU backend.
9
10#include "gm/gm.h"
16#include "include/core/SkRect.h"
17#include "include/core/SkSize.h"
26#include "src/gpu/ganesh/SkGr.h"
29#include "tools/DecodeUtils.h"
30#include "tools/Resources.h"
31#include "tools/gpu/TestOps.h"
32
33#include <memory>
34#include <utility>
35
36using namespace skia_private;
37
41
42namespace skiagm {
43/**
44 * This GM directly exercises GrTextureEffect::MakeTexelSubset.
45 */
46class TexelSubset : public GpuGM {
47public:
48 TexelSubset(Filter filter, MipmapMode mm, bool upscale)
49 : fFilter(filter), fMipmapMode(mm), fUpscale(upscale) {
50 this->setBGColor(0xFFFFFFFF);
51 }
52
53protected:
54 SkString getName() const override {
55 SkString name("texel_subset");
56 switch (fFilter) {
58 name.append("_nearest");
59 break;
60 case Filter::kLinear:
61 name.append("_linear");
62 break;
63 }
64 switch (fMipmapMode) {
66 break;
68 name.append("_mipmap_nearest");
69 break;
71 name.append("_mipmap_linear");
72 break;
73 }
74 name.append(fUpscale ? "_up" : "_down");
75 return name;
76 }
77
78 SkISize getISize() override {
79 static constexpr int kN = GrSamplerState::kWrapModeCount;
80 int w = kTestPad + 2*kN*(kImageSize.width() + 2*kDrawPad + kTestPad);
81 int h = kTestPad + 2*kN*(kImageSize.height() + 2*kDrawPad + kTestPad);
82 return {w, h};
83 }
84
85 void onOnceBeforeDraw() override {
86 SkAssertResult(ToolUtils::GetResourceAsBitmap("images/mandrill_128.png", &fBitmap));
87 // Make the bitmap non-square to detect any width/height confusion.
88 fBitmap.extractSubset(&fBitmap, SkIRect::MakeSize(fBitmap.dimensions()).makeInset(0, 20));
89 SkASSERT(fBitmap.dimensions() == kImageSize);
90 }
91
92 DrawResult onDraw(GrRecordingContext* rContext, SkCanvas* canvas, SkString* errorMsg) override {
94 if (!sdc) {
95 *errorMsg = kErrorMsg_DrawSkippedGpuOnly;
96 return DrawResult::kSkip;
97 }
98
99 skgpu::Mipmapped mipmapped =
101 if (mipmapped == skgpu::Mipmapped::kYes && !rContext->priv().caps()->mipmapSupport()) {
102 return DrawResult::kSkip;
103 }
105 rContext, fBitmap, /*label=*/"DrawResult_Draw_BitMap", mipmapped));
106 if (!view) {
107 *errorMsg = "Failed to create proxy.";
108 return DrawResult::kFail;
109 }
110
111 SkIRect texelSubset;
112 // Use a smaller subset when upscaling so that wrap is hit on all sides of the rect we
113 // will draw.
114 if (fUpscale) {
115 texelSubset = SkIRect::MakeXYWH(fBitmap.width()/3 - 1, 2*fBitmap.height()/5 - 1,
116 fBitmap.width()/4 + 2, fBitmap.height()/5 + 2);
117 } else {
118 texelSubset = SkIRect::MakeXYWH( fBitmap.width()/8 - 1, fBitmap.height()/7 - 1,
119 3*fBitmap.width()/5 + 2, 4*fBitmap.height()/5 + 2);
120 }
121
122 TArray<SkMatrix> textureMatrices;
123
124 SkRect a = SkRect::Make(texelSubset);
125 SkRect b = fUpscale ? a.makeInset (.31f * a.width(), .31f * a.height())
126 : a.makeOutset(.25f * a.width(), .25f * a.height());
127 textureMatrices.push_back() = SkMatrix::RectToRect(a, b);
128
129 b = fUpscale ? a.makeInset (.25f * a.width(), .35f * a.height())
130 : a.makeOutset(.20f * a.width(), .35f * a.height());
131 textureMatrices.push_back() = SkMatrix::RectToRect(a, b);
132 textureMatrices.back().preRotate(45.f, a.centerX(), a.centerY());
133 textureMatrices.back().postSkew(.05f, -.05f);
134
135 SkBitmap subsetBmp;
136 fBitmap.extractSubset(&subsetBmp, texelSubset);
137 subsetBmp.setImmutable();
139 rContext, subsetBmp, /*label=*/"DrawResult_Draw_SubsetBitMap", mipmapped));
140
141 SkRect localRect = SkRect::Make(fBitmap.bounds()).makeOutset(kDrawPad, kDrawPad);
142
143 auto size = this->getISize();
144
145 SkScalar y = kDrawPad + kTestPad;
146 SkRect drawRect;
147 for (int tm = 0; tm < textureMatrices.size(); ++tm) {
148 for (int my = 0; my < GrSamplerState::kWrapModeCount; ++my) {
149 SkScalar x = kDrawPad + kTestPad;
150 auto wmy = static_cast<Wrap>(my);
151 for (int mx = 0; mx < GrSamplerState::kWrapModeCount; ++mx) {
152 auto wmx = static_cast<Wrap>(mx);
153
154 const auto& caps = *rContext->priv().caps();
155
156 GrSamplerState sampler(wmx, wmy, fFilter, fMipmapMode);
157
158 drawRect = localRect.makeOffset(x, y);
159
160 std::unique_ptr<GrFragmentProcessor> fp1;
162 fBitmap.alphaType(),
163 textureMatrices[tm],
164 sampler,
165 SkRect::Make(texelSubset),
166 caps);
167 if (!fp1) {
168 continue;
169 }
170
171 // Throw a translate in the local matrix just to test having something other
172 // than identity. Compensate with an offset local rect.
173 static constexpr SkVector kT = {-100, 300};
174 if (auto op = sk_gpu_test::test_ops::MakeRect(rContext,
175 std::move(fp1),
176 drawRect,
177 localRect.makeOffset(kT),
178 SkMatrix::Translate(-kT))) {
179 sdc->addDrawOp(std::move(op));
180 }
181
182 x += localRect.width() + kTestPad;
183
184 // Now draw with a subsetted proxy using fixed function texture sampling
185 // rather than a texture subset as a comparison.
186 drawRect = localRect.makeOffset(x, y);
187 SkMatrix subsetTextureMatrix = SkMatrix::Concat(
188 SkMatrix::Translate(-texelSubset.topLeft()), textureMatrices[tm]);
189
190 auto fp2 = GrTextureEffect::Make(subsetView,
191 fBitmap.alphaType(),
192 subsetTextureMatrix,
193 sampler,
194 caps);
195 if (auto op = sk_gpu_test::test_ops::MakeRect(rContext, std::move(fp2),
196 drawRect, localRect)) {
197 sdc->addDrawOp(std::move(op));
198 }
199
200 if (mx < GrSamplerState::kWrapModeCount - 1) {
201 SkScalar midX =
202 SkScalarFloorToScalar(drawRect.right() + kTestPad/2.f) + 0.5f;
203 canvas->drawLine({midX, -1}, {midX, (float)size.fHeight+1}, {});
204 }
205 x += localRect.width() + kTestPad;
206 }
207 if (my < GrSamplerState::kWrapModeCount - 1) {
208 SkScalar midY = SkScalarFloorToScalar(drawRect.bottom() + kTestPad/2.f) + 0.5f;
209 canvas->drawLine({-1, midY}, {(float)size.fWidth+1, midY}, {});
210 }
211 y += localRect.height() + kTestPad;
212 }
213 if (tm < textureMatrices.size() - 1) {
215 paint.setColor(SK_ColorRED);
216 SkScalar midY = SkScalarFloorToScalar(drawRect.bottom() + kTestPad/2.f) + 0.5f;
217 canvas->drawLine({-1, midY}, {(float)size.fWidth + 1, midY}, paint);
218 }
219 }
220 return DrawResult::kOk;
221 }
222
223private:
224 inline static constexpr SkISize kImageSize = {128, 88};
225 inline static constexpr SkScalar kDrawPad = 10.f;
226 inline static constexpr SkScalar kTestPad = 10.f;
227 SkBitmap fBitmap;
228 Filter fFilter;
229 MipmapMode fMipmapMode;
230 bool fUpscale;
231
232 using INHERITED = GM;
233};
234
235DEF_GM(return new TexelSubset(Filter::kNearest, MipmapMode::kNone , false);)
236DEF_GM(return new TexelSubset(Filter::kNearest, MipmapMode::kNone , true );)
237DEF_GM(return new TexelSubset(Filter::kLinear , MipmapMode::kNone , false);)
238DEF_GM(return new TexelSubset(Filter::kLinear , MipmapMode::kNone , true );)
239// It doesn't make sense to have upscaling MIP map.
240DEF_GM(return new TexelSubset(Filter::kNearest, MipmapMode::kNearest, false);)
241DEF_GM(return new TexelSubset(Filter::kLinear , MipmapMode::kNearest, false);)
242DEF_GM(return new TexelSubset(Filter::kNearest, MipmapMode::kLinear , false);)
243DEF_GM(return new TexelSubset(Filter::kLinear , MipmapMode::kLinear , false);)
244
245} // namespace skiagm
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
#define SkASSERT(cond)
Definition: SkAssert.h:116
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
std::tuple< GrSurfaceProxyView, GrColorType > GrMakeCachedBitmapProxyView(GrRecordingContext *rContext, const SkBitmap &bitmap, std::string_view label, skgpu::Mipmapped mipmapped)
Definition: SkGr.cpp:188
SkFilterMode
SkMipmapMode
#define SkScalarFloorToScalar(x)
Definition: SkScalar.h:30
const GrCaps * caps() const
bool mipmapSupport() const
Definition: GrCaps.h:72
GrRecordingContextPriv priv()
SkFilterMode Filter
SkMipmapMode MipmapMode
static constexpr int kWrapModeCount
static std::unique_ptr< GrFragmentProcessor > MakeSubset(GrSurfaceProxyView, SkAlphaType, const SkMatrix &, GrSamplerState, const SkRect &subset, const GrCaps &caps, const float border[4]=kDefaultBorder, bool alwaysUseShaderTileMode=false)
static std::unique_ptr< GrFragmentProcessor > Make(GrSurfaceProxyView, SkAlphaType, const SkMatrix &=SkMatrix::I(), GrSamplerState::Filter=GrSamplerState::Filter::kNearest, GrSamplerState::MipmapMode mipmapMode=GrSamplerState::MipmapMode::kNone)
void setImmutable()
Definition: SkBitmap.cpp:400
SkAlphaType alphaType() const
Definition: SkBitmap.h:162
bool extractSubset(SkBitmap *dst, const SkIRect &subset) const
Definition: SkBitmap.cpp:453
SkISize dimensions() const
Definition: SkBitmap.h:388
int width() const
Definition: SkBitmap.h:149
SkIRect bounds() const
Definition: SkBitmap.h:382
int height() const
Definition: SkBitmap.h:158
void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint &paint)
Definition: SkCanvas.cpp:2700
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
static SkMatrix Concat(const SkMatrix &a, const SkMatrix &b)
Definition: SkMatrix.h:1775
SkMatrix & postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:524
SkMatrix & preRotate(SkScalar degrees, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:462
int size() const
Definition: SkTArray.h:421
SkISize getISize() override
Definition: texelsubset.cpp:78
DrawResult onDraw(GrRecordingContext *rContext, SkCanvas *canvas, SkString *errorMsg) override
Definition: texelsubset.cpp:92
TexelSubset(Filter filter, MipmapMode mm, bool upscale)
Definition: texelsubset.cpp:48
void onOnceBeforeDraw() override
Definition: texelsubset.cpp:85
SkString getName() const override
Definition: texelsubset.cpp:54
const Paint & paint
Definition: color_source.cc:38
float SkScalar
Definition: extension.cpp:12
static bool b
struct MyStruct a[10]
double y
double x
bool GetResourceAsBitmap(const char *resource, SkBitmap *dst)
Definition: DecodeUtils.h:21
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
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
const myers::Point & get< 0 >(const myers::Segment &s)
Definition: Myers.h:80
GrOp::Owner MakeRect(GrRecordingContext *context, GrPaint &&paint, const SkRect &drawRect, const SkRect &localRect, const SkMatrix &localM)
Definition: TestOps.cpp:227
SurfaceDrawContext * TopDeviceSurfaceDrawContext(const SkCanvas *canvas)
Definition: GrCanvas.cpp:20
Mipmapped
Definition: GpuTypes.h:53
DEF_GM(return F(C(clipbox), 0.0f, 0.0f, {})) DEF_GM(return F(C(clipbox)
DrawResult
Definition: gm.h:104
SkScalar w
SkScalar h
Definition: SkRect.h:32
static constexpr SkIRect MakeSize(const SkISize &size)
Definition: SkRect.h:66
constexpr SkIPoint topLeft() const
Definition: SkRect.h:151
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
Definition: SkRect.h:104
SkIRect makeInset(int32_t dx, int32_t dy) const
Definition: SkRect.h:332
Definition: SkSize.h:16
constexpr int32_t width() const
Definition: SkSize.h:36
constexpr int32_t height() const
Definition: SkSize.h:37
static SkRect Make(const SkISize &size)
Definition: SkRect.h:669
constexpr SkRect makeOffset(float dx, float dy) const
Definition: SkRect.h:965
SkRect makeOutset(float dx, float dy) const
Definition: SkRect.h:1002
constexpr float height() const
Definition: SkRect.h:769
constexpr float right() const
Definition: SkRect.h:748
constexpr float width() const
Definition: SkRect.h:762
constexpr float bottom() const
Definition: SkRect.h:755