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