• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // ANGLETest:
7 //   Implementation of common ANGLE testing fixture.
8 //
9 
10 #include "ANGLETest.h"
11 
12 #include "common/platform.h"
13 #include "gpu_info_util/SystemInfo.h"
14 #include "util/EGLWindow.h"
15 #include "util/OSWindow.h"
16 #include "util/random_utils.h"
17 #include "util/test_utils.h"
18 
19 #if defined(ANGLE_PLATFORM_WINDOWS)
20 #    include <VersionHelpers.h>
21 #endif  // defined(ANGLE_PLATFORM_WINDOWS)
22 
23 namespace angle
24 {
25 
26 const GLColorRGB GLColorRGB::black(0u, 0u, 0u);
27 const GLColorRGB GLColorRGB::blue(0u, 0u, 255u);
28 const GLColorRGB GLColorRGB::green(0u, 255u, 0u);
29 const GLColorRGB GLColorRGB::red(255u, 0u, 0u);
30 const GLColorRGB GLColorRGB::yellow(255u, 255u, 0);
31 
32 const GLColor GLColor::black            = GLColor(0u, 0u, 0u, 255u);
33 const GLColor GLColor::blue             = GLColor(0u, 0u, 255u, 255u);
34 const GLColor GLColor::cyan             = GLColor(0u, 255u, 255u, 255u);
35 const GLColor GLColor::green            = GLColor(0u, 255u, 0u, 255u);
36 const GLColor GLColor::red              = GLColor(255u, 0u, 0u, 255u);
37 const GLColor GLColor::transparentBlack = GLColor(0u, 0u, 0u, 0u);
38 const GLColor GLColor::white            = GLColor(255u, 255u, 255u, 255u);
39 const GLColor GLColor::yellow           = GLColor(255u, 255u, 0, 255u);
40 const GLColor GLColor::magenta          = GLColor(255u, 0u, 255u, 255u);
41 
42 namespace
43 {
ColorNorm(GLubyte channelValue)44 float ColorNorm(GLubyte channelValue)
45 {
46     return static_cast<float>(channelValue) / 255.0f;
47 }
48 
ColorDenorm(float colorValue)49 GLubyte ColorDenorm(float colorValue)
50 {
51     return static_cast<GLubyte>(colorValue * 255.0f);
52 }
53 
TestPlatform_logError(PlatformMethods * platform,const char * errorMessage)54 void TestPlatform_logError(PlatformMethods *platform, const char *errorMessage)
55 {
56     auto *testPlatformContext = static_cast<TestPlatformContext *>(platform->context);
57     if (testPlatformContext->ignoreMessages)
58         return;
59 
60     GTEST_NONFATAL_FAILURE_(errorMessage);
61 
62     PrintStackBacktrace();
63 }
64 
TestPlatform_logWarning(PlatformMethods * platform,const char * warningMessage)65 void TestPlatform_logWarning(PlatformMethods *platform, const char *warningMessage)
66 {
67     auto *testPlatformContext = static_cast<TestPlatformContext *>(platform->context);
68     if (testPlatformContext->ignoreMessages)
69         return;
70 
71     if (testPlatformContext->warningsAsErrors)
72     {
73         FAIL() << warningMessage;
74     }
75     else
76     {
77         std::cerr << "Warning: " << warningMessage << std::endl;
78     }
79 }
80 
TestPlatform_logInfo(PlatformMethods * platform,const char * infoMessage)81 void TestPlatform_logInfo(PlatformMethods *platform, const char *infoMessage) {}
82 
TestPlatform_overrideWorkaroundsD3D(PlatformMethods * platform,FeaturesD3D * featuresD3D)83 void TestPlatform_overrideWorkaroundsD3D(PlatformMethods *platform, FeaturesD3D *featuresD3D)
84 {
85     auto *testPlatformContext = static_cast<TestPlatformContext *>(platform->context);
86     if (testPlatformContext->currentTest)
87     {
88         testPlatformContext->currentTest->overrideWorkaroundsD3D(featuresD3D);
89     }
90 }
91 
TestPlatform_overrideFeaturesVk(PlatformMethods * platform,FeaturesVk * featuresVulkan)92 void TestPlatform_overrideFeaturesVk(PlatformMethods *platform, FeaturesVk *featuresVulkan)
93 {
94     auto *testPlatformContext = static_cast<TestPlatformContext *>(platform->context);
95     if (testPlatformContext->currentTest)
96     {
97         testPlatformContext->currentTest->overrideFeaturesVk(featuresVulkan);
98     }
99 }
100 
101 const std::array<Vector3, 6> kQuadVertices = {{
102     Vector3(-1.0f, 1.0f, 0.5f),
103     Vector3(-1.0f, -1.0f, 0.5f),
104     Vector3(1.0f, -1.0f, 0.5f),
105     Vector3(-1.0f, 1.0f, 0.5f),
106     Vector3(1.0f, -1.0f, 0.5f),
107     Vector3(1.0f, 1.0f, 0.5f),
108 }};
109 
110 const std::array<Vector3, 4> kIndexedQuadVertices = {{
111     Vector3(-1.0f, 1.0f, 0.5f),
112     Vector3(-1.0f, -1.0f, 0.5f),
113     Vector3(1.0f, -1.0f, 0.5f),
114     Vector3(1.0f, 1.0f, 0.5f),
115 }};
116 
117 constexpr std::array<GLushort, 6> kIndexedQuadIndices = {{0, 1, 2, 0, 2, 3}};
118 
GetColorName(GLColor color)119 const char *GetColorName(GLColor color)
120 {
121     if (color == GLColor::red)
122     {
123         return "Red";
124     }
125 
126     if (color == GLColor::green)
127     {
128         return "Green";
129     }
130 
131     if (color == GLColor::blue)
132     {
133         return "Blue";
134     }
135 
136     if (color == GLColor::white)
137     {
138         return "White";
139     }
140 
141     if (color == GLColor::black)
142     {
143         return "Black";
144     }
145 
146     if (color == GLColor::transparentBlack)
147     {
148         return "Transparent Black";
149     }
150 
151     if (color == GLColor::yellow)
152     {
153         return "Yellow";
154     }
155 
156     if (color == GLColor::magenta)
157     {
158         return "Magenta";
159     }
160 
161     if (color == GLColor::cyan)
162     {
163         return "Cyan";
164     }
165 
166     return nullptr;
167 }
168 
ShouldAlwaysForceNewDisplay()169 bool ShouldAlwaysForceNewDisplay()
170 {
171     // We prefer to reuse config displays. This is faster and solves a driver issue where creating
172     // many displays causes crashes. However this exposes other driver bugs on many other platforms.
173     // Conservatively enable the feature only on Windows Intel and NVIDIA for now.
174     SystemInfo *systemInfo = GetTestSystemInfo();
175     return (!systemInfo || !IsWindows() || systemInfo->hasAMDGPU());
176 }
177 }  // anonymous namespace
178 
GLColorRGB(const Vector3 & floatColor)179 GLColorRGB::GLColorRGB(const Vector3 &floatColor)
180     : R(ColorDenorm(floatColor.x())), G(ColorDenorm(floatColor.y())), B(ColorDenorm(floatColor.z()))
181 {}
182 
GLColor(const Vector4 & floatColor)183 GLColor::GLColor(const Vector4 &floatColor)
184     : R(ColorDenorm(floatColor.x())),
185       G(ColorDenorm(floatColor.y())),
186       B(ColorDenorm(floatColor.z())),
187       A(ColorDenorm(floatColor.w()))
188 {}
189 
GLColor(GLuint colorValue)190 GLColor::GLColor(GLuint colorValue) : R(0), G(0), B(0), A(0)
191 {
192     memcpy(&R, &colorValue, sizeof(GLuint));
193 }
194 
ExpectNear(const GLColor & expected,const GLColor & err) const195 testing::AssertionResult GLColor::ExpectNear(const GLColor &expected, const GLColor &err) const
196 {
197     testing::AssertionResult result(
198         abs(int(expected.R) - this->R) <= err.R && abs(int(expected.G) - this->G) <= err.G &&
199         abs(int(expected.B) - this->B) <= err.B && abs(int(expected.A) - this->A) <= err.A);
200     if (!bool(result))
201     {
202         result << "Expected " << expected << "+/-" << err << ", was " << *this;
203     }
204     return result;
205 }
206 
CreatePixelCenterWindowCoords(const std::vector<Vector2> & pixelPoints,int windowWidth,int windowHeight,std::vector<Vector3> * outVertices)207 void CreatePixelCenterWindowCoords(const std::vector<Vector2> &pixelPoints,
208                                    int windowWidth,
209                                    int windowHeight,
210                                    std::vector<Vector3> *outVertices)
211 {
212     for (Vector2 pixelPoint : pixelPoints)
213     {
214         outVertices->emplace_back(Vector3((pixelPoint[0] + 0.5f) * 2.0f / windowWidth - 1.0f,
215                                           (pixelPoint[1] + 0.5f) * 2.0f / windowHeight - 1.0f,
216                                           0.0f));
217     }
218 }
219 
toNormalizedVector() const220 Vector4 GLColor::toNormalizedVector() const
221 {
222     return Vector4(ColorNorm(R), ColorNorm(G), ColorNorm(B), ColorNorm(A));
223 }
224 
RandomColor(angle::RNG * rng)225 GLColor RandomColor(angle::RNG *rng)
226 {
227     return GLColor(rng->randomIntBetween(0, 255), rng->randomIntBetween(0, 255),
228                    rng->randomIntBetween(0, 255), rng->randomIntBetween(0, 255));
229 }
230 
ReadColor(GLint x,GLint y)231 GLColor ReadColor(GLint x, GLint y)
232 {
233     GLColor actual;
234     glReadPixels((x), (y), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &actual.R);
235     EXPECT_GL_NO_ERROR();
236     return actual;
237 }
238 
operator ==(const GLColor & a,const GLColor & b)239 bool operator==(const GLColor &a, const GLColor &b)
240 {
241     return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;
242 }
243 
operator !=(const GLColor & a,const GLColor & b)244 bool operator!=(const GLColor &a, const GLColor &b)
245 {
246     return !(a == b);
247 }
248 
operator <<(std::ostream & ostream,const GLColor & color)249 std::ostream &operator<<(std::ostream &ostream, const GLColor &color)
250 {
251     const char *colorName = GetColorName(color);
252     if (colorName)
253     {
254         return ostream << colorName;
255     }
256 
257     ostream << "(" << static_cast<unsigned int>(color.R) << ", "
258             << static_cast<unsigned int>(color.G) << ", " << static_cast<unsigned int>(color.B)
259             << ", " << static_cast<unsigned int>(color.A) << ")";
260     return ostream;
261 }
262 
operator ==(const GLColor32F & a,const GLColor32F & b)263 bool operator==(const GLColor32F &a, const GLColor32F &b)
264 {
265     return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;
266 }
267 
operator <<(std::ostream & ostream,const GLColor32F & color)268 std::ostream &operator<<(std::ostream &ostream, const GLColor32F &color)
269 {
270     ostream << "(" << color.R << ", " << color.G << ", " << color.B << ", " << color.A << ")";
271     return ostream;
272 }
273 
ReadColor32F(GLint x,GLint y)274 GLColor32F ReadColor32F(GLint x, GLint y)
275 {
276     GLColor32F actual;
277     glReadPixels((x), (y), 1, 1, GL_RGBA, GL_FLOAT, &actual.R);
278     EXPECT_GL_NO_ERROR();
279     return actual;
280 }
281 
LoadEntryPointsWithUtilLoader(angle::GLESDriverType driverType)282 void LoadEntryPointsWithUtilLoader(angle::GLESDriverType driverType)
283 {
284 #if defined(ANGLE_USE_UTIL_LOADER)
285     PFNEGLGETPROCADDRESSPROC getProcAddress;
286     ANGLETestEnvironment::GetDriverLibrary(driverType)->getAs("eglGetProcAddress", &getProcAddress);
287     ASSERT_NE(nullptr, getProcAddress);
288 
289     LoadEGL(getProcAddress);
290     LoadGLES(getProcAddress);
291 #endif  // defined(ANGLE_USE_UTIL_LOADER)
292 }
293 }  // namespace angle
294 
295 using namespace angle;
296 
297 PlatformMethods gDefaultPlatformMethods;
298 
299 namespace
300 {
301 TestPlatformContext gPlatformContext;
302 
303 // After a fixed number of iterations we reset the test window. This works around some driver bugs.
304 constexpr uint32_t kWindowReuseLimit = 50;
305 
306 constexpr char kUseConfig[]                = "--use-config=";
307 constexpr char kSeparateProcessPerConfig[] = "--separate-process-per-config";
308 
RunSeparateProcessesForEachConfig(int * argc,char * argv[])309 bool RunSeparateProcessesForEachConfig(int *argc, char *argv[])
310 {
311     std::vector<const char *> commonArgs;
312     for (int argIndex = 0; argIndex < *argc; ++argIndex)
313     {
314         if (strncmp(argv[argIndex], kSeparateProcessPerConfig, strlen(kSeparateProcessPerConfig)) !=
315             0)
316         {
317             commonArgs.push_back(argv[argIndex]);
318         }
319     }
320 
321     // Force GoogleTest init now so that we hit the test config init in angle_test_instantiate.cpp.
322     // After instantiation is finished we can gather a full list of enabled configs. Then we can
323     // iterate the list of configs to spawn a child process for each enabled config.
324     testing::InitGoogleTest(argc, argv);
325 
326     std::vector<std::string> configNames = GetAvailableTestPlatformNames();
327 
328     bool success = true;
329 
330     for (const std::string &config : configNames)
331     {
332         std::stringstream strstr;
333         strstr << kUseConfig << config;
334 
335         std::string configStr = strstr.str();
336 
337         std::vector<const char *> childArgs = commonArgs;
338         childArgs.push_back(configStr.c_str());
339 
340         ProcessHandle process(childArgs, false, false);
341         if (!process->started() || !process->finish())
342         {
343             std::cerr << "Launching child config " << config << " failed.\n";
344         }
345         else if (process->getExitCode() != 0)
346         {
347             std::cerr << "Child config " << config << " failed with exit code "
348                       << process->getExitCode() << ".\n";
349             success = false;
350         }
351     }
352     return success;
353 }
354 }  // anonymous namespace
355 
356 // static
GetQuadVertices()357 std::array<Vector3, 6> ANGLETestBase::GetQuadVertices()
358 {
359     return kQuadVertices;
360 }
361 
362 // static
GetQuadIndices()363 std::array<GLushort, 6> ANGLETestBase::GetQuadIndices()
364 {
365     return kIndexedQuadIndices;
366 }
367 
368 // static
GetIndexedQuadVertices()369 std::array<Vector3, 4> ANGLETestBase::GetIndexedQuadVertices()
370 {
371     return kIndexedQuadVertices;
372 }
373 
ANGLETestBase(const PlatformParameters & params)374 ANGLETestBase::ANGLETestBase(const PlatformParameters &params)
375     : mWidth(16),
376       mHeight(16),
377       mIgnoreD3D11SDKLayersWarnings(false),
378       mQuadVertexBuffer(0),
379       mQuadIndexBuffer(0),
380       m2DTexturedQuadProgram(0),
381       m3DTexturedQuadProgram(0),
382       mDeferContextInit(false),
383       mAlwaysForceNewDisplay(ShouldAlwaysForceNewDisplay()),
384       mForceNewDisplay(mAlwaysForceNewDisplay),
385       mSetUpCalled(false),
386       mTearDownCalled(false),
387       mCurrentParams(nullptr),
388       mFixture(nullptr)
389 {
390     // Override the default platform methods with the ANGLE test methods pointer.
391     PlatformParameters withMethods            = params;
392     withMethods.eglParameters.platformMethods = &gDefaultPlatformMethods;
393 
394     // We don't build vulkan debug layers on Mac (http://anglebug.com/4376)
395     if (IsOSX() && withMethods.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
396     {
397         withMethods.eglParameters.debugLayersEnabled = false;
398     }
399 
400     auto iter = gFixtures.find(withMethods);
401     if (iter != gFixtures.end())
402     {
403         mCurrentParams = &iter->first;
404 
405         if (!params.noFixture)
406         {
407             mFixture = &iter->second;
408             mFixture->configParams.reset();
409         }
410         return;
411     }
412 
413     TestFixture platform;
414     auto insertIter = gFixtures.emplace(withMethods, platform);
415     mCurrentParams  = &insertIter.first->first;
416 
417     if (!params.noFixture)
418     {
419         mFixture = &insertIter.first->second;
420         initOSWindow();
421     }
422 }
423 
initOSWindow()424 void ANGLETestBase::initOSWindow()
425 {
426     std::stringstream windowNameStream;
427     windowNameStream << "ANGLE Tests - " << *mCurrentParams;
428     std::string windowName = windowNameStream.str();
429 
430     if (IsAndroid())
431     {
432         // Only one window per test application on Android, shared among all fixtures
433         mFixture->osWindow = mOSWindowSingleton;
434     }
435 
436     if (!mFixture->osWindow)
437     {
438         mFixture->osWindow = OSWindow::New();
439         if (!mFixture->osWindow->initialize(windowName.c_str(), 128, 128))
440         {
441             std::cerr << "Failed to initialize OS Window.";
442         }
443 
444         if (IsAndroid())
445         {
446             // Initialize the single window on Andoird only once
447             mOSWindowSingleton = mFixture->osWindow;
448         }
449     }
450 
451     // On Linux we must keep the test windows visible. On Windows it doesn't seem to need it.
452     setWindowVisible(getOSWindow(), !IsWindows());
453 
454     switch (mCurrentParams->driver)
455     {
456         case GLESDriverType::AngleEGL:
457         case GLESDriverType::SystemEGL:
458         {
459             mFixture->eglWindow =
460                 EGLWindow::New(mCurrentParams->majorVersion, mCurrentParams->minorVersion);
461             break;
462         }
463 
464         case GLESDriverType::SystemWGL:
465         {
466             // WGL tests are currently disabled.
467             std::cerr << "Unsupported driver." << std::endl;
468             break;
469         }
470     }
471 }
472 
~ANGLETestBase()473 ANGLETestBase::~ANGLETestBase()
474 {
475     if (mQuadVertexBuffer)
476     {
477         glDeleteBuffers(1, &mQuadVertexBuffer);
478     }
479     if (mQuadIndexBuffer)
480     {
481         glDeleteBuffers(1, &mQuadIndexBuffer);
482     }
483     if (m2DTexturedQuadProgram)
484     {
485         glDeleteProgram(m2DTexturedQuadProgram);
486     }
487     if (m3DTexturedQuadProgram)
488     {
489         glDeleteProgram(m3DTexturedQuadProgram);
490     }
491 
492     if (!mSetUpCalled)
493     {
494         GTEST_NONFATAL_FAILURE_("SetUp not called.");
495     }
496 
497     if (!mTearDownCalled)
498     {
499         GTEST_NONFATAL_FAILURE_("TearDown not called.");
500     }
501 }
502 
ANGLETestSetUp()503 void ANGLETestBase::ANGLETestSetUp()
504 {
505     mSetUpCalled = true;
506 
507     gDefaultPlatformMethods.overrideWorkaroundsD3D = TestPlatform_overrideWorkaroundsD3D;
508     gDefaultPlatformMethods.overrideFeaturesVk     = TestPlatform_overrideFeaturesVk;
509     gDefaultPlatformMethods.logError               = TestPlatform_logError;
510     gDefaultPlatformMethods.logWarning             = TestPlatform_logWarning;
511     gDefaultPlatformMethods.logInfo                = TestPlatform_logInfo;
512     gDefaultPlatformMethods.context                = &gPlatformContext;
513 
514     gPlatformContext.ignoreMessages   = false;
515     gPlatformContext.warningsAsErrors = false;
516     gPlatformContext.currentTest      = this;
517 
518     // TODO(geofflang): Nexus6P generates GL errors during initialization. Suppress error messages
519     // temporarily until enough logging is in place to figure out exactly which calls generate
520     // errors.  http://crbug.com/998503
521     if (IsNexus6P())
522     {
523         gPlatformContext.ignoreMessages = true;
524     }
525 
526     if (IsWindows())
527     {
528         const auto &info = testing::UnitTest::GetInstance()->current_test_info();
529         WriteDebugMessage("Entering %s.%s\n", info->test_case_name(), info->name());
530     }
531 
532     if (mCurrentParams->noFixture)
533     {
534         LoadEntryPointsWithUtilLoader(mCurrentParams->driver);
535         return;
536     }
537 
538     if (mLastLoadedDriver.valid() && mCurrentParams->driver != mLastLoadedDriver.value())
539     {
540         LoadEntryPointsWithUtilLoader(mCurrentParams->driver);
541         mLastLoadedDriver = mCurrentParams->driver;
542     }
543 
544     // Resize the window before creating the context so that the first make current
545     // sets the viewport and scissor box to the right size.
546     bool needSwap = false;
547     if (mFixture->osWindow->getWidth() != mWidth || mFixture->osWindow->getHeight() != mHeight)
548     {
549         if (!mFixture->osWindow->resize(mWidth, mHeight))
550         {
551             FAIL() << "Failed to resize ANGLE test window.";
552         }
553         needSwap = true;
554     }
555 
556     // WGL tests are currently disabled.
557     if (mFixture->wglWindow)
558     {
559         FAIL() << "Unsupported driver.";
560     }
561     else
562     {
563         Library *driverLib = ANGLETestEnvironment::GetDriverLibrary(mCurrentParams->driver);
564 
565         if (mForceNewDisplay || !mFixture->eglWindow->isDisplayInitialized())
566         {
567             mFixture->eglWindow->destroyGL();
568             if (!mFixture->eglWindow->initializeDisplay(mFixture->osWindow, driverLib,
569                                                         mCurrentParams->driver,
570                                                         mCurrentParams->eglParameters))
571             {
572                 FAIL() << "EGL Display init failed.";
573             }
574         }
575         else if (mCurrentParams->eglParameters != mFixture->eglWindow->getPlatform())
576         {
577             FAIL() << "Internal parameter conflict error.";
578         }
579 
580         if (!mFixture->eglWindow->initializeSurface(mFixture->osWindow, driverLib,
581                                                     mFixture->configParams))
582         {
583             FAIL() << "egl surface init failed.";
584         }
585 
586         if (!mDeferContextInit && !mFixture->eglWindow->initializeContext())
587         {
588             FAIL() << "GL Context init failed.";
589         }
590     }
591 
592     if (needSwap)
593     {
594         // Swap the buffers so that the default framebuffer picks up the resize
595         // which will allow follow-up test code to assume the framebuffer covers
596         // the whole window.
597         swapBuffers();
598     }
599 
600     // This Viewport command is not strictly necessary but we add it so that programs
601     // taking OpenGL traces can guess the size of the default framebuffer and show it
602     // in their UIs
603     glViewport(0, 0, mWidth, mHeight);
604 }
605 
ANGLETestTearDown()606 void ANGLETestBase::ANGLETestTearDown()
607 {
608     mTearDownCalled              = true;
609     gPlatformContext.currentTest = nullptr;
610 
611     if (IsWindows())
612     {
613         const testing::TestInfo *info = testing::UnitTest::GetInstance()->current_test_info();
614         WriteDebugMessage("Exiting %s.%s\n", info->test_case_name(), info->name());
615     }
616 
617     if (mCurrentParams->noFixture)
618     {
619         return;
620     }
621 
622     swapBuffers();
623     mFixture->osWindow->messageLoop();
624 
625     if (mFixture->eglWindow)
626     {
627         checkD3D11SDKLayersMessages();
628     }
629 
630     if (mFixture->reuseCounter++ >= kWindowReuseLimit || mForceNewDisplay)
631     {
632         mFixture->reuseCounter = 0;
633         getGLWindow()->destroyGL();
634     }
635     else
636     {
637         mFixture->eglWindow->destroyContext();
638         mFixture->eglWindow->destroySurface();
639     }
640 
641     // Check for quit message
642     Event myEvent;
643     while (mFixture->osWindow->popEvent(&myEvent))
644     {
645         if (myEvent.Type == Event::EVENT_CLOSED)
646         {
647             exit(0);
648         }
649     }
650 }
651 
ReleaseFixtures()652 void ANGLETestBase::ReleaseFixtures()
653 {
654     for (auto it = gFixtures.begin(); it != gFixtures.end(); it++)
655     {
656         if (it->second.eglWindow)
657         {
658             it->second.eglWindow->destroyGL();
659         }
660     }
661 }
662 
swapBuffers()663 void ANGLETestBase::swapBuffers()
664 {
665     if (getGLWindow()->isGLInitialized())
666     {
667         getGLWindow()->swap();
668 
669         if (mFixture->eglWindow)
670         {
671             EXPECT_EGL_SUCCESS();
672         }
673     }
674 }
675 
setupQuadVertexBuffer(GLfloat positionAttribZ,GLfloat positionAttribXYScale)676 void ANGLETestBase::setupQuadVertexBuffer(GLfloat positionAttribZ, GLfloat positionAttribXYScale)
677 {
678     if (mQuadVertexBuffer == 0)
679     {
680         glGenBuffers(1, &mQuadVertexBuffer);
681     }
682 
683     auto quadVertices = GetQuadVertices();
684     for (Vector3 &vertex : quadVertices)
685     {
686         vertex.x() *= positionAttribXYScale;
687         vertex.y() *= positionAttribXYScale;
688         vertex.z() = positionAttribZ;
689     }
690 
691     glBindBuffer(GL_ARRAY_BUFFER, mQuadVertexBuffer);
692     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 6, quadVertices.data(), GL_STATIC_DRAW);
693 }
694 
setupIndexedQuadVertexBuffer(GLfloat positionAttribZ,GLfloat positionAttribXYScale)695 void ANGLETestBase::setupIndexedQuadVertexBuffer(GLfloat positionAttribZ,
696                                                  GLfloat positionAttribXYScale)
697 {
698     if (mQuadVertexBuffer == 0)
699     {
700         glGenBuffers(1, &mQuadVertexBuffer);
701     }
702 
703     auto quadVertices = kIndexedQuadVertices;
704     for (Vector3 &vertex : quadVertices)
705     {
706         vertex.x() *= positionAttribXYScale;
707         vertex.y() *= positionAttribXYScale;
708         vertex.z() = positionAttribZ;
709     }
710 
711     glBindBuffer(GL_ARRAY_BUFFER, mQuadVertexBuffer);
712     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 4, quadVertices.data(), GL_STATIC_DRAW);
713 }
714 
setupIndexedQuadIndexBuffer()715 void ANGLETestBase::setupIndexedQuadIndexBuffer()
716 {
717     if (mQuadIndexBuffer == 0)
718     {
719         glGenBuffers(1, &mQuadIndexBuffer);
720     }
721 
722     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mQuadIndexBuffer);
723     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexedQuadIndices), kIndexedQuadIndices.data(),
724                  GL_STATIC_DRAW);
725 }
726 
727 // static
drawQuad(GLuint program,const std::string & positionAttribName,GLfloat positionAttribZ)728 void ANGLETestBase::drawQuad(GLuint program,
729                              const std::string &positionAttribName,
730                              GLfloat positionAttribZ)
731 {
732     drawQuad(program, positionAttribName, positionAttribZ, 1.0f);
733 }
734 
735 // static
drawQuad(GLuint program,const std::string & positionAttribName,GLfloat positionAttribZ,GLfloat positionAttribXYScale)736 void ANGLETestBase::drawQuad(GLuint program,
737                              const std::string &positionAttribName,
738                              GLfloat positionAttribZ,
739                              GLfloat positionAttribXYScale)
740 {
741     drawQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale, false);
742 }
743 
drawQuad(GLuint program,const std::string & positionAttribName,GLfloat positionAttribZ,GLfloat positionAttribXYScale,bool useVertexBuffer)744 void ANGLETestBase::drawQuad(GLuint program,
745                              const std::string &positionAttribName,
746                              GLfloat positionAttribZ,
747                              GLfloat positionAttribXYScale,
748                              bool useVertexBuffer)
749 {
750     drawQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale, useVertexBuffer,
751              false, 0u);
752 }
753 
drawQuadInstanced(GLuint program,const std::string & positionAttribName,GLfloat positionAttribZ,GLfloat positionAttribXYScale,bool useVertexBuffer,GLuint numInstances)754 void ANGLETestBase::drawQuadInstanced(GLuint program,
755                                       const std::string &positionAttribName,
756                                       GLfloat positionAttribZ,
757                                       GLfloat positionAttribXYScale,
758                                       bool useVertexBuffer,
759                                       GLuint numInstances)
760 {
761     drawQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale, useVertexBuffer,
762              true, numInstances);
763 }
764 
drawQuad(GLuint program,const std::string & positionAttribName,GLfloat positionAttribZ,GLfloat positionAttribXYScale,bool useVertexBuffer,bool useInstancedDrawCalls,GLuint numInstances)765 void ANGLETestBase::drawQuad(GLuint program,
766                              const std::string &positionAttribName,
767                              GLfloat positionAttribZ,
768                              GLfloat positionAttribXYScale,
769                              bool useVertexBuffer,
770                              bool useInstancedDrawCalls,
771                              GLuint numInstances)
772 {
773     GLint previousProgram = 0;
774     glGetIntegerv(GL_CURRENT_PROGRAM, &previousProgram);
775     if (previousProgram != static_cast<GLint>(program))
776     {
777         glUseProgram(program);
778     }
779 
780     GLint previousBuffer = 0;
781     glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &previousBuffer);
782 
783     GLint positionLocation = glGetAttribLocation(program, positionAttribName.c_str());
784 
785     std::array<Vector3, 6> quadVertices = GetQuadVertices();
786 
787     if (useVertexBuffer)
788     {
789         setupQuadVertexBuffer(positionAttribZ, positionAttribXYScale);
790         glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
791         glBindBuffer(GL_ARRAY_BUFFER, previousBuffer);
792     }
793     else
794     {
795         for (Vector3 &vertex : quadVertices)
796         {
797             vertex.x() *= positionAttribXYScale;
798             vertex.y() *= positionAttribXYScale;
799             vertex.z() = positionAttribZ;
800         }
801 
802         if (previousBuffer != 0)
803         {
804             glBindBuffer(GL_ARRAY_BUFFER, 0);
805         }
806         glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
807         if (previousBuffer != 0)
808         {
809             glBindBuffer(GL_ARRAY_BUFFER, previousBuffer);
810         }
811     }
812     glEnableVertexAttribArray(positionLocation);
813 
814     if (useInstancedDrawCalls)
815     {
816         glDrawArraysInstanced(GL_TRIANGLES, 0, 6, numInstances);
817     }
818     else
819     {
820         glDrawArrays(GL_TRIANGLES, 0, 6);
821     }
822 
823     glDisableVertexAttribArray(positionLocation);
824     glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
825 
826     if (previousProgram != static_cast<GLint>(program))
827     {
828         glUseProgram(previousProgram);
829     }
830 }
831 
drawIndexedQuad(GLuint program,const std::string & positionAttribName,GLfloat positionAttribZ)832 void ANGLETestBase::drawIndexedQuad(GLuint program,
833                                     const std::string &positionAttribName,
834                                     GLfloat positionAttribZ)
835 {
836     drawIndexedQuad(program, positionAttribName, positionAttribZ, 1.0f);
837 }
838 
drawIndexedQuad(GLuint program,const std::string & positionAttribName,GLfloat positionAttribZ,GLfloat positionAttribXYScale)839 void ANGLETestBase::drawIndexedQuad(GLuint program,
840                                     const std::string &positionAttribName,
841                                     GLfloat positionAttribZ,
842                                     GLfloat positionAttribXYScale)
843 {
844     drawIndexedQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale, false);
845 }
846 
drawIndexedQuad(GLuint program,const std::string & positionAttribName,GLfloat positionAttribZ,GLfloat positionAttribXYScale,bool useIndexBuffer)847 void ANGLETestBase::drawIndexedQuad(GLuint program,
848                                     const std::string &positionAttribName,
849                                     GLfloat positionAttribZ,
850                                     GLfloat positionAttribXYScale,
851                                     bool useIndexBuffer)
852 {
853     drawIndexedQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale,
854                     useIndexBuffer, false);
855 }
856 
drawIndexedQuad(GLuint program,const std::string & positionAttribName,GLfloat positionAttribZ,GLfloat positionAttribXYScale,bool useIndexBuffer,bool restrictedRange)857 void ANGLETestBase::drawIndexedQuad(GLuint program,
858                                     const std::string &positionAttribName,
859                                     GLfloat positionAttribZ,
860                                     GLfloat positionAttribXYScale,
861                                     bool useIndexBuffer,
862                                     bool restrictedRange)
863 {
864     GLint positionLocation = glGetAttribLocation(program, positionAttribName.c_str());
865 
866     GLint activeProgram = 0;
867     glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram);
868     if (static_cast<GLuint>(activeProgram) != program)
869     {
870         glUseProgram(program);
871     }
872 
873     GLuint prevCoordBinding = 0;
874     glGetIntegerv(GL_ARRAY_BUFFER_BINDING, reinterpret_cast<GLint *>(&prevCoordBinding));
875 
876     setupIndexedQuadVertexBuffer(positionAttribZ, positionAttribXYScale);
877 
878     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
879     glEnableVertexAttribArray(positionLocation);
880     glBindBuffer(GL_ARRAY_BUFFER, prevCoordBinding);
881 
882     GLuint prevIndexBinding = 0;
883     const GLvoid *indices;
884     if (useIndexBuffer)
885     {
886         glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING,
887                       reinterpret_cast<GLint *>(&prevIndexBinding));
888 
889         setupIndexedQuadIndexBuffer();
890         indices = 0;
891     }
892     else
893     {
894         indices = kIndexedQuadIndices.data();
895     }
896 
897     if (!restrictedRange)
898     {
899         glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
900     }
901     else
902     {
903         glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, indices);
904     }
905 
906     if (useIndexBuffer)
907     {
908         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prevIndexBinding);
909     }
910 
911     glDisableVertexAttribArray(positionLocation);
912     glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
913 
914     if (static_cast<GLuint>(activeProgram) != program)
915     {
916         glUseProgram(static_cast<GLuint>(activeProgram));
917     }
918 }
919 
get2DTexturedQuadProgram()920 GLuint ANGLETestBase::get2DTexturedQuadProgram()
921 {
922     if (m2DTexturedQuadProgram)
923     {
924         return m2DTexturedQuadProgram;
925     }
926 
927     constexpr char kVS[] =
928         "attribute vec2 position;\n"
929         "varying mediump vec2 texCoord;\n"
930         "void main()\n"
931         "{\n"
932         "    gl_Position = vec4(position, 0, 1);\n"
933         "    texCoord = position * 0.5 + vec2(0.5);\n"
934         "}\n";
935 
936     constexpr char kFS[] =
937         "varying mediump vec2 texCoord;\n"
938         "uniform sampler2D tex;\n"
939         "void main()\n"
940         "{\n"
941         "    gl_FragColor = texture2D(tex, texCoord);\n"
942         "}\n";
943 
944     m2DTexturedQuadProgram = CompileProgram(kVS, kFS);
945     return m2DTexturedQuadProgram;
946 }
947 
get3DTexturedQuadProgram()948 GLuint ANGLETestBase::get3DTexturedQuadProgram()
949 {
950     if (m3DTexturedQuadProgram)
951     {
952         return m3DTexturedQuadProgram;
953     }
954 
955     constexpr char kVS[] = R"(#version 300 es
956 in vec2 position;
957 out vec2 texCoord;
958 void main()
959 {
960     gl_Position = vec4(position, 0, 1);
961     texCoord = position * 0.5 + vec2(0.5);
962 })";
963 
964     constexpr char kFS[] = R"(#version 300 es
965 precision highp float;
966 
967 in vec2 texCoord;
968 out vec4 my_FragColor;
969 
970 uniform highp sampler3D tex;
971 uniform float u_layer;
972 
973 void main()
974 {
975     my_FragColor = texture(tex, vec3(texCoord, u_layer));
976 })";
977 
978     m3DTexturedQuadProgram = CompileProgram(kVS, kFS);
979     return m3DTexturedQuadProgram;
980 }
981 
draw2DTexturedQuad(GLfloat positionAttribZ,GLfloat positionAttribXYScale,bool useVertexBuffer)982 void ANGLETestBase::draw2DTexturedQuad(GLfloat positionAttribZ,
983                                        GLfloat positionAttribXYScale,
984                                        bool useVertexBuffer)
985 {
986     ASSERT_NE(0u, get2DTexturedQuadProgram());
987     drawQuad(get2DTexturedQuadProgram(), "position", positionAttribZ, positionAttribXYScale,
988              useVertexBuffer);
989 }
990 
draw3DTexturedQuad(GLfloat positionAttribZ,GLfloat positionAttribXYScale,bool useVertexBuffer,float layer)991 void ANGLETestBase::draw3DTexturedQuad(GLfloat positionAttribZ,
992                                        GLfloat positionAttribXYScale,
993                                        bool useVertexBuffer,
994                                        float layer)
995 {
996     GLuint program = get3DTexturedQuadProgram();
997     ASSERT_NE(0u, program);
998     GLint activeProgram = 0;
999     glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram);
1000     if (static_cast<GLuint>(activeProgram) != program)
1001     {
1002         glUseProgram(program);
1003     }
1004     glUniform1f(glGetUniformLocation(program, "u_layer"), layer);
1005 
1006     drawQuad(program, "position", positionAttribZ, positionAttribXYScale, useVertexBuffer);
1007 
1008     if (static_cast<GLuint>(activeProgram) != program)
1009     {
1010         glUseProgram(static_cast<GLuint>(activeProgram));
1011     }
1012 }
1013 
platformSupportsMultithreading() const1014 bool ANGLETestBase::platformSupportsMultithreading() const
1015 {
1016     return (IsOpenGLES() && IsAndroid()) || IsVulkan();
1017 }
1018 
checkD3D11SDKLayersMessages()1019 void ANGLETestBase::checkD3D11SDKLayersMessages()
1020 {
1021 #if defined(ANGLE_PLATFORM_WINDOWS)
1022     // On Windows D3D11, check ID3D11InfoQueue to see if any D3D11 SDK Layers messages
1023     // were outputted by the test. We enable the Debug layers in Release tests as well.
1024     if (mIgnoreD3D11SDKLayersWarnings ||
1025         mFixture->eglWindow->getPlatform().renderer != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE ||
1026         mFixture->eglWindow->getDisplay() == EGL_NO_DISPLAY)
1027     {
1028         return;
1029     }
1030 
1031     const char *extensionString = static_cast<const char *>(
1032         eglQueryString(mFixture->eglWindow->getDisplay(), EGL_EXTENSIONS));
1033     if (!extensionString)
1034     {
1035         std::cout << "Error getting extension string from EGL Window." << std::endl;
1036         return;
1037     }
1038 
1039     if (!strstr(extensionString, "EGL_EXT_device_query"))
1040     {
1041         return;
1042     }
1043 
1044     EGLAttrib device      = 0;
1045     EGLAttrib angleDevice = 0;
1046 
1047     ASSERT_EGL_TRUE(
1048         eglQueryDisplayAttribEXT(mFixture->eglWindow->getDisplay(), EGL_DEVICE_EXT, &angleDevice));
1049     ASSERT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice),
1050                                             EGL_D3D11_DEVICE_ANGLE, &device));
1051     ID3D11Device *d3d11Device = reinterpret_cast<ID3D11Device *>(device);
1052 
1053     ID3D11InfoQueue *infoQueue = nullptr;
1054     HRESULT hr =
1055         d3d11Device->QueryInterface(__uuidof(infoQueue), reinterpret_cast<void **>(&infoQueue));
1056     if (SUCCEEDED(hr))
1057     {
1058         UINT64 numStoredD3DDebugMessages =
1059             infoQueue->GetNumStoredMessagesAllowedByRetrievalFilter();
1060 
1061         if (numStoredD3DDebugMessages > 0)
1062         {
1063             for (UINT64 i = 0; i < numStoredD3DDebugMessages; i++)
1064             {
1065                 SIZE_T messageLength = 0;
1066                 hr                   = infoQueue->GetMessage(i, nullptr, &messageLength);
1067 
1068                 if (SUCCEEDED(hr))
1069                 {
1070                     D3D11_MESSAGE *pMessage =
1071                         reinterpret_cast<D3D11_MESSAGE *>(malloc(messageLength));
1072                     infoQueue->GetMessage(i, pMessage, &messageLength);
1073 
1074                     std::cout << "Message " << i << ":"
1075                               << " " << pMessage->pDescription << "\n";
1076                     free(pMessage);
1077                 }
1078             }
1079             // Clear the queue, so that previous failures are not reported
1080             // for subsequent, otherwise passing, tests
1081             infoQueue->ClearStoredMessages();
1082 
1083             FAIL() << numStoredD3DDebugMessages
1084                    << " D3D11 SDK Layers message(s) detected! Test Failed.\n";
1085         }
1086     }
1087 
1088     SafeRelease(infoQueue);
1089 #endif  // defined(ANGLE_PLATFORM_WINDOWS)
1090 }
1091 
setWindowWidth(int width)1092 void ANGLETestBase::setWindowWidth(int width)
1093 {
1094     mWidth = width;
1095 }
1096 
setWindowHeight(int height)1097 void ANGLETestBase::setWindowHeight(int height)
1098 {
1099     mHeight = height;
1100 }
1101 
getGLWindow() const1102 GLWindowBase *ANGLETestBase::getGLWindow() const
1103 {
1104     // WGL tests are currently disabled.
1105     assert(!mFixture->wglWindow);
1106     return mFixture->eglWindow;
1107 }
1108 
setConfigRedBits(int bits)1109 void ANGLETestBase::setConfigRedBits(int bits)
1110 {
1111     mFixture->configParams.redBits = bits;
1112 }
1113 
setConfigGreenBits(int bits)1114 void ANGLETestBase::setConfigGreenBits(int bits)
1115 {
1116     mFixture->configParams.greenBits = bits;
1117 }
1118 
setConfigBlueBits(int bits)1119 void ANGLETestBase::setConfigBlueBits(int bits)
1120 {
1121     mFixture->configParams.blueBits = bits;
1122 }
1123 
setConfigAlphaBits(int bits)1124 void ANGLETestBase::setConfigAlphaBits(int bits)
1125 {
1126     mFixture->configParams.alphaBits = bits;
1127 }
1128 
setConfigDepthBits(int bits)1129 void ANGLETestBase::setConfigDepthBits(int bits)
1130 {
1131     mFixture->configParams.depthBits = bits;
1132 }
1133 
setConfigStencilBits(int bits)1134 void ANGLETestBase::setConfigStencilBits(int bits)
1135 {
1136     mFixture->configParams.stencilBits = bits;
1137 }
1138 
setConfigComponentType(EGLenum componentType)1139 void ANGLETestBase::setConfigComponentType(EGLenum componentType)
1140 {
1141     mFixture->configParams.componentType = componentType;
1142 }
1143 
setMultisampleEnabled(bool enabled)1144 void ANGLETestBase::setMultisampleEnabled(bool enabled)
1145 {
1146     mFixture->configParams.multisample = enabled;
1147 }
1148 
setSamples(EGLint samples)1149 void ANGLETestBase::setSamples(EGLint samples)
1150 {
1151     mFixture->configParams.samples = samples;
1152 }
1153 
setDebugEnabled(bool enabled)1154 void ANGLETestBase::setDebugEnabled(bool enabled)
1155 {
1156     mFixture->configParams.debug = enabled;
1157 }
1158 
setNoErrorEnabled(bool enabled)1159 void ANGLETestBase::setNoErrorEnabled(bool enabled)
1160 {
1161     mFixture->configParams.noError = enabled;
1162 }
1163 
setWebGLCompatibilityEnabled(bool webglCompatibility)1164 void ANGLETestBase::setWebGLCompatibilityEnabled(bool webglCompatibility)
1165 {
1166     mFixture->configParams.webGLCompatibility = webglCompatibility;
1167 }
1168 
setExtensionsEnabled(bool extensionsEnabled)1169 void ANGLETestBase::setExtensionsEnabled(bool extensionsEnabled)
1170 {
1171     mFixture->configParams.extensionsEnabled = extensionsEnabled;
1172 }
1173 
setRobustAccess(bool enabled)1174 void ANGLETestBase::setRobustAccess(bool enabled)
1175 {
1176     mFixture->configParams.robustAccess = enabled;
1177 }
1178 
setBindGeneratesResource(bool bindGeneratesResource)1179 void ANGLETestBase::setBindGeneratesResource(bool bindGeneratesResource)
1180 {
1181     mFixture->configParams.bindGeneratesResource = bindGeneratesResource;
1182 }
1183 
setClientArraysEnabled(bool enabled)1184 void ANGLETestBase::setClientArraysEnabled(bool enabled)
1185 {
1186     mFixture->configParams.clientArraysEnabled = enabled;
1187 }
1188 
setRobustResourceInit(bool enabled)1189 void ANGLETestBase::setRobustResourceInit(bool enabled)
1190 {
1191     mFixture->configParams.robustResourceInit = enabled;
1192 }
1193 
setContextProgramCacheEnabled(bool enabled)1194 void ANGLETestBase::setContextProgramCacheEnabled(bool enabled)
1195 {
1196     mFixture->configParams.contextProgramCacheEnabled = enabled;
1197 }
1198 
setContextResetStrategy(EGLenum resetStrategy)1199 void ANGLETestBase::setContextResetStrategy(EGLenum resetStrategy)
1200 {
1201     mFixture->configParams.resetStrategy = resetStrategy;
1202 }
1203 
forceNewDisplay()1204 void ANGLETestBase::forceNewDisplay()
1205 {
1206     mForceNewDisplay = true;
1207 }
1208 
setDeferContextInit(bool enabled)1209 void ANGLETestBase::setDeferContextInit(bool enabled)
1210 {
1211     mDeferContextInit = enabled;
1212 }
1213 
getClientMajorVersion() const1214 int ANGLETestBase::getClientMajorVersion() const
1215 {
1216     return getGLWindow()->getClientMajorVersion();
1217 }
1218 
getClientMinorVersion() const1219 int ANGLETestBase::getClientMinorVersion() const
1220 {
1221     return getGLWindow()->getClientMinorVersion();
1222 }
1223 
getEGLWindow() const1224 EGLWindow *ANGLETestBase::getEGLWindow() const
1225 {
1226     return mFixture->eglWindow;
1227 }
1228 
getWindowWidth() const1229 int ANGLETestBase::getWindowWidth() const
1230 {
1231     return mWidth;
1232 }
1233 
getWindowHeight() const1234 int ANGLETestBase::getWindowHeight() const
1235 {
1236     return mHeight;
1237 }
1238 
isMultisampleEnabled() const1239 bool ANGLETestBase::isMultisampleEnabled() const
1240 {
1241     return mFixture->eglWindow->isMultisample();
1242 }
1243 
setWindowVisible(OSWindow * osWindow,bool isVisible)1244 void ANGLETestBase::setWindowVisible(OSWindow *osWindow, bool isVisible)
1245 {
1246     // SwiftShader windows are not required to be visible for test correctness,
1247     // moreover, making a SwiftShader window visible flaky hangs on Xvfb, so we keep them hidden.
1248     if (isSwiftshader())
1249     {
1250         return;
1251     }
1252     osWindow->setVisible(isVisible);
1253 }
1254 
1255 ANGLETestBase::TestFixture::TestFixture()  = default;
1256 ANGLETestBase::TestFixture::~TestFixture() = default;
1257 
getPlatformRenderer() const1258 EGLint ANGLETestBase::getPlatformRenderer() const
1259 {
1260     assert(mFixture->eglWindow);
1261     return mFixture->eglWindow->getPlatform().renderer;
1262 }
1263 
ignoreD3D11SDKLayersWarnings()1264 void ANGLETestBase::ignoreD3D11SDKLayersWarnings()
1265 {
1266     // Some tests may need to disable the D3D11 SDK Layers Warnings checks
1267     mIgnoreD3D11SDKLayersWarnings = true;
1268 }
1269 
treatPlatformWarningsAsErrors()1270 void ANGLETestBase::treatPlatformWarningsAsErrors()
1271 {
1272 #if defined(ANGLE_PLATFORM_WINDOWS)
1273     // Only do warnings-as-errors on 8 and above. We may fall back to the old
1274     // compiler DLL on Windows 7.
1275     gPlatformContext.warningsAsErrors = IsWindows8OrGreater();
1276 #endif  // defined(ANGLE_PLATFORM_WINDOWS)
1277 }
1278 
ScopedIgnorePlatformMessages()1279 ANGLETestBase::ScopedIgnorePlatformMessages::ScopedIgnorePlatformMessages()
1280 {
1281     gPlatformContext.ignoreMessages = true;
1282 }
1283 
~ScopedIgnorePlatformMessages()1284 ANGLETestBase::ScopedIgnorePlatformMessages::~ScopedIgnorePlatformMessages()
1285 {
1286     gPlatformContext.ignoreMessages = false;
1287 }
1288 
1289 OSWindow *ANGLETestBase::mOSWindowSingleton = nullptr;
1290 std::map<angle::PlatformParameters, ANGLETestBase::TestFixture> ANGLETestBase::gFixtures;
1291 Optional<EGLint> ANGLETestBase::mLastRendererType;
1292 Optional<angle::GLESDriverType> ANGLETestBase::mLastLoadedDriver;
1293 
1294 std::unique_ptr<Library> ANGLETestEnvironment::gAngleEGLLibrary;
1295 std::unique_ptr<Library> ANGLETestEnvironment::gSystemEGLLibrary;
1296 std::unique_ptr<Library> ANGLETestEnvironment::gSystemWGLLibrary;
1297 
SetUp()1298 void ANGLETestEnvironment::SetUp() {}
1299 
TearDown()1300 void ANGLETestEnvironment::TearDown()
1301 {
1302     ANGLETestBase::ReleaseFixtures();
1303 }
1304 
1305 // static
GetDriverLibrary(angle::GLESDriverType driver)1306 Library *ANGLETestEnvironment::GetDriverLibrary(angle::GLESDriverType driver)
1307 {
1308     switch (driver)
1309     {
1310         case angle::GLESDriverType::AngleEGL:
1311             return GetAngleEGLLibrary();
1312         case angle::GLESDriverType::SystemEGL:
1313             return GetSystemEGLLibrary();
1314         case angle::GLESDriverType::SystemWGL:
1315             return GetSystemWGLLibrary();
1316         default:
1317             return nullptr;
1318     }
1319 }
1320 
1321 // static
GetAngleEGLLibrary()1322 Library *ANGLETestEnvironment::GetAngleEGLLibrary()
1323 {
1324 #if defined(ANGLE_USE_UTIL_LOADER)
1325     if (!gAngleEGLLibrary)
1326     {
1327         gAngleEGLLibrary.reset(
1328             OpenSharedLibrary(ANGLE_EGL_LIBRARY_NAME, SearchType::ApplicationDir));
1329     }
1330 #endif  // defined(ANGLE_USE_UTIL_LOADER)
1331     return gAngleEGLLibrary.get();
1332 }
1333 
1334 // static
GetSystemEGLLibrary()1335 Library *ANGLETestEnvironment::GetSystemEGLLibrary()
1336 {
1337 #if defined(ANGLE_USE_UTIL_LOADER)
1338     if (!gSystemEGLLibrary)
1339     {
1340         gSystemEGLLibrary.reset(
1341             OpenSharedLibraryWithExtension(GetNativeEGLLibraryNameWithExtension()));
1342     }
1343 #endif  // defined(ANGLE_USE_UTIL_LOADER)
1344     return gSystemEGLLibrary.get();
1345 }
1346 
1347 // static
GetSystemWGLLibrary()1348 Library *ANGLETestEnvironment::GetSystemWGLLibrary()
1349 {
1350 #if defined(ANGLE_USE_UTIL_LOADER) && defined(ANGLE_PLATFORM_WINDOWS)
1351     if (!gSystemWGLLibrary)
1352     {
1353         gSystemWGLLibrary.reset(OpenSharedLibrary("opengl32", SearchType::SystemDir));
1354     }
1355 #endif  // defined(ANGLE_USE_UTIL_LOADER) && defined(ANGLE_PLATFORM_WINDOWS)
1356     return gSystemWGLLibrary.get();
1357 }
1358 
ANGLEProcessTestArgs(int * argc,char * argv[])1359 void ANGLEProcessTestArgs(int *argc, char *argv[])
1360 {
1361     testing::AddGlobalTestEnvironment(new ANGLETestEnvironment());
1362 
1363     for (int argIndex = 1; argIndex < *argc; argIndex++)
1364     {
1365         if (strncmp(argv[argIndex], kUseConfig, strlen(kUseConfig)) == 0)
1366         {
1367             SetSelectedConfig(argv[argIndex] + strlen(kUseConfig));
1368         }
1369         if (strncmp(argv[argIndex], kSeparateProcessPerConfig, strlen(kSeparateProcessPerConfig)) ==
1370             0)
1371         {
1372             gSeparateProcessPerConfig = true;
1373         }
1374     }
1375 
1376     if (gSeparateProcessPerConfig)
1377     {
1378         if (IsConfigSelected())
1379         {
1380             std::cout << "Cannot use both a single test config and separate processes.\n";
1381             exit(1);
1382         }
1383 
1384         if (RunSeparateProcessesForEachConfig(argc, argv))
1385         {
1386             exit(0);
1387         }
1388         else
1389         {
1390             std::cout << "Some subprocesses failed.\n";
1391             exit(1);
1392         }
1393     }
1394 }
1395