1 /* 2 * Copyright 2013 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 #ifndef GrBicubicTextureEffect_DEFINED 9 #define GrBicubicTextureEffect_DEFINED 10 11 #include "src/gpu/effects/GrTextureDomain.h" 12 #include "src/gpu/glsl/GrGLSLFragmentProcessor.h" 13 14 class GrInvariantOutput; 15 16 class GrBicubicEffect : public GrFragmentProcessor { 17 public: 18 enum { 19 kFilterTexelPad = 2, // Given a src rect in texels to be filtered, this number of 20 // surrounding texels are needed by the kernel in x and y. 21 }; 22 23 enum class Direction { 24 /** Apply bicubic kernel in local coord x, nearest neighbor in y. */ 25 kX, 26 /** Apply bicubic kernel in local coord y, nearest neighbor in x. */ 27 kY, 28 /** Apply bicubic in both x and y. */ 29 kXY 30 }; 31 name()32 const char* name() const override { return "Bicubic"; } 33 clone()34 std::unique_ptr<GrFragmentProcessor> clone() const override { 35 return std::unique_ptr<GrFragmentProcessor>(new GrBicubicEffect(*this)); 36 } 37 domain()38 const GrTextureDomain& domain() const { return fDomain; } 39 direction()40 Direction direction() const { return fDirection; } 41 alphaType()42 SkAlphaType alphaType() const { return fAlphaType; } 43 44 /** 45 * Create a Mitchell filter effect with specified texture matrix with clamp wrap mode. 46 */ Make(sk_sp<GrTextureProxy> proxy,const SkMatrix & matrix,Direction direction,SkAlphaType alphaType)47 static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy, 48 const SkMatrix& matrix, 49 Direction direction, 50 SkAlphaType alphaType) { 51 static constexpr GrSamplerState::WrapMode kClampClamp[] = { 52 GrSamplerState::WrapMode::kClamp, GrSamplerState::WrapMode::kClamp}; 53 return Make(std::move(proxy), matrix, kClampClamp, GrTextureDomain::kIgnore_Mode, 54 GrTextureDomain::kIgnore_Mode, direction, alphaType); 55 } 56 57 /** 58 * Create a Mitchell filter effect with specified texture matrix and x/y tile modes. 59 */ Make(sk_sp<GrTextureProxy> proxy,const SkMatrix & matrix,const GrSamplerState::WrapMode wrapModes[2],Direction direction,SkAlphaType alphaType)60 static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy, 61 const SkMatrix& matrix, 62 const GrSamplerState::WrapMode wrapModes[2], 63 Direction direction, 64 SkAlphaType alphaType) { 65 // Ignore the domain on x and y, since this factory relies solely on the wrap mode of the 66 // sampler to constrain texture coordinates 67 return Make(std::move(proxy), matrix, wrapModes, GrTextureDomain::kIgnore_Mode, 68 GrTextureDomain::kIgnore_Mode, direction, alphaType); 69 } 70 71 /** 72 * Create a Mitchell filter effect with specified texture matrix and x/y tile modes. This 73 * supports providing modes for the texture domain explicitly, in the event that it should 74 * override the behavior of the sampler's tile mode (e.g. clamp to border unsupported). 75 */ 76 static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy, 77 const SkMatrix& matrix, 78 const GrSamplerState::WrapMode wrapModes[2], 79 GrTextureDomain::Mode modeX, 80 GrTextureDomain::Mode modeY, 81 Direction direction, 82 SkAlphaType alphaType, 83 const SkRect* domain = nullptr) { 84 SkRect resolvedDomain = domain ? *domain : GrTextureDomain::MakeTexelDomain( 85 SkIRect::MakeWH(proxy->width(), proxy->height()), modeX, modeY); 86 return std::unique_ptr<GrFragmentProcessor>( 87 new GrBicubicEffect(std::move(proxy), matrix, resolvedDomain, wrapModes, modeX, 88 modeY, direction, alphaType)); 89 } 90 91 /** 92 * Create a Mitchell filter effect with a texture matrix and a domain. 93 */ Make(sk_sp<GrTextureProxy> proxy,const SkMatrix & matrix,const SkRect & domain,Direction direction,SkAlphaType alphaType)94 static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy, 95 const SkMatrix& matrix, 96 const SkRect& domain, 97 Direction direction, 98 SkAlphaType alphaType) { 99 static const GrSamplerState::WrapMode kClampClamp[] = { 100 GrSamplerState::WrapMode::kClamp, GrSamplerState::WrapMode::kClamp}; 101 return Make(std::move(proxy), matrix, kClampClamp, GrTextureDomain::kClamp_Mode, 102 GrTextureDomain::kClamp_Mode, direction, alphaType, &domain); 103 } 104 105 /** 106 * Determines whether the bicubic effect should be used based on the transformation from the 107 * local coords to the device. Returns true if the bicubic effect should be used. filterMode 108 * is set to appropriate filtering mode to use regardless of the return result (e.g. when this 109 * returns false it may indicate that the best fallback is to use kMipMap, kBilerp, or 110 * kNearest). 111 */ 112 static bool ShouldUseBicubic(const SkMatrix& localCoordsToDevice, 113 GrSamplerState::Filter* filterMode); 114 115 private: 116 GrBicubicEffect(sk_sp<GrTextureProxy>, const SkMatrix& matrix, const SkRect& domain, 117 const GrSamplerState::WrapMode wrapModes[2], GrTextureDomain::Mode modeX, 118 GrTextureDomain::Mode modeY, Direction direction, SkAlphaType alphaType); 119 explicit GrBicubicEffect(const GrBicubicEffect&); 120 121 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; 122 123 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; 124 125 bool onIsEqual(const GrFragmentProcessor&) const override; 126 onTextureSampler(int)127 const TextureSampler& onTextureSampler(int) const override { return fTextureSampler; } 128 129 GrCoordTransform fCoordTransform; 130 GrTextureDomain fDomain; 131 TextureSampler fTextureSampler; 132 SkAlphaType fAlphaType; 133 Direction fDirection; 134 135 GR_DECLARE_FRAGMENT_PROCESSOR_TEST 136 137 typedef GrFragmentProcessor INHERITED; 138 }; 139 140 #endif 141