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