// // Copyright 2013 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. // #include "SampleApplication.h" #include "common/debug.h" #include "util/EGLWindow.h" #include "util/gles_loader_autogen.h" #include "util/random_utils.h" #include "util/shader_utils.h" #include "util/test_utils.h" #include "util/util_gl.h" #include #include #include #if defined(ANGLE_PLATFORM_WINDOWS) # include "util/windows/WGLWindow.h" #endif // defined(ANGLE_PLATFORM_WINDOWS) namespace { const char *kUseAngleArg = "--use-angle="; const char *kUseGlArg = "--use-gl=native"; using DisplayTypeInfo = std::pair; const DisplayTypeInfo kDisplayTypes[] = { {"d3d9", EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE}, {"d3d11", EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE}, {"gl", EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE}, {"gles", EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE}, {"metal", EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE}, {"null", EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE}, {"swiftshader", EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE}, {"vulkan", EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE}, }; EGLint GetDisplayTypeFromArg(const char *displayTypeArg) { for (const auto &displayTypeInfo : kDisplayTypes) { if (strcmp(displayTypeInfo.first, displayTypeArg) == 0) { std::cout << "Using ANGLE back-end API: " << displayTypeInfo.first << std::endl; return displayTypeInfo.second; } } std::cout << "Unknown ANGLE back-end API: " << displayTypeArg << std::endl; return EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE; } EGLint GetDeviceTypeFromArg(const char *displayTypeArg) { if (strcmp(displayTypeArg, "swiftshader") == 0) { return EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE; } else { return EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE; } } ANGLE_MAYBE_UNUSED bool IsGLExtensionEnabled(const std::string &extName) { return angle::CheckExtensionExists(reinterpret_cast(glGetString(GL_EXTENSIONS)), extName); } } // anonymous namespace SampleApplication::SampleApplication(std::string name, int argc, char **argv, EGLint glesMajorVersion, EGLint glesMinorVersion, uint32_t width, uint32_t height) : mName(std::move(name)), mWidth(width), mHeight(height), mRunning(false), mFrameCount(0), mGLWindow(nullptr), mEGLWindow(nullptr), mOSWindow(nullptr), mDriverType(angle::GLESDriverType::AngleEGL) { mPlatformParams.renderer = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE; bool useNativeGL = false; for (int argIndex = 1; argIndex < argc; argIndex++) { if (strncmp(argv[argIndex], kUseAngleArg, strlen(kUseAngleArg)) == 0) { const char *arg = argv[argIndex] + strlen(kUseAngleArg); mPlatformParams.renderer = GetDisplayTypeFromArg(arg); mPlatformParams.deviceType = GetDeviceTypeFromArg(arg); } if (strncmp(argv[argIndex], kUseGlArg, strlen(kUseGlArg)) == 0) { useNativeGL = true; } } mOSWindow = OSWindow::New(); // Load EGL library so we can initialize the display. if (useNativeGL) { #if defined(ANGLE_PLATFORM_WINDOWS) mGLWindow = WGLWindow::New(glesMajorVersion, glesMinorVersion); mEntryPointsLib.reset(angle::OpenSharedLibrary("opengl32", angle::SearchType::SystemDir)); mDriverType = angle::GLESDriverType::SystemWGL; #else mGLWindow = EGLWindow::New(glesMajorVersion, glesMinorVersion); mEntryPointsLib.reset(angle::OpenSharedLibraryWithExtension( angle::GetNativeEGLLibraryNameWithExtension(), angle::SearchType::SystemDir)); mDriverType = angle::GLESDriverType::SystemEGL; #endif // defined(ANGLE_PLATFORM_WINDOWS) } else { mGLWindow = mEGLWindow = EGLWindow::New(glesMajorVersion, glesMinorVersion); mEntryPointsLib.reset( angle::OpenSharedLibrary(ANGLE_EGL_LIBRARY_NAME, angle::SearchType::ModuleDir)); } } SampleApplication::~SampleApplication() { GLWindowBase::Delete(&mGLWindow); OSWindow::Delete(&mOSWindow); } bool SampleApplication::initialize() { return true; } void SampleApplication::destroy() {} void SampleApplication::step(float dt, double totalTime) {} void SampleApplication::draw() {} void SampleApplication::swap() { mGLWindow->swap(); } OSWindow *SampleApplication::getWindow() const { return mOSWindow; } EGLConfig SampleApplication::getConfig() const { ASSERT(mEGLWindow); return mEGLWindow->getConfig(); } EGLDisplay SampleApplication::getDisplay() const { ASSERT(mEGLWindow); return mEGLWindow->getDisplay(); } EGLSurface SampleApplication::getSurface() const { ASSERT(mEGLWindow); return mEGLWindow->getSurface(); } EGLContext SampleApplication::getContext() const { ASSERT(mEGLWindow); return mEGLWindow->getContext(); } int SampleApplication::run() { if (!mOSWindow->initialize(mName, mWidth, mHeight)) { return -1; } mOSWindow->setVisible(true); ConfigParameters configParams; configParams.redBits = 8; configParams.greenBits = 8; configParams.blueBits = 8; configParams.alphaBits = 8; configParams.depthBits = 24; configParams.stencilBits = 8; if (!mGLWindow->initializeGL(mOSWindow, mEntryPointsLib.get(), mDriverType, mPlatformParams, configParams)) { return -1; } // Disable vsync if (!mGLWindow->setSwapInterval(0)) { return -1; } mRunning = true; int result = 0; #if defined(ANGLE_ENABLE_ASSERTS) if (IsGLExtensionEnabled("GL_KHR_debug")) { EnableDebugCallback(nullptr, nullptr); } #endif if (!initialize()) { mRunning = false; result = -1; } mTimer.start(); double prevTime = 0.0; while (mRunning) { double elapsedTime = mTimer.getElapsedTime(); double deltaTime = elapsedTime - prevTime; step(static_cast(deltaTime), elapsedTime); // Clear events that the application did not process from this frame Event event; while (popEvent(&event)) { // If the application did not catch a close event, close now switch (event.Type) { case Event::EVENT_CLOSED: exit(); break; case Event::EVENT_KEY_RELEASED: onKeyUp(event.Key); break; case Event::EVENT_KEY_PRESSED: onKeyDown(event.Key); break; default: break; } } if (!mRunning) { break; } draw(); swap(); mOSWindow->messageLoop(); prevTime = elapsedTime; mFrameCount++; if (mFrameCount % 100 == 0) { printf("Rate: %0.2lf frames / second\n", static_cast(mFrameCount) / mTimer.getElapsedTime()); } } destroy(); mGLWindow->destroyGL(); mOSWindow->destroy(); return result; } void SampleApplication::exit() { mRunning = false; } bool SampleApplication::popEvent(Event *event) { return mOSWindow->popEvent(event); } void SampleApplication::onKeyUp(const Event::KeyEvent &keyEvent) { // Default no-op. } void SampleApplication::onKeyDown(const Event::KeyEvent &keyEvent) { // Default no-op. }