LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu/effects - GrYUVEffect.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 169 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 35 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include "GrYUVEffect.h"
       9             : 
      10             : #include "GrCoordTransform.h"
      11             : #include "GrFragmentProcessor.h"
      12             : #include "GrProcessor.h"
      13             : #include "GrTextureProxy.h"
      14             : #include "glsl/GrGLSLFragmentProcessor.h"
      15             : #include "glsl/GrGLSLFragmentShaderBuilder.h"
      16             : #include "glsl/GrGLSLProgramDataManager.h"
      17             : #include "glsl/GrGLSLUniformHandler.h"
      18             : 
      19             : namespace {
      20             : 
      21             : static const float kJPEGConversionMatrix[16] = {
      22             :     1.0f,  0.0f,      1.402f,  -0.701f,
      23             :     1.0f, -0.34414f, -0.71414f, 0.529f,
      24             :     1.0f,  1.772f,    0.0f,    -0.886f,
      25             :     0.0f,  0.0f,      0.0f,     1.0
      26             : };
      27             : 
      28             : static const float kRec601ConversionMatrix[16] = {
      29             :     1.164f,  0.0f,    1.596f, -0.87075f,
      30             :     1.164f, -0.391f, -0.813f,  0.52925f,
      31             :     1.164f,  2.018f,  0.0f,   -1.08175f,
      32             :     0.0f,    0.0f,    0.0f,    1.0}
      33             : ;
      34             : 
      35             : static const float kRec709ConversionMatrix[16] = {
      36             :     1.164f,  0.0f,    1.793f, -0.96925f,
      37             :     1.164f, -0.213f, -0.533f,  0.30025f,
      38             :     1.164f,  2.112f,  0.0f,   -1.12875f,
      39             :     0.0f,    0.0f,    0.0f,    1.0f}
      40             : ;
      41             : 
      42             : static const float kJPEGInverseConversionMatrix[16] = {
      43             :      0.299001f,  0.586998f,  0.114001f,  0.0000821798f,
      44             :     -0.168736f, -0.331263f,  0.499999f,  0.499954f,
      45             :      0.499999f, -0.418686f, -0.0813131f, 0.499941f,
      46             :      0.f,        0.f,        0.f,        1.f
      47             : };
      48             : 
      49             : static const float kRec601InverseConversionMatrix[16] = {
      50             :      0.256951f,  0.504421f,  0.0977346f, 0.0625f,
      51             :     -0.148212f, -0.290954f,  0.439166f,  0.5f,
      52             :      0.439166f, -0.367886f, -0.0712802f, 0.5f,
      53             :      0.f,        0.f,        0.f,        1.f
      54             : };
      55             : 
      56             : static const float kRec709InverseConversionMatrix[16] = {
      57             :      0.182663f,  0.614473f, 0.061971f, 0.0625f,
      58             :     -0.100672f, -0.338658f, 0.43933f,  0.5f,
      59             :      0.439142f, -0.39891f, -0.040231f, 0.5f,
      60             :      0.f,        0.f,       0.f,       1.
      61             : };
      62             : 
      63           0 : class YUVtoRGBEffect : public GrFragmentProcessor {
      64             : public:
      65           0 :     static sk_sp<GrFragmentProcessor> Make(GrResourceProvider* resourceProvider,
      66             :                                            sk_sp<GrTextureProxy> yProxy,
      67             :                                            sk_sp<GrTextureProxy> uProxy,
      68             :                                            sk_sp<GrTextureProxy> vProxy, const SkISize sizes[3],
      69             :                                            SkYUVColorSpace colorSpace, bool nv12) {
      70             :         SkScalar w[3], h[3];
      71           0 :         w[0] = SkIntToScalar(sizes[0].fWidth);
      72           0 :         h[0] = SkIntToScalar(sizes[0].fHeight);
      73           0 :         w[1] = SkIntToScalar(sizes[1].fWidth);
      74           0 :         h[1] = SkIntToScalar(sizes[1].fHeight);
      75           0 :         w[2] = SkIntToScalar(sizes[2].fWidth);
      76           0 :         h[2] = SkIntToScalar(sizes[2].fHeight);
      77             :         const SkMatrix yuvMatrix[3] = {
      78           0 :             SkMatrix::I(),
      79           0 :             SkMatrix::MakeScale(w[1] / w[0], h[1] / h[0]),
      80           0 :             SkMatrix::MakeScale(w[2] / w[0], h[2] / h[0])
      81           0 :         };
      82             :         GrSamplerParams::FilterMode uvFilterMode =
      83           0 :             ((sizes[1].fWidth  != sizes[0].fWidth) ||
      84           0 :              (sizes[1].fHeight != sizes[0].fHeight) ||
      85           0 :              (sizes[2].fWidth  != sizes[0].fWidth) ||
      86           0 :              (sizes[2].fHeight != sizes[0].fHeight)) ?
      87             :             GrSamplerParams::kBilerp_FilterMode :
      88           0 :             GrSamplerParams::kNone_FilterMode;
      89             :         return sk_sp<GrFragmentProcessor>(new YUVtoRGBEffect(
      90           0 :             resourceProvider, std::move(yProxy), std::move(uProxy), std::move(vProxy),
      91           0 :             yuvMatrix, uvFilterMode, colorSpace, nv12));
      92             :     }
      93             : 
      94           0 :     const char* name() const override { return "YUV to RGB"; }
      95             : 
      96           0 :     SkYUVColorSpace getColorSpace() const { return fColorSpace; }
      97             : 
      98           0 :     bool isNV12() const {
      99           0 :         return fNV12;
     100             :     }
     101             : 
     102           0 :     class GLSLProcessor : public GrGLSLFragmentProcessor {
     103             :     public:
     104           0 :         void emitCode(EmitArgs& args) override {
     105           0 :             GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     106           0 :             const YUVtoRGBEffect& effect = args.fFp.cast<YUVtoRGBEffect>();
     107             : 
     108           0 :             const char* colorSpaceMatrix = nullptr;
     109           0 :             fMatrixUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
     110             :                                                           kMat44f_GrSLType, kDefault_GrSLPrecision,
     111           0 :                                                           "ColorSpaceMatrix", &colorSpaceMatrix);
     112           0 :             fragBuilder->codeAppendf("%s = vec4(", args.fOutputColor);
     113           0 :             fragBuilder->appendTextureLookup(args.fTexSamplers[0],
     114           0 :                                              args.fTransformedCoords[0].c_str(),
     115           0 :                                              args.fTransformedCoords[0].getType());
     116           0 :             fragBuilder->codeAppend(".r,");
     117           0 :             fragBuilder->appendTextureLookup(args.fTexSamplers[1],
     118           0 :                                              args.fTransformedCoords[1].c_str(),
     119           0 :                                              args.fTransformedCoords[1].getType());
     120           0 :             if (effect.fNV12) {
     121           0 :                 fragBuilder->codeAppendf(".rg,");
     122             :             } else {
     123           0 :                 fragBuilder->codeAppend(".r,");
     124           0 :                 fragBuilder->appendTextureLookup(args.fTexSamplers[2],
     125           0 :                                                  args.fTransformedCoords[2].c_str(),
     126           0 :                                                  args.fTransformedCoords[2].getType());
     127           0 :                 fragBuilder->codeAppendf(".g,");
     128             :             }
     129           0 :             fragBuilder->codeAppendf("1.0) * %s;", colorSpaceMatrix);
     130           0 :         }
     131             : 
     132             :     protected:
     133           0 :         void onSetData(const GrGLSLProgramDataManager& pdman,
     134             :                        const GrFragmentProcessor& processor) override {
     135           0 :             const YUVtoRGBEffect& yuvEffect = processor.cast<YUVtoRGBEffect>();
     136           0 :             switch (yuvEffect.getColorSpace()) {
     137             :                 case kJPEG_SkYUVColorSpace:
     138           0 :                     pdman.setMatrix4f(fMatrixUni, kJPEGConversionMatrix);
     139           0 :                     break;
     140             :                 case kRec601_SkYUVColorSpace:
     141           0 :                     pdman.setMatrix4f(fMatrixUni, kRec601ConversionMatrix);
     142           0 :                     break;
     143             :                 case kRec709_SkYUVColorSpace:
     144           0 :                     pdman.setMatrix4f(fMatrixUni, kRec709ConversionMatrix);
     145           0 :                     break;
     146             :             }
     147           0 :         }
     148             : 
     149             :     private:
     150             :         GrGLSLProgramDataManager::UniformHandle fMatrixUni;
     151             : 
     152             :         typedef GrGLSLFragmentProcessor INHERITED;
     153             :     };
     154             : 
     155             : private:
     156           0 :     YUVtoRGBEffect(GrResourceProvider* resourceProvider,
     157             :                    sk_sp<GrTextureProxy> yProxy, sk_sp<GrTextureProxy> uProxy,
     158             :                    sk_sp<GrTextureProxy> vProxy, const SkMatrix yuvMatrix[3],
     159             :                    GrSamplerParams::FilterMode uvFilterMode, SkYUVColorSpace colorSpace, bool nv12)
     160           0 :             : INHERITED(kPreservesOpaqueInput_OptimizationFlag)
     161             :             , fYTransform(resourceProvider, yuvMatrix[0], yProxy.get())
     162           0 :             , fYSampler(resourceProvider, std::move(yProxy))
     163           0 :             , fUTransform(resourceProvider, yuvMatrix[1], uProxy.get())
     164           0 :             , fUSampler(resourceProvider, std::move(uProxy), uvFilterMode)
     165             :             , fVSampler(resourceProvider, vProxy, uvFilterMode)
     166             :             , fColorSpace(colorSpace)
     167           0 :             , fNV12(nv12) {
     168           0 :         this->initClassID<YUVtoRGBEffect>();
     169           0 :         this->addCoordTransform(&fYTransform);
     170           0 :         this->addTextureSampler(&fYSampler);
     171           0 :         this->addCoordTransform(&fUTransform);
     172           0 :         this->addTextureSampler(&fUSampler);
     173           0 :         if (!fNV12) {
     174           0 :             fVTransform = GrCoordTransform(resourceProvider, yuvMatrix[2], vProxy.get());
     175           0 :             this->addCoordTransform(&fVTransform);
     176           0 :             this->addTextureSampler(&fVSampler);
     177             :         }
     178           0 :     }
     179             : 
     180           0 :     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
     181           0 :         return new GLSLProcessor;
     182             :     }
     183             : 
     184           0 :     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
     185           0 :         b->add32(fNV12);
     186           0 :     }
     187             : 
     188           0 :     bool onIsEqual(const GrFragmentProcessor& sBase) const override {
     189           0 :         const YUVtoRGBEffect& s = sBase.cast<YUVtoRGBEffect>();
     190           0 :         return (fColorSpace == s.getColorSpace()) && (fNV12 == s.isNV12());
     191             :     }
     192             : 
     193             :     GrCoordTransform fYTransform;
     194             :     TextureSampler   fYSampler;
     195             :     GrCoordTransform fUTransform;
     196             :     TextureSampler   fUSampler;
     197             :     GrCoordTransform fVTransform;
     198             :     TextureSampler   fVSampler;
     199             :     SkYUVColorSpace fColorSpace;
     200             :     bool fNV12;
     201             : 
     202             :     typedef GrFragmentProcessor INHERITED;
     203             : };
     204             : 
     205             : 
     206           0 : class RGBToYUVEffect : public GrFragmentProcessor {
     207             : public:
     208             :     enum OutputChannels {
     209             :         // output color r = y, g = u, b = v, a = a
     210             :         kYUV_OutputChannels,
     211             :         // output color rgba = y
     212             :         kY_OutputChannels,
     213             :         // output color r = u, g = v, b = 0, a = a
     214             :         kUV_OutputChannels,
     215             :         // output color rgba = u
     216             :         kU_OutputChannels,
     217             :         // output color rgba = v
     218             :         kV_OutputChannels
     219             :     };
     220             : 
     221           0 :     RGBToYUVEffect(sk_sp<GrFragmentProcessor> rgbFP, SkYUVColorSpace colorSpace,
     222             :                    OutputChannels output)
     223             :             // This could advertise kConstantOutputForConstantInput, but doesn't seem useful.
     224           0 :             : INHERITED(kPreservesOpaqueInput_OptimizationFlag)
     225             :             , fColorSpace(colorSpace)
     226           0 :             , fOutputChannels(output) {
     227           0 :         this->initClassID<RGBToYUVEffect>();
     228           0 :         this->registerChildProcessor(std::move(rgbFP));
     229           0 :     }
     230             : 
     231           0 :     const char* name() const override { return "RGBToYUV"; }
     232             : 
     233           0 :     SkYUVColorSpace getColorSpace() const { return fColorSpace; }
     234             : 
     235           0 :     OutputChannels outputChannels() const { return fOutputChannels; }
     236             : 
     237           0 :     class GLSLProcessor : public GrGLSLFragmentProcessor {
     238             :     public:
     239           0 :         GLSLProcessor() : fLastColorSpace(-1), fLastOutputChannels(-1) {}
     240             : 
     241           0 :         void emitCode(EmitArgs& args) override {
     242           0 :             GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     243           0 :             OutputChannels oc = args.fFp.cast<RGBToYUVEffect>().outputChannels();
     244             : 
     245           0 :             SkString outputColor("rgbColor");
     246           0 :             this->emitChild(0, args.fInputColor, &outputColor, args);
     247             : 
     248             :             const char* uniName;
     249           0 :             switch (oc) {
     250             :                 case kYUV_OutputChannels:
     251           0 :                     fRGBToYUVUni = args.fUniformHandler->addUniformArray(
     252             :                         kFragment_GrShaderFlag,
     253             :                         kVec4f_GrSLType, kDefault_GrSLPrecision,
     254           0 :                         "RGBToYUV", 3, &uniName);
     255           0 :                     fragBuilder->codeAppendf("%s = vec4(dot(rgbColor.rgb, %s[0].rgb) + %s[0].a,"
     256             :                                                        "dot(rgbColor.rgb, %s[1].rgb) + %s[1].a,"
     257             :                                                        "dot(rgbColor.rgb, %s[2].rgb) + %s[2].a,"
     258             :                                                        "rgbColor.a);",
     259             :                                              args.fOutputColor, uniName, uniName, uniName, uniName,
     260           0 :                                              uniName, uniName);
     261           0 :                     break;
     262             :                 case kUV_OutputChannels:
     263           0 :                     fRGBToYUVUni = args.fUniformHandler->addUniformArray(
     264             :                         kFragment_GrShaderFlag,
     265             :                         kVec4f_GrSLType, kDefault_GrSLPrecision,
     266           0 :                         "RGBToUV", 2, &uniName);
     267           0 :                     fragBuilder->codeAppendf("%s = vec4(dot(rgbColor.rgb, %s[0].rgb) + %s[0].a,"
     268             :                                                        "dot(rgbColor.rgb, %s[1].rgb) + %s[1].a,"
     269             :                                                        "0.0,"
     270             :                                                        "rgbColor.a);",
     271           0 :                                              args.fOutputColor, uniName, uniName, uniName, uniName);
     272           0 :                     break;
     273             :                 case kY_OutputChannels:
     274             :                 case kU_OutputChannels:
     275             :                 case kV_OutputChannels:
     276           0 :                     fRGBToYUVUni = args.fUniformHandler->addUniform(
     277             :                         kFragment_GrShaderFlag,
     278             :                         kVec4f_GrSLType, kDefault_GrSLPrecision,
     279           0 :                         "RGBToYUorV", &uniName);
     280           0 :                     fragBuilder->codeAppendf("%s = vec4(dot(rgbColor.rgb, %s.rgb) + %s.a);\n",
     281           0 :                                              args.fOutputColor, uniName, uniName);
     282           0 :                     break;
     283             :             }
     284           0 :         }
     285             : 
     286             :     private:
     287           0 :         void onSetData(const GrGLSLProgramDataManager& pdman,
     288             :                        const GrFragmentProcessor& processor) override {
     289           0 :             const RGBToYUVEffect& effect = processor.cast<RGBToYUVEffect>();
     290           0 :             OutputChannels oc = effect.outputChannels();
     291           0 :             if (effect.getColorSpace() != fLastColorSpace || oc != fLastOutputChannels) {
     292             : 
     293           0 :                 const float* matrix = nullptr;
     294           0 :                 switch (effect.getColorSpace()) {
     295             :                     case kJPEG_SkYUVColorSpace:
     296           0 :                         matrix = kJPEGInverseConversionMatrix;
     297           0 :                         break;
     298             :                     case kRec601_SkYUVColorSpace:
     299           0 :                         matrix = kRec601InverseConversionMatrix;
     300           0 :                         break;
     301             :                     case kRec709_SkYUVColorSpace:
     302           0 :                         matrix = kRec709InverseConversionMatrix;
     303           0 :                         break;
     304             :                 }
     305           0 :                 switch (oc) {
     306             :                     case kYUV_OutputChannels:
     307           0 :                         pdman.set4fv(fRGBToYUVUni, 3, matrix);
     308           0 :                         break;
     309             :                     case kUV_OutputChannels:
     310           0 :                         pdman.set4fv(fRGBToYUVUni, 2, matrix + 4);
     311           0 :                         break;
     312             :                     case kY_OutputChannels:
     313           0 :                         pdman.set4fv(fRGBToYUVUni, 1, matrix);
     314           0 :                         break;
     315             :                     case kU_OutputChannels:
     316           0 :                         pdman.set4fv(fRGBToYUVUni, 1, matrix + 4);
     317           0 :                         break;
     318             :                     case kV_OutputChannels:
     319           0 :                         pdman.set4fv(fRGBToYUVUni, 1, matrix + 8);
     320           0 :                         break;
     321             :                 }
     322           0 :                 fLastColorSpace = effect.getColorSpace();
     323             :             }
     324           0 :         }
     325             :         GrGLSLProgramDataManager::UniformHandle fRGBToYUVUni;
     326             :         int                                     fLastColorSpace;
     327             :         int                                     fLastOutputChannels;
     328             : 
     329             :         typedef GrGLSLFragmentProcessor INHERITED;
     330             :     };
     331             : 
     332             : private:
     333           0 :     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
     334           0 :         return new GLSLProcessor;
     335             :     }
     336             : 
     337           0 :     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
     338             :         // kY, kU, and kV all generate the same code, just upload different coefficients.
     339           0 :         if (kU_OutputChannels == fOutputChannels || kV_OutputChannels == fOutputChannels) {
     340           0 :             b->add32(kY_OutputChannels);
     341             :         } else {
     342           0 :             b->add32(fOutputChannels);
     343             :         }
     344           0 :     }
     345             : 
     346           0 :     bool onIsEqual(const GrFragmentProcessor& sBase) const override {
     347           0 :         const RGBToYUVEffect& s = sBase.cast<RGBToYUVEffect>();
     348           0 :         return fColorSpace == s.getColorSpace() && fOutputChannels == s.outputChannels();
     349             :     }
     350             : 
     351             :     GrCoordTransform    fTransform;
     352             :     TextureSampler      fTextureSampler;
     353             :     SkYUVColorSpace     fColorSpace;
     354             :     OutputChannels      fOutputChannels;
     355             : 
     356             :     typedef GrFragmentProcessor INHERITED;
     357             : };
     358             : 
     359             : }
     360             : 
     361             : //////////////////////////////////////////////////////////////////////////////
     362             : 
     363           0 : sk_sp<GrFragmentProcessor> GrYUVEffect::MakeYUVToRGB(GrResourceProvider* resourceProvider,
     364             :                                                      sk_sp<GrTextureProxy> yProxy,
     365             :                                                      sk_sp<GrTextureProxy> uProxy,
     366             :                                                      sk_sp<GrTextureProxy> vProxy,
     367             :                                                      const SkISize sizes[3],
     368             :                                                      SkYUVColorSpace colorSpace, bool nv12) {
     369           0 :     SkASSERT(yProxy && uProxy && vProxy && sizes);
     370             :     return YUVtoRGBEffect::Make(resourceProvider,
     371           0 :                                 std::move(yProxy), std::move(uProxy), std::move(vProxy),
     372           0 :                                 sizes, colorSpace, nv12);
     373             : }
     374             : 
     375             : sk_sp<GrFragmentProcessor>
     376           0 : GrYUVEffect::MakeRGBToYUV(sk_sp<GrFragmentProcessor> rgbFP, SkYUVColorSpace colorSpace) {
     377           0 :     SkASSERT(rgbFP);
     378             :     return sk_sp<GrFragmentProcessor>(
     379           0 :         new RGBToYUVEffect(std::move(rgbFP), colorSpace, RGBToYUVEffect::kYUV_OutputChannels));
     380             : }
     381             : 
     382             : sk_sp<GrFragmentProcessor>
     383           0 : GrYUVEffect::MakeRGBToY(sk_sp<GrFragmentProcessor> rgbFP, SkYUVColorSpace colorSpace) {
     384           0 :     SkASSERT(rgbFP);
     385             :     return sk_sp<GrFragmentProcessor>(
     386           0 :         new RGBToYUVEffect(std::move(rgbFP), colorSpace, RGBToYUVEffect::kY_OutputChannels));
     387             : }
     388             : 
     389             : sk_sp<GrFragmentProcessor>
     390           0 : GrYUVEffect::MakeRGBToUV(sk_sp<GrFragmentProcessor> rgbFP, SkYUVColorSpace colorSpace) {
     391           0 :     SkASSERT(rgbFP);
     392             :     return sk_sp<GrFragmentProcessor>(
     393           0 :         new RGBToYUVEffect(std::move(rgbFP), colorSpace, RGBToYUVEffect::kUV_OutputChannels));
     394             : }
     395             : 
     396             : sk_sp<GrFragmentProcessor>
     397           0 : GrYUVEffect::MakeRGBToU(sk_sp<GrFragmentProcessor> rgbFP, SkYUVColorSpace colorSpace) {
     398           0 :     SkASSERT(rgbFP);
     399             :     return sk_sp<GrFragmentProcessor>(
     400           0 :         new RGBToYUVEffect(std::move(rgbFP), colorSpace, RGBToYUVEffect::kU_OutputChannels));
     401             : }
     402             : 
     403             : sk_sp<GrFragmentProcessor>
     404           0 : GrYUVEffect::MakeRGBToV(sk_sp<GrFragmentProcessor> rgbFP, SkYUVColorSpace colorSpace) {
     405           0 :     SkASSERT(rgbFP);
     406             :     return sk_sp<GrFragmentProcessor>(
     407           0 :         new RGBToYUVEffect(std::move(rgbFP), colorSpace, RGBToYUVEffect::kV_OutputChannels));
     408             : }

Generated by: LCOV version 1.13