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