diff options
Diffstat (limited to 'gfx/angle/src/tests/test_utils')
-rwxr-xr-x | gfx/angle/src/tests/test_utils/ANGLETest.cpp | 863 | ||||
-rwxr-xr-x | gfx/angle/src/tests/test_utils/ANGLETest.h | 274 | ||||
-rwxr-xr-x | gfx/angle/src/tests/test_utils/angle_test_configs.cpp | 598 | ||||
-rwxr-xr-x | gfx/angle/src/tests/test_utils/angle_test_configs.h | 144 | ||||
-rwxr-xr-x | gfx/angle/src/tests/test_utils/angle_test_instantiate.cpp | 88 | ||||
-rwxr-xr-x | gfx/angle/src/tests/test_utils/angle_test_instantiate.h | 52 | ||||
-rwxr-xr-x | gfx/angle/src/tests/test_utils/compiler_test.cpp | 256 | ||||
-rwxr-xr-x | gfx/angle/src/tests/test_utils/compiler_test.h | 103 | ||||
-rwxr-xr-x | gfx/angle/src/tests/test_utils/gl_raii.h | 96 |
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 ¶m) +{ + 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 ¶m); + +// 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_ |