Path: blob/main_old/src/tests/test_utils/ANGLETest.h
1693 views
//1// Copyright 2012 The ANGLE Project Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4//5// ANGLETest:6// Implementation of common ANGLE testing fixture.7//89#ifndef ANGLE_TESTS_ANGLE_TEST_H_10#define ANGLE_TESTS_ANGLE_TEST_H_1112#include <gtest/gtest.h>13#include <algorithm>14#include <array>1516#include "RenderDoc.h"17#include "angle_test_configs.h"18#include "angle_test_platform.h"19#include "common/angleutils.h"20#include "common/system_utils.h"21#include "common/vector_utils.h"22#include "platform/PlatformMethods.h"23#include "util/EGLWindow.h"24#include "util/shader_utils.h"25#include "util/util_gl.h"2627namespace angle28{29struct SystemInfo;30class RNG;31} // namespace angle3233#define ASSERT_GL_TRUE(a) ASSERT_EQ(static_cast<GLboolean>(GL_TRUE), (a))34#define ASSERT_GL_FALSE(a) ASSERT_EQ(static_cast<GLboolean>(GL_FALSE), (a))35#define EXPECT_GL_TRUE(a) EXPECT_EQ(static_cast<GLboolean>(GL_TRUE), (a))36#define EXPECT_GL_FALSE(a) EXPECT_EQ(static_cast<GLboolean>(GL_FALSE), (a))3738#define EXPECT_GL_ERROR(err) EXPECT_EQ(static_cast<GLenum>(err), glGetError())39#define EXPECT_GL_NO_ERROR() EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError())4041#define ASSERT_GL_ERROR(err) ASSERT_EQ(static_cast<GLenum>(err), glGetError())42#define ASSERT_GL_NO_ERROR() ASSERT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError())4344#define EXPECT_EGL_ERROR(err) EXPECT_EQ((err), eglGetError())45#define EXPECT_EGL_SUCCESS() EXPECT_EGL_ERROR(EGL_SUCCESS)4647// EGLBoolean is |unsigned int| but EGL_TRUE is 0, not 0u.48#define ASSERT_EGL_TRUE(a) ASSERT_EQ(static_cast<EGLBoolean>(EGL_TRUE), static_cast<EGLBoolean>(a))49#define ASSERT_EGL_FALSE(a) \50ASSERT_EQ(static_cast<EGLBoolean>(EGL_FALSE), static_cast<EGLBoolean>(a))51#define EXPECT_EGL_TRUE(a) EXPECT_EQ(static_cast<EGLBoolean>(EGL_TRUE), static_cast<EGLBoolean>(a))52#define EXPECT_EGL_FALSE(a) \53EXPECT_EQ(static_cast<EGLBoolean>(EGL_FALSE), static_cast<EGLBoolean>(a))5455#define ASSERT_EGL_ERROR(err) ASSERT_EQ((err), eglGetError())56#define ASSERT_EGL_SUCCESS() ASSERT_EGL_ERROR(EGL_SUCCESS)5758#define ASSERT_GLENUM_EQ(expected, actual) \59ASSERT_EQ(static_cast<GLenum>(expected), static_cast<GLenum>(actual))60#define EXPECT_GLENUM_EQ(expected, actual) \61EXPECT_EQ(static_cast<GLenum>(expected), static_cast<GLenum>(actual))62#define ASSERT_GLENUM_NE(expected, actual) \63ASSERT_NE(static_cast<GLenum>(expected), static_cast<GLenum>(actual))64#define EXPECT_GLENUM_NE(expected, actual) \65EXPECT_NE(static_cast<GLenum>(expected), static_cast<GLenum>(actual))6667testing::AssertionResult AssertEGLEnumsEqual(const char *lhsExpr,68const char *rhsExpr,69EGLenum lhs,70EGLenum rhs);7172#define ASSERT_EGLENUM_EQ(expected, actual) \73ASSERT_PRED_FORMAT2(AssertEGLEnumsEqual, static_cast<EGLenum>(expected), \74static_cast<EGLenum>(actual))75#define EXPECT_EGLENUM_EQ(expected, actual) \76EXPECT_PRED_FORMAT2(AssertEGLEnumsEqual, static_cast<EGLenum>(expected), \77static_cast<EGLenum>(actual))7879#define ASSERT_GL_FRAMEBUFFER_COMPLETE(framebuffer) \80ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(framebuffer))81#define EXPECT_GL_FRAMEBUFFER_COMPLETE(framebuffer) \82EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(framebuffer))8384namespace angle85{86struct GLColorRGB87{88constexpr GLColorRGB() : R(0), G(0), B(0) {}89constexpr GLColorRGB(GLubyte r, GLubyte g, GLubyte b) : R(r), G(g), B(b) {}90GLColorRGB(const angle::Vector3 &floatColor);9192const GLubyte *data() const { return &R; }93GLubyte *data() { return &R; }9495GLubyte R, G, B;9697static const GLColorRGB black;98static const GLColorRGB blue;99static const GLColorRGB green;100static const GLColorRGB red;101static const GLColorRGB yellow;102};103104struct GLColorRG105{106constexpr GLColorRG() : R(0), G(0) {}107constexpr GLColorRG(GLubyte r, GLubyte g) : R(r), G(g) {}108GLColorRG(const angle::Vector2 &floatColor);109110const GLubyte *data() const { return &R; }111GLubyte *data() { return &R; }112113GLubyte R, G;114};115116struct GLColorR117{118constexpr GLColorR() : R(0) {}119constexpr GLColorR(GLubyte r) : R(r) {}120GLColorR(const float floatColor);121122const GLubyte *data() const { return &R; }123GLubyte *data() { return &R; }124125GLubyte R;126};127128struct GLColor129{130constexpr GLColor() : R(0), G(0), B(0), A(0) {}131constexpr GLColor(GLubyte r, GLubyte g, GLubyte b, GLubyte a) : R(r), G(g), B(b), A(a) {}132GLColor(const angle::Vector4 &floatColor);133GLColor(GLuint colorValue);134135angle::Vector4 toNormalizedVector() const;136137GLubyte &operator[](size_t index) { return (&R)[index]; }138139const GLubyte &operator[](size_t index) const { return (&R)[index]; }140141const GLubyte *data() const { return &R; }142GLubyte *data() { return &R; }143144GLuint asUint() const;145146testing::AssertionResult ExpectNear(const GLColor &expected, const GLColor &err) const;147148GLubyte R, G, B, A;149150static const GLColor black;151static const GLColor blue;152static const GLColor cyan;153static const GLColor green;154static const GLColor red;155static const GLColor transparentBlack;156static const GLColor white;157static const GLColor yellow;158static const GLColor magenta;159};160161struct GLColor16UI162{163constexpr GLColor16UI() : GLColor16UI(0, 0, 0, 0) {}164constexpr GLColor16UI(GLushort r, GLushort g, GLushort b, GLushort a) : R(r), G(g), B(b), A(a)165{}166167GLushort R, G, B, A;168};169170struct GLColor32F171{172constexpr GLColor32F() : GLColor32F(0.0f, 0.0f, 0.0f, 0.0f) {}173constexpr GLColor32F(GLfloat r, GLfloat g, GLfloat b, GLfloat a) : R(r), G(g), B(b), A(a) {}174175GLfloat R, G, B, A;176};177178static constexpr GLColor32F kFloatBlack = {0.0f, 0.0f, 0.0f, 1.0f};179static constexpr GLColor32F kFloatRed = {1.0f, 0.0f, 0.0f, 1.0f};180static constexpr GLColor32F kFloatGreen = {0.0f, 1.0f, 0.0f, 1.0f};181static constexpr GLColor32F kFloatBlue = {0.0f, 0.0f, 1.0f, 1.0f};182183// The input here for pixelPoints are the expected integer window coordinates, we add .5 to every184// one of them and re-scale the numbers to be between [-1,1]. Using this technique, we can make185// sure the rasterization stage will end up drawing pixels at the expected locations.186void CreatePixelCenterWindowCoords(const std::vector<Vector2> &pixelPoints,187int windowWidth,188int windowHeight,189std::vector<Vector3> *outVertices);190191// Useful to cast any type to GLubyte.192template <typename TR, typename TG, typename TB, typename TA>193GLColor MakeGLColor(TR r, TG g, TB b, TA a)194{195return GLColor(static_cast<GLubyte>(r), static_cast<GLubyte>(g), static_cast<GLubyte>(b),196static_cast<GLubyte>(a));197}198199GLColor RandomColor(angle::RNG *rng);200201bool operator==(const GLColor &a, const GLColor &b);202bool operator!=(const GLColor &a, const GLColor &b);203std::ostream &operator<<(std::ostream &ostream, const GLColor &color);204GLColor ReadColor(GLint x, GLint y);205206bool operator==(const GLColorRGB &a, const GLColorRGB &b);207bool operator!=(const GLColorRGB &a, const GLColorRGB &b);208std::ostream &operator<<(std::ostream &ostream, const GLColorRGB &color);209210// Useful to cast any type to GLfloat.211template <typename TR, typename TG, typename TB, typename TA>212GLColor32F MakeGLColor32F(TR r, TG g, TB b, TA a)213{214return GLColor32F(static_cast<GLfloat>(r), static_cast<GLfloat>(g), static_cast<GLfloat>(b),215static_cast<GLfloat>(a));216}217218bool operator==(const GLColor32F &a, const GLColor32F &b);219std::ostream &operator<<(std::ostream &ostream, const GLColor32F &color);220GLColor32F ReadColor32F(GLint x, GLint y);221222constexpr std::array<GLenum, 6> kCubeFaces = {223{GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,224GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,225GL_TEXTURE_CUBE_MAP_NEGATIVE_Z}};226227void LoadEntryPointsWithUtilLoader(angle::GLESDriverType driver);228229} // namespace angle230231#define EXPECT_PIXEL_EQ(x, y, r, g, b, a) \232EXPECT_EQ(angle::MakeGLColor(r, g, b, a), angle::ReadColor(x, y))233234#define EXPECT_PIXEL_NE(x, y, r, g, b, a) \235EXPECT_NE(angle::MakeGLColor(r, g, b, a), angle::ReadColor(x, y))236237#define EXPECT_PIXEL_32F_EQ(x, y, r, g, b, a) \238EXPECT_EQ(angle::MakeGLColor32F(r, g, b, a), angle::ReadColor32F(x, y))239240#define EXPECT_PIXEL_ALPHA_EQ(x, y, a) EXPECT_EQ(a, angle::ReadColor(x, y).A)241242#define EXPECT_PIXEL_ALPHA32F_EQ(x, y, a) EXPECT_EQ(a, angle::ReadColor32F(x, y).A)243244#define EXPECT_PIXEL_COLOR_EQ(x, y, angleColor) EXPECT_EQ(angleColor, angle::ReadColor(x, y))245#define EXPECT_PIXEL_COLOR_EQ_VEC2(vec2, angleColor) \246EXPECT_EQ(angleColor, \247angle::ReadColor(static_cast<GLint>(vec2.x()), static_cast<GLint>(vec2.y())))248249#define EXPECT_PIXEL_COLOR32F_EQ(x, y, angleColor) EXPECT_EQ(angleColor, angle::ReadColor32F(x, y))250251#define EXPECT_PIXEL_RECT_EQ(x, y, width, height, color) \252do \253{ \254std::vector<GLColor> actualColors((width) * (height)); \255glReadPixels((x), (y), (width), (height), GL_RGBA, GL_UNSIGNED_BYTE, actualColors.data()); \256std::vector<GLColor> expectedColors((width) * (height), color); \257EXPECT_EQ(expectedColors, actualColors); \258} while (0)259260#define EXPECT_PIXEL_NEAR_HELPER(x, y, r, g, b, a, abs_error, ctype, format, type) \261do \262{ \263ctype pixel[4]; \264glReadPixels((x), (y), 1, 1, format, type, pixel); \265EXPECT_GL_NO_ERROR(); \266EXPECT_NEAR((r), pixel[0], abs_error); \267EXPECT_NEAR((g), pixel[1], abs_error); \268EXPECT_NEAR((b), pixel[2], abs_error); \269EXPECT_NEAR((a), pixel[3], abs_error); \270} while (0)271272#define EXPECT_PIXEL_EQ_HELPER(x, y, r, g, b, a, ctype, format, type) \273do \274{ \275ctype pixel[4]; \276glReadPixels((x), (y), 1, 1, format, type, pixel); \277EXPECT_GL_NO_ERROR(); \278EXPECT_EQ((r), pixel[0]); \279EXPECT_EQ((g), pixel[1]); \280EXPECT_EQ((b), pixel[2]); \281EXPECT_EQ((a), pixel[3]); \282} while (0)283284#define EXPECT_PIXEL_NEAR(x, y, r, g, b, a, abs_error) \285EXPECT_PIXEL_NEAR_HELPER(x, y, r, g, b, a, abs_error, GLubyte, GL_RGBA, GL_UNSIGNED_BYTE)286287#define EXPECT_PIXEL_32F_NEAR(x, y, r, g, b, a, abs_error) \288EXPECT_PIXEL_NEAR_HELPER(x, y, r, g, b, a, abs_error, GLfloat, GL_RGBA, GL_FLOAT)289290#define EXPECT_PIXEL_8I(x, y, r, g, b, a) \291EXPECT_PIXEL_EQ_HELPER(x, y, r, g, b, a, GLbyte, GL_RGBA_INTEGER, GL_BYTE)292293#define EXPECT_PIXEL_8UI(x, y, r, g, b, a) \294EXPECT_PIXEL_EQ_HELPER(x, y, r, g, b, a, GLubyte, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE)295296#define EXPECT_PIXEL_16UI(x, y, r, g, b, a) \297EXPECT_PIXEL_EQ_HELPER(x, y, r, g, b, a, GLushort, GL_RGBA, GL_UNSIGNED_SHORT)298299#define EXPECT_PIXEL_16UI_COLOR(x, y, color) \300EXPECT_PIXEL_16UI(x, y, color.R, color.G, color.B, color.A)301302// TODO(jmadill): Figure out how we can use GLColor's nice printing with EXPECT_NEAR.303#define EXPECT_PIXEL_COLOR_NEAR(x, y, angleColor, abs_error) \304EXPECT_PIXEL_NEAR(x, y, angleColor.R, angleColor.G, angleColor.B, angleColor.A, abs_error)305306#define EXPECT_PIXEL_COLOR32F_NEAR(x, y, angleColor, abs_error) \307EXPECT_PIXEL32F_NEAR(x, y, angleColor.R, angleColor.G, angleColor.B, angleColor.A, abs_error)308309#define EXPECT_COLOR_NEAR(expected, actual, abs_error) \310do \311{ \312EXPECT_NEAR(expected.R, actual.R, abs_error); \313EXPECT_NEAR(expected.G, actual.G, abs_error); \314EXPECT_NEAR(expected.B, actual.B, abs_error); \315EXPECT_NEAR(expected.A, actual.A, abs_error); \316} while (0)317#define EXPECT_PIXEL32F_NEAR(x, y, r, g, b, a, abs_error) \318do \319{ \320GLfloat pixel[4]; \321glReadPixels((x), (y), 1, 1, GL_RGBA, GL_FLOAT, pixel); \322EXPECT_GL_NO_ERROR(); \323EXPECT_NEAR((r), pixel[0], abs_error); \324EXPECT_NEAR((g), pixel[1], abs_error); \325EXPECT_NEAR((b), pixel[2], abs_error); \326EXPECT_NEAR((a), pixel[3], abs_error); \327} while (0)328329#define EXPECT_PIXEL_COLOR32F_NEAR(x, y, angleColor, abs_error) \330EXPECT_PIXEL32F_NEAR(x, y, angleColor.R, angleColor.G, angleColor.B, angleColor.A, abs_error)331332#define EXPECT_PIXEL_STENCIL_EQ(x, y, expected) \333do \334{ \335GLubyte actual; \336glReadPixels((x), (y), 1, 1, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, &actual); \337EXPECT_GL_NO_ERROR(); \338EXPECT_EQ((expected), actual); \339} while (0)340341class ANGLETestBase;342class EGLWindow;343class GLWindowBase;344class OSWindow;345class WGLWindow;346347struct TestPlatformContext final : private angle::NonCopyable348{349bool ignoreMessages = false;350bool warningsAsErrors = false;351ANGLETestBase *currentTest = nullptr;352};353354class ANGLETestBase355{356protected:357ANGLETestBase(const angle::PlatformParameters ¶ms);358virtual ~ANGLETestBase();359360public:361void setWindowVisible(OSWindow *osWindow, bool isVisible);362363virtual void overrideWorkaroundsD3D(angle::FeaturesD3D *featuresD3D) {}364virtual void overrideFeaturesVk(angle::FeaturesVk *featuresVulkan) {}365366static void ReleaseFixtures();367368bool isSwiftshader() const369{370// Renderer might be swiftshader even if local swiftshader not used.371return mCurrentParams->isSwiftshader() || angle::IsSwiftshaderDevice();372}373374bool enableDebugLayers() const375{376return mCurrentParams->eglParameters.debugLayersEnabled != EGL_FALSE;377}378379protected:380void ANGLETestSetUp();381void ANGLETestPreTearDown();382void ANGLETestTearDown();383384virtual void swapBuffers();385386void setupQuadVertexBuffer(GLfloat positionAttribZ, GLfloat positionAttribXYScale);387void setupIndexedQuadVertexBuffer(GLfloat positionAttribZ, GLfloat positionAttribXYScale);388void setupIndexedQuadIndexBuffer();389390void drawQuad(GLuint program, const std::string &positionAttribName, GLfloat positionAttribZ);391void drawQuad(GLuint program,392const std::string &positionAttribName,393GLfloat positionAttribZ,394GLfloat positionAttribXYScale);395void drawQuad(GLuint program,396const std::string &positionAttribName,397GLfloat positionAttribZ,398GLfloat positionAttribXYScale,399bool useVertexBuffer);400void drawQuadInstanced(GLuint program,401const std::string &positionAttribName,402GLfloat positionAttribZ,403GLfloat positionAttribXYScale,404bool useVertexBuffer,405GLuint numInstances);406void drawPatches(GLuint program,407const std::string &positionAttribName,408GLfloat positionAttribZ,409GLfloat positionAttribXYScale,410bool useVertexBuffer);411412void drawQuadPPO(GLuint vertProgram,413const std::string &positionAttribName,414const GLfloat positionAttribZ,415const GLfloat positionAttribXYScale);416417static std::array<angle::Vector3, 6> GetQuadVertices();418static std::array<GLushort, 6> GetQuadIndices();419static std::array<angle::Vector3, 4> GetIndexedQuadVertices();420421void drawIndexedQuad(GLuint program,422const std::string &positionAttribName,423GLfloat positionAttribZ);424void drawIndexedQuad(GLuint program,425const std::string &positionAttribName,426GLfloat positionAttribZ,427GLfloat positionAttribXYScale);428void drawIndexedQuad(GLuint program,429const std::string &positionAttribName,430GLfloat positionAttribZ,431GLfloat positionAttribXYScale,432bool useBufferObject);433434void drawIndexedQuad(GLuint program,435const std::string &positionAttribName,436GLfloat positionAttribZ,437GLfloat positionAttribXYScale,438bool useBufferObject,439bool restrictedRange);440441void draw2DTexturedQuad(GLfloat positionAttribZ,442GLfloat positionAttribXYScale,443bool useVertexBuffer);444445// The layer parameter chooses the 3D texture layer to sample from.446void draw3DTexturedQuad(GLfloat positionAttribZ,447GLfloat positionAttribXYScale,448bool useVertexBuffer,449float layer);450451void setWindowWidth(int width);452void setWindowHeight(int height);453void setConfigRedBits(int bits);454void setConfigGreenBits(int bits);455void setConfigBlueBits(int bits);456void setConfigAlphaBits(int bits);457void setConfigDepthBits(int bits);458void setConfigStencilBits(int bits);459void setConfigComponentType(EGLenum componentType);460void setMultisampleEnabled(bool enabled);461void setSamples(EGLint samples);462void setDebugEnabled(bool enabled);463void setNoErrorEnabled(bool enabled);464void setWebGLCompatibilityEnabled(bool webglCompatibility);465void setExtensionsEnabled(bool extensionsEnabled);466void setRobustAccess(bool enabled);467void setBindGeneratesResource(bool bindGeneratesResource);468void setClientArraysEnabled(bool enabled);469void setRobustResourceInit(bool enabled);470void setContextProgramCacheEnabled(bool enabled);471void setContextResetStrategy(EGLenum resetStrategy);472void forceNewDisplay();473474// Some EGL extension tests would like to defer the Context init until the test body.475void setDeferContextInit(bool enabled);476477int getClientMajorVersion() const;478int getClientMinorVersion() const;479480GLWindowBase *getGLWindow() const;481EGLWindow *getEGLWindow() const;482int getWindowWidth() const;483int getWindowHeight() const;484bool isEmulatedPrerotation() const;485486EGLint getPlatformRenderer() const;487488void ignoreD3D11SDKLayersWarnings();489490// Allows a test to be more restrictive about platform warnings.491void treatPlatformWarningsAsErrors();492493OSWindow *getOSWindow() { return mFixture->osWindow; }494495GLuint get2DTexturedQuadProgram();496497// Has a float uniform "u_layer" to choose the 3D texture layer.498GLuint get3DTexturedQuadProgram();499500class ScopedIgnorePlatformMessages : angle::NonCopyable501{502public:503ScopedIgnorePlatformMessages();504~ScopedIgnorePlatformMessages();505};506507// Can be used before we get a GL context.508bool isGLRenderer() const509{510return mCurrentParams->getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE;511}512513bool isGLESRenderer() const514{515return mCurrentParams->getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;516}517518bool isD3D11Renderer() const519{520return mCurrentParams->getRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;521}522523bool isVulkanRenderer() const524{525return mCurrentParams->getRenderer() == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;526}527528bool isVulkanSwiftshaderRenderer() const529{530return mCurrentParams->getRenderer() == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE &&531mCurrentParams->isSwiftshader();532}533534bool isAsyncCommandQueueFeatureEnabled() const535{536return mCurrentParams->eglParameters.asyncCommandQueueFeatureVulkan == EGL_TRUE;537}538539bool platformSupportsMultithreading() const;540541bool isAllocateNonZeroMemoryEnabled() const542{543return mCurrentParams->getAllocateNonZeroMemoryFeature() == EGL_TRUE;544}545546bool mIsSetUp = false;547548private:549void checkD3D11SDKLayersMessages();550551void drawQuad(GLuint program,552const std::string &positionAttribName,553GLfloat positionAttribZ,554GLfloat positionAttribXYScale,555bool useVertexBuffer,556bool useInstancedDrawCalls,557bool useTessellationPatches,558GLuint numInstances);559560void initOSWindow();561562struct TestFixture563{564TestFixture();565~TestFixture();566567EGLWindow *eglWindow = nullptr;568WGLWindow *wglWindow = nullptr;569OSWindow *osWindow = nullptr;570ConfigParameters configParams;571uint32_t reuseCounter = 0;572};573574int mWidth;575int mHeight;576577bool mIgnoreD3D11SDKLayersWarnings;578579// Used for indexed quad rendering580GLuint mQuadVertexBuffer;581GLuint mQuadIndexBuffer;582583// Used for texture rendering.584GLuint m2DTexturedQuadProgram;585GLuint m3DTexturedQuadProgram;586587bool mDeferContextInit;588bool mAlwaysForceNewDisplay;589bool mForceNewDisplay;590591bool mSetUpCalled;592bool mTearDownCalled;593594// Usually, we use an OS Window per "fixture" (a frontend and backend combination).595// This allows:596// 1. Reusing EGL Display on Windows.597// Other platforms have issues with display reuse even if a window per fixture is used.598// 2. Hiding only SwiftShader OS Window on Linux.599// OS Windows for other backends must be visible, to allow driver to communicate with X11.600// However, we must use a single OS Window for all backends on Android,601// since test Application can have only one window.602static OSWindow *mOSWindowSingleton;603604static std::map<angle::PlatformParameters, TestFixture> gFixtures;605const angle::PlatformParameters *mCurrentParams;606TestFixture *mFixture;607608RenderDoc mRenderDoc;609610// Workaround for NVIDIA not being able to share a window with OpenGL and Vulkan.611static Optional<EGLint> mLastRendererType;612static Optional<angle::GLESDriverType> mLastLoadedDriver;613};614615template <typename Params = angle::PlatformParameters>616class ANGLETestWithParam : public ANGLETestBase, public ::testing::TestWithParam<Params>617{618protected:619ANGLETestWithParam();620621virtual void testSetUp() {}622virtual void testTearDown() {}623624void recreateTestFixture()625{626TearDown();627SetUp();628}629630private:631void SetUp() final632{633ANGLETestBase::ANGLETestSetUp();634if (mIsSetUp)635{636testSetUp();637}638}639640void TearDown() final641{642ANGLETestBase::ANGLETestPreTearDown();643if (mIsSetUp)644{645testTearDown();646}647ANGLETestBase::ANGLETestTearDown();648}649};650651template <typename Params>652ANGLETestWithParam<Params>::ANGLETestWithParam()653: ANGLETestBase(std::get<angle::PlatformParameters>(this->GetParam()))654{}655656template <>657inline ANGLETestWithParam<angle::PlatformParameters>::ANGLETestWithParam()658: ANGLETestBase(this->GetParam())659{}660661// Note: this hack is not necessary in C++17. Once we switch to C++17, we can just rename662// ANGLETestWithParam to ANGLETest.663using ANGLETest = ANGLETestWithParam<>;664665class ANGLETestEnvironment : public testing::Environment666{667public:668void SetUp() override;669void TearDown() override;670671static angle::Library *GetDriverLibrary(angle::GLESDriverType driver);672673private:674static angle::Library *GetAngleEGLLibrary();675static angle::Library *GetSystemEGLLibrary();676static angle::Library *GetSystemWGLLibrary();677678// For loading entry points.679static std::unique_ptr<angle::Library> gAngleEGLLibrary;680static std::unique_ptr<angle::Library> gSystemEGLLibrary;681static std::unique_ptr<angle::Library> gSystemWGLLibrary;682};683684extern angle::PlatformMethods gDefaultPlatformMethods;685686#endif // ANGLE_TESTS_ANGLE_TEST_H_687688689