Always build the ANGLE test code. Always build ANGLE on windows and linux.

Make ANGLE test code independent of having ANGLE lib. Make ANGLE test code not include EGL headers.

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4040

DOCS_PREVIEW= https://skia.org/?cl=4040

Change-Id: I7b857e9785246743f53fb969647b1162ce7419ab
Reviewed-on: https://skia-review.googlesource.com/4040
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Mike Klein <mtklein@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index dab8918..64e69e7 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -11,7 +11,6 @@
 }
 
 declare_args() {
-  skia_use_angle = false
   skia_use_expat = true
   skia_use_fontconfig = is_linux
   skia_use_freetype = is_android || is_fuchsia || is_linux
@@ -755,6 +754,7 @@
         "tools/gpu/GrTest.cpp",
         "tools/gpu/TestContext.cpp",
         "tools/gpu/gl/GLTestContext.cpp",
+        "tools/gpu/gl/angle/GLTestContext_angle.cpp",
         "tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp",
         "tools/gpu/gl/debug/DebugGLTestContext.cpp",
         "tools/gpu/gl/debug/GrBufferObj.cpp",
@@ -774,6 +774,7 @@
         libs += [ "OpenGLES.framework" ]
       } else if (is_linux) {
         sources += [ "tools/gpu/gl/glx/CreatePlatformGLTestContext_glx.cpp" ]
+        deps += [ "//third_party/angle2" ]
       } else if (is_mac) {
         sources += [ "tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp" ]
       } else if (is_win) {
@@ -782,13 +783,9 @@
           "Gdi32.lib",
           "OpenGL32.lib",
         ]
+        deps += [ "//third_party/angle2" ]
       }
 
-      if (skia_use_angle) {
-        public_defines += [ "SK_ANGLE" ]
-        deps += [ "//third_party/angle2" ]
-        sources += [ "tools/gpu/gl/angle/GLTestContext_angle.cpp" ]
-      }
       if (skia_use_mesa) {
         public_defines += [ "SK_MESA" ]
         sources += [ "tools/gpu/gl/mesa/GLTestContext_mesa.cpp" ]
@@ -1103,9 +1100,6 @@
         ":tool_utils",
         ":views",
       ]
-      if (skia_use_angle) {
-        deps += [ "//third_party/angle2" ]
-      }
       testonly = true
     }
   }
diff --git a/infra/bots/recipe_modules/flavor/gn_flavor.py b/infra/bots/recipe_modules/flavor/gn_flavor.py
index af400d9..705cfe2 100644
--- a/infra/bots/recipe_modules/flavor/gn_flavor.py
+++ b/infra/bots/recipe_modules/flavor/gn_flavor.py
@@ -73,8 +73,6 @@
 
     if configuration != 'Debug':
       args['is_debug'] = 'false'
-    if extra_config == 'ANGLE':
-      args['skia_use_angle'] = 'true'
     if extra_config == 'CommandBuffer':
       self.m.run.run_once(self.build_command_buffer)
     if extra_config == 'GDI':
diff --git a/infra/bots/recipes/swarm_compile.expected/Build-Ubuntu-GCC-x86_64-Release-ANGLE.json b/infra/bots/recipes/swarm_compile.expected/Build-Ubuntu-GCC-x86_64-Release-ANGLE.json
index 79a420a..3cc7a39 100644
--- a/infra/bots/recipes/swarm_compile.expected/Build-Ubuntu-GCC-x86_64-Release-ANGLE.json
+++ b/infra/bots/recipes/swarm_compile.expected/Build-Ubuntu-GCC-x86_64-Release-ANGLE.json
@@ -92,7 +92,7 @@
       "gn",
       "gen",
       "[CUSTOM_/_B_WORK]/skia/out/Build-Ubuntu-GCC-x86_64-Release-ANGLE/Release",
-      "--args=cc=\"gcc\" cxx=\"g++\" is_debug=false skia_use_angle=true"
+      "--args=cc=\"gcc\" cxx=\"g++\" is_debug=false"
     ],
     "cwd": "[CUSTOM_/_B_WORK]/skia",
     "env": {
diff --git a/infra/bots/recipes/swarm_compile.expected/Build-Win-MSVC-x86-Debug-ANGLE.json b/infra/bots/recipes/swarm_compile.expected/Build-Win-MSVC-x86-Debug-ANGLE.json
index 39940cf..c94c98a 100644
--- a/infra/bots/recipes/swarm_compile.expected/Build-Win-MSVC-x86-Debug-ANGLE.json
+++ b/infra/bots/recipes/swarm_compile.expected/Build-Win-MSVC-x86-Debug-ANGLE.json
@@ -92,7 +92,7 @@
       "gn.bat",
       "gen",
       "[CUSTOM_C:\\_B_WORK]\\skia\\out\\Build-Win-MSVC-x86-Debug-ANGLE\\Debug",
-      "--args=skia_use_angle=true target_cpu=\"x86\" windk=\"[SLAVE_BUILD]\\t\\depot_tools\\win_toolchain\\vs_files\\95ddda401ec5678f15eeed01d2bee08fcbc5ee97\""
+      "--args=target_cpu=\"x86\" windk=\"[SLAVE_BUILD]\\t\\depot_tools\\win_toolchain\\vs_files\\95ddda401ec5678f15eeed01d2bee08fcbc5ee97\""
     ],
     "cwd": "[CUSTOM_C:\\_B_WORK]\\skia",
     "env": {
diff --git a/site/user/special/angle.md b/site/user/special/angle.md
index ff8f1c8..2ff7a35 100644
--- a/site/user/special/angle.md
+++ b/site/user/special/angle.md
@@ -13,8 +13,7 @@
 
 `gclient sync` downloads ANGLE's source alongside Skia's other test-only dependencies.
 
-To build Skia testing tools against ANGLE, add `skia_use_angle = true` to your
-`args.gn` file (or run `gn args` to edit it).
+ANGLE is built when building Skia test tools on Windows and Linux.
 
 When running tools, use `--config angle_<backend>_<frontend>`, e.g.
 
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index 0acb428..2752c98 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -452,7 +452,16 @@
     }
 }
 
-DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkImage_newTextureImage, reporter, contextInfo) {
+static bool is_rendering_and_not_angle_gl(sk_gpu_test::GrContextFactory::ContextType type) {
+    if (type == sk_gpu_test::GrContextFactory::kANGLE_GL_ES3_ContextType ||
+        type == sk_gpu_test::GrContextFactory::kANGLE_GL_ES2_ContextType) {
+        return false;
+    }
+    return sk_gpu_test::GrContextFactory::IsRenderingContext(type);
+}
+
+DEF_GPUTEST_FOR_CONTEXTS(SkImage_newTextureImage, is_rendering_and_not_angle_gl, reporter,
+                         contextInfo) {
     GrContext* context = contextInfo.grContext();
     sk_gpu_test::TestContext* testContext = contextInfo.testContext();
 
@@ -884,7 +893,7 @@
     }
 }
 
-DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredTextureImage, reporter, ctxInfo) {
+DEF_GPUTEST_FOR_CONTEXTS(DeferredTextureImage, is_rendering_and_not_angle_gl, reporter, ctxInfo) {
     GrContext* context = ctxInfo.grContext();
     sk_gpu_test::TestContext* testContext = ctxInfo.testContext();
     sk_sp<GrContextThreadSafeProxy> proxy = context->threadSafeProxy();
diff --git a/tools/gpu/GrContextFactory.cpp b/tools/gpu/GrContextFactory.cpp
index ffc5295..63d5f0a 100644
--- a/tools/gpu/GrContextFactory.cpp
+++ b/tools/gpu/GrContextFactory.cpp
@@ -9,9 +9,7 @@
 #include "GrContextFactory.h"
 #include "gl/GLTestContext.h"
 
-#if SK_ANGLE
-    #include "gl/angle/GLTestContext_angle.h"
-#endif
+#include "gl/angle/GLTestContext_angle.h"
 #include "gl/command_buffer/GLTestContext_command_buffer.h"
 #include "gl/debug/DebugGLTestContext.h"
 #if SK_MESA
@@ -116,7 +114,6 @@
                 case kGLES_ContextType:
                     glCtx = CreatePlatformGLTestContext(kGLES_GrGLStandard);
                     break;
-#if SK_ANGLE
                 case kANGLE_D3D9_ES2_ContextType:
                     glCtx = MakeANGLETestContext(ANGLEBackend::kD3D9, ANGLEContextVersion::kES2).release();
                     break;
@@ -132,7 +129,6 @@
                 case kANGLE_GL_ES3_ContextType:
                     glCtx = MakeANGLETestContext(ANGLEBackend::kOpenGL, ANGLEContextVersion::kES3).release();
                     break;
-#endif
                 case kCommandBuffer_ContextType:
                     glCtx = CommandBufferGLTestContext::Create();
                     break;
diff --git a/tools/gpu/gl/angle/GLTestContext_angle.cpp b/tools/gpu/gl/angle/GLTestContext_angle.cpp
index c3ec431..92c6cf4 100644
--- a/tools/gpu/gl/angle/GLTestContext_angle.cpp
+++ b/tools/gpu/gl/angle/GLTestContext_angle.cpp
@@ -8,9 +8,6 @@
 
 #include "GLTestContext_angle.h"
 
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
 #include "gl/GrGLDefines.h"
 #include "gl/GrGLUtil.h"
 
@@ -18,61 +15,308 @@
 #include "gl/GrGLAssembleInterface.h"
 #include "../ports/SkOSLibrary.h"
 
-#include <EGL/egl.h>
+#include "SkRefCnt.h"
+#include "SkSpinlock.h"
+#include "SkTDArray.h"
+
+/**
+ * EGL.h stuff. We don't want to worry about whether we're pulling in ANGLE's functions or some
+ * other system EGL implementation. So we just define all the EGL types we need and dynamically
+ * load all the functions we need.
+ */
+
+#if defined(SK_BUILD_FOR_WIN)
+    #include <Windows.h>
+    using EGLNativeDisplayType  = HDC;
+    using EGLNativePixmapType   = HBITMAP;
+    using EGLNativeWindowType   = HWND;
+#elif defined(SK_BUILD_FOR_UNIX)
+    #include <X11/Xlib.h>
+    using EGLNativeDisplayType  = Display*;
+    using EGLNativePixmapType   = Pixmap;
+    using EGLNativeWindowType   = Window;
+#else
+    using EGLNativeDisplayType  = void*;
+    using EGLNativePixmapType   = void*;
+    using EGLNativeWindowType   = void*;
+#endif
+
+using EGLint = int32_t;
+using EGLFn = void(void);
+using EGLDisplay = void*;
+using EGLSurface = void*;
+using EGLContext = void*;
+using EGLConfig = void*;
+using EGLenum = unsigned int;
+using EGLBoolean = unsigned int;
+
+using EGLGetProcAddressFn = EGLFn*(const char *procname);
+using EGLInitializeFn = EGLBoolean(EGLDisplay display, EGLint * major, EGLint * minor);
+using EGLTerminateFn = EGLBoolean(EGLDisplay display);
+using EGLChooseConfigFn = EGLBoolean(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+using EGLCreateContextFn = EGLContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
+using EGLCreatePbufferSurfaceFn = EGLSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
+using EGLMakeCurrentFn = EGLBoolean(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
+using EGLDestroyContextFn = EGLBoolean(EGLDisplay dpy, EGLContext ctx);
+using EGLDestroySurfaceFn = EGLBoolean(EGLDisplay dpy, EGLSurface surface);
+using EGLSwapBuffersFn = EGLBoolean(EGLDisplay dpy, EGLSurface surface);
+using EGLGetErrorFn = EGLint();
 
 #define EGL_PLATFORM_ANGLE_ANGLE                0x3202
 #define EGL_PLATFORM_ANGLE_TYPE_ANGLE           0x3203
 #define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE      0x3207
 #define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE     0x3208
 #define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE    0x320D
+#define EGL_NO_DISPLAY                          ((EGLDisplay)0)
+#define EGL_NO_CONTEXT                          ((EGLContext)0)
+#define EGL_NO_SURFACE                          ((EGLSurface)0)
+#define EGL_DEFAULT_DISPLAY                     ((EGLNativeDisplayType)0)
+#define EGL_NONE                                0x3038
+#define EGL_SURFACE_TYPE                        0x3033
+#define EGL_PBUFFER_BIT                         0x0001
+#define EGL_RENDERABLE_TYPE                     0x3040
+#define EGL_OPENGL_ES2_BIT                      0x0004
+#define EGL_RED_SIZE                            0x3024
+#define EGL_GREEN_SIZE                          0x3023
+#define EGL_BLUE_SIZE                           0x3022
+#define EGL_ALPHA_SIZE                          0x3021
+#define EGL_CONTEXT_CLIENT_VERSION              0x3098
+#define EGL_WIDTH                               0x3057
+#define EGL_HEIGHT                              0x3056
+#define EGL_FALSE                               0
+#define EGL_TRUE                                1
 
 using sk_gpu_test::ANGLEBackend;
 using sk_gpu_test::ANGLEContextVersion;
 
 namespace {
-struct Libs {
-    void* fGLLib;
-    void* fEGLLib;
+
+class ANGLE : public ::SkRefCnt {
+public:
+    static sk_sp<ANGLE> Get() {
+        gSpinlock.acquire();
+        if (!gANGLE) {
+            sk_sp<ANGLE> angle(new ANGLE);
+            if (angle->load()) {
+                gANGLE = angle;
+            }
+        }
+        gSpinlock.release();
+        return gANGLE;
+    }
+
+    EGLBoolean initialize(EGLDisplay display, EGLint * major, EGLint * minor) const {
+        return fInitialize(display, major, minor);
+    }
+
+    EGLBoolean terminate(EGLDisplay display) const {
+        return fTerminate(display);
+    }
+
+    EGLFn* getProcAddress(const char* procname) const {
+        void* lib = (0 == strncmp("gl", procname, 2)) ? fGLLib : fEGLLib;
+        EGLFn* proc = (EGLFn*)GetProcedureAddress(lib, procname);
+        if (!proc) {
+            proc = fGetProcAddress(procname);
+        }
+        return proc;
+    }
+
+    EGLBoolean chooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs,
+                            EGLint config_size, EGLint *num_config) const {
+        return fChooseConfig(dpy, attrib_list, configs, config_size, num_config);
+    }
+
+    EGLContext createContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context,
+                             const EGLint *attrib_list) const {
+        return fCreateContext(dpy, config, share_context, attrib_list);
+    }
+
+    EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config,
+                                    const EGLint *attrib_list) const {
+        return fCreatePbufferSurface(dpy, config, attrib_list);
+    }
+
+    EGLBoolean makeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) const {
+        return fMakeCurrent(dpy, draw, read, ctx);
+    }
+
+    EGLBoolean destroyContext(EGLDisplay dpy, EGLContext ctx) const {
+        return fDestroyContext(dpy, ctx);
+    }
+
+    EGLBoolean destroySurface(EGLDisplay dpy, EGLSurface surface) const {
+        return fDestroySurface(dpy, surface);
+    }
+
+    EGLBoolean swapBuffers(EGLDisplay display, EGLSurface surface) const {
+        return fSwapBuffers(display, surface);
+    }
+
+    EGLint getError() const { return fGetError(); }
+
+private:
+    bool load() {
+        // We load the ANGLE library and never let it go
+#if defined(SK_BUILD_FOR_WIN)
+        fGLLib = DynamicLoadLibrary("libGLESv2.dll");
+        fEGLLib = DynamicLoadLibrary("libEGL.dll");
+#elif defined(SK_BUILD_FOR_MAC)
+        fGLLib = DynamicLoadLibrary("libGLESv2.dylib");
+        fEGLLib = DynamicLoadLibrary("libEGL.dylib");
+#else
+        fGLLib = DynamicLoadLibrary("libGLESv2.so");
+        fEGLLib = DynamicLoadLibrary("libEGL.so");
+#endif
+        if (!fGLLib || !fEGLLib) {
+            return false;
+        }
+#define GET_PROC(NAME) f ## NAME = (EGL ## NAME ##Fn*) GetProcedureAddress(fEGLLib, "egl" #NAME); \
+                       if (!f ## NAME) { return false; }
+        GET_PROC(GetProcAddress);
+        GET_PROC(Initialize);
+        GET_PROC(Terminate);
+        GET_PROC(ChooseConfig);
+        GET_PROC(CreateContext)
+        GET_PROC(CreatePbufferSurface);
+        GET_PROC(MakeCurrent);
+        GET_PROC(DestroyContext);
+        GET_PROC(DestroySurface);
+        GET_PROC(SwapBuffers);
+        GET_PROC(GetError);
+#undef GET_PROC
+        return true;
+    }
+
+    ANGLE() = default;
+    ~ANGLE() {
+        SkDebugf("Done!");
+    }
+
+    EGLGetProcAddressFn*        fGetProcAddress;
+    EGLInitializeFn*            fInitialize;
+    EGLTerminateFn*             fTerminate;
+    EGLChooseConfigFn*          fChooseConfig;
+    EGLCreateContextFn*         fCreateContext;
+    EGLCreatePbufferSurfaceFn*  fCreatePbufferSurface;
+    EGLMakeCurrentFn*           fMakeCurrent;
+    EGLDestroyContextFn*        fDestroyContext;
+    EGLDestroySurfaceFn*        fDestroySurface;
+    EGLSwapBuffersFn*           fSwapBuffers;
+    EGLGetErrorFn*              fGetError;
+
+    void*                       fGLLib;
+    void*                       fEGLLib;
+
+    static sk_sp<ANGLE>         gANGLE;
+    static SkSpinlock           gSpinlock;
 };
 
+SkSpinlock ANGLE::gSpinlock;
+sk_sp<ANGLE> ANGLE::gANGLE;
+
 static GrGLFuncPtr angle_get_gl_proc(void* ctx, const char name[]) {
-    const Libs* libs = reinterpret_cast<const Libs*>(ctx);
-    GrGLFuncPtr proc = (GrGLFuncPtr) GetProcedureAddress(libs->fGLLib, name);
-    if (proc) {
-        return proc;
-    }
-    proc = (GrGLFuncPtr) GetProcedureAddress(libs->fEGLLib, name);
-    if (proc) {
-        return proc;
-    }
-    return eglGetProcAddress(name);
+    const ANGLE* angle = reinterpret_cast<const ANGLE*>(ctx);
+    return angle->getProcAddress(name);
 }
 
-void* get_angle_egl_display(void* nativeDisplay, ANGLEBackend type) {
-    PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT;
-    eglGetPlatformDisplayEXT =
-        (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
-
-    // We expect ANGLE to support this extension
-    if (!eglGetPlatformDisplayEXT) {
-        return EGL_NO_DISPLAY;
+class Display {
+public:
+    static std::unique_ptr<Display> Make(ANGLEBackend type) {
+        gSpinlock.acquire();
+        EGLDisplay display = GetEGLDisplay(type);
+        if (display == EGL_NO_DISPLAY) {
+            // This happens often (e.g. D3D on Linux) so no print.
+            if (0) {
+                SkDebugf("Could not get display.\n");
+            }
+            gSpinlock.release();
+            return nullptr;
+        }
+        int i = 0;
+        for (; i < gEGLDisplays.count(); ++i) {
+            if (gEGLDisplays[i].fDisplay == display) {
+                ++gEGLDisplays[i].fRefCnt;
+                break;
+            }
+        }
+        if (i == gEGLDisplays.count()) {
+            EGLint majorVersion;
+            EGLint minorVersion;
+            if (ANGLE::Get()->initialize(display, &majorVersion, &minorVersion) == EGL_FALSE) {
+                SkDebugf("Failed to initialize display.\n");
+                gSpinlock.release();
+                return nullptr;
+            }
+            gEGLDisplays.push()->fDisplay = display;
+            gEGLDisplays.top().fRefCnt = 1;
+        }
+        gSpinlock.release();
+        return std::unique_ptr<Display>(new Display(display));
     }
 
-    EGLint typeNum = 0;
-    switch (type) {
-        case ANGLEBackend::kD3D9:
-            typeNum = EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;
-            break;
-        case ANGLEBackend::kD3D11:
-            typeNum = EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
-            break;
-        case ANGLEBackend::kOpenGL:
-            typeNum = EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE;
-            break;
+    ~Display() {
+        gSpinlock.acquire();
+        for (int i = 0; i < gEGLDisplays.count(); ++i) {
+            if (gEGLDisplays[i].fDisplay == fDisplay) {
+                if (--gEGLDisplays[i].fRefCnt == 0) {
+                    ANGLE::Get()->terminate(fDisplay);
+                    gEGLDisplays.removeShuffle(i);
+                }
+                gSpinlock.release();
+                return;
+            }
+        }
+        SkFAIL("Didn't find ref counted EGLDisplay entry.");
     }
-    const EGLint attribs[] = { EGL_PLATFORM_ANGLE_TYPE_ANGLE, typeNum, EGL_NONE };
-    return eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, nativeDisplay, attribs);
-}
+
+    EGLDisplay get() const { return fDisplay; }
+
+private:
+    Display& operator=(const Display&) = delete;
+    Display(EGLDisplay display) : fDisplay(display) {}
+    Display(const Display&) = delete;
+
+    static EGLDisplay GetEGLDisplay(ANGLEBackend type) {
+        using EGLGetPlatformDisplayEXTFn = EGLDisplay(EGLenum platform, void *native_display,
+                                                      const EGLint *attrib_list);
+        EGLGetPlatformDisplayEXTFn* eglGetPlatformDisplayEXT =
+                (EGLGetPlatformDisplayEXTFn*)ANGLE::Get()->getProcAddress(
+                        "eglGetPlatformDisplayEXT");
+
+        // We expect ANGLE to support this extension
+        if (!eglGetPlatformDisplayEXT) {
+            return EGL_NO_DISPLAY;
+        }
+
+        EGLint typeNum = 0;
+        switch (type) {
+            case ANGLEBackend::kD3D9:
+                typeNum = EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;
+                break;
+            case ANGLEBackend::kD3D11:
+                typeNum = EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
+                break;
+            case ANGLEBackend::kOpenGL:
+                typeNum = EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE;
+                break;
+        }
+        const EGLint attribs[] = { EGL_PLATFORM_ANGLE_TYPE_ANGLE, typeNum, EGL_NONE };
+        return eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, attribs);
+    }
+
+    EGLDisplay fDisplay;
+
+    struct D {
+        EGLDisplay fDisplay;
+        int fRefCnt;
+    };
+    static SkTDArray<D>     gEGLDisplays;
+    static SkSpinlock       gSpinlock;
+};
+
+SkSpinlock Display::gSpinlock;
+SkTDArray<Display::D> Display::gEGLDisplays;
 
 class ANGLEGLContext : public sk_gpu_test::GLTestContext {
 public:
@@ -85,26 +329,32 @@
     std::unique_ptr<sk_gpu_test::GLTestContext> makeNew() const override;
 
 private:
+    EGLDisplay display() const { return fDisplay.get()->get(); }
     void destroyGLContext();
 
     void onPlatformMakeCurrent() const override;
     void onPlatformSwapBuffers() const override;
     GrGLFuncPtr onPlatformGetProcAddress(const char* name) const override;
 
-    void*                       fContext;
-    void*                       fDisplay;
-    void*                       fSurface;
+    sk_sp<ANGLE>                fANGLE;
+    EGLContext                  fContext;
+    std::unique_ptr<Display>    fDisplay;
+    EGLSurface                  fSurface;
     ANGLEBackend                fType;
     ANGLEContextVersion         fVersion;
 };
 
 ANGLEGLContext::ANGLEGLContext(ANGLEBackend type, ANGLEContextVersion version)
-    : fContext(EGL_NO_CONTEXT)
-    , fDisplay(EGL_NO_DISPLAY)
+    : fANGLE(ANGLE::Get())
+    , fContext(EGL_NO_CONTEXT)
+    , fDisplay(Display::Make(type))
     , fSurface(EGL_NO_SURFACE)
     , fType(type)
     , fVersion(version) {
 
+    if (!fANGLE || !fDisplay) {
+        return;
+    }
     EGLint numConfigs;
     static const EGLint configAttribs[] = {
         EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
@@ -116,26 +366,24 @@
         EGL_NONE
     };
 
-    fDisplay = get_angle_egl_display(EGL_DEFAULT_DISPLAY, type);
-    if (EGL_NO_DISPLAY == fDisplay) {
-        SkDebugf("Could not create EGL display!");
+    EGLConfig surfaceConfig;
+    if (fANGLE->chooseConfig(this->display(), configAttribs, &surfaceConfig, 1, &numConfigs) ==
+        EGL_FALSE) {
+        SkDebugf("Could not choose config for display!\n");
         return;
     }
 
-    EGLint majorVersion;
-    EGLint minorVersion;
-    eglInitialize(fDisplay, &majorVersion, &minorVersion);
-
-    EGLConfig surfaceConfig;
-    eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs);
-
     int versionNum = ANGLEContextVersion::kES2 == version ? 2 : 3;
     const EGLint contextAttribs[] = {
         EGL_CONTEXT_CLIENT_VERSION, versionNum,
         EGL_NONE
     };
-    fContext = eglCreateContext(fDisplay, surfaceConfig, nullptr, contextAttribs);
+    fContext = fANGLE->createContext(this->display(), surfaceConfig, nullptr, contextAttribs);
 
+    if (EGL_NO_CONTEXT == fContext) {
+        SkDebugf("Failed to create context\n");
+        return;
+    }
 
     static const EGLint surfaceAttribs[] = {
         EGL_WIDTH, 1,
@@ -143,11 +391,12 @@
         EGL_NONE
     };
 
-    fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, surfaceAttribs);
+    fSurface = fANGLE->createPbufferSurface(this->display(), surfaceConfig, surfaceAttribs);
 
-    eglMakeCurrent(fDisplay, fSurface, fSurface, fContext);
+    fANGLE->makeCurrent(this->display(), fSurface, fSurface, fContext);
 
-    sk_sp<const GrGLInterface> gl(sk_gpu_test::CreateANGLEGLInterface());
+    sk_sp<const GrGLInterface> gl(GrGLAssembleGLESInterface((void*)fANGLE.get(),
+                                                            angle_get_gl_proc));
     if (nullptr == gl.get()) {
         SkDebugf("Could not create ANGLE GL interface!\n");
         this->destroyGLContext();
@@ -178,13 +427,13 @@
     // 64 bit cast is to shut Visual C++ up about casting 32 bit value to a pointer.
     GrEGLClientBuffer clientBuffer = reinterpret_cast<GrEGLClientBuffer>((uint64_t)texID);
     GR_GL_CALL_RET(this->gl(), img,
-                   EGLCreateImage(fDisplay, fContext, GR_EGL_GL_TEXTURE_2D, clientBuffer,
+                   EGLCreateImage(this->display(), fContext, GR_EGL_GL_TEXTURE_2D, clientBuffer,
                                   attribs));
     return img;
 }
 
 void ANGLEGLContext::destroyEGLImage(GrEGLImage image) const {
-    GR_GL_CALL(this->gl(), EGLDestroyImage(fDisplay, image));
+    GR_GL_CALL(this->gl(), EGLDestroyImage(this->display(), image));
 }
 
 GrGLuint ANGLEGLContext::eglImageToExternalTexture(GrEGLImage image) const {
@@ -192,9 +441,9 @@
     if (!this->gl()->hasExtension("GL_OES_EGL_image_external")) {
         return 0;
     }
-    typedef GrGLvoid (EGLAPIENTRY *EGLImageTargetTexture2DProc)(GrGLenum, GrGLeglImage);
-    EGLImageTargetTexture2DProc glEGLImageTargetTexture2D =
-        (EGLImageTargetTexture2DProc)eglGetProcAddress("glEGLImageTargetTexture2DOES");
+    using EGLImageTargetTexture2DFn = GrGLvoid(GrGLenum, GrGLeglImage);
+    EGLImageTargetTexture2DFn* glEGLImageTargetTexture2D =
+        (EGLImageTargetTexture2DFn*)fANGLE->getProcAddress("glEGLImageTargetTexture2DOES");
     if (!glEGLImageTargetTexture2D) {
         return 0;
     }
@@ -227,64 +476,46 @@
 
 void ANGLEGLContext::destroyGLContext() {
     if (fDisplay) {
-        eglMakeCurrent(fDisplay, 0, 0, 0);
+        fANGLE->makeCurrent(this->display(), 0, 0, 0);
 
         if (fContext) {
-            eglDestroyContext(fDisplay, fContext);
+            fANGLE->destroyContext(this->display(), fContext);
             fContext = EGL_NO_CONTEXT;
         }
 
         if (fSurface) {
-            eglDestroySurface(fDisplay, fSurface);
+            fANGLE->destroySurface(this->display(), fSurface);
             fSurface = EGL_NO_SURFACE;
         }
-
-        //TODO should we close the display?
-        fDisplay = EGL_NO_DISPLAY;
+        fDisplay.reset();
     }
 }
 
 void ANGLEGLContext::onPlatformMakeCurrent() const {
-    if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
+    if (!fANGLE->makeCurrent(this->display(), fSurface, fSurface, fContext)) {
         SkDebugf("Could not set the context.\n");
     }
 }
 
 void ANGLEGLContext::onPlatformSwapBuffers() const {
-    if (!eglSwapBuffers(fDisplay, fSurface)) {
+    if (!fANGLE->swapBuffers(this->display(), fSurface)) {
         SkDebugf("Could not complete eglSwapBuffers.\n");
     }
 }
 
 GrGLFuncPtr ANGLEGLContext::onPlatformGetProcAddress(const char* name) const {
-    return eglGetProcAddress(name);
+    return fANGLE->getProcAddress(name);
 }
+
 }  // anonymous namespace
 
 namespace sk_gpu_test {
 const GrGLInterface* CreateANGLEGLInterface() {
-    static Libs gLibs = { nullptr, nullptr };
-
-    if (nullptr == gLibs.fGLLib) {
-        // We load the ANGLE library and never let it go
-#if defined _WIN32
-        gLibs.fGLLib = DynamicLoadLibrary("libGLESv2.dll");
-        gLibs.fEGLLib = DynamicLoadLibrary("libEGL.dll");
-#elif defined SK_BUILD_FOR_MAC
-        gLibs.fGLLib = DynamicLoadLibrary("libGLESv2.dylib");
-        gLibs.fEGLLib = DynamicLoadLibrary("libEGL.dylib");
-#else
-        gLibs.fGLLib = DynamicLoadLibrary("libGLESv2.so");
-        gLibs.fEGLLib = DynamicLoadLibrary("libEGL.so");
-#endif
-    }
-
-    if (nullptr == gLibs.fGLLib || nullptr == gLibs.fEGLLib) {
-        // We can't setup the interface correctly w/o the so
+    sk_sp<ANGLE> angle = ANGLE::Get();
+    if (!angle) {
         return nullptr;
     }
-
-    return GrGLAssembleGLESInterface(&gLibs, angle_get_gl_proc);
+    return GrGLAssembleGLESInterface((void*)angle.get(), angle_get_gl_proc);
 }
 
 std::unique_ptr<GLTestContext> MakeANGLETestContext(ANGLEBackend type, ANGLEContextVersion version){