Add an extension to share textures at the display level.

BUG=angleproject:1639

Change-Id: If9140142ebce89f33921c13d9d212c17d1894162
Reviewed-on: https://chromium-review.googlesource.com/437618
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/Caps.cpp b/src/libANGLE/Caps.cpp
index b16f27e..47b45f3 100644
--- a/src/libANGLE/Caps.cpp
+++ b/src/libANGLE/Caps.cpp
@@ -1032,7 +1032,8 @@
       createContextBindGeneratesResource(false),
       swapBuffersWithDamage(false),
       pixelFormatFloat(false),
-      surfacelessContext(false)
+      surfacelessContext(false),
+      displayTextureShareGroup(false)
 {
 }
 
@@ -1072,6 +1073,7 @@
     InsertExtensionString("EGL_EXT_swap_buffers_with_damage",                    swapBuffersWithDamage,              &extensionStrings);
     InsertExtensionString("EGL_EXT_pixel_format_float",                          pixelFormatFloat,                   &extensionStrings);
     InsertExtensionString("EGL_KHR_surfaceless_context",                         surfacelessContext,                 &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_display_texture_share_group",               displayTextureShareGroup,            &extensionStrings);
     // TODO(jmadill): Enable this when complete.
     //InsertExtensionString("KHR_create_context_no_error",                       createContextNoError,               &extensionStrings);
     // clang-format on
diff --git a/src/libANGLE/Caps.h b/src/libANGLE/Caps.h
index 1b64f1a..31fb003 100644
--- a/src/libANGLE/Caps.h
+++ b/src/libANGLE/Caps.h
@@ -646,6 +646,9 @@
 
     // EGL_KHR_surfaceless_context
     bool surfacelessContext;
+
+    // EGL_ANGLE_display_texture_share_group
+    bool displayTextureShareGroup;
 };
 
 struct DeviceExtensions
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index 96c7c8a..6f04a4c 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -236,10 +236,12 @@
 Context::Context(rx::EGLImplFactory *implFactory,
                  const egl::Config *config,
                  const Context *shareContext,
+                 TextureManager *shareTextures,
                  const egl::AttributeMap &attribs,
                  const egl::DisplayExtensions &displayExtensions)
 
     : ValidationContext(shareContext,
+                        shareTextures,
                         GetClientVersion(attribs),
                         &mGLState,
                         mCaps,
diff --git a/src/libANGLE/Context.h b/src/libANGLE/Context.h
index 7037c9d..c1dd093 100644
--- a/src/libANGLE/Context.h
+++ b/src/libANGLE/Context.h
@@ -61,6 +61,7 @@
     Context(rx::EGLImplFactory *implFactory,
             const egl::Config *config,
             const Context *shareContext,
+            TextureManager *shareTextures,
             const egl::AttributeMap &attribs,
             const egl::DisplayExtensions &displayExtensions);
 
diff --git a/src/libANGLE/ContextState.cpp b/src/libANGLE/ContextState.cpp
index 6a24816..c5fb61c 100644
--- a/src/libANGLE/ContextState.cpp
+++ b/src/libANGLE/ContextState.cpp
@@ -36,10 +36,34 @@
     }
 }
 
+TextureManager *AllocateOrGetSharedTextureManager(const ContextState *shareContextState,
+                                                  TextureManager *shareTextures,
+                                                  ContextStateMember<TextureManager> member)
+{
+    if (shareContextState)
+    {
+        TextureManager *textureManager = (*shareContextState).*member;
+        ASSERT(shareTextures == nullptr || textureManager == shareTextures);
+        textureManager->addRef();
+        return textureManager;
+    }
+    else if (shareTextures)
+    {
+        TextureManager *textureManager = shareTextures;
+        textureManager->addRef();
+        return textureManager;
+    }
+    else
+    {
+        return new TextureManager();
+    }
+}
+
 }  // anonymous namespace
 
 ContextState::ContextState(uintptr_t contextIn,
                            const ContextState *shareContextState,
+                           TextureManager *shareTextures,
                            const Version &clientVersion,
                            State *stateIn,
                            const Caps &capsIn,
@@ -56,7 +80,9 @@
       mBuffers(AllocateOrGetSharedResourceManager(shareContextState, &ContextState::mBuffers)),
       mShaderPrograms(
           AllocateOrGetSharedResourceManager(shareContextState, &ContextState::mShaderPrograms)),
-      mTextures(AllocateOrGetSharedResourceManager(shareContextState, &ContextState::mTextures)),
+      mTextures(AllocateOrGetSharedTextureManager(shareContextState,
+                                                  shareTextures,
+                                                  &ContextState::mTextures)),
       mRenderbuffers(
           AllocateOrGetSharedResourceManager(shareContextState, &ContextState::mRenderbuffers)),
       mSamplers(AllocateOrGetSharedResourceManager(shareContextState, &ContextState::mSamplers)),
@@ -85,6 +111,7 @@
 }
 
 ValidationContext::ValidationContext(const ValidationContext *shareContext,
+                                     TextureManager *shareTextures,
                                      const Version &clientVersion,
                                      State *state,
                                      const Caps &caps,
@@ -94,13 +121,15 @@
                                      bool skipValidation)
     : mState(reinterpret_cast<uintptr_t>(this),
              shareContext ? &shareContext->mState : nullptr,
+             shareTextures,
              clientVersion,
              state,
              caps,
              textureCaps,
              extensions,
              limitations),
-      mSkipValidation(skipValidation)
+      mSkipValidation(skipValidation),
+      mDisplayTextureShareGroup(shareTextures != nullptr)
 {
 }
 
@@ -673,4 +702,9 @@
     return mState.mFramebuffers->isFramebufferGenerated(framebuffer);
 }
 
+bool ValidationContext::usingDisplayTextureShareGroup() const
+{
+    return mDisplayTextureShareGroup;
+}
+
 }  // namespace gl
diff --git a/src/libANGLE/ContextState.h b/src/libANGLE/ContextState.h
index 5c384a2..7af0e9c 100644
--- a/src/libANGLE/ContextState.h
+++ b/src/libANGLE/ContextState.h
@@ -35,6 +35,7 @@
   public:
     ContextState(uintptr_t context,
                  const ContextState *shareContextState,
+                 TextureManager *shareTextures,
                  const Version &clientVersion,
                  State *state,
                  const Caps &caps,
@@ -55,6 +56,8 @@
 
     const TextureCaps &getTextureCap(GLenum internalFormat) const;
 
+    bool usingDisplayTextureShareGroup() const;
+
   private:
     friend class Context;
     friend class ValidationContext;
@@ -81,6 +84,7 @@
 {
   public:
     ValidationContext(const ValidationContext *shareContext,
+                      TextureManager *shareTextures,
                       const Version &clientVersion,
                       State *state,
                       const Caps &caps,
@@ -115,9 +119,12 @@
     bool isRenderbufferGenerated(GLuint renderbuffer) const;
     bool isFramebufferGenerated(GLuint framebuffer) const;
 
+    bool usingDisplayTextureShareGroup() const;
+
   protected:
     ContextState mState;
     bool mSkipValidation;
+    bool mDisplayTextureShareGroup;
 };
 }  // namespace gl
 
diff --git a/src/libANGLE/Display.cpp b/src/libANGLE/Display.cpp
index 2a6b65b..0cb7621 100644
--- a/src/libANGLE/Display.cpp
+++ b/src/libANGLE/Display.cpp
@@ -29,6 +29,7 @@
 #include "libANGLE/Image.h"
 #include "libANGLE/Surface.h"
 #include "libANGLE/Stream.h"
+#include "libANGLE/ResourceManager.h"
 #include "libANGLE/renderer/DisplayImpl.h"
 #include "libANGLE/renderer/ImageImpl.h"
 #include "third_party/trace_event/trace_event.h"
@@ -358,7 +359,8 @@
       mDisplayExtensionString(),
       mVendorString(),
       mDevice(eglDevice),
-      mPlatform(platform)
+      mPlatform(platform),
+      mTextureManager(nullptr)
 {
 }
 
@@ -462,6 +464,9 @@
         ASSERT(mDevice != nullptr);
     }
 
+    ASSERT(mTextureManager == nullptr);
+    mTextureManager = new gl::TextureManager();
+
     mInitialized = true;
 
     return egl::Error(EGL_SUCCESS);
@@ -469,6 +474,12 @@
 
 void Display::terminate()
 {
+    if (mTextureManager)
+    {
+        mTextureManager->release();
+        mTextureManager = nullptr;
+    }
+
     makeCurrent(nullptr, nullptr, nullptr);
 
     while (!mContextSet.empty())
@@ -673,8 +684,12 @@
         ANGLE_TRY(restoreLostDevice());
     }
 
-    gl::Context *context =
-        new gl::Context(mImplementation, configuration, shareContext, attribs, mDisplayExtensions);
+    bool usingDisplayTextureShareGroup =
+        attribs.get(EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_FALSE) == EGL_TRUE;
+    gl::TextureManager *shareTextures = usingDisplayTextureShareGroup ? mTextureManager : nullptr;
+
+    gl::Context *context = new gl::Context(mImplementation, configuration, shareContext,
+                                           shareTextures, attribs, mDisplayExtensions);
 
     ASSERT(context != nullptr);
     mContextSet.insert(context);
diff --git a/src/libANGLE/Display.h b/src/libANGLE/Display.h
index 5b61ce7..767e322 100644
--- a/src/libANGLE/Display.h
+++ b/src/libANGLE/Display.h
@@ -24,6 +24,7 @@
 namespace gl
 {
 class Context;
+class TextureManager;
 }
 
 namespace rx
@@ -172,6 +173,8 @@
     Device *mDevice;
     EGLenum mPlatform;
     angle::LoggingAnnotator mAnnotator;
+
+    gl::TextureManager *mTextureManager;
 };
 
 }
diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
index 357b2bd..a50ce00 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
@@ -1099,6 +1099,9 @@
 
     outExtensions->flexibleSurfaceCompatibility = true;
     outExtensions->directComposition            = !!mDCompModule;
+
+    // Contexts are virtualized so textures can be shared globally
+    outExtensions->displayTextureShareGroup = true;
 }
 
 gl::Error Renderer11::flush()
diff --git a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
index 4ec64fc..4d1b67f 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
+++ b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
@@ -540,6 +540,9 @@
     outExtensions->glRenderbufferImage = true;
 
     outExtensions->flexibleSurfaceCompatibility = true;
+
+    // Contexts are virtualized so textures can be shared globally
+    outExtensions->displayTextureShareGroup = true;
 }
 
 void Renderer9::startScene()
diff --git a/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm b/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm
index 41df548..e1e344e 100644
--- a/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm
+++ b/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm
@@ -246,6 +246,9 @@
 void DisplayCGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
 {
     outExtensions->surfacelessContext = true;
+
+    // Contexts are virtualized so textures can be shared globally
+    outExtensions->displayTextureShareGroup = true;
 }
 
 void DisplayCGL::generateCaps(egl::Caps *outCaps) const
diff --git a/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp b/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp
index 34ca22d..d7215d0 100644
--- a/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp
+++ b/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp
@@ -102,6 +102,9 @@
         mEGL->hasExtension("EGL_EXT_create_context_robustness");
 
     outExtensions->postSubBuffer = false;  // Since SurfaceEGL::postSubBuffer is not implemented
+
+    // Contexts are virtualized so textures can be shared globally
+    outExtensions->displayTextureShareGroup = true;
 }
 
 void DisplayEGL::generateCaps(egl::Caps *outCaps) const
diff --git a/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp b/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp
index 3654e09..858481b 100644
--- a/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp
+++ b/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp
@@ -891,6 +891,9 @@
 void DisplayGLX::generateExtensions(egl::DisplayExtensions *outExtensions) const
 {
     outExtensions->createContextRobustness = mHasARBCreateContextRobustness;
+
+    // Contexts are virtualized so textures can be shared globally
+    outExtensions->displayTextureShareGroup = true;
 }
 
 void DisplayGLX::generateCaps(egl::Caps *outCaps) const
diff --git a/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp b/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp
index f135cc7..8eb51b8 100644
--- a/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp
+++ b/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp
@@ -660,6 +660,9 @@
     outExtensions->createContextRobustness = mHasRobustness;
 
     outExtensions->d3dTextureClientBuffer = mFunctionsWGL->hasExtension("WGL_NV_DX_interop2");
+
+    // Contexts are virtualized so textures can be shared globally
+    outExtensions->displayTextureShareGroup = true;
 }
 
 void DisplayWGL::generateCaps(egl::Caps *outCaps) const
diff --git a/src/libANGLE/validationEGL.cpp b/src/libANGLE/validationEGL.cpp
index 1e6bfe3..83e41a0 100644
--- a/src/libANGLE/validationEGL.cpp
+++ b/src/libANGLE/validationEGL.cpp
@@ -427,8 +427,30 @@
               }
               break;
 
+          case EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE:
+              if (!display->getExtensions().displayTextureShareGroup)
+              {
+                  return Error(EGL_BAD_ATTRIBUTE,
+                               "Attribute EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE requires "
+                               "EGL_ANGLE_display_texture_share_group.");
+              }
+              if (value != EGL_TRUE && value != EGL_FALSE)
+              {
+                  return Error(
+                      EGL_BAD_ATTRIBUTE,
+                      "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE must be EGL_TRUE or EGL_FALSE.");
+              }
+              if (shareContext &&
+                  (shareContext->usingDisplayTextureShareGroup() != (value == EGL_TRUE)))
+              {
+                  return Error(EGL_BAD_ATTRIBUTE,
+                               "All contexts within a share group must be created with the same "
+                               "value of EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE.");
+              }
+              break;
+
           default:
-            return Error(EGL_BAD_ATTRIBUTE);
+              return Error(EGL_BAD_ATTRIBUTE, "Unknown attribute.");
         }
     }
 
diff --git a/src/libANGLE/validationES_unittest.cpp b/src/libANGLE/validationES_unittest.cpp
index 7a23026..586bd71 100644
--- a/src/libANGLE/validationES_unittest.cpp
+++ b/src/libANGLE/validationES_unittest.cpp
@@ -31,6 +31,7 @@
 {
   public:
     MockValidationContext(const ValidationContext *shareContext,
+                          TextureManager *shareTextures,
                           const Version &version,
                           State *state,
                           const Caps &caps,
@@ -39,6 +40,7 @@
                           const Limitations &limitations,
                           bool skipValidation)
         : ValidationContext(shareContext,
+                            shareTextures,
                             version,
                             state,
                             caps,
@@ -97,8 +99,8 @@
     state.setDrawFramebufferBinding(framebuffer);
     state.setProgram(program);
 
-    NiceMock<MockValidationContext> testContext(nullptr, Version(3, 0), &state, caps, textureCaps,
-                                                extensions, limitations, false);
+    NiceMock<MockValidationContext> testContext(nullptr, nullptr, Version(3, 0), &state, caps,
+                                                textureCaps, extensions, limitations, false);
 
     // Set the expectation for the validation error here.
     Error expectedError(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage);
diff --git a/src/tests/egl_tests/EGLContextSharingTest.cpp b/src/tests/egl_tests/EGLContextSharingTest.cpp
index fc66b79..ce1bd83 100644
--- a/src/tests/egl_tests/EGLContextSharingTest.cpp
+++ b/src/tests/egl_tests/EGLContextSharingTest.cpp
@@ -82,6 +82,128 @@
     ASSERT_GL_NO_ERROR();
 }
 
+// Tests the creation of contexts using EGL_ANGLE_display_texture_share_group
+TEST_P(EGLContextSharingTest, DisplayShareGroupContextCreation)
+{
+    EGLDisplay display = getEGLWindow()->getDisplay();
+    EGLConfig config   = getEGLWindow()->getConfig();
+
+    const EGLint inShareGroupContextAttribs[] = {
+        EGL_CONTEXT_CLIENT_VERSION, 2, EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_TRUE, EGL_NONE};
+
+    // Test creating two contexts in the global share group
+    mContexts[0] = eglCreateContext(display, config, nullptr, inShareGroupContextAttribs);
+    mContexts[1] = eglCreateContext(display, config, mContexts[1], inShareGroupContextAttribs);
+
+    if (!ANGLETest::eglDisplayExtensionEnabled(display, "EGL_ANGLE_display_texture_share_group"))
+    {
+        // Make sure an error is generated and early-exit
+        ASSERT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
+        ASSERT_EQ(EGL_NO_CONTEXT, mContexts[0]);
+        return;
+    }
+
+    ASSERT_EGL_SUCCESS();
+
+    ASSERT_NE(EGL_NO_CONTEXT, mContexts[0]);
+    ASSERT_NE(EGL_NO_CONTEXT, mContexts[1]);
+    eglDestroyContext(display, mContexts[0]);
+
+    // Try creating a context that is not in the global share group but tries to share with a
+    // context that is
+    const EGLint notInShareGroupContextAttribs[] = {
+        EGL_CONTEXT_CLIENT_VERSION, 2, EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_FALSE, EGL_NONE};
+    mContexts[1] = eglCreateContext(display, config, mContexts[1], notInShareGroupContextAttribs);
+    ASSERT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
+    ASSERT_TRUE(mContexts[1] == EGL_NO_CONTEXT);
+}
+
+// Tests the sharing of textures using EGL_ANGLE_display_texture_share_group
+TEST_P(EGLContextSharingTest, DisplayShareGroupObjectSharing)
+{
+    EGLDisplay display = getEGLWindow()->getDisplay();
+    if (!ANGLETest::eglDisplayExtensionEnabled(display, "EGL_ANGLE_display_texture_share_group"))
+    {
+        std::cout << "Test skipped because EGL_ANGLE_display_texture_share_group is not present."
+                  << std::endl;
+        return;
+    }
+
+    EGLConfig config   = getEGLWindow()->getConfig();
+    EGLSurface surface = getEGLWindow()->getSurface();
+
+    const EGLint inShareGroupContextAttribs[] = {
+        EGL_CONTEXT_CLIENT_VERSION, 2, EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_TRUE, EGL_NONE};
+
+    // Create two contexts in the global share group but not in the same context share group
+    mContexts[0] = eglCreateContext(display, config, nullptr, inShareGroupContextAttribs);
+    mContexts[1] = eglCreateContext(display, config, nullptr, inShareGroupContextAttribs);
+
+    ASSERT_EGL_SUCCESS();
+
+    ASSERT_NE(EGL_NO_CONTEXT, mContexts[0]);
+    ASSERT_NE(EGL_NO_CONTEXT, mContexts[1]);
+
+    ASSERT_EGL_TRUE(eglMakeCurrent(display, surface, surface, mContexts[0]));
+    ASSERT_EGL_SUCCESS();
+
+    // Create a texture and buffer in ctx 0
+    GLuint textureFromCtx0 = 0;
+    glGenTextures(1, &textureFromCtx0);
+    glBindTexture(GL_TEXTURE_2D, textureFromCtx0);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glBindTexture(GL_TEXTURE_2D, 0);
+    ASSERT_GL_TRUE(glIsTexture(textureFromCtx0));
+
+    GLuint bufferFromCtx0 = 0;
+    glGenBuffers(1, &bufferFromCtx0);
+    glBindBuffer(GL_ARRAY_BUFFER, bufferFromCtx0);
+    glBufferData(GL_ARRAY_BUFFER, 1, nullptr, GL_STATIC_DRAW);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    ASSERT_GL_TRUE(glIsBuffer(bufferFromCtx0));
+
+    ASSERT_GL_NO_ERROR();
+
+    // Switch to context 1 and verify that the texture is accessible but the buffer is not
+    ASSERT_EGL_TRUE(eglMakeCurrent(display, surface, surface, mContexts[1]));
+    ASSERT_EGL_SUCCESS();
+
+    ASSERT_GL_TRUE(glIsTexture(textureFromCtx0));
+
+    ASSERT_GL_FALSE(glIsBuffer(bufferFromCtx0));
+    glDeleteBuffers(1, &bufferFromCtx0);
+    ASSERT_GL_NO_ERROR();
+
+    // Call readpixels on the texture to verify that the backend has proper support
+    GLuint fbo = 0;
+    glGenFramebuffers(1, &fbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureFromCtx0, 0);
+
+    GLubyte pixel[4];
+    glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
+    ASSERT_GL_NO_ERROR();
+
+    glDeleteFramebuffers(1, &fbo);
+
+    glDeleteTextures(1, &textureFromCtx0);
+    ASSERT_GL_NO_ERROR();
+    ASSERT_GL_FALSE(glIsTexture(textureFromCtx0));
+
+    // Switch back to context 0 and delete the buffer
+    ASSERT_EGL_TRUE(eglMakeCurrent(display, surface, surface, mContexts[0]));
+    ASSERT_EGL_SUCCESS();
+
+    ASSERT_GL_TRUE(glIsBuffer(bufferFromCtx0));
+    glDeleteBuffers(1, &bufferFromCtx0);
+    ASSERT_GL_NO_ERROR();
+}
+
 }  // anonymous namespace
 
-ANGLE_INSTANTIATE_TEST(EGLContextSharingTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL());
+ANGLE_INSTANTIATE_TEST(EGLContextSharingTest,
+                       ES2_D3D9(),
+                       ES2_D3D11(),
+                       ES3_D3D11(),
+                       ES2_OPENGL(),
+                       ES3_OPENGL());
diff --git a/src/tests/test_utils/ANGLETest.h b/src/tests/test_utils/ANGLETest.h
index 07b2d2f..fbe4dbc 100644
--- a/src/tests/test_utils/ANGLETest.h
+++ b/src/tests/test_utils/ANGLETest.h
@@ -21,6 +21,11 @@
 #include "shader_utils.h"
 #include "system_utils.h"
 
+#define ASSERT_GL_TRUE(a) ASSERT_EQ(static_cast<GLboolean>(GL_TRUE), (a))
+#define ASSERT_GL_FALSE(a) ASSERT_EQ(static_cast<GLboolean>(GL_FALSE), (a))
+#define EXPECT_GL_TRUE(a) EXPECT_EQ(static_cast<GLboolean>(GL_TRUE), (a))
+#define EXPECT_GL_FALSE(a) EXPECT_EQ(static_cast<GLboolean>(GL_FALSE), (a))
+
 #define EXPECT_GL_ERROR(err) EXPECT_EQ(static_cast<GLenum>(err), glGetError())
 #define EXPECT_GL_NO_ERROR() EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError())