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