LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu/glsl - GrGLSLFragmentShaderBuilder.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 171 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 24 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 "GrGLSLFragmentShaderBuilder.h"
       9             : #include "GrRenderTarget.h"
      10             : #include "GrRenderTargetPriv.h"
      11             : #include "GrShaderCaps.h"
      12             : #include "gl/GrGLGpu.h"
      13             : #include "glsl/GrGLSLProgramBuilder.h"
      14             : #include "glsl/GrGLSLUniformHandler.h"
      15             : #include "glsl/GrGLSLVarying.h"
      16             : #include "../private/GrGLSL.h"
      17             : 
      18             : const char* GrGLSLFragmentShaderBuilder::kDstColorName = "_dstColor";
      19             : 
      20           0 : static const char* sample_offset_array_name(GrGLSLFPFragmentBuilder::Coordinates coords) {
      21             :     static const char* kArrayNames[] = {
      22             :         "deviceSpaceSampleOffsets",
      23             :         "windowSpaceSampleOffsets"
      24             :     };
      25           0 :     return kArrayNames[coords];
      26             : 
      27             :     GR_STATIC_ASSERT(0 == GrGLSLFPFragmentBuilder::kSkiaDevice_Coordinates);
      28             :     GR_STATIC_ASSERT(1 == GrGLSLFPFragmentBuilder::kGLSLWindow_Coordinates);
      29             :     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kArrayNames) == GrGLSLFPFragmentBuilder::kLast_Coordinates + 1);
      30             : }
      31             : 
      32           0 : static const char* specific_layout_qualifier_name(GrBlendEquation equation) {
      33           0 :     SkASSERT(GrBlendEquationIsAdvanced(equation));
      34             : 
      35             :     static const char* kLayoutQualifierNames[] = {
      36             :         "blend_support_screen",
      37             :         "blend_support_overlay",
      38             :         "blend_support_darken",
      39             :         "blend_support_lighten",
      40             :         "blend_support_colordodge",
      41             :         "blend_support_colorburn",
      42             :         "blend_support_hardlight",
      43             :         "blend_support_softlight",
      44             :         "blend_support_difference",
      45             :         "blend_support_exclusion",
      46             :         "blend_support_multiply",
      47             :         "blend_support_hsl_hue",
      48             :         "blend_support_hsl_saturation",
      49             :         "blend_support_hsl_color",
      50             :         "blend_support_hsl_luminosity"
      51             :     };
      52           0 :     return kLayoutQualifierNames[equation - kFirstAdvancedGrBlendEquation];
      53             : 
      54             :     GR_STATIC_ASSERT(0 == kScreen_GrBlendEquation - kFirstAdvancedGrBlendEquation);
      55             :     GR_STATIC_ASSERT(1 == kOverlay_GrBlendEquation - kFirstAdvancedGrBlendEquation);
      56             :     GR_STATIC_ASSERT(2 == kDarken_GrBlendEquation - kFirstAdvancedGrBlendEquation);
      57             :     GR_STATIC_ASSERT(3 == kLighten_GrBlendEquation - kFirstAdvancedGrBlendEquation);
      58             :     GR_STATIC_ASSERT(4 == kColorDodge_GrBlendEquation - kFirstAdvancedGrBlendEquation);
      59             :     GR_STATIC_ASSERT(5 == kColorBurn_GrBlendEquation - kFirstAdvancedGrBlendEquation);
      60             :     GR_STATIC_ASSERT(6 == kHardLight_GrBlendEquation - kFirstAdvancedGrBlendEquation);
      61             :     GR_STATIC_ASSERT(7 == kSoftLight_GrBlendEquation - kFirstAdvancedGrBlendEquation);
      62             :     GR_STATIC_ASSERT(8 == kDifference_GrBlendEquation - kFirstAdvancedGrBlendEquation);
      63             :     GR_STATIC_ASSERT(9 == kExclusion_GrBlendEquation - kFirstAdvancedGrBlendEquation);
      64             :     GR_STATIC_ASSERT(10 == kMultiply_GrBlendEquation - kFirstAdvancedGrBlendEquation);
      65             :     GR_STATIC_ASSERT(11 == kHSLHue_GrBlendEquation - kFirstAdvancedGrBlendEquation);
      66             :     GR_STATIC_ASSERT(12 == kHSLSaturation_GrBlendEquation - kFirstAdvancedGrBlendEquation);
      67             :     GR_STATIC_ASSERT(13 == kHSLColor_GrBlendEquation - kFirstAdvancedGrBlendEquation);
      68             :     GR_STATIC_ASSERT(14 == kHSLLuminosity_GrBlendEquation - kFirstAdvancedGrBlendEquation);
      69             :     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kLayoutQualifierNames) ==
      70             :                      kGrBlendEquationCnt - kFirstAdvancedGrBlendEquation);
      71             : }
      72             : 
      73           0 : uint8_t GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(GrSurfaceOrigin origin) {
      74           0 :     SkASSERT(kTopLeft_GrSurfaceOrigin == origin || kBottomLeft_GrSurfaceOrigin == origin);
      75           0 :     return origin;
      76             : 
      77             :     GR_STATIC_ASSERT(1 == kTopLeft_GrSurfaceOrigin);
      78             :     GR_STATIC_ASSERT(2 == kBottomLeft_GrSurfaceOrigin);
      79             : }
      80             : 
      81           0 : GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program)
      82             :     : GrGLSLFragmentBuilder(program)
      83             :     , fSetupFragPosition(false)
      84             :     , fHasCustomColorOutput(false)
      85             :     , fCustomColorOutputIndex(-1)
      86             :     , fHasSecondaryOutput(false)
      87             :     , fUsedSampleOffsetArrays(0)
      88             :     , fHasInitializedSampleMask(false)
      89           0 :     , fDefaultPrecision(kMedium_GrSLPrecision) {
      90           0 :     fSubstageIndices.push_back(0);
      91             : #ifdef SK_DEBUG
      92           0 :     fUsedProcessorFeatures = GrProcessor::kNone_RequiredFeatures;
      93           0 :     fHasReadDstColor = false;
      94             : #endif
      95           0 : }
      96             : 
      97           0 : bool GrGLSLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
      98           0 :     const GrShaderCaps& shaderCaps = *fProgramBuilder->shaderCaps();
      99           0 :     switch (feature) {
     100             :         case kMultisampleInterpolation_GLSLFeature:
     101           0 :             if (!shaderCaps.multisampleInterpolationSupport()) {
     102           0 :                 return false;
     103             :             }
     104           0 :             if (const char* extension = shaderCaps.multisampleInterpolationExtensionString()) {
     105           0 :                 this->addFeature(1 << kMultisampleInterpolation_GLSLFeature, extension);
     106             :             }
     107           0 :             return true;
     108             :         default:
     109           0 :             SkFAIL("Unexpected GLSLFeature requested.");
     110           0 :             return false;
     111             :     }
     112             : }
     113             : 
     114           0 : SkString GrGLSLFragmentShaderBuilder::ensureCoords2D(const GrShaderVar& coords) {
     115           0 :     if (kVec3f_GrSLType != coords.getType()) {
     116           0 :         SkASSERT(kVec2f_GrSLType == coords.getType());
     117           0 :         return coords.getName();
     118             :     }
     119             : 
     120           0 :     SkString coords2D;
     121           0 :     coords2D.printf("%s_ensure2D", coords.c_str());
     122           0 :     this->codeAppendf("\tvec2 %s = %s.xy / %s.z;", coords2D.c_str(), coords.c_str(),
     123           0 :                       coords.c_str());
     124           0 :     return coords2D;
     125             : }
     126             : 
     127           0 : const char* GrGLSLFragmentShaderBuilder::distanceVectorName() const {
     128           0 :     return "fsDistanceVector";
     129             : }
     130             : 
     131           0 : void GrGLSLFragmentShaderBuilder::appendOffsetToSample(const char* sampleIdx, Coordinates coords) {
     132           0 :     SkASSERT(fProgramBuilder->header().fSamplePatternKey);
     133           0 :     SkDEBUGCODE(fUsedProcessorFeatures |= GrProcessor::kSampleLocations_RequiredFeature);
     134           0 :     if (kTopLeft_GrSurfaceOrigin == this->getSurfaceOrigin()) {
     135             :         // With a top left origin, device and window space are equal, so we only use device coords.
     136           0 :         coords = kSkiaDevice_Coordinates;
     137             :     }
     138           0 :     this->codeAppendf("%s[%s]", sample_offset_array_name(coords), sampleIdx);
     139           0 :     fUsedSampleOffsetArrays |= (1 << coords);
     140           0 : }
     141             : 
     142           0 : void GrGLSLFragmentShaderBuilder::maskSampleCoverage(const char* mask, bool invert) {
     143           0 :     const GrShaderCaps& shaderCaps = *fProgramBuilder->shaderCaps();
     144           0 :     if (!shaderCaps.sampleVariablesSupport()) {
     145           0 :         SkDEBUGFAIL("Attempted to mask sample coverage without support.");
     146           0 :         return;
     147             :     }
     148           0 :     if (const char* extension = shaderCaps.sampleVariablesExtensionString()) {
     149           0 :         this->addFeature(1 << kSampleVariables_GLSLPrivateFeature, extension);
     150             :     }
     151           0 :     if (!fHasInitializedSampleMask) {
     152           0 :         this->codePrependf("gl_SampleMask[0] = -1;");
     153           0 :         fHasInitializedSampleMask = true;
     154             :     }
     155           0 :     if (invert) {
     156           0 :         this->codeAppendf("gl_SampleMask[0] &= ~(%s);", mask);
     157             :     } else {
     158           0 :         this->codeAppendf("gl_SampleMask[0] &= %s;", mask);
     159             :     }
     160             : }
     161             : 
     162           0 : void GrGLSLFragmentShaderBuilder::overrideSampleCoverage(const char* mask) {
     163           0 :     const GrShaderCaps& shaderCaps = *fProgramBuilder->shaderCaps();
     164           0 :     if (!shaderCaps.sampleMaskOverrideCoverageSupport()) {
     165           0 :         SkDEBUGFAIL("Attempted to override sample coverage without support.");
     166           0 :         return;
     167             :     }
     168           0 :     SkASSERT(shaderCaps.sampleVariablesSupport());
     169           0 :     if (const char* extension = shaderCaps.sampleVariablesExtensionString()) {
     170           0 :         this->addFeature(1 << kSampleVariables_GLSLPrivateFeature, extension);
     171             :     }
     172           0 :     if (this->addFeature(1 << kSampleMaskOverrideCoverage_GLSLPrivateFeature,
     173             :                          "GL_NV_sample_mask_override_coverage")) {
     174             :         // Redeclare gl_SampleMask with layout(override_coverage) if we haven't already.
     175           0 :         fOutputs.push_back().set(kInt_GrSLType, "gl_SampleMask", 1, GrShaderVar::kOut_TypeModifier,
     176           0 :                                  kHigh_GrSLPrecision, "override_coverage");
     177             :     }
     178           0 :     this->codeAppendf("gl_SampleMask[0] = %s;", mask);
     179           0 :     fHasInitializedSampleMask = true;
     180             : }
     181             : 
     182           0 : void GrGLSLFragmentShaderBuilder::elevateDefaultPrecision(GrSLPrecision precision) {
     183           0 :     fDefaultPrecision = SkTMax(fDefaultPrecision, precision);
     184           0 : }
     185             : 
     186           0 : const char* GrGLSLFragmentShaderBuilder::dstColor() {
     187           0 :     SkDEBUGCODE(fHasReadDstColor = true;)
     188             : 
     189           0 :     const char* override = fProgramBuilder->primitiveProcessor().getDestColorOverride();
     190           0 :     if (override != nullptr) {
     191           0 :         return override;
     192             :     }
     193             : 
     194           0 :     const GrShaderCaps* shaderCaps = fProgramBuilder->shaderCaps();
     195           0 :     if (shaderCaps->fbFetchSupport()) {
     196           0 :         this->addFeature(1 << kFramebufferFetch_GLSLPrivateFeature,
     197           0 :                          shaderCaps->fbFetchExtensionString());
     198             : 
     199             :         // Some versions of this extension string require declaring custom color output on ES 3.0+
     200           0 :         const char* fbFetchColorName = shaderCaps->fbFetchColorName();
     201           0 :         if (shaderCaps->fbFetchNeedsCustomOutput()) {
     202           0 :             this->enableCustomOutput();
     203           0 :             fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOut_TypeModifier);
     204           0 :             fbFetchColorName = DeclaredColorOutputName();
     205             :             // Set the dstColor to an intermediate variable so we don't override it with the output
     206           0 :             this->codeAppendf("vec4 %s = %s;", kDstColorName, fbFetchColorName);
     207             :         } else {
     208           0 :             return fbFetchColorName;
     209             :         }
     210             :     }
     211           0 :     return kDstColorName;
     212             : }
     213             : 
     214           0 : void GrGLSLFragmentShaderBuilder::enableAdvancedBlendEquationIfNeeded(GrBlendEquation equation) {
     215           0 :     SkASSERT(GrBlendEquationIsAdvanced(equation));
     216             : 
     217           0 :     const GrShaderCaps& caps = *fProgramBuilder->shaderCaps();
     218           0 :     if (!caps.mustEnableAdvBlendEqs()) {
     219           0 :         return;
     220             :     }
     221             : 
     222           0 :     this->addFeature(1 << kBlendEquationAdvanced_GLSLPrivateFeature,
     223           0 :                      "GL_KHR_blend_equation_advanced");
     224           0 :     if (caps.mustEnableSpecificAdvBlendEqs()) {
     225           0 :         this->addLayoutQualifier(specific_layout_qualifier_name(equation), kOut_InterfaceQualifier);
     226             :     } else {
     227           0 :         this->addLayoutQualifier("blend_support_all_equations", kOut_InterfaceQualifier);
     228             :     }
     229             : }
     230             : 
     231           0 : void GrGLSLFragmentShaderBuilder::enableCustomOutput() {
     232           0 :     if (!fHasCustomColorOutput) {
     233           0 :         fHasCustomColorOutput = true;
     234           0 :         fCustomColorOutputIndex = fOutputs.count();
     235           0 :         fOutputs.push_back().set(kVec4f_GrSLType, DeclaredColorOutputName(),
     236           0 :                                  GrShaderVar::kOut_TypeModifier);
     237           0 :         fProgramBuilder->finalizeFragmentOutputColor(fOutputs.back()); 
     238             :     }
     239           0 : }
     240             : 
     241           0 : void GrGLSLFragmentShaderBuilder::enableSecondaryOutput() {
     242           0 :     SkASSERT(!fHasSecondaryOutput);
     243           0 :     fHasSecondaryOutput = true;
     244           0 :     const GrShaderCaps& caps = *fProgramBuilder->shaderCaps();
     245           0 :     if (const char* extension = caps.secondaryOutputExtensionString()) {
     246           0 :         this->addFeature(1 << kBlendFuncExtended_GLSLPrivateFeature, extension);
     247             :     }
     248             : 
     249             :     // If the primary output is declared, we must declare also the secondary output
     250             :     // and vice versa, since it is not allowed to use a built-in gl_FragColor and a custom
     251             :     // output. The condition also co-incides with the condition in whici GLES SL 2.0
     252             :     // requires the built-in gl_SecondaryFragColorEXT, where as 3.0 requires a custom output.
     253           0 :     if (caps.mustDeclareFragmentShaderOutput()) {
     254           0 :         fOutputs.push_back().set(kVec4f_GrSLType, DeclaredSecondaryColorOutputName(),
     255           0 :                                  GrShaderVar::kOut_TypeModifier);
     256           0 :         fProgramBuilder->finalizeFragmentSecondaryColor(fOutputs.back());
     257             :     }
     258           0 : }
     259             : 
     260           0 : const char* GrGLSLFragmentShaderBuilder::getPrimaryColorOutputName() const {
     261           0 :     return fHasCustomColorOutput ? DeclaredColorOutputName() : "sk_FragColor";
     262             : }
     263             : 
     264           0 : void GrGLSLFragmentBuilder::declAppendf(const char* fmt, ...) {
     265             :     va_list argp;
     266           0 :     va_start(argp, fmt);
     267           0 :     inputs().appendVAList(fmt, argp);
     268           0 :     va_end(argp);
     269           0 : }
     270             : 
     271           0 : const char* GrGLSLFragmentShaderBuilder::getSecondaryColorOutputName() const {
     272           0 :     const GrShaderCaps& caps = *fProgramBuilder->shaderCaps();
     273           0 :     return caps.mustDeclareFragmentShaderOutput() ? DeclaredSecondaryColorOutputName()
     274           0 :                                                   : "gl_SecondaryFragColorEXT";
     275             : }
     276             : 
     277           0 : GrSurfaceOrigin GrGLSLFragmentShaderBuilder::getSurfaceOrigin() const {
     278           0 :     SkASSERT(fProgramBuilder->header().fSurfaceOriginKey);
     279           0 :     return static_cast<GrSurfaceOrigin>(fProgramBuilder->header().fSurfaceOriginKey);
     280             : 
     281             :     GR_STATIC_ASSERT(1 == kTopLeft_GrSurfaceOrigin);
     282             :     GR_STATIC_ASSERT(2 == kBottomLeft_GrSurfaceOrigin);
     283             : }
     284             : 
     285           0 : void GrGLSLFragmentShaderBuilder::onFinalize() {
     286           0 :     fProgramBuilder->varyingHandler()->getFragDecls(&this->inputs(), &this->outputs());
     287           0 :     GrGLSLAppendDefaultFloatPrecisionDeclaration(fDefaultPrecision,
     288           0 :                                                  *fProgramBuilder->shaderCaps(),
     289           0 :                                                  &this->precisionQualifier());
     290           0 :     if (fUsedSampleOffsetArrays & (1 << kSkiaDevice_Coordinates)) {
     291           0 :         this->defineSampleOffsetArray(sample_offset_array_name(kSkiaDevice_Coordinates),
     292           0 :                                       SkMatrix::MakeTrans(-0.5f, -0.5f));
     293             :     }
     294           0 :     if (fUsedSampleOffsetArrays & (1 << kGLSLWindow_Coordinates)) {
     295             :         // With a top left origin, device and window space are equal, so we only use device coords.
     296           0 :         SkASSERT(kBottomLeft_GrSurfaceOrigin == this->getSurfaceOrigin());
     297             :         SkMatrix m;
     298           0 :         m.setScale(1, -1);
     299           0 :         m.preTranslate(-0.5f, -0.5f);
     300           0 :         this->defineSampleOffsetArray(sample_offset_array_name(kGLSLWindow_Coordinates), m);
     301             :     }
     302           0 : }
     303             : 
     304           0 : void GrGLSLFragmentShaderBuilder::defineSampleOffsetArray(const char* name, const SkMatrix& m) {
     305           0 :     SkASSERT(fProgramBuilder->caps()->sampleLocationsSupport());
     306           0 :     const GrPipeline& pipeline = fProgramBuilder->pipeline();
     307           0 :     const GrRenderTargetPriv& rtp = pipeline.getRenderTarget()->renderTargetPriv();
     308           0 :     const GrGpu::MultisampleSpecs& specs = rtp.getMultisampleSpecs(pipeline);
     309           0 :     SkSTArray<16, SkPoint, true> offsets;
     310           0 :     offsets.push_back_n(specs.fEffectiveSampleCnt);
     311           0 :     m.mapPoints(offsets.begin(), specs.fSampleLocations, specs.fEffectiveSampleCnt);
     312           0 :     this->definitions().appendf("const highp vec2 %s[] = vec2[](", name);
     313           0 :     for (int i = 0; i < specs.fEffectiveSampleCnt; ++i) {
     314           0 :         this->definitions().appendf("vec2(%f, %f)", offsets[i].x(), offsets[i].y());
     315           0 :         this->definitions().append(i + 1 != specs.fEffectiveSampleCnt ? ", " : ");\n");
     316             :     }
     317           0 : }
     318             : 
     319           0 : void GrGLSLFragmentShaderBuilder::onBeforeChildProcEmitCode() {
     320           0 :     SkASSERT(fSubstageIndices.count() >= 1);
     321           0 :     fSubstageIndices.push_back(0);
     322             :     // second-to-last value in the fSubstageIndices stack is the index of the child proc
     323             :     // at that level which is currently emitting code.
     324           0 :     fMangleString.appendf("_c%d", fSubstageIndices[fSubstageIndices.count() - 2]);
     325           0 : }
     326             : 
     327           0 : void GrGLSLFragmentShaderBuilder::onAfterChildProcEmitCode() {
     328           0 :     SkASSERT(fSubstageIndices.count() >= 2);
     329           0 :     fSubstageIndices.pop_back();
     330           0 :     fSubstageIndices.back()++;
     331           0 :     int removeAt = fMangleString.findLastOf('_');
     332           0 :     fMangleString.remove(removeAt, fMangleString.size() - removeAt);
     333           0 : }

Generated by: LCOV version 1.13