Add computation of requestedFeatures to GrProgramInfo and use it

This is a deferred TODO/code review request. In general, this improves the encapsulation of program information w/in GrProgramInfo. Additionally, it is desirable to stop using the Desc/Key to access this information.

Bug: skia:9455
Change-Id: I854ff3225a49657d3a523e88e4bfa549128ee486
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/247336
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrProgramDesc.cpp b/src/gpu/GrProgramDesc.cpp
index c416e23..af81577 100644
--- a/src/gpu/GrProgramDesc.cpp
+++ b/src/gpu/GrProgramDesc.cpp
@@ -212,16 +212,12 @@
         return false;
     }
 
-    // TODO: use programInfo.requestedFeatures here
-    GrProcessor::CustomFeatures processorFeatures = programInfo.primProc().requestedFeatures();
-
     for (int i = 0; i < programInfo.pipeline().numFragmentProcessors(); ++i) {
         const GrFragmentProcessor& fp = programInfo.pipeline().getFragmentProcessor(i);
         if (!gen_frag_proc_and_meta_keys(programInfo.primProc(), fp, gpu, shaderCaps, &b)) {
             desc->key().reset();
             return false;
         }
-        processorFeatures |= fp.requestedFeatures();
     }
 
     const GrXferProcessor& xp = programInfo.pipeline().getXferProcessor();
@@ -236,9 +232,8 @@
         desc->key().reset();
         return false;
     }
-    processorFeatures |= xp.requestedFeatures();
 
-    if (processorFeatures & GrProcessor::CustomFeatures::kSampleLocations) {
+    if (programInfo.requestedFeatures() & GrProcessor::CustomFeatures::kSampleLocations) {
         SkASSERT(programInfo.pipeline().isHWAntialiasState());
         b.add32(renderTarget->renderTargetPriv().getSamplePatternKey());
     }
@@ -262,9 +257,10 @@
     // If we knew the shader won't depend on origin, we could skip this (and use the same program
     // for both origins). Instrumenting all fragment processors would be difficult and error prone.
     header->fSurfaceOriginKey =
-        GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(programInfo.origin());
-    header->fProcessorFeatures = (uint8_t)processorFeatures;
-    SkASSERT(header->processorFeatures() == processorFeatures);  // Ensure enough bits.
+                    GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(programInfo.origin());
+    header->fProcessorFeatures = (uint8_t)programInfo.requestedFeatures();
+    // Ensure enough bits.
+    SkASSERT(header->fProcessorFeatures == (int) programInfo.requestedFeatures());
     header->fSnapVerticesToPixelCenters = programInfo.pipeline().snapVerticesToPixelCenters();
     header->fHasPointSize = hasPointSize ? 1 : 0;
     return true;
diff --git a/src/gpu/GrProgramDesc.h b/src/gpu/GrProgramDesc.h
index 275b868..f504393 100644
--- a/src/gpu/GrProgramDesc.h
+++ b/src/gpu/GrProgramDesc.h
@@ -86,12 +86,6 @@
     }
 
     struct KeyHeader {
-        SkDEBUGCODE(bool hasSurfaceOriginKey() const { return SkToBool(fSurfaceOriginKey); })
-
-        GrProcessor::CustomFeatures processorFeatures() const {
-            return (GrProcessor::CustomFeatures)fProcessorFeatures;
-        }
-
         // Set to uniquely idenitify any swizzling of the shader's output color(s).
         uint16_t fOutputSwizzle;
         uint8_t fColorFragmentProcessorCnt; // Can be packed into 4 bits if required.
diff --git a/src/gpu/GrProgramInfo.h b/src/gpu/GrProgramInfo.h
index fd2672f..63f5e1a 100644
--- a/src/gpu/GrProgramInfo.h
+++ b/src/gpu/GrProgramInfo.h
@@ -29,9 +29,16 @@
             , fPrimProc(primProc)
             , fFixedDynamicState(fixedDynamicState)
             , fDynamicStateArrays(dynamicStateArrays) {
+        fRequestedFeatures = fPrimProc.requestedFeatures();
+        for (int i = 0; i < fPipeline.numFragmentProcessors(); ++i) {
+            fRequestedFeatures |= fPipeline.getFragmentProcessor(i).requestedFeatures();
+        }
+        fRequestedFeatures |= fPipeline.getXferProcessor().requestedFeatures();
         SkDEBUGCODE(this->validate();)
     }
 
+    GrProcessor::CustomFeatures requestedFeatures() const { return fRequestedFeatures; }
+
     int numSamples() const { return fNumSamples;  }
     GrSurfaceOrigin origin() const { return fOrigin;  }
     const GrPipeline& pipeline() const { return fPipeline; }
@@ -101,16 +108,6 @@
         return fPrimProc.isPathRendering() && !fPrimProc.willUseGeoShader() &&
                !fPrimProc.numVertexAttributes() && !fPrimProc.numInstanceAttributes();
     }
-
-    // TODO: calculate this once in the ctor and use more widely
-    GrProcessor::CustomFeatures requestedFeatures() const {
-        GrProcessor::CustomFeatures requestedFeatures = fPrimProc.requestedFeatures();
-        for (int i = 0; i < fPipeline.numFragmentProcessors(); ++i) {
-            requestedFeatures |= fPipeline.getFragmentProcessor(i).requestedFeatures();
-        }
-        requestedFeatures |= fPipeline.getXferProcessor().requestedFeatures();
-        return requestedFeatures;
-    }
 #endif
 
 private:
@@ -120,6 +117,7 @@
     const GrPrimitiveProcessor&           fPrimProc;
     const GrPipeline::FixedDynamicState*  fFixedDynamicState;
     const GrPipeline::DynamicStateArrays* fDynamicStateArrays;
+    GrProcessor::CustomFeatures           fRequestedFeatures;
 };
 
 #endif
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
index 343cd4c..85dc827 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
@@ -85,7 +85,7 @@
 }
 
 const char* GrGLSLFragmentShaderBuilder::sampleOffsets() {
-    SkASSERT(CustomFeatures::kSampleLocations & fProgramBuilder->header().processorFeatures());
+    SkASSERT(CustomFeatures::kSampleLocations & fProgramBuilder->processorFeatures());
     SkDEBUGCODE(fUsedProcessorFeaturesThisStage_DebugOnly |= CustomFeatures::kSampleLocations);
     SkDEBUGCODE(fUsedProcessorFeaturesAllStages_DebugOnly |= CustomFeatures::kSampleLocations);
     return "_sampleOffsets";
@@ -118,7 +118,7 @@
 
 void GrGLSLFragmentShaderBuilder::applyFnToMultisampleMask(
         const char* fn, const char* grad, ScopeFlags scopeFlags) {
-    SkASSERT(CustomFeatures::kSampleLocations & fProgramBuilder->header().processorFeatures());
+    SkASSERT(CustomFeatures::kSampleLocations & fProgramBuilder->processorFeatures());
     SkDEBUGCODE(fUsedProcessorFeaturesThisStage_DebugOnly |= CustomFeatures::kSampleLocations);
     SkDEBUGCODE(fUsedProcessorFeaturesAllStages_DebugOnly |= CustomFeatures::kSampleLocations);
 
@@ -283,18 +283,13 @@
 }
 
 GrSurfaceOrigin GrGLSLFragmentShaderBuilder::getSurfaceOrigin() const {
-    SkASSERT(fProgramBuilder->header().hasSurfaceOriginKey());
-    return static_cast<GrSurfaceOrigin>(fProgramBuilder->header().fSurfaceOriginKey-1);
-
-    GR_STATIC_ASSERT(0 == kTopLeft_GrSurfaceOrigin);
-    GR_STATIC_ASSERT(1 == kBottomLeft_GrSurfaceOrigin);
+    return fProgramBuilder->origin();
 }
 
 void GrGLSLFragmentShaderBuilder::onFinalize() {
-    SkASSERT(fProgramBuilder->header().processorFeatures()
-                     == fUsedProcessorFeaturesAllStages_DebugOnly);
+    SkASSERT(fProgramBuilder->processorFeatures() == fUsedProcessorFeaturesAllStages_DebugOnly);
 
-    if (CustomFeatures::kSampleLocations & fProgramBuilder->header().processorFeatures()) {
+    if (CustomFeatures::kSampleLocations & fProgramBuilder->processorFeatures()) {
         const SkTArray<SkPoint>& sampleLocations = fProgramBuilder->getSampleLocations();
         this->definitions().append("const float2 _sampleOffsets[] = float2[](");
         for (int i = 0; i < sampleLocations.count(); ++i) {
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.h b/src/gpu/glsl/GrGLSLProgramBuilder.h
index b9bc61b..a710f0a 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.h
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.h
@@ -42,10 +42,13 @@
     const GrPipeline& pipeline() const { return fProgramInfo.pipeline(); }
     const GrPrimitiveProcessor& primitiveProcessor() const { return fProgramInfo.primProc(); }
     const GrTextureProxy* const* primProcProxies() const { return fProgramInfo.primProcProxies(); }
+    GrProcessor::CustomFeatures processorFeatures() const {
+        return fProgramInfo.requestedFeatures();
+    }
 
     // TODO: stop passing in the renderTarget for just the sampleLocations
     int effectiveSampleCnt() const {
-        SkASSERT(GrProcessor::CustomFeatures::kSampleLocations & header().processorFeatures());
+        SkASSERT(GrProcessor::CustomFeatures::kSampleLocations & fProgramInfo.requestedFeatures());
         return fRenderTarget->renderTargetPriv().getSampleLocations().count();
     }
     const SkTArray<SkPoint>& getSampleLocations() const {