| /* |
| * Copyright 2018 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef GrYUVtoRGBEffect_DEFINED |
| #define GrYUVtoRGBEffect_DEFINED |
| |
| #include "include/core/SkTypes.h" |
| |
| #include "src/gpu/GrCoordTransform.h" |
| #include "src/gpu/GrFragmentProcessor.h" |
| #include "src/gpu/effects/GrTextureDomain.h" |
| |
| #include "include/core/SkYUVAIndex.h" |
| |
| class GrYUVtoRGBEffect : public GrFragmentProcessor { |
| public: |
| // The domain supported by this effect is more limited than the general GrTextureDomain due |
| // to the multi-planar, varying resolution images that it has to sample. If 'domain' is provided |
| // it is the Y plane's domain. This will automatically inset for bilinear filtering, and only |
| // the clamp wrap mode is supported. |
| static std::unique_ptr<GrFragmentProcessor> Make(const sk_sp<GrTextureProxy> proxies[], |
| const SkYUVAIndex indices[4], |
| SkYUVColorSpace yuvColorSpace, |
| GrSamplerState::Filter filterMode, |
| const SkMatrix& localMatrix = SkMatrix::I(), |
| const SkRect* domain = nullptr); |
| #ifdef SK_DEBUG |
| SkString dumpInfo() const override; |
| #endif |
| |
| SkYUVColorSpace yuvColorSpace() const { return fYUVColorSpace; } |
| const SkYUVAIndex& yuvaIndex(int i) const { return fYUVAIndices[i]; } |
| |
| GrYUVtoRGBEffect(const GrYUVtoRGBEffect& src); |
| std::unique_ptr<GrFragmentProcessor> clone() const override; |
| const char* name() const override { return "YUVtoRGBEffect"; } |
| |
| private: |
| GrYUVtoRGBEffect(const sk_sp<GrTextureProxy> proxies[], const SkSize scales[], |
| const GrSamplerState::Filter filterModes[], int numPlanes, |
| const SkYUVAIndex yuvaIndices[4], SkYUVColorSpace yuvColorSpace, |
| const SkMatrix& localMatrix, const SkRect* domain) |
| : INHERITED(kGrYUVtoRGBEffect_ClassID, kNone_OptimizationFlags) |
| , fDomains{GrTextureDomain::IgnoredDomain(), GrTextureDomain::IgnoredDomain(), |
| GrTextureDomain::IgnoredDomain(), GrTextureDomain::IgnoredDomain()} |
| , fYUVColorSpace(yuvColorSpace) { |
| for (int i = 0; i < numPlanes; ++i) { |
| SkMatrix planeMatrix = SkMatrix::MakeScale(scales[i].width(), scales[i].height()); |
| if (domain) { |
| SkASSERT(filterModes[i] != GrSamplerState::Filter::kMipMap); |
| |
| SkRect scaledDomain = planeMatrix.mapRect(*domain); |
| if (filterModes[i] != GrSamplerState::Filter::kNearest) { |
| // Inset by half a pixel for bilerp, after scaling to the size of the plane |
| scaledDomain.inset(0.5f, 0.5f); |
| } |
| |
| fDomains[i] = GrTextureDomain(proxies[i].get(), scaledDomain, |
| GrTextureDomain::kClamp_Mode, GrTextureDomain::kClamp_Mode, i); |
| } |
| |
| planeMatrix.preConcat(localMatrix); |
| fSamplers[i].reset(std::move(proxies[i]), |
| GrSamplerState(GrSamplerState::WrapMode::kClamp, filterModes[i])); |
| fSamplerTransforms[i] = planeMatrix; |
| fSamplerCoordTransforms[i] = |
| GrCoordTransform(fSamplerTransforms[i], fSamplers[i].proxy()); |
| } |
| |
| this->setTextureSamplerCnt(numPlanes); |
| for (int i = 0; i < numPlanes; ++i) { |
| this->addCoordTransform(&fSamplerCoordTransforms[i]); |
| } |
| |
| memcpy(fYUVAIndices, yuvaIndices, sizeof(fYUVAIndices)); |
| } |
| GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; |
| void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; |
| bool onIsEqual(const GrFragmentProcessor&) const override; |
| const TextureSampler& onTextureSampler(int) const override; |
| GR_DECLARE_FRAGMENT_PROCESSOR_TEST |
| |
| TextureSampler fSamplers[4]; |
| SkMatrix44 fSamplerTransforms[4]; |
| GrCoordTransform fSamplerCoordTransforms[4]; |
| GrTextureDomain fDomains[4]; |
| SkYUVAIndex fYUVAIndices[4]; |
| SkYUVColorSpace fYUVColorSpace; |
| |
| typedef GrFragmentProcessor INHERITED; |
| }; |
| #endif |