When glSync is not available on android fake it out with EGL for our tests.

Change-Id: Ie1c98f1927146cce938204c2ea60899887a3bcea
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/271746
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp b/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp
index af6d110..d2e6ea9 100644
--- a/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp
+++ b/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp
@@ -69,6 +69,8 @@
     void onPlatformSwapBuffers() const override;
     GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;
 
+    void setupFenceSync(sk_sp<const GrGLInterface>);
+
     PFNEGLCREATEIMAGEKHRPROC fEglCreateImageProc = nullptr;
     PFNEGLDESTROYIMAGEKHRPROC fEglDestroyImageProc = nullptr;
 
@@ -207,6 +209,8 @@
             continue;
         }
 
+        this->setupFenceSync(gl);
+
         if (!gl->validate()) {
             SkDebugf("Failed to validate gl interface.\n");
             this->destroyGLContext();
@@ -224,6 +228,126 @@
     }
 }
 
+static bool supports_egl_extension(EGLDisplay display, const char* extension) {
+    size_t extensionLength = strlen(extension);
+    const char* extensionsStr = eglQueryString(display, EGL_EXTENSIONS);
+    while (const char* match = strstr(extensionsStr, extension)) {
+        // Ensure the string we found is its own extension, not a substring of a larger extension
+        // (e.g. GL_ARB_occlusion_query / GL_ARB_occlusion_query2).
+        if ((match == extensionsStr || match[-1] == ' ') &&
+            (match[extensionLength] == ' ' || match[extensionLength] == '\0')) {
+            return true;
+        }
+        extensionsStr = match + extensionLength;
+    }
+    return false;
+}
+
+void EGLGLTestContext::setupFenceSync(sk_sp<const GrGLInterface> interface) {
+    GrGLInterface* glInt = const_cast<GrGLInterface*>(interface.get());
+
+
+    if (kGL_GrGLStandard == glInt->fStandard) {
+        if (GrGLGetVersion(glInt) >= GR_GL_VER(3,2) || glInt->hasExtension("GL_ARB_sync")) {
+            return;
+        }
+    } else {
+        if (glInt->hasExtension("GL_APPLE_sync") || glInt->hasExtension("GL_NV_fence") ||
+            GrGLGetVersion(glInt) >= GR_GL_VER(3, 0)) {
+            return;
+        }
+    }
+
+    if (!supports_egl_extension(fDisplay, "EGL_KHR_fence_sync")) {
+        return;
+    }
+
+    auto grEGLCreateSyncKHR = (PFNEGLCREATESYNCKHRPROC) eglGetProcAddress("eglCreateSyncKHR");
+    auto grEGLClientWaitSyncKHR =
+            (PFNEGLCLIENTWAITSYNCKHRPROC) eglGetProcAddress("eglClientWaitSyncKHR");
+    auto grEGLDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC) eglGetProcAddress("eglDestroySyncKHR");
+    auto grEGLGetSyncAttribKHR =
+            (PFNEGLGETSYNCATTRIBKHRPROC) eglGetProcAddress("eglGetSyncAttribKHR");
+    SkASSERT(grEGLCreateSyncKHR && grEGLClientWaitSyncKHR && grEGLDestroySyncKHR &&
+             grEGLGetSyncAttribKHR);
+
+    PFNEGLWAITSYNCKHRPROC grEGLWaitSyncKHR = nullptr;
+    if (supports_egl_extension(fDisplay, "EGL_KHR_wait_sync")) {
+        grEGLWaitSyncKHR = (PFNEGLWAITSYNCKHRPROC)eglGetProcAddress("eglWaitSyncKHR");
+        SkASSERT(grEGLWaitSyncKHR);
+    }
+
+    // Fake out glSync using eglSync
+    glInt->fExtensions.add("GL_APPLE_sync");
+
+    glInt->fFunctions.fFenceSync =
+            [grEGLCreateSyncKHR, display = fDisplay](GrGLenum condition, GrGLbitfield flags) {
+        SkASSERT(condition == GR_GL_SYNC_GPU_COMMANDS_COMPLETE);
+        SkASSERT(flags == 0);
+
+        EGLSyncKHR sync = grEGLCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);
+
+        return reinterpret_cast<GrGLsync>(sync);
+    };
+
+    glInt->fFunctions.fDeleteSync = [grEGLDestroySyncKHR, display = fDisplay](GrGLsync sync) {
+        EGLSyncKHR eglSync = reinterpret_cast<EGLSyncKHR>(sync);
+        grEGLDestroySyncKHR(display, eglSync);
+    };
+
+    glInt->fFunctions.fClientWaitSync =
+            [grEGLClientWaitSyncKHR, display = fDisplay] (GrGLsync sync, GrGLbitfield flags,
+                                                          GrGLuint64 timeout) -> GrGLenum {
+        EGLSyncKHR eglSync = reinterpret_cast<EGLSyncKHR>(sync);
+
+        EGLint egl_flags = 0;
+
+        if (flags & GR_GL_SYNC_FLUSH_COMMANDS_BIT) {
+            egl_flags |= EGL_SYNC_FLUSH_COMMANDS_BIT_KHR;
+        }
+
+        EGLint result = grEGLClientWaitSyncKHR(display, eglSync, egl_flags, timeout);
+
+        switch (result) {
+            case EGL_CONDITION_SATISFIED_KHR:
+                return GR_GL_CONDITION_SATISFIED;
+            case EGL_TIMEOUT_EXPIRED_KHR:
+                return GR_GL_TIMEOUT_EXPIRED;
+            case EGL_FALSE:
+                return GR_GL_WAIT_FAILED;
+        }
+        SkUNREACHABLE;
+    };
+
+    glInt->fFunctions.fWaitSync =
+            [grEGLClientWaitSyncKHR, grEGLWaitSyncKHR, display = fDisplay](GrGLsync sync,
+                                                                           GrGLbitfield flags,
+                                                                           GrGLuint64 timeout) {
+        EGLSyncKHR eglSync = reinterpret_cast<EGLSyncKHR>(sync);
+
+        SkASSERT(timeout == GR_GL_TIMEOUT_IGNORED);
+        SkASSERT(flags == 0);
+
+        if (!grEGLWaitSyncKHR) {
+            grEGLClientWaitSyncKHR(display, eglSync, 0, EGL_FOREVER_KHR);
+            return;
+        }
+
+        SkDEBUGCODE(EGLint result =) grEGLWaitSyncKHR(display, eglSync, 0);
+        SkASSERT(result);
+    };
+
+    glInt->fFunctions.fIsSync =
+            [grEGLGetSyncAttribKHR, display = fDisplay](GrGLsync sync) -> GrGLboolean {
+        EGLSyncKHR eglSync = reinterpret_cast<EGLSyncKHR>(sync);
+        EGLint value;
+        if (grEGLGetSyncAttribKHR(display, eglSync, EGL_SYNC_TYPE_KHR, &value)) {
+            return true;
+        }
+        return false;
+    };
+}
+
 EGLGLTestContext::~EGLGLTestContext() {
     this->teardown();
     this->destroyGLContext();
@@ -331,21 +455,6 @@
     return eglGetProcAddress(procName);
 }
 
-static bool supports_egl_extension(EGLDisplay display, const char* extension) {
-    size_t extensionLength = strlen(extension);
-    const char* extensionsStr = eglQueryString(display, EGL_EXTENSIONS);
-    while (const char* match = strstr(extensionsStr, extension)) {
-        // Ensure the string we found is its own extension, not a substring of a larger extension
-        // (e.g. GL_ARB_occlusion_query / GL_ARB_occlusion_query2).
-        if ((match == extensionsStr || match[-1] == ' ') &&
-            (match[extensionLength] == ' ' || match[extensionLength] == '\0')) {
-            return true;
-        }
-        extensionsStr = match + extensionLength;
-    }
-    return false;
-}
-
 std::unique_ptr<EGLFenceSync> EGLFenceSync::MakeIfSupported(EGLDisplay display) {
     if (!display || !supports_egl_extension(display, "EGL_KHR_fence_sync")) {
         return nullptr;