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