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