diff --git a/CMakeLists.txt b/CMakeLists.txt index 0808f1fef..0f4e7c9de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,13 +71,15 @@ include_directories("${PROJECT_SOURCE_DIR}/lib/enet/include") add_subdirectory("${PROJECT_SOURCE_DIR}/lib/glew") include_directories("${PROJECT_SOURCE_DIR}/lib/glew/include") -if(WIN32 AND NOT MINGW) +if((WIN32 AND NOT MINGW) OR APPLE) + if (NOT APPLE) # Build zlib library add_subdirectory("${PROJECT_SOURCE_DIR}/lib/zlib") include_directories("${PROJECT_SOURCE_DIR}/lib/zlib") set(ZLIB_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/lib/zlib" "${PROJECT_BINARY_DIR}/lib/zlib/") set(ZLIB_LIBRARY zlibstatic) + endif() # Build png library set (SKIP_INSTALL_ALL TRUE) @@ -431,7 +433,7 @@ if(STK_ASSETS_DIR AND CHECK_ASSETS) install(DIRECTORY ${STK_ASSETS_DIR} DESTINATION ${STK_INSTALL_DATA_DIR}/data PATTERN ".svn" EXCLUDE PATTERN ".git" EXCLUDE) endif() install(FILES ${STK_DATA_DIR}/supertuxkart.desktop DESTINATION share/applications) -install(FILES data/supertuxkart_32.png DESTINATION share/icons/hicolor/32x32 RENAME supertuxkart.png) -install(FILES data/supertuxkart_128.png DESTINATION share/icons/hicolor/128x128 RENAME supertuxkart.png) +install(FILES data/supertuxkart_32.png DESTINATION share/icons/hicolor/32x32/apps RENAME supertuxkart.png) +install(FILES data/supertuxkart_128.png DESTINATION share/icons/hicolor/128x128/apps RENAME supertuxkart.png) install(FILES data/supertuxkart_32.png data/supertuxkart_128.png DESTINATION share/pixmaps) install(FILES data/supertuxkart.appdata.xml DESTINATION share/appdata) diff --git a/data/CREDITS b/data/CREDITS index 351d10bee..e27fbb540 100644 Binary files a/data/CREDITS and b/data/CREDITS differ diff --git a/data/graphical_restrictions.xml b/data/graphical_restrictions.xml index f6352aff1..625858991 100644 --- a/data/graphical_restrictions.xml +++ b/data/graphical_restrictions.xml @@ -1,6 +1,7 @@ - + + @@ -9,6 +10,9 @@ + + + diff --git a/data/optimize_data.sh b/data/optimize_data.sh index dca4d040d..675f9db74 100755 --- a/data/optimize_data.sh +++ b/data/optimize_data.sh @@ -1,23 +1,74 @@ -#!/bin/sh +#!/bin/bash # # (C) 2013 Lauri Kasanen, under the GPLv3 +# (C) 2014-2015 Odd0002, under the GPLv3 # # Script to optimize the data, currently PNG, JPEG, B3DZ. +# experimental B3D to B3DZ compression added, not enabled by default # Run it before making a release, and after adding new data. -# Takes 5-10min depending on your cpu. + +#Takes 30+ minutes, depending on your cpu or compression options. # Spaces in filenames are supported. +#define number of threads +threads=$(nproc) + # Start checks +#if you do not want to use a program, set the variable for it to false here +jpegtran=true +advdef=true +advzip=true +optipng=true -fail=0 -which awk >/dev/null && which jpegtran >/dev/null && which advdef >/dev/null && \ -which advzip >/dev/null || fail=1 +#WARNING! SETTING TO TRUE MAY POSSIBLY INCREASE LOAD TIMES ON A SLOW CPU (UNTESTED) OR LEAD TO FILE NOT FOUND ERRORS WHEN RUNNING SUPERTUXKART! +compress_b3d=false + + +#--------------------------------------------------------- +# Begin main code + +#Check for reqired programs; if a program is not available, disable it or quit the program + +#TODO: make awk optional +if [ ! $(which awk) ] +then + echo "Please install awk. It is required by this program. \nQuitting..." + exit 1 +fi + +#check for jpegtran +if [ ! $(which jpegtran) ] +then + echo "jpegtran not installed, therefore it will not be used. It is included in the package \"libjpeg-progs\"."; jpegtran=false + sleep 2 +fi + +#check for advdef +if [ ! $(which advdef) ] +then + echo "advdef is not installed, therefore it will not be used. It is included in the package \"advancecomp\"."; advdef=false + sleep 2 +fi + +#check for advzip +if [ ! $(which advzip) ] +then + echo "advzip is not installed, therefore it will not be used. It is included in the package \"advancecomp\"."; advzip=false + sleep 2 +fi + +#check for optipng +if [ ! $(which optipng) ] +then + echo "optipng is not installed, therefore it will not be used."; optipng=false + sleep 2 +fi -[ "$fail" -eq 1 ] && echo "Please install awk, advdef and jpegtran" && exit 1 # Defines +#Internal Field Seperator IFS=" " @@ -25,25 +76,111 @@ export LANG=C # Go +#store disk usage of files beforehand BEFORE=`du -sk | awk '{print $1}'` -for png in `find -name "*.png"`; do - advdef -z4 "$png" -done -for jpeg in `find -name "*.jpg"`; do - jpegtran -optimize -copy none -outfile "$jpeg".$$ "$jpeg" - mv "$jpeg".$$ "$jpeg" -done +#functions for xargs multithreading, used instead of GNU parallel for cross-compatibility +#TODO: let next set of optimization scripts run if one set is stuck on a single file at the end to decrease total runtime -for b3dz in `find -name "*.b3dz"`; do - advzip -z4 "$b3dz" +#optimize PNG's +optimpng () { +for arg; do + optipng -quiet -o3 "$arg" +#level 3 = 16 trials, which according to http://optipng.sourceforge.net/pngtech/optipng.html (retrieved October 2014) should be satisfactory for all users done +} +export -f optimpng + + +#compress PNG in-stream data +comprpng () { +for arg; do + advdef -z4 "$arg" +done +} +export -f comprpng + + +#optimize and recompress jpeg files (losslessly) +optimjpg () { +for arg; do + jpegtran -optimize -copy none -outfile "$arg".$$ "$arg" + mv "$arg".$$ "$arg" +done +} +export -f optimjpg + + +#recompress b3dz files +recomprb3dz () { +for arg; do + advzip -z4 "$arg" +done +} +export -f recomprb3dz +#END MULTITHREADING FUNCTIONS + +#lossless png image optimization +if [ "$optipng" = true ]; then + find . -path .svn -prune -o -name "*.png" -print0 | xargs -0 -n 1 -P "$threads" bash -c 'optimpng "$@"' -- #multithread the png optimization +else echo "optipng not installed. Ignoring commands using optipng..."; sleep 1 +fi + + +#in-stream data/png compression +if [ "$advdef" = true ]; then + find . -path .svn -prune -o -name "*.png" -print0 | xargs -0 -n 1 -P "$threads" bash -c 'comprpng "$@"' -- #multithread image compression +else echo "advdef is not installed. Ignoring commands using advdef..."; sleep 1 +fi + + +#lossless jpeg optimization/recompression +if [ "$jpegtran" = true ]; then + find . -path .svn -prune -o -name "*.jpg" -print0 | xargs -0 -n 1 -P "$threads" bash -c 'optimjpg "$@"' -- #multithread jpg compression and optimization +else echo "jpegtran not installed. Ignoring commands using jpegtran..."; sleep 1 +fi + + +#b3dz to b3dz compression +#WARNING: BETA, MAY CAUSE MISSING FILE WARNINGS! +if [ "$compress_b3d" = true ]; then + for xmls in $(find . -name "*.xml"); do + sed 's/b3d/b3dz/g' "$xmls" > "$xmls".$$ + mv "$xmls".$$ "$xmls" + #echo "$xmls" + sed 's/b3dzz/b3dz/g' "$xmls" > "$xmls".$$ + mv "$xmls".$$ "$xmls" + sed 's/b3dzz/b3dz/g' "$xmls" > "$xmls".$$ + mv "$xmls".$$ "$xmls" + done + + find . -name "*.b3d" -execdir zip '{}.zip' '{}' \; + + for b3dzip in $(find -name "*.b3d.zip"); do + b3dz="${b3dzip%.zip}" + #echo "$b3dz" + mv "$b3dzip" "${b3dz}z" + done + + find . -type d -name "models" -prune -o -name "*.b3d" -print0 | xargs -0 rm + +else echo "b3d to b3dz compression disabled. Ignoring actions..."; sleep 1 +fi + +#b3dz file stream compression +if [ "$advzip" = true ]; then + find . -path .svn -prune -o -name "*.b3dz" -print0 | xargs -0 -n 1 -P "$threads" bash -c 'recomprb3dz "$@"' -- #multithread b3dz recompression +else echo "advzip not installed. Ignoring commands using advzip..."; sleep 1 +fi + # Add optimizations for other types if necessary +# get and store new disk usage info AFTER=`du -sk | awk '{print $1}'` + # Print stats out -echo $BEFORE $AFTER | awk '{print "Before: " $1/1024 "mb, after: " $2/1024 "mb" }' +echo $BEFORE $AFTER | awk '{print "Size before: " $1/1024 "mb; Size after: " $2/1024 "mb" }' echo $BEFORE $AFTER | awk '{print "Saved " (1-($2/$1)) * 100 "%" }' diff --git a/data/po/pl.po b/data/po/pl.po index f0d24e9e4..dfcf4d861 100644 --- a/data/po/pl.po +++ b/data/po/pl.po @@ -9,8 +9,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " -"|| n%100>=20) ? 1 : 2;\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" "X-Launchpad-Export-Date: 2015-01-20 00:41+0000\n" "X-Generator: Launchpad (build 17304)\n" "X-Poedit-Country: POLAND\n" diff --git a/data/shaders/fog.frag b/data/shaders/fog.frag index 95353b8ed..7f4d7075a 100644 --- a/data/shaders/fog.frag +++ b/data/shaders/fog.frag @@ -10,7 +10,7 @@ vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix); void main() { - vec2 uv = 2. * gl_FragCoord.xy / screen; + vec2 uv = gl_FragCoord.xy / screen; float z = texture(tex, uv).x; vec4 xpos = getPosFromUVDepth(vec3(uv, z), InverseProjectionMatrix); diff --git a/lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.cpp b/lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.cpp index ba6cdc833..6846e7912 100644 --- a/lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.cpp +++ b/lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2002-2012 Nikolaus Gebhardt -// Copyright (C) 2014 Dawid Gan +// Copyright (C) 2014-2015 Dawid Gan // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -11,6 +11,7 @@ extern bool GLContextDebugBit; #include #include +#include #include #include #include "IEventReceiver.h" @@ -58,7 +59,7 @@ namespace irr { namespace video { - extern bool useCoreContext; + extern bool useCoreContext; IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceLinux* device); } @@ -500,7 +501,7 @@ void IrrPrintXGrabError(int grabResult, const c8 * grabCommand ) static GLXContext getMeAGLContext(Display *display, GLXFBConfig glxFBConfig) { GLXContext Context; - irr::video::useCoreContext = true; + irr::video::useCoreContext = true; int core43ctxdebug[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 4, @@ -509,13 +510,13 @@ static GLXContext getMeAGLContext(Display *display, GLXFBConfig glxFBConfig) GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB, None }; - int core43ctx[] = - { - GLX_CONTEXT_MAJOR_VERSION_ARB, 4, - GLX_CONTEXT_MINOR_VERSION_ARB, 3, - GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, - None - }; + int core43ctx[] = + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 4, + GLX_CONTEXT_MINOR_VERSION_ARB, 3, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + None + }; int core33ctxdebug[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 3, @@ -524,21 +525,21 @@ static GLXContext getMeAGLContext(Display *display, GLXFBConfig glxFBConfig) GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB, None }; - int core33ctx[] = - { - GLX_CONTEXT_MAJOR_VERSION_ARB, 3, - GLX_CONTEXT_MINOR_VERSION_ARB, 3, - GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, - None - }; - int core31ctxdebug[] = - { - GLX_CONTEXT_MAJOR_VERSION_ARB, 3, - GLX_CONTEXT_MINOR_VERSION_ARB, 1, - GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, - GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB, - None - }; + int core33ctx[] = + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 3, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + None + }; + int core31ctxdebug[] = + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 1, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB, + None + }; int core31ctx[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 3, @@ -557,30 +558,30 @@ static GLXContext getMeAGLContext(Display *display, GLXFBConfig glxFBConfig) glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" ); // create core 4.3 context - os::Printer::log("Creating OpenGL 4.3 context...", ELL_INFORMATION); - Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, GLContextDebugBit ? core43ctxdebug : core43ctx); + os::Printer::log("Creating OpenGL 4.3 context...", ELL_INFORMATION); + Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, GLContextDebugBit ? core43ctxdebug : core43ctx); if (!XErrorSignaled) return Context; XErrorSignaled = false; // create core 3.3 context - os::Printer::log("Creating OpenGL 3.3 context...", ELL_INFORMATION); - Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, GLContextDebugBit ? core33ctxdebug : core33ctx); + os::Printer::log("Creating OpenGL 3.3 context...", ELL_INFORMATION); + Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, GLContextDebugBit ? core33ctxdebug : core33ctx); if (!XErrorSignaled) return Context; XErrorSignaled = false; // create core 3.1 context (for older mesa) - os::Printer::log("Creating OpenGL 3.1 context...", ELL_INFORMATION); - Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, GLContextDebugBit ? core31ctxdebug : core31ctx); + os::Printer::log("Creating OpenGL 3.1 context...", ELL_INFORMATION); + Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, GLContextDebugBit ? core31ctxdebug : core31ctx); if (!XErrorSignaled) return Context; XErrorSignaled = false; - irr::video::useCoreContext = false; + irr::video::useCoreContext = false; // fall back to legacy context - os::Printer::log("Creating legacy OpenGL 2.1 context...", ELL_INFORMATION); - Context = glXCreateNewContext(display, glxFBConfig, GLX_RGBA_TYPE, NULL, True); + os::Printer::log("Creating legacy OpenGL 2.1 context...", ELL_INFORMATION); + Context = glXCreateNewContext(display, glxFBConfig, GLX_RGBA_TYPE, NULL, True); return Context; } @@ -2042,7 +2043,7 @@ bool CIrrDeviceLinux::activateJoysticks(core::array & joystickInf ActiveJoysticks.push_back(info); - returnInfo.HasGenericName = false; + returnInfo.HasGenericName = false; returnInfo.Joystick = joystick; returnInfo.PovHat = SJoystickInfo::POV_HAT_UNKNOWN; returnInfo.Axes = info.axes; @@ -2218,47 +2219,59 @@ bool CIrrDeviceLinux::getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &bright const c8* CIrrDeviceLinux::getTextFromClipboard() const { #if defined(_IRR_COMPILE_WITH_X11_) - Window ownerWindow = XGetSelectionOwner (display, X_ATOM_CLIPBOARD); - if ( ownerWindow == window ) + if (X_ATOM_CLIPBOARD == None) + { + os::Printer::log("Couldn't access X clipboard", ELL_WARNING); + return 0; + } + + Window ownerWindow = XGetSelectionOwner(display, X_ATOM_CLIPBOARD); + if (ownerWindow == window) { return Clipboard.c_str(); } + Clipboard = ""; - if (ownerWindow != None ) + + if (ownerWindow == None) + return 0; + + Atom selection = XInternAtom(display, "IRR_SELECTION", False); + XConvertSelection(display, X_ATOM_CLIPBOARD, XA_STRING, selection, window, CurrentTime); + + const int SELECTION_RETRIES = 500; + int i = 0; + for (i = 0; i < SELECTION_RETRIES; i++) { - XConvertSelection (display, X_ATOM_CLIPBOARD, XA_STRING, None, ownerWindow, CurrentTime); - XFlush (display); + XEvent xevent; + bool res = XCheckTypedWindowEvent(display, window, SelectionNotify, &xevent); + + if (res && xevent.xselection.selection == X_ATOM_CLIPBOARD) + break; - // check for data - Atom type; - int format; - unsigned long numItems, bytesLeft, dummy; - unsigned char *data; - XGetWindowProperty (display, ownerWindow, - XA_STRING, // property name - 0, // offset - 0, // length (we only check for data, so 0) - 0, // Delete 0==false - AnyPropertyType, // AnyPropertyType or property identifier - &type, // return type - &format, // return format - &numItems, // number items - &bytesLeft, // remaining bytes for partial reads - &data); // data - if ( bytesLeft > 0 ) - { - // there is some data to get - int result = XGetWindowProperty (display, ownerWindow, XA_STRING, 0, - bytesLeft, 0, AnyPropertyType, &type, &format, - &numItems, &dummy, &data); - if (result == Success) - Clipboard = (irr::c8*)data; - XFree (data); - } + usleep(1000); } + + if (i == SELECTION_RETRIES) + { + os::Printer::log("Timed out waiting for SelectionNotify event", ELL_WARNING); + return 0; + } + + Atom type; + int format; + unsigned long numItems, dummy; + unsigned char *data; + int result = XGetWindowProperty(display, window, selection, 0, INT_MAX/4, + False, AnyPropertyType, &type, &format, + &numItems, &dummy, &data); + + if (result == Success) + Clipboard = (irr::c8*)data; + + XFree (data); return Clipboard.c_str(); - #else return 0; #endif diff --git a/lib/jpeglib/CMakeLists.txt b/lib/jpeglib/CMakeLists.txt index 72f37556f..c3d02d78f 100644 --- a/lib/jpeglib/CMakeLists.txt +++ b/lib/jpeglib/CMakeLists.txt @@ -1,5 +1,10 @@ cmake_minimum_required(VERSION 2.4.4) +if(APPLE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -arch i386") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -arch i386 -F/Library/Frameworks") +endif() + SET(JPEG_SRCS jaricom.c jcapimin.c diff --git a/lib/libpng/CMakeLists.txt b/lib/libpng/CMakeLists.txt index aa0fd69b7..1450173c0 100644 --- a/lib/libpng/CMakeLists.txt +++ b/lib/libpng/CMakeLists.txt @@ -38,6 +38,11 @@ set(PNGLIB_RELEASE 9) set(PNGLIB_NAME libpng${PNGLIB_MAJOR}${PNGLIB_MINOR}) set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_RELEASE}) +if(APPLE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -arch i386") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -arch i386 -F/Library/Frameworks") +endif() + # needed packages find_package(ZLIB REQUIRED) include_directories(${ZLIB_INCLUDE_DIR}) diff --git a/lib/zlib/gzwrite.c b/lib/zlib/gzwrite.c index 29dcc5362..62de1cc98 100644 --- a/lib/zlib/gzwrite.c +++ b/lib/zlib/gzwrite.c @@ -569,7 +569,7 @@ int ZEXPORT gzclose_w(file) #ifdef _WIN32 if (_close(state->fd) == -1) #else - if (_close(state->fd) == -1) + if (close(state->fd) == -1) #endif ret = Z_ERRNO; free(state); diff --git a/src/achievements/achievement.cpp b/src/achievements/achievement.cpp index 3879fe49e..74ae97ff3 100644 --- a/src/achievements/achievement.cpp +++ b/src/achievements/achievement.cpp @@ -199,8 +199,8 @@ void Achievement::check() if(m_achievement_info->checkCompletion(this)) { //show achievement - core::stringw s = StringUtils::insertValues(_("Completed achievement \"%s\"."), - m_achievement_info->getName()); + core::stringw s = _("Completed achievement \"%s\".", + m_achievement_info->getName().c_str()); MessageQueue::add(MessageQueue::MT_ACHIEVEMENT, s); // Sends a confirmation to the server that an achievement has been diff --git a/src/graphics/IBL.cpp b/src/graphics/IBL.cpp index 735accc24..ef22186d8 100644 --- a/src/graphics/IBL.cpp +++ b/src/graphics/IBL.cpp @@ -3,6 +3,7 @@ #include "shaders.hpp" #include #include +#include "central_settings.hpp" static void getXYZ(GLenum face, float i, float j, float &x, float &y, float &z) { @@ -293,7 +294,7 @@ GLuint generateSpecularCubemap(GLuint probe) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA16F, cubemap_size, cubemap_size, 0, GL_BGRA, GL_FLOAT, 0); glGenerateMipmap(GL_TEXTURE_CUBE_MAP); - if (!UserConfigParams::m_dynamic_lights) + if (!CVS->isDefferedEnabled()) return cubemap_texture; GLuint fbo; diff --git a/src/graphics/central_settings.cpp b/src/graphics/central_settings.cpp index 2da49c7eb..0cecaaae5 100644 --- a/src/graphics/central_settings.cpp +++ b/src/graphics/central_settings.cpp @@ -272,6 +272,11 @@ bool CentralVideoSettings::supportsIndirectInstancingRendering() const } bool CentralVideoSettings::supportsComputeShadersFiltering() const +{ + return isARBBufferStorageUsable() && isARBImageLoadStoreUsable() && isARBComputeShaderUsable(); +} + +bool CentralVideoSettings::supportsAsyncInstanceUpload() const { return isARBBufferStorageUsable() && isARBImageLoadStoreUsable(); } @@ -307,4 +312,9 @@ bool CentralVideoSettings::isAZDOEnabled() const bool CentralVideoSettings::isESMEnabled() const { return UserConfigParams::m_esm; +} + +bool CentralVideoSettings::isDefferedEnabled() const +{ + return UserConfigParams::m_dynamic_lights && !GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_ADVANCED_PIPELINE); } \ No newline at end of file diff --git a/src/graphics/central_settings.hpp b/src/graphics/central_settings.hpp index a354c73fe..980c0a666 100644 --- a/src/graphics/central_settings.hpp +++ b/src/graphics/central_settings.hpp @@ -58,6 +58,7 @@ public: bool supportsGlobalIllumination() const; bool supportsIndirectInstancingRendering() const; bool supportsComputeShadersFiltering() const; + bool supportsAsyncInstanceUpload() const; // "Macro" around feature support and user config bool isShadowEnabled() const; @@ -66,6 +67,7 @@ public: bool isSDSMEnabled() const; bool isAZDOEnabled() const; bool isESMEnabled() const; + bool isDefferedEnabled() const; }; extern CentralVideoSettings* CVS; diff --git a/src/graphics/graphics_restrictions.cpp b/src/graphics/graphics_restrictions.cpp index 4780de9ae..eb8c3e6ac 100644 --- a/src/graphics/graphics_restrictions.cpp +++ b/src/graphics/graphics_restrictions.cpp @@ -56,7 +56,8 @@ namespace GraphicsRestrictions "TextureCompressionS3TC", "AMDVertexShaderLayer", "DriverRecentEnough", - "HighDefinitionTextures" + "HighDefinitionTextures", + "AdvancedPipeline" }; } // namespace Private using namespace Private; @@ -216,7 +217,7 @@ public: for(unsigned int i=0; i other.m_version[i]) return false; + if (m_version[i] < other.m_version[i]) return true; } - return true; - } // operator> + if (m_version.size() >= other.m_version.size()) + return false; + else + return true; + } // operator< // ------------------------------------------------------------------------ /** If *this <= other. */ bool operator<= (const Version &other) const @@ -246,8 +251,11 @@ public: if (m_version[i] > other.m_version[i]) return false; if (m_version[i] < other.m_version[i]) return true; } - return true; - } // operator> + if (m_version.size() > other.m_version.size()) + return false; + else + return true; + } // operator<= }; // class Version // ============================================================================ @@ -396,6 +404,10 @@ void unitTesting() assert(Version("1.2.3") <= Version("1.2.3.1")); assert(Version("1.2.3") <= Version("1.2.3")); assert(Version("1.2.3") == Version("1.2.3")); + assert(Version("10.3") < Version("10.3.2")); + assert(Version("10.3") <= Version("10.3.2")); + assert(!(Version("10.3.2") < Version("10.3"))); + assert(!(Version("10.3.2") <= Version("10.3"))); assert(Version("3.3 NVIDIA-10.0.19 310.90.10.05b1", "NVIDIA GeForce GTX 680MX OpenGL Engine") == Version("310.90.10.5") ); diff --git a/src/graphics/graphics_restrictions.hpp b/src/graphics/graphics_restrictions.hpp index 5e442939c..171fa10fe 100644 --- a/src/graphics/graphics_restrictions.hpp +++ b/src/graphics/graphics_restrictions.hpp @@ -51,6 +51,7 @@ namespace GraphicsRestrictions GR_AMD_VERTEX_SHADER_LAYER, GR_DRIVER_RECENT_ENOUGH, GR_HIGHDEFINITION_TEXTURES, + GR_ADVANCED_PIPELINE, GR_COUNT /** MUST be last entry. */ } ; diff --git a/src/graphics/irr_driver.hpp b/src/graphics/irr_driver.hpp index 6c73247fc..c8411cc96 100644 --- a/src/graphics/irr_driver.hpp +++ b/src/graphics/irr_driver.hpp @@ -342,6 +342,7 @@ private: void renderGlow(std::vector& glows); void renderSSAO(); void renderLights(unsigned pointlightCount, bool hasShadow); + void renderAmbientScatter(); void renderLightsScatter(unsigned pointlightCount); void renderShadowsDebug(); void doScreenShot(); diff --git a/src/graphics/referee.cpp b/src/graphics/referee.cpp index 6a73389c9..d4c0d85ff 100644 --- a/src/graphics/referee.cpp +++ b/src/graphics/referee.cpp @@ -150,7 +150,7 @@ Referee::Referee() irr_driver->applyObjectPassShader(m_scene_node); - if (CVS->isGLSL() && UserConfigParams::m_dynamic_lights) + if (CVS->isGLSL() && CVS->isDefferedEnabled()) { m_light = irr_driver->addLight(core::vector3df(0.0f, 0.0f, 0.6f), 0.7f, 2.0f, 0.7f /* r */, 0.0 /* g */, 0.0f /* b */, false /* sun */, m_scene_node); diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index 5dd03d3c5..f68306e8a 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -138,7 +138,7 @@ void IrrDriver::renderGLSL(float dt) RaceGUIBase *rg = world->getRaceGUI(); if (rg) rg->update(dt); - if (!UserConfigParams::m_dynamic_lights) + if (!CVS->isDefferedEnabled()) { SColor clearColor(0, 150, 150, 150); if (World::getWorld() != NULL) @@ -161,7 +161,7 @@ void IrrDriver::renderGLSL(float dt) oss << "drawAll() for kart " << cam; PROFILER_PUSH_CPU_MARKER(oss.str().c_str(), (cam+1)*60, 0x00, 0x00); - camera->activate(!UserConfigParams::m_dynamic_lights); + camera->activate(!CVS->isDefferedEnabled()); rg->preRenderCallback(camera); // adjusts start referee m_scene_manager->setActiveCamera(camnode); @@ -176,7 +176,7 @@ void IrrDriver::renderGLSL(float dt) prepareSkybox(); m_skybox_ready = true; } - if (!UserConfigParams::m_dynamic_lights) + if (!CVS->isDefferedEnabled()) glEnable(GL_FRAMEBUFFER_SRGB); PROFILER_PUSH_CPU_MARKER("Update Light Info", 0xFF, 0x0, 0x0); @@ -242,7 +242,7 @@ void IrrDriver::renderGLSL(float dt) } // Render the post-processed scene - if (UserConfigParams::m_dynamic_lights) + if (CVS->isDefferedEnabled()) { bool isRace = StateManager::get()->getGameState() == GUIEngine::GAME; FrameBuffer *fbo = m_post_processing->render(camnode, isRace); @@ -269,7 +269,7 @@ void IrrDriver::renderGLSL(float dt) { glEnable(GL_FRAMEBUFFER_SRGB); glBindFramebuffer(GL_FRAMEBUFFER, 0); - if (UserConfigParams::m_dynamic_lights) + if (CVS->isDefferedEnabled()) camera->activate(); m_post_processing->renderPassThrough(fbo->getRTT()[0]); glDisable(GL_FRAMEBUFFER_SRGB); @@ -348,7 +348,7 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned po { // To avoid wrong culling, use the largest view possible m_scene_manager->setActiveCamera(m_suncam); - if (UserConfigParams::m_dynamic_lights && + if (CVS->isDefferedEnabled() && CVS->isShadowEnabled() && hasShadow) { PROFILER_PUSH_CPU_MARKER("- Shadow", 0x30, 0x6F, 0x90); @@ -371,7 +371,7 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned po glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); glEnable(GL_CULL_FACE); - if (UserConfigParams::m_dynamic_lights || forceRTT) + if (CVS->isDefferedEnabled() || forceRTT) { m_rtts->getFBO(FBO_NORMAL_AND_DEPTHS).Bind(); glClearColor(0., 0., 0., 0.); @@ -385,7 +385,7 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned po // Lights { PROFILER_PUSH_CPU_MARKER("- Light", 0x00, 0xFF, 0x00); - if (UserConfigParams::m_dynamic_lights) + if (CVS->isDefferedEnabled()) renderLights(pointlightcount, hasShadow); PROFILER_POP_CPU_MARKER(); } @@ -400,7 +400,7 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned po } PROFILER_PUSH_CPU_MARKER("- Solid Pass 2", 0x00, 0x00, 0xFF); - if (UserConfigParams::m_dynamic_lights || forceRTT) + if (CVS->isDefferedEnabled() || forceRTT) { m_rtts->getFBO(FBO_COLORS).Bind(); SColor clearColor(0, 150, 150, 150); @@ -422,12 +422,13 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned po m_rtts->getFBO(FBO_COLORS).Bind(); } - if (UserConfigParams::m_dynamic_lights && World::getWorld() != NULL && + // Render ambient scattering + if (CVS->isDefferedEnabled() && World::getWorld() != NULL && World::getWorld()->isFogEnabled()) { - PROFILER_PUSH_CPU_MARKER("- Fog", 0xFF, 0x00, 0x00); + PROFILER_PUSH_CPU_MARKER("- Ambient scatter", 0xFF, 0x00, 0x00); ScopedGPUTimer Timer(getGPUTimer(Q_FOG)); - renderLightsScatter(pointlightcount); + renderAmbientScatter(); PROFILER_POP_CPU_MARKER(); } @@ -438,6 +439,16 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned po PROFILER_POP_CPU_MARKER(); } + // Render discrete lights scattering + if (CVS->isDefferedEnabled() && World::getWorld() != NULL && + World::getWorld()->isFogEnabled()) + { + PROFILER_PUSH_CPU_MARKER("- PointLight Scatter", 0xFF, 0x00, 0x00); + ScopedGPUTimer Timer(getGPUTimer(Q_FOG)); + renderLightsScatter(pointlightcount); + PROFILER_POP_CPU_MARKER(); + } + if (getRH()) { glDisable(GL_BLEND); @@ -479,7 +490,7 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned po renderParticles(); PROFILER_POP_CPU_MARKER(); } - if (!UserConfigParams::m_dynamic_lights && !forceRTT) + if (!CVS->isDefferedEnabled() && !forceRTT) { glDisable(GL_FRAMEBUFFER_SRGB); glDisable(GL_DEPTH_TEST); diff --git a/src/graphics/render_geometry.cpp b/src/graphics/render_geometry.cpp index 44c560eaf..3a822a7e1 100644 --- a/src/graphics/render_geometry.cpp +++ b/src/graphics/render_geometry.cpp @@ -614,6 +614,9 @@ void IrrDriver::renderSolidSecondPass() glMakeTextureHandleResidentARB(DepthHandle); } + if (CVS->supportsIndirectInstancingRendering()) + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, SolidPassCmd::getInstance()->drawindirectcmd); + { ScopedGPUTimer Timer(getGPUTimer(Q_SOLID_PASS2)); @@ -800,7 +803,7 @@ void IrrDriver::renderTransparent() for (unsigned i = 0; i < BillBoardList::getInstance()->size(); i++) BillBoardList::getInstance()->at(i)->render(); - if (!UserConfigParams::m_dynamic_lights) + if (!CVS->isDefferedEnabled()) return; // Render displacement nodes diff --git a/src/graphics/render_lighting.cpp b/src/graphics/render_lighting.cpp index ff0253ef2..0996d9867 100644 --- a/src/graphics/render_lighting.cpp +++ b/src/graphics/render_lighting.cpp @@ -228,12 +228,8 @@ void IrrDriver::renderSSAO() } -void IrrDriver::renderLightsScatter(unsigned pointlightcount) +void IrrDriver::renderAmbientScatter() { - getFBO(FBO_HALF1).Bind(); - glClearColor(0., 0., 0., 0.); - glClear(GL_COLOR_BUFFER_BIT); - const Track * const track = World::getWorld()->getTrack(); // This function is only called once per frame - thus no need for setters. @@ -252,6 +248,28 @@ void IrrDriver::renderLightsScatter(unsigned pointlightcount) FullScreenShader::FogShader::getInstance()->SetTextureUnits(irr_driver->getDepthStencilTexture()); DrawFullScreenEffect(1.f / (40.f * start), col); +} + +void IrrDriver::renderLightsScatter(unsigned pointlightcount) +{ + getFBO(FBO_HALF1).Bind(); + glClearColor(0., 0., 0., 0.); + glClear(GL_COLOR_BUFFER_BIT); + + const Track * const track = World::getWorld()->getTrack(); + + // This function is only called once per frame - thus no need for setters. + float start = track->getFogStart() + .001f; + const video::SColor tmpcol = track->getFogColor(); + + core::vector3df col(tmpcol.getRed() / 255.0f, + tmpcol.getGreen() / 255.0f, + tmpcol.getBlue() / 255.0f); + + glDepthMask(GL_FALSE); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_ONE, GL_ONE); glEnable(GL_DEPTH_TEST); core::vector3df col2(1., 1., 1.); diff --git a/src/graphics/stkanimatedmesh.cpp b/src/graphics/stkanimatedmesh.cpp index f2708057c..a91811c9a 100644 --- a/src/graphics/stkanimatedmesh.cpp +++ b/src/graphics/stkanimatedmesh.cpp @@ -181,7 +181,7 @@ void STKAnimatedMesh::updateGL() size_t size = mb->getVertexCount() * GLmeshes[i].Stride, offset = GLmeshes[i].vaoBaseVertex * GLmeshes[i].Stride; void *buf; - if (CVS->isARBBufferStorageUsable()) + if (CVS->supportsAsyncInstanceUpload()) { buf = VAOManager::getInstance()->getVBOPtr(mb->getVertexType()); buf = (char *)buf + offset; @@ -197,7 +197,7 @@ void STKAnimatedMesh::updateGL() buf = glMapBufferRange(GL_ARRAY_BUFFER, offset, size, bitfield); } memcpy(buf, mb->getVertices(), size); - if (!CVS->isARBBufferStorageUsable()) + if (!CVS->supportsAsyncInstanceUpload()) { glUnmapBuffer(GL_ARRAY_BUFFER); glBindBuffer(GL_ARRAY_BUFFER, 0); diff --git a/src/graphics/stkmeshscenenode.cpp b/src/graphics/stkmeshscenenode.cpp index 3154d64dc..fbd3a76e8 100644 --- a/src/graphics/stkmeshscenenode.cpp +++ b/src/graphics/stkmeshscenenode.cpp @@ -294,7 +294,7 @@ void STKMeshSceneNode::render() AbsoluteTransformation.getInverse(invmodel); glDisable(GL_CULL_FACE); - if (update_each_frame && !UserConfigParams::m_dynamic_lights) + if (update_each_frame && !CVS->isDefferedEnabled()) updatevbo(); glUseProgram(MeshShader::ObjectPass2Shader::getInstance()->Program); // Only untextured diff --git a/src/graphics/stkscenemanager.cpp b/src/graphics/stkscenemanager.cpp index 8618a1786..e68da0f7f 100644 --- a/src/graphics/stkscenemanager.cpp +++ b/src/graphics/stkscenemanager.cpp @@ -14,6 +14,7 @@ #include "tracks/track.hpp" #include "lod_node.hpp" #include "utils/profiler.hpp" +#include "utils/time.hpp" #include #include @@ -484,7 +485,7 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector *Immed } static void -parseSceneManager(core::list List, std::vector *ImmediateDraw, +parseSceneManager(core::list &List, std::vector *ImmediateDraw, const scene::ICameraSceneNode* cam, scene::ICameraSceneNode *shadow_cam[4], const scene::ICameraSceneNode *rsmcam, bool culledforcam, bool culledforshadowcam[4], bool culledforrsm, bool drawRSM) { @@ -517,7 +518,7 @@ parseSceneManager(core::list List, std::vectorgetChildren(), ImmediateDraw, cam, shadow_cam, rsmcam, newculledforcam, newculledforshadowcam, newculledforrsm, drawRSM); + parseSceneManager(const_cast& >((*I)->getChildren()), ImmediateDraw, cam, shadow_cam, rsmcam, newculledforcam, newculledforshadowcam, newculledforrsm, drawRSM); } } @@ -590,8 +591,14 @@ PROFILER_POP_CPU_MARKER(); if (!m_sync) m_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); PROFILER_PUSH_CPU_MARKER("- Sync Stall", 0xFF, 0x0, 0x0); - GLenum reason; - do { reason = glClientWaitSync(m_sync, GL_SYNC_FLUSH_COMMANDS_BIT, 0); if (reason == GL_WAIT_FAILED) break; } while (reason != GL_ALREADY_SIGNALED); + GLenum reason = glClientWaitSync(m_sync, GL_SYNC_FLUSH_COMMANDS_BIT, 0); + + while (reason != GL_ALREADY_SIGNALED) + { + if (reason == GL_WAIT_FAILED) break; + StkTime::sleep(1); + reason = glClientWaitSync(m_sync, GL_SYNC_FLUSH_COMMANDS_BIT, 0); + } glDeleteSync(m_sync); PROFILER_POP_CPU_MARKER(); /* switch (reason) @@ -627,7 +634,7 @@ PROFILER_POP_CPU_MARKER(); DrawElementsIndirectCommand *RSMCmdBuffer; DrawElementsIndirectCommand *GlowCmdBuffer; - if (CVS->isARBBufferStorageUsable()) + if (CVS->supportsAsyncInstanceUpload()) { InstanceBufferDualTex = (InstanceDataDualTex*)VAOManager::getInstance()->getInstanceBufferPtr(InstanceTypeDualTex); InstanceBufferThreeTex = (InstanceDataThreeTex*)VAOManager::getInstance()->getInstanceBufferPtr(InstanceTypeThreeTex); @@ -660,7 +667,7 @@ PROFILER_POP_CPU_MARKER(); #pragma omp section { size_t offset = 0, current_cmd = 0; - if (!CVS->isARBBufferStorageUsable()) + if (!CVS->supportsAsyncInstanceUpload()) { glBindBuffer(GL_ARRAY_BUFFER, VAOManager::getInstance()->getInstanceBuffer(InstanceTypeDualTex)); InstanceBufferDualTex = (InstanceDataDualTex*)glMapBufferRange(GL_ARRAY_BUFFER, 0, 10000 * sizeof(InstanceDataDualTex), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); @@ -690,7 +697,7 @@ PROFILER_POP_CPU_MARKER(); FillInstances(MeshForSolidPass[Material::SHADERTYPE_VEGETATION], ListInstancedMatGrass::getInstance()->SolidPass, InstanceBufferDualTex, CmdBuffer, offset, current_cmd, SolidPoly); SolidPassCmd::getInstance()->Size[Material::SHADERTYPE_VEGETATION] = current_cmd - SolidPassCmd::getInstance()->Offset[Material::SHADERTYPE_VEGETATION]; - if (!CVS->isARBBufferStorageUsable()) + if (!CVS->supportsAsyncInstanceUpload()) { glUnmapBuffer(GL_ARRAY_BUFFER); glBindBuffer(GL_ARRAY_BUFFER, VAOManager::getInstance()->getInstanceBuffer(InstanceTypeThreeTex)); @@ -708,7 +715,7 @@ PROFILER_POP_CPU_MARKER(); SolidPassCmd::getInstance()->Size[Material::SHADERTYPE_NORMAL_MAP] = current_cmd - SolidPassCmd::getInstance()->Offset[Material::SHADERTYPE_NORMAL_MAP]; - if (!CVS->isARBBufferStorageUsable()) + if (!CVS->supportsAsyncInstanceUpload()) { glUnmapBuffer(GL_ARRAY_BUFFER); glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER); @@ -718,7 +725,7 @@ PROFILER_POP_CPU_MARKER(); { size_t offset = 0, current_cmd = 0; - if (!CVS->isARBBufferStorageUsable()) + if (!CVS->supportsAsyncInstanceUpload()) { glBindBuffer(GL_ARRAY_BUFFER, VAOManager::getInstance()->getInstanceBuffer(InstanceTypeGlow)); GlowInstanceBuffer = (GlowInstanceData*)glMapBufferRange(GL_ARRAY_BUFFER, 0, 10000 * sizeof(InstanceDataDualTex), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); @@ -742,7 +749,7 @@ PROFILER_POP_CPU_MARKER(); if (CVS->isAZDOEnabled()) GlowPassCmd::getInstance()->Size = current_cmd - GlowPassCmd::getInstance()->Offset; - if (!CVS->isARBBufferStorageUsable()) + if (!CVS->supportsAsyncInstanceUpload()) { glUnmapBuffer(GL_ARRAY_BUFFER); glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER); @@ -753,7 +760,7 @@ PROFILER_POP_CPU_MARKER(); irr_driver->setPhase(SHADOW_PASS); size_t offset = 0, current_cmd = 0; - if (!CVS->isARBBufferStorageUsable()) + if (!CVS->supportsAsyncInstanceUpload()) { glBindBuffer(GL_ARRAY_BUFFER, VAOManager::getInstance()->getInstanceBuffer(InstanceTypeShadow)); ShadowInstanceBuffer = (InstanceDataSingleTex*)glMapBufferRange(GL_ARRAY_BUFFER, 0, 10000 * sizeof(InstanceDataDualTex), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); @@ -778,7 +785,7 @@ PROFILER_POP_CPU_MARKER(); // Mat Grass GenDrawCalls(i, ListInstancedMatGrass::getInstance()->Shadows[i], ShadowInstanceBuffer, ShadowCmdBuffer, offset, current_cmd, ShadowPoly); } - if (!CVS->isARBBufferStorageUsable()) + if (!CVS->supportsAsyncInstanceUpload()) { glUnmapBuffer(GL_ARRAY_BUFFER); glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER); @@ -788,7 +795,7 @@ PROFILER_POP_CPU_MARKER(); if (!m_rsm_map_available) { size_t offset = 0, current_cmd = 0; - if (!CVS->isARBBufferStorageUsable()) + if (!CVS->supportsAsyncInstanceUpload()) { glBindBuffer(GL_ARRAY_BUFFER, VAOManager::getInstance()->getInstanceBuffer(InstanceTypeRSM)); RSMInstanceBuffer = (InstanceDataSingleTex*)glMapBufferRange(GL_ARRAY_BUFFER, 0, 10000 * sizeof(InstanceDataDualTex), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); @@ -817,7 +824,7 @@ PROFILER_POP_CPU_MARKER(); FillInstances(MeshForRSM[Material::SHADERTYPE_NORMAL_MAP], ListInstancedMatNormalMap::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly); RSMPassCmd::getInstance()->Size[Material::SHADERTYPE_NORMAL_MAP] = current_cmd - RSMPassCmd::getInstance()->Offset[Material::SHADERTYPE_NORMAL_MAP]; - if (!CVS->isARBBufferStorageUsable()) + if (!CVS->supportsAsyncInstanceUpload()) { glUnmapBuffer(GL_ARRAY_BUFFER); glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER); @@ -828,6 +835,6 @@ PROFILER_POP_CPU_MARKER(); poly_count[SOLID_NORMAL_AND_DEPTH_PASS] += SolidPoly; poly_count[SHADOW_PASS] += ShadowPoly; - if (CVS->isARBBufferStorageUsable()) + if (CVS->supportsAsyncInstanceUpload()) glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); } \ No newline at end of file diff --git a/src/graphics/stkscenemanager.hpp b/src/graphics/stkscenemanager.hpp index 03c60b384..a25ac34ff 100644 --- a/src/graphics/stkscenemanager.hpp +++ b/src/graphics/stkscenemanager.hpp @@ -21,7 +21,7 @@ public: { glGenBuffers(1, &drawindirectcmd); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, drawindirectcmd); - if (CVS->isARBBufferStorageUsable()) + if (CVS->supportsAsyncInstanceUpload()) { glBufferStorage(GL_DRAW_INDIRECT_BUFFER, 10000 * sizeof(DrawElementsIndirectCommand), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT); Ptr = (DrawElementsIndirectCommand *)glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, 10000 * sizeof(DrawElementsIndirectCommand), GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT); diff --git a/src/graphics/vaomanager.cpp b/src/graphics/vaomanager.cpp index b42ed79c5..4d4ee1d41 100644 --- a/src/graphics/vaomanager.cpp +++ b/src/graphics/vaomanager.cpp @@ -21,7 +21,7 @@ VAOManager::VAOManager() { glGenBuffers(1, &instance_vbo[i]); glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[i]); - if (CVS->isARBBufferStorageUsable()) + if (CVS->supportsAsyncInstanceUpload()) { glBufferStorage(GL_ARRAY_BUFFER, 10000 * sizeof(InstanceDataDualTex), 0, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); Ptr[i] = glMapBufferRange(GL_ARRAY_BUFFER, 0, 10000 * sizeof(InstanceDataDualTex), GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); @@ -70,7 +70,7 @@ resizeBufferIfNecessary(size_t &lastIndex, size_t newLastIndex, size_t bufferSiz GLuint newVBO; glGenBuffers(1, &newVBO); glBindBuffer(type, newVBO); - if (CVS->isARBBufferStorageUsable()) + if (CVS->supportsAsyncInstanceUpload()) { glBufferStorage(type, bufferSize *stride, 0, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); Pointer = glMapBufferRange(type, 0, bufferSize * stride, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); @@ -271,7 +271,7 @@ void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp) size_t old_idx_cnt = last_index[tp]; regenerateBuffer(tp, old_vtx_cnt + mb->getVertexCount(), old_idx_cnt + mb->getIndexCount()); - if (CVS->isARBBufferStorageUsable()) + if (CVS->supportsAsyncInstanceUpload()) { void *tmp = (char*)VBOPtr[tp] + old_vtx_cnt * getVertexPitch(tp); memcpy(tmp, mb->getVertices(), mb->getVertexCount() * getVertexPitch(tp)); @@ -281,7 +281,7 @@ void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp) glBindBuffer(GL_ARRAY_BUFFER, vbo[tp]); glBufferSubData(GL_ARRAY_BUFFER, old_vtx_cnt * getVertexPitch(tp), mb->getVertexCount() * getVertexPitch(tp), mb->getVertices()); } - if (CVS->isARBBufferStorageUsable()) + if (CVS->supportsAsyncInstanceUpload()) { void *tmp = (char*)IBOPtr[tp] + old_idx_cnt * sizeof(u16); memcpy(tmp, mb->getIndices(), mb->getIndexCount() * sizeof(u16)); diff --git a/src/main.cpp b/src/main.cpp index fcde656ae..0ab5e467a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1094,7 +1094,7 @@ void initRest() if (!track_manager->getTrack(UserConfigParams::m_last_track)) UserConfigParams::m_last_track.revertToDefaults(); - + race_manager->setTrack(UserConfigParams::m_last_track); } // initRest @@ -1201,7 +1201,7 @@ int main(int argc, char *argv[] ) material_manager->addSharedMaterial( file_manager->getAsset(FileManager::FONT,"materials.xml")); file_manager->popTextureSearchPath(); - + GUIEngine::addLoadingIcon( irr_driver->getTexture(FileManager::GUI, "options_video.png")); kart_properties_manager -> loadAllKarts (); @@ -1462,7 +1462,6 @@ static void cleanSuperTuxKart() if(Online::RequestManager::isRunning()) Online::RequestManager::get()->stopNetworkThread(); - SFXManager::get()->stopThread(); irr_driver->updateConfigIfRelevant(); AchievementsManager::destroy(); diff --git a/src/online/http_request.cpp b/src/online/http_request.cpp index 7edc7de0b..2262d40ef 100644 --- a/src/online/http_request.cpp +++ b/src/online/http_request.cpp @@ -361,11 +361,9 @@ namespace Online { HTTPRequest *request = (HTTPRequest *)clientp; - RequestManager* request_manager = RequestManager::get(); - // Check if we are asked to abort the download. If so, signal this // back to libcurl by returning a non-zero status. - if ((request_manager->getAbort() || request->isCancelled()) && + if ((RequestManager::get()->getAbort() || request->isCancelled()) && request->isAbortable() ) { // Indicates to abort the current download, which means that this diff --git a/src/online/request.cpp b/src/online/request.cpp index b3d919242..7ffb1a981 100644 --- a/src/online/request.cpp +++ b/src/online/request.cpp @@ -61,13 +61,13 @@ namespace Online { assert(isBusy()); // Abort as early as possible if abort is requested - if(RequestManager::get()->getAbort()) return; + if (RequestManager::get()->getAbort() && isAbortable()) return; prepareOperation(); - if(RequestManager::get()->getAbort()) return; + if (RequestManager::get()->getAbort() && isAbortable()) return; operation(); - if(RequestManager::get()->getAbort()) return; + if (RequestManager::get()->getAbort() && isAbortable()) return; setExecuted(); - if(RequestManager::get()->getAbort()) return; + if (RequestManager::get()->getAbort() && isAbortable()) return; afterOperation(); } // execute diff --git a/src/online/request_manager.cpp b/src/online/request_manager.cpp index 4006162af..ee873aca5 100644 --- a/src/online/request_manager.cpp +++ b/src/online/request_manager.cpp @@ -63,7 +63,7 @@ namespace Online } // isRunning // ------------------------------------------------------------------------ /** Constructor. It only initialised values, it does not start the actual - * thread. + * thread. */ RequestManager::RequestManager() { diff --git a/src/online/request_manager.hpp b/src/online/request_manager.hpp index e5d379313..313240f21 100644 --- a/src/online/request_manager.hpp +++ b/src/online/request_manager.hpp @@ -122,7 +122,7 @@ namespace Online > m_request_queue; /** The list of pointers to all requests that are already executed - * by the networking thread, but still need to be processed by the + * by the networking thread, but still need to be processed by the * main thread. */ Synchronised< std::queue > m_result_queue; @@ -133,7 +133,7 @@ namespace Online RequestManager(); //const std::string &url ~RequestManager(); - + static RequestManager * m_request_manager; public: @@ -159,12 +159,12 @@ namespace Online void startNetworkThread(); void stopNetworkThread(); - bool getAbort(){ return m_abort.getAtomic(); } + bool getAbort() { return m_abort.getAtomic(); } void update(float dt); // ---------------------------------------------------------------- /** Sets the interval with which poll requests are send to the - * server. This can happen from the news manager (i.e. info + * server. This can happen from the news manager (i.e. info * contained in the news.xml file), or a poll request. */ void setMenuPollingInterval(float polling_interval) { @@ -172,7 +172,7 @@ namespace Online } // setPollingInterval // ---------------------------------------------------------------- /** Sets the interval with which poll requests are send to the - * server. This can happen from the news manager (i.e. info + * server. This can happen from the news manager (i.e. info * contained in the news.xml file), or a poll request. */ void setGamePollingInterval(float polling_interval) { diff --git a/src/tinygettext/dictionary_manager.cpp b/src/tinygettext/dictionary_manager.cpp index 83defce0c..254530042 100644 --- a/src/tinygettext/dictionary_manager.cpp +++ b/src/tinygettext/dictionary_manager.cpp @@ -121,7 +121,7 @@ DictionaryManager::get_dictionary(const Language& language) { std::vector files = filesystem->open_directory(*p); - std::string best_filename; + std::string best_filename = ""; int best_score = 0; for(std::vector::iterator filename = files.begin(); filename != files.end(); filename++) @@ -130,7 +130,7 @@ DictionaryManager::get_dictionary(const Language& language) if (has_suffix(*filename, ".po")) { // ignore anything that isn't a .po file - Language po_language = Language::from_env(convertFilename2Language(*filename)); + Language po_language = Language::from_env(convertFilename2Language(*filename)); if (!po_language) { @@ -194,7 +194,12 @@ DictionaryManager::get_languages() { if (has_suffix(*file, ".po")) { - languages.insert(Language::from_env(file->substr(0, file->size()-3))); + Language po_language = Language::from_env(file->substr(0, file->size()-3)); + + if (po_language) + { + languages.insert(po_language); + } } } } diff --git a/src/tinygettext/plural_forms.cpp b/src/tinygettext/plural_forms.cpp index 5e13a5307..c206ca587 100644 --- a/src/tinygettext/plural_forms.cpp +++ b/src/tinygettext/plural_forms.cpp @@ -58,16 +58,26 @@ PluralForms::from_string(const std::string& str) plural_forms["Plural-Forms:nplurals=2;plural=(n!=1);"] = PluralForms(2, plural2_1); plural_forms["Plural-Forms:nplurals=2;plural=n!=1;"] = PluralForms(2, plural2_1); plural_forms["Plural-Forms:nplurals=2;plural=(n>1);"] = PluralForms(2, plural2_2); + plural_forms["Plural-Forms:nplurals=2;plural=n>1;"] = PluralForms(2, plural2_2); + plural_forms["Plural-Forms:nplurals=2;plural=(n==1||n%10==1?0:1);"] = PluralForms(2, plural2_mk); plural_forms["Plural-Forms:nplurals=2;plural=n==1||n%10==1?0:1;"] = PluralForms(2, plural2_mk); - plural_forms["Plural-Forms:nplurals=3;plural=n%10==1&&n%100!=11?0:n!=0?1:2);"] = PluralForms(2, plural3_lv); + plural_forms["Plural-Forms:nplurals=3;plural=(n%10==1&&n%100!=11?0:n!=0?1:2);"] = PluralForms(2, plural3_lv); + plural_forms["Plural-Forms:nplurals=3;plural=n%10==1&&n%100!=11?0:n!=0?1:2;"] = PluralForms(2, plural3_lv); + plural_forms["Plural-Forms:nplurals=3;plural=(n==1?0:n==2?1:2);"] = PluralForms(3, plural3_ga); plural_forms["Plural-Forms:nplurals=3;plural=n==1?0:n==2?1:2;"] = PluralForms(3, plural3_ga); plural_forms["Plural-Forms:nplurals=3;plural=(n%10==1&&n%100!=11?0:n%10>=2&&(n%100<10||n%100>=20)?1:2);"] = PluralForms(3, plural3_lt); + plural_forms["Plural-Forms:nplurals=3;plural=n%10==1&&n%100!=11?0:n%10>=2&&(n%100<10||n%100>=20)?1:2;"] = PluralForms(3, plural3_lt); plural_forms["Plural-Forms:nplurals=3;plural=(n%10==1&&n%100!=11?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2);"] = PluralForms(3, plural3_1); + plural_forms["Plural-Forms:nplurals=3;plural=n%10==1&&n%100!=11?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2;"] = PluralForms(3, plural3_1); + plural_forms["Plural-Forms:nplurals=3;plural=((n==1)?0:(n>=2&&n<=4)?1:2);"] = PluralForms(3, plural3_sk); plural_forms["Plural-Forms:nplurals=3;plural=(n==1)?0:(n>=2&&n<=4)?1:2;"] = PluralForms(3, plural3_sk); plural_forms["Plural-Forms:nplurals=3;plural=(n==1?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2);"] = PluralForms(3, plural3_pl); + plural_forms["Plural-Forms:nplurals=3;plural=n==1?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2;"] = PluralForms(3, plural3_pl); plural_forms["Plural-Forms:nplurals=3;plural=(n%100==1?0:n%100==2?1:n%100==3||n%100==4?2:3);"] = PluralForms(3, plural3_sl); - + plural_forms["Plural-Forms:nplurals=3;plural=n%100==1?0:n%100==2?1:n%100==3||n%100==4?2:3;"] = PluralForms(3, plural3_sl); + plural_forms["Plural-Forms:nplurals=4;plural=(n==1?0:n==2?1:n>=3&&n<=10?2:3);"]=PluralForms(4, plural4_ar); plural_forms["Plural-Forms:nplurals=4;plural=n==1?0:n==2?1:n>=3&&n<=10?2:3;"]=PluralForms(4, plural4_ar); + plural_forms["Plural-Forms:nplurals=4;plural=((n==1||n==11)?0:(n==2||n==12)?1:(n>2&&n<20)?2:3);"]=PluralForms(4, plural4_gd); plural_forms["Plural-Forms:nplurals=4;plural=(n==1||n==11)?0:(n==2||n==12)?1:(n>2&&n<20)?2:3;"]=PluralForms(4, plural4_gd); } diff --git a/src/tracks/track_manager.cpp b/src/tracks/track_manager.cpp index e39601f7b..3a7cb0885 100644 --- a/src/tracks/track_manager.cpp +++ b/src/tracks/track_manager.cpp @@ -209,8 +209,10 @@ bool TrackManager::loadTrack(const std::string& dirname) m_track_avail.push_back(true); updateGroups(track); - //Populate the texture cache with track screenshots - irr_driver->getTexture(track->getScreenshotFile()); + // Populate the texture cache with track screenshots + // (internal tracks like end cutscene don't have screenshots) + if (!track->isInternal()) + irr_driver->getTexture(track->getScreenshotFile()); return true; } // loadTrack diff --git a/src/utils/translation.cpp b/src/utils/translation.cpp index 1202d4248..38113bf01 100644 --- a/src/utils/translation.cpp +++ b/src/utils/translation.cpp @@ -95,27 +95,22 @@ wchar_t* utf8_to_wide(const char* input) // ---------------------------------------------------------------------------- Translations::Translations() //: m_dictionary_manager("UTF-16") { - + m_dictionary_manager.add_directory( + file_manager->getAsset(FileManager::TRANSLATION,"")); + if (g_language_list.size() == 0) { - std::set flist; - file_manager->listFiles(flist, - file_manager->getAsset(FileManager::TRANSLATION,"")); - + std::set languages = m_dictionary_manager.get_languages(); + // English is always there but won't be found on file system g_language_list.push_back("en"); - - std::set::iterator it; - for ( it=flist.begin() ; it != flist.end(); it++ ) + + std::set::iterator it; + for (it = languages.begin(); it != languages.end(); it++) { - if (StringUtils::hasSuffix(*it, "po")) - { - g_language_list.push_back - (m_dictionary_manager.convertFilename2Language(*it) ); - // printf("Lang : <%s>\n", (*it).c_str()); - } - } // for it in flist - } // if (g_language_list.size() == 0) + g_language_list.push_back((*it).str()); + } + } // LC_ALL does not work, sscanf will then not always be able // to scan for example: s=-1.1,-2.3,-3.3 correctly, which is @@ -149,9 +144,6 @@ Translations::Translations() //: m_dictionary_manager("UTF-16") textdomain (PACKAGE); */ - m_dictionary_manager.add_directory( - file_manager->getAsset(FileManager::TRANSLATION,"")); - /* const std::set& languages = m_dictionary_manager.get_languages(); Log::info("Translatings", "Number of languages: %d", languages.size()); diff --git a/src/windows_installer/supertuxkart.nsi b/src/windows_installer/supertuxkart.nsi index d3c3196d4..7530cde5f 100644 --- a/src/windows_installer/supertuxkart.nsi +++ b/src/windows_installer/supertuxkart.nsi @@ -24,7 +24,7 @@ ;Name and file Name "SuperTuxKart" - OutFile "supertuxkart.exe" + OutFile "supertuxkart-installer.exe" RequestExecutionLevel admin @@ -42,6 +42,7 @@ !define MUI_UNICON "SuperTuxKart\uninstall.ico" !define MUI_HEADERIMAGE !define MUI_WELCOMEFINISHPAGE_BITMAP "stk_installer.bmp" + !define MUI_WELCOMEFINISHPAGE_BITMAP_NOSTRETCH !define MUI_HEADERIMAGE_BITMAP "logo_slim.bmp" ;!define MUI_TEXT_INSTALLING_SUBTITLE "Please vote for SuperTuxKart to become SourceForge's Project of the month at vote.supertuxkart.net" ;!define MUI_TEXT_FINISH_INFO_TEXT "Please vote for SuperTuxKart to become $\"Project of the Month$\" at vote.supertuxkart.net" @@ -67,14 +68,14 @@ Function validate_dir IfFileExists $INSTDIR\data\*.* 0 return IfFileExists $INSTDIR\Uninstall.exe 0 dont_uninstall - MessageBox MB_YESNO "You can't install SuperTuxKart 0.8.1-rc1 in an existing directory. Do you wish to run the uninstaller in $INSTDIR?" IDNO dont_uninstall + MessageBox MB_YESNO "You can't install SuperTuxKart 0.8.2 in an existing directory. Do you wish to run the uninstaller in $INSTDIR?" IDNO dont_uninstall ; -?=$INSTDIR makes sure that this installer waits for the uninstaller ; to finish. The uninstaller (and directory) are not removed, but the ; uninstaller will be overwritten by our installer anyway. ExecWait '"$INSTDIR\Uninstall.exe" _?=$INSTDIR' goto return dont_uninstall: - MessageBox MB_OK "You can't install SuperTuxKart 0.8.1-rc1 in an existing directory. Please select a new directory." + MessageBox MB_OK "You can't install SuperTuxKart 0.8.2 in an existing directory. Please select a new directory." abort return: FunctionEnd @@ -134,7 +135,8 @@ Section "Main Section" SecMain SetShellVarContext all CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER" CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\Uninstall.exe" "" "$INSTDIR\uninstall.ico" - CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\supertuxkart.lnk" "$INSTDIR\supertuxkart.exe" "" "$INSTDIR\icon.ico" + CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\supertuxkart.lnk" "$INSTDIR\supertuxkart.exe" "" "$INSTDIR\supertuxkart.ico" + CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\supertuxkart_editor.lnk" "$INSTDIR\supertuxkart_editor.exe" "" "$INSTDIR\supertuxkart_editor.ico" ShellLink::SetShortCutShowMode $SMPROGRAMS\$STARTMENU_FOLDER\supertuxkart.lnk 0 !insertmacro MUI_STARTMENU_WRITE_END @@ -160,9 +162,35 @@ SectionEnd Section "Uninstall"redist ;Removes all the supertuxkart data files - RMDir /r /REBOOTOK $INSTDIR + RMDir /r /REBOOTOK $INSTDIR\data + RMDir /r /REBOOTOK $INSTDIR\Prerequisites - Delete "$INSTDIR\Uninstall.exe" + DELETE /REBOOTOK "$INSTDIR\glew32.dll" + DELETE /REBOOTOK "$INSTDIR\install.ico" + DELETE /REBOOTOK "$INSTDIR\Irrlicht.dll" + DELETE /REBOOTOK "$INSTDIR\libcurl.dll" + DELETE /REBOOTOK "$INSTDIR\libeay32.dll" + DELETE /REBOOTOK "$INSTDIR\libidn-11.dll" + DELETE /REBOOTOK "$INSTDIR\License.txt" + DELETE /REBOOTOK "$INSTDIR\ogg.dll" + DELETE /REBOOTOK "$INSTDIR\OpenAL32.dll" + DELETE /REBOOTOK "$INSTDIR\physfs.dll" + DELETE /REBOOTOK "$INSTDIR\pthreadVC2.dll" + DELETE /REBOOTOK "$INSTDIR\ssleay32.dll" + DELETE /REBOOTOK "$INSTDIR\supertuxkart.exe" + DELETE /REBOOTOK "$INSTDIR\supertuxkart.ico" + DELETE /REBOOTOK "$INSTDIR\supertuxkart.icon" + DELETE /REBOOTOK "$INSTDIR\supertuxkart.ilk" + DELETE /REBOOTOK "$INSTDIR\supertuxkart.pdb" + DELETE /REBOOTOK "$INSTDIR\supertuxkart_editor.exe" + DELETE /REBOOTOK "$INSTDIR\supertuxkart_editor.ico" + DELETE /REBOOTOK "$INSTDIR\supertuxkart_editor.pdb" + DELETE /REBOOTOK "$INSTDIR\uninstall.ico" + DELETE /REBOOTOK "$INSTDIR\vorbis.dll" + DELETE /REBOOTOK "$INSTDIR\zlib.dll" + DELETE /REBOOTOK "$INSTDIR\zlib1.dll" + + Delete /REBOOTOK "$INSTDIR\Uninstall.exe" RMDir "$INSTDIR" SetShellVarContext all @@ -172,6 +200,7 @@ Section "Uninstall"redist Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" Delete "$SMPROGRAMS\$MUI_TEMP\supertuxkart.lnk" + Delete "$SMPROGRAMS\$MUI_TEMP\supertuxkart_editor.lnk" ;Delete empty start menu parent diretories StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP"