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