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