Implement program binary caching in ES2 (with GL_OES_get_program_binary)

Change-Id: I6f9ee51f7c063ca03bf48fccd413dae244edd191
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/221778
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/gpu/gl/GrGLAssembleGLESInterfaceAutogen.cpp b/src/gpu/gl/GrGLAssembleGLESInterfaceAutogen.cpp
index 41411dc..0cd9bf2 100644
--- a/src/gpu/gl/GrGLAssembleGLESInterfaceAutogen.cpp
+++ b/src/gpu/gl/GrGLAssembleGLESInterfaceAutogen.cpp
@@ -437,6 +437,12 @@
     if (glVer >= GR_GL_VER(3,0)) {
         GET_PROC(GetProgramBinary);
         GET_PROC(ProgramBinary);
+    } else if (extensions.has("GL_OES_get_program_binary")) {
+        GET_PROC_SUFFIX(GetProgramBinary, OES);
+        GET_PROC_SUFFIX(ProgramBinary, OES);
+    }
+
+    if (glVer >= GR_GL_VER(3,0)) {
         GET_PROC(ProgramParameteri);
     }
 
diff --git a/src/gpu/gl/GrGLAssembleGLInterfaceAutogen.cpp b/src/gpu/gl/GrGLAssembleGLInterfaceAutogen.cpp
index f47b3b0..6d281ef 100644
--- a/src/gpu/gl/GrGLAssembleGLInterfaceAutogen.cpp
+++ b/src/gpu/gl/GrGLAssembleGLInterfaceAutogen.cpp
@@ -417,6 +417,9 @@
     if (glVer >= GR_GL_VER(4,1)) {
         GET_PROC(GetProgramBinary);
         GET_PROC(ProgramBinary);
+    }
+
+    if (glVer >= GR_GL_VER(4,1)) {
         GET_PROC(ProgramParameteri);
     }
 
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index d355208..4e099cb 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -60,6 +60,7 @@
     fDetachStencilFromMSAABuffersBeforeReadPixels = false;
     fDontSetBaseOrMaxLevelForExternalTextures = false;
     fProgramBinarySupport = false;
+    fProgramParameterSupport = false;
     fSamplerObjectSupport = false;
     fFBFetchRequiresEnablePerSample = false;
 
@@ -649,8 +650,11 @@
 
     if (GR_IS_GR_GL(standard)) {
         fProgramBinarySupport = (version >= GR_GL_VER(4, 1));
+        fProgramParameterSupport = (version >= GR_GL_VER(4, 1));
     } else if (GR_IS_GR_GL_ES(standard)) {
-        fProgramBinarySupport = (version >= GR_GL_VER(3, 0));
+        fProgramBinarySupport =
+                (version >= GR_GL_VER(3, 0)) || ctxInfo.hasExtension("GL_OES_get_program_binary");
+        fProgramParameterSupport = (version >= GR_GL_VER(3, 0));
     } // Explicitly not supported in WebGL 2.0
       // https://www.khronos.org/registry/webgl/specs/2.0/#5.4
     if (fProgramBinarySupport) {
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index fe1a9f2..e6b3ba0 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -403,6 +403,7 @@
                             bool* rectsMustMatch, bool* disallowSubrect) const override;
 
     bool programBinarySupport() const { return fProgramBinarySupport; }
+    bool programParameterSupport() const { return fProgramParameterSupport; }
 
     bool samplerObjectSupport() const { return fSamplerObjectSupport; }
 
@@ -496,6 +497,7 @@
     bool fUseBufferDataNullHint                : 1;
     bool fClearTextureSupport : 1;
     bool fProgramBinarySupport : 1;
+    bool fProgramParameterSupport : 1;
     bool fSamplerObjectSupport : 1;
     bool fFBFetchRequiresEnablePerSample : 1;
 
diff --git a/src/gpu/gl/GrGLInterfaceAutogen.cpp b/src/gpu/gl/GrGLInterfaceAutogen.cpp
index f9ec236..b861122 100644
--- a/src/gpu/gl/GrGLInterfaceAutogen.cpp
+++ b/src/gpu/gl/GrGLInterfaceAutogen.cpp
@@ -610,10 +610,19 @@
     if ((GR_IS_GR_GL(fStandard) && (
           (glVer >= GR_GL_VER(4,1)))) ||
        (GR_IS_GR_GL_ES(fStandard) && (
-          (glVer >= GR_GL_VER(3,0))))) {
+          (glVer >= GR_GL_VER(3,0)) ||
+          fExtensions.has("GL_OES_get_program_binary")))) {
         if (!fFunctions.fGetProgramBinary ||
-            !fFunctions.fProgramBinary ||
-            !fFunctions.fProgramParameteri) {
+            !fFunctions.fProgramBinary) {
+            RETURN_FALSE_INTERFACE;
+        }
+    }
+
+    if ((GR_IS_GR_GL(fStandard) && (
+          (glVer >= GR_GL_VER(4,1)))) ||
+       (GR_IS_GR_GL_ES(fStandard) && (
+          (glVer >= GR_GL_VER(3,0))))) {
+        if (!fFunctions.fProgramParameteri) {
             RETURN_FALSE_INTERFACE;
         }
     }
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index bed69a3..c830fad 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -195,6 +195,7 @@
     }
 
     if (this->gpu()->glCaps().programBinarySupport() &&
+        this->gpu()->glCaps().programParameterSupport() &&
         this->gpu()->getContext()->priv().getPersistentCache()) {
         GL_CALL(ProgramParameteri(programID, GR_GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GR_GL_TRUE));
     }