• 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 "common/platform.h"
13 #include "gpu_info_util/SystemInfo.h"
14 #include "util/EGLWindow.h"
15 #include "util/OSWindow.h"
16 
17 #if defined(ANGLE_PLATFORM_WINDOWS)
18 #    include <VersionHelpers.h>
19 #endif  // defined(ANGLE_PLATFORM_WINDOWS)
20 
21 namespace angle
22 {
23 
24 const GLColorRGB GLColorRGB::black(0u, 0u, 0u);
25 const GLColorRGB GLColorRGB::blue(0u, 0u, 255u);
26 const GLColorRGB GLColorRGB::green(0u, 255u, 0u);
27 const GLColorRGB GLColorRGB::red(255u, 0u, 0u);
28 const GLColorRGB GLColorRGB::yellow(255u, 255u, 0);
29 
30 const GLColor GLColor::black            = GLColor(0u, 0u, 0u, 255u);
31 const GLColor GLColor::blue             = GLColor(0u, 0u, 255u, 255u);
32 const GLColor GLColor::cyan             = GLColor(0u, 255u, 255u, 255u);
33 const GLColor GLColor::green            = GLColor(0u, 255u, 0u, 255u);
34 const GLColor GLColor::red              = GLColor(255u, 0u, 0u, 255u);
35 const GLColor GLColor::transparentBlack = GLColor(0u, 0u, 0u, 0u);
36 const GLColor GLColor::white            = GLColor(255u, 255u, 255u, 255u);
37 const GLColor GLColor::yellow           = GLColor(255u, 255u, 0, 255u);
38 const GLColor GLColor::magenta          = GLColor(255u, 0u, 255u, 255u);
39 
40 namespace
41 {
ColorNorm(GLubyte channelValue)42 float ColorNorm(GLubyte channelValue)
43 {
44     return static_cast<float>(channelValue) / 255.0f;
45 }
46 
ColorDenorm(float colorValue)47 GLubyte ColorDenorm(float colorValue)
48 {
49     return static_cast<GLubyte>(colorValue * 255.0f);
50 }
51 
TestPlatform_logError(PlatformMethods * platform,const char * errorMessage)52 void TestPlatform_logError(PlatformMethods *platform, const char *errorMessage)
53 {
54     auto *testPlatformContext = static_cast<TestPlatformContext *>(platform->context);
55     if (testPlatformContext->ignoreMessages)
56         return;
57 
58     GTEST_NONFATAL_FAILURE_(errorMessage);
59 
60     // Print the stack and stop any crash handling to prevent duplicate reports.
61     PrintStackBacktrace();
62     TerminateCrashHandler();
63 }
64 
TestPlatform_logWarning(PlatformMethods * platform,const char * warningMessage)65 void TestPlatform_logWarning(PlatformMethods *platform, const char *warningMessage)
66 {
67     auto *testPlatformContext = static_cast<TestPlatformContext *>(platform->context);
68     if (testPlatformContext->ignoreMessages)
69         return;
70 
71     if (testPlatformContext->warningsAsErrors)
72     {
73         FAIL() << warningMessage;
74     }
75     else
76     {
77         std::cerr << "Warning: " << warningMessage << std::endl;
78     }
79 }
80 
TestPlatform_logInfo(PlatformMethods * platform,const char * infoMessage)81 void TestPlatform_logInfo(PlatformMethods *platform, const char *infoMessage) {}
82 
TestPlatform_overrideWorkaroundsD3D(PlatformMethods * platform,FeaturesD3D * featuresD3D)83 void TestPlatform_overrideWorkaroundsD3D(PlatformMethods *platform, FeaturesD3D *featuresD3D)
84 {
85     auto *testPlatformContext = static_cast<TestPlatformContext *>(platform->context);
86     if (testPlatformContext->currentTest)
87     {
88         testPlatformContext->currentTest->overrideWorkaroundsD3D(featuresD3D);
89     }
90 }
91 
TestPlatform_overrideFeaturesVk(PlatformMethods * platform,FeaturesVk * featuresVulkan)92 void TestPlatform_overrideFeaturesVk(PlatformMethods *platform, FeaturesVk *featuresVulkan)
93 {
94     auto *testPlatformContext = static_cast<TestPlatformContext *>(platform->context);
95     if (testPlatformContext->currentTest)
96     {
97         testPlatformContext->currentTest->overrideFeaturesVk(featuresVulkan);
98     }
99 }
100 
101 const std::array<Vector3, 6> kQuadVertices = {{
102     Vector3(-1.0f, 1.0f, 0.5f),
103     Vector3(-1.0f, -1.0f, 0.5f),
104     Vector3(1.0f, -1.0f, 0.5f),
105     Vector3(-1.0f, 1.0f, 0.5f),
106     Vector3(1.0f, -1.0f, 0.5f),
107     Vector3(1.0f, 1.0f, 0.5f),
108 }};
109 
110 const std::array<Vector3, 4> kIndexedQuadVertices = {{
111     Vector3(-1.0f, 1.0f, 0.5f),
112     Vector3(-1.0f, -1.0f, 0.5f),
113     Vector3(1.0f, -1.0f, 0.5f),
114     Vector3(1.0f, 1.0f, 0.5f),
115 }};
116 
117 constexpr std::array<GLushort, 6> kIndexedQuadIndices = {{0, 1, 2, 0, 2, 3}};
118 
GetColorName(GLColor color)119 const char *GetColorName(GLColor color)
120 {
121     if (color == GLColor::red)
122     {
123         return "Red";
124     }
125 
126     if (color == GLColor::green)
127     {
128         return "Green";
129     }
130 
131     if (color == GLColor::blue)
132     {
133         return "Blue";
134     }
135 
136     if (color == GLColor::white)
137     {
138         return "White";
139     }
140 
141     if (color == GLColor::black)
142     {
143         return "Black";
144     }
145 
146     if (color == GLColor::transparentBlack)
147     {
148         return "Transparent Black";
149     }
150 
151     if (color == GLColor::yellow)
152     {
153         return "Yellow";
154     }
155 
156     if (color == GLColor::magenta)
157     {
158         return "Magenta";
159     }
160 
161     if (color == GLColor::cyan)
162     {
163         return "Cyan";
164     }
165 
166     return nullptr;
167 }
168 
ShouldAlwaysForceNewDisplay()169 bool ShouldAlwaysForceNewDisplay()
170 {
171     // We prefer to reuse config displays. This is faster and solves a driver issue where creating
172     // many displays causes crashes. However this exposes other driver bugs on many other platforms.
173     // Conservatively enable the feature only on Windows Intel and NVIDIA for now.
174     SystemInfo *systemInfo = GetTestSystemInfo();
175     return (!systemInfo || !IsWindows() || systemInfo->hasAMDGPU());
176 }
177 }  // anonymous namespace
178 
GLColorRGB(const Vector3 & floatColor)179 GLColorRGB::GLColorRGB(const Vector3 &floatColor)
180     : R(ColorDenorm(floatColor.x())), G(ColorDenorm(floatColor.y())), B(ColorDenorm(floatColor.z()))
181 {}
182 
GLColor(const Vector4 & floatColor)183 GLColor::GLColor(const Vector4 &floatColor)
184     : R(ColorDenorm(floatColor.x())),
185       G(ColorDenorm(floatColor.y())),
186       B(ColorDenorm(floatColor.z())),
187       A(ColorDenorm(floatColor.w()))
188 {}
189 
GLColor(GLuint colorValue)190 GLColor::GLColor(GLuint colorValue) : R(0), G(0), B(0), A(0)
191 {
192     memcpy(&R, &colorValue, sizeof(GLuint));
193 }
194 
ExpectNear(const GLColor & expected,const GLColor & err) const195 testing::AssertionResult GLColor::ExpectNear(const GLColor &expected, const GLColor &err) const
196 {
197     testing::AssertionResult result(
198         abs(int(expected.R) - this->R) <= err.R && abs(int(expected.G) - this->G) <= err.G &&
199         abs(int(expected.B) - this->B) <= err.B && abs(int(expected.A) - this->A) <= err.A);
200     if (!bool(result))
201     {
202         result << "Expected " << expected << "+/-" << err << ", was " << *this;
203     }
204     return result;
205 }
206 
CreatePixelCenterWindowCoords(const std::vector<Vector2> & pixelPoints,int windowWidth,int windowHeight,std::vector<Vector3> * outVertices)207 void CreatePixelCenterWindowCoords(const std::vector<Vector2> &pixelPoints,
208                                    int windowWidth,
209                                    int windowHeight,
210                                    std::vector<Vector3> *outVertices)
211 {
212     for (Vector2 pixelPoint : pixelPoints)
213     {
214         outVertices->emplace_back(Vector3((pixelPoint[0] + 0.5f) * 2.0f / windowWidth - 1.0f,
215                                           (pixelPoint[1] + 0.5f) * 2.0f / windowHeight - 1.0f,
216                                           0.0f));
217     }
218 }
219 
toNormalizedVector() const220 Vector4 GLColor::toNormalizedVector() const
221 {
222     return Vector4(ColorNorm(R), ColorNorm(G), ColorNorm(B), ColorNorm(A));
223 }
224 
ReadColor(GLint x,GLint y)225 GLColor ReadColor(GLint x, GLint y)
226 {
227     GLColor actual;
228     glReadPixels((x), (y), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &actual.R);
229     EXPECT_GL_NO_ERROR();
230     return actual;
231 }
232 
operator ==(const GLColor & a,const GLColor & b)233 bool operator==(const GLColor &a, const GLColor &b)
234 {
235     return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;
236 }
237 
operator !=(const GLColor & a,const GLColor & b)238 bool operator!=(const GLColor &a, const GLColor &b)
239 {
240     return !(a == b);
241 }
242 
operator <<(std::ostream & ostream,const GLColor & color)243 std::ostream &operator<<(std::ostream &ostream, const GLColor &color)
244 {
245     const char *colorName = GetColorName(color);
246     if (colorName)
247     {
248         return ostream << colorName;
249     }
250 
251     ostream << "(" << static_cast<unsigned int>(color.R) << ", "
252             << static_cast<unsigned int>(color.G) << ", " << static_cast<unsigned int>(color.B)
253             << ", " << static_cast<unsigned int>(color.A) << ")";
254     return ostream;
255 }
256 
operator ==(const GLColor32F & a,const GLColor32F & b)257 bool operator==(const GLColor32F &a, const GLColor32F &b)
258 {
259     return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;
260 }
261 
operator <<(std::ostream & ostream,const GLColor32F & color)262 std::ostream &operator<<(std::ostream &ostream, const GLColor32F &color)
263 {
264     ostream << "(" << color.R << ", " << color.G << ", " << color.B << ", " << color.A << ")";
265     return ostream;
266 }
267 
ReadColor32F(GLint x,GLint y)268 GLColor32F ReadColor32F(GLint x, GLint y)
269 {
270     GLColor32F actual;
271     glReadPixels((x), (y), 1, 1, GL_RGBA, GL_FLOAT, &actual.R);
272     EXPECT_GL_NO_ERROR();
273     return actual;
274 }
275 }  // namespace angle
276 
277 using namespace angle;
278 
279 PlatformMethods gDefaultPlatformMethods;
280 
281 namespace
282 {
283 TestPlatformContext gPlatformContext;
284 
285 // After a fixed number of iterations we reset the test window. This works around some driver bugs.
286 constexpr uint32_t kWindowReuseLimit = 50;
287 
288 constexpr char kUseConfig[]                = "--use-config=";
289 constexpr char kSeparateProcessPerConfig[] = "--separate-process-per-config";
290 
RunSeparateProcessesForEachConfig(int * argc,char * argv[])291 bool RunSeparateProcessesForEachConfig(int *argc, char *argv[])
292 {
293     std::vector<const char *> commonArgs;
294     for (int argIndex = 0; argIndex < *argc; ++argIndex)
295     {
296         if (strncmp(argv[argIndex], kSeparateProcessPerConfig, strlen(kSeparateProcessPerConfig)) !=
297             0)
298         {
299             commonArgs.push_back(argv[argIndex]);
300         }
301     }
302 
303     // Force GoogleTest init now so that we hit the test config init in angle_test_instantiate.cpp.
304     // After instantiation is finished we can gather a full list of enabled configs. Then we can
305     // iterate the list of configs to spawn a child process for each enabled config.
306     testing::InitGoogleTest(argc, argv);
307 
308     std::vector<std::string> configNames = GetAvailableTestPlatformNames();
309 
310     bool success = true;
311 
312     for (const std::string &config : configNames)
313     {
314         std::stringstream strstr;
315         strstr << kUseConfig << config;
316 
317         std::string configStr = strstr.str();
318 
319         std::vector<const char *> childArgs = commonArgs;
320         childArgs.push_back(configStr.c_str());
321 
322         int exitCode = 0;
323         if (!RunApp(childArgs, nullptr, nullptr, &exitCode))
324         {
325             std::cerr << "Launching child config " << config << " failed.\n";
326         }
327         else if (exitCode != 0)
328         {
329             std::cerr << "Child config " << config << " failed with exit code " << exitCode
330                       << ".\n";
331             success = false;
332         }
333     }
334     return success;
335 }
336 }  // anonymous namespace
337 
338 // static
GetQuadVertices()339 std::array<Vector3, 6> ANGLETestBase::GetQuadVertices()
340 {
341     return kQuadVertices;
342 }
343 
344 // static
GetQuadIndices()345 std::array<GLushort, 6> ANGLETestBase::GetQuadIndices()
346 {
347     return kIndexedQuadIndices;
348 }
349 
350 // static
GetIndexedQuadVertices()351 std::array<Vector3, 4> ANGLETestBase::GetIndexedQuadVertices()
352 {
353     return kIndexedQuadVertices;
354 }
355 
ANGLETestBase(const PlatformParameters & params)356 ANGLETestBase::ANGLETestBase(const PlatformParameters &params)
357     : mWidth(16),
358       mHeight(16),
359       mIgnoreD3D11SDKLayersWarnings(false),
360       mQuadVertexBuffer(0),
361       mQuadIndexBuffer(0),
362       m2DTexturedQuadProgram(0),
363       m3DTexturedQuadProgram(0),
364       mDeferContextInit(false),
365       mAlwaysForceNewDisplay(ShouldAlwaysForceNewDisplay()),
366       mForceNewDisplay(mAlwaysForceNewDisplay),
367       mSetUpCalled(false),
368       mTearDownCalled(false),
369       mCurrentParams(nullptr),
370       mFixture(nullptr)
371 {
372     // Override the default platform methods with the ANGLE test methods pointer.
373     PlatformParameters withMethods            = params;
374     withMethods.eglParameters.platformMethods = &gDefaultPlatformMethods;
375 
376     auto iter = gFixtures.find(withMethods);
377     if (iter != gFixtures.end())
378     {
379         mCurrentParams = &iter->first;
380 
381         if (!params.noFixture)
382         {
383             mFixture = &iter->second;
384             mFixture->configParams.reset();
385         }
386         return;
387     }
388 
389     TestFixture platform;
390     auto insertIter = gFixtures.emplace(withMethods, platform);
391     mCurrentParams  = &insertIter.first->first;
392 
393     if (!params.noFixture)
394     {
395         mFixture = &insertIter.first->second;
396         initOSWindow();
397     }
398 }
399 
initOSWindow()400 void ANGLETestBase::initOSWindow()
401 {
402     std::stringstream windowNameStream;
403     windowNameStream << "ANGLE Tests - " << *mCurrentParams;
404     std::string windowName = windowNameStream.str();
405 
406     if (mAlwaysForceNewDisplay)
407     {
408         mFixture->osWindow = mOSWindowSingleton;
409     }
410 
411     if (!mFixture->osWindow)
412     {
413         mFixture->osWindow = OSWindow::New();
414         if (!mFixture->osWindow->initialize(windowName.c_str(), 128, 128))
415         {
416             std::cerr << "Failed to initialize OS Window.";
417         }
418 
419         mOSWindowSingleton = mFixture->osWindow;
420     }
421 
422     // On Linux we must keep the test windows visible. On Windows it doesn't seem to need it.
423     mFixture->osWindow->setVisible(!IsWindows());
424 
425     switch (mCurrentParams->driver)
426     {
427         case GLESDriverType::AngleEGL:
428         {
429             mFixture->eglWindow =
430                 EGLWindow::New(mCurrentParams->majorVersion, mCurrentParams->minorVersion);
431             break;
432         }
433 
434         case GLESDriverType::SystemEGL:
435         {
436             std::cerr << "Unsupported driver." << std::endl;
437             break;
438         }
439 
440         case GLESDriverType::SystemWGL:
441         {
442             // WGL tests are currently disabled.
443             std::cerr << "Unsupported driver." << std::endl;
444             break;
445         }
446     }
447 }
448 
~ANGLETestBase()449 ANGLETestBase::~ANGLETestBase()
450 {
451     if (mQuadVertexBuffer)
452     {
453         glDeleteBuffers(1, &mQuadVertexBuffer);
454     }
455     if (mQuadIndexBuffer)
456     {
457         glDeleteBuffers(1, &mQuadIndexBuffer);
458     }
459     if (m2DTexturedQuadProgram)
460     {
461         glDeleteProgram(m2DTexturedQuadProgram);
462     }
463     if (m3DTexturedQuadProgram)
464     {
465         glDeleteProgram(m3DTexturedQuadProgram);
466     }
467 
468     if (!mSetUpCalled)
469     {
470         GTEST_NONFATAL_FAILURE_("SetUp not called.");
471     }
472 
473     if (!mTearDownCalled)
474     {
475         GTEST_NONFATAL_FAILURE_("TearDown not called.");
476     }
477 }
478 
ANGLETestSetUp()479 void ANGLETestBase::ANGLETestSetUp()
480 {
481     mSetUpCalled = true;
482 
483     InitCrashHandler();
484 
485     gDefaultPlatformMethods.overrideWorkaroundsD3D = TestPlatform_overrideWorkaroundsD3D;
486     gDefaultPlatformMethods.overrideFeaturesVk     = TestPlatform_overrideFeaturesVk;
487     gDefaultPlatformMethods.logError               = TestPlatform_logError;
488     gDefaultPlatformMethods.logWarning             = TestPlatform_logWarning;
489     gDefaultPlatformMethods.logInfo                = TestPlatform_logInfo;
490     gDefaultPlatformMethods.context                = &gPlatformContext;
491 
492     gPlatformContext.ignoreMessages   = false;
493     gPlatformContext.warningsAsErrors = false;
494     gPlatformContext.currentTest      = this;
495 
496     if (IsWindows())
497     {
498         const auto &info = testing::UnitTest::GetInstance()->current_test_info();
499         WriteDebugMessage("Entering %s.%s\n", info->test_case_name(), info->name());
500     }
501 
502     if (mCurrentParams->noFixture)
503     {
504 #if defined(ANGLE_USE_UTIL_LOADER)
505         PFNEGLGETPROCADDRESSPROC getProcAddress;
506         ANGLETestEnvironment::GetEGLLibrary()->getAs("eglGetProcAddress", &getProcAddress);
507         ASSERT_NE(nullptr, getProcAddress);
508 
509         LoadEGL(getProcAddress);
510         LoadGLES(getProcAddress);
511 #endif  // defined(ANGLE_USE_UTIL_LOADER)
512         return;
513     }
514 
515     // Resize the window before creating the context so that the first make current
516     // sets the viewport and scissor box to the right size.
517     bool needSwap = false;
518     if (mFixture->osWindow->getWidth() != mWidth || mFixture->osWindow->getHeight() != mHeight)
519     {
520         if (!mFixture->osWindow->resize(mWidth, mHeight))
521         {
522             FAIL() << "Failed to resize ANGLE test window.";
523         }
524         needSwap = true;
525     }
526 
527     // WGL tests are currently disabled.
528     if (mFixture->wglWindow)
529     {
530         FAIL() << "Unsupported driver.";
531     }
532     else
533     {
534         if (mForceNewDisplay || !mFixture->eglWindow->isDisplayInitialized())
535         {
536             mFixture->eglWindow->destroyGL();
537             if (!mFixture->eglWindow->initializeDisplay(mFixture->osWindow,
538                                                         ANGLETestEnvironment::GetEGLLibrary(),
539                                                         mCurrentParams->eglParameters))
540             {
541                 FAIL() << "EGL Display init failed.";
542             }
543         }
544         else if (mCurrentParams->eglParameters != mFixture->eglWindow->getPlatform())
545         {
546             FAIL() << "Internal parameter conflict error.";
547         }
548 
549         if (!mFixture->eglWindow->initializeSurface(
550                 mFixture->osWindow, ANGLETestEnvironment::GetEGLLibrary(), mFixture->configParams))
551         {
552             FAIL() << "egl surface init failed.";
553         }
554 
555         if (!mDeferContextInit && !mFixture->eglWindow->initializeContext())
556         {
557             FAIL() << "GL Context init failed.";
558         }
559     }
560 
561     if (needSwap)
562     {
563         // Swap the buffers so that the default framebuffer picks up the resize
564         // which will allow follow-up test code to assume the framebuffer covers
565         // the whole window.
566         swapBuffers();
567     }
568 
569     // This Viewport command is not strictly necessary but we add it so that programs
570     // taking OpenGL traces can guess the size of the default framebuffer and show it
571     // in their UIs
572     glViewport(0, 0, mWidth, mHeight);
573 }
574 
ANGLETestTearDown()575 void ANGLETestBase::ANGLETestTearDown()
576 {
577     mTearDownCalled              = true;
578     gPlatformContext.currentTest = nullptr;
579 
580     if (IsWindows())
581     {
582         const testing::TestInfo *info = testing::UnitTest::GetInstance()->current_test_info();
583         WriteDebugMessage("Exiting %s.%s\n", info->test_case_name(), info->name());
584     }
585 
586     if (mCurrentParams->noFixture)
587     {
588         return;
589     }
590 
591     swapBuffers();
592     mFixture->osWindow->messageLoop();
593 
594     if (mFixture->eglWindow)
595     {
596         checkD3D11SDKLayersMessages();
597     }
598 
599     if (mFixture->reuseCounter++ >= kWindowReuseLimit || mForceNewDisplay)
600     {
601         mFixture->reuseCounter = 0;
602         getGLWindow()->destroyGL();
603     }
604     else
605     {
606         mFixture->eglWindow->destroyContext();
607         mFixture->eglWindow->destroySurface();
608     }
609 
610     TerminateCrashHandler();
611 
612     // Check for quit message
613     Event myEvent;
614     while (mFixture->osWindow->popEvent(&myEvent))
615     {
616         if (myEvent.Type == Event::EVENT_CLOSED)
617         {
618             exit(0);
619         }
620     }
621 }
622 
swapBuffers()623 void ANGLETestBase::swapBuffers()
624 {
625     if (getGLWindow()->isGLInitialized())
626     {
627         getGLWindow()->swap();
628 
629         if (mFixture->eglWindow)
630         {
631             EXPECT_EGL_SUCCESS();
632         }
633     }
634 }
635 
setupQuadVertexBuffer(GLfloat positionAttribZ,GLfloat positionAttribXYScale)636 void ANGLETestBase::setupQuadVertexBuffer(GLfloat positionAttribZ, GLfloat positionAttribXYScale)
637 {
638     if (mQuadVertexBuffer == 0)
639     {
640         glGenBuffers(1, &mQuadVertexBuffer);
641     }
642 
643     auto quadVertices = GetQuadVertices();
644     for (Vector3 &vertex : quadVertices)
645     {
646         vertex.x() *= positionAttribXYScale;
647         vertex.y() *= positionAttribXYScale;
648         vertex.z() = positionAttribZ;
649     }
650 
651     glBindBuffer(GL_ARRAY_BUFFER, mQuadVertexBuffer);
652     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 6, quadVertices.data(), GL_STATIC_DRAW);
653 }
654 
setupIndexedQuadVertexBuffer(GLfloat positionAttribZ,GLfloat positionAttribXYScale)655 void ANGLETestBase::setupIndexedQuadVertexBuffer(GLfloat positionAttribZ,
656                                                  GLfloat positionAttribXYScale)
657 {
658     if (mQuadVertexBuffer == 0)
659     {
660         glGenBuffers(1, &mQuadVertexBuffer);
661     }
662 
663     auto quadVertices = kIndexedQuadVertices;
664     for (Vector3 &vertex : quadVertices)
665     {
666         vertex.x() *= positionAttribXYScale;
667         vertex.y() *= positionAttribXYScale;
668         vertex.z() = positionAttribZ;
669     }
670 
671     glBindBuffer(GL_ARRAY_BUFFER, mQuadVertexBuffer);
672     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 4, quadVertices.data(), GL_STATIC_DRAW);
673 }
674 
setupIndexedQuadIndexBuffer()675 void ANGLETestBase::setupIndexedQuadIndexBuffer()
676 {
677     if (mQuadIndexBuffer == 0)
678     {
679         glGenBuffers(1, &mQuadIndexBuffer);
680     }
681 
682     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mQuadIndexBuffer);
683     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexedQuadIndices), kIndexedQuadIndices.data(),
684                  GL_STATIC_DRAW);
685 }
686 
687 // static
drawQuad(GLuint program,const std::string & positionAttribName,GLfloat positionAttribZ)688 void ANGLETestBase::drawQuad(GLuint program,
689                              const std::string &positionAttribName,
690                              GLfloat positionAttribZ)
691 {
692     drawQuad(program, positionAttribName, positionAttribZ, 1.0f);
693 }
694 
695 // static
drawQuad(GLuint program,const std::string & positionAttribName,GLfloat positionAttribZ,GLfloat positionAttribXYScale)696 void ANGLETestBase::drawQuad(GLuint program,
697                              const std::string &positionAttribName,
698                              GLfloat positionAttribZ,
699                              GLfloat positionAttribXYScale)
700 {
701     drawQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale, false);
702 }
703 
drawQuad(GLuint program,const std::string & positionAttribName,GLfloat positionAttribZ,GLfloat positionAttribXYScale,bool useVertexBuffer)704 void ANGLETestBase::drawQuad(GLuint program,
705                              const std::string &positionAttribName,
706                              GLfloat positionAttribZ,
707                              GLfloat positionAttribXYScale,
708                              bool useVertexBuffer)
709 {
710     drawQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale, useVertexBuffer,
711              false, 0u);
712 }
713 
drawQuadInstanced(GLuint program,const std::string & positionAttribName,GLfloat positionAttribZ,GLfloat positionAttribXYScale,bool useVertexBuffer,GLuint numInstances)714 void ANGLETestBase::drawQuadInstanced(GLuint program,
715                                       const std::string &positionAttribName,
716                                       GLfloat positionAttribZ,
717                                       GLfloat positionAttribXYScale,
718                                       bool useVertexBuffer,
719                                       GLuint numInstances)
720 {
721     drawQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale, useVertexBuffer,
722              true, numInstances);
723 }
724 
drawQuad(GLuint program,const std::string & positionAttribName,GLfloat positionAttribZ,GLfloat positionAttribXYScale,bool useVertexBuffer,bool useInstancedDrawCalls,GLuint numInstances)725 void ANGLETestBase::drawQuad(GLuint program,
726                              const std::string &positionAttribName,
727                              GLfloat positionAttribZ,
728                              GLfloat positionAttribXYScale,
729                              bool useVertexBuffer,
730                              bool useInstancedDrawCalls,
731                              GLuint numInstances)
732 {
733     GLint previousProgram = 0;
734     glGetIntegerv(GL_CURRENT_PROGRAM, &previousProgram);
735     if (previousProgram != static_cast<GLint>(program))
736     {
737         glUseProgram(program);
738     }
739 
740     GLint previousBuffer = 0;
741     glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &previousBuffer);
742 
743     GLint positionLocation = glGetAttribLocation(program, positionAttribName.c_str());
744 
745     std::array<Vector3, 6> quadVertices;
746 
747     if (useVertexBuffer)
748     {
749         setupQuadVertexBuffer(positionAttribZ, positionAttribXYScale);
750         glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
751         glBindBuffer(GL_ARRAY_BUFFER, previousBuffer);
752     }
753     else
754     {
755         quadVertices = GetQuadVertices();
756         for (Vector3 &vertex : quadVertices)
757         {
758             vertex.x() *= positionAttribXYScale;
759             vertex.y() *= positionAttribXYScale;
760             vertex.z() = positionAttribZ;
761         }
762 
763         if (previousBuffer != 0)
764         {
765             glBindBuffer(GL_ARRAY_BUFFER, 0);
766         }
767         glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
768         if (previousBuffer != 0)
769         {
770             glBindBuffer(GL_ARRAY_BUFFER, previousBuffer);
771         }
772     }
773     glEnableVertexAttribArray(positionLocation);
774 
775     if (useInstancedDrawCalls)
776     {
777         glDrawArraysInstanced(GL_TRIANGLES, 0, 6, numInstances);
778     }
779     else
780     {
781         glDrawArrays(GL_TRIANGLES, 0, 6);
782     }
783 
784     glDisableVertexAttribArray(positionLocation);
785     glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
786 
787     if (previousProgram != static_cast<GLint>(program))
788     {
789         glUseProgram(previousProgram);
790     }
791 }
792 
drawIndexedQuad(GLuint program,const std::string & positionAttribName,GLfloat positionAttribZ)793 void ANGLETestBase::drawIndexedQuad(GLuint program,
794                                     const std::string &positionAttribName,
795                                     GLfloat positionAttribZ)
796 {
797     drawIndexedQuad(program, positionAttribName, positionAttribZ, 1.0f);
798 }
799 
drawIndexedQuad(GLuint program,const std::string & positionAttribName,GLfloat positionAttribZ,GLfloat positionAttribXYScale)800 void ANGLETestBase::drawIndexedQuad(GLuint program,
801                                     const std::string &positionAttribName,
802                                     GLfloat positionAttribZ,
803                                     GLfloat positionAttribXYScale)
804 {
805     drawIndexedQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale, false);
806 }
807 
drawIndexedQuad(GLuint program,const std::string & positionAttribName,GLfloat positionAttribZ,GLfloat positionAttribXYScale,bool useIndexBuffer)808 void ANGLETestBase::drawIndexedQuad(GLuint program,
809                                     const std::string &positionAttribName,
810                                     GLfloat positionAttribZ,
811                                     GLfloat positionAttribXYScale,
812                                     bool useIndexBuffer)
813 {
814     drawIndexedQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale,
815                     useIndexBuffer, false);
816 }
817 
drawIndexedQuad(GLuint program,const std::string & positionAttribName,GLfloat positionAttribZ,GLfloat positionAttribXYScale,bool useIndexBuffer,bool restrictedRange)818 void ANGLETestBase::drawIndexedQuad(GLuint program,
819                                     const std::string &positionAttribName,
820                                     GLfloat positionAttribZ,
821                                     GLfloat positionAttribXYScale,
822                                     bool useIndexBuffer,
823                                     bool restrictedRange)
824 {
825     GLint positionLocation = glGetAttribLocation(program, positionAttribName.c_str());
826 
827     GLint activeProgram = 0;
828     glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram);
829     if (static_cast<GLuint>(activeProgram) != program)
830     {
831         glUseProgram(program);
832     }
833 
834     GLuint prevCoordBinding = 0;
835     glGetIntegerv(GL_ARRAY_BUFFER_BINDING, reinterpret_cast<GLint *>(&prevCoordBinding));
836 
837     setupIndexedQuadVertexBuffer(positionAttribZ, positionAttribXYScale);
838 
839     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
840     glEnableVertexAttribArray(positionLocation);
841     glBindBuffer(GL_ARRAY_BUFFER, prevCoordBinding);
842 
843     GLuint prevIndexBinding = 0;
844     const GLvoid *indices;
845     if (useIndexBuffer)
846     {
847         glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING,
848                       reinterpret_cast<GLint *>(&prevIndexBinding));
849 
850         setupIndexedQuadIndexBuffer();
851         indices = 0;
852     }
853     else
854     {
855         indices = kIndexedQuadIndices.data();
856     }
857 
858     if (!restrictedRange)
859     {
860         glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
861     }
862     else
863     {
864         glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, indices);
865     }
866 
867     if (useIndexBuffer)
868     {
869         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prevIndexBinding);
870     }
871 
872     glDisableVertexAttribArray(positionLocation);
873     glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
874 
875     if (static_cast<GLuint>(activeProgram) != program)
876     {
877         glUseProgram(static_cast<GLuint>(activeProgram));
878     }
879 }
880 
get2DTexturedQuadProgram()881 GLuint ANGLETestBase::get2DTexturedQuadProgram()
882 {
883     if (m2DTexturedQuadProgram)
884     {
885         return m2DTexturedQuadProgram;
886     }
887 
888     constexpr char kVS[] =
889         "attribute vec2 position;\n"
890         "varying mediump vec2 texCoord;\n"
891         "void main()\n"
892         "{\n"
893         "    gl_Position = vec4(position, 0, 1);\n"
894         "    texCoord = position * 0.5 + vec2(0.5);\n"
895         "}\n";
896 
897     constexpr char kFS[] =
898         "varying mediump vec2 texCoord;\n"
899         "uniform sampler2D tex;\n"
900         "void main()\n"
901         "{\n"
902         "    gl_FragColor = texture2D(tex, texCoord);\n"
903         "}\n";
904 
905     m2DTexturedQuadProgram = CompileProgram(kVS, kFS);
906     return m2DTexturedQuadProgram;
907 }
908 
get3DTexturedQuadProgram()909 GLuint ANGLETestBase::get3DTexturedQuadProgram()
910 {
911     if (m3DTexturedQuadProgram)
912     {
913         return m3DTexturedQuadProgram;
914     }
915 
916     constexpr char kVS[] = R"(#version 300 es
917 in vec2 position;
918 out vec2 texCoord;
919 void main()
920 {
921     gl_Position = vec4(position, 0, 1);
922     texCoord = position * 0.5 + vec2(0.5);
923 })";
924 
925     constexpr char kFS[] = R"(#version 300 es
926 precision highp float;
927 
928 in vec2 texCoord;
929 out vec4 my_FragColor;
930 
931 uniform highp sampler3D tex;
932 uniform float u_layer;
933 
934 void main()
935 {
936     my_FragColor = texture(tex, vec3(texCoord, u_layer));
937 })";
938 
939     m3DTexturedQuadProgram = CompileProgram(kVS, kFS);
940     return m3DTexturedQuadProgram;
941 }
942 
draw2DTexturedQuad(GLfloat positionAttribZ,GLfloat positionAttribXYScale,bool useVertexBuffer)943 void ANGLETestBase::draw2DTexturedQuad(GLfloat positionAttribZ,
944                                        GLfloat positionAttribXYScale,
945                                        bool useVertexBuffer)
946 {
947     ASSERT_NE(0u, get2DTexturedQuadProgram());
948     drawQuad(get2DTexturedQuadProgram(), "position", positionAttribZ, positionAttribXYScale,
949              useVertexBuffer);
950 }
951 
draw3DTexturedQuad(GLfloat positionAttribZ,GLfloat positionAttribXYScale,bool useVertexBuffer,float layer)952 void ANGLETestBase::draw3DTexturedQuad(GLfloat positionAttribZ,
953                                        GLfloat positionAttribXYScale,
954                                        bool useVertexBuffer,
955                                        float layer)
956 {
957     GLuint program = get3DTexturedQuadProgram();
958     ASSERT_NE(0u, program);
959     GLint activeProgram = 0;
960     glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram);
961     if (static_cast<GLuint>(activeProgram) != program)
962     {
963         glUseProgram(program);
964     }
965     glUniform1f(glGetUniformLocation(program, "u_layer"), layer);
966 
967     drawQuad(program, "position", positionAttribZ, positionAttribXYScale, useVertexBuffer);
968 
969     if (static_cast<GLuint>(activeProgram) != program)
970     {
971         glUseProgram(static_cast<GLuint>(activeProgram));
972     }
973 }
974 
checkD3D11SDKLayersMessages()975 void ANGLETestBase::checkD3D11SDKLayersMessages()
976 {
977 #if defined(ANGLE_PLATFORM_WINDOWS)
978     // On Windows D3D11, check ID3D11InfoQueue to see if any D3D11 SDK Layers messages
979     // were outputted by the test. We enable the Debug layers in Release tests as well.
980     if (mIgnoreD3D11SDKLayersWarnings ||
981         mFixture->eglWindow->getPlatform().renderer != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE ||
982         mFixture->eglWindow->getDisplay() == EGL_NO_DISPLAY)
983     {
984         return;
985     }
986 
987     const char *extensionString = static_cast<const char *>(
988         eglQueryString(mFixture->eglWindow->getDisplay(), EGL_EXTENSIONS));
989     if (!extensionString)
990     {
991         std::cout << "Error getting extension string from EGL Window." << std::endl;
992         return;
993     }
994 
995     if (!strstr(extensionString, "EGL_EXT_device_query"))
996     {
997         return;
998     }
999 
1000     EGLAttrib device      = 0;
1001     EGLAttrib angleDevice = 0;
1002 
1003     ASSERT_EGL_TRUE(
1004         eglQueryDisplayAttribEXT(mFixture->eglWindow->getDisplay(), EGL_DEVICE_EXT, &angleDevice));
1005     ASSERT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice),
1006                                             EGL_D3D11_DEVICE_ANGLE, &device));
1007     ID3D11Device *d3d11Device = reinterpret_cast<ID3D11Device *>(device);
1008 
1009     ID3D11InfoQueue *infoQueue = nullptr;
1010     HRESULT hr =
1011         d3d11Device->QueryInterface(__uuidof(infoQueue), reinterpret_cast<void **>(&infoQueue));
1012     if (SUCCEEDED(hr))
1013     {
1014         UINT64 numStoredD3DDebugMessages =
1015             infoQueue->GetNumStoredMessagesAllowedByRetrievalFilter();
1016 
1017         if (numStoredD3DDebugMessages > 0)
1018         {
1019             for (UINT64 i = 0; i < numStoredD3DDebugMessages; i++)
1020             {
1021                 SIZE_T messageLength = 0;
1022                 hr                   = infoQueue->GetMessage(i, nullptr, &messageLength);
1023 
1024                 if (SUCCEEDED(hr))
1025                 {
1026                     D3D11_MESSAGE *pMessage =
1027                         reinterpret_cast<D3D11_MESSAGE *>(malloc(messageLength));
1028                     infoQueue->GetMessage(i, pMessage, &messageLength);
1029 
1030                     std::cout << "Message " << i << ":"
1031                               << " " << pMessage->pDescription << "\n";
1032                     free(pMessage);
1033                 }
1034             }
1035             // Clear the queue, so that previous failures are not reported
1036             // for subsequent, otherwise passing, tests
1037             infoQueue->ClearStoredMessages();
1038 
1039             FAIL() << numStoredD3DDebugMessages
1040                    << " D3D11 SDK Layers message(s) detected! Test Failed.\n";
1041         }
1042     }
1043 
1044     SafeRelease(infoQueue);
1045 #endif  // defined(ANGLE_PLATFORM_WINDOWS)
1046 }
1047 
setWindowWidth(int width)1048 void ANGLETestBase::setWindowWidth(int width)
1049 {
1050     mWidth = width;
1051 }
1052 
setWindowHeight(int height)1053 void ANGLETestBase::setWindowHeight(int height)
1054 {
1055     mHeight = height;
1056 }
1057 
getGLWindow() const1058 GLWindowBase *ANGLETestBase::getGLWindow() const
1059 {
1060     // WGL tests are currently disabled.
1061     assert(!mFixture->wglWindow);
1062     return mFixture->eglWindow;
1063 }
1064 
setConfigRedBits(int bits)1065 void ANGLETestBase::setConfigRedBits(int bits)
1066 {
1067     mFixture->configParams.redBits = bits;
1068 }
1069 
setConfigGreenBits(int bits)1070 void ANGLETestBase::setConfigGreenBits(int bits)
1071 {
1072     mFixture->configParams.greenBits = bits;
1073 }
1074 
setConfigBlueBits(int bits)1075 void ANGLETestBase::setConfigBlueBits(int bits)
1076 {
1077     mFixture->configParams.blueBits = bits;
1078 }
1079 
setConfigAlphaBits(int bits)1080 void ANGLETestBase::setConfigAlphaBits(int bits)
1081 {
1082     mFixture->configParams.alphaBits = bits;
1083 }
1084 
setConfigDepthBits(int bits)1085 void ANGLETestBase::setConfigDepthBits(int bits)
1086 {
1087     mFixture->configParams.depthBits = bits;
1088 }
1089 
setConfigStencilBits(int bits)1090 void ANGLETestBase::setConfigStencilBits(int bits)
1091 {
1092     mFixture->configParams.stencilBits = bits;
1093 }
1094 
setConfigComponentType(EGLenum componentType)1095 void ANGLETestBase::setConfigComponentType(EGLenum componentType)
1096 {
1097     mFixture->configParams.componentType = componentType;
1098 }
1099 
setMultisampleEnabled(bool enabled)1100 void ANGLETestBase::setMultisampleEnabled(bool enabled)
1101 {
1102     mFixture->configParams.multisample = enabled;
1103 }
1104 
setSamples(EGLint samples)1105 void ANGLETestBase::setSamples(EGLint samples)
1106 {
1107     mFixture->configParams.samples = samples;
1108 }
1109 
setDebugEnabled(bool enabled)1110 void ANGLETestBase::setDebugEnabled(bool enabled)
1111 {
1112     mFixture->configParams.debug = enabled;
1113 }
1114 
setNoErrorEnabled(bool enabled)1115 void ANGLETestBase::setNoErrorEnabled(bool enabled)
1116 {
1117     mFixture->configParams.noError = enabled;
1118 }
1119 
setWebGLCompatibilityEnabled(bool webglCompatibility)1120 void ANGLETestBase::setWebGLCompatibilityEnabled(bool webglCompatibility)
1121 {
1122     mFixture->configParams.webGLCompatibility = webglCompatibility;
1123 }
1124 
setExtensionsEnabled(bool extensionsEnabled)1125 void ANGLETestBase::setExtensionsEnabled(bool extensionsEnabled)
1126 {
1127     mFixture->configParams.extensionsEnabled = extensionsEnabled;
1128 }
1129 
setRobustAccess(bool enabled)1130 void ANGLETestBase::setRobustAccess(bool enabled)
1131 {
1132     mFixture->configParams.robustAccess = enabled;
1133 }
1134 
setBindGeneratesResource(bool bindGeneratesResource)1135 void ANGLETestBase::setBindGeneratesResource(bool bindGeneratesResource)
1136 {
1137     mFixture->configParams.bindGeneratesResource = bindGeneratesResource;
1138 }
1139 
setClientArraysEnabled(bool enabled)1140 void ANGLETestBase::setClientArraysEnabled(bool enabled)
1141 {
1142     mFixture->configParams.clientArraysEnabled = enabled;
1143 }
1144 
setRobustResourceInit(bool enabled)1145 void ANGLETestBase::setRobustResourceInit(bool enabled)
1146 {
1147     mFixture->configParams.robustResourceInit = enabled;
1148 }
1149 
setContextProgramCacheEnabled(bool enabled)1150 void ANGLETestBase::setContextProgramCacheEnabled(bool enabled)
1151 {
1152     mFixture->configParams.contextProgramCacheEnabled = enabled;
1153 }
1154 
setContextResetStrategy(EGLenum resetStrategy)1155 void ANGLETestBase::setContextResetStrategy(EGLenum resetStrategy)
1156 {
1157     mFixture->configParams.resetStrategy = resetStrategy;
1158 }
1159 
forceNewDisplay()1160 void ANGLETestBase::forceNewDisplay()
1161 {
1162     mForceNewDisplay = true;
1163 }
1164 
setDeferContextInit(bool enabled)1165 void ANGLETestBase::setDeferContextInit(bool enabled)
1166 {
1167     mDeferContextInit = enabled;
1168 }
1169 
getClientMajorVersion() const1170 int ANGLETestBase::getClientMajorVersion() const
1171 {
1172     return getGLWindow()->getClientMajorVersion();
1173 }
1174 
getClientMinorVersion() const1175 int ANGLETestBase::getClientMinorVersion() const
1176 {
1177     return getGLWindow()->getClientMinorVersion();
1178 }
1179 
getEGLWindow() const1180 EGLWindow *ANGLETestBase::getEGLWindow() const
1181 {
1182     return mFixture->eglWindow;
1183 }
1184 
getWindowWidth() const1185 int ANGLETestBase::getWindowWidth() const
1186 {
1187     return mWidth;
1188 }
1189 
getWindowHeight() const1190 int ANGLETestBase::getWindowHeight() const
1191 {
1192     return mHeight;
1193 }
1194 
isMultisampleEnabled() const1195 bool ANGLETestBase::isMultisampleEnabled() const
1196 {
1197     return mFixture->eglWindow->isMultisample();
1198 }
1199 
setWindowVisible(bool isVisible)1200 void ANGLETestBase::setWindowVisible(bool isVisible)
1201 {
1202     mFixture->osWindow->setVisible(isVisible);
1203 }
1204 
IsAdreno()1205 bool IsAdreno()
1206 {
1207     std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
1208     return (rendererString.find("Adreno") != std::string::npos);
1209 }
1210 
IsD3D11()1211 bool IsD3D11()
1212 {
1213     std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
1214     return (rendererString.find("Direct3D11 vs_5_0") != std::string::npos);
1215 }
1216 
IsD3D11_FL93()1217 bool IsD3D11_FL93()
1218 {
1219     std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
1220     return (rendererString.find("Direct3D11 vs_4_0_") != std::string::npos);
1221 }
1222 
IsD3D9()1223 bool IsD3D9()
1224 {
1225     std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
1226     return (rendererString.find("Direct3D9") != std::string::npos);
1227 }
1228 
IsD3DSM3()1229 bool IsD3DSM3()
1230 {
1231     return IsD3D9() || IsD3D11_FL93();
1232 }
1233 
IsDesktopOpenGL()1234 bool IsDesktopOpenGL()
1235 {
1236     return IsOpenGL() && !IsOpenGLES();
1237 }
1238 
IsOpenGLES()1239 bool IsOpenGLES()
1240 {
1241     std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
1242     return (rendererString.find("OpenGL ES") != std::string::npos);
1243 }
1244 
IsOpenGL()1245 bool IsOpenGL()
1246 {
1247     std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
1248     return (rendererString.find("OpenGL") != std::string::npos);
1249 }
1250 
IsNULL()1251 bool IsNULL()
1252 {
1253     std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
1254     return (rendererString.find("NULL") != std::string::npos);
1255 }
1256 
IsVulkan()1257 bool IsVulkan()
1258 {
1259     const char *renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
1260     std::string rendererString(renderer);
1261     return (rendererString.find("Vulkan") != std::string::npos);
1262 }
1263 
IsDebug()1264 bool IsDebug()
1265 {
1266 #if !defined(NDEBUG)
1267     return true;
1268 #else
1269     return false;
1270 #endif
1271 }
1272 
IsRelease()1273 bool IsRelease()
1274 {
1275     return !IsDebug();
1276 }
1277 
1278 ANGLETestBase::TestFixture::TestFixture()  = default;
1279 ANGLETestBase::TestFixture::~TestFixture() = default;
1280 
getPlatformRenderer() const1281 EGLint ANGLETestBase::getPlatformRenderer() const
1282 {
1283     assert(mFixture->eglWindow);
1284     return mFixture->eglWindow->getPlatform().renderer;
1285 }
1286 
ignoreD3D11SDKLayersWarnings()1287 void ANGLETestBase::ignoreD3D11SDKLayersWarnings()
1288 {
1289     // Some tests may need to disable the D3D11 SDK Layers Warnings checks
1290     mIgnoreD3D11SDKLayersWarnings = true;
1291 }
1292 
treatPlatformWarningsAsErrors()1293 void ANGLETestBase::treatPlatformWarningsAsErrors()
1294 {
1295 #if defined(ANGLE_PLATFORM_WINDOWS)
1296     // Only do warnings-as-errors on 8 and above. We may fall back to the old
1297     // compiler DLL on Windows 7.
1298     gPlatformContext.warningsAsErrors = IsWindows8OrGreater();
1299 #endif  // defined(ANGLE_PLATFORM_WINDOWS)
1300 }
1301 
ScopedIgnorePlatformMessages()1302 ANGLETestBase::ScopedIgnorePlatformMessages::ScopedIgnorePlatformMessages()
1303 {
1304     gPlatformContext.ignoreMessages = true;
1305 }
1306 
~ScopedIgnorePlatformMessages()1307 ANGLETestBase::ScopedIgnorePlatformMessages::~ScopedIgnorePlatformMessages()
1308 {
1309     gPlatformContext.ignoreMessages = false;
1310 }
1311 
1312 OSWindow *ANGLETestBase::mOSWindowSingleton = nullptr;
1313 std::map<angle::PlatformParameters, ANGLETestBase::TestFixture> ANGLETestBase::gFixtures;
1314 Optional<EGLint> ANGLETestBase::mLastRendererType;
1315 
1316 std::unique_ptr<Library> ANGLETestEnvironment::gEGLLibrary;
1317 std::unique_ptr<Library> ANGLETestEnvironment::gWGLLibrary;
1318 
SetUp()1319 void ANGLETestEnvironment::SetUp() {}
1320 
TearDown()1321 void ANGLETestEnvironment::TearDown() {}
1322 
GetEGLLibrary()1323 Library *ANGLETestEnvironment::GetEGLLibrary()
1324 {
1325 #if defined(ANGLE_USE_UTIL_LOADER)
1326     if (!gEGLLibrary)
1327     {
1328         gEGLLibrary.reset(OpenSharedLibrary(ANGLE_EGL_LIBRARY_NAME, SearchType::ApplicationDir));
1329     }
1330 #endif  // defined(ANGLE_USE_UTIL_LOADER)
1331     return gEGLLibrary.get();
1332 }
1333 
GetWGLLibrary()1334 Library *ANGLETestEnvironment::GetWGLLibrary()
1335 {
1336 #if defined(ANGLE_USE_UTIL_LOADER) && defined(ANGLE_PLATFORM_WINDOWS)
1337     if (!gWGLLibrary)
1338     {
1339         gWGLLibrary.reset(OpenSharedLibrary("opengl32", SearchType::SystemDir));
1340     }
1341 #endif  // defined(ANGLE_USE_UTIL_LOADER) && defined(ANGLE_PLATFORM_WINDOWS)
1342     return gWGLLibrary.get();
1343 }
1344 
ANGLEProcessTestArgs(int * argc,char * argv[])1345 void ANGLEProcessTestArgs(int *argc, char *argv[])
1346 {
1347     testing::AddGlobalTestEnvironment(new ANGLETestEnvironment());
1348 
1349     for (int argIndex = 1; argIndex < *argc; argIndex++)
1350     {
1351         if (strncmp(argv[argIndex], kUseConfig, strlen(kUseConfig)) == 0)
1352         {
1353             gSelectedConfig = std::string(argv[argIndex] + strlen(kUseConfig));
1354         }
1355         if (strncmp(argv[argIndex], kSeparateProcessPerConfig, strlen(kSeparateProcessPerConfig)) ==
1356             0)
1357         {
1358             gSeparateProcessPerConfig = true;
1359         }
1360     }
1361 
1362     if (gSeparateProcessPerConfig)
1363     {
1364         if (!gSelectedConfig.empty())
1365         {
1366             std::cout << "Cannot use both a single test config and separate processes.\n";
1367             exit(1);
1368         }
1369 
1370         if (RunSeparateProcessesForEachConfig(argc, argv))
1371         {
1372             exit(0);
1373         }
1374         else
1375         {
1376             std::cout << "Some subprocesses failed.\n";
1377             exit(1);
1378         }
1379     }
1380 }
1381 
EnsureGLExtensionEnabled(const std::string & extName)1382 bool EnsureGLExtensionEnabled(const std::string &extName)
1383 {
1384     if (IsGLExtensionEnabled("GL_ANGLE_request_extension") && IsGLExtensionRequestable(extName))
1385     {
1386         glRequestExtensionANGLE(extName.c_str());
1387     }
1388 
1389     return IsGLExtensionEnabled(extName);
1390 }
1391 
IsEGLClientExtensionEnabled(const std::string & extName)1392 bool IsEGLClientExtensionEnabled(const std::string &extName)
1393 {
1394     return CheckExtensionExists(eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS), extName);
1395 }
1396 
IsEGLDeviceExtensionEnabled(EGLDeviceEXT device,const std::string & extName)1397 bool IsEGLDeviceExtensionEnabled(EGLDeviceEXT device, const std::string &extName)
1398 {
1399     return CheckExtensionExists(eglQueryDeviceStringEXT(device, EGL_EXTENSIONS), extName);
1400 }
1401 
IsEGLDisplayExtensionEnabled(EGLDisplay display,const std::string & extName)1402 bool IsEGLDisplayExtensionEnabled(EGLDisplay display, const std::string &extName)
1403 {
1404     return CheckExtensionExists(eglQueryString(display, EGL_EXTENSIONS), extName);
1405 }
1406 
IsGLExtensionEnabled(const std::string & extName)1407 bool IsGLExtensionEnabled(const std::string &extName)
1408 {
1409     return CheckExtensionExists(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)),
1410                                 extName);
1411 }
1412 
IsGLExtensionRequestable(const std::string & extName)1413 bool IsGLExtensionRequestable(const std::string &extName)
1414 {
1415     return CheckExtensionExists(
1416         reinterpret_cast<const char *>(glGetString(GL_REQUESTABLE_EXTENSIONS_ANGLE)), extName);
1417 }
1418