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