Add a mustWriteToFragColor() workaround flag

Bug: skia:
Change-Id: Ifeff01125ebe5418d4632ffe2422140944e44469
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/206351
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/GrShaderCaps.cpp b/src/gpu/GrShaderCaps.cpp
index bd1f667..56dbc23 100644
--- a/src/gpu/GrShaderCaps.cpp
+++ b/src/gpu/GrShaderCaps.cpp
@@ -43,6 +43,7 @@
     fEmulateAbsIntFunction = false;
     fRewriteDoWhileLoops = false;
     fRemovePowWithConstantExponent = false;
+    fMustWriteToFragColor = false;
     fFlatInterpolationSupport = false;
     fPreferFlatInterpolation = false;
     fNoPerspectiveInterpolationSupport = false;
@@ -117,6 +118,7 @@
     writer->appendBool("Emulate abs(int) function", fEmulateAbsIntFunction);
     writer->appendBool("Rewrite do while loops", fRewriteDoWhileLoops);
     writer->appendBool("Rewrite pow with constant exponent", fRemovePowWithConstantExponent);
+    writer->appendBool("Must write to sk_FragColor [workaround]", fMustWriteToFragColor);
     writer->appendBool("Flat interpolation support", fFlatInterpolationSupport);
     writer->appendBool("Prefer flat interpolation", fPreferFlatInterpolation);
     writer->appendBool("No perspective interpolation support", fNoPerspectiveInterpolationSupport);
@@ -157,6 +159,7 @@
         SkASSERT(!fEmulateAbsIntFunction);
         SkASSERT(!fRewriteDoWhileLoops);
         SkASSERT(!fRemovePowWithConstantExponent);
+        SkASSERT(!fMustWriteToFragColor);
     }
 #if GR_TEST_UTILS
     fDualSourceBlendingSupport = fDualSourceBlendingSupport && !options.fSuppressDualSourceBlending;
diff --git a/src/gpu/GrShaderCaps.h b/src/gpu/GrShaderCaps.h
index 3ebb92a..bbac42d 100644
--- a/src/gpu/GrShaderCaps.h
+++ b/src/gpu/GrShaderCaps.h
@@ -154,6 +154,10 @@
         return fMustGuardDivisionEvenAfterExplicitZeroCheck;
     }
 
+    // On Nexus 6, the GL context can get lost if a shader does not write a value to gl_FragColor.
+    // https://bugs.chromium.org/p/chromium/issues/detail?id=445377
+    bool mustWriteToFragColor() const { return fMustWriteToFragColor; }
+
     // Returns the string of an extension that must be enabled in the shader to support
     // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling
     // this function, the caller should check that shaderDerivativeSupport exists.
@@ -288,6 +292,7 @@
     bool fEmulateAbsIntFunction                       : 1;
     bool fRewriteDoWhileLoops                         : 1;
     bool fRemovePowWithConstantExponent               : 1;
+    bool fMustWriteToFragColor                        : 1;
 
     const char* fVersionDeclString;
 
diff --git a/src/gpu/effects/GrDisableColorXP.cpp b/src/gpu/effects/GrDisableColorXP.cpp
index 2ff36c4..7fba0b7 100644
--- a/src/gpu/effects/GrDisableColorXP.cpp
+++ b/src/gpu/effects/GrDisableColorXP.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "effects/GrDisableColorXP.h"
+#include "GrShaderCaps.h"
 #include "GrPipeline.h"
 #include "GrProcessor.h"
 #include "glsl/GrGLSLFragmentShaderBuilder.h"
@@ -50,11 +51,14 @@
 
 private:
     void emitOutputsForBlendState(const EmitArgs& args) override {
-        // This emit code should be empty. However, on the nexus 6 there is a driver bug where if
-        // you do not give gl_FragColor a value, the gl context is lost and we end up drawing
-        // nothing. So this fix just sets the gl_FragColor arbitrarily to 0.
-        GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
-        fragBuilder->codeAppendf("%s = half4(0);", args.fOutputPrimary);
+        if (args.fShaderCaps->mustWriteToFragColor()) {
+            // This emit code should be empty. However, on the nexus 6 there is a driver bug where
+            // if you do not give gl_FragColor a value, the gl context is lost and we end up drawing
+            // nothing. So this fix just sets the gl_FragColor arbitrarily to 0.
+            // https://bugs.chromium.org/p/chromium/issues/detail?id=445377
+            GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
+            fragBuilder->codeAppendf("%s = half4(0);", args.fOutputPrimary);
+        }
     }
 
     void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 7d70e7f..bbc86fc 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -2902,6 +2902,11 @@
         shaderCaps->fRemovePowWithConstantExponent = true;
     }
 
+    if (kAdreno3xx_GrGLRenderer == ctxInfo.renderer() ||
+        kAdreno4xx_other_GrGLRenderer == ctxInfo.renderer()) {
+        shaderCaps->fMustWriteToFragColor = true;
+    }
+
     // Disabling advanced blend on various platforms with major known issues. We also block Chrome
     // for now until its own blacklists can be updated.
     if (kAdreno430_GrGLRenderer == ctxInfo.renderer() ||