From b876c3553bd6c7fe040ec8ece4aa34268bb407b0 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Sun, 19 Feb 2017 22:17:00 +0100 Subject: [PATCH] Feature/luaextensions (#232) * Add systemcapabilities bindings that make the functions of GeneralSystemCapabilitiesComponent and OpenGLSystemCapabilitiesComponent available in Lua scripts * Windows compile fix * Return OpenGL extensions as array in Lua --- include/openspace/scripting/scriptengine.h | 6 +- .../scripting/systemcapabilitiesbinding.h | 39 ++ src/CMakeLists.txt | 2 + src/documentation/core_registration.cpp | 4 + src/scripting/scriptengine.cpp | 49 ++- src/scripting/systemcapabilitiesbinding.cpp | 347 ++++++++++++++++++ 6 files changed, 419 insertions(+), 28 deletions(-) create mode 100644 include/openspace/scripting/systemcapabilitiesbinding.h create mode 100644 src/scripting/systemcapabilitiesbinding.cpp diff --git a/include/openspace/scripting/scriptengine.h b/include/openspace/scripting/scriptengine.h index 5dad097168..cc272e577f 100644 --- a/include/openspace/scripting/scriptengine.h +++ b/include/openspace/scripting/scriptengine.h @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -93,8 +94,9 @@ public: //bool shouldScriptBeSent(const std::string &library, const std::string &function); //void cacheScript(const std::string &library, const std::string &function, const std::string &script); + static std::string OpenSpaceLibraryName; + private: - bool registerLuaLibrary(lua_State* state, const LuaLibrary& library); void addLibraryFunctions(lua_State* state, const LuaLibrary& library, bool replace); @@ -103,7 +105,7 @@ private: void addBaseLibrary(); void remapPrintFunction(); - lua_State* _state = nullptr; + ghoul::lua::LuaState _state; std::set _registeredLibraries; //sync variables diff --git a/include/openspace/scripting/systemcapabilitiesbinding.h b/include/openspace/scripting/systemcapabilitiesbinding.h new file mode 100644 index 0000000000..c470140a86 --- /dev/null +++ b/include/openspace/scripting/systemcapabilitiesbinding.h @@ -0,0 +1,39 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_CORE___SYSTEMCAPABLITIESBINDING___H__ +#define __OPENSPACE_CORE___SYSTEMCAPABLITIESBINDING___H__ + +#include + +namespace openspace { +namespace scripting { + +LuaLibrary generalSystemCapabilities(); +LuaLibrary openglSystemCapabilities(); + +} // namespace scripting +} // namespace openspace + +#endif // __OPENSPACE_CORE___SYSTEMCAPABLITIESBINDING___H__ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6522114623..9727ee0ca3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -135,6 +135,7 @@ set(OPENSPACE_SOURCE ${OPENSPACE_BASE_DIR}/src/scripting/scriptengine_lua.inl ${OPENSPACE_BASE_DIR}/src/scripting/scriptscheduler.cpp ${OPENSPACE_BASE_DIR}/src/scripting/scriptscheduler_lua.inl + ${OPENSPACE_BASE_DIR}/src/scripting/systemcapabilitiesbinding.cpp ${OPENSPACE_BASE_DIR}/src/util/blockplaneintersectiongeometry.cpp ${OPENSPACE_BASE_DIR}/src/util/boxgeometry.cpp ${OPENSPACE_BASE_DIR}/src/util/camera.cpp @@ -275,6 +276,7 @@ set(OPENSPACE_HEADER ${OPENSPACE_BASE_DIR}/include/openspace/scripting/script_helper.h ${OPENSPACE_BASE_DIR}/include/openspace/scripting/scriptengine.h ${OPENSPACE_BASE_DIR}/include/openspace/scripting/scriptscheduler.h + ${OPENSPACE_BASE_DIR}/include/openspace/scripting/systemcapabilitiesbinding.h ${OPENSPACE_BASE_DIR}/include/openspace/util/blockplaneintersectiongeometry.h ${OPENSPACE_BASE_DIR}/include/openspace/util/boxgeometry.h ${OPENSPACE_BASE_DIR}/include/openspace/util/camera.h diff --git a/src/documentation/core_registration.cpp b/src/documentation/core_registration.cpp index badcb5586f..5d4ff2436f 100644 --- a/src/documentation/core_registration.cpp +++ b/src/documentation/core_registration.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,9 @@ void registerCoreClasses(scripting::ScriptEngine& engine) { engine.addLibrary(scripting::ScriptScheduler::luaLibrary()); engine.addLibrary(WindowWrapper::luaLibrary()); engine.addLibrary(MissionManager::luaLibrary()); + + engine.addLibrary(scripting::generalSystemCapabilities()); + engine.addLibrary(scripting::openglSystemCapabilities()); } } // namespace openspace diff --git a/src/scripting/scriptengine.cpp b/src/scripting/scriptengine.cpp index 64e559ab9a..72e9536eeb 100644 --- a/src/scripting/scriptengine.cpp +++ b/src/scripting/scriptengine.cpp @@ -41,12 +41,12 @@ #include "scriptengine_lua.inl" namespace { - const std::string MainTemplateFilename = "${OPENSPACE_DATA}/web/luascripting/main.hbs"; - const std::string ScriptingTemplateFilename = "${OPENSPACE_DATA}/web/luascripting/scripting.hbs"; - const std::string HandlebarsFilename = "${OPENSPACE_DATA}/web/common/handlebars-v4.0.5.js"; - const std::string JsFilename = "${OPENSPACE_DATA}/web/luascripting/script.js"; - const std::string BootstrapFilename = "${OPENSPACE_DATA}/web/common/bootstrap.min.css"; - const std::string CssFilename = "${OPENSPACE_DATA}/web/common/style.css"; + const char* MainTemplateFilename = "${OPENSPACE_DATA}/web/luascripting/main.hbs"; + const char* ScriptingTemplateFilename = "${OPENSPACE_DATA}/web/luascripting/scripting.hbs"; + const char* HandlebarsFilename = "${OPENSPACE_DATA}/web/common/handlebars-v4.0.5.js"; + const char* JsFilename = "${OPENSPACE_DATA}/web/luascripting/script.js"; + const char* BootstrapFilename = "${OPENSPACE_DATA}/web/common/bootstrap.min.css"; + const char* CssFilename = "${OPENSPACE_DATA}/web/common/style.css"; } namespace openspace { @@ -56,40 +56,35 @@ namespace scripting { namespace { const std::string _loggerCat = "ScriptEngine"; - const std::string _openspaceLibraryName = "openspace"; - const std::string _luaGlobalNamespace = "_G"; - const std::string _printFunctionName = "print"; + const char* LuaGlobalNamespace = "_G"; + const char* PrintFunctionName = "print"; //const lua_CFunction _printFunctionReplacement = luascriptfunctions::printInfo; - const int _setTableOffset = -3; // -1 (top) -1 (first argument) -1 (second argument) + const int TableOffset = -3; // -1 (top) -1 (first argument) -1 (second argument) } +std::string ScriptEngine::OpenSpaceLibraryName = "openspace"; + void ScriptEngine::initialize() { LDEBUG("Adding base library"); addBaseLibrary(); - LDEBUG("Creating new Lua state"); - _state = ghoul::lua::createNewLuaState(); LDEBUG("Initializing Lua state"); initializeLuaState(_state); LDEBUG("Remapping Print functions"); remapPrintFunction(); } -void ScriptEngine::deinitialize() { - if (_state) { - lua_close(_state); - _state = nullptr; - } -} +void ScriptEngine::deinitialize() {} void ScriptEngine::initializeLuaState(lua_State* state) { LDEBUG("Create openspace base library"); lua_newtable(state); - lua_setglobal(state, _openspaceLibraryName.c_str()); + lua_setglobal(state, OpenSpaceLibraryName.c_str()); LDEBUG("Add OpenSpace modules"); - for (const LuaLibrary& lib : _registeredLibraries) + for (const LuaLibrary& lib : _registeredLibraries) { registerLuaLibrary(state, lib); + } } void ScriptEngine::addLibrary(LuaLibrary library) { @@ -294,7 +289,7 @@ bool ScriptEngine::parseLibraryAndFunctionNames(std::string &library, std::strin */ bool ScriptEngine::isLibraryNameAllowed(lua_State* state, const std::string& name) { bool result = false; - lua_getglobal(state, _openspaceLibraryName.c_str()); + lua_getglobal(state, OpenSpaceLibraryName.c_str()); const bool hasOpenSpaceLibrary = lua_istable(state, -1); if (!hasOpenSpaceLibrary) { LFATAL("OpenSpace library was not created in initialize method"); @@ -360,7 +355,7 @@ void ScriptEngine::addLibraryFunctions(lua_State* state, const LuaLibrary& libra //ghoul::lua::logStack(_state); lua_pushcfunction(state, p.function); //ghoul::lua::logStack(_state); - lua_settable(state, _setTableOffset); + lua_settable(state, TableOffset); //ghoul::lua::logStack(_state); } } @@ -443,14 +438,15 @@ void ScriptEngine::remapPrintFunction() { } bool ScriptEngine::registerLuaLibrary(lua_State* state, const LuaLibrary& library) { - assert(state); + ghoul_assert(state, "State must not be nullptr"); + if (library.functions.empty()) { LERROR("Lua library '" << library.name << "' does not have any functions"); return false; } //ghoul::lua::logStack(_state); - lua_getglobal(state, _openspaceLibraryName.c_str()); + lua_getglobal(state, OpenSpaceLibraryName.c_str()); //ghoul::lua::logStack(_state); if (library.name.empty()) { //ghoul::lua::logStack(_state); @@ -461,8 +457,9 @@ bool ScriptEngine::registerLuaLibrary(lua_State* state, const LuaLibrary& librar } else { const bool allowed = isLibraryNameAllowed(state, library.name); - if (!allowed) + if (!allowed) { return false; + } //ghoul::lua::logStack(_state); @@ -471,7 +468,7 @@ bool ScriptEngine::registerLuaLibrary(lua_State* state, const LuaLibrary& librar lua_newtable(state); //ghoul::lua::logStack(_state); addLibraryFunctions(state, library, false); - lua_settable(state, _setTableOffset); + lua_settable(state, TableOffset); //ghoul::lua::logStack(_state); //_registeredLibraries.insert(library); diff --git a/src/scripting/systemcapabilitiesbinding.cpp b/src/scripting/systemcapabilitiesbinding.cpp new file mode 100644 index 0000000000..1c8bdb3595 --- /dev/null +++ b/src/scripting/systemcapabilitiesbinding.cpp @@ -0,0 +1,347 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +using namespace ghoul::lua; +using namespace ghoul::systemcapabilities; + +namespace luascripting { +namespace general { + +int operatingSystem(lua_State* L) { + lua_pushstring(L, CpuCap.operatingSystemString().c_str()); + return 1; +} + +int fullOperatingSystem(lua_State* L) { + lua_pushstring(L, CpuCap.fullOperatingSystem().c_str()); + return 1; +} + +int installedMainMemory(lua_State* L) { + lua_pushnumber(L, CpuCap.installedMainMemory()); + return 1; +} + +int cores(lua_State* L) { + lua_pushnumber(L, CpuCap.cores()); + return 1; +} + +int cacheLineSize(lua_State* L) { + lua_pushnumber(L, CpuCap.cacheLineSize()); + return 1; +} + +int L2Associativity(lua_State* L) { + lua_pushnumber(L, CpuCap.L2Associativity()); + return 1; +} + +int cacheSize(lua_State* L) { + lua_pushnumber(L, CpuCap.cacheSize()); + return 1; +} + +int extensions(lua_State* L) { + lua_pushstring(L, CpuCap.extensions().c_str()); + return 1; + +} + +} // namespace general + +namespace opengl { + +int hasOpenGLVersion(lua_State* L) { + int nArguments = lua_gettop(L); + SCRIPT_CHECK_ARGUMENTS("hasVersion", L, 1, nArguments); + + std::vector v = ghoul::tokenizeString(luaL_checkstring(L, -1)); + if (v.size() != 2 && v.size() != 3) { + LERRORC("hasVersion", ghoul::lua::errorLocation(L) << "Malformed version string"); + return 0; + } + + for (const std::string& i : v) { + for (char c : i) { + if (!std::isdigit(c)) { + LERRORC( + "hasVersion", + ghoul::lua::errorLocation(L) << "Malformed version string" + ); + return 0; + + } + } + } + + int major = std::stoi(v[0]); + int minor = std::stoi(v[1]); + int release = v.size() == 3 ? std::stoi(v[2]) : 0; + OpenGLCapabilitiesComponent::Version version = { major, minor, release }; + + bool supported = OpenGLCap.openGLVersion() >= version; + + lua_pushboolean(L, supported); + + return 1; +} + +int openGLVersion(lua_State* L) { + lua_pushstring(L, OpenGLCap.openGLVersion().toString().c_str()); + return 1; +} + +int glslCompiler(lua_State* L) { + lua_pushstring(L, OpenGLCap.glslCompiler().c_str()); + return 1; +} + +int gpuVendor(lua_State* L) { + lua_pushstring(L, OpenGLCap.gpuVendorString().c_str()); + return 1; +} + +int extensions(lua_State* L) { + const std::vector& extensions = OpenGLCap.extensions(); + + lua_newtable(L); + + for (int i = 1; i <= extensions.size(); ++i) { + lua_pushstring(L, extensions[i].c_str()); + lua_rawseti(L, -2, i); + } + return 1; +} + +int isExtensionSupported(lua_State* L) { + int nArguments = lua_gettop(L); + SCRIPT_CHECK_ARGUMENTS("hasVersion", L, 1, nArguments); + + std::string extension = luaL_checkstring(L, -1); + + lua_pushboolean(L, OpenGLCap.isExtensionSupported(extension)); + return 1; +} + +int maxTextureUnits(lua_State* L) { + lua_pushnumber(L, OpenGLCap.maxTextureUnits()); + return 1; +} + +int max2DTextureSize(lua_State* L) { + lua_pushnumber(L, OpenGLCap.max2DTextureSize()); + return 1; +} + +int max3DTextureSize(lua_State* L) { + lua_pushnumber(L, OpenGLCap.max3DTextureSize()); + return 1; +} + +int maxAtomicCounterBufferBindings(lua_State* L) { + lua_pushnumber(L, OpenGLCap.maxAtomicCounterBufferBindings()); + return 1; +} + +int maxShaderStorageBufferBindings(lua_State* L) { + lua_pushnumber(L, OpenGLCap.maxShaderStorageBufferBindings()); + return 1; +} + +int maxUniformBufferBindings(lua_State* L) { + lua_pushnumber(L, OpenGLCap.maxUniformBufferBindings()); + return 1; +} + + +} // namespace opengl +} // namespace luascripting + +namespace openspace { +namespace scripting { + +LuaLibrary generalSystemCapabilities() { + return { + "systemCapabilities", + { + { + "operatingSystem", + &luascripting::general::operatingSystem, + "", + "Returns a parsed string of the operating system type, for example " + "Windows, Linux, MacOS, or others, together with the specific version, " + "where available." + }, + { + "fullOperatingSystem", + &luascripting::general::fullOperatingSystem, + "", + "Returns the operating system as a string. The exact format of the " + "returned string is implementation and operating system-dependent but it " + "should contain the manufacturer and the version." + }, + { + "installedMainMemory", + &luascripting::general::installedMainMemory, + "", + "Returns the amount of available, installed main memory (RAM) on the " + "system in MB." + }, + { + "cores", + &luascripting::general::cores, + "", + "Returns the number of cores." + }, + { + "cacheLineSize", + &luascripting::general::cacheLineSize, + "", + "Returns the cache line size." + }, + { + "L2Associativity", + &luascripting::general::L2Associativity, + "", + "Returns the L2 associativity." + }, + { + "cacheSize", + &luascripting::general::cacheSize, + "", + "Returns the cache size." + }, + { + "extensions", + &luascripting::general::extensions, + "", + "Returns all supported exteions as comma-separated string." + } + } + }; +} + +LuaLibrary openglSystemCapabilities() { + return { + "openglCapabilities", + { + { + "hasOpenGLVersion", + &luascripting::opengl::hasOpenGLVersion, + "string", + "Tests whether the current instance supports the passed OpenGL version. " + "The parameter has to have the form 'X.Y' or 'X.Y.Z'." + }, + { + "openGLVersion", + &luascripting::opengl::openGLVersion, + "", + "Returns the maximum OpenGL version that is supported on this platform." + }, + { + "glslCompiler", + &luascripting::opengl::glslCompiler, + "", + "Returns the value of a call to glGetString(GL_VENDOR). " + "This will give detailed information about the vendor of the main " + "graphics card. This string can be used if the automatic Vendor " + "detection failed." + }, + { + "gpuVendor", + &luascripting::opengl::gpuVendor, + "", + "Returns the vendor of the main graphics card." + }, + { + "extensions", + &luascripting::opengl::extensions, + "", + "Returns all available extensions as a list of names." + }, + { + "isExtensionSupported", + &luascripting::opengl::isExtensionSupported, + "string", + "Checks is a specific extension is supported or not." + }, + { + "maxTextureUnits", + &luascripting::opengl::maxTextureUnits, + "", + "Returns the maximum number of texture units that are available on the " + "main graphics card." + }, + { + "max2DTextureSize", + &luascripting::opengl::max2DTextureSize, + "", + "Returns the largest dimension for a 2D texture on this graphics card." + }, + { + "max3DTextureSize", + &luascripting::opengl::max3DTextureSize, + "", + "Returns the largest dimension for a 3D texture on this graphics card." + }, + { + "maxAtomicCounterBufferBindings", + &luascripting::opengl::maxAtomicCounterBufferBindings, + "", + "Returns the maximum number of atomic counter buffer bindings that are " + "available on the main graphics card." + }, + { + "maxShaderStorageBufferBindings", + &luascripting::opengl::maxShaderStorageBufferBindings, + "", + "Returns the maximum number of shader storage bindings that are " + "available on the main graphics card." + }, + { + "maxUniformBufferBindings", + &luascripting::opengl::maxUniformBufferBindings, + "", + "Returns the maximum number of uniform buffer bindings that are " + "available on the main graphics card." + } + } + }; +} + +} // namespace scripting +} // namespace openspace