summaryrefslogtreecommitdiffstats
path: root/gfx/angle/src/tests/test_utils
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/src/tests/test_utils')
-rwxr-xr-xgfx/angle/src/tests/test_utils/ANGLETest.cpp863
-rwxr-xr-xgfx/angle/src/tests/test_utils/ANGLETest.h274
-rwxr-xr-xgfx/angle/src/tests/test_utils/angle_test_configs.cpp598
-rwxr-xr-xgfx/angle/src/tests/test_utils/angle_test_configs.h144
-rwxr-xr-xgfx/angle/src/tests/test_utils/angle_test_instantiate.cpp88
-rwxr-xr-xgfx/angle/src/tests/test_utils/angle_test_instantiate.h52
-rwxr-xr-xgfx/angle/src/tests/test_utils/compiler_test.cpp256
-rwxr-xr-xgfx/angle/src/tests/test_utils/compiler_test.h103
-rwxr-xr-xgfx/angle/src/tests/test_utils/gl_raii.h96
9 files changed, 2474 insertions, 0 deletions
diff --git a/gfx/angle/src/tests/test_utils/ANGLETest.cpp b/gfx/angle/src/tests/test_utils/ANGLETest.cpp
new file mode 100755
index 000000000..77f1d8dec
--- /dev/null
+++ b/gfx/angle/src/tests/test_utils/ANGLETest.cpp
@@ -0,0 +1,863 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ANGLETest:
+// Implementation of common ANGLE testing fixture.
+//
+
+#include "ANGLETest.h"
+#include "EGLWindow.h"
+#include "OSWindow.h"
+#include "platform/Platform.h"
+
+namespace angle
+{
+
+const GLColorRGB GLColorRGB::black(0u, 0u, 0u);
+const GLColorRGB GLColorRGB::blue(0u, 0u, 255u);
+const GLColorRGB GLColorRGB::green(0u, 255u, 0u);
+const GLColorRGB GLColorRGB::red(255u, 0u, 0u);
+const GLColorRGB GLColorRGB::yellow(255u, 255u, 0);
+
+const GLColor GLColor::black = GLColor(0u, 0u, 0u, 255u);
+const GLColor GLColor::blue = GLColor(0u, 0u, 255u, 255u);
+const GLColor GLColor::cyan = GLColor(0u, 255u, 255u, 255u);
+const GLColor GLColor::green = GLColor(0u, 255u, 0u, 255u);
+const GLColor GLColor::red = GLColor(255u, 0u, 0u, 255u);
+const GLColor GLColor::transparentBlack = GLColor(0u, 0u, 0u, 0u);
+const GLColor GLColor::white = GLColor(255u, 255u, 255u, 255u);
+const GLColor GLColor::yellow = GLColor(255u, 255u, 0, 255u);
+
+namespace
+{
+float ColorNorm(GLubyte channelValue)
+{
+ return static_cast<float>(channelValue) / 255.0f;
+}
+
+GLubyte ColorDenorm(float colorValue)
+{
+ return static_cast<GLubyte>(colorValue * 255.0f);
+}
+
+// Use a custom ANGLE platform class to capture and report internal errors.
+class TestPlatform : public angle::Platform
+{
+ public:
+ TestPlatform() : mIgnoreMessages(false) {}
+
+ void logError(const char *errorMessage) override;
+ void logWarning(const char *warningMessage) override;
+ void logInfo(const char *infoMessage) override;
+
+ void ignoreMessages();
+ void enableMessages();
+
+ private:
+ bool mIgnoreMessages;
+};
+
+void TestPlatform::logError(const char *errorMessage)
+{
+ if (mIgnoreMessages)
+ return;
+
+ FAIL() << errorMessage;
+}
+
+void TestPlatform::logWarning(const char *warningMessage)
+{
+ if (mIgnoreMessages)
+ return;
+
+ std::cerr << "Warning: " << warningMessage << std::endl;
+}
+
+void TestPlatform::logInfo(const char *infoMessage)
+{
+ if (mIgnoreMessages)
+ return;
+
+ angle::WriteDebugMessage("%s\n", infoMessage);
+}
+
+void TestPlatform::ignoreMessages()
+{
+ mIgnoreMessages = true;
+}
+
+void TestPlatform::enableMessages()
+{
+ mIgnoreMessages = false;
+}
+
+TestPlatform g_testPlatformInstance;
+
+std::array<Vector3, 4> GetIndexedQuadVertices()
+{
+ std::array<Vector3, 4> vertices;
+ vertices[0] = Vector3(-1.0f, 1.0f, 0.5f);
+ vertices[1] = Vector3(-1.0f, -1.0f, 0.5f);
+ vertices[2] = Vector3(1.0f, -1.0f, 0.5f);
+ vertices[3] = Vector3(1.0f, 1.0f, 0.5f);
+ return vertices;
+}
+
+} // anonymous namespace
+
+GLColorRGB::GLColorRGB() : R(0), G(0), B(0)
+{
+}
+
+GLColorRGB::GLColorRGB(GLubyte r, GLubyte g, GLubyte b) : R(r), G(g), B(b)
+{
+}
+
+GLColorRGB::GLColorRGB(const Vector3 &floatColor)
+ : R(ColorDenorm(floatColor.x)), G(ColorDenorm(floatColor.y)), B(ColorDenorm(floatColor.z))
+{
+}
+
+GLColor::GLColor() : R(0), G(0), B(0), A(0)
+{
+}
+
+GLColor::GLColor(GLubyte r, GLubyte g, GLubyte b, GLubyte a) : R(r), G(g), B(b), A(a)
+{
+}
+
+GLColor::GLColor(const Vector4 &floatColor)
+ : R(ColorDenorm(floatColor.x)),
+ G(ColorDenorm(floatColor.y)),
+ B(ColorDenorm(floatColor.z)),
+ A(ColorDenorm(floatColor.w))
+{
+}
+
+GLColor::GLColor(GLuint colorValue) : R(0), G(0), B(0), A(0)
+{
+ memcpy(&R, &colorValue, sizeof(GLuint));
+}
+
+Vector4 GLColor::toNormalizedVector() const
+{
+ return Vector4(ColorNorm(R), ColorNorm(G), ColorNorm(B), ColorNorm(A));
+}
+
+GLColor ReadColor(GLint x, GLint y)
+{
+ GLColor actual;
+ glReadPixels((x), (y), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &actual.R);
+ EXPECT_GL_NO_ERROR();
+ return actual;
+}
+
+bool operator==(const GLColor &a, const GLColor &b)
+{
+ return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;
+}
+
+std::ostream &operator<<(std::ostream &ostream, const GLColor &color)
+{
+ ostream << "(" << static_cast<unsigned int>(color.R) << ", "
+ << static_cast<unsigned int>(color.G) << ", " << static_cast<unsigned int>(color.B)
+ << ", " << static_cast<unsigned int>(color.A) << ")";
+ return ostream;
+}
+
+} // namespace angle
+
+// static
+std::array<Vector3, 6> ANGLETest::GetQuadVertices()
+{
+ std::array<Vector3, 6> vertices;
+ vertices[0] = Vector3(-1.0f, 1.0f, 0.5f);
+ vertices[1] = Vector3(-1.0f, -1.0f, 0.5f);
+ vertices[2] = Vector3(1.0f, -1.0f, 0.5f);
+ vertices[3] = Vector3(-1.0f, 1.0f, 0.5f);
+ vertices[4] = Vector3(1.0f, -1.0f, 0.5f);
+ vertices[5] = Vector3(1.0f, 1.0f, 0.5f);
+ return vertices;
+}
+
+ANGLETest::ANGLETest()
+ : mEGLWindow(nullptr),
+ mWidth(16),
+ mHeight(16),
+ mIgnoreD3D11SDKLayersWarnings(false),
+ mQuadVertexBuffer(0)
+{
+ mEGLWindow =
+ new EGLWindow(GetParam().majorVersion, GetParam().minorVersion, GetParam().eglParameters);
+}
+
+ANGLETest::~ANGLETest()
+{
+ if (mQuadVertexBuffer)
+ {
+ glDeleteBuffers(1, &mQuadVertexBuffer);
+ }
+ SafeDelete(mEGLWindow);
+}
+
+void ANGLETest::SetUp()
+{
+ angle::g_testPlatformInstance.enableMessages();
+
+ // Resize the window before creating the context so that the first make current
+ // sets the viewport and scissor box to the right size.
+ bool needSwap = false;
+ if (mOSWindow->getWidth() != mWidth || mOSWindow->getHeight() != mHeight)
+ {
+ if (!mOSWindow->resize(mWidth, mHeight))
+ {
+ FAIL() << "Failed to resize ANGLE test window.";
+ }
+ needSwap = true;
+ }
+
+ if (!createEGLContext())
+ {
+ FAIL() << "egl context creation failed.";
+ }
+
+ if (needSwap)
+ {
+ // Swap the buffers so that the default framebuffer picks up the resize
+ // which will allow follow-up test code to assume the framebuffer covers
+ // the whole window.
+ swapBuffers();
+ }
+
+ // This Viewport command is not strictly necessary but we add it so that programs
+ // taking OpenGL traces can guess the size of the default framebuffer and show it
+ // in their UIs
+ glViewport(0, 0, mWidth, mHeight);
+
+ const auto &info = testing::UnitTest::GetInstance()->current_test_info();
+ angle::WriteDebugMessage("Entering %s.%s\n", info->test_case_name(), info->name());
+}
+
+void ANGLETest::TearDown()
+{
+ checkD3D11SDKLayersMessages();
+
+ const auto &info = testing::UnitTest::GetInstance()->current_test_info();
+ angle::WriteDebugMessage("Exiting %s.%s\n", info->test_case_name(), info->name());
+
+ swapBuffers();
+ mOSWindow->messageLoop();
+
+ if (!destroyEGLContext())
+ {
+ FAIL() << "egl context destruction failed.";
+ }
+
+ // Check for quit message
+ Event myEvent;
+ while (mOSWindow->popEvent(&myEvent))
+ {
+ if (myEvent.Type == Event::EVENT_CLOSED)
+ {
+ exit(0);
+ }
+ }
+}
+
+void ANGLETest::swapBuffers()
+{
+ if (mEGLWindow->isGLInitialized())
+ {
+ mEGLWindow->swap();
+ }
+}
+
+void ANGLETest::setupQuadVertexBuffer(GLfloat positionAttribZ, GLfloat positionAttribXYScale)
+{
+ if (mQuadVertexBuffer == 0)
+ {
+ glGenBuffers(1, &mQuadVertexBuffer);
+ }
+
+ auto quadVertices = GetQuadVertices();
+ for (Vector3 &vertex : quadVertices)
+ {
+ vertex.x *= positionAttribXYScale;
+ vertex.y *= positionAttribXYScale;
+ vertex.z = positionAttribZ;
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, mQuadVertexBuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 6, quadVertices.data(), GL_STATIC_DRAW);
+}
+
+void ANGLETest::setupIndexedQuadVertexBuffer(GLfloat positionAttribZ, GLfloat positionAttribXYScale)
+{
+ if (mQuadVertexBuffer == 0)
+ {
+ glGenBuffers(1, &mQuadVertexBuffer);
+ }
+
+ auto quadVertices = angle::GetIndexedQuadVertices();
+ for (Vector3 &vertex : quadVertices)
+ {
+ vertex.x *= positionAttribXYScale;
+ vertex.y *= positionAttribXYScale;
+ vertex.z = positionAttribZ;
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, mQuadVertexBuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 4, quadVertices.data(), GL_STATIC_DRAW);
+}
+
+// static
+void ANGLETest::drawQuad(GLuint program,
+ const std::string &positionAttribName,
+ GLfloat positionAttribZ)
+{
+ drawQuad(program, positionAttribName, positionAttribZ, 1.0f);
+}
+
+// static
+void ANGLETest::drawQuad(GLuint program,
+ const std::string &positionAttribName,
+ GLfloat positionAttribZ,
+ GLfloat positionAttribXYScale)
+{
+ drawQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale, false);
+}
+
+void ANGLETest::drawQuad(GLuint program,
+ const std::string &positionAttribName,
+ GLfloat positionAttribZ,
+ GLfloat positionAttribXYScale,
+ bool useVertexBuffer)
+{
+ GLint previousProgram = 0;
+ glGetIntegerv(GL_CURRENT_PROGRAM, &previousProgram);
+ if (previousProgram != static_cast<GLint>(program))
+ {
+ glUseProgram(program);
+ }
+
+ GLint positionLocation = glGetAttribLocation(program, positionAttribName.c_str());
+
+ if (useVertexBuffer)
+ {
+ setupQuadVertexBuffer(positionAttribZ, positionAttribXYScale);
+ glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+ else
+ {
+ auto quadVertices = GetQuadVertices();
+ for (Vector3 &vertex : quadVertices)
+ {
+ vertex.x *= positionAttribXYScale;
+ vertex.y *= positionAttribXYScale;
+ vertex.z = positionAttribZ;
+ }
+
+ glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
+ }
+ glEnableVertexAttribArray(positionLocation);
+
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+
+ glDisableVertexAttribArray(positionLocation);
+ glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, NULL);
+
+ if (previousProgram != static_cast<GLint>(program))
+ {
+ glUseProgram(previousProgram);
+ }
+}
+
+void ANGLETest::drawIndexedQuad(GLuint program,
+ const std::string &positionAttribName,
+ GLfloat positionAttribZ)
+{
+ drawIndexedQuad(program, positionAttribName, positionAttribZ, 1.0f);
+}
+
+void ANGLETest::drawIndexedQuad(GLuint program,
+ const std::string &positionAttribName,
+ GLfloat positionAttribZ,
+ GLfloat positionAttribXYScale)
+{
+ GLint positionLocation = glGetAttribLocation(program, positionAttribName.c_str());
+
+ GLint activeProgram = 0;
+ glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram);
+ if (static_cast<GLuint>(activeProgram) != program)
+ {
+ glUseProgram(program);
+ }
+
+ GLuint prevBinding = 0;
+ glGetIntegerv(GL_ARRAY_BUFFER_BINDING, reinterpret_cast<GLint *>(&prevBinding));
+
+ setupIndexedQuadVertexBuffer(positionAttribZ, positionAttribXYScale);
+
+ glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
+ glEnableVertexAttribArray(positionLocation);
+ glBindBuffer(GL_ARRAY_BUFFER, prevBinding);
+
+ const GLushort indices[] = {
+ 0, 1, 2, 0, 2, 3,
+ };
+
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+
+ glDisableVertexAttribArray(positionLocation);
+ glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, NULL);
+
+ if (static_cast<GLuint>(activeProgram) != program)
+ {
+ glUseProgram(static_cast<GLuint>(activeProgram));
+ }
+}
+
+GLuint ANGLETest::compileShader(GLenum type, const std::string &source)
+{
+ GLuint shader = glCreateShader(type);
+
+ const char *sourceArray[1] = { source.c_str() };
+ glShaderSource(shader, 1, sourceArray, NULL);
+ glCompileShader(shader);
+
+ GLint compileResult;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
+
+ if (compileResult == 0)
+ {
+ GLint infoLogLength;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+ if (infoLogLength == 0)
+ {
+ std::cerr << "shader compilation failed with empty log." << std::endl;
+ }
+ else
+ {
+ std::vector<GLchar> infoLog(infoLogLength);
+ glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), NULL, &infoLog[0]);
+
+ std::cerr << "shader compilation failed: " << &infoLog[0];
+ }
+
+ glDeleteShader(shader);
+ shader = 0;
+ }
+
+ return shader;
+}
+
+void ANGLETest::checkD3D11SDKLayersMessages()
+{
+#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(NDEBUG)
+ // In debug D3D11 mode, check ID3D11InfoQueue to see if any D3D11 SDK Layers messages
+ // were outputted by the test
+ if (mIgnoreD3D11SDKLayersWarnings ||
+ mEGLWindow->getPlatform().renderer != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE ||
+ mEGLWindow->getDisplay() == EGL_NO_DISPLAY)
+ {
+ return;
+ }
+
+ const char *extensionString =
+ static_cast<const char *>(eglQueryString(mEGLWindow->getDisplay(), EGL_EXTENSIONS));
+ if (!strstr(extensionString, "EGL_EXT_device_query"))
+ {
+ return;
+ }
+
+ EGLAttrib device = 0;
+ EGLAttrib angleDevice = 0;
+
+ PFNEGLQUERYDISPLAYATTRIBEXTPROC queryDisplayAttribEXT;
+ PFNEGLQUERYDEVICEATTRIBEXTPROC queryDeviceAttribEXT;
+
+ queryDisplayAttribEXT = reinterpret_cast<PFNEGLQUERYDISPLAYATTRIBEXTPROC>(
+ eglGetProcAddress("eglQueryDisplayAttribEXT"));
+ queryDeviceAttribEXT = reinterpret_cast<PFNEGLQUERYDEVICEATTRIBEXTPROC>(
+ eglGetProcAddress("eglQueryDeviceAttribEXT"));
+ ASSERT_NE(nullptr, queryDisplayAttribEXT);
+ ASSERT_NE(nullptr, queryDeviceAttribEXT);
+
+ ASSERT_EGL_TRUE(queryDisplayAttribEXT(mEGLWindow->getDisplay(), EGL_DEVICE_EXT, &angleDevice));
+ ASSERT_EGL_TRUE(queryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice),
+ EGL_D3D11_DEVICE_ANGLE, &device));
+ ID3D11Device *d3d11Device = reinterpret_cast<ID3D11Device *>(device);
+
+ ID3D11InfoQueue *infoQueue = nullptr;
+ HRESULT hr =
+ d3d11Device->QueryInterface(__uuidof(infoQueue), reinterpret_cast<void **>(&infoQueue));
+ if (SUCCEEDED(hr))
+ {
+ UINT64 numStoredD3DDebugMessages =
+ infoQueue->GetNumStoredMessagesAllowedByRetrievalFilter();
+
+ if (numStoredD3DDebugMessages > 0)
+ {
+ for (UINT64 i = 0; i < numStoredD3DDebugMessages; i++)
+ {
+ SIZE_T messageLength = 0;
+ hr = infoQueue->GetMessage(i, nullptr, &messageLength);
+
+ if (SUCCEEDED(hr))
+ {
+ D3D11_MESSAGE *pMessage =
+ reinterpret_cast<D3D11_MESSAGE *>(malloc(messageLength));
+ infoQueue->GetMessage(i, pMessage, &messageLength);
+
+ std::cout << "Message " << i << ":"
+ << " " << pMessage->pDescription << "\n";
+ free(pMessage);
+ }
+ }
+
+ FAIL() << numStoredD3DDebugMessages
+ << " D3D11 SDK Layers message(s) detected! Test Failed.\n";
+ }
+ }
+
+ SafeRelease(infoQueue);
+#endif
+}
+
+static bool checkExtensionExists(const char *allExtensions, const std::string &extName)
+{
+ return strstr(allExtensions, extName.c_str()) != nullptr;
+}
+
+bool ANGLETest::extensionEnabled(const std::string &extName)
+{
+ return checkExtensionExists(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)),
+ extName);
+}
+
+bool ANGLETest::eglDisplayExtensionEnabled(EGLDisplay display, const std::string &extName)
+{
+ return checkExtensionExists(eglQueryString(display, EGL_EXTENSIONS), extName);
+}
+
+bool ANGLETest::eglClientExtensionEnabled(const std::string &extName)
+{
+ return checkExtensionExists(eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS), extName);
+}
+
+bool ANGLETest::eglDeviceExtensionEnabled(EGLDeviceEXT device, const std::string &extName)
+{
+ PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT =
+ reinterpret_cast<PFNEGLQUERYDEVICESTRINGEXTPROC>(
+ eglGetProcAddress("eglQueryDeviceStringEXT"));
+ return checkExtensionExists(eglQueryDeviceStringEXT(device, EGL_EXTENSIONS), extName);
+}
+
+void ANGLETest::setWindowWidth(int width)
+{
+ mWidth = width;
+}
+
+void ANGLETest::setWindowHeight(int height)
+{
+ mHeight = height;
+}
+
+void ANGLETest::setConfigRedBits(int bits)
+{
+ mEGLWindow->setConfigRedBits(bits);
+}
+
+void ANGLETest::setConfigGreenBits(int bits)
+{
+ mEGLWindow->setConfigGreenBits(bits);
+}
+
+void ANGLETest::setConfigBlueBits(int bits)
+{
+ mEGLWindow->setConfigBlueBits(bits);
+}
+
+void ANGLETest::setConfigAlphaBits(int bits)
+{
+ mEGLWindow->setConfigAlphaBits(bits);
+}
+
+void ANGLETest::setConfigDepthBits(int bits)
+{
+ mEGLWindow->setConfigDepthBits(bits);
+}
+
+void ANGLETest::setConfigStencilBits(int bits)
+{
+ mEGLWindow->setConfigStencilBits(bits);
+}
+
+void ANGLETest::setMultisampleEnabled(bool enabled)
+{
+ mEGLWindow->setMultisample(enabled);
+}
+
+void ANGLETest::setDebugEnabled(bool enabled)
+{
+ mEGLWindow->setDebugEnabled(enabled);
+}
+
+void ANGLETest::setNoErrorEnabled(bool enabled)
+{
+ mEGLWindow->setNoErrorEnabled(enabled);
+}
+
+void ANGLETest::setWebGLCompatibilityEnabled(bool webglCompatibility)
+{
+ mEGLWindow->setWebGLCompatibilityEnabled(webglCompatibility);
+}
+
+void ANGLETest::setBindGeneratesResource(bool bindGeneratesResource)
+{
+ mEGLWindow->setBindGeneratesResource(bindGeneratesResource);
+}
+
+int ANGLETest::getClientMajorVersion() const
+{
+ return mEGLWindow->getClientMajorVersion();
+}
+
+int ANGLETest::getClientMinorVersion() const
+{
+ return mEGLWindow->getClientMinorVersion();
+}
+
+EGLWindow *ANGLETest::getEGLWindow() const
+{
+ return mEGLWindow;
+}
+
+int ANGLETest::getWindowWidth() const
+{
+ return mWidth;
+}
+
+int ANGLETest::getWindowHeight() const
+{
+ return mHeight;
+}
+
+bool ANGLETest::isMultisampleEnabled() const
+{
+ return mEGLWindow->isMultisample();
+}
+
+bool ANGLETest::createEGLContext()
+{
+ return mEGLWindow->initializeGL(mOSWindow);
+}
+
+bool ANGLETest::destroyEGLContext()
+{
+ mEGLWindow->destroyGL();
+ return true;
+}
+
+bool ANGLETest::InitTestWindow()
+{
+ mOSWindow = CreateOSWindow();
+ if (!mOSWindow->initialize("ANGLE_TEST", 128, 128))
+ {
+ return false;
+ }
+
+ mOSWindow->setVisible(true);
+
+ return true;
+}
+
+bool ANGLETest::DestroyTestWindow()
+{
+ if (mOSWindow)
+ {
+ mOSWindow->destroy();
+ delete mOSWindow;
+ mOSWindow = NULL;
+ }
+
+ return true;
+}
+
+void ANGLETest::SetWindowVisible(bool isVisible)
+{
+ mOSWindow->setVisible(isVisible);
+}
+
+bool IsIntel()
+{
+ std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+ return (rendererString.find("Intel") != std::string::npos);
+}
+
+bool IsAdreno()
+{
+ std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+ return (rendererString.find("Adreno") != std::string::npos);
+}
+
+bool IsAMD()
+{
+ std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+ return (rendererString.find("AMD") != std::string::npos) ||
+ (rendererString.find("ATI") != std::string::npos);
+}
+
+bool IsNVIDIA()
+{
+ std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+ return (rendererString.find("NVIDIA") != std::string::npos);
+}
+
+bool IsD3D11()
+{
+ std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+ return (rendererString.find("Direct3D11 vs_5_0") != std::string::npos);
+}
+
+bool IsD3D11_FL93()
+{
+ std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+ return (rendererString.find("Direct3D11 vs_4_0_") != std::string::npos);
+}
+
+bool IsD3D9()
+{
+ std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+ return (rendererString.find("Direct3D9") != std::string::npos);
+}
+
+bool IsD3DSM3()
+{
+ return IsD3D9() || IsD3D11_FL93();
+}
+
+bool IsDesktopOpenGL()
+{
+ return IsOpenGL() && !IsOpenGLES();
+}
+
+bool IsOpenGLES()
+{
+ std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+ return (rendererString.find("OpenGL ES") != std::string::npos);
+}
+
+bool IsOpenGL()
+{
+ std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+ return (rendererString.find("OpenGL") != std::string::npos);
+}
+
+bool IsAndroid()
+{
+#if defined(ANGLE_PLATFORM_ANDROID)
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool IsLinux()
+{
+#if defined(ANGLE_PLATFORM_LINUX)
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool IsOSX()
+{
+#if defined(ANGLE_PLATFORM_APPLE)
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool IsWindows()
+{
+#if defined(ANGLE_PLATFORM_WINDOWS)
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool IsDebug()
+{
+#if !defined(NDEBUG)
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool IsRelease()
+{
+ return !IsDebug();
+}
+
+EGLint ANGLETest::getPlatformRenderer() const
+{
+ assert(mEGLWindow);
+ return mEGLWindow->getPlatform().renderer;
+}
+
+void ANGLETest::ignoreD3D11SDKLayersWarnings()
+{
+ // Some tests may need to disable the D3D11 SDK Layers Warnings checks
+ mIgnoreD3D11SDKLayersWarnings = true;
+}
+
+OSWindow *ANGLETest::mOSWindow = NULL;
+
+void ANGLETestEnvironment::SetUp()
+{
+ mGLESLibrary.reset(angle::loadLibrary("libGLESv2"));
+ if (mGLESLibrary)
+ {
+ auto initFunc = reinterpret_cast<ANGLEPlatformInitializeFunc>(
+ mGLESLibrary->getSymbol("ANGLEPlatformInitialize"));
+ if (initFunc)
+ {
+ initFunc(&angle::g_testPlatformInstance);
+ }
+ }
+
+ if (!ANGLETest::InitTestWindow())
+ {
+ FAIL() << "Failed to create ANGLE test window.";
+ }
+}
+
+void ANGLETestEnvironment::TearDown()
+{
+ ANGLETest::DestroyTestWindow();
+
+ if (mGLESLibrary)
+ {
+ auto shutdownFunc = reinterpret_cast<ANGLEPlatformShutdownFunc>(
+ mGLESLibrary->getSymbol("ANGLEPlatformShutdown"));
+ if (shutdownFunc)
+ {
+ shutdownFunc();
+ }
+ }
+}
+
+void IgnoreANGLEPlatformMessages()
+{
+ // Negative tests may trigger expected errors/warnings in the ANGLE Platform.
+ angle::g_testPlatformInstance.ignoreMessages();
+}
diff --git a/gfx/angle/src/tests/test_utils/ANGLETest.h b/gfx/angle/src/tests/test_utils/ANGLETest.h
new file mode 100755
index 000000000..a1bef48e6
--- /dev/null
+++ b/gfx/angle/src/tests/test_utils/ANGLETest.h
@@ -0,0 +1,274 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ANGLETest:
+// Implementation of common ANGLE testing fixture.
+//
+
+#ifndef ANGLE_TESTS_ANGLE_TEST_H_
+#define ANGLE_TESTS_ANGLE_TEST_H_
+
+#include <gtest/gtest.h>
+#include <algorithm>
+#include <array>
+
+#include "angle_gl.h"
+#include "angle_test_configs.h"
+#include "common/angleutils.h"
+#include "shader_utils.h"
+#include "system_utils.h"
+#include "Vector.h"
+
+#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())
+
+#define ASSERT_GL_ERROR(err) ASSERT_EQ(static_cast<GLenum>(err), glGetError())
+#define ASSERT_GL_NO_ERROR() ASSERT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError())
+
+#define EXPECT_EGL_ERROR(err) EXPECT_EQ((err), eglGetError())
+#define EXPECT_EGL_SUCCESS() EXPECT_EGL_ERROR(EGL_SUCCESS)
+
+// EGLBoolean is |unsigned int| but EGL_TRUE is 0, not 0u.
+#define ASSERT_EGL_TRUE(a) ASSERT_EQ(static_cast<EGLBoolean>(EGL_TRUE), (a))
+#define ASSERT_EGL_FALSE(a) ASSERT_EQ(static_cast<EGLBoolean>(EGL_FALSE), (a))
+#define EXPECT_EGL_TRUE(a) EXPECT_EQ(static_cast<EGLBoolean>(EGL_TRUE), (a))
+#define EXPECT_EGL_FALSE(a) EXPECT_EQ(static_cast<EGLBoolean>(EGL_FALSE), (a))
+
+#define ASSERT_EGL_ERROR(err) ASSERT_EQ((err), eglGetError())
+#define ASSERT_EGL_SUCCESS() ASSERT_EGL_ERROR(EGL_SUCCESS)
+
+#define ASSERT_GLENUM_EQ(expected, actual) ASSERT_EQ(static_cast<GLenum>(expected), static_cast<GLenum>(actual))
+#define EXPECT_GLENUM_EQ(expected, actual) EXPECT_EQ(static_cast<GLenum>(expected), static_cast<GLenum>(actual))
+
+namespace angle
+{
+struct GLColorRGB
+{
+ GLColorRGB();
+ GLColorRGB(GLubyte r, GLubyte g, GLubyte b);
+ GLColorRGB(const Vector3 &floatColor);
+
+ GLubyte R, G, B;
+
+ static const GLColorRGB black;
+ static const GLColorRGB blue;
+ static const GLColorRGB green;
+ static const GLColorRGB red;
+ static const GLColorRGB yellow;
+};
+
+struct GLColor
+{
+ GLColor();
+ GLColor(GLubyte r, GLubyte g, GLubyte b, GLubyte a);
+ GLColor(const Vector4 &floatColor);
+ GLColor(GLuint colorValue);
+
+ Vector4 toNormalizedVector() const;
+
+ GLubyte R, G, B, A;
+
+ static const GLColor black;
+ static const GLColor blue;
+ static const GLColor cyan;
+ static const GLColor green;
+ static const GLColor red;
+ static const GLColor transparentBlack;
+ static const GLColor white;
+ static const GLColor yellow;
+};
+
+// Useful to cast any type to GLubyte.
+template <typename TR, typename TG, typename TB, typename TA>
+GLColor MakeGLColor(TR r, TG g, TB b, TA a)
+{
+ return GLColor(static_cast<GLubyte>(r), static_cast<GLubyte>(g), static_cast<GLubyte>(b),
+ static_cast<GLubyte>(a));
+}
+
+bool operator==(const GLColor &a, const GLColor &b);
+std::ostream &operator<<(std::ostream &ostream, const GLColor &color);
+GLColor ReadColor(GLint x, GLint y);
+
+} // namespace angle
+
+#define EXPECT_PIXEL_EQ(x, y, r, g, b, a) \
+ EXPECT_EQ(angle::MakeGLColor(r, g, b, a), angle::ReadColor(x, y))
+
+#define EXPECT_PIXEL_ALPHA_EQ(x, y, a) EXPECT_EQ(a, angle::ReadColor(x, y).A)
+
+#define EXPECT_PIXEL_COLOR_EQ(x, y, angleColor) EXPECT_EQ(angleColor, angle::ReadColor(x, y))
+
+#define EXPECT_PIXEL_NEAR(x, y, r, g, b, a, abs_error) \
+{ \
+ GLubyte pixel[4]; \
+ glReadPixels((x), (y), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); \
+ EXPECT_GL_NO_ERROR(); \
+ EXPECT_NEAR((r), pixel[0], abs_error); \
+ EXPECT_NEAR((g), pixel[1], abs_error); \
+ EXPECT_NEAR((b), pixel[2], abs_error); \
+ EXPECT_NEAR((a), pixel[3], abs_error); \
+}
+
+// TODO(jmadill): Figure out how we can use GLColor's nice printing with EXPECT_NEAR.
+#define EXPECT_PIXEL_COLOR_NEAR(x, y, angleColor, abs_error) \
+ EXPECT_PIXEL_NEAR(x, y, angleColor.R, angleColor.G, angleColor.B, angleColor.A, abs_error)
+
+#define EXPECT_COLOR_NEAR(expected, actual, abs_error) \
+ \
+{ \
+ EXPECT_NEAR(expected.R, actual.R, abs_error); \
+ EXPECT_NEAR(expected.G, actual.G, abs_error); \
+ EXPECT_NEAR(expected.B, actual.B, abs_error); \
+ EXPECT_NEAR(expected.A, actual.A, abs_error); \
+ \
+}
+
+class EGLWindow;
+class OSWindow;
+
+class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters>
+{
+ protected:
+ ANGLETest();
+ ~ANGLETest();
+
+ public:
+ static bool InitTestWindow();
+ static bool DestroyTestWindow();
+ static void SetWindowVisible(bool isVisible);
+ static bool eglDisplayExtensionEnabled(EGLDisplay display, const std::string &extName);
+
+ protected:
+ virtual void SetUp();
+ virtual void TearDown();
+
+ virtual void swapBuffers();
+
+ void setupQuadVertexBuffer(GLfloat positionAttribZ, GLfloat positionAttribXYScale);
+ void setupIndexedQuadVertexBuffer(GLfloat positionAttribZ, GLfloat positionAttribXYScale);
+
+ void drawQuad(GLuint program, const std::string &positionAttribName, GLfloat positionAttribZ);
+ void drawQuad(GLuint program,
+ const std::string &positionAttribName,
+ GLfloat positionAttribZ,
+ GLfloat positionAttribXYScale);
+ void drawQuad(GLuint program,
+ const std::string &positionAttribName,
+ GLfloat positionAttribZ,
+ GLfloat positionAttribXYScale,
+ bool useVertexBuffer);
+ static std::array<Vector3, 6> GetQuadVertices();
+ void drawIndexedQuad(GLuint program,
+ const std::string &positionAttribName,
+ GLfloat positionAttribZ);
+ void drawIndexedQuad(GLuint program,
+ const std::string &positionAttribName,
+ GLfloat positionAttribZ,
+ GLfloat positionAttribXYScale);
+
+ static GLuint compileShader(GLenum type, const std::string &source);
+ static bool extensionEnabled(const std::string &extName);
+ static bool eglClientExtensionEnabled(const std::string &extName);
+ static bool eglDeviceExtensionEnabled(EGLDeviceEXT device, const std::string &extName);
+
+ void setWindowWidth(int width);
+ void setWindowHeight(int height);
+ void setConfigRedBits(int bits);
+ void setConfigGreenBits(int bits);
+ void setConfigBlueBits(int bits);
+ void setConfigAlphaBits(int bits);
+ void setConfigDepthBits(int bits);
+ void setConfigStencilBits(int bits);
+ void setMultisampleEnabled(bool enabled);
+ void setDebugEnabled(bool enabled);
+ void setNoErrorEnabled(bool enabled);
+ void setWebGLCompatibilityEnabled(bool webglCompatibility);
+ void setBindGeneratesResource(bool bindGeneratesResource);
+
+ int getClientMajorVersion() const;
+ int getClientMinorVersion() const;
+
+ EGLWindow *getEGLWindow() const;
+ int getWindowWidth() const;
+ int getWindowHeight() const;
+ bool isMultisampleEnabled() const;
+
+ EGLint getPlatformRenderer() const;
+
+ void ignoreD3D11SDKLayersWarnings();
+
+ private:
+ bool createEGLContext();
+ bool destroyEGLContext();
+
+ void checkD3D11SDKLayersMessages();
+
+ EGLWindow *mEGLWindow;
+ int mWidth;
+ int mHeight;
+
+ bool mIgnoreD3D11SDKLayersWarnings;
+
+ // Used for indexed quad rendering
+ GLuint mQuadVertexBuffer;
+
+ static OSWindow *mOSWindow;
+};
+
+class ANGLETestEnvironment : public testing::Environment
+{
+ public:
+ void SetUp() override;
+ void TearDown() override;
+
+ private:
+ // For loading and freeing platform
+ std::unique_ptr<angle::Library> mGLESLibrary;
+};
+
+// Driver vendors
+bool IsIntel();
+bool IsAdreno();
+bool IsAMD();
+bool IsNVIDIA();
+
+// Renderer back-ends
+// Note: FL9_3 is explicitly *not* considered D3D11.
+bool IsD3D11();
+bool IsD3D11_FL93();
+// Is a D3D9-class renderer.
+bool IsD3D9();
+// Is D3D9 or SM9_3 renderer.
+bool IsD3DSM3();
+bool IsDesktopOpenGL();
+bool IsOpenGLES();
+bool IsOpenGL();
+
+// Operating systems
+bool IsAndroid();
+bool IsLinux();
+bool IsOSX();
+bool IsWindows();
+
+// Debug/Release
+bool IsDebug();
+bool IsRelease();
+
+// Negative tests may trigger expected errors/warnings in the ANGLE Platform.
+void IgnoreANGLEPlatformMessages();
+
+// Note: git cl format messes up this formatting.
+#define ANGLE_SKIP_TEST_IF(COND) \
+ \
+if(COND) \
+ \
+{ \
+ std::cout << "Test skipped: " #COND "." << std::endl; \
+ return; \
+ \
+}
+
+#endif // ANGLE_TESTS_ANGLE_TEST_H_
diff --git a/gfx/angle/src/tests/test_utils/angle_test_configs.cpp b/gfx/angle/src/tests/test_utils/angle_test_configs.cpp
new file mode 100755
index 000000000..76690ca7b
--- /dev/null
+++ b/gfx/angle/src/tests/test_utils/angle_test_configs.cpp
@@ -0,0 +1,598 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/angle_test_configs.h"
+
+namespace angle
+{
+
+PlatformParameters::PlatformParameters()
+ : PlatformParameters(2, 0, EGLPlatformParameters())
+{
+}
+
+PlatformParameters::PlatformParameters(EGLint majorVersion, EGLint minorVersion,
+ const EGLPlatformParameters &eglPlatformParameters)
+ : majorVersion(majorVersion),
+ minorVersion(minorVersion),
+ eglParameters(eglPlatformParameters)
+{
+}
+
+EGLint PlatformParameters::getRenderer() const
+{
+ return eglParameters.renderer;
+}
+
+bool operator<(const PlatformParameters &a, const PlatformParameters &b)
+{
+ if (a.majorVersion != b.majorVersion)
+ {
+ return a.majorVersion < b.majorVersion;
+ }
+
+ if (a.minorVersion != b.minorVersion)
+ {
+ return a.minorVersion < b.minorVersion;
+ }
+
+ return a.eglParameters < b.eglParameters;
+}
+
+bool operator==(const PlatformParameters &a, const PlatformParameters &b)
+{
+ return (a.majorVersion == b.majorVersion) &&
+ (a.minorVersion == b.minorVersion) &&
+ (a.eglParameters == b.eglParameters);
+}
+
+std::ostream &operator<<(std::ostream& stream, const PlatformParameters &pp)
+{
+ stream << "ES" << pp.majorVersion << "_" ;
+ if (pp.minorVersion != 0)
+ {
+ stream << pp.minorVersion << "_";
+ }
+
+ switch (pp.eglParameters.renderer)
+ {
+ case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
+ stream << "D3D9";
+ break;
+ case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
+ stream << "D3D11";
+ break;
+ case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
+ stream << "OPENGL";
+ break;
+ case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
+ stream << "OPENGLES";
+ break;
+ case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
+ stream << "DEFAULT";
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ if (pp.eglParameters.majorVersion != EGL_DONT_CARE)
+ {
+ stream << "_" << pp.eglParameters.majorVersion;
+ }
+
+ if (pp.eglParameters.minorVersion != EGL_DONT_CARE)
+ {
+ stream << "_" << pp.eglParameters.minorVersion;
+ }
+
+ switch (pp.eglParameters.deviceType)
+ {
+ case EGL_DONT_CARE:
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
+ // default
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
+ stream << "_NULL";
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE:
+ stream << "_REFERENCE";
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE:
+ stream << "_WARP";
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ switch (pp.eglParameters.presentPath)
+ {
+ case EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE:
+ stream << "_PRESENT_PATH_COPY";
+ break;
+
+ case EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE:
+ stream << "_PRESENT_PATH_FAST";
+ break;
+
+ case EGL_DONT_CARE:
+ // default
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return stream;
+}
+
+// EGL platforms
+namespace egl_platform
+{
+
+EGLPlatformParameters DEFAULT()
+{
+ return EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
+}
+
+EGLPlatformParameters DEFAULT_NULL()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE,
+ EGL_DONT_CARE, EGL_DONT_CARE,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE);
+}
+
+EGLPlatformParameters D3D9()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE,
+ EGL_DONT_CARE, EGL_DONT_CARE,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+}
+
+EGLPlatformParameters D3D9_NULL()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE,
+ EGL_DONT_CARE, EGL_DONT_CARE,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE);
+}
+
+EGLPlatformParameters D3D9_REFERENCE()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE,
+ EGL_DONT_CARE, EGL_DONT_CARE,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE);
+}
+
+EGLPlatformParameters D3D11()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ EGL_DONT_CARE, EGL_DONT_CARE,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+}
+
+EGLPlatformParameters D3D11(EGLenum presentPath)
+{
+ return EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_DONT_CARE, EGL_DONT_CARE,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE, presentPath);
+}
+
+EGLPlatformParameters D3D11_FL11_1()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ 11, 1,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL11_0()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ 11, 0,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL10_1()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ 10, 1,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL10_0()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ 10, 0,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL9_3()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ 9, 3,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+}
+
+EGLPlatformParameters D3D11_NULL()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ EGL_DONT_CARE, EGL_DONT_CARE,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE);
+}
+
+EGLPlatformParameters D3D11_WARP()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ EGL_DONT_CARE, EGL_DONT_CARE,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL11_1_WARP()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ 11, 1,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL11_0_WARP()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ 11, 0,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL10_1_WARP()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ 10, 1,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL10_0_WARP()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ 10, 0,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL9_3_WARP()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ 9, 3,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE);
+}
+
+EGLPlatformParameters D3D11_REFERENCE()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ EGL_DONT_CARE, EGL_DONT_CARE,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL11_1_REFERENCE()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ 11, 1,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL11_0_REFERENCE()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ 11, 0,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL10_1_REFERENCE()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ 10, 1,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL10_0_REFERENCE()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ 10, 0,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE);
+}
+
+EGLPlatformParameters D3D11_FL9_3_REFERENCE()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ 9, 3,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE);
+}
+
+EGLPlatformParameters OPENGL()
+{
+ return EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE);
+}
+
+
+EGLPlatformParameters OPENGL(EGLint major, EGLint minor)
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE,
+ major, minor,
+ EGL_DONT_CARE);
+}
+
+EGLPlatformParameters OPENGL_NULL()
+{
+ return EGLPlatformParameters(
+ EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE,
+ 0, 0,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE);
+}
+
+EGLPlatformParameters OPENGLES()
+{
+ return EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE);
+}
+
+EGLPlatformParameters OPENGLES(EGLint major, EGLint minor)
+{
+ return EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, major, minor,
+ EGL_DONT_CARE);
+}
+
+} // namespace egl_platform
+
+// ANGLE tests platforms
+PlatformParameters ES2_D3D9()
+{
+ return PlatformParameters(2, 0, egl_platform::D3D9());
+}
+
+PlatformParameters ES2_D3D9_REFERENCE()
+{
+ return PlatformParameters(2, 0, egl_platform::D3D9_REFERENCE());
+}
+
+PlatformParameters ES2_D3D11()
+{
+ return PlatformParameters(2, 0, egl_platform::D3D11());
+}
+
+PlatformParameters ES2_D3D11(EGLenum presentPath)
+{
+ return PlatformParameters(2, 0, egl_platform::D3D11(presentPath));
+}
+
+PlatformParameters ES2_D3D11_FL11_0()
+{
+ return PlatformParameters(2, 0, egl_platform::D3D11_FL11_0());
+}
+
+PlatformParameters ES2_D3D11_FL10_1()
+{
+ return PlatformParameters(2, 0, egl_platform::D3D11_FL10_1());
+}
+
+PlatformParameters ES2_D3D11_FL10_0()
+{
+ return PlatformParameters(2, 0, egl_platform::D3D11_FL10_0());
+}
+
+PlatformParameters ES2_D3D11_FL9_3()
+{
+ return PlatformParameters(2, 0, egl_platform::D3D11_FL9_3());
+}
+
+PlatformParameters ES2_D3D11_WARP()
+{
+ return PlatformParameters(2, 0, egl_platform::D3D11_WARP());
+}
+
+PlatformParameters ES2_D3D11_FL11_0_WARP()
+{
+ return PlatformParameters(2, 0, egl_platform::D3D11_FL11_0_WARP());
+}
+
+PlatformParameters ES2_D3D11_FL10_1_WARP()
+{
+ return PlatformParameters(2, 0, egl_platform::D3D11_FL10_1_WARP());
+}
+
+PlatformParameters ES2_D3D11_FL10_0_WARP()
+{
+ return PlatformParameters(2, 0, egl_platform::D3D11_FL10_0_WARP());
+}
+
+PlatformParameters ES2_D3D11_FL9_3_WARP()
+{
+ return PlatformParameters(2, 0, egl_platform::D3D11_FL9_3_WARP());
+}
+
+PlatformParameters ES2_D3D11_REFERENCE()
+{
+ return PlatformParameters(2, 0, egl_platform::D3D11_REFERENCE());
+}
+
+PlatformParameters ES2_D3D11_FL11_0_REFERENCE()
+{
+ return PlatformParameters(2, 0, egl_platform::D3D11_FL11_0_REFERENCE());
+}
+
+PlatformParameters ES2_D3D11_FL10_1_REFERENCE()
+{
+ return PlatformParameters(2, 0, egl_platform::D3D11_FL10_1_REFERENCE());
+}
+
+PlatformParameters ES2_D3D11_FL10_0_REFERENCE()
+{
+ return PlatformParameters(2, 0, egl_platform::D3D11_FL10_0_REFERENCE());
+}
+
+PlatformParameters ES2_D3D11_FL9_3_REFERENCE()
+{
+ return PlatformParameters(2, 0, egl_platform::D3D11_FL9_3_REFERENCE());
+}
+
+PlatformParameters ES3_D3D11()
+{
+ return PlatformParameters(3, 0, egl_platform::D3D11());
+}
+
+PlatformParameters ES3_D3D11_FL11_1()
+{
+ return PlatformParameters(3, 0, egl_platform::D3D11_FL11_1());
+}
+
+PlatformParameters ES3_D3D11_FL11_0()
+{
+ return PlatformParameters(3, 0, egl_platform::D3D11_FL11_0());
+}
+
+PlatformParameters ES3_D3D11_FL10_1()
+{
+ return PlatformParameters(3, 0, egl_platform::D3D11_FL10_1());
+}
+
+PlatformParameters ES3_D3D11_FL10_0()
+{
+ return PlatformParameters(3, 0, egl_platform::D3D11_FL10_0());
+}
+
+PlatformParameters ES3_D3D11_WARP()
+{
+ return PlatformParameters(3, 0, egl_platform::D3D11_WARP());
+}
+
+PlatformParameters ES3_D3D11_FL11_1_WARP()
+{
+ return PlatformParameters(3, 0, egl_platform::D3D11_FL11_1_WARP());
+}
+
+PlatformParameters ES3_D3D11_FL11_0_WARP()
+{
+ return PlatformParameters(3, 0, egl_platform::D3D11_FL11_0_WARP());
+}
+
+PlatformParameters ES3_D3D11_FL10_1_WARP()
+{
+ return PlatformParameters(3, 0, egl_platform::D3D11_FL10_1_WARP());
+}
+
+PlatformParameters ES3_D3D11_FL10_0_WARP()
+{
+ return PlatformParameters(3, 0, egl_platform::D3D11_FL10_0_WARP());
+}
+
+PlatformParameters ES3_D3D11_REFERENCE()
+{
+ return PlatformParameters(3, 0, egl_platform::D3D11_REFERENCE());
+}
+
+PlatformParameters ES3_D3D11_FL11_1_REFERENCE()
+{
+ return PlatformParameters(3, 0, egl_platform::D3D11_FL11_1_REFERENCE());
+}
+
+PlatformParameters ES3_D3D11_FL11_0_REFERENCE()
+{
+ return PlatformParameters(3, 0, egl_platform::D3D11_FL11_0_REFERENCE());
+}
+
+PlatformParameters ES3_D3D11_FL10_1_REFERENCE()
+{
+ return PlatformParameters(3, 0, egl_platform::D3D11_FL10_1_REFERENCE());
+}
+
+PlatformParameters ES3_D3D11_FL10_0_REFERENCE()
+{
+ return PlatformParameters(3, 0, egl_platform::D3D11_FL10_0_REFERENCE());
+}
+
+PlatformParameters ES2_OPENGLES()
+{
+ return PlatformParameters(2, 0, egl_platform::OPENGLES());
+}
+
+PlatformParameters ES2_OPENGLES(EGLint major, EGLint minor)
+{
+ return PlatformParameters(2, 0, egl_platform::OPENGLES(major, minor));
+}
+
+PlatformParameters ES3_OPENGLES()
+{
+ return PlatformParameters(3, 0, egl_platform::OPENGLES());
+}
+
+PlatformParameters ES3_OPENGLES(EGLint major, EGLint minor)
+{
+ return PlatformParameters(3, 0, egl_platform::OPENGLES(major, minor));
+}
+
+PlatformParameters ES31_OPENGLES()
+{
+ return PlatformParameters(3, 1, egl_platform::OPENGLES());
+}
+
+PlatformParameters ES31_OPENGLES(EGLint major, EGLint minor)
+{
+ return PlatformParameters(3, 1, egl_platform::OPENGLES(major, minor));
+}
+
+PlatformParameters ES2_OPENGL()
+{
+ return PlatformParameters(2, 0, egl_platform::OPENGL());
+}
+
+PlatformParameters ES2_OPENGL(EGLint major, EGLint minor)
+{
+ return PlatformParameters(2, 0, egl_platform::OPENGL(major, minor));
+}
+
+PlatformParameters ES3_OPENGL()
+{
+ return PlatformParameters(3, 0, egl_platform::OPENGL());
+}
+
+PlatformParameters ES3_OPENGL(EGLint major, EGLint minor)
+{
+ return PlatformParameters(3, 0, egl_platform::OPENGL(major, minor));
+}
+
+PlatformParameters ES31_OPENGL()
+{
+ return PlatformParameters(3, 1, egl_platform::OPENGL());
+}
+
+PlatformParameters ES31_OPENGL(EGLint major, EGLint minor)
+{
+ return PlatformParameters(3, 1, egl_platform::OPENGL(major, minor));
+}
+
+} // namespace angle
diff --git a/gfx/angle/src/tests/test_utils/angle_test_configs.h b/gfx/angle/src/tests/test_utils/angle_test_configs.h
new file mode 100755
index 000000000..fa595a556
--- /dev/null
+++ b/gfx/angle/src/tests/test_utils/angle_test_configs.h
@@ -0,0 +1,144 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef ANGLE_TEST_CONFIGS_H_
+#define ANGLE_TEST_CONFIGS_H_
+
+// On Linux EGL/egl.h includes X.h which does defines for some very common
+// names that are used by gtest (like None and Bool) and causes a lot of
+// compilation errors. To work around this, even if this file doesn't use it,
+// we include gtest before EGL so that it compiles fine in other files that
+// want to use gtest.
+#include <gtest/gtest.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "angle_test_instantiate.h"
+#include "EGLWindow.h"
+
+namespace angle
+{
+
+struct PlatformParameters
+{
+ PlatformParameters();
+ PlatformParameters(EGLint majorVersion, EGLint minorVersion,
+ const EGLPlatformParameters &eglPlatformParameters);
+
+ EGLint getRenderer() const;
+
+ EGLint majorVersion;
+ EGLint minorVersion;
+ EGLPlatformParameters eglParameters;
+};
+
+bool operator<(const PlatformParameters &a, const PlatformParameters &b);
+bool operator==(const PlatformParameters &a, const PlatformParameters &b);
+std::ostream &operator<<(std::ostream& stream, const PlatformParameters &pp);
+
+// EGL platforms
+namespace egl_platform
+{
+
+EGLPlatformParameters DEFAULT();
+EGLPlatformParameters DEFAULT_NULL();
+
+EGLPlatformParameters D3D9();
+EGLPlatformParameters D3D9_NULL();
+EGLPlatformParameters D3D9_REFERENCE();
+
+EGLPlatformParameters D3D11();
+EGLPlatformParameters D3D11(EGLenum presentPath);
+EGLPlatformParameters D3D11_FL11_1();
+EGLPlatformParameters D3D11_FL11_0();
+EGLPlatformParameters D3D11_FL10_1();
+EGLPlatformParameters D3D11_FL10_0();
+EGLPlatformParameters D3D11_FL9_3();
+
+EGLPlatformParameters D3D11_NULL();
+
+EGLPlatformParameters D3D11_WARP();
+EGLPlatformParameters D3D11_FL11_1_WARP();
+EGLPlatformParameters D3D11_FL11_0_WARP();
+EGLPlatformParameters D3D11_FL10_1_WARP();
+EGLPlatformParameters D3D11_FL10_0_WARP();
+EGLPlatformParameters D3D11_FL9_3_WARP();
+
+EGLPlatformParameters D3D11_REFERENCE();
+EGLPlatformParameters D3D11_FL11_1_REFERENCE();
+EGLPlatformParameters D3D11_FL11_0_REFERENCE();
+EGLPlatformParameters D3D11_FL10_1_REFERENCE();
+EGLPlatformParameters D3D11_FL10_0_REFERENCE();
+EGLPlatformParameters D3D11_FL9_3_REFERENCE();
+
+EGLPlatformParameters OPENGL();
+EGLPlatformParameters OPENGL(EGLint major, EGLint minor);
+EGLPlatformParameters OPENGL_NULL();
+
+EGLPlatformParameters OPENGLES();
+EGLPlatformParameters OPENGLES(EGLint major, EGLint minor);
+
+} // namespace egl_platform
+
+// ANGLE tests platforms
+PlatformParameters ES2_D3D9();
+PlatformParameters ES2_D3D9_REFERENCE();
+
+PlatformParameters ES2_D3D11();
+PlatformParameters ES2_D3D11(EGLenum presentPath);
+PlatformParameters ES2_D3D11_FL11_0();
+PlatformParameters ES2_D3D11_FL10_1();
+PlatformParameters ES2_D3D11_FL10_0();
+PlatformParameters ES2_D3D11_FL9_3();
+
+PlatformParameters ES2_D3D11_WARP();
+PlatformParameters ES2_D3D11_FL11_0_WARP();
+PlatformParameters ES2_D3D11_FL10_1_WARP();
+PlatformParameters ES2_D3D11_FL10_0_WARP();
+PlatformParameters ES2_D3D11_FL9_3_WARP();
+
+PlatformParameters ES2_D3D11_REFERENCE();
+PlatformParameters ES2_D3D11_FL11_0_REFERENCE();
+PlatformParameters ES2_D3D11_FL10_1_REFERENCE();
+PlatformParameters ES2_D3D11_FL10_0_REFERENCE();
+PlatformParameters ES2_D3D11_FL9_3_REFERENCE();
+
+PlatformParameters ES3_D3D11();
+PlatformParameters ES3_D3D11_FL11_1();
+PlatformParameters ES3_D3D11_FL11_0();
+PlatformParameters ES3_D3D11_FL10_1();
+PlatformParameters ES3_D3D11_FL10_0();
+
+PlatformParameters ES3_D3D11_WARP();
+PlatformParameters ES3_D3D11_FL11_1_WARP();
+PlatformParameters ES3_D3D11_FL11_0_WARP();
+PlatformParameters ES3_D3D11_FL10_1_WARP();
+PlatformParameters ES3_D3D11_FL10_0_WARP();
+
+PlatformParameters ES3_D3D11_REFERENCE();
+PlatformParameters ES3_D3D11_FL11_1_REFERENCE();
+PlatformParameters ES3_D3D11_FL11_0_REFERENCE();
+PlatformParameters ES3_D3D11_FL10_1_REFERENCE();
+PlatformParameters ES3_D3D11_FL10_0_REFERENCE();
+
+PlatformParameters ES2_OPENGL();
+PlatformParameters ES2_OPENGL(EGLint major, EGLint minor);
+PlatformParameters ES3_OPENGL();
+PlatformParameters ES3_OPENGL(EGLint major, EGLint minor);
+PlatformParameters ES31_OPENGL();
+PlatformParameters ES31_OPENGL(EGLint major, EGLint minor);
+
+PlatformParameters ES2_OPENGLES();
+PlatformParameters ES2_OPENGLES(EGLint major, EGLint minor);
+PlatformParameters ES3_OPENGLES();
+PlatformParameters ES3_OPENGLES(EGLint major, EGLint minor);
+PlatformParameters ES31_OPENGLES();
+PlatformParameters ES31_OPENGLES(EGLint major, EGLint minor);
+
+} // namespace angle
+
+#endif // ANGLE_TEST_CONFIGS_H_
diff --git a/gfx/angle/src/tests/test_utils/angle_test_instantiate.cpp b/gfx/angle/src/tests/test_utils/angle_test_instantiate.cpp
new file mode 100755
index 000000000..a928d85e1
--- /dev/null
+++ b/gfx/angle/src/tests/test_utils/angle_test_instantiate.cpp
@@ -0,0 +1,88 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// angle_test_instantiate.cpp: Adds support for filtering parameterized
+// tests by platform, so we skip unsupported configs.
+
+#include "test_utils/angle_test_instantiate.h"
+
+#include <map>
+#include <iostream>
+
+#include "EGLWindow.h"
+#include "OSWindow.h"
+#include "test_utils/angle_test_configs.h"
+
+namespace angle
+{
+
+bool IsPlatformAvailable(const PlatformParameters &param)
+{
+ switch (param.getRenderer())
+ {
+ case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
+#ifndef ANGLE_ENABLE_D3D9
+ return false;
+#endif
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
+#ifndef ANGLE_ENABLE_D3D11
+ return false;
+#endif
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
+ case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
+#ifndef ANGLE_ENABLE_OPENGL
+ return false;
+#endif
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ static std::map<PlatformParameters, bool> paramAvailabilityCache;
+ auto iter = paramAvailabilityCache.find(param);
+ if (iter != paramAvailabilityCache.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ OSWindow *osWindow = CreateOSWindow();
+ bool result = osWindow->initialize("CONFIG_TESTER", 1, 1);
+
+ if (result)
+ {
+ EGLWindow *eglWindow =
+ new EGLWindow(param.majorVersion, param.minorVersion, param.eglParameters);
+ result = eglWindow->initializeGL(osWindow);
+
+ eglWindow->destroyGL();
+ SafeDelete(eglWindow);
+ }
+
+ osWindow->destroy();
+ SafeDelete(osWindow);
+
+ paramAvailabilityCache[param] = result;
+
+ if (!result)
+ {
+ std::cout << "Skipping tests using configuration " << param << " because it is not available." << std::endl;
+ }
+
+ return result;
+ }
+}
+
+}
diff --git a/gfx/angle/src/tests/test_utils/angle_test_instantiate.h b/gfx/angle/src/tests/test_utils/angle_test_instantiate.h
new file mode 100755
index 000000000..a7b6a81aa
--- /dev/null
+++ b/gfx/angle/src/tests/test_utils/angle_test_instantiate.h
@@ -0,0 +1,52 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// angle_test_instantiate.h: Adds support for filtering parameterized
+// tests by platform, so we skip unsupported configs.
+
+#ifndef ANGLE_TEST_INSTANTIATE_H_
+#define ANGLE_TEST_INSTANTIATE_H_
+
+#include <gtest/gtest.h>
+
+#include "common/debug.h"
+
+namespace angle
+{
+
+struct PlatformParameters;
+
+bool IsPlatformAvailable(const PlatformParameters &param);
+
+// This functions is used to filter which tests should be registered,
+// T must be or inherit from angle::PlatformParameters.
+template <typename T>
+std::vector<T> FilterTestParams(const T *params, size_t numParams)
+{
+ std::vector<T> filtered;
+
+ for (size_t i = 0; i < numParams; i++)
+ {
+ if (IsPlatformAvailable(params[i]))
+ {
+ filtered.push_back(params[i]);
+ }
+ }
+
+ return filtered;
+}
+
+// Instantiate the test once for each extra argument. The types of all the
+// arguments must match, and getRenderer must be implemented for that type.
+#define ANGLE_INSTANTIATE_TEST(testName, firstParam, ...) \
+ const decltype(firstParam) testName##params[] = { firstParam, ##__VA_ARGS__ }; \
+ INSTANTIATE_TEST_CASE_P(, testName, \
+ testing::ValuesIn(::angle::FilterTestParams(testName##params, ArraySize(testName##params))), \
+ testing::PrintToStringParamName());
+
+} // namespace angle
+
+#endif // ANGLE_TEST_INSTANTIATE_H_
diff --git a/gfx/angle/src/tests/test_utils/compiler_test.cpp b/gfx/angle/src/tests/test_utils/compiler_test.cpp
new file mode 100755
index 000000000..873541ecd
--- /dev/null
+++ b/gfx/angle/src/tests/test_utils/compiler_test.cpp
@@ -0,0 +1,256 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// compiler_test.cpp:
+// utilities for compiler unit tests.
+
+#include "tests/test_utils/compiler_test.h"
+
+#include "angle_gl.h"
+#include "compiler/translator/Compiler.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class ShaderVariableFinder : public TIntermTraverser
+{
+ public:
+ ShaderVariableFinder(const TString &variableName, TBasicType basicType)
+ : TIntermTraverser(true, false, false),
+ mVariableName(variableName),
+ mNodeFound(nullptr),
+ mBasicType(basicType)
+ {
+ }
+
+ void visitSymbol(TIntermSymbol *node)
+ {
+ if (node->getBasicType() == mBasicType && node->getSymbol() == mVariableName)
+ {
+ mNodeFound = node;
+ }
+ }
+
+ bool isFound() const { return mNodeFound != nullptr; }
+ const TIntermSymbol *getNode() const { return mNodeFound; }
+
+ private:
+ TString mVariableName;
+ TIntermSymbol *mNodeFound;
+ TBasicType mBasicType;
+};
+
+class FunctionCallFinder : public TIntermTraverser
+{
+ public:
+ FunctionCallFinder(const TString &functionName)
+ : TIntermTraverser(true, false, false), mFunctionName(functionName), mNodeFound(nullptr)
+ {
+ }
+
+ bool visitAggregate(Visit visit, TIntermAggregate *node) override
+ {
+ if (node->getOp() == EOpFunctionCall &&
+ node->getFunctionSymbolInfo()->getName() == mFunctionName)
+ {
+ mNodeFound = node;
+ return false;
+ }
+ return true;
+ }
+
+ bool isFound() const { return mNodeFound != nullptr; }
+ const TIntermAggregate *getNode() const { return mNodeFound; }
+
+ private:
+ TString mFunctionName;
+ TIntermAggregate *mNodeFound;
+};
+
+} // anonymous namespace
+
+bool compileTestShader(GLenum type,
+ ShShaderSpec spec,
+ ShShaderOutput output,
+ const std::string &shaderString,
+ ShBuiltInResources *resources,
+ ShCompileOptions compileOptions,
+ std::string *translatedCode,
+ std::string *infoLog)
+{
+ sh::TCompiler *translator = sh::ConstructCompiler(type, spec, output);
+ if (!translator->Init(*resources))
+ {
+ SafeDelete(translator);
+ return false;
+ }
+
+ const char *shaderStrings[] = { shaderString.c_str() };
+
+ bool compilationSuccess = translator->compile(shaderStrings, 1, SH_OBJECT_CODE | compileOptions);
+ TInfoSink &infoSink = translator->getInfoSink();
+ if (translatedCode)
+ *translatedCode = infoSink.obj.c_str();
+ if (infoLog)
+ *infoLog = infoSink.info.c_str();
+ SafeDelete(translator);
+ return compilationSuccess;
+}
+
+bool compileTestShader(GLenum type,
+ ShShaderSpec spec,
+ ShShaderOutput output,
+ const std::string &shaderString,
+ ShCompileOptions compileOptions,
+ std::string *translatedCode,
+ std::string *infoLog)
+{
+ ShBuiltInResources resources;
+ sh::InitBuiltInResources(&resources);
+ return compileTestShader(type, spec, output, shaderString, &resources, compileOptions, translatedCode, infoLog);
+}
+
+MatchOutputCodeTest::MatchOutputCodeTest(GLenum shaderType,
+ ShCompileOptions defaultCompileOptions,
+ ShShaderOutput outputType)
+ : mShaderType(shaderType), mDefaultCompileOptions(defaultCompileOptions)
+{
+ sh::InitBuiltInResources(&mResources);
+ mOutputCode[outputType] = std::string();
+}
+
+void MatchOutputCodeTest::addOutputType(const ShShaderOutput outputType)
+{
+ mOutputCode[outputType] = std::string();
+}
+
+ShBuiltInResources *MatchOutputCodeTest::getResources()
+{
+ return &mResources;
+}
+
+void MatchOutputCodeTest::compile(const std::string &shaderString)
+{
+ compile(shaderString, mDefaultCompileOptions);
+}
+
+void MatchOutputCodeTest::compile(const std::string &shaderString,
+ const ShCompileOptions compileOptions)
+{
+ std::string infoLog;
+ for (auto &code : mOutputCode)
+ {
+ bool compilationSuccess =
+ compileWithSettings(code.first, shaderString, compileOptions, &code.second, &infoLog);
+ if (!compilationSuccess)
+ {
+ FAIL() << "Shader compilation failed:\n" << infoLog;
+ }
+ }
+}
+
+bool MatchOutputCodeTest::compileWithSettings(ShShaderOutput output,
+ const std::string &shaderString,
+ const ShCompileOptions compileOptions,
+ std::string *translatedCode,
+ std::string *infoLog)
+{
+ return compileTestShader(mShaderType, SH_GLES3_SPEC, output, shaderString, &mResources,
+ compileOptions, translatedCode, infoLog);
+}
+
+bool MatchOutputCodeTest::foundInCode(ShShaderOutput output, const char *stringToFind) const
+{
+ const auto code = mOutputCode.find(output);
+ EXPECT_NE(mOutputCode.end(), code);
+ if (code == mOutputCode.end())
+ {
+ return false;
+ }
+
+ return code->second.find(stringToFind) != std::string::npos;
+}
+
+bool MatchOutputCodeTest::foundInCode(ShShaderOutput output,
+ const char *stringToFind,
+ const int expectedOccurrences) const
+{
+ const auto code = mOutputCode.find(output);
+ EXPECT_NE(mOutputCode.end(), code);
+ if (code == mOutputCode.end())
+ {
+ return false;
+ }
+
+ size_t currentPos = 0;
+ int occurencesLeft = expectedOccurrences;
+ while (occurencesLeft-- > 0)
+ {
+ auto position = code->second.find(stringToFind, currentPos);
+ if (position == std::string::npos)
+ {
+ return false;
+ }
+ currentPos = position + 1;
+ }
+ return code->second.find(stringToFind, currentPos) == std::string::npos;
+}
+
+bool MatchOutputCodeTest::foundInCode(const char *stringToFind) const
+{
+ for (auto &code : mOutputCode)
+ {
+ if (!foundInCode(code.first, stringToFind))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool MatchOutputCodeTest::foundInCode(const char *stringToFind, const int expectedOccurrences) const
+{
+ for (auto &code : mOutputCode)
+ {
+ if (!foundInCode(code.first, stringToFind, expectedOccurrences))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool MatchOutputCodeTest::notFoundInCode(const char *stringToFind) const
+{
+ for (auto &code : mOutputCode)
+ {
+ if (foundInCode(code.first, stringToFind))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+const TIntermSymbol *FindSymbolNode(TIntermNode *root,
+ const TString &symbolName,
+ TBasicType basicType)
+{
+ ShaderVariableFinder finder(symbolName, basicType);
+ root->traverse(&finder);
+ return finder.getNode();
+}
+
+const TIntermAggregate *FindFunctionCallNode(TIntermNode *root, const TString &functionName)
+{
+ FunctionCallFinder finder(functionName);
+ root->traverse(&finder);
+ return finder.getNode();
+}
+
+} // namespace sh
diff --git a/gfx/angle/src/tests/test_utils/compiler_test.h b/gfx/angle/src/tests/test_utils/compiler_test.h
new file mode 100755
index 000000000..a0dd2d82a
--- /dev/null
+++ b/gfx/angle/src/tests/test_utils/compiler_test.h
@@ -0,0 +1,103 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// compiler_test.h:
+// utilities for compiler unit tests.
+
+#ifndef TESTS_TEST_UTILS_COMPILER_TEST_H_
+#define TESTS_TEST_UTILS_COMPILER_TEST_H_
+
+#include <map>
+
+#include "gtest/gtest.h"
+
+#include "angle_gl.h"
+#include "compiler/translator/TranslatorESSL.h"
+#include "GLSLANG/ShaderLang.h"
+
+namespace sh
+{
+
+bool compileTestShader(GLenum type,
+ ShShaderSpec spec,
+ ShShaderOutput output,
+ const std::string &shaderString,
+ ShBuiltInResources *resources,
+ ShCompileOptions compileOptions,
+ std::string *translatedCode,
+ std::string *infoLog);
+
+bool compileTestShader(GLenum type,
+ ShShaderSpec spec,
+ ShShaderOutput output,
+ const std::string &shaderString,
+ ShCompileOptions compileOptions,
+ std::string *translatedCode,
+ std::string *infoLog);
+
+class MatchOutputCodeTest : public testing::Test
+{
+ protected:
+ MatchOutputCodeTest(GLenum shaderType,
+ ShCompileOptions defaultCompileOptions,
+ ShShaderOutput outputType);
+
+ void addOutputType(const ShShaderOutput outputType);
+
+ ShBuiltInResources *getResources();
+
+ // Compile functions clear any results from earlier calls to them.
+ void compile(const std::string &shaderString);
+ void compile(const std::string &shaderString, const ShCompileOptions compileOptions);
+
+ bool foundInESSLCode(const char *stringToFind) const
+ {
+ return foundInCode(SH_ESSL_OUTPUT, stringToFind);
+ }
+
+ bool foundInGLSLCode(const char *stringToFind) const
+ {
+ return foundInCode(SH_GLSL_COMPATIBILITY_OUTPUT, stringToFind);
+ }
+
+ bool foundInCode(ShShaderOutput output, const char *stringToFind) const;
+
+ // Test that the string occurs for exactly expectedOccurrences times
+ bool foundInCode(ShShaderOutput output,
+ const char *stringToFind,
+ const int expectedOccurrences) const;
+
+ // Test that the string is found in all outputs
+ bool foundInCode(const char *stringToFind) const;
+
+ // Test that the string occurs for exactly expectedOccurrences times in all outputs
+ bool foundInCode(const char *stringToFind, const int expectedOccurrences) const;
+
+ // Test that the string is found in none of the outputs
+ bool notFoundInCode(const char *stringToFind) const;
+
+ private:
+ bool compileWithSettings(ShShaderOutput output,
+ const std::string &shaderString,
+ ShCompileOptions compileOptions,
+ std::string *translatedCode,
+ std::string *infoLog);
+
+ GLenum mShaderType;
+ ShCompileOptions mDefaultCompileOptions;
+ ShBuiltInResources mResources;
+
+ std::map<ShShaderOutput, std::string> mOutputCode;
+};
+
+const TIntermSymbol *FindSymbolNode(TIntermNode *root,
+ const TString &symbolName,
+ TBasicType basicType);
+
+// Returns a pointer to a function call node with a mangled name functionName.
+const TIntermAggregate *FindFunctionCallNode(TIntermNode *root, const TString &functionName);
+}
+
+#endif // TESTS_TEST_UTILS_COMPILER_TEST_H_
diff --git a/gfx/angle/src/tests/test_utils/gl_raii.h b/gfx/angle/src/tests/test_utils/gl_raii.h
new file mode 100755
index 000000000..b42a56396
--- /dev/null
+++ b/gfx/angle/src/tests/test_utils/gl_raii.h
@@ -0,0 +1,96 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// gl_raii:
+// Helper methods for containing GL objects like buffers and textures.
+
+#ifndef ANGLE_TESTS_GL_RAII_H_
+#define ANGLE_TESTS_GL_RAII_H_
+
+#include <functional>
+
+#include "angle_gl.h"
+
+namespace angle
+{
+
+// This is a bit of hack to work around a bug in MSVS intellisense, and make it very easy to
+// use the correct function pointer type without worrying about the various definitions of
+// GL_APICALL.
+using GLGen = decltype(glGenBuffers);
+using GLDelete = decltype(glDeleteBuffers);
+
+template <GLGen GenF, GLDelete DeleteF>
+class GLWrapper
+{
+ public:
+ GLWrapper() {}
+ ~GLWrapper() { DeleteF(1, &mHandle); }
+
+ GLuint get()
+ {
+ if (!mHandle)
+ {
+ GenF(1, &mHandle);
+ }
+ return mHandle;
+ }
+
+ private:
+ GLuint mHandle = 0;
+};
+
+using GLBuffer = GLWrapper<glGenBuffers, glDeleteBuffers>;
+using GLTexture = GLWrapper<glGenTextures, glDeleteTextures>;
+using GLFramebuffer = GLWrapper<glGenFramebuffers, glDeleteFramebuffers>;
+using GLRenderbuffer = GLWrapper<glGenRenderbuffers, glDeleteRenderbuffers>;
+using GLSampler = GLWrapper<glGenSamplers, glDeleteSamplers>;
+
+class GLProgram
+{
+ public:
+ GLProgram(const std::string &vertexShader, const std::string &fragmentShader)
+ : mHandle(0), mVertexShader(vertexShader), mFragmentShader(fragmentShader)
+ {
+ }
+
+ GLProgram(const std::string &computeShader) : mHandle(0), mComputeShader(computeShader) {}
+
+ ~GLProgram() { glDeleteProgram(mHandle); }
+
+ GLuint get()
+ {
+ if (mHandle == 0)
+ {
+ if (!mComputeShader.empty())
+ {
+ mHandle = CompileComputeProgram(mComputeShader);
+ }
+ else
+ {
+ mHandle = CompileProgram(mVertexShader, mFragmentShader);
+ }
+ }
+ return mHandle;
+ }
+
+ private:
+ GLuint mHandle;
+ const std::string mVertexShader;
+ const std::string mFragmentShader;
+ const std::string mComputeShader;
+};
+
+#define ANGLE_GL_PROGRAM(name, vertex, fragment) \
+ GLProgram name(vertex, fragment); \
+ ASSERT_NE(0u, name.get());
+
+#define ANGLE_GL_COMPUTE_PROGRAM(name, compute) \
+ GLProgram name(compute); \
+ ASSERT_NE(0u, name.get());
+
+} // namespace angle
+
+#endif // ANGLE_TESTS_GL_RAII_H_