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