Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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) {
57 case Filter::kNearest:
58 name.append("_nearest");
59 break;
60 case Filter::kLinear:
61 name.append("_linear");
62 break;
63 }
64 switch (fMipmapMode) {
65 case MipmapMode::kNone:
66 break;
67 case MipmapMode::kNearest:
68 name.append("_mipmap_nearest");
69 break;
70 case MipmapMode::kLinear:
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 =
100 (fMipmapMode != MipmapMode::kNone) ? skgpu::Mipmapped::kYes : skgpu::Mipmapped::kNo;
101 if (mipmapped == skgpu::Mipmapped::kYes && !rContext->priv().caps()->mipmapSupport()) {
102 return DrawResult::kSkip;
103 }
104 auto view = std::get<0>(GrMakeCachedBitmapProxyView(
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();
138 auto subsetView = std::get<0>(GrMakeCachedBitmapProxyView(
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
#define SkAssertResult(cond)
Definition SkAssert.h:123
#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)
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
int size() const
Definition SkTArray.h:416
SkISize getISize() override
DrawResult onDraw(GrRecordingContext *rContext, SkCanvas *canvas, SkString *errorMsg) override
TexelSubset(Filter filter, MipmapMode mm, bool upscale)
void onOnceBeforeDraw() override
SkString getName() const override
const Paint & paint
float SkScalar
Definition extension.cpp:12
static bool b
struct MyStruct a[10]
const char * name
Definition fuchsia.cc:50
#define DEF_GM(CODE)
Definition gm.h:40
double y
double x
bool GetResourceAsBitmap(const char *resource, SkBitmap *dst)
Definition DecodeUtils.h:21
SurfaceDrawContext * TopDeviceSurfaceDrawContext(const SkCanvas *canvas)
Definition GrCanvas.cpp:20
Mipmapped
Definition GpuTypes.h:53
DrawResult
Definition gm.h:104
SkScalar w
SkScalar h
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
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