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