Ansariel 2022-03-01 08:38:19 +01:00
commit c5e258f40f
77 changed files with 3284 additions and 963 deletions

View File

@ -3,6 +3,34 @@
<map>
<key>installables</key>
<map>
<key>gstreamer10</key>
<map>
<key>copyright</key>
<string>Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</string>
<key>license</key>
<string>LGPL</string>
<key>license_file</key>
<string>LICENSES/gstreamer.txt</string>
<key>name</key>
<string>gstreamer10</string>
<key>platforms</key>
<map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>01f39ecf80dae64e30402ac384035b3e</string>
<key>url</key>
<string>http://downloads.phoenixviewer.com/gstreamer10-1.6.3.201605191852-linux-201605191852.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
</map>
<key>version</key>
<string>0.10.6.294903</string>
</map>
<key>breakpad</key>
<map>
<key>copyright</key>
@ -792,9 +820,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>96dd770f246917589b776300a2d07f9e</string>
<string>0bcccd248a5e4084af4026eee439816b</string>
<key>url</key>
<string>http://3p.firestormviewer.org/curl-7.54.1.212891029-linux64-212891029.tar.bz2</string>
<string>http://3p.firestormviewer.org/curl-7.81.0.220511906-linux64_bionic-220511906.tar.bz2</string>
</map>
<key>name</key>
<string>linux64</string>
@ -3567,30 +3595,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>name</key>
<string>darwin64</string>
</map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>9f9582031af3b78d6153ec296d6dde9f</string>
<key>url</key>
<string>http://3p.firestormviewer.org/vlc_bin-2.2.3-linux-201607071822-r16.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
<key>linux64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>5eace400c487011a678493fc520be24d</string>
<key>url</key>
<string>http://3p.firestormviewer.org/vlc_bin-2.2.3-linux-x64-201610182130-r16.tar.bz2</string>
</map>
<key>name</key>
<string>linux64</string>
</map>
<key>windows</key>
<map>
<key>archive</key>

View File

@ -112,6 +112,10 @@ if (NOT USE_BUGSPLAT)
add_subdirectory(${LIBS_OPEN_PREFIX}llcrashlogger)
endif (NOT USE_BUGSPLAT)
if( LINUX )
add_subdirectory(${VIEWER_PREFIX}linux_crash_logger)
endif()
add_subdirectory(${LIBS_OPEN_PREFIX}llplugin)
add_subdirectory(${LIBS_OPEN_PREFIX}llui)
add_subdirectory(${LIBS_OPEN_PREFIX}viewer_components)
@ -159,6 +163,10 @@ endif (USE_BUGSPLAT)
add_subdirectory(${VIEWER_PREFIX}newview)
add_dependencies(viewer firestorm-bin)
set_target_properties(
firestorm-bin PROPERTIES
VS_DEBUGGER_WORKING_DIRECTORY "..\\..\\indra\\newview")
add_subdirectory(${VIEWER_PREFIX}doxygen EXCLUDE_FROM_ALL)
if (LL_TESTS)

View File

@ -0,0 +1,32 @@
# -*- cmake -*-
include(Prebuilt)
include(GLIB)
if (USESYSTEMLIBS)
include(FindPkgConfig)
pkg_check_modules(GSTREAMER10 REQUIRED gstreamer-1.0)
pkg_check_modules(GSTREAMER10_PLUGINS_BASE REQUIRED gstreamer-plugins-base-1.0)
elseif (LINUX OR WINDOWS)
use_prebuilt_binary(gstreamer10)
use_prebuilt_binary(libxml2)
set(GSTREAMER10_FOUND ON FORCE BOOL)
set(GSTREAMER10_PLUGINS_BASE_FOUND ON FORCE BOOL)
set(GSTREAMER10_INCLUDE_DIRS
${GLIB_INCLUDE_DIRS}
${LIBS_PREBUILT_DIR}/include/gstreamer-1.0
${LIBS_PREBUILT_DIR}/include/libxml2
)
# We don't need to explicitly link against gstreamer itself, because
# LLMediaImplGStreamer probes for the system's copy at runtime.
set(GSTREAMER10_LIBRARIES)
endif (USESYSTEMLIBS)
if (GSTREAMER10_FOUND AND GSTREAMER10_PLUGINS_BASE_FOUND)
set(GSTREAMER10 ON CACHE BOOL "Build with GStreamer-1.0 streaming media support.")
endif (GSTREAMER10_FOUND AND GSTREAMER10_PLUGINS_BASE_FOUND)
if (GSTREAMER10)
add_definitions(-DLL_GSTREAMER10_ENABLED=1)
endif (GSTREAMER10)

View File

@ -35,8 +35,10 @@ if (USE_BUGSPLAT)
set(BUGSPLAT_DB "" CACHE STRING "BugSplat crash database name")
if( LINUX )
set(BUGSPLAT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/breakpad)
add_compile_definitions(__STDC_FORMAT_MACROS)
set(BUGSPLAT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/breakpad)
# <FS:ND/> Sadly we cannot have the nice things yet and need add_definitions for older cmake
#add_compile_definitions(__STDC_FORMAT_MACROS)
add_definitions(-D__STDC_FORMAT_MACROS)
else()
set(BUGSPLAT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/bugsplat)
endif()

View File

@ -3,18 +3,11 @@
project(linux_crash_logger)
include(00-Common)
include(GLH)
include(LLCoreHttp)
include(LLCommon)
include(LLCrashLogger)
include(LLMath)
include(LLMessage)
include(LLFileSystem)
include(LLXML)
include(Linking)
include(UI)
include(FreeType)
include(Boost)
include(CURL)
include(OpenSSL)
include(ZLIB)
include_directories(
${LLCOREHTTP_INCLUDE_DIRS}
@ -36,7 +29,6 @@ include_directories(SYSTEM
set(linux_crash_logger_SOURCE_FILES
linux_crash_logger.cpp
llcrashloggerlinux.cpp
)
set(linux_crash_logger_HEADER_FILES
@ -61,19 +53,13 @@ set(LIBRT_LIBRARY rt)
target_link_libraries(linux-crash-logger
${LLCRASHLOGGER_LIBRARIES}
${LLFILESYSTEM_LIBRARIES}
${LLXML_LIBRARIES}
${LLMESSAGE_LIBRARIES}
${LLMATH_LIBRARIES}
${LLCOREHTTP_LIBRARIES}
${LLCOMMON_LIBRARIES}
${BOOST_FIBER_LIBRARY}
${BOOST_CONTEXT_LIBRARY}
${UI_LIBRARIES}
${DB_LIBRARIES}
${FREETYPE_LIBRARIES}
${CURL_LIBRARIES}
${OPENSSL_LIBRARIES}
${CRYPTO_LIBRARIES}
${ZLIB_LIBRARIES}
${LIBRT_LIBRARY}
X11
)
add_custom_target(linux-crash-logger-target ALL

View File

@ -24,35 +24,77 @@
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llcrashloggerlinux.h"
#include "llsdutil.h"
#include <iostream>
#include <string>
#include <curl/curl.h>
#include <FL/fl_ask.H>
/* Called via
execl( gCrashLogger.c_str(), gCrashLogger.c_str(), descriptor.path(), gVersion.c_str(), gBugsplatDB.c_str(), nullptr );
*/
int main(int argc, char **argv)
{
LL_INFOS() << "Starting crash reporter." << LL_ENDL;
std::cerr << "linux crash logger called: ";
for( int i = 1; i < argc; ++i )
std::cerr << argv[i] << " ";
LLCrashLoggerLinux app;
app.parseCommandOptions(argc, argv);
std::cerr << std::endl;
LLSD options = LLApp::instance()->getOptionData(
LLApp::PRIORITY_COMMAND_LINE);
//LLApp::PRIORITY_RUNTIME_OVERRIDE);
if (!(options.has("pid") && options.has("dumpdir")))
if( argc < 4 )
{
LL_WARNS() << "Insufficient parameters to crash report." << LL_ENDL;
std::cerr << argv[0] << "Not enough arguments" << std::endl;
return 1;
}
if (! app.init())
std::string dmpFile{ argv[1] };
std::string version{ argv[2] };
std::string strDb{ argv[3] };
std::string strAsk{ argv[4] };
if( strAsk == "ask" )
{
LL_WARNS() << "Unable to initialize application." << LL_ENDL;
return 1;
auto choice = fl_choice( "Firestorm has crashed, submit the minidump?", "No", "Yes", nullptr );
if( choice == 0 )
{
std::cerr << "Abort send due to users choice" << std::endl;
return 0;
}
}
app.frame();
app.cleanup();
LL_INFOS() << "Crash reporter finished normally." << LL_ENDL;
return 0;
std::string url{ "https://" };
url += strDb;
url += ".bugsplat.com/post/bp/crash/crashpad.php";
curl_global_init(CURL_GLOBAL_ALL);
auto curl = curl_easy_init();
if( curl)
{
auto form = curl_mime_init(curl);
auto field = curl_mime_addpart(form);
curl_mime_name(field, "upload_file_minidump");
curl_mime_filedata(field, dmpFile.c_str() );
field = curl_mime_addpart(form);
curl_mime_name(field, "product");
curl_mime_data(field, "Firestorm-Releasex64", CURL_ZERO_TERMINATED);
field = curl_mime_addpart(form);
curl_mime_name(field, "version");
curl_mime_data(field, version.c_str(), CURL_ZERO_TERMINATED);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str() );
curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);
auto res = curl_easy_perform(curl);
if(res != CURLE_OK)
std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
curl_easy_cleanup(curl);
curl_mime_free(form);
}
return 0;
}

View File

@ -1,172 +0,0 @@
/**
* @file llcrashloggerlinux.cpp
* @brief Linux crash logger implementation
*
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llcrashloggerlinux.h"
#include <iostream>
#include "linden_common.h"
#include "indra_constants.h" // CRASH_BEHAVIOR_ASK, CRASH_SETTING_NAME
#include "llerror.h"
#include "llfile.h"
#include "lltimer.h"
#include "llstring.h"
#include "lldir.h"
#include "llsdserialize.h"
#if LL_GTK
# include "gtk/gtk.h"
#error "Direct use of GTK is deprecated"
#endif // LL_GTK
#define MAX_LOADSTRING 100
// <FS:ND> Fire-901 / Crashreporting: Brand for FS, add URL to privacy policy
// These need to be localized.
// static const char dialog_text[] =
// "Second Life appears to have crashed or frozen last time it ran.\n"
// "This crash reporter collects information about your computer's hardware, operating system, and some Second Life logs, all of which are used for debugging purposes only.\n"
// "\n"
// "Send crash report?";
//
// static const char dialog_title[] =
// "Second Life Crash Logger";
static const char dialog_text[] =
"Firestorm appears to have crashed or frozen last time it ran.\n"
"This crash reporter collects information about your computer's hardware, operating system which are used for debugging purposes only. SecondLife logs are not collected.\n"
"This report will be send to firestormviewer.org. Review our privacy policy at http://www.firestormviewer.org/privacy-policy for more information.\n"
"\n"
"Send crash report?";
static const char dialog_title[] =
"Firestorm Crash Logger";
// </FS:ND>
#if 0
#if LL_GTK
static void response_callback (GtkDialog *dialog,
gint arg1,
gpointer user_data)
{
gint *response = (gint*)user_data;
*response = arg1;
gtk_widget_destroy(GTK_WIDGET(dialog));
gtk_main_quit();
}
#endif // LL_GTK
static BOOL do_ask_dialog(void)
{
#if LL_GTK
gtk_disable_setlocale();
if (!gtk_init_check(NULL, NULL)) {
LL_INFOS() << "Could not initialize GTK for 'ask to send crash report' dialog; not sending report." << LL_ENDL;
return FALSE;
}
GtkWidget *win = NULL;
GtkDialogFlags flags = GTK_DIALOG_MODAL;
GtkMessageType messagetype = GTK_MESSAGE_QUESTION;
GtkButtonsType buttons = GTK_BUTTONS_YES_NO;
gint response = GTK_RESPONSE_NONE;
win = gtk_message_dialog_new(NULL,
flags, messagetype, buttons,
"%s", dialog_text);
gtk_window_set_type_hint(GTK_WINDOW(win),
GDK_WINDOW_TYPE_HINT_DIALOG);
gtk_window_set_title(GTK_WINDOW(win), dialog_title);
g_signal_connect (win,
"response",
G_CALLBACK (response_callback),
&response);
gtk_widget_show_all (win);
gtk_main();
return (GTK_RESPONSE_OK == response ||
GTK_RESPONSE_YES == response ||
GTK_RESPONSE_APPLY == response);
#else
return FALSE;
#endif // LL_GTK
}
#endif
LLCrashLoggerLinux::LLCrashLoggerLinux(void)
{
}
LLCrashLoggerLinux::~LLCrashLoggerLinux(void)
{
}
void LLCrashLoggerLinux::gatherPlatformSpecificFiles()
{
}
bool LLCrashLoggerLinux::frame()
{
// <FS:ND> Get around the crash logger popping up all the time.
// Right now there seems to be no easy way to test if there's logs from a real crash to send. Which
// would be preferred, as then asking for sending in data makes sense. Right now the dialog will just open always.
// bool send_logs = true;
// if(CRASH_BEHAVIOR_ASK == getCrashBehavior())
// {
// send_logs = do_ask_dialog();
// }
// else if(CRASH_BEHAVIOR_NEVER_SEND == getCrashBehavior())
// {
// send_logs = false;
// }
bool send_logs = (CRASH_BEHAVIOR_NEVER_SEND == getCrashBehavior());
// </FS:ND>
if(send_logs)
{
sendCrashLogs();
}
return true;
}
bool LLCrashLoggerLinux::cleanup()
{
commonCleanup();
mKeyMaster.releaseMaster();
return true;
}
void LLCrashLoggerLinux::updateApplication(const std::string& message)
{
LLCrashLogger::updateApplication(message);
}

View File

@ -508,7 +508,12 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
check_curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1);
check_curl_easy_setopt(mCurlHandle, CURLOPT_URL, mReqURL.c_str());
check_curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, getHandle());
// <FS:ND/> Newer versions of curl are stricter with checkinng Cotent-Encoding: header
// Aws returns Content-Encoding: binary/octet-stream which is no valid scheme defined by HTTP/1.1 (compress,deflate, gzip)
#if LIBCURL_VERSION_NUM < 0x075100
check_curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
#endif
check_curl_easy_setopt(mCurlHandle, CURLOPT_AUTOREFERER, 1);
check_curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT);

View File

@ -289,8 +289,12 @@ CURL *getCurlTemplateHandle()
check_curl_code(result, CURLOPT_NOSIGNAL);
result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_NOPROGRESS, 1);
check_curl_code(result, CURLOPT_NOPROGRESS);
// <FS:ND/> Newer versions of curl are stricter with checkinng Cotent-Encoding: header
// Aws returns Content-Encoding: binary/octet-stream which is no valid scheme defined by HTTP/1.1 (compress,deflate, gzip)
#if LIBCURL_VERSION_NUM < 0x075100
result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_ENCODING, "");
check_curl_code(result, CURLOPT_ENCODING);
#endif
result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_AUTOREFERER, 1);
check_curl_code(result, CURLOPT_AUTOREFERER);
result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_FOLLOWLOCATION, 1);

View File

@ -2,10 +2,9 @@
add_subdirectory(base)
if (LINUX)
# add_subdirectory(gstreamer010)
add_subdirectory(cef)
add_subdirectory(libvlc)
#add_subdirectory(example)
add_subdirectory(gstreamer10)
add_subdirectory(cef)
#add_subdirectory(libvlc)
endif (LINUX)
if (DARWIN)

View File

@ -0,0 +1,78 @@
# -*- cmake -*-
project(media_plugin_gstreamer10)
include(00-Common)
include(LLCommon)
include(LLImage)
include(LLPlugin)
include(LLMath)
include(LLRender)
include(LLWindow)
include(Linking)
include(PluginAPI)
include(MediaPluginBase)
include(OpenGL)
include(GLIB)
include(GStreamer10Plugin)
include_directories(
${LLPLUGIN_INCLUDE_DIRS}
${MEDIA_PLUGIN_BASE_INCLUDE_DIRS}
${LLCOMMON_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS}
${LLIMAGE_INCLUDE_DIRS}
${LLRENDER_INCLUDE_DIRS}
${LLWINDOW_INCLUDE_DIRS}
${GSTREAMER10_INCLUDE_DIRS}
${GSTREAMER10_PLUGINS_BASE_INCLUDE_DIRS}
)
include_directories(SYSTEM
${LLCOMMON_SYSTEM_INCLUDE_DIRS}
)
### media_plugin_gstreamer10
if(NOT WORD_SIZE EQUAL 32)
if(NOT WINDOWS) # not windows therefore gcc LINUX and DARWIN
add_definitions(-fPIC)
endif()
endif(NOT WORD_SIZE EQUAL 32)
set(media_plugin_gstreamer10_SOURCE_FILES
media_plugin_gstreamer10.cpp
llmediaimplgstreamer_syms.cpp
)
set(media_plugin_gstreamer10_HEADER_FILES
llmediaimplgstreamer_syms.h
llmediaimplgstreamertriviallogging.h
)
add_library(media_plugin_gstreamer10
SHARED
${media_plugin_gstreamer10_SOURCE_FILES}
)
target_link_libraries(media_plugin_gstreamer10
${LLPLUGIN_LIBRARIES}
${MEDIA_PLUGIN_BASE_LIBRARIES}
${LLCOMMON_LIBRARIES}
${PLUGIN_API_WINDOWS_LIBRARIES}
${GSTREAMER10_LIBRARIES}
)
#add_dependencies(media_plugin_gstreamer10
# ${LLPLUGIN_LIBRARIES}
# ${MEDIA_PLUGIN_BASE_LIBRARIES}
# ${LLCOMMON_LIBRARIES}
#)
if (WINDOWS)
set_target_properties(
media_plugin_gstreamer10
PROPERTIES
LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMT"
)
endif (WINDOWS)

View File

@ -0,0 +1,53 @@
/**
* @file llmediaimplgstreamer.h
* @author Tofu Linden
* @brief implementation that supports media playback via GStreamer.
*
* @cond
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
*/
// header guard
#ifndef llmediaimplgstreamer_h
#define llmediaimplgstreamer_h
#if LL_GSTREAMER010_ENABLED
extern "C" {
#include <stdio.h>
#include <gst/gst.h>
#include "apr_pools.h"
#include "apr_dso.h"
}
extern "C" {
gboolean llmediaimplgstreamer_bus_callback (GstBus *bus,
GstMessage *message,
gpointer data);
}
#endif // LL_GSTREAMER010_ENABLED
#endif // llmediaimplgstreamer_h

View File

@ -0,0 +1,197 @@
/**
* @file llmediaimplgstreamer_syms.cpp
* @brief dynamic GStreamer symbol-grabbing code
*
* @cond
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
*/
#include <string>
#include <iostream>
#include <vector>
#ifdef LL_WINDOWS
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0502
#include <Windows.h>
#endif
#include "linden_common.h"
extern "C" {
#include <gst/gst.h>
#include <gst/app/gstappsink.h>
}
#include "apr_pools.h"
#include "apr_dso.h"
#ifdef LL_WINDOWS
#ifndef _M_AMD64
#define GSTREAMER_REG_KEY "Software\\GStreamer1.0\\x86"
#define GSTREAMER_DIR_SUFFIX "1.0\\x86\\bin\\"
#else
#define GSTREAMER_REG_KEY "Software\\GStreamer1.0\\x86_64"
#define GSTREAMER_DIR_SUFFIX "1.0\\x86_64\\bin\\"
#endif
bool openRegKey( HKEY &aKey )
{
// Try native (32 bit view/64 bit view) of registry first.
if( ERROR_SUCCESS == ::RegOpenKeyExA( HKEY_LOCAL_MACHINE, GSTREAMER_REG_KEY, 0, KEY_QUERY_VALUE, &aKey ) )
return true;
// If native view fails, use 32 bit view or registry.
if( ERROR_SUCCESS == ::RegOpenKeyExA( HKEY_LOCAL_MACHINE, GSTREAMER_REG_KEY, 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &aKey ) )
return true;
return false;
}
std::string getGStreamerDir()
{
std::string ret;
HKEY hKey;
if( openRegKey( hKey ) )
{
DWORD dwLen(0);
::RegQueryValueExA( hKey, "InstallDir", nullptr, nullptr, nullptr, &dwLen );
if( dwLen > 0 )
{
std::vector< char > vctBuffer;
vctBuffer.resize( dwLen );
::RegQueryValueExA( hKey, "InstallDir", nullptr, nullptr, reinterpret_cast< LPBYTE>(&vctBuffer[ 0 ]), &dwLen );
ret = &vctBuffer[0];
if( ret[ dwLen-1 ] != '\\' )
ret += "\\";
ret += GSTREAMER_DIR_SUFFIX;
SetDllDirectoryA( ret.c_str() );
}
::RegCloseKey( hKey );
}
return ret;
}
#else
std::string getGStreamerDir() { return ""; }
#endif
#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) RTN (*ll##GSTSYM)(__VA_ARGS__) = NULL;
#include "llmediaimplgstreamer_syms_raw.inc"
#undef LL_GST_SYM
struct Symloader
{
bool mRequired;
char const *mName;
apr_dso_handle_sym_t *mPPFunc;
};
#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) { REQ, #GSTSYM , (apr_dso_handle_sym_t*)&ll##GSTSYM},
Symloader sSyms[] = {
#include "llmediaimplgstreamer_syms_raw.inc"
{ false, 0, 0 } };
#undef LL_GST_SYM
// a couple of stubs for disgusting reasons
GstDebugCategory*
ll_gst_debug_category_new(gchar *name, guint color, gchar *description)
{
static GstDebugCategory dummy;
return &dummy;
}
void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname)
{
}
static bool sSymsGrabbed = false;
static apr_pool_t *sSymGSTDSOMemoryPool = NULL;
std::vector< apr_dso_handle_t* > sLoadedLibraries;
bool grab_gst_syms( std::vector< std::string > const &aDSONames )
{
if (sSymsGrabbed)
return true;
//attempt to load the shared libraries
apr_pool_create(&sSymGSTDSOMemoryPool, NULL);
for( std::vector< std::string >::const_iterator itr = aDSONames.begin(); itr != aDSONames.end(); ++itr )
{
apr_dso_handle_t *pDSO(NULL);
std::string strDSO = getGStreamerDir() + *itr;
if( APR_SUCCESS == apr_dso_load( &pDSO, strDSO.c_str(), sSymGSTDSOMemoryPool ))
sLoadedLibraries.push_back( pDSO );
for( int i = 0; sSyms[ i ].mName; ++i )
{
if( !*sSyms[ i ].mPPFunc )
{
apr_dso_sym( sSyms[ i ].mPPFunc, pDSO, sSyms[ i ].mName );
}
}
}
std::stringstream strm;
bool sym_error = false;
for( int i = 0; sSyms[ i ].mName; ++i )
{
if( sSyms[ i ].mRequired && ! *sSyms[ i ].mPPFunc )
{
sym_error = true;
strm << sSyms[ i ].mName << std::endl;
}
}
sSymsGrabbed = !sym_error;
return sSymsGrabbed;
}
void ungrab_gst_syms()
{
// should be safe to call regardless of whether we've
// actually grabbed syms.
for( std::vector< apr_dso_handle_t* >::iterator itr = sLoadedLibraries.begin(); itr != sLoadedLibraries.end(); ++itr )
apr_dso_unload( *itr );
sLoadedLibraries.clear();
if ( sSymGSTDSOMemoryPool )
{
apr_pool_destroy(sSymGSTDSOMemoryPool);
sSymGSTDSOMemoryPool = NULL;
}
for( int i = 0; sSyms[ i ].mName; ++i )
*sSyms[ i ].mPPFunc = NULL;
sSymsGrabbed = false;
}

View File

@ -0,0 +1,68 @@
/**
* @file llmediaimplgstreamer_syms.h
* @brief dynamic GStreamer symbol-grabbing code
*
* @cond
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
*/
#include "linden_common.h"
#include <vector>
extern "C" {
#include <gst/gst.h>
}
bool grab_gst_syms( std::vector< std::string > const&);
void ungrab_gst_syms();
#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) extern RTN (*ll##GSTSYM)(__VA_ARGS__);
#include "llmediaimplgstreamer_syms_raw.inc"
#undef LL_GST_SYM
// regrettable hacks to give us better runtime compatibility with older systems
#define llg_return_if_fail(COND) do{if (!(COND)) return;}while(0)
#define llg_return_val_if_fail(COND,V) do{if (!(COND)) return V;}while(0)
// regrettable hacks because GStreamer was not designed for runtime loading
#undef GST_TYPE_MESSAGE
#define GST_TYPE_MESSAGE (llgst_message_get_type())
#undef GST_TYPE_OBJECT
#define GST_TYPE_OBJECT (llgst_object_get_type())
#undef GST_TYPE_PIPELINE
#define GST_TYPE_PIPELINE (llgst_pipeline_get_type())
#undef GST_TYPE_ELEMENT
#define GST_TYPE_ELEMENT (llgst_element_get_type())
#undef GST_TYPE_VIDEO_SINK
#define GST_TYPE_VIDEO_SINK (llgst_video_sink_get_type())
// more regrettable hacks to stub-out these .h-exposed GStreamer internals
void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname);
#undef _gst_debug_register_funcptr
#define _gst_debug_register_funcptr ll_gst_debug_register_funcptr
GstDebugCategory* ll_gst_debug_category_new(gchar *name, guint color, gchar *description);
#undef _gst_debug_category_new
#define _gst_debug_category_new ll_gst_debug_category_new
#undef __gst_debug_enabled
#define __gst_debug_enabled (0)
// more hacks
#define LLGST_MESSAGE_TYPE_NAME(M) (llgst_message_type_get_name(GST_MESSAGE_TYPE(M)))

View File

@ -0,0 +1,68 @@
LL_GST_SYM(true, gst_buffer_new, GstBuffer*, void)
LL_GST_SYM(true, gst_structure_set_value, void, GstStructure *, const gchar *, const GValue*)
LL_GST_SYM(true, gst_init_check, gboolean, int *argc, char **argv[], GError ** err)
LL_GST_SYM(true, gst_message_get_type, GType, void)
LL_GST_SYM(true, gst_message_type_get_name, const gchar*, GstMessageType type)
LL_GST_SYM(true, gst_message_parse_error, void, GstMessage *message, GError **gerror, gchar **debug)
LL_GST_SYM(true, gst_message_parse_warning, void, GstMessage *message, GError **gerror, gchar **debug)
LL_GST_SYM(true, gst_message_parse_state_changed, void, GstMessage *message, GstState *oldstate, GstState *newstate, GstState *pending)
LL_GST_SYM(true, gst_element_set_state, GstStateChangeReturn, GstElement *element, GstState state)
LL_GST_SYM(true, gst_object_unref, void, gpointer object)
LL_GST_SYM(true, gst_object_get_type, GType, void)
LL_GST_SYM(true, gst_pipeline_get_type, GType, void)
LL_GST_SYM(true, gst_pipeline_get_bus, GstBus*, GstPipeline *pipeline)
LL_GST_SYM(true, gst_bus_add_watch, guint, GstBus * bus, GstBusFunc func, gpointer user_data)
LL_GST_SYM(true, gst_element_factory_make, GstElement*, const gchar *factoryname, const gchar *name)
LL_GST_SYM(true, gst_element_get_type, GType, void)
LL_GST_SYM(true, gst_static_pad_template_get, GstPadTemplate*, GstStaticPadTemplate *pad_template)
LL_GST_SYM(true, gst_element_class_add_pad_template, void, GstElementClass *klass, GstPadTemplate *temp)
LL_GST_SYM(true, gst_caps_from_string, GstCaps *, const gchar *string)
LL_GST_SYM(true, gst_caps_get_structure, GstStructure *, const GstCaps *caps, guint index)
LL_GST_SYM(true, gst_element_register, gboolean, GstPlugin *plugin, const gchar *name, guint rank, GType type)
LL_GST_SYM(true, gst_structure_get_int, gboolean, const GstStructure *structure, const gchar *fieldname, gint *value)
LL_GST_SYM(true, gst_structure_get_value, G_CONST_RETURN GValue *, const GstStructure *structure, const gchar *fieldname)
LL_GST_SYM(true, gst_value_get_fraction_numerator, gint, const GValue *value)
LL_GST_SYM(true, gst_value_get_fraction_denominator, gint, const GValue *value)
LL_GST_SYM(true, gst_structure_get_name, G_CONST_RETURN gchar *, const GstStructure *structure)
LL_GST_SYM(true, gst_element_seek, bool, GstElement *, gdouble, GstFormat, GstSeekFlags, GstSeekType, gint64, GstSeekType, gint64)
LL_GST_SYM(false, gst_registry_fork_set_enabled, void, gboolean enabled)
LL_GST_SYM(false, gst_segtrap_set_enabled, void, gboolean enabled)
LL_GST_SYM(false, gst_message_parse_buffering, void, GstMessage *message, gint *percent)
LL_GST_SYM(false, gst_message_parse_info, void, GstMessage *message, GError **gerror, gchar **debug)
LL_GST_SYM(false, gst_element_query_position, gboolean, GstElement *element, GstFormat *format, gint64 *cur)
LL_GST_SYM(false, gst_version, void, guint *major, guint *minor, guint *micro, guint *nano)
LL_GST_SYM( true, gst_message_parse_tag, void, GstMessage *, GstTagList **)
LL_GST_SYM( true, gst_tag_list_foreach, void, const GstTagList *, GstTagForeachFunc, gpointer)
LL_GST_SYM( true, gst_tag_list_get_tag_size, guint, const GstTagList *, const gchar *)
LL_GST_SYM( true, gst_tag_list_get_value_index, const GValue *, const GstTagList *, const gchar *, guint)
LL_GST_SYM( true, gst_caps_new_simple, GstCaps*, const char *, const char*, ... )
LL_GST_SYM( true, gst_sample_get_caps, GstCaps*, GstSample* )
LL_GST_SYM( true, gst_sample_get_buffer, GstBuffer*, GstSample* )
LL_GST_SYM( true, gst_buffer_map, gboolean, GstBuffer*, GstMapInfo*, GstMapFlags )
LL_GST_SYM( true, gst_buffer_unmap, void, GstBuffer*, GstMapInfo* )
LL_GST_SYM( true, gst_app_sink_set_caps, void, GstAppSink*, GstCaps const* )
LL_GST_SYM( true, gst_app_sink_pull_sample, GstSample*, GstAppSink* )
LL_GST_SYM( true, g_free, void, gpointer )
LL_GST_SYM( true, g_error_free, void, GError* )
LL_GST_SYM( true, g_main_context_pending, gboolean, GMainContext* )
LL_GST_SYM( true, g_main_loop_get_context, GMainContext*, GMainLoop* )
LL_GST_SYM( true, g_main_context_iteration, gboolean, GMainContext*, gboolean )
LL_GST_SYM( true, g_main_loop_new, GMainLoop*, GMainContext*, gboolean )
LL_GST_SYM( true, g_main_loop_quit, void, GMainLoop* )
LL_GST_SYM( true, gst_mini_object_unref, void, GstMiniObject* )
LL_GST_SYM( true, g_object_set, void, gpointer, gchar const*, ... )
LL_GST_SYM( true, g_source_remove, gboolean, guint )
LL_GST_SYM( true, g_value_get_string, gchar const*, GValue const* )
LL_GST_SYM( true, gst_debug_set_active, void, gboolean )
LL_GST_SYM( true, gst_debug_add_log_function, void, GstLogFunction, gpointer, GDestroyNotify )
LL_GST_SYM( true, gst_debug_set_default_threshold, void, GstDebugLevel )
LL_GST_SYM( true, gst_debug_message_get , gchar const*, GstDebugMessage * )

View File

@ -0,0 +1,980 @@
/**
* @file media_plugin_gstreamer10.cpp
* @brief GStreamer-1.0 plugin for LLMedia API plugin system
*
* @cond
* $LicenseInfo:firstyear=2016&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2016, Linden Research, Inc. / Nicky Dasmijn
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
*/
#define FLIP_Y
#include "linden_common.h"
#include "llgl.h"
#include "llplugininstance.h"
#include "llpluginmessage.h"
#include "llpluginmessageclasses.h"
#include "media_plugin_base.h"
#define G_DISABLE_CAST_CHECKS
extern "C" {
#include <gst/gst.h>
#include <gst/app/gstappsink.h>
}
#include "llmediaimplgstreamer.h"
#include "llmediaimplgstreamer_syms.h"
static inline void llgst_caps_unref( GstCaps * caps )
{
llgst_mini_object_unref( GST_MINI_OBJECT_CAST( caps ) );
}
static inline void llgst_sample_unref( GstSample *aSample )
{
llgst_mini_object_unref( GST_MINI_OBJECT_CAST( aSample ) );
}
//////////////////////////////////////////////////////////////////////////////
//
class MediaPluginGStreamer10 : public MediaPluginBase
{
public:
MediaPluginGStreamer10(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
~MediaPluginGStreamer10();
/* virtual */ void receiveMessage(const char *message_string);
static bool startup();
static bool closedown();
gboolean processGSTEvents(GstBus *bus, GstMessage *message);
private:
std::string getVersion();
bool navigateTo( const std::string urlIn );
bool seek( double time_sec );
bool setVolume( float volume );
// misc
bool pause();
bool stop();
bool play(double rate);
bool getTimePos(double &sec_out);
double MIN_LOOP_SEC = 1.0F;
U32 INTERNAL_TEXTURE_SIZE = 1024;
bool mIsLooping;
enum ECommand {
COMMAND_NONE,
COMMAND_STOP,
COMMAND_PLAY,
COMMAND_FAST_FORWARD,
COMMAND_FAST_REWIND,
COMMAND_PAUSE,
COMMAND_SEEK,
};
ECommand mCommand;
private:
bool unload();
bool load();
bool update(int milliseconds);
void mouseDown( int x, int y );
void mouseUp( int x, int y );
void mouseMove( int x, int y );
static bool mDoneInit;
guint mBusWatchID;
float mVolume;
int mDepth;
// padded texture size we need to write into
int mTextureWidth;
int mTextureHeight;
bool mSeekWanted;
double mSeekDestination;
// Very GStreamer-specific
GMainLoop *mPump; // event pump for this media
GstElement *mPlaybin;
GstAppSink *mAppSink;
};
//static
bool MediaPluginGStreamer10::mDoneInit = false;
MediaPluginGStreamer10::MediaPluginGStreamer10( LLPluginInstance::sendMessageFunction host_send_func,
void *host_user_data )
: MediaPluginBase(host_send_func, host_user_data)
, mBusWatchID ( 0 )
, mSeekWanted(false)
, mSeekDestination(0.0)
, mPump ( NULL )
, mPlaybin ( NULL )
, mAppSink ( NULL )
, mCommand ( COMMAND_NONE )
{
}
gboolean MediaPluginGStreamer10::processGSTEvents(GstBus *bus, GstMessage *message)
{
if (!message)
return TRUE; // shield against GStreamer bug
switch (GST_MESSAGE_TYPE (message))
{
case GST_MESSAGE_BUFFERING:
{
// NEEDS GST 0.10.11+
if (llgst_message_parse_buffering)
{
gint percent = 0;
llgst_message_parse_buffering(message, &percent);
}
break;
}
case GST_MESSAGE_STATE_CHANGED:
{
GstState old_state;
GstState new_state;
GstState pending_state;
llgst_message_parse_state_changed(message,
&old_state,
&new_state,
&pending_state);
switch (new_state)
{
case GST_STATE_VOID_PENDING:
break;
case GST_STATE_NULL:
break;
case GST_STATE_READY:
setStatus(STATUS_LOADED);
break;
case GST_STATE_PAUSED:
setStatus(STATUS_PAUSED);
break;
case GST_STATE_PLAYING:
setStatus(STATUS_PLAYING);
break;
}
break;
}
case GST_MESSAGE_ERROR:
{
GError *err = NULL;
gchar *debug = NULL;
llgst_message_parse_error (message, &err, &debug);
if (err)
llg_error_free (err);
llg_free (debug);
mCommand = COMMAND_STOP;
setStatus(STATUS_ERROR);
break;
}
case GST_MESSAGE_INFO:
{
if (llgst_message_parse_info)
{
GError *err = NULL;
gchar *debug = NULL;
llgst_message_parse_info (message, &err, &debug);
if (err)
llg_error_free (err);
llg_free (debug);
}
break;
}
case GST_MESSAGE_WARNING:
{
GError *err = NULL;
gchar *debug = NULL;
llgst_message_parse_warning (message, &err, &debug);
if (err)
llg_error_free (err);
llg_free (debug);
break;
}
case GST_MESSAGE_EOS:
/* end-of-stream */
if (mIsLooping)
{
double eos_pos_sec = 0.0F;
bool got_eos_position = getTimePos(eos_pos_sec);
if (got_eos_position && eos_pos_sec < MIN_LOOP_SEC)
{
// if we know that the movie is really short, don't
// loop it else it can easily become a time-hog
// because of GStreamer spin-up overhead
// inject a COMMAND_PAUSE
mCommand = COMMAND_PAUSE;
}
else
{
stop();
play(1.0);
}
}
else // not a looping media
{
// inject a COMMAND_STOP
mCommand = COMMAND_STOP;
}
break;
default:
/* unhandled message */
break;
}
/* we want to be notified again the next time there is a message
* on the bus, so return true (false means we want to stop watching
* for messages on the bus and our callback should not be called again)
*/
return TRUE;
}
extern "C" {
gboolean llmediaimplgstreamer_bus_callback (GstBus *bus,
GstMessage *message,
gpointer data)
{
MediaPluginGStreamer10 *impl = (MediaPluginGStreamer10*)data;
return impl->processGSTEvents(bus, message);
}
} // extern "C"
bool MediaPluginGStreamer10::navigateTo ( const std::string urlIn )
{
if (!mDoneInit)
return false; // error
setStatus(STATUS_LOADING);
mSeekWanted = false;
if (NULL == mPump || NULL == mPlaybin)
{
setStatus(STATUS_ERROR);
return false; // error
}
llg_object_set (G_OBJECT (mPlaybin), "uri", urlIn.c_str(), NULL);
// navigateTo implicitly plays, too.
play(1.0);
return true;
}
class GstSampleUnref
{
GstSample *mT;
public:
GstSampleUnref( GstSample *aT )
: mT( aT )
{ llassert_always( mT ); }
~GstSampleUnref( )
{ llgst_sample_unref( mT ); }
};
bool MediaPluginGStreamer10::update(int milliseconds)
{
if (!mDoneInit)
return false; // error
// DEBUGMSG("updating media...");
// sanity check
if (NULL == mPump || NULL == mPlaybin)
{
return false;
}
// see if there's an outstanding seek wanted
if (mSeekWanted &&
// bleh, GST has to be happy that the movie is really truly playing
// or it may quietly ignore the seek (with rtsp:// at least).
(GST_STATE(mPlaybin) == GST_STATE_PLAYING))
{
seek(mSeekDestination);
mSeekWanted = false;
}
// *TODO: time-limit - but there isn't a lot we can do here, most
// time is spent in gstreamer's own opaque worker-threads. maybe
// we can do something sneaky like only unlock the video object
// for 'milliseconds' and otherwise hold the lock.
while (llg_main_context_pending(llg_main_loop_get_context(mPump)))
{
llg_main_context_iteration(llg_main_loop_get_context(mPump), FALSE);
}
// check for availability of a new frame
if( !mAppSink )
return true;
if( GST_STATE(mPlaybin) != GST_STATE_PLAYING) // Do not try to pull a sample if not in playing state
return true;
GstSample *pSample = llgst_app_sink_pull_sample( mAppSink );
if(!pSample)
return false; // Done playing
GstSampleUnref oSampleUnref( pSample );
GstCaps *pCaps = llgst_sample_get_caps ( pSample );
if (!pCaps)
return false;
gint width, height;
GstStructure *pStruct = llgst_caps_get_structure ( pCaps, 0);
int res = llgst_structure_get_int ( pStruct, "width", &width);
res |= llgst_structure_get_int ( pStruct, "height", &height);
if( !mPixels )
return true;
GstBuffer *pBuffer = llgst_sample_get_buffer ( pSample );
GstMapInfo map;
llgst_buffer_map ( pBuffer, &map, GST_MAP_READ);
// Our render buffer is always 1kx1k
U32 rowSkip = INTERNAL_TEXTURE_SIZE / mTextureHeight;
U32 colSkip = INTERNAL_TEXTURE_SIZE / mTextureWidth;
for (int row = 0; row < mTextureHeight; ++row)
{
U8 const *pTexelIn = map.data + (row*rowSkip * width *3);
#ifndef FLIP_Y
U8 *pTexelOut = mPixels + (row * mTextureWidth * mDepth );
#else
U8 *pTexelOut = mPixels + ((mTextureHeight-row-1) * mTextureWidth * mDepth );
#endif
for( int col = 0; col < mTextureWidth; ++col )
{
pTexelOut[ 0 ] = pTexelIn[0];
pTexelOut[ 1 ] = pTexelIn[1];
pTexelOut[ 2 ] = pTexelIn[2];
pTexelOut += mDepth;
pTexelIn += colSkip*3;
}
}
llgst_buffer_unmap( pBuffer, &map );
setDirty(0,0,mTextureWidth,mTextureHeight);
return true;
}
void MediaPluginGStreamer10::mouseDown( int x, int y )
{
// do nothing
}
void MediaPluginGStreamer10::mouseUp( int x, int y )
{
// do nothing
}
void MediaPluginGStreamer10::mouseMove( int x, int y )
{
// do nothing
}
bool MediaPluginGStreamer10::pause()
{
// todo: error-check this?
if (mDoneInit && mPlaybin)
{
llgst_element_set_state(mPlaybin, GST_STATE_PAUSED);
return true;
}
return false;
}
bool MediaPluginGStreamer10::stop()
{
// todo: error-check this?
if (mDoneInit && mPlaybin)
{
llgst_element_set_state(mPlaybin, GST_STATE_READY);
return true;
}
return false;
}
bool MediaPluginGStreamer10::play(double rate)
{
// NOTE: we don't actually support non-natural rate.
// todo: error-check this?
if (mDoneInit && mPlaybin)
{
llgst_element_set_state(mPlaybin, GST_STATE_PLAYING);
return true;
}
return false;
}
bool MediaPluginGStreamer10::setVolume( float volume )
{
// we try to only update volume as conservatively as
// possible, as many gst-plugins-base versions up to at least
// November 2008 have critical race-conditions in setting volume - sigh
if (mVolume == volume)
return true; // nothing to do, everything's fine
mVolume = volume;
if (mDoneInit && mPlaybin)
{
llg_object_set(mPlaybin, "volume", mVolume, NULL);
return true;
}
return false;
}
bool MediaPluginGStreamer10::seek(double time_sec)
{
bool success = false;
if (mDoneInit && mPlaybin)
{
success = llgst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME,
GstSeekFlags(GST_SEEK_FLAG_FLUSH |
GST_SEEK_FLAG_KEY_UNIT),
GST_SEEK_TYPE_SET, gint64(time_sec*GST_SECOND),
GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
}
return success;
}
bool MediaPluginGStreamer10::getTimePos(double &sec_out)
{
bool got_position = false;
if (mDoneInit && mPlaybin)
{
gint64 pos(0);
GstFormat timefmt = GST_FORMAT_TIME;
got_position =
llgst_element_query_position &&
llgst_element_query_position(mPlaybin,
&timefmt,
&pos);
got_position = got_position
&& (timefmt == GST_FORMAT_TIME);
// GStreamer may have other ideas, but we consider the current position
// undefined if not PLAYING or PAUSED
got_position = got_position &&
(GST_STATE(mPlaybin) == GST_STATE_PLAYING ||
GST_STATE(mPlaybin) == GST_STATE_PAUSED);
if (got_position && !GST_CLOCK_TIME_IS_VALID(pos))
{
if (GST_STATE(mPlaybin) == GST_STATE_PLAYING)
{
// if we're playing then we treat an invalid clock time
// as 0, for complicated reasons (insert reason here)
pos = 0;
}
else
{
got_position = false;
}
}
// If all the preconditions succeeded... we can trust the result.
if (got_position)
{
sec_out = double(pos) / double(GST_SECOND); // gst to sec
}
}
return got_position;
}
bool MediaPluginGStreamer10::load()
{
if (!mDoneInit)
return false; // error
setStatus(STATUS_LOADING);
mIsLooping = false;
mVolume = 0.1234567f; // minor hack to force an initial volume update
// Create a pumpable main-loop for this media
mPump = llg_main_loop_new (NULL, FALSE);
if (!mPump)
{
setStatus(STATUS_ERROR);
return false; // error
}
// instantiate a playbin element to do the hard work
mPlaybin = llgst_element_factory_make ("playbin", "");
if (!mPlaybin)
{
setStatus(STATUS_ERROR);
return false; // error
}
// get playbin's bus
GstBus *bus = llgst_pipeline_get_bus (GST_PIPELINE (mPlaybin));
if (!bus)
{
setStatus(STATUS_ERROR);
return false; // error
}
mBusWatchID = llgst_bus_add_watch (bus,
llmediaimplgstreamer_bus_callback,
this);
llgst_object_unref (bus);
mAppSink = (GstAppSink*)(llgst_element_factory_make ("appsink", ""));
GstCaps* pCaps = llgst_caps_new_simple( "video/x-raw",
"format", G_TYPE_STRING, "RGB",
"width", G_TYPE_INT, INTERNAL_TEXTURE_SIZE,
"height", G_TYPE_INT, INTERNAL_TEXTURE_SIZE,
NULL );
llgst_app_sink_set_caps( mAppSink, pCaps );
llgst_caps_unref( pCaps );
if (!mAppSink)
{
setStatus(STATUS_ERROR);
return false;
}
llg_object_set(mPlaybin, "video-sink", mAppSink, NULL);
return true;
}
bool MediaPluginGStreamer10::unload ()
{
if (!mDoneInit)
return false; // error
// stop getting callbacks for this bus
llg_source_remove(mBusWatchID);
mBusWatchID = 0;
if (mPlaybin)
{
llgst_element_set_state (mPlaybin, GST_STATE_NULL);
llgst_object_unref (GST_OBJECT (mPlaybin));
mPlaybin = NULL;
}
if (mPump)
{
llg_main_loop_quit(mPump);
mPump = NULL;
}
mAppSink = NULL;
setStatus(STATUS_NONE);
return true;
}
void LogFunction(GstDebugCategory *category, GstDebugLevel level, const gchar *file, const gchar *function, gint line, GObject *object, GstDebugMessage *message, gpointer user_data )
#ifndef LL_LINUX // Docu says we need G_GNUC_NO_INSTRUMENT, but GCC says 'error'
G_GNUC_NO_INSTRUMENT
#endif
{
#ifdef LL_LINUX
std::cerr << file << ":" << line << "(" << function << "): " << llgst_debug_message_get( message ) << std::endl;
#endif
}
//static
bool MediaPluginGStreamer10::startup()
{
// first - check if GStreamer is explicitly disabled
if (NULL != getenv("LL_DISABLE_GSTREAMER"))
return false;
// only do global GStreamer initialization once.
if (!mDoneInit)
{
ll_init_apr();
// Get symbols!
std::vector< std::string > vctDSONames;
#if LL_DARWIN
#elif LL_WINDOWS
vctDSONames.push_back( "libgstreamer-1.0-0.dll" );
vctDSONames.push_back( "libgstapp-1.0-0.dll" );
vctDSONames.push_back( "libglib-2.0-0.dll" );
vctDSONames.push_back( "libgobject-2.0-0.dll" );
#else // linux or other ELFy unixoid
vctDSONames.push_back( "libgstreamer-1.0.so.0" );
vctDSONames.push_back( "libgstapp-1.0.so.0" );
vctDSONames.push_back( "libglib-2.0.so.0" );
vctDSONames.push_back( "libgobject-2.0.so" );
#endif
if( !grab_gst_syms( vctDSONames ) )
{
return false;
}
if (llgst_segtrap_set_enabled)
{
llgst_segtrap_set_enabled(FALSE);
}
#if LL_LINUX
// Gstreamer tries a fork during init, waitpid-ing on it,
// which conflicts with any installed SIGCHLD handler...
struct sigaction tmpact, oldact;
if (llgst_registry_fork_set_enabled ) {
// if we can disable SIGCHLD-using forking behaviour,
// do it.
llgst_registry_fork_set_enabled(false);
}
else {
// else temporarily install default SIGCHLD handler
// while GStreamer initialises
tmpact.sa_handler = SIG_DFL;
sigemptyset( &tmpact.sa_mask );
tmpact.sa_flags = SA_SIGINFO;
sigaction(SIGCHLD, &tmpact, &oldact);
}
#endif // LL_LINUX
// Protect against GStreamer resetting the locale, yuck.
static std::string saved_locale;
saved_locale = setlocale(LC_ALL, NULL);
// _putenv_s( "GST_PLUGIN_PATH", "E:\\gstreamer\\1.0\\x86\\lib\\gstreamer-1.0" );
llgst_debug_set_default_threshold( GST_LEVEL_WARNING );
llgst_debug_add_log_function( LogFunction, NULL, NULL );
llgst_debug_set_active( false );
// finally, try to initialize GStreamer!
GError *err = NULL;
gboolean init_gst_success = llgst_init_check(NULL, NULL, &err);
// restore old locale
setlocale(LC_ALL, saved_locale.c_str() );
#if LL_LINUX
// restore old SIGCHLD handler
if (!llgst_registry_fork_set_enabled)
sigaction(SIGCHLD, &oldact, NULL);
#endif // LL_LINUX
if (!init_gst_success) // fail
{
if (err)
{
llg_error_free(err);
}
return false;
}
mDoneInit = true;
}
return true;
}
//static
bool MediaPluginGStreamer10::closedown()
{
if (!mDoneInit)
return false; // error
ungrab_gst_syms();
mDoneInit = false;
return true;
}
MediaPluginGStreamer10::~MediaPluginGStreamer10()
{
closedown();
}
std::string MediaPluginGStreamer10::getVersion()
{
std::string plugin_version = "GStreamer10 media plugin, GStreamer version ";
if (mDoneInit &&
llgst_version)
{
guint major, minor, micro, nano;
llgst_version(&major, &minor, &micro, &nano);
plugin_version += llformat("%u.%u.%u.%u (runtime), %u.%u.%u.%u (headers)", (unsigned int)major, (unsigned int)minor,
(unsigned int)micro, (unsigned int)nano, (unsigned int)GST_VERSION_MAJOR, (unsigned int)GST_VERSION_MINOR,
(unsigned int)GST_VERSION_MICRO, (unsigned int)GST_VERSION_NANO);
}
else
{
plugin_version += "(unknown)";
}
return plugin_version;
}
void MediaPluginGStreamer10::receiveMessage(const char *message_string)
{
LLPluginMessage message_in;
if(message_in.parse(message_string) >= 0)
{
std::string message_class = message_in.getClass();
std::string message_name = message_in.getName();
if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
{
if(message_name == "init")
{
LLPluginMessage message("base", "init_response");
LLSD versions = LLSD::emptyMap();
versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION;
message.setValueLLSD("versions", versions);
load();
message.setValue("plugin_version", getVersion());
sendMessage(message);
}
else if(message_name == "idle")
{
// no response is necessary here.
double time = message_in.getValueReal("time");
// Convert time to milliseconds for update()
update((int)(time * 1000.0f));
}
else if(message_name == "cleanup")
{
unload();
closedown();
}
else if(message_name == "shm_added")
{
SharedSegmentInfo info;
info.mAddress = message_in.getValuePointer("address");
info.mSize = (size_t)message_in.getValueS32("size");
std::string name = message_in.getValue("name");
mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
}
else if(message_name == "shm_remove")
{
std::string name = message_in.getValue("name");
SharedSegmentMap::iterator iter = mSharedSegments.find(name);
if(iter != mSharedSegments.end())
{
if(mPixels == iter->second.mAddress)
{
// This is the currently active pixel buffer. Make sure we stop drawing to it.
mPixels = NULL;
mTextureSegmentName.clear();
}
mSharedSegments.erase(iter);
}
// Send the response so it can be cleaned up.
LLPluginMessage message("base", "shm_remove_response");
message.setValue("name", name);
sendMessage(message);
}
}
else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
{
if(message_name == "init")
{
// Plugin gets to decide the texture parameters to use.
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
// lame to have to decide this now, it depends on the movie. Oh well.
mDepth = 4;
mTextureWidth = 1;
mTextureHeight = 1;
message.setValueU32("format", GL_RGBA);
message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV);
message.setValueS32("depth", mDepth);
message.setValueS32("default_width", INTERNAL_TEXTURE_SIZE );
message.setValueS32("default_height", INTERNAL_TEXTURE_SIZE );
message.setValueU32("internalformat", GL_RGBA8);
message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left.
message.setValueBoolean("allow_downsample", true); // we respond with grace and performance if asked to downscale
sendMessage(message);
}
else if(message_name == "size_change")
{
std::string name = message_in.getValue("name");
S32 width = message_in.getValueS32("width");
S32 height = message_in.getValueS32("height");
S32 texture_width = message_in.getValueS32("texture_width");
S32 texture_height = message_in.getValueS32("texture_height");
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
message.setValue("name", name);
message.setValueS32("width", width);
message.setValueS32("height", height);
message.setValueS32("texture_width", texture_width);
message.setValueS32("texture_height", texture_height);
sendMessage(message);
if(!name.empty())
{
// Find the shared memory region with this name
SharedSegmentMap::iterator iter = mSharedSegments.find(name);
if(iter != mSharedSegments.end())
{
mPixels = (unsigned char*)iter->second.mAddress;
mTextureSegmentName = name;
mTextureWidth = texture_width;
mTextureHeight = texture_height;
memset( mPixels, 0, mTextureWidth*mTextureHeight*mDepth );
}
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request");
message.setValue("name", mTextureSegmentName);
message.setValueS32("width", INTERNAL_TEXTURE_SIZE );
message.setValueS32("height", INTERNAL_TEXTURE_SIZE );
sendMessage(message);
}
}
else if(message_name == "load_uri")
{
std::string uri = message_in.getValue("uri");
navigateTo( uri );
sendStatus();
}
else if(message_name == "mouse_event")
{
std::string event = message_in.getValue("event");
S32 x = message_in.getValueS32("x");
S32 y = message_in.getValueS32("y");
if(event == "down")
{
mouseDown(x, y);
}
else if(event == "up")
{
mouseUp(x, y);
}
else if(event == "move")
{
mouseMove(x, y);
};
};
}
else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
{
if(message_name == "stop")
{
stop();
}
else if(message_name == "start")
{
double rate = 0.0;
if(message_in.hasValue("rate"))
{
rate = message_in.getValueReal("rate");
}
// NOTE: we don't actually support rate.
play(rate);
}
else if(message_name == "pause")
{
pause();
}
else if(message_name == "seek")
{
double time = message_in.getValueReal("time");
// defer the actual seek in case we haven't
// really truly started yet in which case there
// is nothing to seek upon
mSeekWanted = true;
mSeekDestination = time;
}
else if(message_name == "set_loop")
{
bool loop = message_in.getValueBoolean("loop");
mIsLooping = loop;
}
else if(message_name == "set_volume")
{
double volume = message_in.getValueReal("volume");
setVolume(volume);
}
}
}
}
int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
{
if( MediaPluginGStreamer10::startup() )
{
MediaPluginGStreamer10 *self = new MediaPluginGStreamer10(host_send_func, host_user_data);
*plugin_send_func = MediaPluginGStreamer10::staticReceiveMessage;
*plugin_user_data = (void*)self;
return 0; // okay
}
else
{
return -1; // failed to init
}
}

View File

@ -1864,6 +1864,8 @@ if (WINDOWS)
COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}"
)
set_source_files_properties( llappviewer.cpp llviewermenu.cpp PROPERTIES COMPILE_FLAGS /bigobj )
list(APPEND viewer_HEADER_FILES
llappviewerwin32.h
llwindebug.h
@ -2565,26 +2567,30 @@ if (LINUX)
set(product Firestorm-${ARCH}-${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION})
# These are the generated targets that are copied to package/
if (NOT ENABLE_MEDIA_PLUGINS)
set(COPY_INPUT_DEPENDENCIES
${VIEWER_BINARY_NAME}
SLPlugin
media_plugin_cef
#media_plugin_gstreamer010
media_plugin_libvlc
llcommon
)
else (NOT ENABLE_MEDIA_PLUGINS)
set(COPY_INPUT_DEPENDENCIES
${VIEWER_BINARY_NAME}
#linux-crash-logger
SLPlugin
media_plugin_cef
#media_plugin_gstreamer010
llcommon
)
endif (NOT ENABLE_MEDIA_PLUGINS)
if (NOT ENABLE_MEDIA_PLUGINS)
set(COPY_INPUT_DEPENDENCIES
${VIEWER_BINARY_NAME}
SLPlugin
media_plugin_cef
media_plugin_gstreamer10
#media_plugin_libvlc
llcommon
linux-crash-logger
)
else (NOT ENABLE_MEDIA_PLUGINS)
set(COPY_INPUT_DEPENDENCIES
${VIEWER_BINARY_NAME}
#linux-crash-logger
SLPlugin
media_plugin_cef
media_plugin_gstreamer10
llcommon
linux-crash-logger
)
endif (NOT ENABLE_MEDIA_PLUGINS)
add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_gstreamer10 media_plugin_cef linux-crash-logger)
add_custom_command(
OUTPUT ${product}.tar.bz2
COMMAND ${PYTHON_EXECUTABLE}
@ -2610,7 +2616,6 @@ endif (NOT ENABLE_MEDIA_PLUGINS)
${COPY_INPUT_DEPENDENCIES}
)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.copy_touched
COMMAND ${PYTHON_EXECUTABLE}
@ -2861,8 +2866,10 @@ if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIE
endif (LINUX)
endif (USE_BUGSPLAT)
# for both Bugsplat and Breakpad
add_dependencies(llpackage generate_symbols)
if (NOT LINUX) #Linux generates symbols via viewer_manifest.py/fs_viewer_manifest.py
# for both Bugsplat and Breakpad
add_dependencies(llpackage generate_symbols)
endif()
endif ()
if (LL_TESTS)

View File

@ -25946,6 +25946,17 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>FSAutoTuneLock</key>
<map>
<key>Comment</key>
<string>When enabled the viewer will dynamically change settings until auto tune is explicitly turned off.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>FSAllowSelfImpostor</key>
@ -26025,6 +26036,17 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Value</key>
<integer>0</integer>
</map>
<key>FSUserTargetReflections</key>
<map>
<key>Comment</key>
<string>Set by auto tune floater on build</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>4</integer>
</map>
<key>FSReportRegionRestartToChat</key>
<map>
<key>Comment</key>

View File

@ -198,17 +198,17 @@ class FSViewerManifest:
from shutil import rmtree
import tarfile
#if isdir( "symbols" ):
# rmtree( "symbols" )
if isdir( "symbols" ):
rmtree( "symbols" )
#files = glob( "%s/bin/*" % self.args['dest'] )
#for f in files:
# self.fs_generate_breakpad_symbols_for_file( f )
#files = glob( "%s/lib/*.so" % self.args['dest'] )
#for f in files:
# self.fs_generate_breakpad_symbols_for_file( f )
files = glob( "%s/bin/*" % self.args['dest'] )
for f in files:
self.fs_generate_breakpad_symbols_for_file( f )
files = glob( "%s/lib/*.so" % self.args['dest'] )
for f in files:
if f.find( "libcef.so" ) == -1:
self.fs_generate_breakpad_symbols_for_file( f )
if isdir( "symbols" ):
for a in self.args:

View File

@ -51,8 +51,12 @@
#include "pipeline.h"
#include "llviewercontrol.h"
#include "fsavatarrenderpersistence.h"
#include "llpresetsmanager.h"
#include "fsperfstats.h" // <FS:Beq> performance stats support
#include "fslslbridge.h"
#include <llbutton.h>
extern F32 gSavedDrawDistance;
const F32 REFRESH_INTERVAL = 1.0f;
const S32 BAR_LEFT_PAD = 2;
@ -119,8 +123,11 @@ BOOL FSFloaterPerformance::postBuild()
auto tgt_panel = findChild<LLPanel>("target_subpanel");
if (tgt_panel)
{
tgt_panel->getChild<LLButton>("target_btn")->setCommitCallback(boost::bind(&FSFloaterPerformance::showSelectedPanel, this, mAutoTunePanel));
tgt_panel->getChild<LLComboBox>("FSTuningFPSStrategy")->setCurrentByIndex(gSavedSettings.getU32("FSTuningFPSStrategy"));
tgt_panel->getChild<LLButton>("target_btn")->setCommitCallback(boost::bind(&FSFloaterPerformance::showSelectedPanel, this, mAutoTunePanel));
tgt_panel->getChild<LLComboBox>("FSTuningFPSStrategy")->setCurrentByIndex(gSavedSettings.getU32("FSTuningFPSStrategy"));
tgt_panel->getChild<LLButton>("PrefSaveButton")->setCommitCallback(boost::bind(&FSFloaterPerformance::savePreset, this));
tgt_panel->getChild<LLButton>("PrefLoadButton")->setCommitCallback(boost::bind(&FSFloaterPerformance::loadPreset, this));
tgt_panel->getChild<LLButton>("Defaults")->setCommitCallback(boost::bind(&FSFloaterPerformance::setHardwareDefaults, this));
}
initBackBtn(mNearbyPanel);
@ -146,6 +153,7 @@ BOOL FSFloaterPerformance::postBuild()
mNearbyPanel->getChild<LLCheckBoxCtrl>("hide_avatars")->set(!LLPipeline::hasRenderTypeControl(LLPipeline::RENDER_TYPE_AVATAR));
mNearbyList = mNearbyPanel->getChild<LLNameListCtrl>("nearby_list");
mNearbyList->setRightMouseDownCallback(boost::bind(&FSFloaterPerformance::onAvatarListRightClick, this, _1, _2, _3));
updateComplexityText();
mComplexityChangedSignal = gSavedSettings.getControl("RenderAvatarMaxComplexity")->getCommitSignal()->connect(boost::bind(&FSFloaterPerformance::updateComplexityText, this));
@ -155,10 +163,53 @@ BOOL FSFloaterPerformance::postBuild()
mNearbyPanel->getChild<LLSliderCtrl>("FSRenderAvatarMaxART")->setCommitCallback(boost::bind(&FSFloaterPerformance::updateMaxRenderTime, this));
LLAvatarComplexityControls::setIndirectMaxArc();
// store the current setting as the users desired reflection detail and DD
gSavedSettings.setS32("FSUserTargetReflections", LLPipeline::RenderReflectionDetail);
if(!FSPerfStats::tunables.userAutoTuneEnabled)
{
if (gSavedDrawDistance)
{
gSavedSettings.setF32("FSAutoTuneRenderFarClipTarget", gSavedDrawDistance);
}
else
{
gSavedSettings.setF32("FSAutoTuneRenderFarClipTarget", LLPipeline::RenderFarClip);
}
}
return TRUE;
}
void FSFloaterPerformance::resetMaxArtSlider()
{
FSPerfStats::renderAvatarMaxART_ns = 0;
FSPerfStats::tunables.updateSettingsFromRenderCostLimit();
FSPerfStats::tunables.applyUpdates();
updateMaxRenderTime();
}
void FSFloaterPerformance::savePreset()
{
LLFloaterReg::showInstance("save_pref_preset", "graphic" );
}
void FSFloaterPerformance::loadPreset()
{
LLFloaterReg::showInstance("load_pref_preset", "graphic");
resetMaxArtSlider();
}
void FSFloaterPerformance::setHardwareDefaults()
{
LLFeatureManager::getInstance()->applyRecommendedSettings();
// reset indirects before refresh because we may have changed what they control
LLAvatarComplexityControls::setIndirectControls();
gSavedSettings.setString("PresetGraphicActive", "");
LLPresetsManager::getInstance()->triggerChangeSignal();
resetMaxArtSlider();
}
void FSFloaterPerformance::showSelectedPanel(LLPanel* selected_panel)
{
hidePanels();
@ -284,7 +335,7 @@ void FSFloaterPerformance::draw()
textbox->setColor(LLUIColorTable::instance().getColor("DrYellow"));
unreliable = true;
}
else if (FSPerfStats::autoTune)
else if (FSPerfStats::tunables.userAutoTuneEnabled)
{
textbox->setVisible(true);
textbox->setText(getString("tuning_fps", args));
@ -295,7 +346,12 @@ void FSFloaterPerformance::draw()
textbox->setVisible(false);
}
if (FSPerfStats::autoTune && !unreliable )
auto button = getChild<LLButton>("AutoTuneFPS");
if((bool)button->getToggleState() != FSPerfStats::tunables.userAutoTuneEnabled)
{
button->toggleState();
}
if (FSPerfStats::tunables.userAutoTuneEnabled && !unreliable )
{
// the tuning itself is managed from another thread but we can report progress here

View File

@ -55,6 +55,10 @@ public:
void onCustomAction (const LLSD& userdata, const LLUUID& av_id);
bool isActionChecked(const LLSD& userdata, const LLUUID& av_id);
void onExtendedAction(const LLSD& userdata, const LLUUID& av_id);
void resetMaxArtSlider();
void savePreset();
void loadPreset();
void setHardwareDefaults();
private:
void initBackBtn(LLPanel* panel);

View File

@ -32,6 +32,7 @@
#include "llagentcamera.h"
#include "llvoavatar.h"
#include "llworld.h"
#include <llthread.h>
extern LLControlGroup gSavedSettings;
@ -47,11 +48,10 @@ namespace FSPerfStats
#endif
std::atomic<int64_t> tunedAvatars{0};
U32 targetFPS; // desired FPS
U64 renderAvatarMaxART_ns{(U64)(ART_UNLIMITED_NANOS)}; // highest render time we'll allow without culling features
std::atomic<U64> renderAvatarMaxART_ns{(U64)(ART_UNLIMITED_NANOS)}; // highest render time we'll allow without culling features
bool belowTargetFPS{false};
U32 lastGlobalPrefChange{0};
std::mutex bufferToggleLock{};
bool autoTune{false};
Tunables tunables;
@ -65,9 +65,69 @@ namespace FSPerfStats
void Tunables::applyUpdates()
{
assert_main_thread();
if( tuningFlag & NonImposters ){ gSavedSettings.setU32("IndirectMaxNonImpostors", nonImposters); };
// these following variables are proxies for pipeline statics we do not need a two way update (no llviewercontrol handler)
if( tuningFlag & NonImpostors ){ gSavedSettings.setU32("IndirectMaxNonImpostors", nonImpostors); };
if( tuningFlag & ReflectionDetail ){ gSavedSettings.setS32("RenderReflectionDetail", reflectionDetail); };
if( tuningFlag & FarClip ){ gSavedSettings.setF32("RenderFarClip", farClip); };
if( tuningFlag & UserMinDrawDistance ){ gSavedSettings.setF32("FSAutoTuneRenderFarClipMin", userMinDrawDistance); };
if( tuningFlag & UserTargetDrawDistance ){ gSavedSettings.setF32("FSAutoTuneRenderFarClipTarget", userTargetDrawDistance); };
if( tuningFlag & UserImpostorDistance ){ gSavedSettings.setF32("FSAutoTuneImpostorFarAwayDistance", userImpostorDistance); };
if( tuningFlag & UserImpostorDistanceTuningEnabled ){ gSavedSettings.setBOOL("FSAutoTuneImpostorByDistEnabled", userImpostorDistanceTuningEnabled); };
if( tuningFlag & UserFPSTuningStrategy ){ gSavedSettings.setU32("FSTuningFPSStrategy", userFPSTuningStrategy); };
if( tuningFlag & UserAutoTuneEnabled ){ gSavedSettings.setBOOL("FSAutoTuneFPS", userAutoTuneEnabled); };
if( tuningFlag & UserAutoTuneLock ){ gSavedSettings.setBOOL("FSAutoTuneLock", userAutoTuneLock); };
if( tuningFlag & UserTargetFPS ){ gSavedSettings.setU32("FSTargetFPS", userTargetFPS); };
if( tuningFlag & UserTargetReflections ){ gSavedSettings.setS32("FSUserTargetReflections", userTargetReflections); };
// Note: The Max ART slider is logarithmic and thus we have an intermediate proxy value
if( tuningFlag & UserARTCutoff ){ gSavedSettings.setF32("FSRenderAvatarMaxART", userARTCutoffSliderValue); };
resetChanges();
}
void Tunables::updateRenderCostLimitFromSettings()
{
assert_main_thread();
const auto newval = gSavedSettings.getF32("FSRenderAvatarMaxART");
if(newval < log10(FSPerfStats::ART_UNLIMITED_NANOS/1000))
{
FSPerfStats::renderAvatarMaxART_ns = pow(10,newval)*1000;
}
else
{
FSPerfStats::renderAvatarMaxART_ns = 0;
};
}
// static
void Tunables::updateSettingsFromRenderCostLimit()
{
if( userARTCutoffSliderValue != log10( ( (F32)FSPerfStats::renderAvatarMaxART_ns )/1000 ) )
{
if( FSPerfStats::renderAvatarMaxART_ns != 0 )
{
updateUserARTCutoffSlider(log10( ( (F32)FSPerfStats::renderAvatarMaxART_ns )/1000 ) );
}
else
{
updateUserARTCutoffSlider(log10( (F32)FSPerfStats::ART_UNLIMITED_NANOS/1000 ) );
}
}
}
void Tunables::initialiseFromSettings()
{
assert_main_thread();
// the following variables are two way and have "push" in llviewercontrol
FSPerfStats::tunables.userMinDrawDistance = gSavedSettings.getF32("FSAutoTuneRenderFarClipMin");
FSPerfStats::tunables.userTargetDrawDistance = gSavedSettings.getF32("FSAutoTuneRenderFarClipTarget");
FSPerfStats::tunables.userImpostorDistance = gSavedSettings.getF32("FSAutoTuneImpostorFarAwayDistance");
FSPerfStats::tunables.userImpostorDistanceTuningEnabled = gSavedSettings.getBOOL("FSAutoTuneImpostorByDistEnabled");
FSPerfStats::tunables.userFPSTuningStrategy = gSavedSettings.getU32("FSTuningFPSStrategy");
FSPerfStats::tunables.userTargetFPS = gSavedSettings.getU32("FSTargetFPS");
FSPerfStats::tunables.userTargetReflections = gSavedSettings.getU32("FSUserTargetReflections");
FSPerfStats::tunables.userAutoTuneEnabled = gSavedSettings.getBOOL("FSAutoTuneFPS");
FSPerfStats::tunables.userAutoTuneLock = gSavedSettings.getBOOL("FSAutoTuneLock");
// Note: The Max ART slider is logarithmic and thus we have an intermediate proxy value
updateRenderCostLimitFromSettings();
resetChanges();
}
@ -75,12 +135,7 @@ namespace FSPerfStats
{
// create a queue
// create a thread to consume from the queue
FSPerfStats::targetFPS = gSavedSettings.getU32("FSTargetFPS");
FSPerfStats::autoTune = gSavedSettings.getBOOL("FSAutoTuneFPS");
updateRenderCostLimitFromSettings();
tunables.initialiseFromSettings();
t.detach();
}
@ -91,8 +146,7 @@ namespace FSPerfStats
using ST = StatType_t;
bool unreliable{false};
static LLCachedControl<U32> smoothingPeriods(gSavedSettings, "FSPerfFloaterSmoothingPeriods");
FSPerfStats::StatsRecorder::getSceneStat(FSPerfStats::StatType_t::RENDER_FRAME);
auto& sceneStats = statsDoubleBuffer[writeBuffer][static_cast<size_t>(ObjType_t::OT_GENERAL)][LLUUID::null];
auto& lastStats = statsDoubleBuffer[writeBuffer ^ 1][static_cast<size_t>(ObjType_t::OT_GENERAL)][LLUUID::null];
@ -129,7 +183,7 @@ namespace FSPerfStats
{
auto avg = lastStats[static_cast<size_t>(statEntry)];
auto val = sceneStats[static_cast<size_t>(statEntry)];
sceneStats[static_cast<size_t>(statEntry)] = avg + (val/smoothingPeriods) - (avg/smoothingPeriods);
sceneStats[static_cast<size_t>(statEntry)] = avg + (val / SMOOTHING_PERIODS) - (avg / SMOOTHING_PERIODS);
// LL_INFOS("scenestats") << "Scenestat: " << static_cast<size_t>(statEntry) << " before=" << avg << " new=" << val << " newavg=" << statsDoubleBuffer[writeBuffer][static_cast<size_t>(ObjType_t::OT_GENERAL)][LLUUID::null][static_cast<size_t>(statEntry)] << LL_ENDL;
}
@ -137,9 +191,9 @@ namespace FSPerfStats
for(auto& stat_entry : statsMap)
{
auto val = stat_entry.second[static_cast<size_t>(ST::RENDER_COMBINED)];
if(val>smoothingPeriods){
if(val > SMOOTHING_PERIODS){
auto avg = statsDoubleBuffer[writeBuffer ^ 1][static_cast<size_t>(ObjType_t::OT_ATTACHMENT)][stat_entry.first][static_cast<size_t>(ST::RENDER_COMBINED)];
stat_entry.second[static_cast<size_t>(ST::RENDER_COMBINED)] = avg + (val/smoothingPeriods) - (avg/smoothingPeriods);
stat_entry.second[static_cast<size_t>(ST::RENDER_COMBINED)] = avg + (val / SMOOTHING_PERIODS) - (avg / SMOOTHING_PERIODS);
}
}
@ -150,10 +204,10 @@ namespace FSPerfStats
for(auto& stat : avatarStatsToAvg)
{
auto val = stat_entry.second[static_cast<size_t>(stat)];
if(val>smoothingPeriods)
if(val > SMOOTHING_PERIODS)
{
auto avg = statsDoubleBuffer[writeBuffer ^ 1][static_cast<size_t>(ObjType_t::OT_AVATAR)][stat_entry.first][static_cast<size_t>(stat)];
stat_entry.second[static_cast<size_t>(stat)] = avg + (val/smoothingPeriods) - (avg/smoothingPeriods);
stat_entry.second[static_cast<size_t>(stat)] = avg + (val / SMOOTHING_PERIODS) - (avg / SMOOTHING_PERIODS);
}
}
}
@ -185,7 +239,7 @@ namespace FSPerfStats
}
// and now adjust the proxy vars so that the main thread can adjust the visuals.
if(autoTune)
if(tunables.userAutoTuneEnabled)
{
updateAvatarParams();
}
@ -238,37 +292,6 @@ namespace FSPerfStats
}
}
// static
void StatsRecorder::updateSettingsFromRenderCostLimit()
{
static LLCachedControl<F32> maxRenderCost_us(gSavedSettings, "FSRenderAvatarMaxART");
if( (F32)maxRenderCost_us != log10( ( (F32)FSPerfStats::renderAvatarMaxART_ns )/1000 ) )
{
if( FSPerfStats::renderAvatarMaxART_ns != 0 )
{
gSavedSettings.setF32( "FSRenderAvatarMaxART", log10( ( (F32)FSPerfStats::renderAvatarMaxART_ns )/1000 ) );
}
else
{
gSavedSettings.setF32( "FSRenderAvatarMaxART",log10( FSPerfStats::ART_UNLIMITED_NANOS/1000 ) );
}
}
}
// static
void StatsRecorder::updateRenderCostLimitFromSettings()
{
const auto newval = gSavedSettings.getF32("FSRenderAvatarMaxART");
if(newval < log10(FSPerfStats::ART_UNLIMITED_NANOS/1000))
{
FSPerfStats::renderAvatarMaxART_ns = pow(10,newval)*1000;
}
else
{
FSPerfStats::renderAvatarMaxART_ns = 0;
};
}
//static
int StatsRecorder::countNearbyAvatars(S32 distance)
{
@ -283,23 +306,16 @@ namespace FSPerfStats
// static
void StatsRecorder::updateAvatarParams()
{
static LLCachedControl<F32> drawDistance(gSavedSettings, "RenderFarClip");
static LLCachedControl<F32> userMinDrawDistance(gSavedSettings, "FSAutoTuneRenderFarClipMin");
static LLCachedControl<F32> userTargetDrawDistance(gSavedSettings, "FSAutoTuneRenderFarClipTarget");
static LLCachedControl<F32> impostorDistance(gSavedSettings, "FSAutoTuneImpostorFarAwayDistance");
static LLCachedControl<bool> impostorDistanceTuning(gSavedSettings, "FSAutoTuneImpostorByDistEnabled");
static LLCachedControl<U32> maxNonImpostors (gSavedSettings, "IndirectMaxNonImpostors");
static LLCachedControl<U32> fpsTuningStrategy (gSavedSettings, "FSTuningFPSStrategy");
if(impostorDistanceTuning)
if(tunables.userImpostorDistanceTuningEnabled)
{
// if we have less than the user's "max Non-Impostors" avatars within the desired range then adjust the limit.
// also adjusts back up again for nearby crowds.
auto count = countNearbyAvatars(std::min(drawDistance, impostorDistance));
if( count != maxNonImpostors )
auto count = countNearbyAvatars(std::min(LLPipeline::RenderFarClip, tunables.userImpostorDistance));
if( count != tunables.nonImpostors )
{
tunables.updateNonImposters( (count < LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER)?count : LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER );
LL_DEBUGS("AutoTune") << "There are " << count << "avatars within " << std::min(drawDistance, impostorDistance) << "m of the camera" << LL_ENDL;
LL_DEBUGS("AutoTune") << "There are " << count << "avatars within " << std::min(LLPipeline::RenderFarClip, tunables.userImpostorDistance) << "m of the camera" << LL_ENDL;
}
}
@ -326,44 +342,51 @@ namespace FSPerfStats
}
// The frametime budget we have based on the target FPS selected
auto target_frame_time_raw = (U64)llround((F64)LLTrace::BlockTimer::countsPerSecond()/(targetFPS==0?1:targetFPS));
auto target_frame_time_raw = (U64)llround((F64)LLTrace::BlockTimer::countsPerSecond()/(tunables.userTargetFPS==0?1:tunables.userTargetFPS));
// LL_INFOS() << "Effective FPS(raw):" << tot_frame_time_raw << " Target:" << target_frame_time_raw << LL_ENDL;
auto inferredFPS{1000/(U32)std::max(raw_to_ms(tot_frame_time_raw),1.0)};
U32 settingsChangeFrequency{inferredFPS > 25?inferredFPS:25};
if( tot_limit_time_raw != 0)
{
// This could be problematic.
tot_frame_time_raw -= tot_limit_time_raw;
}
// 1) Is the target frame tim lower than current?
// 1) Is the target frame time lower than current?
if( target_frame_time_raw <= tot_frame_time_raw )
{
if(belowTargetFPS == false)
{
// this is the first frame under. hold fire to add a little hysteresis
belowTargetFPS = true;
FSPerfStats::lastGlobalPrefChange = gFrameCount;
}
// if so we've got work to do
// how much of the frame was spent on non avatar related work?
U32 non_avatar_time_raw = tot_frame_time_raw - tot_avatar_time_raw;
// If the target frame time < non avatar frame time thne adjusting avatars is only goin gto get us so far.
// If the target frame time < scene time (estimated as non_avatar time)
U64 target_avatar_time_raw;
if(target_frame_time_raw < non_avatar_time_raw)
{
// we cannnot do this by avatar adjustment alone.
if((gFrameCount - FSPerfStats::lastGlobalPrefChange) > 10) // give changes a short time to take effect.
if((gFrameCount - FSPerfStats::lastGlobalPrefChange) > settingsChangeFrequency) // give changes a short time to take effect.
{
if(fpsTuningStrategy == 1)
if(tunables.userFPSTuningStrategy == TUNE_SCENE_AND_AVATARS)
{
// 1 - hack the water to opaque. all non opaque have a significant hit, this is a big boost for (arguably) a minor visual hit.
// the other reflection options make comparatively little change and iof this overshoots we'll be stepping back up later
// the other reflection options make comparatively little change and if this overshoots we'll be stepping back up later
if(LLPipeline::RenderReflectionDetail != -2)
{
FSPerfStats::tunables.updateReflectionDetail(-2);
FSPerfStats::lastGlobalPrefChange = gFrameCount;
return;
}
else // deliberately "else" here so we only do these in steps
else // deliberately "else" here so we only do one of these in any given frame
{
// step down the DD by 10m per update
auto new_dd = (drawDistance-10>userMinDrawDistance)?(drawDistance - 10) : userMinDrawDistance;
if(new_dd != drawDistance)
auto new_dd = (LLPipeline::RenderFarClip - DD_STEP > tunables.userMinDrawDistance)?(LLPipeline::RenderFarClip - DD_STEP) : tunables.userMinDrawDistance;
if(new_dd != LLPipeline::RenderFarClip)
{
FSPerfStats::tunables.updateFarClip( new_dd );
FSPerfStats::lastGlobalPrefChange = gFrameCount;
@ -371,26 +394,28 @@ namespace FSPerfStats
}
}
}
// if we reach here, we've no more changes to make to tune scenery so we'll resort to agressive Avatar tuning
// Note: moved from outside "if changefrequency elapsed" to stop fallthrough and allow scenery changes time to take effect.
target_avatar_time_raw = 0;
}
else
{
// we made a settings change recently so let's give it time.
return;
}
target_avatar_time_raw = 0;
}
else
{
// desired avatar budget.
// set desired avatar budget.
target_avatar_time_raw = target_frame_time_raw - non_avatar_time_raw;
}
if( target_avatar_time_raw < tot_avatar_time_raw )
{
// we need to spend less time drawing avatars to meet our budget
// Note: working in usecs now cos reasons.
auto new_render_limit_ns {renderAvatarMaxART_ns};
auto new_render_limit_ns {FSPerfStats::raw_to_ns(av_render_max_raw)};
// max render this frame may be higher than the last (cos new entrants and jitter) so make sure we are heading in the right direction
if(FSPerfStats::raw_to_ns(av_render_max_raw) < renderAvatarMaxART_ns)
{
new_render_limit_ns = FSPerfStats::raw_to_ns(av_render_max_raw);
}
else
if( new_render_limit_ns > renderAvatarMaxART_ns )
{
new_render_limit_ns = renderAvatarMaxART_ns;
}
@ -400,30 +425,55 @@ namespace FSPerfStats
new_render_limit_ns = std::max((U64)new_render_limit_ns, (U64)FSPerfStats::ART_MINIMUM_NANOS);
// assign the new value
renderAvatarMaxART_ns = new_render_limit_ns;
if(renderAvatarMaxART_ns != new_render_limit_ns)
{
renderAvatarMaxART_ns = new_render_limit_ns;
tunables.updateSettingsFromRenderCostLimit();
}
// LL_DEBUGS() << "AUTO_TUNE: avatar_budget adjusted to:" << new_render_limit_ns << LL_ENDL;
}
// LL_DEBUGS() << "AUTO_TUNE: Target frame time:"<< FSPerfStats::raw_to_us(target_frame_time_raw) << "usecs (non_avatar is " << FSPerfStats::raw_to_us(non_avatar_time_raw) << "usecs) Max cost limited=" << renderAvatarMaxART_ns << LL_ENDL;
}
else if( FSPerfStats::raw_to_ns(target_frame_time_raw) > (FSPerfStats::raw_to_ns(tot_frame_time_raw) + renderAvatarMaxART_ns) )
{
if( FSPerfStats::tunedAvatars >= 0 )
if(belowTargetFPS == true)
{
// if we have more time to spare let's shift up little in the hope we'll restore an avatar.
renderAvatarMaxART_ns += FSPerfStats::ART_MIN_ADJUST_UP_NANOS;
// we reached target, force a pause
lastGlobalPrefChange = gFrameCount;
belowTargetFPS = false;
}
if( drawDistance < userTargetDrawDistance )
// once we're over the FPS target we slow down further
if((gFrameCount - lastGlobalPrefChange) > settingsChangeFrequency*3)
{
FSPerfStats::tunables.updateFarClip( drawDistance + 10. );
}
if( (target_frame_time_raw * 1.5) > tot_frame_time_raw &&
FSPerfStats::tunedAvatars == 0 &&
drawDistance >= userTargetDrawDistance)
{
// if everything else is "max" and we have 50% headroom let's knock the water quality up a notch at a time.
FSPerfStats::tunables.updateReflectionDetail( gSavedSettings.getS32("RenderReflectionDetail") + 1 );
if(!tunables.userAutoTuneLock)
{
// we've reached the target and stayed long enough to consider stable.
// turn off if we are not locked.
tunables.updateUserAutoTuneEnabled(false);
}
if( FSPerfStats::tunedAvatars > 0 )
{
// if we have more time to spare let's shift up little in the hope we'll restore an avatar.
renderAvatarMaxART_ns += FSPerfStats::ART_MIN_ADJUST_UP_NANOS;
tunables.updateSettingsFromRenderCostLimit();
return;
}
if(tunables.userFPSTuningStrategy == TUNE_SCENE_AND_AVATARS)
{
if( LLPipeline::RenderFarClip < tunables.userTargetDrawDistance )
{
FSPerfStats::tunables.updateFarClip( std::min(LLPipeline::RenderFarClip + DD_STEP, tunables.userTargetDrawDistance) );
FSPerfStats::lastGlobalPrefChange = gFrameCount;
return;
}
if( (tot_frame_time_raw * 1.5) < target_frame_time_raw )
{
// if everything else is "max" and we have >50% headroom let's knock the water quality up a notch at a time.
FSPerfStats::tunables.updateReflectionDetail( std::min(LLPipeline::RenderReflectionDetail + 1, tunables.userTargetReflections) );
}
}
}
}
updateSettingsFromRenderCostLimit();
}
}

View File

@ -64,19 +64,23 @@ namespace FSPerfStats
extern std::atomic<int64_t> inUseAttachmentUnRigged;
#endif
// Note if changing these, they should correspond with the log range of the correpsonding sliders
constexpr U64 ART_UNLIMITED_NANOS{50000000};
constexpr U64 ART_MINIMUM_NANOS{100000};
constexpr U64 ART_MIN_ADJUST_UP_NANOS{10000};
constexpr U64 ART_MIN_ADJUST_DOWN_NANOS{10000};
static constexpr U64 ART_UNLIMITED_NANOS{50000000};
static constexpr U64 ART_MINIMUM_NANOS{100000};
static constexpr U64 ART_MIN_ADJUST_UP_NANOS{10000};
static constexpr U64 ART_MIN_ADJUST_DOWN_NANOS{10000};
constexpr F32 PREFERRED_DD{180};
static constexpr F32 PREFERRED_DD{180};
static constexpr U32 SMOOTHING_PERIODS{50};
static constexpr U32 DD_STEP{10};
static constexpr U32 TUNE_AVATARS_ONLY{0};
static constexpr U32 TUNE_SCENE_AND_AVATARS{1};
extern std::atomic<int64_t> tunedAvatars;
extern U32 targetFPS; // desired FPS
extern U64 renderAvatarMaxART_ns;
extern std::atomic<U64> renderAvatarMaxART_ns;
extern bool belowTargetFPS;
extern U32 lastGlobalPrefChange;
extern std::mutex bufferToggleLock;
extern bool autoTune;
enum class ObjType_t{
OT_GENERAL=0, // Also Unknown. Used for n/a type stats such as scenery
@ -118,21 +122,56 @@ namespace FSPerfStats
struct Tunables
{
static constexpr U32 Nothing{0};
static constexpr U32 NonImposters{1};
static constexpr U32 NonImpostors{1};
static constexpr U32 ReflectionDetail{2};
static constexpr U32 FarClip{4};
static constexpr U32 UserMinDrawDistance{8};
static constexpr U32 UserTargetDrawDistance{16};
static constexpr U32 UserImpostorDistance{32};
static constexpr U32 UserImpostorDistanceTuningEnabled{64};
static constexpr U32 UserFPSTuningStrategy{128};
static constexpr U32 UserAutoTuneEnabled{256};
static constexpr U32 UserTargetFPS{512};
static constexpr U32 UserARTCutoff{1024};
static constexpr U32 UserTargetReflections{2048};
static constexpr U32 UserAutoTuneLock{4096};
U32 tuningFlag{0};
U32 nonImposters;
S32 reflectionDetail;
F32 farClip;
U32 tuningFlag{0}; // bit mask for changed settings
void updateFarClip(F32 nv){farClip=nv; tuningFlag |= FarClip;};
void updateNonImposters(U32 nv){nonImposters=nv; tuningFlag |= NonImposters;};
// proxy variables, used to pas the new value to be set via the mainthread
U32 nonImpostors{0};
S32 reflectionDetail{0};
F32 farClip{0.0};
F32 userMinDrawDistance{0.0};
F32 userTargetDrawDistance{0.0};
F32 userImpostorDistance{0.0};
bool userImpostorDistanceTuningEnabled{false};
U32 userFPSTuningStrategy{0};
bool userAutoTuneEnabled{false};
bool userAutoTuneLock{true};
U32 userTargetFPS{0};
F32 userARTCutoffSliderValue{0};
S32 userTargetReflections{0};
void updateNonImposters(U32 nv){nonImpostors=nv; tuningFlag |= NonImpostors;};
void updateReflectionDetail(S32 nv){reflectionDetail=nv; tuningFlag |= ReflectionDetail;};
void updateFarClip(F32 nv){farClip=nv; tuningFlag |= FarClip;};
void updateUserMinDrawDistance(F32 nv){userMinDrawDistance=nv; tuningFlag |= UserMinDrawDistance;};
void updateUserTargetDrawDistance(F32 nv){userTargetDrawDistance=nv; tuningFlag |= UserTargetDrawDistance;};
void updateImposterDistance(F32 nv){userImpostorDistance=nv; tuningFlag |= UserImpostorDistance;};
void updateImposterDistanceTuningEnabled(bool nv){userImpostorDistanceTuningEnabled=nv; tuningFlag |= UserImpostorDistanceTuningEnabled;};
void updateUserFPSTuningStrategy(U32 nv){userFPSTuningStrategy=nv; tuningFlag |= UserFPSTuningStrategy;};
void updateTargetFps(U32 nv){userTargetFPS=nv; tuningFlag |= UserTargetFPS;};
void updateUserARTCutoffSlider(F32 nv){userARTCutoffSliderValue=nv; tuningFlag |= UserARTCutoff;};
void updateUserAutoTuneEnabled(bool nv){userAutoTuneEnabled=nv; tuningFlag |= UserAutoTuneEnabled;};
void updateUserAutoTuneLock(bool nv){userAutoTuneLock=nv; tuningFlag |= UserAutoTuneLock;};
void updateUserTargetReflections(S32 nv){userTargetReflections=nv; tuningFlag |= UserTargetReflections;};
void applyUpdates();
void resetChanges(){tuningFlag=Nothing;};
void initialiseFromSettings();
void updateRenderCostLimitFromSettings();
void updateSettingsFromRenderCostLimit();
void applyUpdates();
};
extern Tunables tunables;
@ -177,8 +216,6 @@ namespace FSPerfStats
{
return max[getReadBufferIndex()][static_cast<size_t>(otype)][static_cast<size_t>(type)];
}
static void updateSettingsFromRenderCostLimit();
static void updateRenderCostLimitFromSettings();
static void updateAvatarParams();
private:
StatsRecorder();

View File

@ -3,6 +3,8 @@
SCRIPT_PATH=`readlink -f $0`
SCRIPT_PATH=`dirname $SCRIPT_PATH`
echo "Trying to build AppImage in directory $1 into file $3"
# All hope is lost if there is no lsb_release command
command -v lsb_release >/dev/null 2>/dev/null || exit 0
@ -45,3 +47,8 @@ chmod a+x appimagetool-x86_64.AppImage
./appimagetool-x86_64.AppImage --appimage-extract
rm appimagetool-x86_64.AppImage
ARCH=x86_64 squashfs-root/AppRun packaged
if [ -f $2 ]
then
mv $2 $3
fi

View File

@ -146,10 +146,10 @@
#include "stringize.h"
#include "llcoros.h"
#include "llexception.h"
//#if !LL_LINUX
#include "cef/dullahan_version.h"
#if !LL_LINUX
#include "vlc/libvlc_version.h"
//#endif // LL_LINUX
#endif // LL_LINUX
// Third party library includes
#include <boost/bind.hpp>
@ -1643,7 +1643,7 @@ bool LLAppViewer::doFrame()
// <FS:Beq> Perfstats collection Frame boundary
{
// and now adjust the visuals from previous frame.
if(FSPerfStats::autoTune && FSPerfStats::tunables.tuningFlag != FSPerfStats::Tunables::Nothing)
if(FSPerfStats::tunables.userAutoTuneEnabled && FSPerfStats::tunables.tuningFlag != FSPerfStats::Tunables::Nothing)
{
FSPerfStats::tunables.applyUpdates();
}
@ -3969,7 +3969,7 @@ LLSD LLAppViewer::getViewerInfo() const
// info["LIBCEF_VERSION"] = "Undefined";
//#endif
//#if !LL_LINUX
#if !LL_LINUX
std::ostringstream vlc_ver_codec;
vlc_ver_codec << LIBVLC_VERSION_MAJOR;
vlc_ver_codec << ".";
@ -3977,9 +3977,9 @@ LLSD LLAppViewer::getViewerInfo() const
vlc_ver_codec << ".";
vlc_ver_codec << LIBVLC_VERSION_REVISION;
info["LIBVLC_VERSION"] = vlc_ver_codec.str();
//#else
// info["LIBVLC_VERSION"] = "Undefined";
//#endif
#else
info["LIBVLC_VERSION"] = "Using gstreamer 1.0";
#endif
S32 packets_in = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_IN);
if (packets_in > 0)

View File

@ -49,8 +49,11 @@
#include "breakpad/client/linux/handler/exception_handler.h"
#include "breakpad/common/linux/http_upload.h"
#include "lldir.h"
#include "../llcrashlogger/llcrashlogger.h"
#endif
#include "fsversionvalues.h"
#define VIEWERAPI_SERVICE "com.secondlife.ViewerAppAPIService"
#define VIEWERAPI_PATH "/com/secondlife/ViewerAppAPI"
#define VIEWERAPI_INTERFACE "com.secondlife.ViewerAppAPI"
@ -138,11 +141,56 @@ LLAppViewerLinux::~LLAppViewerLinux()
}
#if LL_SEND_CRASH_REPORTS
std::string gCrashLogger;
std::string gVersion;
std::string gBugsplatDB;
std::string gCrashBehavior;
static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded)
{
printf("Dump path: %s\n", descriptor.path() );
if( fork() == 0 )
execl( gCrashLogger.c_str(), gCrashLogger.c_str(), descriptor.path(), gVersion.c_str(), gBugsplatDB.c_str(), gCrashBehavior.c_str(), nullptr );
return succeeded;
}
void setupBreadpad()
{
std::string build_data_fname(gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "build_data.json"));
gCrashLogger = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "linux-crash-logger.bin");
llifstream inf(build_data_fname.c_str());
if(!inf.is_open())
{
LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, can't read '" << build_data_fname << "'" << LL_ENDL;
return;
}
Json::Reader reader;
Json::Value build_data;
if(!reader.parse(inf, build_data, false))
{
LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, can't parse '" << build_data_fname << "': "
<< reader.getFormatedErrorMessages() << LL_ENDL;
return;
}
Json::Value BugSplat_DB = build_data["BugSplat DB"];
if(!BugSplat_DB)
{
LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, no 'BugSplat DB' entry in '" << build_data_fname
<< "'" << LL_ENDL;
return;
}
gVersion = STRINGIZE(
LL_VIEWER_VERSION_MAJOR << '.' << LL_VIEWER_VERSION_MINOR << '.' << LL_VIEWER_VERSION_PATCH
<< '.' << LL_VIEWER_VERSION_BUILD);
gBugsplatDB = BugSplat_DB.asString();
LL_INFOS("BUGSPLAT") << "Initializing with crash logger: " << gCrashLogger << " database: " << gBugsplatDB << " version: " << gVersion << LL_ENDL;
google_breakpad::MinidumpDescriptor *descriptor = new google_breakpad::MinidumpDescriptor(gDirUtilp->getExpandedFilename(LL_PATH_DUMP, ""));
google_breakpad::ExceptionHandler *eh = new google_breakpad::ExceptionHandler(*descriptor, NULL, dumpCallback, NULL, true, -1);
}
#endif
bool LLAppViewerLinux::init()
@ -155,11 +203,17 @@ bool LLAppViewerLinux::init()
bool success = LLAppViewer::init();
#if LL_SEND_CRASH_REPORTS
if (success)
{
google_breakpad::MinidumpDescriptor *descriptor = new google_breakpad::MinidumpDescriptor(gDirUtilp->getExpandedFilename(LL_PATH_DUMP,""));
google_breakpad::ExceptionHandler *eh = new google_breakpad::ExceptionHandler(*descriptor, NULL, dumpCallback, NULL, true, -1);
}
S32 nCrashSubmitBehavior = gCrashSettings.getS32("CrashSubmitBehavior");
// For the first version we just consider always send and create a nice dialog for CRASH_BEHAVIOR_ASK later.
if (success && nCrashSubmitBehavior != CRASH_BEHAVIOR_NEVER_SEND )
{
if( nCrashSubmitBehavior == CRASH_BEHAVIOR_ASK )
gCrashBehavior = "ask";
else
gCrashBehavior = "send";
setupBreadpad();
}
#endif
return success;

View File

@ -711,7 +711,7 @@ void LLPresetsManager::handleGraphicPresetControlChanged(LLControlVariablePtr co
if (!mIsLoadingPreset &&
(!mIsDrawDistanceSteppingActive || control->getName() != "RenderFarClip") &&
(!FSPerfStats::autoTune) )
(!FSPerfStats::tunables.userAutoTuneEnabled) )
{
LL_DEBUGS() << "Trigger graphic preset control changed signal" << LL_ENDL;

View File

@ -1094,14 +1094,20 @@ void handleDiskCacheSizeChanged(const LLSD& newValue)
void handleTargetFPSChanged(const LLSD& newValue)
{
const auto targetFPS = gSavedSettings.getU32("FSTargetFPS");
FSPerfStats::targetFPS = targetFPS;
FSPerfStats::tunables.userTargetFPS = targetFPS;
}
// <FS:Beq> perf floater stuffs
void handleAutoTuneLockChanged(const LLSD& newValue)
{
const auto newval = gSavedSettings.getBOOL("FSAutoTuneLock");
FSPerfStats::tunables.userAutoTuneLock = newval;
}
// <FS:Beq> perrf floater stuffs
void handleAutoTuneFPSChanged(const LLSD& newValue)
{
const auto newval = gSavedSettings.getBOOL("FSAutoTuneFPS");
FSPerfStats::autoTune = newval;
FSPerfStats::tunables.userAutoTuneEnabled = newval;
if(newval && FSPerfStats::renderAvatarMaxART_ns == 0) // If we've enabled autotune we override "unlimited" to max
{
gSavedSettings.setF32("FSRenderAvatarMaxART",log10(FSPerfStats::ART_UNLIMITED_NANOS-1000));//triggers callback to update static var
@ -1110,7 +1116,19 @@ void handleAutoTuneFPSChanged(const LLSD& newValue)
void handleRenderAvatarMaxARTChanged(const LLSD& newValue)
{
FSPerfStats::StatsRecorder::updateRenderCostLimitFromSettings();
FSPerfStats::tunables.updateRenderCostLimitFromSettings();
}
void handleUserTargetDrawDistanceChanged(const LLSD& newValue)
{
const auto newval = gSavedSettings.getF32("FSAutoTuneRenderFarClipTarget");
FSPerfStats::tunables.userTargetDrawDistance = newval;
}
void handleUserTargetReflectionsChanged(const LLSD& newValue)
{
const auto newval = gSavedSettings.getF32("FSUserTargetReflections");
FSPerfStats::tunables.userTargetReflections = newval;
}
void handlePerformanceStatsEnabledChanged(const LLSD& newValue)
@ -1118,6 +1136,22 @@ void handlePerformanceStatsEnabledChanged(const LLSD& newValue)
const auto newval = gSavedSettings.getBOOL("FSPerfStatsCaptureEnabled");
FSPerfStats::StatsRecorder::setEnabled(newval);
}
void handleUserImpostorByDistEnabledChanged(const LLSD& newValue)
{
const auto newval = gSavedSettings.getBOOL("FSAutoTuneImpostorByDistEnabled");
FSPerfStats::tunables.userImpostorDistanceTuningEnabled = newval;
}
void handleUserImpostorDistanceChanged(const LLSD& newValue)
{
const auto newval = gSavedSettings.getF32("FSAutoTuneImpostorFarAwayDistance");
FSPerfStats::tunables.userImpostorDistance = newval;
}
void handleFPSTuningStrategyChanged(const LLSD& newValue)
{
const auto newval = gSavedSettings.getU32("FSTuningFPSStrategy");
FSPerfStats::tunables.userFPSTuningStrategy = newval;
}
// </FS:Beq>
////////////////////////////////////////////////////////////////////////////
@ -1378,8 +1412,14 @@ void settings_setup_listeners()
// <FS:Beq> perf floater controls
gSavedSettings.getControl("FSTargetFPS")->getSignal()->connect(boost::bind(&handleTargetFPSChanged, _2));
gSavedSettings.getControl("FSAutoTuneFPS")->getSignal()->connect(boost::bind(&handleAutoTuneFPSChanged, _2));
gSavedSettings.getControl("FSAutoTuneLock")->getSignal()->connect(boost::bind(&handleAutoTuneLockChanged, _2));
gSavedSettings.getControl("FSRenderAvatarMaxART")->getSignal()->connect(boost::bind(&handleRenderAvatarMaxARTChanged, _2));
gSavedSettings.getControl("FSPerfStatsCaptureEnabled")->getSignal()->connect(boost::bind(&handlePerformanceStatsEnabledChanged, _2));
gSavedSettings.getControl("FSUserTargetReflections")->getSignal()->connect(boost::bind(&handleUserTargetReflectionsChanged, _2));
gSavedSettings.getControl("FSAutoTuneRenderFarClipTarget")->getSignal()->connect(boost::bind(&handleUserTargetDrawDistanceChanged, _2));
gSavedSettings.getControl("FSAutoTuneImpostorFarAwayDistance")->getSignal()->connect(boost::bind(&handleUserImpostorDistanceChanged, _2));
gSavedSettings.getControl("FSAutoTuneImpostorByDistEnabled")->getSignal()->connect(boost::bind(&handleUserImpostorByDistEnabledChanged, _2));
gSavedSettings.getControl("FSTuningFPSStrategy")->getSignal()->connect(boost::bind(&handleFPSTuningStrategyChanged, _2));
// </FS:Beq>
}

View File

@ -344,7 +344,10 @@ public:
switch (curlcode)
{
case CURLE_SSL_PEER_CERTIFICATE:
// <FS:ND/> CURLE_SSL_CACERT has been deprecated, the LIBCURL-VERSION_NUM check is probably no checking for the lowest curl vesion this did happen
#if LIBCURL_VERSION_NUM < 0x075100
case CURLE_SSL_CACERT:
#endif
data["certificate"] = mTransaction->getErrorCertData();
break;

View File

@ -517,7 +517,10 @@ void LLXMLRPCTransaction::Impl::setHttpStatus(const LLCore::HttpStatus &status)
message = LLTrans::getString("ssl_peer_certificate");
break;
// <FS:ND/> CURLE_SSL_CACERT has been deprecated, the LIBCURL-VERSION_NUM check is probably no checking for the lowest curl vesion this did happen
#if LIBCURL_VERSION_NUM < 0x075100
case CURLE_SSL_CACERT:
#endif
case CURLE_SSL_CONNECT_ERROR:
message = LLTrans::getString("ssl_connect_error");
break;

View File

@ -425,11 +425,6 @@ Prøv venligst om lidt igen.
<string name="ReleaseNotes">
Noter om version
</string>
<!--
<string name="RELEASE_NOTES_BASE_URL">
https://releasenotes.secondlife.com/viewer/
</string>
-->
<string name="LoadingData">
Henter...
</string>

View File

@ -18,6 +18,12 @@
<floater.string name="focus_fps">
Im Hintergrund
</floater.string>
<floater.string name="info_waitforit">
5-10 Sekunden warten auf Effekt der Anpassungen.
</floater.string>
<floater.string name="info_frozen">
Statistik pausiert, wenn FPS begrenzt oder im Hintergrund.
</floater.string>
<floater.string name="tot_av_template">
Gesamt: [TOT_AV] ([TOT_AV_TIME]μs)
</floater.string>
@ -30,25 +36,32 @@
Bilder pro Sekunde
</text>
<text name="fps_desc1_lbl">
5-10 Sekunden warten auf Effekt der Anpassungen.
Statistik pausiert, wenn FPS begrenzt oder im Hintergrund.
</text>
<text name="frame_breakdown">
Frame-Aufschlüsselung erfolgt hier.
</text>
</panel>
<panel name="target_subpanel">
<text name="settings_lbl">
Auto-Anpassung Ziel-FPS
<text name="settings_lbl" width="140" tool_tip="Automatisch Einstellungen anpassen, um FPS zu halten. Ziel auf die gewünschte Bildrate setzen und der Viewer wird automatisch versuchen diese zu halten, indem Einstellungen angepasst werden.">
Auto-Anpassung:
</text>
<check_box label="Auto-Anpassung" name="AutoTuneFPS" tool_tip="Der Viewer wird automatisch versuchen, die Ziel-FPS zu erreichen." />
<text name="targetfps_desc" width="75">
Ziel-FPS:
</text>
<spinner name="target_fps" tool_tip="Ziel-FPS - Der Viewer wird automatisch versuchen, die gewünschte FPS durch Anpassung der Einstellungen zu erreichen." />
<check_box label="Auto-Anp." name="AutoTuneFPS" tool_tip="Der Viewer wird automatisch versuchen, die Ziel-FPS zu erreichen." />
<check_box label="Kontinuierlich" name="AutoTuneContinuous" tool_tip="Der Viewer wird kontinuierlich Einstellungen anpassen, um die gewünschte Ziel-FPS zu halten, auch wenn das Fenster geschlossen wurde. Falls deaktiviert, werden die Einstellungen durch Klick auf den Anto-Anpassung-Button einmalig angepasst." />
<button name="PrefSaveButton" tool_tip="Aktuelle Einstellungen als Standard für zukünftige Verwendung speichern." />
<button name="PrefLoadButton" tool_tip="Bestehende Voreinstellung laden." />
<button tool_tip="Standardeinstellungen für die erkannte Hardware laden." name="Defaults" />
<text name="settings_desc">
Einstellungen automatisch für FPS anpassen.
Tuning-Strategie:
</text>
<combo_box name="FSTuningFPSStrategy">
<combo_box.item label="Nur Avatar-Einstellungen" name="av_only" />
<combo_box.item label="Nur Avatare" name="av_only" />
<combo_box.item label="Avatar und Szenerie" name="av_and_scene" />
</combo_box>
<spinner name="target_fps" tool_tip="Ziel-FPS - Der Viewer wird automatisch versuchen, die gewünschte FPS durch Anpassung der Einstellungen zu erreichen." />
</panel>
</panel>
<panel name="panel_performance_main">

View File

@ -310,6 +310,7 @@
<menu_item_call label="Lag-Anzeige" name="Lag Meter"/>
<menu_item_check label="Statistikleiste" name="Statistics Bar"/>
<menu_item_check label="Statistiken zum Laden von Szenen" name="Scene Load Statistics"/>
<menu_item_check label="Grafikleistung verbessern..." name="Performance"/>
<menu_item_check label="Informationen zur Avatarkomplexität anzeigen" name="Avatar Draw Info"/>
</menu>
<menu label="Hervorhebung und Sichtbarkeit" name="Highlighting and Visibility">

View File

@ -6,9 +6,9 @@
<panel.string name="forgot_password_url">
http://secondlife.com/account/request.php?lang=de
</panel.string>
<panel.string name="ServerComboTooltip">
<string name="ServerComboTooltip">
Ein bekanntes Grid oder eine Grid-URI
</panel.string>
</string>
<layout_stack name="login_widgets">
<layout_panel name="login">
<text name="log_in_text">

View File

@ -3,9 +3,9 @@
<panel.string name="forgot_password_url">
http://secondlife.com/account/request.php?lang=de
</panel.string>
<panel.string name="ServerComboTooltip">
<string name="ServerComboTooltip">
Ein bekanntes Grid oder eine Grid-URI
</panel.string>
</string>
<layout_stack name="ui_stack">
<layout_panel name="ui_container">
<layout_stack name="vert_stack_left">

View File

@ -11,9 +11,10 @@
</text>
<check_box label="Distanz-basierte Optimierung" name="FSAutoTuneImpostorByDistEnabled" tool_tip="Falls aktiviert wird die Einstellung MaxNonImpostors angepasst, um komplett dargestellte Avatare auf den angegebenen Radius zu beschränken." />
<spinner label="Entferntester kompl. Avatar" name="ffa_autotune" />
<text name="distant_av_advice">
Avatare in größerer Entfernung haben weiterhin einen hohen Einfluss.
<text name="distant_av_advice" height="68">
Avatare in größerer Entfernung können automatisch optimiert werden unabhängig ihrer Darstellungskosten.
Entfernung von der Kamera setzen, ab dem ein Avatar optimiert wird.
Hinweis: Diese Einstellung setzt MaxNonImpostors auf 1 falls kein Avatar in der Nähe.
</text>
<text name="distance_lbl">
Sichtweiten-
@ -22,7 +23,7 @@ Tuning-Limit
<spinner label="Minimale Distanz" name="min_dd_autotune" />
<spinner label="Präferierte Distanz" name="pref_dd_autotune" />
<text name="distance_desc1">
Beim Anpassen der Szenerie-Parameter wird Auto-Anpassung die Sichtweite zwischen dem Minimum und der Präferenz optimieren.
Beim Anpassen der Szenerie-Parameter wird Auto-Anpassung Werte zwischen dem Minimum und der präferierten Sichtweiten wählen.
</text>
<text name="sundry_lbl">
Verschiedene Einstellungen

View File

@ -27,8 +27,11 @@
<text name="av_nearby_desc2">
Per Rechts-Klick auf einen Avatar kann auch die Darstellung angepasst werden.
</text>
<button label="Ausnahmen..." name="exceptions_btn" />
<text name="av_nearby_desc3">
Hinweis: Für den Einfluss des eigenen Avatars den Reiter "Eigene Avatar-Komplexität" öffnen.
</text>
<check_box label="Freunde immer komplett darstellen" name="display_friends" />
<button label="Ausnahmen..." name="exceptions_btn" />
<check_box label="Alle Avatare verstecken (Gut für Landschaftsaufnahmen) " name="hide_avatars" />
<text name="name_tags_textbox">
Avatar namen:

View File

@ -805,11 +805,6 @@ nächsten Eigentümer angehängt werden.
<string name="ReleaseNotes">
Versionshinweise
</string>
<!--
<string name="RELEASE_NOTES_BASE_URL">
https://releasenotes.secondlife.com/viewer/
</string>
-->
<string name="LoadingData">
Wird geladen...
</string>

File diff suppressed because it is too large Load Diff

View File

@ -2885,6 +2885,17 @@
function="Floater.Toggle"
parameter="scene_load_stats" />
</menu_item_check>
<menu_item_check
label="Improve graphics speed..."
name="Performance">
<menu_item_check.on_click
function="Floater.Toggle"
parameter="performance" />
<menu_item_check.on_check
function="Floater.Visible"
parameter="performance" />
</menu_item_check>
<menu_item_check
label="Show avatar complexity information"
name="Avatar Draw Info">

View File

@ -130,7 +130,7 @@
movie
</widgettype>
<impl>
media_plugin_libvlc
media_plugin_gstreamer
</impl>
</scheme>
<mimetype name="blank">
@ -163,7 +163,7 @@
audio
</widgettype>
<impl>
media_plugin_libvlc
media_plugin_gstreamer
</impl>
</mimetype>
<mimetype name="video/*">
@ -174,7 +174,7 @@
movie
</widgettype>
<impl>
media_plugin_libvlc
media_plugin_gstreamer
</impl>
</mimetype>
<mimetype name="image/*">
@ -196,7 +196,7 @@
movie
</widgettype>
<impl>
media_plugin_libvlc
media_plugin_gstreamer
</impl>
</mimetype>
<mimetype name="application/javascript">
@ -218,7 +218,7 @@
audio
</widgettype>
<impl>
media_plugin_libvlc
media_plugin_gstreamer
</impl>
</mimetype>
<mimetype name="application/pdf">
@ -295,7 +295,7 @@
audio
</widgettype>
<impl>
media_plugin_libvlc
media_plugin_gstreamer
</impl>
</mimetype>
<mimetype name="audio/mpeg">
@ -306,7 +306,7 @@
audio
</widgettype>
<impl>
media_plugin_libvlc
media_plugin_gstreamer
</impl>
</mimetype>
<mimetype name="audio/x-aiff">
@ -317,7 +317,7 @@
audio
</widgettype>
<impl>
media_plugin_libvlc
media_plugin_gstreamer
</impl>
</mimetype>
<mimetype name="audio/x-wav">
@ -328,7 +328,7 @@
audio
</widgettype>
<impl>
media_plugin_libvlc
media_plugin_gstreamer
</impl>
</mimetype>
<mimetype menu="1" name="image/bmp">
@ -438,7 +438,7 @@
movie
</widgettype>
<impl>
media_plugin_libvlc
media_plugin_gstreamer
</impl>
</mimetype>
<mimetype name="video/mp4">
@ -449,7 +449,7 @@
movie
</widgettype>
<impl>
media_plugin_libvlc
media_plugin_gstreamer
</impl>
</mimetype>
<mimetype menu="1" name="video/quicktime">
@ -460,7 +460,7 @@
movie
</widgettype>
<impl>
media_plugin_libvlc
media_plugin_gstreamer
</impl>
</mimetype>
<mimetype name="video/x-ms-asf">
@ -471,7 +471,7 @@
movie
</widgettype>
<impl>
media_plugin_libvlc
media_plugin_gstreamer
</impl>
</mimetype>
<mimetype name="video/x-ms-wmv">
@ -482,7 +482,7 @@
movie
</widgettype>
<impl>
media_plugin_libvlc
media_plugin_gstreamer
</impl>
</mimetype>
<mimetype menu="1" name="video/x-msvideo">
@ -493,7 +493,7 @@
movie
</widgettype>
<impl>
media_plugin_libvlc
media_plugin_gstreamer
</impl>
</mimetype>
</mimetypes>

View File

@ -68,7 +68,7 @@ Distant Avatars
<check_box
control_name="FSAutoTuneImpostorByDistEnabled"
height="19"
label="Enable distance based optimization"
label="Enable distance-based optimization"
layout="topleft"
follows="top|left"
left_pad="40"
@ -95,14 +95,16 @@ Distant Avatars
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="28"
height="46"
layout="topleft"
top_pad="15"
left="160"
name="distant_av_advice"
width="450">
Avatars that are further away still have a high impact.
width="450"
wrap="true">
Distant avatars can be automatically optimized regardless of their render cost.
Set the distance from camera beyond which an avatar will be optimized.
Note: This setting will force MaxNonImpostors to 1 if nobody is nearby.
</text>
<view_border
bevel_style="in"
@ -166,7 +168,7 @@ left="160"
name="distance_desc1"
wrap="true"
width="400">
When adjusting scene parameters, autotune will optimize draw distance to between the minimum and the preferred.
When adjusting scene parameters, autotune will choose values between the minimum and the preferred draw distances.
</text>
<view_border
bevel_style="in"

View File

@ -183,15 +183,18 @@ top="0">
width="580">
You can also right-click on an avatar in-world to control display.
</text>
<button
height="23"
label="Exceptions..."
layout="topleft"
left="460"
top_delta="2"
name="exceptions_btn"
width="100">
</button>
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="18"
layout="topleft"
left="20"
top_pad="0"
name="av_nearby_desc3"
width="580">
Note: Your own avatar includes viewer overheads. Use the attachment tab to see how you affect others.
</text>
<check_box
control_name="AlwaysRenderFriends"
height="16"
@ -200,16 +203,25 @@ top="0">
label_text.text_color="White"
layout="topleft"
name="display_friends"
top_pad="3"
top_pad="2"
left="18"
width="256">
</check_box>
<button
height="23"
label="Exceptions..."
layout="topleft"
left="460"
top_delta="0"
name="exceptions_btn"
width="100">
</button>
<view_border
bevel_style="in"
height="0"
layout="topleft"
name="border"
top_pad="15"
top_pad="10"
left="20"
width="540"/>
<check_box

View File

@ -390,7 +390,7 @@ can be attached to notecards.
<string name="ReleaseNotes">Release Notes</string>
<!-- Always mark translate="false" for strings that are nothing but URLs, as they don't need translation. -->
<string name="RELEASE_NOTES_BASE_URL" translate="false">https://wiki.firestormviewer.org/firestorm_change_log_</string>
<string name="RELEASE_NOTES_BASE_URL" translate="false">https://wiki.firestormviewer.org/changelog:firestorm_change_log_</string>
<!-- Indicates something is being loaded. Maybe should be merged with RetrievingData -->
<string name="LoadingData">Loading...</string>

View File

@ -663,11 +663,6 @@ pueden adjuntarse a las notas.
<string name="ReleaseNotes">
Notas de la versión
</string>
<!--
<string name="RELEASE_NOTES_BASE_URL">
https://releasenotes.secondlife.com/viewer/
</string>
-->
<string name="LoadingData">
Cargando...
</string>

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="performance" title="Améliorer les performances graphiques (expérimental)">
<floater.string name="frame_stats">
Images: [TOT_FRAME_TIME]ms - Scène:[SCENERY_FRAME_PCT]% Avatars:[AV_FRAME_PCT]% UI:[UI_FRAME_PCT]% Huds:[HUDS_FRAME_PCT]% Swap:[SWAP_FRAME_PCT]% Tâches:[IDLE_FRAME_PCT]%
</floater.string>
<floater.string name="limit_fps">
FPS limité à: [FPSCAP] fps
</floater.string>
<floater.string name="tuning_fps">
Objectif: [FPSTARGET] fps
</floater.string>
<floater.string name="focus_fps">
En arrière-plan
</floater.string>
<floater.string name="tot_av_template">
Total: [TOT_AV] ([TOT_AV_TIME]μs)
</floater.string>
<floater.string name="tot_att_template">
Total: [TOT_ATT] ([TOT_ATT_TIME]μs)
</floater.string>
<panel name="panel_top">
<panel name="fps_subpanel">
<text name="fps_lbl">
images par seconde
</text>
<text name="fps_desc1_lbl">
Attendez 5 à 10 secondes pour voir les changements.
</text>
<text name="frame_breakdown">
[----------------- Vous verrez ici l'analyse du cadre. -----------------]
</text>
</panel>
<panel name="target_subpanel">
<text name="settings_lbl">
Réglage auto de l'affichage
</text>
<check_box label="Réglage automatique" name="AutoTuneFPS" tool_tip="Le visualiseur tentera d'ajuster les paramètres pour atteindre la fréquence d'images souhaitée.." />
<text name="settings_desc">
Réglage auto pour maint. le nombre de FPS.
</text>
<combo_box name="FSTuningFPSStrategy">
<combo_box.item label="Uniquement les avatars" name="av_only" />
<combo_box.item label="Avatars et scène" name="av_and_scene" />
</combo_box>
<spinner name="target_fps" tool_tip="FPS cible - Le niveau de FPS souhaité. Le visualisateur essaiera d'atteindre ce niveau en ajustant vos paramètres graphiques.." />
</panel>
</panel>
<panel name="panel_performance_main">
<panel name="settings_subpanel">
<text name="settings_lbl">
Paramètres graphiques
</text>
<text name="settings_desc">
Sélectionnez les paramètres de distance, d'eau, d'éclairage, etc..
</text>
</panel>
<panel name="nearby_subpanel">
<text name="avatars_nearby_lbl">
Avatars à proximité
</text>
<text name="avatars_nearby_desc">
Définir quels avatars sont entièrement affichés.
</text>
<text name="avatars_frme_pct_lbl">
Temps
Dessin
Avatars
</text>
</panel>
<panel name="complexity_subpanel">
<text name="complexity_lbl">
Complexité de l'avatar
</text>
<text name="complexity_info">
Soyez un bon citoyen. Gérez l'impact de votre avatar.
</text>
</panel>
<panel name="huds_subpanel">
<text name="huds_lbl">
Vos HUD actifs
</text>
<text name="huds_desc">
La suppress. des HUD inutiles peut améliorer la fluidité.
</text>
<text name="huds_frme_pct_lbl">
Temps
Dessin
HUDs
</text>
</panel>
</panel>
</floater>

View File

@ -127,6 +127,7 @@
<menu_item_check label="Propriétés de la parcelle" name="Parcel Properties"/>
<menu_item_check label="Menu Avancé" name="Show Advanced Menu"/>
</menu>
<menu_item_check label="Améliorer les performances graphiques..." name="Performance" />
<menu_item_call label="Me téléporter chez moi" name="Teleport Home"/>
<menu label="Environnement" name="Environment">
<menu_item_check label="Aube" name="Sunrise"/>

View File

@ -3,9 +3,9 @@
<panel.string name="forgot_password_url">
http://secondlife.com/account/request.php?lang=fr
</panel.string>
<panel.string name="ServerComboTooltip">
<string name="ServerComboTooltip">
Une grille connue ou l'URI d'une grille
</panel.string>
</string>
<layout_stack name="ui_stack">
<layout_panel name="ui_container">
<layout_stack name="vert_stack_left">

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="panel_performance_autotune">
<text name="back_lbl">
Retour
</text>
<text name="settings_title">
Options de réglage automatique
</text>
<text name="quality_lbl">
Avatars éloignés
</text>
<check_box label="Optimisation basée sur la distance" name="FSAutoTuneImpostorByDistEnabled" tool_tip="Le visualiseur ajustera le paramètre MaxNonImpostors pour limiter les avatars entièrement rendus à ceux qui se trouvent dans le rayon défini." />
<spinner label="Avatar complet le plus loin" name="ffa_autotune" />
<text name="distant_av_advice">
Les avatars qui sont plus éloignés ont toujours un impact élevé.
Définissez la dist. de la caméra au-delà de laquelle un avatar sera optimisé.
</text>
<text name="distance_lbl">
Réglage de la distance de visibilité
</text>
<spinner label="Distance minimale" name="min_dd_autotune" />
<spinner label="Distance préférée" name="pref_dd_autotune" />
<text name="distance_desc1">
Lors du réglage des paramètres de la scène, l'autotune optimisera la distance de visibilité entre le minimum et le maximum.
</text>
<text name="sundry_lbl">
Divers
</text>
<check_box label="Permettre l'optimisation de votre avatar" name="alow_self_impostor" tool_tip="Activée, le visualiseur pourra utiliser un avatar 2D pour votre avatar." />
<check_box label="Afficher le temps de rendu optimisé" name="show_tuned_art" tool_tip="Activée, la colonne Temps indique le temps de rendu actuel et non le temps de rendu avant réglage." />
<text name="sundry_desc1">
Ces options contrôlent des paramètres plus fins. Utilisez la page d'aide en ligne pour obtenir plus d'informations sur leur fonctionnement.
</text>
</panel>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="panel_performance_complexity">
<text name="back_lbl">
Retour
</text>
<text name="attachments_title">
Complexité des attachements
</text>
<text name="attachments_desc1">
Les attachements complexifient l'avatar et le rendu est plus lent.
</text>
<text name="attachments_desc2">
Cet écran vous permet de visualiser les attachements de votre avatar.
</text>
<text name="attachments_desc3">
Vous pouvez facilement supprimer vos attachements en cliquant sur le "X".
</text>
<name_list name="obj_list">
<name_list.columns label="Temps (μs)" name="art_value" tool_tip="Temps nécessaire au rendu de l'attachement (microsecondes)" />
<name_list.columns name="complex_value" tool_tip="Complexité de l'attachement (ARC)" />
<name_list.columns label="Nom de l'attachement" tool_tip="Cliquez sur 'X' pour détacher l'attachement" name="name" />
</name_list>
</panel>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="panel_performance_huds">
<text name="back_lbl">
Retour
</text>
<text name="huds_title">
Vos HUDs actifs
</text>
<text name="huds_desc1">
Détacher les HUDs inutilisés économise de la mémoire et peut rendre le visualiseur plus rapide.
</text>
<text name="huds_desc2">
Les HUD sont souvent très scriptés et contribuent également au lag côté serveur.
</text>
<text name="huds_desc3">
L'utilisation du bouton de réduction d'un HUD ne le détache pas. Utilisez le X pour le retirer.
</text>
<name_list name="hud_list">
<name_list.columns label="Temps (μs)" name="art_value" tool_tip="Temps nécessaire au rendu de ce HUD (microsecondes)" />
<name_list.columns label="Nom" tool_tip="Cliquez sur le 'X' pour détacher le hud" name="name" />
</name_list>
</panel>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="panel_performance_nearby">
<text name="back_lbl">
Retour
</text>
<text name="av_nearby_title">
Avatars à proximité
</text>
<text name="av_nearby_desc">
Masquer les avatars les plus complexes pour gagner en fluidité.
</text>
<slider tool_tip="Contrôle le moment où un avatar visuellement complexe est dessiné sous forme d'avatar de substitution" label="Complexité maximale (K)" name="IndirectMaxComplexity" />
<slider tool_tip="Contrôle quand un avatar visuellement complexe est considéré comme prenant trop de temps pour être rendu (unité : microsecondes)" label="Temps de rendu max. (μs)" name="FSRenderAvatarMaxART" />
<text name="FSRenderAvatarMaxARTText">
illimité
</text>
<name_list name="nearby_list">
<name_list.columns tool_tip="Graphique à barres montrant le temps de rendu actuel (incluant l'auto-tuning) en % du plus lent." name="art_visual" />
<name_list.columns label="Temps (μs)" tool_tip="Temps de rendu de l'avatar (ART). Le temps réel nécessaire au rendu de cet avatar avant tout réglage automatique (en microsecondes)." name="art_value" />
<name_list.columns tool_tip="Complexité (ARC) basée sur des règles standard." name="complex_value" />
<name_list.columns tool_tip="Indique tout réglage. I=Avatar de substitution, S=pas d'ombre." name="state" />
<name_list.columns label="Nom" name="name"/>
</name_list>
<text name="av_nearby_desc2">
Vous pouvez également faire un clic droit sur un avatar pour contr. l'affichage.
</text>
<button label="Exceptions..." name="exceptions_btn" />
<check_box label="Toujours afficher complètement les amis" name="display_friends" />
<check_box label="Masquer complètement les avatars." name="hide_avatars" />
<text name="name_tags_textbox">
Des noms:
</text>
<radio_group name="name_tag_mode">
<radio_item label="Non" name="radio" />
<radio_item label="Oui" name="radio2" />
<radio_item label="Brièvement" name="radio3" />
</radio_group>
</panel>

View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="panel_performance_preferences">
<text name="back_lbl">
Retour
</text>
<text name="settings_title">
Paramètres graphiques
</text>
<text name="quality_lbl">
Qualité ou rapidité
</text>
<text name="FasterText">
Rapide
</text>
<text name="BetterText">
Meilleure qualité
</text>
<text name="ShadersPrefText">
Bas
</text>
<text name="ShadersPrefText2">
Moyen
</text>
<text name="ShadersPrefText3">
Haut
</text>
<text name="quality_desc">
Choisir un préréglage réinitialise toutes les modifications manuelles.
</text>
<text name="distance_lbl">
Champ visuel
</text>
<text name="faster_lbl">
Rapide
</text>
<text name="farther_lbl">
Loin
</text>
<text name="distance_desc1">
Gardez un niveau bas pour de meilleures perf. Augmentez pour voir loin.
</text>
<text name="environment_lbl">
Environnement
</text>
<text name="enhancements_desc">
La réduction/suppression des ombres peut augmenter la fréq. d'images,
mais affecte l'atmosphère et l'aspect de la scène.
</text>
<text name="RenderShadowDetailText">
Sources des ombres :
</text>
<combo_box name="ShadowDetail">
<combo_box.item label="Aucune" name="0" />
<combo_box.item label="Soleil/Lune" name="1" />
<combo_box.item label="Soleil/Lune + Projecteurs" name="2" />
</combo_box>
<text name="water_lbl">
Eau
</text>
<text name="water_desc">
La réduction de la qualité des effets de l'eau améliore la fréq. des images.
</text>
<text name="ReflectionsText">
Reflets dans l'eau :
</text>
<combo_box name="Reflections">
<combo_box.item label="Aucun ; opaque" name="-2" />
<combo_box.item label="Aucun ; transparent" name="-1" />
<combo_box.item label="Minimum" name="0" />
<combo_box.item label="Terrain et arbres" name="1" />
<combo_box.item label="Tous les objets statiques" name="2" />
<combo_box.item label="Tous les avatars et les objets" name="3" />
<combo_box.item label="Tout" name="4" />
</combo_box>
<text name="photo_lbl">
Photographie
</text>
<text name="photo_desc">
Les photographes exigent une meilleure qualité,
souvent au détriment de la fréquence d'images.
Les outils photo de [APP_NAME] vous aideront à trouver l'équilibre.
</text>
<button name="open_phototools" label="Outils photo" tool_tip="Ouvre les outils photo dédiés pour affiner les paramètres avancés de l'image." />
</panel>

View File

@ -635,11 +635,6 @@ peuvent être joints aux notes.
<string name="ReleaseNotes">
Notes de version
</string>
<!--
<string name="RELEASE_NOTES_BASE_URL">
https://releasenotes.secondlife.com/viewer/
</string>
-->
<string name="LoadingData">
Chargement...
</string>

View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="performance" title="Migliora la velocita grafica (Sperimentale)">
<floater.string name="limit_fps">
Limita FPS: [FPSCAP] fps
</floater.string>
<floater.string name="tuning_fps">
Obbiett.: [FPSTARGET] fps
</floater.string>
<floater.string name="focus_fps">
Sfondo
</floater.string>
<floater.string name="tot_av_template">
Totale: [TOT_AV] ([TOT_AV_TIME]μs)
</floater.string>
<floater.string name="tot_att_template">
Totale: [TOT_ATT] ([TOT_ATT_TIME]μs)
</floater.string>
<panel name="panel_top">
<panel name="fps_subpanel">
<text name="fps_lbl">
fotogr. al secondo
</text>
<text name="fps_desc1_lbl">
Attendi 5-10 Sec per aggiornamento modifiche
</text>
<text name="frame_breakdown">
[------------ La suddivisione del frame apparirà qui ------------]
</text>
</panel>
<panel name="target_subpanel">
<text name="settings_lbl">
Autoregolazione Frame Rate
</text>
<check_box label="Autoregolazione" name="AutoTuneFPS" tool_tip="Il programma tenterà di regolare le impostazioni per soddisfare l'FPS target." />
<text name="settings_desc">
Autoregola impostazioni per mantenere FPS
</text>
<combo_box name="FSTuningFPSStrategy">
<combo_box.item label="Sintonizza solo avatar" name="av_only" />
<combo_box.item label="Avatar e scena" name="av_and_scene" />
</combo_box>
<spinner name="target_fps" tool_tip="Target FPS - Il livello FPS desiderato. Lo spettatore tenterà di raggiungere questo obiettivo regolando le impostazioni grafiche." />
</panel>
</panel>
<panel name="panel_performance_main">
<panel name="settings_subpanel">
<text name="settings_lbl">
Impostazioni grafiche
</text>
<text name="settings_desc">
Scegli impostazioni per distanza, acqua, illuminazione e altro.
</text>
</panel>
<panel name="nearby_subpanel">
<text name="avatars_nearby_lbl">
Avatar nelle vicinanze
</text>
<text name="avatars_nearby_desc">
Gestisci quali avatar vicini vengono visti completamente.
</text>
<text name="avatars_frme_pct_lbl">
Tempo trasc.
a disegnare
avatar
</text>
</panel>
<panel name="complexity_subpanel">
<text name="complexity_lbl">
La tua complessita
</text>
<text name="complexity_info">
Sii un buon cittadino. Gestisci l'impatto del tuo avatar.
</text>
</panel>
<panel name="huds_subpanel">
<text name="huds_lbl">
I tuoi HUD attivi
</text>
<text name="huds_desc">
Rimuovi HUD non necessari. Migliora la velocita.
</text>
<text name="huds_frme_pct_lbl">
Tempo trasc.
a disegnare
HUD
</text>
</panel>
</panel>
</floater>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="panel_performance_complexity">
<text name="back_lbl">
Indietro
</text>
<text name="attachments_title">
Complessita oggetti indossati avatar
</text>
<text name="attachments_desc1">
Gli allegati rendono il tuo avatar piu complesso e lento da renderizzare.
</text>
<text name="attachments_desc2">
Questa schermata ti consente di visualizzare gli allegati del tuo avatar.
</text>
<text name="attachments_desc3">
Puoi rimuovere i tuoi allegati rapidamente e facilmente premendo la 'X'.
</text>
<name_list name="obj_list">
<name_list.columns label="Tempo (μs)" name="art_value" tool_tip="Tempo impiegato per il rendering di questo allegato (microsecondi)" />
<name_list.columns name="complex_value" tool_tip="Complessità dell'oggetto (ARC)" />
<name_list.columns label="Nome Allegato" tool_tip="Fare clic sulla 'X' per staccare" name="name" />
</name_list>
</panel>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="panel_performance_huds">
<text name="back_lbl">
Indietro
</text>
<text name="huds_title">
I tuoi HUDs attivi
</text>
<text name="huds_desc1">
Staccare gli HUD inutilizzati. Usare meno memoria e rendere il viewer piu veloce.
</text>
<text name="huds_desc2">
Gli HUD hanno spesso script pesanti e contribuiscono anche alla LAG lato server.
</text>
<text name="huds_desc3">
Nota: l'utilizzo del pulsante di riduzione a icona di un HUD non lo stacca. Usa la X per rimuoverlo.
</text>
<name_list name="hud_list">
<name_list.columns label="Tempo (μs)" name="art_value" tool_tip="Tempo impiegato per il rendering di questo HUD (microsecondi)" />
<name_list.columns label="Nome" tool_tip="Fare clic sulla 'X' per staccare" name="name" />
</name_list>
</panel>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="panel_performance_nearby">
<text name="back_lbl">
Indietro
</text>
<text name="av_nearby_title">
Avatars nelle vicinanze
</text>
<text name="av_nearby_desc">
Nascondi gli avatar piu complessi per aumentare la velocita.
</text>
<slider tool_tip="Controlla a che punto un avatar visivamente complesso viene disegnato come impostore" label="Massima complessità (K)" name="IndirectMaxComplexity" />
<slider tool_tip="Controlla quando si ritiene che un avatar visivamente complesso richieda troppo tempo per il rendering (unità: microsecondi)" label="Tempo mass. di rendering (μs)" name="FSRenderAvatarMaxART" />
<text name="FSRenderAvatarMaxARTText">
senza limiti
</text>
<name_list name="nearby_list">
<name_list.columns tool_tip="Grafico a barre che mostra il tempo di rendering corrente (include l'autotuning) come % del più lento." name="art_visual" />
<name_list.columns label="Tempo (μs)" tool_tip="Tempo di rendering avatar. Tempo effettivo impiegato per il rendering prima di qualsiasi ottimizzazione automatica (in microsec)." name="art_value" />
<name_list.columns tool_tip="Complessita (ARC) basata su regole standard." name="complex_value" />
<name_list.columns tool_tip="Mostra qualsiasi sintonizzazione. I=Impostore, S=nessuna ombra." name="state" />
<name_list.columns label="Nome" name="name"/>
</name_list>
<text name="av_nearby_desc2">
Puoi anche fare clic destro del mouse su un avatar per contr. la visualizz.
</text>
<button label="Eccezioni..." name="exceptions_btn" />
<check_box label="Mostra gli amici sempre con il massimo dettaglio" name="display_friends" />
<check_box label="Nascondi completamente gli avatar" name="hide_avatars" />
<text name="name_tags_textbox">
Nomi:
</text>
<radio_group name="name_tag_mode">
<radio_item label="Off" name="radio" />
<radio_item label="On" name="radio2" />
<radio_item label="Mostra brevemente" name="radio3" />
</radio_group>
</panel>

View File

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="panel_performance_preferences">
<text name="back_lbl">
Indietro
</text>
<text name="settings_title">
Impostazioni Grafiche
</text>
<text name="quality_lbl">
Qualita vs Velocita
</text>
<text name="FasterText">
Piu veloce
</text>
<text name="BetterText">
Piu Qualita
</text>
<text name="quality_desc">
La scelta di un preset ripristinera tutte le modifiche manuali apportate.
</text>
<text name="distance_lbl">
Distanza di Visibilita
</text>
<text name="faster_lbl">
Piu veloce
</text>
<text name="farther_lbl">
Piu lontano
</text>
<text name="distance_desc1">
Un valore basso ha prestazioni migliori, aumentalo per vedere piu lontano.
</text>
<text name="environment_lbl">
Ambiente
</text>
<text name="enhancements_desc">
Ridurre/eliminare le ombre puo aumentare gli FPS ma ha
un impatto su atmosfera e aspetto della scena.
</text>
<text name="RenderShadowDetailText">
Origine Ombre:
</text>
<combo_box name="ShadowDetail">
<combo_box.item label="Nessuno" name="0" />
<combo_box.item label="Sole/Luna" name="1" />
<combo_box.item label="Sole/Luna + altre sorgenti" name="2" />
</combo_box>
<text name="water_lbl">
Acqua
</text>
<text name="water_desc">
Ridurre qualita agli effetti dell'acqua puo migliorare
notevolmente la frequenza dei fotogrammi.
</text>
<text name="ReflectionsText">
Riflessi Acqua:
</text>
<combo_box name="Reflections">
<combo_box.item label="None; opaquo" name="-2" />
<combo_box.item label="None; transparente" name="-1" />
<combo_box.item label="Minimo" name="0" />
<combo_box.item label="Terra e alberi" name="1" />
<combo_box.item label="Tutti gli oggetti statici" name="2" />
<combo_box.item label="Tutti gli avatar e gli oggetti" name="3" />
<combo_box.item label="Qualunque cosa" name="4" />
</combo_box>
<text name="photo_lbl">
Fotografia
</text>
<text name="photo_desc">
I fotografi hanno bisogno di alta qualita, ma spesso
a discapito del frame rate. [APP_NAME] phototools puo
aiutarti a trovare il giusto equilibrio.
</text>
<button name="open_phototools" label="Phototools" tool_tip="Apri gli strumenti fotografici dedicati per le impostazioni avanzate delle foto." />
</panel>

View File

@ -613,11 +613,6 @@ support@secondlife.com にお問い合わせください。
<string name="ReleaseNotes">
リリースノート
</string>
<!--
<string name="RELEASE_NOTES_BASE_URL">
https://releasenotes.secondlife.com/viewer/
</string>
-->
<string name="LoadingData">
ローディング...
</string>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="performance" title="Popraw szybkość grafiki (eksperymentalne)">
<floater.string name="frame_stats">
Klatki: [TOT_FRAME_TIME]ms - Scena:[SCENERY_FRAME_PCT]% Awatary:[AV_FRAME_PCT]% UI:[UI_FRAME_PCT]% HUDy:[HUDS_FRAME_PCT]% SWAP:[SWAP_FRAME_PCT]% ZADANIA:[IDLE_FRAME_PCT]%
Klatki: [TOT_FRAME_TIME]ms - Scena:[SCENERY_FRAME_PCT]% Awatary:[AV_FRAME_PCT]% UI:[UI_FRAME_PCT]% HUDy:[HUDS_FRAME_PCT]% Swap:[SWAP_FRAME_PCT]% Zadania:[IDLE_FRAME_PCT]%
</floater.string>
<floater.string name="limit_fps">
Limit FPS: [FPSCAP] fps
@ -12,6 +12,12 @@
<floater.string name="focus_fps">
W tle
</floater.string>
<floater.string name="info_waitforit">
Poczekaj 5-10 sekund, by nastąpiły zmiany.
</floater.string>
<floater.string name="info_frozen">
Statystyki pauzują, gdy FPS jest limitowane lub w tle.
</floater.string>
<floater.string name="tot_av_template">
Łącznie: [TOT_AV] ([TOT_AV_TIME]μs)
</floater.string>
@ -24,25 +30,33 @@
klatek na sekundę
</text>
<text name="fps_desc1_lbl">
Poczekaj 5-10 sekund, by nastąpiły zmiany.
Statystyki pauzują, gdy FPS jest limitowane lub w tle.
</text>
<text name="frame_breakdown">
[----------------- Tutaj pojawi się analiza klatek. -----------------]
</text>
</panel>
<panel name="target_subpanel">
<text name="settings_lbl">
Autostrojenie klatek
<text name="settings_lbl" tool_tip="Automatycznie dostosuj ustawienia, aby utrzymać FPS. Ustaw docelową żądaną liczbę klatek na sekundę, a przeglądarka spróbuje ją utrzymać dynamicznie zmieniając ustawienia.">
Automat:
</text>
<check_box label="Autostrojenie" name="AutoTuneFPS" tool_tip="Przeglądarka spróbuje dostosowywać ustawienia, aby osiągnąć docelową liczbę klatek na sekundę." />
<text name="targetfps_desc">
Docelowy FPS
</text>
<spinner name="target_fps" tool_tip="Docelowa liczba FPS — żądany poziom klatek na sekundę. Przeglądarka spróbuje go osiągnąć dostosowując ustawienia grafiki." />
<button name="AutoTuneFPS" tool_tip="Przeglądarka spróbuje dostosowywać ustawienia, aby osiągnąć docelową liczbę klatek na sekundę." />
<check_box label="Ciągłość" name="AutoTuneContinuous" tool_tip="Przeglądarka będzie stale dostosowywać ustawienia, aby osiągnąć docelową liczbę klatek na sekundę, aż do zatrzymania, nawet przy zamkniętym okna. Po wyłączeniu kliknięcie przycisku Autostrojenia spowoduje dostosowanie do bieżących ustawień, a następnie zatrzymanie." />
<button name="PrefSaveButton" tool_tip="Zapisz bieżące ustawienia do wartości domyślnych, do wykorzystania w przyszłości." />
<button name="PrefLoadButton" tool_tip="Załaduj zapisane wcześniej ustawienia." />
<button tool_tip="Załaduj ponownie domyślne ustawienia graficzne dla swojego sprzętu." name="Defaults" />
<text name="settings_desc">
Autostrojenie ustawień, by utrzymać FPS.
Strategia strojenia
</text>
<combo_box name="FSTuningFPSStrategy">
<combo_box.item label="Dostrój tylko awatary" name="av_only" />
<combo_box.item label="Tylko awatary" name="av_only" />
<combo_box.item label="Awatary i scena" name="av_and_scene" />
</combo_box>
<spinner name="target_fps" tool_tip="Docelowa liczba FPS — żądany poziom klatek na sekundę. Przeglądarka spróbuje go osiągnąć dostosowując ustawienia grafiki." />
<button name="target_btn" tool_tip="Zmień zachowanie strategii strojenia." />
</panel>
</panel>
<panel name="panel_performance_main">

View File

@ -326,6 +326,7 @@
<menu_item_call label="Miernik lagów" name="Lag Meter"/>
<menu_item_check label="Statystyki ogólne" name="Statistics Bar"/>
<menu_item_check label="Statystyki obciążenia sceny" name="Scene Load Statistics"/>
<menu_item_check label="Popraw szybkość grafiki..." name="Performance" />
<menu_item_check label="Stopień złożoności awatarów" name="Avatar Draw Info"/>
</menu>
<menu label="Podświetlanie i widoczność" name="Highlighting and Visibility">

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="panel_login">
<panel.string name="ServerComboTooltip">
<string name="ServerComboTooltip">
Istniejący świat lub URI świata
</panel.string>
</string>
<layout_stack name="login_widgets">
<layout_panel name="login">
<text name="log_in_text">

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="panel_login">
<panel.string name="ServerComboTooltip">
<string name="ServerComboTooltip">
Istniejący świat lub URI świata
</panel.string>
</string>
<layout_stack name="ui_stack">
<layout_panel name="ui_container">
<layout_stack name="vert_stack_left">

View File

@ -12,8 +12,9 @@
<check_box label="Optymalizacja oparta na odległości" name="FSAutoTuneImpostorByDistEnabled" tool_tip="Przeglądarka dostosuje ustawienie MaxNonImpostors, aby ograniczyć w pełni renderowane awatary do tych w sprecyzowanym promieniu." />
<spinner label="Najdalszy pełny awatar" name="ffa_autotune" />
<text name="distant_av_advice">
Awatary, które są dalej, nadal wpływają na renderowanie.
Awatary w oddali mogą być optymalizowane niezależnie od kosztu renderowania.
Określ odległość po której awatar zostanie zoptymalizowany.
To ustawienie wymusi MaxNonImpostors do 1, jeśli nikogo nie będzie w pobliżu.
</text>
<text name="distance_lbl">
Limity dostrajania pola widzenia
@ -21,7 +22,7 @@ Określ odległość po której awatar zostanie zoptymalizowany.
<spinner label="Minimalna odległość" name="min_dd_autotune" />
<spinner label="Preferowana odległość" name="pref_dd_autotune" />
<text name="distance_desc1">
Podczas przetwarzania sceny autostrojenie zoptymalizuje pole widzenia między minimalnym a preferowanym.
Podczas przetwarzania sceny autostrojenie wybierze wartości między minimalnymi a preferowanymi dla pola widzenia.
</text>
<text name="sundry_lbl">
Różne

View File

@ -24,8 +24,11 @@
<text name="av_nearby_desc2">
Możesz kliknąć PPM na awatarze w świecie, aby sterować wyświetlaniem.
</text>
<button label="Wyjątki..." name="exceptions_btn" />
<text name="av_nearby_desc3">
Twój własny awatar zawiera narzut przeglądarki. Na karcie dodatków zobaczysz jak wpływasz na innych.
</text>
<check_box label="Znajomi zawsze z pełnymi detalami" name="display_friends" />
<button label="Wyjątki..." name="exceptions_btn" />
<check_box label="Całkowicie ukryj awatary" name="hide_avatars" />
<text name="name_tags_textbox">
Imiona:

View File

@ -591,11 +591,6 @@ ser anexado às anotações.&quot;
<string name="ReleaseNotes">
Notas de versão
</string>
<!--
<string name="RELEASE_NOTES_BASE_URL">
https://releasenotes.secondlife.com/viewer/
</string>
-->
<string name="LoadingData">
Carregando...
</string>

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="performance" title="Увеличить скорость графики (экспериментально)">
<floater name="performance" title="Увеличить скорость графики (Экспериментально)">
<floater.string name="frame_stats">
Кадр: [TOT_FRAME_TIME]ms - Пейзаж:[SCENERY_FRAME_PCT]% Аватары:[AV_FRAME_PCT]% UI:[UI_FRAME_PCT]% HUDS:[HUDS_FRAME_PCT]% SWAP:[SWAP_FRAME_PCT]% TASKS:[IDLE_FRAME_PCT]%
Кадр:[TOT_FRAME_TIME]ms Сцена:[SCENERY_FRAME_PCT]% Аватары:[AV_FRAME_PCT]% UI:[UI_FRAME_PCT]% HUDS:[HUDS_FRAME_PCT]% Swap:[SWAP_FRAME_PCT]% Задачи:[IDLE_FRAME_PCT]%
</floater.string>
<floater.string name="limit_fps">
<floater.string name="limit_fps">
FPS ограничен [FPSCAP] к/с
</floater.string>
<floater.string name="tuning_fps">
@ -12,6 +12,12 @@
<floater.string name="focus_fps">
Фоновый режим
</floater.string>
<floater.string name="info_waitforit">
Дайте 5-10 секунд чтобы изменения произошли.
</floater.string>
<floater.string name="info_frozen">
Пауза статистики при ограничении FPS или фоновый режим.
</floater.string>
<floater.string name="tot_av_template">
Всего: [TOT_AV] ([TOT_AV_TIME]μs)
</floater.string>
@ -20,28 +26,30 @@
</floater.string>
<panel name="panel_top">
<panel name="fps_subpanel">
<text name="fps_lbl">
кадров в секунду
</text>
<text name="fps_desc1_lbl">
Дайте 510 секунд, чтобы изменения применились.
</text>
<text name="fps_lbl">кадров в секунду</text>
<text name="fps_warning">Ограничение @ 000 FPS</text>
<text name="fps_desc1_lbl">Пауза статистики при ограничении FPS или фоновый режим.</text>
<text name="frame_breakdown">
[---------------------Здесь появится разбивка кадров.----------------------]
</text>
</panel>
<panel name="target_subpanel">
<text name="settings_lbl">Автонастройка FPS</text>
<check_box label="Автонастройка" name="AutoTuneFPS" tool_tip="Программа попытается настроить параметры для достижения целевой частоты кадров."/>
<text name="settings_desc">Автоподстройка настроек для FPS</text>
<text name="settings_lbl" tool_tip="Автоматически настраивайет параметры для поддержания FPS. Установите цель на желаемую частоту кадров, и программа просмотра попытается соответствовать этому, динамически изменяя ваши настройки.">Авто.:</text>
<text name="targetfps_desc">Целевая частота (fps)</text>
<spinner name="target_fps" tool_tip="Цель FPS - Желаемый уровень FPS. Программа просмотра попытается добиться этого, изменив настройки графики."/>
<button name="AutoTuneFPS" label="Старт" label_selected="Стоп" tool_tip="Программа попытается настроить параметры для достижения целевой частоты кадров."/>
<check_box name="AutoTuneContinuous" label="Непрерывно" tool_tip="Программа просмотра будет постоянно изменять настройки для достижения целевого FPS, пока не остановится, даже если окно закрыто. Если функция отключена, нажатие кнопки Автонастройка приведет к настройке текущих параметров, а затем остановится."/>
<button name="PrefSaveButton" tool_tip="Сохранить текущие настройки по умолчанию для использования в будущем."/>
<button name="PrefLoadButton" tool_tip="Загрузить существующие предустановки."/>
<button name="Defaults" tool_tip="Перезагрузить настройки графики по умолчанию для вашего оборудования."/>
<text name="settings_desc">Стратегия подстройки</text>
<combo_box name="FSTuningFPSStrategy">
<combo_box.item label="Только аватары" name="av_only"/>
<combo_box.item label="Аватары и сцена" name="av_and_scene"/>
</combo_box>
<spinner name="target_fps" tool_tip="Цель FPS - Желаемый уровень FPS. Программа просмотра попытается добиться этого, изменив настройки графики."/>
<button name="target_btn" tool_tip="Изменить поведение стратегии подстройки."/>
</panel>
</panel>
<panel name="panel_performance_main">
<panel name="settings_subpanel">
<text name="settings_lbl">Настройки графики</text>
@ -51,7 +59,7 @@
<text name="avatars_nearby_lbl">Аватары рядом</text>
<text name="avatars_nearby_desc" >Управляйте отображением ближайших аватаров.</text>
<text name="avatars_frme_pct_lbl">
время
Время
отрисовки
аватаров
</text>
@ -64,7 +72,7 @@
<text name="huds_lbl">HUD-ы аватара</text>
<text name="huds_desc">Удаление ненужных HUD может улучшить скорость.</text>
<text name="huds_frme_pct_lbl">
время
Время
отрисовки
HUD-ов
</text>

View File

@ -366,6 +366,7 @@
<menu_item_call label="Измерение лагов" name="Lag Meter"/>
<menu_item_check label="Окно статистики" name="Statistics Bar"/>
<menu_item_check label="Статистика загрузки сцены" name="Scene Load Statistics"/>
<menu_item_check label="Увеличить скорость графики ..." name="Performance"/>
<menu_item_check label="Показать информацию сложности аватаров" name="Avatar Draw Info"/>
</menu>
<menu label="Подсветка и видимость" name="Highlighting and Visibility">

View File

@ -5290,4 +5290,11 @@ https://wiki.firestormviewer.org/fs_voice
Предмет с названием "[NAME]" является ригованым мешем, но прикреплен на экран в "[HUD_POINT]". Это значит, что для вас он будет отображаться правильно, но все остальные вообще не смогут его увидеть. Возможно, вы захотите снять его и снова прикрепить к обычной точке крепления на теле.
<usetemplate ignoretext="Предупреждать меня когда ригованные вещи прикрепляются на экран пользователя." name="notifyignore"/>
</notification>
<notification name="WarnForceLoginURL">
URL-адрес заставки входа в систему переопределен в целях тестирования.
Сбросить URL по умолчанию?
<usetemplate name="okcancelbuttons" notext="Напомни мне в следующий раз" yestext="Сбросить"/>
</notification>
</notifications>

View File

@ -6,14 +6,15 @@
<check_box name="FSAutoTuneImpostorByDistEnabled" label="Оптимизация на основе расстояния" tool_tip="Если этот параметр включен, средство просмотра настроит параметр MaxNonImpostors, чтобы ограничить полностью визуализированные аватары только теми, которые находятся в пределах определенного радиуса."/>
<spinner name="ffa_autotune" label="Самый дальний"/>
<text name="distant_av_advice">
Аватары которые далеко, по-прежнему имеют большое влияние.
Установи дальность, дальше которой аватар будет оптимизирован.
Далекие аватары будут оптимизированы независимо от рендеринга. Установи дальность, с которой аватар будет оптимизирован.
Примечание. Этот параметр установит MaxNonImpostors значение 1,
если поблизости никого нет.
</text>
<text name="distance_lbl">Пределы настройки расстояния</text>
<spinner name="min_dd_autotune" label="Минимальн. дистанция"/>
<spinner name="pref_dd_autotune" label="Предпочтит. дистанция"/>
<text name="distance_desc1">
При настройке параметров сцены, автонастройка оптимизирует расстояние прорисовки между минимальным и предпочтительным.
При настройке параметров сцены, автонастройка будет выбирать значения между минимальным и предпочтительным расстоянием прорисовки.
</text>
<text name="sundry_lbl">Разные настройки</text>
<check_box name="alow_self_impostor" label="Оптимизировать свой аватар" tool_tip="Когда этот параметр включен, ваш собственный аватар может отображаться как силуэт."/>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="panel_performance_nearby">
<text name="back_lbl">Назад</text>
<text name="av_nearby_title">Аватары рядом</text>
@ -17,8 +17,11 @@
<text name="av_nearby_desc2">
Вы можете щелкнуть ПКМ на аватар в мире, чтобы управлять отображением.
</text>
<button label="Исключения..." name="exceptions_btn"/>
<text name="av_nearby_desc3">
Примечание. Используйте вкладку Сложность аватара, чтобы видеть как вы влияете на других.
</text>
<check_box label="Всегда отображать друзей во всех подробностях" name="display_friends"/>
<button label="Исключения..." name="exceptions_btn"/>
<check_box label="Полностью скрыть аватары" name="hide_avatars"/>
<text name="name_tags_textbox">Бейджи:</text>
<radio_group name="name_tag_mode">

View File

@ -29,6 +29,9 @@
http://secondlife.com/account/request.php
</panel.string>
<!-- *NOTE: Custom resize logic for login_html in llpanellogin.cpp -->
<string name="ServerComboTooltip">
An existing grid or a grid URI
</string>
<web_browser
name="login_html"
top="18"

View File

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="panel_login">
<string name="ServerComboTooltip">
Istniejący świat lub URI świata
</string>
<layout_stack name="login_widgets">
<layout_panel name="login">
<text name="log_in_text">

View File

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="panel_login">
<string name="ServerComboTooltip">
Существующая сетка или URI сетки
</string>
<layout_stack name="login_widgets">
<layout_panel name="login">
<text name="username_text">

View File

@ -1864,8 +1864,9 @@ class LinuxManifest(ViewerManifest):
self.path("install.sh")
with self.prefix(dst="bin"):
self.path( os.path.join(os.pardir,'build_data.json'), "build_data.json" )
self.path("firestorm-bin","do-not-directly-run-firestorm-bin")
#self.path("../linux_crash_logger/linux-crash-logger","linux-crash-logger.bin")
self.path("../linux_crash_logger/linux-crash-logger","linux-crash-logger.bin")
self.path2basename("../llplugin/slplugin", "SLPlugin")
#this copies over the python wrapper script, associated utilities and required libraries, see SL-321, SL-322 and SL-323
# <FS:Ansariel> Remove VMP
@ -1886,25 +1887,9 @@ class LinuxManifest(ViewerManifest):
# plugins
with self.prefix(src=os.path.join(self.args['build'], os.pardir, 'media_plugins'), dst="bin/llplugin"):
#self.path("gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so")
self.path2basename("libvlc", "libmedia_plugin_libvlc.so")
self.path("gstreamer10/libmedia_plugin_gstreamer10.so", "libmedia_plugin_gstreamer.so")
self.path("cef/libmedia_plugin_cef.so", "libmedia_plugin_cef.so" )
with self.prefix(src=os.path.join(pkgdir, 'lib', 'vlc', 'plugins'), dst="bin/llplugin/vlc/plugins"):
self.path( "plugins.dat" )
self.path( "*/*.so" )
with self.prefix(src=os.path.join(pkgdir, 'lib' ), dst="lib"):
self.path( "libvlc*.so*" )
with self.prefix(src=os.path.join(pkgdir, 'lib', 'vlc', 'plugins'), dst="bin/llplugin/vlc/plugins"):
self.path( "plugins.dat" )
self.path( "*/*.so" )
with self.prefix(src=os.path.join(pkgdir, 'lib' ), dst="lib"):
self.path( "libvlc*.so*" )
# CEF files
with self.prefix(src=os.path.join(pkgdir, 'lib', 'release'), dst="lib"):
self.path( "libcef.so" )
@ -2095,7 +2080,10 @@ class LinuxManifest(ViewerManifest):
# name in the tarfile
realname = self.get_dst_prefix()
tempname = self.build_path_of(installer_name)
self.run_command([self.args["source"] + "/installers/linux/appimage.sh", self.args["build"]] )
self.run_command([
self.args["source"] + "/installers/linux/appimage.sh", self.args["build"],
self.args["build"] + "/Firestorm-x86_64.AppImage", self.args["build"] + "/" + installer_name + ".AppImage"
] )
self.run_command(["mv", realname, tempname])
try:
# only create tarball if it's a release build.

View File

@ -50,6 +50,7 @@ LL_ARGS_PASSTHRU=""
JOBS="0"
WANTS_NINJA=$FALSE
WANTS_VSCODE=$FALSE
USE_VSTOOL=$TRUE
TESTBUILD_PERIOD="0"
SINGLEGRID_URI=""
@ -87,6 +88,7 @@ showUsage()
echo " --ninja : Build using Ninja"
echo " --vscode : Exports compile commands for VSCode (Linux only)"
echo " --compiler-cache : Try to detect and use compiler cache (needs also --ninja for OSX and Windows)"
echo " --no-vstools : Do not use vstool to setup project startup properties (windows only)"
echo
echo "All arguments not in the above list will be passed through to LL's configure/build."
echo
@ -96,7 +98,7 @@ getArgs()
# $* = the options passed in from main
{
if [ $# -gt 0 ]; then
while getoptex "clean build config version package no-package fmodstudio openal ninja vscode compiler-cache jobs: platform: kdu opensim no-opensim singlegrid: avx avx2 tracy crashreporting testbuild: help chan: btype:" "$@" ; do
while getoptex "clean build config version package no-package fmodstudio openal ninja vscode compiler-cache no-vstools jobs: platform: kdu opensim no-opensim singlegrid: avx avx2 tracy crashreporting testbuild: help chan: btype:" "$@" ; do
#ensure options are valid
if [ -z "$OPTOPT" ] ; then
@ -136,6 +138,7 @@ getArgs()
ninja) WANTS_NINJA=$TRUE;;
vscode) WANTS_VSCODE=$TRUE;;
compiler-cache) WANTS_CACHE=$TRUE;;
no-vstools) USE_VSTOOL=$FALSE;;
help) showUsage && exit 0;;
@ -520,7 +523,7 @@ if [ $WANTS_CONFIG -eq $TRUE ] ; then
CRASH_REPORTING="-DRELEASE_CRASH_REPORTING=ON"
if [ ! -z $CHANNEL_SIMPLE ]
then
CRASH_REPORTING="$CRASH_REPORTING -DUSE_BUGSPLAT=On -DBUGSPLAT_DB=firestorm_"`echo $CHANNEL_SIMPLE | tr [:upper:] [:lower:] | sed -e 's/_x64//'`
CRASH_REPORTING="$CRASH_REPORTING -DUSE_BUGSPLAT=On -DBUGSPLAT_DB=firestorm_"`echo $CHANNEL_SIMPLE | tr [:upper:] [:lower:] | sed -e 's/x64//' | sed -e 's/_//g'`
fi
else
CRASH_REPORTING="-DRELEASE_CRASH_REPORTING:BOOL=OFF"
@ -577,7 +580,8 @@ if [ $WANTS_CONFIG -eq $TRUE ] ; then
$UNATTENDED -DLL_TESTS:BOOL=OFF -DADDRESS_SIZE:STRING=$AUTOBUILD_ADDRSIZE -DCMAKE_BUILD_TYPE:STRING=$BTYPE $CACHE_OPT \
$CRASH_REPORTING -DVIEWER_SYMBOL_FILE:STRING="${VIEWER_SYMBOL_FILE:-}" -DROOT_PROJECT_NAME:STRING=Firestorm $LL_ARGS_PASSTHRU ${VSCODE_FLAGS:-} | tee $LOG
if [ $TARGET_PLATFORM == "windows" ] ; then
if [ $TARGET_PLATFORM == "windows" -a $USE_VSTOOL -eq $TRUE ] ; then
echo "Setting startup project via vstool"
../indra/tools/vstool/VSTool.exe --solution Firestorm.sln --startup firestorm-bin --workingdir firestorm-bin "..\\..\\indra\\newview" --config $BTYPE
fi
fi