mirror of
https://github.com/godotengine/godot-angle-static.git
synced 2026-01-06 02:09:55 +03:00
This is currently only supported for end2end tests (those which use ANGLETestBase, excluding those that use WithNoFixture) and Vulkan. Use WithEmulatedPreoration(*_VULKAN(), degree) where degree is either 90, 180 or 270. With emulated prerotation, the window dimensions are physically swapped if 90 and 270 degrees, while the width and height is still reported as requested by the test. In the Vulkan backend, the width and height are swapped after getting queried from the surface, and prerotation is assumed. Bug: angleproject:4901 Change-Id: I294436be4c7015d2a63463c4d61de7b67f38c95d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2495544 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Ian Elliott <ianelliott@google.com> Reviewed-by: Jamie Madill <jmadill@chromium.org>
1396 lines
39 KiB
C++
1396 lines
39 KiB
C++
//
|
|
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
//
|
|
// ANGLETest:
|
|
// Implementation of common ANGLE testing fixture.
|
|
//
|
|
|
|
#include "ANGLETest.h"
|
|
|
|
#include <algorithm>
|
|
#include <cstdlib>
|
|
|
|
#include "common/platform.h"
|
|
#include "gpu_info_util/SystemInfo.h"
|
|
#include "util/EGLWindow.h"
|
|
#include "util/OSWindow.h"
|
|
#include "util/random_utils.h"
|
|
#include "util/test_utils.h"
|
|
|
|
#if defined(ANGLE_PLATFORM_WINDOWS)
|
|
# include <VersionHelpers.h>
|
|
#endif // defined(ANGLE_PLATFORM_WINDOWS)
|
|
|
|
namespace angle
|
|
{
|
|
|
|
const GLColorRGB GLColorRGB::black(0u, 0u, 0u);
|
|
const GLColorRGB GLColorRGB::blue(0u, 0u, 255u);
|
|
const GLColorRGB GLColorRGB::green(0u, 255u, 0u);
|
|
const GLColorRGB GLColorRGB::red(255u, 0u, 0u);
|
|
const GLColorRGB GLColorRGB::yellow(255u, 255u, 0);
|
|
|
|
const GLColor GLColor::black = GLColor(0u, 0u, 0u, 255u);
|
|
const GLColor GLColor::blue = GLColor(0u, 0u, 255u, 255u);
|
|
const GLColor GLColor::cyan = GLColor(0u, 255u, 255u, 255u);
|
|
const GLColor GLColor::green = GLColor(0u, 255u, 0u, 255u);
|
|
const GLColor GLColor::red = GLColor(255u, 0u, 0u, 255u);
|
|
const GLColor GLColor::transparentBlack = GLColor(0u, 0u, 0u, 0u);
|
|
const GLColor GLColor::white = GLColor(255u, 255u, 255u, 255u);
|
|
const GLColor GLColor::yellow = GLColor(255u, 255u, 0, 255u);
|
|
const GLColor GLColor::magenta = GLColor(255u, 0u, 255u, 255u);
|
|
|
|
namespace
|
|
{
|
|
float ColorNorm(GLubyte channelValue)
|
|
{
|
|
return static_cast<float>(channelValue) / 255.0f;
|
|
}
|
|
|
|
GLubyte ColorDenorm(float colorValue)
|
|
{
|
|
return static_cast<GLubyte>(colorValue * 255.0f);
|
|
}
|
|
|
|
void TestPlatform_logError(PlatformMethods *platform, const char *errorMessage)
|
|
{
|
|
auto *testPlatformContext = static_cast<TestPlatformContext *>(platform->context);
|
|
if (testPlatformContext->ignoreMessages)
|
|
return;
|
|
|
|
GTEST_NONFATAL_FAILURE_(errorMessage);
|
|
|
|
PrintStackBacktrace();
|
|
}
|
|
|
|
void TestPlatform_logWarning(PlatformMethods *platform, const char *warningMessage)
|
|
{
|
|
auto *testPlatformContext = static_cast<TestPlatformContext *>(platform->context);
|
|
if (testPlatformContext->ignoreMessages)
|
|
return;
|
|
|
|
if (testPlatformContext->warningsAsErrors)
|
|
{
|
|
FAIL() << warningMessage;
|
|
}
|
|
else
|
|
{
|
|
std::cerr << "Warning: " << warningMessage << std::endl;
|
|
}
|
|
}
|
|
|
|
void TestPlatform_logInfo(PlatformMethods *platform, const char *infoMessage) {}
|
|
|
|
void TestPlatform_overrideWorkaroundsD3D(PlatformMethods *platform, FeaturesD3D *featuresD3D)
|
|
{
|
|
auto *testPlatformContext = static_cast<TestPlatformContext *>(platform->context);
|
|
if (testPlatformContext->currentTest)
|
|
{
|
|
testPlatformContext->currentTest->overrideWorkaroundsD3D(featuresD3D);
|
|
}
|
|
}
|
|
|
|
void TestPlatform_overrideFeaturesVk(PlatformMethods *platform, FeaturesVk *featuresVulkan)
|
|
{
|
|
auto *testPlatformContext = static_cast<TestPlatformContext *>(platform->context);
|
|
if (testPlatformContext->currentTest)
|
|
{
|
|
testPlatformContext->currentTest->overrideFeaturesVk(featuresVulkan);
|
|
}
|
|
}
|
|
|
|
const std::array<Vector3, 6> kQuadVertices = {{
|
|
Vector3(-1.0f, 1.0f, 0.5f),
|
|
Vector3(-1.0f, -1.0f, 0.5f),
|
|
Vector3(1.0f, -1.0f, 0.5f),
|
|
Vector3(-1.0f, 1.0f, 0.5f),
|
|
Vector3(1.0f, -1.0f, 0.5f),
|
|
Vector3(1.0f, 1.0f, 0.5f),
|
|
}};
|
|
|
|
const std::array<Vector3, 4> kIndexedQuadVertices = {{
|
|
Vector3(-1.0f, 1.0f, 0.5f),
|
|
Vector3(-1.0f, -1.0f, 0.5f),
|
|
Vector3(1.0f, -1.0f, 0.5f),
|
|
Vector3(1.0f, 1.0f, 0.5f),
|
|
}};
|
|
|
|
constexpr std::array<GLushort, 6> kIndexedQuadIndices = {{0, 1, 2, 0, 2, 3}};
|
|
|
|
const char *GetColorName(GLColor color)
|
|
{
|
|
if (color == GLColor::red)
|
|
{
|
|
return "Red";
|
|
}
|
|
|
|
if (color == GLColor::green)
|
|
{
|
|
return "Green";
|
|
}
|
|
|
|
if (color == GLColor::blue)
|
|
{
|
|
return "Blue";
|
|
}
|
|
|
|
if (color == GLColor::white)
|
|
{
|
|
return "White";
|
|
}
|
|
|
|
if (color == GLColor::black)
|
|
{
|
|
return "Black";
|
|
}
|
|
|
|
if (color == GLColor::transparentBlack)
|
|
{
|
|
return "Transparent Black";
|
|
}
|
|
|
|
if (color == GLColor::yellow)
|
|
{
|
|
return "Yellow";
|
|
}
|
|
|
|
if (color == GLColor::magenta)
|
|
{
|
|
return "Magenta";
|
|
}
|
|
|
|
if (color == GLColor::cyan)
|
|
{
|
|
return "Cyan";
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
// Always re-use displays when using --bot-mode in the test runner.
|
|
bool gReuseDisplays = false;
|
|
|
|
bool ShouldAlwaysForceNewDisplay()
|
|
{
|
|
if (gReuseDisplays)
|
|
return false;
|
|
|
|
// We prefer to reuse config displays. This is faster and solves a driver issue where creating
|
|
// many displays causes crashes. However this exposes other driver bugs on many other platforms.
|
|
// Conservatively enable the feature only on Windows Intel and NVIDIA for now.
|
|
SystemInfo *systemInfo = GetTestSystemInfo();
|
|
return (!systemInfo || !IsWindows() || systemInfo->hasAMDGPU());
|
|
}
|
|
} // anonymous namespace
|
|
|
|
GLColorRGB::GLColorRGB(const Vector3 &floatColor)
|
|
: R(ColorDenorm(floatColor.x())), G(ColorDenorm(floatColor.y())), B(ColorDenorm(floatColor.z()))
|
|
{}
|
|
|
|
GLColor::GLColor(const Vector4 &floatColor)
|
|
: R(ColorDenorm(floatColor.x())),
|
|
G(ColorDenorm(floatColor.y())),
|
|
B(ColorDenorm(floatColor.z())),
|
|
A(ColorDenorm(floatColor.w()))
|
|
{}
|
|
|
|
GLColor::GLColor(GLuint colorValue) : R(0), G(0), B(0), A(0)
|
|
{
|
|
memcpy(&R, &colorValue, sizeof(GLuint));
|
|
}
|
|
|
|
testing::AssertionResult GLColor::ExpectNear(const GLColor &expected, const GLColor &err) const
|
|
{
|
|
testing::AssertionResult result(
|
|
abs(int(expected.R) - this->R) <= err.R && abs(int(expected.G) - this->G) <= err.G &&
|
|
abs(int(expected.B) - this->B) <= err.B && abs(int(expected.A) - this->A) <= err.A);
|
|
if (!bool(result))
|
|
{
|
|
result << "Expected " << expected << "+/-" << err << ", was " << *this;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void CreatePixelCenterWindowCoords(const std::vector<Vector2> &pixelPoints,
|
|
int windowWidth,
|
|
int windowHeight,
|
|
std::vector<Vector3> *outVertices)
|
|
{
|
|
for (Vector2 pixelPoint : pixelPoints)
|
|
{
|
|
outVertices->emplace_back(Vector3((pixelPoint[0] + 0.5f) * 2.0f / windowWidth - 1.0f,
|
|
(pixelPoint[1] + 0.5f) * 2.0f / windowHeight - 1.0f,
|
|
0.0f));
|
|
}
|
|
}
|
|
|
|
Vector4 GLColor::toNormalizedVector() const
|
|
{
|
|
return Vector4(ColorNorm(R), ColorNorm(G), ColorNorm(B), ColorNorm(A));
|
|
}
|
|
|
|
GLColor RandomColor(angle::RNG *rng)
|
|
{
|
|
return GLColor(rng->randomIntBetween(0, 255), rng->randomIntBetween(0, 255),
|
|
rng->randomIntBetween(0, 255), rng->randomIntBetween(0, 255));
|
|
}
|
|
|
|
GLColor ReadColor(GLint x, GLint y)
|
|
{
|
|
GLColor actual;
|
|
glReadPixels((x), (y), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &actual.R);
|
|
EXPECT_GL_NO_ERROR();
|
|
return actual;
|
|
}
|
|
|
|
bool operator==(const GLColor &a, const GLColor &b)
|
|
{
|
|
return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;
|
|
}
|
|
|
|
bool operator!=(const GLColor &a, const GLColor &b)
|
|
{
|
|
return !(a == b);
|
|
}
|
|
|
|
std::ostream &operator<<(std::ostream &ostream, const GLColor &color)
|
|
{
|
|
const char *colorName = GetColorName(color);
|
|
if (colorName)
|
|
{
|
|
return ostream << colorName;
|
|
}
|
|
|
|
ostream << "(" << static_cast<unsigned int>(color.R) << ", "
|
|
<< static_cast<unsigned int>(color.G) << ", " << static_cast<unsigned int>(color.B)
|
|
<< ", " << static_cast<unsigned int>(color.A) << ")";
|
|
return ostream;
|
|
}
|
|
|
|
bool operator==(const GLColor32F &a, const GLColor32F &b)
|
|
{
|
|
return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;
|
|
}
|
|
|
|
std::ostream &operator<<(std::ostream &ostream, const GLColor32F &color)
|
|
{
|
|
ostream << "(" << color.R << ", " << color.G << ", " << color.B << ", " << color.A << ")";
|
|
return ostream;
|
|
}
|
|
|
|
GLColor32F ReadColor32F(GLint x, GLint y)
|
|
{
|
|
GLColor32F actual;
|
|
glReadPixels((x), (y), 1, 1, GL_RGBA, GL_FLOAT, &actual.R);
|
|
EXPECT_GL_NO_ERROR();
|
|
return actual;
|
|
}
|
|
|
|
void LoadEntryPointsWithUtilLoader(angle::GLESDriverType driverType)
|
|
{
|
|
#if defined(ANGLE_USE_UTIL_LOADER)
|
|
PFNEGLGETPROCADDRESSPROC getProcAddress;
|
|
ANGLETestEnvironment::GetDriverLibrary(driverType)->getAs("eglGetProcAddress", &getProcAddress);
|
|
ASSERT_NE(nullptr, getProcAddress);
|
|
|
|
LoadEGL(getProcAddress);
|
|
LoadGLES(getProcAddress);
|
|
#endif // defined(ANGLE_USE_UTIL_LOADER)
|
|
}
|
|
} // namespace angle
|
|
|
|
using namespace angle;
|
|
|
|
PlatformMethods gDefaultPlatformMethods;
|
|
|
|
namespace
|
|
{
|
|
TestPlatformContext gPlatformContext;
|
|
|
|
// After a fixed number of iterations we reset the test window. This works around some driver bugs.
|
|
constexpr uint32_t kWindowReuseLimit = 50;
|
|
|
|
constexpr char kUseConfig[] = "--use-config=";
|
|
constexpr char kReuseDisplays[] = "--reuse-displays";
|
|
constexpr char kEnableANGLEPerTestCaptureLabel[] = "--angle-per-test-capture-label";
|
|
constexpr char kBatchId[] = "--batch-id=";
|
|
|
|
void SetupEnvironmentVarsForCaptureReplay()
|
|
{
|
|
const ::testing::TestInfo *const testInfo =
|
|
::testing::UnitTest::GetInstance()->current_test_info();
|
|
std::string testName = std::string{testInfo->name()};
|
|
std::replace(testName.begin(), testName.end(), '/', '_');
|
|
SetEnvironmentVar("ANGLE_CAPTURE_LABEL",
|
|
(std::string{testInfo->test_case_name()} + "_" + testName).c_str());
|
|
}
|
|
} // anonymous namespace
|
|
|
|
// static
|
|
std::array<Vector3, 6> ANGLETestBase::GetQuadVertices()
|
|
{
|
|
return kQuadVertices;
|
|
}
|
|
|
|
// static
|
|
std::array<GLushort, 6> ANGLETestBase::GetQuadIndices()
|
|
{
|
|
return kIndexedQuadIndices;
|
|
}
|
|
|
|
// static
|
|
std::array<Vector3, 4> ANGLETestBase::GetIndexedQuadVertices()
|
|
{
|
|
return kIndexedQuadVertices;
|
|
}
|
|
|
|
ANGLETestBase::ANGLETestBase(const PlatformParameters ¶ms)
|
|
: mWidth(16),
|
|
mHeight(16),
|
|
mIgnoreD3D11SDKLayersWarnings(false),
|
|
mQuadVertexBuffer(0),
|
|
mQuadIndexBuffer(0),
|
|
m2DTexturedQuadProgram(0),
|
|
m3DTexturedQuadProgram(0),
|
|
mDeferContextInit(false),
|
|
mAlwaysForceNewDisplay(ShouldAlwaysForceNewDisplay()),
|
|
mForceNewDisplay(mAlwaysForceNewDisplay),
|
|
mSetUpCalled(false),
|
|
mTearDownCalled(false),
|
|
mCurrentParams(nullptr),
|
|
mFixture(nullptr)
|
|
{
|
|
// Override the default platform methods with the ANGLE test methods pointer.
|
|
PlatformParameters withMethods = params;
|
|
withMethods.eglParameters.platformMethods = &gDefaultPlatformMethods;
|
|
|
|
if (withMethods.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
|
|
{
|
|
#if defined(ANGLE_ENABLE_VULKAN_VALIDATION_LAYERS)
|
|
withMethods.eglParameters.debugLayersEnabled = true;
|
|
#else
|
|
withMethods.eglParameters.debugLayersEnabled = false;
|
|
#endif
|
|
}
|
|
|
|
auto iter = gFixtures.find(withMethods);
|
|
if (iter != gFixtures.end())
|
|
{
|
|
mCurrentParams = &iter->first;
|
|
|
|
if (!params.noFixture)
|
|
{
|
|
mFixture = &iter->second;
|
|
mFixture->configParams.reset();
|
|
}
|
|
return;
|
|
}
|
|
|
|
TestFixture platform;
|
|
auto insertIter = gFixtures.emplace(withMethods, platform);
|
|
mCurrentParams = &insertIter.first->first;
|
|
|
|
if (!params.noFixture)
|
|
{
|
|
mFixture = &insertIter.first->second;
|
|
initOSWindow();
|
|
}
|
|
}
|
|
|
|
void ANGLETestBase::initOSWindow()
|
|
{
|
|
std::stringstream windowNameStream;
|
|
windowNameStream << "ANGLE Tests - " << *mCurrentParams;
|
|
std::string windowName = windowNameStream.str();
|
|
|
|
if (IsAndroid())
|
|
{
|
|
// Only one window per test application on Android, shared among all fixtures
|
|
mFixture->osWindow = mOSWindowSingleton;
|
|
}
|
|
|
|
if (!mFixture->osWindow)
|
|
{
|
|
mFixture->osWindow = OSWindow::New();
|
|
mFixture->osWindow->disableErrorMessageDialog();
|
|
if (!mFixture->osWindow->initialize(windowName.c_str(), 128, 128))
|
|
{
|
|
std::cerr << "Failed to initialize OS Window.\n";
|
|
}
|
|
|
|
if (IsAndroid())
|
|
{
|
|
// Initialize the single window on Andoird only once
|
|
mOSWindowSingleton = mFixture->osWindow;
|
|
}
|
|
}
|
|
|
|
if (!mFixture->osWindow->valid())
|
|
{
|
|
return;
|
|
}
|
|
|
|
// On Linux we must keep the test windows visible. On Windows it doesn't seem to need it.
|
|
setWindowVisible(getOSWindow(), !IsWindows());
|
|
|
|
switch (mCurrentParams->driver)
|
|
{
|
|
case GLESDriverType::AngleEGL:
|
|
case GLESDriverType::SystemEGL:
|
|
{
|
|
mFixture->eglWindow =
|
|
EGLWindow::New(mCurrentParams->majorVersion, mCurrentParams->minorVersion);
|
|
break;
|
|
}
|
|
|
|
case GLESDriverType::SystemWGL:
|
|
{
|
|
// WGL tests are currently disabled.
|
|
std::cerr << "Unsupported driver." << std::endl;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
ANGLETestBase::~ANGLETestBase()
|
|
{
|
|
if (mQuadVertexBuffer)
|
|
{
|
|
glDeleteBuffers(1, &mQuadVertexBuffer);
|
|
}
|
|
if (mQuadIndexBuffer)
|
|
{
|
|
glDeleteBuffers(1, &mQuadIndexBuffer);
|
|
}
|
|
if (m2DTexturedQuadProgram)
|
|
{
|
|
glDeleteProgram(m2DTexturedQuadProgram);
|
|
}
|
|
if (m3DTexturedQuadProgram)
|
|
{
|
|
glDeleteProgram(m3DTexturedQuadProgram);
|
|
}
|
|
|
|
if (!mSetUpCalled)
|
|
{
|
|
GTEST_NONFATAL_FAILURE_("SetUp not called.");
|
|
}
|
|
|
|
if (!mTearDownCalled)
|
|
{
|
|
GTEST_NONFATAL_FAILURE_("TearDown not called.");
|
|
}
|
|
}
|
|
|
|
void ANGLETestBase::ANGLETestSetUp()
|
|
{
|
|
mSetUpCalled = true;
|
|
|
|
gDefaultPlatformMethods.overrideWorkaroundsD3D = TestPlatform_overrideWorkaroundsD3D;
|
|
gDefaultPlatformMethods.overrideFeaturesVk = TestPlatform_overrideFeaturesVk;
|
|
gDefaultPlatformMethods.logError = TestPlatform_logError;
|
|
gDefaultPlatformMethods.logWarning = TestPlatform_logWarning;
|
|
gDefaultPlatformMethods.logInfo = TestPlatform_logInfo;
|
|
gDefaultPlatformMethods.context = &gPlatformContext;
|
|
|
|
gPlatformContext.ignoreMessages = false;
|
|
gPlatformContext.warningsAsErrors = false;
|
|
gPlatformContext.currentTest = this;
|
|
|
|
// TODO(geofflang): Nexus6P generates GL errors during initialization. Suppress error messages
|
|
// temporarily until enough logging is in place to figure out exactly which calls generate
|
|
// errors. http://crbug.com/998503
|
|
if (IsNexus6P())
|
|
{
|
|
gPlatformContext.ignoreMessages = true;
|
|
}
|
|
|
|
if (IsWindows())
|
|
{
|
|
const auto &info = testing::UnitTest::GetInstance()->current_test_info();
|
|
WriteDebugMessage("Entering %s.%s\n", info->test_case_name(), info->name());
|
|
}
|
|
|
|
if (mCurrentParams->noFixture)
|
|
{
|
|
LoadEntryPointsWithUtilLoader(mCurrentParams->driver);
|
|
return;
|
|
}
|
|
|
|
if (mLastLoadedDriver.valid() && mCurrentParams->driver != mLastLoadedDriver.value())
|
|
{
|
|
LoadEntryPointsWithUtilLoader(mCurrentParams->driver);
|
|
mLastLoadedDriver = mCurrentParams->driver;
|
|
}
|
|
|
|
if (gEnableANGLEPerTestCaptureLabel)
|
|
{
|
|
SetupEnvironmentVarsForCaptureReplay();
|
|
}
|
|
|
|
if (!mFixture->osWindow->valid())
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Resize the window before creating the context so that the first make current
|
|
// sets the viewport and scissor box to the right size.
|
|
bool needSwap = false;
|
|
|
|
int osWindowWidth = mFixture->osWindow->getWidth();
|
|
int osWindowHeight = mFixture->osWindow->getHeight();
|
|
|
|
const bool isRotated = mCurrentParams->eglParameters.emulatedPrerotation == 90 ||
|
|
mCurrentParams->eglParameters.emulatedPrerotation == 270;
|
|
if (isRotated)
|
|
{
|
|
std::swap(osWindowWidth, osWindowHeight);
|
|
}
|
|
|
|
if (osWindowWidth != mWidth || osWindowHeight != mHeight)
|
|
{
|
|
int newWindowWidth = mWidth;
|
|
int newWindowHeight = mHeight;
|
|
if (isRotated)
|
|
{
|
|
std::swap(newWindowWidth, newWindowHeight);
|
|
}
|
|
|
|
if (!mFixture->osWindow->resize(newWindowWidth, newWindowHeight))
|
|
{
|
|
FAIL() << "Failed to resize ANGLE test window.";
|
|
}
|
|
needSwap = true;
|
|
}
|
|
// WGL tests are currently disabled.
|
|
if (mFixture->wglWindow)
|
|
{
|
|
FAIL() << "Unsupported driver.";
|
|
}
|
|
else
|
|
{
|
|
Library *driverLib = ANGLETestEnvironment::GetDriverLibrary(mCurrentParams->driver);
|
|
|
|
if (mForceNewDisplay || !mFixture->eglWindow->isDisplayInitialized())
|
|
{
|
|
mFixture->eglWindow->destroyGL();
|
|
if (!mFixture->eglWindow->initializeDisplay(mFixture->osWindow, driverLib,
|
|
mCurrentParams->driver,
|
|
mCurrentParams->eglParameters))
|
|
{
|
|
FAIL() << "EGL Display init failed.";
|
|
}
|
|
}
|
|
else if (mCurrentParams->eglParameters != mFixture->eglWindow->getPlatform())
|
|
{
|
|
FAIL() << "Internal parameter conflict error.";
|
|
}
|
|
|
|
if (!mFixture->eglWindow->initializeSurface(mFixture->osWindow, driverLib,
|
|
mFixture->configParams))
|
|
{
|
|
FAIL() << "egl surface init failed.";
|
|
}
|
|
|
|
if (!mDeferContextInit && !mFixture->eglWindow->initializeContext())
|
|
{
|
|
FAIL() << "GL Context init failed.";
|
|
}
|
|
}
|
|
|
|
if (needSwap)
|
|
{
|
|
// Swap the buffers so that the default framebuffer picks up the resize
|
|
// which will allow follow-up test code to assume the framebuffer covers
|
|
// the whole window.
|
|
swapBuffers();
|
|
}
|
|
|
|
// This Viewport command is not strictly necessary but we add it so that programs
|
|
// taking OpenGL traces can guess the size of the default framebuffer and show it
|
|
// in their UIs
|
|
glViewport(0, 0, mWidth, mHeight);
|
|
}
|
|
|
|
void ANGLETestBase::ANGLETestTearDown()
|
|
{
|
|
mTearDownCalled = true;
|
|
gPlatformContext.currentTest = nullptr;
|
|
|
|
if (IsWindows())
|
|
{
|
|
const testing::TestInfo *info = testing::UnitTest::GetInstance()->current_test_info();
|
|
WriteDebugMessage("Exiting %s.%s\n", info->test_case_name(), info->name());
|
|
}
|
|
|
|
if (mCurrentParams->noFixture || !mFixture->osWindow->valid())
|
|
{
|
|
return;
|
|
}
|
|
|
|
swapBuffers();
|
|
mFixture->osWindow->messageLoop();
|
|
|
|
if (mFixture->eglWindow)
|
|
{
|
|
checkD3D11SDKLayersMessages();
|
|
}
|
|
|
|
if (mFixture->reuseCounter++ >= kWindowReuseLimit || mForceNewDisplay)
|
|
{
|
|
mFixture->reuseCounter = 0;
|
|
getGLWindow()->destroyGL();
|
|
}
|
|
else
|
|
{
|
|
mFixture->eglWindow->destroyContext();
|
|
mFixture->eglWindow->destroySurface();
|
|
}
|
|
|
|
// Check for quit message
|
|
Event myEvent;
|
|
while (mFixture->osWindow->popEvent(&myEvent))
|
|
{
|
|
if (myEvent.Type == Event::EVENT_CLOSED)
|
|
{
|
|
exit(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ANGLETestBase::ReleaseFixtures()
|
|
{
|
|
for (auto it = gFixtures.begin(); it != gFixtures.end(); it++)
|
|
{
|
|
if (it->second.eglWindow)
|
|
{
|
|
it->second.eglWindow->destroyGL();
|
|
}
|
|
}
|
|
}
|
|
|
|
void ANGLETestBase::swapBuffers()
|
|
{
|
|
if (getGLWindow()->isGLInitialized())
|
|
{
|
|
getGLWindow()->swap();
|
|
|
|
if (mFixture->eglWindow)
|
|
{
|
|
EXPECT_EGL_SUCCESS();
|
|
}
|
|
}
|
|
}
|
|
|
|
void ANGLETestBase::setupQuadVertexBuffer(GLfloat positionAttribZ, GLfloat positionAttribXYScale)
|
|
{
|
|
if (mQuadVertexBuffer == 0)
|
|
{
|
|
glGenBuffers(1, &mQuadVertexBuffer);
|
|
}
|
|
|
|
auto quadVertices = GetQuadVertices();
|
|
for (Vector3 &vertex : quadVertices)
|
|
{
|
|
vertex.x() *= positionAttribXYScale;
|
|
vertex.y() *= positionAttribXYScale;
|
|
vertex.z() = positionAttribZ;
|
|
}
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mQuadVertexBuffer);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 6, quadVertices.data(), GL_STATIC_DRAW);
|
|
}
|
|
|
|
void ANGLETestBase::setupIndexedQuadVertexBuffer(GLfloat positionAttribZ,
|
|
GLfloat positionAttribXYScale)
|
|
{
|
|
if (mQuadVertexBuffer == 0)
|
|
{
|
|
glGenBuffers(1, &mQuadVertexBuffer);
|
|
}
|
|
|
|
auto quadVertices = kIndexedQuadVertices;
|
|
for (Vector3 &vertex : quadVertices)
|
|
{
|
|
vertex.x() *= positionAttribXYScale;
|
|
vertex.y() *= positionAttribXYScale;
|
|
vertex.z() = positionAttribZ;
|
|
}
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mQuadVertexBuffer);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 4, quadVertices.data(), GL_STATIC_DRAW);
|
|
}
|
|
|
|
void ANGLETestBase::setupIndexedQuadIndexBuffer()
|
|
{
|
|
if (mQuadIndexBuffer == 0)
|
|
{
|
|
glGenBuffers(1, &mQuadIndexBuffer);
|
|
}
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mQuadIndexBuffer);
|
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexedQuadIndices), kIndexedQuadIndices.data(),
|
|
GL_STATIC_DRAW);
|
|
}
|
|
|
|
// static
|
|
void ANGLETestBase::drawQuad(GLuint program,
|
|
const std::string &positionAttribName,
|
|
GLfloat positionAttribZ)
|
|
{
|
|
drawQuad(program, positionAttribName, positionAttribZ, 1.0f);
|
|
}
|
|
|
|
// static
|
|
void ANGLETestBase::drawQuad(GLuint program,
|
|
const std::string &positionAttribName,
|
|
GLfloat positionAttribZ,
|
|
GLfloat positionAttribXYScale)
|
|
{
|
|
drawQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale, false);
|
|
}
|
|
|
|
void ANGLETestBase::drawQuad(GLuint program,
|
|
const std::string &positionAttribName,
|
|
GLfloat positionAttribZ,
|
|
GLfloat positionAttribXYScale,
|
|
bool useVertexBuffer)
|
|
{
|
|
drawQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale, useVertexBuffer,
|
|
false, 0u);
|
|
}
|
|
|
|
void ANGLETestBase::drawQuadInstanced(GLuint program,
|
|
const std::string &positionAttribName,
|
|
GLfloat positionAttribZ,
|
|
GLfloat positionAttribXYScale,
|
|
bool useVertexBuffer,
|
|
GLuint numInstances)
|
|
{
|
|
drawQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale, useVertexBuffer,
|
|
true, numInstances);
|
|
}
|
|
|
|
void ANGLETestBase::drawQuad(GLuint program,
|
|
const std::string &positionAttribName,
|
|
GLfloat positionAttribZ,
|
|
GLfloat positionAttribXYScale,
|
|
bool useVertexBuffer,
|
|
bool useInstancedDrawCalls,
|
|
GLuint numInstances)
|
|
{
|
|
GLint previousProgram = 0;
|
|
glGetIntegerv(GL_CURRENT_PROGRAM, &previousProgram);
|
|
if (previousProgram != static_cast<GLint>(program))
|
|
{
|
|
glUseProgram(program);
|
|
}
|
|
|
|
GLint previousBuffer = 0;
|
|
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &previousBuffer);
|
|
|
|
GLint positionLocation = glGetAttribLocation(program, positionAttribName.c_str());
|
|
|
|
std::array<Vector3, 6> quadVertices = GetQuadVertices();
|
|
|
|
if (useVertexBuffer)
|
|
{
|
|
setupQuadVertexBuffer(positionAttribZ, positionAttribXYScale);
|
|
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
|
|
glBindBuffer(GL_ARRAY_BUFFER, previousBuffer);
|
|
}
|
|
else
|
|
{
|
|
for (Vector3 &vertex : quadVertices)
|
|
{
|
|
vertex.x() *= positionAttribXYScale;
|
|
vertex.y() *= positionAttribXYScale;
|
|
vertex.z() = positionAttribZ;
|
|
}
|
|
|
|
if (previousBuffer != 0)
|
|
{
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
}
|
|
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
|
|
if (previousBuffer != 0)
|
|
{
|
|
glBindBuffer(GL_ARRAY_BUFFER, previousBuffer);
|
|
}
|
|
}
|
|
glEnableVertexAttribArray(positionLocation);
|
|
|
|
if (useInstancedDrawCalls)
|
|
{
|
|
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, numInstances);
|
|
}
|
|
else
|
|
{
|
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
|
}
|
|
|
|
glDisableVertexAttribArray(positionLocation);
|
|
glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
|
|
|
|
if (previousProgram != static_cast<GLint>(program))
|
|
{
|
|
glUseProgram(previousProgram);
|
|
}
|
|
}
|
|
|
|
void ANGLETestBase::drawIndexedQuad(GLuint program,
|
|
const std::string &positionAttribName,
|
|
GLfloat positionAttribZ)
|
|
{
|
|
drawIndexedQuad(program, positionAttribName, positionAttribZ, 1.0f);
|
|
}
|
|
|
|
void ANGLETestBase::drawIndexedQuad(GLuint program,
|
|
const std::string &positionAttribName,
|
|
GLfloat positionAttribZ,
|
|
GLfloat positionAttribXYScale)
|
|
{
|
|
drawIndexedQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale, false);
|
|
}
|
|
|
|
void ANGLETestBase::drawIndexedQuad(GLuint program,
|
|
const std::string &positionAttribName,
|
|
GLfloat positionAttribZ,
|
|
GLfloat positionAttribXYScale,
|
|
bool useIndexBuffer)
|
|
{
|
|
drawIndexedQuad(program, positionAttribName, positionAttribZ, positionAttribXYScale,
|
|
useIndexBuffer, false);
|
|
}
|
|
|
|
void ANGLETestBase::drawIndexedQuad(GLuint program,
|
|
const std::string &positionAttribName,
|
|
GLfloat positionAttribZ,
|
|
GLfloat positionAttribXYScale,
|
|
bool useIndexBuffer,
|
|
bool restrictedRange)
|
|
{
|
|
GLint positionLocation = glGetAttribLocation(program, positionAttribName.c_str());
|
|
|
|
GLint activeProgram = 0;
|
|
glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram);
|
|
if (static_cast<GLuint>(activeProgram) != program)
|
|
{
|
|
glUseProgram(program);
|
|
}
|
|
|
|
GLuint prevCoordBinding = 0;
|
|
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, reinterpret_cast<GLint *>(&prevCoordBinding));
|
|
|
|
setupIndexedQuadVertexBuffer(positionAttribZ, positionAttribXYScale);
|
|
|
|
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
|
|
glEnableVertexAttribArray(positionLocation);
|
|
glBindBuffer(GL_ARRAY_BUFFER, prevCoordBinding);
|
|
|
|
GLuint prevIndexBinding = 0;
|
|
const GLvoid *indices;
|
|
if (useIndexBuffer)
|
|
{
|
|
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING,
|
|
reinterpret_cast<GLint *>(&prevIndexBinding));
|
|
|
|
setupIndexedQuadIndexBuffer();
|
|
indices = 0;
|
|
}
|
|
else
|
|
{
|
|
indices = kIndexedQuadIndices.data();
|
|
}
|
|
|
|
if (!restrictedRange)
|
|
{
|
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
|
|
}
|
|
else
|
|
{
|
|
glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, indices);
|
|
}
|
|
|
|
if (useIndexBuffer)
|
|
{
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prevIndexBinding);
|
|
}
|
|
|
|
glDisableVertexAttribArray(positionLocation);
|
|
glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
|
|
|
|
if (static_cast<GLuint>(activeProgram) != program)
|
|
{
|
|
glUseProgram(static_cast<GLuint>(activeProgram));
|
|
}
|
|
}
|
|
|
|
GLuint ANGLETestBase::get2DTexturedQuadProgram()
|
|
{
|
|
if (m2DTexturedQuadProgram)
|
|
{
|
|
return m2DTexturedQuadProgram;
|
|
}
|
|
|
|
constexpr char kVS[] =
|
|
"attribute vec2 position;\n"
|
|
"varying mediump vec2 texCoord;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" gl_Position = vec4(position, 0, 1);\n"
|
|
" texCoord = position * 0.5 + vec2(0.5);\n"
|
|
"}\n";
|
|
|
|
constexpr char kFS[] =
|
|
"varying mediump vec2 texCoord;\n"
|
|
"uniform sampler2D tex;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" gl_FragColor = texture2D(tex, texCoord);\n"
|
|
"}\n";
|
|
|
|
m2DTexturedQuadProgram = CompileProgram(kVS, kFS);
|
|
return m2DTexturedQuadProgram;
|
|
}
|
|
|
|
GLuint ANGLETestBase::get3DTexturedQuadProgram()
|
|
{
|
|
if (m3DTexturedQuadProgram)
|
|
{
|
|
return m3DTexturedQuadProgram;
|
|
}
|
|
|
|
constexpr char kVS[] = R"(#version 300 es
|
|
in vec2 position;
|
|
out vec2 texCoord;
|
|
void main()
|
|
{
|
|
gl_Position = vec4(position, 0, 1);
|
|
texCoord = position * 0.5 + vec2(0.5);
|
|
})";
|
|
|
|
constexpr char kFS[] = R"(#version 300 es
|
|
precision highp float;
|
|
|
|
in vec2 texCoord;
|
|
out vec4 my_FragColor;
|
|
|
|
uniform highp sampler3D tex;
|
|
uniform float u_layer;
|
|
|
|
void main()
|
|
{
|
|
my_FragColor = texture(tex, vec3(texCoord, u_layer));
|
|
})";
|
|
|
|
m3DTexturedQuadProgram = CompileProgram(kVS, kFS);
|
|
return m3DTexturedQuadProgram;
|
|
}
|
|
|
|
void ANGLETestBase::draw2DTexturedQuad(GLfloat positionAttribZ,
|
|
GLfloat positionAttribXYScale,
|
|
bool useVertexBuffer)
|
|
{
|
|
ASSERT_NE(0u, get2DTexturedQuadProgram());
|
|
drawQuad(get2DTexturedQuadProgram(), "position", positionAttribZ, positionAttribXYScale,
|
|
useVertexBuffer);
|
|
}
|
|
|
|
void ANGLETestBase::draw3DTexturedQuad(GLfloat positionAttribZ,
|
|
GLfloat positionAttribXYScale,
|
|
bool useVertexBuffer,
|
|
float layer)
|
|
{
|
|
GLuint program = get3DTexturedQuadProgram();
|
|
ASSERT_NE(0u, program);
|
|
GLint activeProgram = 0;
|
|
glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram);
|
|
if (static_cast<GLuint>(activeProgram) != program)
|
|
{
|
|
glUseProgram(program);
|
|
}
|
|
glUniform1f(glGetUniformLocation(program, "u_layer"), layer);
|
|
|
|
drawQuad(program, "position", positionAttribZ, positionAttribXYScale, useVertexBuffer);
|
|
|
|
if (static_cast<GLuint>(activeProgram) != program)
|
|
{
|
|
glUseProgram(static_cast<GLuint>(activeProgram));
|
|
}
|
|
}
|
|
|
|
bool ANGLETestBase::platformSupportsMultithreading() const
|
|
{
|
|
return (IsOpenGLES() && IsAndroid()) || IsVulkan();
|
|
}
|
|
|
|
void ANGLETestBase::checkD3D11SDKLayersMessages()
|
|
{
|
|
#if defined(ANGLE_PLATFORM_WINDOWS)
|
|
// On Windows D3D11, check ID3D11InfoQueue to see if any D3D11 SDK Layers messages
|
|
// were outputted by the test. We enable the Debug layers in Release tests as well.
|
|
if (mIgnoreD3D11SDKLayersWarnings ||
|
|
mFixture->eglWindow->getPlatform().renderer != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE ||
|
|
mFixture->eglWindow->getDisplay() == EGL_NO_DISPLAY)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const char *extensionString = static_cast<const char *>(
|
|
eglQueryString(mFixture->eglWindow->getDisplay(), EGL_EXTENSIONS));
|
|
if (!extensionString)
|
|
{
|
|
std::cout << "Error getting extension string from EGL Window." << std::endl;
|
|
return;
|
|
}
|
|
|
|
if (!strstr(extensionString, "EGL_EXT_device_query"))
|
|
{
|
|
return;
|
|
}
|
|
|
|
EGLAttrib device = 0;
|
|
EGLAttrib angleDevice = 0;
|
|
|
|
ASSERT_EGL_TRUE(
|
|
eglQueryDisplayAttribEXT(mFixture->eglWindow->getDisplay(), EGL_DEVICE_EXT, &angleDevice));
|
|
ASSERT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice),
|
|
EGL_D3D11_DEVICE_ANGLE, &device));
|
|
ID3D11Device *d3d11Device = reinterpret_cast<ID3D11Device *>(device);
|
|
|
|
ID3D11InfoQueue *infoQueue = nullptr;
|
|
HRESULT hr =
|
|
d3d11Device->QueryInterface(__uuidof(infoQueue), reinterpret_cast<void **>(&infoQueue));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
UINT64 numStoredD3DDebugMessages =
|
|
infoQueue->GetNumStoredMessagesAllowedByRetrievalFilter();
|
|
|
|
if (numStoredD3DDebugMessages > 0)
|
|
{
|
|
for (UINT64 i = 0; i < numStoredD3DDebugMessages; i++)
|
|
{
|
|
SIZE_T messageLength = 0;
|
|
hr = infoQueue->GetMessage(i, nullptr, &messageLength);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
D3D11_MESSAGE *pMessage =
|
|
reinterpret_cast<D3D11_MESSAGE *>(malloc(messageLength));
|
|
infoQueue->GetMessage(i, pMessage, &messageLength);
|
|
|
|
std::cout << "Message " << i << ":"
|
|
<< " " << pMessage->pDescription << "\n";
|
|
free(pMessage);
|
|
}
|
|
}
|
|
// Clear the queue, so that previous failures are not reported
|
|
// for subsequent, otherwise passing, tests
|
|
infoQueue->ClearStoredMessages();
|
|
|
|
FAIL() << numStoredD3DDebugMessages
|
|
<< " D3D11 SDK Layers message(s) detected! Test Failed.\n";
|
|
}
|
|
}
|
|
|
|
SafeRelease(infoQueue);
|
|
#endif // defined(ANGLE_PLATFORM_WINDOWS)
|
|
}
|
|
|
|
void ANGLETestBase::setWindowWidth(int width)
|
|
{
|
|
mWidth = width;
|
|
}
|
|
|
|
void ANGLETestBase::setWindowHeight(int height)
|
|
{
|
|
mHeight = height;
|
|
}
|
|
|
|
GLWindowBase *ANGLETestBase::getGLWindow() const
|
|
{
|
|
// WGL tests are currently disabled.
|
|
assert(!mFixture->wglWindow);
|
|
return mFixture->eglWindow;
|
|
}
|
|
|
|
void ANGLETestBase::setConfigRedBits(int bits)
|
|
{
|
|
mFixture->configParams.redBits = bits;
|
|
}
|
|
|
|
void ANGLETestBase::setConfigGreenBits(int bits)
|
|
{
|
|
mFixture->configParams.greenBits = bits;
|
|
}
|
|
|
|
void ANGLETestBase::setConfigBlueBits(int bits)
|
|
{
|
|
mFixture->configParams.blueBits = bits;
|
|
}
|
|
|
|
void ANGLETestBase::setConfigAlphaBits(int bits)
|
|
{
|
|
mFixture->configParams.alphaBits = bits;
|
|
}
|
|
|
|
void ANGLETestBase::setConfigDepthBits(int bits)
|
|
{
|
|
mFixture->configParams.depthBits = bits;
|
|
}
|
|
|
|
void ANGLETestBase::setConfigStencilBits(int bits)
|
|
{
|
|
mFixture->configParams.stencilBits = bits;
|
|
}
|
|
|
|
void ANGLETestBase::setConfigComponentType(EGLenum componentType)
|
|
{
|
|
mFixture->configParams.componentType = componentType;
|
|
}
|
|
|
|
void ANGLETestBase::setMultisampleEnabled(bool enabled)
|
|
{
|
|
mFixture->configParams.multisample = enabled;
|
|
}
|
|
|
|
void ANGLETestBase::setSamples(EGLint samples)
|
|
{
|
|
mFixture->configParams.samples = samples;
|
|
}
|
|
|
|
void ANGLETestBase::setDebugEnabled(bool enabled)
|
|
{
|
|
mFixture->configParams.debug = enabled;
|
|
}
|
|
|
|
void ANGLETestBase::setNoErrorEnabled(bool enabled)
|
|
{
|
|
mFixture->configParams.noError = enabled;
|
|
}
|
|
|
|
void ANGLETestBase::setWebGLCompatibilityEnabled(bool webglCompatibility)
|
|
{
|
|
mFixture->configParams.webGLCompatibility = webglCompatibility;
|
|
}
|
|
|
|
void ANGLETestBase::setExtensionsEnabled(bool extensionsEnabled)
|
|
{
|
|
mFixture->configParams.extensionsEnabled = extensionsEnabled;
|
|
}
|
|
|
|
void ANGLETestBase::setRobustAccess(bool enabled)
|
|
{
|
|
mFixture->configParams.robustAccess = enabled;
|
|
}
|
|
|
|
void ANGLETestBase::setBindGeneratesResource(bool bindGeneratesResource)
|
|
{
|
|
mFixture->configParams.bindGeneratesResource = bindGeneratesResource;
|
|
}
|
|
|
|
void ANGLETestBase::setClientArraysEnabled(bool enabled)
|
|
{
|
|
mFixture->configParams.clientArraysEnabled = enabled;
|
|
}
|
|
|
|
void ANGLETestBase::setRobustResourceInit(bool enabled)
|
|
{
|
|
mFixture->configParams.robustResourceInit = enabled;
|
|
}
|
|
|
|
void ANGLETestBase::setContextProgramCacheEnabled(bool enabled)
|
|
{
|
|
mFixture->configParams.contextProgramCacheEnabled = enabled;
|
|
}
|
|
|
|
void ANGLETestBase::setContextResetStrategy(EGLenum resetStrategy)
|
|
{
|
|
mFixture->configParams.resetStrategy = resetStrategy;
|
|
}
|
|
|
|
void ANGLETestBase::forceNewDisplay()
|
|
{
|
|
mForceNewDisplay = true;
|
|
}
|
|
|
|
void ANGLETestBase::setDeferContextInit(bool enabled)
|
|
{
|
|
mDeferContextInit = enabled;
|
|
}
|
|
|
|
int ANGLETestBase::getClientMajorVersion() const
|
|
{
|
|
return getGLWindow()->getClientMajorVersion();
|
|
}
|
|
|
|
int ANGLETestBase::getClientMinorVersion() const
|
|
{
|
|
return getGLWindow()->getClientMinorVersion();
|
|
}
|
|
|
|
EGLWindow *ANGLETestBase::getEGLWindow() const
|
|
{
|
|
return mFixture->eglWindow;
|
|
}
|
|
|
|
int ANGLETestBase::getWindowWidth() const
|
|
{
|
|
return mWidth;
|
|
}
|
|
|
|
int ANGLETestBase::getWindowHeight() const
|
|
{
|
|
return mHeight;
|
|
}
|
|
|
|
bool ANGLETestBase::isEmulatedPrerotation() const
|
|
{
|
|
return mCurrentParams->eglParameters.emulatedPrerotation != 0;
|
|
}
|
|
|
|
void ANGLETestBase::setWindowVisible(OSWindow *osWindow, bool isVisible)
|
|
{
|
|
// SwiftShader windows are not required to be visible for test correctness,
|
|
// moreover, making a SwiftShader window visible flaky hangs on Xvfb, so we keep them hidden.
|
|
if (isSwiftshader())
|
|
{
|
|
return;
|
|
}
|
|
osWindow->setVisible(isVisible);
|
|
}
|
|
|
|
ANGLETestBase::TestFixture::TestFixture() = default;
|
|
ANGLETestBase::TestFixture::~TestFixture() = default;
|
|
|
|
EGLint ANGLETestBase::getPlatformRenderer() const
|
|
{
|
|
assert(mFixture->eglWindow);
|
|
return mFixture->eglWindow->getPlatform().renderer;
|
|
}
|
|
|
|
void ANGLETestBase::ignoreD3D11SDKLayersWarnings()
|
|
{
|
|
// Some tests may need to disable the D3D11 SDK Layers Warnings checks
|
|
mIgnoreD3D11SDKLayersWarnings = true;
|
|
}
|
|
|
|
void ANGLETestBase::treatPlatformWarningsAsErrors()
|
|
{
|
|
#if defined(ANGLE_PLATFORM_WINDOWS)
|
|
// Only do warnings-as-errors on 8 and above. We may fall back to the old
|
|
// compiler DLL on Windows 7.
|
|
gPlatformContext.warningsAsErrors = IsWindows8OrGreater();
|
|
#endif // defined(ANGLE_PLATFORM_WINDOWS)
|
|
}
|
|
|
|
ANGLETestBase::ScopedIgnorePlatformMessages::ScopedIgnorePlatformMessages()
|
|
{
|
|
gPlatformContext.ignoreMessages = true;
|
|
}
|
|
|
|
ANGLETestBase::ScopedIgnorePlatformMessages::~ScopedIgnorePlatformMessages()
|
|
{
|
|
gPlatformContext.ignoreMessages = false;
|
|
}
|
|
|
|
OSWindow *ANGLETestBase::mOSWindowSingleton = nullptr;
|
|
std::map<angle::PlatformParameters, ANGLETestBase::TestFixture> ANGLETestBase::gFixtures;
|
|
Optional<EGLint> ANGLETestBase::mLastRendererType;
|
|
Optional<angle::GLESDriverType> ANGLETestBase::mLastLoadedDriver;
|
|
|
|
std::unique_ptr<Library> ANGLETestEnvironment::gAngleEGLLibrary;
|
|
std::unique_ptr<Library> ANGLETestEnvironment::gSystemEGLLibrary;
|
|
std::unique_ptr<Library> ANGLETestEnvironment::gSystemWGLLibrary;
|
|
|
|
void ANGLETestEnvironment::SetUp() {}
|
|
|
|
void ANGLETestEnvironment::TearDown()
|
|
{
|
|
ANGLETestBase::ReleaseFixtures();
|
|
}
|
|
|
|
// static
|
|
Library *ANGLETestEnvironment::GetDriverLibrary(angle::GLESDriverType driver)
|
|
{
|
|
switch (driver)
|
|
{
|
|
case angle::GLESDriverType::AngleEGL:
|
|
return GetAngleEGLLibrary();
|
|
case angle::GLESDriverType::SystemEGL:
|
|
return GetSystemEGLLibrary();
|
|
case angle::GLESDriverType::SystemWGL:
|
|
return GetSystemWGLLibrary();
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
// static
|
|
Library *ANGLETestEnvironment::GetAngleEGLLibrary()
|
|
{
|
|
#if defined(ANGLE_USE_UTIL_LOADER)
|
|
if (!gAngleEGLLibrary)
|
|
{
|
|
gAngleEGLLibrary.reset(
|
|
OpenSharedLibrary(ANGLE_EGL_LIBRARY_NAME, SearchType::ApplicationDir));
|
|
}
|
|
#endif // defined(ANGLE_USE_UTIL_LOADER)
|
|
return gAngleEGLLibrary.get();
|
|
}
|
|
|
|
// static
|
|
Library *ANGLETestEnvironment::GetSystemEGLLibrary()
|
|
{
|
|
#if defined(ANGLE_USE_UTIL_LOADER)
|
|
if (!gSystemEGLLibrary)
|
|
{
|
|
gSystemEGLLibrary.reset(
|
|
OpenSharedLibraryWithExtension(GetNativeEGLLibraryNameWithExtension()));
|
|
}
|
|
#endif // defined(ANGLE_USE_UTIL_LOADER)
|
|
return gSystemEGLLibrary.get();
|
|
}
|
|
|
|
// static
|
|
Library *ANGLETestEnvironment::GetSystemWGLLibrary()
|
|
{
|
|
#if defined(ANGLE_USE_UTIL_LOADER) && defined(ANGLE_PLATFORM_WINDOWS)
|
|
if (!gSystemWGLLibrary)
|
|
{
|
|
gSystemWGLLibrary.reset(OpenSharedLibrary("opengl32", SearchType::SystemDir));
|
|
}
|
|
#endif // defined(ANGLE_USE_UTIL_LOADER) && defined(ANGLE_PLATFORM_WINDOWS)
|
|
return gSystemWGLLibrary.get();
|
|
}
|
|
|
|
void ANGLEProcessTestArgs(int *argc, char *argv[])
|
|
{
|
|
testing::AddGlobalTestEnvironment(new ANGLETestEnvironment());
|
|
|
|
for (int argIndex = 1; argIndex < *argc; argIndex++)
|
|
{
|
|
if (strncmp(argv[argIndex], kUseConfig, strlen(kUseConfig)) == 0)
|
|
{
|
|
SetSelectedConfig(argv[argIndex] + strlen(kUseConfig));
|
|
}
|
|
else if (strncmp(argv[argIndex], kReuseDisplays, strlen(kReuseDisplays)) == 0)
|
|
{
|
|
gReuseDisplays = true;
|
|
}
|
|
else if (strncmp(argv[argIndex], kBatchId, strlen(kBatchId)) == 0)
|
|
{
|
|
// Enable display reuse when running under --bot-mode.
|
|
gReuseDisplays = true;
|
|
}
|
|
else if (strncmp(argv[argIndex], kEnableANGLEPerTestCaptureLabel,
|
|
strlen(kEnableANGLEPerTestCaptureLabel)) == 0)
|
|
{
|
|
gEnableANGLEPerTestCaptureLabel = true;
|
|
}
|
|
}
|
|
}
|