• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"
11 #include "include/core/SkBitmap.h"
12 #include "include/core/SkBlendMode.h"
13 #include "include/core/SkCanvas.h"
14 #include "include/core/SkColor.h"
15 #include "include/core/SkMatrix.h"
16 #include "include/core/SkPaint.h"
17 #include "include/core/SkRect.h"
18 #include "include/core/SkRefCnt.h"
19 #include "include/core/SkScalar.h"
20 #include "include/core/SkShader.h"
21 #include "include/core/SkSize.h"
22 #include "include/core/SkString.h"
23 #include "include/core/SkTypes.h"
24 #include "include/effects/SkGradientShader.h"
25 #include "include/gpu/GrContext.h"
26 #include "include/gpu/GrTypes.h"
27 #include "include/private/GrTypesPriv.h"
28 #include "include/private/SkTArray.h"
29 #include "src/gpu/GrCaps.h"
30 #include "src/gpu/GrContextPriv.h"
31 #include "src/gpu/GrFragmentProcessor.h"
32 #include "src/gpu/GrPaint.h"
33 #include "src/gpu/GrProxyProvider.h"
34 #include "src/gpu/GrRenderTargetContext.h"
35 #include "src/gpu/GrRenderTargetContextPriv.h"
36 #include "src/gpu/GrSamplerState.h"
37 #include "src/gpu/GrTextureProxy.h"
38 #include "src/gpu/effects/GrPorterDuffXferProcessor.h"
39 #include "src/gpu/effects/GrTextureDomain.h"
40 #include "src/gpu/ops/GrDrawOp.h"
41 #include "src/gpu/ops/GrFillRectOp.h"
42 
43 #include <memory>
44 #include <utility>
45 
46 namespace skiagm {
47 /**
48  * This GM directly exercises GrTextureDomainEffect.
49  */
50 class TextureDomainEffect : public GpuGM {
51 public:
TextureDomainEffect(GrSamplerState::Filter filter)52     TextureDomainEffect(GrSamplerState::Filter filter)
53             : fFilter(filter) {
54         this->setBGColor(0xFFFFFFFF);
55     }
56 
57 protected:
onShortName()58     SkString onShortName() override {
59         SkString name("texture_domain_effect");
60         if (fFilter == GrSamplerState::Filter::kBilerp) {
61             name.append("_bilerp");
62         } else if (fFilter == GrSamplerState::Filter::kMipMap) {
63             name.append("_mipmap");
64         }
65         return name;
66     }
67 
onISize()68     SkISize onISize() override {
69         const SkScalar canvasWidth = kDrawPad +
70                 (kTargetWidth + 2 * kDrawPad) * GrTextureDomain::kModeCount +
71                 kTestPad * GrTextureDomain::kModeCount;
72         return SkISize::Make(SkScalarCeilToInt(canvasWidth), 800);
73     }
74 
onOnceBeforeDraw()75     void onOnceBeforeDraw() override {
76         fBitmap.allocN32Pixels(kTargetWidth, kTargetHeight);
77         SkCanvas canvas(fBitmap);
78         canvas.clear(0x00000000);
79         SkPaint paint;
80 
81         SkColor colors1[] = { SK_ColorCYAN, SK_ColorLTGRAY, SK_ColorGRAY };
82         paint.setShader(SkGradientShader::MakeSweep(65.f, 75.f, colors1, nullptr,
83                                                     SK_ARRAY_COUNT(colors1)));
84         canvas.drawOval(SkRect::MakeXYWH(-5.f, -5.f, kTargetWidth + 10.f, kTargetHeight + 10.f),
85                         paint);
86 
87         SkColor colors2[] = { SK_ColorMAGENTA, SK_ColorLTGRAY, SK_ColorYELLOW };
88         paint.setShader(SkGradientShader::MakeSweep(45.f, 55.f, colors2, nullptr,
89                                                     SK_ARRAY_COUNT(colors2)));
90         paint.setBlendMode(SkBlendMode::kDarken);
91         canvas.drawOval(SkRect::MakeXYWH(-5.f, -5.f, kTargetWidth + 10.f, kTargetHeight + 10.f),
92                         paint);
93 
94         SkColor colors3[] = { SK_ColorBLUE, SK_ColorLTGRAY, SK_ColorGREEN };
95         paint.setShader(SkGradientShader::MakeSweep(25.f, 35.f, colors3, nullptr,
96                                                     SK_ARRAY_COUNT(colors3)));
97         paint.setBlendMode(SkBlendMode::kLighten);
98         canvas.drawOval(SkRect::MakeXYWH(-5.f, -5.f, kTargetWidth + 10.f, kTargetHeight + 10.f),
99                         paint);
100     }
101 
onDraw(GrContext * context,GrRenderTargetContext * renderTargetContext,SkCanvas * canvas,SkString * errorMsg)102     DrawResult onDraw(GrContext* context, GrRenderTargetContext* renderTargetContext,
103                       SkCanvas* canvas, SkString* errorMsg) override {
104         GrProxyProvider* proxyProvider = context->priv().proxyProvider();
105         sk_sp<GrTextureProxy> proxy;
106         GrMipMapped mipMapped = fFilter == GrSamplerState::Filter::kMipMap &&
107                                 context->priv().caps()->mipMapSupport()
108                 ? GrMipMapped::kYes : GrMipMapped::kNo;
109         proxy = proxyProvider->createProxyFromBitmap(fBitmap, mipMapped);
110         if (!proxy) {
111             *errorMsg = "Failed to create proxy.";
112             return DrawResult::kFail;
113         }
114 
115         SkTArray<SkMatrix> textureMatrices;
116         textureMatrices.push_back() = SkMatrix::I();
117         textureMatrices.push_back() = SkMatrix::MakeScale(1.5f, 0.85f);
118         textureMatrices.push_back();
119         textureMatrices.back().setRotate(45.f, proxy->width() / 2.f, proxy->height() / 2.f);
120 
121         const SkIRect texelDomains[] = {
122             fBitmap.bounds(),
123             SkIRect::MakeXYWH(fBitmap.width() / 4 - 1, fBitmap.height() / 4 - 1,
124                               fBitmap.width() / 2 + 2, fBitmap.height() / 2 + 2),
125         };
126 
127         SkRect renderRect = SkRect::Make(fBitmap.bounds());
128         renderRect.outset(kDrawPad, kDrawPad);
129 
130         SkScalar y = kDrawPad + kTestPad;
131         for (int tm = 0; tm < textureMatrices.count(); ++tm) {
132             for (size_t d = 0; d < SK_ARRAY_COUNT(texelDomains); ++d) {
133                 SkScalar x = kDrawPad + kTestPad;
134                 for (int m = 0; m < GrTextureDomain::kModeCount; ++m) {
135                     GrTextureDomain::Mode mode = (GrTextureDomain::Mode) m;
136                     if (fFilter != GrSamplerState::Filter::kNearest &&
137                         mode == GrTextureDomain::kRepeat_Mode) {
138                         // Repeat mode doesn't produce correct results with bilerp filtering
139                         continue;
140                     }
141 
142                     GrPaint grPaint;
143                     grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
144                     auto fp = GrTextureDomainEffect::Make(
145                             proxy, textureMatrices[tm],
146                             GrTextureDomain::MakeTexelDomain(texelDomains[d], mode),
147                             mode, fFilter);
148 
149                     if (!fp) {
150                         continue;
151                     }
152                     const SkMatrix viewMatrix = SkMatrix::MakeTrans(x, y);
153                     grPaint.addColorFragmentProcessor(std::move(fp));
154                     renderTargetContext->priv().testingOnly_addDrawOp(
155                             GrFillRectOp::MakeNonAARect(context, std::move(grPaint),
156                                                         viewMatrix, renderRect));
157                     x += renderRect.width() + kTestPad;
158                 }
159                 y += renderRect.height() + kTestPad;
160             }
161         }
162         return DrawResult::kOk;
163     }
164 
165 private:
166     static constexpr SkScalar kDrawPad = 10.f;
167     static constexpr SkScalar kTestPad = 10.f;
168     static constexpr int      kTargetWidth = 100;
169     static constexpr int      kTargetHeight = 100;
170     SkBitmap fBitmap;
171     GrSamplerState::Filter fFilter;
172 
173     typedef GM INHERITED;
174 };
175 
176 DEF_GM(return new TextureDomainEffect(GrSamplerState::Filter::kNearest);)
177 DEF_GM(return new TextureDomainEffect(GrSamplerState::Filter::kBilerp);)
178 DEF_GM(return new TextureDomainEffect(GrSamplerState::Filter::kMipMap);)
179 
180 }
181