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