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