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