Path: blob/main_old/src/tests/test_utils/ANGLETest.cpp
1693 views
//1// Copyright 2015 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#include "ANGLETest.h"1011#include <algorithm>12#include <cstdlib>1314#include "common/platform.h"15#include "gpu_info_util/SystemInfo.h"16#include "test_utils/runner/TestSuite.h"17#include "util/EGLWindow.h"18#include "util/OSWindow.h"19#include "util/random_utils.h"20#include "util/test_utils.h"2122#if defined(ANGLE_PLATFORM_WINDOWS)23# include <VersionHelpers.h>24#endif // defined(ANGLE_PLATFORM_WINDOWS)2526namespace angle27{2829const GLColorRGB GLColorRGB::black(0u, 0u, 0u);30const GLColorRGB GLColorRGB::blue(0u, 0u, 255u);31const GLColorRGB GLColorRGB::green(0u, 255u, 0u);32const GLColorRGB GLColorRGB::red(255u, 0u, 0u);33const GLColorRGB GLColorRGB::yellow(255u, 255u, 0);3435const GLColor GLColor::black = GLColor(0u, 0u, 0u, 255u);36const GLColor GLColor::blue = GLColor(0u, 0u, 255u, 255u);37const GLColor GLColor::cyan = GLColor(0u, 255u, 255u, 255u);38const GLColor GLColor::green = GLColor(0u, 255u, 0u, 255u);39const GLColor GLColor::red = GLColor(255u, 0u, 0u, 255u);40const GLColor GLColor::transparentBlack = GLColor(0u, 0u, 0u, 0u);41const GLColor GLColor::white = GLColor(255u, 255u, 255u, 255u);42const GLColor GLColor::yellow = GLColor(255u, 255u, 0, 255u);43const GLColor GLColor::magenta = GLColor(255u, 0u, 255u, 255u);4445namespace46{47float ColorNorm(GLubyte channelValue)48{49return static_cast<float>(channelValue) / 255.0f;50}5152GLubyte ColorDenorm(float colorValue)53{54return static_cast<GLubyte>(colorValue * 255.0f);55}5657void TestPlatform_logError(PlatformMethods *platform, const char *errorMessage)58{59auto *testPlatformContext = static_cast<TestPlatformContext *>(platform->context);60if (testPlatformContext->ignoreMessages)61return;6263GTEST_NONFATAL_FAILURE_(errorMessage);6465PrintStackBacktrace();66}6768void TestPlatform_logWarning(PlatformMethods *platform, const char *warningMessage)69{70auto *testPlatformContext = static_cast<TestPlatformContext *>(platform->context);71if (testPlatformContext->ignoreMessages)72return;7374if (testPlatformContext->warningsAsErrors)75{76FAIL() << warningMessage;77}78else79{80std::cerr << "Warning: " << warningMessage << std::endl;81}82}8384void TestPlatform_logInfo(PlatformMethods *platform, const char *infoMessage) {}8586void TestPlatform_overrideWorkaroundsD3D(PlatformMethods *platform, FeaturesD3D *featuresD3D)87{88auto *testPlatformContext = static_cast<TestPlatformContext *>(platform->context);89if (testPlatformContext->currentTest)90{91testPlatformContext->currentTest->overrideWorkaroundsD3D(featuresD3D);92}93}9495void TestPlatform_overrideFeaturesVk(PlatformMethods *platform, FeaturesVk *featuresVulkan)96{97auto *testPlatformContext = static_cast<TestPlatformContext *>(platform->context);98if (testPlatformContext->currentTest)99{100testPlatformContext->currentTest->overrideFeaturesVk(featuresVulkan);101}102}103104const std::array<Vector3, 6> kQuadVertices = {{105Vector3(-1.0f, 1.0f, 0.5f),106Vector3(-1.0f, -1.0f, 0.5f),107Vector3(1.0f, -1.0f, 0.5f),108Vector3(-1.0f, 1.0f, 0.5f),109Vector3(1.0f, -1.0f, 0.5f),110Vector3(1.0f, 1.0f, 0.5f),111}};112113const std::array<Vector3, 4> kIndexedQuadVertices = {{114Vector3(-1.0f, 1.0f, 0.5f),115Vector3(-1.0f, -1.0f, 0.5f),116Vector3(1.0f, -1.0f, 0.5f),117Vector3(1.0f, 1.0f, 0.5f),118}};119120constexpr std::array<GLushort, 6> kIndexedQuadIndices = {{0, 1, 2, 0, 2, 3}};121122const char *GetColorName(GLColor color)123{124if (color == GLColor::red)125{126return "Red";127}128129if (color == GLColor::green)130{131return "Green";132}133134if (color == GLColor::blue)135{136return "Blue";137}138139if (color == GLColor::white)140{141return "White";142}143144if (color == GLColor::black)145{146return "Black";147}148149if (color == GLColor::transparentBlack)150{151return "Transparent Black";152}153154if (color == GLColor::yellow)155{156return "Yellow";157}158159if (color == GLColor::magenta)160{161return "Magenta";162}163164if (color == GLColor::cyan)165{166return "Cyan";167}168169return nullptr;170}171172const char *GetColorName(GLColorRGB color)173{174return GetColorName(GLColor(color.R, color.G, color.B, 255));175}176177// Always re-use displays when using --bot-mode in the test runner.178bool gReuseDisplays = false;179180bool ShouldAlwaysForceNewDisplay()181{182if (gReuseDisplays)183return false;184185// We prefer to reuse config displays. This is faster and solves a driver issue where creating186// many displays causes crashes. However this exposes other driver bugs on many other platforms.187// Conservatively enable the feature only on Windows Intel and NVIDIA for now.188SystemInfo *systemInfo = GetTestSystemInfo();189return (!systemInfo || !IsWindows() || systemInfo->hasAMDGPU());190}191192GPUTestConfig::API GetTestConfigAPIFromRenderer(EGLenum renderer, EGLenum deviceType)193{194switch (renderer)195{196case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:197return GPUTestConfig::kAPID3D11;198case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:199return GPUTestConfig::kAPID3D9;200case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:201return GPUTestConfig::kAPIGLDesktop;202case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:203return GPUTestConfig::kAPIGLES;204case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:205if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE)206{207return GPUTestConfig::kAPISwiftShader;208}209else210{211return GPUTestConfig::kAPIVulkan;212}213case EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE:214return GPUTestConfig::kAPIMetal;215default:216std::cerr << "Unknown Renderer enum: 0x%X\n" << renderer;217return GPUTestConfig::kAPIUnknown;218}219}220} // anonymous namespace221222GLColorRGB::GLColorRGB(const Vector3 &floatColor)223: R(ColorDenorm(floatColor.x())), G(ColorDenorm(floatColor.y())), B(ColorDenorm(floatColor.z()))224{}225226GLColor::GLColor(const Vector4 &floatColor)227: R(ColorDenorm(floatColor.x())),228G(ColorDenorm(floatColor.y())),229B(ColorDenorm(floatColor.z())),230A(ColorDenorm(floatColor.w()))231{}232233GLColor::GLColor(GLuint colorValue) : R(0), G(0), B(0), A(0)234{235memcpy(&R, &colorValue, sizeof(GLuint));236}237238GLuint GLColor::asUint() const239{240GLuint uint = 0;241memcpy(&uint, &R, sizeof(GLuint));242return uint;243}244245testing::AssertionResult GLColor::ExpectNear(const GLColor &expected, const GLColor &err) const246{247testing::AssertionResult result(248abs(int(expected.R) - this->R) <= err.R && abs(int(expected.G) - this->G) <= err.G &&249abs(int(expected.B) - this->B) <= err.B && abs(int(expected.A) - this->A) <= err.A);250if (!bool(result))251{252result << "Expected " << expected << "+/-" << err << ", was " << *this;253}254return result;255}256257void CreatePixelCenterWindowCoords(const std::vector<Vector2> &pixelPoints,258int windowWidth,259int windowHeight,260std::vector<Vector3> *outVertices)261{262for (Vector2 pixelPoint : pixelPoints)263{264outVertices->emplace_back(Vector3((pixelPoint[0] + 0.5f) * 2.0f / windowWidth - 1.0f,265(pixelPoint[1] + 0.5f) * 2.0f / windowHeight - 1.0f,2660.0f));267}268}269270Vector4 GLColor::toNormalizedVector() const271{272return Vector4(ColorNorm(R), ColorNorm(G), ColorNorm(B), ColorNorm(A));273}274275GLColor RandomColor(angle::RNG *rng)276{277return GLColor(rng->randomIntBetween(0, 255), rng->randomIntBetween(0, 255),278rng->randomIntBetween(0, 255), rng->randomIntBetween(0, 255));279}280281GLColor ReadColor(GLint x, GLint y)282{283GLColor actual;284glReadPixels((x), (y), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &actual.R);285EXPECT_GL_NO_ERROR();286return actual;287}288289bool operator==(const GLColor &a, const GLColor &b)290{291return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;292}293294bool operator!=(const GLColor &a, const GLColor &b)295{296return !(a == b);297}298299std::ostream &operator<<(std::ostream &ostream, const GLColor &color)300{301const char *colorName = GetColorName(color);302if (colorName)303{304return ostream << colorName;305}306307ostream << "(" << static_cast<unsigned int>(color.R) << ", "308<< static_cast<unsigned int>(color.G) << ", " << static_cast<unsigned int>(color.B)309<< ", " << static_cast<unsigned int>(color.A) << ")";310return ostream;311}312313bool operator==(const GLColorRGB &a, const GLColorRGB &b)314{315return a.R == b.R && a.G == b.G && a.B == b.B;316}317318bool operator!=(const GLColorRGB &a, const GLColorRGB &b)319{320return !(a == b);321}322323std::ostream &operator<<(std::ostream &ostream, const GLColorRGB &color)324{325const char *colorName = GetColorName(color);326if (colorName)327{328return ostream << colorName;329}330331ostream << "(" << static_cast<unsigned int>(color.R) << ", "332<< static_cast<unsigned int>(color.G) << ", " << static_cast<unsigned int>(color.B)333<< ")";334return ostream;335}336337bool operator==(const GLColor32F &a, const GLColor32F &b)338{339return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;340}341342std::ostream &operator<<(std::ostream &ostream, const GLColor32F &color)343{344ostream << "(" << color.R << ", " << color.G << ", " << color.B << ", " << color.A << ")";345return ostream;346}347348GLColor32F ReadColor32F(GLint x, GLint y)349{350GLColor32F actual;351glReadPixels((x), (y), 1, 1, GL_RGBA, GL_FLOAT, &actual.R);352EXPECT_GL_NO_ERROR();353return actual;354}355356void LoadEntryPointsWithUtilLoader(angle::GLESDriverType driverType)357{358#if defined(ANGLE_USE_UTIL_LOADER)359PFNEGLGETPROCADDRESSPROC getProcAddress;360ANGLETestEnvironment::GetDriverLibrary(driverType)->getAs("eglGetProcAddress", &getProcAddress);361ASSERT_NE(nullptr, getProcAddress);362363LoadEGL(getProcAddress);364LoadGLES(getProcAddress);365#endif // defined(ANGLE_USE_UTIL_LOADER)366}367} // namespace angle368369using namespace angle;370371PlatformMethods gDefaultPlatformMethods;372373namespace374{375TestPlatformContext gPlatformContext;376377// After a fixed number of iterations we reset the test window. This works around some driver bugs.378constexpr uint32_t kWindowReuseLimit = 50;379380constexpr char kUseConfig[] = "--use-config=";381constexpr char kReuseDisplays[] = "--reuse-displays";382constexpr char kEnableANGLEPerTestCaptureLabel[] = "--angle-per-test-capture-label";383constexpr char kBatchId[] = "--batch-id=";384constexpr char kDelayTestStart[] = "--delay-test-start=";385constexpr char kRenderDoc[] = "--renderdoc";386387void SetupEnvironmentVarsForCaptureReplay()388{389const ::testing::TestInfo *const testInfo =390::testing::UnitTest::GetInstance()->current_test_info();391std::string testName = std::string{testInfo->name()};392std::replace(testName.begin(), testName.end(), '/', '_');393SetEnvironmentVar("ANGLE_CAPTURE_LABEL",394(std::string{testInfo->test_case_name()} + "_" + testName).c_str());395}396} // anonymous namespace397398int gTestStartDelaySeconds = 0;399400int GetTestStartDelaySeconds()401{402return gTestStartDelaySeconds;403}404405void SetTestStartDelay(const char *testStartDelay)406{407gTestStartDelaySeconds = std::stoi(testStartDelay);408}409410bool gEnableRenderDocCapture = false;411412// static413std::array<Vector3, 6> ANGLETestBase::GetQuadVertices()414{415return kQuadVertices;416}417418// static419std::array<GLushort, 6> ANGLETestBase::GetQuadIndices()420{421return kIndexedQuadIndices;422}423424// static425std::array<Vector3, 4> ANGLETestBase::GetIndexedQuadVertices()426{427return kIndexedQuadVertices;428}429430testing::AssertionResult AssertEGLEnumsEqual(const char *lhsExpr,431const char *rhsExpr,432EGLenum lhs,433EGLenum rhs)434{435if (lhs == rhs)436{437return testing::AssertionSuccess();438}439else440{441std::stringstream strstr;442strstr << std::hex << lhsExpr << " (0x" << int(lhs) << ") != " << rhsExpr << " (0x"443<< int(rhs) << ")";444return testing::AssertionFailure() << strstr.str();445}446}447448ANGLETestBase::ANGLETestBase(const PlatformParameters ¶ms)449: mWidth(16),450mHeight(16),451mIgnoreD3D11SDKLayersWarnings(false),452mQuadVertexBuffer(0),453mQuadIndexBuffer(0),454m2DTexturedQuadProgram(0),455m3DTexturedQuadProgram(0),456mDeferContextInit(false),457mAlwaysForceNewDisplay(ShouldAlwaysForceNewDisplay()),458mForceNewDisplay(mAlwaysForceNewDisplay),459mSetUpCalled(false),460mTearDownCalled(false),461mCurrentParams(nullptr),462mFixture(nullptr)463{464// Override the default platform methods with the ANGLE test methods pointer.465PlatformParameters withMethods = params;466withMethods.eglParameters.platformMethods = &gDefaultPlatformMethods;467468if (withMethods.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)469{470#if defined(ANGLE_ENABLE_VULKAN_VALIDATION_LAYERS)471withMethods.eglParameters.debugLayersEnabled = true;472#else473withMethods.eglParameters.debugLayersEnabled = false;474#endif475}476477if (gEnableRenderDocCapture)478{479mRenderDoc.attach();480}481482auto iter = gFixtures.find(withMethods);483if (iter != gFixtures.end())484{485mCurrentParams = &iter->first;486487if (!params.noFixture)488{489mFixture = &iter->second;490mFixture->configParams.reset();491}492return;493}494495TestFixture platform;496auto insertIter = gFixtures.emplace(withMethods, platform);497mCurrentParams = &insertIter.first->first;498499if (!params.noFixture)500{501mFixture = &insertIter.first->second;502initOSWindow();503}504}505506void ANGLETestBase::initOSWindow()507{508std::stringstream windowNameStream;509windowNameStream << "ANGLE Tests - " << *mCurrentParams;510std::string windowName = windowNameStream.str();511512if (IsAndroid())513{514// Only one window per test application on Android, shared among all fixtures515mFixture->osWindow = mOSWindowSingleton;516}517518if (!mFixture->osWindow)519{520mFixture->osWindow = OSWindow::New();521mFixture->osWindow->disableErrorMessageDialog();522if (!mFixture->osWindow->initialize(windowName.c_str(), 128, 128))523{524std::cerr << "Failed to initialize OS Window.\n";525}526527if (IsAndroid())528{529// Initialize the single window on Andoird only once530mOSWindowSingleton = mFixture->osWindow;531}532}533534if (!mFixture->osWindow->valid())535{536return;537}538539// On Linux we must keep the test windows visible. On Windows it doesn't seem to need it.540setWindowVisible(getOSWindow(), !IsWindows());541542switch (mCurrentParams->driver)543{544case GLESDriverType::AngleEGL:545case GLESDriverType::SystemEGL:546{547mFixture->eglWindow =548EGLWindow::New(mCurrentParams->majorVersion, mCurrentParams->minorVersion);549break;550}551552case GLESDriverType::SystemWGL:553{554// WGL tests are currently disabled.555std::cerr << "Unsupported driver." << std::endl;556break;557}558}559}560561ANGLETestBase::~ANGLETestBase()562{563if (mQuadVertexBuffer)564{565glDeleteBuffers(1, &mQuadVertexBuffer);566}567if (mQuadIndexBuffer)568{569glDeleteBuffers(1, &mQuadIndexBuffer);570}571if (m2DTexturedQuadProgram)572{573glDeleteProgram(m2DTexturedQuadProgram);574}575if (m3DTexturedQuadProgram)576{577glDeleteProgram(m3DTexturedQuadProgram);578}579580if (!mSetUpCalled)581{582GTEST_NONFATAL_FAILURE_("SetUp not called.");583}584585if (!mTearDownCalled)586{587GTEST_NONFATAL_FAILURE_("TearDown not called.");588}589}590591void ANGLETestBase::ANGLETestSetUp()592{593mSetUpCalled = true;594595// Delay test startup to allow a debugger to attach.596if (GetTestStartDelaySeconds())597{598angle::Sleep(GetTestStartDelaySeconds() * 1000);599}600601gDefaultPlatformMethods.overrideWorkaroundsD3D = TestPlatform_overrideWorkaroundsD3D;602gDefaultPlatformMethods.overrideFeaturesVk = TestPlatform_overrideFeaturesVk;603gDefaultPlatformMethods.logError = TestPlatform_logError;604gDefaultPlatformMethods.logWarning = TestPlatform_logWarning;605gDefaultPlatformMethods.logInfo = TestPlatform_logInfo;606gDefaultPlatformMethods.context = &gPlatformContext;607608gPlatformContext.ignoreMessages = false;609gPlatformContext.warningsAsErrors = false;610gPlatformContext.currentTest = this;611612const testing::TestInfo *testInfo = testing::UnitTest::GetInstance()->current_test_info();613614// Check the skip list.615616angle::GPUTestConfig::API api = GetTestConfigAPIFromRenderer(mCurrentParams->getRenderer(),617mCurrentParams->getDeviceType());618GPUTestConfig testConfig = GPUTestConfig(api, 0, false);619620std::stringstream fullTestNameStr;621fullTestNameStr << testInfo->test_case_name() << "." << testInfo->name();622std::string fullTestName = fullTestNameStr.str();623624TestSuite *testSuite = TestSuite::GetInstance();625int32_t testExpectation =626testSuite->getTestExpectationWithConfigAndUpdateTimeout(testConfig, fullTestName);627628if (testExpectation == GPUTestExpectationsParser::kGpuTestSkip)629{630GTEST_SKIP() << "Test skipped on this config";631}632633if (IsWindows())634{635WriteDebugMessage("Entering %s\n", fullTestName.c_str());636}637638if (mCurrentParams->noFixture)639{640LoadEntryPointsWithUtilLoader(mCurrentParams->driver);641mIsSetUp = true;642return;643}644645if (mLastLoadedDriver.valid() && mCurrentParams->driver != mLastLoadedDriver.value())646{647LoadEntryPointsWithUtilLoader(mCurrentParams->driver);648mLastLoadedDriver = mCurrentParams->driver;649}650651if (gEnableANGLEPerTestCaptureLabel)652{653SetupEnvironmentVarsForCaptureReplay();654}655656if (!mFixture->osWindow->valid())657{658mIsSetUp = true;659return;660}661662// Resize the window before creating the context so that the first make current663// sets the viewport and scissor box to the right size.664bool needSwap = false;665666int osWindowWidth = mFixture->osWindow->getWidth();667int osWindowHeight = mFixture->osWindow->getHeight();668669const bool isRotated = mCurrentParams->eglParameters.emulatedPrerotation == 90 ||670mCurrentParams->eglParameters.emulatedPrerotation == 270;671if (isRotated)672{673std::swap(osWindowWidth, osWindowHeight);674}675676if (osWindowWidth != mWidth || osWindowHeight != mHeight)677{678int newWindowWidth = mWidth;679int newWindowHeight = mHeight;680if (isRotated)681{682std::swap(newWindowWidth, newWindowHeight);683}684685if (!mFixture->osWindow->resize(newWindowWidth, newWindowHeight))686{687FAIL() << "Failed to resize ANGLE test window.";688}689needSwap = true;690}691// WGL tests are currently disabled.692if (mFixture->wglWindow)693{694FAIL() << "Unsupported driver.";695}696else697{698Library *driverLib = ANGLETestEnvironment::GetDriverLibrary(mCurrentParams->driver);699700if (mForceNewDisplay || !mFixture->eglWindow->isDisplayInitialized())701{702mFixture->eglWindow->destroyGL();703if (!mFixture->eglWindow->initializeDisplay(mFixture->osWindow, driverLib,704mCurrentParams->driver,705mCurrentParams->eglParameters))706{707FAIL() << "EGL Display init failed.";708}709}710else if (mCurrentParams->eglParameters != mFixture->eglWindow->getPlatform())711{712FAIL() << "Internal parameter conflict error.";713}714715if (!mFixture->eglWindow->initializeSurface(mFixture->osWindow, driverLib,716mFixture->configParams))717{718FAIL() << "egl surface init failed.";719}720721if (!mDeferContextInit && !mFixture->eglWindow->initializeContext())722{723FAIL() << "GL Context init failed.";724}725}726727if (needSwap)728{729// Swap the buffers so that the default framebuffer picks up the resize730// which will allow follow-up test code to assume the framebuffer covers731// the whole window.732swapBuffers();733}734735// This Viewport command is not strictly necessary but we add it so that programs736// taking OpenGL traces can guess the size of the default framebuffer and show it737// in their UIs738glViewport(0, 0, mWidth, mHeight);739740mIsSetUp = true;741742mRenderDoc.startFrame();743}744745void ANGLETestBase::ANGLETestPreTearDown()746{747// We swap an extra time before we call "tearDown" to capture resources before they're freed.748if (gEnableANGLEPerTestCaptureLabel)749{750swapBuffers();751}752}753754void ANGLETestBase::ANGLETestTearDown()755{756mTearDownCalled = true;757gPlatformContext.currentTest = nullptr;758759if (IsWindows())760{761const testing::TestInfo *info = testing::UnitTest::GetInstance()->current_test_info();762WriteDebugMessage("Exiting %s.%s\n", info->test_case_name(), info->name());763}764765if (mCurrentParams->noFixture || !mFixture->osWindow->valid())766{767mRenderDoc.endFrame();768return;769}770771swapBuffers();772mFixture->osWindow->messageLoop();773774mRenderDoc.endFrame();775776if (mFixture->eglWindow)777{778checkD3D11SDKLayersMessages();779}780781if (mFixture->reuseCounter++ >= kWindowReuseLimit || mForceNewDisplay)782{783if (!mForceNewDisplay)784{785printf("Recreating test window because of reuse limit of %d\n", kWindowReuseLimit);786}787788mFixture->reuseCounter = 0;789getGLWindow()->destroyGL();790}791else792{793mFixture->eglWindow->destroyContext();794mFixture->eglWindow->destroySurface();795}796797// Check for quit message798Event myEvent;799while (mFixture->osWindow->popEvent(&myEvent))800{801if (myEvent.Type == Event::EVENT_CLOSED)802{803exit(0);804}805}806}807808void ANGLETestBase::ReleaseFixtures()809{810for (auto it = gFixtures.begin(); it != gFixtures.end(); it++)811{812if (it->second.eglWindow)813{814it->second.eglWindow->destroyGL();815}816}817}818819void ANGLETestBase::swapBuffers()820{821if (getGLWindow()->isGLInitialized())822{823getGLWindow()->swap();824825if (mFixture->eglWindow)826{827EXPECT_EGL_SUCCESS();828}829}830}831832void ANGLETestBase::setupQuadVertexBuffer(GLfloat positionAttribZ, GLfloat positionAttribXYScale)833{834if (mQuadVertexBuffer == 0)835{836glGenBuffers(1, &mQuadVertexBuffer);837}838839auto quadVertices = GetQuadVertices();840for (Vector3 &vertex : quadVertices)841{842vertex.x() *= positionAttribXYScale;843vertex.y() *= positionAttribXYScale;844vertex.z() = positionAttribZ;845}846847glBindBuffer(GL_ARRAY_BUFFER, mQuadVertexBuffer);848glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 6, quadVertices.data(), GL_STATIC_DRAW);849}850851void ANGLETestBase::setupIndexedQuadVertexBuffer(GLfloat positionAttribZ,852GLfloat positionAttribXYScale)853{854if (mQuadVertexBuffer == 0)855{856glGenBuffers(1, &mQuadVertexBuffer);857}858859auto quadVertices = kIndexedQuadVertices;860for (Vector3 &vertex : quadVertices)861{862vertex.x() *= positionAttribXYScale;863vertex.y() *= positionAttribXYScale;864vertex.z() = positionAttribZ;865}866867glBindBuffer(GL_ARRAY_BUFFER, mQuadVertexBuffer);868glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 4, quadVertices.data(), GL_STATIC_DRAW);869}870871void ANGLETestBase::setupIndexedQuadIndexBuffer()872{873if (mQuadIndexBuffer == 0)874{875glGenBuffers(1, &mQuadIndexBuffer);876}877878glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mQuadIndexBuffer);879glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexedQuadIndices), kIndexedQuadIndices.data(),880GL_STATIC_DRAW);881}882883// static884void ANGLETestBase::drawQuad(GLuint program,885const std::string &positionAttribName,886GLfloat positionAttribZ)887{888drawQuad(program, positionAttribName, positionAttribZ, 1.0f);889}890891// static892void ANGLETestBase::drawQuad(GLuint program,893const std::string &positionAttribName,894GLfloat positionAttribZ,895GLfloat positionAttribXYScale)896{897drawQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale, false);898}899900void ANGLETestBase::drawQuad(GLuint program,901const std::string &positionAttribName,902GLfloat positionAttribZ,903GLfloat positionAttribXYScale,904bool useVertexBuffer)905{906drawQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale, useVertexBuffer,907false, false, 0u);908}909910void ANGLETestBase::drawQuadInstanced(GLuint program,911const std::string &positionAttribName,912GLfloat positionAttribZ,913GLfloat positionAttribXYScale,914bool useVertexBuffer,915GLuint numInstances)916{917drawQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale, useVertexBuffer,918true, false, numInstances);919}920921void ANGLETestBase::drawPatches(GLuint program,922const std::string &positionAttribName,923GLfloat positionAttribZ,924GLfloat positionAttribXYScale,925bool useVertexBuffer)926{927drawQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale, useVertexBuffer,928false, true, 0u);929}930931void ANGLETestBase::drawQuad(GLuint program,932const std::string &positionAttribName,933GLfloat positionAttribZ,934GLfloat positionAttribXYScale,935bool useVertexBuffer,936bool useInstancedDrawCalls,937bool useTessellationPatches,938GLuint numInstances)939{940GLint previousProgram = 0;941glGetIntegerv(GL_CURRENT_PROGRAM, &previousProgram);942if (previousProgram != static_cast<GLint>(program))943{944glUseProgram(program);945}946947GLint previousBuffer = 0;948glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &previousBuffer);949950GLint positionLocation = glGetAttribLocation(program, positionAttribName.c_str());951952std::array<Vector3, 6> quadVertices = GetQuadVertices();953954if (useVertexBuffer)955{956setupQuadVertexBuffer(positionAttribZ, positionAttribXYScale);957glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);958glBindBuffer(GL_ARRAY_BUFFER, previousBuffer);959}960else961{962for (Vector3 &vertex : quadVertices)963{964vertex.x() *= positionAttribXYScale;965vertex.y() *= positionAttribXYScale;966vertex.z() = positionAttribZ;967}968969if (previousBuffer != 0)970{971glBindBuffer(GL_ARRAY_BUFFER, 0);972}973glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());974if (previousBuffer != 0)975{976glBindBuffer(GL_ARRAY_BUFFER, previousBuffer);977}978}979glEnableVertexAttribArray(positionLocation);980GLenum drawMode = (useTessellationPatches) ? GL_PATCHES : GL_TRIANGLES;981982if (useInstancedDrawCalls)983{984glDrawArraysInstanced(drawMode, 0, 6, numInstances);985}986else987{988glDrawArrays(drawMode, 0, 6);989}990991glDisableVertexAttribArray(positionLocation);992glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);993994if (previousProgram != static_cast<GLint>(program))995{996glUseProgram(previousProgram);997}998}9991000void ANGLETestBase::drawQuadPPO(GLuint vertProgram,1001const std::string &positionAttribName,1002const GLfloat positionAttribZ,1003const GLfloat positionAttribXYScale)1004{1005GLint activeProgram = 0;1006glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram);1007if (activeProgram)1008{1009glUseProgram(0);1010}10111012std::array<Vector3, 6> quadVertices = GetQuadVertices();10131014for (Vector3 &vertex : quadVertices)1015{1016vertex.x() *= positionAttribXYScale;1017vertex.y() *= positionAttribXYScale;1018vertex.z() = positionAttribZ;1019}10201021GLint positionLocation = glGetAttribLocation(vertProgram, positionAttribName.c_str());10221023glBindBuffer(GL_ARRAY_BUFFER, 0);1024glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());1025glEnableVertexAttribArray(positionLocation);10261027glDrawArrays(GL_TRIANGLES, 0, 6);10281029glDisableVertexAttribArray(positionLocation);1030glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);10311032if (activeProgram)1033{1034glUseProgram(static_cast<GLuint>(activeProgram));1035}1036}10371038void ANGLETestBase::drawIndexedQuad(GLuint program,1039const std::string &positionAttribName,1040GLfloat positionAttribZ)1041{1042drawIndexedQuad(program, positionAttribName, positionAttribZ, 1.0f);1043}10441045void ANGLETestBase::drawIndexedQuad(GLuint program,1046const std::string &positionAttribName,1047GLfloat positionAttribZ,1048GLfloat positionAttribXYScale)1049{1050ASSERT(!mFixture->configParams.webGLCompatibility.valid() ||1051!mFixture->configParams.webGLCompatibility.value());1052drawIndexedQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale, false);1053}10541055void ANGLETestBase::drawIndexedQuad(GLuint program,1056const std::string &positionAttribName,1057GLfloat positionAttribZ,1058GLfloat positionAttribXYScale,1059bool useIndexBuffer)1060{1061drawIndexedQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale,1062useIndexBuffer, false);1063}10641065void ANGLETestBase::drawIndexedQuad(GLuint program,1066const std::string &positionAttribName,1067GLfloat positionAttribZ,1068GLfloat positionAttribXYScale,1069bool useIndexBuffer,1070bool restrictedRange)1071{1072GLint positionLocation = glGetAttribLocation(program, positionAttribName.c_str());10731074GLint activeProgram = 0;1075glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram);1076if (static_cast<GLuint>(activeProgram) != program)1077{1078glUseProgram(program);1079}10801081GLuint prevCoordBinding = 0;1082glGetIntegerv(GL_ARRAY_BUFFER_BINDING, reinterpret_cast<GLint *>(&prevCoordBinding));10831084setupIndexedQuadVertexBuffer(positionAttribZ, positionAttribXYScale);10851086glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);1087glEnableVertexAttribArray(positionLocation);1088glBindBuffer(GL_ARRAY_BUFFER, prevCoordBinding);10891090GLuint prevIndexBinding = 0;1091const GLvoid *indices;1092if (useIndexBuffer)1093{1094glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING,1095reinterpret_cast<GLint *>(&prevIndexBinding));10961097setupIndexedQuadIndexBuffer();1098indices = 0;1099}1100else1101{1102indices = kIndexedQuadIndices.data();1103}11041105if (!restrictedRange)1106{1107glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);1108}1109else1110{1111glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, indices);1112}11131114if (useIndexBuffer)1115{1116glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prevIndexBinding);1117}11181119glDisableVertexAttribArray(positionLocation);1120glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);11211122if (static_cast<GLuint>(activeProgram) != program)1123{1124glUseProgram(static_cast<GLuint>(activeProgram));1125}1126}11271128GLuint ANGLETestBase::get2DTexturedQuadProgram()1129{1130if (m2DTexturedQuadProgram)1131{1132return m2DTexturedQuadProgram;1133}11341135constexpr char kVS[] =1136"attribute vec2 position;\n"1137"varying mediump vec2 texCoord;\n"1138"void main()\n"1139"{\n"1140" gl_Position = vec4(position, 0, 1);\n"1141" texCoord = position * 0.5 + vec2(0.5);\n"1142"}\n";11431144constexpr char kFS[] =1145"varying mediump vec2 texCoord;\n"1146"uniform sampler2D tex;\n"1147"void main()\n"1148"{\n"1149" gl_FragColor = texture2D(tex, texCoord);\n"1150"}\n";11511152m2DTexturedQuadProgram = CompileProgram(kVS, kFS);1153return m2DTexturedQuadProgram;1154}11551156GLuint ANGLETestBase::get3DTexturedQuadProgram()1157{1158if (m3DTexturedQuadProgram)1159{1160return m3DTexturedQuadProgram;1161}11621163constexpr char kVS[] = R"(#version 300 es1164in vec2 position;1165out vec2 texCoord;1166void main()1167{1168gl_Position = vec4(position, 0, 1);1169texCoord = position * 0.5 + vec2(0.5);1170})";11711172constexpr char kFS[] = R"(#version 300 es1173precision highp float;11741175in vec2 texCoord;1176out vec4 my_FragColor;11771178uniform highp sampler3D tex;1179uniform float u_layer;11801181void main()1182{1183my_FragColor = texture(tex, vec3(texCoord, u_layer));1184})";11851186m3DTexturedQuadProgram = CompileProgram(kVS, kFS);1187return m3DTexturedQuadProgram;1188}11891190void ANGLETestBase::draw2DTexturedQuad(GLfloat positionAttribZ,1191GLfloat positionAttribXYScale,1192bool useVertexBuffer)1193{1194ASSERT_NE(0u, get2DTexturedQuadProgram());1195drawQuad(get2DTexturedQuadProgram(), "position", positionAttribZ, positionAttribXYScale,1196useVertexBuffer);1197}11981199void ANGLETestBase::draw3DTexturedQuad(GLfloat positionAttribZ,1200GLfloat positionAttribXYScale,1201bool useVertexBuffer,1202float layer)1203{1204GLuint program = get3DTexturedQuadProgram();1205ASSERT_NE(0u, program);1206GLint activeProgram = 0;1207glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram);1208if (static_cast<GLuint>(activeProgram) != program)1209{1210glUseProgram(program);1211}1212glUniform1f(glGetUniformLocation(program, "u_layer"), layer);12131214drawQuad(program, "position", positionAttribZ, positionAttribXYScale, useVertexBuffer);12151216if (static_cast<GLuint>(activeProgram) != program)1217{1218glUseProgram(static_cast<GLuint>(activeProgram));1219}1220}12211222bool ANGLETestBase::platformSupportsMultithreading() const1223{1224return (IsOpenGLES() && IsAndroid()) || IsVulkan();1225}12261227void ANGLETestBase::checkD3D11SDKLayersMessages()1228{1229#if defined(ANGLE_PLATFORM_WINDOWS)1230// On Windows D3D11, check ID3D11InfoQueue to see if any D3D11 SDK Layers messages1231// were outputted by the test. We enable the Debug layers in Release tests as well.1232if (mIgnoreD3D11SDKLayersWarnings ||1233mFixture->eglWindow->getPlatform().renderer != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE ||1234mFixture->eglWindow->getDisplay() == EGL_NO_DISPLAY)1235{1236return;1237}12381239const char *extensionString = static_cast<const char *>(1240eglQueryString(mFixture->eglWindow->getDisplay(), EGL_EXTENSIONS));1241if (!extensionString)1242{1243std::cout << "Error getting extension string from EGL Window." << std::endl;1244return;1245}12461247if (!strstr(extensionString, "EGL_EXT_device_query"))1248{1249return;1250}12511252EGLAttrib device = 0;1253EGLAttrib angleDevice = 0;12541255ASSERT_EGL_TRUE(1256eglQueryDisplayAttribEXT(mFixture->eglWindow->getDisplay(), EGL_DEVICE_EXT, &angleDevice));1257ASSERT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice),1258EGL_D3D11_DEVICE_ANGLE, &device));1259ID3D11Device *d3d11Device = reinterpret_cast<ID3D11Device *>(device);12601261ID3D11InfoQueue *infoQueue = nullptr;1262HRESULT hr =1263d3d11Device->QueryInterface(__uuidof(infoQueue), reinterpret_cast<void **>(&infoQueue));1264if (SUCCEEDED(hr))1265{1266UINT64 numStoredD3DDebugMessages =1267infoQueue->GetNumStoredMessagesAllowedByRetrievalFilter();12681269if (numStoredD3DDebugMessages > 0)1270{1271for (UINT64 i = 0; i < numStoredD3DDebugMessages; i++)1272{1273SIZE_T messageLength = 0;1274hr = infoQueue->GetMessage(i, nullptr, &messageLength);12751276if (SUCCEEDED(hr))1277{1278D3D11_MESSAGE *pMessage =1279reinterpret_cast<D3D11_MESSAGE *>(malloc(messageLength));1280infoQueue->GetMessage(i, pMessage, &messageLength);12811282std::cout << "Message " << i << ":"1283<< " " << pMessage->pDescription << "\n";1284free(pMessage);1285}1286}1287// Clear the queue, so that previous failures are not reported1288// for subsequent, otherwise passing, tests1289infoQueue->ClearStoredMessages();12901291FAIL() << numStoredD3DDebugMessages1292<< " D3D11 SDK Layers message(s) detected! Test Failed.\n";1293}1294}12951296SafeRelease(infoQueue);1297#endif // defined(ANGLE_PLATFORM_WINDOWS)1298}12991300void ANGLETestBase::setWindowWidth(int width)1301{1302mWidth = width;1303}13041305void ANGLETestBase::setWindowHeight(int height)1306{1307mHeight = height;1308}13091310GLWindowBase *ANGLETestBase::getGLWindow() const1311{1312// WGL tests are currently disabled.1313assert(!mFixture->wglWindow);1314return mFixture->eglWindow;1315}13161317void ANGLETestBase::setConfigRedBits(int bits)1318{1319mFixture->configParams.redBits = bits;1320}13211322void ANGLETestBase::setConfigGreenBits(int bits)1323{1324mFixture->configParams.greenBits = bits;1325}13261327void ANGLETestBase::setConfigBlueBits(int bits)1328{1329mFixture->configParams.blueBits = bits;1330}13311332void ANGLETestBase::setConfigAlphaBits(int bits)1333{1334mFixture->configParams.alphaBits = bits;1335}13361337void ANGLETestBase::setConfigDepthBits(int bits)1338{1339mFixture->configParams.depthBits = bits;1340}13411342void ANGLETestBase::setConfigStencilBits(int bits)1343{1344mFixture->configParams.stencilBits = bits;1345}13461347void ANGLETestBase::setConfigComponentType(EGLenum componentType)1348{1349mFixture->configParams.componentType = componentType;1350}13511352void ANGLETestBase::setMultisampleEnabled(bool enabled)1353{1354mFixture->configParams.multisample = enabled;1355}13561357void ANGLETestBase::setSamples(EGLint samples)1358{1359mFixture->configParams.samples = samples;1360}13611362void ANGLETestBase::setDebugEnabled(bool enabled)1363{1364mFixture->configParams.debug = enabled;1365}13661367void ANGLETestBase::setNoErrorEnabled(bool enabled)1368{1369mFixture->configParams.noError = enabled;1370}13711372void ANGLETestBase::setWebGLCompatibilityEnabled(bool webglCompatibility)1373{1374mFixture->configParams.webGLCompatibility = webglCompatibility;1375}13761377void ANGLETestBase::setExtensionsEnabled(bool extensionsEnabled)1378{1379mFixture->configParams.extensionsEnabled = extensionsEnabled;1380}13811382void ANGLETestBase::setRobustAccess(bool enabled)1383{1384mFixture->configParams.robustAccess = enabled;1385}13861387void ANGLETestBase::setBindGeneratesResource(bool bindGeneratesResource)1388{1389mFixture->configParams.bindGeneratesResource = bindGeneratesResource;1390}13911392void ANGLETestBase::setClientArraysEnabled(bool enabled)1393{1394mFixture->configParams.clientArraysEnabled = enabled;1395}13961397void ANGLETestBase::setRobustResourceInit(bool enabled)1398{1399mFixture->configParams.robustResourceInit = enabled;1400}14011402void ANGLETestBase::setContextProgramCacheEnabled(bool enabled)1403{1404mFixture->configParams.contextProgramCacheEnabled = enabled;1405}14061407void ANGLETestBase::setContextResetStrategy(EGLenum resetStrategy)1408{1409mFixture->configParams.resetStrategy = resetStrategy;1410}14111412void ANGLETestBase::forceNewDisplay()1413{1414mForceNewDisplay = true;1415}14161417void ANGLETestBase::setDeferContextInit(bool enabled)1418{1419mDeferContextInit = enabled;1420}14211422int ANGLETestBase::getClientMajorVersion() const1423{1424return getGLWindow()->getClientMajorVersion();1425}14261427int ANGLETestBase::getClientMinorVersion() const1428{1429return getGLWindow()->getClientMinorVersion();1430}14311432EGLWindow *ANGLETestBase::getEGLWindow() const1433{1434return mFixture->eglWindow;1435}14361437int ANGLETestBase::getWindowWidth() const1438{1439return mWidth;1440}14411442int ANGLETestBase::getWindowHeight() const1443{1444return mHeight;1445}14461447bool ANGLETestBase::isEmulatedPrerotation() const1448{1449return mCurrentParams->eglParameters.emulatedPrerotation != 0;1450}14511452void ANGLETestBase::setWindowVisible(OSWindow *osWindow, bool isVisible)1453{1454// SwiftShader windows are not required to be visible for test correctness,1455// moreover, making a SwiftShader window visible flaky hangs on Xvfb, so we keep them hidden.1456if (isSwiftshader())1457{1458return;1459}1460osWindow->setVisible(isVisible);1461}14621463ANGLETestBase::TestFixture::TestFixture() = default;1464ANGLETestBase::TestFixture::~TestFixture() = default;14651466EGLint ANGLETestBase::getPlatformRenderer() const1467{1468assert(mFixture->eglWindow);1469return mFixture->eglWindow->getPlatform().renderer;1470}14711472void ANGLETestBase::ignoreD3D11SDKLayersWarnings()1473{1474// Some tests may need to disable the D3D11 SDK Layers Warnings checks1475mIgnoreD3D11SDKLayersWarnings = true;1476}14771478void ANGLETestBase::treatPlatformWarningsAsErrors()1479{1480#if defined(ANGLE_PLATFORM_WINDOWS)1481// Only do warnings-as-errors on 8 and above. We may fall back to the old1482// compiler DLL on Windows 7.1483gPlatformContext.warningsAsErrors = IsWindows8OrGreater();1484#endif // defined(ANGLE_PLATFORM_WINDOWS)1485}14861487ANGLETestBase::ScopedIgnorePlatformMessages::ScopedIgnorePlatformMessages()1488{1489gPlatformContext.ignoreMessages = true;1490}14911492ANGLETestBase::ScopedIgnorePlatformMessages::~ScopedIgnorePlatformMessages()1493{1494gPlatformContext.ignoreMessages = false;1495}14961497OSWindow *ANGLETestBase::mOSWindowSingleton = nullptr;1498std::map<angle::PlatformParameters, ANGLETestBase::TestFixture> ANGLETestBase::gFixtures;1499Optional<EGLint> ANGLETestBase::mLastRendererType;1500Optional<angle::GLESDriverType> ANGLETestBase::mLastLoadedDriver;15011502std::unique_ptr<Library> ANGLETestEnvironment::gAngleEGLLibrary;1503std::unique_ptr<Library> ANGLETestEnvironment::gSystemEGLLibrary;1504std::unique_ptr<Library> ANGLETestEnvironment::gSystemWGLLibrary;15051506void ANGLETestEnvironment::SetUp() {}15071508void ANGLETestEnvironment::TearDown()1509{1510ANGLETestBase::ReleaseFixtures();1511}15121513// static1514Library *ANGLETestEnvironment::GetDriverLibrary(angle::GLESDriverType driver)1515{1516switch (driver)1517{1518case angle::GLESDriverType::AngleEGL:1519return GetAngleEGLLibrary();1520case angle::GLESDriverType::SystemEGL:1521return GetSystemEGLLibrary();1522case angle::GLESDriverType::SystemWGL:1523return GetSystemWGLLibrary();1524default:1525return nullptr;1526}1527}15281529// static1530Library *ANGLETestEnvironment::GetAngleEGLLibrary()1531{1532#if defined(ANGLE_USE_UTIL_LOADER)1533if (!gAngleEGLLibrary)1534{1535gAngleEGLLibrary.reset(OpenSharedLibrary(ANGLE_EGL_LIBRARY_NAME, SearchType::ModuleDir));1536}1537#endif // defined(ANGLE_USE_UTIL_LOADER)1538return gAngleEGLLibrary.get();1539}15401541// static1542Library *ANGLETestEnvironment::GetSystemEGLLibrary()1543{1544#if defined(ANGLE_USE_UTIL_LOADER)1545if (!gSystemEGLLibrary)1546{1547gSystemEGLLibrary.reset(OpenSharedLibraryWithExtension(1548GetNativeEGLLibraryNameWithExtension(), SearchType::SystemDir));1549}1550#endif // defined(ANGLE_USE_UTIL_LOADER)1551return gSystemEGLLibrary.get();1552}15531554// static1555Library *ANGLETestEnvironment::GetSystemWGLLibrary()1556{1557#if defined(ANGLE_USE_UTIL_LOADER) && defined(ANGLE_PLATFORM_WINDOWS)1558if (!gSystemWGLLibrary)1559{1560gSystemWGLLibrary.reset(OpenSharedLibrary("opengl32", SearchType::SystemDir));1561}1562#endif // defined(ANGLE_USE_UTIL_LOADER) && defined(ANGLE_PLATFORM_WINDOWS)1563return gSystemWGLLibrary.get();1564}15651566void ANGLEProcessTestArgs(int *argc, char *argv[])1567{1568testing::AddGlobalTestEnvironment(new ANGLETestEnvironment());15691570for (int argIndex = 1; argIndex < *argc; argIndex++)1571{1572if (strncmp(argv[argIndex], kUseConfig, strlen(kUseConfig)) == 0)1573{1574SetSelectedConfig(argv[argIndex] + strlen(kUseConfig));1575}1576else if (strncmp(argv[argIndex], kReuseDisplays, strlen(kReuseDisplays)) == 0)1577{1578gReuseDisplays = true;1579}1580else if (strncmp(argv[argIndex], kBatchId, strlen(kBatchId)) == 0)1581{1582// Enable display reuse when running under --bot-mode.1583gReuseDisplays = true;1584}1585else if (strncmp(argv[argIndex], kEnableANGLEPerTestCaptureLabel,1586strlen(kEnableANGLEPerTestCaptureLabel)) == 0)1587{1588gEnableANGLEPerTestCaptureLabel = true;1589}1590else if (strncmp(argv[argIndex], kDelayTestStart, strlen(kDelayTestStart)) == 0)1591{1592SetTestStartDelay(argv[argIndex] + strlen(kDelayTestStart));1593}1594else if (strncmp(argv[argIndex], kRenderDoc, strlen(kRenderDoc)) == 0)1595{1596gEnableRenderDocCapture = true;1597}1598}1599}160016011602